예제 #1
0
def test_delete_case_with_father_links(
    cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers
):
    """Test that the delete case will not delete a sample linked to another case as father"""
    # GIVEN a database with a case
    base_store: Store = base_context.status_db
    case_obj = helpers.add_case(base_store, "first_case_linked_to_sample")
    case_id = case_obj.internal_id
    sample_father = helpers.add_sample(base_store, "father")
    sample_child = helpers.add_sample(base_store, "child")
    helpers.add_relationship(store=base_store, case=case_obj, sample=sample_father)
    case_obj2 = helpers.add_case(base_store, "second_case_linked_to_sample")
    helpers.add_relationship(
        store=base_store, case=case_obj2, sample=sample_child, father=sample_father
    )

    assert base_store.Family.query.count() == 2
    assert base_store.FamilySample.query.count() == 2
    assert base_store.Sample.query.count() == 2

    # WHEN deleting a case
    result = cli_runner.invoke(delete_case_command, [case_id, "--yes"], obj=base_context)

    # THEN the first case should be gone with its link to the sample but not the other or
    # the father sample
    assert result.exit_code == SUCCESS
    assert base_store.Family.query.count() == 1
    assert base_store.FamilySample.query.count() == 1
    assert base_store.Sample.query.count() == 2
예제 #2
0
def test_delete_child_case(cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers):
    """Test that the delete case will not delete a sample linked to another case as mother"""
    # GIVEN a database with a mother case and a child case with the mother as mother
    base_store: Store = base_context.status_db
    case_mother = helpers.add_case(base_store, "case_mother")
    sample_mother = helpers.add_sample(base_store, "mother")
    sample_child = helpers.add_sample(base_store, "child")
    helpers.add_relationship(store=base_store, case=case_mother, sample=sample_mother)
    case_child = helpers.add_case(base_store, "case_child")
    case_child_id = case_child.internal_id
    helpers.add_relationship(
        store=base_store, case=case_child, sample=sample_child, mother=sample_mother
    )

    assert base_store.Family.query.count() == 2
    assert base_store.FamilySample.query.count() == 2
    assert base_store.Sample.query.count() == 2

    # WHEN deleting the child case
    result = cli_runner.invoke(delete_case_command, [case_child_id, "--yes"], obj=base_context)

    # THEN the child sample is deletable
    assert result.exit_code == SUCCESS
    assert base_store.Family.query.count() == 1
    assert base_store.FamilySample.query.count() == 1
    assert base_store.Sample.query.count() == 1
예제 #3
0
def fixture_analysis_store(base_store: Store, workflow_case_id: str,
                           helpers: StoreHelpers) -> Store:
    """Store to be used in tests"""
    _store = base_store

    case = helpers.add_case(_store,
                            workflow_case_id,
                            data_analysis=Pipeline.MIP_DNA)

    dna_sample = helpers.add_sample(_store,
                                    "dna_sample",
                                    is_rna=False,
                                    sequenced_at=datetime.now(),
                                    reads=10000000)
    helpers.add_relationship(_store, sample=dna_sample, case=case)

    case = helpers.add_case(_store, "rna_case", data_analysis=Pipeline.MIP_RNA)
    rna_sample = helpers.add_sample(_store,
                                    "rna_sample",
                                    is_rna=True,
                                    sequenced_at=datetime.now(),
                                    reads=10000000)
    helpers.add_relationship(_store, sample=rna_sample, case=case)

    case = helpers.add_case(_store,
                            "dna_rna_mix_case",
                            data_analysis=Pipeline.MIP_DNA)
    helpers.add_relationship(_store, sample=rna_sample, case=case)
    helpers.add_relationship(_store, sample=dna_sample, case=case)

    return _store
def test_add_relationship_mother(cli_runner: CliRunner, base_context: CGConfig,
                                 helpers: StoreHelpers):
    """Test to add a relationship with a mother"""
    # GIVEN a database with a sample and an case
    disk_store: Store = base_context.status_db
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id
    mother = helpers.add_sample(disk_store, name="mother")
    mother_id = mother.internal_id
    case = helpers.add_case(disk_store)
    case_id = case.internal_id
    status = "affected"

    # WHEN adding a relationship
    result = cli_runner.invoke(
        add,
        [
            "relationship",
            case_id,
            sample_id,
            "-s",
            status,
            "-m",
            mother_id,
        ],
        obj=base_context,
    )

    # THEN it should be added
    assert result.exit_code == 0
    assert disk_store.FamilySample.query.count() == 1
    assert disk_store.FamilySample.query.first(
    ).mother.internal_id == mother_id
