Beispiel #1
0
    def __get_rack_labels(self, rack_specifier):
        """
        Gets the rack labels for a verified rack specifier.
        """
        rack_labels = []
        tokens = rack_specifier[rack_specifier.find(" ") + 1 :].split(",")
        for token in tokens:
            token = token.strip()
            if len(token) < 1:
                continue
            if "-" in token:
                start, stop = token.split("-")
                try:
                    # only number-specified racks might be specified in ranges
                    rack_nums = range(int(start), int(stop) + 1)
                    if len(rack_nums) < 1:
                        msg = 'Unable to parse rack range "%s".' % (token)
                        self._create_error(msg)
                    else:
                        for rack_num in rack_nums:
                            rack_labels.append(get_trimmed_string(rack_num))
                except ValueError:
                    msg = 'Invalid range "%s" in racks ' 'specifier "%s".' % (token, rack_specifier)
                    self._create_error(msg)
                    return None
            else:
                rack_labels.append(get_trimmed_string(token))
                # without out a range it can be a rack_numer (int) or a barcode

        if len(rack_labels) < 1:
            return None
        return rack_labels
Beispiel #2
0
    def _create_worklist_series(self):
        """
        Generates all the buffer dilution worklists (as series).
        The worklists for the transfer from 1-molecule-design stock rack to
        pool stock rack are not included but stored at the ISO sample
        stock racks to enable quadrant tracking.
        """
        self.add_debug('Create worklist series ...')

        volume_calculator = \
          VolumeCalculator(self.target_volume, self.target_concentration,
                           self.__number_designs, self.__stock_concentration)
        generator = StockSampleCreationWorklistGenerator(
                                    volume_calculator, self.iso_request_label,
                                    parent=self)
        self.__worklist_series = generator.get_result()
        if self.__worklist_series is None:
            msg = 'Error when trying to generate worklist series.'
            self.add_error(msg)
        else:
            self.__adj_target_volume = \
                                volume_calculator.get_adjusted_target_volume()
            if not self.__adj_target_volume is None:
                robot_specs = get_pipetting_specs_cybio()
                msg = 'The target volume you have requested needs to be ' \
                      'increased slightly because of the constraints of the ' \
                      'pipetting robot (%s, min. transfer volume: %s ul, ' \
                      'step size: 0.1 ul). The target volume will be ' \
                      'increased from %s ul to %s ul.' \
                      % (robot_specs.name,
                         get_trimmed_string(robot_specs.min_transfer_volume \
                                            * VOLUME_CONVERSION_FACTOR),
                         get_trimmed_string(self.target_volume),
                         get_trimmed_string(self.__adj_target_volume))
                self.add_warning(msg)
Beispiel #3
0
 def __write_general_section(self):
     # Volume, concentration, dilution factors, etc.
     header = self.GENERAL_TITLE % (self.generator.return_value.label)
     self._write_headline(header, preceding_blank_lines=0,
                          trailing_blank_lines=1)
     general_lines = []
     if self.__support_mastermix:
         robot_support = 'yes'
     else:
         robot_support = 'no'
     general_lines.append(self.SUPPORTS_MASTERMIX_LINE % robot_support)
     general_lines.append(self.LIBRARY_LINE % (self.__library.label))
     iso_vol = self.__library.final_volume * VOLUME_CONVERSION_FACTOR
     general_lines.append(self.ISO_VOLUME_LINE % (get_trimmed_string(
                                                             iso_vol)))
     self.__iso_conc = self.__library.final_concentration \
                       * CONCENTRATION_CONVERSION_FACTOR
     general_lines.append(self.ISO_CONCENTRATION_LINE \
                          % get_trimmed_string(self.__iso_conc))
     parameters = TransfectionParameters
     self.__final_conc = self.__parameter_values[
                                             parameters.FINAL_CONCENTRATION]
     general_lines.append(self.FINAL_CONCENTRATION_LINE % (
                                     get_trimmed_string(self.__final_conc)))
     odf = self.__parameter_values[parameters.OPTIMEM_DIL_FACTOR]
     general_lines.append(self.ODF_LINE % (get_trimmed_string(odf)))
     reagent_name = self.__parameter_values[parameters.REAGENT_NAME]
     general_lines.append(self.REAGENT_NAME_LINE % (reagent_name))
     reagent_df = self.__parameter_values[parameters.REAGENT_DIL_FACTOR]
     general_lines.append(self.REAGENT_DF_LINE % (
                                             get_trimmed_string(reagent_df)))
     self._write_body_lines(general_lines)
Beispiel #4
0
 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
Beispiel #5
0
    def __get_rack_labels(self, rack_specifier):
        """
        Gets the rack labels for a verified rack specifier.
        """
        rack_labels = []
        tokens = rack_specifier[rack_specifier.find(' ') + 1:].split(',')
        for token in tokens:
            token = token.strip()
            if len(token) < 1: continue
            if '-' in token:
                start, stop = token.split('-')
                try:
                    # only number-specified racks might be specified in ranges
                    rack_nums = range(int(start), int(stop) + 1)
                    if len(rack_nums) < 1:
                        msg = 'Unable to parse rack range "%s".' % (token)
                        self._create_error(msg)
                    else:
                        for rack_num in rack_nums:
                            rack_labels.append(get_trimmed_string(rack_num))
                except ValueError:
                    msg = 'Invalid range "%s" in racks ' \
                          'specifier "%s".' % (token, rack_specifier)
                    self._create_error(msg)
                    return None
            else:
                rack_labels.append(get_trimmed_string(token))
                # without out a range it can be a rack_numer (int) or a barcode

        if len(rack_labels) < 1: return None
        return rack_labels
Beispiel #6
0
    def _create_worklist_series(self):
        """
        Generates all the buffer dilution worklists (as series).
        The worklists for the transfer from 1-molecule-design stock rack to
        pool stock rack are not included but stored at the ISO sample
        stock racks to enable quadrant tracking.
        """
        self.add_debug('Create worklist series ...')

        volume_calculator = \
          VolumeCalculator(self.target_volume, self.target_concentration,
                           self.__number_designs, self.__stock_concentration)
        generator = StockSampleCreationWorklistGenerator(
            volume_calculator, self.iso_request_label, parent=self)
        self.__worklist_series = generator.get_result()
        if self.__worklist_series is None:
            msg = 'Error when trying to generate worklist series.'
            self.add_error(msg)
        else:
            self.__adj_target_volume = \
                                volume_calculator.get_adjusted_target_volume()
            if not self.__adj_target_volume is None:
                robot_specs = get_pipetting_specs_cybio()
                msg = 'The target volume you have requested needs to be ' \
                      'increased slightly because of the constraints of the ' \
                      'pipetting robot (%s, min. transfer volume: %s ul, ' \
                      'step size: 0.1 ul). The target volume will be ' \
                      'increased from %s ul to %s ul.' \
                      % (robot_specs.name,
                         get_trimmed_string(robot_specs.min_transfer_volume \
                                            * VOLUME_CONVERSION_FACTOR),
                         get_trimmed_string(self.target_volume),
                         get_trimmed_string(self.__adj_target_volume))
                self.add_warning(msg)
Beispiel #7
0
    def __store_line_value(self, dil_info, total_vol, pos_label):
        """
        Stores the values for one line.
        """

        dil_info = dil_info.strip()
        info_tokens = dil_info.split(' (')
        final_dil_factor = float(info_tokens[1][:-1])
        initial_dil_factor = TransfectionParameters.\
                            calculate_initial_reagent_dilution(final_dil_factor)

        reagent_vol = round_up((total_vol / initial_dil_factor))
        total_vol = reagent_vol * initial_dil_factor
        total_vol = round(total_vol, 1)
        diluent_vol = total_vol - reagent_vol
        initial_dil_factor = round(initial_dil_factor, 1)

        self.__position_values.append(pos_label)
        self.__name_values.append(info_tokens[0])
        self.__final_dil_factor_values.append(
                                        get_trimmed_string(final_dil_factor))
        self.__ini_dil_factor_values.append(
                                        get_trimmed_string(initial_dil_factor))
        self.__total_volume_values.append(get_trimmed_string(total_vol))
        self.__reagent_volume_values.append(get_trimmed_string(reagent_vol))
        self.__diluent_volume_values.append(get_trimmed_string(diluent_vol))
Beispiel #8
0
    def __store_line_value(self, dil_info, total_vol, pos_label):
        """
        Stores the values for one line.
        """

        dil_info = dil_info.strip()
        info_tokens = dil_info.split(' (')
        final_dil_factor = float(info_tokens[1][:-1])
        initial_dil_factor = TransfectionParameters.\
                            calculate_initial_reagent_dilution(final_dil_factor)

        reagent_vol = round_up((total_vol / initial_dil_factor))
        total_vol = reagent_vol * initial_dil_factor
        total_vol = round(total_vol, 1)
        diluent_vol = total_vol - reagent_vol
        initial_dil_factor = round(initial_dil_factor, 1)

        self.__position_values.append(pos_label)
        self.__name_values.append(info_tokens[0])
        self.__final_dil_factor_values.append(
            get_trimmed_string(final_dil_factor))
        self.__ini_dil_factor_values.append(
            get_trimmed_string(initial_dil_factor))
        self.__total_volume_values.append(get_trimmed_string(total_vol))
        self.__reagent_volume_values.append(get_trimmed_string(reagent_vol))
        self.__diluent_volume_values.append(get_trimmed_string(diluent_vol))
Beispiel #9
0
 def __write_general_section(self):
     # Volume, concentration, dilution factors, etc.
     header = self.GENERAL_TITLE % (self.generator.return_value.label)
     self._write_headline(header,
                          preceding_blank_lines=0,
                          trailing_blank_lines=1)
     general_lines = []
     if self.__support_mastermix:
         robot_support = 'yes'
     else:
         robot_support = 'no'
     general_lines.append(self.SUPPORTS_MASTERMIX_LINE % robot_support)
     general_lines.append(self.LIBRARY_LINE % (self.__library.label))
     iso_vol = self.__library.final_volume * VOLUME_CONVERSION_FACTOR
     general_lines.append(self.ISO_VOLUME_LINE %
                          (get_trimmed_string(iso_vol)))
     self.__iso_conc = self.__library.final_concentration \
                       * CONCENTRATION_CONVERSION_FACTOR
     general_lines.append(self.ISO_CONCENTRATION_LINE \
                          % get_trimmed_string(self.__iso_conc))
     parameters = TransfectionParameters
     self.__final_conc = self.__parameter_values[
         parameters.FINAL_CONCENTRATION]
     general_lines.append(self.FINAL_CONCENTRATION_LINE %
                          (get_trimmed_string(self.__final_conc)))
     odf = self.__parameter_values[parameters.OPTIMEM_DIL_FACTOR]
     general_lines.append(self.ODF_LINE % (get_trimmed_string(odf)))
     reagent_name = self.__parameter_values[parameters.REAGENT_NAME]
     general_lines.append(self.REAGENT_NAME_LINE % (reagent_name))
     reagent_df = self.__parameter_values[parameters.REAGENT_DIL_FACTOR]
     general_lines.append(self.REAGENT_DF_LINE %
                          (get_trimmed_string(reagent_df)))
     self._write_body_lines(general_lines)
Beispiel #10
0
 def __write_formula_section(self):
     # Writes the formula for the determination of the OptiMem dilution
     # factor.
     self._write_headline(self.ODF_TITLE)
     formula = self.ODF_FORMULA % (get_trimmed_string(self.__iso_conc),
                         get_trimmed_string(self.__final_conc),
                         TransfectionParameters.REAGENT_MM_DILUTION_FACTOR,
                         TransfectionParameters.CELL_DILUTION_FACTOR)
     self._stream.write(formula)
Beispiel #11
0
 def __write_formula_section(self):
     # Writes the formula for the determination of the OptiMem dilution
     # factor.
     self._write_headline(self.ODF_TITLE)
     formula = self.ODF_FORMULA % (
         get_trimmed_string(
             self.__iso_conc), get_trimmed_string(self.__final_conc),
         TransfectionParameters.REAGENT_MM_DILUTION_FACTOR,
         TransfectionParameters.CELL_DILUTION_FACTOR)
     self._stream.write(formula)
