impy-array 2.5.2__tar.gz → 2.5.3__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.
Files changed (72) hide show
  1. {impy_array-2.5.2 → impy_array-2.5.3}/PKG-INFO +1 -1
  2. {impy_array-2.5.2 → impy_array-2.5.3}/impy/__init__.py +1 -1
  3. {impy_array-2.5.2 → impy_array-2.5.3}/impy/array_api.py +2 -2
  4. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_corr.py +3 -3
  5. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_zarr.py +2 -4
  6. {impy_array-2.5.2 → impy_array-2.5.3}/impy/viewer/utils.py +13 -16
  7. {impy_array-2.5.2 → impy_array-2.5.3}/impy/viewer/viewer.py +107 -109
  8. {impy_array-2.5.2 → impy_array-2.5.3}/.gitignore +0 -0
  9. {impy_array-2.5.2 → impy_array-2.5.3}/LICENSE +0 -0
  10. {impy_array-2.5.2 → impy_array-2.5.3}/README.md +0 -0
  11. {impy_array-2.5.2 → impy_array-2.5.3}/impy/__main__.py +0 -0
  12. {impy_array-2.5.2 → impy_array-2.5.3}/impy/_const.py +0 -0
  13. {impy_array-2.5.2 → impy_array-2.5.3}/impy/_types.py +0 -0
  14. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/__init__.py +0 -0
  15. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_imshow.py +0 -0
  16. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/__init__.py +0 -0
  17. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_deconv.py +0 -0
  18. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_docs.py +0 -0
  19. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_filters.py +0 -0
  20. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_glcm.py +0 -0
  21. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_linalg.py +0 -0
  22. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_misc.py +0 -0
  23. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_plot.py +0 -0
  24. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_process_numba.py +0 -0
  25. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_skimage.py +0 -0
  26. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_structures.py +0 -0
  27. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/_utils/_transform.py +0 -0
  28. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/axesmixin.py +0 -0
  29. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/bases/__init__.py +0 -0
  30. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/bases/metaarray.py +0 -0
  31. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/bases/overload.py +0 -0
  32. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/big.py +0 -0
  33. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/imgarray.py +0 -0
  34. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/label.py +0 -0
  35. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/labeledarray.py +0 -0
  36. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/lazy.py +0 -0
  37. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/phasearray.py +0 -0
  38. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/specials.py +0 -0
  39. {impy_array-2.5.2 → impy_array-2.5.3}/impy/arrays/tiled.py +0 -0
  40. {impy_array-2.5.2 → impy_array-2.5.3}/impy/axes/__init__.py +0 -0
  41. {impy_array-2.5.2 → impy_array-2.5.3}/impy/axes/_axes.py +0 -0
  42. {impy_array-2.5.2 → impy_array-2.5.3}/impy/axes/_axes_tuple.py +0 -0
  43. {impy_array-2.5.2 → impy_array-2.5.3}/impy/axes/_axis.py +0 -0
  44. {impy_array-2.5.2 → impy_array-2.5.3}/impy/axes/_slicer.py +0 -0
  45. {impy_array-2.5.2 → impy_array-2.5.3}/impy/binder.py +0 -0
  46. {impy_array-2.5.2 → impy_array-2.5.3}/impy/collections.py +0 -0
  47. {impy_array-2.5.2 → impy_array-2.5.3}/impy/core.py +0 -0
  48. {impy_array-2.5.2 → impy_array-2.5.3}/impy/correlation.py +0 -0
  49. {impy_array-2.5.2 → impy_array-2.5.3}/impy/frame/__init__.py +0 -0
  50. {impy_array-2.5.2 → impy_array-2.5.3}/impy/frame/frames.py +0 -0
  51. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/__init__.py +0 -0
  52. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_czi.py +0 -0
  53. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_mrc.py +0 -0
  54. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_nd2.py +0 -0
  55. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_npy.py +0 -0
  56. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_registry.py +0 -0
  57. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_tiff.py +0 -0
  58. {impy_array-2.5.2 → impy_array-2.5.3}/impy/io/_utils.py +0 -0
  59. {impy_array-2.5.2 → impy_array-2.5.3}/impy/lazy/__init__.py +0 -0
  60. {impy_array-2.5.2 → impy_array-2.5.3}/impy/lazy/core.py +0 -0
  61. {impy_array-2.5.2 → impy_array-2.5.3}/impy/lazy/random.py +0 -0
  62. {impy_array-2.5.2 → impy_array-2.5.3}/impy/random.py +0 -0
  63. {impy_array-2.5.2 → impy_array-2.5.3}/impy/roi.py +0 -0
  64. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/__init__.py +0 -0
  65. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/axesop.py +0 -0
  66. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/deco.py +0 -0
  67. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/gauss.py +0 -0
  68. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/misc.py +0 -0
  69. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/slicer.py +0 -0
  70. {impy_array-2.5.2 → impy_array-2.5.3}/impy/utils/utilcls.py +0 -0
  71. {impy_array-2.5.2 → impy_array-2.5.3}/impy/viewer/__init__.py +0 -0
  72. {impy_array-2.5.2 → impy_array-2.5.3}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: impy-array
3
- Version: 2.5.2
3
+ Version: 2.5.3
4
4
  Summary: Speed up coding/extending image analysis in Python.
5
5
  Project-URL: Download, https://github.com/hanjinliu/impy
6
6
  Author-email: Hanjin Liu <liuhanjin-sc@g.ecc.u-tokyo.ac.jp>
@@ -1,4 +1,4 @@
1
- __version__ = "2.5.2"
1
+ __version__ = "2.5.3"
2
2
  __author__ = "Hanjin Liu"
3
3
  __email__ = "liuhanjin-sc@g.ecc.u-tokyo.ac.jp"
4
4
 
@@ -97,7 +97,7 @@ class XP:
97
97
  self.angle = np.angle
98
98
  self.abs = np.abs
99
99
  self.mod = np.mod
100
- self.fix = np.fix
100
+ self.trunc = np.trunc
101
101
  self.round = np.round
102
102
  self.gradient = np.gradient
103
103
  self.tensordot = np.tensordot
@@ -165,7 +165,7 @@ class XP:
165
165
  self.angle = cp.angle
166
166
  self.abs = cp.abs
167
167
  self.mod = cp.mod
168
- self.fix = cp.fix
168
+ self.trunc = cp.trunc
169
169
  self.round = cp.round
170
170
  try:
171
171
  self.gradient = cp.gradient
@@ -38,16 +38,16 @@ def subpixel_pcc(
38
38
  ):
39
39
  power, product = _pcc_and_power_spec(f0, f1, max_shifts)
40
40
  maxima = xp.unravel_index(xp.argmax(power), power.shape)
41
- midpoints = xp.array([np.fix(axis_size / 2) for axis_size in power.shape])
41
+ midpoints = xp.array([np.trunc(axis_size / 2) for axis_size in power.shape])
42
42
 
43
43
  shifts = xp.asarray(maxima, dtype=np.float32)
44
44
  shifts[shifts > midpoints] -= xp.array(power.shape)[shifts > midpoints]
45
45
  # Initial shift estimate in upsampled grid
46
- shifts = xp.fix(shifts * upsample_factor) / upsample_factor
46
+ shifts = xp.trunc(shifts * upsample_factor) / upsample_factor
47
47
  if upsample_factor > 1:
48
48
  upsampled_region_size = np.ceil(upsample_factor * 1.5)
49
49
  # Center of output array at dftshift + 1
50
- dftshift = xp.fix(upsampled_region_size / 2.0)
50
+ dftshift = xp.trunc(upsampled_region_size / 2.0)
51
51
  upsample_factor = xp.array(upsample_factor, dtype=np.float32)
52
52
  # Matrix multiply DFT around the current shift estimate
53
53
  sample_region_offset = dftshift - shifts*upsample_factor
@@ -5,8 +5,6 @@ import numpy as np
5
5
  from impy.io._registry import IO
6
6
  from impy.io._utils import get_channel_labels, ImpyArray, ImageData
7
7
 
8
- from impy.axes import ImageAxesError
9
-
10
8
 
11
9
  @IO.mark_reader(".zarr")
12
10
  def _(path: str, memmap: bool = False) -> ImageData:
@@ -32,6 +30,7 @@ def _(path: str, memmap: bool = False) -> ImageData:
32
30
  def _(path: str, img: ImpyArray, lazy: bool = False):
33
31
  """The zarr writer."""
34
32
  import zarr
33
+ from dask import array as da
35
34
 
36
35
  f = zarr.open(path, mode="w")
37
36
  metadata = img.metadata.copy()
@@ -44,6 +43,5 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
44
43
  if lazy:
45
44
  img.value.to_zarr(url=os.path.join(path, "data"))
46
45
  else:
47
- z = img.value
48
- f.array("data", z)
46
+ da.from_array(img.value).to_zarr(url=os.path.join(path, "data"))
49
47
  return None
@@ -127,19 +127,10 @@ def add_labeledarray(viewer: napari.Viewer, img: LabeledArray, **kwargs):
127
127
  channel_axis=chn_ax,
128
128
  scale=scale,
129
129
  name=name if len(name) > 1 else name[0],
130
+ units=[a.unit for a in img.axes],
130
131
  **kwargs
131
132
  )
132
133
 
133
- if viewer.scale_bar.unit:
134
- if viewer.scale_bar.unit != img.scale_unit:
135
- msg = (
136
- f"Incompatible scales. Viewer is {viewer.scale_bar.unit} while "
137
- f"image is {img.scale_unit}."
138
- )
139
- warnings.warn(msg)
140
- else:
141
- viewer.scale_bar.unit = img.scale_unit
142
-
143
134
  new_axes = [str(a) for a in img.axes if a != "c"]
144
135
  # add axis labels to slide bars and image orientation.
145
136
  if len(new_axes) >= len(viewer.dims.axis_labels):
