Exemplo n.º 1
0
    def humanize_address(self, address):
        """
        Returns a human-readable string for a particular address.

        If ((0, 0), (1, 0)) is passed and no labels are attached to
        A1, this will return 'A1:B1'.

        For ('label', (1, 0)), it will return the valid label with
        the first provided capitalization, for example "LaBeL:B1".
        """
        start, end = address
        try:
            start = normalize_position(start)  # Try to convert 'A1'.
            # Find a label for that tuple position.
            label = self.get_container_label(start)
            if label is not None:
                start = label
        except ValueError:
            # If it's not a tuple position, it's a string label.
            if start.lower() not in self._container_labels:
                raise x.ContainerMissing(
                    "Invalid container: {}".format(start)
                )
            start = self._label_case.get(start.lower(), start)
        end = humanize_position(end)
        return "{}:{}".format(start, end)
Exemplo n.º 2
0
 def get_coordinates(self, position, axis=None, tool=None):
     """ Returns the calibrated coordinates for a position. """
     if len(position) == 1:
         position = [position[0], (0, 0)]
     if tool is not None:
         axis = tool.axis
     cal = self.get_axis_calibration(axis)
     slot, well = position
     if slot not in cal:
         raise ex.CalibrationMissing(
             "No calibration for {} (axis {}).".format(
                 humanize_position(slot), axis))
     defaults = ({'top': 0, 'bottom': 0, 'x': 0, 'y': 0})
     output = {}
     # Calibration for A1 in this container (x, y, top, bottom).
     slot_cal = {}
     slot_cal.update(defaults)
     slot_cal.update(cal.get((slot), {}))
     # Default offset on x, y calculated from container definition.
     ox, oy = self._deck.slot(slot).get_child(well).coordinates()
     # x, y, top bottom
     well_cal = cal.get((slot, well), {})
     output.update(well_cal)
     # Use calculated offsets if no custom well calibration provided.
     if 'x' not in output:
         output['x'] = slot_cal['x'] + ox
     if 'y' not in output:
         output['y'] = slot_cal['y'] + oy
     # Merge slot and well calibration
     if 'top' not in output:
         output['top'] = slot_cal['top']
     if 'bottom' not in output:
         output['bottom'] = slot_cal['bottom']
     return output
Exemplo n.º 3
0
 def find_well(self, value):
     """
     Returns the well position on this plate matching a particular value.
     """
     for pos in sorted(self.map.keys()):
         if self.map[pos].strip() == value:
             return humanize_position(pos)
Exemplo n.º 4
0
 def find_well(self, value):
     """
     Returns the well position on this plate matching a particular value.
     """
     for pos in sorted(self.map.keys()):
         if self.map[pos].strip() == value:
             return humanize_position(pos)
Exemplo n.º 5
0
 def get_coordinates(self, position, axis=None, tool=None):
     """ Returns the calibrated coordinates for a position. """
     if len(position) == 1:
         position = [position[0], (0, 0)]
     if tool is not None:
         axis = tool.axis
     cal = self.get_axis_calibration(axis)
     slot, well = position
     if slot not in cal:
         raise ex.CalibrationMissing(
             "No calibration for {} (axis {}).".
             format(humanize_position(slot), axis)
         )
     defaults = ({'top': 0, 'bottom': 0, 'x': 0, 'y': 0})
     output = {}
     # Calibration for A1 in this container (x, y, top, bottom).
     slot_cal = {}
     slot_cal.update(defaults)
     slot_cal.update(cal.get((slot), {}))
     # Default offset on x, y calculated from container definition.
     ox, oy = self._deck.slot(slot).get_child(well).coordinates()
     # x, y, top bottom
     well_cal = cal.get((slot, well), {})
     output.update(well_cal)
     # Use calculated offsets if no custom well calibration provided.
     if 'x' not in output:
         output['x'] = slot_cal['x'] + ox
     if 'y' not in output:
         output['y'] = slot_cal['y'] + oy
     # Merge slot and well calibration
     if 'top' not in output:
         output['top'] = slot_cal['top']
     if 'bottom' not in output:
         output['bottom'] = slot_cal['bottom']
     return output
Exemplo n.º 6
0
 def slot(self, position):
     pos = self._normalize_position(position)
     if pos not in self._children:
         raise x.ContainerMissing(
             "No deck module at slot {}."
             .format(humanize_position(pos))
         )
     return self._children[pos]
Exemplo n.º 7
0
 def slot(self, position):
     pos = self._normalize_position(position)
     if pos not in self._children:
         raise KeyError(
             "No deck module at slot {}/{}."
             .format(humanize_position(pos), pos)
         )
     return self._children[pos]
