Thank you @fderop for your message and report of the issue’s you’re encountering.
That is exactly the same issue I encountered, starting this thread ![]()
I have been working on identifying the problem and fixing it since February; it would be awesome to have another person working on this!
A couple of things to note and a summary of the work I’ve done so far with @rickwierenga:
- We renamed what has been named “CarrierSite skirt” to “pedestal” because
Plates have skirts,CarrierSites don’t. Small item but the nomenclature can become very confusing.
- I completely agree; this issue is so deeply engrained in PLR and affects so much functionality, making it very complex. A good guide is needed. I’ve created a series of visualisations in the PRs I created for this purpose. But ultimately I aimed to write up a “Plate Definition Post-Mortem” similar to the 50ul Tip Troubleshooting Report / Post-Mortem I wrote after we fixed the 50ul tip definition
- This is already the definition of
Plate.size_z(to my knowledge).
- This is already the definition of
Well.size_z-Well.material_z_thickness.
- This has been one of the cruxes of the definition problem:
This attribute has so far been completely missing in PLR, and what makes the matter more confusing, this attribute is supposed to be calledWell.dzas it is the offset of the well in relationship to its plate.
However, the termdzhas already been incorrectly occupied in PLR, as theWell.material_z_thickness(due to an import error from VENUS definitions).
Fixing the definition ofPlateis a precedence constraint to fixing the placement issue.
We therefore agreed upon a new definition scheme that I made this visualisation for:
- I completely agree; though most people I’ve met use a metal plate adapter instead of this plastic one because the plastic one tends to create a friction fit between the plastic_adapter and the plastic semi-/non-skirted plate. As a result the robot is at risk of picking up both plastic_adapter+non-skirted plate when trying to move the plate.
Since we didn’t have a plate adapter definition that correctly, automatically adjusts the placement of a plate onto an adapter I developed one viaPlateAdapterin PR#152.
- Unfortunately, that is not completely accurate for all plates:
Many plates’ wells actually stick out of the plate top plateau (hence why I added a plate like this in the figure I made above).
This means it is very hard to calculate theWell.material_z_thickness, the attribute you calledwell_bottom_dz, from other information and that is currently being added to allContainerin PR#183.
Instead it is a lot easier to measure it directly on a Hamilton machine:
i. Use the CMM cLLD function that I developed in PR#69,STAR.probe_z_height_using_channel()to measure the pedestal z-coordinate of aPlateCarrierSitewith a pedestal.
ii. Place plate on thatPlateCarrierSite
iii. move channel with tip to the inside bottom of a well of that plate, incrementally decreasing the z-coordinate of the tip, checking whether the tip can scratch the bottom already (not pressing against it), note the z-coordinate
iv. the difference between these two measures is theWell.material_z_thickness
(funnily that is exactly the same way that I’ve seen Hamilton engineers identify this attribute, which they call “thickness_of_container_base”)
- Unfortunately, no, this is not quite what I was trying to say (and I apologise for the confusion, there are multiple parallel problems that all need to be solved at the same time, and I might have not conveyed them all in an easy to understand matter):
What you are suggesting, i.e. adding theWell.material_z_thickness(yourmaterial_bottom_dz) as the offset when a plate sits on aPlateCarrierSitewith a pedestal, is exactly what PLR is doing right now.
→ The problem is that PLR doesn’t change this when the plate sits on aPlateCarrierSitewithout a pedestal AND that PLR currently cannot do so because it misses the definition ofWell.dzandWell.material_z_thickness.
.
I investigated a couple of different methods to fix this:
A.) change the z-origin of the well based on the type ofPlateCarrierSite→ this doesn’t work because the well origin never changes its location in relationship to the origin of the plate.
From a coding side, this is because the well origin coordinates are created bycreate_equally_spaced_2dinpylabrobot/resources/utils.pybut, importantly, thedx,dy, anddzvariables are not attributes ofPlate, making their modifications based on whatPlateCarrierSitethe plate sits on (i.e. with vs without a pedestal) very hard. It would get us back into “offset land” where we have to correct for definition errors with offsets which have to be maintained and updated every time we change the definition, creating infinite technical dept.
From a physical reality side, this doesn’t make sense because it is not the well that changes its location, it is the entire plate.
B.) Correct the definition ofPlate→ minimal required information is- getting the site ready:
PlateCarrierSite.pedestal_z_height(added in PR#143) - getting the plate ready:
Well.material_z_thickness(currently being added in PR#183)
Well.dz(currently being discussed to be added in PR#183 under the synonymskirt_base_to_well_base→ reason:dzis wrongly pre-occupied with the value of the realWell.material_z_thicknessat the moment, and we have to transition to the corrected nomenclature without breaking anything)
- getting the site ready:
-
With this information we can simply say:
- If
PlateCarrierSite.pedestal_z_height>Plate’sWell.dz“sink” plate into thePlateCarrierSite(to get the plate origin into its real location) - Else place
Plateorigin ontoPlateCarrierSiteorigin
- If
-
I hope this explains it a little bit better, and showcases how deeply the problem is engrained, and what we have to do to fix it.

-
There are two issues with this:
i. The bottom of the pedestal is not at the purple arrow but is higher up (in z-dimension) at the cyan arrow. This little protrusion at the sides is what a plate skirt would sit on top of if theWell.dz>PlateCarrierSite.pedestal_z_height.
@rickwierenga add a new photo to demonstrate what has to be measured to Docs: Plate Carriers
ii. the origin of the
PlateCarrierSiteis at the topmost surface of the site, i.e. the top of the pedestal (this is how VENUS appears to handle this problem, and we chose to adapt a similar solution).
ThereforePlateCarrierSite.pedestal_z_heightis actually a negative float that showcases how far a plate can sink into its site.
- Yes, that is a big problem for using robots for actual experiments, and I believe this is one of the main reasons why most robotics in biology has been confined to what I call “process churning”, i.e. perform the same repetitive tasks over and over again, not changing anything about the setup… because as you said: even changing a plate to a different
PlateCarrierSiteon the same carrier can have different offsets.
What we all seem to want though is using robotics for experiments, i.e. tasks that are fundamentally changing from one automation run to the next. (thanks to procedural robotic control like PLR this is now possible from a software side but the hardware is now the next challenge).
I found working with careful considerations of tolerances gets me 90% where I need to go.
Plus, for those really tough applications there is lld_mode=4, z-touchoff, i.e. crash tip into the bottom and aspirate from there… but that might not work for all applications and it is slower.
Besides that I am myself trying to work out a couple of new solutions for applications where this has become a limiting problem


