Beispiel #1
0
def get_sector_positions(sector_index, rack_shape, number_sectors,
                         row_count=None, col_count=None):
    """
    A helper function return the positions of the given sector.

    :param int sector_index: Sector index assuming Z-configuration.
    :param int number_sectors: The total number of sectors.
    :param rack_shape: The rack shape to be considered.
    :type rack_shape: :class:`thelma.entities.rack.RackShape
    :param int row_count: The number of sector rows - if you do not provide
        a number the row number is calculated assuming a square setup.
    :param int col_count: The number of sector columns - if you do not provide
        a number the row number is calculated assuming a square setup.
    """
    translator = RackSectorTranslator(number_sectors=number_sectors,
                source_sector_index=sector_index,
                target_sector_index=0,
                row_count=row_count, col_count=col_count,
                behaviour=RackSectorTranslator.MANY_TO_MANY)
    positions = []
    for rack_pos in get_positions_for_shape(rack_shape):
        # Filter for positions
        try:
            translator.translate(rack_pos)
        except ValueError:
            continue
        else:
            positions.append(rack_pos)
    return positions
Beispiel #2
0
 def get_positions_without_tube(self):
     """
     Returns the positions in the rack that are not occupied at the moment.
     """
     shape_96 = get_96_rack_shape()
     free_positions = []
     for rack_pos in get_positions_for_shape(shape_96):
         if not self.tubes.has_key(rack_pos):
             free_positions.append(rack_pos)
     return free_positions
Beispiel #3
0
 def get_positions_without_tube(self):
     """
     Returns the positions in the rack that are not occupied at the moment.
     """
     shape_96 = get_96_rack_shape()
     free_positions = []
     for rack_pos in get_positions_for_shape(shape_96):
         if not self.tubes.has_key(rack_pos):
             free_positions.append(rack_pos)
     return free_positions
Beispiel #4
0
 def _init_source_data(self):
     """
     Initialises the source rack related values and lookups.
     """
     for rack_pos in get_positions_for_shape(self.reservoir_specs.rack_shape):
         self._source_volumes[rack_pos] = 0
     self._source_dead_volume = self.reservoir_specs.min_dead_volume \
                                * VOLUME_CONVERSION_FACTOR
     self._source_max_volume = self.reservoir_specs.max_volume \
                                * VOLUME_CONVERSION_FACTOR
     self.__emtpy_pos_manager = EmptyPositionManager(
                                 rack_shape=self.reservoir_specs.rack_shape)
Beispiel #5
0
 def _init_source_data(self):
     """
     Initialises the source rack related values and lookups.
     """
     for rack_pos in get_positions_for_shape(
             self.reservoir_specs.rack_shape):
         self._source_volumes[rack_pos] = 0
     self._source_dead_volume = self.reservoir_specs.min_dead_volume \
                                * VOLUME_CONVERSION_FACTOR
     self._source_max_volume = self.reservoir_specs.max_volume \
                                * VOLUME_CONVERSION_FACTOR
     self.__emtpy_pos_manager = EmptyPositionManager(
         rack_shape=self.reservoir_specs.rack_shape)
Beispiel #6
0
 def __get_layout(self):
     # Fetches the stock sample layout and sorts its positions into
     # quadrants.
     self.add_debug("Fetch stock sample layout ...")
     converter = StockSampleCreationLayoutConverter(self.entity.rack_layout, parent=self)
     self.__ssc_layout = converter.get_result()
     if self.__ssc_layout is None:
         msg = "Error when trying to convert stock sample creation ISO " "layout."
         self.add_error(msg)
     else:
         ssc_positions = self.__ssc_layout.get_positions()
         for rack_pos in get_positions_for_shape(RACK_SHAPE_NAMES.SHAPE_96):
             if not rack_pos in ssc_positions:
                 self.__ignore_positions.append(rack_pos)
Beispiel #7
0
 def __build_preparation_plate_map(self):
     for spp in self.iso.iso_sector_preparation_plates:
         self.__prep_plate_map[spp.sector_index] = spp
         # Record empty positions to ignore later when building the
         # dilution jobs.
         cnv = StockSampleCreationLayoutConverter(spp.rack_layout,
                                                  parent=self)
         ssc_layout = cnv.get_result()
         self.__ssc_layout_map[spp.sector_index] = ssc_layout
         all_poss = get_positions_for_shape(RACK_SHAPE_NAMES.SHAPE_96)
         empty_poss = \
             list(set(all_poss).difference(ssc_layout.get_positions()))
         self.__empty_stock_rack_positions_map[spp.sector_index] = \
                                                             empty_poss
