Esempio n. 1
0
    def _normalize_address(self, address):
        """
        Takes an address like "A1:A1" or "Ingredients:A1" and returns a tuple
        like ((0, 0), (0, 0)).

        To retain label names, use humanize_address.
        """

        if ':' not in address:
            raise ValueError(
                "Address must be in the form of 'container:well'.")

        container, well = address.split(':')
        well = normalize_position(well)

        try:
            container = normalize_position(container)
        except ValueError:
            # Try to find the slot as a label.
            container = container.lower()
            if container not in self._container_labels:
                raise x.ContainerMissing(
                    "Container not found: {}".format(address))
            container = self._container_labels[container]

        return (container, well)
Esempio n. 2
0
    def _normalize_address(self, address):
        """
        Takes an address like "A1:A1" or "Ingredients:A1" and returns a tuple
        like (0, 0) or ('ingredients', 0).

        Container labels are retained in the address tuples so that named
        containers can be assigned to different slots within the user
        interface.
        """

        if ':' not in address:
            raise ValueError(
                "Address must be in the form of 'container:well'."
            )

        container, well = address.split(':')
        well = normalize_position(well)

        try:
            container = normalize_position(container)
        except ValueError:
            container = container.lower()
            if container not in self._container_labels:
                raise KeyError("Container not found: {}".format(container))

        return (container, well)
Esempio n. 3
0
    def _normalize_address(self, address):
        """
        Takes an address like "A1:A1" or "Ingredients:A1" and returns a tuple
        like ((0, 0), (0, 0)).

        To retain label names, use humanize_address.
        """

        if ':' not in address:
            raise ValueError(
                "Address must be in the form of 'container:well'."
            )

        container, well = address.split(':')
        well = normalize_position(well)

        try:
            container = normalize_position(container)
        except ValueError:
            # Try to find the slot as a label.
            container = container.lower()
            if container not in self._container_labels:
                raise x.ContainerMissing(
                    "Container not found: {}".format(address)
                )
            container = self._container_labels[container]

        return (container, well)
Esempio n. 4
0
    def test_normalize_position(self):
        """
        Normalize coordinate strings ('A1')
        """
        expected = normalize_position('A1')
        self.assertEqual(expected, (0, 0))

        expected = normalize_position('B1')
        self.assertEqual(expected, (1, 0))

        expected = normalize_position('C2')
        self.assertEqual(expected, (2, 1))
Esempio n. 5
0
    def test_normalize_position(self):
        """
        Normalize coordinate strings ('A1')
        """
        expected = normalize_position('A1')
        self.assertEqual(expected, (0, 0))

        expected = normalize_position('B1')
        self.assertEqual(expected, (1, 0))

        expected = normalize_position('C2')
        self.assertEqual(expected, (2, 1))
Esempio n. 6
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)
Esempio n. 7
0
    def get_plate(self, label_cell, **kwargs):
        """
        Takes the 'label cell' of a plate definition and returns a Plate
        object set to that particular starting position within the CSV.

        Then you can use Plate to get the string contents of particular
        wells on that plate within the definition file.

        For example:

            plate_map.get_plate('K2').get_well('H12')

        Where 'K2' is the spreadsheet cell containing the plate label and
        'H12' is the specific well in that plate.
        """

        # If the label_cell is in labels, use that position instead of
        # converting it to a coordinate tuple.
        #
        # Only works for 96 well plates for now.
        if label_cell in self._labels:
            label_cell = self._labels[label_cell]

        # Pass default orientation option.
        if 'rotated' not in kwargs and self._rotated is not None:
            kwargs['rotated'] = self._rotated

        col, row = normalize_position(label_cell)
        start = (col, row)
        if start not in self._plates:
            self._plates[start] = Plate(start, self._sheet, **kwargs)
        return self._plates[start]
Esempio n. 8
0
 def add_plate(self, label, start, **kwargs):
     """
     Allows adding plates by reference along with config vars.
     """
     start = normalize_position(start)
     self._labels[label] = start
     self._plates[start] = self.get_plate(start, **kwargs)