Exemplo n.º 8
0
 def add_module(self, position, mod):
     pos = self._normalize_position(position)
     if isinstance(mod, str):
         mod = load_container(mod)()
     if pos not in self._children:
         self._children[pos] = mod
         mod.position = position
     else:
         raise x.ContainerConflict(
             "Module already allocated to slot: {}.".format(
                 humanize_position(pos)))
Exemplo n.º 9
0
 def add_module(self, position, mod):
     pos = self._normalize_position(position)
     if isinstance(mod, str):
         mod = load_container(mod)()
     if pos not in self._children:
         self._children[pos] = mod
         mod.position = position
     else:
         raise x.ContainerConflict(
             "Module already allocated to slot: {}."
             .format(humanize_position(pos))
         )
Exemplo n.º 10
0
 def map(self):
     """
     Uses the coordinates of label cell to list plate contents by well.
     """
     plate_map = {}
     for col in range(0, self._cols):
         for row in range(0, self._rows):
             pos = (col, row)
             loc = humanize_position(pos)
             data = self.get_well(pos)
             if data:
                 plate_map[loc] = data
     return plate_map
Exemplo n.º 11
0
 def map(self):
     """
     Uses the coordinates of label cell to list plate contents by well.
     """
     plate_map = {}
     for col in range(0, self._cols):
         for row in range(0, self._rows):
             pos = (col, row)
             loc = humanize_position(pos)
             data = self.get_well(pos)
             if data:
                 plate_map[loc] = data
     return plate_map
Exemplo n.º 12
0
 def apply_protocol(self, b):
     """
     Applies all the operational data from another Protocol to this one.
     """
     # Second info supercedes first.
     self.set_info(**b.info)
     # Add the containers from second.
     for slot, name in b._containers.items():
         if slot in self._containers and self._containers[slot] != name:
             raise x.ContainerConflict(
                 "Slot {} already allocated to {}".format(slot, name)
             )
         if slot not in self._containers:
             # Add container if it's not there already.
             self.add_container(slot, name)
     # Add the labels from second.
     labels = {v: k for k, v in self._container_labels.items()}
     for label, slot in b._container_labels.items():
         if slot in labels and labels[slot] != label:
             raise x.ContainerConflict(
                 "Conflicting labels at {}: {} vs {}"
                 .format(
                     humanize_position(slot),
                     labels[slot],
                     label
                 )
             )
         self._container_labels[label] = slot
     # Supercede labelcase from second.
     for label, case in b._label_case.items():
         self._label_case[label] = case
     # Add the instruments from second.
     for axis, name in b._head.items():
         if axis in self._head \
            and self._head[axis] != name:
             raise x.InstrumentConflict(
                 "Axis {} already allocated to {}".format(axis, name)
             )
         self.add_instrument(axis, name)
     # Rerun command definitions from second.
     for command in b.actions:
         c = copy.deepcopy(command)
         # Make sure this command runs properly.
         self.add_command(c.pop('command'), **c)
         self.commands.append(command)
Exemplo n.º 13
0
    def export(self):
        info = OrderedDict()
        i = self._protocol.info
        order = ['name', 'author', 'description', 'version', 'version_hash',
                 'created', 'updated']
        for key in order:
            v = i.pop(key, None)
            if v is not None:
                info[key] = v

        instruments = OrderedDict()
        for axis, name in sorted(self._protocol.instruments.items()):
            label = "{}_{}".format(name, axis.lower())
            instruments[label] = OrderedDict([
                ('axis', axis),
                ('name', name)
            ])

        modules = []
        for slot, name in sorted(self._protocol._containers.items()):
            c = OrderedDict([('name', name)])
            label = self._protocol.get_container_label(slot)
            if label:
                c['label'] = label
            if slot:
                c['slot'] = humanize_position(slot)
            modules.append(c)

        instructions = []
        for command in self._protocol.commands:
            command = self._export_command(command)
            instructions.append(command)

        out = OrderedDict()
        out['info'] = info
        out['instruments'] = instruments
        out['containers'] = modules
        out['instructions'] = instructions
        return json.dumps(out, indent=4)
Exemplo n.º 14
0
    def test_well_offsets(self):
        """
        Well offsets.
        """

        # We have a plate map listing offset order.
        cdir = os.path.dirname(os.path.realpath(__file__))
        self.csv_file = os.path.join(
            cdir,
            '../../fixtures/offset_map.csv'
        )
        self.plate_map = PlateMap(self.csv_file)
        plate = self.plate_map.get_plate('A1', rotated=True)

        # Go through every row, col in a standard 96 well plate
        # and check against the documented offset order.
        n = 0
        for col in range(0, 8):
            for row in range(0, 12):
                c = humanize_position((col, row))
                self.assertEqual(int(plate.get_well(c)), n)
                n += 1
