about summary refs log tree commit diff
path: root/qc_app/upload
diff options
context:
space:
mode:
Diffstat (limited to 'qc_app/upload')
-rw-r--r--qc_app/upload/rqtl2.py104
1 files changed, 101 insertions, 3 deletions
diff --git a/qc_app/upload/rqtl2.py b/qc_app/upload/rqtl2.py
index c05f675..7a53756 100644
--- a/qc_app/upload/rqtl2.py
+++ b/qc_app/upload/rqtl2.py
@@ -28,9 +28,9 @@ from qc_app.files import save_file, fullpath
 from qc_app.dbinsert import species as all_species
 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.tissues import all_tissues, tissue_by_id, create_new_tissue
 from qc_app.db import (
     species_by_id,
     save_population,
@@ -65,6 +65,7 @@ def select_species():
     flash("Invalid species or no species selected!", "alert-error error-rqtl2")
     return redirect(url_for("upload.rqtl2.select_species"))
 
+
 @rqtl2.route("/upload/species/<int:species_id>/select-population",
              methods=["GET", "POST"])
 def select_population(species_id: int):
@@ -93,6 +94,7 @@ def select_population(species_id: int):
                                 species_id=species["SpeciesId"],
                                 population_id=population["InbredSetId"]))
 
+
 @rqtl2.route("/upload/species/<int:species_id>/create-population",
              methods=["POST"])
 def create_population(species_id: int):
@@ -129,9 +131,11 @@ def create_population(species_id: int):
                 pgsrc="create-population"),
         code=307)
 
+
 class __RequestError__(Exception): #pylint: disable=[invalid-name]
     """Internal class to avoid pylint's `too-many-return-statements` error."""
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle"),
     methods=["GET", "POST"])
@@ -197,6 +201,7 @@ def upload_rqtl2_bundle(species_id: int, population_id: int):
             return redirect(url_for(
                 "upload.rqtl2.rqtl2_bundle_qc_status", jobid=jobid))
 
+
 @rqtl2.route("/upload/species/rqtl2-bundle/qc-status/<uuid:jobid>",
              methods=["GET", "POST"])
 def rqtl2_bundle_qc_status(jobid: UUID):
@@ -255,15 +260,18 @@ def rqtl2_bundle_qc_status(jobid: UUID):
         except jobs.JobNotFound:
             return render_template("rqtl2/no-such-job.html", jobid=jobid)
 
+
 def form_errors(formargs, *errorcheckers) -> Iterable[tuple[str, Response]]:
     """Retrieve all errors from the form inputs"""
     return (checker(formargs) for checker in errorcheckers)
 
+
 def redirect_on_error(flaskroute, **kwargs):
     """Utility to redirect on error"""
     return redirect(url_for(flaskroute, **kwargs, pgsrc="error"),
                     code=(307 if request.method == "POST" else 302))
 
+
 def check_species(conn: mdb.Connection, formargs: dict) -> Optional[
         tuple[str, Response]]:
     """
@@ -280,6 +288,7 @@ def check_species(conn: mdb.Connection, formargs: dict) -> Optional[
 
     return None
 
+
 def check_population(conn: mdb.Connection,
                      formargs: dict,
                      species_id) -> Optional[tuple[str, Response]]:
@@ -299,6 +308,7 @@ def check_population(conn: mdb.Connection,
 
     return None
 
+
 def check_r_qtl2_bundle(formargs: dict,
                         species_id,
                         population_id) -> Optional[tuple[str, Response]]:
@@ -315,6 +325,7 @@ def check_r_qtl2_bundle(formargs: dict,
 
     return None
 
+
 def check_geno_dataset(formargs: dict,
                        species_id,
                        population_id) -> Optional[tuple[str, Response]]:
@@ -328,6 +339,7 @@ def check_geno_dataset(formargs: dict,
 
     return None
 
+
 def check_probe_study(formargs: dict,
                       species_id,
                       population_id) -> Optional[tuple[str, Response]]:
@@ -340,6 +352,7 @@ def check_probe_study(formargs: dict,
 
     return None
 
+
 def check_probe_dataset(formargs: dict,
                         species_id,
                         population_id) -> Optional[tuple[str, Response]]:
@@ -352,6 +365,7 @@ def check_probe_dataset(formargs: dict,
 
     return None
 
+
 def with_errors(conn: mdb.Connection, endpointthunk: Callable, *checkerstrings):
     """Run 'endpointthunk' with error checking."""
     formargs = {**dict(request.args), **dict(request.form)}
@@ -378,6 +392,7 @@ def with_errors(conn: mdb.Connection, endpointthunk: Callable, *checkerstrings):
 
     return endpointthunk()
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-geno-dataset"),
              methods=["POST"])
@@ -406,6 +421,7 @@ def select_geno_dataset(species_id: int, population_id: int):
         return with_errors(
             conn, __thunk__, "species", "population", "rqtl2_bundle_file", "geno_dataset")
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-geno-dataset"),
              methods=["POST"])
@@ -457,6 +473,71 @@ def create_geno_dataset(species_id: int, population_id: int):
         return with_errors(conn, __thunk__, "species", "population",
                            "rqtl2_bundle_file")
 
+
+@rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
+              "/rqtl2-bundle/select-tissue"),
+             methods=["POST"])
+def select_tissue(species_id: int, population_id: int):
+    """Select from existing tissues."""
+    with database_connection(app.config["SQL_URI"]) as conn:
+        def __thunk__():
+            if not bool(request.form.get("tissueid", "").strip()):
+                flash("Invalid tissue selection!",
+                      "alert-error error-select-tissue error-rqtl2")
+
+            return redirect(url_for("upload.rqtl2.select_dataset_info",
+                                    species_id=species_id,
+                                    population_id=population_id,
+                                    pgsrc="upload.rqtl2.select_geno_dataset"),
+                            code=307)
+
+        return with_errors(
+            conn, __thunk__, "species", "population", "rqtl2_bundle_file", "geno_dataset")
+
+@rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
+              "/rqtl2-bundle/create-tissue"),
+             methods=["POST"])
+def create_tissue(species_id: int, population_id: int):
+    """Add new tissue, organ or biological material to the system."""
+    form = request.form
+    datasetinfopage = redirect(
+        url_for("upload.rqtl2.select_dataset_info",
+                species_id=species_id,
+                population_id=population_id,
+                pgsrc="upload.rqtl2.select_geno_dataset"),
+    code=307)
+    with database_connection(app.config["SQL_URI"]) as conn:
+        tissuename = form.get("tissuename", "").strip()
+        tissueshortname = form.get("tissueshortname", "").strip()
+        if not bool(tissuename):
+            flash("Organ/Tissue name MUST be provided.",
+                  "alert-error error-create-tissue error-rqtl2")
+            return datasetinfopage
+
+        if not bool(tissueshortname):
+            flash("Organ/Tissue short name MUST be provided.",
+                  "alert-error error-create-tissue error-rqtl2")
+            return datasetinfopage
+
+        try:
+            tissue = create_new_tissue(conn, tissuename, tissueshortname)
+            flash("Tissue created successfully!", "alert-success")
+            return render_template(
+                "rqtl2/create-tissue-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"])),
+                tissue=tissue)
+        except mdb.IntegrityError as _ierr:
+            flash("Tissue/Organ with that short name already exists!",
+                  "alert-error error-create-tissue error-rqtl2")
+            return datasetinfopage
+
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-probeset-study"),
              methods=["POST"])
@@ -477,6 +558,7 @@ def select_probeset_study(species_id: int, population_id: int):
                            "rqtl2_bundle_file", "geno_dataset",
                            "probeset_study")
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-probeset-dataset"),
              methods=["POST"])
@@ -498,6 +580,7 @@ def select_probeset_dataset(species_id: int, population_id: int):
                            "rqtl2_bundle_file", "geno_dataset",
                            "probeset_study", "probeset_dataset")
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-probeset-study"),
              methods=["POST"])
@@ -540,6 +623,7 @@ def create_probeset_study(species_id: int, population_id: int):
         return with_errors(conn, __thunk__, "species", "population",
                            "rqtl2_bundle_file", "geno_dataset")
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-probeset-dataset"),
              methods=["POST"])
@@ -597,6 +681,7 @@ def create_probeset_dataset(species_id: int, population_id: int):#pylint: disabl
                            "rqtl2_bundle_file", "geno_dataset",
                            "probeset_study")
 
+
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/dataset-info"),
              methods=["POST"])
@@ -625,6 +710,19 @@ def select_dataset_info(species_id: int, population_id: int):
                 geno_dataset = geno_dataset_by_id(conn, int(form["geno-dataset-id"]))
 
                 if "pheno" in cdata and not bool(form.get("probe-study-id")):
+                    tissue = tissue_by_id(conn, form.get("tissueid", "").strip())
+                    if not bool(tissue):
+                        return render_template(
+                            "rqtl2/select-tissue.html",
+                            species=species,
+                            population=population,
+                            rqtl2_bundle_file=thefile.name,
+                            geno_dataset=geno_dataset,
+                            studies=probeset_studies_by_species_and_population(
+                                conn, species_id, population_id),
+                            platforms=platforms_by_species(conn, species_id),
+                            tissues=all_tissues(conn))
+
                     return render_template(
                         "rqtl2/select-probeset-study-id.html",
                         species=species,
@@ -634,7 +732,7 @@ def select_dataset_info(species_id: int, population_id: int):
                         studies=probeset_studies_by_species_and_population(
                                 conn, species_id, population_id),
                         platforms=platforms_by_species(conn, species_id),
-                        tissues=all_tissues(conn))
+                        tissue=tissue)
                 probeset_study = probeset_study_by_id(
                     conn, int(form["probe-study-id"]))
 
@@ -666,7 +764,6 @@ def select_dataset_info(species_id: int, population_id: int):
                            "rqtl2_bundle_file")
 
 
-
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/confirm-bundle-details"),
              methods=["POST"])
@@ -719,6 +816,7 @@ def confirm_bundle_details(species_id: int, population_id: int):
                            "rqtl2_bundle_file", "geno_dataset",
                            "probeset_study", "probeset_dataset")
 
+
 @rqtl2.route("/status/<uuid:jobid>")
 def rqtl2_processing_status(jobid: UUID):
     """Retrieve the status of the job processing the uploaded R/qtl2 bundle."""