Esempio n. 9
0
 def add_container(self, slot, name, label=None):
     slot = normalize_position(slot)
     self._context_handler.add_container(slot, name)
     self._containers[slot] = name
     if (label):
         label = label.lower()
         self._container_labels[label] = slot
Esempio n. 10
0
    def get_plate(self, label_cell, **kwargs):
        """
        Takes the 'label cell' of a plate definition and returns a Plate
        object set to that particular starting position within the CSV.

        Then you can use Plate to get the string contents of particular
        wells on that plate within the definition file.

        For example:

            plate_map.get_plate('K2').get_well('H12')

        Where 'K2' is the spreadsheet cell containing the plate label and
        'H12' is the specific well in that plate.
        """

        # If the label_cell is in labels, use that position instead of
        # converting it to a coordinate tuple.
        #
        # Only works for 96 well plates for now.
        if label_cell in self._labels:
            label_cell = self._labels[label_cell]

        # Pass default orientation option.
        if 'rotated' not in kwargs and self._rotated is not None:
            kwargs['rotated'] = self._rotated

        col, row = normalize_position(label_cell)
        start = (col, row)
        if start not in self._plates:
            self._plates[start] = Plate(start, self._sheet, **kwargs)
        return self._plates[start]
Esempio n. 11
0
 def add_plate(self, label, start, **kwargs):
     """
     Allows adding plates by reference along with config vars.
     """
     start = normalize_position(start)
     self._labels[label] = start
     self._plates[start] = self.get_plate(start, **kwargs)
Esempio n. 12
0
 def test_nonletter_colum(self):
     """
     Exception on invalid coordinate string (']1').
     """
     # Make sure the entire valid range works.
     normalize_position('A1')
     normalize_position('Z1')
     # Test out of range (@ and ] are the edges of A-Z in ASCII).
     with self.assertRaises(ValueError):
         normalize_position(']1')
     with self.assertRaises(ValueError):
         normalize_position('@1')
Esempio n. 13
0
 def test_nonletter_colum(self):
     """
     Exception on invalid coordinate string (']1').
     """
     # Make sure the entire valid range works.
     normalize_position('A1')
     normalize_position('Z1')
     # Test out of range (@ and ] are the edges of A-Z in ASCII).
     with self.assertRaises(ValueError):
         normalize_position(']1')
     with self.assertRaises(ValueError):
         normalize_position('@1')
Esempio n. 14
0
 def add_container(self, slot, name, label=None):
     slot = normalize_position(slot)
     if (label):
         lowlabel = label.lower()
         if lowlabel in self._container_labels:
             raise x.ContainerConflict(
                 "Label already in use: {}".format(label))
         # Maintain label capitalization, but only one form.
         if lowlabel not in self._label_case:
             self._label_case[lowlabel] = label
         self._container_labels[lowlabel] = slot
     self._context_handler.add_container(slot, name)
     self._containers[slot] = name
Esempio n. 15
0
 def add_container(self, slot, name, label=None):
     slot = normalize_position(slot)
     if (label):
         lowlabel = label.lower()
         if lowlabel in self._container_labels:
             raise x.ContainerConflict(
                 "Label already in use: {}".format(label)
             )
         # Maintain label capitalization, but only one form.
         if lowlabel not in self._label_case:
             self._label_case[lowlabel] = label
         self._container_labels[lowlabel] = slot
     self._context_handler.add_container(slot, name)
     self._containers[slot] = name
Esempio n. 16
0
    def _get_slot(self, name):
        """
        Returns a container within a given slot, can take a slot position
        as a tuple (0, 0) or as a user-friendly name ('A1') or as a label
        ('ingredients').
        """
        slot = None

        try:
            slot = normalize_position(name)
        except TypeError:
            if slot in self._container_labels:
                slot = self._container_labels[slot]

        if not slot:
            raise KeyError("Slot not defined: " + name)
        if slot not in self._deck:
            raise KeyError("Nothing in slot: " + name)

        return self._deck[slot]
