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
2 changes: 1 addition & 1 deletion pylabrobot/capabilities/automated_retrieval/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .automated_retrieval import AutomatedRetrieval
from .backend import AutomatedRetrievalBackend
from .backend import AutomatedRetrievalBackend, ensure_single_tray
27 changes: 21 additions & 6 deletions pylabrobot/capabilities/automated_retrieval/automated_retrieval.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from pylabrobot.capabilities.capability import Capability, need_capability_ready
from pylabrobot.resources import Plate, PlateHolder

Expand All @@ -15,14 +17,27 @@ def __init__(self, backend: AutomatedRetrievalBackend):
self.backend: AutomatedRetrievalBackend = backend

@need_capability_ready
async def fetch_plate_to_loading_tray(self, plate: Plate):
"""Retrieve a plate from storage and place it on the loading tray."""
await self.backend.fetch_plate_to_loading_tray(plate)
async def fetch_plate_to_loading_tray(self, plate: Plate, tray: Optional[int] = None):
"""Retrieve a plate from storage and place it on a loading tray.

Args:
plate: The plate to retrieve.
tray: 0-based index of the loading tray to deliver to. ``None`` selects the
device's default tray (single-tray devices only accept ``None``/``0``).
"""
await self.backend.fetch_plate_to_loading_tray(plate, tray=tray)

@need_capability_ready
async def store_plate(self, plate: Plate, site: PlateHolder):
"""Store a plate from the loading tray into the given site."""
await self.backend.store_plate(plate, site)
async def store_plate(self, plate: Plate, site: PlateHolder, tray: Optional[int] = None):
"""Store a plate from a loading tray into the given site.

Args:
plate: The plate to store.
site: The destination storage site.
tray: 0-based index of the loading tray the plate is on. ``None`` selects
the device's default tray.
"""
await self.backend.store_plate(plate, site, tray=tray)

async def _on_stop(self):
await super()._on_stop()
34 changes: 30 additions & 4 deletions pylabrobot/capabilities/automated_retrieval/backend.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
from abc import ABCMeta, abstractmethod
from typing import Optional

from pylabrobot.capabilities.capability import CapabilityBackend
from pylabrobot.resources import Plate, PlateHolder


def ensure_single_tray(tray: Optional[int]) -> None:
"""Guard for backends with exactly one loading tray.

Raises ``ValueError`` if ``tray`` is anything other than ``None`` (default) or
``0`` (the only tray).
"""
if tray not in (None, 0):
raise ValueError(f"This device has a single loading tray; got tray={tray}. Use None or 0.")


class AutomatedRetrievalBackend(CapabilityBackend, metaclass=ABCMeta):
"""Abstract backend for automated plate retrieval/storage devices."""

@abstractmethod
async def fetch_plate_to_loading_tray(self, plate: Plate):
"""Retrieve a plate from storage and place it on the loading tray."""
async def fetch_plate_to_loading_tray(self, plate: Plate, tray: Optional[int] = None):
"""Retrieve a plate from storage and place it on a loading tray.

Args:
plate: The plate to retrieve.
tray: 0-based index of the loading tray to deliver the plate to. ``None``
selects the device's default tray. Devices with a single loading tray
accept ``None``/``0`` and reject any other value (see
:func:`ensure_single_tray`).
"""

@abstractmethod
async def store_plate(self, plate: Plate, site: PlateHolder):
"""Store a plate from the loading tray into the given site."""
async def store_plate(self, plate: Plate, site: PlateHolder, tray: Optional[int] = None):
"""Store a plate from a loading tray into the given site.

Args:
plate: The plate to store.
site: The destination storage site.
tray: 0-based index of the loading tray the plate is currently on. ``None``
selects the device's default tray.
"""
9 changes: 5 additions & 4 deletions pylabrobot/capabilities/automated_retrieval/chatterbox.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
from typing import Optional

from pylabrobot.resources.carrier import PlateHolder
from pylabrobot.resources.plate import Plate
Expand All @@ -11,8 +12,8 @@
class AutomatedRetrievalChatterboxBackend(AutomatedRetrievalBackend):
"""Chatterbox backend for device-free testing."""

async def fetch_plate_to_loading_tray(self, plate: Plate):
logger.info("Fetching plate %s to loading tray.", plate.name)
async def fetch_plate_to_loading_tray(self, plate: Plate, tray: Optional[int] = None):
logger.info("Fetching plate %s to loading tray %s.", plate.name, tray)

async def store_plate(self, plate: Plate, site: PlateHolder):
logger.info("Storing plate %s at site %s.", plate.name, site.name)
async def store_plate(self, plate: Plate, site: PlateHolder, tray: Optional[int] = None):
logger.info("Storing plate %s at site %s (tray %s).", plate.name, site.name, tray)
Empty file added pylabrobot/highres/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions pylabrobot/highres/tundrastore/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from .backend import TundraStoreBackend
from .chatterbox import TundraStoreChatterboxBackend
from .constants import DoorState, NestState
from .errors import (
PlateNotFoundError,
TundraStoreAbortedError,
TundraStoreError,
TundraStoreFault,
)
from .settings import TundraStoreSettings
from .standard import (
DoorStatus,
EnvironmentParameter,
NestStatus,
StackerDimensions,
VersionInfo,
)
from .tundrastore import NoFreeSiteError, TundraStore
Loading
Loading