예제 #1
0
파일: status.py 프로젝트: eriksjolund/cg
 def store_pools(
     self, customer: str, order: str, ordered: dt.datetime, ticket: int, pools: List[dict],
 ) -> List[models.Pool]:
     """Store pools in the status database."""
     customer_obj = self.status.customer(customer)
     if customer_obj is None:
         raise OrderError(f"unknown customer: {customer}")
     new_pools = []
     for pool in pools:
         with self.status.session.no_autoflush:
             application_version = self.status.current_application_version(pool["application"])
             if application_version is None:
                 raise OrderError(f"Invalid application: {pool['application']}")
         new_pool = self.status.add_pool(
             customer=customer_obj,
             name=pool["name"],
             order=order,
             ordered=ordered,
             ticket=ticket,
             application_version=application_version,
             data_analysis=pool["data_analysis"],
             capture_kit=pool["capture_kit"],
         )
         new_delivery = self.status.add_delivery(destination="caesar", pool=new_pool)
         self.status.add(new_delivery)
         new_pools.append(new_pool)
     self.status.add_commit(new_pools)
     return new_pools
예제 #2
0
파일: status.py 프로젝트: eriksjolund/cg
    def store_samples(
        self, customer: str, order: str, ordered: dt.datetime, ticket: int, samples: List[dict],
    ) -> List[models.Sample]:
        """Store samples in the status database."""
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_samples = []

        with self.status.session.no_autoflush:
            for sample in samples:
                new_sample = self.status.add_sample(
                    name=sample["name"],
                    internal_id=sample["internal_id"],
                    sex=sample["sex"] or "unknown",
                    order=order,
                    ordered=ordered,
                    ticket=ticket,
                    priority=sample["priority"],
                    comment=sample["comment"],
                    tumour=sample["tumour"],
                    data_analysis=sample["data_analysis"],
                )
                new_sample.customer = customer_obj
                application_tag = sample["application"]
                application_version = self.status.current_application_version(application_tag)
                if application_version is None:
                    raise OrderError(f"Invalid application: {sample['application']}")
                new_sample.application_version = application_version
                new_samples.append(new_sample)

        self.status.add_commit(new_samples)
        return new_samples
예제 #3
0
파일: status.py 프로젝트: mayabrandi/cg
 def store_pools(self, customer: str, order: str, ordered: dt.datetime,
                 ticket: int, pools: List[dict]) -> List[models.Pool]:
     """Store pools in the status database."""
     customer_obj = self.status.customer(customer)
     if customer_obj is None:
         raise OrderError(f"unknown customer: {customer}")
     new_pools = []
     for pool in pools:
         with self.status.session.no_autoflush:
             application_version = self.status.latest_version(
                 pool['application'])
             if application_version is None:
                 raise OrderError(
                     f"unknown application: {pool['application']}")
         new_pool = self.status.add_pool(
             customer=customer_obj,
             name=pool['name'],
             order=order,
             ordered=ordered,
             ticket=ticket,
             application_version=application_version,
         )
         new_delivery = self.status.add_delivery(destination='caesar',
                                                 pool=new_pool)
         self.status.add(new_delivery)
         new_pools.append(new_pool)
     self.status.add_commit(new_pools)
     return new_pools
예제 #4
0
 def group_containers(samples):
     """Group samples by containers."""
     tubes = {}
     plates = {}
     no_container = {}
     for sample_data in samples:
         if sample_data["container"] == "Tube":
             # detected tube: name after sample unless specified
             container_name = sample_data.get(
                 "container_name") or sample_data["name"]
             if container_name in tubes:
                 raise OrderError(
                     f"{container_name}: conflicting sample/tube name")
             tubes[container_name] = [sample_data]
         elif sample_data["container"] == "96 well plate":
             # detected plate: require container name
             if sample_data["container_name"] not in plates:
                 plates[sample_data["container_name"]] = []
             plates[sample_data["container_name"]].append(sample_data)
         elif sample_data["container"] == "No container":
             # detected no-container: name after sample unless specified
             container_name = sample_data.get(
                 "container_name") or sample_data["name"]
             if container_name in tubes:
                 raise OrderError(
                     f"{container_name}: conflicting sample/container name")
             tubes[container_name] = [sample_data]
         else:
             raise ValueError(
                 f"unknown container type: {sample_data['container']}")
     return tubes, plates, no_container
