diff --git a/docs/resources/library/hamilton.md b/docs/resources/library/hamilton.md index 75ea4ce2bd3..b2b70eaf8b4 100644 --- a/docs/resources/library/hamilton.md +++ b/docs/resources/library/hamilton.md @@ -20,6 +20,7 @@ Company history: [Hamilton Robotics history](https://www.hamiltoncompany.com/his | - | - | - | | 'PLT_CAR_L5AC_A00'
Part no.: 182090
[manufacturer website](https://www.hamiltoncompany.com/automated-liquid-handling/other-robotics/182090)
Carrier for 5x 96 Deep Well Plates or for 5x 384 tip racks (e.g.384HEAD_384TIPS_50μl) (6T) | ![](img/hamilton/PLT_CAR_L5AC_A00_182090.jpg) | `hamilton_plate_carrier_L5_ac` | | 'PLT_CAR_L5MD_A00'
Part no.: 182365/02
[manufacturer website](https://www.hamiltoncompany.com/automated-liquid-handling/other-robotics/182365)
Carries five ANSI/SLAS footprint MTPs in landscape orientation. Occupies six tracks.| ![](img/hamilton/182365-Plate-Carrier.webp) | `PLT_CAR_L5MD_A00` | +| 'PLT_CAR_L5PCR'
Part no.: 182070
[manufacturer website](https://www.hamiltoncompany.com/other-robotics/182070)
Carrier for 5x 96-well PCR plates in landscape orientation using 182531 inserts (6T). | ![Hamilton 182070 PCR carrier with five 182531 inserts](img/hamilton/PLT_CAR_L5PCR.jpg) | `PLT_CAR_L5PCR` | | 'PLT_CAR_P3AC'
Part no.: 182365/03
[manufacturer website](https://www.hamiltoncompany.com/automated-liquid-handling/other-robotics/182365)
Hamilton Deepwell Plate Carrier for 3 Plates (Portrait, 6 tracks wide)| ![](img/hamilton/PLT_CAR_P3AC.jpg) | `PLT_CAR_P3AC` | | 'PLT_CAR_L5_DWP'
Part no.: 93522-01/03
manufacturer website?
Hamilton Plate Carrier for 5 Plates (Landscape, 6 tracks wide). Plastic tabs. | ![](img/hamilton/PLT_CAR_L5_DWP.jpg) | `PLT_CAR_L5_DWP` | @@ -68,6 +69,7 @@ Sometimes called "reagent carriers" in Hamilton jargon. | Description | Image | PLR definition | | - | - | - | +| 'Hamilton_96_adapter_182531'
Part no.: 182531
PCR insert for the [182070 carrier](https://www.hamiltoncompany.com/other-robotics/182070). 110 × 75 × 15 mm, with a 12 × 8 hole grid at 9 mm spacing. Geometry and image derived from Hamilton's 3D model. | ![](img/hamilton/Hamilton_96_adapter_182531.jpg) | `Hamilton_96_adapter_182531` | | 'Hamilton_96_adapter_188182'
Part no.: 188182
[manufacturer website](https://www.hamiltoncompany.com/automated-liquid-handling/other-robotics/188182) (<-non-functional link?)
Adapter for 96 well PCR plate, plunged. Does not have an ANSI/SLAS footprint -> requires assignment with specified location. | ![](img/hamilton/hamilton_96_adapter_188182.png) | `Hamilton_96_adapter_188182` | ## Consumables diff --git a/docs/resources/library/img/hamilton/Hamilton_96_adapter_182531.jpg b/docs/resources/library/img/hamilton/Hamilton_96_adapter_182531.jpg new file mode 100644 index 00000000000..7127144e7bc Binary files /dev/null and b/docs/resources/library/img/hamilton/Hamilton_96_adapter_182531.jpg differ diff --git a/docs/resources/library/img/hamilton/PLT_CAR_L5PCR.jpg b/docs/resources/library/img/hamilton/PLT_CAR_L5PCR.jpg new file mode 100644 index 00000000000..719718faf0a Binary files /dev/null and b/docs/resources/library/img/hamilton/PLT_CAR_L5PCR.jpg differ diff --git a/pylabrobot/resources/hamilton/plate_adapters.py b/pylabrobot/resources/hamilton/plate_adapters.py index e60115f1bc7..af67887476f 100644 --- a/pylabrobot/resources/hamilton/plate_adapters.py +++ b/pylabrobot/resources/hamilton/plate_adapters.py @@ -1,8 +1,40 @@ -"""Hamilton magnetic racks""" +"""Hamilton PCR plate adapters.""" from pylabrobot.resources.plate_adapter import PlateAdapter +def Hamilton_96_adapter_182531(name: str) -> PlateAdapter: + """Hamilton 182531 PCR insert for the 182070 landscape carrier. + + Geometry is derived from the five ``182531_RNO`` meshes in Hamilton's 3D model. + The 12 x 8 hole grid has 9 mm spacing; H1 is 5.5/6.0 mm from the left/front edges. + The mesh's top opening diameter is approximately 7.732 mm, and its cavity bottom + is 1.951 mm above the insert base, giving a 13.049 mm cavity depth. + + ``dz`` represents the modeled cavity bottom. Automatic plate placement uses that + reference; it does not model contact between a particular PCR plate and the tapered + cavities. Supply an explicit plate location if its seating height differs. + + Args: + name: The insert name. + """ + hole_diameter = 7.732 # from the .x mesh's top opening vertices, rounded to 0.001 mm + return PlateAdapter( + name=name, + size_x=110.0, # from the .x mesh bounds + size_y=75.0, # from the .x mesh bounds + size_z=15.0, # from the .x mesh: 108.7 - 93.7 + dx=5.5 - hole_diameter / 2, # from the .x hole centers relative to the insert's left edge + dy=6.0 - hole_diameter / 2, # from the .x hole centers relative to the insert's front edge + dz=1.951, # from the .x mesh: cavity bottom 95.651 - insert base 93.7 + adapter_hole_size_x=hole_diameter, + adapter_hole_size_y=hole_diameter, + adapter_hole_dx=9.0, # from the .x hole grid + adapter_hole_dy=9.0, # from the .x hole grid + model="Hamilton_96_adapter_182531", + ) + + def Hamilton_96_adapter_188182(name: str) -> PlateAdapter: """Hamilton cat. no.: 188182 Adapter for 96 well PCR plate, plunged. diff --git a/pylabrobot/resources/hamilton/plate_carriers.py b/pylabrobot/resources/hamilton/plate_carriers.py index 1f9e43ea986..6246793b35e 100644 --- a/pylabrobot/resources/hamilton/plate_carriers.py +++ b/pylabrobot/resources/hamilton/plate_carriers.py @@ -6,6 +6,7 @@ PlateHolder, create_homogeneous_resources, ) +from pylabrobot.resources.hamilton.plate_adapters import Hamilton_96_adapter_182531 def PLT_CAR_L4_HHS_ALT_A00(name: str) -> PlateCarrier: @@ -254,28 +255,79 @@ def PLT_CAR_L5MD_A00(name: str) -> PlateCarrier: ) -def PLT_CAR_L5PCR(name: str) -> PlateCarrier: - """ """ - return PlateCarrier( +def PLT_CAR_L5PCR(name: str, *, with_adapters: bool = False) -> PlateCarrier: + """Hamilton 182070 carrier for five 96-well PCR plates in landscape orientation (6 tracks). + + https://www.hamiltoncompany.com/other-robotics/182070 + + Geometry: + Hamilton's VENUS template specifies a 135 x 497 x 130 mm carrier envelope and + 96 mm site pitch. Its 130 mm height and clearance describe the envelope, not the insert + support surface. The 75 mm inserts have 21 mm clear gaps. + + Insert locations are derived from the five 182531_RNO meshes in Hamilton's 3D model. + Coordinates are referenced to the main body's left/front edges and the rail underside, + excluding the projecting front latch. In the model's stored axes, the reference + is lateral X = -67, longitudinal Z = -244, and vertical Y = -12 mm. Subtracting + these from the first insert's minimum coordinates (-55, -229.4, 93.7 mm, + respectively) gives these carrier-relative locations: + + Site | Insert X (mm) | Insert Y (mm) | Support Z (mm) + 0 | 12.00 | 14.60 | 105.70 + 1 | 12.00 | 110.60 | 105.70 + 2 | 12.00 | 206.60 | 105.70 + 3 | 12.00 | 302.60 | 105.70 + 4 | 12.00 | 398.60 | 105.70 + + Each site is a 110 x 75 mm support plane with no additional offset or sinking. + Each insert is 15 mm high, with H1 at 5.5/6.0 mm from its left/front edges and a + 9 x 9 mm hole grid. The first H1 center is therefore 17.5/20.6 mm from the carrier + body edges. STARlet track placement adds a 100 mm Z datum, giving insert bottoms + at Z = 205.7 mm and tops at Z = 220.7 mm. + + The template also declares 127 x 86 mm plate sites at X = 5, Y = 9.5 + 96i, + Z = 109.2 mm. These are separate VENUS plate-placement references, not insert-base + coordinates, and are not added to the insert locations above. VENUS site IDs run + 5 through 1 from front to back; PyLabRobot indices run 0 through 4. + + The insert model gives an approximately 7.732 mm top opening and 13.049 mm cavity + depth, with the cavity bottom 1.951 mm above the insert base. The adapter's dz uses + this modeled bottom. Automatic plate placement aligns the plate origin to that + reference; it does not calculate how a particular plate contacts the tapered + cavities. Supply an explicit plate location when its seating height differs. + + Args: + name: The carrier name. + with_adapters: Mount five independent 182531 inserts. Defaults to empty sites. + """ + + support_height = 105.7 # from .x: insert base 93.7 minus rail underside -12.0 + adapter_x = 12.0 # from .x: insert edge -55.0 minus body left edge -67.0 + first_adapter_y = 14.6 # from .x: insert edge -229.4 minus body front edge -244.0 + site_pitch = 96.0 # from spec: .tml site Y differences; also present in the .x model + carrier = PlateCarrier( name=name, - size_x=135.0, - size_y=497.0, - size_z=130.0, + size_x=135.0, # from spec: .tml Dim.Dx + size_y=497.0, # from spec: .tml Dim.Dy + size_z=130.0, # from spec: .tml Dim.Dz and Clearance sites=create_homogeneous_resources( klass=PlateHolder, locations=[ - Coordinate(4.0, 8.5, 107.5), - Coordinate(4.0, 104.5, 107.5), - Coordinate(4.0, 200.5, 107.5), - Coordinate(4.0, 296.5, 107.5), - Coordinate(4.0, 392.5, 107.5), + Coordinate(adapter_x, first_adapter_y + i * site_pitch, support_height) + for i in range(5) # number of positions from spec ], - resource_size_x=127.0, - resource_size_y=86.0, + resource_size_x=110.0, # from the .x insert mesh bounds + resource_size_y=75.0, # from the .x insert mesh bounds + resource_size_z=0.0, # sites represent the adapter support plane name_prefix=name, + pedestal_size_z=0.0, # adapters rest on the support plane without sinking ), model="PLT_CAR_L5PCR", ) + if with_adapters: + for i in carrier.sites: + carrier[i] = Hamilton_96_adapter_182531(f"{name}_adapter_{i}") + return carrier def PLT_CAR_L5PCR_A00(name: str) -> PlateCarrier: