From 885f113fd4f975e27b738b26ecd1a4ecc1803987 Mon Sep 17 00:00:00 2001 From: Vincent Janvid Date: Fri, 22 Mar 2024 18:20:32 +0100 Subject: [PATCH] Try to refactor PhenotypeStatus --- cg/apps/mip/confighandler.py | 6 +++--- cg/constants/subject.py | 11 +++++------ cg/meta/workflow/raredisease.py | 6 +++--- cg/models/scout/scout_load_config.py | 3 ++- cg/store/models.py | 5 ++--- tests/cli/workflow/mip/conftest.py | 6 ++++-- tests/conftest.py | 13 ++++++++----- tests/store_helpers.py | 2 +- 8 files changed, 28 insertions(+), 24 deletions(-) diff --git a/cg/apps/mip/confighandler.py b/cg/apps/mip/confighandler.py index 11eb9da129..bd35861c8b 100644 --- a/cg/apps/mip/confighandler.py +++ b/cg/apps/mip/confighandler.py @@ -4,7 +4,7 @@ from marshmallow import Schema, fields, validate from cg.constants import DEFAULT_CAPTURE_KIT -from cg.constants.subject import RelationshipStatus +from cg.constants.subject import PhenotypeStatus, RelationshipStatus from cg.exc import PedigreeConfigError LOG = logging.getLogger(__name__) @@ -26,9 +26,9 @@ class SampleSchema(Schema): ) father = fields.Str(dump_default=RelationshipStatus.HAS_NO_PARENT) mother = fields.Str(dump_default=RelationshipStatus.HAS_NO_PARENT) - phenotype = fields.Str( + phenotype = fields.Enum( + PhenotypeStatus, required=True, - validate=validate.OneOf(choices=["affected", "unaffected", "unknown"]), ) sex = fields.Str(required=True, validate=validate.OneOf(choices=["female", "male", "unknown"])) expected_coverage = fields.Float() diff --git a/cg/constants/subject.py b/cg/constants/subject.py index 9850593d23..1fae57dfe0 100644 --- a/cg/constants/subject.py +++ b/cg/constants/subject.py @@ -1,4 +1,4 @@ -from enum import IntEnum, StrEnum +from enum import Enum, IntEnum, StrEnum, auto class Sex(StrEnum): @@ -9,11 +9,10 @@ class Sex(StrEnum): MISSING = "" -class PhenotypeStatus(StrEnum): - UNKNOWN = "unknown" - UNAFFECTED = "unaffected" - AFFECTED = "affected" - MISSING = "" +class PhenotypeStatus(Enum): + UNKNOWN = auto() + UNAFFECTED = auto() + AFFECTED = auto() class PlinkPhenotypeStatus(IntEnum): diff --git a/cg/meta/workflow/raredisease.py b/cg/meta/workflow/raredisease.py index 1e350bb214..ecdc3e805b 100644 --- a/cg/meta/workflow/raredisease.py +++ b/cg/meta/workflow/raredisease.py @@ -5,7 +5,7 @@ from cg.constants import GenePanelMasterList, Workflow from cg.constants.gene_panel import GENOME_BUILD_37 -from cg.constants.subject import PlinkPhenotypeStatus, PlinkSex +from cg.constants.subject import PhenotypeStatus, PlinkPhenotypeStatus, PlinkSex from cg.meta.workflow.analysis import add_gene_panel_combo from cg.meta.workflow.nf_analysis import NfAnalysisAPI from cg.models.cg_config import CGConfig @@ -81,11 +81,11 @@ def get_workflow_parameters(self, case_id: str) -> WorkflowParameters: ) @staticmethod - def get_phenotype_code(phenotype: str) -> int: + def get_phenotype_code(phenotype: PhenotypeStatus) -> int: """Return Raredisease phenotype code.""" LOG.debug("Translate phenotype to integer code") try: - code = PlinkPhenotypeStatus[phenotype.upper()] + code = PlinkPhenotypeStatus[phenotype.name] except KeyError: raise ValueError(f"{phenotype} is not a valid phenotype") return code diff --git a/cg/models/scout/scout_load_config.py b/cg/models/scout/scout_load_config.py index b535311b7e..d3d2170156 100644 --- a/cg/models/scout/scout_load_config.py +++ b/cg/models/scout/scout_load_config.py @@ -6,6 +6,7 @@ from typing_extensions import Annotated, Literal from cg.constants.scout import UploadTrack +from cg.constants.subject import PhenotypeStatus from cg.models.scout.validators import field_not_none @@ -44,7 +45,7 @@ class ScoutIndividual(BaseModel): confirmed_sex: bool | None = None father: str | None = None mother: str | None = None - phenotype: str | None = None + phenotype: PhenotypeStatus | None = None sample_id: Annotated[str, BeforeValidator(field_not_none)] = None sample_name: str | None = None sex: Annotated[str | None, BeforeValidator(field_not_none)] = None diff --git a/cg/store/models.py b/cg/store/models.py index 45d54ed6d7..3b47f6de06 100644 --- a/cg/store/models.py +++ b/cg/store/models.py @@ -29,6 +29,7 @@ StatusOptions, ) from cg.constants.priority import SlurmQos +from cg.constants.subject import PhenotypeStatus from cg.constants.symbols import EMPTY_STRING BigInt = Annotated[int, None] @@ -618,9 +619,7 @@ class CaseSample(Base): id: Mapped[PrimaryKeyInt] case_id: Mapped[str] = mapped_column(ForeignKey("case.id", ondelete="CASCADE")) sample_id: Mapped[int] = mapped_column(ForeignKey("sample.id", ondelete="CASCADE")) - status: Mapped[str] = mapped_column( - types.Enum(*(status.value for status in StatusOptions)), default=StatusOptions.UNKNOWN.value - ) + status: Mapped[PhenotypeStatus] = mapped_column(default=StatusOptions.UNKNOWN) created_at: Mapped[datetime | None] updated_at: Mapped[datetime | None] diff --git a/tests/cli/workflow/mip/conftest.py b/tests/cli/workflow/mip/conftest.py index a6479f88e4..f936c5b5b0 100644 --- a/tests/cli/workflow/mip/conftest.py +++ b/tests/cli/workflow/mip/conftest.py @@ -7,7 +7,7 @@ from cg.apps.scout.scoutapi import ScoutAPI from cg.apps.tb import TrailblazerAPI from cg.constants import Workflow -from cg.constants.subject import Sex +from cg.constants.subject import PhenotypeStatus, Sex from cg.meta.compress import CompressAPI from cg.meta.workflow.mip_dna import MipDNAAnalysisAPI from cg.meta.workflow.mip_rna import MipRNAAnalysisAPI @@ -149,7 +149,9 @@ def mip_dna_context( customer_id="cust000", sex=Sex.UNKNOWN, ) - helpers.add_relationship(store=_store, sample=sample, case=case_obj, status="affected") + helpers.add_relationship( + store=_store, sample=sample, case=case_obj, status=PhenotypeStatus.AFFECTED + ) cg_context.meta_apis["analysis_api"] = mip_analysis_api return cg_context diff --git a/tests/conftest.py b/tests/conftest.py index 47275de63c..3f5fde7c25 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -32,7 +32,7 @@ from cg.constants.housekeeper_tags import HK_DELIVERY_REPORT_TAG from cg.constants.priority import SlurmQos from cg.constants.sequencing import SequencingPlatform -from cg.constants.subject import Sex +from cg.constants.subject import PhenotypeStatus, Sex from cg.io.controller import WriteFile from cg.io.json import read_json, write_json from cg.io.yaml import read_yaml, write_yaml @@ -50,7 +50,10 @@ from cg.models.flow_cell.flow_cell import FlowCellDirectoryData from cg.models.raredisease.raredisease import RarediseaseSampleSheetHeaders from cg.models.rnafusion.rnafusion import RnafusionParameters, RnafusionSampleSheetEntry -from cg.models.taxprofiler.taxprofiler import TaxprofilerParameters, TaxprofilerSampleSheetEntry +from cg.models.taxprofiler.taxprofiler import ( + TaxprofilerParameters, + TaxprofilerSampleSheetEntry, +) from cg.models.tomte.tomte import TomteSampleSheetHeaders from cg.store.database import create_all_tables, drop_all_tables, initialize_database from cg.store.models import Bed, BedVersion, Case, Customer, Order, Organism, Sample @@ -266,7 +269,7 @@ def analysis_family(case_id: str, family_name: str, sample_id: str, ticket_id: s "internal_id": sample_id, "father": "ADM2", "mother": "ADM3", - "status": "affected", + "status": PhenotypeStatus.AFFECTED, "original_ticket": ticket_id, "reads": 5000000, "capture_kit": "GMSmyeloid", @@ -275,7 +278,7 @@ def analysis_family(case_id: str, family_name: str, sample_id: str, ticket_id: s "name": "father", "sex": Sex.MALE, "internal_id": "ADM2", - "status": "unaffected", + "status": PhenotypeStatus.UNAFFECTED, "original_ticket": ticket_id, "reads": 6000000, "capture_kit": "GMSmyeloid", @@ -284,7 +287,7 @@ def analysis_family(case_id: str, family_name: str, sample_id: str, ticket_id: s "name": "mother", "sex": Sex.FEMALE, "internal_id": "ADM3", - "status": "unaffected", + "status": PhenotypeStatus.UNAFFECTED, "original_ticket": ticket_id, "reads": 7000000, "capture_kit": "GMSmyeloid", diff --git a/tests/store_helpers.py b/tests/store_helpers.py index dac431d899..9097ac292b 100644 --- a/tests/store_helpers.py +++ b/tests/store_helpers.py @@ -699,7 +699,7 @@ def add_relationship( store: Store, sample: Sample, case: Case, - status: str = PhenotypeStatus.UNKNOWN, + status: PhenotypeStatus = PhenotypeStatus.UNKNOWN, father: Sample = None, mother: Sample = None, ) -> CaseSample: