about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-03-29 13:14:14 +0300
committerFrederick Muriuki Muriithi2024-03-29 13:14:14 +0300
commit6326357250711650bc8b4c0b90f8c0b94d72c39e (patch)
tree26bfb9f169f45176dbc439839b7d96d07de52627
parent62e54fd5b457d67f3f01a35e28eae94d653d9908 (diff)
downloadgn-uploader-6326357250711650bc8b4c0b90f8c0b94d72c39e.tar.gz
Add UI to select/create tissue.
-rw-r--r--qc_app/db/tissues.py31
-rw-r--r--qc_app/templates/rqtl2/create-tissue-success.html104
-rw-r--r--qc_app/templates/rqtl2/select-probeset-study-id.html20
-rw-r--r--qc_app/templates/rqtl2/select-tissue.html112
-rw-r--r--qc_app/upload/rqtl2.py104
5 files changed, 349 insertions, 22 deletions
diff --git a/qc_app/db/tissues.py b/qc_app/db/tissues.py
index ebf24fd..062e824 100644
--- a/qc_app/db/tissues.py
+++ b/qc_app/db/tissues.py
@@ -1,5 +1,5 @@
 """Handle db interactions for tissue."""
-from typing import Optional
+from typing import Union, Optional
 
 import MySQLdb as mdb
 from MySQLdb.cursors import DictCursor
@@ -10,6 +10,7 @@ def all_tissues(conn: mdb.Connection) -> tuple[dict, ...]:
         cursor.execute("SELECT * FROM Tissue ORDER BY TissueName")
         return tuple(dict(row) for row in cursor.fetchall())
 
+
 def tissue_by_id(conn: mdb.Connection, tissueid: int) -> Optional[dict]:
     """Retrieve a tissue by its ID"""
     with conn.cursor(cursorclass=DictCursor) as cursor:
@@ -20,3 +21,31 @@ def tissue_by_id(conn: mdb.Connection, tissueid: int) -> Optional[dict]:
             return dict(result)
 
     return None
+
+
+def create_new_tissue(
+        conn: mdb.Connection,
+        name: str,
+        shortname: str,
+        birnlexid: Optional[str] = None,
+        birnlexname: Optional[str] = None
+) -> dict[str, Union[int, str, None]]:
+    """Add a new tissue, organ or biological material to the database."""
+    with conn.cursor() as cursor:
+        cursor.execute(
+            "INSERT INTO "
+            "Tissue(TissueName, Name, Short_Name, BIRN_lex_ID, BIRN_lex_Name) "
+            "VALUES (%s, %s, %s, %s, %s)",
+            (name, name, shortname, birnlexid, birnlexname))
+        tissueid = cursor.lastrowid
+        cursor.execute("UPDATE Tissue SET TissueId=%s WHERE Id=%s",
+                       (tissueid, tissueid))
+        return {
+            "Id": tissueid,
+            "TissueId": tissueid,
+            "TissueName": name,
+            "Name": name,
+            "Short_Name": shortname,
+            "BIRN_lex_ID": birnlexid,
+            "BIRN_lex_Name": birnlexname
+        }
diff --git a/qc_app/templates/rqtl2/create-tissue-success.html b/qc_app/templates/rqtl2/create-tissue-success.html
new file mode 100644
index 0000000..ea05624
--- /dev/null
+++ b/qc_app/templates/rqtl2/create-tissue-success.html
@@ -0,0 +1,104 @@
+{%extends "base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block title%}Upload R/qtl2 Bundle{%endblock%}
+
+{%block contents%}
+<h2 class="heading">Select Tissue</h2>
+
+<div class="explainer">
+  <p>You have successfully added a new tissue, organ or biological material with
+    the following details:</p>
+</div>
+
+{{flash_all_messages()}}
+
+<form id="frm-create-tissue-display"
+      method="POST"
+      action="#">
+  <legend class="heading">Create Tissue</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="tissueid" value="{{tissue.Id}}" />
+
+  <fieldset>
+    <label>Name</label>
+    <label>{{tissue.TissueName}}</label>
+  </fieldset>
+
+  <fieldset>
+    <label>Short Name</label>
+    <label>{{tissue.Short_Name}}</label>
+  </fieldset>
+
+  {%if tissue.BIRN_lex_ID%}
+  <fieldset>
+    <label>BIRN Lex ID</label>
+    <label>{{tissue.BIRN_lex_ID}}</label>
+  </fieldset>
+  {%endif%}
+
+  {%if tissue.BIRN_lex_Name%}
+  <fieldset>
+    <label>BIRN Lex Name</label>
+    <label>{{tissue.BIRN_lex_Name}}</label>
+  </fieldset>
+  {%endif%}
+</form>
+
+<div id="action-buttons"
+     style="width:65ch;display:inline-grid;column-gap:5px;">
+
+  <form id="frm-create-tissue-success-continue"
+        method="POST"
+        action="{{url_for('upload.rqtl2.select_dataset_info',
+	        species_id=species.SpeciesId,
+	        population_id=population.InbredSetId)}}"
+        style="display: inline; width: 100%; grid-column: 1 / 2;
+               padding-top: 0.5em; text-align: center; border: none;
+               background-color: inherit;">
+
+    <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="tissueid" value="{{tissue.Id}}" />
+
+    <input type="submit"
+	   value="continue"
+	   class="btn btn-main form-col-2" />
+  </form>
+
+  <p style="display:inline;width:100%;grid-column:2/3;text-align:center;
+            color:#336699;font-weight:bold;">
+    OR
+  </p>
+
+  <form id="frm-create-tissue-success-select-existing"
+        method="POST"
+        action="{{url_for('upload.rqtl2.select_tissue',
+	        species_id=species.SpeciesId,
+	        population_id=population.InbredSetId)}}"
+        style="display: inline; width: 100%; grid-column: 3 / 4;
+               padding-top: 0.5em; text-align: center; border: none;
+               background-color: inherit;">
+
+    <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="submit"
+	   value="select from existing tissues"
+	   class="btn btn-main form-col-2" />
+  </form>
+
+</div>
+
+{%endblock%}
diff --git a/qc_app/templates/rqtl2/select-probeset-study-id.html b/qc_app/templates/rqtl2/select-probeset-study-id.html
index 3bbb94a..23bbbf0 100644
--- a/qc_app/templates/rqtl2/select-probeset-study-id.html
+++ b/qc_app/templates/rqtl2/select-probeset-study-id.html
@@ -26,6 +26,7 @@
   <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="tissueid" value="{{tissue.Id}}" />
 
   <fieldset>
     <label for="select:probe-study">Study</label>
