def __get_translation_map(self, sector_index): """ Returns the 96-well position corresponding to the position in a particular 384-well sector. """ positions = dict() translator = RackSectorTranslator(number_sectors=NUMBER_SECTORS, source_sector_index=sector_index, target_sector_index=0, enforce_type=RackSectorTranslator.MANY_TO_ONE) for rack_pos_96 in get_positions_for_shape(self.stock_rack_shape): rack_pos_384 = translator.translate(rack_pos_96) positions[rack_pos_96] = rack_pos_384 return positions
def __write_section(self): # Writes the section. self.add_debug('Write section ...') prst = self.rack_transfer_job.planned_rack_sample_transfer head_line = self.HEAD_LINE % (self.step_number) from_line = self.FROM_LINE % ( self.rack_transfer_job.source_rack.barcode) to_line = self.TO_LINE % (self.rack_transfer_job.target_rack.barcode) volume_line = self.VOLUME_LINE % (prst.volume \ * VOLUME_CONVERSION_FACTOR) translation_type = RackSectorTranslator.get_translation_behaviour( source_shape=self.rack_transfer_job.source_rack.rack_shape, target_shape=self.rack_transfer_job.target_rack.rack_shape, number_sectors=prst.number_sectors) if prst.number_sectors > 1: if not translation_type == RackSectorTranslator.MANY_TO_ONE: src_addition = self.SECTOR_ADDITION \ % (prst.source_sector_index + 1) from_line += src_addition if not translation_type == RackSectorTranslator.ONE_TO_MANY: trg_addition = self.SECTOR_ADDITION \ % (prst.target_sector_index + 1) to_line += trg_addition paragraph = head_line + (2 * LINEBREAK_CHAR) paragraph += (from_line + LINEBREAK_CHAR) paragraph += (to_line + LINEBREAK_CHAR) paragraph += (volume_line + LINEBREAK_CHAR) paragraph += (2 * LINEBREAK_CHAR) # spacer return paragraph
def __get_translation_map(self, sector_index): """ Returns the 96-well position corresponding to the position in a particular 384-well sector. """ positions = dict() translator = RackSectorTranslator( number_sectors=NUMBER_SECTORS, source_sector_index=sector_index, target_sector_index=0, enforce_type=RackSectorTranslator.MANY_TO_ONE) for rack_pos_96 in get_positions_for_shape(self.stock_rack_shape): rack_pos_384 = translator.translate(rack_pos_96) positions[rack_pos_96] = rack_pos_384 return positions
def __write_section(self): # Writes the section. self.add_debug('Write section ...') prst = self.rack_transfer_job.planned_rack_sample_transfer head_line = self.HEAD_LINE % (self.step_number) from_line = self.FROM_LINE % (self.rack_transfer_job.source_rack.barcode) to_line = self.TO_LINE % (self.rack_transfer_job.target_rack.barcode) volume_line = self.VOLUME_LINE % (prst.volume \ * VOLUME_CONVERSION_FACTOR) translation_type = RackSectorTranslator.get_translation_behaviour( source_shape=self.rack_transfer_job.source_rack.rack_shape, target_shape=self.rack_transfer_job.target_rack.rack_shape, number_sectors=prst.number_sectors) if prst.number_sectors > 1: if not translation_type == RackSectorTranslator.MANY_TO_ONE: src_addition = self.SECTOR_ADDITION \ % (prst.source_sector_index + 1) from_line += src_addition if not translation_type == RackSectorTranslator.ONE_TO_MANY: trg_addition = self.SECTOR_ADDITION \ % (prst.target_sector_index + 1) to_line += trg_addition paragraph = head_line + (2 * LINEBREAK_CHAR) paragraph += (from_line + LINEBREAK_CHAR) paragraph += (to_line + LINEBREAK_CHAR) paragraph += (volume_line + LINEBREAK_CHAR) paragraph += (2 * LINEBREAK_CHAR) # spacer return paragraph
def __check_pool_stock_racks(self): # Ensures that the new pool tube racks have tubes in the expected # positions using the layout of the sector preparation plates. Also # builds a map sector index -> pool stock rack barcode. self.add_debug('Checking new pool tube racks.') pool_stock_rack_map = {} for ispp in self.iso.iso_sector_preparation_plates: trl = RackSectorTranslator( 4, ispp.sector_index, 0, behaviour=RackSectorTranslator.MANY_TO_ONE) exp_poss = ispp.rack_layout.get_positions() pool_stock_rack_bc = self.pool_stock_racks[ispp.sector_index] pool_stock_rack_map[ispp.sector_index] = pool_stock_rack_bc new_tube_rack = self.__tube_rack_map[pool_stock_rack_bc] tube_map = dict([(trl.translate(t.location.position), t) for t in new_tube_rack.containers]) missing_poss = set(exp_poss).difference(tube_map.keys()) if len(missing_poss) > 0: msg = 'There are some tubes missing in the new stock rack ' \ 'for sector %i (%s): %s.' \ % (ispp.sector_index, new_tube_rack.barcode, ', '.join(sorted([p.label for p in missing_poss]))) self.add_error(msg) extra_poss = set(tube_map.keys()).difference(exp_poss) if len(extra_poss) > 0: msg = 'There are some empty tubes in the new stock rack ' \ 'for sector %i in positions which should be empty: ' \ ' %s. ' \ % (ispp.sector_index, ', '.join(sorted([p.label for p in extra_poss]))) self.add_warning(msg) not_empty = [ t.location.position for t in tube_map.values() if not t.sample is None and t.sample.volume > 0 ] if len(not_empty) > 0: msg = 'Some tubes in the new stock rack for sector %i are ' \ 'not empty: %s.' \ % (ispp.sector_index, ', '.join([p.label for p in not_empty])) self.add_error(msg) return pool_stock_rack_map
def __init_translators(self): # The translators are used to determine the rack position holding # the pool information. for sector_index, issr in self.sample_stock_racks.iteritems(): barcode = issr.rack.barcode translator = RackSectorTranslator(number_sectors=NUMBER_SECTORS, source_sector_index=0, target_sector_index=sector_index, enforce_type=RackSectorTranslator.MANY_TO_ONE) self.__translators[barcode] = translator
def __check_pool_stock_racks(self): # Ensures that the new pool tube racks have tubes in the expected # positions using the layout of the sector preparation plates. Also # builds a map sector index -> pool stock rack barcode. self.add_debug('Checking new pool tube racks.') pool_stock_rack_map = {} for ispp in self.iso.iso_sector_preparation_plates: trl = RackSectorTranslator(4, ispp.sector_index, 0, behaviour= RackSectorTranslator.MANY_TO_ONE) exp_poss = ispp.rack_layout.get_positions() pool_stock_rack_bc = self.pool_stock_racks[ispp.sector_index] pool_stock_rack_map[ispp.sector_index] = pool_stock_rack_bc new_tube_rack = self.__tube_rack_map[pool_stock_rack_bc] tube_map = dict([(trl.translate(t.location.position), t) for t in new_tube_rack.containers]) missing_poss = set(exp_poss).difference(tube_map.keys()) if len(missing_poss) > 0: msg = 'There are some tubes missing in the new stock rack ' \ 'for sector %i (%s): %s.' \ % (ispp.sector_index, new_tube_rack.barcode, ', '.join(sorted([p.label for p in missing_poss]))) self.add_error(msg) extra_poss = set(tube_map.keys()).difference(exp_poss) if len(extra_poss) > 0: msg = 'There are some empty tubes in the new stock rack ' \ 'for sector %i in positions which should be empty: ' \ ' %s. ' \ % (ispp.sector_index, ', '.join(sorted([p.label for p in extra_poss]))) self.add_warning(msg) not_empty = [t.location.position for t in tube_map.values() if not t.sample is None and t.sample.volume > 0] if len(not_empty) > 0: msg = 'Some tubes in the new stock rack for sector %i are ' \ 'not empty: %s.' \ % (ispp.sector_index, ', '.join([p.label for p in not_empty])) self.add_error(msg) return pool_stock_rack_map
def __find_ignored_sector_positions(self, ignore_positions_384): """ Converts the position in the ignored position list for the 384-well layout into 96-well position. Positions for sectors that are not required (might be the case on the last plate) are not checked. """ for sector_index in range(NUMBER_SECTORS): if not self.__library_sectors.has_key(sector_index): continue sector_positions = get_sector_positions(sector_index=sector_index, rack_shape=get_384_rack_shape(), number_sectors=NUMBER_SECTORS) translator = RackSectorTranslator(number_sectors=NUMBER_SECTORS, source_sector_index=sector_index, target_sector_index=0, enforce_type=RackSectorTranslator.ONE_TO_MANY) for sector_pos in sector_positions: if sector_pos in ignore_positions_384: rack_pos_96 = translator.translate(sector_pos) self.__ignore_positions_96[sector_index].append(rack_pos_96)
def __create_buffer_worklist(self, quadrant_layout, buffer_volume, label, sector_index): # Creates buffer dilutions worklist for a particular quadrant # and adds it to the worklist series. volume = buffer_volume / VOLUME_CONVERSION_FACTOR planned_transfers = [] translator = RackSectorTranslator( number_sectors=NUMBER_SECTORS, source_sector_index=sector_index, target_sector_index=0, enforce_type=RackSectorTranslator.ONE_TO_MANY) for rack_pos_384 in quadrant_layout.get_positions(): rack_pos_96 = translator.translate(rack_pos_384) planned_transfer = PlannedSampleDilution.get_entity( volume, self.DILUTION_INFO, rack_pos_96) planned_transfers.append(planned_transfer) worklist = PlannedWorklist(label=label, planned_transfers=planned_transfers) self.__last_worklist_index += 1 self.__worklist_series.add_worklist(self.__last_worklist_index, worklist)
def __find_ignored_sector_positions(self, ignore_positions_384): """ Converts the position in the ignored position list for the 384-well layout into 96-well position. Positions for sectors that are not required (might be the case on the last plate) are not checked. """ for sector_index in range(NUMBER_SECTORS): if not self.__library_sectors.has_key(sector_index): continue sector_positions = get_sector_positions( sector_index=sector_index, rack_shape=get_384_rack_shape(), number_sectors=NUMBER_SECTORS) translator = RackSectorTranslator( number_sectors=NUMBER_SECTORS, source_sector_index=sector_index, target_sector_index=0, enforce_type=RackSectorTranslator.ONE_TO_MANY) for sector_pos in sector_positions: if sector_pos in ignore_positions_384: rack_pos_96 = translator.translate(sector_pos) self.__ignore_positions_96[sector_index].append( rack_pos_96)
def __get_expected_stock_rack_position(self, plate_layout, sector_positions): """ There can only be one positions, because otherwise the positions do not match the sectors. """ stock_rack_positions = set() ref_sectors = set() for sector_index, positions in sector_positions.iteritems(): ref_sectors.add(sector_index) if plate_layout.shape.name == RACK_SHAPE_NAMES.SHAPE_96: for plate_pos in positions: stock_rack_positions.add(plate_pos.rack_position) else: if self.__ssc_layout_map.has_key(sector_index): translator = self.__ssc_layout_map[sector_index] else: translator = RackSectorTranslator(number_sectors=4, source_sector_index=sector_index, target_sector_index=0, behaviour=RackSectorTranslator.ONE_TO_MANY) self.__ssc_layout_map[sector_index] = translator for plate_pos in positions: base_msg = 'Error when trying to determine stock rack ' \ 'position for position %s:' \ % (plate_pos.rack_position.label) trans_pos = self._run_and_record_error(translator.translate, base_msg, ValueError, **dict(rack_position=plate_pos.rack_position)) if trans_pos is None: return None stock_rack_positions.add(trans_pos) if len(stock_rack_positions) > 1: return None return (list(stock_rack_positions)[0], min(ref_sectors))