diff --git a/.github/pr_labels.yml b/.github/pr_labels.yml
deleted file mode 100644
index d04f24f38..000000000
--- a/.github/pr_labels.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-version: '1'
-invalidStatus: "pending"
-labelRule:
- values:
- - "validation"
- - "no validation"
diff --git a/.github/workflows/check_pr_label.yml b/.github/workflows/check_pr_label.yml
new file mode 100644
index 000000000..cac9312cf
--- /dev/null
+++ b/.github/workflows/check_pr_label.yml
@@ -0,0 +1,21 @@
+name: Check Label on PR
+on:
+ pull_request:
+ types: [opened, synchronize, labeled, unlabeled]
+
+jobs:
+ check-pr_label:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout PR
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0 # Fetch all history for all branches and tags
+
+ - name: Check if the PR contains the label validation or no validation
+ id: prlabel_check
+ if: |
+ ! contains( github.event.pull_request.labels.*.name, 'validation') && ! contains( github.event.pull_request.labels.*.name, 'no validation')
+ run: |
+ echo "Neither 'validation' nor 'no validation' labels are present."
+ exit 1 # Exit with a failure
\ No newline at end of file
diff --git a/run_dir/design/deliveries.html b/run_dir/design/deliveries.html
index 676e63379..8cc2fa8d7 100644
--- a/run_dir/design/deliveries.html
+++ b/run_dir/design/deliveries.html
@@ -145,7 +145,13 @@
|
|
- {{ flowcell_id }} |
+ {% set url_addition = "" %}
+ {% if flowcell.get("instrument_type") == "element"%}
+ {% set url_addition = "_element" %}
+ {% elif flowcell.get("instrument_type") == "ont"%}
+ {% set url_addition = "_ont" %}
+ {% end %}
+ {{ flowcell_id }} |
{{ flowcell['flowcell_status'] }} |
diff --git a/run_dir/design/project_samples_old.html b/run_dir/design/project_samples_old.html
index 60996fa6a..ce5dcd88d 100644
--- a/run_dir/design/project_samples_old.html
+++ b/run_dir/design/project_samples_old.html
@@ -135,23 +135,34 @@ User project description
Running Notes
User communication
Links
- {% if not multiqc %}
- Open MultiQC reports
- {% else %}
-
- Open MultiQC reports
-
+
Open bioinfo tab
Agreements
diff --git a/status/bioinfo_analysis.py b/status/bioinfo_analysis.py
index bbf98849d..2b267a9de 100644
--- a/status/bioinfo_analysis.py
+++ b/status/bioinfo_analysis.py
@@ -4,6 +4,7 @@
import dateutil
+from status.reports import MultiQCReportHandler
from status.util import SafeHandler
@@ -282,8 +283,8 @@ def get(self, project_id):
if application in app_classes[key]:
application = key
break
- # to check if multiqc report exists (get_multiqc() is defined in util.BaseHandler)
- multiqc = self.get_multiqc(project_id) or ""
+
+ multiqc = MultiQCReportHandler.get_multiqc(self.application, project_id) or ""
self.write(
t.generate(
gs_globals=self.application.gs_globals,
diff --git a/status/clone_project.py b/status/clone_project.py
index 801980297..e58e23045 100644
--- a/status/clone_project.py
+++ b/status/clone_project.py
@@ -28,32 +28,21 @@ class LIMSProjectCloningHandler(SafeHandler):
"""
def get(self, project_identifier):
- # Check if the project_identifier matches a project id.
- # If not, assuming it's a project name, try to get the project id from the project name,
- # since the LIMS API only accepts project ids
- if not re.match("^(P[0-9]{3,7})", project_identifier):
- try:
- projectid = (
- self.application.projects_db.view("projects/name_to_id")[
- project_identifier
- ]
- .rows[0]
- .value
- )
- except IndexError:
- self.set_status(404)
- return self.write({"error": "Project not found"})
- else:
- projectid = project_identifier
+ projectid = self.get_project_id(project_identifier)
+ if not projectid:
+ self.set_status(404)
+ return self.write({"error": "Project not found"})
+
proj_values = self.get_project_data_from_lims(projectid, "get")
if not proj_values:
self.set_status(404)
self.write({"error": "Project not found"})
return
+
self.set_header("Content-type", "application/json")
self.write(proj_values)
- def post(self, projectid):
+ def post(self, project_identifier):
if not (
self.get_current_user().is_proj_coord
or self.get_current_user().is_any_admin
@@ -63,6 +52,11 @@ def post(self, projectid):
"Error: You do not have the permissions for this operation!"
)
+ projectid = self.get_project_id(project_identifier)
+ if not projectid:
+ self.set_status(404)
+ return self.write({"error": "Project not found"})
+
new_proj = self.get_project_data_from_lims(projectid, "post")
if "error" in new_proj:
self.set_status(400)
@@ -72,7 +66,7 @@ def post(self, projectid):
self.set_status(201)
self.write(new_proj)
- def get_project_data_from_lims(self, projectid, type):
+ def get_project_data_from_lims(self, projectid, req_type):
copy_udfs = {
"Customer project reference",
"Project Comment",
@@ -128,7 +122,7 @@ def get_project_data_from_lims(self, projectid, type):
udfs[udf] = existing_project.udf[udf]
proj_values["udfs"] = udfs
- if type == "get":
+ if req_type == "get":
return proj_values
else:
@@ -149,3 +143,24 @@ def get_project_data_from_lims(self, projectid, type):
return {"error": e.message}
return {"project_id": new_project.id, "project_name": new_project.name}
+
+ def get_project_id(self, project_identifier):
+ """Return projectid for the provided identifier"""
+ # Check if the project_identifier matches a project id.
+ # If not, assuming it's a project name, try to get the project id from the project name,
+ # since the LIMS API only accepts project ids
+ projectid = None
+ if re.match("^(P[0-9]{3,7})", project_identifier):
+ projectid = project_identifier
+ else:
+ try:
+ projectid = (
+ self.application.projects_db.view("projects/name_to_id")[
+ project_identifier
+ ]
+ .rows[0]
+ .value
+ )
+ except IndexError:
+ pass
+ return projectid
diff --git a/status/deliveries.py b/status/deliveries.py
index 7c586f86b..1f11f2825 100644
--- a/status/deliveries.py
+++ b/status/deliveries.py
@@ -159,6 +159,7 @@ def get(self):
# define bioinfo checklist
sample_data = flowcells[flowcell_id][lane_id][sample_id]
+ instrument_type = sample_data.get("instrument_type")
checklist = self.__fill_checklist(sample_data)
if checklist["total"] and len(checklist["total"]) == len(
checklist["passed"]
@@ -233,6 +234,7 @@ def get(self):
flowcell_status = self.__aggregate_status(flowcell_statuses)
runs_bioinfo[flowcell_id]["flowcell_status"] = flowcell_status
runs_bioinfo[flowcell_id]["checklist"] = flowcell_checklists
+ runs_bioinfo[flowcell_id]["instrument_type"] = instrument_type
# add flowcell_status to the status_list (needed for filtering)
if flowcell_status not in status_list:
diff --git a/status/flowcell.py b/status/flowcell.py
index 413a38992..18613a6e9 100644
--- a/status/flowcell.py
+++ b/status/flowcell.py
@@ -470,8 +470,9 @@ def __init__(self, application, request, **kwargs):
super(SafeHandler, self).__init__(application, request, **kwargs)
def get(self, name):
- reports_dir = self.application.minknow_reports_path
- report_path = os.path.join(reports_dir, f"report_{name}.html")
+ report_path = os.path.join(
+ self.application.report_path["minknow"], f"report_{name}.html"
+ )
self.write(open(report_path).read())
@@ -483,8 +484,9 @@ def __init__(self, application, request, **kwargs):
super(SafeHandler, self).__init__(application, request, **kwargs)
def get(self, name):
- reports_dir = self.application.toulligqc_reports_path
- report_path = os.path.join(reports_dir, f"report_{name}.html")
+ report_path = os.path.join(
+ self.application.report_path["toulligqc"], f"report_{name}.html"
+ )
self.write(open(report_path).read())
@@ -758,10 +760,16 @@ def get(self, name):
barcodes=self.fetch_barcodes(name),
args=self.fetch_args(name),
has_minknow_report=os.path.exists(
- f"{self.application.minknow_reports_path}/report_{name}.html"
+ os.path.join(
+ self.application.report_path["minknow"],
+ f"report_{name}.html",
+ )
),
has_toulligqc_report=os.path.exists(
- f"{self.application.toulligqc_reports_path}/report_{name}.html"
+ os.path.join(
+ self.application.report_path["tooulligqc"],
+ f"report_{name}.html",
+ )
),
user=self.get_current_user(),
)
diff --git a/status/multiqc_report.py b/status/multiqc_report.py
deleted file mode 100644
index d0fe92008..000000000
--- a/status/multiqc_report.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from status.util import SafeHandler
-
-
-class MultiQCReportHandler(SafeHandler):
- def get(self, project):
- type = self.get_argument("type")
- # get_multiqc() is defined in BaseHandler
- multiqc_report = self.get_multiqc(project)
- if multiqc_report:
- self.write(multiqc_report[type])
- else:
- t = self.application.loader.load("error_page.html")
- self.write(
- t.generate(
- gs_globals=self.application.gs_globals,
- status="404",
- reason="MultiQC Report Not Found",
- user=self.get_current_user(),
- )
- )
diff --git a/status/projects.py b/status/projects.py
index b30264f37..59068ec97 100644
--- a/status/projects.py
+++ b/status/projects.py
@@ -5,6 +5,7 @@
import itertools
import json
import logging
+import re
from collections import OrderedDict
import dateutil.parser
@@ -13,9 +14,15 @@
from dateutil.relativedelta import relativedelta
from genologics import lims
from genologics.config import BASEURI, PASSWORD, USERNAME
-from genologics.entities import Artifact, Project
+from genologics.entities import Artifact
+from ibm_cloud_sdk_core.api_exception import ApiException
from zenpy import ZenpyException
+from status.reports import (
+ MultiQCReportHandler,
+ ProjectSummaryReportHandler,
+ SingleCellSampleSummaryReportHandler,
+)
from status.util import SafeHandler, dthandler
lims = lims.Lims(BASEURI, USERNAME, PASSWORD)
@@ -593,6 +600,13 @@ def search_project_names(self, search_string=""):
}
projects.append(project)
+ # Sort projects by project number so that the latest P-number is first
+ projects = sorted(
+ projects,
+ key=lambda x: int(x["name"].split(",")[0].replace("P", "")),
+ reverse=True,
+ )
+
return projects
@@ -693,7 +707,9 @@ def project_info(self, project, view_with_sources=False):
"_qc_": "QC MultiQC",
"_pipeline_": "Pipeline MultiQC",
}
- for report_type in self.get_multiqc(project, read_file=False).keys():
+ for report_type in MultiQCReportHandler.get_multiqc(
+ self.application, project, read_file=False
+ ).keys():
# Attempt to assign a name of the report type, otherwise default to the type itself
report_name = type_to_name.get(report_type, report_type)
reports[report_name] = f"/multiqc_report/{project}?type={report_type}"
@@ -962,8 +978,38 @@ def get(self, project):
worksets_view = self.application.worksets_db.view(
"project/ws_name", descending=True
)
- # to check if multiqc report exists (get_multiqc() is defined in util.BaseHandler)
- multiqc = list(self.get_multiqc(project).keys())
+
+ reports = {}
+ multiqc = list(
+ MultiQCReportHandler.get_multiqc(
+ self.application, project, read_file=False
+ ).keys()
+ )
+ if multiqc:
+ reports["multiqc"] = multiqc
+ if ProjectSummaryReportHandler.get_summary_report(
+ self.application, project, read_file=False
+ ):
+ reports["project_summary"] = True
+ sample_summary_reports = (
+ SingleCellSampleSummaryReportHandler.get_sample_summary_reports(
+ self.application, project
+ )
+ )
+ if sample_summary_reports:
+ group_summary_reports = {}
+ for report in sample_summary_reports:
+ # Match report names in the format _(_<(optional)>)_report.html/pdf
+ match = re.match(
+ rf"^({project}_\d+)_([^_]+(_[^_]+)?)_report\.(pdf|html)", report
+ )
+ if match:
+ sample_id = match.group(1)
+ method = match.group(2)
+ if sample_id not in group_summary_reports:
+ group_summary_reports[sample_id] = {}
+ group_summary_reports[sample_id][method] = report
+ reports["sample_summary_reports"] = group_summary_reports
self.write(
t.generate(
gs_globals=self.application.gs_globals,
@@ -974,7 +1020,7 @@ def get(self, project):
lims_dashboard_url=self.application.settings["lims_dashboard_url"],
prettify=prettify_css_names,
worksets=worksets_view[project],
- multiqc=multiqc,
+ reports=reports,
lims_uri=BASEURI,
)
)
@@ -1025,11 +1071,15 @@ class LinksDataHandler(SafeHandler):
"""
def get(self, project):
- self.set_header("Content-type", "application/json")
- p = Project(lims, id=project)
- p.get(force=True)
-
- links = json.loads(p.udf["Links"]) if "Links" in p.udf else {}
+ links_doc = {}
+ try:
+ links_doc = self.application.cloudant.get_document(
+ db="gs_links", doc_id=project
+ ).get_result()
+ except ApiException as e:
+ if e.message == "not_found":
+ pass
+ links = links_doc.get("links", {})
# Sort by descending date, then hopefully have deviations on top
sorted_links = OrderedDict()
@@ -1038,6 +1088,8 @@ def get(self, project):
sorted_links = OrderedDict(
sorted(sorted_links.items(), key=lambda k: k[1]["type"])
)
+
+ self.set_header("Content-type", "application/json")
self.write(sorted_links)
def post(self, project):
@@ -1051,19 +1103,39 @@ def post(self, project):
self.set_status(400)
self.finish("Link title and type is required")
else:
- p = Project(lims, id=project)
- p.get(force=True)
- links = json.loads(p.udf["Links"]) if "Links" in p.udf else {}
- links[str(datetime.datetime.now())] = {
- "user": user.name,
- "email": user.email,
- "type": a_type,
- "title": title,
- "url": url,
- "desc": desc,
- }
- p.udf["Links"] = json.dumps(links)
- p.put()
+ links_doc = {}
+ links = {}
+ try:
+ links_doc = self.application.cloudant.get_document(
+ db="gs_links", doc_id=project
+ ).get_result()
+ except ApiException as e:
+ if e.message == "not_found":
+ links_doc["_id"] = project
+ links_doc["links"] = {}
+ links = links_doc.get("links", {})
+ links.update(
+ {
+ str(datetime.datetime.now()): {
+ "user": user.name,
+ "email": user.email,
+ "type": a_type,
+ "title": title,
+ "url": url,
+ "desc": desc,
+ }
+ }
+ )
+ links_doc["links"] = links
+
+ response = self.application.cloudant.post_document(
+ db="gs_links", document=links_doc
+ ).get_result()
+
+ if not response.get("ok"):
+ self.set_status(500)
+ return
+
self.set_status(200)
# ajax cries if it does not get anything back
self.set_header("Content-type", "application/json")
diff --git a/status/reports.py b/status/reports.py
new file mode 100644
index 000000000..3d61ee2a7
--- /dev/null
+++ b/status/reports.py
@@ -0,0 +1,168 @@
+import os
+from typing import Any, Union
+
+from status.util import SafeHandler
+
+
+class MultiQCReportHandler(SafeHandler):
+ def get(self, project: str) -> None:
+ report_type = self.get_argument("type")
+ multiqc_report = self.get_multiqc(self.application, project)
+ if multiqc_report:
+ self.write(multiqc_report[report_type])
+ else:
+ t = self.application.loader.load("error_page.html")
+ self.write(
+ t.generate(
+ gs_globals=self.application.gs_globals,
+ status="404",
+ reason="MultiQC Report Not Found",
+ user=self.get_current_user(),
+ )
+ )
+
+ @staticmethod
+ def get_multiqc(
+ app: Any, project_id: str, read_file: bool = True
+ ) -> Union[str, dict, None]:
+ """
+ Getting multiqc reports for requested project from the filesystem
+ Returns a string containing html if report exists, otherwise None
+ If read_file is false, the value of the dictionary will be the path to the file
+ """
+
+ project_name = ""
+ multiqc_reports = {}
+ query_res = app.cloudant.post_view(
+ db="projects", ddoc="projects", view="id_to_name", key=project_id
+ ).get_result()
+ if query_res["rows"]:
+ project_name = query_res["rows"][0]["value"]
+
+ if project_name:
+ multiqc_path = app.report_path["multiqc"] or ""
+ for report_type in ["_", "_qc_", "_pipeline_"]:
+ multiqc_name = f"{project_name}{report_type}multiqc_report.html"
+ multiqc_file_path = os.path.join(multiqc_path, multiqc_name)
+ if os.path.exists(multiqc_file_path):
+ if read_file:
+ with open(multiqc_file_path, encoding="utf-8") as multiqc_file:
+ html = multiqc_file.read()
+ multiqc_reports[report_type] = html
+ else:
+ multiqc_reports[report_type] = multiqc_file_path
+ return multiqc_reports
+
+
+class ProjectSummaryReportHandler(SafeHandler):
+ """Handler for project summary reports generated using yggdrasil"""
+
+ def get(self, project_id: str) -> None:
+ report = self.get_summary_report(self.application, project_id)
+ if report:
+ self.write(report)
+ else:
+ t = self.application.loader.load("error_page.html")
+ self.write(
+ t.generate(
+ gs_globals=self.application.gs_globals,
+ status="404",
+ reason="Project Summary Report Not Found",
+ user=self.get_current_user(),
+ )
+ )
+
+ @staticmethod
+ def get_summary_report(
+ app: Any, project_id: str, read_file: bool = True
+ ) -> Union[str, bool, None]:
+ """If read_file is false, the function will return True if the file exists, otherwise None
+ If read_file is True, it returns a string containing the report in html if it exists"""
+ project_name = ""
+
+ query_res = app.cloudant.post_view(
+ db="projects", ddoc="projects", view="id_to_name", key=project_id
+ ).get_result()
+
+ if query_res["rows"]:
+ project_name = query_res["rows"][0]["value"]
+
+ if project_name:
+ report_path = os.path.join(
+ app.report_path["yggdrasil"],
+ project_id,
+ f"{project_name}_project_summary.html",
+ )
+ if os.path.exists(report_path):
+ if read_file:
+ with open(report_path, encoding="utf-8") as report_file:
+ return report_file.read()
+ else:
+ return True
+ else:
+ return None
+
+
+class SingleCellSampleSummaryReportHandler(SafeHandler):
+ """Handler for Single Cell sample summary reports generated using yggdrasil"""
+
+ def get(self, project_id: str, sample_id: str, rep_name: str) -> None:
+ proj_path = os.path.join(self.application.report_path["yggdrasil"], project_id)
+ file_type = rep_name.split(".")[-1]
+ mode = "rb" if file_type == "pdf" else "r"
+ encoding = None if file_type == "pdf" else "utf-8"
+ report_path = os.path.join(proj_path, sample_id, rep_name)
+ report = None
+ if os.path.exists(report_path):
+ with open(report_path, mode, encoding=encoding) as report_file:
+ report = report_file.read()
+
+ if report:
+ if "pdf" in rep_name:
+ self.set_header("Content-Type", "application/pdf")
+ self.set_header(
+ "Content-Disposition",
+ f"inline; filename={sample_id}_single_cell_sample_summary_report.pdf",
+ )
+ self.write(report)
+ else:
+ t = self.application.loader.load("error_page.html")
+ self.write(
+ t.generate(
+ gs_globals=self.application.gs_globals,
+ status="404",
+ reason="Single Cell Sample Summary Report Not Found",
+ user=self.get_current_user(),
+ )
+ )
+
+ @staticmethod
+ def get_sample_summary_reports(
+ app: Any,
+ project_id: str,
+ ) -> Union[list[str], None]:
+ """Returns a list of sample summary reports for the requested project if sample_id is None,
+ otherwise returns the report for the requested sample"""
+
+ proj_path = os.path.join(app.report_path["yggdrasil"], project_id)
+ reports = []
+
+ if os.path.exists(proj_path):
+ for item in os.listdir(proj_path):
+ if os.path.isdir(os.path.join(proj_path, item)) and item.startswith(
+ f"{project_id}_"
+ ):
+ sample_path = os.path.join(proj_path, item)
+ if os.path.exists(sample_path):
+ # Reports will be named as __<(optional)>_report.html/pdf
+ reports = [
+ f
+ for f in os.listdir(sample_path)
+ if os.path.isfile(os.path.join(sample_path, f))
+ and (
+ f.startswith(f"{item}_")
+ and f.endswith(("_report.pdf", "_report.html"))
+ )
+ ]
+
+ return reports
diff --git a/status/running_notes.py b/status/running_notes.py
index 7516e3359..645ff1814 100644
--- a/status/running_notes.py
+++ b/status/running_notes.py
@@ -330,7 +330,7 @@ def notify_tagged_user(
html = '\
\
\
- {} in the project {}, {}! The note is as follows \
+ {} in the project {}, {} The note is as follows\
\
\
\
diff --git a/status/util.py b/status/util.py
index 38fb741d4..584527b00 100644
--- a/status/util.py
+++ b/status/util.py
@@ -159,35 +159,6 @@ def write_error(self, status_code, **kwargs):
)
)
- def get_multiqc(self, project_id, read_file=True):
- """
- Getting multiqc reports for requested project from the filesystem
- Returns a string containing html if report exists, otherwise None
- If read_file is false, the value of the dictionary will be the path to the file
- """
- view = self.application.projects_db.view("project/id_name_dates")
- rows = view[project_id].rows
- project_name = ""
- multiqc_reports = {}
- # get only the first one
- for row in rows:
- project_name = row.value.get("project_name", "")
- break
-
- if project_name:
- multiqc_path = self.application.multiqc_path or ""
- for type in ["_", "_qc_", "_pipeline_"]:
- multiqc_name = f"{project_name}{type}multiqc_report.html"
- multiqc_file_path = os.path.join(multiqc_path, multiqc_name)
- if os.path.exists(multiqc_file_path):
- if read_file:
- with open(multiqc_file_path, encoding="utf-8") as multiqc_file:
- html = multiqc_file.read()
- multiqc_reports[type] = html
- else:
- multiqc_reports[type] = multiqc_file_path
- return multiqc_reports
-
@staticmethod
def get_user_details(app, user_email):
user_details = {}
diff --git a/status_app.py b/status_app.py
index e7759ffe8..f877d4af8 100644
--- a/status_app.py
+++ b/status_app.py
@@ -65,7 +65,6 @@
SentInvoiceHandler,
)
from status.lanes_ordered import LanesOrderedDataHandler, LanesOrderedHandler
-from status.multiqc_report import MultiQCReportHandler
from status.ngisweden_stats import NGISwedenHandler
from status.ont_plot import ONTFlowcellPlotHandler, ONTFlowcellYieldHandler
from status.people_assignments import (
@@ -128,6 +127,11 @@
qPCRPoolsHandler,
)
from status.reads_plot import DataFlowcellYieldHandler, FlowcellPlotHandler
+from status.reports import (
+ MultiQCReportHandler,
+ ProjectSummaryReportHandler,
+ SingleCellSampleSummaryReportHandler,
+)
from status.running_notes import (
LatestStickyNoteHandler,
LatestStickyNotesMultipleHandler,
@@ -402,6 +406,7 @@ def __init__(self, settings):
("/projects", ProjectsHandler),
("/project_cards", ProjectCardsHandler),
("/proj_meta", ProjMetaCompareHandler),
+ ("/proj_summary_report/([^/]*)$", ProjectSummaryReportHandler),
("/reads_total/([^/]*)$", ReadsTotalHandler),
("/rec_ctrl_view/([^/]*)$", RecCtrlDataHandler),
("/sample_requirements", SampleRequirementsViewHandler),
@@ -409,6 +414,10 @@ def __init__(self, settings):
("/sample_requirements_update", SampleRequirementsUpdateHandler),
("/sensorpush", SensorpushHandler),
("/sequencing_queues", SequencingQueuesHandler),
+ (
+ "/singlecell_sample_summary_report/(P[^/]*)/([^/]*)/([^/]*)$",
+ SingleCellSampleSummaryReportHandler,
+ ),
("/smartseq3_progress", SmartSeq3ProgressPageHandler),
("/suggestion_box", SuggestionBoxHandler),
("/user_management", UserManagementHandler),
@@ -530,14 +539,22 @@ def __init__(self, settings):
# to display instruments in the server status
self.server_status = settings.get("server_status")
- # project summary - multiqc tab
- self.multiqc_path = settings.get("multiqc_path")
-
- # MinKNOW reports
- self.minknow_reports_path = settings.get("minknow_reports_path")
-
- # ToulligQC reports
- self.toulligqc_reports_path = settings.get("toulligqc_reports_path")
+ # project summary - reports tab
+ # Structure of the reports folder:
+ # /
+ # ├── other_reports/
+ # │ └── toulligqc_reports/
+ # ├── minknow_reports/
+ # ├── mqc_reports/
+ # └── yggdrasil//
+ self.reports_path = settings.get("reports_path")
+ self.report_path = {}
+ self.report_path["minknow"] = Path(self.reports_path, "minknow_reports")
+ self.report_path["multiqc"] = Path(self.reports_path, "mqc_reports")
+ self.report_path["toullingqc"] = Path(
+ self.reports_path, "other_reports", "toulligqc_reports"
+ )
+ self.report_path["yggdrasil"] = Path(self.reports_path, "yggdrasil")
# lims backend credentials
limsbackend_cred_loc = Path(
|