From 33e106334a212853842c30f8c595da1099c3d84e Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Wed, 17 Jan 2024 11:41:43 +0300 Subject: UI: Select ProbeSet study. --- qc_app/db/__init__.py | 2 +- qc_app/db/datasets.py | 30 ++++- .../templates/rqtl2/select-probeset-dataset.html | 17 +++ .../templates/rqtl2/select-probeset-study-id.html | 59 +++++++++ qc_app/upload/rqtl2.py | 132 +++++++++++++++------ 5 files changed, 199 insertions(+), 41 deletions(-) create mode 100644 qc_app/templates/rqtl2/select-probeset-dataset.html create mode 100644 qc_app/templates/rqtl2/select-probeset-study-id.html diff --git a/qc_app/db/__init__.py b/qc_app/db/__init__.py index 270f1a0..36e93e8 100644 --- a/qc_app/db/__init__.py +++ b/qc_app/db/__init__.py @@ -5,4 +5,4 @@ from .populations import ( population_by_id, populations_by_species, population_by_species_and_id) -from .datasets import geno_dataset_by_species_and_population +from .datasets import geno_datasets_by_species_and_population diff --git a/qc_app/db/datasets.py b/qc_app/db/datasets.py index 8122cfa..086c103 100644 --- a/qc_app/db/datasets.py +++ b/qc_app/db/datasets.py @@ -2,7 +2,7 @@ import MySQLdb as mdb from MySQLdb.cursors import DictCursor -def geno_dataset_by_species_and_population( +def geno_datasets_by_species_and_population( conn: mdb.Connection, speciesid: int, populationid: int) -> tuple[dict, ...]: @@ -21,3 +21,31 @@ def geno_dataset_by_id(conn: mdb.Connection, dataset_id: int) -> dict: cursor.execute("SELECT * FROM GenoFreeze WHERE Id=%s", (dataset_id,)) return dict(cursor.fetchone()) + +def probeset_studies_by_species_and_population( + conn: mdb.Connection, + speciesid: int, + populationid: int) -> tuple[dict, ...]: + """Retrieve all probesets""" + with conn.cursor(cursorclass=DictCursor) as cursor: + cursor.execute( + "SELECT pf.* FROM InbredSet AS iset INNER JOIN ProbeFreeze AS pf " + "ON iset.InbredSetId=pf.InbredSetId " + "WHERE iset.SpeciesId=%(sid)s AND iset.InbredSetId=%(pid)s", + {"sid": speciesid, "pid": populationid}) + return tuple(dict(row) for row in cursor.fetchall()) + +def probeset_datasets_by_study(conn: mdb.Connection, + studyid: int) -> tuple[dict, ...]: + """Retrieve all probeset databases by study.""" + with conn.cursor(cursorclass=DictCursor) as cursor: + cursor.execute("SELECT * FROM ProbeSetFreeze WHERE ProbeFreezeId=%s", + (studyid,)) + return tuple(dict(row) for row in cursor.fetchall()) + +def probe_study_by_id(conn: mdb.Connection, studyid: int) -> dict: + """Retrieve ProbeSet study by ID""" + with conn.cursor(cursorclass=DictCursor) as cursor: + cursor.execute("SELECT * FROM ProbeFreeze WHERE Id=%s", + (studyid,)) + return dict(cursor.fetchone()) diff --git a/qc_app/templates/rqtl2/select-probeset-dataset.html b/qc_app/templates/rqtl2/select-probeset-dataset.html new file mode 100644 index 0000000..c0c6401 --- /dev/null +++ b/qc_app/templates/rqtl2/select-probeset-dataset.html @@ -0,0 +1,17 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +

Phenotype(ProbeSet) Dataset

+ +
+

The R/qtl2 bundle you uploaded contains (a) "pheno" + file(s). This data needs to be organised under a dataset..

+

This page gives you the ability to do that.

+
+ +

Under Construction

+ +{%endblock%} diff --git a/qc_app/templates/rqtl2/select-probeset-study-id.html b/qc_app/templates/rqtl2/select-probeset-study-id.html new file mode 100644 index 0000000..bb31fde --- /dev/null +++ b/qc_app/templates/rqtl2/select-probeset-study-id.html @@ -0,0 +1,59 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_messages%} + +{%block title%}Upload R/qtl2 Bundle{%endblock%} + +{%block contents%} +

Phenotype(ProbeSet) Study

+ +
+

The R/qtl2 bundle you uploaded contains (a) "pheno" + file(s). This data needs to be organised under a study.

+

This page gives you the ability to do that.

+
+ +
+ Select from existing ProbeSet datasets + + + + + + +
+ + +
+ +
+ +
+
+ +

OR

