Skip to content

Conversation

@ericguan04
Copy link
Contributor

Adding Sergi Lab Magnet Rack and VWR reagent reservoirs.

How should we handle the case where we want the resource to inherit from both Plate and Trough? This is because VWR reagent reservoir dimensions are pretty much plates, but could also be classified as a trough for liquid storage. Issue arises when we want to add the resource to plate/trough carrier or stack - has to be one or the other.

Added vwr to both plates.py and troughs.py, but there could be a more robust way to implement this. Would love to hear your thoughts / ideas!

@rickwierenga
Copy link
Member

issue arises when we want to add the resource to plate/trough carrier or stack - has to be one or the other.

can you share a picture of the plate/trough and the carrier?

@rickwierenga
Copy link
Member

also could you please add it to the resource library docs? part number/name/image/manufacturer website. see existing resources for examples

@rickwierenga
Copy link
Member

if you referenced technical drawings (ideal), please link them

if you measured some attributes, please add a # measured comment after each attribute that was measured.

@ericguan04
Copy link
Contributor Author

issue arises when we want to add the resource to plate/trough carrier or stack - has to be one or the other.

can you share a picture of the plate/trough and the carrier?

Technical data sheet:
image

Picture of the carrier:
20250612_154311

@maraxen are the reagent reservoirs we currently have on the carrier the same as the vwr 96 channel reagent reservoir?

@ericguan04 ericguan04 closed this Jun 12, 2025
@ericguan04 ericguan04 reopened this Jun 12, 2025
@ericguan04
Copy link
Contributor Author

@maraxen are the reagent reservoirs we currently have on the carrier the same as the vwr 96 channel reagent reservoir?

nevermind the two reservoirs are definitely different

@rickwierenga
Copy link
Member

(added a tutorial for posterity: #576, will be live in the docs in ~30 min)

@rickwierenga
Copy link
Member

we have historically modeled these resources as single-well plates. see AGenBio_1_troughplate_190000uL_Fl for an example.

they can only be used on what we call "plate carriers"

(you are right - what constitutes a "trough carrier" is a little ambiguous right now.)

perhaps in the future we will model these are troughs, but for now let's be consistent with the existing code

@rickwierenga
Copy link
Member

would be great to link

# technical drawing:
# https://github.com/PyLabRobot/pylabrobot/pull/574#issuecomment-2967988150

in your code :)

@ericguan04
Copy link
Contributor Author

Comments addressed, let me know if i missed anything!

Comment on lines +36 to +37
num_items_x=12, # from spec
num_items_y=8, # from spec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be 1, 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought num_items_x and num_items_y refer to the number of wells in the x and y direction - 12 x 8 wells should get us the 96 wells

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what Rick was calling attention to is that since it is reservoir, it is essentially a single well plate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to
num_items_x=1
num_items_y=1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rickwierenga just a quick question about num_items_x and num_items_y - the vwr plate does have 96 different wells, so setting num_items_x and num_items_y to 1 won't let me use aspirate96 - see picture below

20250618_152556

could you explain a little bit about why it should be represented as a single well plate - im new the wet lab work so apologies if this is a naive question

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the plate in the image, it is num_items_x = 12, num_items_y = 8 because they are clearly 8x12 wells.

this seems to be a different plate from the technical drawing above, which has one big well (with 96 drain points)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, i'll double check with @maraxen about this and confirm the plate specifications

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks. it's possible you're talking about two separate plates i think :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they are two different plates. Eric will add both and hopefully we can merge

@rickwierenga
Copy link
Member

given that there was an import error and the code didn't run at all, i would like to ask: have you tested this plate definition and verified it works?

i just fixed the errors and updated it to adhere to the PLR plate naming convention

@rickwierenga
Copy link
Member

the PlateAdapter definition seems to have the parameters of a Plate definition. The definitions for a Plate and PlateAdapter are completely different. Please test the definitions before submitting them.

see the original PlateAdapter PR #152 for more information.

@ericguan04
Copy link
Contributor Author

the PlateAdapter definition seems to have the parameters of a Plate definition. The definitions for a Plate and PlateAdapter are completely different. Please test the definitions before submitting them.

see the original PlateAdapter PR #152 for more information.

my apologies, will test before submitting -- initial reason for this PR was to get thoughts on the implementation, but probably should've opened an issue instead

@rickwierenga
Copy link
Member

no worries, just making sure we keep a high code quality on plr:main

in the future, for discussions feel free to go to discuss.pylabrobot.org or create a draft PR :)

@rickwierenga rickwierenga marked this pull request as draft June 16, 2025 18:24
@ericguan04
Copy link
Contributor Author

the PlateAdapter definition seems to have the parameters of a Plate definition. The definitions for a Plate and PlateAdapter are completely different. Please test the definitions before submitting them.

see the original PlateAdapter PR #152 for more information.

def SergiLabSupplies_96_MagneticRack_250ul_Vb(name: str) -> PlateAdapter:
  """
  Sergi Lab Supplies Magnetic Rack [cat. no. 1047]
  - Holds a 96-well PCR plate for DNA/RNA purification
  - SBS footprint: 127.76 x 85.48 mm
  - Rack height: 22.0 mm
  - Pulls magnetic beads ~1-2 mm above bottom
  """

  # measurements from technical drawing:
  # https://sergilabsupplies.com/collections/magnetic-racks/products/96-wells-magnetic-rack-for-dna-rna-and-other-molecules-purification
  return PlateAdapter(
    name=name,
    size_x=127.76,  # from spec
    size_y=85.48,  # from spec
    size_z=22.0,  # from spec
    dx=9.88, # measured (127.76 - 108) / 2 = 9.88
    dy=4.74, # measured (85.48 - 76) / 2 = 4.74
    dz=7.0, # measured
    adapter_hole_size_x=7.0, # measured
    adapter_hole_size_y=7.0, # measured
    adapter_hole_size_z=16.0, # measured (22.0 - 6) = 16.0
    site_pedestal_z=6.0, # measured, but not sure if correct
    model="SergiLabSupplies_96_MagneticRack_250ul_Vb",
  )

