Repository: Clinical-Genomics/cg
Pull request #4390: create customer/internal map file and feed-in to raredisease
Author: login: rannick
Created: 2025-05-08T13:41:45Z | Merged: 2025-05-13T13:58:08Z

## Description

### Added

- Create a csv file with the corresponding customer and internal sample ids upon raredisease config-case

### Changed

-

### Fixed

-


### How to prepare for test

- [ ] Ssh to relevant server (depending on type of change)
- [ ] Use stage: `us`
- [ ] Paxa the environment: `paxa`
- [ ] Install on stage (example for Hasta):
    ```shell
    bash /home/proj/production/servers/resources/hasta.scilifelab.se/update-tool-stage.sh -e S_cg -t cg -b [THIS-BRANCH-NAME] -a
    ```

### How to test

- [ ] Do ...

### Expected test outcome

- [ ] Check that ...
- [ ] Take a screenshot and attach or copy/paste the output.

## Review

- [ ] Tests executed by
- [ ] "Merge and deploy" approved by
Thanks for filling in who performed the code review and the test!

### This [version](https://semver.org/) is a

- [ ] **MAJOR** - when you make incompatible API changes
- [ ] **MINOR** - when you add functionality in a backwards compatible manner
- [ ] **PATCH** - when you make backwards compatible bug fixes or documentation/instructions

## Implementation Plan

- [ ] Document in ...
- [ ] Deploy this branch on ...
- [ ] Inform to ...



Diff:
diff --git a/cg/meta/workflow/nallo.py b/cg/meta/workflow/nallo.py
index f2f477d7d43..a072763ee99 100644
--- a/cg/meta/workflow/nallo.py
+++ b/cg/meta/workflow/nallo.py
@@ -9,18 +9,18 @@
 from cg.clients.chanjo2.models import (
     CoverageMetrics,
     CoveragePostRequest,
-    CoverageSample,
     CoveragePostResponse,
+    CoverageSample,
 )
 from cg.constants import Workflow
-from cg.constants.constants import GenomeVersion, FileFormat
+from cg.constants.constants import FileFormat, GenomeVersion
 from cg.constants.nf_analysis import (
-    NALLO_METRIC_CONDITIONS,
-    NALLO_COVERAGE_THRESHOLD,
-    NALLO_COVERAGE_INTERVAL_TYPE,
     NALLO_COVERAGE_FILE_TAGS,
+    NALLO_COVERAGE_INTERVAL_TYPE,
+    NALLO_COVERAGE_THRESHOLD,
+    NALLO_METRIC_CONDITIONS,
 )
-from cg.constants.scout import ScoutExportFileName, NALLO_CASE_TAGS
+from cg.constants.scout import NALLO_CASE_TAGS, ScoutExportFileName
 from cg.constants.subject import PlinkPhenotypeStatus, PlinkSex
 from cg.io.controller import WriteFile
 from cg.meta.workflow.nf_analysis import NfAnalysisAPI
@@ -29,9 +29,9 @@
 from cg.models.deliverables.metric_deliverables import MetricsBase
 from cg.models.nallo.nallo import (
     NalloParameters,
+    NalloQCMetrics,
     NalloSampleSheetEntry,
     NalloSampleSheetHeaders,
-    NalloQCMetrics,
 )
 from cg.resources import NALLO_BUNDLE_FILENAMES_PATH
 from cg.store.models import CaseSample, Sample
@@ -110,7 +110,7 @@ def get_sex_code(sex: str) -> int:
             raise ValueError(f"{sex} is not a valid sex")
         return code
 
-    def get_built_workflow_parameters(self, case_id: str) -> NalloParameters:
+    def get_built_workflow_parameters(self, case_id: str, dry_run: bool = False) -> NalloParameters:
         """Return parameters."""
         outdir = self.get_case_path(case_id=case_id)
 