예제 #5
0
    def store_items_in_status(self, customer: str, order: str,
                              ordered: dt.datetime, ticket: int,
                              items: List[dict]) -> List[models.Sample]:
        """Store fastq samples in the status database including family connection and delivery"""
        production_customer = self.status.customer("cust000")
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_samples = []

        with self.status.session.no_autoflush:
            for sample in items:
                new_sample = self.status.add_sample(
                    comment=sample["comment"],
                    internal_id=sample.get("internal_id"),
                    name=sample["name"],
                    order=order,
                    ordered=ordered,
                    priority=sample["priority"],
                    sex=sample["sex"] or "unknown",
                    ticket=ticket,
                    tumour=sample["tumour"],
                )
                new_sample.customer = customer_obj
                application_tag = sample["application"]
                application_version = self.status.current_application_version(
                    application_tag)
                if application_version is None:
                    raise OrderError(
                        f"Invalid application: {sample['application']}")
                new_sample.application_version = application_version
                new_samples.append(new_sample)
                data_analysis: Pipeline = self._get_fastq_pipeline(
                    application_version, new_sample.is_tumour)
                new_case = self.status.add_case(
                    data_analysis=data_analysis,
                    data_delivery=DataDelivery(sample["data_delivery"]),
                    name=sample["name"],
                    panels=["OMIM-AUTO"],
                    priority="research",
                )
                new_case.customer = production_customer
                self.status.add(new_case)
                new_relationship = self.status.relate_sample(
                    family=new_case,
                    sample=new_sample,
                    status=StatusEnum.unknown)
                self.status.add(new_relationship)
                new_delivery = self.status.add_delivery(destination="caesar",
                                                        sample=new_sample)
                self.status.add(new_delivery)

        self.status.add_commit(new_samples)
        return new_samples
예제 #6
0
파일: status.py 프로젝트: eriksjolund/cg
    def store_microbial_order(
        self,
        customer: str,
        order: str,
        ordered: dt.datetime,
        ticket: int,
        lims_project: str,
        samples: List[dict],
        comment: str = None,
    ) -> models.MicrobialOrder:
        """Store microbial samples in the status database."""
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        with self.status.session.no_autoflush:
            new_order = self.status.add_microbial_order(
                customer=customer_obj,
                name=order,
                ordered=ordered,
                internal_id=lims_project,
                ticket_number=ticket,
                comment=comment,
            )
            for sample_data in samples:
                application_tag = sample_data["application"]
                application_version = self.status.current_application_version(application_tag)
                if application_version is None:
                    raise OrderError(f"Invalid application: {sample_data['application']}")

                organism = self.status.organism(sample_data["organism_id"])

                if not organism:
                    organism = self.status.add_organism(
                        internal_id=sample_data["organism_id"],
                        name=sample_data["organism_id"],
                        reference_genome=sample_data["reference_genome"],
                    )
                    self.status.add_commit(organism)

                new_sample = self.status.add_microbial_sample(
                    name=sample_data["name"],
                    internal_id=sample_data["internal_id"],
                    reference_genome=sample_data["reference_genome"],
                    comment=sample_data["comment"],
                    organism=organism,
                    application_version=application_version,
                    priority=sample_data["priority"],
                    data_analysis=sample_data["data_analysis"],
                )
                new_order.microbial_samples.append(new_sample)

        self.status.add_commit(new_order)
        return new_order
