pymmcore-plus 0.9.4__py3-none-any.whl → 0.13.0__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 (68) hide show
  1. pymmcore_plus/__init__.py +7 -4
  2. pymmcore_plus/_benchmark.py +203 -0
  3. pymmcore_plus/_build.py +6 -1
  4. pymmcore_plus/_cli.py +131 -31
  5. pymmcore_plus/_logger.py +19 -10
  6. pymmcore_plus/_pymmcore.py +12 -0
  7. pymmcore_plus/_util.py +133 -30
  8. pymmcore_plus/core/__init__.py +5 -0
  9. pymmcore_plus/core/_config.py +6 -4
  10. pymmcore_plus/core/_config_group.py +4 -3
  11. pymmcore_plus/core/_constants.py +135 -10
  12. pymmcore_plus/core/_device.py +4 -4
  13. pymmcore_plus/core/_metadata.py +3 -3
  14. pymmcore_plus/core/_mmcore_plus.py +254 -170
  15. pymmcore_plus/core/_property.py +6 -6
  16. pymmcore_plus/core/_sequencing.py +370 -233
  17. pymmcore_plus/core/events/__init__.py +6 -6
  18. pymmcore_plus/core/events/_device_signal_view.py +8 -6
  19. pymmcore_plus/core/events/_norm_slot.py +2 -4
  20. pymmcore_plus/core/events/_prop_event_mixin.py +7 -4
  21. pymmcore_plus/core/events/_protocol.py +5 -2
  22. pymmcore_plus/core/events/_psygnal.py +2 -2
  23. pymmcore_plus/experimental/__init__.py +0 -0
  24. pymmcore_plus/experimental/unicore/__init__.py +14 -0
  25. pymmcore_plus/experimental/unicore/_device_manager.py +173 -0
  26. pymmcore_plus/experimental/unicore/_proxy.py +127 -0
  27. pymmcore_plus/experimental/unicore/_unicore.py +703 -0
  28. pymmcore_plus/experimental/unicore/devices/__init__.py +0 -0
  29. pymmcore_plus/experimental/unicore/devices/_device.py +269 -0
  30. pymmcore_plus/experimental/unicore/devices/_properties.py +400 -0
  31. pymmcore_plus/experimental/unicore/devices/_stage.py +221 -0
  32. pymmcore_plus/install.py +16 -11
  33. pymmcore_plus/mda/__init__.py +1 -1
  34. pymmcore_plus/mda/_engine.py +320 -148
  35. pymmcore_plus/mda/_protocol.py +6 -4
  36. pymmcore_plus/mda/_runner.py +62 -51
  37. pymmcore_plus/mda/_thread_relay.py +5 -3
  38. pymmcore_plus/mda/events/__init__.py +2 -2
  39. pymmcore_plus/mda/events/_protocol.py +10 -2
  40. pymmcore_plus/mda/events/_psygnal.py +2 -2
  41. pymmcore_plus/mda/handlers/_5d_writer_base.py +106 -15
  42. pymmcore_plus/mda/handlers/__init__.py +7 -1
  43. pymmcore_plus/mda/handlers/_img_sequence_writer.py +11 -6
  44. pymmcore_plus/mda/handlers/_ome_tiff_writer.py +8 -4
  45. pymmcore_plus/mda/handlers/_ome_zarr_writer.py +82 -9
  46. pymmcore_plus/mda/handlers/_tensorstore_handler.py +374 -0
  47. pymmcore_plus/mda/handlers/_util.py +1 -1
  48. pymmcore_plus/metadata/__init__.py +36 -0
  49. pymmcore_plus/metadata/functions.py +353 -0
  50. pymmcore_plus/metadata/schema.py +472 -0
  51. pymmcore_plus/metadata/serialize.py +120 -0
  52. pymmcore_plus/mocks.py +51 -0
  53. pymmcore_plus/model/_config_file.py +5 -6
  54. pymmcore_plus/model/_config_group.py +29 -2
  55. pymmcore_plus/model/_core_device.py +12 -1
  56. pymmcore_plus/model/_core_link.py +2 -1
  57. pymmcore_plus/model/_device.py +39 -8
  58. pymmcore_plus/model/_microscope.py +39 -3
  59. pymmcore_plus/model/_pixel_size_config.py +27 -4
  60. pymmcore_plus/model/_property.py +13 -3
  61. pymmcore_plus/seq_tester.py +1 -1
  62. {pymmcore_plus-0.9.4.dist-info → pymmcore_plus-0.13.0.dist-info}/METADATA +22 -11
  63. pymmcore_plus-0.13.0.dist-info/RECORD +71 -0
  64. {pymmcore_plus-0.9.4.dist-info → pymmcore_plus-0.13.0.dist-info}/WHEEL +1 -1
  65. pymmcore_plus/core/_state.py +0 -244
  66. pymmcore_plus-0.9.4.dist-info/RECORD +0 -55
  67. {pymmcore_plus-0.9.4.dist-info → pymmcore_plus-0.13.0.dist-info}/entry_points.txt +0 -0
  68. {pymmcore_plus-0.9.4.dist-info → pymmcore_plus-0.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,244 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from contextlib import suppress
4
- from typing import TYPE_CHECKING, Any, Literal, Sequence, TypedDict, cast
5
-
6
- if TYPE_CHECKING:
7
- from pymmcore_plus import CMMCorePlus
8
-
9
-
10
- class SystemInfoDict(TypedDict):
11
- APIVersionInfo: str
12
- BufferFreeCapacity: int
13
- BufferTotalCapacity: int
14
- CircularBufferMemoryFootprint: int
15
- DeviceAdapterSearchPaths: tuple[str, ...]
16
- PrimaryLogFile: str
17
- RemainingImageCount: int
18
- TimeoutMs: int # rarely needed for metadata
19
- VersionInfo: str
20
- # these were removed in mmcore11 and probably shouldn't be used anyway
21
- # HostName: str
22
- # MACAddresses: tuple[str, ...]
23
- # UserId: str
24
-
25
-
26
- class ImageDict(TypedDict):
27
- BytesPerPixel: int
28
- CurrentPixelSizeConfig: str
29
- Exposure: float
30
- ImageBitDepth: int
31
- ImageBufferSize: int
32
- ImageHeight: int
33
- ImageWidth: int
34
- MagnificationFactor: float
35
- MultiROI: tuple[list[int], list[int], list[int], list[int]] | None
36
- NumberOfCameraChannels: int
37
- NumberOfComponents: int
38
- PixelSizeAffine: tuple[float, float, float, float, float, float]
39
- PixelSizeUm: int
40
- ROI: list[int]
41
-
42
-
43
- class PositionDict(TypedDict):
44
- X: float | None
45
- Y: float | None
46
- Focus: float | None
47
-
48
-
49
- class AutoFocusDict(TypedDict):
50
- CurrentFocusScore: float
51
- LastFocusScore: float
52
- AutoFocusOffset: float | None
53
-
54
-
55
- class PixelSizeConfigDict(TypedDict):
56
- Objective: dict[str, str]
57
- PixelSizeUm: float
58
- PixelSizeAffine: tuple[float, float, float, float, float, float]
59
-
60
-
61
- class DeviceTypeDict(TypedDict):
62
- Type: str
63
- Description: str
64
- Adapter: str
65
-
66
-
67
- class SystemStatusDict(TypedDict):
68
- debugLogEnabled: bool
69
- isBufferOverflowed: bool
70
- isContinuousFocusEnabled: bool
71
- isContinuousFocusLocked: bool
72
- isSequenceRunning: bool
73
- stderrLogEnabled: bool
74
- systemBusy: bool
75
- autoShutter: bool
76
- shutterOpen: bool
77
-
78
-
79
- class StateDict(TypedDict, total=False):
80
- Devices: dict[str, dict[str, str]]
81
- SystemInfo: SystemInfoDict
82
- SystemStatus: SystemStatusDict
83
- ConfigGroups: dict[str, dict[str, Any]]
84
- Image: ImageDict
85
- Position: PositionDict
86
- AutoFocus: AutoFocusDict
87
- PixelSizeConfig: dict[str, str | PixelSizeConfigDict]
88
- DeviceTypes: dict[str, DeviceTypeDict]
89
-
90
-
91
- def core_state(
92
- core: CMMCorePlus,
93
- *,
94
- devices: bool = True,
95
- image: bool = True,
96
- system_info: bool = False,
97
- system_status: bool = False,
98
- config_groups: bool | Sequence[str] = True,
99
- position: bool = False,
100
- autofocus: bool = False,
101
- pixel_size_configs: bool = False,
102
- device_types: bool = False,
103
- cached: bool = True,
104
- error_value: Any = None,
105
- ) -> StateDict:
106
- out: StateDict = {}
107
- if devices:
108
- out["Devices"] = get_device_state(core, error_value)
109
- if system_info:
110
- out["SystemInfo"] = get_system_info(core)
111
- if system_status:
112
- out["SystemStatus"] = get_system_status(core)
113
- if config_groups:
114
- out["ConfigGroups"] = get_config_groups(core, config_groups, cached)
115
- if image:
116
- out["Image"] = get_image_info(core, error_value)
117
- if position:
118
- out["Position"] = get_position(core, error_value)
119
- if autofocus:
120
- out["AutoFocus"] = get_autofocus(core, error_value)
121
- if pixel_size_configs:
122
- out["PixelSizeConfig"] = get_pix_size_config(core)
123
- if device_types:
124
- out["DeviceTypes"] = get_device_types(core)
125
- return out
126
-
127
-
128
- def get_device_state(
129
- core: CMMCorePlus, cached: bool = True, error_value: Any = None
130
- ) -> dict[str, dict[str, Any]]:
131
- # this actually appears to be faster than getSystemStateCache
132
- getProp = core.getPropertyFromCache if cached else core.getProperty
133
- device_state: dict = {}
134
- for dev in core.getLoadedDevices():
135
- dd = device_state.setdefault(dev, {})
136
- for prop in core.getDevicePropertyNames(dev):
137
- try:
138
- val = getProp(dev, prop)
139
- except Exception:
140
- val = error_value
141
- dd[prop] = val
142
- return device_state
143
-
144
-
145
- def get_system_info(core: CMMCorePlus) -> SystemInfoDict:
146
- return { # type: ignore
147
- key: getattr(core, f"get{key}")()
148
- for key in sorted(SystemInfoDict.__annotations__)
149
- }
150
-
151
-
152
- def get_system_status(core: CMMCorePlus) -> SystemStatusDict:
153
- out = {
154
- "autoShutter": core.getAutoShutter(),
155
- "shutterOpen": core.getShutterOpen(),
156
- }
157
- out.update(
158
- {
159
- key: getattr(core, key)()
160
- for key in sorted(SystemStatusDict.__annotations__)
161
- if key not in {"autoShutter", "shutterOpen"}
162
- }
163
- )
164
- return cast("SystemStatusDict", out)
165
-
166
-
167
- def get_config_groups(
168
- core: CMMCorePlus,
169
- config_groups: bool | Sequence[str | Literal["[Channel]"]],
170
- cached: bool = True,
171
- ) -> dict[str, dict[str, Any]]:
172
- if not isinstance(config_groups, (list, tuple, set)):
173
- config_groups = core.getAvailableConfigGroups()
174
-
175
- getState = core.getConfigGroupStateFromCache if cached else core.getConfigGroupState
176
- curGrp = core.getCurrentConfigFromCache if cached else core.getCurrentConfig
177
- cfg_group_dict: dict = {}
178
- for grp in config_groups:
179
- if grp == "[Channel]":
180
- # special case for accessing channel group
181
- grp = core.getChannelGroup()
182
-
183
- grp_dict = cfg_group_dict.setdefault(grp, {})
184
- grp_dict["Current"] = curGrp(grp)
185
-
186
- for dev, prop, val in getState(grp):
187
- grp_dict.setdefault(dev, {})[prop] = val
188
- return cfg_group_dict
189
-
190
-
191
- def get_image_info(core: CMMCorePlus, error_value: Any = None) -> ImageDict:
192
- img_dict = {}
193
- for key in sorted(ImageDict.__annotations__):
194
- try:
195
- val = getattr(core, f"get{key}")()
196
- except Exception:
197
- val = error_value
198
- img_dict[key] = val
199
- return cast("ImageDict", img_dict)
200
-
201
-
202
- def get_position(core: CMMCorePlus, error_value: Any = None) -> PositionDict:
203
- pos: PositionDict = {"X": error_value, "Y": error_value, "Focus": error_value}
204
- with suppress(Exception):
205
- pos["X"] = core.getXPosition()
206
- pos["Y"] = core.getYPosition()
207
- with suppress(Exception):
208
- pos["Focus"] = core.getPosition()
209
- return pos
210
-
211
-
212
- def get_autofocus(core: CMMCorePlus, error_value: Any = None) -> AutoFocusDict:
213
- out: AutoFocusDict = {
214
- "CurrentFocusScore": core.getCurrentFocusScore(),
215
- "LastFocusScore": core.getLastFocusScore(),
216
- "AutoFocusOffset": error_value,
217
- }
218
- with suppress(Exception):
219
- out["AutoFocusOffset"] = core.getAutoFocusOffset()
220
- return out
221
-
222
-
223
- def get_pix_size_config(core: CMMCorePlus) -> dict[str, str | PixelSizeConfigDict]:
224
- # the Current value is a string, all the rest are PixelSizeConfigDict
225
- px: dict = {"Current": core.getCurrentPixelSizeConfig()}
226
- for px_cfg_name in core.getAvailablePixelSizeConfigs():
227
- px_cfg_info: dict = {}
228
- for dev, prop, val in core.getPixelSizeConfigData(px_cfg_name):
229
- px_cfg_info.setdefault(dev, {})[prop] = val
230
- px_cfg_info["PixelSizeUm"] = core.getPixelSizeUmByID(px_cfg_name)
231
- px_cfg_info["PixelSizeAffine"] = core.getPixelSizeAffineByID(px_cfg_name)
232
- px[px_cfg_name] = px_cfg_info
233
- return px
234
-
235
-
236
- def get_device_types(core: CMMCorePlus) -> dict[str, DeviceTypeDict]:
237
- return {
238
- dev_name: {
239
- "Type": core.getDeviceType(dev_name).name,
240
- "Description": core.getDeviceDescription(dev_name),
241
- "Adapter": core.getDeviceName(dev_name),
242
- }
243
- for dev_name in core.getLoadedDevices()
244
- }
@@ -1,55 +0,0 @@
1
- pymmcore_plus/__init__.py,sha256=byZeA2-r2pGztxIZgCDZ__Q2DYddc4aQ2alWg2pgQ5I,1337
2
- pymmcore_plus/_build.py,sha256=_jw1e1PWaIejjeghPTweySdgeohle0jhqVDagYNT3k8,10892
3
- pymmcore_plus/_cli.py,sha256=eHKUCGz6l6X3QBnTXzOkRz6odqjaC1_kJ75uAnzzeP0,13115
4
- pymmcore_plus/_logger.py,sha256=JHuXsowStqX6e-WpyNYFmuoqmdLtFqlDkRN8k5pUGaA,5162
5
- pymmcore_plus/_util.py,sha256=9tTXiOzFpdAQrz97kZiISBl4ZGoWXdNQ4Qtz2o2F4Io,17021
6
- pymmcore_plus/install.py,sha256=EKY8dTOVEf4kbzf7z4K22LZCHfoXAPKr47lbGcraFkQ,8477
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=8YNtX8U4PZlEJjmnxoYWbQPY6Y4jHTnYOMO4i5hdrc8,861
10
- pymmcore_plus/core/_adapter.py,sha256=eu2BhGe_dnoQrIsh-u3poxWXsiF2Y8pfbKIGWbUgOk8,2857
11
- pymmcore_plus/core/_config.py,sha256=5Vzwv2QEuJSXgKjERSHiTzwmpWyizY_aa4n3OjpPyPc,10620
12
- pymmcore_plus/core/_config_group.py,sha256=w-psUtMk3X6MzqU17j4D2yZ_ugLP7u0-mvPIXPuIxwQ,8472
13
- pymmcore_plus/core/_constants.py,sha256=bIXsi8ff-silrCbkrtBFZYG7i5SvQCz68kzPEOV9fDs,8726
14
- pymmcore_plus/core/_device.py,sha256=Uy5A58Jj_bIY5n6OymtTJPRnYkktoCq6ZtQV4KcLwPo,7756
15
- pymmcore_plus/core/_metadata.py,sha256=64RdptyRGRqtRJ8pWMlAyevSgYMAE1Hzs8TB3DBQHAA,2618
16
- pymmcore_plus/core/_mmcore_plus.py,sha256=wMPf-Wtu2hVpRDox9450R-6B4r7rdD7KgyETV1sl_X0,86477
17
- pymmcore_plus/core/_property.py,sha256=sd28rZE-_l4HaIJxqJlUX7DlM-Fa9_Xr6cLERwOtBYc,8283
18
- pymmcore_plus/core/_sequencing.py,sha256=ueyuqsUPbfH7FLMdqFUpHoxSZfBRHHkYmv12lOt72hI,11847
19
- pymmcore_plus/core/_state.py,sha256=80kr-_x9Z8MwZG0-mgIE0lR4XUSNOnlmKm-zzoH3BJA,7535
20
- pymmcore_plus/core/events/__init__.py,sha256=8NjFkVdRVRiiLUQ_brGQSlTaK3rqNizdNEX17NEXAis,1106
21
- pymmcore_plus/core/events/_device_signal_view.py,sha256=st_di51xOmKKOM9-yY8ouKlTZqG-7NWorRaoaN1sJ44,1065
22
- pymmcore_plus/core/events/_norm_slot.py,sha256=cp6VeH5h98G7bPWrKzTsHJmzCIbi2D4sv6bSdywQbsk,2937
23
- pymmcore_plus/core/events/_prop_event_mixin.py,sha256=XfoXrMjRRXPHv6XkavBmSuz-6nItpJ8oG60DqK2WBEA,3939
24
- pymmcore_plus/core/events/_protocol.py,sha256=Cf9uGZe_uP8nIa8rsaDIX5RCW5pNQQt2juLL-rriRn4,7448
25
- pymmcore_plus/core/events/_psygnal.py,sha256=NNM-MrUOKJPF4_fiNgidQb2r_tK21Sqs1qIY_AcnxlA,1620
26
- pymmcore_plus/core/events/_qsignals.py,sha256=gr-GDiSVLhFhSfaoKrdTz2y3I_2IUg62bYDGuGrB3j0,3018
27
- pymmcore_plus/mda/__init__.py,sha256=MrRYE2rYuIw4dQib4KiRgVbTkjdsE-6tcTjns68Grzk,298
28
- pymmcore_plus/mda/_engine.py,sha256=061kamoq6FkPFLmzf6z3Nc1cmm2vhF6I1YHhEQBzSpk,21084
29
- pymmcore_plus/mda/_protocol.py,sha256=p98OkG390Q2Rj05Cl5mza6BUTscPol_cgTxXXMkpNcI,3182
30
- pymmcore_plus/mda/_runner.py,sha256=zhH8T5tz-ivl0MXx2PRQ1cK6jP3vVbUGpZU6P6rOpKw,15283
31
- pymmcore_plus/mda/_thread_relay.py,sha256=wjP1tag7nN2Sr0RzaPnYRqHl8XjAQg2MpXOt0ONLcQ8,6112
32
- pymmcore_plus/mda/events/__init__.py,sha256=UZFBlIzTmKqgMw_vVSZSSAN1tkAu8qccYb-aXXBRc3I,1192
33
- pymmcore_plus/mda/events/_protocol.py,sha256=Ve4RbjcdHyDob-GZ2ny4gmw46JhahvI4XbXUwVZ-7zc,1315
34
- pymmcore_plus/mda/events/_psygnal.py,sha256=SDorjfCsyt6GrEjDCCvwifKO8BR3ZhLjEuJ8lUaWhKo,614
35
- pymmcore_plus/mda/events/_qsignals.py,sha256=tULQg-e_NX197DxJXaWHn1zLJ-4tzc9QyOAnsobEDtA,554
36
- pymmcore_plus/mda/handlers/_5d_writer_base.py,sha256=JSG8ay10M0ZWymAKh0-XmA-5Zl-L9-zDmWF4yrvoH-Q,8497
37
- pymmcore_plus/mda/handlers/__init__.py,sha256=7-GUBtyEN3NFsHv4CW_EnFf3Q9gtxYm1ktM-L82Oh9M,211
38
- pymmcore_plus/mda/handlers/_img_sequence_writer.py,sha256=9zIqwTlW1GmgkpSol1V69ADHwAEt-n8E4DkqAiSk5mM,11493
39
- pymmcore_plus/mda/handlers/_ome_tiff_writer.py,sha256=x92hIhuKKO2fBqMoxOR1yGx5fAtUhPp9UReO1TDGe_0,6119
40
- pymmcore_plus/mda/handlers/_ome_zarr_writer.py,sha256=KJU1t_owW3HFoUoFEZvA2QmE9J6id4_NWNvYStdb3Wg,9532
41
- pymmcore_plus/mda/handlers/_util.py,sha256=p-8Gg5Q2Jo0zyYdniP9a0NirUOnuKNLWzwjhzcKqskg,1601
42
- pymmcore_plus/model/__init__.py,sha256=zKZkkSpNK4ERu-VMdi9gvRrj1aXAjNaYxlYB5PdYSg0,479
43
- pymmcore_plus/model/_config_file.py,sha256=AwUHlCd6PUCCCDJFPBzanhVp7Cv751k6MHVEaUAdsxw,13335
44
- pymmcore_plus/model/_config_group.py,sha256=zpLimXUSaz2dcqfy2GCI0_MqhjN-A022MOi9QmkiOh4,2517
45
- pymmcore_plus/model/_core_device.py,sha256=afNYGIRFunUPYNYJ_yHJwOjo7HO9FW8qGWTMeiKRmNU,2370
46
- pymmcore_plus/model/_core_link.py,sha256=myE0qa2pEWEinbsIhTN4uB_c-lr9dtUG3npLgsHEI_0,2706
47
- pymmcore_plus/model/_device.py,sha256=cQngFxQ6tufrT9G46oO5iX9wh-44zZraaIFNQCyzMLc,15026
48
- pymmcore_plus/model/_microscope.py,sha256=-soGj918ue_71mrROQ5_7cbjexKp41wPn7im0l2BfaY,9822
49
- pymmcore_plus/model/_pixel_size_config.py,sha256=J4qJmPZsN9dwEkoMtct5Ik-8zEC-v0aKxOBKGFH7kOE,2718
50
- pymmcore_plus/model/_property.py,sha256=gJM7SFjLB2HnN0E8HOn4qVlB2wAxmkEFxSJFjKauZEk,3328
51
- pymmcore_plus-0.9.4.dist-info/METADATA,sha256=skw5S1zkL15_kuPRFrLc4Ig4pLbzWHuVC4-GfCcyW7w,9130
52
- pymmcore_plus-0.9.4.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
53
- pymmcore_plus-0.9.4.dist-info/entry_points.txt,sha256=NtFyndrQzBpUNJyil-8e5hMGke2utAf7mkGavTLcLOY,51
54
- pymmcore_plus-0.9.4.dist-info/licenses/LICENSE,sha256=OHJjRpOPKKRc7FEnpehNWdR5LRBdBhUtIFG-ZI0dCEA,1522
55
- pymmcore_plus-0.9.4.dist-info/RECORD,,