From c9e9e5acea6ded33b28417b27287cdedb71e499c Mon Sep 17 00:00:00 2001 From: Michael Osthege Date: Thu, 18 Jul 2024 19:00:17 +0200 Subject: [PATCH] Introduce `Worklist(diti_mode=...)` for DiTi-compatible wash schemes Closes #77 --- robotools/fluenttools/worklist.py | 3 ++- robotools/worklists/base.py | 11 +++++++++++ robotools/worklists/test_base.py | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/robotools/fluenttools/worklist.py b/robotools/fluenttools/worklist.py index 76ff6f9..48adaeb 100644 --- a/robotools/fluenttools/worklist.py +++ b/robotools/fluenttools/worklist.py @@ -25,8 +25,9 @@ def __init__( filepath: Optional[Union[str, Path]] = None, max_volume: Union[int, float] = 950, auto_split: bool = True, + diti_mode: bool = False, ) -> None: - super().__init__(filepath, max_volume, auto_split) + super().__init__(filepath, max_volume, auto_split, diti_mode) def _get_well_position(self, labware: Labware, well: str) -> int: return get_well_position(labware, well) diff --git a/robotools/worklists/base.py b/robotools/worklists/base.py index fcff899..8d11d4b 100644 --- a/robotools/worklists/base.py +++ b/robotools/worklists/base.py @@ -26,6 +26,7 @@ def __init__( filepath: Optional[Union[str, Path]] = None, max_volume: Union[int, float] = 950, auto_split: bool = True, + diti_mode: bool = False, ) -> None: """Creates a worklist writer. @@ -38,6 +39,9 @@ def __init__( auto_split : bool If `True`, large volumes in transfer operations are automatically splitted. If set to `False`, `InvalidOperationError` is raised when a pipetting volume exceeds `max_volume`. + diti_mode + Activate this when using DiTis. + Uses ``W;`` for all wash schemes and raises errors when using commands that are only for fixed tips. """ self._filepath: Optional[Path] = None if filepath is not None: @@ -46,6 +50,7 @@ def __init__( raise ValueError("The `max_volume` parameter is required.") self.max_volume = max_volume self.auto_split = auto_split + self.diti_mode = diti_mode super().__init__() @property @@ -113,6 +118,10 @@ def wash(self, scheme: int = 1) -> None: scheme : int Number indicating the wash scheme (default: 1) """ + if self.diti_mode: + self.append("W;") + return + if not scheme in {1, 2, 3, 4}: raise ValueError("scheme must be either 1, 2, 3 or 4") self.append(f"W{scheme};") @@ -120,6 +129,8 @@ def wash(self, scheme: int = 1) -> None: def decontaminate(self) -> None: """Decontamination wash consists of a decontamination wash followed by a normal wash.""" + if self.diti_mode: + raise InvalidOperationError("Decontamination wash is not available with DiTis.") self.append("WD;") return diff --git a/robotools/worklists/test_base.py b/robotools/worklists/test_base.py index 222f57a..0eb6383 100644 --- a/robotools/worklists/test_base.py +++ b/robotools/worklists/test_base.py @@ -201,6 +201,14 @@ def test_wash(self) -> None: "W4;", ] assert wl == exp + + with BaseWorklist(diti_mode=True) as wl: + wl.wash() + wl.wash(3) + assert wl == [ + "W;", + "W;", + ] return @pytest.mark.parametrize("cls", [EvoWorklist, FluentWorklist]) @@ -233,12 +241,21 @@ def test_wash_schemes(self, cls, scheme, exp): assert wl[-1] == "F;" else: raise NotImplementedError() + + # In DiTi mode, any numeric wash scheme results in "W;" + with cls(diti_mode=True) as wl: + wl.transfer(A, "A01", A, "A01", 25, wash_scheme=2) + assert wl[-1] == "W;" pass def test_decontaminate(self) -> None: with BaseWorklist() as wl: wl.decontaminate() assert wl == ["WD;"] + + with BaseWorklist(diti_mode=True) as wl: + with pytest.raises(InvalidOperationError, match="not available"): + wl.decontaminate() return def test_flush(self) -> None: