-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add nallo upload #4205
base: master
Are you sure you want to change the base?
Add nallo upload #4205
Changes from all commits
4a5505b
e3acdf0
6d81084
423cb20
39fc647
1a1f1d1
43e3250
1a4b4dd
bbbfcf4
4cd83a9
0eb752f
591730f
922f273
03d2de7
3c381f0
e36ac8c
a25bb61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
"""NALLO upload API.""" | ||
|
||
import datetime as dt | ||
import logging | ||
|
||
import rich_click as click | ||
|
||
from cg.cli.generate.delivery_report.base import generate_delivery_report | ||
from cg.cli.upload.scout import upload_to_scout | ||
from cg.constants import REPORT_SUPPORTED_DATA_DELIVERY, DataDelivery | ||
from cg.meta.upload.upload_api import UploadAPI | ||
from cg.meta.workflow.nallo import NalloAnalysisAPI | ||
from cg.models.cg_config import CGConfig | ||
from cg.store.models import Analysis, Case | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class NalloUploadAPI(UploadAPI): | ||
"""NALLO upload API.""" | ||
|
||
def __init__(self, config: CGConfig): | ||
self.analysis_api = NalloAnalysisAPI(config) | ||
super().__init__(config=config, analysis_api=self.analysis_api) | ||
|
||
def upload(self, ctx: click.Context, case: Case, restart: bool) -> None: | ||
"""Uploads NALLO analysis data and files.""" | ||
analysis: Analysis = case.analyses[0] | ||
self.update_upload_started_at(analysis=analysis) | ||
# Delivery report generation | ||
if case.data_delivery in REPORT_SUPPORTED_DATA_DELIVERY: | ||
ctx.invoke(generate_delivery_report, case_id=case.internal_id) | ||
|
||
# Scout specific upload | ||
if DataDelivery.SCOUT in case.data_delivery: | ||
ctx.invoke(upload_to_scout, case_id=case.internal_id, re_upload=restart) | ||
LOG.info( | ||
f"Upload of case {case.internal_id} was successful. Uploaded at {dt.datetime.now()} in StatusDB" | ||
) | ||
self.update_uploaded_at(analysis=analysis) | ||
|
||
# Clinical delivery upload | ||
self.upload_files_to_customer_inbox(case) |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,88 @@ | ||||||||||
import logging | ||||||||||
|
||||||||||
from housekeeper.store.models import Version | ||||||||||
|
||||||||||
from cg.apps.lims import LimsAPI | ||||||||||
from cg.apps.madeline.api import MadelineAPI | ||||||||||
from cg.constants.housekeeper_tags import HK_DELIVERY_REPORT_TAG | ||||||||||
from cg.constants.scout import ( | ||||||||||
NALLO_CASE_TAGS, | ||||||||||
NALLO_RANK_MODEL_THRESHOLD, | ||||||||||
NALLO_RANK_MODEL_VERSION_SNV, | ||||||||||
NALLO_RANK_MODEL_VERSION_SV, | ||||||||||
NALLO_SAMPLE_TAGS, | ||||||||||
GenomeBuild, | ||||||||||
UploadTrack, | ||||||||||
) | ||||||||||
from cg.meta.upload.scout.hk_tags import CaseTags, SampleTags | ||||||||||
from cg.meta.upload.scout.scout_config_builder import ScoutConfigBuilder | ||||||||||
from cg.meta.workflow.nallo import NalloAnalysisAPI | ||||||||||
from cg.models.scout.scout_load_config import NalloLoadConfig, ScoutNalloIndividual | ||||||||||
from cg.store.models import Analysis | ||||||||||
|
||||||||||
LOG = logging.getLogger(__name__) | ||||||||||
|
||||||||||
|
||||||||||
class NalloConfigBuilder(ScoutConfigBuilder): | ||||||||||
def __init__( | ||||||||||
self, | ||||||||||
hk_version_obj: Version, | ||||||||||
analysis_obj: Analysis, | ||||||||||
Comment on lines
+29
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of scope but I do not like designs where we tie the whole class to a single Version/Analysis. It makes it less flexible There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also out of scope but modifying the input and making all methods return None is confusing to me. If we redesign at some point it might be nice to consider changing. |
||||||||||
nallo_analysis_api: NalloAnalysisAPI, | ||||||||||
lims_api: LimsAPI, | ||||||||||
madeline_api: MadelineAPI, | ||||||||||
): | ||||||||||
super().__init__( | ||||||||||
hk_version_obj=hk_version_obj, | ||||||||||
analysis_obj=analysis_obj, | ||||||||||
lims_api=lims_api, | ||||||||||
) | ||||||||||
self.case_tags: CaseTags = CaseTags(**NALLO_CASE_TAGS) | ||||||||||
self.sample_tags: SampleTags = SampleTags(**NALLO_SAMPLE_TAGS) | ||||||||||
Comment on lines
+40
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
self.nallo_analysis_api: NalloAnalysisAPI = nallo_analysis_api | ||||||||||
self.lims_api: LimsAPI = lims_api | ||||||||||
self.madeline_api: MadelineAPI = madeline_api | ||||||||||
|
||||||||||
def build_load_config(self) -> NalloLoadConfig: | ||||||||||
"""Create a NALLO specific load config for uploading analysis to Scout.""" | ||||||||||
LOG.info("Build load config for NALLO case") | ||||||||||
load_config: NalloLoadConfig = NalloLoadConfig( | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
track=UploadTrack.RARE_DISEASE.value, | ||||||||||
delivery_report=self.get_file_from_hk({HK_DELIVERY_REPORT_TAG}), | ||||||||||
) | ||||||||||
self.add_common_info_to_load_config(load_config) | ||||||||||
load_config.gene_panels = self.nallo_analysis_api.get_aggregated_panels( | ||||||||||
customer_id=self.analysis_obj.case.customer.internal_id, | ||||||||||
default_panels=set(self.analysis_obj.case.panels), | ||||||||||
) | ||||||||||
self.include_case_files(load_config) | ||||||||||
self.get_sample_information(load_config) | ||||||||||
self.include_pedigree_picture(load_config) | ||||||||||
load_config.human_genome_build = GenomeBuild.hg38 | ||||||||||
load_config.rank_score_threshold = NALLO_RANK_MODEL_THRESHOLD | ||||||||||
load_config.rank_model_version = NALLO_RANK_MODEL_VERSION_SNV | ||||||||||
load_config.sv_rank_model_version = NALLO_RANK_MODEL_VERSION_SV | ||||||||||
return load_config | ||||||||||
|
||||||||||
def include_case_files(self, load_config: NalloLoadConfig) -> None: | ||||||||||
"""Include case level files for NALLO case.""" | ||||||||||
LOG.info("Including NALLO specific case level files") | ||||||||||
for scout_key in NALLO_CASE_TAGS.keys(): | ||||||||||
self._include_case_file(load_config, scout_key) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we have named arguments? |
||||||||||
|
||||||||||
def _include_case_file(self, load_config: NalloLoadConfig, scout_key: str) -> None: | ||||||||||
"""Include the file path associated to a scout configuration parameter if the corresponding housekeeper tags | ||||||||||
are found. Otherwise return None.""" | ||||||||||
file_path = self.get_file_from_hk(getattr(self.case_tags, scout_key)) | ||||||||||
setattr(load_config, scout_key, file_path) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Named arguments |
||||||||||
|
||||||||||
def include_sample_files(self, config_sample: ScoutNalloIndividual) -> None: | ||||||||||
"""Include sample level files that are optional.""" | ||||||||||
LOG.info("Including NALLO specific sample level files") | ||||||||||
sample_id: str = config_sample.sample_id | ||||||||||
config_sample.d4_file = self.get_sample_file( | ||||||||||
hk_tags=self.sample_tags.d4_file, sample_id=sample_id | ||||||||||
) | ||||||||||
config_sample.paraphase_alignment_path = self.get_sample_file( | ||||||||||
hk_tags=self.sample_tags.paraphase_alignment_path, sample_id=sample_id | ||||||||||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,6 +82,11 @@ class ScoutMipIndividual(ScoutIndividual): | |
mitodel_file: str | None = None | ||
|
||
|
||
class ScoutNalloIndividual(ScoutIndividual): | ||
d4_file: str | None = None | ||
paraphase_alignment_path: str | None = None | ||
|
||
|
||
class ScoutRarediseaseIndividual(ScoutIndividual): | ||
mt_bam: str | None = None | ||
chromograph_images: ChromographImages = ChromographImages() | ||
|
@@ -163,6 +168,18 @@ class MipLoadConfig(ScoutLoadConfig): | |
vcf_sv_research: Annotated[str | None, BeforeValidator(field_not_none)] = None | ||
|
||
|
||
class NalloLoadConfig(ScoutLoadConfig): | ||
madeline: str | None = None | ||
samples: list[ScoutNalloIndividual] = [] | ||
somalier_samples: str | None = None | ||
somalier_pairs: str | None = None | ||
vcf_snv: Annotated[str, BeforeValidator(field_not_none)] = None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am very confused by us having a BeforeValidator seemingly avoiding "field not None" behaviour, but also us having a default value of None. Seems a bit contradictory to me. You can consider it out of scope though, the pattern does not seem introduced by you. |
||
vcf_snv_research: Annotated[str | None, BeforeValidator(field_not_none)] = None | ||
vcf_sv: Annotated[str | None, BeforeValidator(field_not_none)] = None | ||
vcf_sv_research: Annotated[str | None, BeforeValidator(field_not_none)] = None | ||
vcf_str: str | None = None | ||
|
||
|
||
class RarediseaseLoadConfig(ScoutLoadConfig): | ||
madeline: str | None = None | ||
peddy_check: str | None = None | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe very minor but I thought this was done after uploads to Caesar? So after line 43?