Exemplo n.º 15
0
    def test_well_offsets(self):
        """
        Well offsets.
        """

        # We have a plate map listing offset order.
        cdir = os.path.dirname(os.path.realpath(__file__))
        self.csv_file = os.path.join(
            cdir,
            '../../fixtures/offset_map.csv'
        )
        self.plate_map = PlateMap(self.csv_file)
        plate = self.plate_map.get_plate('A1', rotated=True)

        # Go through every row, col in a standard 96 well plate
        # and check against the documented offset order.
        n = 0
        for col in range(0, 8):
            for row in range(0, 12):
                c = humanize_position((col, row))
                self.assertEqual(int(plate.get_well(c)), n)
                n += 1
Exemplo n.º 16
0
 def apply_protocol(self, b):
     """
     Applies all the operational data from another Protocol to this one.
     """
     # Second info supercedes first.
     self.set_info(**b.info)
     # Add the containers from second.
     for slot, name in b._containers.items():
         if slot in self._containers and self._containers[slot] != name:
             raise x.ContainerConflict(
                 "Slot {} already allocated to {}".format(slot, name))
         if slot not in self._containers:
             # Add container if it's not there already.
             self.add_container(slot, name)
     # Add the labels from second.
     labels = {v: k for k, v in self._container_labels.items()}
     for label, slot in b._container_labels.items():
         if slot in labels and labels[slot] != label:
             raise x.ContainerConflict(
                 "Conflicting labels at {}: {} vs {}".format(
                     humanize_position(slot), labels[slot], label))
         self._container_labels[label] = slot
     # Supercede labelcase from second.
     for label, case in b._label_case.items():
         self._label_case[label] = case
     # Add the instruments from second.
     for axis, name in b._head.items():
         if axis in self._head \
            and self._head[axis] != name:
             raise x.InstrumentConflict(
                 "Axis {} already allocated to {}".format(axis, name))
         self.add_instrument(axis, name)
     # Rerun command definitions from second.
     for command in b.actions:
         c = copy.deepcopy(command)
         # Make sure this command runs properly.
         self.add_command(c.pop('command'), **c)
         self.commands.append(command)
Exemplo n.º 17
0
    def export(self):
        info = OrderedDict()
        i = self._protocol.info
        order = [
            'name', 'author', 'description', 'version', 'version_hash',
            'created', 'updated'
        ]
        for key in order:
            v = i.pop(key, None)
            if v is not None:
                info[key] = v

        instruments = OrderedDict()
        for axis, name in sorted(self._protocol.instruments.items()):
            label = "{}_{}".format(name, axis.lower())
            instruments[label] = OrderedDict([('axis', axis), ('name', name)])

        modules = []
        for slot, name in sorted(self._protocol._containers.items()):
            c = OrderedDict([('name', name)])
            label = self._protocol.get_container_label(slot)
            if label:
                c['label'] = label
            if slot:
                c['slot'] = humanize_position(slot)
            modules.append(c)

        instructions = []
        for command in self._protocol.commands:
            command = self._export_command(command)
            instructions.append(command)

        out = OrderedDict()
        out['info'] = info
        out['instruments'] = instruments
        out['containers'] = modules
        out['instructions'] = instructions
        return json.dumps(out, indent=4)
Exemplo n.º 18
0
    def humanize_address(self, address):
        """
        Returns a human-readable string for a particular address.

        If ((0, 0), (1, 0)) is passed and no labels are attached to
        A1, this will return 'A1:B1'.

        For ('label', (1, 0)), it will return the valid label with
        the first provided capitalization, for example "LaBeL:B1".
        """
        start, end = address
        try:
            start = normalize_position(start)  # Try to convert 'A1'.
            # Find a label for that tuple position.
            label = self.get_container_label(start)
            if label is not None:
                start = label
        except ValueError:
            # If it's not a tuple position, it's a string label.
            if start.lower() not in self._container_labels:
                raise x.ContainerMissing("Invalid container: {}".format(start))
            start = self._label_case.get(start.lower(), start)
        end = humanize_position(end)
        return "{}:{}".format(start, end)
Exemplo n.º 19
0
 def slot(self, position):
     pos = self._normalize_position(position)
     if pos not in self._children:
         raise x.ContainerMissing("No deck module at slot {}.".format(
             humanize_position(pos)))
     return self._children[pos]