Beispiel #8
0
 def __build_preparation_plate_map(self):
     for spp in self.iso.iso_sector_preparation_plates:
         self.__prep_plate_map[spp.sector_index] = spp
         # Record empty positions to ignore later when building the
         # dilution jobs.
         cnv = StockSampleCreationLayoutConverter(spp.rack_layout,
                                                  parent=self)
         ssc_layout = cnv.get_result()
         self.__ssc_layout_map[spp.sector_index] = ssc_layout
         all_poss = get_positions_for_shape(RACK_SHAPE_NAMES.SHAPE_96)
         empty_poss = \
             list(set(all_poss).difference(ssc_layout.get_positions()))
         self.__empty_stock_rack_positions_map[spp.sector_index] = \
                                                             empty_poss
Beispiel #9
0
 def __verify_pool_stock_rack(self):
     # Makes sure there are empty tubes in all required positions and none
     # in positions that must be empty.
     converter = PoolCreationStockRackLayoutConverter(self.__pool_stock_rack.rack_layout, parent=self)
     layout = converter.get_result()
     if layout is None:
         msg = "Error when trying to convert pool stock rack layout!"
         self.add_error(msg)
     else:
         additional_tubes = []
         non_empty_tube = []
         positions = layout.get_positions()
         tube_positions = set()
         rack = self.__pool_stock_rack.rack
         for tube in rack.containers:
             rack_pos = tube.location.position
             tube_positions.add(rack_pos)
             info = "%s (%s)" % (tube.barcode, rack_pos.label)
             if not rack_pos in positions:
                 additional_tubes.append(info)
             elif not tube.sample is None:
                 non_empty_tube.append(info)
         missing_tube = []
         for rack_pos in get_positions_for_shape(layout.shape):
             sr_pos = layout.get_working_position(rack_pos)
             if sr_pos is None:
                 continue
             elif rack_pos not in tube_positions:
                 missing_tube.append(rack_pos.label)
         if len(additional_tubes) > 0:
             msg = (
                 "There are unexpected tubes in the pool stock rack "
                 "(%s): %s. Please remove them and try again."
                 % (rack.barcode, self._get_joined_str(additional_tubes))
             )
             self.add_error(msg)
         if len(non_empty_tube) > 0:
             msg = (
                 "The following tubes in the pool stock rack (%s) are "
                 "not empty: %s. Please replace them by empty tubes and "
                 "try again." % (rack.barcode, self._get_joined_str(non_empty_tube))
             )
             self.add_error(msg)
         if len(missing_tube) > 0:
             msg = "There are tubes missing in the following positions " "of the pool stock rack (%s): %s." % (
                 rack.barcode,
                 self._get_joined_str(missing_tube),
             )
             self.add_error(msg)
Beispiel #10
0
 def __get_layout(self):
     # Fetches the stock sample layout and sorts its positions into
     # quadrants.
     self.add_debug('Fetch stock sample layout ...')
     converter = StockSampleCreationLayoutConverter(self.entity.rack_layout,
                                                    parent=self)
     self.__ssc_layout = converter.get_result()
     if self.__ssc_layout is None:
         msg = 'Error when trying to convert stock sample creation ISO ' \
               'layout.'
         self.add_error(msg)
     else:
         ssc_positions = self.__ssc_layout.get_positions()
         for rack_pos in get_positions_for_shape(RACK_SHAPE_NAMES.SHAPE_96):
             if not rack_pos in ssc_positions:
                 self.__ignore_positions.append(rack_pos)
Beispiel #11
0
 def _create_iso_layout(self):
     """
     Creates a :class:`StockSampleCreationLayout` for a single ISO.
     Positions are populated column-wise.
     """
     ssc_layout = StockSampleCreationLayout()
     for rack_pos in get_positions_for_shape(ssc_layout.shape,
                                             vertical_sorting=True):
         if not self._have_candidates:
             break
         pool_cand = self._pool_candidates.pop(0)
         ssc_pos = \
             StockSampleCreationPosition(rack_pos,
                                         pool_cand.pool,
                                         pool_cand.get_tube_barcodes())
         ssc_layout.add_position(ssc_pos)
     return ssc_layout
