Skip to content

Commit

Permalink
test: add
Browse files Browse the repository at this point in the history
  • Loading branch information
fdrgsp committed Jul 11, 2024
1 parent 854c303 commit 555cf94
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,6 @@ def setValue(self, plan: useq.RelativeMultiPointPlan) -> None:
"""Set the current plan."""
self._selector.setValue(plan)

def wellSize(self) -> tuple[float | None, float | None]:
"""Return the well size in mm."""
w = self._well_width_µm / 1000 if self._well_width_µm is not None else None
h = self._well_height_µm / 1000 if self._well_height_µm is not None else None
return w, h

def setWellSize(
self, width: float | None = None, height: float | None = None
) -> None:
Expand All @@ -84,7 +78,7 @@ def setWellShape(self, shape: useq.Shape | str) -> None:
if isinstance(shape, str):
if shape.lower() == "circle":
shape = useq.Shape.ELLIPSE
if shape.lower() == "square":
elif shape.lower() == "square":
shape = useq.Shape.RECTANGLE
shape = useq.Shape(shape)
self._well_view.setWellCircular(shape == useq.Shape.ELLIPSE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,6 @@ def __init__(self, parent: QWidget | None = None) -> None:
def sizeHint(self) -> QSize:
return QSize(500, 500)

def wellSize(self) -> tuple[float | None, float | None]:
"""Return the well size in mm."""
return (
self._well_width_um / 1000 if self._well_width_um else None,
self._well_height_um / 1000 if self._well_height_um else None,
)

def setWellSize(self, width_mm: float | None, height_mm: float | None) -> None:
"""Set the well size width and height in mm."""
self._well_width_um = (width_mm * 1000) if width_mm else None
Expand Down
121 changes: 90 additions & 31 deletions tests/useq_widgets/test_useq_points_plans.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, NamedTuple

import pytest
import qtpy
import useq
from qtpy.QtCore import Qt
from qtpy.QtGui import QMouseEvent
from qtpy.QtWidgets import QGraphicsEllipseItem, QGraphicsLineItem, QGraphicsRectItem
from useq import GridRowsColumns, OrderMode, RandomPoints, RelativePosition, Shape

from pymmcore_widgets.useq_widgets import points_plans as pp

if TYPE_CHECKING:
from pytestqt.qtbot import QtBot

from pymmcore_widgets.useq_widgets.points_plans._well_graphics_view import WellView

RANDOM_POINTS = RandomPoints(
num_points=5,
shape="rectangle",
Expand Down Expand Up @@ -43,8 +46,8 @@ def test_random_points_widget(qtbot: QtBot) -> None:
wdg = pp.RandomPointWidget()
qtbot.addWidget(wdg)
assert wdg.num_points.value() == 1
assert wdg.max_width.value() == 1000
assert wdg.max_height.value() == 1000
assert wdg.max_width.value() == 6000
assert wdg.max_height.value() == 6000
assert wdg.shape.currentText() == "ellipse"
assert not wdg.allow_overlap.isChecked()
assert wdg.order.currentText() == "two_opt"
Expand Down Expand Up @@ -201,45 +204,101 @@ def test_max_points_detected(qtbot: QtBot) -> None:
assert wdg.value().num_points < 60


def test_set_well_area(qtbot: QtBot) -> None:
def test_points_plan_set_well_info(qtbot: QtBot) -> None:
wdg = pp.PointsPlanWidget()
wdg.show()

assert wdg._well_view._well_outline_item is None
assert wdg._well_view._bounding_area_item is None
assert wdg._well_view._well_is_circular

wdg.setWellSize(3, 3)

with qtbot.waitSignal(wdg._well_view.wellSizeSet):
wdg.setWellSize(3, 3)
assert wdg._selector.random_points_wdg.max_width.maximum() == 3000
assert wdg._selector.random_points_wdg.max_height.maximum() == 3000
assert wdg._well_view._well_outline_item
assert wdg._well_view._well_outline_item.isVisible()
assert isinstance(wdg._well_view._well_outline_item, QGraphicsEllipseItem)

wdg.setWellShape("square")
assert isinstance(wdg._well_view._well_outline_item, QGraphicsRectItem)

plan = RandomPoints(
num_points=20, fov_width=500, fov_height=500, max_width=4000, max_height=4000
num_points=3, fov_width=500, fov_height=0, max_width=1000, max_height=1500
)
wdg.setValue(plan)
# max_width and max_height should be capped at 3000
assert wdg.value().max_width == 3000
assert wdg.value().max_height == 3000

with qtbot.waitSignal(wdg._well_view.wellSizeSet):
wdg.setWellSize(None, None)
assert wdg._well_view._outline_item is None
assert wdg._well_view._bounding_area is None
assert wdg._well_view._bounding_area_item
assert wdg._well_view._bounding_area_item.isVisible()
assert isinstance(wdg._well_view._bounding_area_item, QGraphicsEllipseItem)

well = wdg._well_view._well_outline_item.sceneBoundingRect()
bound = wdg._well_view._bounding_area_item.sceneBoundingRect()
assert well.center() == bound.center()
offset = 20 # ofset automatically added when drawing
# bounding rect should be 1/2 the size of the well rect in width
assert well.width() - offset == (bound.width() - offset) * 3
# bounding rect should be 1/3 the size of the well rect in height
assert well.height() - offset == (bound.height() - offset) * 2

wdg.setWellSize(None, None)
assert wdg._well_view._well_outline_item is None


class SceneItems(NamedTuple):
rect: int # QGraphicsRectItem (fovs/well area/bounding area)
lines: int # QGraphicsLineItem (fovs lines)
circles: int # QGraphicsEllipseItem (well area/bounding area)


def get_items_number(view: WellView) -> SceneItems:
"""Return the number of items in the scene as a SceneItems namedtuple."""
items = view.scene().items()
lines = len([ln for ln in items if isinstance(ln, QGraphicsLineItem)])
circles = len([c for c in items if isinstance(c, QGraphicsEllipseItem)])
rect = len([r for r in items if isinstance(r, QGraphicsRectItem)])
return SceneItems(rect, lines, circles)


# fmt: off
rp = RandomPoints(num_points=3, max_width=1000, max_height=1000,fov_width=410, fov_height=300, random_seed=0) # noqa E501
plans = [
# plan, well_shape, expected number of QGraphicsItems
(useq.RelativePosition(), "square", SceneItems(rect=0, lines=0, circles=2)),
(useq.RelativePosition(fov_width=100, fov_height=50), "circle", SceneItems(rect=1, lines=0, circles=1)), # noqa E501
(rp, "ellipse", SceneItems(rect=3, lines=2, circles=2)),
(rp.replace(shape="rectangle"),"rectangle", SceneItems(rect=4, lines=2, circles=1)),
(GridRowsColumns(rows=2, columns=3, fov_width=400, fov_height=500), "circle", SceneItems(rect=6, lines=5, circles=1)) # noqa E501
]
# fmt: on


# make sure that the correct QGraphicsItems are drawn in the scene
@pytest.mark.parametrize(["plan", "shape", "expedted_items"], plans)
def test_points_plan_plans(
qtbot: QtBot,
plan: useq.RelativeMultiPointPlan,
shape: str,
expedted_items: SceneItems,
):
wdg = pp.PointsPlanWidget(plan=plan)
wdg.setWellSize(3, 3) # fix well size
wdg.setWellShape("circle") # fix well shape
wdg.show()
assert get_items_number(wdg._well_view) == expedted_items

def test_restricted_area(qtbot: QtBot) -> None:

@pytest.mark.parametrize(["plan", "shape", "expedted_items"], plans)
def test_points_plan_set_get_value(
qtbot: QtBot,
plan: useq.RelativeMultiPointPlan,
shape: str,
expedted_items: SceneItems,
):
wdg = pp.PointsPlanWidget()
wdg.setWellSize(3, 3) # fix well size
wdg.setWellShape("circle") # fix well shape
wdg.show()

wdg.setWellSize(3, 3)
plan = RandomPoints(
num_points=20, fov_width=200, fov_height=300, max_width=1500, max_height=1000
)
wdg.setValue(plan)

well_rect = wdg._well_view._outline_item.sceneBoundingRect()
bounding_rect = wdg._well_view._bounding_area.sceneBoundingRect()

# both rects should have the same center
assert well_rect.center() == bounding_rect.center()
offset = 20 # ofset automatically added when using addEllipse
# bounding rect should be 1/2 the size of the well rect in width
assert well_rect.width() - offset == (bounding_rect.width() - offset) * 2
# bounding rect should be 1/3 the size of the well rect in height
assert well_rect.height() - offset == (bounding_rect.height() - offset) * 3
assert get_items_number(wdg._well_view) == expedted_items
assert wdg.value() == plan

0 comments on commit 555cf94

Please sign in to comment.