Skip to content

Make Plate Site-adaptive (Fix PLR plate location 3) #205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
de500cd
adding conditional logic for plate placement & updating plate definit…
BioCam Jul 29, 2024
e8005d0
testing updated definitions & correct plate placements
BioCam Jul 29, 2024
8b8db62
fix linting
BioCam Jul 30, 2024
1d769ab
fixing type checking
BioCam Jul 30, 2024
b4dc644
implement well_bottom update based on material_z_thickness in STAR.py
BioCam Aug 12, 2024
9b87d12
resolve Tilter updates
BioCam Aug 12, 2024
7a98645
resolving updates 2
BioCam Aug 12, 2024
558792a
resolving Tilter update 3
BioCam Aug 12, 2024
e8275b7
resolving Tilter updates 4
BioCam Aug 12, 2024
5c3e273
fix linting
BioCam Aug 12, 2024
beb6fe9
Is MyPy dumb?
BioCam Aug 12, 2024
dfe7345
mypy appears to have difficulties with Non-Short-Circuiting
BioCam Aug 12, 2024
f3c9328
remove VENUS relic that's most likely a ballpark material_z_thickness
BioCam Aug 13, 2024
e4f12bc
Merge branch 'PyLabRobot:main' into Make-Plate-Site-Adaptive-&-Fix-it…
BioCam Aug 13, 2024
7f99a5c
implement easy container cavity_bottom access
BioCam Aug 13, 2024
5ee3798
move specialised cavity_bottom into Container method overwrite
BioCam Aug 14, 2024
73e0e76
fix linting
BioCam Aug 14, 2024
84827e6
remove "cb" from Container.get_anchor() to avoid confusion
BioCam Aug 14, 2024
12dbb00
fix STAR liquid handling with updated plate loc
rickwierenga Aug 15, 2024
9ac2e62
fix resource movements
rickwierenga Aug 17, 2024
a03634e
update vantage
rickwierenga Aug 17, 2024
e0b4627
lint
rickwierenga Aug 17, 2024
49ffdc5
correct sinking deserialization & fix tests
rickwierenga Aug 17, 2024
b23ae05
ugh
rickwierenga Aug 17, 2024
ea74aa7
Merge branch 'main' into Make-Plate-Site-Adaptive-&-Fix-its-Definition
rickwierenga Aug 17, 2024
6d3d8c0
Merge branch 'main' into Make-Plate-Site-Adaptive-&-Fix-its-Definition
rickwierenga Aug 19, 2024
90be7dd
Update CHANGELOG
rickwierenga Aug 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Merge `height_functions.py` and `volume_functions.py` into `height_volume_functions.py` (https://github.com/PyLabRobot/pylabrobot/pull/200)
- Type checking for `lh.pick_up_tips`, `lh.drop_tips`, `lh.aspirate`, and `lh.dispense` and 96-channel versions.
- `ChatterBoxBackend` outputs are now pretty (https://github.com/PyLabRobot/pylabrobot/pull/208)
- `liquid_height` now defaults to 0 instead of 1 (https://github.com/PyLabRobot/pylabrobot/pull/205/)
- `material_z_thickness` of a `Container` is used in computing its bottom (https://github.com/PyLabRobot/pylabrobot/pull/205/)
- Default `pickup_distance_from_top` in `LiquidHandler.{move_plate,move_lid}` were lowered by 3.33 (https://github.com/PyLabRobot/pylabrobot/pull/205/)

### Added

Expand All @@ -47,13 +50,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- `adapter_hole_size_z` and `plate_z_offset` parameters to `PlateAdapter` (https://github.com/PyLabRobot/pylabrobot/pull/215)
- `wide_high_volume_tip_with_filter` and `HTF_L_WIDE` (https://github.com/PyLabRobot/pylabrobot/pull/222)
- Serialize code cells and closures (https://github.com/PyLabRobot/pylabrobot/pull/220)
- `Container.get_anchor()` now supports `"cavity_bottom"` as an argument for `z` (https://github.com/PyLabRobot/pylabrobot/pull/205/)

### Deprecated

- All VENUS-imported Corning-Costar plates, because they don't have unique and usable identifiers, and are probably wrong.
- Passing single values to LiquidHandler `pick_up_tips`, `drop_tips`, `aspirate`, and `dispense` methods. These methods now require a list of values.
- `utils.positions`: `string_to_position`, `string_to_index`, `string_to_indices`, `string_to_pattern`.
- `ThermoScientific_96_DWP_1200ul_Rd` in favor of `Thermo_TS_96_wellplate_1200ul_Rb` (https://github.com/PyLabRobot/pylabrobot/pull/215)
- `Azenta4titudeFrameStar_96_wellplate_skirted` in favor of `Azenta4titudeFrameStar_96_wellplate_200ul_Vb` (https://github.com/PyLabRobot/pylabrobot/pull/205/)
- `Cos_96_DWP_2mL_Vb` in favor of `Cos_96_wellplate_2mL_Vb (https://github.com/PyLabRobot/pylabrobot/pull/205/)`

### Fixed

Expand All @@ -62,6 +68,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- Fix Opentrons backend resource definitions: Opentrons takes well locations as ccc instead of lfb
- Fix ThermoScientific_96_DWP_1200ul_Rd to ThermoScientific_96_wellplate_1200ul_Rd (https://github.com/PyLabRobot/pylabrobot/pull/183).
- `libusb_package` is now an optional dependency.
- Plates with a skirt are now correctly lowered when placed on plate carriers with a pedestal (https://github.com/PyLabRobot/pylabrobot/pull/205/)
- `minimum_height` in `STAR` and `Vantage` now correctly refer to a `Container`s bottom instead of being a function of liquid height (https://github.com/PyLabRobot/pylabrobot/pull/205/)

### Removed

Expand Down
2 changes: 1 addition & 1 deletion docs/resources/plates.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Plates

Microplates are modelled by the {class}`~pylabrobot.resources.plate.Plate` class consist of equally spaced wells. Wells are children of the `Plate` and are modelled by the {class}`~pylabrobot.resources.well.Well` class. The relative positioning of `Well`s is what determines their location. `Plate` is a subclass of {class}`~pylabrobot.resources.itemized_resource.ItemizedResource`, allowing convenient integer and string indexing.
Microplates are modelled by the {class}`~pylabrobot.resources.plate.Plate` class consisting of equally spaced wells. Wells are children of the `Plate` and are modelled by the {class}`~pylabrobot.resources.well.Well` class. The relative positioning of `Well`s is what determines their location. `Plate` is a subclass of {class}`~pylabrobot.resources.itemized_resource.ItemizedResource`, allowing convenient integer and string indexing.

There is some standardization on plate dimensions by SLAS, which you can read more about in the [ANSI SLAS 1-2004 (R2012): Footprint Dimensions doc](https://www.slas.org/SLAS/assets/File/public/standards/ANSI_SLAS_1-2004_FootprintDimensions.pdf). Note that PLR fully supports all plate dimensions, sizes, relative well spacings, etc.

Expand Down
28 changes: 15 additions & 13 deletions pylabrobot/liquid_handling/backends/hamilton/STAR.py
Original file line number Diff line number Diff line change
Expand Up @@ -1574,8 +1574,9 @@ async def aspirate(
for op, hlc in zip(ops, hamilton_liquid_classes):
op.volume = hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume

well_bottoms = [op.resource.get_absolute_location().z + op.offset.z for op in ops]
liquid_surfaces_no_lld = [wb + (op.liquid_height or 1)
well_bottoms = [op.resource.get_absolute_location().z + op.offset.z + \
op.resource.material_z_thickness for op in ops]
liquid_surfaces_no_lld = [wb + (op.liquid_height or 0)
for wb, op in zip(well_bottoms, ops)]
if lld_search_height is None:
lld_search_height = [
Expand All @@ -1590,8 +1591,7 @@ async def aspirate(
pull_out_distance_transport_air = _fill_in_defaults(pull_out_distance_transport_air, [10]*n)
second_section_height = _fill_in_defaults(second_section_height, [3.2]*n)
second_section_ratio = _fill_in_defaults(second_section_ratio, [618.0]*n)
minimum_height = \
_fill_in_defaults(minimum_height, [ls-5 for ls in liquid_surfaces_no_lld])
minimum_height = _fill_in_defaults(minimum_height, well_bottoms)
# TODO: I think minimum height should be the minimum height of the well
immersion_depth = _fill_in_defaults(immersion_depth, [0]*n)
immersion_depth_direction = _fill_in_defaults(immersion_depth_direction, [0]*n)
Expand Down Expand Up @@ -1836,9 +1836,10 @@ async def dispense(
for op, hlc in zip(ops, hamilton_liquid_classes):
op.volume = hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume

well_bottoms = [op.resource.get_absolute_location().z + op.offset.z for op in ops]
well_bottoms = [op.resource.get_absolute_location().z + op.offset.z + \
op.resource.material_z_thickness for op in ops]
liquid_surfaces_no_lld = liquid_surface_no_lld or \
[ls + (op.liquid_height or 1) for ls, op in zip(well_bottoms, ops)]
[ls + (op.liquid_height or 0) for ls, op in zip(well_bottoms, ops)]
if lld_search_height is None:
lld_search_height = [
(wb + op.resource.get_size_z() + (2.7 if isinstance(op.resource, Well) else 5)) #?
Expand All @@ -1855,8 +1856,7 @@ async def dispense(
pull_out_distance_transport_air = _fill_in_defaults(pull_out_distance_transport_air, [10.0]*n)
second_section_height = _fill_in_defaults(second_section_height, [3.2]*n)
second_section_ratio = _fill_in_defaults(second_section_ratio, [618.0]*n)
minimum_height = _fill_in_defaults(minimum_height,
default=[ls+5 for ls in liquid_surfaces_no_lld])
minimum_height = _fill_in_defaults(minimum_height, well_bottoms)
immersion_depth = _fill_in_defaults(immersion_depth, [0]*n)
immersion_depth_direction = _fill_in_defaults(immersion_depth_direction, [0]*n)
surface_following_distance = _fill_in_defaults(surface_following_distance, [0]*n)
Expand Down Expand Up @@ -2005,7 +2005,7 @@ async def aspirate96(
blow_out: bool = False,

use_lld: bool = False,
liquid_height: float = 1,
liquid_height: float = 0,
air_transport_retract_dist: float = 10,
hlc: Optional[HamiltonLiquidClass] = None,

Expand Down Expand Up @@ -2080,7 +2080,8 @@ async def aspirate96(
# get the first well and tip as representatives
if isinstance(aspiration, AspirationPlate):
top_left_well = aspiration.wells[0]
position = top_left_well.get_absolute_location() + top_left_well.center() + aspiration.offset
position = top_left_well.get_absolute_location() + top_left_well.center() + \
Coordinate(z=top_left_well.material_z_thickness) + aspiration.offset
else:
position = aspiration.container.get_absolute_location(y="b") + aspiration.offset

Expand Down Expand Up @@ -2185,7 +2186,7 @@ async def dispense96(
blow_out: bool = False,
hlc: Optional[HamiltonLiquidClass] = None,

liquid_height: float = 1,
liquid_height: float = 0,
dispense_mode: Optional[int] = None,
air_transport_retract_dist=10,
use_lld: bool = False,
Expand Down Expand Up @@ -2254,7 +2255,8 @@ async def dispense96(
# get the first well and tip as representatives
if isinstance(dispense, DispensePlate):
top_left_well = dispense.wells[0]
position = top_left_well.get_absolute_location() + top_left_well.center() + dispense.offset
position = top_left_well.get_absolute_location() + top_left_well.center() + \
Coordinate(z=top_left_well.material_z_thickness) + dispense.offset
else:
position = dispense.container.get_absolute_location(y="b") + dispense.offset
tip = dispense.tips[0]
Expand Down Expand Up @@ -4390,7 +4392,7 @@ async def core_get_plate(
minimum_traverse_height_at_beginning_of_a_command: int = 2750,
minimum_z_position_at_the_command_end: int = 2750,
):
""" Get plate with CoRe gripper tool from wasteblock mount. """\
""" Get plate with CoRe gripper tool from wasteblock mount. """

assert 0 <= x_position <= 30000, "x_position must be between 0 and 30000"
assert 0 <= x_direction <= 1, "x_direction must be between 0 and 1"
Expand Down
Loading
Loading