예제 #7
0
파일: status.py 프로젝트: eriksjolund/cg
    def store_fastq_samples(
        self, customer: str, order: str, ordered: dt.datetime, ticket: int, samples: List[dict],
    ) -> List[models.Sample]:
        """Store fast samples in the status database including family connection and delivery."""
        production_customer = self.status.customer("cust000")
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_samples = []

        with self.status.session.no_autoflush:
            for sample in samples:
                new_sample = self.status.add_sample(
                    name=sample["name"],
                    internal_id=sample["internal_id"],
                    sex=sample["sex"] or "unknown",
                    order=order,
                    ordered=ordered,
                    ticket=ticket,
                    priority=sample["priority"],
                    comment=sample["comment"],
                    tumour=sample["tumour"],
                    data_analysis=sample["data_analysis"],
                )
                new_sample.customer = customer_obj

                application_tag = sample["application"]
                application_version = self.status.current_application_version(application_tag)
                if application_version is None:
                    raise OrderError(f"Invalid application: {sample['application']}")
                new_sample.application_version = application_version
                new_samples.append(new_sample)

                if not new_sample.is_tumour:
                    new_family = self.status.add_family(
                        name=sample["name"], panels=["OMIM-AUTO"], priority="research"
                    )
                    new_family.customer = production_customer
                    self.status.add(new_family)

                    new_relationship = self.status.relate_sample(
                        family=new_family, sample=new_sample, status=sample["status"] or "unknown",
                    )
                    self.status.add(new_relationship)

                new_delivery = self.status.add_delivery(destination="caesar", sample=new_sample)
                self.status.add(new_delivery)

        self.status.add_commit(new_samples)
        return new_samples
예제 #8
0
    def store_items_in_status(self, customer: str, order: str,
                              ordered: dt.datetime, ticket: int,
                              items: List[dict]) -> List[models.Sample]:
        """Store samples in the status database."""
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_samples = []

        with self.status.session.no_autoflush:
            for sample in items:
                new_sample = self.status.add_sample(
                    comment=sample["comment"],
                    internal_id=sample.get("internal_id"),
                    name=sample["name"],
                    order=order,
                    ordered=ordered,
                    priority=sample["priority"],
                    sex="unknown",
                    ticket=ticket,
                )
                new_sample.customer = customer_obj
                application_tag = sample["application"]
                application_version = self.status.current_application_version(
                    application_tag)
                if application_version is None:
                    raise OrderError(
                        f"Invalid application: {sample['application']}")
                new_sample.application_version = application_version
                new_samples.append(new_sample)

                new_case = self.status.add_case(
                    data_analysis=Pipeline(sample["data_analysis"]),
                    data_delivery=DataDelivery(sample["data_delivery"]),
                    name=sample["name"],
                    panels=None,
                    priority=sample["priority"],
                )
                new_case.customer = customer_obj
                self.status.add(new_case)

                new_relationship = self.status.relate_sample(
                    family=new_case,
                    sample=new_sample,
                    status=StatusEnum.unknown)
                self.status.add(new_relationship)

        self.status.add_commit(new_samples)
        return new_samples
예제 #9
0
    def submit(self, project: OrderType, data: dict, ticket: dict) -> dict:
        """Submit a batch of samples."""
        try:
            ORDER_SCHEMES[project].validate(data)
        except (ValueError, TypeError) as error:
            raise OrderError(error.args[0])

        # detect manual ticket assignment
        ticket_match = re.search(r'^#?([0-9]{6})$', data['name'])
        ticket_number = int(ticket_match.group()) if ticket_match else None
        if ticket_number:
            LOG.info(f"{ticket_number}: detected ticket in order name")
            data['ticket'] = ticket_number
        else:
            # open and assign ticket to order
            try:
                if self.osticket:
                    message = f"New incoming samples, {ticket['name']}"
                    data['ticket'] = self.osticket.open_ticket(
                        name=ticket['name'],
                        email=ticket['email'],
                        subject=data['name'],
                        message=message,
                    )
                    LOG.info(f"{data['ticket']}: opened new ticket")
                else:
                    data['ticket'] = None
            except TicketCreationError as error:
                LOG.warning(error.message)
                data['ticket'] = None
        order_func = getattr(self, f"submit_{project.value}")
        result = order_func(data)
        return result
