Skip to content

Commit

Permalink
Merge branch 'master' into ticket-tag-existing-data
Browse files Browse the repository at this point in the history
  • Loading branch information
eliottBo authored Jan 29, 2025
2 parents 0537153 + 8cba7f7 commit 0c4dde2
Show file tree
Hide file tree
Showing 21 changed files with 268 additions and 105 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 67.0.3
current_version = 67.0.9
commit = True
tag = True
tag_name = v{new_version}
Expand Down
2 changes: 1 addition & 1 deletion cg/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__title__ = "cg"
__version__ = "67.0.3"
__version__ = "67.0.9"
30 changes: 26 additions & 4 deletions cg/cli/workflow/fluffy/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand Down Expand Up @@ -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
Expand All @@ -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,
):
"""
Expand All @@ -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")
Expand Down
1 change: 1 addition & 0 deletions cg/constants/scout.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
Expand Down
1 change: 1 addition & 0 deletions cg/meta/upload/scout/hk_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 4 additions & 5 deletions cg/meta/upload/scout/raredisease_config_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
)
14 changes: 9 additions & 5 deletions cg/meta/workflow/fluffy.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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),
]
Expand Down
1 change: 1 addition & 0 deletions cg/models/scout/scout_load_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
6 changes: 3 additions & 3 deletions cg/services/orders/submitter/ticket_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,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
Expand Down Expand Up @@ -183,6 +181,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,
Expand All @@ -192,6 +191,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,
Expand Down
10 changes: 9 additions & 1 deletion cg/services/orders/validation/models/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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):
Expand Down
9 changes: 9 additions & 0 deletions cg/services/orders/validation/rules/case/utils.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
23 changes: 12 additions & 11 deletions cg/services/orders/validation/rules/case_sample/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 0c4dde2

Please sign in to comment.