From fe3520748851c314ecfbbb869282e53f1da3deb8 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Thu, 12 Sep 2024 17:41:32 -0400 Subject: [PATCH] refactor: make None imply no selected wells (#186) --- .pre-commit-config.yaml | 6 +++--- src/useq/_plate.py | 17 ++++++++++++++--- tests/test_well_plate.py | 4 ++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fe5fab3..a36962b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,19 +7,19 @@ default_install_hook_types: [pre-commit, commit-msg] repos: - repo: https://github.com/abravalheri/validate-pyproject - rev: v0.18 + rev: v0.19 hooks: - id: validate-pyproject - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.5.6 + rev: v0.6.4 hooks: - id: ruff args: [--fix, --unsafe-fixes] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.1 + rev: v1.11.2 hooks: - id: mypy files: "^src/" diff --git a/src/useq/_plate.py b/src/useq/_plate.py index f273f0c..aa7a767 100644 --- a/src/useq/_plate.py +++ b/src/useq/_plate.py @@ -120,6 +120,8 @@ def from_str(cls, name: str) -> WellPlate: f"Unknown plate name {name!r}. " "Use `useq.register_well_plates` to add new plate definitions" ) from e + if isinstance(obj, dict) and "name" not in obj: + obj = {**obj, "name": name} return WellPlate.model_validate(obj) @@ -144,10 +146,11 @@ class WellPlatePlan(UseqModel, Sequence[Position]): selected_wells : IndexExpression | None Any <=2-dimensional index expression for selecting wells. for example: - - None -> all wells are selected. + - None -> No wells are selected. + - slice(0) -> (also) select no wells. + - slice(None) -> Selects all wells. - 0 -> Selects the first row. - [0, 1, 2] -> Selects the first three rows. - - slice(0) -> select no wells - slice(1, 5) -> selects wells from row 1 to row 4. - (2, slice(1, 4)) -> select wells in the second row and only columns 1 to 3. - ([1, 2], [3, 4]) -> select wells in (row, column): (1, 3) and (2, 4) @@ -236,6 +239,10 @@ def _validate_selected_wells( if isinstance(value, list): value = tuple(value) + # make falsey values select no wells (rather than all wells) + if not value: + value = slice(0) + try: selected = plate.indices(value) except (TypeError, IndexError) as e: @@ -261,11 +268,15 @@ def __iter__(self) -> Iterable[Position]: # type: ignore def __len__(self) -> int: """Return the total number of points (stage positions) to be acquired.""" if self.selected_wells is None: - n_wells = self.plate.size + n_wells = 0 else: n_wells = len(self.selected_wells[0]) return n_wells * self.num_points_per_well + def __bool__(self) -> bool: + """bool(WellPlatePlan) == True.""" + return True + @overload def __getitem__(self, index: int) -> Position: ... diff --git a/tests/test_well_plate.py b/tests/test_well_plate.py index 70f91c6..9023be4 100644 --- a/tests/test_well_plate.py +++ b/tests/test_well_plate.py @@ -33,9 +33,13 @@ def test_plate_plan_well_points() -> None: a1_center_xy=(500, 200), rotation="0.2rad", well_points_plan=useq.RandomPoints(num_points=10), + selected_wells=slice(None), ) assert len(pp) == 96 * 10 + pp2 = useq.WellPlatePlan(plate=96, a1_center_xy=(500, 200), selected_wells=None) + assert len(pp2) == 0 + def test_plate_plan_plot(monkeypatch: pytest.MonkeyPatch) -> None: mpl = pytest.importorskip("matplotlib.pyplot")