Beispiel #12
0
    def __store_column_values(self):
        # Store the values for the columns.
        self.add_debug('Store values ...')
        source_rack_map = dict()
        for ew in self.executed_worklists:
            for elt in ew:
                source_rack_barcode = elt.source_container.rack.barcode
                add_list_map_element(source_rack_map, source_rack_barcode, elt)
        well_containers = dict()
        missing_layouts = []
        sorted_elts = dict()
        for source_rack_barcode in sorted(source_rack_map.keys()):
            executed_transfers = source_rack_map[source_rack_barcode]
            if not self.stock_rack_data.has_key(source_rack_barcode):
                missing_layouts.append(source_rack_barcode)
                continue
            layout = self.stock_rack_data[source_rack_barcode]
            pool_map = self.__get_sorted_executed_transfers(
                executed_transfers, layout, source_rack_barcode)
            if self.has_errors(): break
            for pool_id, elts in pool_map.iteritems():
                sorted_elts[pool_id] = elts
        for pool_id in sorted(sorted_elts.keys()):
            elts = sorted_elts[pool_id]
            for elt in elts:
                self.__pool_values.append(get_trimmed_string(pool_id))
                source_container = elt.source_container
                plt = elt.planned_liquid_transfer
                if not isinstance(source_container, Tube):
                    pos_label = plt.source_position.label
                    add_list_map_element(well_containers,
                                         source_container.rack.barcode,
                                         pos_label)
                    continue
                self.__tube_barcode_values.append(source_container.barcode)
                volume = plt.volume * VOLUME_CONVERSION_FACTOR
                self.__volume_values.append(get_trimmed_string(volume))
                self.__trg_rack_barcode_values.append(
                    elt.target_container.rack.barcode)
                self.__trg_position_values.append(plt.target_position.label)

        if len(well_containers) > 0:
            msg = 'Some source containers in the worklists are wells: %s!' \
                   % (self._get_joined_map_str(well_containers,
                                               'plate %s (positions %s)'))
            self.add_error(msg)
        if len(missing_layouts) > 0:
            msg = 'Unable to find the layouts for the following stock ' \
                  'racks: %s.' % (self._get_joined_str(missing_layouts))
            self.add_error(msg)
Beispiel #13
0
    def hash_full(self):
        """
        A string that can be used as hash value for comparison. This hash
        covers all four parameters (molecule design pool, reagent name, reagent
        concentration and final concentration) needed to make well
        associations.
        """
        if self.is_empty: return '%s' % (self.rack_position)

        fc = self.final_concentration
        if self.is_mock: fc = None
        return '%s%s%s%s' % (self.molecule_design_pool_id, self.reagent_name,
                             get_trimmed_string(self.reagent_dil_factor),
                             get_trimmed_string(fc))
Beispiel #14
0
    def __store_column_values(self):
        # Store the values for the columns.
        self.add_debug('Store values ...')
        target_rack_map = dict()
        for ew in self.executed_worklists.values():
            for et in ew.executed_transfers:
                target_rack_barcode = et.target_container.location.rack.barcode
                if not target_rack_map.has_key(target_rack_barcode):
                    target_rack_map[target_rack_barcode] = []
                target_rack_map[target_rack_barcode].append(et)
        barcodes = sorted(target_rack_map.keys())
        well_containers = set()
        for target_rack_barcode in barcodes:
            non_single_md_src_pool = []
            executed_transfers = target_rack_map[target_rack_barcode]
            pool_map = self.__get_sorted_executed_transfers(executed_transfers,
                                                            target_rack_barcode)
            if self.has_errors(): break
            pools = sorted(pool_map.keys(), cmp=lambda p1, p2:
                                            cmp(p1.id, p2.id))
            for pool in pools:
                ets = pool_map[pool]
                for et in ets:
                    self.__lib_pool_values.append(get_trimmed_string(pool.id))
                    volume = et.planned_transfer.volume \
                                                    * VOLUME_CONVERSION_FACTOR
                    self.__volume_values.append(get_trimmed_string(volume))
                    self.__trg_rack_barcode_values.append(target_rack_barcode)
                    trg_label = et.planned_transfer.target_position.label
                    self.__trg_position_values.append(trg_label)

                    src_tube = et.source_container
                    self.__tube_barcode_values.append(src_tube.barcode)
                    md_id = self.__get_molecule_design_id(src_tube)
                    if md_id is None:
                        info = '%s (rack %s)' % (src_tube.barcode,
                                                 target_rack_barcode)
                        non_single_md_src_pool.append(info)
                    else:
                        self.__md_values.append(get_trimmed_string(md_id))
            if len(non_single_md_src_pool) > 0:
                msg = 'Some source container contain more than one ' \
                      'molecule design: %s.' % (sorted(non_single_md_src_pool))
                self.add_error(msg)
        if len(well_containers) > 0:
            well_container_list = list(well_containers)
            well_container_list.sort()
            msg = 'Some source containers in the worklists are wells: %s!' \
                   % (well_container_list)
            self.add_error(msg)
Beispiel #15
0
    def hash_full(self):
        """
        A string that can be used as hash value for comparison. This hash
        covers all four parameters (molecule design pool, reagent name, reagent
        concentration and final concentration) needed to make well
        associations.
        """
        if self.is_empty: return '%s' % (self.rack_position)

        fc = self.final_concentration
        if self.is_mock: fc = None
        return '%s%s%s%s' % (self.molecule_design_pool_id,
                             self.reagent_name,
                             get_trimmed_string(self.reagent_dil_factor),
                             get_trimmed_string(fc))