@@ -71,6 +72,7 @@
   <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="tissueid" value="{{tissue.Id}}" />
 
   <fieldset>
     <label for="select:platform">Platform</label>
@@ -90,24 +92,6 @@
   </fieldset>
 
   <fieldset>
-    <label for="select:tissue">Tissue</label>
-    <select id="select:tissue"
-	    name="tissueid"
-	    required="required"
-	    {%if tissues | length == 0%}disabled="disabled"{%endif%}>
-      <option value="">Select tissue</option>
-      {%for tissue in tissues%}
-      <option value="{{tissue.Id}}">
-	{{tissue.TissueName}} ({{tissue.Short_Name}})
-      </option>
-      {%endfor%}
-    </select>
-    <span class="form-col-2">
-      Select the Tissue to which the data is concerned.
-    </span>
-  </fieldset>
-
-  <fieldset>
     <label for="txt:studyname">Study name</label>
     <input type="text" id="txt:studyname" name="studyname"
 	   placeholder="Name of the study. (Required)"
diff --git a/qc_app/templates/rqtl2/select-tissue.html b/qc_app/templates/rqtl2/select-tissue.html
new file mode 100644
index 0000000..6f7d134
--- /dev/null
+++ b/qc_app/templates/rqtl2/select-tissue.html
@@ -0,0 +1,112 @@
+{%extends "base.html"%}
+{%from "flash_messages.html" import flash_messages%}
+
+{%block title%}Upload R/qtl2 Bundle{%endblock%}
+
+{%block contents%}
+<h2 class="heading">Tissue</h2>
+
+<div class="explainer">
+  <p>The data you are uploading concerns a tissue, cell, organ, or other
+    biological material used in an experiment.</p>
+  <p>Select the appropriate biological material below</p>
+</div>
+
+{%if tissues | length > 0%}
+<form method="POST"
+      action="{{url_for('upload.rqtl2.select_tissue',
+	      species_id=species.SpeciesId, population_id=population.Id)}}"
+      id="frm:select-probeset-dataset">
+  <legend class="heading">Select from existing ProbeSet datasets</legend>
+  {{flash_messages("error-select-tissue")}}
+
+  <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}}" />
+
+  <fieldset>
+    <label for="select-tissue">Tissue</label>
+    <select id="select-tissue"
+	    name="tissueid"
+	    required="required"
+	    {%if tissues | length == 0%}disabled="disabled"{%endif%}>
+      <option value="">Select a tissue</option>
+      {%for tissue in tissues%}
+      <option value={{tissue.Id}}>
+	{{tissue.Name}}
+	{%if tissue.Short_Name%}
+	 -- ({{tissue.Short_Name}})
+	{%endif%}
+      </option>
+      {%endfor%}
+    </select>
+
+    <span class="form-col-2">Select from existing biological material.</span>
+  </fieldset>
+
+  <fieldset>
+    <input type="submit"
+	   value="use selected"
+	   class="btn btn-main form-col-2" />
+  </fieldset>
+</form>
+
+<p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p>
+{%endif%}
+
+<div class="explainer">
+  <p>If you cannot find the biological material in the drop-down above, add it
+    to the system below.</p>
+</div>
+
+<form method="POST"
+      action="{{url_for('upload.rqtl2.create_tissue',
+	      species_id=species.SpeciesId, population_id=population.Id)}}"
+      id="frm:create-probeset-dataset">
+  <legend class="heading">Add new tissue, organ or biological material</legend>
+  {{flash_messages("error-create-tissue")}}
+
+  <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}}" />
+
+  <fieldset>
+    <label for="tissue-name">name</label>
+    <input type="text"
+           id="txt-tissuename"
+           name="tissuename"
+           required="required"
+           title = "A name to identify the tissue, organ or biological material." />
+
+    <span class="form-col-2">
+      A name to identify the tissue, organ or biological material.
+    </span>
+  </fieldset>
+
+  <fieldset>
+    <label for="txt-shortname">short name</label>
+    <input type="text" id="txt-tissueshortname" name="tissueshortname"
+	   required="required"
+	   maxlength="7"
+	   title="A short name (e.g. 'Mam') for the biological material." />
+
+    <span class="form-col-2">
+      Provide a short name for the tissue, organ or biological material used in
+      the experiment.
+    </span>
+  </fieldset>
+
+  <fieldset>
+    <input type="submit"
+	   value="add new material"
+	   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 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."""