about summary refs log tree commit diff
path: root/uploader
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-08-28 17:12:26 -0500
committerFrederick Muriuki Muriithi2024-08-28 17:54:17 -0500
commit06c6a7f7f42e8ff2d33a934ff695efde24d26d65 (patch)
tree0ab6115fa7a8ee490cc6efc343c44549c1871281 /uploader
parent05191fa146fac31fd079c50bf6bcc4983f2f0792 (diff)
downloadgn-uploader-06c6a7f7f42e8ff2d33a934ff695efde24d26d65.tar.gz
Move code handling expression data upload into new module.
Diffstat (limited to 'uploader')
-rw-r--r--uploader/__init__.py10
-rw-r--r--uploader/base_routes.py19
-rw-r--r--uploader/expression_data/__init__.py13
-rw-r--r--uploader/expression_data/index.py (renamed from uploader/entry.py)29
-rw-r--r--uploader/expression_data/parse.py (renamed from uploader/parse.py)8
-rw-r--r--uploader/expression_data/rqtl2.py (renamed from uploader/upload/rqtl2.py)72
-rw-r--r--uploader/expression_data/samples.py (renamed from uploader/samples.py)16
-rw-r--r--uploader/templates/base.html3
-rw-r--r--uploader/templates/data_review.html2
-rw-r--r--uploader/templates/expression-data/index.html95
-rw-r--r--uploader/templates/index.html2
-rw-r--r--uploader/templates/job_progress.html2
-rw-r--r--uploader/templates/no_such_job.html2
-rw-r--r--uploader/templates/parse_results.html2
-rw-r--r--uploader/templates/rqtl2/create-geno-dataset-success.html2
-rw-r--r--uploader/templates/rqtl2/create-probe-dataset-success.html2
-rw-r--r--uploader/templates/rqtl2/create-probe-study-success.html2
-rw-r--r--uploader/templates/rqtl2/create-tissue-success.html4
-rw-r--r--uploader/templates/rqtl2/index.html2
-rw-r--r--uploader/templates/rqtl2/rqtl2-qc-job-results.html2
-rw-r--r--uploader/templates/rqtl2/rqtl2-qc-job-success.html2
-rw-r--r--uploader/templates/rqtl2/select-geno-dataset.html4
-rw-r--r--uploader/templates/rqtl2/select-population.html4
-rw-r--r--uploader/templates/rqtl2/select-probeset-dataset.html4
-rw-r--r--uploader/templates/rqtl2/select-probeset-study-id.html4
-rw-r--r--uploader/templates/rqtl2/select-tissue.html4
-rw-r--r--uploader/templates/rqtl2/summary-info.html2
-rw-r--r--uploader/templates/rqtl2/upload-rqtl2-bundle-step-01.html4
-rw-r--r--uploader/templates/rqtl2/upload-rqtl2-bundle-step-02.html2
-rw-r--r--uploader/templates/samples/select-species.html2
-rw-r--r--uploader/templates/select_species.html2
-rw-r--r--uploader/upload/__init__.py7
32 files changed, 219 insertions, 111 deletions
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")