예제 #10
0
    def _validate_subject_sex(self, samples: [Of1508Sample], customer_id: str):
        """Validate that sex is consistent with existing samples, skips samples of unknown sex

        Args:
            samples     (list[dict]):   Samples to validate
            customer_id (str):          Customer that the samples belong to
        Returns:
            Nothing
        """

        sample: Of1508Sample
        for sample in samples:
            subject_id: str = sample.subject_id
            if not subject_id:
                continue
            new_gender: str = sample.sex
            if new_gender == "unknown":
                continue
            existing_samples: [
                models.Sample
            ] = self.status.samples_by_subject_id(customer_id=customer_id,
                                                  subject_id=subject_id)
            existing_sample: models.Sample
            for existing_sample in existing_samples:
                previous_gender = existing_sample.sex
                if previous_gender == "unknown":
                    continue

                if previous_gender != new_gender:
                    raise OrderError(
                        f"Sample gender inconsistency for subject_id: {subject_id}: previous gender {previous_gender}, new gender {new_gender}"
                    )
예제 #11
0
파일: api.py 프로젝트: eriksjolund/cg
    def _validate_customer_on_imported_samples(self, project, data):
        for sample in data.get("samples"):

            if sample.get("internal_id"):

                if project not in (
                    OrderType.MIP,
                    OrderType.EXTERNAL,
                    OrderType.BALSAMIC,
                    OrderType.MIP_BALSAMIC,
                    OrderType.MIP_RNA,
                ):
                    raise OrderError(
                        f"Only MIP, Balsamic and external orders can have imported "
                        f"samples: "
                        f"{sample.get('name')}"
                    )

                existing_sample = self.status.sample(sample.get("internal_id"))
                data_customer = self.status.customer(data["customer"])

                if existing_sample.customer.customer_group_id != data_customer.customer_group_id:
                    raise OrderError(f"Sample not available: {sample.get('name')}")
예제 #12
0
    def prepare(cls, samples):
        """Convert API input to LIMS input data."""
        lims_containers = []
        tubes, plates, no_container = cls.group_containers(samples)
        # "96 well plate" = container type "1"; Tube = container type "2"; "No container" = container type "3"
        for container_type, containers in [("1", plates), ("2", tubes),
                                           ("3", no_container)]:
            for container_name, samples in containers.items():
                new_container = {
                    "name": container_name,
                    "type": container_type,
                    "samples": []
                }
                # check that positions in plate are unique
                well_positions = {}
                for sample_data in samples:
                    location = sample_data["well_position"] or None
                    if location:
                        if location in well_positions:
                            first_sample = well_positions[location]
                            message = (
                                f"duplicate well position: {location} | {first_sample}"
                                f" - {sample_data['name']}")
                            raise OrderError(message)
                        well_positions[location] = sample_data["name"]
                    if sample_data[
                            "container"] == "96 well plate" and location is None:
                        message = f"missing 'well_position' for sample: {sample_data['name']}"
                        raise ValueError(message)
                    new_sample = {
                        "name": sample_data["name"],
                        "location": location or "1:1",
                        "index_sequence": sample_data["index_sequence"],
                        "udfs": {},
                    }
                    for key, value in sample_data["udfs"].items():
                        if value is None:
                            LOG.debug(f"{key}: skipping null value UDF")
                            continue
                        if key in PROP2UDF:
                            if isinstance(value, bool):
                                value = "yes" if value else "no"
                            new_sample["udfs"][PROP2UDF[key]] = value
                        else:
                            LOG.debug(f"UDF not found: {key} - {value}")

                    new_container["samples"].append(new_sample)
                lims_containers.append(new_container)
        return lims_containers
예제 #13
0
    def _validate_case_names_are_available(self, customer_id: str,
                                           samples: List[RmlSample],
                                           ticket: int):
        """Validate that the names of all pools are unused for all samples"""
        customer_obj: models.Customer = self.status.customer(customer_id)

        sample: RmlSample
        for sample in samples:
            case_name: str = self.create_case_name(pool_name=sample.pool,
                                                   ticket=ticket)

            if self.status.find_family(customer=customer_obj, name=case_name):
                raise OrderError(
                    f"Case name {case_name} already in use for customer {customer_obj.name}"
                )
