napari-mlarray 0.0.1__tar.gz → 0.0.2__tar.gz
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.
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/PKG-INFO +2 -1
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/pyproject.toml +2 -1
- napari_mlarray-0.0.2/src/napari_mlarray/_reader.py +271 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray/_version.py +3 -3
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray/_writer.py +1 -1
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/PKG-INFO +2 -1
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/requires.txt +1 -0
- napari_mlarray-0.0.1/src/napari_mlarray/_reader.py +0 -77
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.copier-answers.yml +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/ISSUE_TEMPLATE/task.md +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/dependabot.yml +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.github/workflows/test_and_deploy.yml +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.gitignore +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.napari-hub/DESCRIPTION.md +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/.napari-hub/config.yml +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/LICENSE +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/MANIFEST.in +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/README.md +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/setup.cfg +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray/__init__.py +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray/_widget.py +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray/napari.yaml +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/SOURCES.txt +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/dependency_links.txt +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/entry_points.txt +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/top_level.txt +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/tests/__init__.py +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/tests/test_default.py +0 -0
- {napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: napari-mlarray
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2
|
|
4
4
|
Summary: A reader/writer Napari plugin for MLArray images.
|
|
5
5
|
Author: Karol-G
|
|
6
6
|
Author-email: karol.gotkowski@dkfz.de
|
|
@@ -44,6 +44,7 @@ Requires-Python: >=3.10
|
|
|
44
44
|
Description-Content-Type: text/markdown
|
|
45
45
|
License-File: LICENSE
|
|
46
46
|
Requires-Dist: mlarray
|
|
47
|
+
Requires-Dist: numpy
|
|
47
48
|
Provides-Extra: all
|
|
48
49
|
Requires-Dist: napari[all]; extra == "all"
|
|
49
50
|
Dynamic: license-file
|
|
@@ -29,7 +29,8 @@ requires-python = ">=3.10"
|
|
|
29
29
|
# or any other Qt bindings directly (e.g. PyQt5, PySide2).
|
|
30
30
|
# See best practices: https://napari.org/stable/plugins/building_a_plugin/best_practices.html
|
|
31
31
|
dependencies = [
|
|
32
|
-
"mlarray"
|
|
32
|
+
"mlarray",
|
|
33
|
+
"numpy"
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[project.optional-dependencies]
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module is an example of a barebones numpy reader plugin for napari.
|
|
3
|
+
|
|
4
|
+
It implements the Reader specification, but your plugin may choose to
|
|
5
|
+
implement multiple readers or even other plugin contributions. see:
|
|
6
|
+
https://napari.org/stable/plugins/building_a_plugin/guides.html#readers
|
|
7
|
+
"""
|
|
8
|
+
from mlarray import MLArray
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def napari_get_reader(path):
|
|
14
|
+
"""A basic implementation of a Reader contribution.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
path : str or list of str
|
|
19
|
+
Path to file, or list of paths.
|
|
20
|
+
|
|
21
|
+
Returns
|
|
22
|
+
-------
|
|
23
|
+
function or None
|
|
24
|
+
If the path is a recognized format, return a function that accepts the
|
|
25
|
+
same path or list of paths, and returns a list of layer data tuples.
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(path, list):
|
|
28
|
+
# reader plugins may be handed single path, or a list of paths.
|
|
29
|
+
# if it is a list, it is assumed to be an image stack...
|
|
30
|
+
# so we are only going to look at the first file.
|
|
31
|
+
path = path[0]
|
|
32
|
+
|
|
33
|
+
# the get_reader function should make as many checks as possible
|
|
34
|
+
# (without loading the full file) to determine if it can read
|
|
35
|
+
# the path. Here, we check the dtype of the array by loading
|
|
36
|
+
# it with memmap, so that we don't actually load the full array into memory.
|
|
37
|
+
# We pretend that this reader can only read integer arrays.
|
|
38
|
+
try:
|
|
39
|
+
if not str(path).endswith(".mla"):
|
|
40
|
+
return None
|
|
41
|
+
# napari_get_reader should never raise an exception, because napari
|
|
42
|
+
# raises its own specific errors depending on what plugins are
|
|
43
|
+
# available for the given path, so we catch
|
|
44
|
+
# the OSError that np.load might raise if the file is malformed
|
|
45
|
+
except OSError:
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
# otherwise we return the *function* that can read ``path``.
|
|
49
|
+
return reader_function
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def reader_function(path):
|
|
53
|
+
"""Take a path or list of paths and return a list of LayerData tuples.
|
|
54
|
+
|
|
55
|
+
Readers are expected to return data as a list of tuples, where each tuple
|
|
56
|
+
is (data, [add_kwargs, [layer_type]]), "add_kwargs" and "layer_type" are
|
|
57
|
+
both optional.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
path : str or list of str
|
|
62
|
+
Path to file, or list of paths.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
layer_data : list of tuples
|
|
67
|
+
A list of LayerData tuples where each tuple in the list contains
|
|
68
|
+
(data, metadata, layer_type), where data is a numpy array, metadata is
|
|
69
|
+
a dict of keyword arguments for the corresponding viewer.add_* method
|
|
70
|
+
in napari, and layer_type is a lower-case string naming the type of
|
|
71
|
+
layer. Both "meta", and "layer_type" are optional. napari will
|
|
72
|
+
default to layer_type=="image" if not provided
|
|
73
|
+
"""
|
|
74
|
+
paths = [path] if isinstance(path, str) else path
|
|
75
|
+
layer_data = []
|
|
76
|
+
for path in paths:
|
|
77
|
+
name = Path(path).stem
|
|
78
|
+
mlarray = MLArray.open(path)
|
|
79
|
+
if mlarray.meta._has_array.has_array == True:
|
|
80
|
+
data = mlarray
|
|
81
|
+
metadata = {"name": f"{name}", "affine": mlarray.affine, "metadata": mlarray.meta.to_mapping()}
|
|
82
|
+
layer_type = "labels" if mlarray.meta.is_seg.is_seg == True else "image"
|
|
83
|
+
layer_data.append((data, metadata, layer_type))
|
|
84
|
+
if mlarray.meta.bbox.bboxes is not None:
|
|
85
|
+
data = bboxes_minmax_to_napari_rectangles_2d(mlarray.meta.bbox.bboxes)
|
|
86
|
+
edge_color = _napari_bbox_edge_colors(
|
|
87
|
+
data,
|
|
88
|
+
labels=getattr(mlarray.meta.bbox, "labels", None),
|
|
89
|
+
)
|
|
90
|
+
text = _napari_bbox_score_text(
|
|
91
|
+
scores=getattr(mlarray.meta.bbox, "scores", None),
|
|
92
|
+
labels=getattr(mlarray.meta.bbox, "labels", None),
|
|
93
|
+
count=len(data),
|
|
94
|
+
edge_color=edge_color,
|
|
95
|
+
rectangles=data,
|
|
96
|
+
)
|
|
97
|
+
metadata = {
|
|
98
|
+
"name": f"{name} (BBoxes)",
|
|
99
|
+
"shape_type": "rectangle",
|
|
100
|
+
"affine": mlarray.affine,
|
|
101
|
+
"metadata": mlarray.meta.to_mapping(),
|
|
102
|
+
"face_color": "transparent",
|
|
103
|
+
"edge_color": edge_color,
|
|
104
|
+
}
|
|
105
|
+
if text is not None:
|
|
106
|
+
metadata["text"] = text
|
|
107
|
+
layer_type = "shapes"
|
|
108
|
+
layer_data.append((data, metadata, layer_type))
|
|
109
|
+
return layer_data
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def bboxes_minmax_to_napari_rectangles_2d(
|
|
113
|
+
bboxes,
|
|
114
|
+
*,
|
|
115
|
+
dtype=np.float32,
|
|
116
|
+
validate: bool = True,
|
|
117
|
+
) -> np.ndarray:
|
|
118
|
+
"""
|
|
119
|
+
Convert 2D axis-aligned bounding boxes from min/max format to napari Shapes rectangles.
|
|
120
|
+
|
|
121
|
+
Accepted input formats (both mean the same thing):
|
|
122
|
+
1) (N, 2, 2): [[min_dim0, max_dim0], [min_dim1, max_dim1]]
|
|
123
|
+
Example (dim order is whatever you use, e.g. (y, x)):
|
|
124
|
+
[[[ymin, ymax], [xmin, xmax]], ...]
|
|
125
|
+
|
|
126
|
+
2) (N, 4): [min_dim0, min_dim1, max_dim0, max_dim1]
|
|
127
|
+
Example:
|
|
128
|
+
[[ymin, xmin, ymax, xmax], ...]
|
|
129
|
+
|
|
130
|
+
Output format (napari Shapes rectangle vertices):
|
|
131
|
+
(N, 4, 2) with vertices in non-twisting cyclic order:
|
|
132
|
+
(min0, min1) -> (min0, max1) -> (max0, max1) -> (max0, min1)
|
|
133
|
+
|
|
134
|
+
Raises:
|
|
135
|
+
ValueError if bboxes are not 2D (i.e., D != 2) or shapes are invalid.
|
|
136
|
+
"""
|
|
137
|
+
arr = np.asarray(bboxes)
|
|
138
|
+
|
|
139
|
+
# Normalize input to shape (N, 2, 2)
|
|
140
|
+
if arr.ndim == 2 and arr.shape[1] == 4:
|
|
141
|
+
# (N, 4) -> (N, 2, 2)
|
|
142
|
+
arr = np.stack(
|
|
143
|
+
[
|
|
144
|
+
arr[:, [0, 2]], # dim0: [min0, max0]
|
|
145
|
+
arr[:, [1, 3]], # dim1: [min1, max1]
|
|
146
|
+
],
|
|
147
|
+
axis=1,
|
|
148
|
+
)
|
|
149
|
+
elif arr.ndim == 3 and arr.shape[1:] == (2, 2):
|
|
150
|
+
pass
|
|
151
|
+
else:
|
|
152
|
+
raise ValueError(
|
|
153
|
+
f"Expected bboxes of shape (N, 2, 2) or (N, 4). Got {arr.shape}."
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
N, D, two = arr.shape
|
|
157
|
+
if D != 2 or two != 2:
|
|
158
|
+
# Defensive; should never hit because of checks above.
|
|
159
|
+
raise ValueError(f"Only 2D bboxes are supported. Got (N, {D}, {two}).")
|
|
160
|
+
|
|
161
|
+
mins = arr[:, :, 0]
|
|
162
|
+
maxs = arr[:, :, 1]
|
|
163
|
+
|
|
164
|
+
if validate and np.any(maxs < mins):
|
|
165
|
+
bad = np.argwhere(maxs < mins)
|
|
166
|
+
raise ValueError(
|
|
167
|
+
"Found bbox with max < min at indices (bbox_index, dim): "
|
|
168
|
+
f"{bad[:10].tolist()}" + (" ..." if len(bad) > 10 else "")
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
min0, min1 = mins[:, 0], mins[:, 1]
|
|
172
|
+
max0, max1 = maxs[:, 0], maxs[:, 1]
|
|
173
|
+
|
|
174
|
+
# Cyclic order (no twisting):
|
|
175
|
+
rects = np.stack(
|
|
176
|
+
[
|
|
177
|
+
np.stack([min0, min1], axis=1),
|
|
178
|
+
np.stack([min0, max1], axis=1),
|
|
179
|
+
np.stack([max0, max1], axis=1),
|
|
180
|
+
np.stack([max0, min1], axis=1),
|
|
181
|
+
],
|
|
182
|
+
axis=1,
|
|
183
|
+
).astype(dtype, copy=False)
|
|
184
|
+
|
|
185
|
+
return rects
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _napari_bbox_edge_colors(rectangles, labels):
|
|
189
|
+
"""Return RGBA edge colors for each bbox."""
|
|
190
|
+
count = len(rectangles)
|
|
191
|
+
if count == 0:
|
|
192
|
+
return np.empty((0, 4), dtype=np.float32)
|
|
193
|
+
|
|
194
|
+
if labels is not None and len(labels) == count:
|
|
195
|
+
unique_labels = list(dict.fromkeys(labels))
|
|
196
|
+
label_to_color = {
|
|
197
|
+
label: _palette_rgba(idx) for idx, label in enumerate(unique_labels)
|
|
198
|
+
}
|
|
199
|
+
colors = np.array([label_to_color[label] for label in labels], dtype=np.float32)
|
|
200
|
+
else:
|
|
201
|
+
colors = np.array([_palette_rgba(idx) for idx in range(count)], dtype=np.float32)
|
|
202
|
+
|
|
203
|
+
return colors
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _napari_bbox_score_text(scores, labels, count, edge_color, rectangles):
|
|
207
|
+
"""Return napari Shapes text metadata if scores are provided."""
|
|
208
|
+
have_scores = scores is not None and len(scores) == count
|
|
209
|
+
have_labels = labels is not None and len(labels) == count
|
|
210
|
+
if not have_scores and not have_labels:
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
# Place text at the top-left corner of each rectangle.
|
|
214
|
+
top_left = rectangles[:, 0, :]
|
|
215
|
+
top_left = np.maximum(top_left - np.array([4.0, 0.0], dtype=top_left.dtype), 0)
|
|
216
|
+
|
|
217
|
+
strings = []
|
|
218
|
+
for idx in range(count):
|
|
219
|
+
parts = []
|
|
220
|
+
if have_labels:
|
|
221
|
+
parts.append(f"Label: {labels[idx]}")
|
|
222
|
+
if have_scores:
|
|
223
|
+
parts.append(f"Score: {scores[idx]:.3f}")
|
|
224
|
+
# Add a trailing empty line to create spacing below the score.
|
|
225
|
+
parts.append("\n")
|
|
226
|
+
strings.append("\n".join(parts))
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
"string": strings,
|
|
230
|
+
"color": edge_color,
|
|
231
|
+
"size": 12,
|
|
232
|
+
"anchor": "upper_left",
|
|
233
|
+
"position": top_left,
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _palette_rgba(index):
|
|
238
|
+
"""Simple, distinct-ish palette; returns RGBA in 0..1."""
|
|
239
|
+
palette = [
|
|
240
|
+
(0.90, 0.10, 0.12, 1.0),
|
|
241
|
+
(0.00, 0.48, 1.00, 1.0),
|
|
242
|
+
(0.20, 0.80, 0.20, 1.0),
|
|
243
|
+
(0.98, 0.60, 0.00, 1.0),
|
|
244
|
+
(0.60, 0.20, 0.80, 1.0),
|
|
245
|
+
(0.10, 0.75, 0.80, 1.0),
|
|
246
|
+
(0.80, 0.80, 0.00, 1.0),
|
|
247
|
+
(0.95, 0.40, 0.60, 1.0),
|
|
248
|
+
(0.90, 0.30, 0.00, 1.0),
|
|
249
|
+
(0.00, 0.70, 0.40, 1.0),
|
|
250
|
+
(0.40, 0.80, 1.00, 1.0),
|
|
251
|
+
(1.00, 0.20, 0.70, 1.0),
|
|
252
|
+
(0.50, 0.90, 0.20, 1.0),
|
|
253
|
+
(0.20, 0.90, 0.70, 1.0),
|
|
254
|
+
(0.70, 0.50, 1.00, 1.0),
|
|
255
|
+
(1.00, 0.50, 0.20, 1.0),
|
|
256
|
+
(0.20, 0.60, 1.00, 1.0),
|
|
257
|
+
(1.00, 0.70, 0.20, 1.0),
|
|
258
|
+
(0.60, 1.00, 0.20, 1.0),
|
|
259
|
+
(0.20, 1.00, 0.40, 1.0),
|
|
260
|
+
(0.20, 1.00, 0.90, 1.0),
|
|
261
|
+
(0.20, 0.90, 1.00, 1.0),
|
|
262
|
+
(0.40, 0.60, 1.00, 1.0),
|
|
263
|
+
(0.80, 0.20, 1.00, 1.0),
|
|
264
|
+
(1.00, 0.20, 0.30, 1.0),
|
|
265
|
+
(1.00, 0.30, 0.50, 1.0),
|
|
266
|
+
(1.00, 0.60, 0.60, 1.0),
|
|
267
|
+
(1.00, 0.90, 0.30, 1.0),
|
|
268
|
+
(0.60, 1.00, 0.60, 1.0),
|
|
269
|
+
(0.60, 0.90, 1.00, 1.0),
|
|
270
|
+
]
|
|
271
|
+
return palette[index % len(palette)]
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.2'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 2)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gb43d6a1af'
|
|
@@ -34,7 +34,7 @@ def write_single_image(path: str, data: Any, meta: dict) -> list[str]:
|
|
|
34
34
|
-------
|
|
35
35
|
[path] : A list containing the string path to the saved file.
|
|
36
36
|
"""
|
|
37
|
-
mlarray = MLArray(data, meta=Meta.
|
|
37
|
+
mlarray = MLArray(data, meta=Meta.from_mapping(meta["metadata"]))
|
|
38
38
|
mlarray.save(path)
|
|
39
39
|
|
|
40
40
|
# return path to any file(s) that were successfully written
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: napari-mlarray
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2
|
|
4
4
|
Summary: A reader/writer Napari plugin for MLArray images.
|
|
5
5
|
Author: Karol-G
|
|
6
6
|
Author-email: karol.gotkowski@dkfz.de
|
|
@@ -44,6 +44,7 @@ Requires-Python: >=3.10
|
|
|
44
44
|
Description-Content-Type: text/markdown
|
|
45
45
|
License-File: LICENSE
|
|
46
46
|
Requires-Dist: mlarray
|
|
47
|
+
Requires-Dist: numpy
|
|
47
48
|
Provides-Extra: all
|
|
48
49
|
Requires-Dist: napari[all]; extra == "all"
|
|
49
50
|
Dynamic: license-file
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module is an example of a barebones numpy reader plugin for napari.
|
|
3
|
-
|
|
4
|
-
It implements the Reader specification, but your plugin may choose to
|
|
5
|
-
implement multiple readers or even other plugin contributions. see:
|
|
6
|
-
https://napari.org/stable/plugins/building_a_plugin/guides.html#readers
|
|
7
|
-
"""
|
|
8
|
-
from mlarray import MLArray
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def napari_get_reader(path):
|
|
12
|
-
"""A basic implementation of a Reader contribution.
|
|
13
|
-
|
|
14
|
-
Parameters
|
|
15
|
-
----------
|
|
16
|
-
path : str or list of str
|
|
17
|
-
Path to file, or list of paths.
|
|
18
|
-
|
|
19
|
-
Returns
|
|
20
|
-
-------
|
|
21
|
-
function or None
|
|
22
|
-
If the path is a recognized format, return a function that accepts the
|
|
23
|
-
same path or list of paths, and returns a list of layer data tuples.
|
|
24
|
-
"""
|
|
25
|
-
if isinstance(path, list):
|
|
26
|
-
# reader plugins may be handed single path, or a list of paths.
|
|
27
|
-
# if it is a list, it is assumed to be an image stack...
|
|
28
|
-
# so we are only going to look at the first file.
|
|
29
|
-
path = path[0]
|
|
30
|
-
|
|
31
|
-
# the get_reader function should make as many checks as possible
|
|
32
|
-
# (without loading the full file) to determine if it can read
|
|
33
|
-
# the path. Here, we check the dtype of the array by loading
|
|
34
|
-
# it with memmap, so that we don't actually load the full array into memory.
|
|
35
|
-
# We pretend that this reader can only read integer arrays.
|
|
36
|
-
try:
|
|
37
|
-
if not str(path).endswith(".mla"):
|
|
38
|
-
return None
|
|
39
|
-
# napari_get_reader should never raise an exception, because napari
|
|
40
|
-
# raises its own specific errors depending on what plugins are
|
|
41
|
-
# available for the given path, so we catch
|
|
42
|
-
# the OSError that np.load might raise if the file is malformed
|
|
43
|
-
except OSError:
|
|
44
|
-
return None
|
|
45
|
-
|
|
46
|
-
# otherwise we return the *function* that can read ``path``.
|
|
47
|
-
return reader_function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def reader_function(path):
|
|
51
|
-
"""Take a path or list of paths and return a list of LayerData tuples.
|
|
52
|
-
|
|
53
|
-
Readers are expected to return data as a list of tuples, where each tuple
|
|
54
|
-
is (data, [add_kwargs, [layer_type]]), "add_kwargs" and "layer_type" are
|
|
55
|
-
both optional.
|
|
56
|
-
|
|
57
|
-
Parameters
|
|
58
|
-
----------
|
|
59
|
-
path : str or list of str
|
|
60
|
-
Path to file, or list of paths.
|
|
61
|
-
|
|
62
|
-
Returns
|
|
63
|
-
-------
|
|
64
|
-
layer_data : list of tuples
|
|
65
|
-
A list of LayerData tuples where each tuple in the list contains
|
|
66
|
-
(data, metadata, layer_type), where data is a numpy array, metadata is
|
|
67
|
-
a dict of keyword arguments for the corresponding viewer.add_* method
|
|
68
|
-
in napari, and layer_type is a lower-case string naming the type of
|
|
69
|
-
layer. Both "meta", and "layer_type" are optional. napari will
|
|
70
|
-
default to layer_type=="image" if not provided
|
|
71
|
-
"""
|
|
72
|
-
# handle both a string and a list of strings
|
|
73
|
-
paths = [path] if isinstance(path, str) else path
|
|
74
|
-
# load all files into array
|
|
75
|
-
mlarrays = [MLArray.open(_path) for _path in paths]
|
|
76
|
-
layer_data = [(mlarray, {"affine": mlarray.affine, "metadata": mlarray.meta.to_dict()}, "labels" if mlarray.meta.is_seg.is_seg == True else "image") for mlarray in mlarrays]
|
|
77
|
-
return layer_data
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{napari_mlarray-0.0.1 → napari_mlarray-0.0.2}/src/napari_mlarray.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|