@@ -173,7 +164,7 @@ def add_labels(
173
164
 
174
165
  out_layers = []
175
166
  for lbl, name in zip(lbls, names):
176
- layer = viewer.add_labels(lbl.value, name=name, **kw)
167
+ layer = viewer.add_labels(lbl.value, name=name, units=[a.unit for a in lbl.axes], **kw)
177
168
  out_layers.append(layer)
178
169
  return out_layers
179
170
 
@@ -188,17 +179,23 @@ def add_dask(viewer: napari.Viewer, img: LazyImgArray, **kwargs):
188
179
  else:
189
180
  name = ["[Lazy]" + name]
190
181
 
191
- layer = viewer.add_image(img, channel_axis=chn_ax, scale=scale,
192
- name=name if len(name)>1 else name[0], **kwargs)
193
- viewer.scale_bar.unit = img.scale_unit
182
+ layer = viewer.add_image(
183
+ img,
184
+ channel_axis=chn_ax,
185
+ scale=scale,
186
+ name=name if len(name)>1 else name[0],
187
+ units=[a.unit for a in img.axes],
188
+ **kwargs
189
+ )
194
190
  new_axes = [str(a) for a in img.axes if a != "c"]
195
191
  # add axis labels to slide bars and image orientation.
196
192
  if len(new_axes) >= len(viewer.dims.axis_labels):
197
193
  viewer.dims.axis_labels = new_axes
198
194
  return layer
199
195
 
200
- def add_points(viewer:napari.Viewer, points: AxesFrame, **kwargs):
196
+ def add_points(viewer: napari.Viewer, points: AxesFrame, **kwargs):
201
197
  from ..frame import MarkerFrame
198
+
202
199
  if isinstance(points, MarkerFrame):
203
200
  scale = make_world_scale(points)
204
201
  points = points.get_coords()
@@ -382,4 +379,4 @@ class ComplexArrayView:
382
379
  return self._data.nbytes
383
380
 
384
381
  def __getitem__(self, key):
385
- return self.__class__(self._data[key])
382
+ return self.__class__(self._data[key])
@@ -8,7 +8,7 @@ import numpy as np
8
8
 
9
9
  from .utils import (
10
10
  layer_to_impy_object,
11
- add_dask,
11
+ add_dask,
12
12
  add_labeledarray,
13
13
  add_labels,
14
14
  add_paths,
@@ -31,8 +31,8 @@ if TYPE_CHECKING:
31
31
  import pandas as pd
32
32
  from numpy.typing import ArrayLike
33
33
 
34
- # TODO:
35
- # - Layer does not remember the original data after c-split ... this will be solved after
34
+ # TODO:
35
+ # - Layer does not remember the original data after c-split ... this will be solved after
36
36
  # layer group is implemented in napari.
37
37
  # - channel axis will be dropped in the future: https://github.com/napari/napari/issues/3019
38
38
 
@@ -41,16 +41,16 @@ ImpyObject = NewType("ImpyObject", Any)
41
41
  class napariViewers:
42
42
  """
43
43
  The controller of ``napari.Viewer``s from ``impy``. Always access by ``ip.gui``.
44
- """
44
+ """
45
45
  def __init__(self):
46
- self._viewers: WeakValueDictionary[str, "napari.Viewer"] = WeakValueDictionary()
46
+ self._viewers: WeakValueDictionary[str, napari.Viewer] = WeakValueDictionary()
47
47
  self._front_viewer: str = None
48
48
  self._axes: Axes = None
49
-
49
+
50
50
  def __repr__(self):
51
51
  w = "".join([f"<{k}>" for k in self._viewers.keys()])
52
52
  return f"{self.__class__}{w}"
53
-
53
+
54
54
  def __getitem__(self, key: str) -> napariViewers:
55
55
  """
56
56
  This method looks strange but intuitive because you can access the last viewer by
@@ -62,33 +62,33 @@ class napariViewers:
62
62
  ----------
63
63
  key : str
64
64
  Viewer's title
65
- """
65
+ """
66
66
  if key in self._viewers.keys():
67
67
  self._front_viewer = key
68
68
  else:
69
69
  self.start(key)
70
70
  return self
71
-
71
+
72
72
  @property
73
- def viewer(self) -> "napari.Viewer":
73
+ def viewer(self) -> napari.Viewer:
74
74
  """The most front viewer you're using"""
75
75
  if self._front_viewer not in self._viewers.keys():
76
76
  self.start()
77
77
  return self._viewers[self._front_viewer]
78
-
78
+
79
79
  @property
80
- def layers(self) -> "LayerList":
81
- """Napari layer list. Identical to ``ip.gui.viewer.layers``."""
80
+ def layers(self) -> LayerList:
81
+ """Napari layer list. Identical to ``ip.gui.viewer.layers``."""
82
82
  return self.viewer.layers
83
-
83
+
84
84
  @property
85
85
  def current_slice(self) -> tuple[slice | int, ...]:
86
86
  """
87
- Return a tuple of slicer that corresponds to current field of view.
88
-
89
- For instance, when the viewer is displaying yx-plane at t=1, then this property
87
+ Return a tuple of slicer that corresponds to current field of view.
88
+
89
+ For instance, when the viewer is displaying yx-plane at t=1, then this property
90
90
  returns ``(1, slice(None), slice(None))``.
91
- """
91
+ """
92
92
  current_step = list(self.viewer.dims.current_step)
93
93
  ndim = min(self.viewer.dims.ndisplay, self.viewer.dims.ndim)
94
94
  active_plane = list(self.viewer.dims.order[-ndim:])
@@ -96,60 +96,58 @@ class napariViewers:
96
96
  current_step[i] = slice(None)
97
97
  return tuple(current_step)
98
98
 
99
-
99
+
100
100
  @property
101
101
  def selection(self) -> list[ImpyObject]:
102
- """Return selected layers' data as a list of impy objects."""
103
- return [layer_to_impy_object(self.viewer, layer)
102
+ """Return selected layers' data as a list of impy objects."""
103
+ return [layer_to_impy_object(self.viewer, layer)
104
104
  for layer in self.viewer.layers.selection]
105
-
105
+
106
106
  @property
107
107
  def cursor_pos(self) -> np.ndarray:
108
108
  """Return cursor position. Scale is considered."""
109
109
  return np.array(self.viewer.cursor.position) / self.scale
110
-
110
+
111
111
  @property
112
112
  def axes(self) -> Axes:
113
113
  """
114
- Axes information of current viewer.
115
-
114
+ Axes information of current viewer.
115
+
116
116
  Defined to make compatible with ``ImgArray``.
117
117
  """
118
118
  d = self.viewer.dims
119
- unit = self.viewer.scale_bar.unit
120
119
  axes: list[Axis] = []
121
120
  for a, r in zip(d.axis_labels, d.range):
122
121
  if a in ["z", "y", "x"]:
123
- axis = Axis(a, {"scale": r[2], "unit": unit})
122
+ axis = Axis(a, {"scale": r[2]})
124
123
  else:
125
124
  axis = Axis(a)
126
125
  axes.append(axis)
127
126
  self._axes = Axes(axes) # because scale-view uses a weakref
128
127
  return self._axes
129
-
128
+
130
129
  @property
131
130
  def scale(self) -> ScaleView:
132
- """
133
- Scale information of current viewer.
134
-
131
+ """Scale information of current viewer.
132
+
135
133
  Defined to make compatible with ``ImgArray``.
136
- """
134
+ """
137
135
  return self.axes.scale
138
-
136
+
139
137
  def start(self, key: str = "impy"):
140
138
  """Create a napari window with name ``key``."""
141
139
  if not isinstance(key, str):
142
140
  raise TypeError("`key` must be str.")
143
141
  if key in self._viewers.keys():
144
142
  raise ValueError(f"Key {key} already exists.")
145
-
143
+
146
144
  viewer = napari.Viewer(title=key)
147
145
  self._viewers[key] = viewer
148
146
  self._front_viewer = key
149
147
  return None
150
148
 
151
149
  def get(
152
- self,
150
+ self,
153
151
  kind: str = "image",
154
152
  layer_state: str = "visible",
155
153
  returns: str = "last"
@@ -161,7 +159,7 @@ class napariViewers:
161
159
  ----------
162
160
  kind : str, optional
163
161
  Kind of layers/shapes to return.
164
-
162
+
165
163
  - "image": Image layer.
166
164
  - "labels": Labels layer
167
165
  - "points": Points layer.
@@ -174,41 +172,41 @@ class napariViewers:
174
172
  - "path": Path shapes in Shapes layer.
175
173
  - "polygon": Polygon shapes in Shapes layer.
176
174
  - "ellipse": Ellipse shapes in Shapes layer.
177
-
175
+
178
176
  layer_state : {"selected", "visible", "any"}, default is "any"
179
177
  How to filter layer list.
180
-
178
+
181
179
  - "selected": Only selected layers will be searched.
182
180
  - "visible": Only visible layers will be searched.
183
- - "any": All the layers will be searched.
184
-
181
+ - "any": All the layers will be searched.
182
+
185
183
  returns : {"first", "last", "all"}
186
184
  What will be returned in case that there are multiple layers/shapes.
187
-
185
+
188
186
  - "first": Only the first object will be returned.
189
187
  - "last": Only the last object will be returned.
190
188
  - "all": All the objects will be returned as a list.
191
-
189
+
192
190
  Returns
193
191
  -------
194
192
  ImgArray, Label, MarkerFrame or TrackFrame, np.ndarray, or list of one of them.
195
193
  impy object(s) that satisfies the options.
196
-
194
+
197
195
  Examples
198
196
  --------
199
197
  1. Get the front image.
200
-
198
+
201
199
  >>> ip.gui.get("image")
202
-
200
+
203
201
  2. Get all the selected images as a list.
204
-
202
+
205
203
  >>> ip.gui.get("image", layer_state="selected", returns="all")
206
-
204
+
207
205
  3. Get all the lines from the front visible shapes layer.
208
-
209
- >>> ip.gui.get("line", layer_state="visible")
210
-
211
- """
206
+
207
+ >>> ip.gui.get("line", layer_state="visible")
208
+
209
+ """
212
210
  if layer_state == "selected":
213
211
  layer_list = list(self.viewer.layers.selection)
214
212
  elif layer_state == "visible":
@@ -217,16 +215,16 @@ class napariViewers:
217
215
  layer_list = self.viewer.layers
218
216
  else:
219
217
  raise ValueError("`filter` must be 'selected', 'visible' or 'any'")
220
-
218
+
221
219
  kind = kind.capitalize()
222
220
  out = []
223
221
  if kind in ("Image", "Labels", "Points", "Shapes", "Tracks", "Vectors", "Surface"):
224
222
  layer_type = getattr(napari.layers, kind)
225
-
223
+
226
224
  for layer in layer_list:
227
225
  if isinstance(layer, layer_type):
228
226
  out.append(layer_to_impy_object(self.viewer, layer))
229
-
227
+
230
228
  elif kind in ("Line", "Rectangle", "Path", "Polygon", "Ellipse"):
231
229
  layer_type = napari.layers.Shapes
232
230
  shape_type = kind.lower()
@@ -236,10 +234,10 @@ class napariViewers:
236
234
  for s, t in zip(layer.data, layer.shape_type):
237
235
  if t == shape_type:
238
236
  out.append(s)
239
-
237
+
240
238
  else:
241
239
  raise TypeError(f"Cannot interpret type {kind}")
242
-
240
+
243
241
  try:
244
242
  if returns == "first":
245
243
  out = out[0]
@@ -247,19 +245,19 @@ class napariViewers:
247
245
  out = out[-1]
248
246
  elif returns != "all":
249
247
  raise ValueError("`returns` must be 'first', 'last' or 'all'")
250
-
248
+
251
249
  except IndexError:
252
250
  if layer_state != "none":
253
251
  msg = f"No {layer_state} {kind.lower()} found in the viewer layer list."
254
252
  else:
255
253
  msg = f"No {kind.lower()} found in the viewer layer list."
256
254
  raise IndexError(msg)
257
-
255
+
258
256
  return out
259
-
257
+
260
258
  def cursor_to_pixel(
261
- self,
262
- ref: "napari.layers.Image" | int | str | LabeledArray | LazyImgArray,
259
+ self,
260
+ ref: napari.layers.Image | int | str | LabeledArray | LazyImgArray,
263
261
  ndim: int = None
264
262
  ) -> np.ndarray:
265
263
  """
@@ -269,17 +267,17 @@ class napariViewers:
269
267
  Parameters
270
268
  ----------
271
269
  ref : napari.layers.Image, int, str, LabeledArray or LazyImgArray
272
- Reference layer or its identifier. To determine the reference layer, this parameter is interpreted in
270
+ Reference layer or its identifier. To determine the reference layer, this parameter is interpreted in
273
271
  different ways depending on its type:
274
272
 
275
- - napari.layers.Image ... layer itself
273
+ - napari.layers.Image ... layer itself
276
274
  - int ... the index of layer list
277
275
  - str ... the name of layer list
278
276
  - LabeledArray or LazyImgArray ... layer that has same object as data
279
-
277
+
280
278
  ndim : int, optional
281
279
  If specified, the last ndim coordinates will be returned.
282
-
280
+
283
281
  Returns
284
282
  -------
285
283
  np.ndarray
@@ -295,13 +293,13 @@ class napariViewers:
295
293
  break
296
294
  else:
297
295
  raise ValueError("Input image was not found in napari layer list.")
298
-
296
+
299
297
  elif isinstance(ref, (Image, Labels)):
300
298
  layer = ref
301
299
  else:
302
300
  raise TypeError("`layer` must be an image layer, int, str or impy's LabeledArray, "
303
301
  f"but got {type(ref)}")
304
-
302
+
305
303
  if not isinstance(layer, (Image, Labels)):
306
304
  raise TypeError(f"Layer {layer} is not an image or labels layer.")
307
305
 
@@ -309,7 +307,7 @@ class napariViewers:
309
307
  cursor_coords = np.array(self.viewer.cursor.position[-ndim:])
310
308
  pos = (cursor_coords - layer.translate)/layer.scale
311
309
  return (pos + 0.5).astype(np.int64)
312
-
310
+
313
311
  def add(self, obj: ImpyObject, **kwargs):
314
312
  """
315
313
  Add images, points, labels, tracks etc to viewer.
@@ -318,76 +316,76 @@ class napariViewers:
318
316
  ----------
319
317
  obj : ImpyObject
320
318
  Object to add.
321
- """
319
+ """
322
320
  import pandas as pd
323
321
  from dask import array as da
324
322
  from impy.frame import MarkerFrame, TrackFrame, PathFrame
325
-
323
+
326
324
  try:
327
325
  self.viewer.window.activate()
328
326
  except RuntimeError:
329
327
  # Restart viewer
330
328
  viewer = napari.Viewer(title=self._front_viewer)
331
329
  self._viewers[self._front_viewer] = viewer
332
-
330
+
333
331
  # Add image and its labels
334
332
  if isinstance(obj, LabeledArray):
335
333
  self._add_image(obj, **kwargs)
336
-
334
+
337
335
  # Add points
338
336
  elif isinstance(obj, MarkerFrame):
339
337
  add_points(self.viewer, obj, **kwargs)
340
-
338
+
341
339
  # Add labels
342
340
  elif isinstance(obj, Label):
343
341
  add_labels(self.viewer, obj, **kwargs)
344
-
342
+
345
343
  # Add tracks
346
344
  elif isinstance(obj, TrackFrame):
347
345
  add_tracks(self.viewer, obj, **kwargs)
348
-
346
+
349
347
  # Add path
350
348
  elif isinstance(obj, PathFrame):
351
349
  add_paths(self.viewer, obj, **kwargs)
352
-
350
+
353
351
  # Add a table
354
352
  elif isinstance(obj, (pd.DataFrame, PropArray)):
355
353
  self.add_table(obj, **kwargs)
356
-
354
+
357
355
  # Add a lazy-loaded image
358
356
  elif isinstance(obj, LazyImgArray):
359
357
  if obj.gb > Const["MAX_GB"] and self.viewer.dims.ndisplay == 3:
360
358
  raise MemoryError("Cannot send large files while the viewer is 3D mode.")
361
359
  add_dask(self.viewer, obj, **kwargs)
362
-
360
+
363
361
  # Add an array as an image
364
362
  elif type(obj) is np.ndarray:
365
363
  self._add_image(ip_array(obj))
366
-
364
+
367
365
  # Add an dask array as an image
368
366
  elif type(obj) is da.core.Array:
369
367
  self._add_image(ip_aslazy(obj))
370
-
368
+
371
369
  # Add an image from a path
372
370
  elif isinstance(obj, (str, Path)):
373
371
  viewer_imread(self.viewer, obj)
374
-
372
+
375
373
  # Add many objects of same type
376
374
  elif isinstance(obj, DataList):
377
375
  [self.add(each, **kwargs) for each in obj]
378
-
376
+
379
377
  # Add a RoiList object as a shapes
380
378
  elif type(obj).__name__ == "RoiList":
381
379
  add_rois(self.viewer, obj, **kwargs)
382
-
380
+
383
381
  # Add a Roi object as a shape
384
382
  elif hasattr(obj, "from_imagejroi"):
385
383
  add_rois(self.viewer, [obj], **kwargs)
386
-
384
+
387
385
  else:
388
386
  raise TypeError(f"Could not interpret type: {type(obj)}")
389
-
390
-
387
+
388
+
391
389
  def add_surface(
392
390
  self,
393
391
  image3d: LabeledArray,
@@ -403,11 +401,11 @@ class napariViewers:
403
401
  ----------
404
402
  image3d : LabeledArray
405
403
  3D image from which surface will be generated
406
- level, step_size, mask :
404
+ level, step_size, mask :
407
405
  Passed to ``skimage.measure.marching_cubes``
408
- """
406
+ """
409
407
  from skimage.measure import marching_cubes
410
- verts, faces, _, values = marching_cubes(image3d, level=level,
408
+ verts, faces, _, values = marching_cubes(image3d, level=level,
411
409
  step_size=step_size, mask=mask)
412
410
  scale = make_world_scale(image3d)
413
411
  name = f"[Surf]{image3d.name}"
@@ -417,8 +415,8 @@ class napariViewers:
417
415
  warnings.simplefilter("ignore")
418
416
  self.viewer.add_surface((verts, faces, values), **kw)
419
417
  return None
420
-
421
-
418
+
419
+
422
420
  def goto(self, **kwargs) -> tuple[int, ...]:
423
421
  """
424
422
  Change the current step of the viewer.
@@ -426,24 +424,24 @@ class napariViewers:
426
424
  Examples
427
425
  --------
428
426
  1. Go to t=3.
429
-
427
+
430
428
  >>> ip.gui.goto(t=3)
431
-
432
- 2. Go to t=3 and last z.
433
-
429
+
430
+ 2. Go to t=3 and last z.
431
+
434
432
  >>> ip.gui.goto(t=3, z=-1)
435
-
436
- """
433
+
434
+ """
437
435
  step = list(self.viewer.dims.current_step)
438
436
  for axis, ind in kwargs.items():
439
437
  i = self.axisof(axis)
440
438
  if ind < 0:
441
439
  ind = self.viewer.dims.nsteps[i] + ind # support minus indexing
442
440
  step[i] = min(max(int(ind), 0), self.viewer.dims.nsteps[i]-1) # between min/max
443
-
441
+
444
442
  self.viewer.dims.current_step = step
445
443
  return step
446
-
444
+
447
445
  def stepof(self, symbol: AxisLike) -> int:
448
446
  """
449
447
  Get the current step of certain axis.
@@ -452,13 +450,13 @@ class napariViewers:
452
450
  ----------
453
451
  symbol : AxisLike
454
452
  Axis symbol
455
- """
453
+ """
456
454
  i = self.axes.find(symbol)
457
455
  return self.viewer.dims.current_step[i]
458
456
 
459
457
  def axisof(self, symbol: AxisLike) -> int:
460
458
  return self.axes.find(symbol)
461
-
459
+
462
460
  def _add_image(self, img: LabeledArray, **kwargs):
463
461
  layer = add_labeledarray(self.viewer, img, **kwargs)
464
462
  if isinstance(layer, list):
@@ -468,30 +466,30 @@ class napariViewers:
468
466
  if img.labels is not None:
469
467
  add_labels(self.viewer, img.labels, name=name, metadata={"destination_image": img})
470
468
  return None
471
-
469
+
472
470
  def add_table(self, table: pd.DataFrame | dict[str, ArrayLike], **kwargs):
473
471
  from magicgui.widgets import Table
474
472
  table = Table(value=table)
475
473
  self.viewer.window.add_dock_widget(table, **kwargs)
476
474
  return table
477
-
475
+
478
476
  def add_image(self, *args, **kwargs):
479
477
  return self.viewer.add_image(*args, **kwargs)
480
-
478
+
481
479
  def add_shapes(self, *args, **kwargs):
482
480
  return self.viewer.add_shapes(*args, **kwargs)
483
-
481
+
484
482
  def add_surface(self, *args, **kwargs):
485
483
  return self.viewer.add_surface(*args, **kwargs)
486
-
484
+
487
485
  def add_points(self, *args, **kwargs):
488
486
  return self.viewer.add_points(*args, **kwargs)
489
-
487
+
490
488
  def add_labels(self, *args, **kwargs):
491
489
  return self.viewer.add_labels(*args, **kwargs)
492
-
490
+
493
491
  def add_vectors(self, *args, **kwargs):
494
492
  return self.viewer.add_vectors(*args, **kwargs)
495
-
493
+
496
494
  def add_tracks(self, *args, **kwargs):
497
495
  return self.viewer.add_tracks(*args, **kwargs)
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