Beispiel #12
0
 def __verify_pool_stock_rack(self):
     # Makes sure there are empty tubes in all required positions and none
     # in positions that must be empty.
     converter = PoolCreationStockRackLayoutConverter(
         self.__pool_stock_rack.rack_layout, parent=self)
     layout = converter.get_result()
     if layout is None:
         msg = 'Error when trying to convert pool stock rack layout!'
         self.add_error(msg)
     else:
         additional_tubes = []
         non_empty_tube = []
         positions = layout.get_positions()
         tube_positions = set()
         rack = self.__pool_stock_rack.rack
         for tube in rack.containers:
             rack_pos = tube.location.position
             tube_positions.add(rack_pos)
             info = '%s (%s)' % (tube.barcode, rack_pos.label)
             if not rack_pos in positions:
                 additional_tubes.append(info)
             elif not tube.sample is None:
                 non_empty_tube.append(info)
         missing_tube = []
         for rack_pos in get_positions_for_shape(layout.shape):
             sr_pos = layout.get_working_position(rack_pos)
             if sr_pos is None:
                 continue
             elif rack_pos not in tube_positions:
                 missing_tube.append(rack_pos.label)
         if len(additional_tubes) > 0:
             msg = 'There are unexpected tubes in the pool stock rack ' \
                   '(%s): %s. Please remove them and try again.' \
                   % (rack.barcode, self._get_joined_str(additional_tubes))
             self.add_error(msg)
         if len(non_empty_tube) > 0:
             msg = 'The following tubes in the pool stock rack (%s) are ' \
                   'not empty: %s. Please replace them by empty tubes and ' \
                   'try again.' % (rack.barcode,
                                   self._get_joined_str(non_empty_tube))
             self.add_error(msg)
         if len(missing_tube) > 0:
             msg = 'There are tubes missing in the following positions ' \
                   'of the pool stock rack (%s): %s.' % (rack.barcode,
                    self._get_joined_str(missing_tube))
             self.add_error(msg)
Beispiel #13
0
 def _create_iso_layout(self):
     """
     Creates a :class:`StockSampleCreationLayout` for a single ISO.
     Positions are populated column-wise.
     """
     ssc_layout = StockSampleCreationLayout()
     for rack_pos in get_positions_for_shape(ssc_layout.shape,
                                             vertical_sorting=True):
         if not self._have_candidates:
             break
         pool_cand = self._pool_candidates.pop(0)
         ssc_pos = \
             StockSampleCreationPosition(rack_pos,
                                         pool_cand.pool,
                                         pool_cand.get_tube_barcodes())
         ssc_layout.add_position(ssc_pos)
     return ssc_layout
Beispiel #14
0
    def get_empty_position(self):
        """
        Returns the position with the lowest column and row index
        (and removes it from the pool).

        :raises ValueError: If there is no empty position left.
        """
        picked_position = None

        for rack_pos in get_positions_for_shape(self.rack_shape):
            if rack_pos in self._all_empty_positions:
                picked_position = rack_pos
                break

        if picked_position is None:
            raise ValueError('No empty position left!')

        self._all_empty_positions.discard(picked_position)
        return picked_position
Beispiel #15
0
    def get_empty_position(self):
        """
        Returns the position with the lowest column and row index
        (and removes it from the pool).

        :raises ValueError: If there is no empty position left.
        """
        picked_position = None

        for rack_pos in get_positions_for_shape(self.rack_shape):
            if rack_pos in self._all_empty_positions:
                picked_position = rack_pos
                break

        if picked_position is None:
            raise ValueError('No empty position left!')

        self._all_empty_positions.discard(picked_position)
        return picked_position
Beispiel #16
0
 def __create_transfers(self):
     # Creates a :class:`PlannedSampleDilution` for each rack position
     # in a 8x12 rack shape.
     self.add_debug('Create transfers ...')
     self._run_and_record_error(self.volume_calculator.calculate,
                         'Error when trying to determine buffer volume: ',
                         ValueError)
     buffer_volume = self.volume_calculator.get_buffer_volume()
     if buffer_volume is not None:
         volume = buffer_volume / VOLUME_CONVERSION_FACTOR
         wl_label = LABELS.create_buffer_worklist_label(
                                                 self.iso_request_label)
         wl = PlannedWorklist(wl_label,
                              TRANSFER_TYPES.SAMPLE_DILUTION,
                              get_pipetting_specs_cybio())
         for rack_pos in get_positions_for_shape(RACK_SHAPE_NAMES.SHAPE_96):
             psd = PlannedSampleDilution.get_entity(volume=volume,
                   target_position=rack_pos, diluent_info=DILUENT_INFO)
             wl.planned_liquid_transfers.append(psd)
         self.__worklist_series.add_worklist(self.BUFFER_WORKLIST_INDEX, wl)
Beispiel #17
0
    def compare_ignoring_untreated_types(layout1, layout2):
        """
        Compares two transfection layouts ignoring potential untreated
        positions.
        """
        if layout1.shape != layout2.shape: return False

        for rack_pos in get_positions_for_shape(layout1.shape):
            tf1 = layout1.get_working_position(rack_pos)
            tf2 = layout2.get_working_position(rack_pos)
            if tf1 is None and tf2 is None: continue
            if tf1 is not None and (tf1.is_untreated_type or tf1.is_empty):
                tf1 = None
            if tf2 is not None and (tf2.is_untreated_type or tf2.is_empty):
                tf2 = None
            if tf1 is None and tf2 is None:
                continue
            elif not tf1 == tf2:
                return False

        return True
Beispiel #18
0
 def __create_transfers(self):
     # Creates a :class:`PlannedSampleDilution` for each rack position
     # in a 8x12 rack shape.
     self.add_debug('Create transfers ...')
     self._run_and_record_error(
         self.volume_calculator.calculate,
         'Error when trying to determine buffer volume: ', ValueError)
     buffer_volume = self.volume_calculator.get_buffer_volume()
     if buffer_volume is not None:
         volume = buffer_volume / VOLUME_CONVERSION_FACTOR
         wl_label = LABELS.create_buffer_worklist_label(
             self.iso_request_label)
         wl = PlannedWorklist(wl_label, TRANSFER_TYPES.SAMPLE_DILUTION,
                              get_pipetting_specs_cybio())
         for rack_pos in get_positions_for_shape(RACK_SHAPE_NAMES.SHAPE_96):
             psd = PlannedSampleDilution.get_entity(
                 volume=volume,
                 target_position=rack_pos,
                 diluent_info=DILUENT_INFO)
             wl.planned_liquid_transfers.append(psd)
         self.__worklist_series.add_worklist(self.BUFFER_WORKLIST_INDEX, wl)
Beispiel #19
0
    def __create_layout_from_map(self):
        """
        Creates the actual working layout object.
        """
        self.add_debug('Convert position map into working layout.')

        working_layout = self._initialize_working_layout(self.rack_layout.shape)
        for rack_position in get_positions_for_shape(self.rack_layout.shape):
            working_position = self.__position_map[rack_position]
            if working_position is None: continue
            self._run_and_record_error(working_layout.add_position,
                    base_msg='Error when trying to add position to layout: ',
                    error_types=set([ValueError, AttributeError, KeyError,
                                     TypeError]),
                    **dict(working_position=working_position))
            if self.has_errors(): break

        if self.has_errors(): return None
        self._perform_layout_validity_checks(working_layout)
        if self.has_errors(): return None
        return working_layout
Beispiel #20
0
    def compare_ignoring_untreated_types(layout1, layout2):
        """
        Compares two transfection layouts ignoring potential untreated
        positions.
        """
        if layout1.shape != layout2.shape: return False

        for rack_pos in get_positions_for_shape(layout1.shape):
            tf1 = layout1.get_working_position(rack_pos)
            tf2 = layout2.get_working_position(rack_pos)
            if tf1 is None and tf2 is None: continue
            if tf1 is not None and (tf1.is_untreated_type or tf1.is_empty):
                tf1 = None
            if tf2 is not None and (tf2.is_untreated_type or tf2.is_empty):
                tf2 = None
            if tf1 is None and tf2 is None:
                continue
            elif not tf1 == tf2:
                return False

        return True
Beispiel #21
0
    def __get_values_for_rack_layout(self, validators, rack_layout):
        """
        Finds the parameters values for each position in a design rack layout.
        """
        shape_positions = get_positions_for_shape(self._rack_shape)

        # Initialise the value maps
        value_maps = dict()
        for parameter in validators.keys():
            rack_pos_dict = dict()
            for rack_pos in shape_positions:
                rack_pos_dict[rack_pos] = None
            value_maps[parameter] = rack_pos_dict

        for trps in rack_layout.tagged_rack_position_sets:
            for tag in trps.tags:
                for parameter, validator in validators.iteritems():
                    if validator.has_alias(tag.predicate):
                        value_map = value_maps[parameter]
                        for rack_pos in trps.rack_position_set:
                            value_map[rack_pos] = tag.value

        return value_maps
