Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions pylabrobot/resources/hamilton/vantage_decks.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from pylabrobot.resources.coordinate import Coordinate
from pylabrobot.resources.hamilton.hamilton_decks import (
_TRACK_WIDTH,
Expand All @@ -16,6 +18,7 @@ def __init__(
category: str = "deck",
origin: Coordinate = Coordinate.zero(),
with_trash: bool = True,
model: Optional[str] = None,
) -> None:
"""Create a new Vantage deck of the given size.

Expand All @@ -38,6 +41,7 @@ def __init__(
name=name,
category=category,
origin=origin,
model=model,
)
self.size = 1.3

Expand All @@ -50,7 +54,30 @@ def __init__(
location=Coordinate(x=trash_x, y=185.6, z=137.1),
) # z I am not sure about
elif size == 2.0:
raise NotImplementedError("2.0m Vantage decks are not yet supported.")
# A 2.0 m Vantage reports 84 tracks in its machine configuration, on the same 22.5 mm
# raster as the 1.3 m deck.
size_x = (84 + 1) * _TRACK_WIDTH # 1912.5
super().__init__(
num_tracks=84,
size_x=size_x,
size_y=653.5,
size_z=900.0,
name=name,
category=category,
origin=origin,
model=model,
)
self.size = 2.0

if with_trash:
# x and z are where a 2.0 m Vantage ejects tips into the waste when initializing the
# pipetting channels (`A1PMDI xp13845 ... tz1235`: eject x 1384.5, tip-end deposit
# z 123.5, with the channels spread between y 201.6 and 389.1). y is the same front
# edge as on the 1.3 m deck.
self.assign_child_resource(
resource=Trash("trash", size_x=0, size_y=260, size_z=0),
location=Coordinate(x=1384.5, y=185.6, z=123.5),
)
else:
raise ValueError(f"Invalid deck size: {size}")

Expand All @@ -60,6 +87,15 @@ def track_to_location(self, track: int) -> Coordinate:

def serialize(self) -> dict:
super_serialized = super().serialize()
for key in ["size_x", "size_y", "size_z", "num_rails"]:
# Drop the keys `__init__` derives from `size`, and the `HamiltonDeck` keys it does not take.
for key in [
"size_x",
"size_y",
"size_z",
"num_tracks",
"num_rails",
"with_trash96",
"core_grippers",
]:
super_serialized.pop(key, None)
return {"size": self.size, **super_serialized}
44 changes: 44 additions & 0 deletions pylabrobot/resources/hamilton/vantage_decks_tests.py

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we do not need tests for declarations like this

Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import unittest

from pylabrobot.resources import Coordinate, Deck
from pylabrobot.resources.hamilton import VantageDeck


class VantageDeckTests(unittest.TestCase):
def test_a_1_3_m_deck_has_54_tracks(self):
deck = VantageDeck(size=1.3)
self.assertEqual(deck.num_tracks, 54)
self.assertEqual(deck.get_absolute_size_x(), 1237.5)
self.assertEqual(deck.get_absolute_size_y(), 653.5)

def test_a_2_0_m_deck_has_84_tracks_on_the_same_raster(self):
deck = VantageDeck(size=2.0)
self.assertEqual(deck.num_tracks, 84)
self.assertEqual(deck.get_absolute_size_x(), 1912.5)
self.assertEqual(deck.get_absolute_size_y(), 653.5)
self.assertEqual(deck.track_to_location(1), Coordinate(x=32.5, y=63, z=100))
self.assertEqual(deck.track_to_location(84), Coordinate(x=32.5 + 83 * 22.5, y=63, z=100))

def test_a_2_0_m_deck_puts_the_trash_at_the_channel_waste(self):
deck = VantageDeck(size=2.0)
trash = deck.get_trash_area()
self.assertEqual(trash.get_location_wrt(deck), Coordinate(x=1384.5, y=185.6, z=123.5))

def test_an_unknown_size_is_refused(self):
with self.assertRaises(ValueError):
VantageDeck(size=1.8)

def test_serialization_keeps_the_size(self):
for size in (1.3, 2.0):
with self.subTest(size=size):
deck = VantageDeck(size=size)
serialized = deck.serialize()
self.assertEqual(serialized["size"], size)
deck2 = Deck.deserialize(serialized)
assert isinstance(deck2, VantageDeck)
self.assertEqual(deck2.size, size)
self.assertEqual(deck2.num_tracks, deck.num_tracks)
self.assertEqual(
deck2.get_trash_area().get_location_wrt(deck2),
deck.get_trash_area().get_location_wrt(deck),
)
Loading