Beispiel #16
0
    def __calculate_single_stock_transfer_volume(self):
        # Determines the volume that has to be transferred from a single design
        # stock tube to a future pool stock tube (for the given volume,
        # concentration, and number of designs). The target volume might
        # be increased if the resulting single design transfer volume has
        # more than 1 decimal place.
        # :raises ValueErrors: if something the values are not compatible
        target_single_conc = float(self.__target_concentration) \
                             / self.__number_designs
        if target_single_conc > self.__stock_concentration:
            msg = 'The requested target concentration (%i nM) cannot be ' \
                  'achieved since it would require a concentration of %s nM ' \
                  'for each single design in the pool. However, the stock ' \
                  'concentration for this design type is only %s nM.' \
                  % (self.__target_concentration,
                     get_trimmed_string(target_single_conc),
                     get_trimmed_string(self.__stock_concentration))
            raise ValueError(msg)
        dil_factor = self.__stock_concentration / target_single_conc
        min_target_volume = round_up(dil_factor *
                                     self.__min_cybio_transfer_vol)
        if (min_target_volume > self.__target_volume):
            msg = 'The target volume you have requested (%i ul) is too low ' \
                  'for the required dilution (1:%s) since the CyBio cannot ' \
                  'pipet less than %.1f ul per transfer. The volume that has ' \
                  'to be taken from the stock for each single molecule ' \
                  'design would be lower that that. Increase the target ' \
                  'volume to %.1f ul or increase the target concentration.' \
                  % (self.__target_volume, get_trimmed_string(dil_factor),
                     self.__min_cybio_transfer_vol,
                     round_up(min_target_volume, 0))
            raise ValueError(msg)
        self.__stock_transfer_vol = round_up(self.__target_volume / dil_factor)
        self.__adjusted_target_vol = round(
            self.__stock_transfer_vol * dil_factor, 1)

        # must be at least 1 ul according to the last check
        total_transfer_vol = self.__stock_transfer_vol * self.__number_designs
        if total_transfer_vol > self.__target_volume:
            msg = 'The target volume you have requested (%i ul) is too low ' \
                  'for the concentration you have ordered (%i uM) since it ' \
                  'would require already %s ul per molecule design (%s ul in ' \
                  'total) to achieve the requested concentration. Increase ' \
                  'the volume or lower the concentration, please.' \
                  % (self.__target_volume, self.__target_concentration,
                     get_trimmed_string(self.__stock_transfer_vol),
                     get_trimmed_string(total_transfer_vol))
            raise ValueError(msg)
Beispiel #17
0
    def __store_column_values(self):
        # Store the values for the columns.
        self.add_debug("Store values ...")
        source_rack_map = dict()
        for ew in self.executed_worklists:
            for elt in ew:
                source_rack_barcode = elt.source_container.rack.barcode
                add_list_map_element(source_rack_map, source_rack_barcode, elt)
        well_containers = dict()
        missing_layouts = []
        sorted_elts = dict()
        for source_rack_barcode in sorted(source_rack_map.keys()):
            executed_transfers = source_rack_map[source_rack_barcode]
            if not self.stock_rack_data.has_key(source_rack_barcode):
                missing_layouts.append(source_rack_barcode)
                continue
            layout = self.stock_rack_data[source_rack_barcode]
            pool_map = self.__get_sorted_executed_transfers(executed_transfers, layout, source_rack_barcode)
            if self.has_errors():
                break
            for pool_id, elts in pool_map.iteritems():
                sorted_elts[pool_id] = elts
        for pool_id in sorted(sorted_elts.keys()):
            elts = sorted_elts[pool_id]
            for elt in elts:
                self.__pool_values.append(get_trimmed_string(pool_id))
                source_container = elt.source_container
                plt = elt.planned_liquid_transfer
                if not isinstance(source_container, Tube):
                    pos_label = plt.source_position.label
                    add_list_map_element(well_containers, source_container.rack.barcode, pos_label)
                    continue
                self.__tube_barcode_values.append(source_container.barcode)
                volume = plt.volume * VOLUME_CONVERSION_FACTOR
                self.__volume_values.append(get_trimmed_string(volume))
                self.__trg_rack_barcode_values.append(elt.target_container.rack.barcode)
                self.__trg_position_values.append(plt.target_position.label)

        if len(well_containers) > 0:
            msg = "Some source containers in the worklists are wells: %s!" % (
                self._get_joined_map_str(well_containers, "plate %s (positions %s)")
            )
            self.add_error(msg)
        if len(missing_layouts) > 0:
            msg = "Unable to find the layouts for the following stock " "racks: %s." % (
                self._get_joined_str(missing_layouts)
            )
            self.add_error(msg)
Beispiel #18
0
    def _get_joined_str(self,
                        item_list,
                        is_strs=True,
                        sort_items=True,
                        separator=', '):
        """
        Helper method converting the passed list into a joined string, separated
        by comma (default). By default, the elements are sorted before
        conversion. This is handy i.e. when printing error messages.

        :param item_list: The recorded events in a list.
        :type item_list: :class:`list` or iterable that can be converted into
            a list.
        :param bool is_strs: If not the items must be converted first.
            Without conversion the join method will raise an error.
        :default is_strs: *True*
        :param bool sort_items: Shall the items be sorted?
        :default sort_items: *True*
        :param str separator: The string to use for the joining.
        :default separator: Comma and 1 space.
        """
        if not isinstance(item_list, list):
            item_list = list(item_list)
        if sort_items: item_list.sort()
        if is_strs:
            item_strs = item_list
        else:
            item_strs = [get_trimmed_string(item) for item in item_list]
        return separator.join(item_strs)
Beispiel #19
0
 def __stock_concentration_match(self, candidate, container, error_list):
     """
     Makes sure tube candidate and stock tube container expect the same
     stock concentration.
     """
     container_conc = container.get_stock_concentration()
     candidate_conc = candidate.concentration
     if not are_equal_values(container_conc, candidate_conc):
         info = '%s (pool: %i, expected: %s nM, found at tube: %s nM)' \
                % (candidate.tube_barcode, candidate.pool_id,
                   get_trimmed_string(container_conc),
                   get_trimmed_string(candidate_conc))
         error_list.append(info)
         return False
     else:
         return True
Beispiel #20
0
 def _create_planned_liquid_transfers(self):
     """
     Generates the planned container dilutions for the worklist.
     """
     self.add_debug('Generate planned container dilutions ...')
     invalid_dil_factor = dict()
     for rack_pos, tf_pos in self.transfection_layout.iterpositions():
         if tf_pos.is_empty:
             continue
         dil_volume = tf_pos.calculate_reagent_dilution_volume() \
                      / VOLUME_CONVERSION_FACTOR
         ini_dil_factor = TransfectionParameters.\
                             calculate_initial_reagent_dilution(
                             float(tf_pos.reagent_dil_factor))
         if ini_dil_factor <= 1:
             add_list_map_element(invalid_dil_factor,
                                  tf_pos.reagent_dil_factor, rack_pos.label)
             continue
         rdf_str = get_trimmed_string(tf_pos.reagent_dil_factor)
         diluent_info = '%s (%s)' % (tf_pos.reagent_name, rdf_str)
         psd = PlannedSampleDilution.get_entity(volume=dil_volume,
                                                target_position=rack_pos,
                                                diluent_info=diluent_info)
         self._add_planned_transfer(psd)
     if len(invalid_dil_factor) > 0:
         msg = 'Invalid dilution reagent factor for rack positions: %s. ' \
               'The factor would result in an initial dilution factor of ' \
               'less then 1!' % (self._get_joined_map_str(invalid_dil_factor))
         self.add_error(msg)