+ +
+ Create new ProbeSet dataset + Under construction +
+ +{%endblock%} diff --git a/qc_app/upload/rqtl2.py b/qc_app/upload/rqtl2.py index 6ddc83f..3411f98 100644 --- a/qc_app/upload/rqtl2.py +++ b/qc_app/upload/rqtl2.py @@ -25,7 +25,11 @@ from qc_app.db import ( populations_by_species, population_by_species_and_id,) from qc_app.db.datasets import ( - geno_dataset_by_id, geno_dataset_by_species_and_population) + geno_dataset_by_id, + geno_datasets_by_species_and_population, + + probeset_datasets_by_study, + probeset_studies_by_species_and_population) rqtl2 = Blueprint("rqtl2", __name__) @@ -199,44 +203,16 @@ def check_errors(conn, *args, **kwargs): pgsrc="error"), code=307) - return None - -@rqtl2.route(("/upload/species//population/" - "/rqtl2-bundle/dataset-info"), - methods=["POST"]) -def select_dataset_info(species_id: int, population_id: int): - """ - If `geno` files exist in the R/qtl2 bundle, prompt user to provide the - dataset the genotypes belong to. - """ - form = request.form - with database_connection(app.config["SQL_URI"]) as conn: - error_page = check_errors(conn, "species", "population", "rqtl2_bundle_file") - if bool(error_page): - return error_page - - species = species_by_id(conn, species_id) - population = population_by_species_and_id( - conn, species_id, population_id) - thefile = fullpath(form["rqtl2_bundle_file"]) - with ZipFile(str(thefile), "r") as zfile: - cdata = r_qtl2.control_data(zfile) - if "geno" in cdata and not bool(form.get("geno-dataset-id")): - return render_template( - "rqtl2/select-geno-dataset.html", - species=species, - population=population, - rqtl2_bundle_file=thefile.name, - datasets=geno_dataset_by_species_and_population( - conn, species_id, population_id)) - - geno_dataset = geno_dataset_by_id( - conn, int(form["geno-dataset-id"])) + if ("probe-study-id" in args and + not bool(request.form.get("probe-study-id"))): + flash("No probeset study was selected!", "alert-error alert-rqtl2") + return redirect(url_for("upload.rqtl2.select_probeset_study", + species_id=species_id, + population_id=population_id, + pgsrc="error"), + code=307) - return render_template("rqtl2/summary-info.html", - species=species, - population=population, - geno_dataset=geno_dataset) + return None @rqtl2.route(("/upload/species//population/" "/rqtl2-bundle/select-geno-dataset"), @@ -249,7 +225,7 @@ def select_geno_dataset(species_id: int, population_id: int): if bool(error): return error - geno_dset = geno_dataset_by_species_and_population( + geno_dset = geno_datasets_by_species_and_population( conn, species_id, population_id) if not bool(geno_dset): flash("No genotype dataset was provided!", @@ -321,3 +297,81 @@ def create_geno_dataset(species_id: int, population_id: int): conn, species_id, population_id), rqtl2_bundle_file=request.form["rqtl2_bundle_file"], geno_dataset={**new_dataset, "id": cursor.lastrowid}) + +@rqtl2.route(("/upload/species//population/" + "/rqtl2-bundle/select-probeset-study"), + methods=["POST"]) +def select_probeset_study(species_id: int, population_id: int): + """Select or create a probeset study.""" + 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 + + summary_page = redirect(url_for("upload.rqtl2.select_dataset_info", + species=species_by_id(conn, species_id), + population=population_by_species_and_id( + conn, species_id, population_id)), + code=307) + if not bool(probe_study_by_id(conn, int(request.form["probe-study-id"]))): + flash("Invalid study selected!", "alert-error alert-rqtl2") + return summary_page + + return summary_page + +@rqtl2.route(("/upload/species//population/" + "/rqtl2-bundle/dataset-info"), + methods=["POST"]) +def select_dataset_info(species_id: int, population_id: int): + """ + If `geno` files exist in the R/qtl2 bundle, prompt user to provide the + dataset the genotypes belong to. + """ + form = request.form + with database_connection(app.config["SQL_URI"]) as conn: + error_page = check_errors(conn, "species", "population", "rqtl2_bundle_file") + if bool(error_page): + return error_page + + species = species_by_id(conn, species_id) + population = population_by_species_and_id( + conn, species_id, population_id) + thefile = fullpath(form["rqtl2_bundle_file"]) + with ZipFile(str(thefile), "r") as zfile: + cdata = r_qtl2.control_data(zfile) + if "geno" in cdata and not bool(form.get("geno-dataset-id")): + return render_template( + "rqtl2/select-geno-dataset.html", + species=species, + population=population, + rqtl2_bundle_file=thefile.name, + datasets=geno_datasets_by_species_and_population( + conn, species_id, population_id)) + geno_dataset = geno_dataset_by_id(conn, int(form["geno-dataset-id"])) + + if "pheno" in cdata and not bool(form.get("probe-study-id")): + return render_template( + "rqtl2/select-probeset-study-id.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)) + + if "pheno" in cdata and not bool(form.get("probe-dataset-id")): + return render_template( + "rqtl2/select-probeset-dataset.html", + species=species, + population=population, + rqtl2_bundle_file=thefile.name, + geno_dataset=geno_dataset, + datasets=probeset_datasets_by_study( + conn, int(form["probe-study-id"]))) + + return render_template("rqtl2/summary-info.html", + species=species, + population=population, + geno_dataset=geno_dataset) -- cgit v1.2.3