I was on making plate readers more understanding about plates when the lid is on. But stumbled upon this issue where the full height of a plate when the lid is on does not share a standardised API. PLR currently models lids as child resources of Plate. That makes sense because lids can be moved separately, but it also means the usual size APIs only report the plate body height, not the full height taken up by the plate + lid.
For example, Cor_96_wellplate_360ul_Fb(..., with_lid=True) creates the lid separately:
The lid is then placed using the nesting height here:
But Resource.get_absolute_size_z() only looks at the resource's own rotated corners, not child resources:
So for a covered plate, these all return the plate body height:
plate.get_size_z()
plate.get_absolute_size_z()
plate.get_absolute_location(z="t").z
They do not return the actual top height including the lid.
Example with Cor_96_wellplate_360ul_Fb("plate", with_lid=True):
plate.get_size_z() = 14.2 mm
plate.get_absolute_size_z() = 14.2 mm
plate.get_absolute_location(z="t") = 14.2 mm
lid.get_size_z() = 8.9 mm
lid.nesting_z_height = 7.6 mm
lid.location.z = 6.6 mm
occupied height with lid = 15.5 mm
The lid-aware height calculation already exists in a few places, but it is done manually each time.
In pylabrobot/resources/resource_stack.py#L90-L95:
if isinstance(resource, Plate) and resource.lid is not None:
return resource.get_size_z() + resource.lid.get_size_z() - resource.lid.nesting_z_height
return resource.get_size_z()
In pylabrobot/plate_reading/agilent/biotek_backend.py#L321-L323:
plate_size_z = plate.get_size_z()
if plate.lid is not None:
plate_size_z += plate.lid.get_size_z() - plate.lid.nesting_z_height
There is also an approximate version in the incubator placement logic, with a TODO saying the PLR nesting height should be used:
pylabrobot/storage/incubator.py#L90-L95
def _plate_height(p: Plate):
if p.has_lid():
# TODO: we can use plr nesting height
# lid.location.z + lid.get_anchor(z="t").z
return p.get_size_z() + 3
return p.get_size_z()
Would it make sense for PLR to expose one standard helper for the occupied height / top Z including the lid?
Some possible API names:
plate.get_size_z_with_lid()
plate.get_occupied_size_z()
plate.get_top_z(include_children=True)
I do not think get_size_z() itself should change, since it currently seems to mean the resource's own local geometry. Changing that could break stuffs. But having one official helper would make storage, stacking, plate-reader clearance checks, and backend plate geometry handling less error-prone.
I was on making plate readers more understanding about plates when the lid is on. But stumbled upon this issue where the full height of a plate when the lid is on does not share a standardised API. PLR currently models lids as child resources of
Plate. That makes sense because lids can be moved separately, but it also means the usual size APIs only report the plate body height, not the full height taken up by the plate + lid.For example,
Cor_96_wellplate_360ul_Fb(..., with_lid=True)creates the lid separately:pylabrobot/resources/corning/plates.py#L52-L57pylabrobot/resources/corning/plates.py#L85-L90The lid is then placed using the nesting height here:
pylabrobot/resources/plate.py#L122-L124But
Resource.get_absolute_size_z()only looks at the resource's own rotated corners, not child resources:pylabrobot/resources/resource.py#L331-L334So for a covered plate, these all return the plate body height:
They do not return the actual top height including the lid.
Example with
Cor_96_wellplate_360ul_Fb("plate", with_lid=True):The lid-aware height calculation already exists in a few places, but it is done manually each time.
In
pylabrobot/resources/resource_stack.py#L90-L95:In
pylabrobot/plate_reading/agilent/biotek_backend.py#L321-L323:There is also an approximate version in the incubator placement logic, with a TODO saying the PLR nesting height should be used:
pylabrobot/storage/incubator.py#L90-L95Would it make sense for PLR to expose one standard helper for the occupied height / top Z including the lid?
Some possible API names:
I do not think
get_size_z()itself should change, since it currently seems to mean the resource's own local geometry. Changing that could break stuffs. But having one official helper would make storage, stacking, plate-reader clearance checks, and backend plate geometry handling less error-prone.