Esempio n. 17
0
    def get_well(self, well):
        """
        Returns the contents of the cell of the CSV range attached to this
        particular plate mapping to the given well coordinates.

        For example, well A1 might actually be B36 in the CSV.

        Contents are simply whatever string is stored in the cell of that
        particular location in the Excel-based plate mapping.
        """
        col, row = normalize_position(well)
        scol, srow = self._start
        if (self._rotated):
            cell_col = scol + col + 1
            cell_row = srow + self._rows - row
        else:
            cell_row = srow + col + 1
            cell_col = scol + row + 1

        return self._sheet.get_cell((cell_col, cell_row))
Esempio n. 18
0
    def get_well(self, well):
        """
        Returns the contents of the cell of the CSV range attached to this
        particular plate mapping to the given well coordinates.

        For example, well A1 might actually be B36 in the CSV.

        Contents are simply whatever string is stored in the cell of that
        particular location in the Excel-based plate mapping.
        """
        col, row = normalize_position(well)
        scol, srow = self._start
        if (self._rotated):
            cell_col = scol + col + 1
            cell_row = srow + self._rows - row
        else:
            cell_row = srow + col + 1
            cell_col = scol + row + 1

        return self._sheet.get_cell((cell_col, cell_row))
Esempio n. 19
0
    def _get_slot(self, name):
        """
        Returns a container within a given slot, can take a slot position
        as a tuple (0, 0) or as a user-friendly name ('A1') or as a label
        ('ingredients').
        """
        slot = None

        try:
            slot = normalize_position(name)
        except TypeError:
            # Try to find the slot as a label.
            if slot in self._container_labels:
                slot = self._container_labels[slot]

        if not slot:
            raise x.MissingContainer("No slot defined for {}".format(name))
        if slot not in self._deck:
            raise x.MissingContainer("Nothing in slot: {}".format(name))

        return self._deck[slot]
Esempio n. 20
0
    def _get_slot(self, name):
        """
        Returns a container within a given slot, can take a slot position
        as a tuple (0, 0) or as a user-friendly name ('A1') or as a label
        ('ingredients').
        """
        slot = None

        try:
            slot = normalize_position(name)
        except TypeError:
            # Try to find the slot as a label.
            if slot in self._container_labels:
                slot = self._container_labels[slot]

        if not slot:
            raise x.MissingContainer("No slot defined for {}".format(name))
        if slot not in self._deck:
            raise x.MissingContainer("Nothing in slot: {}".format(name))

        return self._deck[slot]
Esempio n. 21
0
def convert_legacy_container(container):
    """
    Takes the dict from an old-style legacy containers.json format and
    converts it to the new format for serializing to YAML.
    """

    lines = []

    wells = container['locations']

    a1 = wells.get('A1')
    b1 = wells.get('B1', {})
    a2 = wells.get('A2', {})

    out = {}

    out['volume'] = a1.get('total-liquid-volume', 0)
    out['diameter'] = a1.get('diameter', 0)
    out['well_depth'] = a1.get('depth', 0)
    out['height'] = a1.get('depth', 0)
    out['a1_x'] = container.get('origin-offset', {'x': 0}).get('x')
    out['a1_y'] = container.get('origin-offset', {'y': 0}).get('y')

    spacing_x = b1.get('x', 0)
    spacing_y = a2.get('y', 0)

    if spacing_x == spacing_y:
        out['spacing'] = spacing_y
    else:
        out['col_spacing'] = spacing_x
        out['row_spacing'] = spacing_y

    max_col, max_row = normalize_position(max(wells.keys()))

    out['rows'] = max_row + 1
    out['cols'] = max_col + 1

    return out
Esempio n. 22
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)
Esempio n. 23
0
def convert_legacy_container(container):
    """
    Takes the dict from an old-style legacy containers.json format and
    converts it to the new format for serializing to YAML.
    """

    wells = container['locations']

    a1 = wells.get('A1')
    b1 = wells.get('B1', {})
    a2 = wells.get('A2', {})

    out = {}

    out['volume'] = a1.get('total-liquid-volume', 0)
    out['diameter'] = a1.get('diameter', 0)
    out['well_depth'] = a1.get('depth', 0)
    out['height'] = a1.get('depth', 0)
    out['a1_x'] = container.get('origin-offset', {'x': 0}).get('x')
    out['a1_y'] = container.get('origin-offset', {'y': 0}).get('y')

    spacing_x = b1.get('x', 0)
    spacing_y = a2.get('y', 0)

    if spacing_x == spacing_y:
        out['spacing'] = spacing_y
    else:
        out['col_spacing'] = spacing_x
        out['row_spacing'] = spacing_y

    max_col, max_row = normalize_position(max(wells.keys()))

    out['rows'] = max_row + 1
    out['cols'] = max_col + 1

    return out