Beispiel #22
0
    def __get_values_for_rack_layout(self, validators, rack_layout):
        """
        Finds the parameters values for each position in a design rack layout.
        """
        shape_positions = get_positions_for_shape(self._rack_shape)

        # Initialise the value maps
        value_maps = dict()
        for parameter in validators.keys():
            rack_pos_dict = dict()
            for rack_pos in shape_positions:
                rack_pos_dict[rack_pos] = None
            value_maps[parameter] = rack_pos_dict

        for trps in rack_layout.tagged_rack_position_sets:
            for tag in trps.tags:
                for parameter, validator in validators.iteritems():
                    if validator.has_alias(tag.predicate):
                        value_map = value_maps[parameter]
                        for rack_pos in trps.rack_position_set:
                            value_map[rack_pos] = tag.value

        return value_maps
Beispiel #23
0
    def run(self):
        """
        Runs the conversion.
        """
        self.reset()
        self.add_info('Start conversion ...')

        self._check_input()
        if not self.has_errors():
            self._initialize_parameter_validators()
            self._initialize_other_attributes()
            self.__check_parameter_completeness()
        if not self.has_errors():
            for rack_position in get_positions_for_shape(self.rack_layout.shape):
                tag_set = self.rack_layout.get_tags_for_position(rack_position)
                parameter_map = self._get_parameter_map(tag_set, rack_position)
                working_position = self.__obtain_working_position(parameter_map)
                self.__position_map[rack_position] = working_position
        self._record_errors()

        if not self.has_errors():
            self.return_value = self.__create_layout_from_map()
            self.add_info('Layout conversion completed.')
Beispiel #24
0
    def __check_value_presence(self, value_maps, label):
        """
        Checks the presence of mandatory, optional and forbidden parameters
        for each rack position in a layout.
        """
        pool_map = value_maps[TransfectionParameters.MOLECULE_DESIGN_POOL]
        pool_forbidden = TransfectionParameters.MOLECULE_DESIGN_POOL in \
                         self.__forbidden_parameters

        non_empty = []
        missing_value = dict()
        additional_values = dict()
        inconsistent_optionals = dict()

        for rack_pos in get_positions_for_shape(self._rack_shape):
            pool_id = pool_map[rack_pos]

            is_untreated = (isinstance(pool_id, basestring) and \
                      TransfectionParameters.is_untreated_type(pool_id.lower()))
            if is_untreated: continue

            if pool_id is None:  # Empty position should not have values
                for parameter, value_map in value_maps.iteritems():
                    if not value_map[rack_pos] is None:
                        non_empty.append(rack_pos.label)
                        break
                if not pool_forbidden: continue

            for parameter, value_map in value_maps.iteritems():
                if parameter == TransfectionParameters.MOLECULE_DESIGN_POOL:
                    continue
                elif pool_id == MOCK_POSITION_TYPE and \
                    parameter == TransfectionParameters.FINAL_CONCENTRATION:
                    continue

                value = value_map[rack_pos]

                # Check consistency of definition
                present_parameter = self.__parameter_presence[parameter]
                if present_parameter and value is None:
                    if not inconsistent_optionals.has_key(parameter):
                        inconsistent_optionals[parameter] = []
                    inconsistent_optionals[parameter].append(rack_pos.label)
                elif not present_parameter and not value is None and \
                                                            not pool_forbidden:
                    self.__parameter_presence[parameter] = True

                # Check mandatory and forbidden parameters
                if parameter in self.__mandatory_parameters and \
                                                            value is None:
                    if not missing_value.has_key(parameter):
                        missing_value[parameter] = []
                    missing_value[parameter].append(rack_pos.label)
                elif parameter in self.__forbidden_parameters and \
                                                        not value is None:
                    if not additional_values.has_key(parameter):
                        additional_values[parameter] = []
                    info = '%s (%s)' % (rack_pos.label, value)
                    additional_values[parameter].append(info)

        # Error recording
        if len(non_empty) > 0 and not pool_forbidden:
            msg = 'Some rack positions in design rack %s contain values ' \
                  'although there are no molecule designs for them: %s.' \
                   % (label, ', '.join(sorted(non_empty)))
            self.add_error(msg)

        if len(missing_value) > 0:
            records_str = self.__get_error_record_string(missing_value)
            msg = 'There are mandatory values missing for some rack ' \
                  'positions in design rack %s: %s. Assumed scenario: %s.' \
                   % (label, records_str, self.scenario.display_name)
            self.add_error(msg)

        if len(additional_values) > 0:
            records_str = self.__get_error_record_string(additional_values)
            msg = 'Some factors must not be specified in %s scenarios. The ' \
                  'following position in design rack %s contain ' \
                  'specifications for forbidden factors: %s.' \
                  % (self.scenario.display_name, label, records_str)
            self.add_error(msg)

        if len(inconsistent_optionals) > 0:
            records_str = self.__get_error_record_string(
                inconsistent_optionals)
            msg = 'If you specify a factor, you have to specify it for each ' \
                  'non-empty well in all design racks. The following wells ' \
                  'in design rack %s lack a specification: %s.' \
                   % (label, records_str)
            self.add_error(msg)
Beispiel #25
0
    def __check_value_presence(self, value_maps, label):
        """
        Checks the presence of mandatory, optional and forbidden parameters
        for each rack position in a layout.
        """
        pool_map = value_maps[TransfectionParameters.MOLECULE_DESIGN_POOL]
        pool_forbidden = TransfectionParameters.MOLECULE_DESIGN_POOL in \
                         self.__forbidden_parameters

        non_empty = []
        missing_value = dict()
        additional_values = dict()
        inconsistent_optionals = dict()

        for rack_pos in get_positions_for_shape(self._rack_shape):
            pool_id = pool_map[rack_pos]

            is_untreated = (isinstance(pool_id, basestring) and \
                      TransfectionParameters.is_untreated_type(pool_id.lower()))
            if is_untreated: continue

            if pool_id is None: # Empty position should not have values
                for parameter, value_map in value_maps.iteritems():
                    if not value_map[rack_pos] is None:
                        non_empty.append(rack_pos.label)
                        break
                if not pool_forbidden: continue

            for parameter, value_map in value_maps.iteritems():
                if parameter == TransfectionParameters.MOLECULE_DESIGN_POOL:
                    continue
                elif pool_id == MOCK_POSITION_TYPE and \
                    parameter == TransfectionParameters.FINAL_CONCENTRATION:
                    continue

                value = value_map[rack_pos]

                # Check consistency of definition
                present_parameter = self.__parameter_presence[parameter]
                if present_parameter and value is None:
                    if not inconsistent_optionals.has_key(parameter):
                        inconsistent_optionals[parameter] = []
                    inconsistent_optionals[parameter].append(rack_pos.label)
                elif not present_parameter and not value is None and \
                                                            not pool_forbidden:
                    self.__parameter_presence[parameter] = True

                # Check mandatory and forbidden parameters
                if parameter in self.__mandatory_parameters and \
                                                            value is None:
                    if not missing_value.has_key(parameter):
                        missing_value[parameter] = []
                    missing_value[parameter].append(rack_pos.label)
                elif parameter in self.__forbidden_parameters and \
                                                        not value is None:
                    if not additional_values.has_key(parameter):
                        additional_values[parameter] = []
                    info = '%s (%s)' % (rack_pos.label, value)
                    additional_values[parameter].append(info)

        # Error recording
        if len(non_empty) > 0 and not pool_forbidden:
            msg = 'Some rack positions in design rack %s contain values ' \
                  'although there are no molecule designs for them: %s.' \
                   % (label, ', '.join(sorted(non_empty)))
            self.add_error(msg)

        if len(missing_value) > 0:
            records_str = self.__get_error_record_string(missing_value)
            msg = 'There are mandatory values missing for some rack ' \
                  'positions in design rack %s: %s. Assumed scenario: %s.' \
                   % (label, records_str, self.scenario.display_name)
            self.add_error(msg)

        if len(additional_values) > 0:
            records_str = self.__get_error_record_string(additional_values)
            msg = 'Some factors must not be specified in %s scenarios. The ' \
                  'following position in design rack %s contain ' \
                  'specifications for forbidden factors: %s.' \
                  % (self.scenario.display_name, label, records_str)
            self.add_error(msg)

        if len(inconsistent_optionals) > 0:
            records_str = self.__get_error_record_string(inconsistent_optionals)
            msg = 'If you specify a factor, you have to specify it for each ' \
                  'non-empty well in all design racks. The following wells ' \
                  'in design rack %s lack a specification: %s.' \
                   % (label, records_str)
            self.add_error(msg)
Beispiel #26
0
 def _init_empty_positions(self):
     """
     Initialises the maps.
     """
     for rack_pos in get_positions_for_shape(self.rack_shape):
         self._all_empty_positions.add(rack_pos)
Beispiel #27
0
 def _init_empty_positions(self):
     """
     Initialises the maps.
     """
     for rack_pos in get_positions_for_shape(self.rack_shape):
         self._all_empty_positions.add(rack_pos)