about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-01-18 14:43:00 +0300
committerFrederick Muriuki Muriithi2024-01-18 14:43:00 +0300
commitaf485aff7d25c1f5128586c550ca36debe24fd66 (patch)
tree16593e9e7a11cbd2ae2f5ab228f6620520a0b1b2
parent0369fc21eaa54466bd64f3b12d1fe6a1dbc81de0 (diff)
downloadgn-uploader-af485aff7d25c1f5128586c550ca36debe24fd66.tar.gz
UI: Create new ProbeSet dataset.
-rw-r--r--qc_app/db/averaging.py23
-rw-r--r--qc_app/db/datasets.py33
-rw-r--r--qc_app/templates/rqtl2/create-probe-dataset-success.html60
-rw-r--r--qc_app/templates/rqtl2/select-probeset-dataset.html82
-rw-r--r--qc_app/upload/rqtl2.py65
5 files changed, 260 insertions, 3 deletions
diff --git a/qc_app/db/averaging.py b/qc_app/db/averaging.py
new file mode 100644
index 0000000..62bbe67
--- /dev/null
+++ b/qc_app/db/averaging.py
@@ -0,0 +1,23 @@
+"""Functions for db interactions for averaging methods"""
+from typing import Optional
+
+import MySQLdb as mdb
+from MySQLdb.cursors import DictCursor
+
+def averaging_methods(conn: mdb.Connection) -> tuple[dict, ...]:
+    """Fetch all available averaging methods"""
+    with conn.cursor(cursorclass=DictCursor) as cursor:
+        cursor.execute("SELECT * FROM AvgMethod")
+        return tuple(dict(row) for row in cursor.fetchall())
+
+def averaging_method_by_id(
+        conn: mdb.Connection, averageid: int) -> Optional[dict]:
+    """Fetch the averaging method by its ID"""
+    with conn.cursor(cursorclass=DictCursor) as cursor:
+        cursor.execute("SELECT * FROM AvgMethod WHERE Id=%s",
+                       (averageid,))
+        result = cursor.fetchone()
+        if bool(result):
+            return dict(result)
+
+    return None
diff --git a/qc_app/db/datasets.py b/qc_app/db/datasets.py
index 5f6a2d5..5816146 100644
--- a/qc_app/db/datasets.py
+++ b/qc_app/db/datasets.py
@@ -85,3 +85,36 @@ def probeset_create_study(conn: mdb.Connection,#pylint: disable=[too-many-argume
         cursor.execute("UPDATE ProbeFreeze SET ProbeFreezeId=%s",
                        (studyid,))
         return {**studydata, "studyid": studyid}
+
+def probeset_create_dataset(conn: mdb.Connection,#pylint: disable=[too-many-arguments]
+                            studyid: int,
+                            averageid: int,
+                            datasetname: str,
+                            datasetfullname: str,
+                            datasetshortname: str="",
+                            public: bool = True,
+                            datascale="log2") -> dict:
+    """Create a new ProbeSet dataset."""
+    with conn.cursor(cursorclass=DictCursor) as cursor:
+        dataset = {
+            "studyid": studyid,
+            "averageid": averageid,
+            "name2": datasetname,
+            "fname": datasetfullname,
+            "name": datasetshortname,
+            "sname": datasetshortname,
+            "today": date.today().isoformat(),
+            "public": 2 if public else 0,
+            "datascale": datascale
+        }
+        cursor.execute(
+            """
+            insert into ProbeSetFreeze(
+              ProbeFreezeId, AvgId, Name, Name2, FullName, ShortName,
+              CreateTime, public, DataScale)
+            VALUES(
+              %(studyid)s, %(averageid)s, %(name)s, %(name2)s, %(fname)s,
+              %(sname)s, %(today)s, %(public)s, %(datascale)s)
+            """,
+            dataset)
+        return {**dataset, "datasetid": cursor.lastrowid}
diff --git a/qc_app/templates/rqtl2/create-probe-dataset-success.html b/qc_app/templates/rqtl2/create-probe-dataset-success.html
new file mode 100644
index 0000000..33612c4
--- /dev/null
+++ b/qc_app/templates/rqtl2/create-probe-dataset-success.html
@@ -0,0 +1,60 @@
+{%extends "base.html"%}
+{%from "flash_messages.html" import flash_messages%}
+
+{%block title%}Upload R/qtl2 Bundle{%endblock%}
+
+{%block contents%}
+<h2 class="heading">Create ProbeSet Dataset</h2>
+
+<div class="explainer">
+  <p>You successfully created the ProbeSet dataset with the following
+    information.
+    <dl>
+      <dt>Averaging Method</dt>
+      <dd>{{avgmethod.Name}}</dd>
+
+      <dt>ID</dt>
+      <dd>{{dataset.datasetid}}</dd>
+
+      <dt>Name</dt>
+      <dd>{{dataset.name2}}</dd>
+
+      <dt>Full Name</dt>
+      <dd>{{dataset.fname}}</dd>
+
+      <dt>Short Name</dt>
+      <dd>{{dataset.sname}}</dd>
+
+      <dt>Created On</dt>
+      <dd>{{dataset.today}}</dd>
+
+      <dt>DataScale</dt>
+      <dd>{{dataset.datascale}}</dd>
+    </dl>
+  </p>
+</div>
+
+<form id="frm-upload-rqtl2-bundle"
+      action="{{url_for('upload.rqtl2.select_dataset_info',
+	      species_id=species.SpeciesId,
+	      population_id=population.InbredSetId)}}"
+      method="POST"
+      enctype="multipart/form-data">
+  <legend class="heading">Create ProbeSet dataset</legend>
+
+  <input type="hidden" name="species_id" value="{{species.SpeciesId}}" />
+  <input type="hidden" name="population_id"
+	 value="{{population.InbredSetId}}" />
+  <input type="hidden" name="rqtl2_bundle_file" value="{{rqtl2_bundle_file}}" />
+  <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" />
+  <input type="hidden" name="probe-study-id" value="{{study.Id}}" />
+  <input type="hidden" name="probe-dataset-id" value="{{dataset.datasetid}}" />
+
+  <fieldset>
+    <input type="submit"
+	   value="continue"
+	   class="btn btn-main form-col-2" />
+  </fieldset>
+</form>
+
+{%endblock%}
diff --git a/qc_app/templates/rqtl2/select-probeset-dataset.html b/qc_app/templates/rqtl2/select-probeset-dataset.html
index 8b9e5ed..3e160fd 100644
--- a/qc_app/templates/rqtl2/select-probeset-dataset.html
+++ b/qc_app/templates/rqtl2/select-probeset-dataset.html
@@ -14,6 +14,7 @@
 
 {{flash_all_messages()}}
 