diff --git a/cg/meta/workflow/nf_analysis.py b/cg/meta/workflow/nf_analysis.py
index 9c6b834561d..ddba72cbb03 100644
--- a/cg/meta/workflow/nf_analysis.py
+++ b/cg/meta/workflow/nf_analysis.py
@@ -130,7 +130,9 @@ def get_workflow_version(self, case_id: str) -> str:
         """Get workflow version from config."""
         return self.revision
 
-    def get_built_workflow_parameters(self, case_id: str) -> WorkflowParameters:
+    def get_built_workflow_parameters(
+        self, case_id: str, dry_run: bool = False
+    ) -> WorkflowParameters:
         """Return workflow parameters."""
         raise NotImplementedError
 
@@ -348,7 +350,7 @@ def create_params_file(self, case_id: str, dry_run: bool) -> None:
         """Create parameters file for a case."""
         LOG.debug("Getting parameters information built on-the-fly")
         built_workflow_parameters: dict | None = self.get_built_workflow_parameters(
-            case_id=case_id
+            case_id=case_id, dry_run=dry_run
         ).model_dump()
         LOG.debug("Adding parameters from the pipeline config file if it exist")
 
diff --git a/cg/meta/workflow/raredisease.py b/cg/meta/workflow/raredisease.py
index 6adf0fa2d87..56a6841edf8 100644
--- a/cg/meta/workflow/raredisease.py
+++ b/cg/meta/workflow/raredisease.py
@@ -1,5 +1,6 @@
 """Module for Raredisease Analysis API."""
 
+import csv
 import logging
 from itertools import permutations
 from pathlib import Path
@@ -97,11 +98,17 @@ def is_gene_panel_required(self) -> bool:
         """Return True if a gene panel needs to be created using the information in StatusDB and exporting it from Scout."""
         return True
 
-    def get_built_workflow_parameters(self, case_id: str) -> RarediseaseParameters:
+    def get_built_workflow_parameters(
+        self, case_id: str, dry_run: bool = False
+    ) -> RarediseaseParameters:
         """Return parameters."""
         analysis_type: AnalysisType = self.get_data_analysis_type(case_id=case_id)
         target_bed_file: str = self.get_target_bed_from_lims(case_id=case_id) or ""
         outdir = self.get_case_path(case_id=case_id)
+        sample_id_map: Path = self.get_sample_name_mapping_csv_path(case=case_id)
+        # Build the sample_id_map path
+        if not dry_run:
+            self.export_customer_internal_mapping_csv(case=case_id, output_path=sample_id_map)
 
         return RarediseaseParameters(
             input=self.get_sample_sheet_path(case_id=case_id),
@@ -111,6 +118,7 @@ def get_built_workflow_parameters(self, case_id: str) -> RarediseaseParameters:
             save_mapped_as_cram=True,
             vcfanno_extra_resources=f"{outdir}/{ScoutExportFileName.MANAGED_VARIANTS}",
             vep_filters_scout_fmt=f"{outdir}/{ScoutExportFileName.PANELS}",
+            sample_id_map=sample_id_map,
         )
 
     @staticmethod
@@ -274,3 +282,20 @@ def parse_analysis(self, qc_metrics_raw: list[MetricsBase], **kwargs) -> Nextflo
         return super().parse_analysis(
             qc_metrics_raw=qc_metrics_raw, qc_metrics_model=qc_metrics_model, **kwargs
         )