예제 #5
0
def test_delete_case_with_dry_run(
    cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers, caplog
):
    """Test that the delete case will not delete the case in dry-run mode"""
    # GIVEN a database with a case
    base_store: Store = base_context.status_db
    case_obj = helpers.add_case(base_store)
    case_id = case_obj.internal_id
    sample = helpers.add_sample(base_store)
    helpers.add_relationship(store=base_store, case=case_obj, sample=sample)
    assert base_store.Family.query.count() == 1
    assert base_store.FamilySample.query.count() == 1
    assert base_store.Sample.query.count() == 1

    # WHEN deleting a case
    caplog.set_level(logging.DEBUG)
    result = cli_runner.invoke(
        delete_case_command, [case_id, "--yes", "--dry-run"], obj=base_context
    )

    # THEN it should not have been deleted
    assert result.exit_code == SUCCESS
    assert base_store.Family.query.count() == 1
    assert base_store.FamilySample.query.count() == 1
    assert base_store.Sample.query.count() == 1
    assert "Link:" in caplog.text
    assert "Sample is linked" in caplog.text
    assert "Case:" in caplog.text
    assert " was NOT deleted due to --dry-run" in caplog.text
예제 #6
0
def test_validate_sex_unknown_new_sex(orders_api: OrdersAPI,
                                      mip_order_to_submit: dict,
                                      helpers: StoreHelpers):
    # GIVEN we have an order with a sample that is already in the database and with different gender but the new is of
    # type "unknown"
    order_data = OrderIn.parse_obj(mip_order_to_submit,
                                   project=OrderType.MIP_DNA)
    store = orders_api.status
    customer_obj = store.customer(order_data.customer)

    # add sample with different sex than in order
    for sample in order_data.samples:
        sample_obj: models.Sample = helpers.add_sample(
            store=store,
            subject_id=sample.subject_id,
            name=sample.name,
            gender=sample.sex,
            customer_id=customer_obj.internal_id,
        )
        sample.sex = "unknown"
        store.add_commit(sample_obj)

    for sample in order_data.samples:
        assert sample_obj.sex != sample.sex

    submitter: MipDnaSubmitter = MipDnaSubmitter(lims=orders_api.lims,
                                                 status=orders_api.status)

    # WHEN calling _validate_sex
    submitter._validate_subject_sex(samples=order_data.samples,
                                    customer_id=order_data.customer)
예제 #7
0
def test_validate_sex_inconsistent_sex(orders_api: OrdersAPI,
                                       mip_order_to_submit: dict,
                                       helpers: StoreHelpers):
    # GIVEN we have an order with a sample that is already in the database but with different sex
    order_data = OrderIn.parse_obj(mip_order_to_submit,
                                   project=OrderType.MIP_DNA)
    store = orders_api.status
    customer_obj = store.customer(order_data.customer)

    # add sample with different sex than in order
    sample: MipDnaSample
    for sample in order_data.samples:
        sample_obj: models.Sample = helpers.add_sample(
            store=store,
            subject_id=sample.subject_id,
            name=sample.name,
            gender="male" if sample.sex == "female" else "female",
            customer_id=customer_obj.internal_id,
        )
        store.add_commit(sample_obj)
        assert sample_obj.sex != sample.sex

    submitter: MipDnaSubmitter = MipDnaSubmitter(lims=orders_api.lims,
                                                 status=orders_api.status)

    # WHEN calling _validate_sex
    # THEN an OrderError should be raised on non-matching sex
    with pytest.raises(OrderError):
        submitter._validate_subject_sex(samples=order_data.samples,
                                        customer_id=order_data.customer)
def test_add_relationship_bad_father(cli_runner: CliRunner,
                                     base_context: CGConfig,
                                     helpers: StoreHelpers):
    """Test to add a relationship using a non-existing father"""
    # GIVEN a database with a sample and an case
    disk_store: Store = base_context.status_db
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id

    father_id = "bad_father"
    case = helpers.add_case(disk_store)
    case_id = case.internal_id

    status = "affected"

    # WHEN adding a relationship
    result = cli_runner.invoke(
        add,
        [
            "relationship",
            case_id,
            sample_id,
            "-s",
            status,
            "-f",
            father_id,
        ],
        obj=base_context,
    )

    # THEN it should not be added
    assert result.exit_code == 1
    assert disk_store.FamilySample.query.count() == 0
예제 #9
0
def test_validate_submitted_order(sarscov2_order_to_submit: dict,
                                  base_store: Store, helpers: StoreHelpers):
    # GIVEN sarscov2 order with three samples, all in the database
    order: OrderIn = OrderIn.parse_obj(sarscov2_order_to_submit,
                                       OrderType.SARS_COV_2)

    sample: SarsCov2Sample
    for sample in order.samples:
        helpers.add_sample(store=base_store,
                           name=sample.name,
                           customer_id=order.customer)

    # WHEN validating the order
    # THEN it should be regarded as invalid
    with (pytest.raises(OrderError)):
        SarsCov2Submitter(status=base_store,
                          lims=None).validate_order(order=order)
예제 #10
0
def test_validate_submitted_control_order(sarscov2_order_to_submit: dict,
                                          base_store: Store,
                                          helpers: StoreHelpers):
    # GIVEN sarscov2 order with three control samples, all in the database
    order: OrderIn = OrderIn.parse_obj(sarscov2_order_to_submit,
                                       OrderType.SARS_COV_2)

    sample: SarsCov2Sample
    for sample in order.samples:
        helpers.add_sample(store=base_store,
                           name=sample.name,
                           customer_id=order.customer)
        sample.control = ControlEnum.positive

    # WHEN validating the order
    # THEN it should be regarded as valid
    SarsCov2Submitter(status=base_store, lims=None).validate_order(order=order)
