TwoPy 0.1.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.
- twopy/__init__.py +168 -0
- twopy/_segments.py +53 -0
- twopy/analysis/__init__.py +101 -0
- twopy/analysis/background_subtraction.py +672 -0
- twopy/analysis/dff.py +524 -0
- twopy/analysis/epoch_mapping.py +223 -0
- twopy/analysis/motion.py +66 -0
- twopy/analysis/persistence.py +975 -0
- twopy/analysis/response_processing/__init__.py +55 -0
- twopy/analysis/response_processing/apply.py +298 -0
- twopy/analysis/response_processing/options.py +192 -0
- twopy/analysis/response_processing/qc.py +270 -0
- twopy/analysis/response_processing/signals.py +200 -0
- twopy/analysis/responses.py +345 -0
- twopy/analysis/trials.py +341 -0
- twopy/analysis/workflow.py +457 -0
- twopy/api.py +78 -0
- twopy/config.py +200 -0
- twopy/conversion/__init__.py +40 -0
- twopy/conversion/alignment_crop.py +329 -0
- twopy/conversion/api.py +113 -0
- twopy/conversion/frame_ranges.py +35 -0
- twopy/conversion/hdf5_writing.py +362 -0
- twopy/conversion/matlab_values.py +123 -0
- twopy/conversion/source_loading.py +403 -0
- twopy/conversion/stimulus_code.py +248 -0
- twopy/conversion/types.py +295 -0
- twopy/converted.py +681 -0
- twopy/database/__init__.py +33 -0
- twopy/database/cache.py +166 -0
- twopy/database/catalog.py +90 -0
- twopy/database/connection.py +27 -0
- twopy/database/generic.py +254 -0
- twopy/database/modeled.py +419 -0
- twopy/database/sql.py +46 -0
- twopy/database/types.py +116 -0
- twopy/inspection.py +492 -0
- twopy/matlab.py +398 -0
- twopy/napari/__init__.py +27 -0
- twopy/napari/__main__.py +10 -0
- twopy/napari/constants.py +13 -0
- twopy/napari/controls.py +739 -0
- twopy/napari/display.py +181 -0
- twopy/napari/display_paths.py +197 -0
- twopy/napari/interactive.py +310 -0
- twopy/napari/launcher.py +175 -0
- twopy/napari/layout.py +147 -0
- twopy/napari/loading.py +207 -0
- twopy/napari/movie.py +71 -0
- twopy/napari/paths.py +181 -0
- twopy/napari/plotting/__init__.py +21 -0
- twopy/napari/plotting/data.py +266 -0
- twopy/napari/plotting/docks.py +1052 -0
- twopy/napari/plotting/export.py +803 -0
- twopy/napari/plotting/export_controls.py +209 -0
- twopy/napari/plotting/label_visibility.py +260 -0
- twopy/napari/plotting/options.py +269 -0
- twopy/napari/plotting/panels.py +119 -0
- twopy/napari/plotting/widgets.py +767 -0
- twopy/napari/protocols.py +90 -0
- twopy/napari/responses.py +91 -0
- twopy/napari/roi.py +238 -0
- twopy/napari/session.py +381 -0
- twopy/napari/state.py +106 -0
- twopy/napari/text.py +26 -0
- twopy/napari/types.py +39 -0
- twopy/napari/viewer.py +405 -0
- twopy/parity/__init__.py +30 -0
- twopy/parity/dff.py +399 -0
- twopy/parity/roi.py +145 -0
- twopy/parity/saved_analysis.py +174 -0
- twopy/photodiode.py +375 -0
- twopy/photodiode_classification.py +484 -0
- twopy/roi.py +462 -0
- twopy/session.py +167 -0
- twopy/spatial.py +154 -0
- twopy/stimulus.py +233 -0
- twopy/synchronization.py +235 -0
- twopy/typing_guards.py +255 -0
- twopy-0.1.0.dist-info/METADATA +311 -0
- twopy-0.1.0.dist-info/RECORD +84 -0
- twopy-0.1.0.dist-info/WHEEL +5 -0
- twopy-0.1.0.dist-info/entry_points.txt +2 -0
- twopy-0.1.0.dist-info/top_level.txt +1 -0
twopy/matlab.py
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
"""Inspect MATLAB files used by two-photon microscope recordings.
|
|
2
|
+
|
|
3
|
+
Inputs: MATLAB ``.mat`` files from a recording or prior lab analysis.
|
|
4
|
+
Outputs: typed summaries of variables, shapes, dtypes, and storage format.
|
|
5
|
+
|
|
6
|
+
This module is intentionally an inspection layer first. It lets twopy understand
|
|
7
|
+
what MATLAB files contain before later code converts selected variables into
|
|
8
|
+
analysis-specific Python objects.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from collections.abc import Iterable
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Literal, cast
|
|
15
|
+
|
|
16
|
+
import h5py
|
|
17
|
+
import scipy.io
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"MatlabHdf5Group",
|
|
21
|
+
"MatlabFileSummary",
|
|
22
|
+
"MatlabLoadedFile",
|
|
23
|
+
"MatlabVariableSummary",
|
|
24
|
+
"inspect_mat_file",
|
|
25
|
+
"load_mat_file",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
MatlabFileFormat = Literal["hdf5-mat", "scipy-mat"]
|
|
29
|
+
ScipyLoadAction = Literal["inspect", "load"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class MatlabVariableSummary:
|
|
34
|
+
"""Human-readable summary of one MATLAB variable.
|
|
35
|
+
|
|
36
|
+
Inputs: one variable loaded from or discovered inside a MATLAB file.
|
|
37
|
+
Outputs: name, Python-facing type, shape, dtype, and whether it is a group.
|
|
38
|
+
|
|
39
|
+
This object keeps inspection results small and auditable; large arrays stay
|
|
40
|
+
on disk unless later conversion code explicitly asks to load them.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
name: str
|
|
44
|
+
python_type: str
|
|
45
|
+
shape: tuple[int, ...] | None
|
|
46
|
+
dtype: str | None
|
|
47
|
+
is_group: bool
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class MatlabFileSummary:
|
|
52
|
+
"""Summary of one MATLAB file.
|
|
53
|
+
|
|
54
|
+
Inputs: path to a MATLAB file.
|
|
55
|
+
Outputs: detected storage format plus summaries of visible variables.
|
|
56
|
+
|
|
57
|
+
The summary is designed for logs and GUI inspection, not numerical analysis.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
path: Path
|
|
61
|
+
file_format: MatlabFileFormat
|
|
62
|
+
variables: tuple[MatlabVariableSummary, ...]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class MatlabHdf5Group:
|
|
67
|
+
"""Reference-like summary for an HDF5 group inside a MATLAB file.
|
|
68
|
+
|
|
69
|
+
Inputs: group name and its child names.
|
|
70
|
+
Outputs: a small Python object that says the group exists without loading it.
|
|
71
|
+
|
|
72
|
+
HDF5 groups can contain nested references and large data. Keeping them as a
|
|
73
|
+
summary avoids pretending every MATLAB value is a simple array.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
name: str
|
|
77
|
+
child_names: tuple[str, ...]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True)
|
|
81
|
+
class MatlabLoadedFile:
|
|
82
|
+
"""Loaded MATLAB variables as Python objects.
|
|
83
|
+
|
|
84
|
+
Inputs: MATLAB file path and optional variable names to load.
|
|
85
|
+
Outputs: a mapping from variable names to Python objects.
|
|
86
|
+
|
|
87
|
+
For older MAT files, SciPy returns Python and NumPy objects. For HDF5-backed
|
|
88
|
+
MAT files, datasets are loaded when requested and groups are summarized.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
path: Path
|
|
92
|
+
file_format: MatlabFileFormat
|
|
93
|
+
variables: dict[str, object]
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def inspect_mat_file(path: Path) -> MatlabFileSummary:
|
|
97
|
+
"""Inspect one MATLAB file without loading more data than needed.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
path: MATLAB ``.mat`` file to inspect.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
A summary describing the file format and visible variables.
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
FileNotFoundError: If the path does not exist as a file.
|
|
107
|
+
ValueError: If neither h5py nor SciPy can read the file.
|
|
108
|
+
|
|
109
|
+
h5py is tried first because HDF5-backed MAT files can be inspected lazily.
|
|
110
|
+
Older MAT files then fall back to SciPy.
|
|
111
|
+
"""
|
|
112
|
+
mat_path = path.expanduser()
|
|
113
|
+
if not mat_path.is_file():
|
|
114
|
+
msg = f"Missing MATLAB file: {mat_path}"
|
|
115
|
+
raise FileNotFoundError(msg)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
return _inspect_hdf5_mat_file(mat_path)
|
|
119
|
+
except OSError:
|
|
120
|
+
return _inspect_scipy_mat_file(mat_path)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def load_mat_file(
|
|
124
|
+
path: Path,
|
|
125
|
+
variable_names: Iterable[str] | None = None,
|
|
126
|
+
) -> MatlabLoadedFile:
|
|
127
|
+
"""Load variables from one MATLAB file into Python objects.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
path: MATLAB ``.mat`` file to read.
|
|
131
|
+
variable_names: Optional variable names to load. ``None`` means load all
|
|
132
|
+
visible top-level variables.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Loaded variables keyed by MATLAB variable name.
|
|
136
|
+
|
|
137
|
+
Raises:
|
|
138
|
+
FileNotFoundError: If the path does not exist as a file.
|
|
139
|
+
KeyError: If a requested variable is absent.
|
|
140
|
+
ValueError: If neither h5py nor SciPy can read the file.
|
|
141
|
+
|
|
142
|
+
Use explicit ``variable_names`` for large HDF5-backed files, such as aligned
|
|
143
|
+
movies, so callers control memory use.
|
|
144
|
+
"""
|
|
145
|
+
mat_path = path.expanduser()
|
|
146
|
+
if not mat_path.is_file():
|
|
147
|
+
msg = f"Missing MATLAB file: {mat_path}"
|
|
148
|
+
raise FileNotFoundError(msg)
|
|
149
|
+
|
|
150
|
+
wanted = tuple(variable_names) if variable_names is not None else None
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
return _load_hdf5_mat_file(mat_path, wanted)
|
|
154
|
+
except OSError:
|
|
155
|
+
return _load_scipy_mat_file(mat_path, wanted)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _inspect_hdf5_mat_file(path: Path) -> MatlabFileSummary:
|
|
159
|
+
"""Inspect an HDF5-backed MATLAB file with lazy dataset metadata.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
path: MATLAB file that h5py can open.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
A summary of top-level HDF5 groups and datasets.
|
|
166
|
+
|
|
167
|
+
HDF5 stores array shape and dtype in metadata, so this path avoids loading
|
|
168
|
+
large movie arrays while still showing what is inside.
|
|
169
|
+
"""
|
|
170
|
+
variables: list[MatlabVariableSummary] = []
|
|
171
|
+
|
|
172
|
+
with h5py.File(path, "r") as mat_file:
|
|
173
|
+
for name, item in sorted(mat_file.items()):
|
|
174
|
+
if isinstance(item, h5py.Dataset):
|
|
175
|
+
variables.append(
|
|
176
|
+
MatlabVariableSummary(
|
|
177
|
+
name=name,
|
|
178
|
+
python_type="h5py.Dataset",
|
|
179
|
+
shape=tuple(int(length) for length in item.shape),
|
|
180
|
+
dtype=str(item.dtype),
|
|
181
|
+
is_group=False,
|
|
182
|
+
),
|
|
183
|
+
)
|
|
184
|
+
else:
|
|
185
|
+
variables.append(
|
|
186
|
+
MatlabVariableSummary(
|
|
187
|
+
name=name,
|
|
188
|
+
python_type=type(item).__name__,
|
|
189
|
+
shape=None,
|
|
190
|
+
dtype=None,
|
|
191
|
+
is_group=True,
|
|
192
|
+
),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return MatlabFileSummary(
|
|
196
|
+
path=path, file_format="hdf5-mat", variables=tuple(variables)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _load_hdf5_mat_file(
|
|
201
|
+
path: Path,
|
|
202
|
+
variable_names: tuple[str, ...] | None,
|
|
203
|
+
) -> MatlabLoadedFile:
|
|
204
|
+
"""Load requested top-level variables from an HDF5-backed MATLAB file.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
path: MATLAB file that h5py can open.
|
|
208
|
+
variable_names: Variable names to load, or ``None`` for all top-level
|
|
209
|
+
entries.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
Loaded dataset values and group summaries.
|
|
213
|
+
|
|
214
|
+
HDF5 datasets are read with ``[()]`` because that is h5py's direct way to
|
|
215
|
+
materialize one dataset as a Python/NumPy object.
|
|
216
|
+
"""
|
|
217
|
+
variables: dict[str, object] = {}
|
|
218
|
+
|
|
219
|
+
with h5py.File(path, "r") as mat_file:
|
|
220
|
+
names = variable_names if variable_names is not None else tuple(mat_file.keys())
|
|
221
|
+
_ensure_hdf5_names_exist(mat_file, names)
|
|
222
|
+
|
|
223
|
+
for name in names:
|
|
224
|
+
item = mat_file[name]
|
|
225
|
+
if isinstance(item, h5py.Dataset):
|
|
226
|
+
variables[name] = item[()]
|
|
227
|
+
else:
|
|
228
|
+
variables[name] = MatlabHdf5Group(
|
|
229
|
+
name=name,
|
|
230
|
+
child_names=tuple(sorted(str(child) for child in item)),
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
return MatlabLoadedFile(path=path, file_format="hdf5-mat", variables=variables)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def _inspect_scipy_mat_file(path: Path) -> MatlabFileSummary:
|
|
237
|
+
"""Inspect an older MATLAB file through SciPy.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
path: MATLAB file that SciPy can load.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
A summary of non-private MATLAB variables.
|
|
244
|
+
|
|
245
|
+
SciPy loads older MAT files into Python objects. We use it only for files
|
|
246
|
+
that h5py cannot open, which avoids accidentally loading large HDF5 arrays.
|
|
247
|
+
"""
|
|
248
|
+
visible = _load_visible_scipy_variables(path, action="inspect")
|
|
249
|
+
|
|
250
|
+
variables = tuple(
|
|
251
|
+
_summarize_loaded_variable(name, value)
|
|
252
|
+
for name, value in sorted(visible.items())
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
return MatlabFileSummary(path=path, file_format="scipy-mat", variables=variables)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _load_scipy_mat_file(
|
|
259
|
+
path: Path,
|
|
260
|
+
variable_names: tuple[str, ...] | None,
|
|
261
|
+
) -> MatlabLoadedFile:
|
|
262
|
+
"""Load variables from an older MATLAB file through SciPy.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
path: MATLAB file that SciPy can read.
|
|
266
|
+
variable_names: Variable names to keep, or ``None`` for all visible
|
|
267
|
+
variables.
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
Loaded variables keyed by MATLAB variable name.
|
|
271
|
+
|
|
272
|
+
SciPy loads the file into memory. That is acceptable for the small metadata
|
|
273
|
+
files observed so far, but large files should use HDF5-backed loading.
|
|
274
|
+
"""
|
|
275
|
+
visible = _load_visible_scipy_variables(path, action="load")
|
|
276
|
+
|
|
277
|
+
if variable_names is None:
|
|
278
|
+
return MatlabLoadedFile(path=path, file_format="scipy-mat", variables=visible)
|
|
279
|
+
|
|
280
|
+
missing = tuple(name for name in variable_names if name not in visible)
|
|
281
|
+
if missing:
|
|
282
|
+
msg = f"Missing MATLAB variable(s) in {path}: {', '.join(missing)}"
|
|
283
|
+
raise KeyError(msg)
|
|
284
|
+
|
|
285
|
+
return MatlabLoadedFile(
|
|
286
|
+
path=path,
|
|
287
|
+
file_format="scipy-mat",
|
|
288
|
+
variables={name: visible[name] for name in variable_names},
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _load_visible_scipy_variables(
|
|
293
|
+
path: Path,
|
|
294
|
+
*,
|
|
295
|
+
action: ScipyLoadAction,
|
|
296
|
+
) -> dict[str, object]:
|
|
297
|
+
"""Load visible variables from an older MATLAB file through SciPy.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
path: MATLAB file that SciPy can read.
|
|
301
|
+
action: Caller intent used only for the error message.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Non-private MATLAB variables keyed by name.
|
|
305
|
+
|
|
306
|
+
SciPy adds private ``__header__``-style entries. twopy hides those because
|
|
307
|
+
they are file bookkeeping, not recording data.
|
|
308
|
+
"""
|
|
309
|
+
try:
|
|
310
|
+
loaded = scipy.io.loadmat(path, struct_as_record=False, squeeze_me=False)
|
|
311
|
+
except (NotImplementedError, OSError, ValueError) as error:
|
|
312
|
+
msg = f"Could not {action} MATLAB file {path}: {error}"
|
|
313
|
+
raise ValueError(msg) from error
|
|
314
|
+
|
|
315
|
+
return {
|
|
316
|
+
str(name): cast(object, value)
|
|
317
|
+
for name, value in loaded.items()
|
|
318
|
+
if not name.startswith("__")
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _summarize_loaded_variable(name: str, value: object) -> MatlabVariableSummary:
|
|
323
|
+
"""Summarize one SciPy-loaded MATLAB variable.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
name: MATLAB variable name.
|
|
327
|
+
value: Python object returned by ``scipy.io.loadmat``.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
Shape and dtype information when available, plus the Python type name.
|
|
331
|
+
|
|
332
|
+
This function uses structural checks instead of assuming every MATLAB value
|
|
333
|
+
is a NumPy array. MATLAB structs, cells, and scalars can arrive differently.
|
|
334
|
+
"""
|
|
335
|
+
shape = _shape_tuple(value)
|
|
336
|
+
dtype = _dtype_name(value)
|
|
337
|
+
|
|
338
|
+
return MatlabVariableSummary(
|
|
339
|
+
name=name,
|
|
340
|
+
python_type=type(value).__name__,
|
|
341
|
+
shape=shape,
|
|
342
|
+
dtype=dtype,
|
|
343
|
+
is_group=False,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def _shape_tuple(value: object) -> tuple[int, ...] | None:
|
|
348
|
+
"""Return an object's shape as a tuple of ints when it has one.
|
|
349
|
+
|
|
350
|
+
Args:
|
|
351
|
+
value: Python object from a MATLAB loader.
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
The object's shape or ``None`` when shape metadata is absent.
|
|
355
|
+
|
|
356
|
+
The conversion to plain ``int`` keeps summaries stable across NumPy scalar
|
|
357
|
+
integer implementations.
|
|
358
|
+
"""
|
|
359
|
+
shape = getattr(value, "shape", None)
|
|
360
|
+
if not isinstance(shape, tuple):
|
|
361
|
+
return None
|
|
362
|
+
return tuple(int(length) for length in shape)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def _dtype_name(value: object) -> str | None:
|
|
366
|
+
"""Return an object's dtype name when it has one.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
value: Python object from a MATLAB loader.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
String dtype name or ``None`` when dtype metadata is absent.
|
|
373
|
+
|
|
374
|
+
The result is text because the inspection layer is for display and logging.
|
|
375
|
+
"""
|
|
376
|
+
dtype = getattr(value, "dtype", None)
|
|
377
|
+
if dtype is None:
|
|
378
|
+
return None
|
|
379
|
+
return str(cast(object, dtype))
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def _ensure_hdf5_names_exist(mat_file: h5py.File, names: tuple[str, ...]) -> None:
|
|
383
|
+
"""Raise a clear error when requested HDF5 variables are absent.
|
|
384
|
+
|
|
385
|
+
Args:
|
|
386
|
+
mat_file: Open HDF5-backed MATLAB file.
|
|
387
|
+
names: Requested top-level variable names.
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
None when every requested name exists.
|
|
391
|
+
|
|
392
|
+
Raises:
|
|
393
|
+
KeyError: If one or more names are absent.
|
|
394
|
+
"""
|
|
395
|
+
missing = tuple(name for name in names if name not in mat_file)
|
|
396
|
+
if missing:
|
|
397
|
+
msg = f"Missing MATLAB variable(s) in {mat_file.filename}: {', '.join(missing)}"
|
|
398
|
+
raise KeyError(msg)
|
twopy/napari/__init__.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Napari adapter for twopy.
|
|
2
|
+
|
|
3
|
+
Inputs: converted twopy recordings, ROI labels, and optional launch settings.
|
|
4
|
+
Outputs: napari viewers, image layers, Labels ROI layers, and small magicgui
|
|
5
|
+
controls.
|
|
6
|
+
|
|
7
|
+
The package keeps GUI code scoped by responsibility. Core conversion,
|
|
8
|
+
database, ROI, and analysis modules stay independent so a future napari plugin
|
|
9
|
+
can wrap these helpers instead of owning scientific logic.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from twopy.napari.controls import NapariControlDocks, add_twopy_magicgui_controls
|
|
13
|
+
from twopy.napari.launcher import launch_napari, main
|
|
14
|
+
from twopy.napari.roi import roi_label_image_from_layer, save_napari_label_rois
|
|
15
|
+
from twopy.napari.types import NapariRecordingView
|
|
16
|
+
from twopy.napari.viewer import open_recording_in_napari
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"NapariRecordingView",
|
|
20
|
+
"NapariControlDocks",
|
|
21
|
+
"add_twopy_magicgui_controls",
|
|
22
|
+
"launch_napari",
|
|
23
|
+
"main",
|
|
24
|
+
"open_recording_in_napari",
|
|
25
|
+
"roi_label_image_from_layer",
|
|
26
|
+
"save_napari_label_rois",
|
|
27
|
+
]
|
twopy/napari/__main__.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Command-line module entry point for ``python -m twopy.napari``.
|
|
2
|
+
|
|
3
|
+
Inputs: command-line arguments parsed by ``twopy.napari.launcher``.
|
|
4
|
+
Outputs: a napari app session.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from twopy.napari.launcher import main
|
|
8
|
+
|
|
9
|
+
if __name__ == "__main__":
|
|
10
|
+
main()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Shared constants for the twopy napari adapter.
|
|
2
|
+
|
|
3
|
+
Inputs: none.
|
|
4
|
+
Outputs: small GUI defaults used by launcher and controls.
|
|
5
|
+
|
|
6
|
+
Keeping defaults in one file prevents launcher and widget behavior from
|
|
7
|
+
drifting as the napari surface grows.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
DEFAULT_PATH_TEXT = "default"
|
|
11
|
+
DEFAULT_ROI_FILENAME = "rois.h5"
|
|
12
|
+
RECORDING_DATA_FILENAME = "recording_data.h5"
|
|
13
|
+
ALIGNED_MOVIE_FILENAME = "aligned_movie.h5"
|