+
+    def get_sample_name_mapping_csv_path(self, case: str) -> Path:
+        """Return the path to the CSV file containing the mapping between sample names and internal ids."""
+        return Path(self.get_case_path(case), f"{case}_customer_internal_mapping.csv")
+
+    def export_customer_internal_mapping_csv(self, case: str, output_path: Path):
+        """Export a CSV file mapping customer sample names to internal sample IDs."""
+        LOG.info(f"Exporting customer internal mapping CSV for case {case} to {output_path}")
+        with output_path.open("w", newline="") as csvfile:
+            writer = csv.writer(csvfile)
+            writer.writerow(
+                ["customer_id", "internal_id"]
+            )  # this is the header expected by the pipeline
+            for link in self.status_db.get_case_by_internal_id(case).links:
+                customer_sample_name = link.sample.name
+                internal_id = link.sample.internal_id
+                writer.writerow([customer_sample_name, internal_id])
diff --git a/cg/meta/workflow/rnafusion.py b/cg/meta/workflow/rnafusion.py
index 57920d23627..75fbf27a68a 100644
--- a/cg/meta/workflow/rnafusion.py
+++ b/cg/meta/workflow/rnafusion.py
@@ -14,8 +14,8 @@
 from cg.models.deliverables.metric_deliverables import MetricsBase
 from cg.models.rnafusion.rnafusion import (
     RnafusionParameters,
-    RnafusionSampleSheetEntry,
     RnafusionQCMetrics,
+    RnafusionSampleSheetEntry,
 )
 from cg.resources import RNAFUSION_BUNDLE_FILENAMES_PATH
 from cg.store.models import CaseSample
@@ -83,7 +83,7 @@ def get_sample_sheet_content_per_sample(self, case_sample: CaseSample) -> list[l
         return sample_sheet_entry.reformat_sample_content()
 
     def get_built_workflow_parameters(
-        self, case_id: str, genomes_base: Path | None = None
+        self, case_id: str, dry_run: bool = False
     ) -> RnafusionParameters:
         """Get Rnafusion parameters."""
         return RnafusionParameters(
diff --git a/cg/meta/workflow/taxprofiler.py b/cg/meta/workflow/taxprofiler.py
index 9cb2f685cae..6833f0371e2 100644
--- a/cg/meta/workflow/taxprofiler.py
+++ b/cg/meta/workflow/taxprofiler.py
@@ -13,8 +13,8 @@
 from cg.models.deliverables.metric_deliverables import MetricsBase
 from cg.models.taxprofiler.taxprofiler import (
     TaxprofilerParameters,
-    TaxprofilerSampleSheetEntry,
     TaxprofilerQCMetrics,
+    TaxprofilerSampleSheetEntry,
 )
 from cg.resources import TAXPROFILER_BUNDLE_FILENAMES_PATH
 from cg.store.models import CaseSample, Sample
@@ -80,7 +80,9 @@ def get_sample_sheet_content_per_sample(self, case_sample: CaseSample) -> list[l
         )
         return sample_sheet_entry.reformat_sample_content()
 
-    def get_built_workflow_parameters(self, case_id: str) -> TaxprofilerParameters:
+    def get_built_workflow_parameters(
+        self, case_id: str, dry_run: bool = False
+    ) -> TaxprofilerParameters:
         """Return Taxprofiler parameters."""
         return TaxprofilerParameters(
             input=self.get_sample_sheet_path(case_id=case_id),
diff --git a/cg/meta/workflow/tomte.py b/cg/meta/workflow/tomte.py
index 219550174ab..d4044f828ff 100644
--- a/cg/meta/workflow/tomte.py
+++ b/cg/meta/workflow/tomte.py
@@ -12,9 +12,9 @@
 from cg.models.deliverables.metric_deliverables import MetricsBase
 from cg.models.tomte.tomte import (
     TomteParameters,
+    TomteQCMetrics,
     TomteSampleSheetEntry,
     TomteSampleSheetHeaders,
-    TomteQCMetrics,
 )
 from cg.resources import TOMTE_BUNDLE_FILENAMES_PATH
 from cg.store.models import CaseSample
@@ -77,7 +77,7 @@ def get_sample_sheet_content_per_sample(self, case_sample: CaseSample) -> list[l
         )
         return sample_sheet_entry.reformat_sample_content
 
-    def get_built_workflow_parameters(self, case_id: str) -> TomteParameters:
+    def get_built_workflow_parameters(self, case_id: str, dry_run: bool = False) -> TomteParameters:
         """Return parameters."""
         return TomteParameters(
             input=self.get_sample_sheet_path(case_id=case_id),
diff --git a/cg/models/raredisease/raredisease.py b/cg/models/raredisease/raredisease.py
index 2fd730a0d85..8b0e81459dc 100644
--- a/cg/models/raredisease/raredisease.py
+++ b/cg/models/raredisease/raredisease.py
@@ -1,4 +1,5 @@
 from enum import StrEnum
+from pathlib import Path
 
 from cg.constants.constants import SexOptions
 from cg.models.nf_analysis import NextflowSampleSheetEntry, WorkflowParameters
@@ -69,3 +70,4 @@ class RarediseaseParameters(WorkflowParameters):
     save_mapped_as_cram: bool
     vcfanno_extra_resources: str
     vep_filters_scout_fmt: str
+    sample_id_map: Path
diff --git a/tests/conftest.py b/tests/conftest.py
index ce81ca41d68..2fa380774fb 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2916,6 +2916,14 @@ def raredisease_sample_sheet_path(raredisease_dir, raredisease_case_id) -> Path:
     ).with_suffix(FileExtensions.CSV)
 
 
+@pytest.fixture(scope="function")
+def raredisease_sample_id_map(raredisease_dir: str, raredisease_case_id: str) -> Path:
+    """Return sample id map path."""
+    return Path(
+        raredisease_dir, raredisease_case_id, f"{raredisease_case_id}_customer_internal_mapping"
+    ).with_suffix(FileExtensions.CSV)
+
+
 @pytest.fixture(scope="function")
 def raredisease_params_file_path(raredisease_dir, raredisease_case_id) -> Path:
     """Path to parameters file."""
@@ -2970,7 +2978,8 @@ def raredisease_parameters_default(
     raredisease_dir: Path,
     raredisease_case_id: str,
     raredisease_sample_sheet_path: Path,
-    bed_version_file_name,
+    bed_version_file_name: str,
+    raredisease_sample_id_map: Path,
 ) -> RarediseaseParameters:
     """Return Tomte parameters."""
     return RarediseaseParameters(
@@ -2979,6 +2988,7 @@ def raredisease_parameters_default(
         target_bed_file=bed_version_file_name,
         analysis_type=AnalysisType.WES,
         save_mapped_as_cram=True,
+        sample_id_map=raredisease_sample_id_map,
         vcfanno_extra_resources=str(
             Path(raredisease_dir, raredisease_case_id + ScoutExportFileName.MANAGED_VARIANTS)
         ),


Reviews:
user: login: islean
body: Is this something that needs a dry run option? It seems as if nothing previously has had that need in the "get_built_workflow_parameters"?
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-09T09:14:30Z
user: login: diitaz93
body: It looks good! I think some naming can be improved regarding the mapping, it is unclear what the mapping contains just by the function naming and docstring. Also, in the new implementation (#4227) we removed all dry-runs. I think the csv mapping is something that we want to generate in all cases, not only in non-dry runs. Is there a reason why it should be excluded in dry-runs?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T15:31:06Z
user: login: rannick
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T10:27:09Z
user: login: rannick
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T10:30:15Z
user: login: diitaz93
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T07:50:13Z
user: login: diitaz93
body: Go for it 🚀 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T07:51:04Z

Review comments:
diff_hunk: @@ -110,7 +110,7 @@ def get_sex_code(sex: str) -> int:
             raise ValueError(f"{sex} is not a valid sex")
         return code
 
-    def get_built_workflow_parameters(self, case_id: str) -> NalloParameters:
+    def get_built_workflow_parameters(self, case_id: str, dry_run: bool = False) -> NalloParameters:
path: cg/meta/workflow/nallo.py
user: login: islean
body: Why was the dry run option added? It does not seem to do anything
created_at: 2025-05-09T09:11:11Z
author_association: MEMBER
diff_hunk: @@ -274,3 +282,18 @@ def parse_analysis(self, qc_metrics_raw: list[MetricsBase], **kwargs) -> Nextflo
         return super().parse_analysis(
             qc_metrics_raw=qc_metrics_raw, qc_metrics_model=qc_metrics_model, **kwargs
         )
+
+    def get_customer_internal_mapping_csv_path(self, case: str) -> Path:
+        """Return the path to the customer internal mapping CSV file."""
+        return Path(self.get_case_path(case)) / f"{case}_customer_internal_mapping.csv"
path: cg/meta/workflow/raredisease.py
user: login: diitaz93
body: ```suggestion
        return Path(self.get_case_path(case), f"{case}_customer_internal_mapping.csv")
```
created_at: 2025-05-09T15:16:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -274,3 +282,18 @@ def parse_analysis(self, qc_metrics_raw: list[MetricsBase], **kwargs) -> Nextflo
         return super().parse_analysis(
             qc_metrics_raw=qc_metrics_raw, qc_metrics_model=qc_metrics_model, **kwargs
         )
+
+    def get_customer_internal_mapping_csv_path(self, case: str) -> Path:
+        """Return the path to the customer internal mapping CSV file."""
+        return Path(self.get_case_path(case)) / f"{case}_customer_internal_mapping.csv"
+
+    def export_customer_internal_mapping_csv(self, case: str, output_path: Path):
+        """Export a CSV file mapping customer sample names to internal sample IDs."""
+        LOG.info(f"Exporting customer internal mapping CSV for case {case} to {output_path}")
+        with output_path.open("w", newline="") as csvfile:
+            writer = csv.writer(csvfile)
+            writer.writerow(["customer_id", "internal_id"])
+            for link in self.status_db.get_case_by_internal_id(case).links:
+                customer_name = link.sample.name
path: cg/meta/workflow/raredisease.py
user: login: diitaz93
body: I think `customer_id` and `customer_name` are a bit confusing as they are actually referring to the sample name. Could they be renamed?
created_at: 2025-05-09T15:21:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -274,3 +282,18 @@ def parse_analysis(self, qc_metrics_raw: list[MetricsBase], **kwargs) -> Nextflo
         return super().parse_analysis(
             qc_metrics_raw=qc_metrics_raw, qc_metrics_model=qc_metrics_model, **kwargs
         )
+
+    def get_customer_internal_mapping_csv_path(self, case: str) -> Path:
+        """Return the path to the customer internal mapping CSV file."""
path: cg/meta/workflow/raredisease.py
user: login: diitaz93
body: ```suggestion
    def get_sample_name_mapping_csv_path(self, case: str) -> Path:
        """Return the path to the CSV file containing the mapping between sample names and internal ids."""
```
created_at: 2025-05-09T15:24:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -110,7 +110,7 @@ def get_sex_code(sex: str) -> int:
             raise ValueError(f"{sex} is not a valid sex")
         return code
 
-    def get_built_workflow_parameters(self, case_id: str) -> NalloParameters:
+    def get_built_workflow_parameters(self, case_id: str, dry_run: bool = False) -> NalloParameters:
path: cg/meta/workflow/nallo.py
user: login: rannick
body: As mentionned, it is just so the unit test for dry-runs runs
created_at: 2025-05-12T10:27:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -274,3 +282,18 @@ def parse_analysis(self, qc_metrics_raw: list[MetricsBase], **kwargs) -> Nextflo
         return super().parse_analysis(
             qc_metrics_raw=qc_metrics_raw, qc_metrics_model=qc_metrics_model, **kwargs
         )
+
+    def get_customer_internal_mapping_csv_path(self, case: str) -> Path:
+        """Return the path to the customer internal mapping CSV file."""
+        return Path(self.get_case_path(case)) / f"{case}_customer_internal_mapping.csv"
+
+    def export_customer_internal_mapping_csv(self, case: str, output_path: Path):
+        """Export a CSV file mapping customer sample names to internal sample IDs."""
+        LOG.info(f"Exporting customer internal mapping CSV for case {case} to {output_path}")
+        with output_path.open("w", newline="") as csvfile:
+            writer = csv.writer(csvfile)
+            writer.writerow(["customer_id", "internal_id"])
+            for link in self.status_db.get_case_by_internal_id(case).links:
+                customer_name = link.sample.name
path: cg/meta/workflow/raredisease.py
user: login: rannick
body: Done
created_at: 2025-05-12T10:30:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -274,3 +282,20 @@ def parse_analysis(self, qc_metrics_raw: list[MetricsBase], **kwargs) -> Nextflo
         return super().parse_analysis(
             qc_metrics_raw=qc_metrics_raw, qc_metrics_model=qc_metrics_model, **kwargs
         )
+
+    def get_sample_name_mapping_csv_path(self, case: str) -> Path:
+        """Return the path to the CSV file containing the mapping between sample names and internal ids."""
+        return Path(self.get_case_path(case), f"{case}_customer_internal_mapping.csv")
+
+    def export_customer_internal_mapping_csv(self, case: str, output_path: Path):
+        """Export a CSV file mapping customer sample names to internal sample IDs."""
+        LOG.info(f"Exporting customer internal mapping CSV for case {case} to {output_path}")
+        with output_path.open("w", newline="") as csvfile:
+            writer = csv.writer(csvfile)
+            writer.writerow(
+                ["customer_id", "internal_id"]
path: cg/meta/workflow/raredisease.py
user: login: diitaz93
body: I would still prefer that the first column would be "customer_sample_name" but I understand that this is something hard-coded in raredisease and there is little we can do about it now. Maybe for a future release we could have this changed? 😬 
created_at: 2025-05-13T07:50:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-05-13T13:24:12Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Clinical-Genomics_cg&pullRequest=4390) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_cg&pullRequest=4390&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Clinical-Genomics_cg&pullRequest=4390&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Clinical-Genomics_cg&pullRequest=4390&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_cg&pullRequest=4390&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Clinical-Genomics_cg&pullRequest=4390&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=Clinical-Genomics_cg&pullRequest=4390)


author_association: NONE
user: login: rannick
created_at: 2025-05-13T14:51:50Z
body: ```
Logging deploy ...
Getting deployer... done.
Getting last commit message and SHA... done.
Getting version of deploy scripts... /home/annick.renevey
done.
Log deploy... done.
cg, version 70.0.1
remote: Enumerating objects: 75, done.
remote: Counting objects: 100% (75/75), done.
remote: Compressing objects: 100% (28/28), done.
remote: Total 75 (delta 50), reused 65 (delta 46), pack-reused 0 (from 0)
Unpacking objects: 100% (75/75), done.
From https://github.com/Clinical-Genomics/cg
   7a6cc60..ca4af3d  master     -> origin/master
   b3d34eb..829a80a  one-case-per-sample-metagenome -> origin/one-case-per-sample-metagenome
 * [new tag]         v70.0.1    -> v70.0.1
Already on 'master'
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
Updating 7a6cc60..ca4af3d
Fast-forward
 .bumpversion.cfg                     |  2 +-
 cg/__init__.py                       |  2 +-
 cg/meta/workflow/nallo.py            | 16 ++++++++--------
 cg/meta/workflow/nf_analysis.py      |  6 ++++--
 cg/meta/workflow/raredisease.py      | 27 ++++++++++++++++++++++++++-
 cg/meta/workflow/rnafusion.py        |  4 ++--
 cg/meta/workflow/taxprofiler.py      |  6 ++++--
 cg/meta/workflow/tomte.py            |  4 ++--
 cg/models/raredisease/raredisease.py |  2 ++
 pyproject.toml                       |  2 +-
 tests/conftest.py                    | 12 +++++++++++-
 11 files changed, 62 insertions(+), 21 deletions(-)
/home/annick.renevey
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
```
author_association: CONTRIBUTOR