예제 #14
0
    def _validate_case_names_are_unique(self, samples: List[OrderInSample],
                                        customer_id: str) -> None:
        """Validate that the names of all cases are unused for all samples"""
        customer_obj: models.Customer = self.status.customer(customer_id)

        sample: Of1508Sample
        for sample in samples:

            if self._rerun_of_existing_case(sample):
                continue

            if self.status.find_family(customer=customer_obj,
                                       name=sample.family_name):
                raise OrderError(
                    f"Case name {sample.family_name} already in use")
예제 #15
0
    def _validate_samples_available_to_customer(self,
                                                samples: List[OrderInSample],
                                                customer_id: str) -> None:
        """Validate that the customer have access to all samples"""
        sample: Of1508Sample
        for sample in samples:
            if not sample.internal_id:
                continue

            existing_sample: models.Sample = self.status.sample(
                sample.internal_id)
            data_customer: models.Customer = self.status.customer(customer_id)

            if existing_sample.customer.customer_group_id != data_customer.customer_group_id:
                raise OrderError(f"Sample not available: {sample.name}")
예제 #16
0
파일: order.py 프로젝트: mayabrandi/cg
    def prepare(cls, samples):
        """Convert API input to LIMS input data."""
        lims_containers = []
        tubes, plates = cls.group_containers(samples)
        # "96 well plate" = container type "1"; Tube = container type "2"
        for container_type, containers in [('1', plates), ('2', tubes)]:
            for container_name, samples in containers.items():
                new_container = {
                    'name': container_name,
                    'type': container_type,
                    'samples': [],
                }
                # check that positions in plate are unique
                well_positions = {}
                for sample_data in samples:
                    location = sample_data['well_position'] or None
                    if location:
                        if location in well_positions:
                            first_sample = well_positions[location]
                            message = (
                                f"duplicate well position: {location} | {first_sample}"
                                f" - {sample_data['name']}")
                            raise OrderError(message)
                        well_positions[location] = sample_data['name']
                    if sample_data[
                            'container'] == '96 well plate' and location is None:
                        message = f"missing 'well_position' for sample: {sample_data['name']}"
                        raise ValueError(message)
                    new_sample = {
                        'name': sample_data['name'],
                        'location': location or '1:1',
                        'index_sequence': sample_data['index_sequence'],
                        'udfs': {}
                    }
                    for key, value in sample_data['udfs'].items():
                        if value is None:
                            LOG.debug(f"{key}: skipping null value UDF")
                            continue
                        if key in PROP2UDF:
                            if isinstance(value, bool):
                                value = 'yes' if value else 'no'
                            new_sample['udfs'][PROP2UDF[key]] = value
                        else:
                            LOG.debug(f"UDF not found: {key} - {value}")

                    new_container['samples'].append(new_sample)
                lims_containers.append(new_container)
        return lims_containers
예제 #17
0
파일: status.py 프로젝트: mayabrandi/cg
    def store_samples(self, customer: str, order: str, ordered: dt.datetime,
                      ticket: int, samples: List[dict]) -> List[models.Sample]:
        """Store samples in the status database."""
        production_customer = self.status.customer('cust000')
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_samples = []
        for sample in samples:
            with self.status.session.no_autoflush:
                new_sample = self.status.add_sample(
                    name=sample['name'],
                    internal_id=sample['internal_id'],
                    sex=sample['sex'] or 'unknown',
                    order=order,
                    ordered=ordered,
                    ticket=ticket,
                    priority=sample['priority'],
                    comment=sample['comment'],
                    tumour=sample['tumour'],
                )
            new_sample.customer = customer_obj
            with self.status.session.no_autoflush:
                new_sample.application_version = self.status.latest_version(
                    sample['application'])
            new_samples.append(new_sample)

            if not new_sample.is_tumour:
                with self.status.session.no_autoflush:
                    new_family = self.status.add_family(name=sample['name'],
                                                        panels=['OMIM-AUTO'],
                                                        priority='research')
                new_family.customer = production_customer
                self.status.add(new_family)

                new_relationship = self.status.relate_sample(
                    family=new_family,
                    sample=new_sample,
                    status=sample['status'] or 'unknown',
                )
                self.status.add(new_relationship)

            new_delivery = self.status.add_delivery(destination='caesar',
                                                    sample=new_sample)
            self.status.add(new_delivery)

        self.status.add_commit(new_samples)
        return new_samples