Beispiel #21
0
 def __stock_concentration_match(self, candidate, container, error_list):
     """
     Makes sure tube candidate and stock tube container expect the same
     stock concentration.
     """
     container_conc = container.get_stock_concentration()
     candidate_conc = candidate.concentration
     if not are_equal_values(container_conc, candidate_conc):
         info = '%s (pool: %i, expected: %s nM, found at tube: %s nM)' \
                % (candidate.tube_barcode, candidate.pool_id,
                   get_trimmed_string(container_conc),
                   get_trimmed_string(candidate_conc))
         error_list.append(info)
         return False
     else:
         return True
Beispiel #22
0
 def _create_planned_liquid_transfers(self):
     """
     Generates the planned container dilutions for the worklist.
     """
     self.add_debug('Generate planned container dilutions ...')
     invalid_dil_factor = dict()
     for rack_pos, tf_pos in self.transfection_layout.iterpositions():
         if tf_pos.is_empty:
             continue
         dil_volume = tf_pos.calculate_reagent_dilution_volume() \
                      / VOLUME_CONVERSION_FACTOR
         ini_dil_factor = TransfectionParameters.\
                             calculate_initial_reagent_dilution(
                             float(tf_pos.reagent_dil_factor))
         if ini_dil_factor <= 1:
             add_list_map_element(invalid_dil_factor,
                                  tf_pos.reagent_dil_factor, rack_pos.label)
             continue
         rdf_str = get_trimmed_string(tf_pos.reagent_dil_factor)
         diluent_info = '%s (%s)' % (tf_pos.reagent_name, rdf_str)
         psd = PlannedSampleDilution.get_entity(volume=dil_volume,
                                        target_position=rack_pos,
                                        diluent_info=diluent_info)
         self._add_planned_transfer(psd)
     if len(invalid_dil_factor) > 0:
         msg = 'Invalid dilution reagent factor for rack positions: %s. ' \
               'The factor would result in an initial dilution factor of ' \
               'less then 1!' % (self._get_joined_map_str(invalid_dil_factor))
         self.add_error(msg)
Beispiel #23
0
    def _get_joined_str(self, item_list, is_strs=True, sort_items=True,
                        separator=', '):
        """
        Helper method converting the passed list into a joined string, separated
        by comma (default). By default, the elements are sorted before
        conversion. This is handy i.e. when printing error messages.

        :param item_list: The recorded events in a list.
        :type item_list: :class:`list` or iterable that can be converted into
            a list.
        :param bool is_strs: If not the items must be converted first.
            Without conversion the join method will raise an error.
        :default is_strs: *True*
        :param bool sort_items: Shall the items be sorted?
        :default sort_items: *True*
        :param str separator: The string to use for the joining.
        :default separator: Comma and 1 space.
        """
        if not isinstance(item_list, list):
            item_list = list(item_list)
        if sort_items: item_list.sort()
        if is_strs:
            item_strs = item_list
        else:
            item_strs = [get_trimmed_string(item) for item in item_list]
        return separator.join(item_strs)
Beispiel #24
0
    def __calculate_single_stock_transfer_volume(self):
        # Determines the volume that has to be transferred from a single design
        # stock tube to a future pool stock tube (for the given volume,
        # concentration, and number of designs). The target volume might
        # be increased if the resulting single design transfer volume has
        # more than 1 decimal place.
        # :raises ValueErrors: if something the values are not compatible
        target_single_conc = float(self.__target_concentration) \
                             / self.__number_designs
        if target_single_conc > self.__stock_concentration:
            msg = 'The requested target concentration (%i nM) cannot be ' \
                  'achieved since it would require a concentration of %s nM ' \
                  'for each single design in the pool. However, the stock ' \
                  'concentration for this design type is only %s nM.' \
                  % (self.__target_concentration,
                     get_trimmed_string(target_single_conc),
                     get_trimmed_string(self.__stock_concentration))
            raise ValueError(msg)
        dil_factor = self.__stock_concentration / target_single_conc
        min_target_volume = round_up(dil_factor * self.__min_cybio_transfer_vol)
        if (min_target_volume > self.__target_volume):
            msg = 'The target volume you have requested (%i ul) is too low ' \
                  'for the required dilution (1:%s) since the CyBio cannot ' \
                  'pipet less than %.1f ul per transfer. The volume that has ' \
                  'to be taken from the stock for each single molecule ' \
                  'design would be lower that that. Increase the target ' \
                  'volume to %.1f ul or increase the target concentration.' \
                  % (self.__target_volume, get_trimmed_string(dil_factor),
                     self.__min_cybio_transfer_vol,
                     round_up(min_target_volume, 0))
            raise ValueError(msg)
        self.__stock_transfer_vol = round_up(self.__target_volume / dil_factor)
        self.__adjusted_target_vol = round(
                                     self.__stock_transfer_vol * dil_factor, 1)

        # must be at least 1 ul according to the last check
        total_transfer_vol = self.__stock_transfer_vol * self.__number_designs
        if total_transfer_vol > self.__target_volume:
            msg = 'The target volume you have requested (%i ul) is too low ' \
                  'for the concentration you have ordered (%i uM) since it ' \
                  'would require already %s ul per molecule design (%s ul in ' \
                  'total) to achieve the requested concentration. Increase ' \
                  'the volume or lower the concentration, please.' \
                  % (self.__target_volume, self.__target_concentration,
                     get_trimmed_string(self.__stock_transfer_vol),
                     get_trimmed_string(total_transfer_vol))
            raise ValueError(msg)
Beispiel #25
0
    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)
