aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-09-23 16:29:25 -0500
committerFrederick Muriuki Muriithi2024-09-23 16:35:39 -0500
commit480ee0b657b762f1dd0b1164f98ab13bc9a11f56 (patch)
tree28c7e8e450112039bb764a6fe967838369aba937
parent4285cc10e24d6410206329ba079406e9aa21cc30 (diff)
downloadgn-uploader-480ee0b657b762f1dd0b1164f98ab13bc9a11f56.tar.gz
Initialise "Platforms" section.
-rw-r--r--uploader/db/platforms.py25
-rw-r--r--uploader/platforms/__init__.py2
-rw-r--r--uploader/platforms/models.py41
-rw-r--r--uploader/platforms/views.py86
-rw-r--r--uploader/species/views.py2
-rw-r--r--uploader/templates/platforms/base.html13
-rw-r--r--uploader/templates/platforms/create-platform.html103
-rw-r--r--uploader/templates/platforms/index.html21
-rw-r--r--uploader/templates/platforms/list-platforms.html93
9 files changed, 361 insertions, 25 deletions
diff --git a/uploader/db/platforms.py b/uploader/db/platforms.py
deleted file mode 100644
index cb527a7..0000000
--- a/uploader/db/platforms.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""Handle db interactions for platforms."""
-from typing import Optional
-
-import MySQLdb as mdb
-from MySQLdb.cursors import DictCursor
-
-def platforms_by_species(
- conn: mdb.Connection, speciesid: int) -> tuple[dict, ...]:
- """Retrieve platforms by the species"""
- with conn.cursor(cursorclass=DictCursor) as cursor:
- cursor.execute("SELECT * FROM GeneChip WHERE SpeciesId=%s "
- "ORDER BY GeneChipName ASC",
- (speciesid,))
- return tuple(dict(row) for row in cursor.fetchall())
-
-def platform_by_id(conn: mdb.Connection, platformid: int) -> Optional[dict]:
- """Retrieve a platform by its ID"""
- with conn.cursor(cursorclass=DictCursor) as cursor:
- cursor.execute("SELECT * FROM GeneChip WHERE Id=%s",
- (platformid,))
- result = cursor.fetchone()
- if bool(result):
- return dict(result)
-
- return None
diff --git a/uploader/platforms/__init__.py b/uploader/platforms/__init__.py
new file mode 100644
index 0000000..8cb89c9
--- /dev/null
+++ b/uploader/platforms/__init__.py
@@ -0,0 +1,2 @@
+"""Module to handle management of genetic platforms."""
+from .views import platformsbp
diff --git a/uploader/platforms/models.py b/uploader/platforms/models.py
new file mode 100644
index 0000000..adad0b2
--- /dev/null
+++ b/uploader/platforms/models.py
@@ -0,0 +1,41 @@
+"""Handle db interactions for platforms."""
+from typing import Optional
+
+import MySQLdb as mdb
+from MySQLdb.cursors import DictCursor
+
+def platforms_by_species(
+ conn: mdb.Connection,
+ speciesid: int,
+ offset: int = 0,
+ limit: Optional[int] = None
+) -> tuple[dict, ...]:
+ """Retrieve platforms by the species"""
+ _query = ("SELECT * FROM GeneChip WHERE SpeciesId=%s "
+ "ORDER BY GeneChipName ASC")
+ if bool(limit) and limit > 0:
+ _query = f"{_query} LIMIT {limit} OFFSET {offset}"
+ with conn.cursor(cursorclass=DictCursor) as cursor:
+ cursor.execute(_query, (speciesid,))
+ return tuple(dict(row) for row in cursor.fetchall())
+
+
+def species_platforms_count(conn: mdb.Connection, species_id: int) -> int:
+ """Get the number of platforms in the database for a particular species."""
+ with conn.cursor(cursorclass=DictCursor) as cursor:
+ cursor.execute(
+ "SELECT COUNT(GeneChipName) AS count FROM GeneChip "
+ "WHERE SpeciesId=%s",
+ (species_id,))
+ return int(cursor.fetchone()["count"])
+
+def platform_by_id(conn: mdb.Connection, platformid: int) -> Optional[dict]:
+ """Retrieve a platform by its ID"""
+ with conn.cursor(cursorclass=DictCursor) as cursor:
+ cursor.execute("SELECT * FROM GeneChip WHERE Id=%s",
+ (platformid,))
+ result = cursor.fetchone()
+ if bool(result):
+ return dict(result)
+
+ return None
diff --git a/uploader/platforms/views.py b/uploader/platforms/views.py
new file mode 100644
index 0000000..56390ab
--- /dev/null
+++ b/uploader/platforms/views.py
@@ -0,0 +1,86 @@
+"""The endpoints for the platforms"""
+from flask import (
+ flash,
+ request,
+ url_for,
+ redirect,
+ Blueprint,
+ current_app as app)
+
+from uploader.ui import make_template_renderer
+from uploader.authorisation import require_login
+from uploader.db_utils import database_connection
+from uploader.species.models import all_species, species_by_id
+from uploader.datautils import safe_int, order_by_family, enumerate_sequence
+
+from .models import platforms_by_species, species_platforms_count
+
+platformsbp = Blueprint("platforms", __name__)
+render_template = make_template_renderer("platforms")
+
+@platformsbp.route("platforms", methods=["GET"])
+@require_login
+def index():
+ """Entry-point to the platforms feature."""
+ with database_connection(app.config["SQL_URI"]) as conn:
+ if not bool(request.args.get("species_id")):
+ return render_template(
+ "platforms/index.html",
+ species=order_by_family(all_species(conn)),
+ activelink="platforms")
+
+ species = species_by_id(conn, request.args["species_id"])
+ if not bool(species):
+ flash("No species selected.", "alert-danger")
+ return redirect(url_for("species.platforms.index"))
+
+ return redirect(url_for("species.platforms.list_platforms",
+ species_id=species["SpeciesId"]))
+
+
+@platformsbp.route("<int:species_id>/platforms", methods=["GET"])
+@require_login
+def list_platforms(species_id: int):
+ """List all the available genetic sequencing platforms."""
+ with database_connection(app.config["SQL_URI"]) as conn:
+ species = species_by_id(conn, species_id)
+ if not bool(species):
+ flash("No species provided.", "alert-danger")
+ return redirect(url_for("species.platforms.index"))
+
+ start_from = safe_int(request.args.get("start_from") or 0)
+ if start_from < 0:
+ start_from = 0
+ count = safe_int(request.args.get("count") or 20)
+ return render_template(
+ "platforms/list-platforms.html",
+ species=species,
+ platforms=enumerate_sequence(
+ platforms_by_species(conn,
+ species_id,
+ offset=start_from,
+ limit=count),
+ start=start_from+1),
+ start_from=start_from,
+ count=count,
+ total_platforms=species_platforms_count(conn, species_id),
+ activelink="list-platforms")
+
+
+@platformsbp.route("<int:species_id>/platforms/create", methods=["GET", "POST"])
+@require_login
+def create_platform(species_id: int):
+ """Create a new genetic sequencing platform."""
+ with database_connection(app.config["SQL_URI"]) as conn:
+ species = species_by_id(conn, species_id)
+ if not bool(species):
+ flash("No species provided.", "alert-danger")
+ return redirect(url_for("species.platforms.index"))
+
+ if request.method == "GET":
+ return render_template(
+ "platforms/create-platform.html",
+ species=species,
+ activelink="create-platform")
+
+ raise NotImplementedError("This still needs to be implemented.")
diff --git a/uploader/species/views.py b/uploader/species/views.py
index f478505..10715a5 100644
--- a/uploader/species/views.py
+++ b/uploader/species/views.py
@@ -8,6 +8,7 @@ from flask import (flash,
current_app as app)
from uploader.population import popbp
+from uploader.platforms import platformsbp
from uploader.ui import make_template_renderer
from uploader.db_utils import database_connection
from uploader.oauth2.client import oauth2_get, oauth2_post
@@ -23,6 +24,7 @@ from .models import (all_species,
speciesbp = Blueprint("species", __name__)
speciesbp.register_blueprint(popbp, url_prefix="/")
+speciesbp.register_blueprint(platformsbp, url_prefix="/")
render_template = make_template_renderer("species")
diff --git a/uploader/templates/platforms/base.html b/uploader/templates/platforms/base.html
new file mode 100644
index 0000000..dac965f
--- /dev/null
+++ b/uploader/templates/platforms/base.html
@@ -0,0 +1,13 @@
+{%extends "species/base.html"%}
+
+{%block lvl3_breadcrumbs%}
+<li {%if activelink=="platforms"%}
+ class="breadcrumb-item active"
+ {%else%}
+ class="breadcrumb-item"
+ {%endif%}>
+ <a href="{{url_for('species.populations.platforms.index')}}">
+ Sequencing Platforms</a>
+</li>
+{%block lvl4_breadcrumbs%}{%endblock%}
+{%endblock%}
diff --git a/uploader/templates/platforms/create-platform.html b/uploader/templates/platforms/create-platform.html
new file mode 100644
index 0000000..b5961ce
--- /dev/null
+++ b/uploader/templates/platforms/create-platform.html
@@ -0,0 +1,103 @@
+{%extends "platforms/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "species/macro-display-species-card.html" import display_species_card%}
+
+{%block title%}Platforms &mdash; Create Platforms{%endblock%}
+
+{%block pagetitle%}Platforms &mdash; Create Platforms{%endblock%}
+
+{%block lvl3_breadcrumbs%}
+<li {%if activelink=="create-platform"%}
+ class="breadcrumb-item active"
+ {%else%}
+ class="breadcrumb-item"
+ {%endif%}>
+ <a href="{{url_for('species.platforms.create_platform',
+ species_id=species.SpeciesId)}}">create platform</a>
+</li>
+{%endblock%}
+
+{%block contents%}
+{{flash_all_messages()}}
+
+<div class="row">
+ <h2>Create New Platform</h2>
+
+ <p>You can create a new genetic sequencing platform below.</p>
+</div>
+
+<div class="row">
+ <form id="frm-create-platform"
+ method="POST"
+ action="{{url_for('species.platforms.create_platform',
+ species_id=species.SpeciesId)}}">
+
+ <div class="form-group">
+ <label for="txt-geo-platform" class="form-label">GEO Platform</label>
+ <input type="text"
+ id="txt-geo-platform"
+ name="geo-platform"
+ required="required"
+ class="form-control" />
+ <small class="form-text text-muted">
+ <p>This is the platform's
+ <a href="https://www.ncbi.nlm.nih.gov/geo/browse/?view=platforms&tax={{species.TaxonomyId}}"
+ title="Platforms for '{{species.FullName}}' on NCBI">
+ accession value on NCBI</a>. If you do not know the value, click the
+ link and search on NCBI for species '{{species.FullName}}'.</p></small>
+ </div>
+
+ <div class="form-group">
+ <label for="txt-platform-name" class="form-label">Platform Name</label>
+ <input type="text"
+ id="txt-platform-name"
+ name="platform-name"
+ required="required"
+ class="form-control" />
+ <small class="form-text text-muted">
+ <p>This is name of the genetic sequencing platform.</p></small>
+ </div>
+
+ <div class="form-group">
+ <label for="txt-platform-shortname" class="form-label">
+ Platform Short Name</label>
+ <input type="text"
+ id="txt-platform-shortname"
+ name="platform-shortname"
+ required="required"
+ class="form-control" />
+ <small class="form-text text-muted">
+ <p>Use the following conventions for this field:
+ <ol>
+ <li>Start with a 4-letter vendor code, e.g. "Affy" for "Affymetrix", "Illu" for "Illumina", etc.</li>
+ <li>Append an underscore to the 4-letter vendor code</li>
+ <li>Use the name of the array given by the vendor, e.g. U74AV2, MOE430A, etc.</li>
+ </ol>
+ </p>
+ </small>
+ </div>
+
+ <div class="form-group">
+ <label for="txt-platform-title" class="form-label">Platform Title</label>
+ <input type="text"
+ id="txt-platform-title"
+ name="platform-title"
+ required="required"
+ class="form-control" />
+ <small class="form-text text-muted">
+ <p>The full platform title. Sometimes, this is the same as the Platform
+ Name above.</p></small>
+ </div>
+
+ <div class="form-group">
+ <input type="submit"
+ value="create new platform"
+ class="btn btn-primary" />
+ </div>
+ </form>
+</div>
+{%endblock%}
+
+{%block sidebarcontents%}
+{{display_species_card(species)}}
+{%endblock%}
diff --git a/uploader/templates/platforms/index.html b/uploader/templates/platforms/index.html
new file mode 100644
index 0000000..35b6464
--- /dev/null
+++ b/uploader/templates/platforms/index.html
@@ -0,0 +1,21 @@
+{%extends "platforms/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "species/macro-select-species.html" import select_species_form%}
+
+{%block title%}Platforms{%endblock%}
+
+{%block pagetitle%}Platforms{%endblock%}
+
+
+{%block contents%}
+{{flash_all_messages()}}
+
+<div class="row">
+ <p>In this section, you will be able to view and manage the sequencing
+ platforms that are currently supported by GeneNetwork.</p>
+</div>
+
+<div class="row">
+ {{select_species_form(url_for("species.platforms.index"), species)}}
+</div>
+{%endblock%}
diff --git a/uploader/templates/platforms/list-platforms.html b/uploader/templates/platforms/list-platforms.html
new file mode 100644
index 0000000..718dd1d
--- /dev/null
+++ b/uploader/templates/platforms/list-platforms.html
@@ -0,0 +1,93 @@
+{%extends "platforms/base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+{%from "species/macro-display-species-card.html" import display_species_card%}
+
+{%block title%}Platforms &mdash; List Platforms{%endblock%}
+
+{%block pagetitle%}Platforms &mdash; List Platforms{%endblock%}
+
+
+{%block contents%}
+{{flash_all_messages()}}
+
+<div class="row">
+ <p>View the list of the genetic sequencing platforms that are currently
+ supported by GeneNetwork.</p>
+ <p>If you cannot find the platform you wish to use, you can add it by clicking
+ the "New Platform" button below.</p>
+ <p><a href="{{url_for('species.platforms.create_platform',
+ species_id=species.SpeciesId)}}"
+ title="Create a new genetic sequencing platform for species {{species.FullName}}"
+ class="btn btn-primary">Create Platform</a></p>
+</div>
+
+<div class="row">
+ <h2>Supported Platforms</h2>
+ {%if platforms is defined and platforms | length > 0%}
+ <p>There are {{total_platforms}} platforms supported by GeneNetwork</p>
+
+ <div class="row">
+ <div class="col-md-2" style="text-align: start;">
+ {%if start_from > 0%}
+ <a href="{{url_for('species.platforms.list_platforms',
+ species_id=species.SpeciesId,
+ start_from=start_from-count,
+ count=count)}}">
+ <span class="glyphicon glyphicon-backward"></span>
+ Previous
+ </a>
+ {%endif%}
+ </div>
+ <div class="col-md-8" style="text-align: center;">
+ Displaying platforms {{start_from+1}} to {{start_from+count if start_from+count < total_platforms else total_platforms}} of
+ {{total_platforms}}
+ </div>
+ <div class="col-md-2" style="text-align: end;">
+ {%if start_from + count < total_platforms%}
+ <a href="{{url_for('species.platforms.list_platforms',
+ species_id=species.SpeciesId,
+ start_from=start_from+count,
+ count=count)}}">
+ Next
+ <span class="glyphicon glyphicon-forward"></span>
+ </a>
+ {%endif%}
+ </div>
+ </div>
+
+ <table class="table">
+ <thead>
+ <tr>
+ <th>#</th>
+ <th>Platform Name</th>
+ <th><a href="https://www.ncbi.nlm.nih.gov/geo/browse/?view=platforms&tax={{species.TaxonomyId}}"
+ title="Gene Expression Omnibus: Platforms section"
+ target="_blank">GEO Platform</a></th>
+ <th>Title</th>
+ </tr>
+ </thead>
+
+ <tbody>
+ {%for platform in platforms%}
+ <tr>
+ <td>{{platform.sequence_number}}</td>
+ <td>{{platform.GeneChipName}}</td>
+ <td><a href="https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc={{platform.GeoPlatform}}"
+ title="View platform on the Gene Expression Omnibus"
+ target="_blank">{{platform.GeoPlatform}}</a></td>
+ <td>{{platform.Title}}</td>
+ </tr>
+ {%endfor%}
+ </tbody>
+ </table>
+ {%else%}
+ <p class="text-warning">
+ <span class="glyphicon glyphicon-exclamation-sign"></span>
+ There are no platforms supported at this time!</p>
+ {%endif%}
+</div>
+{%endblock%}
+
+{%block sidebarcontents%}
+{{display_species_card(species)}}
+{%endblock%}