+{%if datasets | length > 0%}
 <form method="POST"
       action="{{url_for('upload.rqtl2.select_probeset_dataset',
 	      species_id=species.SpeciesId, population_id=population.Id)}}"
@@ -53,6 +54,85 @@
   </fieldset>
 </form>
 
-<p style="color: red; font-weight: bold;">Under Construction</p>
+<p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p>
+{%endif%}
+
+<form method="POST"
+      action="{{url_for('upload.rqtl2.create_probeset_dataset',
+	      species_id=species.SpeciesId, population_id=population.Id)}}"
+      id="frm:create-probeset-dataset">
+  <legend class="heading">Create a new ProbeSet dataset</legend>
+
+  <input type="hidden" name="species_id" value="{{species.SpeciesId}}" />
+  <input type="hidden" name="population_id"
+	 value="{{population.InbredSetId}}" />
+  <input type="hidden" name="rqtl2_bundle_file"
+	 value="{{rqtl2_bundle_file}}" />
+  <input type="hidden" name="geno-dataset-id" value="{{geno_dataset.Id}}" />
+  <input type="hidden" name="probe-study-id" value="{{probe_study.Id}}" />
+
+  <fieldset>
+    <label for="select:average">averaging method</label>
+    <select id="select:average"
+	    name="averageid"
+	    required="required">
+      <option value="">Select averaging method</option>
+      {%for avgmethod in avgmethods%}
+      <option value="{{avgmethod.Id}}">
+	{{avgmethod.Name}}
+	{%if avgmethod.Normalization%}
+	({{avgmethod.Normalization}})
+	{%endif%}
+      </option>
+      {%endfor%}
+    </select>
+  </fieldset>
+
+  <fieldset>
+    <label for="txt:datasetname">Name</label>
+    <input type="text" id="txt:datasetname" name="datasetname"
+	   required="required"
+	   title="Name of the dataset, e.g 'BXDMicroArray_ProbeSet_June03'. (Required)" />
+  </fieldset>
+
+  <fieldset>
+    <label for="txt:datasetfullname">Full Name</label>
+    <input type="text" id="txt:datasetfullname" name="datasetfullname"
+	   required="required"
+	   title="A longer name for the dataset, e.g. 'UTHSC Brain mRNA U74Av2 (Jun03) MAS5'. (Required)" />
+  </fieldset>
+
+  <fieldset>
+    <label for="txt:datasetshortname">Short Name</label>
+    <input type="text" id="txt:datasetshortname" name="datasetshortname"
+	   title="An abbreviated name for the dataset, e.g 'Br_U_0603_M'. (Optional)" />
+  </fieldset>
+
+  <fieldset>
+    <input type="checkbox" id="chk:public" name="datasetpublic"
+	   checked="checked"
+	   title="Whether or not the dataset is accessible by the general public." />
+    <label for="chk:datasetpublic">Public?</label>
+  </fieldset>
+
+  <fieldset>
+    <label for="select:datasetdatascale">Data Scale</label>
+    <select id="select:datasetdatascale"
+	    name="datasetdatascale"
+	    required="required">
+      <option value="log2" selected="selected">log2</option>
+      <option value="z_score">z_score</option>
+      <option value="log2_ratio">log2_ratio</option>
+      <option value="linear">linear</option>
+      <option value="linear_positive">linear_positive</option>
+    </select>
+  </fieldset>
+
+  <fieldset>
+    <input type="submit"
+	   value="create dataset"
+	   class="btn btn-main form-col-2" />
+  </fieldset>
+</form>
 
 {%endblock%}
diff --git a/qc_app/upload/rqtl2.py b/qc_app/upload/rqtl2.py
index fc4e0e8..0b446ac 100644
--- a/qc_app/upload/rqtl2.py
+++ b/qc_app/upload/rqtl2.py
@@ -22,6 +22,7 @@ from qc_app.db_utils import with_db_connection, database_connection
 
 from qc_app.db.tissues import all_tissues, tissue_by_id
 from qc_app.db.platforms import platform_by_id, platforms_by_species
+from qc_app.db.averaging import averaging_methods, averaging_method_by_id
 from qc_app.db import (
     species_by_id,
     save_population,
@@ -33,6 +34,7 @@ from qc_app.db.datasets import (
 
     probeset_study_by_id,
     probeset_create_study,
+    probeset_create_dataset,
     probeset_datasets_by_study,
     probeset_studies_by_species_and_population)
 
@@ -349,7 +351,7 @@ def select_probeset_dataset(species_id: int, population_id: int):
                                         population_id=population_id),
                                 code=307)
         if not bool(probeset_study_by_id(conn, int(request.form["probe-study-id"]))):
-            flash("Invalid dataset selected!", "alert-error alert-rqtl2")
+            flash("Invalid study selected!", "alert-error alert-rqtl2")
             return summary_page
 
         return summary_page
@@ -398,6 +400,64 @@ def create_probeset_study(species_id: int, population_id: int):
             study=study)
 
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
+              "/rqtl2-bundle/create-probeset-dataset"),
+             methods=["POST"])
+def create_probeset_dataset(species_id: int, population_id: int):#pylint: disable=[too-many-return-statements]
+    """Create a new probeset dataset."""
+    with database_connection(app.config["SQL_URI"]) as conn:
+        error = check_errors(
+            conn, "species", "population", "rqtl2_bundle_file", "geno-dataset",
+            "probe-study-id")
+        if bool(error):
+            return error
+
+        form = request.form
+        summary_page = redirect(url_for("upload.rqtl2.select_dataset_info",
+                                        species_id=species_id,
+                                        population_id=population_id),
+                                code=307)
+        if not bool(form.get("averageid")):
+            flash("Averaging method not selected!", "alert-error alert-rqtl2")
+            return summary_page
+        if not bool(form.get("datasetname")):
+            flash("Dataset name not provided!", "alert-error alert-rqtl2")
+            return summary_page
+        if not bool(form.get("datasetfullname")):
+            flash("Dataset full name not provided!", "alert-error alert-rqtl2")
+            return summary_page
+
+        study = probeset_study_by_id(conn, int(form["probe-study-id"]))
+        if not bool(study):
+            flash("Invalid ProbeSet study provided!", "alert-error alert-rqtl2")
+            return summary_page
+
+        avgmethod = averaging_method_by_id(conn, int(form["averageid"]))
+        if not bool(avgmethod):
+            flash("Invalid averaging method provided!", "alert-error alert-rqtl2")
+            return summary_page
+
+        dset = probeset_create_dataset(conn,
+                                       int(form["probe-study-id"]),
+                                       int(form["averageid"]),
+                                       form["datasetname"],
+                                       form["datasetfullname"],
+                                       form["datasetshortname"],
+                                       form["datasetpublic"] == "on",
+                                       form.get("datasetdatascale", "log2"))
+        return render_template(
+            "rqtl2/create-probe-dataset-success.html",
+            species=species_by_id(conn, species_id),
+            population=population_by_species_and_id(
+                conn, species_id, population_id),
+            rqtl2_bundle_file=request.form["rqtl2_bundle_file"],
+            geno_dataset=geno_dataset_by_id(
+                conn,
+                int(request.form["geno-dataset-id"])),
+            study=study,
+            avgmethod=avgmethod,
+            dataset=dset)
+
+@rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/dataset-info"),
              methods=["POST"])
 def select_dataset_info(species_id: int, population_id: int):
@@ -450,7 +510,8 @@ def select_dataset_info(species_id: int, population_id: int):
                     geno_dataset=geno_dataset,
                     probe_study=probeset_study,
                     datasets=probeset_datasets_by_study(
-                        conn, int(form["probe-study-id"])))
+                        conn, int(form["probe-study-id"])),
+                    avgmethods=averaging_methods(conn))
 
     return render_template("rqtl2/summary-info.html",
                            species=species,