Skip to content

Commit

Permalink
Add delivery report Raredisease (#3459)
Browse files Browse the repository at this point in the history
### Added:
- Delivery report Raredisease
  • Loading branch information
ivadym authored Jul 29, 2024
1 parent 850a489 commit 127f0ab
Show file tree
Hide file tree
Showing 40 changed files with 581 additions and 203 deletions.
5 changes: 5 additions & 0 deletions cg/cli/generate/report/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from cg.meta.report.balsamic_qc import BalsamicQCReportAPI
from cg.meta.report.balsamic_umi import BalsamicUmiReportAPI
from cg.meta.report.mip_dna import MipDNAReportAPI
from cg.meta.report.raredisease import RarediseaseReportAPI
from cg.meta.report.report_api import ReportAPI
from cg.meta.report.rnafusion import RnafusionReportAPI
from cg.meta.report.taxprofiler import TaxprofilerReportAPI
Expand All @@ -22,6 +23,7 @@
from cg.meta.workflow.balsamic_qc import BalsamicQCAnalysisAPI
from cg.meta.workflow.balsamic_umi import BalsamicUmiAnalysisAPI
from cg.meta.workflow.mip_dna import MipDNAAnalysisAPI
from cg.meta.workflow.raredisease import RarediseaseAnalysisAPI
from cg.meta.workflow.rnafusion import RnafusionAnalysisAPI
from cg.meta.workflow.taxprofiler import TaxprofilerAnalysisAPI
from cg.meta.workflow.tomte import TomteAnalysisAPI
Expand Down Expand Up @@ -98,6 +100,9 @@ def get_report_api_workflow(context: click.Context, workflow: Workflow) -> Repor
Workflow.MIP_DNA: MipDNAReportAPI(
config=context.obj, analysis_api=MipDNAAnalysisAPI(config=context.obj)
),
Workflow.RAREDISEASE: RarediseaseReportAPI(
config=context.obj, analysis_api=RarediseaseAnalysisAPI(config=context.obj)
),
Workflow.RNAFUSION: RnafusionReportAPI(
config=context.obj, analysis_api=RnafusionAnalysisAPI(config=context.obj)
),
Expand Down
4 changes: 2 additions & 2 deletions cg/cli/workflow/balsamic/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
OPTION_GENOME_VERSION = click.option(
"--genome-version",
show_default=True,
default=GenomeVersion.hg19,
type=click.Choice([GenomeVersion.hg19, GenomeVersion.hg38, GenomeVersion.canfam3]),
default=GenomeVersion.HG19,
type=click.Choice([GenomeVersion.HG19, GenomeVersion.HG38, GenomeVersion.CANFAM3]),
help="Type and build version of the reference genome. Set this option to override the default.",
)
OPTION_PANEL_BED = click.option(
Expand Down
6 changes: 6 additions & 0 deletions cg/clients/chanjo2/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,9 @@ def root_must_not_be_empty(cls, root: dict[str, CoverageMetrics]):
if not root:
raise ValueError("Coverage POST response must not be an empty dictionary")
return root

def get_sample_coverage_metrics(self, sample_id: str) -> CoverageMetrics:
"""Return the coverage metrics for the specified sample ID."""
if sample_id not in self.root:
raise ValueError(f"Sample ID '{sample_id}' not found in the coverage POST response")
return self.root[sample_id]
6 changes: 3 additions & 3 deletions cg/constants/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,9 @@ class GenomeVersion(StrEnum):
GRCh37: str = "GRCh37"
GRCh38: str = "GRCh38"
T2T_CHM13: str = "T2T-CHM13v2.0"
canfam3: str = "canfam3"
hg19: str = "hg19"
hg38: str = "hg38"
CANFAM3 = auto()
HG19 = auto()
HG38 = auto()


class SampleType(StrEnum):
Expand Down
8 changes: 6 additions & 2 deletions cg/constants/delivery.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,17 @@
"case_tags": RNAFUSION_ANALYSIS_CASE_TAGS,
"sample_tags": RNAFUSION_ANALYSIS_SAMPLE_TAGS,
},
Workflow.RAREDISEASE: {
"case_tags": NF_ANALYSIS_CASE_TAGS,
"sample_tags": NF_ANALYSIS_SAMPLE_TAGS,
},
Workflow.TAXPROFILER: {
"case_tags": NF_ANALYSIS_CASE_TAGS,
"sample_tags": NF_ANALYSIS_CASE_TAGS,
"sample_tags": NF_ANALYSIS_SAMPLE_TAGS,
},
Workflow.TOMTE: {
"case_tags": NF_ANALYSIS_CASE_TAGS,
"sample_tags": NF_ANALYSIS_CASE_TAGS,
"sample_tags": NF_ANALYSIS_SAMPLE_TAGS,
},
}