예제 #18
0
    def _validate_sample_names_are_available(self,
                                             samples: List[SarsCov2Sample],
                                             customer_id: str) -> None:
        """Validate that the names of all samples are unused for all samples"""
        customer_obj: models.Customer = self.status.customer(customer_id)

        sample: SarsCov2Sample
        for sample in samples:
            sample_name: str = sample.name

            if sample.control:
                continue

            if self.status.find_samples(customer=customer_obj,
                                        name=sample_name).first():
                raise OrderError(
                    f"Sample name {sample_name} already in use for customer {customer_obj.name}"
                )
예제 #19
0
파일: status.py 프로젝트: mayabrandi/cg
 def pools_to_status(data: dict) -> dict:
     """Convert input to pools."""
     pools = {}
     for sample in data['samples']:
         if sample['pool'] not in pools:
             pools[sample['pool']] = set()
         pools[sample['pool']].add(sample['application'])
     status_data = {
         'customer': data['customer'],
         'order': data['name'],
         'pools': []
     }
     for pool_name, applications in pools.items():
         if len(applications) != 1:
             raise OrderError(
                 f"different application in pool: {pool_name} - {applications}"
             )
         status_data['pools'].append({
             'name': pool_name,
             'application': applications.pop(),
         })
     return status_data
예제 #20
0
    def order_to_status(order: OrderIn) -> dict:
        """Convert input to pools."""

        status_data = {
            "customer": order.customer,
            "order": order.name,
            "comment": order.comment,
            "pools": [],
        }

        # group pools
        pools = {}

        for sample in order.samples:
            pool_name = sample.pool
            application = sample.application
            data_analysis = sample.data_analysis
            data_delivery = sample.data_delivery
            priority = sample.priority

            if pool_name not in pools:
                pools[pool_name] = {}
                pools[pool_name]["name"] = pool_name
                pools[pool_name]["applications"] = set()
                pools[pool_name]["priorities"] = set()
                pools[pool_name]["samples"] = []

            pools[pool_name]["samples"].append(sample)
            pools[pool_name]["applications"].add(application)
            pools[pool_name]["priorities"].add(priority)

        # each pool must only have same of some values
        for pool in pools.values():

            applications = pool["applications"]
            priorities = pool["priorities"]
            pool_name = pool["name"]
            if len(applications) > 1:
                raise OrderError(
                    f"different applications in pool: {pool_name} - {applications}"
                )
            if len(priorities) > 1:
                raise OrderError(
                    f"different priorities in pool: {pool_name} - {priorities}"
                )

        for pool in pools.values():

            pool_name = pool["name"]
            applications = pool["applications"]
            application = applications.pop()
            pool_samples = pool["samples"]
            priorities = pool["priorities"]
            priority = priorities.pop()

            status_data["pools"].append({
                "name":
                pool_name,
                "application":
                application,
                "data_analysis":
                data_analysis,
                "data_delivery":
                data_delivery,
                "priority":
                priority,
                "samples": [{
                    "comment": sample.comment,
                    "control": sample.control,
                    "name": sample.name,
                } for sample in pool_samples],
            })
        return status_data
