diff options
33 files changed, 220 insertions, 112 deletions
diff --git a/scripts/insert_samples.py b/scripts/insert_samples.py index 87f29dc..8493112 100644 --- a/scripts/insert_samples.py +++ b/scripts/insert_samples.py @@ -10,7 +10,7 @@ from redis import Redis from uploader.db_utils import database_connection from uploader.check_connections import check_db, check_redis from uploader.db import species_by_id, population_by_id -from uploader.samples import ( +from uploader.expression_data.samples import ( save_samples_data, read_samples_file, cross_reference_samples) diff --git a/uploader/__init__.py b/uploader/__init__.py index 2d731af..941765d 100644 --- a/uploader/__init__.py +++ b/uploader/__init__.py @@ -9,13 +9,10 @@ from flask_session import Session from uploader.oauth2.client import user_logged_in, authserver_authorise_uri -from .entry import entrybp -from .upload import upload -from .parse import parsebp -from .samples import samples from .base_routes import base from .dbinsert import dbinsertbp from .oauth2.views import oauth2 +from .expression_data import exprdatabp from .errors import register_error_handlers def override_settings_with_envvars( @@ -83,12 +80,9 @@ def create_app(): # setup blueprints app.register_blueprint(base, url_prefix="/") - app.register_blueprint(entrybp, url_prefix="/") - app.register_blueprint(parsebp, url_prefix="/parse") app.register_blueprint(oauth2, url_prefix="/oauth2") - app.register_blueprint(upload, url_prefix="/upload") app.register_blueprint(dbinsertbp, url_prefix="/dbinsert") - app.register_blueprint(samples, url_prefix="/samples") + app.register_blueprint(exprdatabp, url_prefix="/expression-data") register_error_handlers(app) return app diff --git a/uploader/base_routes.py b/uploader/base_routes.py index 9daf439..39db31f 100644 --- a/uploader/base_routes.py +++ b/uploader/base_routes.py @@ -1,9 +1,26 @@ """Basic routes required for all pages""" import os -from flask import Blueprint, send_from_directory + +from flask import Blueprint, render_template, send_from_directory + +from uploader.oauth2.client import user_logged_in base = Blueprint("base", __name__) + +@base.route("/favicon.ico", methods=["GET"]) +def favicon(): + """Return the favicon.""" + return send_from_directory(os.path.join(app.root_path, "static"), + "images/CITGLogo.png", + mimetype="image/png") + + +@base.route("/", methods=["GET"]) +def index(): + """Load the landing page""" + return render_template("index.html" if user_logged_in() else "login.html") + def appenv(): """Get app's guix environment path.""" return os.environ.get("GN_UPLOADER_ENVIRONMENT") diff --git a/uploader/expression_data/__init__.py b/uploader/expression_data/__init__.py new file mode 100644 index 0000000..b773bce --- /dev/null +++ b/uploader/expression_data/__init__.py @@ -0,0 +1,13 @@ +"""Package handling upload of files.""" +from flask import Blueprint + +from .rqtl2 import rqtl2 +from .index import indexbp +from .parse import parsebp +from .samples import samples + +exprdatabp = Blueprint("expression-data", __name__) +exprdatabp.register_blueprint(indexbp, url_prefix="/") +exprdatabp.register_blueprint(rqtl2, url_prefix="/rqtl2") +exprdatabp.register_blueprint(parsebp, url_prefix="/parse") +exprdatabp.register_blueprint(samples, url_prefix="/sample") diff --git a/uploader/entry.py b/uploader/expression_data/index.py index 82034ed..a334c51 100644 --- a/uploader/entry.py +++ b/uploader/expression_data/index.py @@ -18,16 +18,8 @@ from flask import ( from uploader.db import species from uploader.authorisation import require_login from uploader.db_utils import with_db_connection -from uploader.oauth2.client import user_logged_in -entrybp = Blueprint("entry", __name__) - -@entrybp.route("/favicon.ico", methods=["GET"]) -def favicon(): - """Return the favicon.""" - return send_from_directory(os.path.join(app.root_path, "static"), - "images/CITGLogo.png", - mimetype="image/png") +indexbp = Blueprint("index", __name__) def errors(rqst) -> Tuple[str, ...]: @@ -86,12 +78,15 @@ def zip_file_errors(filepath, upload_dir) -> Tuple[str, ...]: return zfile_errors -@entrybp.route("/", methods=["GET"]) + +@indexbp.route("/", methods=["GET"]) +@require_login def index(): - """Load the landing page""" - return render_template("index.html" if user_logged_in() else "login.html") + """Display the expression data index page.""" + return render_template("expression-data/index.html") + -@entrybp.route("/upload", methods=["GET", "POST"]) +@indexbp.route("/upload", methods=["GET", "POST"]) @require_login def upload_file(): """Enables uploading the files""" @@ -104,7 +99,7 @@ def upload_file(): if request_errors: for error in request_errors: flash(error, "alert-danger error-expr-data") - return redirect(url_for("entry.upload_file")) + return redirect(url_for("expression-data.index.upload_file")) filename = secure_filename(request.files["qc_text_file"].filename) if not os.path.exists(upload_dir): @@ -117,14 +112,14 @@ def upload_file(): if zip_errors: for error in zip_errors: flash(error, "alert-danger error-expr-data") - return redirect(url_for("entry.upload_file")) + return redirect(url_for("expression-data.index.upload_file")) - return redirect(url_for("parse.parse", + return redirect(url_for("expression-data.parse.parse", speciesid=request.form["speciesid"], filename=filename, filetype=request.form["filetype"])) -@entrybp.route("/data-review", methods=["GET"]) +@indexbp.route("/data-review", methods=["GET"]) @require_login def data_review(): """Provide some help on data expectations to the user.""" diff --git a/uploader/parse.py b/uploader/expression_data/parse.py index dea4f95..fc1c3f0 100644 --- a/uploader/parse.py +++ b/uploader/expression_data/parse.py @@ -67,7 +67,7 @@ def parse(): errors = True if errors: - return redirect(url_for("entry.upload_file")) + return redirect(url_for("expression-data.index.upload_file")) redisurl = app.config["REDIS_URL"] with Redis.from_url(redisurl, decode_responses=True) as rconn: @@ -79,7 +79,7 @@ def parse(): redisurl, f"{app.config['UPLOAD_FOLDER']}/job_errors") - return redirect(url_for("parse.parse_status", job_id=job["jobid"])) + return redirect(url_for("expression-data.parse.parse_status", job_id=job["jobid"])) @parsebp.route("/status/<job_id>", methods=["GET"]) def parse_status(job_id: str): @@ -104,7 +104,7 @@ def parse_status(job_id: str): errors = jsonpickle.decode( job.get("errors", jsonpickle.encode(tuple()))) if status in ("success", "aborted"): - return redirect(url_for("parse.results", job_id=job_id)) + return redirect(url_for("expression-data.parse.results", job_id=job_id)) if status == "parse-error": return redirect(url_for("parse.fail", job_id=job_id)) @@ -175,4 +175,4 @@ def abort(): key="user_aborted", value=int(True)) - return redirect(url_for("parse.parse_status", job_id=job_id)) + return redirect(url_for("expression-data.parse.parse_status", job_id=job_id)) diff --git a/uploader/upload/rqtl2.py b/uploader/expression_data/rqtl2.py index ff7556d..48df66c 100644 --- a/uploader/upload/rqtl2.py +++ b/uploader/expression_data/rqtl2.py @@ -68,9 +68,9 @@ def select_species(): lambda conn: species_by_id(conn, species_id)) if bool(species): return redirect(url_for( - "upload.rqtl2.select_population", species_id=species_id)) + "expression-data.rqtl2.select_population", species_id=species_id)) flash("Invalid species or no species selected!", "alert-error error-rqtl2") - return redirect(url_for("upload.rqtl2.select_species")) + return redirect(url_for("expression-data.rqtl2.select_species")) @rqtl2.route("/upload/species/<int:species_id>/select-population", @@ -82,7 +82,7 @@ def select_population(species_id: int): species = species_by_id(conn, species_id) if not bool(species): flash("Invalid species selected!", "alert-error error-rqtl2") - return redirect(url_for("upload.rqtl2.select_species")) + return redirect(url_for("expression-data.rqtl2.select_species")) if request.method == "GET": return render_template( @@ -95,10 +95,10 @@ def select_population(species_id: int): if not bool(population): flash("Invalid Population!", "alert-error error-rqtl2") return redirect( - url_for("upload.rqtl2.select_population", pgsrc="error"), + url_for("expression-data.rqtl2.select_population", pgsrc="error"), code=307) - return redirect(url_for("upload.rqtl2.upload_rqtl2_bundle", + return redirect(url_for("expression-data.rqtl2.upload_rqtl2_bundle", species_id=species["SpeciesId"], population_id=population["InbredSetId"])) @@ -108,7 +108,7 @@ def select_population(species_id: int): @require_login def create_population(species_id: int): """Create a new population for the given species.""" - population_page = redirect(url_for("upload.rqtl2.select_population", + population_page = redirect(url_for("expression-data.rqtl2.select_population", species_id=species_id)) with database_connection(app.config["SQL_URI"]) as conn: species = species_by_id(conn, species_id) @@ -116,7 +116,7 @@ def create_population(species_id: int): population_fullname = request.form.get("inbredset_fullname", "").strip() if not bool(species): flash("Invalid species!", "alert-error error-rqtl2") - return redirect(url_for("upload.rqtl2.select_species")) + return redirect(url_for("expression-data.rqtl2.select_species")) if not bool(population_name): flash("Invalid Population Name!", "alert-error error-rqtl2") return population_page @@ -134,7 +134,7 @@ def create_population(species_id: int): flash("Population created successfully.", "alert-success") return redirect( - url_for("upload.rqtl2.upload_rqtl2_bundle", + url_for("expression-data.rqtl2.upload_rqtl2_bundle", species_id=species_id, population_id=new_population["population_id"], pgsrc="create-population"), @@ -157,11 +157,11 @@ def upload_rqtl2_bundle(species_id: int, population_id: int): conn, species["SpeciesId"], population_id) if not bool(species): flash("Invalid species!", "alert-error error-rqtl2") - return redirect(url_for("upload.rqtl2.select_species")) + return redirect(url_for("expression-data.rqtl2.select_species")) if not bool(population): flash("Invalid Population!", "alert-error error-rqtl2") return redirect( - url_for("upload.rqtl2.select_population", pgsrc="error"), + url_for("expression-data.rqtl2.select_population", pgsrc="error"), code=307) if request.method == "GET" or ( request.method == "POST" @@ -178,7 +178,7 @@ def upload_rqtl2_bundle(species_id: int, population_id: int): app.logger.debug(traceback.format_exc()) flash("Please provide a valid R/qtl2 zip bundle.", "alert-error error-rqtl2") - return redirect(url_for("upload.rqtl2.upload_rqtl2_bundle", + return redirect(url_for("expression-data.rqtl2.upload_rqtl2_bundle", species_id=species_id, population_id=population_id)) @@ -192,7 +192,7 @@ def upload_rqtl2_bundle(species_id: int, population_id: int): the_file, request.files["rqtl2_bundle_file"].filename)#type: ignore[arg-type] return redirect(url_for( - "upload.rqtl2.rqtl2_bundle_qc_status", jobid=jobid)) + "expression-data.rqtl2.rqtl2_bundle_qc_status", jobid=jobid)) def trigger_rqtl2_bundle_qc( @@ -255,7 +255,7 @@ def upload_rqtl2_bundle_chunked_get(# pylint: disable=["unused-argument"] """ Extension to the `upload_rqtl2_bundle` endpoint above that provides a way for testing whether all the chunks have been uploaded and to assist with - resuming a failed upload. + resuming a failed expression-data. """ fileid = request.args.get("resumableIdentifier", type=str) or "" filename = request.args.get("resumableFilename", type=str) or "" @@ -335,7 +335,7 @@ def upload_rqtl2_bundle_chunked_post(species_id: int, population_id: int): jobid = trigger_rqtl2_bundle_qc( species_id, population_id, _targetfile, _uploadfilename) return url_for( - "upload.rqtl2.rqtl2_bundle_qc_status", jobid=jobid) + "expression-data.rqtl2.rqtl2_bundle_qc_status", jobid=jobid) except Exception as exc:# pylint: disable=[broad-except] msg = "Error processing uploaded file chunks." app.logger.error(msg, exc_info=True, stack_info=True) @@ -422,7 +422,7 @@ def check_species(conn: mdb.Connection, formargs: dict) -> Optional[ corresponding species exists in the database. Maybe give the function a better name...""" - speciespage = redirect_on_error("upload.rqtl2.select_species") + speciespage = redirect_on_error("expression-data.rqtl2.select_species") if "species_id" not in formargs: return "You MUST provide the Species identifier.", speciespage @@ -441,7 +441,7 @@ def check_population(conn: mdb.Connection, Maybe give the function a better name...""" poppage = redirect_on_error( - "upload.rqtl2.select_species", species_id=species_id) + "expression-data.rqtl2.select_species", species_id=species_id) if "population_id" not in formargs: return "You MUST provide the Population identifier.", poppage @@ -456,12 +456,12 @@ def check_r_qtl2_bundle(formargs: dict, species_id, population_id) -> Optional[tuple[str, Response]]: """Check for the existence of the R/qtl2 bundle.""" - fileuploadpage = redirect_on_error("upload.rqtl2.upload_rqtl2_bundle", + fileuploadpage = redirect_on_error("expression-data.rqtl2.upload_rqtl2_bundle", species_id=species_id, population_id=population_id) if not "rqtl2_bundle_file" in formargs: return ( - "You MUST provide a R/qtl2 zip bundle for upload.", fileuploadpage) + "You MUST provide a R/qtl2 zip bundle for expression-data.", fileuploadpage) if not Path(fullpath(formargs["rqtl2_bundle_file"])).exists(): return "No R/qtl2 bundle with the given name exists.", fileuploadpage @@ -474,7 +474,7 @@ def check_geno_dataset(conn: mdb.Connection, species_id, population_id) -> Optional[tuple[str, Response]]: """Check for the Genotype dataset.""" - genodsetpg = redirect_on_error("upload.rqtl2.select_dataset_info", + genodsetpg = redirect_on_error("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id) if not bool(formargs.get("geno-dataset-id")): @@ -499,7 +499,7 @@ def check_geno_dataset(conn: mdb.Connection, def check_tissue( conn: mdb.Connection,formargs: dict) -> Optional[tuple[str, Response]]: """Check for tissue/organ/biological material.""" - selectdsetpg = redirect_on_error("upload.rqtl2.select_dataset_info", + selectdsetpg = redirect_on_error("expression-data.rqtl2.select_dataset_info", species_id=formargs["species_id"], population_id=formargs["population_id"]) if not bool(formargs.get("tissueid", "").strip()): @@ -527,7 +527,7 @@ def check_probe_study(conn: mdb.Connection, species_id, population_id) -> Optional[tuple[str, Response]]: """Check for the ProbeSet study.""" - dsetinfopg = redirect_on_error("upload.rqtl2.select_dataset_info", + dsetinfopg = redirect_on_error("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id) if not bool(formargs.get("probe-study-id")): @@ -545,7 +545,7 @@ def check_probe_dataset(conn: mdb.Connection, species_id, population_id) -> Optional[tuple[str, Response]]: """Check for the ProbeSet dataset.""" - dsetinfopg = redirect_on_error("upload.rqtl2.select_dataset_info", + dsetinfopg = redirect_on_error("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id) if not bool(formargs.get("probe-dataset-id")): @@ -583,17 +583,17 @@ def select_geno_dataset(species_id: int, population_id: int): if not bool(geno_dset): flash("No genotype dataset was provided!", "alert-error error-rqtl2") - return redirect(url_for("upload.rqtl2.select_geno_dataset", + return redirect(url_for("expression-data.rqtl2.select_geno_dataset", species_id=species_id, population_id=population_id, pgsrc="error"), code=307) flash("Genotype accepted", "alert-success error-rqtl2") - return redirect(url_for("upload.rqtl2.select_dataset_info", + return redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id, - pgsrc="upload.rqtl2.select_geno_dataset"), + pgsrc="expression-data.rqtl2.select_geno_dataset"), code=307) return with_errors(__thunk__, @@ -617,7 +617,7 @@ def create_geno_dataset(species_id: int, population_id: int): """Create a new geno dataset.""" with database_connection(app.config["SQL_URI"]) as conn: def __thunk__(): - sgeno_page = redirect(url_for("upload.rqtl2.select_dataset_info", + sgeno_page = redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id, pgsrc="error"), @@ -649,7 +649,7 @@ def create_geno_dataset(species_id: int, population_id: int): f"A genotype dataset with name '{escape(datasetname)}' " "already exists.", errorclasses) - return redirect(url_for("upload.rqtl2.select_dataset_info", + return redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id, pgsrc="error"), @@ -691,10 +691,10 @@ def select_tissue(species_id: int, population_id: int): flash("Invalid tissue selection!", "alert-error error-select-tissue error-rqtl2") - return redirect(url_for("upload.rqtl2.select_dataset_info", + return redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id, - pgsrc="upload.rqtl2.select_geno_dataset"), + pgsrc="expression-data.rqtl2.select_geno_dataset"), code=307) return with_errors(__thunk__, @@ -718,10 +718,10 @@ 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", + url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id, - pgsrc="upload.rqtl2.select_geno_dataset"), + pgsrc="expression-data.rqtl2.select_geno_dataset"), code=307) with database_connection(app.config["SQL_URI"]) as conn: tissuename = form.get("tissuename", "").strip() @@ -763,7 +763,7 @@ 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: def __thunk__(): - summary_page = redirect(url_for("upload.rqtl2.select_dataset_info", + summary_page = redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id), code=307) @@ -799,7 +799,7 @@ def select_probeset_dataset(species_id: int, population_id: int): """Select or create a probeset dataset.""" with database_connection(app.config["SQL_URI"]) as conn: def __thunk__(): - summary_page = redirect(url_for("upload.rqtl2.select_dataset_info", + summary_page = redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id), code=307) @@ -843,7 +843,7 @@ def create_probeset_study(species_id: int, population_id: int): def __thunk__(): form = request.form dataset_info_page = redirect( - url_for("upload.rqtl2.select_dataset_info", + url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id), code=307) @@ -905,7 +905,7 @@ def create_probeset_dataset(species_id: int, population_id: int):#pylint: disabl with database_connection(app.config["SQL_URI"]) as conn: def __thunk__():#pylint: disable=[too-many-return-statements] form = request.form - summary_page = redirect(url_for("upload.rqtl2.select_dataset_info", + summary_page = redirect(url_for("expression-data.rqtl2.select_dataset_info", species_id=species_id, population_id=population_id), code=307) @@ -1126,7 +1126,7 @@ def confirm_bundle_details(species_id: int, population_id: int): redisuri, f"{app.config['UPLOAD_FOLDER']}/job_errors") - return redirect(url_for("upload.rqtl2.rqtl2_processing_status", + return redirect(url_for("expression-data.rqtl2.rqtl2_processing_status", jobid=jobid)) return with_errors(__thunk__, diff --git a/uploader/samples.py b/uploader/expression_data/samples.py index 7a80336..95b9b73 100644 --- a/uploader/samples.py +++ b/uploader/expression_data/samples.py @@ -45,7 +45,7 @@ def select_species(): return render_template("samples/select-species.html", species=with_db_connection(fetch_species)) - index_page = redirect(url_for("entry.upload_file")) + index_page = redirect(url_for("expression-data.index.upload_file")) species_id = request.form.get("species_id") if bool(species_id): species_id = int(species_id) @@ -67,13 +67,13 @@ def create_population(species_id: int): flash("You did not provide a valid species. Please select one to " "continue.", "alert-danger") - return redirect(url_for("samples.select_species")) + return redirect(url_for("expression-data.samples.select_species")) species = with_db_connection(lambda conn: species_by_id(conn, species_id)) if not bool(species): flash("Species with given ID was not found.", "alert-danger") - return redirect(url_for("samples.select_species")) + return redirect(url_for("expression-data.samples.select_species")) - species_page = redirect(url_for("samples.select_species"), code=307) + species_page = redirect(url_for("expression-data.samples.select_species"), code=307) with database_connection(app.config["SQL_URI"]) as conn: species = species_by_id(conn, species_id) pop_name = request.form.get("inbredset_name", "").strip() @@ -110,11 +110,11 @@ def select_population(species_id: int): flash("You did not provide a valid species. Please select one to " "continue.", "alert-danger") - return redirect(url_for("samples.select_species")) + return redirect(url_for("expression-data.samples.select_species")) species = with_db_connection(lambda conn: species_by_id(conn, species_id)) if not bool(species): flash("Species with given ID was not found.", "alert-danger") - return redirect(url_for("samples.select_species")) + return redirect(url_for("expression-data.samples.select_species")) if request.method == "GET": return render_template( @@ -247,11 +247,11 @@ def upload_samples(species_id: int, population_id: int):#pylint: disable=[too-ma flash("You did not provide a valid species. Please select one to " "continue.", "alert-danger") - return redirect(url_for("samples.select_species")) + return redirect(url_for("expression-data.samples.select_species")) species = with_db_connection(lambda conn: species_by_id(conn, species_id)) if not bool(species): flash("Species with given ID was not found.", "alert-danger") - return redirect(url_for("samples.select_species")) + return redirect(url_for("expression-data.samples.select_species")) if not is_integer_input(population_id): flash("You did not provide a valid population. Please select one " diff --git a/uploader/templates/base.html b/uploader/templates/base.html index 40a1255..58227f4 100644 --- a/uploader/templates/base.html +++ b/uploader/templates/base.html @@ -44,13 +44,14 @@ <aside id="nav-sidebar" class="container-fluid"> <ul class="nav flex-column"> <li><a href="/" >Home</a></li> + <li><a href="{{url_for('expression-data.index.index')}}" >Expression Data</a></li> </ul> </aside> <main id="main" class="main container-fluid"> <div class="pagetitle row"> - <h1>GN Uploader: {%block pagetitle%}%{%endblock%}</h1> + <h1>GN Uploader: {%block pagetitle%}{%endblock%}</h1> <nav> <ol class="breadcrumb"> {%block breadcrumb%}{%endblock%} diff --git a/uploader/templates/data_review.html b/uploader/templates/data_review.html index b7528fd..4e5c586 100644 --- a/uploader/templates/data_review.html +++ b/uploader/templates/data_review.html @@ -26,7 +26,7 @@ <small class="text-muted"> If you encounter an error saying your sample(s)/case(s) do not exist in the GeneNetwork database, then you will have to use the - <a href="{{url_for('samples.select_species')}}" + <a href="{{url_for('expression-data.samples.select_species')}}" title="Upload samples/cases feature">Upload Samples/Cases</a> option on this system to upload them. </small> diff --git a/uploader/templates/expression-data/index.html b/uploader/templates/expression-data/index.html new file mode 100644 index 0000000..ed5d8dd --- /dev/null +++ b/uploader/templates/expression-data/index.html @@ -0,0 +1,95 @@ +{%extends "base.html"%} +{%from "flash_messages.html" import flash_all_messages%} + +{%block title%}Expression Data{%endblock%} + +{%block pagetitle%}Expression Data{%endblock%} + +{%block breadcrumb%} +<li class="breadcrumb-item"> + <a href="{{url_for('base.index')}}">Home</a> +</li> +<li class="breadcrumb-item active"> + <a href="{{url_for('expression-data.index.index')}}">Expression Data</a> +</li> +{%endblock%} + +{%block contents%} +<div class="row"> + {{flash_all_messages()}} + + <h1 class="heading">data upload</h1> + + <div class="explainer"> + <p>Each of the sections below gives you a different option for data expression-data. + Please read the documentation for each section carefully to understand what + each section is about.</p> + </div> +</div> + +<div class="row"> + <h2 class="heading">R/qtl2 Bundles</h2> + + <div class="explainer"> + <p>This feature combines and extends the two upload methods below. Instead of + uploading one item at a time, the R/qtl2 bundle you upload can contain both + the genotypes data (samples/individuals/cases and their data) and the + expression data.</p> + <p>The R/qtl2 bundle, additionally, can contain extra metadata, that neither + of the methods below can handle.</p> + + <a href="{{url_for('expression-data.rqtl2.select_species')}}" + title="Upload a zip bundle of R/qtl2 files"> + <button class="btn btn-primary">upload R/qtl2 bundle</button></a> + </div> +</div> + + +<div class="row"> + <h2 class="heading">Expression Data</h2> + + <div class="explainer"> + <p>This feature enables you to upload expression data. It expects the data to + be in <strong>tab-separated values (TSV)</strong> files. The data should be + a simple matrix of <em>phenotype × sample</em>, i.e. The first column is a + list of the <em>phenotypes</em> and the first row is a list of + <em>samples/cases</em>.</p> + + <p>If you haven't done so please go to this page to learn the requirements for + file formats and helpful suggestions to enter your data in a fast and easy + way.</p> + + <ol> + <li><strong>PLEASE REVIEW YOUR DATA.</strong>Make sure your data complies + with our system requirements. ( + <a href="{{url_for('expression-data.index.data_review')}}#data-concerns" + title="Details for the data expectations.">Help</a> + )</li> + <li><strong>UPLOAD YOUR DATA FOR DATA VERIFICATION.</strong> We accept + <strong>.csv</strong>, <strong>.txt</strong> and <strong>.zip</strong> + files (<a href="{{url_for('expression-data.index.data_review')}}#file-types" + title="Details for the data expectations.">Help</a>)</li> + </ol> + </div> + + <a href="{{url_for('expression-data.index.upload_file')}}" + title="Upload your expression data" + class="btn btn-primary">upload expression data</a> +</div> + +<div class="row"> + <h2 class="heading">samples/cases</h2> + + <div class="explainer"> + <p>For the expression data above, you need the samples/cases in your file to + already exist in the GeneNetwork database. If there are any samples that do + not already exist the upload of the expression data will fail.</p> + <p>This section gives you the opportunity to upload any missing samples</p> + </div> + + <a href="{{url_for('expression-data.samples.select_species')}}" + title="Upload samples/cases/individuals for your data" + class="btn btn-primary">upload Samples/Cases</a> +</div> + +{%endblock%} diff --git a/uploader/templates/index.html b/uploader/templates/index.html index e99b031..75d7dec 100644 --- a/uploader/templates/index.html +++ b/uploader/templates/index.html @@ -7,7 +7,7 @@ {%block breadcrumb%} <li class="breadcrumb-item active"> - <a href="{{url_for('entry.index')}}">Home</a> + <a href="{{url_for('base.index')}}">Home</a> </li> {%endblock%} diff --git a/uploader/templates/job_progress.html b/uploader/templates/job_progress.html index 1af0763..2feaa89 100644 --- a/uploader/templates/job_progress.html +++ b/uploader/templates/job_progress.html @@ -11,7 +11,7 @@ <h1 class="heading">{{job_name}}</h2> <div class="row"> - <form action="{{url_for('parse.abort')}}" method="POST"> + <form action="{{url_for('expression-data.parse.abort')}}" method="POST"> <legend class="heading">Status</legend> <div class="form-group"> <label for="job_status" class="form-label">status:</label> diff --git a/uploader/templates/no_such_job.html b/uploader/templates/no_such_job.html index 42a2d48..874d047 100644 --- a/uploader/templates/no_such_job.html +++ b/uploader/templates/no_such_job.html @@ -1,7 +1,7 @@ {%extends "base.html"%} {%block extrameta%} -<meta http-equiv="refresh" content="5;url={{url_for('entry.upload_file')}}"> +<meta http-equiv="refresh" content="5;url={{url_for('expression-data.index.upload_file')}}"> {%endblock%} {%block title%}No Such Job{%endblock%} diff --git a/uploader/templates/parse_results.html b/uploader/templates/parse_results.html index e2bf7f0..46fbaaf 100644 --- a/uploader/templates/parse_results.html +++ b/uploader/templates/parse_results.html @@ -21,7 +21,7 @@ {%if errors | length > 0 or user_aborted %} <br /> -<a href="{{url_for('entry.upload_file')}}" title="Back to index page." +<a href="{{url_for('expression-data.index.upload_file')}}" title="Back to index page." class="btn btn-primary"> Go back </a> diff --git a/uploader/templates/rqtl2/create-geno-dataset-success.html b/uploader/templates/rqtl2/create-geno-dataset-success.html index 1b50221..bb6d63d 100644 --- a/uploader/templates/rqtl2/create-geno-dataset-success.html +++ b/uploader/templates/rqtl2/create-geno-dataset-success.html @@ -33,7 +33,7 @@ <div class="row"> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/rqtl2/create-probe-dataset-success.html b/uploader/templates/rqtl2/create-probe-dataset-success.html index 790d174..03b75c7 100644 --- a/uploader/templates/rqtl2/create-probe-dataset-success.html +++ b/uploader/templates/rqtl2/create-probe-dataset-success.html @@ -36,7 +36,7 @@ <div class="row"> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/rqtl2/create-probe-study-success.html b/uploader/templates/rqtl2/create-probe-study-success.html index d0ee508..e293f6f 100644 --- a/uploader/templates/rqtl2/create-probe-study-success.html +++ b/uploader/templates/rqtl2/create-probe-study-success.html @@ -28,7 +28,7 @@ </p> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/rqtl2/create-tissue-success.html b/uploader/templates/rqtl2/create-tissue-success.html index 5f2c5a0..d6fe154 100644 --- a/uploader/templates/rqtl2/create-tissue-success.html +++ b/uploader/templates/rqtl2/create-tissue-success.html @@ -56,7 +56,7 @@ <form id="frm-create-tissue-success-continue" method="POST" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" style="display: inline; width: 100%; grid-column: 1 / 2; @@ -85,7 +85,7 @@ <div class="row"> <form id="frm-create-tissue-success-select-existing" method="POST" - action="{{url_for('upload.rqtl2.select_tissue', + action="{{url_for('expression-data.rqtl2.select_tissue', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" style="display: inline; width: 100%; grid-column: 3 / 4; diff --git a/uploader/templates/rqtl2/index.html b/uploader/templates/rqtl2/index.html index f3329c2..8ce13bf 100644 --- a/uploader/templates/rqtl2/index.html +++ b/uploader/templates/rqtl2/index.html @@ -8,7 +8,7 @@ <h2>R/qtl2 Upload</h2> -<form method="POST" action="{{url_for('upload.rqtl2.select_species')}}" +<form method="POST" action="{{url_for('expression-data.rqtl2.select_species')}}" id="frm-rqtl2-upload"> <legend class="heading">upload R/qtl2 bundle</legend> {{flash_messages("error-rqtl2")}} diff --git a/uploader/templates/rqtl2/rqtl2-qc-job-results.html b/uploader/templates/rqtl2/rqtl2-qc-job-results.html index 59bc8cd..b3c3a8f 100644 --- a/uploader/templates/rqtl2/rqtl2-qc-job-results.html +++ b/uploader/templates/rqtl2/rqtl2-qc-job-results.html @@ -15,7 +15,7 @@ <div class="row"> <form id="form-qc-job-results" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.Id)}}" method="POST"> diff --git a/uploader/templates/rqtl2/rqtl2-qc-job-success.html b/uploader/templates/rqtl2/rqtl2-qc-job-success.html index 2861a04..f126835 100644 --- a/uploader/templates/rqtl2/rqtl2-qc-job-success.html +++ b/uploader/templates/rqtl2/rqtl2-qc-job-success.html @@ -18,7 +18,7 @@ --> <div class="row"> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/rqtl2/select-geno-dataset.html b/uploader/templates/rqtl2/select-geno-dataset.html index 873f9c3..1db51e0 100644 --- a/uploader/templates/rqtl2/select-geno-dataset.html +++ b/uploader/templates/rqtl2/select-geno-dataset.html @@ -15,7 +15,7 @@ <div class="row"> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.select_geno_dataset', + action="{{url_for('expression-data.rqtl2.select_geno_dataset', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" @@ -62,7 +62,7 @@ <div class="row"> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.create_geno_dataset', + action="{{url_for('expression-data.rqtl2.create_geno_dataset', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/rqtl2/select-population.html b/uploader/templates/rqtl2/select-population.html index 37731f0..7d27303 100644 --- a/uploader/templates/rqtl2/select-population.html +++ b/uploader/templates/rqtl2/select-population.html @@ -17,7 +17,7 @@ </div> <form method="POST" - action="{{url_for('upload.rqtl2.select_population', species_id=species.SpeciesId)}}"> + action="{{url_for('expression-data.rqtl2.select_population', species_id=species.SpeciesId)}}"> <legend class="heading">select grouping/population</legend> {{flash_messages("error-select-population")}} @@ -47,7 +47,7 @@ <p style="color:#FE3535; padding-left:20em; font-weight:bolder;">OR</p> <form method="POST" - action="{{url_for('upload.rqtl2.create_population', species_id=species.SpeciesId)}}"> + action="{{url_for('expression-data.rqtl2.create_population', species_id=species.SpeciesId)}}"> <legend class="heading">create new grouping/population</legend> {{flash_messages("error-create-population")}} diff --git a/uploader/templates/rqtl2/select-probeset-dataset.html b/uploader/templates/rqtl2/select-probeset-dataset.html index 26f52ed..74f8f69 100644 --- a/uploader/templates/rqtl2/select-probeset-dataset.html +++ b/uploader/templates/rqtl2/select-probeset-dataset.html @@ -15,7 +15,7 @@ {%if datasets | length > 0%} <div class="row"> <form method="POST" - action="{{url_for('upload.rqtl2.select_probeset_dataset', + action="{{url_for('expression-data.rqtl2.select_probeset_dataset', species_id=species.SpeciesId, population_id=population.Id)}}" id="frm:select-probeset-dataset"> <legend class="heading">Select from existing ProbeSet datasets</legend> @@ -68,7 +68,7 @@ <div class="row"> <form method="POST" - action="{{url_for('upload.rqtl2.create_probeset_dataset', + action="{{url_for('expression-data.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> diff --git a/uploader/templates/rqtl2/select-probeset-study-id.html b/uploader/templates/rqtl2/select-probeset-study-id.html index b9bf52e..e3fd9cc 100644 --- a/uploader/templates/rqtl2/select-probeset-study-id.html +++ b/uploader/templates/rqtl2/select-probeset-study-id.html @@ -12,7 +12,7 @@ <p>In this page, you can either select from a existing dataset:</p> <form method="POST" - action="{{url_for('upload.rqtl2.select_probeset_study', + action="{{url_for('expression-data.rqtl2.select_probeset_study', species_id=species.SpeciesId, population_id=population.Id)}}" id="frm:select-probeset-study"> <legend class="heading">Select from existing ProbeSet studies</legend> @@ -62,7 +62,7 @@ <p>Create a new ProbeSet dataset below:</p> <form method="POST" - action="{{url_for('upload.rqtl2.create_probeset_study', + action="{{url_for('expression-data.rqtl2.create_probeset_study', species_id=species.SpeciesId, population_id=population.Id)}}" id="frm:create-probeset-study"> <legend class="heading">Create new ProbeSet study</legend> diff --git a/uploader/templates/rqtl2/select-tissue.html b/uploader/templates/rqtl2/select-tissue.html index 34e1758..fe3080a 100644 --- a/uploader/templates/rqtl2/select-tissue.html +++ b/uploader/templates/rqtl2/select-tissue.html @@ -15,7 +15,7 @@ {%if tissues | length > 0%} <div class="row"> <form method="POST" - action="{{url_for('upload.rqtl2.select_tissue', + action="{{url_for('expression-data.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> @@ -65,7 +65,7 @@ to the system below.</p> <form method="POST" - action="{{url_for('upload.rqtl2.create_tissue', + action="{{url_for('expression-data.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> diff --git a/uploader/templates/rqtl2/summary-info.html b/uploader/templates/rqtl2/summary-info.html index 1be87fa..0adba2e 100644 --- a/uploader/templates/rqtl2/summary-info.html +++ b/uploader/templates/rqtl2/summary-info.html @@ -44,7 +44,7 @@ <div class="row"> <form id="frm:confirm-rqtl2bundle-details" - action="{{url_for('upload.rqtl2.confirm_bundle_details', + action="{{url_for('expression-data.rqtl2.confirm_bundle_details', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html index 07c240f..9d45c5f 100644 --- a/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html +++ b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html @@ -71,13 +71,13 @@ </div> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.upload_rqtl2_bundle', + action="{{url_for('expression-data.rqtl2.upload_rqtl2_bundle', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" enctype="multipart/form-data" data-resumable-target="{{url_for( - 'upload.rqtl2.upload_rqtl2_bundle_chunked_post', + 'expression-data.rqtl2.upload_rqtl2_bundle_chunked_post', species_id=species.SpeciesId, population_id=population.InbredSetId)}}"> <input type="hidden" name="species_id" value="{{species.SpeciesId}}" /> diff --git a/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html index 93b1dc9..8210ed0 100644 --- a/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html +++ b/uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html @@ -14,7 +14,7 @@ <p>Click "Continue" below to proceed.</p> <form id="frm-upload-rqtl2-bundle" - action="{{url_for('upload.rqtl2.select_dataset_info', + action="{{url_for('expression-data.rqtl2.select_dataset_info', species_id=species.SpeciesId, population_id=population.InbredSetId)}}" method="POST" diff --git a/uploader/templates/samples/select-species.html b/uploader/templates/samples/select-species.html index edadc61..aa64ecf 100644 --- a/uploader/templates/samples/select-species.html +++ b/uploader/templates/samples/select-species.html @@ -10,7 +10,7 @@ {{flash_all_messages()}} -<form method="POST" action="{{url_for('samples.select_species')}}"> +<form method="POST" action="{{url_for('expression-data.samples.select_species')}}"> <legend class="heading">upload samples</legend> <div class="form-group"> <label for="select_species02" class="form-label">Species</label> diff --git a/uploader/templates/select_species.html b/uploader/templates/select_species.html index 3b1a8a9..1642401 100644 --- a/uploader/templates/select_species.html +++ b/uploader/templates/select_species.html @@ -10,7 +10,7 @@ <h2 class="heading">expression data: select species</h2> <div class="row"> - <form action="{{url_for('entry.upload_file')}}" + <form action="{{url_for('expression-data.index.upload_file')}}" method="POST" enctype="multipart/form-data" id="frm-upload-expression-data"> diff --git a/uploader/upload/__init__.py b/uploader/upload/__init__.py deleted file mode 100644 index 5f120d4..0000000 --- a/uploader/upload/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Package handling upload of files.""" -from flask import Blueprint - -from .rqtl2 import rqtl2 - -upload = Blueprint("upload", __name__) -upload.register_blueprint(rqtl2, url_prefix="/rqtl2") |