def _check_transfer_volume(self, transfer_volume, target_position, source_position=None): """ Checks whether the transfer volume is in a valid volume range, whether the target container can take that amount and whether there is enough volume in the source container. """ volume = transfer_volume * VOLUME_CONVERSION_FACTOR # Check the minimum and maximum transfer volume. if is_smaller_than(volume, self._min_transfer_volume): error_msg = 'target %s (%.1f ul)' \ % (target_position.label, volume) self._transfer_volume_too_small.append(error_msg) return False if self.TRANSFER_TYPE == TRANSFER_TYPES.SAMPLE_TRANSFER \ and is_larger_than(volume, self._max_transfer_volume): error_msg = 'source %s (%.1f ul)' % (source_position, volume) self._transfer_volume_too_large.append(error_msg) # Check whether there is enough space in the target well. max_volume = \ self.__get_max_volume_for_target_container(target_position) if max_volume is None: return False sample_volume = self._target_volumes[target_position] if is_smaller_than(max_volume, (sample_volume + volume)): error_msg = '%s (sample vol: %.1f, transfer vol: %.1f)' \ % (target_position, sample_volume, volume) self._target_volume_too_large.append(error_msg) return False # Check whether there is enough liquid in the source well if self.TRANSFER_TYPE == TRANSFER_TYPES.SAMPLE_DILUTION: return True if source_position is None: msg = 'You must not pass a None value for the source well ' \ 'when checking the volumes if you have passed a source ' \ 'rack!' self.add_error(msg) return False if not self._source_volumes.has_key(source_position): self._source_container_missing.add(source_position.label) return False source_volume = self._source_volumes[source_position] source_volume -= volume dead_volume = self.__get_dead_volume_for_source_container( source_position) if is_smaller_than(source_volume, dead_volume): self._source_volume_too_small.add(source_position.label) return False self._source_volumes[source_position] = source_volume return True
def __accept_tube_candidate(self, tube_candidate, conc_mismatch_list, insufficent_vol_map): """ A valid tube container must have a matching concentration, contain sufficent volume and must be excluded via the rack barcode. Accepted candidates are assigned to the referring containers. """ pool_id = tube_candidate.pool_id pool = self.__pool_map[pool_id] container = self.stock_tube_containers[pool] if not self.__stock_concentration_match(tube_candidate, container, conc_mismatch_list): return False required_vol = self.__volume_map[pool_id] + STOCK_DEAD_VOLUME if is_smaller_than(tube_candidate.volume, required_vol): params = [ tube_candidate.tube_barcode, get_trimmed_string(required_vol), get_trimmed_string(tube_candidate.volume) ] insufficent_vol_map[pool_id] = params return False if tube_candidate.rack_barcode in self.excluded_racks: add_list_map_element(self.__excluded_tubes, pool_id, tube_candidate.tube_barcode, as_set=True) return False else: tube_candidate.set_pool(container.pool) container.tube_candidate = tube_candidate return True
def __accept_tube_candidate(self, tube_candidate, conc_mismatch_list, insufficent_vol_map): """ A valid tube container must have a matching concentration, contain sufficent volume and must be excluded via the rack barcode. Accepted candidates are assigned to the referring containers. """ pool_id = tube_candidate.pool_id pool = self.__pool_map[pool_id] container = self.stock_tube_containers[pool] if not self.__stock_concentration_match(tube_candidate, container, conc_mismatch_list): return False required_vol = self.__volume_map[pool_id] + STOCK_DEAD_VOLUME if is_smaller_than(tube_candidate.volume, required_vol): params = [tube_candidate.tube_barcode, get_trimmed_string(required_vol), get_trimmed_string(tube_candidate.volume)] insufficent_vol_map[pool_id] = params return False if tube_candidate.rack_barcode in self.excluded_racks: add_list_map_element(self.__excluded_tubes, pool_id, tube_candidate.tube_barcode, as_set=True) return False else: tube_candidate.set_pool(container.pool) container.tube_candidate = tube_candidate return True
def __check_and_assign_tube_candidates(self): """ Checks whether there is pool for each requested pool and whether volume and concentration match. """ missing_pools = [] invalid_conc = [] invalid_vol = [] for pool, container in self._stock_tube_containers.iteritems(): if not self.__tube_candidates.has_key(pool): missing_pools.append(pool.id) continue candidate = self.__tube_candidates[pool] exp_stock_conc = pool.default_stock_concentration \ * CONCENTRATION_CONVERSION_FACTOR if not are_equal_values(candidate.concentration, exp_stock_conc): info = '%s (pool: %s, expected: %s nM, found: %s nM)' % ( candidate.tube_barcode, pool, get_trimmed_string(exp_stock_conc), get_trimmed_string(candidate.concentration)) invalid_conc.append(info) continue required_vol = STOCK_DEAD_VOLUME \ + container.get_total_required_volume() if is_smaller_than(candidate.volume, required_vol): info = '%s (pool: %s, required: %s ul, found: %s ul)' % ( candidate.tube_barcode, pool, get_trimmed_string(required_vol), get_trimmed_string(candidate.volume)) invalid_vol.append(info) continue container.tube_candidate = candidate if len(missing_pools) > 0: msg = 'Could not find tubes for the following pools: %s.' % ( self._get_joined_str(missing_pools, is_strs=False)) self.add_error(msg) if len(invalid_conc) > 0: msg = 'The concentrations in some tubes do not match the ' \ 'expected ones: %s.' % (self._get_joined_str(invalid_conc)) self.add_error(msg) if len(invalid_vol) > 0: msg = 'The volumes in some tubes (dead volume included) are not ' \ 'sufficient: %s.' % (self._get_joined_str(invalid_vol)) self.add_error(msg)