def _get_layouts(self): """ The final layouts and ISO preparation layouts for all ISOs are compared and then a reference layout for each rack marker is picked. For job preparation plates, we store layout and rack. """ for prep_plate in self.entity.iso_job_preparation_plates: converter = LabIsoPrepLayoutConverter( rack_layout=prep_plate.rack_layout, parent=self) plate_label = prep_plate.rack.label error_label = 'job preparation plate "%s"' % ( prep_plate.rack.label) self._store_plate_layout(plate_label, converter, error_label) self._store_rack_container(prep_plate.rack, LABELS.ROLE_PREPARATION_JOB, plate_label) final_layouts = dict() for iso in self.entity.isos: converter = FinalLabIsoLayoutConverter(rack_layout=iso.rack_layout, parent=self) error_label = 'final plate layout for ISO "%s"' % (iso.label) self._store_plate_layout(iso.label, converter, error_label) if self.has_errors(): continue self._store_final_plate_data(iso) final_layouts[iso.label] = self._plate_layouts[iso.label] self.__compare_final_layouts(final_layouts) self.__compare_iso_preparation_layouts()
def __compare_iso_preparation_layouts(self): # If we have starting wells for the job in ISO preparation plates and # more than one ISO in the job, we need to remove duplicates (to avoid # generation of duplicate transfers in stock worklists). # We store the layout of a reference plate (using the label of this # plate as key). Plate containers are stored for all plates. position_map = dict() reference_plates = dict() reference_layouts = dict() for iso in self.entity.isos: if self.has_errors(): break for ipp in iso.iso_preparation_plates: plate = ipp.rack plate_label = plate.label value_parts = LABELS.parse_rack_label(plate_label) rack_marker = value_parts[LABELS.MARKER_RACK_MARKER] self._store_rack_container(rack=plate, label=plate_label, rack_marker=rack_marker, role=LABELS.ROLE_PREPARATION_ISO) converter = LabIsoPrepLayoutConverter( rack_layout=ipp.rack_layout, parent=self) layout = converter.get_result() if layout is None: msg = 'Error when trying to convert ISO preparation ' \ 'plate layout for plate "%s".' % (plate_label) self.add_error(msg) break positions = [] for prep_pos in layout.get_sorted_working_positions(): if prep_pos.is_fixed and prep_pos.is_starting_well: positions.append(prep_pos) if not position_map.has_key(rack_marker): position_map[rack_marker] = positions reference_plates[rack_marker] = plate reference_layouts[rack_marker] = layout elif not position_map[rack_marker] == positions: msg = 'The ISO preparation plates for rack type "%s" are ' \ 'inconsistent!' % (rack_marker) self.add_error(msg) break for rack_marker, plate in reference_plates.iteritems(): layout = reference_layouts[rack_marker] self._plate_layouts[plate.label] = layout
def _fetch_expected_layout(self): """ The layouts for preparation plates can be derived from the plate entity. Final plate layouts must be delivered because they are stored at the ISO. """ if isinstance(self.lab_iso_plate, (IsoAliquotPlate, LibraryPlate)): msg = 'The reference layout for a final ISO plate must not ' \ 'be None!' self.add_error(msg) elif isinstance(self.lab_iso_plate, (IsoPreparationPlate, IsoJobPreparationPlate)): converter = LabIsoPrepLayoutConverter( self.lab_iso_plate.rack_layout, parent=self) self._expected_layout = converter.get_result() if self._expected_layout is None: msg = 'Error when trying to convert preparation plate layout!' self.add_error(msg) else: msg = 'Unexpected ISO plate type: %s.' \ % (self.lab_iso_plate.__class__.__name__) self.add_error(msg)
def _get_layouts(self): """ There is one final layout for the ISO. There can be preparation plates as well. """ for prep_plate in self.entity.iso_preparation_plates: converter = LabIsoPrepLayoutConverter( rack_layout=prep_plate.rack_layout, parent=self) plate_label = prep_plate.rack.label error_label = \ 'ISO preparation plate "%s"' % (prep_plate.rack.label) self._store_plate_layout(plate_label, converter, error_label) self._store_rack_container(prep_plate.rack, LABELS.ROLE_PREPARATION_ISO, plate_label) converter = FinalLabIsoLayoutConverter( rack_layout=self.entity.rack_layout, parent=self) self._store_plate_layout(LABELS.ROLE_FINAL, converter, 'final ISO plate layout') self._store_final_plate_data(self.entity)
def _store_and_verify_plate(self, iso_plate, layout=None, verify=True): """ Convenience method verifying and storing the plate as rack container in the :attr:`_rack_containers` map (mapped onto the rack marker). If the expected ISO status is queued all plates must be empty, otherwise we need a :class:`LabIsoPlateVerifier`. """ plate = iso_plate.rack rack_name = '%s (%s)' % (plate.barcode, plate.label) if self._expected_iso_status == ISO_STATUS.QUEUED and verify: sample_positions = [] for well in plate.containers: if well.sample is not None: if layout is not None: ip = layout.get_working_position(well.position) if ip is not None and ip.is_library: continue sample_positions.append(well.position.label) if len(sample_positions) > 0: msg = 'Plate %s should be empty but there are samples in ' \ 'the following positions: %s.' \ % (plate.label, self._get_joined_str(sample_positions)) self.add_error(msg) return None if not isinstance(iso_plate, (IsoAliquotPlate, LibraryPlate)): converter = LabIsoPrepLayoutConverter(iso_plate.rack_layout, parent=self) layout = converter.get_result() if layout is None: msg = 'Error when trying to convert layout of plate "%s"!' \ % (plate.label) self.add_error(msg) return None else: self.__plate_layouts[plate.label] = layout elif verify: verifier = LabIsoPlateVerifier(iso_plate, self.ENTITY_CLS == IsoJob, lab_iso_layout=layout, parent=self) compatible = verifier.get_result() if compatible is None: msg = 'Error when trying to verify plate %s!' % (rack_name) self.add_error(msg) return None elif not compatible: msg = 'Rack %s does not match the expected layout!' \ % (rack_name) self.add_error(msg) return None elif layout is None: self.__plate_layouts[plate.label] = \ verifier.get_expected_layout() iso = None if self._processing_order == LAB_ISO_ORDERS.NO_ISO and \ isinstance(iso_plate, LibraryPlate): rack_marker = LABELS.ROLE_FINAL iso = iso_plate.lab_iso else: values = LABELS.parse_rack_label(plate.label) rack_marker = values[LABELS.MARKER_RACK_MARKER] rack_container = IsoRackContainer(rack=plate, rack_marker=rack_marker) if rack_container.role == LABELS.ROLE_FINAL: rack_marker = LABELS.ROLE_FINAL if iso is None: iso = iso_plate.iso add_list_map_element(self.__final_plates, iso, rack_container) add_list_map_element(self.__rack_containers, rack_marker, rack_container)