Skip to content

Commit 57cf1c8

Browse files
authored
add rna_delivery_report from tomte in related dna cases (#3782) | minor
### Added - Upload of the tomte rna case to the related dna under report section: "rna_delivery_report"/"RNA Delivery Report"
1 parent 1852c7b commit 57cf1c8

File tree

7 files changed

+324
-6
lines changed

7 files changed

+324
-6
lines changed

cg/apps/scout/scoutapi.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,15 @@ def upload_rna_genome_build(
350350
except CalledProcessError as error:
351351
raise ScoutUploadError("Something went wrong when updating rna genome build") from error
352352

353+
def upload_rna_delivery_report(self, case_id: str, report_path: str) -> None:
354+
"""Load a RNA report into a case in the database."""
355+
356+
self.upload_report(
357+
case_id=case_id,
358+
report_path=report_path,
359+
report_type=ScoutCustomCaseReportTags.RNA_DELIVERY,
360+
)
361+
353362
def load_variant_outlier(self, case_id: str) -> None:
354363
"""Load a rna fraser file into a case in the database."""
355364

cg/cli/upload/scout.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def upload_tomte_to_scout(
203203
LOG.info("----------------- UPLOAD RNA TO SCOUT -----------------------")
204204

205205
context.invoke(validate_case_samples_are_rna, case_id=case_id)
206+
context.invoke(upload_rna_delivery_report_to_scout, case_id=case_id)
206207
context.invoke(upload_rna_alignment_file_to_scout, case_id=case_id, dry_run=dry_run)
207208
context.invoke(upload_multiqc_to_scout, case_id=case_id, dry_run=dry_run)
208209
context.invoke(upload_rna_omics_to_scout, case_id=case_id, dry_run=dry_run)
@@ -238,6 +239,19 @@ def upload_rna_fusion_report_to_scout(
238239
)
239240

240241

242+
@click.command(name="rna-delivery-report-to-scout")
243+
@DRY_RUN
244+
@click.argument("case_id")
245+
@click.pass_obj
246+
def upload_rna_delivery_report_to_scout(context: CGConfig, dry_run: bool, case_id: str) -> None:
247+
"""Upload rna delivery report file for a case to Scout."""
248+
249+
LOG.info("----------------- UPLOAD RNA DELIVERY REPORT TO SCOUT -----------------------")
250+
251+
scout_upload_api: UploadScoutAPI = context.meta_apis["upload_api"].scout_upload_api
252+
scout_upload_api.upload_rna_delivery_report_to_scout(dry_run=dry_run, case_id=case_id)
253+
254+
241255
@click.command(name="rna-junctions-to-scout")
242256
@DRY_RUN
243257
@click.argument("case_id")

cg/constants/scout.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class UploadTrack(StrEnum):
2323

2424
class ScoutCustomCaseReportTags(StrEnum):
2525
DELIVERY: str = "delivery_report"
26+
RNA_DELIVERY: str = "rna_delivery_report"
2627
CNV: str = "cnv_report"
2728
COV_QC: str = "coverage_qc_report"
2829
MULTIQC: str = "multiqc"

cg/meta/upload/scout/uploadscoutapi.py

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from cg.apps.scout.scoutapi import ScoutAPI
1313
from cg.constants import HK_MULTIQC_HTML_TAG, Workflow
1414
from cg.constants.constants import FileFormat, PrepCategory, GenomeVersion
15-
from cg.constants.housekeeper_tags import AlignmentFileTag, AnalysisTag
15+
from cg.constants.housekeeper_tags import AlignmentFileTag, AnalysisTag, HK_DELIVERY_REPORT_TAG
1616
from cg.constants.scout import ScoutCustomCaseReportTags
1717
from cg.exc import CgDataError, HousekeeperBundleVersionMissingError
1818
from cg.io.controller import WriteFile
@@ -159,6 +159,13 @@ def get_fusion_report(self, case_id: str, research: bool) -> File | None:
159159

160160
return self.housekeeper.get_file_from_latest_version(bundle_name=case_id, tags=tags)
161161

162+
def get_rna_delivery_report(self, case_id: str) -> File | None:
163+
"""Return a RNA report for a case in housekeeper."""
164+
165+
tags = {HK_DELIVERY_REPORT_TAG}
166+
167+
return self.housekeeper.get_file_from_latest_version(bundle_name=case_id, tags=tags)
168+
162169
def get_splice_junctions_bed(self, case_id: str, sample_id: str) -> File | None:
163170
"""Return a splice junctions bed file for a case in Housekeeper."""
164171

@@ -256,7 +263,7 @@ def upload_fusion_report_to_scout(
256263

257264
related_dna_cases: set[str] = self.get_related_uploaded_dna_cases(case_id)
258265
if not related_dna_cases:
259-
raise CgDataError("No connected DNA case has been uploaded.")
266+
raise CgDataError("No connected DNA case found.")
260267

261268
for dna_case_id in related_dna_cases:
262269
LOG.info(f"Uploading {report_type} fusion report to Scout for case {dna_case_id}.")
@@ -272,6 +279,37 @@ def upload_fusion_report_to_scout(
272279

273280
LOG.info(f"Upload {report_type} fusion report finished!")
274281

282+
def upload_rna_delivery_report_to_scout(self, dry_run: bool, case_id: str) -> None:
283+
"""Upload rna delivery report file for a case to Scout."""
284+
285+
rna_delivery_report: File | None = self.get_rna_delivery_report(case_id)
286+
if not rna_delivery_report:
287+
raise FileNotFoundError(
288+
f"Rna delivery report was not found in Housekeeper for {case_id}."
289+
)
290+
291+
LOG.info(f"Rna delivery report {rna_delivery_report.path} found")
292+
293+
related_dna_cases: set[str] = self.get_related_uploaded_dna_cases(case_id)
294+
if not related_dna_cases:
295+
raise CgDataError("No connected DNA case has been uploaded.")
296+
297+
for dna_case_id in related_dna_cases:
298+
LOG.debug(f"Uploading rna delivery report to Scout for case {dna_case_id}.")
299+
300+
if dry_run:
301+
LOG.debug(
302+
f"Dry run - Would have uploaded rna delivery report to Scout for case {dna_case_id}."
303+
)
304+
continue
305+
self.scout_api.upload_rna_delivery_report(
306+
case_id=dna_case_id,
307+
report_path=rna_delivery_report.full_path,
308+
)
309+
LOG.debug(f"Uploaded rna delivery report for {dna_case_id}.")
310+
311+
LOG.info(f"Upload rna delivery report finished for case {case_id}!")
312+
275313
def upload_rna_report_to_dna_case_in_scout(
276314
self,
277315
dry_run: bool,

cg/meta/upload/tomte/tomte.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@
55

66
import click
77

8-
8+
from cg.cli.generate.delivery_report.base import generate_delivery_report
99
from cg.cli.upload.scout import upload_tomte_to_scout
10-
from cg.constants import DataDelivery, Workflow
10+
from cg.constants import (
11+
REPORT_SUPPORTED_DATA_DELIVERY,
12+
REPORT_SUPPORTED_WORKFLOW,
13+
DataDelivery,
14+
Workflow,
15+
)
1116
from cg.meta.upload.nf_analysis import NfAnalysisUploadAPI
1217
from cg.models.cg_config import CGConfig
1318
from cg.store.models import Analysis, Case
@@ -16,7 +21,7 @@
1621

1722

1823
class TomteUploadAPI(NfAnalysisUploadAPI):
19-
"""MIP-RNA upload API."""
24+
"""Tomte upload API."""
2025

2126
def __init__(self, config: CGConfig):
2227
super().__init__(config=config, workflow=Workflow.TOMTE)
@@ -26,6 +31,13 @@ def upload(self, ctx: click.Context, case: Case, restart: bool) -> None:
2631
analysis: Analysis = case.analyses[0]
2732
self.update_upload_started_at(analysis=analysis)
2833

34+
# Delivery report generation
35+
if (
36+
case.data_analysis in REPORT_SUPPORTED_WORKFLOW
37+
and case.data_delivery in REPORT_SUPPORTED_DATA_DELIVERY
38+
):
39+
ctx.invoke(generate_delivery_report, case_id=case.internal_id)
40+
2941
self.upload_files_to_customer_inbox(case=case)
3042

3143
# Scout specific upload

tests/meta/upload/scout/conftest.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,73 @@ def mip_rna_analysis_hk_bundle_data(
403403
}
404404

405405

406+
@pytest.fixture(scope="function")
407+
def tomte_analysis_hk_bundle_data(
408+
rna_case_id: str,
409+
timestamp: datetime,
410+
tomte_analysis_dir: Path,
411+
rna_sample_son_id: str,
412+
rna_sample_daughter_id: str,
413+
rna_sample_mother_id: str,
414+
rna_sample_father_id: str,
415+
) -> dict:
416+
"""Return MIP RNA bundle data for Housekeeper."""
417+
418+
files: list[dict] = [
419+
{
420+
"path": Path(tomte_analysis_dir, f"{rna_case_id}.cram").as_posix(),
421+
"archive": False,
422+
"tags": ["cram", rna_case_id],
423+
},
424+
{
425+
"path": Path(tomte_analysis_dir, f"{rna_case_id}_report.selected.pdf").as_posix(),
426+
"archive": False,
427+
"tags": ["fusion", "pdf", "clinical", rna_case_id],
428+
},
429+
{
430+
"path": Path(tomte_analysis_dir, f"{rna_case_id}_report.pdf").as_posix(),
431+
"archive": False,
432+
"tags": ["fusion", "pdf", "research", rna_case_id],
433+
},
434+
{
435+
"path": Path(tomte_analysis_dir, f"{rna_case_id}_report.pdf").as_posix(),
436+
"archive": False,
437+
"tags": ["delivery-report", "rna", rna_case_id],
438+
},
439+
]
440+
for sample_id in [
441+
rna_sample_son_id,
442+
rna_sample_daughter_id,
443+
rna_sample_mother_id,
444+
rna_sample_father_id,
445+
]:
446+
files.extend(
447+
[
448+
{
449+
"path": Path(
450+
tomte_analysis_dir, f"{sample_id}_lanes_1_star_sorted_sj.bigWig"
451+
).as_posix(),
452+
"archive": False,
453+
"tags": ["coverage", "bigwig", "scout", sample_id],
454+
},
455+
{
456+
"path": Path(
457+
tomte_analysis_dir, f"{sample_id}_lanes_1234_star_sorted_sj.bed.gz.tbi"
458+
).as_posix(),
459+
"archive": False,
460+
"tags": ["bed", "scout", "junction", sample_id],
461+
},
462+
]
463+
)
464+
465+
return {
466+
"name": rna_case_id,
467+
"created": timestamp,
468+
"expires": timestamp,
469+
"files": files,
470+
}
471+
472+
406473
@pytest.fixture(scope="function")
407474
def balsamic_analysis_hk_bundle_data(
408475
case_id: str,
@@ -515,6 +582,15 @@ def mip_rna_analysis_hk_api(
515582
return housekeeper_api
516583

517584

585+
@pytest.fixture
586+
def tomte_analysis_hk_api(
587+
housekeeper_api: MockHousekeeperAPI, tomte_analysis_hk_bundle_data: dict, helpers
588+
) -> MockHousekeeperAPI:
589+
"""Return a Housekeeper API populated with MIP RNA analysis files."""
590+
helpers.ensure_hk_version(housekeeper_api, tomte_analysis_hk_bundle_data)
591+
return housekeeper_api
592+
593+
518594
@pytest.fixture
519595
def balsamic_analysis_hk_api(
520596
housekeeper_api: MockHousekeeperAPI, balsamic_analysis_hk_bundle_data: dict, helpers
@@ -706,6 +782,29 @@ def upload_mip_analysis_scout_api(
706782
)
707783

708784

785+
@pytest.fixture
786+
def upload_tomte_analysis_scout_api(
787+
cg_context: CGConfig,
788+
scout_api: MockScoutAPI,
789+
madeline_api: MockMadelineAPI,
790+
lims_samples: list[dict],
791+
tomte_analysis_hk_api: MockHousekeeperAPI,
792+
store: Store,
793+
) -> Generator[UploadScoutAPI, None, None]:
794+
"""Return MIP upload Scout API."""
795+
analysis_mock = MockMipAnalysis(config=cg_context, workflow=Workflow.TOMTE)
796+
lims_api = MockLimsAPI(samples=lims_samples)
797+
798+
yield UploadScoutAPI(
799+
hk_api=tomte_analysis_hk_api,
800+
scout_api=scout_api,
801+
madeline_api=madeline_api,
802+
analysis_api=analysis_mock,
803+
lims_api=lims_api,
804+
status_db=store,
805+
)
806+
807+
709808
@pytest.fixture
710809
def upload_balsamic_analysis_scout_api(
711810
cg_context: CGConfig,

0 commit comments

Comments
 (0)