PLR Carrier z-Height Issue

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 :slight_smile:
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:

  1. 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.
  1. 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
  1. This is already the definition of Plate.size_z (to my knowledge).
  1. This is already the definition of Well.size_z - Well.material_z_thickness.
  1. 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 called Well.dz as it is the offset of the well in relationship to its plate.
    However, the term dz has already been incorrectly occupied in PLR, as the Well.material_z_thickness (due to an import error from VENUS definitions).
    Fixing the definition of Plate is a precedence constraint to fixing the placement issue.
    We therefore agreed upon a new definition scheme that I made this visualisation for:

  1. 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 via PlateAdapter in PR#152.
  1. 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 the Well.material_z_thickness, the attribute you called well_bottom_dz, from other information and that is currently being added to all Container in 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 a PlateCarrierSite with a pedestal.
    ii. Place plate on that PlateCarrierSite
    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 the Well.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”)
  1. 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 the Well.material_z_thickness (your material_bottom_dz) as the offset when a plate sits on a PlateCarrierSite with a pedestal, is exactly what PLR is doing right now.
    → The problem is that PLR doesn’t change this when the plate sits on a PlateCarrierSite without a pedestal AND that PLR currently cannot do so because it misses the definition of Well.dz and Well.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 of PlateCarrierSite → 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 by create_equally_spaced_2d in pylabrobot/resources/utils.py but, importantly, the dx, dy, and dz variables are not attributes of Plate, making their modifications based on what PlateCarrierSite the 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 of Plate → 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 synonym skirt_base_to_well_base → reason: dz is wrongly pre-occupied with the value of the real Well.material_z_thickness at the moment, and we have to transition to the corrected nomenclature without breaking anything)
  • With this information we can simply say:

    • If PlateCarrierSite.pedestal_z_height > Plate’s Well.dz “sink” plate into the PlateCarrierSite (to get the plate origin into its real location)
    • Else place Plate origin onto PlateCarrierSite origin
  • 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. :slight_smile:

  1. 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 the Well.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 PlateCarrierSite is 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).
    Therefore PlateCarrierSite.pedestal_z_height is actually a negative float that showcases how far a plate can sink into its site.

  1. 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 PlateCarrierSite on 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 :slight_smile:
1 Like