예제 #11
0
def test_get_samples_required(cli_runner: CliRunner, base_context: CGConfig,
                              disk_store: Store, helpers: StoreHelpers):
    """Test to get several samples using only the required arguments"""
    # GIVEN a database with two samples
    sample_id1 = "1"
    helpers.add_sample(store=disk_store, internal_id=sample_id1)
    sample_id2 = "2"
    helpers.add_sample(store=disk_store, internal_id=sample_id2)

    assert disk_store.Sample.query.count() == 2

    # WHEN getting a sample
    result = cli_runner.invoke(get, ["sample", sample_id1, sample_id2],
                               obj=base_context)

    # THEN it should have been get
    assert result.exit_code == 0
    assert sample_id1 in result.output
    assert sample_id2 in result.output
예제 #12
0
def test_families_by_subject_id(
    data_analysis: Pipeline,
    helpers: StoreHelpers,
    sample_store: Store,
):
    """Test that we get a case back for a subject id"""
    # GIVEN connected case exist
    subject_id = "a_subject_id"
    store: Store = sample_store

    rna_sample: models.Sample = helpers.add_sample(store=store,
                                                   subject_id=subject_id)
    rna_case: models.Family = helpers.add_case(store=store,
                                               data_analysis=Pipeline.MIP_RNA,
                                               name="rna_case")
    helpers.add_relationship(store=store, case=rna_case, sample=rna_sample)
    store.add_commit(rna_case)

    dna_sample: models.Sample = helpers.add_sample(store=store,
                                                   subject_id=subject_id)
    dna_case: models.Family = helpers.add_case(store=store,
                                               data_analysis=data_analysis,
                                               name="dna_case")
    helpers.add_relationship(store=store, case=dna_case, sample=dna_sample)
    store.add_commit(dna_case)

    customer: models.Customer = dna_case.customer

    # WHEN calling method families_by_subject_id
    all_cases: set[models.Family] = sample_store.families_by_subject_id(
        customer_id=customer.internal_id, subject_id=subject_id)

    dna_cases: set[models.Family] = sample_store.families_by_subject_id(
        customer_id=customer.internal_id,
        subject_id=subject_id,
        data_analyses=[data_analysis])

    # THEN we got the case as result and another data_analysis not in result
    assert dna_case in all_cases
    assert rna_case in all_cases
    assert dna_case in dna_cases
    assert rna_case not in dna_cases
예제 #13
0
def store_samples_with_names_from_order(store: Store, helpers: StoreHelpers,
                                        order_data: OrderIn):
    customer_obj = store.customer(order_data.customer)
    for sample in order_data.samples:
        sample_name = sample.name
        if not store.find_samples(customer=customer_obj,
                                  name=sample_name).first():
            sample_obj = helpers.add_sample(
                store=store,
                name=sample_name,
                customer_id=customer_obj.internal_id)
            store.add_commit(sample_obj)
예제 #14
0
def test_get_sample_required(cli_runner: CliRunner, base_context: CGConfig,
                             disk_store: Store, helpers: StoreHelpers):
    """Test to get a sample using only the required argument"""
    # GIVEN a database with a sample
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id
    assert disk_store.Sample.query.count() == 1

    # WHEN getting a sample
    result = cli_runner.invoke(get, ["sample", sample_id], obj=base_context)

    # THEN it should have been get
    assert result.exit_code == 0
    assert sample_id in result.output
예제 #15
0
def test_get_sample_families_without_family(cli_runner: CliRunner,
                                            base_context: CGConfig,
                                            disk_store: Store,
                                            helpers: StoreHelpers):
    """Test that the --families flag works without families"""
    # GIVEN a database with a sample without related samples
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id
    assert not disk_store.Sample.query.first().links

    # WHEN getting a sample with the --families flag
    result = cli_runner.invoke(get, ["sample", sample_id, "--families"],
                               obj=base_context)

    # THEN everything is fine
    assert result.exit_code == 0
예제 #16
0
def test_hide_sample_flowcells_without_flowcell(cli_runner: CliRunner,
                                                base_context: CGConfig,
                                                disk_store: Store,
                                                helpers: StoreHelpers):
    """Test that we can query samples and hide flowcell even when there are none"""
    # GIVEN a database with a sample without related flowcell
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id
    assert not disk_store.Flowcell.query.first()

    # WHEN getting a sample with the --flowcells flag
    result = cli_runner.invoke(get, ["sample", sample_id, "--hide-flowcell"],
                               obj=base_context)

    # THEN everything is fine
    assert result.exit_code == 0
예제 #17
0
def test_get_sample_external_false(cli_runner: CliRunner,
                                   base_context: CGConfig, disk_store: Store,
                                   helpers: StoreHelpers):
    """Test that the output has the external-value of the sample"""
    # GIVEN a database with a sample with data
    sample = helpers.add_sample(disk_store, is_external=False)
    sample_id = sample.internal_id
    is_external_false = "No"
    is_external_true = "Yes"

    # WHEN getting a sample
    result = cli_runner.invoke(get, ["sample", sample_id], obj=base_context)

    # THEN it should have been get
    assert result.exit_code == 0
    assert is_external_false in result.output
    assert is_external_true not in result.output
예제 #18
0
def test_lists_sample_in_unreceived_samples(
    cli_runner: CliRunner, base_context: CGConfig, helpers: StoreHelpers
):
    """Test to that cases displays case in database"""

    # GIVEN a database with a case
    base_store: Store = base_context.status_db
    case = helpers.add_case(base_store)
    sample1 = helpers.add_sample(base_store, "sample1")
    helpers.add_relationship(base_store, case=case, sample=sample1)

    # WHEN listing cases
    result = cli_runner.invoke(cases, ["-o", "count"], obj=base_context)

    # THEN the case should be listed
    assert result.exit_code == 0
    assert case.internal_id in result.output
    assert "0/1" in result.output
예제 #19
0
def test_get_sample_flowcells_with_flowcell(cli_runner: CliRunner,
                                            base_context: CGConfig,
                                            disk_store: Store,
                                            helpers: StoreHelpers):
    """Test that we can query samples and hide flowcell, ensuring that no flowcell name is in the output"""
    # GIVEN a database with a sample and a related flowcell
    flowcell = helpers.add_flowcell(disk_store)
    sample = helpers.add_sample(disk_store, flowcell=flowcell)
    assert flowcell in disk_store.Sample.query.first().flowcells
    sample_id = sample.internal_id

    # WHEN getting a sample with the --flowcells flag
    result = cli_runner.invoke(get, ["sample", sample_id, "--hide-flowcell"],
                               obj=base_context)

    # THEN the related flowcell should be listed in the output
    assert result.exit_code == 0
    for flowcell in disk_store.Sample.query.first().flowcells:
        assert flowcell.name not in result.output
예제 #20
0
def test_get_sample_families_with_family(cli_runner: CliRunner,
                                         base_context: CGConfig,
                                         disk_store: Store,
                                         helpers: StoreHelpers):
    """Test that the --families flag does show case info"""
    # GIVEN a database with a sample with related samples
    case = helpers.add_case(disk_store)
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id
    helpers.add_relationship(disk_store, sample=sample, case=case)
    assert disk_store.Sample.query.first().links

    # WHEN getting a sample with the --families flag
    result = cli_runner.invoke(get, ["sample", sample_id, "--families"],
                               obj=base_context)

    # THEN all related families should be listed in the output
    assert result.exit_code == 0
    for link in disk_store.Sample.query.first().links:
        assert link.family.internal_id in result.output
예제 #21
0
def test_compress_fastq_cli_case_id(populated_compress_context: CGConfig,
                                    cli_runner: CliRunner,
                                    helpers: StoreHelpers, caplog):
    """Test to run the compress command with a specified case id"""
    caplog.set_level(logging.DEBUG)
    status_db: Store = populated_compress_context.status_db

    # GIVEN a context with a case that can be compressed
    case_id = "chonkywombat"

    valid_compressable_case = helpers.add_case(
        store=status_db,
        name=case_id,
        internal_id=case_id,
        data_analysis=Pipeline.MIP_DNA,
        action=None,
    )
    valid_compressable_case.created_at = dt.datetime.now() - dt.timedelta(
        days=1000)
    sample1 = helpers.add_sample(store=status_db, internal_id="ACCR9000")
    sample2 = helpers.add_sample(store=status_db, internal_id="ACCR9001")
    helpers.add_relationship(
        store=status_db,
        sample=sample1,
        case=valid_compressable_case,
    )
    helpers.add_relationship(
        store=status_db,
        sample=sample2,
        case=valid_compressable_case,
    )
    status_db.commit()

    # WHEN running the compress command
    res = cli_runner.invoke(fastq_cmd, ["--case-id", case_id],
                            obj=populated_compress_context)

    # THEN assert the program exits since no cases where found
    assert res.exit_code == 0
    # THEN assert it was communicated that no families where found
    assert f"Individuals in 1 (completed) cases where compressed" in caplog.text
예제 #22
0
def fixture_dna_mip_context(
    cg_context: CGConfig,
    helpers: StoreHelpers,
    mip_case_ids: dict,
    real_housekeeper_api: HousekeeperAPI,
    tb_api,
) -> CGConfig:
    _store = cg_context.status_db
    cg_context.housekeeper_api_ = real_housekeeper_api
    cg_context.trailblazer_api_ = tb_api
    mip_analysis_api = MipDNAAnalysisAPI(config=cg_context)

    # Add apptag to db
    helpers.ensure_application_version(store=_store,
                                       application_tag="WGSA",
                                       application_type="wgs")

    # Add sample, cases and relationships to db

    for case_id in mip_case_ids:
        if not _store.family(case_id):
            case_obj = helpers.add_case(
                store=_store,
                data_analysis=Pipeline.MIP_DNA,
                internal_id=case_id,
                name=mip_case_ids[case_id]["name"],
            )
            sample = helpers.add_sample(
                store=_store,
                customer_id="cust000",
                application_tag="WGSA",
                application_type="wgs",
                gender="unknown",
            )
            helpers.add_relationship(store=_store,
                                     sample=sample,
                                     case=case_obj,
                                     status="affected")
    cg_context.meta_apis["analysis_api"] = mip_analysis_api
    return cg_context
예제 #23
0
def test_get_sample_output(cli_runner: CliRunner, base_context: CGConfig,
                           disk_store: Store, helpers: StoreHelpers):
    """Test that the output has the data of the sample"""
    # GIVEN a database with a sample with data
    sample = helpers.add_sample(disk_store)
    sample_id = sample.internal_id
    name = sample.name
    customer_id = sample.customer.internal_id
    application_tag = sample.application_version.application.tag
    state = sample.state
    priority_human = sample.priority_human

    # WHEN getting a sample
    result = cli_runner.invoke(get, ["sample", sample_id], obj=base_context)

    # THEN it should have been get
    assert result.exit_code == 0
    assert sample_id in result.output
    assert name in result.output
    assert customer_id in result.output
    assert application_tag in result.output
    assert state in result.output
    assert priority_human in result.output
예제 #24
0
def fluffy_context(
    cg_context: CGConfig,
    helpers: StoreHelpers,
    real_housekeeper_api: HousekeeperAPI,
    fluffy_samplesheet_bundle_data,
    fluffy_fastq_hk_bundle_data,
    fluffy_case_id_existing,
    fluffy_sample_lims_id,
) -> CGConfig:
    cg_context.housekeeper_api_ = real_housekeeper_api
    fluffy_analysis_api = FluffyAnalysisAPI(config=cg_context)
    helpers.ensure_hk_version(fluffy_analysis_api.housekeeper_api,
                              bundle_data=fluffy_samplesheet_bundle_data)
    helpers.ensure_hk_version(fluffy_analysis_api.housekeeper_api,
                              fluffy_fastq_hk_bundle_data)
    example_fluffy_case = helpers.add_case(
        fluffy_analysis_api.status_db,
        internal_id=fluffy_case_id_existing,
        name=fluffy_case_id_existing,
        data_analysis=Pipeline.FLUFFY,
    )
    example_fluffy_sample = helpers.add_sample(
        fluffy_analysis_api.status_db,
        internal_id=fluffy_sample_lims_id,
        is_tumour=False,
        application_type="tgs",
        reads=100,
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_flowcell(fluffy_analysis_api.status_db,
                         flowcell_id="flowcell",
                         samples=[example_fluffy_sample])
    helpers.add_relationship(fluffy_analysis_api.status_db,
                             case=example_fluffy_case,
                             sample=example_fluffy_sample)
    cg_context.meta_apis["analysis_api"] = fluffy_analysis_api
    return cg_context
예제 #25
0
def fixture_rna_store(
    base_store: Store,
    helpers: StoreHelpers,
    rna_case_id: str,
    dna_case_id: str,
) -> Store:
    """Populate store with an rna case that is connected to a dna case via sample.subject_id"""

    store: Store = base_store

    # an existing RNA case with related sample
    rna_case = helpers.ensure_case(
        store=store,
        name="rna_case",
        customer=helpers.ensure_customer(store=store),
        data_analysis=Pipeline.MIP_RNA,
        data_delivery=DataDelivery.SCOUT,
    )
    rna_case.internal_id = rna_case_id

    rna_sample_son = helpers.add_sample(store=store, name="rna_son", subject_id="son")
    rna_sample_daughter = helpers.add_sample(
        store=store, name="rna_daughter", subject_id="daughter"
    )
    rna_sample_mother = helpers.add_sample(store=store, name="rna_mother", subject_id="mother")
    rna_sample_father = helpers.add_sample(store=store, name="rna_father", subject_id="father")
    helpers.add_relationship(
        store=store,
        sample=rna_sample_son,
        case=rna_case,
        mother=rna_sample_mother,
        father=rna_sample_father,
        status="affected",
    )
    helpers.add_relationship(
        store=store,
        sample=rna_sample_daughter,
        case=rna_case,
        mother=rna_sample_mother,
        father=rna_sample_father,
        status="unaffected",
    )
    helpers.add_relationship(
        store=store, sample=rna_sample_mother, case=rna_case, status="unaffected"
    )
    helpers.add_relationship(
        store=store, sample=rna_sample_father, case=rna_case, status="affected"
    )

    for link in rna_case.links:
        link.sample.internal_id = link.sample.name

    # an existing DNA case with related sample
    dna_case = helpers.ensure_case(
        store=store,
        name="dna_case",
        customer=helpers.ensure_customer(store=store),
        data_analysis=Pipeline.MIP_DNA,
        data_delivery=DataDelivery.SCOUT,
    )
    dna_case.internal_id = dna_case_id

    dna_sample_son = helpers.add_sample(store=store, name="dna_son", subject_id="son")
    dna_sample_daughter = helpers.add_sample(
        store=store, name="dna_daughter", subject_id="daughter"
    )
    dna_sample_mother = helpers.add_sample(store=store, name="dna_mother", subject_id="mother")
    dna_sample_father = helpers.add_sample(store=store, name="dna_father", subject_id="father")
    helpers.add_relationship(
        store=store,
        sample=dna_sample_son,
        case=dna_case,
        mother=dna_sample_mother,
        father=dna_sample_father,
        status="affected",
    )
    helpers.add_relationship(
        store=store,
        sample=dna_sample_daughter,
        case=dna_case,
        mother=dna_sample_mother,
        father=dna_sample_father,
        status="unaffected",
    )
    helpers.add_relationship(
        store=store, sample=dna_sample_mother, case=dna_case, status="unaffected"
    )
    helpers.add_relationship(
        store=store, sample=dna_sample_father, case=dna_case, status="affected"
    )

    for link in dna_case.links:
        link.sample.internal_id = link.sample.name

    store.commit()
    return store
예제 #26
0
def clean_context(
    cg_context: CGConfig,
    helpers: StoreHelpers,
    project_dir: Path,
    timestamp_yesterday: datetime.datetime,
    timestamp_today: datetime.datetime,
) -> CGConfig:
    analysis_api = BalsamicAnalysisAPI(cg_context)
    store = analysis_api.status_db

    # Create textbook case for cleaning
    case_to_clean = helpers.add_case(
        store=store,
        internal_id="balsamic_case_clean",
        name="balsamic_case_clean",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_to_clean = helpers.add_sample(
        store,
        internal_id="balsamic_sample_clean",
        is_tumour=True,
        application_type="wgs",
    )
    helpers.add_relationship(store,
                             case=case_to_clean,
                             sample=sample_case_to_clean)

    helpers.add_analysis(
        store,
        case=case_to_clean,
        pipeline=Pipeline.BALSAMIC,
        started_at=timestamp_yesterday,
        uploaded_at=timestamp_yesterday,
        cleaned_at=None,
    )
    Path(analysis_api.get_case_path("balsamic_case_clean")).mkdir(
        exist_ok=True, parents=True)

    # Create textbook case not for cleaning
    case_to_not_clean = helpers.add_case(
        store=store,
        internal_id="balsamic_case_not_clean",
        name="balsamic_case_not_clean",
        data_analysis=Pipeline.BALSAMIC,
    )
    case_to_not_clean.action = "running"
    store.commit()

    sample_case_to_not_clean = helpers.add_sample(
        store,
        internal_id="balsamic_sample_not_clean",
        is_tumour=True,
        application_type="wgs",
    )
    helpers.add_relationship(store,
                             case=case_to_not_clean,
                             sample=sample_case_to_not_clean)

    helpers.add_analysis(
        store,
        case=case_to_not_clean,
        pipeline="balsamic",
        started_at=timestamp_yesterday,
        uploaded_at=timestamp_yesterday,
        cleaned_at=None,
    )
    Path(analysis_api.get_case_path("balsamic_case_not_clean")).mkdir(
        exist_ok=True, parents=True)
    cg_context.meta_apis["analysis_api"] = analysis_api

    cg_context.data_delivery.base_path = f"{project_dir}/rsync"

    return cg_context
예제 #27
0
def fixture_balsamic_context(
    cg_context: CGConfig,
    helpers: StoreHelpers,
    balsamic_lims: MockLimsAPI,
    balsamic_housekeeper: HousekeeperAPI,
    trailblazer_api: MockTB,
    hermes_api: HermesApi,
    cg_dir,
) -> CGConfig:
    """context to use in cli"""
    cg_context.housekeeper_api_ = balsamic_housekeeper
    cg_context.lims_api_ = balsamic_lims
    cg_context.trailblazer_api_ = trailblazer_api
    cg_context.meta_apis["analysis_api"] = BalsamicAnalysisAPI(
        config=cg_context)
    status_db: Store = cg_context.status_db

    # Create tgs application version
    helpers.ensure_application_version(store=status_db,
                                       application_tag="TGSA",
                                       application_type="tgs")

    # Create wes application version
    helpers.ensure_application_version(store=status_db,
                                       application_tag="WESA",
                                       application_type="wes")

    # Create textbook case for WGS PAIRED with enough reads
    case_wgs_paired_enough_reads = helpers.add_case(
        store=status_db,
        internal_id="balsamic_case_wgs_paired_enough_reads",
        name="balsamic_case_wgs_paired_enough_reads",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_wgs_paired_tumor_enough_reads = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_tumor_enough_reads",
        is_tumour=True,
        application_type="wgs",
        reads=10,
        sequenced_at=dt.datetime.now(),
    )
    sample_case_wgs_paired_normal_enough_reads = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_normal_enough_reads",
        is_tumour=False,
        application_type="wgs",
        reads=10,
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_wgs_paired_enough_reads,
        sample=sample_case_wgs_paired_tumor_enough_reads,
    )
    helpers.add_relationship(
        status_db,
        case=case_wgs_paired_enough_reads,
        sample=sample_case_wgs_paired_normal_enough_reads,
    )

    # Create textbook case for WGS PAIRED
    case_wgs_paired = helpers.add_case(
        store=status_db,
        internal_id="balsamic_case_wgs_paired",
        name="balsamic_case_wgs_paired",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_wgs_paired_tumor = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_tumor",
        is_tumour=True,
        application_type="wgs",
        reads=10,
        sequenced_at=dt.datetime.now(),
    )
    sample_case_wgs_paired_normal = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_normal",
        is_tumour=False,
        application_type="wgs",
        reads=10,
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(status_db,
                             case=case_wgs_paired,
                             sample=sample_case_wgs_paired_tumor)
    helpers.add_relationship(status_db,
                             case=case_wgs_paired,
                             sample=sample_case_wgs_paired_normal)

    # Create textbook case for TGS PAIRED without enough reads
    case_tgs_paired = helpers.add_case(
        status_db,
        internal_id="balsamic_case_tgs_paired",
        name="balsamic_case_tgs_paired",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_tgs_paired_tumor = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_paired_tumor",
        is_tumour=True,
        application_tag="TGSA",
        application_type="tgs",
        reads=10,
        sequenced_at=dt.datetime.now(),
    )
    sample_case_tgs_paired_normal = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_paired_normal",
        is_tumour=False,
        application_tag="TGSA",
        application_type="tgs",
        reads=0,
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(status_db,
                             case=case_tgs_paired,
                             sample=sample_case_tgs_paired_tumor)
    helpers.add_relationship(status_db,
                             case=case_tgs_paired,
                             sample=sample_case_tgs_paired_normal)

    # Create textbook case for WGS TUMOR ONLY
    case_wgs_single = helpers.add_case(
        status_db,
        internal_id="balsamic_case_wgs_single",
        name="balsamic_case_wgs_single",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_wgs_single_tumor = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_single_tumor",
        is_tumour=True,
        application_type="wgs",
        reads=100,
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(status_db,
                             case=case_wgs_single,
                             sample=sample_case_wgs_single_tumor)

    # Create textbook case for TGS TUMOR ONLY
    case_tgs_single = helpers.add_case(
        status_db,
        internal_id="balsamic_case_tgs_single",
        name="balsamic_case_tgs_single",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_tgs_single_tumor = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_single_tumor",
        is_tumour=True,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(status_db,
                             case=case_tgs_single,
                             sample=sample_case_tgs_single_tumor)

    # Create ERROR case for TGS NORMAL ONLY
    case_tgs_single_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_tgs_single_error",
        name="balsamic_case_tgs_single_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_tgs_single_normal_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_single_normal_error",
        is_tumour=False,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_tgs_single_error,
        sample=sample_case_tgs_single_normal_error,
    )

    # Create ERROR case for TGS TWO TUMOR ONE NORMAL
    case_tgs_paired_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_tgs_paired_error",
        name="balsamic_case_tgs_paired_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_tgs_paired_tumor_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_paired_tumor_error",
        is_tumour=True,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    sample_case_tgs_paired_tumor2_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_paired_tumor2_error",
        is_tumour=True,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    sample_case_tgs_paired_normal_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_tgs_paired_normal_error",
        is_tumour=False,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_tgs_paired_error,
        sample=sample_case_tgs_paired_tumor_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_tgs_paired_error,
        sample=sample_case_tgs_paired_tumor2_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_tgs_paired_error,
        sample=sample_case_tgs_paired_normal_error,
    )

    # Create ERROR case for MIXED application type
    case_mixed_paired_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_mixed_paired_error",
        name="balsamic_case_mixed_paired_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    mixed_sample_case_wgs_paired_tumor_error = helpers.add_sample(
        status_db,
        internal_id="mixed_sample_case_wgs_paired_tumor_error",
        is_tumour=True,
        application_type="wgs",
        sequenced_at=dt.datetime.now(),
    )
    mixed_sample_case_tgs_paired_normal_error = helpers.add_sample(
        status_db,
        internal_id="mixed_sample_case_tgs_paired_normal_error",
        is_tumour=False,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_mixed_paired_error,
        sample=mixed_sample_case_wgs_paired_tumor_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_mixed_paired_error,
        sample=mixed_sample_case_tgs_paired_normal_error,
    )

    # Create ERROR case for MIXED application type NOT BALSAMIC APPLICATION
    case_mixed_wgs_mic_paired_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_mixed_wgs_mic_paired_error",
        name="balsamic_case_mixed_wgs_mic_paired_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    mixed_sample_case_wgs_mic_paired_tumor_error = helpers.add_sample(
        status_db,
        internal_id="mixed_sample_case_wgs_mic_paired_tumor_error",
        is_tumour=True,
        application_type="wgs",
        sequenced_at=dt.datetime.now(),
    )
    mixed_sample_case_wgs_mic_paired_normal_error = helpers.add_sample(
        status_db,
        internal_id="mixed_sample_case_wgs_mic_paired_normal_error",
        is_tumour=False,
        application_tag="MICA",
        application_type="mic",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_mixed_wgs_mic_paired_error,
        sample=mixed_sample_case_wgs_mic_paired_tumor_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_mixed_wgs_mic_paired_error,
        sample=mixed_sample_case_wgs_mic_paired_normal_error,
    )

    # Create ERROR case for MIXED TARGET BED
    case_mixed_bed_paired_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_mixed_bed_paired_error",
        name="balsamic_case_mixed_bed_paired_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    mixed_sample_case_mixed_bed_paired_tumor_error = helpers.add_sample(
        status_db,
        internal_id="mixed_sample_case_mixed_bed_paired_tumor_error",
        is_tumour=True,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    mixed_sample_case_mixed_bed_paired_normal_error = helpers.add_sample(
        status_db,
        internal_id="mixed_sample_case_mixed_bed_paired_normal_error",
        is_tumour=False,
        application_tag="TGSA",
        application_type="tgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_mixed_bed_paired_error,
        sample=mixed_sample_case_mixed_bed_paired_tumor_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_mixed_bed_paired_error,
        sample=mixed_sample_case_mixed_bed_paired_normal_error,
    )

    # Create ERROR case for WGS TUMOR ONLY MIP CLI_OPTION_ANALYSIS ONLY
    mip_case_wgs_single = helpers.add_case(
        status_db,
        internal_id="mip_case_wgs_single",
        name="mip_case_wgs_single",
        data_analysis=Pipeline.MIP_DNA,
    )
    mip_sample_case_wgs_single_tumor = helpers.add_sample(
        status_db,
        internal_id="mip_sample_case_wgs_single_tumor",
        is_tumour=True,
        application_type="wgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=mip_case_wgs_single,
        sample=mip_sample_case_wgs_single_tumor,
    )

    # Create ERROR case for WGS ONE TUMOR TWO NORMAL
    case_wgs_paired_two_normal_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_wgs_paired_two_normal_error",
        name="balsamic_case_wgs_paired_two_normal_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_wgs_paired_two_normal_tumor_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_two_normal_tumor_error",
        is_tumour=True,
        application_tag="WGSA",
        application_type="wgs",
        sequenced_at=dt.datetime.now(),
    )
    sample_case_wgs_paired_two_normal_normal1_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_two_normal_normal1_error",
        is_tumour=False,
        application_tag="WGSA",
        application_type="wgs",
        sequenced_at=dt.datetime.now(),
    )
    sample_case_wgs_paired_two_normal_normal2_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_wgs_paired_two_normal_normal2_error",
        is_tumour=False,
        application_tag="WGSA",
        application_type="wgs",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(
        status_db,
        case=case_wgs_paired_two_normal_error,
        sample=sample_case_wgs_paired_two_normal_tumor_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_wgs_paired_two_normal_error,
        sample=sample_case_wgs_paired_two_normal_normal1_error,
    )
    helpers.add_relationship(
        status_db,
        case=case_wgs_paired_two_normal_error,
        sample=sample_case_wgs_paired_two_normal_normal2_error,
    )

    # Create WES case with 1 tumor sample
    case_wes_tumor = helpers.add_case(
        status_db,
        internal_id="balsamic_case_wes_tumor",
        name="balsamic_case_wes_tumor",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_wes_tumor = helpers.add_sample(
        status_db,
        internal_id="sample_case_wes_tumor",
        is_tumour=True,
        application_tag="WESA",
        application_type="wes",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(status_db,
                             case=case_wes_tumor,
                             sample=sample_case_wes_tumor)

    # Create ERROR case for WES when no panel is found
    case_wes_panel_error = helpers.add_case(
        status_db,
        internal_id="balsamic_case_wes_panel_error",
        name="balsamic_case_wes_panel_error",
        data_analysis=Pipeline.BALSAMIC,
    )
    sample_case_wes_panel_error = helpers.add_sample(
        status_db,
        internal_id="sample_case_wes_panel_error",
        is_tumour=True,
        application_tag="WESA",
        application_type="wes",
        sequenced_at=dt.datetime.now(),
    )
    helpers.add_relationship(status_db,
                             case=case_wes_panel_error,
                             sample=sample_case_wes_panel_error)

    # Create ERROR case with NO SAMPLES
    helpers.add_case(status_db,
                     internal_id="no_sample_case",
                     name="no_sample_case")

    # Create BED1 version 1
    bed1_name = "BalsamicBed1"
    bed1_filename = "balsamic_bed_1.bed"
    Path(cg_dir, bed1_filename).touch(exist_ok=True)
    bed1 = status_db.add_bed(name=bed1_name)
    status_db.add_commit(bed1)
    version1 = status_db.add_bed_version(bed=bed1,
                                         version=1,
                                         filename=bed1_filename,
                                         shortname=bed1_name)
    status_db.add_commit(version1)

    # Create BED2 version 1
    bed2_name = "BalsamicBed2"
    bed2_filename = "balsamic_bed_2.bed"
    Path(cg_dir, bed2_filename).touch(exist_ok=True)
    bed2 = status_db.add_bed(name=bed2_name)
    status_db.add_commit(bed2)
    version2 = status_db.add_bed_version(bed=bed2,
                                         version=1,
                                         filename=bed2_filename,
                                         shortname=bed2_name)
    status_db.add_commit(version2)
    return cg_context