Tutorial: Plate Quadrants#

Note: This notebook can be downloaded and used directly.

In many automated protocols liquid transfers have to be performed between different plate formats, e.g.: between 96-wellplate to 24-wellplates, or between 384-wellplates to 96-wellplates.

To facilitate these liquid transfers, PLR standardized the definition of Plate “Quadrants” and enables dynamically accessing these quadrants to generate complex transfer pipetting patterns with ease:

Plate_instance.get_quadrant(
    quadrant: Literal[
      "tl", "top_left",
      "tr", "top_right",
      "bl", "bottom_left",
      "br", "bottom_right"
    ],
    quadrant_type: Literal["block", "checkerboard"] = "checkerboard",
    quadrant_internal_fill_order: Literal["column-major", "row-major"] = "column-major",
  ) -> List["Well"]

Attribute Explanations#

Quadrant Type#

Depending on 1) manual vs fully-automated processing, and 2) y-channel spacing ability, two common definitions for “quadrant types” are:

  • “block”

    • division of plate into 4 zones based on the plate’s 2 symmetric axes

  • “checkerboard”

    • division of plate into 4 zones based on using every other row + every other column

../../../_images/250304_explainer_quadrants_96.jpg ../../../_images/250304_explainer_quadrants_384.jpg

Quadrant identifiers#

To extract a specific quadrant we simply call the relative position of the desired quadrant, relative to the Plate origin / front-left-bottom:

../../../_images/250304_explainer_quadrant_identifiers.jpg

Fill Order#

All matrices, including plates, can be filled in two different orders:

  • “row-major” order (row-wise filling)

    • Filling proceeds across a row before moving to the next row.

    • Mostly used by manual handling of plates.

  • “column-major” order (column-wise filling)

    • Filling proceeds down a column before moving to the next column.

    • Common standard in robotic handling of plates due to parallelization opportunity of liquid transfer actions in the same x-coordinate(–> massive temporal acceleration)

../../../_images/250304_explainer_fill_order.jpg

Examples#

Start by creating a minimal deck in simulation mode:

from pylabrobot.resources import (
  Cor_6_wellplate_16800ul_Fb,
  CellVis_24_wellplate_3600uL_Fb,
  Thermo_TS_96_wellplate_1200ul_Rb,
  Revvity_384_wellplate_28ul_Ub
)

example_6_wellplate = Cor_6_wellplate_16800ul_Fb(name="example_6_wellplate")
example_24_wellplate = CellVis_24_wellplate_3600uL_Fb(name="example_24_wellplate")
example_96_wellplate = Thermo_TS_96_wellplate_1200ul_Rb(name="example_96_wellplate")
example_384_wellplate = Revvity_384_wellplate_28ul_Ub(name="example_384_wellplate")

“checkerboard” + “column-major” (default)#

example_24_wellplate.get_quadrant(
  quadrant="tl",
  quadrant_type="checkerboard",  # default
  quadrant_internal_fill_order="column-major"  # default
)
[Well(name=example_24_wellplate_well_0_0, location=Coordinate(009.280, 063.800, 000.750), size_x=15.54, size_y=15.54, size_z=19, category=well),
 Well(name=example_24_wellplate_well_0_2, location=Coordinate(009.280, 025.200, 000.750), size_x=15.54, size_y=15.54, size_z=19, category=well),
 Well(name=example_24_wellplate_well_2_0, location=Coordinate(047.880, 063.800, 000.750), size_x=15.54, size_y=15.54, size_z=19, category=well),
 Well(name=example_24_wellplate_well_2_2, location=Coordinate(047.880, 025.200, 000.750), size_x=15.54, size_y=15.54, size_z=19, category=well),
 Well(name=example_24_wellplate_well_4_0, location=Coordinate(086.480, 063.800, 000.750), size_x=15.54, size_y=15.54, size_z=19, category=well),
 Well(name=example_24_wellplate_well_4_2, location=Coordinate(086.480, 025.200, 000.750), size_x=15.54, size_y=15.54, size_z=19, category=well)]

For simplified inspection, we can call .get_identifier() on each Well instance returned:

print([well.get_identifier() for well in example_96_wellplate.get_quadrant(
    quadrant="tl",
    quadrant_type = "checkerboard",  # default
    quadrant_internal_fill_order = "column-major"  # default
)])
['A1', 'C1', 'E1', 'G1', 'A3', 'C3', 'E3', 'G3', 'A5', 'C5', 'E5', 'G5', 'A7', 'C7', 'E7', 'G7', 'A9', 'C9', 'E9', 'G9', 'A11', 'C11', 'E11', 'G11']

“checkerboard” + “row-major”#

print([well.get_identifier() for well in example_96_wellplate.get_quadrant(
  quadrant="tl",
  quadrant_type = "checkerboard", # Literal["block", "checkerboard"]
  quadrant_internal_fill_order = "row-major" # Literal["column-major", "row-major"]
)])
['A1', 'A3', 'A5', 'A7', 'A9', 'A11', 'C1', 'C3', 'C5', 'C7', 'C9', 'C11', 'E1', 'E3', 'E5', 'E7', 'E9', 'E11', 'G1', 'G3', 'G5', 'G7', 'G9', 'G11']

“block” + “column-major”#

print([well.get_identifier() for well in example_96_wellplate.get_quadrant(
  quadrant="tl",
  quadrant_type = "block",
  quadrant_internal_fill_order = "column-major"
)])
['A1', 'B1', 'C1', 'D1', 'A2', 'B2', 'C2', 'D2', 'A3', 'B3', 'C3', 'D3', 'A4', 'B4', 'C4', 'D4', 'A5', 'B5', 'C5', 'D5', 'A6', 'B6', 'C6', 'D6']

“block” + “row-major”#

print([well.get_identifier() for well in example_96_wellplate.get_quadrant(
    quadrant="tl",
    quadrant_type = "block", # Literal["block", "checkerboard"]
    quadrant_internal_fill_order = "row-major" # Literal["column-major", "row-major"]
)])
['A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6']