Expand Down
4 changes: 4 additions & 0 deletions cg/constants/nf_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ class NfTowerStatus(StrEnum):
}
}
"""

RAREDISEASE_COVERAGE_FILE_TAGS: list[str] = ["coverage", "d4"]
RAREDISEASE_COVERAGE_INTERVAL_TYPE: str = "genes"
RAREDISEASE_COVERAGE_THRESHOLD: int = 10
32 changes: 22 additions & 10 deletions cg/constants/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
Workflow.BALSAMIC_QC,
Workflow.BALSAMIC_UMI,
Workflow.MIP_DNA,
Workflow.RAREDISEASE,
Workflow.RNAFUSION,
Workflow.TAXPROFILER,
Workflow.TOMTE,
Expand Down Expand Up @@ -102,10 +103,12 @@
"genome_build",
]

REQUIRED_DATA_ANALYSIS_MIP_DNA_FIELDS: list[str] = REQUIRED_DATA_ANALYSIS_FIELDS + [
REQUIRED_DATA_ANALYSIS_RAREDISEASE_FIELDS: list[str] = REQUIRED_DATA_ANALYSIS_FIELDS + [
"panels",
]

REQUIRED_DATA_ANALYSIS_MIP_DNA_FIELDS: list[str] = REQUIRED_DATA_ANALYSIS_RAREDISEASE_FIELDS

REQUIRED_DATA_ANALYSIS_BALSAMIC_FIELDS: list[str] = REQUIRED_DATA_ANALYSIS_FIELDS + [
"type",
"variant_callers",
Expand All @@ -122,31 +125,31 @@
"name",
"id",
"ticket",
"gender",
"sex",
"source",
"application",
"methods",
"metadata",
"timestamps",
]

_REQUIRED_SAMPLE_RARE_DISEASE_FIELDS: list[str] = _REQUIRED_SAMPLE_FIELDS + [
REQUIRED_SAMPLE_RAREDISEASE_FIELDS: list[str] = _REQUIRED_SAMPLE_FIELDS + [
"status",
]

_REQUIRED_SAMPLE_CANCER_FIELDS: list[str] = _REQUIRED_SAMPLE_FIELDS + [
"tumour",
]

REQUIRED_SAMPLE_MIP_DNA_FIELDS: list[str] = _REQUIRED_SAMPLE_RARE_DISEASE_FIELDS
REQUIRED_SAMPLE_MIP_DNA_FIELDS: list[str] = REQUIRED_SAMPLE_RAREDISEASE_FIELDS

REQUIRED_SAMPLE_BALSAMIC_FIELDS: list[str] = _REQUIRED_SAMPLE_CANCER_FIELDS

REQUIRED_SAMPLE_RNAFUSION_FIELDS: list[str] = _REQUIRED_SAMPLE_CANCER_FIELDS

REQUIRED_SAMPLE_TAXPROFILER_FIELDS: list[str] = _REQUIRED_SAMPLE_FIELDS

REQUIRED_SAMPLE_TOMTE_FIELDS: list[str] = _REQUIRED_SAMPLE_RARE_DISEASE_FIELDS
REQUIRED_SAMPLE_TOMTE_FIELDS: list[str] = REQUIRED_SAMPLE_RAREDISEASE_FIELDS

# Methods required fields (OPTIONAL: "library_prep", "sequencing")
REQUIRED_SAMPLE_METHODS_FIELDS: list[str] = []
Expand All @@ -164,16 +167,25 @@
"million_read_pairs",
]

REQUIRED_SAMPLE_METADATA_MIP_DNA_WGS_FIELDS: list[str] = _REQUIRED_SAMPLE_METADATA_FIELDS + [
"gender",
REQUIRED_SAMPLE_METADATA_RAREDISEASE_WGS_FIELDS: list[str] = _REQUIRED_SAMPLE_METADATA_FIELDS + [
"sex",
"mapped_reads",
"mean_target_coverage",
"pct_10x",
]

REQUIRED_SAMPLE_METADATA_MIP_DNA_FIELDS: list[str] = REQUIRED_SAMPLE_METADATA_MIP_DNA_WGS_FIELDS + [
"bait_set",
]
REQUIRED_SAMPLE_METADATA_RAREDISEASE_FIELDS: list[str] = (
REQUIRED_SAMPLE_METADATA_RAREDISEASE_WGS_FIELDS
+ [
"bait_set",
]
)

REQUIRED_SAMPLE_METADATA_MIP_DNA_WGS_FIELDS: list[str] = (
REQUIRED_SAMPLE_METADATA_RAREDISEASE_WGS_FIELDS
)

REQUIRED_SAMPLE_METADATA_MIP_DNA_FIELDS: list[str] = REQUIRED_SAMPLE_METADATA_RAREDISEASE_FIELDS

_REQUIRED_SAMPLE_METADATA_BALSAMIC_FIELDS: list[str] = _REQUIRED_SAMPLE_METADATA_FIELDS + [
"mean_insert_size",
Expand Down
21 changes: 18 additions & 3 deletions cg/constants/scout.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from enum import StrEnum
from enum import StrEnum, auto

from cg.constants import FileExtensions
from cg.constants.housekeeper_tags import AlignmentFileTag


HGNC_ID = "hgnc_id"


class GenomeBuild(StrEnum):
hg19: str = "37"
hg38: str = "38"
Expand All @@ -29,7 +32,15 @@ class ScoutCustomCaseReportTags(StrEnum):
GENE_FUSION_RESEARCH: str = "gene_fusion_research"


MIP_CASE_TAGS = dict(
class ScoutUploadKey(StrEnum):
SMN_TSV = auto()
SNV_VCF = auto()
SV_VCF = auto()
VCF_STR = auto()
VCF_FUSION = auto()


RAREDISEASE_CASE_TAGS = dict(
delivery_report={"delivery-report"},
multiqc_report={"multiqc-html"},
peddy_check={"ped-check", "peddy"},
Expand All @@ -46,6 +57,8 @@ class ScoutCustomCaseReportTags(StrEnum):
vcf_str={"vcf-str"},
)

MIP_CASE_TAGS: dict[str, set[str]] = RAREDISEASE_CASE_TAGS

BALSAMIC_CASE_TAGS = dict(
sv_vcf={"vcf-sv-clinical"},
snv_vcf={"vcf-snv-clinical"},
Expand Down Expand Up @@ -74,7 +87,7 @@ class ScoutCustomCaseReportTags(StrEnum):
vcf_fusion={"vcf-fusion"},
)

MIP_SAMPLE_TAGS = dict(
RAREDISEASE_SAMPLE_TAGS = dict(
bam_file={"bam"},
alignment_file={"cram"},
vcf2cytosure={"vcf2cytosure"},
Expand All @@ -89,6 +102,8 @@ class ScoutCustomCaseReportTags(StrEnum):
mitodel_file={"mitodel"},
)

MIP_SAMPLE_TAGS: dict[str, set[str]] = RAREDISEASE_SAMPLE_TAGS

BALSAMIC_SAMPLE_TAGS = dict(
bam_file={"bam"},
alignment_file={"cram"},
Expand Down
46 changes: 24 additions & 22 deletions cg/meta/report/balsamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
Workflow,
)
from cg.constants.constants import AnalysisType
from cg.constants.scout import BALSAMIC_CASE_TAGS
from cg.constants.scout import ScoutUploadKey
from cg.meta.report.field_validators import get_million_read_pairs
from cg.meta.report.report_api import ReportAPI
from cg.meta.workflow.balsamic import BalsamicAnalysisAPI
Expand All @@ -33,7 +33,7 @@
BalsamicTargetedSampleMetadataModel,
BalsamicWGSSampleMetadataModel,
)
from cg.models.report.report import CaseModel, ScoutReportFiles
from cg.models.report.report import CaseModel, ScoutReportFiles, ReportRequiredFields
from cg.models.report.sample import SampleModel
from cg.store.models import Bed, BedVersion, Case, Sample

Expand Down Expand Up @@ -139,8 +139,12 @@ def is_report_accredited(
def get_scout_uploaded_files(self, case_id: str) -> ScoutReportFiles:
"""Return files that will be uploaded to Scout."""
return ScoutReportFiles(
snv_vcf=self.get_scout_uploaded_file_from_hk(case_id=case_id, scout_tag="snv_vcf"),
sv_vcf=self.get_scout_uploaded_file_from_hk(case_id=case_id, scout_tag="sv_vcf"),
snv_vcf=self.get_scout_uploaded_file_from_hk(
case_id=case_id, scout_key=ScoutUploadKey.SNV_VCF
),
sv_vcf=self.get_scout_uploaded_file_from_hk(
case_id=case_id, scout_key=ScoutUploadKey.SV_VCF
),
)

def get_required_fields(self, case: CaseModel) -> dict:
Expand All @@ -167,28 +171,26 @@ def get_required_fields(self, case: CaseModel) -> dict:
required_sample_metadata_fields: list[str] = (
REQUIRED_SAMPLE_METADATA_BALSAMIC_TARGETED_FIELDS
)
return {
"report": REQUIRED_REPORT_FIELDS,
"customer": REQUIRED_CUSTOMER_FIELDS,
"case": REQUIRED_CASE_FIELDS,
"applications": self.get_application_required_fields(

report_required_fields = ReportRequiredFields(
applications=self.get_application_required_fields(
case=case, required_fields=REQUIRED_APPLICATION_FIELDS
),
"data_analysis": required_data_analysis_fields,
"samples": self.get_sample_required_fields(
case=case, required_fields=REQUIRED_SAMPLE_BALSAMIC_FIELDS
case=REQUIRED_CASE_FIELDS,
customer=REQUIRED_CUSTOMER_FIELDS,
data_analysis=required_data_analysis_fields,
metadata=self.get_sample_required_fields(
case=case, required_fields=required_sample_metadata_fields
),
"methods": self.get_sample_required_fields(
methods=self.get_sample_required_fields(
case=case, required_fields=REQUIRED_SAMPLE_METHODS_FIELDS
),
"timestamps": self.get_timestamp_required_fields(
case=case, required_fields=REQUIRED_SAMPLE_TIMESTAMP_FIELDS
report=REQUIRED_REPORT_FIELDS,
samples=self.get_sample_required_fields(
case=case, required_fields=REQUIRED_SAMPLE_BALSAMIC_FIELDS
),
"metadata": self.get_sample_required_fields(
case=case, required_fields=required_sample_metadata_fields
timestamps=self.get_timestamp_required_fields(
case=case, required_fields=REQUIRED_SAMPLE_TIMESTAMP_FIELDS
),
}

def get_upload_case_tags(self) -> dict:
"""Return Balsamic upload case tags."""
return BALSAMIC_CASE_TAGS
)
return report_required_fields.model_dump()
5 changes: 0 additions & 5 deletions cg/meta/report/balsamic_umi.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import logging

from cg.constants.scout import BALSAMIC_UMI_CASE_TAGS
from cg.meta.report.balsamic import BalsamicReportAPI
from cg.meta.workflow.balsamic_umi import BalsamicUmiAnalysisAPI
from cg.models.cg_config import CGConfig
Expand All @@ -14,7 +13,3 @@ class BalsamicUmiReportAPI(BalsamicReportAPI):
def __init__(self, config: CGConfig, analysis_api: BalsamicUmiAnalysisAPI):
super().__init__(config=config, analysis_api=analysis_api)
self.analysis_api: BalsamicUmiAnalysisAPI = analysis_api

def get_upload_case_tags(self) -> dict:
"""Return Balsamic UMI upload case tags."""
return BALSAMIC_UMI_CASE_TAGS
Loading

0 comments on commit 127f0ab

Please sign in to comment.