what does site_pedestal_z represent? i couldn't find anything about it in PR #152

@rickwierenga
Copy link
Member

what does site_pedestal_z represent? i couldn't find anything about it in PR #152

@BioCam what does it represent? this attribute is stored but doesn't seem to be used anywhere

@BioCam
Copy link
Collaborator

BioCam commented Jun 18, 2025

what does site_pedestal_z represent? i couldn't find anything about it in PR #152

@BioCam what does it represent? this attribute is stored but doesn't seem to be used anywhere

Thank you for catching this, this is a mistake I've made.

This attribute is best explained with examples:

Some PlateAdapters have a central elevation but surrounding it they have a thin metal plate, enabling them to fit onto an SLAS format plate holder.
E.g. the Opentrons aluminium plate holder:

images (2).jpeg

This attributes captures the thickness of that metal plate at the every bottom.

Other PlateAdapters like the Alpaqua magnets are straight away in SLAS footprint format, so they don't need it.

But thinking about the fact that this attributes is not used at all and the PlateAdapter definition works really well, I propose removing it altogether.

And only use plate_adapter.dz - at runtime! - to define where H1 of a well would go.

Note: this has to be defined/overwritten at runtime because every plate and PlateAdapter have different well/hole shapes. We cannot model all possible combinations. Therefore overwriting at runtime is necessary.

@rickwierenga
Copy link
Member

removing in #582

@rickwierenga
Copy link
Member

thanks @BioCam for quick response

@ericguan04 feel free to sync plr:main into your branch and drop the site_pedestal_z

@ericguan04
Copy link
Contributor Author

@rickwierenga added vwr deep well plate, and fixed vwr reservoir + sergi plate adapter. Testing code below:

tip_car = TIP_CAR_480_A00(name="tip_carrier")
tip_rack = STF(name="tip_rack")
tip_car[0] = tip_rack
lh.deck.assign_child_resource(tip_car, rails=1)

# define custom plate to test plate adapter --> may add this to plr later since we are using some close adjacent
from pylabrobot.resources.utils import create_ordered_items_2d
from pylabrobot.resources.well import (
  CrossSectionType,
  Well,
  WellBottomType,
)

def Custom_PCR_96_250ul_Vb(name: str) -> Plate:
  """
  Custom 96-well PCR Plate (non-skirted or semi-skirted)
  - Fits standard SBS footprint
  - Max volume per well: 250 µL
  - Round wells with conical bottom
  """

  return Plate(
    name=name,
    size_x=120.0,
    size_y=80.0,
    size_z=20.0,
    model="Custom_PCR_96_250ul_Vb",
    lid=None,
    ordered_items=create_ordered_items_2d(
      Well,
      num_items_x=12,
      num_items_y=8,
      dx=10.87,
      dy=7.77,
      dz=3.03,
      item_dx=9.0,
      item_dy=9.0,
      size_x=8.0,
      size_y=8.0,
      size_z=20.0,
      material_z_thickness=0.5,
      bottom_type=WellBottomType.V,
      cross_section_type=CrossSectionType.CIRCLE,
      max_volume=300,

    )
  )

plt_car = PLT_CAR_L5AC_A00(name="plate_carrier")
plt_car[0] = plate_1 = VWR_96_troughplate_195000uL_Ub(name="vwr_trough_plate")
plt_car[1] = plate_2 = SergiLabSupplies_96_MagneticRack_250ul_Vb(name="sergi_plate_adapter")
plt_car[2] = plate_3 = VWR_96_DWP_2mL_Vb(name="vwr_96_dwp_plate")
plt_car[3] = plate_4 = Custom_PCR_96_250ul_Vb(name="custom_pcr_plate")
lh.deck.assign_child_resource(plt_car, rails=8)

# test the troughplate
await lh.pick_up_tips(tip_rack["A1:A1"])
await lh.aspirate(plate_1["A1:A1"], vols=[1000])
await lh.dispense(plate_1["A1:A1"], vols=[1000])
await lh.drop_tips(tip_rack["A1:A1"])

# test the deep well plate
await lh.pick_up_tips96(tip_rack)
await lh.aspirate96(plate_3, volume=360)
await lh.dispense96(plate_3, volume=360)

# test the plate adapter
await lh.move_plate(plate_4, plate_2)

code above ran with no errors --> please check anything else i might've missed, and let me know if there are any formatting issues with the names - thanks!

@rickwierenga rickwierenga marked this pull request as ready for review June 19, 2025 17:26
@rickwierenga rickwierenga merged commit cc3458e into PyLabRobot:main Jun 19, 2025
6 checks passed
@rickwierenga
Copy link
Member

thank you for contributing these resources!

some small changes i made:

  • i updated the resource names to adhere to the naming standard
  • fixed the resource definition for VWR_1_troughplate_195000uL_Ub
    • when there is one well, it is big. you had the size of an individual drain point
  • added docs for VWR_96_wellplate_2mL_Vb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants