From 5af6054095a05b307f63d5e900902b4f53f7aeef Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Fri, 22 Nov 2024 07:53:45 -0500 Subject: [PATCH 1/2] refactor: move useq_widgets to new top level module --- examples/points_plan_widget.py | 2 +- examples/well_plate_widget.py | 2 +- src/pymmcore_widgets/__init__.py | 17 +++++++++-------- .../_pixel_configuration_widget.py | 4 ++-- src/pymmcore_widgets/hcs/_hcs_wizard.py | 2 +- .../hcs/_plate_calibration_widget.py | 2 +- src/pymmcore_widgets/mda/_core_channels.py | 2 +- src/pymmcore_widgets/mda/_core_grid.py | 2 +- src/pymmcore_widgets/mda/_core_mda.py | 6 +++--- src/pymmcore_widgets/mda/_core_positions.py | 6 +++--- src/pymmcore_widgets/mda/_core_z.py | 2 +- .../useq_widgets/__init__.py | 0 .../useq_widgets/_channels.py | 0 .../useq_widgets/_checkable_tabwidget_widget.py | 0 .../useq_widgets/_column_info.py | 0 .../useq_widgets/_data_table.py | 0 .../useq_widgets/_grid.py | 0 .../useq_widgets/_mda_sequence.py | 12 ++++++------ .../useq_widgets/_positions.py | 0 .../useq_widgets/_time.py | 0 .../useq_widgets/_well_plate_widget.py | 0 src/{pymmcore_widgets => }/useq_widgets/_z.py | 0 .../useq_widgets/points_plans/__init__.py | 0 .../points_plans/_grid_row_column_widget.py | 0 .../points_plans/_points_plan_selector.py | 2 +- .../points_plans/_points_plan_widget.py | 2 +- .../points_plans/_random_points_widget.py | 0 .../points_plans/_well_graphics_view.py | 0 tests/hcs/test_well_plate_calibration_widget.py | 2 +- tests/test_useq_core_widgets.py | 4 ++-- tests/useq_widgets/test_plate_widget.py | 2 +- tests/useq_widgets/test_useq_points_plans.py | 4 ++-- tests/useq_widgets/test_useq_widgets.py | 10 +++++----- 33 files changed, 43 insertions(+), 42 deletions(-) rename src/{pymmcore_widgets => }/useq_widgets/__init__.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_channels.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_checkable_tabwidget_widget.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_column_info.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_data_table.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_grid.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_mda_sequence.py (98%) rename src/{pymmcore_widgets => }/useq_widgets/_positions.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_time.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_well_plate_widget.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/_z.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/points_plans/__init__.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/points_plans/_grid_row_column_widget.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/points_plans/_points_plan_selector.py (98%) rename src/{pymmcore_widgets => }/useq_widgets/points_plans/_points_plan_widget.py (97%) rename src/{pymmcore_widgets => }/useq_widgets/points_plans/_random_points_widget.py (100%) rename src/{pymmcore_widgets => }/useq_widgets/points_plans/_well_graphics_view.py (100%) diff --git a/examples/points_plan_widget.py b/examples/points_plan_widget.py index 5a03a5454..f300d6d89 100644 --- a/examples/points_plan_widget.py +++ b/examples/points_plan_widget.py @@ -1,7 +1,7 @@ from qtpy.QtWidgets import QApplication from useq import RandomPoints -from pymmcore_widgets.useq_widgets import PointsPlanWidget +from useq_widgets import PointsPlanWidget app = QApplication([]) diff --git a/examples/well_plate_widget.py b/examples/well_plate_widget.py index 36a9e0ba7..a6df24d4a 100644 --- a/examples/well_plate_widget.py +++ b/examples/well_plate_widget.py @@ -3,7 +3,7 @@ import useq from qtpy.QtWidgets import QApplication -from pymmcore_widgets.useq_widgets import WellPlateWidget +from useq_widgets import WellPlateWidget with suppress(ImportError): from rich import print diff --git a/src/pymmcore_widgets/__init__.py b/src/pymmcore_widgets/__init__.py index 799cb1b44..f82a71c7a 100644 --- a/src/pymmcore_widgets/__init__.py +++ b/src/pymmcore_widgets/__init__.py @@ -43,6 +43,15 @@ "ZPlanWidget", ] +from useq_widgets import ( + ChannelTable, + GridPlanWidget, + MDASequenceWidget, + PositionTable, + TimePlanWidget, + ZPlanWidget, +) + from ._install_widget import InstallWidget from .config_presets import ( GroupPresetTableWidget, @@ -67,14 +76,6 @@ from .hcs import HCSWizard from .hcwizard import ConfigWizard from .mda import MDAWidget -from .useq_widgets import ( - ChannelTable, - GridPlanWidget, - MDASequenceWidget, - PositionTable, - TimePlanWidget, - ZPlanWidget, -) from .views import ImagePreview if TYPE_CHECKING: diff --git a/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py b/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py index b628045c6..5a198bd76 100644 --- a/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py +++ b/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py @@ -32,8 +32,8 @@ ) from pymmcore_widgets.device_properties._device_type_filter import DeviceTypeFilters from pymmcore_widgets.device_properties._property_widget import PropertyWidget -from pymmcore_widgets.useq_widgets import DataTable, DataTableWidget -from pymmcore_widgets.useq_widgets._column_info import FloatColumn, TextColumn +from useq_widgets import DataTable, DataTableWidget +from useq_widgets._column_info import FloatColumn, TextColumn if TYPE_CHECKING: from collections.abc import Sequence diff --git a/src/pymmcore_widgets/hcs/_hcs_wizard.py b/src/pymmcore_widgets/hcs/_hcs_wizard.py index 4fca96bb1..2a1480a60 100644 --- a/src/pymmcore_widgets/hcs/_hcs_wizard.py +++ b/src/pymmcore_widgets/hcs/_hcs_wizard.py @@ -10,7 +10,7 @@ from qtpy.QtWidgets import QFileDialog, QVBoxLayout, QWidget, QWizard, QWizardPage from useq import WellPlatePlan -from pymmcore_widgets.useq_widgets import PointsPlanWidget, WellPlateWidget +from useq_widgets import PointsPlanWidget, WellPlateWidget from ._plate_calibration_widget import PlateCalibrationWidget diff --git a/src/pymmcore_widgets/hcs/_plate_calibration_widget.py b/src/pymmcore_widgets/hcs/_plate_calibration_widget.py index 711143b91..6c1261ac1 100644 --- a/src/pymmcore_widgets/hcs/_plate_calibration_widget.py +++ b/src/pymmcore_widgets/hcs/_plate_calibration_widget.py @@ -26,7 +26,7 @@ GREEN, WellCalibrationWidget, ) -from pymmcore_widgets.useq_widgets._well_plate_widget import WellPlateView +from useq_widgets._well_plate_widget import WellPlateView if TYPE_CHECKING: from collections.abc import Mapping diff --git a/src/pymmcore_widgets/mda/_core_channels.py b/src/pymmcore_widgets/mda/_core_channels.py index 07e30b62e..d1f62a178 100644 --- a/src/pymmcore_widgets/mda/_core_channels.py +++ b/src/pymmcore_widgets/mda/_core_channels.py @@ -4,7 +4,7 @@ from pymmcore_plus import CMMCorePlus -from pymmcore_widgets.useq_widgets import ChannelTable +from useq_widgets import ChannelTable if TYPE_CHECKING: from qtpy.QtWidgets import QWidget diff --git a/src/pymmcore_widgets/mda/_core_grid.py b/src/pymmcore_widgets/mda/_core_grid.py index f9088dfdb..1aa68a86b 100644 --- a/src/pymmcore_widgets/mda/_core_grid.py +++ b/src/pymmcore_widgets/mda/_core_grid.py @@ -3,7 +3,7 @@ from pymmcore_plus import CMMCorePlus from qtpy.QtWidgets import QHBoxLayout, QWidget -from pymmcore_widgets.useq_widgets._grid import GridPlanWidget +from useq_widgets._grid import GridPlanWidget from ._xy_bounds import CoreXYBoundsControl diff --git a/src/pymmcore_widgets/mda/_core_mda.py b/src/pymmcore_widgets/mda/_core_mda.py index cd4b15900..754d78c31 100644 --- a/src/pymmcore_widgets/mda/_core_mda.py +++ b/src/pymmcore_widgets/mda/_core_mda.py @@ -18,9 +18,9 @@ from useq import MDASequence, Position from pymmcore_widgets._util import get_next_available_path -from pymmcore_widgets.useq_widgets import MDASequenceWidget -from pymmcore_widgets.useq_widgets._mda_sequence import PYMMCW_METADATA_KEY, MDATabs -from pymmcore_widgets.useq_widgets._time import TimePlanWidget +from useq_widgets import MDASequenceWidget +from useq_widgets._mda_sequence import PYMMCW_METADATA_KEY, MDATabs +from useq_widgets._time import TimePlanWidget from ._core_channels import CoreConnectedChannelTable from ._core_grid import CoreConnectedGridPlanWidget diff --git a/src/pymmcore_widgets/mda/_core_positions.py b/src/pymmcore_widgets/mda/_core_positions.py index 6f5af1717..3dfa4f46a 100644 --- a/src/pymmcore_widgets/mda/_core_positions.py +++ b/src/pymmcore_widgets/mda/_core_positions.py @@ -20,11 +20,11 @@ from useq import WellPlatePlan from pymmcore_widgets import HCSWizard -from pymmcore_widgets.useq_widgets import PositionTable -from pymmcore_widgets.useq_widgets._column_info import ( +from useq_widgets import PositionTable +from useq_widgets._column_info import ( ButtonColumn, ) -from pymmcore_widgets.useq_widgets._positions import AF_DEFAULT_TOOLTIP +from useq_widgets._positions import AF_DEFAULT_TOOLTIP if TYPE_CHECKING: from collections.abc import Sequence diff --git a/src/pymmcore_widgets/mda/_core_z.py b/src/pymmcore_widgets/mda/_core_z.py index b2e988b20..588ba3de3 100644 --- a/src/pymmcore_widgets/mda/_core_z.py +++ b/src/pymmcore_widgets/mda/_core_z.py @@ -5,7 +5,7 @@ from fonticon_mdi6 import MDI6 from pymmcore_plus import CMMCorePlus -from pymmcore_widgets.useq_widgets._z import ROW_TOP_BOTTOM, Mode, ZPlanWidget +from useq_widgets._z import ROW_TOP_BOTTOM, Mode, ZPlanWidget from ._xy_bounds import MarkVisit diff --git a/src/pymmcore_widgets/useq_widgets/__init__.py b/src/useq_widgets/__init__.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/__init__.py rename to src/useq_widgets/__init__.py diff --git a/src/pymmcore_widgets/useq_widgets/_channels.py b/src/useq_widgets/_channels.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_channels.py rename to src/useq_widgets/_channels.py diff --git a/src/pymmcore_widgets/useq_widgets/_checkable_tabwidget_widget.py b/src/useq_widgets/_checkable_tabwidget_widget.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_checkable_tabwidget_widget.py rename to src/useq_widgets/_checkable_tabwidget_widget.py diff --git a/src/pymmcore_widgets/useq_widgets/_column_info.py b/src/useq_widgets/_column_info.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_column_info.py rename to src/useq_widgets/_column_info.py diff --git a/src/pymmcore_widgets/useq_widgets/_data_table.py b/src/useq_widgets/_data_table.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_data_table.py rename to src/useq_widgets/_data_table.py diff --git a/src/pymmcore_widgets/useq_widgets/_grid.py b/src/useq_widgets/_grid.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_grid.py rename to src/useq_widgets/_grid.py diff --git a/src/pymmcore_widgets/useq_widgets/_mda_sequence.py b/src/useq_widgets/_mda_sequence.py similarity index 98% rename from src/pymmcore_widgets/useq_widgets/_mda_sequence.py rename to src/useq_widgets/_mda_sequence.py index 0be577554..e3ef4fe04 100644 --- a/src/pymmcore_widgets/useq_widgets/_mda_sequence.py +++ b/src/useq_widgets/_mda_sequence.py @@ -22,12 +22,12 @@ from superqt.utils import signals_blocked import pymmcore_widgets -from pymmcore_widgets.useq_widgets._channels import ChannelTable -from pymmcore_widgets.useq_widgets._checkable_tabwidget_widget import CheckableTabWidget -from pymmcore_widgets.useq_widgets._grid import GridPlanWidget -from pymmcore_widgets.useq_widgets._positions import AF_DEFAULT_TOOLTIP, PositionTable -from pymmcore_widgets.useq_widgets._time import TimePlanWidget -from pymmcore_widgets.useq_widgets._z import Mode, ZPlanWidget +from useq_widgets._channels import ChannelTable +from useq_widgets._checkable_tabwidget_widget import CheckableTabWidget +from useq_widgets._grid import GridPlanWidget +from useq_widgets._positions import AF_DEFAULT_TOOLTIP, PositionTable +from useq_widgets._time import TimePlanWidget +from useq_widgets._z import Mode, ZPlanWidget if TYPE_CHECKING: from collections.abc import Sequence diff --git a/src/pymmcore_widgets/useq_widgets/_positions.py b/src/useq_widgets/_positions.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_positions.py rename to src/useq_widgets/_positions.py diff --git a/src/pymmcore_widgets/useq_widgets/_time.py b/src/useq_widgets/_time.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_time.py rename to src/useq_widgets/_time.py diff --git a/src/pymmcore_widgets/useq_widgets/_well_plate_widget.py b/src/useq_widgets/_well_plate_widget.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_well_plate_widget.py rename to src/useq_widgets/_well_plate_widget.py diff --git a/src/pymmcore_widgets/useq_widgets/_z.py b/src/useq_widgets/_z.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/_z.py rename to src/useq_widgets/_z.py diff --git a/src/pymmcore_widgets/useq_widgets/points_plans/__init__.py b/src/useq_widgets/points_plans/__init__.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/points_plans/__init__.py rename to src/useq_widgets/points_plans/__init__.py diff --git a/src/pymmcore_widgets/useq_widgets/points_plans/_grid_row_column_widget.py b/src/useq_widgets/points_plans/_grid_row_column_widget.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/points_plans/_grid_row_column_widget.py rename to src/useq_widgets/points_plans/_grid_row_column_widget.py diff --git a/src/pymmcore_widgets/useq_widgets/points_plans/_points_plan_selector.py b/src/useq_widgets/points_plans/_points_plan_selector.py similarity index 98% rename from src/pymmcore_widgets/useq_widgets/points_plans/_points_plan_selector.py rename to src/useq_widgets/points_plans/_points_plan_selector.py index 41072ab0b..2deff55d0 100644 --- a/src/pymmcore_widgets/useq_widgets/points_plans/_points_plan_selector.py +++ b/src/useq_widgets/points_plans/_points_plan_selector.py @@ -58,7 +58,7 @@ def __init__(self, parent: QWidget | None = None) -> None: class RelativePointPlanSelector(QWidget): """Widget to select a relative multi-position point plan. - See also: [PointsPlanWidget][pymmcore_widgets.useq_widgets.PointsPlanWidget] + See also: [PointsPlanWidget][useq_widgets.PointsPlanWidget] which combines this widget with a graphical representation of the points. In useq, a RelativeMultiPointPlan is one of: diff --git a/src/pymmcore_widgets/useq_widgets/points_plans/_points_plan_widget.py b/src/useq_widgets/points_plans/_points_plan_widget.py similarity index 97% rename from src/pymmcore_widgets/useq_widgets/points_plans/_points_plan_widget.py rename to src/useq_widgets/points_plans/_points_plan_widget.py index f9a4dbba6..43faf374f 100644 --- a/src/pymmcore_widgets/useq_widgets/points_plans/_points_plan_widget.py +++ b/src/useq_widgets/points_plans/_points_plan_widget.py @@ -4,7 +4,7 @@ from qtpy.QtCore import Signal from qtpy.QtWidgets import QHBoxLayout, QWidget -from pymmcore_widgets.useq_widgets.points_plans import RelativePointPlanSelector +from useq_widgets.points_plans import RelativePointPlanSelector from ._well_graphics_view import WellView diff --git a/src/pymmcore_widgets/useq_widgets/points_plans/_random_points_widget.py b/src/useq_widgets/points_plans/_random_points_widget.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/points_plans/_random_points_widget.py rename to src/useq_widgets/points_plans/_random_points_widget.py diff --git a/src/pymmcore_widgets/useq_widgets/points_plans/_well_graphics_view.py b/src/useq_widgets/points_plans/_well_graphics_view.py similarity index 100% rename from src/pymmcore_widgets/useq_widgets/points_plans/_well_graphics_view.py rename to src/useq_widgets/points_plans/_well_graphics_view.py diff --git a/tests/hcs/test_well_plate_calibration_widget.py b/tests/hcs/test_well_plate_calibration_widget.py index 53b8a0f63..9fc198ccc 100644 --- a/tests/hcs/test_well_plate_calibration_widget.py +++ b/tests/hcs/test_well_plate_calibration_widget.py @@ -2,7 +2,7 @@ from pymmcore_plus import CMMCorePlus from pymmcore_widgets.hcs._plate_calibration_widget import PlateCalibrationWidget -from pymmcore_widgets.useq_widgets._well_plate_widget import DATA_POSITION +from useq_widgets._well_plate_widget import DATA_POSITION def test_plate_calibration_value(global_mmcore: CMMCorePlus, qtbot) -> None: diff --git a/tests/test_useq_core_widgets.py b/tests/test_useq_core_widgets.py index e0b93ff73..8745dc519 100644 --- a/tests/test_useq_core_widgets.py +++ b/tests/test_useq_core_widgets.py @@ -17,13 +17,13 @@ from pymmcore_widgets.mda._core_mda import CoreMDATabs from pymmcore_widgets.mda._core_positions import CoreConnectedPositionTable from pymmcore_widgets.mda._core_z import CoreConnectedZPlanWidget -from pymmcore_widgets.useq_widgets._mda_sequence import ( +from useq_widgets._mda_sequence import ( PYMMCW_METADATA_KEY, AutofocusAxis, KeepShutterOpen, QFileDialog, ) -from pymmcore_widgets.useq_widgets._positions import AF_DEFAULT_TOOLTIP, _MDAPopup +from useq_widgets._positions import AF_DEFAULT_TOOLTIP, _MDAPopup if TYPE_CHECKING: from pymmcore_plus import CMMCorePlus diff --git a/tests/useq_widgets/test_plate_widget.py b/tests/useq_widgets/test_plate_widget.py index 0d8f5613c..633aa4dd3 100644 --- a/tests/useq_widgets/test_plate_widget.py +++ b/tests/useq_widgets/test_plate_widget.py @@ -8,7 +8,7 @@ from qtpy.QtCore import Qt from qtpy.QtGui import QMouseEvent -from pymmcore_widgets.useq_widgets import WellPlateWidget +from useq_widgets import WellPlateWidget if TYPE_CHECKING: from pytestqt.qtbot import QtBot diff --git a/tests/useq_widgets/test_useq_points_plans.py b/tests/useq_widgets/test_useq_points_plans.py index e5037ae4f..05d55f48b 100644 --- a/tests/useq_widgets/test_useq_points_plans.py +++ b/tests/useq_widgets/test_useq_points_plans.py @@ -10,12 +10,12 @@ 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 +from 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 + from useq_widgets.points_plans._well_graphics_view import WellView RANDOM_POINTS = RandomPoints( num_points=5, diff --git a/tests/useq_widgets/test_useq_widgets.py b/tests/useq_widgets/test_useq_widgets.py index fd704ff9c..9f0e123c1 100644 --- a/tests/useq_widgets/test_useq_widgets.py +++ b/tests/useq_widgets/test_useq_widgets.py @@ -12,7 +12,7 @@ from qtpy.QtWidgets import QMessageBox import pymmcore_widgets -from pymmcore_widgets.useq_widgets import ( +from useq_widgets import ( PYMMCW_METADATA_KEY, ChannelTable, DataTableWidget, @@ -24,13 +24,13 @@ _grid, _z, ) -from pymmcore_widgets.useq_widgets._column_info import ( +from useq_widgets._column_info import ( FloatColumn, QTimeLineEdit, TextColumn, parse_timedelta, ) -from pymmcore_widgets.useq_widgets._positions import MDAButton, QFileDialog, _MDAPopup +from useq_widgets._positions import MDAButton, QFileDialog, _MDAPopup if TYPE_CHECKING: from pathlib import Path @@ -138,7 +138,7 @@ def test_mda_wdg(qtbot: QtBot): def test_mda_wdg_load_save( qtbot: QtBot, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ext: str ) -> None: - from pymmcore_widgets.useq_widgets._mda_sequence import QFileDialog + from useq_widgets._mda_sequence import QFileDialog wdg = MDASequenceWidget() qtbot.addWidget(wdg) @@ -453,7 +453,7 @@ def test_proper_checked_index(qtbot) -> None: """ import useq - from pymmcore_widgets.useq_widgets._positions import _MDAPopup + from useq_widgets._positions import _MDAPopup seq = useq.MDASequence(grid_plan=useq.GridRowsColumns(rows=2, columns=3)) pop = _MDAPopup(seq) From 37eab44592510e3ad6881b190f3c85ac6977b5b1 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Fri, 22 Nov 2024 08:02:05 -0500 Subject: [PATCH 2/2] avoid private imports --- .../_pixel_configuration_widget.py | 3 +- .../hcs/_plate_calibration_widget.py | 2 +- src/pymmcore_widgets/mda/_core_grid.py | 2 +- src/pymmcore_widgets/mda/_core_mda.py | 4 +- src/pymmcore_widgets/mda/_core_positions.py | 10 ++--- src/pymmcore_widgets/mda/_core_z.py | 13 ++++-- src/useq_widgets/__init__.py | 13 ++++-- src/useq_widgets/_mda_sequence.py | 15 ++++--- src/useq_widgets/_z.py | 44 +++++++++---------- tests/useq_widgets/test_useq_widgets.py | 8 ++-- 10 files changed, 62 insertions(+), 52 deletions(-) diff --git a/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py b/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py index 5a198bd76..1e29c3dd3 100644 --- a/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py +++ b/src/pymmcore_widgets/config_presets/_pixel_configuration_widget.py @@ -32,8 +32,7 @@ ) from pymmcore_widgets.device_properties._device_type_filter import DeviceTypeFilters from pymmcore_widgets.device_properties._property_widget import PropertyWidget -from useq_widgets import DataTable, DataTableWidget -from useq_widgets._column_info import FloatColumn, TextColumn +from useq_widgets import DataTable, DataTableWidget, FloatColumn, TextColumn if TYPE_CHECKING: from collections.abc import Sequence diff --git a/src/pymmcore_widgets/hcs/_plate_calibration_widget.py b/src/pymmcore_widgets/hcs/_plate_calibration_widget.py index 6c1261ac1..92c5e6b2c 100644 --- a/src/pymmcore_widgets/hcs/_plate_calibration_widget.py +++ b/src/pymmcore_widgets/hcs/_plate_calibration_widget.py @@ -26,7 +26,7 @@ GREEN, WellCalibrationWidget, ) -from useq_widgets._well_plate_widget import WellPlateView +from useq_widgets import WellPlateView if TYPE_CHECKING: from collections.abc import Mapping diff --git a/src/pymmcore_widgets/mda/_core_grid.py b/src/pymmcore_widgets/mda/_core_grid.py index 1aa68a86b..6603fe7be 100644 --- a/src/pymmcore_widgets/mda/_core_grid.py +++ b/src/pymmcore_widgets/mda/_core_grid.py @@ -3,7 +3,7 @@ from pymmcore_plus import CMMCorePlus from qtpy.QtWidgets import QHBoxLayout, QWidget -from useq_widgets._grid import GridPlanWidget +from useq_widgets import GridPlanWidget from ._xy_bounds import CoreXYBoundsControl diff --git a/src/pymmcore_widgets/mda/_core_mda.py b/src/pymmcore_widgets/mda/_core_mda.py index 754d78c31..aa3960ef8 100644 --- a/src/pymmcore_widgets/mda/_core_mda.py +++ b/src/pymmcore_widgets/mda/_core_mda.py @@ -18,9 +18,7 @@ from useq import MDASequence, Position from pymmcore_widgets._util import get_next_available_path -from useq_widgets import MDASequenceWidget -from useq_widgets._mda_sequence import PYMMCW_METADATA_KEY, MDATabs -from useq_widgets._time import TimePlanWidget +from useq_widgets import PYMMCW_METADATA_KEY, MDASequenceWidget, MDATabs, TimePlanWidget from ._core_channels import CoreConnectedChannelTable from ._core_grid import CoreConnectedGridPlanWidget diff --git a/src/pymmcore_widgets/mda/_core_positions.py b/src/pymmcore_widgets/mda/_core_positions.py index 3dfa4f46a..aad88c140 100644 --- a/src/pymmcore_widgets/mda/_core_positions.py +++ b/src/pymmcore_widgets/mda/_core_positions.py @@ -20,11 +20,7 @@ from useq import WellPlatePlan from pymmcore_widgets import HCSWizard -from useq_widgets import PositionTable -from useq_widgets._column_info import ( - ButtonColumn, -) -from useq_widgets._positions import AF_DEFAULT_TOOLTIP +from useq_widgets import ButtonColumn, PositionTable if TYPE_CHECKING: from collections.abc import Sequence @@ -33,6 +29,10 @@ UPDATE_POSITIONS = "Update Positions List" ADD_POSITIONS = "Add to Positions List" +AF_DEFAULT_TOOLTIP = ( + "If checked, the user can set a different Hardware Autofocus Offset for each " + "Position in the table." +) class CoreConnectedPositionTable(PositionTable): diff --git a/src/pymmcore_widgets/mda/_core_z.py b/src/pymmcore_widgets/mda/_core_z.py index 588ba3de3..937f958c7 100644 --- a/src/pymmcore_widgets/mda/_core_z.py +++ b/src/pymmcore_widgets/mda/_core_z.py @@ -5,7 +5,7 @@ from fonticon_mdi6 import MDI6 from pymmcore_plus import CMMCorePlus -from useq_widgets._z import ROW_TOP_BOTTOM, Mode, ZPlanWidget +from useq_widgets import ZMode, ZPlanWidget from ._xy_bounds import MarkVisit @@ -13,6 +13,11 @@ from qtpy.QtWidgets import QWidget +# avoiding private import from useq_widgets... but could go out of sync +# see if this can be derived better +ROW_TOP_BOTTOM = 4 + + class CoreConnectedZPlanWidget(ZPlanWidget): """[ZPlanWidget](../ZPlanWidget#) connected to a Micro-Manager core instance. @@ -51,11 +56,11 @@ def __init__( def setMode( self, - mode: Mode | Literal["top_bottom", "range_around", "above_below"], + mode: ZMode | Literal["top_bottom", "range_around", "above_below"], ) -> None: super().setMode(mode) - self.bottom_btn.setVisible(self._mode == Mode.TOP_BOTTOM) - self.top_btn.setVisible(self._mode == Mode.TOP_BOTTOM) + self.bottom_btn.setVisible(self._mode == ZMode.TOP_BOTTOM) + self.top_btn.setVisible(self._mode == ZMode.TOP_BOTTOM) def _mark_bottom(self) -> None: self.bottom.setValue(self._mmc.getZPosition()) diff --git a/src/useq_widgets/__init__.py b/src/useq_widgets/__init__.py index 97cc16542..8d31eccf0 100644 --- a/src/useq_widgets/__init__.py +++ b/src/useq_widgets/__init__.py @@ -3,7 +3,9 @@ from ._channels import ChannelTable from ._column_info import ( BoolColumn, + ButtonColumn, ChoiceColumn, + ColumnInfo, FloatColumn, IntColumn, TextColumn, @@ -11,29 +13,34 @@ ) from ._data_table import DataTable, DataTableWidget from ._grid import GridPlanWidget -from ._mda_sequence import PYMMCW_METADATA_KEY, MDASequenceWidget +from ._mda_sequence import PYMMCW_METADATA_KEY, MDASequenceWidget, MDATabs from ._positions import PositionTable from ._time import TimePlanWidget -from ._well_plate_widget import WellPlateWidget -from ._z import ZPlanWidget +from ._well_plate_widget import WellPlateView, WellPlateWidget +from ._z import ZMode, ZPlanWidget from .points_plans import PointsPlanWidget __all__ = [ "BoolColumn", + "ButtonColumn", "ChannelTable", "ChoiceColumn", + "ColumnInfo", "DataTable", "DataTableWidget", "FloatColumn", "GridPlanWidget", "IntColumn", "MDASequenceWidget", + "MDATabs", "PointsPlanWidget", "PositionTable", "PYMMCW_METADATA_KEY", "TextColumn", "TimeDeltaColumn", "TimePlanWidget", + "WellPlateView", "WellPlateWidget", + "ZMode", "ZPlanWidget", ] diff --git a/src/useq_widgets/_mda_sequence.py b/src/useq_widgets/_mda_sequence.py index e3ef4fe04..f96393912 100644 --- a/src/useq_widgets/_mda_sequence.py +++ b/src/useq_widgets/_mda_sequence.py @@ -22,12 +22,13 @@ from superqt.utils import signals_blocked import pymmcore_widgets -from useq_widgets._channels import ChannelTable -from useq_widgets._checkable_tabwidget_widget import CheckableTabWidget -from useq_widgets._grid import GridPlanWidget -from useq_widgets._positions import AF_DEFAULT_TOOLTIP, PositionTable -from useq_widgets._time import TimePlanWidget -from useq_widgets._z import Mode, ZPlanWidget + +from ._channels import ChannelTable +from ._checkable_tabwidget_widget import CheckableTabWidget +from ._grid import GridPlanWidget +from ._positions import AF_DEFAULT_TOOLTIP, PositionTable +from ._time import TimePlanWidget +from ._z import ZMode, ZPlanWidget if TYPE_CHECKING: from collections.abc import Sequence @@ -524,7 +525,7 @@ def _validate_af_with_z_plan(self) -> None: If the Z Plan is set to TOP_BOTTOM, the autofocus plan cannot be used. """ - if self.z_plan.mode() == Mode.TOP_BOTTOM: + if self.z_plan.mode() == ZMode.TOP_BOTTOM: self._use_af_per_pos = self.stage_positions.af_per_position.isChecked() self._enable_af(False, AF_DISABLED_TOOLTIP, AF_DISABLED_TOOLTIP) if self.af_axis.use_af_p.isChecked(): diff --git a/src/useq_widgets/_z.py b/src/useq_widgets/_z.py index 40c872401..7bc76c7ff 100644 --- a/src/useq_widgets/_z.py +++ b/src/useq_widgets/_z.py @@ -25,7 +25,7 @@ from pymmcore_widgets._util import SeparatorWidget -class Mode(enum.Enum): +class ZMode(enum.Enum): """Recognized ZPlanWidget modes.""" TOP_BOTTOM = "top_bottom" @@ -62,7 +62,7 @@ def __init__(self, parent: QWidget | None = None) -> None: # to store a "suggested" step size self._suggested: float | None = None - self._mode: Mode = Mode.TOP_BOTTOM + self._mode: ZMode = ZMode.TOP_BOTTOM # #################### Mode Buttons #################### @@ -255,13 +255,13 @@ def __init__(self, parent: QWidget | None = None) -> None: # #################### Defaults #################### - self.setMode(Mode.TOP_BOTTOM) + self.setMode(ZMode.TOP_BOTTOM) # ------------------------- Public API ------------------------- def setMode( self, - mode: Mode | Literal["top_bottom", "range_around", "above_below"], + mode: ZMode | Literal["top_bottom", "range_around", "above_below"], ) -> None: """Set the current mode. @@ -274,32 +274,32 @@ def setMode( If None, the mode is determined by the sender().data(), for internal usage. """ if isinstance(mode, QRadioButton): - btn_map: dict[QAbstractButton, Mode] = { - self._btn_top_bot: Mode.TOP_BOTTOM, - self._btn_range: Mode.RANGE_AROUND, - self._button_above_below: Mode.ABOVE_BELOW, + btn_map: dict[QAbstractButton, ZMode] = { + self._btn_top_bot: ZMode.TOP_BOTTOM, + self._btn_range: ZMode.RANGE_AROUND, + self._button_above_below: ZMode.ABOVE_BELOW, } self._mode = btn_map[mode] elif isinstance(mode, str): - self._mode = Mode(mode) + self._mode = ZMode(mode) else: self._mode = mode - if self._mode is Mode.TOP_BOTTOM: + if self._mode is ZMode.TOP_BOTTOM: with signals_blocked(self._mode_btn_group): self._btn_top_bot.setChecked(True) self._set_row_visible(ROW_RANGE_AROUND, False) self._set_row_visible(ROW_ABOVE_BELOW, False) self._set_row_visible(ROW_TOP_BOTTOM, True) - elif self._mode is Mode.RANGE_AROUND: + elif self._mode is ZMode.RANGE_AROUND: with signals_blocked(self._mode_btn_group): self._btn_range.setChecked(True) self._set_row_visible(ROW_TOP_BOTTOM, False) self._set_row_visible(ROW_ABOVE_BELOW, False) self._set_row_visible(ROW_RANGE_AROUND, True) - elif self._mode is Mode.ABOVE_BELOW: + elif self._mode is ZMode.ABOVE_BELOW: with signals_blocked(self._mode_btn_group): self._button_above_below.setChecked(True) self._set_row_visible(ROW_RANGE_AROUND, False) @@ -308,7 +308,7 @@ def setMode( self._on_change() - def mode(self) -> Mode: + def mode(self) -> ZMode: """Return the current mode. One of "top_bottom", "range_around", or "above_below". @@ -347,15 +347,15 @@ def value(self) -> useq.ZAboveBelow | useq.ZRangeAround | useq.ZTopBottom | None return None common = {"step": self.step.value(), "go_up": self._bottom_to_top.isChecked()} - if self._mode is Mode.TOP_BOTTOM: + if self._mode is ZMode.TOP_BOTTOM: return useq.ZTopBottom( top=round(self.top.value(), 4), bottom=round(self.bottom.value(), 4), **common, ) - elif self._mode is Mode.RANGE_AROUND: + elif self._mode is ZMode.RANGE_AROUND: return useq.ZRangeAround(range=round(self.range.value(), 4), **common) - elif self._mode is Mode.ABOVE_BELOW: + elif self._mode is ZMode.ABOVE_BELOW: return useq.ZAboveBelow( above=round(self.above.value(), 4), below=round(self.below.value(), 4), @@ -377,14 +377,14 @@ def setValue( if isinstance(value, useq.ZTopBottom): self.top.setValue(value.top) self.bottom.setValue(value.bottom) - self.setMode(Mode.TOP_BOTTOM) + self.setMode(ZMode.TOP_BOTTOM) elif isinstance(value, useq.ZRangeAround): self.range.setValue(value.range) - self.setMode(Mode.RANGE_AROUND) + self.setMode(ZMode.RANGE_AROUND) elif isinstance(value, useq.ZAboveBelow): self.above.setValue(value.above) self.below.setValue(value.below) - self.setMode(Mode.ABOVE_BELOW) + self.setMode(ZMode.ABOVE_BELOW) else: raise TypeError(f"Invalid value type: {type(value)}") @@ -402,14 +402,14 @@ def setGoUp(self, up: bool) -> None: def currentZRange(self) -> float: """Return the current Z range in microns.""" - if self._mode is Mode.TOP_BOTTOM: + if self._mode is ZMode.TOP_BOTTOM: return abs(self.top.value() - self.bottom.value()) # type: ignore - elif self._mode is Mode.RANGE_AROUND: + elif self._mode is ZMode.RANGE_AROUND: return self.range.value() # type: ignore else: # _Mode.ABOVE_BELOW return self.above.value() + self.below.value() # type: ignore - Mode: Final[type[Mode]] = Mode + Mode: Final[type[ZMode]] = ZMode # ------------------------- Private API ------------------------- diff --git a/tests/useq_widgets/test_useq_widgets.py b/tests/useq_widgets/test_useq_widgets.py index 9f0e123c1..1a274839d 100644 --- a/tests/useq_widgets/test_useq_widgets.py +++ b/tests/useq_widgets/test_useq_widgets.py @@ -355,15 +355,15 @@ def test_z_plan_widget(qtbot: QtBot) -> None: wdg.setMode("top_bottom") - assert wdg.mode() == _z.Mode.TOP_BOTTOM + assert wdg.mode() == _z.ZMode.TOP_BOTTOM assert wdg.top.isVisible() assert not wdg.above.isVisible() assert wdg._btn_top_bot.isChecked() - wdg.setMode(_z.Mode.RANGE_AROUND) + wdg.setMode(_z.ZMode.RANGE_AROUND) assert wdg.range.isVisible() assert not wdg.top.isVisible() assert wdg._btn_range.isChecked() - wdg.setMode(_z.Mode.ABOVE_BELOW) + wdg.setMode(_z.ZMode.ABOVE_BELOW) assert wdg.above.isVisible() assert not wdg.range.isVisible() assert wdg._button_above_below.isChecked() @@ -533,7 +533,7 @@ def _qmsgbox(*args, **kwargs): with patch.object(QMessageBox, "warning", _qmsgbox): wdg.tab_wdg.setChecked(wdg.z_plan, True) - assert wdg.z_plan.mode() == _z.Mode.TOP_BOTTOM + assert wdg.z_plan.mode() == _z.ZMode.TOP_BOTTOM assert not wdg.af_axis.isEnabled() assert not wdg.stage_positions.af_per_position.isEnabled() assert wdg.af_axis.value() == ()