def __build_buffer_transfer_jobs(self, transfer_job_map): self.add_debug('Creating buffer transfer jobs.') # The buffer worklists are stored with the ISO request. ws = self.iso.iso_request.worklist_series rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.QUARTER_MODULAR) has_pool_racks = not self.__pool_stock_rack_map is None for wl in ws.get_sorted_worklists(): sec_idx = wl.index % 4 job_idx = len(transfer_job_map) if has_pool_racks and wl.index < 4: # Pool stock rack buffer worklist. tgt_iso_rack = self.__pool_stock_rack_map.get(sec_idx) elif (has_pool_racks and wl.index < 8) \ or (not has_pool_racks and wl.index < 4): # Preparation plate buffer worklist. tgt_iso_rack = self.__prep_plate_map.get(sec_idx) else: # break if tgt_iso_rack is None: # The last ISO might not have all sectors used. continue trf_job = SampleDilutionJob( job_idx, wl, tgt_iso_rack.rack, rs, source_rack_barcode=self.BUFFER_RESERVOIR_BARCODE, ignored_positions= self.__empty_stock_rack_positions_map[sec_idx]) transfer_job_map[job_idx] = (trf_job, wl)
def __build_buffer_transfer_jobs(self, transfer_job_map): self.add_debug('Creating buffer transfer jobs.') # The buffer worklists are stored with the ISO request. ws = self.iso.iso_request.worklist_series rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.QUARTER_MODULAR) has_pool_racks = not self.__pool_stock_rack_map is None for wl in ws.get_sorted_worklists(): sec_idx = wl.index % 4 job_idx = len(transfer_job_map) if has_pool_racks and wl.index < 4: # Pool stock rack buffer worklist. tgt_iso_rack = self.__pool_stock_rack_map.get(sec_idx) elif (has_pool_racks and wl.index < 8) \ or (not has_pool_racks and wl.index < 4): # Preparation plate buffer worklist. tgt_iso_rack = self.__prep_plate_map.get(sec_idx) else: # break if tgt_iso_rack is None: # The last ISO might not have all sectors used. continue trf_job = SampleDilutionJob( job_idx, wl, tgt_iso_rack.rack, rs, source_rack_barcode=self.BUFFER_RESERVOIR_BARCODE, ignored_positions=self. __empty_stock_rack_positions_map[sec_idx]) transfer_job_map[job_idx] = (trf_job, wl)
def __init__(self, entity, mode, user=None, **kw): """ Constructor: :param entity: The ISO job or ISO to process. :type entity: :class:`thelma.entities.job.IsoJob` or :class:`thelma.entities.iso.LabIso`. :param mode: :attr:`MODE_EXECUTE` or :attr:`MODE_PRINT_WORKLISTS` :type mode: str :param user: The user who conducts the DB update (required for execution mode). :type user: :class:`thelma.entities.user.User` :default user: *None* """ StockTransferWriterExecutor.__init__(self, entity=entity, mode=mode, user=user, **kw) #: The lab ISO requests the entity belongs to. self._iso_request = None #: The final layout for each ISO in this entity mapped onto ISOs. self.__final_layouts = None #: see :class:`LAB_ISO_ORDERS`. self._processing_order = None #: The expected :class:`ISO_STATUS. self._expected_iso_status = None #: The involved racks (as list of :class:`IsoRackContainer` #: objects) mapped onto rack markers. Final plates are mapped onto the #: :attr:`LABELS.ROLE_FINAL` marker. self.__rack_containers = None #: The final plates (as list of :class:`IsoRackContainer` objects) #: mapped onto ISOs. self.__final_plates = None #: The layout for each plate mapped onto plate label. self.__plate_layouts = None #: The ignored positions for each plate. self.__ignored_positions = None #: The stock rack for this entity mapped onto labels. self._stock_racks = None #: The stock rack layouts mapped onto stock rack barcodes #: (for reporting). self.__stock_rack_layouts = None #: The job indices for the buffer dilutions. self.__buffer_dilution_indices = None #: The merged stream for the buffer dilutions (printer mode only). self.__buffer_stream = None #: The source :class:`ReservoirSpecs` for the dilution jobs. self.__dilution_rs = get_reservoir_spec(self.DILUTION_RESERVOIR_SPECS)
def __get_reservoir_specs(self, rack_container): # Also records an error message if the spec has not been found. try: rs = get_reservoir_spec(rack_container.specs.lower()) except ValueError as ve: msg = 'Error when trying to fetch reservoir specs for rack "%s": ' \ '%s' % (rack_container.identifier, ve) self.add_error(msg) result = None else: result = rs return result
def _create_optimem_job(self, optimem_worklist): """ Helper function creating an optimem dilution job. """ quarter_rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.QUARTER_MODULAR) optimem_job = SampleDilutionJob(index=0, planned_worklist=optimem_worklist, target_rack=self._source_plate, reservoir_specs=quarter_rs, source_rack_barcode=self.OPTIMEM_PLATE_BARCODE, ignored_positions=self._ignored_positions) return optimem_job
def _create_reagent_job(self, reagent_worklist): """ Helper function creating an transfection reagent dilution job. """ tube_24_rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.TUBE_24) reagent_job = SampleDilutionJob(index=1, planned_worklist=reagent_worklist, target_rack=self._source_plate, reservoir_specs=tube_24_rs, source_rack_barcode=self.REAGENT_PLATE_BARCODE, ignored_positions=self._ignored_positions) return reagent_job
def _create_optimem_job(self, optimem_worklist): """ Helper function creating an optimem dilution job. """ quarter_rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.QUARTER_MODULAR) optimem_job = SampleDilutionJob( index=0, planned_worklist=optimem_worklist, target_rack=self._source_plate, reservoir_specs=quarter_rs, source_rack_barcode=self.OPTIMEM_PLATE_BARCODE, ignored_positions=self._ignored_positions) return optimem_job
def _create_reagent_job(self, reagent_worklist): """ Helper function creating an transfection reagent dilution job. """ tube_24_rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.TUBE_24) reagent_job = SampleDilutionJob( index=1, planned_worklist=reagent_worklist, target_rack=self._source_plate, reservoir_specs=tube_24_rs, source_rack_barcode=self.REAGENT_PLATE_BARCODE, ignored_positions=self._ignored_positions) return reagent_job
def __create_buffer_transfer_job(self): # Creates the transfer job for the buffer worklist. self.add_debug('Create buffer transfer jobs ...') worklist_series = self.entity.iso_request.worklist_series buffer_worklist = worklist_series.get_worklist_for_index( StockSampleCreationWorklistGenerator.BUFFER_WORKLIST_INDEX) rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.FALCON_MANUAL) job_index = len(self._transfer_jobs) cdj = SampleDilutionJob( index=job_index, planned_worklist=buffer_worklist, target_rack=self.__pool_stock_rack.rack, reservoir_specs=rs, source_rack_barcode=self.BUFFER_RESERVOIR_BARCODE, ignored_positions=self.__ignore_positions) self._transfer_jobs[job_index] = cdj
def get_dynamic_dead_volume(target_well_number, reservoir_specs=RESERVOIR_SPECS_NAMES.STANDARD_96): """ Calculate a dynamic dead volume (for pipetting specs that require dynamic dead volumes, such as Biomek). :param target_well_number: The number of target wells for the given source well. :type target_well_number: :class:` int` :param reservoir_specs: The reservoir specs you are assuming. :type reservoir_specs: a :class:`RESERVOIR_SPECS_NAMES` element or a :class:`thelma.entities.liquidtransfer.ReservoirSpecs` object :default reservoir_specs: RESERVOIR_SPECS_NAMES.STANDARD_96 :Note: At the moment corrections are only applied to plates. :raises TypeError: if resrevoir_specs is not a string or ReservoirSpecs :return: The adjusted dead volume in ul. """ if isinstance(reservoir_specs, ReservoirSpecs): rs = reservoir_specs elif isinstance(reservoir_specs, basestring): rs = get_reservoir_spec(reservoir_specs) else: msg = 'Unsupported type for reservoir specs: %s. Expectes string ' \ 'or ReservoirSpecs object.' % (reservoir_specs.__class__.__name__) raise TypeError(msg) # pylint: disable=E1103 min_dead_volume_ul = rs.min_dead_volume * VOLUME_CONVERSION_FACTOR max_dead_volume_ul = rs.max_dead_volume * VOLUME_CONVERSION_FACTOR # pylint: enable=E1103 if min_dead_volume_ul == max_dead_volume_ul: return min_dead_volume_ul if target_well_number <= LIMIT_TARGET_WELLS: return min_dead_volume_ul exceeding_well_count = target_well_number - LIMIT_TARGET_WELLS additional_volume = exceeding_well_count * DEAD_VOLUME_COEFFICIENT adjusted_dead_volume = min_dead_volume_ul + additional_volume if adjusted_dead_volume > max_dead_volume_ul: adjusted_dead_volume = max_dead_volume_ul return adjusted_dead_volume
def _add_cell_suspension_job(self, cell_worklist, job_index, plate, cell_ignored_positions): """ Helper function registering a container dilution job for the given worklist, plate and job index. In addition, in increments the job index. """ falcon_reservoir = get_reservoir_spec( RESERVOIR_SPECS_NAMES.FALCON_MANUAL) cell_job = SampleDilutionJob(index=job_index, planned_worklist=cell_worklist, target_rack=plate, reservoir_specs=falcon_reservoir, ignored_positions=cell_ignored_positions) self._transfer_jobs[job_index] = cell_job job_index += 1 return job_index
def __create_buffer_transfer_job(self): # Creates the transfer job for the buffer worklist. self.add_debug("Create buffer transfer jobs ...") worklist_series = self.entity.iso_request.worklist_series buffer_worklist = worklist_series.get_worklist_for_index( StockSampleCreationWorklistGenerator.BUFFER_WORKLIST_INDEX ) rs = get_reservoir_spec(RESERVOIR_SPECS_NAMES.FALCON_MANUAL) job_index = len(self._transfer_jobs) cdj = SampleDilutionJob( index=job_index, planned_worklist=buffer_worklist, target_rack=self.__pool_stock_rack.rack, reservoir_specs=rs, source_rack_barcode=self.BUFFER_RESERVOIR_BARCODE, ignored_positions=self.__ignore_positions, ) self._transfer_jobs[job_index] = cdj
def __init__(self, reagent_stream_content, parent=None): """ Constructor. :param str reagent_stream_content: The content of the reagent dilution worklist stream. """ CsvWriter.__init__(self, parent=parent) #: The content of the reagent dilution worklist stream. self.reagent_stream_content = reagent_stream_content #: The relevant data of the worklist (key: line index, values: #: tuple (source pos, dilution volume, diluent info) . self.__worklist_data = None #: The estimated dead volume in ul. self.__dead_volume = get_reservoir_spec(RESERVOIR_SPECS_NAMES.TUBE_24).\ max_dead_volume * VOLUME_CONVERSION_FACTOR #: Intermediate storage for the column values. self.__position_values = None self.__name_values = None self.__final_dil_factor_values = None self.__ini_dil_factor_values = None self.__total_volume_values = None self.__reagent_volume_values = None self.__diluent_volume_values = None