From d02cef83c3c0b3f3098df1a7e7eeaf90430f784a Mon Sep 17 00:00:00 2001
From: Frederick Muriuki Muriithi
Date: Thu, 8 Feb 2024 15:54:32 +0300
Subject: R/qtl2 QC: Set up scaffolding for QC UI
Set up the scaffolding for the flows and UI that will be used when
running QC against the uploaded R/qtl2 bundle.
This will be fleshed out later, and the UI is likely to change
somewhat, down the line.
---
qc_app/templates/base.html | 2 +-
qc_app/templates/rqtl2/rqtl2-qc-job-error.html | 32 ++++++++++++
qc_app/templates/rqtl2/rqtl2-qc-job-status.html | 29 +++++++++++
qc_app/templates/rqtl2/rqtl2-qc-job-success.html | 37 ++++++++++++++
qc_app/upload/rqtl2.py | 63 +++++++++++++++++-------
5 files changed, 144 insertions(+), 19 deletions(-)
create mode 100644 qc_app/templates/rqtl2/rqtl2-qc-job-error.html
create mode 100644 qc_app/templates/rqtl2/rqtl2-qc-job-status.html
create mode 100644 qc_app/templates/rqtl2/rqtl2-qc-job-success.html
(limited to 'qc_app')
diff --git a/qc_app/templates/base.html b/qc_app/templates/base.html
index 3b701bc..2228356 100644
--- a/qc_app/templates/base.html
+++ b/qc_app/templates/base.html
@@ -6,7 +6,7 @@
{%block extrameta%}{%endblock%}
-
QC: {%block title%}{%endblock%}
+ GN Uploader: {%block title%}{%endblock%}
{%block css%}{%endblock%}
diff --git a/qc_app/templates/rqtl2/rqtl2-qc-job-error.html b/qc_app/templates/rqtl2/rqtl2-qc-job-error.html
new file mode 100644
index 0000000..5d2ebee
--- /dev/null
+++ b/qc_app/templates/rqtl2/rqtl2-qc-job-error.html
@@ -0,0 +1,32 @@
+{%extends "base.html"%}
+{%from "cli-output.html" import cli_output%}
+
+{%block title%}R/qtl2 bundle: QC Job Error{%endblock%}
+
+{%block contents%}
+R/qtl2 bundle: QC job Error
+
+
+
The R/qtl2 bundle has failed some Quality Control checks.
+
We list below some of the errors that need to be fixed before the data can
+ be uploaded onto GeneNetwork.
+
+
+Errors
+
+list errors here by file type, I think …
+
+stdout
+{{cli_output(job, "stdout")}}
+
+stderr
+{{cli_output(job, "stderr")}}
+
+Log
+
+ {%for msg in messages%}
+ {{msg}}
+ {%endfor%}
+
+
+{%endblock%}
diff --git a/qc_app/templates/rqtl2/rqtl2-qc-job-status.html b/qc_app/templates/rqtl2/rqtl2-qc-job-status.html
new file mode 100644
index 0000000..85b8864
--- /dev/null
+++ b/qc_app/templates/rqtl2/rqtl2-qc-job-status.html
@@ -0,0 +1,29 @@
+{%extends "base.html"%}
+{%from "flash_messages.html" import flash_messages%}
+
+{%block title%}Job Status{%endblock%}
+
+{%block extrameta%}
+
+{%endblock%}
+
+{%block contents%}
+R/qtl2 bundle: QC job status
+
+R/qtl2 bundle: QC Job Status
+
+
+The job:
+
+{{job}}
+
+
+
+Log
+
+ {%for msg in messages%}
+ {{msg}}
+ {%endfor%}
+
+
+{%endblock%}
diff --git a/qc_app/templates/rqtl2/rqtl2-qc-job-success.html b/qc_app/templates/rqtl2/rqtl2-qc-job-success.html
new file mode 100644
index 0000000..396f241
--- /dev/null
+++ b/qc_app/templates/rqtl2/rqtl2-qc-job-success.html
@@ -0,0 +1,37 @@
+{%extends "base.html"%}
+{%from "flash_messages.html" import flash_all_messages%}
+
+{%block title%}R/qtl2 Bundle: Quality Control Successful{%endblock%}
+
+{%block contents%}
+R/qtl2 Bundle: Quality Control Successful
+
+
+
The R/qtl2 bundle you uploaded has passed all quality control
+ checks successfully, and is now ready for uploading into the database.
+
Click "Continue" below to proceed.
+
+
+
+
+
+{%endblock%}
diff --git a/qc_app/upload/rqtl2.py b/qc_app/upload/rqtl2.py
index 9d787e1..afe0c2e 100644
--- a/qc_app/upload/rqtl2.py
+++ b/qc_app/upload/rqtl2.py
@@ -18,8 +18,6 @@ from flask import (
current_app as app)
from r_qtl import r_qtl2
-from r_qtl import r_qtl2_qc as rqc
-from r_qtl.errors import InvalidFormat
from qc_app import jobs
from qc_app.files import save_file, fullpath
@@ -135,12 +133,6 @@ class __RequestError__(Exception): #pylint: disable=[invalid-name]
methods=["GET", "POST"])
def upload_rqtl2_bundle(species_id: int, population_id: int):
"""Allow upload of R/qtl2 bundle."""
- this_page_with_errors = redirect(url_for("upload.rqtl2.upload_rqtl2_bundle",
- species_id=species_id,
- population_id=population_id,
- pgsrc="error"),
- code=307)
-
with database_connection(app.config["SQL_URI"]) as conn:
species = species_by_id(conn, species_id)
population = population_by_species_and_id(
@@ -171,17 +163,52 @@ def upload_rqtl2_bundle(species_id: int, population_id: int):
if not is_zipfile(str(the_file)):
raise __RequestError__("Invalid file! Expected a zip file.")
+ redisuri = app.config["REDIS_URL"]
+ with Redis.from_url(redisuri, decode_responses=True) as rconn:
+ jobid = str(uuid4())
+ redis_ttl_seconds = app.config["JOBS_TTL_SECONDS"]
+ jobs.launch_job(
+ jobs.initialise_job(
+ rconn,
+ jobs.jobsnamespace(),
+ jobid,
+ [sys.executable, "-m", "scripts.qc_on_rqtl2_bundle",
+ app.config["SQL_URI"], app.config["REDIS_URL"],
+ jobs.jobsnamespace(), jobid, "--redisexpiry",
+ str(redis_ttl_seconds)],
+ "rqtl2-bundle-qc-job",
+ redis_ttl_seconds,
+ {}),
+ redisuri,
+ f"{app.config['UPLOAD_FOLDER']}/job_errors")
+ return redirect(url_for(
+ "upload.rqtl2.rqtl2_bundle_qc_status", jobid=jobid))
+
+@rqtl2.route("/upload/species/rqtl2-bundle/qc-status/",
+ methods=["GET", "POST"])
+def rqtl2_bundle_qc_status(jobid: UUID):
+ """Check the status of the QC jobs."""
+ with Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn:
try:
- with ZipFile(str(the_file), "r") as zfile:
- rqc.validate_bundle(zfile)
- return render_template(
- "rqtl2/upload-rqtl2-bundle-step-02.html",
- species=species,
- population=population,
- rqtl2_bundle_file=the_file.name)#type: ignore[union-attr]
- except (InvalidFormat, __RequestError__) as exc:
- flash("".join(exc.args), "alert-error error-rqtl2")
- return this_page_with_errors
+ thejob = jobs.job(rconn, jobs.jobsnamespace(), jobid)
+ messagelistname = thejob.get("log-messagelist")
+ logmessages = (rconn.lrange(messagelistname, 0, -1)
+ if bool(messagelistname) else [])
+ jobstatus = thejob["status"]
+ if jobstatus == "error":
+ return render_template("rqtl2/rqtl2-qc-job-error.html",
+ job=thejob,
+ messages=logmessages)
+ if jobstatus == "success":
+ return render_template("rqtl2/rqtl2-qc-job-results.html",
+ job=thejob,
+ messages=logmessages)
+
+ return render_template("rqtl2/rqtl2-qc-job-status.html",
+ job=thejob,
+ messages=tuple())
+ except jobs.JobNotFound:
+ return render_template("rqtl2/no-such-job.html", jobid=jobid)
def check_errors(conn, *args, **kwargs):#pylint: disable=[too-many-return-statements]
"""Check for select errors in the forms and return a page to redirect to."""
--
cgit v1.2.3