Esempio n. 24
0
 def get_cell(self, position):
     col, row = normalize_position(position)
     return self._data[row][col]
Esempio n. 25
0
 def test_mistyped_tuple(self):
     """
     Raise exception on mistyped tuple (char, int).
     """
     with self.assertRaises(TypeError):
         normalize_position(('a', 1))
Esempio n. 26
0
 def test_tuple(self):
     """
     Passthrough normalization of 2-member tuple.
     """
     expected = normalize_position((2, 1))
     self.assertEqual(expected, (2, 1))
Esempio n. 27
0
 def test_long_tuple(self):
     """
     Raise exception on three-member tuple.
     """
     with self.assertRaises(TypeError):
         normalize_position((1, 2, 3))
Esempio n. 28
0
 def calibrate(self, position, **kwargs):
     if ':' in position:
         pos = self._normalize_address(position)
     else:
         pos = normalize_position(position)
     self._context_handler.calibrate(pos, **kwargs)
Esempio n. 29
0
 def test_tuple(self):
     """
     Passthrough normalization of 2-member tuple.
     """
     expected = normalize_position((2, 1))
     self.assertEqual(expected, (2, 1))
Esempio n. 30
0
 def test_short_tuple(self):
     """
     Raise exception on one-member tuple.
     """
     with self.assertRaises(TypeError):
         normalize_position((1))
Esempio n. 31
0
 def test_short_tuple(self):
     """
     Raise exception on one-member tuple.
     """
     with self.assertRaises(TypeError):
         normalize_position((1))
Esempio n. 32
0
 def test_invalid_coordinate_string(self):
     """
     Exception on invalid coordinate string ('11').
     """
     with self.assertRaises(ValueError):
         normalize_position('11')
Esempio n. 33
0
 def test_invalid_coordinate_string(self):
     """
     Exception on invalid coordinate string ('11').
     """
     with self.assertRaises(ValueError):
         normalize_position('11')
Esempio n. 34
0
 def calibrate(self, position, **kwargs):
     if ':' in position:
         pos = self._normalize_address(position)
     else:
         pos = normalize_position(position)
     self._context_handler.calibrate(pos, **kwargs)
Esempio n. 35
0
 def test_lowercase(self):
     """
     Normalize lowercase coordinate strings ('a1')
     """
     expected = normalize_position('c2')
     self.assertEqual(expected, (2, 1))
Esempio n. 36
0
 def test_long_tuple(self):
     """
     Raise exception on three-member tuple.
     """
     with self.assertRaises(TypeError):
         normalize_position((1, 2, 3))
Esempio n. 37
0
 def test_mistyped_tuple(self):
     """
     Raise exception on mistyped tuple (char, int).
     """
     with self.assertRaises(TypeError):
         normalize_position(('a', 1))
Esempio n. 38
0
 def get_cell(self, position):
     col, row = normalize_position(position)
     return self._data[row][col]
Esempio n. 39
0
 def test_lowercase(self):
     """
     Normalize lowercase coordinate strings ('a1')
     """
     expected = normalize_position('c2')
     self.assertEqual(expected, (2, 1))
Esempio n. 40
0
 def test_multidigit_row(self):
     """
     Multiple digits in the coordinate row ('b222')
     """
     expected = normalize_position('b222')
     self.assertEqual(expected, (1, 221))
Esempio n. 41
0
 def test_multidigit_row(self):
     """
     Multiple digits in the coordinate row ('b222')
     """
     expected = normalize_position('b222')
     self.assertEqual(expected, (1, 221))