Skip to content
Open
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
20 changes: 15 additions & 5 deletions pylabrobot/visualizer3D/grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ def describe_bands(resource: Resource) -> Optional[List[Dict[str, Any]]]:
return described or None


def _depth_in(child: Resource, frame: Resource) -> float:
"""How far `child` reaches along `frame`'s y axis, in mm: its box, turned as it stands there."""
ys = [
child.get_location_wrt(frame, x, y, z).y
for x in ("l", "r")
for y in ("f", "b")
for z in ("b", "t")
]
return max(ys) - min(ys)


def describe_grid(resource: Resource) -> Optional[Dict[str, Any]]:
"""The repeated grid this resource lays positions on, or None if it lays none.

Expand Down Expand Up @@ -102,18 +113,17 @@ def describe_grid(resource: Resource) -> Optional[Dict[str, Any]]:

# A mark runs to the back of what the positions carry, not of the resource: the deepest child
# seated on the line (sharing its y), or the resource's own depth when nothing stands on it.
try:
depth = resource.get_absolute_size_y()
except Exception:
return None
# Both along the resource's own y, the frame the marks are drawn in, so turning the resource
# turns its marks without changing them.
depth = resource.get_size_y()

seated: List[float] = []
for child in getattr(resource, "children", []):
location = getattr(child, "location", None)
if location is None or abs(location.y - first.y) > SEATED_TOLERANCE:
continue
try:
seated.append(child.get_absolute_size_y())
seated.append(_depth_in(child, resource))
except Exception:
continue

Expand Down
30 changes: 30 additions & 0 deletions pylabrobot/visualizer3D/grids_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""The grids a resource lays its positions on, as the page is given them to draw."""

import unittest

from pylabrobot.resources.hamilton import STARLetDeck, hamilton_plate_carrier_L5_ac
from pylabrobot.visualizer3D.grids import describe_grid


class DescribeGridTests(unittest.TestCase):
"""A deck's grid is measured in the deck's own frame, the frame its marks are drawn in."""

def test_a_turned_deck_has_the_grid_it_has_upright(self):
"""The page draws a deck's marks in the deck's own frame and turns them with the deck, so the
grid is in that frame too. From a STARlet's front edge, its marks end at its back, 653.5 mm,
or at the back of a carrier on track 1, 560 mm: an `extent` of 590.5 or 497 mm from the first
track's line at 63 mm. A STARlet turned 90 degrees and measured along the world's y would end
its marks 1005 mm from its front edge, or 198 mm beside the carrier."""
for turn in (90, 37.5):
for with_carrier, extent in ((False, 590.5), (True, 497.0)):
upright, turned = STARLetDeck(), STARLetDeck()
if with_carrier:
for deck in (upright, turned):
deck.assign_child_resource(hamilton_plate_carrier_L5_ac("carrier"), track=1)
turned.rotate(z=turn)
with self.subTest(turn=turn, with_carrier=with_carrier):
upright_grid, turned_grid = describe_grid(upright), describe_grid(turned)
assert upright_grid is not None and turned_grid is not None
self.assertAlmostEqual(upright_grid.pop("extent"), extent, places=3)
self.assertAlmostEqual(turned_grid.pop("extent"), extent, places=3)
self.assertEqual(turned_grid, upright_grid)
Loading