예제 #21
0
파일: status.py 프로젝트: eriksjolund/cg
    def store_cases(
        self, customer: str, order: str, ordered: dt.datetime, ticket: int, cases: List[dict],
    ) -> List[models.Family]:
        """Store cases and samples in the status database."""
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_families = []
        for case in cases:
            case_obj = self.status.find_family(customer_obj, case["name"])
            if case_obj:
                case_obj.panels = case["panels"]
            else:
                case_obj = self.status.add_family(
                    name=case["name"], panels=case["panels"], priority=case["priority"]
                )
                case_obj.customer = customer_obj
                new_families.append(case_obj)

            family_samples = {}
            for sample in case["samples"]:
                sample_obj = self.status.sample(sample["internal_id"])
                if sample_obj:
                    family_samples[sample["name"]] = sample_obj
                else:
                    new_sample = self.status.add_sample(
                        capture_kit=sample["capture_kit"],
                        comment=sample["comment"],
                        data_analysis=sample["data_analysis"],
                        from_sample=sample["from_sample"],
                        internal_id=sample["internal_id"],
                        name=sample["name"],
                        order=order,
                        ordered=ordered,
                        priority=case["priority"],
                        sex=sample["sex"],
                        ticket=ticket,
                        time_point=sample["time_point"],
                        tumour=sample["tumour"],
                    )
                    new_sample.customer = customer_obj
                    with self.status.session.no_autoflush:
                        application_tag = sample["application"]
                        new_sample.application_version = self.status.current_application_version(
                            application_tag
                        )
                    if new_sample.application_version is None:
                        raise OrderError(f"Invalid application: {sample['application']}")

                    family_samples[new_sample.name] = new_sample
                    self.status.add(new_sample)
                    new_delivery = self.status.add_delivery(destination="caesar", sample=new_sample)
                    self.status.add(new_delivery)

            for sample in case["samples"]:
                mother_obj = family_samples[sample["mother"]] if sample.get("mother") else None
                father_obj = family_samples[sample["father"]] if sample.get("father") else None
                with self.status.session.no_autoflush:
                    link_obj = self.status.link(case_obj.internal_id, sample["internal_id"])
                if link_obj:
                    link_obj.status = sample["status"] or link_obj.status
                    link_obj.mother = mother_obj or link_obj.mother
                    link_obj.father = father_obj or link_obj.father
                else:
                    new_link = self.status.relate_sample(
                        family=case_obj,
                        sample=family_samples[sample["name"]],
                        status=sample["status"],
                        mother=mother_obj,
                        father=father_obj,
                    )
                    self.status.add(new_link)
            self.status.add_commit(new_families)
        return new_families
예제 #22
0
파일: api.py 프로젝트: eriksjolund/cg
    def submit(self, project: OrderType, data: dict, ticket: dict) -> dict:
        """Submit a batch of samples.

        Main entry point for the class towards interfaces that implements it.
        """
        try:
            ORDER_SCHEMES[project].validate(data)
        except (ValueError, TypeError) as error:
            raise OrderError(error.args[0])

        self._validate_customer_on_imported_samples(project, data)

        # detect manual ticket assignment
        ticket_match = re.fullmatch(r"#([0-9]{6})", data["name"])

        if ticket_match:
            ticket_number = int(ticket_match.group(1))
            LOG.info(f"{ticket_number}: detected ticket in order name")
            data["ticket"] = ticket_number
        else:
            # open and assign ticket to order
            try:
                if self.osticket:
                    message = f"data:text/html;charset=utf-8,New incoming samples: "

                    for sample in data.get("samples"):
                        message += "<br />" + sample.get("name")

                        if sample.get("family_name"):
                            message += f", family: {sample.get('family_name')}"

                        if sample.get("internal_id"):

                            existing_sample = self.status.sample(sample.get("internal_id"))
                            sample_customer = ""
                            if existing_sample.customer_id != data["customer"]:
                                sample_customer = " from " + existing_sample.customer.internal_id

                            message += f" (already existing sample{sample_customer})"

                        if sample.get("comment"):
                            message += ", " + sample.get("comment")

                    message += f"<br />"

                    if data.get("comment"):
                        message += f"<br />{data.get('comment')}."

                    if ticket.get("name"):
                        message += f"<br />{ticket.get('name')}"

                    data["ticket"] = self.osticket.open_ticket(
                        name=ticket["name"],
                        email=ticket["email"],
                        subject=data["name"],
                        message=message,
                    )

                    LOG.info(f"{data['ticket']}: opened new ticket")
                else:
                    data["ticket"] = None
            except TicketCreationError as error:
                LOG.warning(error.message)
                data["ticket"] = None
        order_func = getattr(self, f"submit_{project.value}")
        result = order_func(data)
        return result
예제 #23
0
파일: status.py 프로젝트: mayabrandi/cg
    def store_families(self, customer: str, order: str, ordered: dt.datetime,
                       ticket: int,
                       families: List[dict]) -> List[models.Family]:
        """Store families and samples in the status database."""
        customer_obj = self.status.customer(customer)
        if customer_obj is None:
            raise OrderError(f"unknown customer: {customer}")
        new_families = []
        for family in families:
            family_obj = self.status.find_family(customer_obj, family['name'])
            if family_obj:
                family_obj.panels = family['panels']
            else:
                family_obj = self.status.add_family(
                    name=family['name'],
                    panels=family['panels'],
                    priority=family['priority'],
                )
                family_obj.customer = customer_obj
                new_families.append(family_obj)

            family_samples = {}
            for sample in family['samples']:
                sample_obj = self.status.sample(sample['internal_id'])
                if sample_obj:
                    sample_obj.name = sample['name']
                    sample_obj.sex = sample['sex']
                    sample_obj.comment = sample['comment']
                    family_samples[sample_obj.name] = sample_obj
                else:
                    new_sample = self.status.add_sample(
                        name=sample['name'],
                        internal_id=sample['internal_id'],
                        sex=sample['sex'],
                        order=order,
                        ordered=ordered,
                        ticket=ticket,
                        priority=family['priority'],
                        comment=sample['comment'],
                    )
                    new_sample.customer = customer_obj
                    with self.status.session.no_autoflush:
                        application_tag = sample['application']
                        new_sample.application_version = self.status.latest_version(
                            application_tag)
                    if new_sample.application_version is None:
                        raise OrderError(
                            f"unknown application tag: {sample['application']}"
                        )
                    family_samples[new_sample.name] = new_sample
                    self.status.add(new_sample)

                    new_delivery = self.status.add_delivery(
                        destination='caesar', sample=new_sample)
                    self.status.add(new_delivery)

            for sample in family['samples']:
                mother_obj = family_samples[sample['mother']] if sample.get(
                    'mother') else None
                father_obj = family_samples[sample['father']] if sample.get(
                    'father') else None
                with self.status.session.no_autoflush:
                    link_obj = self.status.link(family_obj.internal_id,
                                                sample['internal_id'])
                if link_obj:
                    link_obj.status = sample['status'] or link_obj.status
                    link_obj.mother = mother_obj or link_obj.mother
                    link_obj.father = father_obj or link_obj.father
                else:
                    new_link = self.status.relate_sample(
                        family=family_obj,
                        sample=family_samples[sample['name']],
                        status=sample['status'],
                        mother=mother_obj,
                        father=father_obj,
                    )
                    self.status.add(new_link)
            self.status.add_commit(new_families)
        return new_families
예제 #24
0
파일: status.py 프로젝트: eriksjolund/cg
    def pools_to_status(data: dict) -> dict:
        """Convert input to pools."""

        status_data = {"customer": data["customer"], "order": data["name"], "pools": []}

        # group pools
        pools = {}

        for sample in data["samples"]:
            name = sample["pool"]
            application = sample["application"]
            data_analysis = sample["data_analysis"]
            capture_kit = sample.get("capture_kit")

            if name not in pools:
                pools[name] = {}
                pools[name]["name"] = name
                pools[name]["applications"] = set()
                pools[name]["capture_kits"] = set()

            pools[name]["applications"].add(application)

            if capture_kit:
                pools[name]["capture_kits"].add(capture_kit)

        # each pool must only have one application type
        for pool in pools.values():

            applications = pool["applications"]
            pool_name = pool["name"]
            if len(applications) != 1:
                raise OrderError(f"different application in pool: {pool_name} - {applications}")

        # each pool must only have one capture kit
        for pool in pools.values():

            capture_kits = pool["capture_kits"]
            pool_name = pool["name"]

            if len(capture_kits) > 1:
                raise OrderError(f"different capture kits in pool: {pool_name} - {capture_kits}")

        for pool in pools.values():

            pool_name = pool["name"]
            applications = pool["applications"]
            application = applications.pop()
            capture_kits = pool["capture_kits"]
            capture_kit = None

            if len(capture_kits) == 1:
                capture_kit = capture_kits.pop()

            status_data["pools"].append(
                {
                    "name": pool_name,
                    "application": application,
                    "data_analysis": data_analysis,
                    "capture_kit": capture_kit,
                }
            )
        return status_data