Beispiel #26
0
 def _generate_column_values(self):
     """
     This method generates the value lists for the CSV columns.
     """
     target_rack_barcode = self.target_rack.barcode
     sorted_transfers = self.__get_sorted_transfers()
     for pt in sorted_transfers:
         if pt.target_position in self.ignored_positions:
             continue
         if not self._check_transfer_volume(pt.volume, pt.target_position):
             continue
         split_volumes = self.__split_into_transferable_amounts(pt)
         for i in range(len(split_volumes)):
             volume = round(split_volumes[i], 1)
             source_pos = self.__get_and_adjust_source_position(
                                             pt.diluent_info, volume, i)
             if self.has_errors():
                 break
             self._source_rack_values.append(self.source_rack_barcode)
             self._source_pos_values.append(source_pos.label)
             self._volume_values.append(get_trimmed_string(volume))
             self._target_rack_values.append(target_rack_barcode)
             self._target_pos_values.append(pt.target_position.label)
             self._diluent_info_values.append(pt.diluent_info)
     if self.__has_split_volumes:
         msg = 'Some dilution volumes exceed the allowed maximum transfer ' \
               'volume of %s ul. The dilution volumes have been distributed ' \
               'over different source wells. Have a look on the generated ' \
               'worklist file for details, please.' \
                % (get_trimmed_string(self._max_transfer_volume))
         self.add_warning(msg)
     if len(self.__split_sources) > 0:
         msg = 'The source for the following diluents has been split ' \
               'and distributed over several containers because one ' \
               'single container could not have taken up the required ' \
               'volume (max volume of a source container: %s ul, dead ' \
               'volume: %s ul): %s. Have a look onto the generated ' \
               'worklist files for details, please.' \
               % (get_trimmed_string(self.reservoir_specs.max_volume \
                                     * VOLUME_CONVERSION_FACTOR),
                  get_trimmed_string(self.reservoir_specs.max_dead_volume \
                                     * VOLUME_CONVERSION_FACTOR),
                  list(self.__split_sources))
         self.add_warning(msg)
Beispiel #27
0
 def _generate_column_values(self):
     """
     This method generates the value lists for the CSV columns.
     """
     target_rack_barcode = self.target_rack.barcode
     sorted_transfers = self.__get_sorted_transfers()
     for pt in sorted_transfers:
         if pt.target_position in self.ignored_positions:
             continue
         if not self._check_transfer_volume(pt.volume, pt.target_position):
             continue
         split_volumes = self.__split_into_transferable_amounts(pt)
         for i in range(len(split_volumes)):
             volume = round(split_volumes[i], 1)
             source_pos = self.__get_and_adjust_source_position(
                 pt.diluent_info, volume, i)
             if self.has_errors():
                 break
             self._source_rack_values.append(self.source_rack_barcode)
             self._source_pos_values.append(source_pos.label)
             self._volume_values.append(get_trimmed_string(volume))
             self._target_rack_values.append(target_rack_barcode)
             self._target_pos_values.append(pt.target_position.label)
             self._diluent_info_values.append(pt.diluent_info)
     if self.__has_split_volumes:
         msg = 'Some dilution volumes exceed the allowed maximum transfer ' \
               'volume of %s ul. The dilution volumes have been distributed ' \
               'over different source wells. Have a look on the generated ' \
               'worklist file for details, please.' \
                % (get_trimmed_string(self._max_transfer_volume))
         self.add_warning(msg)
     if len(self.__split_sources) > 0:
         msg = 'The source for the following diluents has been split ' \
               'and distributed over several containers because one ' \
               'single container could not have taken up the required ' \
               'volume (max volume of a source container: %s ul, dead ' \
               'volume: %s ul): %s. Have a look onto the generated ' \
               'worklist files for details, please.' \
               % (get_trimmed_string(self.reservoir_specs.max_volume \
                                     * VOLUME_CONVERSION_FACTOR),
                  get_trimmed_string(self.reservoir_specs.max_dead_volume \
                                     * VOLUME_CONVERSION_FACTOR),
                  list(self.__split_sources))
         self.add_warning(msg)
Beispiel #28
0
 def __write_formulas(self):
     # Write the formula explanations in the stream.
     self._write_headline(self.FORMULA_TITLE,
                          preceding_blank_lines=0,
                          trailing_blank_lines=0)
     self._stream.write(self.FORMULA_BASE)
     min_dead_volume = self.reservoir_specs.min_dead_volume \
                       * VOLUME_CONVERSION_FACTOR
     max_dead_volume = self.reservoir_specs.max_dead_volume \
                       * VOLUME_CONVERSION_FACTOR
     self._stream.write(
         self.ISO_VOLUME_FORMULA %
         (self.number_replicates, TransfectionParameters.TRANSFER_VOLUME,
          TransfectionParameters.MINIMUM_ISO_VOLUME,
          get_trimmed_string(min_dead_volume), LIMIT_TARGET_WELLS,
          DEAD_VOLUME_COEFFICIENT, get_trimmed_string(max_dead_volume)))
     self._stream.write(self.ISO_CONCENTRATION_FORMULA %
                        (TransfectionParameters.REAGENT_MM_DILUTION_FACTOR,
                         TransfectionParameters.CELL_DILUTION_FACTOR))
Beispiel #29
0
    def hash_partial(self):
        """
        A string that can be used as hash value. This hash covers only three
        three of the four parameters (molecule design pool, reagent name
        and reagent concentration). It is meant to enable comparison of
        manual ISO definitions, in which the final concentraiton is not known.
        """
        if self.is_empty: return '%s' % (self.rack_position)

        return '%s%s%s' % (self.molecule_design_pool_id, self.reagent_name,
                           get_trimmed_string(self.reagent_dil_factor))
Beispiel #30
0
 def __write_formulas(self):
     # Write the formula explanations in the stream.
     self._write_headline(self.FORMULA_TITLE, preceding_blank_lines=0,
                          trailing_blank_lines=0)
     self._stream.write(self.FORMULA_BASE)
     min_dead_volume = self.reservoir_specs.min_dead_volume \
                       * VOLUME_CONVERSION_FACTOR
     max_dead_volume = self.reservoir_specs.max_dead_volume \
                       * VOLUME_CONVERSION_FACTOR
     self._stream.write(self.ISO_VOLUME_FORMULA % (
                         self.number_replicates,
                         TransfectionParameters.TRANSFER_VOLUME,
                         TransfectionParameters.MINIMUM_ISO_VOLUME,
                         get_trimmed_string(min_dead_volume),
                         LIMIT_TARGET_WELLS, DEAD_VOLUME_COEFFICIENT,
                         get_trimmed_string(max_dead_volume)
                         ))
     self._stream.write(self.ISO_CONCENTRATION_FORMULA %
                         (TransfectionParameters.REAGENT_MM_DILUTION_FACTOR,
                          TransfectionParameters.CELL_DILUTION_FACTOR))
Beispiel #31
0
    def hash_partial(self):
        """
        A string that can be used as hash value. This hash covers only three
        three of the four parameters (molecule design pool, reagent name
        and reagent concentration). It is meant to enable comparison of
        manual ISO definitions, in which the final concentraiton is not known.
        """
        if self.is_empty: return '%s' % (self.rack_position)

        return '%s%s%s' % (self.molecule_design_pool_id,
                           self.reagent_name,
                           get_trimmed_string(self.reagent_dil_factor))
Beispiel #32
0
 def __write_general_section(self):
     # Writes the GENERAL section.
     self._write_headline(self.GENERAL_HEADER, preceding_blank_lines=1)
     if self.racks_to_empty is None:
         rack_line = self.RACK_TO_EMTPTY_LINE % (self.NOT_SPECIFIED_MARKER)
     else:
         rack_line = self.RACK_TO_EMTPTY_LINE \
                                 % (get_trimmed_string(self.racks_to_empty))
     total_transfer_count = 0
     for scr in self.donor_racks.values():
         for transfer_count in scr.associated_racks.values():
             total_transfer_count += transfer_count
     moved_tubes_line = self.TUBES_MOVED_LINE % (total_transfer_count)
     general_lines = [rack_line, moved_tubes_line]
     self._write_body_lines(general_lines)
Beispiel #33
0
 def __write_general_section(self):
     # Writes the GENERAL section.
     self._write_headline(self.GENERAL_HEADER, preceding_blank_lines=1)
     if self.racks_to_empty is None:
         rack_line = self.RACK_TO_EMTPTY_LINE % (self.NOT_SPECIFIED_MARKER)
     else:
         rack_line = self.RACK_TO_EMTPTY_LINE \
                                 % (get_trimmed_string(self.racks_to_empty))
     total_transfer_count = 0
     for scr in self.donor_racks.values():
         for transfer_count in scr.associated_racks.values():
             total_transfer_count += transfer_count
     moved_tubes_line = self.TUBES_MOVED_LINE % (total_transfer_count)
     general_lines = [rack_line, moved_tubes_line]
     self._write_body_lines(general_lines)
Beispiel #34
0
    def get_value_for_code(self, code):
        """
        Returns the tag value encrypted by the code.

        :param code: Tag value code (string of pattern-color-definition).
        :returns: associated tag value (if any; string)
        """
        try:
            result = self.__code_map[code]
        except KeyError:
            msg = 'Tag value (level) code "%s" not found for factor "%s".' \
                   % (get_trimmed_string(code), self.predicate)
            self._create_error(msg)
            result = None
        return result
Beispiel #35
0
    def get_value_for_code(self, code):
        """
        Returns the tag value encrypted by the code.

        :param code: Tag value code (string of pattern-color-definition).
        :returns: associated tag value (if any; string)
        """
        try:
            result = self.__code_map[code]
        except KeyError:
            msg = 'Tag value (level) code "%s" not found for factor "%s".' \
                   % (get_trimmed_string(code), self.predicate)
            self._create_error(msg)
            result = None
        return result
Beispiel #36
0
 def __fetch_entities(self, interface, agg_filter, ids, entity_name, lookup):
     # Convenience method fetch the entities for the given IDs from the DB.
     # Also records errors if an ID is unknown
     agg = get_root_aggregate(interface)
     agg.filter = agg_filter
     for ent in agg:
         lookup[ent.id] = ent
     missing_ids = []
     for exp_id in ids:
         if not lookup.has_key(exp_id):
             missing_ids.append(exp_id)
     if len(missing_ids) > 0:
         msg = "Unable to find %ss for the following IDs in the DB: %s." % (
             entity_name,
             ", ".join([get_trimmed_string(eid) for eid in sorted(missing_ids)]),
         )
         self.add_error(msg)
Beispiel #37
0
    def _get_joined_map_str(self,
                            item_map,
                            str_pattern='%s (%s)',
                            all_strs=True,
                            sort_lists=True,
                            separator=' - '):
        """
        Helper method converting the passed map into a string joined by the
        given separator. By default, the elements of the lists are sorted
        before conversion (map keys are always sorted).
        This is handy i.e. when printing error messages.

        If the map values are iterables, :func:`_get_joined_str` is used to
        generate a string for the list.

        :param item_map: The recorded events in a map.
        :type item_map: :class:`map` having iterables as values
        :param str str_pattern: Is used to convert key-value pairs into a string.
            The first placeholder is used by the key, the second by the joined
            string value.
        :default str_pattern: *%s (%s)*
        :param bool all_strs: Flag indicating if the value list items are
            strings (only applicable if the value is an iterable)? If not the
            items must be converted first. Without conversion the join method
            will raise an error.
        :default all_strs: *True*
        :param bool sort_lists: Flag indicating if the values items should be
            sorted (only applicable if the value is an iterable).
        :default sort_lists: *True*
        :param str separator: The string to use for the joining the key-value
            strings.
        :default separator: whitespace, dash, whitespace
        """
        details = []
        for k in sorted(item_map.keys()):
            v = item_map[k]
            if isinstance(v, (list, set, dict, tuple)):
                v_str = self._get_joined_str(v,
                                             is_strs=all_strs,
                                             sort_items=sort_lists)
            else:
                v_str = str(v)
            details_str = str_pattern % (get_trimmed_string(k), v_str)
            details.append(details_str)
        return separator.join(details)
Beispiel #38
0
 def __fetch_entities(self, interface, agg_filter, ids, entity_name,
                      lookup):
     # Convenience method fetch the entities for the given IDs from the DB.
     # Also records errors if an ID is unknown
     agg = get_root_aggregate(interface)
     agg.filter = agg_filter
     for ent in agg:
         lookup[ent.id] = ent
     missing_ids = []
     for exp_id in ids:
         if not lookup.has_key(exp_id):
             missing_ids.append(exp_id)
     if len(missing_ids) > 0:
         msg = 'Unable to find %ss for the following IDs in the DB: %s.' \
               % (entity_name,
                  ', '.join([get_trimmed_string(eid) for eid \
                             in sorted(missing_ids)]))
         self.add_error(msg)
Beispiel #39
0
 def _generate_column_values(self):
     """
     This method generates the value lists for the CSV columns.
     """
     source_rack_barcode = self.source_rack.barcode
     target_rack_barcode = self.target_rack.barcode
     sorted_transfers = self.__get_sorted_transfers()
     for pt in sorted_transfers:
         if pt.source_position in self.ignored_positions:
             continue
         if not self._check_transfer_volume(pt.volume, pt.target_position,
                                            pt.source_position):
             continue
         self._source_rack_values.append(source_rack_barcode)
         self._source_pos_values.append(pt.source_position.label)
         self._target_rack_values.append(target_rack_barcode)
         self._target_pos_values.append(pt.target_position.label)
         volume = get_trimmed_string(pt.volume * VOLUME_CONVERSION_FACTOR)
         self._volume_values.append(volume)
Beispiel #40
0
 def _generate_column_values(self):
     """
     This method generates the value lists for the CSV columns.
     """
     source_rack_barcode = self.source_rack.barcode
     target_rack_barcode = self.target_rack.barcode
     sorted_transfers = self.__get_sorted_transfers()
     for pt in sorted_transfers:
         if pt.source_position in self.ignored_positions:
             continue
         if not self._check_transfer_volume(pt.volume, pt.target_position,
                                            pt.source_position):
             continue
         self._source_rack_values.append(source_rack_barcode)
         self._source_pos_values.append(pt.source_position.label)
         self._target_rack_values.append(target_rack_barcode)
         self._target_pos_values.append(pt.target_position.label)
         volume = get_trimmed_string(pt.volume * VOLUME_CONVERSION_FACTOR)
         self._volume_values.append(volume)
Beispiel #41
0
    def _get_joined_map_str(self, item_map, str_pattern='%s (%s)',
                            all_strs=True, sort_lists=True, separator=' - '):
        """
        Helper method converting the passed map into a string joined by the
        given separator. By default, the elements of the lists are sorted
        before conversion (map keys are always sorted).
        This is handy i.e. when printing error messages.

        If the map values are iterables, :func:`_get_joined_str` is used to
        generate a string for the list.

        :param item_map: The recorded events in a map.
        :type item_map: :class:`map` having iterables as values
        :param str str_pattern: Is used to convert key-value pairs into a string.
            The first placeholder is used by the key, the second by the joined
            string value.
        :default str_pattern: *%s (%s)*
        :param bool all_strs: Flag indicating if the value list items are
            strings (only applicable if the value is an iterable)? If not the
            items must be converted first. Without conversion the join method
            will raise an error.
        :default all_strs: *True*
        :param bool sort_lists: Flag indicating if the values items should be
            sorted (only applicable if the value is an iterable).
        :default sort_lists: *True*
        :param str separator: The string to use for the joining the key-value
            strings.
        :default separator: whitespace, dash, whitespace
        """
        details = []
        for k in sorted(item_map.keys()):
            v = item_map[k]
            if isinstance(v, (list, set, dict, tuple)):
                v_str = self._get_joined_str(v, is_strs=all_strs,
                                             sort_items=sort_lists)
            else:
                v_str = str(v)
            details_str = str_pattern % (get_trimmed_string(k), v_str)
            details.append(details_str)
        return separator.join(details)
Beispiel #42
0
 def _record_errors(self):
     """
     Records errors that have been found during value list creation.
     """
     if len(self._transfer_volume_too_small) > 0:
         msg = 'Some transfer volume are smaller than the allowed minimum ' \
               'transfer volume of %s ul: %s.' % (self._min_transfer_volume,
                  ', '.join(sorted(self._transfer_volume_too_small)))
         self.add_error(msg)
     if len(self._transfer_volume_too_large) > 0:
         msg = 'Some transfer volume are larger than the allowed maximum ' \
               'transfer volume of %s ul: %s.' % (self._max_transfer_volume,
                         ', '.join(sorted(self._transfer_volume_too_large)))
         self.add_error(msg)
     if len(self._source_volume_too_small) > 0:
         error_list = sorted(list(self._source_volume_too_small))
         msg = 'Some source containers do not contain enough volume to ' \
               'provide liquid for all target containers: %s.' \
                % (', '.join(error_list))
         self.add_error(msg)
     if len(self._source_container_missing) > 0:
         error_list = sorted(list(self._source_container_missing))
         msg = 'Could not find containers for the following source ' \
               'positions: %s.' % (', '.join(error_list))
         self.add_error(msg)
     if len(self._target_volume_too_large) > 0:
         msg = 'Some target containers cannot take up the transfer volume: ' \
               '%s. ' % (', '.join(sorted(self._target_volume_too_large)))
         if self._target_max_volume is not None:
             msg += 'Assumed maximum volume per target well: %s ul.' \
                    % (get_trimmed_string(self._target_max_volume))
         self.add_error(msg)
     if len(self._target_container_missing) > 0:
         msg = 'Could not find containers for the following target ' \
               'positions: %s.' \
                % (', '.join(sorted(self._target_container_missing)))
         self.add_error(msg)
Beispiel #43
0
 def _record_errors(self):
     """
     Records errors that have been found during value list creation.
     """
     if len(self._transfer_volume_too_small) > 0:
         msg = 'Some transfer volume are smaller than the allowed minimum ' \
               'transfer volume of %s ul: %s.' % (self._min_transfer_volume,
                  ', '.join(sorted(self._transfer_volume_too_small)))
         self.add_error(msg)
     if len(self._transfer_volume_too_large) > 0:
         msg = 'Some transfer volume are larger than the allowed maximum ' \
               'transfer volume of %s ul: %s.' % (self._max_transfer_volume,
                         ', '.join(sorted(self._transfer_volume_too_large)))
         self.add_error(msg)
     if len(self._source_volume_too_small) > 0:
         error_list = sorted(list(self._source_volume_too_small))
         msg = 'Some source containers do not contain enough volume to ' \
               'provide liquid for all target containers: %s.' \
                % (', '.join(error_list))
         self.add_error(msg)
     if len(self._source_container_missing) > 0:
         error_list = sorted(list(self._source_container_missing))
         msg = 'Could not find containers for the following source ' \
               'positions: %s.' % (', '.join(error_list))
         self.add_error(msg)
     if len(self._target_volume_too_large) > 0:
         msg = 'Some target containers cannot take up the transfer volume: ' \
               '%s. ' % (', '.join(sorted(self._target_volume_too_large)))
         if self._target_max_volume is not None:
             msg += 'Assumed maximum volume per target well: %s ul.' \
                    % (get_trimmed_string(self._target_max_volume))
         self.add_error(msg)
     if len(self._target_container_missing) > 0:
         msg = 'Could not find containers for the following target ' \
               'positions: %s.' \
                % (', '.join(sorted(self._target_container_missing)))
         self.add_error(msg)