pymmcore-plus 0.12.0__py3-none-any.whl → 0.13.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. pymmcore_plus/__init__.py +3 -3
  2. pymmcore_plus/_benchmark.py +203 -0
  3. pymmcore_plus/_cli.py +78 -13
  4. pymmcore_plus/_logger.py +10 -2
  5. pymmcore_plus/_pymmcore.py +12 -0
  6. pymmcore_plus/_util.py +16 -10
  7. pymmcore_plus/core/__init__.py +3 -0
  8. pymmcore_plus/core/_config.py +1 -1
  9. pymmcore_plus/core/_config_group.py +2 -2
  10. pymmcore_plus/core/_constants.py +27 -3
  11. pymmcore_plus/core/_device.py +4 -4
  12. pymmcore_plus/core/_metadata.py +1 -1
  13. pymmcore_plus/core/_mmcore_plus.py +184 -118
  14. pymmcore_plus/core/_property.py +3 -5
  15. pymmcore_plus/core/_sequencing.py +369 -234
  16. pymmcore_plus/core/events/__init__.py +3 -3
  17. pymmcore_plus/experimental/__init__.py +0 -0
  18. pymmcore_plus/experimental/unicore/__init__.py +14 -0
  19. pymmcore_plus/experimental/unicore/_device_manager.py +173 -0
  20. pymmcore_plus/experimental/unicore/_proxy.py +127 -0
  21. pymmcore_plus/experimental/unicore/_unicore.py +703 -0
  22. pymmcore_plus/experimental/unicore/devices/__init__.py +0 -0
  23. pymmcore_plus/experimental/unicore/devices/_device.py +269 -0
  24. pymmcore_plus/experimental/unicore/devices/_properties.py +400 -0
  25. pymmcore_plus/experimental/unicore/devices/_stage.py +221 -0
  26. pymmcore_plus/install.py +10 -7
  27. pymmcore_plus/mda/__init__.py +1 -1
  28. pymmcore_plus/mda/_engine.py +152 -43
  29. pymmcore_plus/mda/_runner.py +8 -1
  30. pymmcore_plus/mda/events/__init__.py +2 -2
  31. pymmcore_plus/mda/handlers/__init__.py +1 -1
  32. pymmcore_plus/mda/handlers/_ome_zarr_writer.py +2 -2
  33. pymmcore_plus/mda/handlers/_tensorstore_handler.py +6 -2
  34. pymmcore_plus/metadata/__init__.py +3 -3
  35. pymmcore_plus/metadata/functions.py +18 -8
  36. pymmcore_plus/metadata/schema.py +6 -5
  37. pymmcore_plus/mocks.py +49 -0
  38. pymmcore_plus/model/_config_file.py +1 -1
  39. pymmcore_plus/model/_core_device.py +10 -1
  40. pymmcore_plus/model/_device.py +17 -6
  41. pymmcore_plus/model/_property.py +11 -2
  42. pymmcore_plus/seq_tester.py +1 -1
  43. {pymmcore_plus-0.12.0.dist-info → pymmcore_plus-0.13.1.dist-info}/METADATA +14 -6
  44. pymmcore_plus-0.13.1.dist-info/RECORD +71 -0
  45. {pymmcore_plus-0.12.0.dist-info → pymmcore_plus-0.13.1.dist-info}/WHEEL +1 -1
  46. pymmcore_plus-0.12.0.dist-info/RECORD +0 -59
  47. {pymmcore_plus-0.12.0.dist-info → pymmcore_plus-0.13.1.dist-info}/entry_points.txt +0 -0
  48. {pymmcore_plus-0.12.0.dist-info → pymmcore_plus-0.13.1.dist-info}/licenses/LICENSE +0 -0
@@ -9,6 +9,8 @@ from itertools import product
9
9
  from os import PathLike
10
10
  from typing import TYPE_CHECKING, Any, cast
11
11
 
12
+ import numpy as np
13
+
12
14
  from pymmcore_plus.metadata.serialize import json_dumps, json_loads
13
15
 
14
16
  from ._util import position_sizes
@@ -17,7 +19,6 @@ if TYPE_CHECKING:
17
19
  from collections.abc import Mapping, Sequence
18
20
  from typing import Literal, TypeAlias
19
21
 
20
- import numpy as np
21
22
  import tensorstore as ts
22
23
  import useq
23
24
  from typing_extensions import Self # py311
@@ -234,7 +235,10 @@ class TensorStoreHandler:
234
235
  # FIXME: will fail on slices
235
236
  indexers = {**(indexers or {}), **indexers_kwargs}
236
237
  ts_index = self._event_index_to_store_index(indexers)
237
- return self._store[ts_index].read().result().squeeze() # type: ignore
238
+ if self._store is None: # pragma: no cover
239
+ warnings.warn("No data written.", stacklevel=2)
240
+ return np.empty([])
241
+ return self._store[ts_index].read().result().squeeze() # type: ignore [no-any-return]
238
242
 
