def _check_input(self): """ Checks the input values. """ self.add_debug('Check input values ...') if isinstance(self.molecule_design_pools, (InstrumentedSet, list)): for pool in self.molecule_design_pools: self._check_input_class('molecule design pool', pool, MoleculeDesignPool) if len(self.molecule_design_pools) < 1: msg = 'The pool list is empty!' self.add_error(msg) else: msg = 'The pool list must be a list or an InstrumentedSet ' \ '(obtained: %s).' % \ (self.molecule_design_pools.__class__.__name__) self.add_error(msg) if not self.take_out_volume is None and \ not is_valid_number(self.take_out_volume): msg = 'The stock take out volume must be a positive number ' \ '(obtained: %s) or None.' % (self.take_out_volume) self.add_error(msg) if not is_valid_number(self.stock_concentration): msg = 'The stock concentration must be a positive number ' \ '(obtained: %s).' % (self.stock_concentration) self.add_error(msg) self._check_input_list_classes('excluded rack', self.excluded_racks, basestring, may_be_empty=True) if self._check_input_list_classes('requested tube', self.requested_tubes, basestring, may_be_empty=True): self.requested_tubes = set(self.requested_tubes)
def parse_columns(self): """ Searches the found columns for IDs. """ self._create_debug_info('Parse column ...') invalid_mds = [] invalid_pools = [] self._step_to_next_row() while not self._end_reached: # Get cell values. md_value = None if self.__single_md_column_index is not None: md_value = self._get_cell_value(self._current_row, self.__single_md_column_index) pool_value = None if self.__pool_column_index is not None: pool_value = self._get_cell_value(self._current_row, self.__pool_column_index) if md_value is None and pool_value is None: self._end_reached = True break # Check pool IDs. if not pool_value is None and not is_valid_number(pool_value, is_integer=True): info = 'row %i (%s)' % (self._current_row + 1, pool_value) invalid_pools.append(info) elif not pool_value is None: self._parser.pool_ids[self._current_row] = pool_value # Check single molecule design IDs. if md_value is not None: md_ids = str(md_value).split(self._parser.DELIMITER) valid = True for md_id in md_ids: if not is_valid_number(md_id, is_integer=True): info = 'row %i (%s)' % ((self._current_row + 1), '-'.join(md_ids)) invalid_mds.append(info) valid = False if valid: md_ids = [int(md_id) for md_id in md_ids] self._parser.molecule_design_lists[self._current_row] = \ md_ids self._step_to_next_row() if len(self._parser.molecule_design_lists) < 1 and \ len(self._parser.pool_ids) < 1: msg = 'There is no design data in the columns!' self._create_error(msg) if len(invalid_mds) > 0: msg = 'Some rows contain invalid molecule design IDs: %s.' \ % (', '.join(invalid_mds)) self._create_error(msg) if len(invalid_pools) > 0: msg = 'Some rows contain invalid pool IDs: %s.' \ % (', '.join(invalid_pools)) self._create_error(msg)
def parse_columns(self): """ Searches the found columns for IDs. """ self._create_debug_info('Parse column ...') invalid_mds = [] invalid_pools = [] self._step_to_next_row() while not self._end_reached: # Get cell values. md_value = None if self.__single_md_column_index is not None: md_value = self._get_cell_value(self._current_row, self.__single_md_column_index) pool_value = None if self.__pool_column_index is not None: pool_value = self._get_cell_value(self._current_row, self.__pool_column_index) if md_value is None and pool_value is None: self._end_reached = True break # Check pool IDs. if not pool_value is None and not is_valid_number(pool_value, is_integer=True): info = 'row %i (%s)' % (self._current_row + 1, pool_value) invalid_pools.append(info) elif not pool_value is None: self._parser.pool_ids[self._current_row] = pool_value # Check single molecule design IDs. if md_value is not None: md_ids = str(md_value).split(self._parser.DELIMITER) valid = True for md_id in md_ids: if not is_valid_number(md_id, is_integer=True): info = 'row %i (%s)' % ( (self._current_row + 1), '-'.join(md_ids)) invalid_mds.append(info) valid = False if valid: md_ids = [int(md_id) for md_id in md_ids] self._parser.molecule_design_lists[self._current_row] = \ md_ids self._step_to_next_row() if len(self._parser.molecule_design_lists) < 1 and \ len(self._parser.pool_ids) < 1: msg = 'There is no design data in the columns!' self._create_error(msg) if len(invalid_mds) > 0: msg = 'Some rows contain invalid molecule design IDs: %s.' \ % (', '.join(invalid_mds)) self._create_error(msg) if len(invalid_pools) > 0: msg = 'Some rows contain invalid pool IDs: %s.' \ % (', '.join(invalid_pools)) self._create_error(msg)
def _check_input(self): """ Checks the initialisation values. """ self.add_debug('Check initialisation values ...') self._check_input_class('molecule design library', self.molecule_design_library, MoleculeDesignLibrary) if not is_valid_number(self.number_isos, is_integer=True): msg = 'The number of ISOs order must be a positive integer ' \ '(obtained: %s).' % (self.number_isos) self.add_error(msg) if self._check_input_class('excluded racks list', self.excluded_racks, list): for excl_rack in self.excluded_racks: if not self._check_input_class('excluded rack barcode', excl_rack, basestring): break if self._check_input_class('requested tubes list', self.requested_tubes, list): for req_tube in self.requested_tubes: if not self._check_input_class('requested tube barcode', req_tube, basestring): break
def _check_input(self): """ Checks the initialisation values. """ self.add_debug('Check initialization values ...') if self._check_input_class('ISO request', self.iso_request, IsoRequest): iso_type = self.iso_request.iso_type if not self.__ISO_REQUEST_CLS.has_key(iso_type): msg = 'Unsupported ISO type "%s"!' % (iso_type) self.add_error(msg) else: ir_cls = self.__ISO_REQUEST_CLS[self._ISO_TYPE] self._check_input_class('ISO request', self.iso_request, ir_cls) if not is_valid_number(self.number_isos, is_integer=True): msg = 'The number of ISOs order must be a positive integer ' \ '(obtained: %s).' % (self.number_isos) self.add_error(msg) self._check_input_list_classes('excluded rack', self.excluded_racks, basestring, may_be_empty=True) self._check_input_list_classes('requested tube', self.requested_tubes, basestring, may_be_empty=True)
def __parse_column(self): self.add_debug('Parse column ...') row_index = 1 row_count = self.get_sheet_row_number(self.sheet) invalid_numbers = [] while row_index < row_count: cell_value = self.get_cell_value(self.sheet, row_index, self.__column_index) if cell_value is None: break md_ids = str(cell_value).split(self.DELIMITER) valid = True for md_id in md_ids: if not is_valid_number(md_id, is_integer=True): info = '%i (%s)' % ((row_index + 1), md_ids) invalid_numbers.append(info) valid = False break if valid: md_ids = [int(md_id) for md_id in md_ids] self.molecule_design_lists.append(md_ids) row_index += 1 if len(self.molecule_design_lists) < 1: msg = 'There are no molecule designs in the column!' self.add_error(msg) if len(invalid_numbers) > 0: msg = 'Some cells contain invalid molecule design IDs: %s.' \ % (', '.join(invalid_numbers)) self.add_error(msg)
def __check_numerical_values(self, value_maps, label): """ Checks the values of the numerical parameters. """ invalid_numericals = dict() invalid_mock = dict() invalid_untreated = dict() pool_map = value_maps[TransfectionParameters.MOLECULE_DESIGN_POOL] for parameter, value_map in value_maps.iteritems(): if not parameter in _SCENARIO_PARAMETERS.NUMERICAL_PARAMETERS: continue for rack_pos, value in value_map.iteritems(): if value is None: continue pool = pool_map[rack_pos] if (pool == MOCK_POSITION_TYPE): if not TransfectionParameters.is_valid_mock_value( value, parameter): add_list_map_element(invalid_mock, parameter, rack_pos.label) elif TransfectionParameters.is_untreated_type(pool): if parameter in (TransfectionParameters.FINAL_CONCENTRATION, TransfectionParameters.REAGENT_DIL_FACTOR) \ and not TransfectionPosition.\ is_valid_untreated_value(value): add_list_map_element(invalid_untreated, parameter, rack_pos.label) elif not is_valid_number(value): info = '%s (%s)' % (rack_pos.label, value) add_list_map_element(invalid_numericals, parameter, info) if len(invalid_numericals) > 0: records_str = self.__get_error_record_string(invalid_numericals) msg = 'The levels of some factors must be positive numbers. The ' \ 'following positions in design rack %s have invalid ' \ 'values: %s.' % (label, records_str) self.add_error(msg) if len(invalid_mock) > 0: records_str = self.__get_error_record_string(invalid_mock) msg = 'The levels of some factors for mock positions allow only ' \ 'for the values "None" or "mock" (or no level). Some ' \ 'positions in design rack "%s" have invalid levels. ' \ 'Affected positions: %s.' % (label, records_str) self.add_error(msg) if len(invalid_untreated) > 0: records_str = self.__get_error_record_string(invalid_untreated) msg = 'The levels of some factors for untreated positions allow ' \ 'only for the values "None" and "untreated" (or no level). ' \ 'Some position in design rack "%s" have invalid levels. ' \ 'Affected positions: %s.' % (label, records_str) self.add_error(msg)
def __check_numerical_values(self, value_maps, label): """ Checks the values of the numerical parameters. """ invalid_numericals = dict() invalid_mock = dict() invalid_untreated = dict() pool_map = value_maps[TransfectionParameters.MOLECULE_DESIGN_POOL] for parameter, value_map in value_maps.iteritems(): if not parameter in _SCENARIO_PARAMETERS.NUMERICAL_PARAMETERS: continue for rack_pos, value in value_map.iteritems(): if value is None: continue pool = pool_map[rack_pos] if (pool == MOCK_POSITION_TYPE): if not TransfectionParameters.is_valid_mock_value(value, parameter): add_list_map_element(invalid_mock, parameter, rack_pos.label) elif TransfectionParameters.is_untreated_type(pool): if parameter in (TransfectionParameters.FINAL_CONCENTRATION, TransfectionParameters.REAGENT_DIL_FACTOR) \ and not TransfectionPosition.\ is_valid_untreated_value(value): add_list_map_element(invalid_untreated, parameter, rack_pos.label) elif not is_valid_number(value): info = '%s (%s)' % (rack_pos.label, value) add_list_map_element(invalid_numericals, parameter, info) if len(invalid_numericals) > 0: records_str = self.__get_error_record_string(invalid_numericals) msg = 'The levels of some factors must be positive numbers. The ' \ 'following positions in design rack %s have invalid ' \ 'values: %s.' % (label, records_str) self.add_error(msg) if len(invalid_mock) > 0: records_str = self.__get_error_record_string(invalid_mock) msg = 'The levels of some factors for mock positions allow only ' \ 'for the values "None" or "mock" (or no level). Some ' \ 'positions in design rack "%s" have invalid levels. ' \ 'Affected positions: %s.' % (label, records_str) self.add_error(msg) if len(invalid_untreated) > 0: records_str = self.__get_error_record_string(invalid_untreated) msg = 'The levels of some factors for untreated positions allow ' \ 'only for the values "None" and "untreated" (or no level). ' \ 'Some position in design rack "%s" have invalid levels. ' \ 'Affected positions: %s.' % (label, records_str) self.add_error(msg)
def __check_input(self): # Checks the initialisation values. self.add_debug("Checking input.") self._check_input_class("base library layout", self.base_layout, LibraryBaseLayout) self._check_input_class("library name", self.library_name, basestring) if not is_valid_number(self.stock_concentration): msg = ( "The stock concentration for the single source molecules " "must be a positive number (obtained: %s)." % (self.stock_concentration) ) self.add_error(msg)
def __check_input(self): # Checks the initialisation values. self.add_debug('Check input ...') self._check_input_class('base library layout', self.base_layout, LibraryBaseLayout) self._check_input_class('library name', self.library_name, basestring) if not is_valid_number(self.stock_concentration): msg = 'The stock concentration for the single source molecules ' \ 'must be a positive number (obtained: %s).' \ % (self.stock_concentration) self.add_error(msg)
def is_valid_mock_value(cls, value, parameter): if not super(TransfectionParameters, cls).is_valid_mock_value( value, parameter): return False if parameter in {cls.REAGENT_DIL_FACTOR, cls.OPTIMEM_DIL_FACTOR}: if value is None: return True return is_valid_number(value) elif parameter == cls.REAGENT_NAME: if value is None: return True if not isinstance(value, basestring) or not len(value) > 2: return False return True
def is_valid_mock_value(cls, value, parameter): if not super(TransfectionParameters, cls).is_valid_mock_value(value, parameter): return False if parameter in {cls.REAGENT_DIL_FACTOR, cls.OPTIMEM_DIL_FACTOR}: if value is None: return True return is_valid_number(value) elif parameter == cls.REAGENT_NAME: if value is None: return True if not isinstance(value, basestring) or not len(value) > 2: return False return True
def __check_input(self): """ Checks the input values. """ self.add_debug('Check input values ...') if isinstance(self.molecule_design_pools, (InstrumentedSet, list)): for pool in self.molecule_design_pools: self._check_input_class('library pool', pool, MoleculeDesignPool) if len(self.molecule_design_pools) < 1: msg = 'The pool list is empty!' self.add_error(msg) else: msg = 'The library pool list must be a list or an ' \ 'InstrumentedSet (obtained: %s).' % \ (self.molecule_design_pools.__class__.__name__) self.add_error(msg) if not is_valid_number(self.stock_concentration): msg = 'The stock concentration must be a positive number ' \ '(obtained: %s).' % (self.stock_concentration) self.add_error(msg) if not is_valid_number(self.take_out_volume): msg = 'The stock take out volume must be a positive number ' \ '(obtained: %s).' % (self.take_out_volume) self.add_error(msg) if self._check_input_class('excluded racks list', self.excluded_racks, list): for excl_rack in self.excluded_racks: if not self._check_input_class('excluded rack barcode', excl_rack, basestring): break if self._check_input_class('requested tubes list', self.requested_tubes, list): for req_tube in self.requested_tubes: if not self._check_input_class('requested tube barcode', req_tube, basestring): break
def __check_input(self): """ Checks the initialisation values. """ self._check_input_class('ISO request label', self.iso_request_label, basestring) numbers = {self.target_volume : 'target volume for the pool tubes', self.target_concentration : 'target concentration for the pool tubes'} for value, name in numbers.iteritems(): if not is_valid_number(value=value, is_integer=True): msg = 'The %s must be a positive number (obtained: %s).' \ % (name, value) self.add_error(msg)
def _check_input(self): """ Checks the initialisation values. """ self.add_debug('Check initialisation values ...') self._check_input_class('ISO request', self.iso_request, self.__ISO_REQUEST_CLS[self._ISO_TYPE]) self._check_input_class('job owner', self.job_owner, User) if not is_valid_number(self.number_isos, is_integer=True): msg = 'The number of ISOs order must be a positive integer ' \ '(obtained: %s).' % (self.number_isos) self.add_error(msg) self._check_input_list_classes('excluded rack', self.excluded_racks, basestring, may_be_empty=True) self._check_input_list_classes('requested tube', self.requested_tubes, basestring, may_be_empty=True)
def __check_input(self): """ Checks the initialisation values. """ self._check_input_class('ISO request label', self.iso_request_label, basestring) numbers = { self.target_volume: 'target volume for the pool tubes', self.target_concentration: 'target concentration for the pool tubes' } for value, name in numbers.iteritems(): if not is_valid_number(value=value, is_integer=True): msg = 'The %s must be a positive number (obtained: %s).' \ % (name, value) self.add_error(msg)
def set_optimem_dilution_factor(self, optimem_df): """ The OptiMem dilution factor must be a positive number. The factor might only be set ones, except for fixed positions. :raises AttributeError: If the factor has been set before. :raises ValueError: If the factor is not a positive number. """ if not is_valid_number(optimem_df): msg = 'The OptiMem dilution factor must be a positive number ' \ '(obtained: %s).' % (optimem_df) raise ValueError(msg) if not self._optimem_dil_factor is None and not self.is_fixed: raise AttributeError('The OptiMem dilution factor has already ' \ 'been set!') self._optimem_dil_factor = optimem_df
def get_cell_value(self, sheet, row_index, column_index): """ Returns the value of the specified in the given sheet. Converts the passed cell value either into a ascii string (if basestring) or a number (if non_string). """ cell_value = sheet.cell_value(row_index, column_index) cell_name = '%s%i' % (label_from_number(column_index + 1), row_index + 1) sheet_name = self.get_sheet_name(sheet) conv_value = None if isinstance(cell_value, string_types): try: conv_value = ascii_native_(cell_value) except UnicodeEncodeError: msg = 'Unknown character in cell %s (sheet "%s"). Remove ' \ 'or replace the character, please.' \ % (cell_name, sheet_name) self.add_error(msg) else: if conv_value == '': conv_value = None else: # Try to convert to an int or float. try: conv_value = int(conv_value) except ValueError: try: conv_value = float(conv_value) except ValueError: pass elif isinstance(cell_value, (float, int)): if is_valid_number(value=cell_value, is_integer=True): conv_value = int(cell_value) else: conv_value = cell_value else: msg = 'There is some unknown content in cell %s (sheet %s).' \ % (cell_name, sheet_name) self.add_error(msg) return conv_value
def check_transfers(self): """ Makes sure there is a valid number of source and target positions for each recorded transfer. """ ambiguous = [] invalid_volume = [] for step_container in self.__steps_by_row.values(): for transfer_container in step_container.get_transfer_containers(): # the 2 getters also catch code without any source or target src_positions = transfer_container.get_source_positions() trg_positions = transfer_container.get_target_positions() if src_positions is None or trg_positions is None: continue if len(src_positions) > 1 and len(trg_positions) > 1: info = '%s (step %i)' % (transfer_container.code, step_container.number) ambiguous.append(info) if not is_valid_number(transfer_container.volume): info = '%s (step %i, code %s)' % (transfer_container.volume, step_container.number, transfer_container.code) invalid_volume.append(info) if len(ambiguous) > 0: msg = 'You must not have multiple source AND target positions ' \ 'for a code since the system cannot figure out the correct ' \ 'association in this case. You can either have multiple ' \ 'source positions OR multiple target positions. The ' \ 'following transfers violate this rule: %s.' \ % (', '.join(ambiguous)) # do not sort! self._create_error(msg) if len(invalid_volume) > 0: msg = 'The transfer volume must be a positive number. The ' \ 'following transfers have invalid numbers: %s' \ % (', '.join(invalid_volume)) # do not sort! self._create_error(msg)
def _get_position_init_values(self, parameter_map, rack_pos): kw = IsoRequestLayoutConverter._get_position_init_values( self, parameter_map, rack_pos) if kw is None: return None # includes empty and untreated type pos pos_type = kw['position_type'] pos_label = rack_pos.label reagent_name = parameter_map[self.PARAMETER_SET.REAGENT_NAME] reagent_df = parameter_map[self.PARAMETER_SET.REAGENT_DIL_FACTOR] final_conc = parameter_map[self.PARAMETER_SET.FINAL_CONCENTRATION] optimem_dil_factor = None invalid = False optimem_dil_factor = parameter_map[ self.PARAMETER_SET.OPTIMEM_DIL_FACTOR] if optimem_dil_factor is not None and \ not is_valid_number(optimem_dil_factor): info = '%s (%s)' % (pos_label, optimem_dil_factor) self.__invalid_optimem_factor.append(info) invalid = True if reagent_name is None: if self.__is_mastermix_template: self.__missing_reagent_name.append(pos_label) invalid = True elif not isinstance(reagent_name, basestring) \ or len(reagent_name) < 2: self.__invalid_name.append(pos_label) invalid = True if reagent_df is None: if self.__is_mastermix_template: self.__missing_reagent_df.append(pos_label) invalid = True elif not is_valid_number(reagent_df): self.__invalid_dil_factor.append(pos_label) invalid = True if not self.__is_iso_request_layout and final_conc is None and \ not pos_type == IsoRequestParameters.MOCK_TYPE_VALUE: self.__missing_final_conc.append(pos_label) invalid = True if not final_conc is None: if pos_type == MOCK_POSITION_TYPE: if not TransfectionPosition.is_valid_mock_value( final_conc, self.PARAMETER_SET.FINAL_CONCENTRATION): info = '%s (%s)' % (pos_label, final_conc) self.__invalid_final_concentration.append(info) invalid = True elif not is_valid_number(final_conc): info = '%s (%s)' % (pos_label, final_conc) self.__invalid_final_concentration.append(info) invalid = True if invalid: return None else: kw['reagent_name'] = reagent_name kw['reagent_dil_factor'] = reagent_df kw['final_concentration'] = final_conc kw['optimem_dil_factor'] = optimem_dil_factor return kw
def _get_position_init_values(self, parameter_map, rack_pos): kw = IsoRequestLayoutConverter._get_position_init_values(self, parameter_map, rack_pos) if kw is None: return None # includes empty and untreated type pos pos_type = kw['position_type'] pos_label = rack_pos.label reagent_name = parameter_map[self.PARAMETER_SET.REAGENT_NAME] reagent_df = parameter_map[self.PARAMETER_SET.REAGENT_DIL_FACTOR] final_conc = parameter_map[self.PARAMETER_SET.FINAL_CONCENTRATION] optimem_dil_factor = None invalid = False optimem_dil_factor = parameter_map[ self.PARAMETER_SET.OPTIMEM_DIL_FACTOR] if optimem_dil_factor is not None and \ not is_valid_number(optimem_dil_factor): info = '%s (%s)' % (pos_label, optimem_dil_factor) self.__invalid_optimem_factor.append(info) invalid = True if reagent_name is None: if self.__is_mastermix_template: self.__missing_reagent_name.append(pos_label) invalid = True elif not isinstance(reagent_name, basestring) \ or len(reagent_name) < 2: self.__invalid_name.append(pos_label) invalid = True if reagent_df is None: if self.__is_mastermix_template: self.__missing_reagent_df.append(pos_label) invalid = True elif not is_valid_number(reagent_df): self.__invalid_dil_factor.append(pos_label) invalid = True if not self.__is_iso_request_layout and final_conc is None and \ not pos_type == IsoRequestParameters.MOCK_TYPE_VALUE: self.__missing_final_conc.append(pos_label) invalid = True if not final_conc is None: if pos_type == MOCK_POSITION_TYPE: if not TransfectionPosition.is_valid_mock_value(final_conc, self.PARAMETER_SET.FINAL_CONCENTRATION): info = '%s (%s)' % (pos_label, final_conc) self.__invalid_final_concentration.append(info) invalid = True elif not is_valid_number(final_conc): info = '%s (%s)' % (pos_label, final_conc) self.__invalid_final_concentration.append(info) invalid = True if invalid: return None else: kw['reagent_name'] = reagent_name kw['reagent_dil_factor'] = reagent_df kw['final_concentration'] = final_conc kw['optimem_dil_factor'] = optimem_dil_factor return kw