From 40306db505161895ed29a21ebabbee083a8c3ac0 Mon Sep 17 00:00:00 2001 From: Annick Renevey <47788523+rannick@users.noreply.github.com> Date: Thu, 23 Jan 2025 11:26:49 +0100 Subject: [PATCH 01/16] update raredisease filenames (#4141) | patch ### Changed - Typo in stranger step - Path to chromograph files sites and regions --- .../raredisease_bundle_filenames.yaml | 202 +++++++++--------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/cg/resources/raredisease_bundle_filenames.yaml b/cg/resources/raredisease_bundle_filenames.yaml index f09adeea2e..971d5f6d31 100644 --- a/cg/resources/raredisease_bundle_filenames.yaml +++ b/cg/resources/raredisease_bundle_filenames.yaml @@ -200,7 +200,7 @@ id: CASEID path: PATHTOCASE/repeat_expansions/CASEID_repeat_expansion_stranger.vcf.gz path_index: ~ - step: expansionhunter_stanger + step: expansionhunter_stranger tag: case_sv_str - format: vcf id: CASEID @@ -647,302 +647,302 @@ step: chromograph_rhoviz tag: autozyg - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_1.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_rhocall_filter_cadd_vep_upd_regions_1.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_2.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_2.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_3.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_3.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_4.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_4.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_5.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_5.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_6.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_6.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_7.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_7.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_8.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_8.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_9.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_9.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_10.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_10.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_11.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_11.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_12.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_12.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_13.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_13.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_14.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_14.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_15.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_15.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_16.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_16.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_17.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_17.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_18.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_18.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_19.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_19.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_20.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_20.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_21.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_21.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_22.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_22.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_X.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_X.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_Y.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_Y.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_regions_chromograph/CASEID_rhocall_filter_cadd_vep_upd_regions_M.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_regions/SAMPLEID_upd_regions_M.png path_index: ~ step: chromograph_upd tag: regions - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_1.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_1.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_2.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_2.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_3.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_3.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_4.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_4.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_5.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_5.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_6.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_6.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_7.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_7.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_8.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_8.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_9.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_9.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_10.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_10.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_11.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_11.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_12.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_12.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_13.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_13.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_14.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_14.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_15.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_15.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_16.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_16.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_17.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_17.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_18.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_18.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_19.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_19.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_20.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_20.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_21.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_21.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_22.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_22.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_X.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_X.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_Y.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_Y.png path_index: ~ step: chromograph_upd tag: sites - format: png - id: CASEID - path: PATHTOCASE/annotate_snv/genome/CASEID_rhocall_filter_cadd_vep_upd_sites_chromograph/CASEID_rhocall_filter_cadd_vep_upd_sites_M.png + id: SAMPLEID + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_M.png path_index: ~ step: chromograph_upd tag: sites From aac9406f48c0b1ad6bd203068c9f2bb4180694a3 Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Thu, 23 Jan 2025 10:27:14 +0000 Subject: [PATCH 02/16] =?UTF-8?q?Bump=20version:=2067.0.0=20=E2=86=92=2067?= =?UTF-8?q?.0.1=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 70bd30c6b3..69b3a2eca7 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.0 +current_version = 67.0.1 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index c7594aa2db..62793fecbb 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.0" +__version__ = "67.0.1" diff --git a/pyproject.toml b/pyproject.toml index 49ac0efaae..04a8317adf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.0" +version = "67.0.1" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From 016d4d7caa794bd48cc1876eac3fae580c96d933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20Ohlsson=20=C3=85ngnell?= <40887124+islean@users.noreply.github.com> Date: Thu, 23 Jan 2025 11:36:56 +0100 Subject: [PATCH 03/16] Patch skip rc (#4146)(patch) ## Description Sometimes skip reception control gets sent as None. This gets converted to False now. ### Fixed - skip_reception_control gets converted to False if null --- cg/services/orders/validation/models/order.py | 6 ++++-- cg/services/orders/validation/models/utils.py | 2 ++ .../validation_service/test_model_validator.py | 12 ++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 cg/services/orders/validation/models/utils.py diff --git a/cg/services/orders/validation/models/order.py b/cg/services/orders/validation/models/order.py index 8f950f0c4c..ccc3d74341 100644 --- a/cg/services/orders/validation/models/order.py +++ b/cg/services/orders/validation/models/order.py @@ -1,7 +1,9 @@ -from pydantic import BaseModel, Field, PrivateAttr, model_validator +from pydantic import BaseModel, BeforeValidator, Field, PrivateAttr, model_validator +from typing_extensions import Annotated from cg.constants import DataDelivery from cg.models.orders.constants import OrderType +from cg.services.orders.validation.models.utils import set_null_to_false class Order(BaseModel): @@ -10,7 +12,7 @@ class Order(BaseModel): delivery_type: DataDelivery order_type: OrderType = Field(alias="project_type") name: str = Field(min_length=1) - skip_reception_control: bool = False + skip_reception_control: Annotated[bool, BeforeValidator(set_null_to_false)] = False _generated_ticket_id: int | None = PrivateAttr(default=None) _user_id: int = PrivateAttr(default=None) diff --git a/cg/services/orders/validation/models/utils.py b/cg/services/orders/validation/models/utils.py new file mode 100644 index 0000000000..1d8f27404c --- /dev/null +++ b/cg/services/orders/validation/models/utils.py @@ -0,0 +1,2 @@ +def set_null_to_false(value: bool | None) -> bool: + return value if value else False diff --git a/tests/services/orders/validation_service/test_model_validator.py b/tests/services/orders/validation_service/test_model_validator.py index c2ecb84068..a68eeb760f 100644 --- a/tests/services/orders/validation_service/test_model_validator.py +++ b/tests/services/orders/validation_service/test_model_validator.py @@ -130,3 +130,15 @@ def test_null_conversion(valid_order: TomteOrder, model_validator: ModelValidato # THEN the empty concentration should be converted to None assert order.cases[0].samples[0].concentration_ng_ul is None + + +def test_skip_rc_default_conversion(valid_order: TomteOrder, model_validator: ModelValidator): + # GIVEN a Tomte order with skip_reception_control set to None + valid_order.skip_reception_control = None + raw_order: dict = valid_order.model_dump(by_alias=True) + + # WHEN validating the order + order, _ = model_validator.validate(order=raw_order, model=TomteOrder) + + # THEN the skip_reception_control value should be converted to None + assert order.skip_reception_control is False From 46aa83facd611c3cdb51ba9eb0883b0bfe027d2d Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Thu, 23 Jan 2025 10:37:23 +0000 Subject: [PATCH 04/16] =?UTF-8?q?Bump=20version:=2067.0.1=20=E2=86=92=2067?= =?UTF-8?q?.0.2=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 69b3a2eca7..5eb49ea1a6 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.1 +current_version = 67.0.2 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index 62793fecbb..2d7cf32248 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.1" +__version__ = "67.0.2" diff --git a/pyproject.toml b/pyproject.toml index 04a8317adf..77db412be4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.1" +version = "67.0.2" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From f2a06be181683dfa5a32c93f5831cbb6bd42698d Mon Sep 17 00:00:00 2001 From: Annick Renevey <47788523+rannick@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:23:27 +0100 Subject: [PATCH 05/16] fix typo (#4151) | patch ### Fixed - Typo in paths for raredisease --- .../raredisease_bundle_filenames.yaml | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/cg/resources/raredisease_bundle_filenames.yaml b/cg/resources/raredisease_bundle_filenames.yaml index 971d5f6d31..21ca8587c4 100644 --- a/cg/resources/raredisease_bundle_filenames.yaml +++ b/cg/resources/raredisease_bundle_filenames.yaml @@ -798,151 +798,151 @@ tag: regions - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_1.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_1.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_2.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_2.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_3.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_3.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_4.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_4.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_5.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_5.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_6.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_6.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_7.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_7.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_8.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_8.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_9.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_9.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_10.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_10.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_11.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_11.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_12.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_12.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_13.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_13.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_14.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_14.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_15.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_15.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_16.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_16.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_17.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_17.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_18.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_18.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_19.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_19.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_20.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_20.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_21.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_21.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_22.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_22.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_X.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_X.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_Y.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_Y.png path_index: ~ step: chromograph_upd tag: sites - format: png id: SAMPLEID - path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID__upd_sites_M.png + path: PATHTOCASE/annotate_snv/genome/SAMPLEID_chromograph_sites/SAMPLEID_upd_sites_M.png path_index: ~ step: chromograph_upd tag: sites From 8cec5df47e9e3f73dbae520e5b25a1652e4637c7 Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Thu, 23 Jan 2025 15:23:56 +0000 Subject: [PATCH 06/16] =?UTF-8?q?Bump=20version:=2067.0.2=20=E2=86=92=2067?= =?UTF-8?q?.0.3=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5eb49ea1a6..de1944f325 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.2 +current_version = 67.0.3 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index 2d7cf32248..91a7e716b8 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.2" +__version__ = "67.0.3" diff --git a/pyproject.toml b/pyproject.toml index 77db412be4..014eabf8c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.2" +version = "67.0.3" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From ad7320200e46227ce5bfe4a351e809bdc1849521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20Ohlsson=20=C3=85ngnell?= <40887124+islean@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:42:45 +0100 Subject: [PATCH 07/16] Fix order messages (#4147) (patch) ### Fixed - New lines for every sample - Use sample priority name to avoid ints --- cg/services/orders/submitter/ticket_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cg/services/orders/submitter/ticket_handler.py b/cg/services/orders/submitter/ticket_handler.py index 54ff979156..d6907a41da 100644 --- a/cg/services/orders/submitter/ticket_handler.py +++ b/cg/services/orders/submitter/ticket_handler.py @@ -119,14 +119,12 @@ def add_sample_case_name_to_message(message: str, case_name: str | None) -> str: def add_existing_sample_info_to_message( self, message: str, customer_id: str, internal_id: str, case_name: str ) -> str: - existing_sample: Sample = self.status_db.get_sample_by_internal_id(internal_id=internal_id) sample_customer = "" if existing_sample.customer_id != customer_id: sample_customer = " from " + existing_sample.customer.internal_id - - message += f"{existing_sample.name}, application: {existing_sample.application_version.application.tag}, case: {case_name} (already existing sample{sample_customer}), priority: {existing_sample.priority}" + message += f"{existing_sample.name}, application: {existing_sample.application_version.application.tag}, case: {case_name} (already existing sample{sample_customer}), priority: {existing_sample.priority.name.lower()}" return message @staticmethod @@ -180,6 +178,7 @@ def create_case_xml_sample_list(self, order, message: str) -> str: if not case.is_new: db_case = self.status_db.get_case_by_internal_id(case.internal_id) for sample in db_case.samples: + message += self.NEW_LINE message = self.add_existing_sample_info_to_message( message=message, customer_id=sample.customer.internal_id, @@ -189,6 +188,7 @@ def create_case_xml_sample_list(self, order, message: str) -> str: else: for sample in case.samples: if not sample.is_new: + message += self.NEW_LINE message = self.add_existing_sample_info_to_message( message=message, customer_id=order.customer, From 9d76931876b0c17dcb25a25d742fe471db0efc8b Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Mon, 27 Jan 2025 08:43:14 +0000 Subject: [PATCH 08/16] =?UTF-8?q?Bump=20version:=2067.0.3=20=E2=86=92=2067?= =?UTF-8?q?.0.4=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index de1944f325..c983d93f94 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.3 +current_version = 67.0.4 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index 91a7e716b8..a0b124633f 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.3" +__version__ = "67.0.4" diff --git a/pyproject.toml b/pyproject.toml index 014eabf8c2..8928a9771f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.3" +version = "67.0.4" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From 0eb937400c3c64abbdcc8c3d68396406d0fbfc4a Mon Sep 17 00:00:00 2001 From: Sebastian Diaz Date: Mon, 27 Jan 2025 09:57:45 +0100 Subject: [PATCH 09/16] Fix tests from improve order flow (#4152)(patch) Fix some tests set to fail in the main branch and adds a test for the case when skipping reception control is set to true. --- .../lims_service/test_order_lims_service.py | 101 ++++++++++-------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/tests/services/orders/lims_service/test_order_lims_service.py b/tests/services/orders/lims_service/test_order_lims_service.py index af30e418f4..70765098b1 100644 --- a/tests/services/orders/lims_service/test_order_lims_service.py +++ b/tests/services/orders/lims_service/test_order_lims_service.py @@ -1,5 +1,3 @@ -import pytest - from cg.constants import Workflow from cg.models.lims.sample import LimsSample from cg.services.orders.lims_service.service import OrderLimsService @@ -12,17 +10,17 @@ from cg.services.orders.validation.workflows.rml.models.order import RmlOrder -def test_to_lims_mip(mip_dna_order_to_submit): +def test_to_lims_mip(mip_dna_order: MipDnaOrder): # GIVEN a scout order for a trio - order_data = MipDnaOrder.model_validate(mip_dna_order_to_submit) + # WHEN parsing the order to format for LIMS import - new_samples = [sample for _, _, sample in order_data.enumerated_new_samples] + new_samples = [sample for _, _, sample in mip_dna_order.enumerated_new_samples] samples: list[LimsSample] = OrderLimsService._build_lims_sample( customer="cust003", samples=new_samples, workflow=Workflow.MIP_DNA, - delivery_type=order_data.delivery_type, - skip_reception_control=order_data.skip_reception_control, + delivery_type=mip_dna_order.delivery_type, + skip_reception_control=mip_dna_order.skip_reception_control, ) # THEN it should list all samples @@ -35,7 +33,7 @@ def test_to_lims_mip(mip_dna_order_to_submit): container_names = {sample.container_name for sample in samples if sample.container_name} assert container_names == {"MipPlate"} - # ... and pick out relevant UDFs + # THEN it should pick out relevant UDFs first_sample: LimsSample = samples[0] assert first_sample.well_position == "A:1" assert first_sample.udfs.priority == "standard" @@ -48,40 +46,39 @@ def test_to_lims_mip(mip_dna_order_to_submit): assert isinstance(samples[1].udfs.comment, str) -def test_to_lims_fastq(fastq_order_to_submit): +def test_to_lims_fastq(fastq_order: FastqOrder): # GIVEN a fastq order for two samples; normal vs. tumour - order_data = FastqOrder.model_validate(fastq_order_to_submit) # WHEN parsing the order to format for LIMS samples: list[LimsSample] = OrderLimsService._build_lims_sample( customer="dummyCust", - samples=order_data.samples, + samples=fastq_order.samples, workflow=Workflow.RAW_DATA, - delivery_type=order_data.delivery_type, - skip_reception_control=order_data.skip_reception_control, + delivery_type=fastq_order.delivery_type, + skip_reception_control=fastq_order.skip_reception_control, ) - # THEN should "work" + # THEN two samples should be parsed, one normal and one tumour assert len(samples) == 2 normal_sample = samples[0] tumour_sample = samples[1] - # ... and pick out relevant UDF values + + # THEN it should pick out relevant UDFs assert normal_sample.udfs.tumour is False assert tumour_sample.udfs.tumour is True assert normal_sample.udfs.volume == "54" -@pytest.mark.xfail(reason="RML sample container validation not working") -def test_to_lims_rml(rml_order_to_submit: dict): +def test_to_lims_rml(rml_order: RmlOrder): # GIVEN a rml order for four samples - order_data = RmlOrder.model_validate(rml_order_to_submit) # WHEN parsing for LIMS samples: list[LimsSample] = OrderLimsService._build_lims_sample( customer="cust000", - samples=order_data.samples, + samples=rml_order.samples, workflow=Workflow.RAW_DATA, - delivery_type=order_data.delivery_type, + delivery_type=rml_order.delivery_type, + skip_reception_control=rml_order.skip_reception_control, ) # THEN it should have found the same number of samples @@ -97,17 +94,16 @@ def test_to_lims_rml(rml_order_to_submit: dict): assert first_sample.udfs.well_position_rml == "A:1" -@pytest.mark.xfail(reason="Fluffy sample container validation not working") -def test_to_lims_fluffy(fluffy_order_to_submit: dict): +def test_to_lims_fluffy(fluffy_order: FluffyOrder): # GIVEN a Fluffy order for four samples - order_data = FluffyOrder.model_validate(fluffy_order_to_submit) # WHEN parsing for LIMS samples: list[LimsSample] = OrderLimsService._build_lims_sample( customer="cust000", - samples=order_data.samples, + samples=fluffy_order.samples, workflow=Workflow.FLUFFY, - delivery_type=order_data.delivery_type, + delivery_type=fluffy_order.delivery_type, + skip_reception_control=fluffy_order.skip_reception_control, ) # THEN it should have found the same number of samples @@ -123,22 +119,22 @@ def test_to_lims_fluffy(fluffy_order_to_submit: dict): assert first_sample.udfs.well_position_rml == "A:1" -def test_to_lims_microbial(microbial_order_to_submit: dict): +def test_to_lims_microbial(microsalt_order: MicrosaltOrder): # GIVEN a microbial order for three samples - order_data = MicrosaltOrder.model_validate(microbial_order_to_submit) # WHEN parsing for LIMS samples: list[LimsSample] = OrderLimsService._build_lims_sample( customer="cust000", - samples=order_data.samples, + samples=microsalt_order.samples, workflow=Workflow.MICROSALT, - delivery_type=order_data.delivery_type, - skip_reception_control=order_data.skip_reception_control, + delivery_type=microsalt_order.delivery_type, + skip_reception_control=microsalt_order.skip_reception_control, ) - # THEN it should "work" + # THEN 5 samples should be parsed assert len(samples) == 5 - # ... and pick out relevant UDFs + + # THEN it should pick out relevant UDFs first_sample = samples[0].dict() assert first_sample["udfs"]["priority"] == "research" assert first_sample["udfs"]["organism"] == "C. jejuni" @@ -161,7 +157,8 @@ def test_to_lims_sarscov2(mutant_order: MutantOrder): # THEN it should have found the same number of samples assert len(samples) == 6 - # ... and pick out relevant UDFs + + # THEN it should pick out relevant UDFs first_sample = samples[0].dict() assert first_sample["udfs"]["collection_date"] == "2021-05-05" assert first_sample["udfs"]["extraction_method"] == "MagNaPure 96" @@ -178,27 +175,26 @@ def test_to_lims_sarscov2(mutant_order: MutantOrder): assert first_sample["udfs"]["volume"] == "20" -def test_to_lims_balsamic(balsamic_order_to_submit: dict): +def test_to_lims_balsamic(balsamic_order: BalsamicOrder): # GIVEN a cancer order for a sample - order_data = BalsamicOrder.model_validate(balsamic_order_to_submit) - new_samples = [sample for _, _, sample in order_data.enumerated_new_samples] + new_samples = [sample for _, _, sample in balsamic_order.enumerated_new_samples] # WHEN parsing the order to format for LIMS import samples: list[LimsSample] = OrderLimsService._build_lims_sample( customer="cust000", samples=new_samples, workflow=Workflow.BALSAMIC, - delivery_type=order_data.delivery_type, - skip_reception_control=order_data.skip_reception_control, + delivery_type=balsamic_order.delivery_type, + skip_reception_control=balsamic_order.skip_reception_control, ) - # THEN it should list all samples + # THEN it should list all samples assert len(samples) == 1 - # ... and determine the container, container name, and well position + # THEN it should determine the container, container name, and well position container_names = {sample.container_name for sample in samples if sample.container_name} - # ... and pick out relevant UDFs + # THEN it should pick out relevant UDFs first_sample = samples[0].dict() assert first_sample["name"] == "BalsamicSample" assert {sample.container for sample in samples} == set(["96 well plate"]) @@ -209,15 +205,32 @@ def test_to_lims_balsamic(balsamic_order_to_submit: dict): assert first_sample["udfs"]["source"] == "cytology (FFPE)" assert first_sample["udfs"]["volume"] == "42" assert first_sample["udfs"]["priority"] == "standard" - assert container_names == set(["BalsamicPlate"]) assert first_sample["well_position"] == "A:1" assert first_sample["udfs"]["tumour"] is True assert first_sample["udfs"]["capture_kit"] == "GMCKsolid" assert first_sample["udfs"]["tumour_purity"] == "13" - assert first_sample["udfs"]["formalin_fixation_time"] == "15" assert first_sample["udfs"]["post_formalin_fixation_time"] == "3" assert first_sample["udfs"]["tissue_block_size"] == "large" - assert first_sample["udfs"]["comment"] == "This is a sample comment" + + +def test_order_with_skip_reception_control(balsamic_order: BalsamicOrder): + """Test that an order set to skip reception control can be parsed correctly by LIMS.""" + # GIVEN a Balsamic order with one case and one sample set to skip reception control + balsamic_order.skip_reception_control = True + + # WHEN parsing the order to format for LIMS import + new_samples = [sample for _, _, sample in balsamic_order.enumerated_new_samples] + samples: list[LimsSample] = OrderLimsService._build_lims_sample( + customer="cust000", + samples=new_samples, + workflow=Workflow.BALSAMIC, + delivery_type=balsamic_order.delivery_type, + skip_reception_control=balsamic_order.skip_reception_control, + ) + + # THEN the parsed samples should have the skip reception control flag set + first_sample = samples[0].dict() + assert first_sample["udfs"]["skip_reception_control"] is True From e7621a7ca6c2ac34bbcb3d83d72276ab4c1e6b54 Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Mon, 27 Jan 2025 08:58:19 +0000 Subject: [PATCH 10/16] =?UTF-8?q?Bump=20version:=2067.0.4=20=E2=86=92=2067?= =?UTF-8?q?.0.5=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c983d93f94..2871b01f7c 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.4 +current_version = 67.0.5 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index a0b124633f..fec30ebd0b 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.4" +__version__ = "67.0.5" diff --git a/pyproject.toml b/pyproject.toml index 8928a9771f..ab380588b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.4" +version = "67.0.5" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From 74aebfcdb976b990d81ee2bff4cab0f2da769150 Mon Sep 17 00:00:00 2001 From: Annick Renevey <47788523+rannick@users.noreply.github.com> Date: Mon, 27 Jan 2025 14:04:46 +0100 Subject: [PATCH 11/16] add d4 to rd scout load config (#4154) | patch ### Added - Add d4_file to raredisease scout load config --- cg/constants/scout.py | 1 + cg/meta/upload/scout/hk_tags.py | 1 + cg/meta/upload/scout/raredisease_config_builder.py | 9 ++++----- cg/models/scout/scout_load_config.py | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cg/constants/scout.py b/cg/constants/scout.py index 2507a5abbe..5371f4275c 100644 --- a/cg/constants/scout.py +++ b/cg/constants/scout.py @@ -106,6 +106,7 @@ class ScoutUploadKey(StrEnum): RAREDISEASE_SAMPLE_TAGS: dict[str, set[str]] = dict( alignment_file={AlignmentFileTag.CRAM}, + d4_file={"d4"}, vcf2cytosure={"vcf2cytosure"}, mt_bam={"bam-mt"}, eklipse_path={"eklipse-png"}, diff --git a/cg/meta/upload/scout/hk_tags.py b/cg/meta/upload/scout/hk_tags.py index 8e83daad52..2b65df672c 100644 --- a/cg/meta/upload/scout/hk_tags.py +++ b/cg/meta/upload/scout/hk_tags.py @@ -71,6 +71,7 @@ class SampleTags(BaseModel): bam_file: set[str] | None = None alignment_file: set[str] | None = None alignment_path: set[str] | None = None + d4_file: set[str] | None = None vcf2cytosure: set[str] | None = None eklipse_path: set[str] | None = None mt_bam: set[str] | None = None diff --git a/cg/meta/upload/scout/raredisease_config_builder.py b/cg/meta/upload/scout/raredisease_config_builder.py index 5d8975b70d..68f803ea6e 100644 --- a/cg/meta/upload/scout/raredisease_config_builder.py +++ b/cg/meta/upload/scout/raredisease_config_builder.py @@ -6,11 +6,7 @@ from cg.apps.lims import LimsAPI from cg.apps.madeline.api import MadelineAPI from cg.constants.constants import FileFormat -from cg.constants.housekeeper_tags import ( - HK_DELIVERY_REPORT_TAG, - AnalysisTag, - NFAnalysisTags, -) +from cg.constants.housekeeper_tags import HK_DELIVERY_REPORT_TAG, AnalysisTag, NFAnalysisTags from cg.constants.scout import ( RANK_MODEL_THRESHOLD, RAREDISEASE_CASE_TAGS, @@ -206,3 +202,6 @@ def include_sample_files(self, config_sample: ScoutRarediseaseIndividual) -> Non config_sample.mitodel_file = self.get_sample_file( hk_tags=self.sample_tags.mitodel_file, sample_id=sample_id ) + config_sample.d4_file = self.get_sample_file( + hk_tags=self.sample_tags.d4_file, sample_id=sample_id + ) diff --git a/cg/models/scout/scout_load_config.py b/cg/models/scout/scout_load_config.py index 8075da8be0..3cf2c5eccc 100644 --- a/cg/models/scout/scout_load_config.py +++ b/cg/models/scout/scout_load_config.py @@ -93,6 +93,7 @@ class ScoutRarediseaseIndividual(ScoutIndividual): vcf2cytosure: str | None = None mitodel_file: str | None = None reviewer: Reviewer = Reviewer() + d4_file: str | None = None class ScoutCancerIndividual(ScoutIndividual): From 3303c0e5f3826e0745d22c7883b75880e6f6c8c4 Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Mon, 27 Jan 2025 13:05:14 +0000 Subject: [PATCH 12/16] =?UTF-8?q?Bump=20version:=2067.0.5=20=E2=86=92=2067?= =?UTF-8?q?.0.6=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 2871b01f7c..260f6303cc 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.5 +current_version = 67.0.6 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index fec30ebd0b..b403591292 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.5" +__version__ = "67.0.6" diff --git a/pyproject.toml b/pyproject.toml index ab380588b0..bd6865523f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.5" +version = "67.0.6" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From ea5e73881b1982d65c5c6eb979aecc42bf5a8338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Nyr=C3=A9n?= <45558267+karlnyr@users.noreply.github.com> Date: Tue, 28 Jan 2025 09:47:16 +0100 Subject: [PATCH 13/16] Add option to use BWA-MEM in Fluffy analysis commands (#4158) ### Added - Option to use BWA-MEM in fluffy analysis commands --- cg/cli/workflow/fluffy/base.py | 30 ++++++++++++++++++++++++++---- cg/meta/workflow/fluffy.py | 14 +++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/cg/cli/workflow/fluffy/base.py b/cg/cli/workflow/fluffy/base.py index 6da80b5639..b781effa90 100644 --- a/cg/cli/workflow/fluffy/base.py +++ b/cg/cli/workflow/fluffy/base.py @@ -13,6 +13,7 @@ ARGUMENT_CASE_ID = click.argument("case_id", required=True) OPTION_EXTERNAL_REF = click.option("-e", "--external-ref", is_flag=True) +OPTION_USE_BWA_MEM = click.option("-b", "--use-bwa-mem", is_flag=True) LOG = logging.getLogger(__name__) @@ -51,15 +52,27 @@ def create_samplesheet(context: CGConfig, case_id: str, dry_run: bool): @DRY_RUN @click.option("-c", "--config", help="Path to fluffy config in .json format") @OPTION_EXTERNAL_REF +@OPTION_USE_BWA_MEM @click.pass_obj -def run(context: CGConfig, case_id: str, dry_run: bool, config: str, external_ref: bool = False): +def run( + context: CGConfig, + case_id: str, + dry_run: bool, + config: str, + external_ref: bool, + use_bwa_mem: bool, +): """ Run Fluffy analysis """ analysis_api: FluffyAnalysisAPI = context.meta_apis["analysis_api"] analysis_api.status_db.verify_case_exists(case_internal_id=case_id) analysis_api.run_fluffy( - case_id=case_id, workflow_config=config, dry_run=dry_run, external_ref=external_ref + case_id=case_id, + workflow_config=config, + dry_run=dry_run, + external_ref=external_ref, + use_bwa_mem=use_bwa_mem, ) if dry_run: return @@ -78,12 +91,14 @@ def run(context: CGConfig, case_id: str, dry_run: bool, config: str, external_re @DRY_RUN @click.option("-c", "--config", help="Path to fluffy config in .json format") @OPTION_EXTERNAL_REF +@OPTION_USE_BWA_MEM @click.pass_context def start( context: click.Context, case_id: str, dry_run: bool, - external_ref: bool = False, + external_ref: bool, + use_bwa_mem: bool, config: str = None, ): """ @@ -96,7 +111,14 @@ def start( analysis_api.prepare_fastq_files(case_id=case_id, dry_run=dry_run) context.invoke(link, case_id=case_id, dry_run=dry_run) context.invoke(create_samplesheet, case_id=case_id, dry_run=dry_run) - context.invoke(run, case_id=case_id, config=config, dry_run=dry_run, external_ref=external_ref) + context.invoke( + run, + case_id=case_id, + config=config, + dry_run=dry_run, + external_ref=external_ref, + use_bwa_mem=use_bwa_mem, + ) @fluffy.command("start-available") diff --git a/cg/meta/workflow/fluffy.py b/cg/meta/workflow/fluffy.py index 9a4f7487fe..962d5fa604 100644 --- a/cg/meta/workflow/fluffy.py +++ b/cg/meta/workflow/fluffy.py @@ -227,7 +227,12 @@ def make_sample_sheet(self, case_id: str, dry_run: bool) -> None: fluffy_sample_sheet.write_sample_sheet(sample_sheet_out_path) def run_fluffy( - self, case_id: str, dry_run: bool, workflow_config: str, external_ref: bool = False + self, + case_id: str, + dry_run: bool, + workflow_config: str, + external_ref: bool, + use_bwa_mem: bool, ) -> None: """ Call fluffy with the configured command-line arguments @@ -239,10 +244,8 @@ def run_fluffy( shutil.rmtree(output_path, ignore_errors=True) if not workflow_config: workflow_config = self.fluffy_config.as_posix() - if not external_ref: - batch_ref_flag = "--batch-ref" - else: - batch_ref_flag = "" + batch_ref_flag = "" if external_ref else "--batch-ref" + use_bwa_mem_flag = "--bwa-mem" if use_bwa_mem else "" command_args = [ "--config", workflow_config, @@ -254,6 +257,7 @@ def run_fluffy( self.get_output_path(case_id=case_id).as_posix(), "--analyse", batch_ref_flag, + use_bwa_mem_flag, "--slurm_params", self.get_slurm_param_qos(case_id=case_id), ] From 521c45c62dae3d1cef91ec54553b0800006330eb Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Tue, 28 Jan 2025 08:47:45 +0000 Subject: [PATCH 14/16] =?UTF-8?q?Bump=20version:=2067.0.6=20=E2=86=92=2067?= =?UTF-8?q?.0.7=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 260f6303cc..71f05c097c 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.6 +current_version = 67.0.7 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index b403591292..031aed5ca6 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.6" +__version__ = "67.0.7" diff --git a/pyproject.toml b/pyproject.toml index bd6865523f..89e0f6e781 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.6" +version = "67.0.7" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg" From 9c71d7895911cd91a6ebc5bb210611e0d0a07365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20Ohlsson=20=C3=85ngnell?= <40887124+islean@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:43:02 +0100 Subject: [PATCH 15/16] Patch existing parents in rules (#4160) (patch) ### Fixed - validate_father_in_same_case works with existing samples - validate_mother_in_same_case works with existing samples - validate_fathers_are_male works with existing samples - validate_mothers_are_female works with existing samples --- cg/services/orders/validation/models/case.py | 10 ++- .../orders/validation/rules/case/utils.py | 9 +++ .../validation/rules/case_sample/rules.py | 23 +++--- .../validation/rules/case_sample/utils.py | 46 +++++++----- .../workflows/mip_dna/models/case.py | 4 +- .../validation/workflows/tomte/models/case.py | 4 +- .../workflows/tomte/test_case_sample_rules.py | 74 ++++++++++++++++++- 7 files changed, 132 insertions(+), 38 deletions(-) diff --git a/cg/services/orders/validation/models/case.py b/cg/services/orders/validation/models/case.py index 6c7207b547..81ce1b66ed 100644 --- a/cg/services/orders/validation/models/case.py +++ b/cg/services/orders/validation/models/case.py @@ -6,6 +6,8 @@ from cg.services.orders.validation.models.discriminators import has_internal_id from cg.services.orders.validation.models.existing_sample import ExistingSample from cg.services.orders.validation.models.sample_aliases import SampleInCase +from cg.store.models import Sample as DbSample +from cg.store.store import Store NewSample = Annotated[SampleInCase, Tag("new")] ExistingSampleType = Annotated[ExistingSample, Tag("existing")] @@ -45,11 +47,17 @@ def enumerated_existing_samples(self) -> list[tuple[int, ExistingSample]]: samples.append((sample_index, sample)) return samples - def get_sample(self, sample_name: str) -> SampleInCase | None: + def get_new_sample(self, sample_name: str) -> SampleInCase | None: for _, sample in self.enumerated_new_samples: if sample.name == sample_name: return sample + def get_existing_sample_from_db(self, sample_name: str, store: Store) -> DbSample | None: + for _, sample in self.enumerated_existing_samples: + db_sample: DbSample | None = store.get_sample_by_internal_id(sample.internal_id) + if db_sample and db_sample.name == sample_name: + return db_sample + @model_validator(mode="before") def convert_empty_strings_to_none(cls, data): if isinstance(data, dict): diff --git a/cg/services/orders/validation/rules/case/utils.py b/cg/services/orders/validation/rules/case/utils.py index 350082f884..30ef3ccac7 100644 --- a/cg/services/orders/validation/rules/case/utils.py +++ b/cg/services/orders/validation/rules/case/utils.py @@ -1,3 +1,4 @@ +from cg.services.orders.validation.models.case import Case from cg.services.orders.validation.models.existing_case import ExistingCase from cg.services.orders.validation.workflows.balsamic.models.case import BalsamicCase from cg.services.orders.validation.workflows.balsamic_umi.models.case import BalsamicUmiCase @@ -34,3 +35,11 @@ def is_case_not_from_collaboration(case: ExistingCase, customer_id: str, store: db_case: DbCase | None = store.get_case_by_internal_id(case.internal_id) customer: Customer | None = store.get_customer_by_internal_id(customer_id) return db_case and customer and db_case.customer not in customer.collaborators + + +def is_sample_in_case(case: Case, sample_name: str, store: Store) -> bool: + if case.get_new_sample(sample_name): + return True + elif case.get_existing_sample_from_db(sample_name=sample_name, store=store): + return True + return False diff --git a/cg/services/orders/validation/rules/case_sample/rules.py b/cg/services/orders/validation/rules/case_sample/rules.py index e0c7a79b06..82307bea0a 100644 --- a/cg/services/orders/validation/rules/case_sample/rules.py +++ b/cg/services/orders/validation/rules/case_sample/rules.py @@ -292,48 +292,49 @@ def validate_sample_names_different_from_case_names( return errors -def validate_fathers_are_male(order: OrderWithCases, **kwargs) -> list[InvalidFatherSexError]: +def validate_fathers_are_male( + order: OrderWithCases, store: Store, **kwargs +) -> list[InvalidFatherSexError]: errors: list[InvalidFatherSexError] = [] for index, case in order.enumerated_new_cases: case_errors: list[InvalidFatherSexError] = get_father_sex_errors( - case=case, case_index=index + case=case, case_index=index, store=store ) errors.extend(case_errors) return errors def validate_fathers_in_same_case_as_children( - order: OrderWithCases, **kwargs + order: OrderWithCases, store: Store, **kwargs ) -> list[FatherNotInCaseError]: errors: list[FatherNotInCaseError] = [] for index, case in order.enumerated_new_cases: case_errors: list[FatherNotInCaseError] = get_father_case_errors( - case=case, - case_index=index, + case=case, case_index=index, store=store ) errors.extend(case_errors) return errors -def validate_mothers_are_female(order: OrderWithCases, **kwargs) -> list[InvalidMotherSexError]: +def validate_mothers_are_female( + order: OrderWithCases, store: Store, **kwargs +) -> list[InvalidMotherSexError]: errors: list[InvalidMotherSexError] = [] for index, case in order.enumerated_new_cases: case_errors: list[InvalidMotherSexError] = get_mother_sex_errors( - case=case, - case_index=index, + case=case, case_index=index, store=store ) errors.extend(case_errors) return errors def validate_mothers_in_same_case_as_children( - order: OrderWithCases, **kwargs + order: OrderWithCases, store: Store, **kwargs ) -> list[MotherNotInCaseError]: errors: list[MotherNotInCaseError] = [] for index, case in order.enumerated_new_cases: case_errors: list[MotherNotInCaseError] = get_mother_case_errors( - case=case, - case_index=index, + case=case, case_index=index, store=store ) errors.extend(case_errors) return errors diff --git a/cg/services/orders/validation/rules/case_sample/utils.py b/cg/services/orders/validation/rules/case_sample/utils.py index 9db37b3c9e..979147d510 100644 --- a/cg/services/orders/validation/rules/case_sample/utils.py +++ b/cg/services/orders/validation/rules/case_sample/utils.py @@ -28,6 +28,7 @@ SampleInCase, SampleWithRelatives, ) +from cg.services.orders.validation.rules.case.utils import is_sample_in_case from cg.services.orders.validation.rules.utils import ( get_concentration_interval, has_sample_invalid_concentration, @@ -112,12 +113,12 @@ def get_repeated_case_name_errors(order: OrderWithCases) -> list[RepeatedCaseNam def get_father_sex_errors( - case: CaseContainingRelatives, case_index: int + case: CaseContainingRelatives, case_index: int, store: Store ) -> list[InvalidFatherSexError]: errors: list[InvalidFatherSexError] = [] children: list[tuple[SampleWithRelatives, int]] = case.get_samples_with_father() for child, child_index in children: - if is_father_sex_invalid(child=child, case=case): + if is_father_sex_invalid(child=child, case=case, store=store): error: InvalidFatherSexError = create_father_sex_error( case_index=case_index, sample_index=child_index ) @@ -125,8 +126,14 @@ def get_father_sex_errors( return errors -def is_father_sex_invalid(child: SampleWithRelatives, case: CaseContainingRelatives) -> bool: - father: SampleWithRelatives | None = case.get_sample(child.father) +def is_father_sex_invalid( + child: SampleWithRelatives, case: CaseContainingRelatives, store: Store +) -> bool: + father: SampleWithRelatives | None = case.get_new_sample(child.father) + if not father: + father: DbSample | None = case.get_existing_sample_from_db( + sample_name=child.father, store=store + ) return father and father.sex != Sex.MALE @@ -135,14 +142,14 @@ def create_father_sex_error(case_index: int, sample_index: int) -> InvalidFather def get_father_case_errors( - case: CaseContainingRelatives, - case_index: int, + case: CaseContainingRelatives, case_index: int, store: Store ) -> list[FatherNotInCaseError]: errors: list[FatherNotInCaseError] = [] - children: list[tuple[SampleWithRelatives, int]] = case.get_samples_with_father() + children: list[tuple[SampleWithRelatives | ExistingSample, int]] = ( + case.get_samples_with_father() + ) for child, child_index in children: - father: SampleWithRelatives | None = case.get_sample(child.father) - if not father: + if not is_sample_in_case(case=case, sample_name=child.father, store=store): error: FatherNotInCaseError = create_father_case_error( case_index=case_index, sample_index=child_index, @@ -152,13 +159,12 @@ def get_father_case_errors( def get_mother_sex_errors( - case: CaseContainingRelatives, - case_index: int, + case: CaseContainingRelatives, case_index: int, store: Store ) -> list[InvalidMotherSexError]: errors: list[InvalidMotherSexError] = [] children: list[tuple[SampleWithRelatives, int]] = case.get_samples_with_mother() for child, child_index in children: - if is_mother_sex_invalid(child=child, case=case): + if is_mother_sex_invalid(child=child, case=case, store=store): error: InvalidMotherSexError = create_mother_sex_error( case_index=case_index, sample_index=child_index, @@ -168,14 +174,12 @@ def get_mother_sex_errors( def get_mother_case_errors( - case: CaseContainingRelatives, - case_index: int, + case: CaseContainingRelatives, case_index: int, store: Store ) -> list[MotherNotInCaseError]: errors: list[MotherNotInCaseError] = [] children: list[tuple[SampleWithRelatives, int]] = case.get_samples_with_mother() for child, child_index in children: - mother: SampleWithRelatives | None = case.get_sample(child.mother) - if not mother: + if not is_sample_in_case(case=case, sample_name=child.mother, store=store): error: MotherNotInCaseError = create_mother_case_error( case_index=case_index, sample_index=child_index ) @@ -191,8 +195,14 @@ def create_mother_case_error(case_index: int, sample_index: int) -> MotherNotInC return MotherNotInCaseError(case_index=case_index, sample_index=sample_index) -def is_mother_sex_invalid(child: SampleWithRelatives, case: CaseContainingRelatives) -> bool: - mother: SampleWithRelatives | None = case.get_sample(child.mother) +def is_mother_sex_invalid( + child: SampleWithRelatives, case: CaseContainingRelatives, store: Store +) -> bool: + mother: SampleWithRelatives | None = case.get_new_sample(child.mother) + if not mother: + mother: DbSample | None = case.get_existing_sample_from_db( + sample_name=child.mother, store=store + ) return mother and mother.sex != Sex.FEMALE diff --git a/cg/services/orders/validation/workflows/mip_dna/models/case.py b/cg/services/orders/validation/workflows/mip_dna/models/case.py index 1a77df2902..3c6dda474f 100644 --- a/cg/services/orders/validation/workflows/mip_dna/models/case.py +++ b/cg/services/orders/validation/workflows/mip_dna/models/case.py @@ -16,8 +16,8 @@ class MipDnaCase(Case): synopsis: str | None = None samples: list[Annotated[NewSample | OldSample, Discriminator(has_internal_id)]] - def get_samples_with_father(self) -> list[tuple[MipDnaSample, int]]: + def get_samples_with_father(self) -> list[tuple[MipDnaSample | ExistingSample, int]]: return [(sample, index) for index, sample in self.enumerated_samples if sample.father] - def get_samples_with_mother(self) -> list[tuple[MipDnaSample, int]]: + def get_samples_with_mother(self) -> list[tuple[MipDnaSample | ExistingSample, int]]: return [(sample, index) for index, sample in self.enumerated_samples if sample.mother] diff --git a/cg/services/orders/validation/workflows/tomte/models/case.py b/cg/services/orders/validation/workflows/tomte/models/case.py index ab4504e4ea..7b99fb37e9 100644 --- a/cg/services/orders/validation/workflows/tomte/models/case.py +++ b/cg/services/orders/validation/workflows/tomte/models/case.py @@ -16,8 +16,8 @@ class TomteCase(Case): synopsis: str | None = None samples: list[Annotated[NewSample | OldSample, Discriminator(has_internal_id)]] - def get_samples_with_father(self) -> list[tuple[TomteSample, int]]: + def get_samples_with_father(self) -> list[tuple[TomteSample | ExistingSample, int]]: return [(sample, index) for index, sample in self.enumerated_samples if sample.father] - def get_samples_with_mother(self) -> list[tuple[TomteSample, int]]: + def get_samples_with_mother(self) -> list[tuple[TomteSample | ExistingSample, int]]: return [(sample, index) for index, sample in self.enumerated_samples if sample.mother] diff --git a/tests/services/orders/validation_service/workflows/tomte/test_case_sample_rules.py b/tests/services/orders/validation_service/workflows/tomte/test_case_sample_rules.py index ed244d2330..23a2b4ba92 100644 --- a/tests/services/orders/validation_service/workflows/tomte/test_case_sample_rules.py +++ b/tests/services/orders/validation_service/workflows/tomte/test_case_sample_rules.py @@ -1,3 +1,4 @@ +from cg.constants import Sex from cg.models.orders.sample_base import StatusEnum from cg.services.orders.validation.errors.case_errors import ( InvalidGenePanelsError, @@ -7,6 +8,7 @@ DescendantAsFatherError, FatherNotInCaseError, InvalidFatherSexError, + InvalidMotherSexError, PedigreeError, SampleIsOwnFatherError, ) @@ -16,9 +18,11 @@ validate_fathers_are_male, validate_fathers_in_same_case_as_children, validate_gene_panels_exist, + validate_mothers_are_female, validate_pedigree, ) from cg.services.orders.validation.workflows.tomte.models.order import TomteOrder +from cg.store.models import Sample from cg.store.store import Store from tests.store_helpers import StoreHelpers @@ -55,11 +59,13 @@ def test_repeated_gene_panels(valid_order: TomteOrder, store_with_panels: Store) assert isinstance(errors[0], RepeatedGenePanelsError) -def test_father_must_be_male(order_with_invalid_father_sex: TomteOrder): +def test_father_must_be_male(order_with_invalid_father_sex: TomteOrder, base_store: Store): # GIVEN an order with an incorrectly specified father # WHEN validating the order - errors: list[InvalidFatherSexError] = validate_fathers_are_male(order_with_invalid_father_sex) + errors: list[InvalidFatherSexError] = validate_fathers_are_male( + order=order_with_invalid_father_sex, store=base_store + ) # THEN errors are returned assert errors @@ -68,13 +74,73 @@ def test_father_must_be_male(order_with_invalid_father_sex: TomteOrder): assert isinstance(errors[0], InvalidFatherSexError) -def test_father_in_wrong_case(order_with_father_in_wrong_case: TomteOrder): +def test_existing_father_must_be_male( + valid_order: TomteOrder, store_with_multiple_cases_and_samples: Store +): + """Tests that an order with a father which is a female sample in StatusDB gives an error.""" + + # GIVEN a sample in StatusDB with female sex + father_db_sample: Sample = store_with_multiple_cases_and_samples.session.query(Sample).first() + father_db_sample.sex = Sex.FEMALE + store_with_multiple_cases_and_samples.commit_to_store() + + # GIVEN that an order has a corresponding existing sample in one of its cases + father_sample = ExistingSample(internal_id=father_db_sample.internal_id) + valid_order.cases[0].samples.append(father_sample) + + # GIVEN that another sample in the order specifies the sample as its father + father_name = father_db_sample.name + valid_order.cases[0].samples[0].father = father_name + + # WHEN validating the order + errors: list[InvalidFatherSexError] = validate_fathers_are_male( + order=valid_order, store=store_with_multiple_cases_and_samples + ) + + # THEN errors are returned + assert errors + + # THEN the errors are about the father's sex + assert isinstance(errors[0], InvalidFatherSexError) + + +def test_existing_mother_must_be_female( + valid_order: TomteOrder, store_with_multiple_cases_and_samples: Store +): + """Tests that an order with a mother which is a male sample in StatusDB gives an error.""" + + # GIVEN a sample in StatusDB with male sex + mother_db_sample: Sample = store_with_multiple_cases_and_samples.session.query(Sample).first() + mother_db_sample.sex = Sex.MALE + store_with_multiple_cases_and_samples.commit_to_store() + + # GIVEN that an order has a corresponding existing sample in one of its cases + mother_sample = ExistingSample(internal_id=mother_db_sample.internal_id) + valid_order.cases[0].samples.append(mother_sample) + + # GIVEN that another sample in the order specifies the sample as its mother + mother_name = mother_db_sample.name + valid_order.cases[0].samples[0].mother = mother_name + + # WHEN validating the order + errors: list[InvalidMotherSexError] = validate_mothers_are_female( + order=valid_order, store=store_with_multiple_cases_and_samples + ) + + # THEN errors are returned + assert errors + + # THEN the errors are about the mother's sex + assert isinstance(errors[0], InvalidMotherSexError) + + +def test_father_in_wrong_case(order_with_father_in_wrong_case: TomteOrder, base_store: Store): # GIVEN an order with the father sample in the wrong case # WHEN validating the order errors: list[FatherNotInCaseError] = validate_fathers_in_same_case_as_children( - order_with_father_in_wrong_case + order=order_with_father_in_wrong_case, store=base_store ) # THEN an error is returned From 594366bbec0f1df4bcbcc7d53dbc90d460e3da54 Mon Sep 17 00:00:00 2001 From: Clinical Genomics Bot Date: Tue, 28 Jan 2025 09:43:31 +0000 Subject: [PATCH 16/16] =?UTF-8?q?Bump=20version:=2067.0.7=20=E2=86=92=2067?= =?UTF-8?q?.0.8=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cg/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 71f05c097c..fccb1be93e 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 67.0.7 +current_version = 67.0.8 commit = True tag = True tag_name = v{new_version} diff --git a/cg/__init__.py b/cg/__init__.py index 031aed5ca6..c5a1ba238a 100644 --- a/cg/__init__.py +++ b/cg/__init__.py @@ -1,2 +1,2 @@ __title__ = "cg" -__version__ = "67.0.7" +__version__ = "67.0.8" diff --git a/pyproject.toml b/pyproject.toml index 89e0f6e781..35a226f9b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "cg" -version = "67.0.7" +version = "67.0.8" description = "Clinical Genomics command center" readme = {file = "README.md", content-type = "text/markdown"} homepage = "https://github.com/Clinical-Genomics/cg"