239
243
  def new_store(
240
244
  self, frame: np.ndarray, seq: useq.MDASequence | None, meta: FrameMetaV1
@@ -20,17 +20,17 @@ __all__ = [
20
20
  "ConfigPreset",
21
21
  "ConfigPreset",
22
22
  "DeviceInfo",
23
- "frame_metadata",
24
23
  "FrameMetaV1",
25
24
  "ImageInfo",
26
- "json_dumps",
27
25
  "PixelSizeConfigPreset",
28
26
  "Position",
29
27
  "PropertyInfo",
30
28
  "PropertyValue",
31
29
  "StagePosition",
32
- "summary_metadata",
33
30
  "SummaryMetaV1",
34
31
  "SystemInfo",
32
+ "frame_metadata",
33
+ "json_dumps",
34
+ "summary_metadata",
35
35
  "to_builtins",
36
36
  ]
@@ -8,9 +8,8 @@ from pymmcore_plus._util import timestamp
8
8
  from pymmcore_plus.core._constants import DeviceType, PixelFormat
9
9
 
10
10
  if TYPE_CHECKING:
11
- from typing import Unpack
12
-
13
11
  import useq
12
+ from typing_extensions import Unpack
14
13
 
15
14
  from pymmcore_plus.core import CMMCorePlus
16
15
 
@@ -36,6 +35,7 @@ if TYPE_CHECKING:
36
35
  images_remaining_in_buffer: int
37
36
  camera_metadata: dict[str, Any]
38
37
  extra: dict[str, Any]
38
+ position: Position
39
39
 
40
40
  # -----------------------------------------------------------------
41
41
  # These are the two main functions that are called from the outside
@@ -78,10 +78,11 @@ def frame_metadata(
78
78
  runner_time_ms: float = -1,
79
79
  camera_device: str | None = None,
80
80
  property_values: tuple[PropertyValue, ...] = (),
81
+ include_position: bool = False,
81
82
  **kwargs: Unpack[_OptionalFrameMetaKwargs],
82
83
  ) -> FrameMetaV1:
83
84
  """Return metadata for the current frame."""
84
- return {
85
+ info: FrameMetaV1 = {
85
86
  "format": "frame-dict",
86
87
  "version": "1.0",
87
88
  "runner_time_ms": runner_time_ms,
@@ -89,9 +90,11 @@ def frame_metadata(
89
90
  "property_values": property_values,
90
91
  "exposure_ms": core.getExposure(),
91
92
  "pixel_size_um": core.getPixelSizeUm(cached),
92
- "position": position(core),
93
93
  **kwargs,
94
94
  }
95
+ if include_position and "position" not in kwargs:
96
+ info["position"] = position(core)
97
+ return info
95
98
 
96
99
 
97
100
  # ----------------------------------------------
@@ -213,12 +216,19 @@ def image_infos(core: CMMCorePlus) -> tuple[ImageInfo, ...]:
213
216
  def position(core: CMMCorePlus, all_stages: bool = False) -> Position:
214
217
  """Return current position of active (and, optionally, all) stages."""
215
218
  position: Position = {}
216
- with suppress(Exception):
217
- position["x"] = core.getXPosition()
218
- with suppress(Exception):
219
- position["y"] = core.getYPosition()
219
+
220
+ try:
221
+ # single shot faster when it works
222
+ position["x"], position["y"] = core.getXYPosition()
223
+ except RuntimeError:
224
+ with suppress(Exception):
225
+ position["x"] = core.getXPosition()
226
+ with suppress(Exception):
227
+ position["y"] = core.getYPosition()
228
+
220
229
  with suppress(Exception):
221
230
  position["z"] = core.getPosition()
231
+
222
232
  if all_stages:
223
233
  pos_list: list[StagePosition] = []
224
234
  for stage in core.getLoadedDevicesOfType(DeviceType.Stage):
@@ -4,16 +4,16 @@ import useq
4
4
  from typing_extensions import NotRequired
5
5
 
6
6
  __all__ = [
7
- "FrameMetaV1",
8
- "SummaryMetaV1",
9
7
  "ConfigGroup",
10
8
  "ConfigPreset",
11
9
  "DeviceInfo",
10
+ "FrameMetaV1",
12
11
  "ImageInfo",
13
12
  "PixelSizeConfigPreset",
14
13
  "Position",
15
14
  "PropertyInfo",
16
15
  "PropertyValue",
16
+ "SummaryMetaV1",
17
17
  "SystemInfo",
18
18
  ]
19
19
 
@@ -430,14 +430,15 @@ class FrameMetaV1(TypedDict):
430
430
  The label of the camera device used to acquire the image.
431
431
  exposure_ms: float
432
432
  The exposure time in milliseconds.
433
- position: Position
434
- The current stage position(s) in 3D space.
435
433
  property_values: tuple[PropertyValue, ...]
436
434
  Device property settings. This is not a comprehensive list of all device
437
435
  properties, but only those that may have changed for this frame (such as
438
436
  properties in the channel config or light path config).
439
437
  runner_time_ms: float
440
438
  Elapsed time in milliseconds since the beginning of the MDA sequence.
439
+ position: Position
440
+ *NotRequired*. The current stage position(s) in 3D space. This is often slow
441
+ to retrieve, so its inclusion is optional and left to the implementer.
441
442
  mda_event: useq.MDAEvent
442
443
  *NotRequired*. The MDA event object that commanded the acquisition of this
443
444
  frame.
@@ -461,9 +462,9 @@ class FrameMetaV1(TypedDict):
461
462
  pixel_size_um: float
462
463
  camera_device: Optional[str]
463
464
  exposure_ms: float
464
- position: Position
465
465
  property_values: tuple[PropertyValue, ...]
466
466
  runner_time_ms: float
467
+ position: NotRequired[Position]
467
468
  mda_event: NotRequired[useq.MDAEvent]
468
469
  hardware_triggered: NotRequired[bool]
469
470
  images_remaining_in_buffer: NotRequired[int]
pymmcore_plus/mocks.py ADDED
@@ -0,0 +1,49 @@
1
+ from typing import Any
2
+ from unittest.mock import MagicMock
3
+
4
+
5
+ class MockSequenceableCore(MagicMock):
6
+ """Sequenceable mock for testing."""
7
+
8
+ def __init__(self, *args: Any, max_len: int = 100, **kwargs: Any) -> None:
9
+ super().__init__(*args, **kwargs)
10
+
11
+ from pymmcore_plus import CMMCorePlus
12
+
13
+ if isinstance(kwargs.get("wraps", None), CMMCorePlus):
14
+ self.isExposureSequenceable.return_value = True
15
+ self.getExposureSequenceMaxLength.return_value = max_len
16
+
17
+ self.isStageSequenceable.return_value = True
18
+ self.getStageSequenceMaxLength.return_value = max_len
19
+
20
+ self.isXYStageSequenceable.return_value = True
21
+ self.getXYStageSequenceMaxLength.return_value = max_len
22
+
23
+ self.getSLMSequenceMaxLength.return_value = max_len
24
+ self.getPropertySequenceMaxLength.return_value = max_len
25
+
26
+ self.isPropertySequenceable.side_effect = self._isPropertySequenceable
27
+
28
+ self.loadExposureSequence.return_value = None
29
+ self.loadStageSequence.return_value = None
30
+ self.loadXYStageSequence.return_value = None
31
+ self.loadSLMSequence.return_value = None
32
+
33
+ self.loadPropertySequence.return_value = None
34
+
35
+ self.startExposureSequence.return_value = None
36
+ self.stopExposureSequence.return_value = None
37
+
38
+ self.startStageSequence.return_value = None
39
+ self.stopStageSequence.return_value = None
40
+
41
+ self.startXYStageSequence.return_value = None
42
+ self.stopXYStageSequence.return_value = None
43
+
44
+ self.startPropertySequence.return_value = None
45
+ self.stopPropertySequence.return_value = None
46
+
47
+ def _isPropertySequenceable(self, dev: str, prop: str) -> bool:
48
+ # subclass to implement more interesting behavior
49
+ return True
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
20
20
 
21
21
  Executor: TypeAlias = Callable[[Microscope, Sequence[str]], None]
22
22
 
23
- __all__ = ["load_from_string", "dump"]
23
+ __all__ = ["dump", "load_from_string"]
24
24
 
25
25
 
26
26
  def load_from_string(text: str, scope: Microscope | None = None) -> Microscope:
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING
4
+ from typing import TYPE_CHECKING, Any
5
5
 
6
6
  from pymmcore_plus import CMMCorePlus, DeviceType, Keyword
7
7
 
@@ -50,6 +50,15 @@ class CoreDevice(Device):
50
50
  def __post_init__(self) -> None:
51
51
  self.CORE_GETTERS = {}
52
52
 
53
+ def __setstate__(self, state: dict[str, Any]) -> None:
54
+ super().__setstate__(state)
55
+ prop_objects = []
56
+ for prop in self.properties:
57
+ if isinstance(prop, dict):
58
+ prop = Property(**prop)
59
+ prop_objects.append(prop)
60
+ self.properties = prop_objects
61
+
53
62
  def __hash__(self) -> int:
54
63
  return super().__hash__()
55
64
 
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import dataclasses
4
4
  from contextlib import suppress
5
- from dataclasses import dataclass, field
5
+ from dataclasses import asdict, dataclass, field
6
6
  from typing import TYPE_CHECKING
7
7
 
8
8
  from pymmcore_plus import CMMCorePlus, DeviceType, FocusDirection, Keyword
@@ -193,11 +193,7 @@ class Device(CoreObject):
193
193
  raise RuntimeError(f"Device {self.name} is not loaded in the core.")
194
194
 
195
195
  self.device_type = core.getDeviceType(self.name)
196
- self.CORE_GETTERS = {
197
- DeviceType.StateDevice: STATE_DEVICE_GETTERS,
198
- DeviceType.StageDevice: STAGE_DEVICE_GETTERS,
199
- DeviceType.Hub: HUB_DEVICE_GETTERS,
200
- }.get(self.device_type, DEVICE_GETTERS)
196
+ self._update_core_getters()
201
197
 
202
198
  super().update_from_core(core, exclude=exclude, on_err=on_err)
203
199
  self.properties = [
@@ -205,6 +201,21 @@ class Device(CoreObject):
205
201
  for prop_name in core.getDevicePropertyNames(self.name)
206
202
  ]
207
203
 
204
+ # pulled out for the sake of picklability
205
+ def _update_core_getters(self) -> None:
206
+ self.CORE_GETTERS = {
207
+ DeviceType.StateDevice: STATE_DEVICE_GETTERS,
208
+ DeviceType.StageDevice: STAGE_DEVICE_GETTERS,
209
+ DeviceType.Hub: HUB_DEVICE_GETTERS,
210
+ }.get(self.device_type, DEVICE_GETTERS)
211
+
212
+ def __reduce__(self) -> str | tuple[Any, ...]:
213
+ return self.__class__, (), asdict(self)
214
+
215
+ def __setstate__(self, state: dict[str, Any]) -> None:
216
+ self.__dict__.update(state)
217
+ self._update_core_getters()
218
+
208
219
  def load(self, core: CMMCorePlus, *, reload: bool = False) -> None:
209
220
  """Load device properties from the core."""
210
221
  if reload and self.name in core.getLoadedDevices():
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import dataclass, field
4
- from typing import TYPE_CHECKING
3
+ from dataclasses import asdict, dataclass, field
4
+ from typing import TYPE_CHECKING, Any
5
5
 
6
6
  from pymmcore_plus import CMMCorePlus, PropertyType
7
7
 
@@ -53,6 +53,15 @@ class Property(CoreObject):
53
53
  "exists": CMMCorePlus.hasProperty,
54
54
  }
55
55
 
56
+ def __reduce__(self) -> tuple:
57
+ # Return the class, arguments for __init__, and any state to restore
58
+ state = asdict(self)
59
+ return self.__class__, (self.device_name, self.name), state
60
+
61
+ def __setstate__(self, state: dict[str, Any]) -> None:
62
+ # Restore the state of the object
63
+ self.__dict__.update(state)
64
+
56
65
  def _core_args(self) -> tuple[str, str]:
57
66
  # the first two args to all of the funcs in CORE_GETTERS
58
67
  return self.device_name, self.name
@@ -41,7 +41,7 @@ if TYPE_CHECKING:
41
41
  import numpy as np
42
42
  from typing_extensions import Self # py311
43
43
 
44
- __all__ = ["CameraInfo", "Setting", "SettingEvent", "InfoPacket", "decode_image"]
44
+ __all__ = ["CameraInfo", "InfoPacket", "Setting", "SettingEvent", "decode_image"]
45
45
 
46
46
 
47
47
  @dataclass
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: pymmcore-plus
3
- Version: 0.12.0
3
+ Version: 0.13.1
4
4
  Summary: pymmcore superset providing improved APIs, event handling, and a pure python acquisition engine
5
5
  Project-URL: Source, https://github.com/pymmcore-plus/pymmcore-plus
6
6
  Project-URL: Tracker, https://github.com/pymmcore-plus/pymmcore-plus/issues
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.9
20
20
  Classifier: Programming Language :: Python :: 3.10
21
21
  Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
23
24
  Classifier: Topic :: System :: Hardware
24
25
  Classifier: Topic :: System :: Hardware :: Hardware Drivers
25
26
  Classifier: Topic :: Utilities
@@ -29,11 +30,10 @@ Requires-Dist: platformdirs>=3.0.0
29
30
  Requires-Dist: psygnal>=0.7
30
31
  Requires-Dist: pymmcore>=10.7.0.71.0
31
32
  Requires-Dist: rich>=10.2.0
32
- Requires-Dist: tensorstore
33
+ Requires-Dist: tensorstore; python_version < '3.13'
33
34
  Requires-Dist: typer>=0.4.2
34
35
  Requires-Dist: typing-extensions
35
- Requires-Dist: useq-schema>=0.5.0
36
- Requires-Dist: wrapt>=1.14
36
+ Requires-Dist: useq-schema>=0.6.2
37
37
  Provides-Extra: cli
38
38
  Requires-Dist: rich>=10.2.0; extra == 'cli'
39
39
  Requires-Dist: typer>=0.4.2; extra == 'cli'
@@ -53,9 +53,17 @@ Requires-Dist: mkdocstrings==0.22.0; extra == 'docs'
53
53
  Provides-Extra: io
54
54
  Requires-Dist: tifffile>=2021.6.14; extra == 'io'
55
55
  Requires-Dist: zarr<3,>=2.2; extra == 'io'
56
+ Provides-Extra: pyqt5
57
+ Requires-Dist: pyqt5>=5.15.4; extra == 'pyqt5'
58
+ Provides-Extra: pyqt6
59
+ Requires-Dist: pyqt6<6.8,>=6.4.2; extra == 'pyqt6'
60
+ Provides-Extra: pyside2
61
+ Requires-Dist: pyside2>=5.15; extra == 'pyside2'
62
+ Provides-Extra: pyside6
63
+ Requires-Dist: pyside6<6.8,>=6.4.0; extra == 'pyside6'
56
64
  Provides-Extra: test
57
65
  Requires-Dist: msgpack; extra == 'test'
58
- Requires-Dist: msgspec; extra == 'test'
66
+ Requires-Dist: msgspec; (python_version < '3.13') and extra == 'test'
59
67
  Requires-Dist: pytest-cov>=4; extra == 'test'
60
68
  Requires-Dist: pytest-qt>=4; extra == 'test'
61
69
  Requires-Dist: pytest>=7.3.2; extra == 'test'
@@ -0,0 +1,71 @@
1
+ pymmcore_plus/__init__.py,sha256=9-vK2P2jkJJ2REhCjFDBbJu0wrZM0jvDcf-d2GsjTk0,1415
2
+ pymmcore_plus/_benchmark.py,sha256=YJICxXleFQVbOluJdq4OujnIcTkkuMVzeB8GJ8nUv5I,6011
3
+ pymmcore_plus/_build.py,sha256=RPTAuwCZWGL5IDJj4JZo1DIIouUsIqS3vnbPbG2_bRE,10993
4
+ pymmcore_plus/_cli.py,sha256=FWdIvr6Rh9DVAItFaz9fWx7CbbF8ikOHWICp5h0NHTw,16393
5
+ pymmcore_plus/_logger.py,sha256=d7ldqxY0rGWORKdIzNUiFc9BW6cFBx57kHWtXyY1HE0,5416
6
+ pymmcore_plus/_pymmcore.py,sha256=QGlCEEx2pz5JsRLy3nQX3afAvV-_rm6ptWsv05U5hxI,328
7
+ pymmcore_plus/_util.py,sha256=mz5fuyzOhoMARyKYeri8FnR6eHwXsOh45WNZblewS1E,20435
8
+ pymmcore_plus/install.py,sha256=OLKkssJbQ9VSU0Rclkke0fb4Ng1YKb3Ij9rYYbQuusM,8705
9
+ pymmcore_plus/mocks.py,sha256=jNUfmffD1OArtIvEmqWsy7GCrtTpssVF03flH8cEYx8,1867
10
+ pymmcore_plus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ pymmcore_plus/seq_tester.py,sha256=PJFQmb-JwGhliwIgje9BOUNcaayDsA-2x278xoumfig,3768
12
+ pymmcore_plus/core/__init__.py,sha256=rYHv5JQVMVDlwYD1wodCc5L9ZbpVld1C_swGx4CRogA,1011
13
+ pymmcore_plus/core/_adapter.py,sha256=eu2BhGe_dnoQrIsh-u3poxWXsiF2Y8pfbKIGWbUgOk8,2857
14
+ pymmcore_plus/core/_config.py,sha256=yWwOnW6f37lLt83MnodNce04az-g8YDjyo7BvMiTc8s,10672
15
+ pymmcore_plus/core/_config_group.py,sha256=R-o4xuPDBPQAC3s-mFsiKwHVKWR38L9qq_aoWdPrAq8,8542
16
+ pymmcore_plus/core/_constants.py,sha256=ugXgCKVHt9E2s8outgA1cVgoB2Ea9Io4mcgxu5o_UAA,12617
17
+ pymmcore_plus/core/_device.py,sha256=Pz9Ekhss2c9IBA3B7WyMU2cCwc19Dp_dGVhMkzqUaIE,7762
18
+ pymmcore_plus/core/_metadata.py,sha256=3vb3d36XgNnUY44dpZ4Ccw0tvn4KCinZ8zrnDllmABI,2645
19
+ pymmcore_plus/core/_mmcore_plus.py,sha256=8tjNxpSRfDLmYbNllLgJ2RVbKLpeUsOMb0hw-MPR9BI,91621
20
+ pymmcore_plus/core/_property.py,sha256=QsQEzqOAedR24zEJ1Ge4kwScfT_7NOApVcgz6QxBJrI,8265
21
+ pymmcore_plus/core/_sequencing.py,sha256=Vb6hbRsb8RxSPUAlNSVWTM4Yvg7YYf9ZbewK7u_b-QM,16692
22
+ pymmcore_plus/core/events/__init__.py,sha256=Bb1Ga97GzY2z3fAeJkPs1wxbTXa1o_p6nIKof_UCvZs,1093
23
+ pymmcore_plus/core/events/_device_signal_view.py,sha256=t-NfBdg3E4rms4vDFxkkR5XtrpLxaBT7mfPwkpIsbVk,1079
24
+ pymmcore_plus/core/events/_norm_slot.py,sha256=8DCBoLHGh7cbB1OB19IJYwL6sFBFmkD8IakfBOvFbw8,2907
25
+ pymmcore_plus/core/events/_prop_event_mixin.py,sha256=FvJJnpEKrOR-_Sp3-NNCwFoUUHwmNKiHruo0Y1vybsY,4042
26
+ pymmcore_plus/core/events/_protocol.py,sha256=V4st91mw6LoogII2c05vJxD5SIQU24va86J0iqJWqXU,7528
27
+ pymmcore_plus/core/events/_psygnal.py,sha256=owaKlW2zpvocXDbAW4kHovBoVv4Fjfn-S5oUJrVWsD4,1646
28
+ pymmcore_plus/core/events/_qsignals.py,sha256=gr-GDiSVLhFhSfaoKrdTz2y3I_2IUg62bYDGuGrB3j0,3018
29
+ pymmcore_plus/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ pymmcore_plus/experimental/unicore/__init__.py,sha256=OcjUZ4tq-NtWDR5R3JFivsRePliQSIQ7Z92k_8Gfz2Q,361
31
+ pymmcore_plus/experimental/unicore/_device_manager.py,sha256=c5DAMsnK06xOy6G7YjHdUughc7xdFtzeo10woO5G_KE,6418
32
+ pymmcore_plus/experimental/unicore/_proxy.py,sha256=Sl_Jiwd4RlcKgmsrEUNZT38YPFGlQonELAg_n3sfbdo,4020
33
+ pymmcore_plus/experimental/unicore/_unicore.py,sha256=HM1rTpFFAtn5nuO9vJGsYGVkyTzeV-EY2KYdAY7EbWM,29027
34
+ pymmcore_plus/experimental/unicore/devices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ pymmcore_plus/experimental/unicore/devices/_device.py,sha256=PfX4BSpVMPXyNCNWkZ0Xy1-72ZZdME5zm7NgtCRu8ts,9751
36
+ pymmcore_plus/experimental/unicore/devices/_properties.py,sha256=yqVyoXb3VSbHahN2mXOIgeKOS7pUQeiJIZ_Y2d55dTI,15387
37
+ pymmcore_plus/experimental/unicore/devices/_stage.py,sha256=Ab4uibYq1cjIBtwcthCxH2FudGq9UMjub-qVeRpApQY,7892
38
+ pymmcore_plus/mda/__init__.py,sha256=RXI4ubqV71lLTFVrj62UpGzXVwOOQfJSiXR0k5tRXdk,298
39
+ pymmcore_plus/mda/_engine.py,sha256=m-GsTMCIX2CgyUZb32Cyp52fh3WcUW--evk_yLANu-E,29534
40
+ pymmcore_plus/mda/_protocol.py,sha256=10CDJ9H57oX1z0oqK3eShXyQhufHvvu3_8wdaCYpPIg,3254
41
+ pymmcore_plus/mda/_runner.py,sha256=IeZ34e4rcjRoPayCYJo_xn33yB4kPFltt23ntHE9TVI,16679
42
+ pymmcore_plus/mda/_thread_relay.py,sha256=Ww-9gyvLEzwRhnpL1dpze71wL7IRlhH8K3Q1dmJIxgs,6193
43
+ pymmcore_plus/mda/events/__init__.py,sha256=rHTyhQZJ54dz-KtetvN22GvAY2ilR03x8v4H0qUR070,1191
44
+ pymmcore_plus/mda/events/_protocol.py,sha256=9Q7LjYOgEWQGS8gHMV97UXM9bhoVW2OeyoPyNsQbwzw,1659
45
+ pymmcore_plus/mda/events/_psygnal.py,sha256=TdN1mFGpTPXmEs9iwFKSC1svv87PDZkT2JZvl0tEGrQ,640
46
+ pymmcore_plus/mda/events/_qsignals.py,sha256=tULQg-e_NX197DxJXaWHn1zLJ-4tzc9QyOAnsobEDtA,554
47
+ pymmcore_plus/mda/handlers/_5d_writer_base.py,sha256=c9cA0n8DOBoZcy9asue5eV7jW8hFVC0XEewroFgDNHA,11925
48
+ pymmcore_plus/mda/handlers/__init__.py,sha256=LdO3jf47fb4gXmbP9I8f5xC9Mrfd_-shf86OAaN9LdA,305
49
+ pymmcore_plus/mda/handlers/_img_sequence_writer.py,sha256=fAj6CB90RXYJ2jJIRDFxZgQb-TfwuRPWGCPFopCijRI,11549
50
+ pymmcore_plus/mda/handlers/_ome_tiff_writer.py,sha256=pqqdl3KQd0tH5Gp4rHVgYqqh2Y8iwoKRXTjwq1JLy1E,6239
51
+ pymmcore_plus/mda/handlers/_ome_zarr_writer.py,sha256=cKg3kJR7TId6M2qC1nJMLlxkv5vlfA5XEAlTIr9kt_E,12275
52
+ pymmcore_plus/mda/handlers/_tensorstore_handler.py,sha256=_xaUkDEYoTO29u4iHPQK8ygcCy8CSCXYi1xu5QF8B8E,14829
53
+ pymmcore_plus/mda/handlers/_util.py,sha256=pZydpKAXtQ_gjq5x1yNK1D0hfS7NUL2nH9ivOBg4abc,1600
54
+ pymmcore_plus/metadata/__init__.py,sha256=0o_v53kwR4U_RLlCnr7GD1G6OdFlVuUByIqXiaaM5uk,699
55
+ pymmcore_plus/metadata/functions.py,sha256=EjwB-6UO8c8AUriawhbE7x6ZAR1vJAxc72iYqyes5PQ,12506
56
+ pymmcore_plus/metadata/schema.py,sha256=j7nMwjCBXaAC0zKA2OsF201dsOB_3b2ggjqIa7EiVPQ,17368
57
+ pymmcore_plus/metadata/serialize.py,sha256=hpXJm0tzILELf6OYECMg0sQhuf-h25ob6_DDl-TUUME,3805
58
+ pymmcore_plus/model/__init__.py,sha256=zKZkkSpNK4ERu-VMdi9gvRrj1aXAjNaYxlYB5PdYSg0,479
59
+ pymmcore_plus/model/_config_file.py,sha256=Cw3bF1DLQUbMXVz59ZEUjfSaXcw8Lz6StIagReIKB-k,13280
60
+ pymmcore_plus/model/_config_group.py,sha256=vL_-EWH-Nsb8xTgFqpYIFaJzBk_RDBFchBnQ61DMSvI,3407
61
+ pymmcore_plus/model/_core_device.py,sha256=viwMgrCTZn1XYIyjC8w4xj1XAmoowZmCb93isGbG8BE,2722
62
+ pymmcore_plus/model/_core_link.py,sha256=dsbT0gncfa3TAORSaWUrZR9rcI_nOLX9e5BTmyo-UYo,2737
63
+ pymmcore_plus/model/_device.py,sha256=-0s3NkonDoaMrNy_hn5EDz-c4o33ZiJSQkV_kdBteoo,16115
64
+ pymmcore_plus/model/_microscope.py,sha256=69VV6cuevinOK_LhYEkQygHGesvCZefdn9YNt3mV618,11353
65
+ pymmcore_plus/model/_pixel_size_config.py,sha256=smoOmT54nSkg52RaSQzTFG0YwyMR_SEq_lkS-JyJW9U,3514
66
+ pymmcore_plus/model/_property.py,sha256=NQzNtnEzSCR9ogwx1cfi8X-qbJ_cBSJKdSBAaoKoPQ0,3720
67
+ pymmcore_plus-0.13.1.dist-info/METADATA,sha256=TJaJKDATvzOOeJtqyDBP9Xsp1RZwLZQNM0TUdRvriEA,9594
68
+ pymmcore_plus-0.13.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
69
+ pymmcore_plus-0.13.1.dist-info/entry_points.txt,sha256=NtFyndrQzBpUNJyil-8e5hMGke2utAf7mkGavTLcLOY,51
70
+ pymmcore_plus-0.13.1.dist-info/licenses/LICENSE,sha256=OHJjRpOPKKRc7FEnpehNWdR5LRBdBhUtIFG-ZI0dCEA,1522
71
+ pymmcore_plus-0.13.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,59 +0,0 @@
1
- pymmcore_plus/__init__.py,sha256=y2y48MqOnY-B1h7QnJc36HRDuXEegMsPNqKq51bu8DQ,1415
2
- pymmcore_plus/_build.py,sha256=RPTAuwCZWGL5IDJj4JZo1DIIouUsIqS3vnbPbG2_bRE,10993
3
- pymmcore_plus/_cli.py,sha256=rtbxbru85YcbEVjpmC0-EwlTe4TUYVaUBe2Kb-ZELmk,14252
4
- pymmcore_plus/_logger.py,sha256=YZt1ueX5mHtNGPXMqJQMrNdy46KSGlMReCOcmzjhBvQ,5153
5
- pymmcore_plus/_util.py,sha256=49gAx6G4wzD7MuGd7mtniXbq28qCRXihDuJcRZW7chM,20278
6
- pymmcore_plus/install.py,sha256=Vr_Z2Q9tNWEu0x-iw6HC2h1iv6K9H9tgI9aRFtckgQU,8576
7
- pymmcore_plus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- pymmcore_plus/seq_tester.py,sha256=6PqLFHpd0SvnzYVtE80AxytiqCVtB1ULiU1myzO3G7w,3768
9
- pymmcore_plus/core/__init__.py,sha256=r9bvL6sqgN72ZV7785WuRKT-o1VlsbYQcAKSy3rNS9k,897
10
- pymmcore_plus/core/_adapter.py,sha256=eu2BhGe_dnoQrIsh-u3poxWXsiF2Y8pfbKIGWbUgOk8,2857
11
- pymmcore_plus/core/_config.py,sha256=jatzHm6D-JwvlAPhvNYfzzrqXoKCpQ-EwKu6LhFeruc,10645
12
- pymmcore_plus/core/_config_group.py,sha256=jE0TxM93VuwOa7UrwIBjMBGSSa9oTr84uEn1aMhSBIE,8499
13
- pymmcore_plus/core/_constants.py,sha256=55lKxI38TXceowsM_Z7ShWZ-DfQiBJB_qqzaU8G9PSc,11743
14
- pymmcore_plus/core/_device.py,sha256=Uy5A58Jj_bIY5n6OymtTJPRnYkktoCq6ZtQV4KcLwPo,7756
15
- pymmcore_plus/core/_metadata.py,sha256=RT6dNZ9YkRlFd85hd_Vd6zLVjjbX4Cn831t6wAYDOvI,2618
16
- pymmcore_plus/core/_mmcore_plus.py,sha256=CGtHubJhsnt8Bzd3DjcsmL8sfxixU5P19mhjnVXn5a4,87596
17
- pymmcore_plus/core/_property.py,sha256=gO2Zy1I2y0wBAgQAVHnz1Vm7E2PYegGuLffNA1QBc6Y,8315
18
- pymmcore_plus/core/_sequencing.py,sha256=e1INgj-UGGVG67B_eXbH11RVVwYRI7ZokVpGkXLCIbQ,11797
19
- pymmcore_plus/core/events/__init__.py,sha256=_CIWCstUu2-xTqarK9fS_ENpZu7VxStLP4VNfcVmaBs,1094
20
- pymmcore_plus/core/events/_device_signal_view.py,sha256=t-NfBdg3E4rms4vDFxkkR5XtrpLxaBT7mfPwkpIsbVk,1079
21
- pymmcore_plus/core/events/_norm_slot.py,sha256=8DCBoLHGh7cbB1OB19IJYwL6sFBFmkD8IakfBOvFbw8,2907
22
- pymmcore_plus/core/events/_prop_event_mixin.py,sha256=FvJJnpEKrOR-_Sp3-NNCwFoUUHwmNKiHruo0Y1vybsY,4042
23
- pymmcore_plus/core/events/_protocol.py,sha256=V4st91mw6LoogII2c05vJxD5SIQU24va86J0iqJWqXU,7528
24
- pymmcore_plus/core/events/_psygnal.py,sha256=owaKlW2zpvocXDbAW4kHovBoVv4Fjfn-S5oUJrVWsD4,1646
25
- pymmcore_plus/core/events/_qsignals.py,sha256=gr-GDiSVLhFhSfaoKrdTz2y3I_2IUg62bYDGuGrB3j0,3018
26
- pymmcore_plus/mda/__init__.py,sha256=NF4OReQbShxZeLFaNaLPyMwkr1e5j5zMZmzHvHeSBzE,298
27
- pymmcore_plus/mda/_engine.py,sha256=wHbRDTdIK7G5kERMv81uBe6mYrqvuerTTM9bMlU0haE,24392
28
- pymmcore_plus/mda/_protocol.py,sha256=10CDJ9H57oX1z0oqK3eShXyQhufHvvu3_8wdaCYpPIg,3254
29
- pymmcore_plus/mda/_runner.py,sha256=ieSUh1st1DWvvvToaoHb01-3JCcqt7UbSx9LRGr9ehw,16256
30
- pymmcore_plus/mda/_thread_relay.py,sha256=Ww-9gyvLEzwRhnpL1dpze71wL7IRlhH8K3Q1dmJIxgs,6193
31
- pymmcore_plus/mda/events/__init__.py,sha256=UZFBlIzTmKqgMw_vVSZSSAN1tkAu8qccYb-aXXBRc3I,1192
32
- pymmcore_plus/mda/events/_protocol.py,sha256=9Q7LjYOgEWQGS8gHMV97UXM9bhoVW2OeyoPyNsQbwzw,1659
33
- pymmcore_plus/mda/events/_psygnal.py,sha256=TdN1mFGpTPXmEs9iwFKSC1svv87PDZkT2JZvl0tEGrQ,640
34
- pymmcore_plus/mda/events/_qsignals.py,sha256=tULQg-e_NX197DxJXaWHn1zLJ-4tzc9QyOAnsobEDtA,554
35
- pymmcore_plus/mda/handlers/_5d_writer_base.py,sha256=c9cA0n8DOBoZcy9asue5eV7jW8hFVC0XEewroFgDNHA,11925
36
- pymmcore_plus/mda/handlers/__init__.py,sha256=yQFRVDdCyu5t2JilobHGPC8lgCY4htNF5dzctrteSZA,305
37
- pymmcore_plus/mda/handlers/_img_sequence_writer.py,sha256=fAj6CB90RXYJ2jJIRDFxZgQb-TfwuRPWGCPFopCijRI,11549
38
- pymmcore_plus/mda/handlers/_ome_tiff_writer.py,sha256=pqqdl3KQd0tH5Gp4rHVgYqqh2Y8iwoKRXTjwq1JLy1E,6239
39
- pymmcore_plus/mda/handlers/_ome_zarr_writer.py,sha256=tjq7v3K3wrbPmTSlkvnEDTyMilno2sqyDkZxOjAh7FE,12275
40
- pymmcore_plus/mda/handlers/_tensorstore_handler.py,sha256=0DpHf0SHcHgpbmlIZ2YLK3krDFcEe_aEQSk10a8WHvg,14672
41
- pymmcore_plus/mda/handlers/_util.py,sha256=pZydpKAXtQ_gjq5x1yNK1D0hfS7NUL2nH9ivOBg4abc,1600
42
- pymmcore_plus/metadata/__init__.py,sha256=r_2dI4qbc5GPl3MP6ye-W7-c1RBZZXkCgFqJ4HaPJOA,699
43
- pymmcore_plus/metadata/functions.py,sha256=RsXuYS6ytIRicefRF0h7NiGfDhmimKbpgL9Vrp1p548,12188
44
- pymmcore_plus/metadata/schema.py,sha256=Zsh7D-UptVisP_AiDcAdUDoXZsQfZNSJIrCkIgxtt5Q,17241
45
- pymmcore_plus/metadata/serialize.py,sha256=hpXJm0tzILELf6OYECMg0sQhuf-h25ob6_DDl-TUUME,3805
46
- pymmcore_plus/model/__init__.py,sha256=zKZkkSpNK4ERu-VMdi9gvRrj1aXAjNaYxlYB5PdYSg0,479
47
- pymmcore_plus/model/_config_file.py,sha256=cnTF9fcclnwhnwl-qfZxSyVO75d_ljMD3CQeGrXzzMI,13280
48
- pymmcore_plus/model/_config_group.py,sha256=vL_-EWH-Nsb8xTgFqpYIFaJzBk_RDBFchBnQ61DMSvI,3407
49
- pymmcore_plus/model/_core_device.py,sha256=cucoGtFue71yOqC5VcT7Uvk8mY4EhPmX0pyhXsgakXE,2402
50
- pymmcore_plus/model/_core_link.py,sha256=dsbT0gncfa3TAORSaWUrZR9rcI_nOLX9e5BTmyo-UYo,2737
51
- pymmcore_plus/model/_device.py,sha256=ZQs6luAt2KXpDKpR2DwoHnh3izM6xWX1ckIxFhpHP9U,15748
52
- pymmcore_plus/model/_microscope.py,sha256=69VV6cuevinOK_LhYEkQygHGesvCZefdn9YNt3mV618,11353
53
- pymmcore_plus/model/_pixel_size_config.py,sha256=smoOmT54nSkg52RaSQzTFG0YwyMR_SEq_lkS-JyJW9U,3514
54
- pymmcore_plus/model/_property.py,sha256=fl2wUldY3H9qK9aoIcZLJCr7wDcxOFLoIjvR9rHnAnk,3359
55
- pymmcore_plus-0.12.0.dist-info/METADATA,sha256=nvAEtFjaYJkMQrJY657Fgd5ouJzee72mCfKrSTc9BXU,9221
56
- pymmcore_plus-0.12.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
57
- pymmcore_plus-0.12.0.dist-info/entry_points.txt,sha256=NtFyndrQzBpUNJyil-8e5hMGke2utAf7mkGavTLcLOY,51
58
- pymmcore_plus-0.12.0.dist-info/licenses/LICENSE,sha256=OHJjRpOPKKRc7FEnpehNWdR5LRBdBhUtIFG-ZI0dCEA,1522
59
- pymmcore_plus-0.12.0.dist-info/RECORD,,