impy-array 2.4.7__py3-none-any.whl → 2.4.8__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.
impy/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "2.4.7"
1
+ __version__ = "2.4.8"
2
2
  __author__ = "Hanjin Liu"
3
3
  __email__ = "liuhanjin-sc@g.ecc.u-tokyo.ac.jp"
4
4
 
impy/_const.py CHANGED
@@ -8,13 +8,13 @@ MAX_GB_LIMIT = memory.total / 2 * 1e-9
8
8
 
9
9
  class GlobalConstant(MutableMapping[str, Any]):
10
10
  _const: dict[str, Any]
11
-
11
+
12
12
  def __init__(self, **kwargs):
13
13
  object.__setattr__(self, "_const", dict(**kwargs))
14
-
14
+
15
15
  def __len__(self) -> int:
16
16
  return len(self._const)
17
-
17
+
18
18
  def __iter__(self):
19
19
  raise StopIteration
20
20
 
@@ -47,15 +47,15 @@ class GlobalConstant(MutableMapping[str, Any]):
47
47
  dask.config.set(scheduler=v)
48
48
  else:
49
49
  raise RuntimeError("Cannot set new keys.")
50
-
50
+
51
51
  self._const[k] = v
52
-
52
+
53
53
  __getattr__ = __getitem__
54
54
  __setattr__ = __setitem__
55
55
 
56
56
  def __delitem__(self, v):
57
57
  raise RuntimeError("Cannot delete any items.")
58
-
58
+
59
59
  def __repr__(self):
60
60
  return (
61
61
  f"""
@@ -65,12 +65,12 @@ class GlobalConstant(MutableMapping[str, Any]):
65
65
  SCHEDULER : {self['SCHEDULER']}
66
66
  """
67
67
  )
68
-
68
+
69
69
  def asdict(self) -> dict[str, Any]:
70
70
  return self._const.copy()
71
71
 
72
72
  Const = GlobalConstant(
73
- MAX_GB = MAX_GB_LIMIT/2,
73
+ MAX_GB = MAX_GB_LIMIT * 0.8,
74
74
  ID_AXIS = "N",
75
75
  RESOURCE = "numpy",
76
76
  SCHEDULER = "threads",
@@ -80,12 +80,12 @@ class SetConst:
80
80
  n_ongoing = 0
81
81
  _locked_keys: set[str] = set()
82
82
  _old_dict: dict[str, Any] = dict()
83
-
83
+
84
84
  def __init__(self, dict_: dict[str, Any] | None =None, **kwargs):
85
85
  dict_ = dict_ or {}
86
86
  dict_.update(kwargs)
87
87
  self._kwargs = dict_
88
-
88
+
89
89
  def __enter__(self):
90
90
  self.__class__.n_ongoing += 1
91
91
  if self.__class__.n_ongoing == 1:
impy/arrays/imgarray.py CHANGED
@@ -1,10 +1,12 @@
1
1
  from __future__ import annotations
2
2
  import warnings
3
+ from functools import partial
4
+ from itertools import product
5
+ from typing import TYPE_CHECKING, Literal, Sequence, Iterable, Callable, overload, Any
6
+
3
7
  import numpy as np
4
8
  from numpy.typing import DTypeLike
5
- from functools import partial
6
9
  from scipy import ndimage as ndi
7
- from typing import TYPE_CHECKING, Literal, Sequence, Iterable, Callable, overload, Any
8
10
 
9
11
  from impy.arrays.labeledarray import LabeledArray
10
12
  from impy.arrays.label import Label
@@ -3987,8 +3989,7 @@ class ImgArray(LabeledArray):
3987
3989
  upsample_factor: int = 10,
3988
3990
  max_shift: nDFloat | None = None,
3989
3991
  ) -> MarkerFrame:
3990
- """
3991
- Calculate yx-directional drift using the method equivalent to
3992
+ """Calculate yx-directional drift using the method equivalent to
3992
3993
  ``skimage.registration.phase_cross_correlation``.
3993
3994
 
3994
3995
  Parameters
@@ -4063,9 +4064,10 @@ class ImgArray(LabeledArray):
4063
4064
  dims: Dims = 2,
4064
4065
  update: bool = False,
4065
4066
  ) -> ImgArray:
4066
- """
4067
- Drift correction using iterative Affine translation. If translation vectors ``shift``
4068
- is not given, then it will be determined using ``track_drift`` method of ImgArray.
4067
+ """Drift correction using iterative Affine translation.
4068
+
4069
+ If translation vectors ``shift`` is not given, then it will be determined using
4070
+ ``track_drift`` method of ImgArray.
4069
4071
 
4070
4072
  Parameters
4071
4073
  ----------
@@ -4092,7 +4094,7 @@ class ImgArray(LabeledArray):
4092
4094
  Examples
4093
4095
  --------
4094
4096
  Drift correction of multichannel image using the first channel as the reference.
4095
- >>> img.drift_correction(ref=img["c=0"])
4097
+ >>> img.drift_correction(ref=img["c=0"])
4096
4098
  """
4097
4099
 
4098
4100
  if along is None:
@@ -4107,7 +4109,6 @@ class ImgArray(LabeledArray):
4107
4109
  elif not isinstance(ref, ImgArray):
4108
4110
  ref = self[ref]
4109
4111
  if ref.axes != [along] + dims:
4110
- from itertools import product
4111
4112
  _c_axes = complement_axes([along] + dims, str(ref.axes))
4112
4113
  fmt = slicer.get_formatter(_c_axes)
4113
4114
  out = np.empty_like(self)
@@ -3,7 +3,7 @@ import numpy as np
3
3
  from pathlib import Path
4
4
  import itertools
5
5
  from functools import partial
6
- from typing import TYPE_CHECKING, Any, Sequence, MutableMapping, Protocol
6
+ from typing import TYPE_CHECKING, Any, Literal, Sequence, MutableMapping, Protocol
7
7
  from warnings import warn
8
8
  from scipy import ndimage as ndi
9
9
 
@@ -23,7 +23,7 @@ from impy.array_api import xp
23
23
 
24
24
  if TYPE_CHECKING:
25
25
  from typing_extensions import Self
26
- from numpy.typing import ArrayLike, DTypeLike
26
+ from numpy.typing import ArrayLike, DTypeLike, NDArray
27
27
  from impy.frame import PathFrame
28
28
  from impy.roi import RoiList
29
29
 
@@ -401,10 +401,18 @@ class LabeledArray(MetaArray):
401
401
  out._set_info(self)
402
402
  return out
403
403
 
404
- def as_float(self) -> Self:
405
- if self.dtype == np.float32:
404
+ def as_float(self, *, depth: int = 32) -> Self:
405
+ if depth == 16:
406
+ dtype = np.float16
407
+ elif depth == 32:
408
+ dtype = np.float32
409
+ elif depth == 64:
410
+ dtype = np.float64
411
+ else:
412
+ raise ValueError(f"depth must be 16, 32, or 64, but got {depth}")
413
+ if self.dtype == dtype:
406
414
  return self
407
- out = self.value.astype(np.float32).view(self.__class__)
415
+ out = self.value.astype(dtype).view(self.__class__)
408
416
  out._set_info(self)
409
417
  return out
410
418
 
@@ -417,8 +425,12 @@ class LabeledArray(MetaArray):
417
425
  return self.as_uint16()
418
426
  elif dtype == "uint8":
419
427
  return self.as_uint8()
428
+ elif dtype == "float16":
429
+ return self.as_float(depth=16)
420
430
  elif dtype == "float32":
421
- return self.as_float()
431
+ return self.as_float(depth=32)
432
+ elif dtype == "float64":
433
+ return self.as_float(depth=64)
422
434
  elif dtype == "bool":
423
435
  return self.astype("bool")
424
436
  elif dtype == "float64":
@@ -576,6 +588,7 @@ class LabeledArray(MetaArray):
576
588
  *,
577
589
  order: int = 3,
578
590
  prefilter: bool | None = None,
591
+ how: Literal["pack", "equal"] = "pack",
579
592
  ) -> PropArray:
580
593
  """
581
594
  Measure line profile (kymograph) iteratively for every slice of image. This
@@ -590,7 +603,12 @@ class LabeledArray(MetaArray):
590
603
  `a = [[y0, x0], [y1, x1], ..., [yn, xn]]`
591
604
  b : array-like, optional
592
605
  Destination coordinate. If specified, `a` must be the source coordinate.
593
- {order}
606
+ {order}{prefilter}
607
+ how : "pack" or "equal", default "pack"
608
+ How to sample points on the line. "pack" means that the points are sampled
609
+ at 1-px interval from the start point. "equal" means that the points are
610
+ sampled equally at the interval larger but neareset to 1-px so that the
611
+ points covers the entire line.
594
612
 
595
613
  Returns
596
614
  -------
@@ -616,7 +634,12 @@ class LabeledArray(MetaArray):
616
634
  a = np.asarray(a, dtype=np.float32)
617
635
  _, ndim = a.shape
618
636
  seg = SegmentedLine(a)
619
- coords = seg.sample_points().T
637
+ if how == "pack":
638
+ coords = np.stack(seg.arange(), axis=0)
639
+ elif how == "equal":
640
+ coords = np.stack(seg.linspace(int(seg.length())), axis=0)
641
+ else:
642
+ raise ValueError(f"No option matches how={how}")
620
643
 
621
644
  if ndim == self.ndim:
622
645
  dims = self.axes
@@ -632,7 +655,11 @@ class LabeledArray(MetaArray):
632
655
  axes=c_axes+[new_axis], propname="reslice")
633
656
 
634
657
  out.set_scale(self)
635
- out.set_scale({new_axis: self.scale[dims[-1]] * seg.interv})
658
+ axis = self.axes[dims[-1]]
659
+ if how == "equal":
660
+ out.set_scale({new_axis: axis.scale * seg.interv}, unit=axis.unit)
661
+ else:
662
+ out.set_scale({new_axis: axis.scale}, unit=axis.unit)
636
663
  return out
637
664
 
638
665
  @_docs.write_docs
@@ -1576,31 +1603,61 @@ class SegmentedLine:
1576
1603
  dist = np.sqrt(np.sum(vec**2, axis=1))
1577
1604
  dist_sum = np.sum(dist)
1578
1605
  npoints = int(dist_sum)
1579
- interv = dist_sum / npoints
1606
+ self.interv = dist_sum / npoints
1580
1607
 
1581
- self.length = dist_sum
1582
1608
  self.vec = vec
1583
1609
  self.dist = dist
1584
1610
  self.nodes = nodes
1585
- self.interv = interv
1586
1611
 
1587
1612
  def sample_points(self) -> np.ndarray:
1588
1613
  res = 0
1589
1614
  out = [self.nodes[0:1]]
1590
1615
  npoints = 1
1616
+ interv = self.length() / int(self.length())
1591
1617
  for v, d, p in zip(self.vec, self.dist, self.nodes[:-1]):
1592
1618
  res0 = res
1593
- d_int, res = divmod(d + res, self.interv)
1594
- idx = self.interv*(np.arange(d_int) + 1) - res0
1619
+ d_int, res = divmod(d + res, interv)
1620
+ idx = interv * (np.arange(d_int) + 1) - res0
1595
1621
  xs = idx[:, np.newaxis] * v[np.newaxis]/d + p
1596
1622
  out.append(xs)
1597
1623
  npoints += xs.shape[0]
1598
1624
 
1599
- if npoints <= int(self.length):
1625
+ if npoints <= int(self.length()):
1600
1626
  out.append(self.nodes[-1:])
1601
1627
 
1602
1628
  return np.concatenate(out, axis=0)
1603
1629
 
1630
+ def length(self) -> np.float64:
1631
+ return np.sum(self.lengths())
1632
+
1633
+ def lengths(self) -> NDArray[np.float64]:
1634
+ return np.sqrt(np.sum(np.diff(self.nodes, axis=0) ** 2, axis=1))
1635
+
1636
+ def linspace(self, num: int) -> tuple[NDArray[np.float64], ...]:
1637
+ """Return a tuple of x and y coordinates of np.linspace along the line."""
1638
+ tnots = np.cumsum(
1639
+ np.concatenate([[0], self.lengths()], dtype=np.float64)
1640
+ )
1641
+ teval = np.linspace(0, tnots[-1], num)
1642
+ return tuple(
1643
+ np.interp(teval, tnots, self.nodes[:, i])
1644
+ for i in range(self.nodes.shape[1])
1645
+ )
1646
+
1647
+ def arange(
1648
+ self, step: float = 1.0
1649
+ ) -> tuple[NDArray[np.float64], NDArray[np.float64]]:
1650
+ tnots = np.cumsum(
1651
+ np.concatenate([[0], self.lengths()], dtype=np.float64)
1652
+ )
1653
+ length = tnots[-1]
1654
+ num, rem = divmod(length, step)
1655
+ teval = np.linspace(0, length - rem, int(num + 1))
1656
+ return tuple(
1657
+ np.interp(teval, tnots, self.nodes[:, i])
1658
+ for i in range(self.nodes.shape[1])
1659
+ )
1660
+
1604
1661
  def _count_list_depth(x) -> int:
1605
1662
  n = 0
1606
1663
  out = x
impy/arrays/lazy.py CHANGED
@@ -1612,10 +1612,18 @@ class LazyImgArray(AxesMixin):
1612
1612
  out._set_info(self)
1613
1613
  return out
1614
1614
 
1615
- def as_float(self) -> LazyImgArray:
1616
- if self.dtype == np.float32:
1615
+ def as_float(self, *, depth: int = 32) -> LazyImgArray:
1616
+ if depth == 16:
1617
+ dtype = np.float16
1618
+ elif depth == 32:
1619
+ dtype = np.float32
1620
+ elif depth == 64:
1621
+ dtype = np.float64
1622
+ else:
1623
+ raise ValueError(f"depth must be 16, 32, or 64, but got {depth}")
1624
+ if self.dtype == dtype:
1617
1625
  return self
1618
- out = self.value.astype(np.float32)
1626
+ out = self.value.astype(dtype)
1619
1627
  out = self.__class__(out)
1620
1628
  out._set_info(self)
1621
1629
  return out
@@ -1628,12 +1636,12 @@ class LazyImgArray(AxesMixin):
1628
1636
  return self.as_uint16()
1629
1637
  elif dtype == "uint8":
1630
1638
  return self.as_uint8()
1639
+ elif dtype == "float16":
1640
+ return self.as_float(depth=16)
1631
1641
  elif dtype == "float32":
1632
- return self.as_float()
1642
+ return self.as_float(depth=32)
1633
1643
  elif dtype == "float64":
1634
- warn("Data type float64 is not valid for images. It was converted to float32 instead",
1635
- UserWarning)
1636
- return self.as_float()
1644
+ return self.as_float(depth=64)
1637
1645
  elif dtype == "complex64":
1638
1646
  out = self.value.astype(np.complex64)
1639
1647
  out = self.__class__(out)
impy/core.py CHANGED
@@ -99,8 +99,7 @@ def array(
99
99
  axes: str = None,
100
100
  like: MetaArray | None = None,
101
101
  ) -> ImgArray:
102
- """
103
- make an ImgArray object, like ``np.array(x)``
102
+ """Make an ImgArray object, like ``np.array(x)``
104
103
 
105
104
  Parameters
106
105
  ----------
@@ -116,12 +115,7 @@ def array(
116
115
 
117
116
  """
118
117
  if isinstance(arr, np.ndarray) and dtype is None:
119
- if arr.dtype in (np.uint8, np.uint16, np.float32):
120
- dtype = arr.dtype
121
- elif arr.dtype.kind == "f":
122
- dtype = np.float32
123
- else:
124
- dtype = arr.dtype
118
+ dtype = arr.dtype
125
119
 
126
120
  axes, name = _normalize_params(axes, name, like)
127
121
 
@@ -150,8 +144,7 @@ def asarray(
150
144
  axes: str | None = None,
151
145
  like: MetaArray | None = None,
152
146
  ) -> ImgArray:
153
- """
154
- make an ImgArray object, like ``np.asarray(x)``
147
+ """Make an ImgArray object, like ``np.asarray(x)``
155
148
 
156
149
  Parameters
157
150
  ----------
@@ -296,9 +289,8 @@ def _inject_numpy_function(func: Callable[_P, Any | None]) -> Callable[_P, ImgAr
296
289
  return asarray(npfunc(*args, **kwargs), name=name, axes=axes, like=like)
297
290
 
298
291
  _func.__doc__ = (
299
- f"""
300
- impy version of numpy.{func.__name__}. This function has additional parameters ``axes``
301
- and ``name``. Original docstring follows.
292
+ f"""impy version of numpy.{func.__name__}. This function has additional
293
+ parameters ``axes`` and ``name``. Original docstring follows.
302
294
 
303
295
  Additional Parameters
304
296
  ---------------------
@@ -396,7 +388,7 @@ def gaussian_kernel(
396
388
  """
397
389
  if np.isscalar(sigma):
398
390
  sigma = (sigma,)*len(shape)
399
- g = gauss.GaussianParticle([(np.array(shape)-1)/2, sigma, peak, 0])
391
+ g = gauss.GaussianParticle([(np.array(shape) - 1) / 2, sigma, peak, 0])
400
392
  ker = g.generate(shape)
401
393
  ker = array(ker, name=name or "Gaussian-Kernel", axes=axes)
402
394
  if axes is None and ker.ndim == 3:
@@ -551,12 +543,12 @@ def imread(
551
543
  return _imread_stack(path, dtype=dtype, key=key, squeeze=squeeze)
552
544
  elif "*" in path:
553
545
  return _imread_glob(path, dtype=dtype, key=key, squeeze=squeeze)
554
- elif not os.path.exists(path):
546
+ elif not Path(path).exists():
555
547
  raise FileNotFoundError(f"No such file or directory: {path}")
556
548
 
557
549
  # read tif metadata
558
550
  if not is_memmap:
559
- size = os.path.getsize(path) / 2**30
551
+ size = Path(path).stat().st_size / 2**30
560
552
  if size > Const["MAX_GB"]:
561
553
  raise MemoryError(f"Too large {size:.2f} GB")
562
554
 
impy/io/_mrc.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from pathlib import Path
3
4
  from typing import TYPE_CHECKING
4
5
  import warnings
5
6
  import os
@@ -59,7 +60,13 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
59
60
 
60
61
  if img.dtype == "bool":
61
62
  img = img.astype(np.int8)
62
-
63
+ elif img.dtype == "float64":
64
+ warnings.warn(
65
+ "MRC format does not support float64. Converting to float32.",
66
+ UserWarning,
67
+ stacklevel=2,
68
+ )
69
+ img = img.astype(np.float32)
63
70
  if lazy:
64
71
  from dask import array as da
65
72
 
@@ -75,9 +82,10 @@ def _(path: str, img: ImpyArray, lazy: bool = False):
75
82
  # get voxel_size
76
83
  if img.axes not in ("zyx", "yx"):
77
84
  raise ImageAxesError(
78
- f"Can only save zyx- or yx- image as a mrc file, but image has {img.axes} axes."
79
- )
80
- if os.path.exists(path):
85
+ f"Can only save zyx- or yx- image as a mrc file, but image has {img.axes} "
86
+ "axes."
87
+ )
88
+ if Path(path).exists():
81
89
  with mrcfile.open(path, mode="r+") as mrc:
82
90
  mrc.set_data(img.value)
83
91
  mrc.voxel_size = voxel_size
@@ -98,13 +106,12 @@ _MRC_MODE = {
98
106
  }
99
107
 
100
108
  def _parse_mrcfile(mrc: MrcObject) -> ImageMetadata:
101
- ndim = len(mrc.voxel_size.item())
102
- if ndim == 3:
103
- axes = "zyx"
104
- elif ndim == 2:
109
+ if mrc.is_single_image():
105
110
  axes = "yx"
111
+ elif mrc.is_volume_stack():
112
+ axes = "tzyx"
106
113
  else:
107
- raise RuntimeError(f"ndim = {ndim} not supported")
114
+ axes = "zyx"
108
115
 
109
116
  scale = dict.fromkeys(axes, 1.0)
110
117
  for a in axes:
impy/io/_tiff.py CHANGED
@@ -14,7 +14,7 @@ from impy.utils.axesop import complement_axes
14
14
  if TYPE_CHECKING:
15
15
  from tifffile import TiffFile
16
16
 
17
- @IO.mark_reader(".tif", ".tiff")
17
+ @IO.mark_reader(".tif", ".tiff", ".lsm")
18
18
  def _(path: str, memmap: bool = False) -> ImageData:
19
19
  """The tif file reader."""
20
20
  from tifffile import TiffFile
@@ -28,7 +28,7 @@ def _(path: str, memmap: bool = False) -> ImageData:
28
28
 
29
29
  return ImageData.from_metadata(image, meta)
30
30
 
31
- @IO.mark_header_reader(".tif", ".tiff")
31
+ @IO.mark_header_reader(".tif", ".tiff", ".lsm")
32
32
  def _(path: str) -> ImageMetadata:
33
33
  """The tif header reader."""
34
34
  from tifffile import TiffFile
@@ -39,7 +39,7 @@ def _(path: str) -> ImageMetadata:
39
39
  return meta
40
40
 
41
41
 
42
- @IO.mark_writer(".tif", ".tiff")
42
+ @IO.mark_writer(".tif", ".tiff", ".lsm")
43
43
  def _(path: str, img: ImpyArray, lazy: bool = False):
44
44
  """The TIFF writer."""
45
45
  from tifffile import imwrite, memmap
@@ -103,7 +103,7 @@ def _parse_tifffile(tif: TiffFile) -> ImageMetadata:
103
103
  tags = {v.name: v.value for v in pagetag.values()}
104
104
 
105
105
  labels = ijmeta.get("Labels")
106
- scale = dict()
106
+ scale: dict[str, float] = {}
107
107
  dz = ijmeta.get("spacing", 1.0)
108
108
  scale_unit: dict[str, float] = {}
109
109
  try:
@@ -133,9 +133,9 @@ def _parse_tifffile(tif: TiffFile) -> ImageMetadata:
133
133
  _unit = ijmeta.pop("unit", None)
134
134
  for k in scale.keys():
135
135
  scale_unit[k] = _unit
136
- if tif.is_ome:
136
+ if ome_meta := tif.ome_metadata:
137
137
  try:
138
- xml = xml2dict(tif.ome_metadata)
138
+ xml = xml2dict(ome_meta)
139
139
  meta_data: dict[str, Any] = xml["OME"]["Image"]
140
140
  if isinstance(meta_data, list):
141
141
  meta_data = meta_data[0]
@@ -156,6 +156,14 @@ def _parse_tifffile(tif: TiffFile) -> ImageMetadata:
156
156
 
157
157
  except Exception:
158
158
  pass
159
+ if lsm_meta := tif.lsm_metadata:
160
+ scale_unit = "μm"
161
+ if voxel_size_x := lsm_meta.get("VoxelSizeX"):
162
+ scale["x"] = voxel_size_x * 1e6
163
+ if voxel_size_y := lsm_meta.get("VoxelSizeY"):
164
+ scale["y"] = voxel_size_y * 1e6
165
+ if voxel_size_z := lsm_meta.get("VoxelSizeZ"):
166
+ scale["z"] = voxel_size_z * 1e6
159
167
 
160
168
  return ImageMetadata(
161
169
  axes=axes,
@@ -188,7 +196,7 @@ def _get_ijmeta_from_img(img: ImpyArray, update_lut=True):
188
196
  info = {}
189
197
  metadata["Info"] = str(info)
190
198
  scale_unit = img.scale_unit
191
- if scale_unit[0] in ("μ", "\xb5", "\xc2"):
199
+ if scale_unit and scale_unit[0] in ("μ", "\xb5", "\xc2"):
192
200
  scale_unit = "\\u00B5" + scale_unit[1:]
193
201
  metadata["unit"] = scale_unit
194
202
 
impy/lazy/core.py CHANGED
@@ -108,8 +108,7 @@ def array(
108
108
  axes: str = None,
109
109
  like: MetaArray | None = None,
110
110
  ) -> LazyImgArray:
111
- """
112
- make an LazyImgArray object, like ``np.array(x)``
111
+ """Make an LazyImgArray object, like ``np.array(x)``
113
112
 
114
113
  Parameters
115
114
  ----------
@@ -144,12 +143,7 @@ def array(
144
143
  arr = da.asarray(arr)
145
144
 
146
145
  if isinstance(arr, np.ndarray) and dtype is None:
147
- if arr.dtype in (np.uint8, np.uint16, np.float32):
148
- dtype = arr.dtype
149
- elif arr.dtype.kind == "f":
150
- dtype = np.float32
151
- else:
152
- dtype = arr.dtype
146
+ dtype = arr.dtype
153
147
 
154
148
  axes, name = _normalize_params(axes, name, like)
155
149
 
@@ -172,8 +166,7 @@ def asarray(
172
166
  like: MetaArray | None = None,
173
167
  chunks="auto",
174
168
  ) -> LazyImgArray:
175
- """
176
- make an LazyImgArray object, like ``np.asarray(x)``
169
+ """Make an LazyImgArray object, like ``np.asarray(x)``
177
170
 
178
171
  Parameters
179
172
  ----------
impy/random.py CHANGED
@@ -127,7 +127,7 @@ class ImageGenerator:
127
127
  def standard_normal(
128
128
  self,
129
129
  size: int | tuple[int, ...] | None = None,
130
- dtype = None,
130
+ dtype=np.float32,
131
131
  *,
132
132
  axes: AxesLike | None = None,
133
133
  name: str | None = None,
@@ -142,7 +142,7 @@ class ImageGenerator:
142
142
  def standard_exponential(
143
143
  self,
144
144
  size: int | tuple[int, ...] | None = None,
145
- dtype = None,
145
+ dtype=np.float32,
146
146
  method: Literal["zig", "inv"] = None,
147
147
  *,
148
148
  axes: AxesLike | None = None,
@@ -159,7 +159,7 @@ class ImageGenerator:
159
159
  def random(
160
160
  self,
161
161
  size: int | tuple[int, ...] | None = None,
162
- dtype = None,
162
+ dtype=np.float32,
163
163
  *,
164
164
  axes: AxesLike | None = None,
165
165
  name: str | None = None,
@@ -184,7 +184,7 @@ class ImageGenerator:
184
184
  ) -> ImgArray:
185
185
  size, name, axes = _normalize_like(size, name, axes, like)
186
186
 
187
- arr = self._rng.normal(loc=loc, scale=scale, size=size)
187
+ arr = self._rng.normal(loc=loc, scale=scale, size=size).astype(np.float32)
188
188
  if np.isscalar(arr):
189
189
  return arr
190
190
  return asarray(xp.asnumpy(arr), axes=axes, name=name)
impy/utils/gauss.py CHANGED
@@ -19,7 +19,10 @@ def diagonal_gaussian(r, *params):
19
19
  ndim = len(params[:-2])//2
20
20
  mu = params[:ndim]
21
21
  sg = params[ndim:-2]
22
- z_value = np.array([(x0 - mu0)/sg0 for x0, mu0, sg0 in zip(r, mu, sg)])
22
+ z_value = np.array(
23
+ [(x0 - mu0) / sg0 for x0, mu0, sg0 in zip(r, mu, sg)],
24
+ dtype=np.float32
25
+ )
23
26
  return a * np.exp(-np.sum(z_value**2, axis=0) / 2) + b
24
27
 
25
28
  class Gaussian:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: impy-array
3
- Version: 2.4.7
3
+ Version: 2.4.8
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>
@@ -131,6 +131,7 @@ img_prj.imsave("image_max.tif") # Save in the same place. Don't spend tim
131
131
  `impy` automatically chooses the proper reader/writer according to the extension.
132
132
 
133
133
  - Tiff file (".tif", ".tiff")
134
+ - LSM file (".lsm")
134
135
  - MRC file (".mrc", ".rec", ".st", ".map", ".map.gz")
135
136
  - Zarr file (".zarr")
136
137
  - ND2 file (".nd2")
@@ -1,22 +1,22 @@
1
- impy/__init__.py,sha256=ElW_q_sd5NE1DWtX7zciQLcgl47n3a55WpQwq2ChVLk,1638
1
+ impy/__init__.py,sha256=caLalIZHTPzZHRUtqTEO4bT5iBHCcz_FNVftU3Amqyg,1638
2
2
  impy/__main__.py,sha256=BAQkQ4X8EFo42pbNx__EqpZ5KL4MTfTUWsVbJIQF0O0,4974
3
- impy/_const.py,sha256=XFkgkyqs_clQJDqr2vdh5rCyfM83iMFChOLJjwNWHtM,3736
3
+ impy/_const.py,sha256=uNHxxY5ltZuOsJWpwlBWFmUM0QfMgIk5WODqlHuBomo,3700
4
4
  impy/_types.py,sha256=gO4l0hx9qxe6eI0PyC4ukW3k4IYxCEZ9gT-rQ3jj3zU,808
5
5
  impy/array_api.py,sha256=9suP_Wck9maSiEa5qK6aZrCfaky6xhCMfIRcc9WuIs8,5585
6
6
  impy/binder.py,sha256=CTMb11g6uYDVVQV5Wtef865IO0G2V3vGXc8SiGYRD5k,9651
7
7
  impy/collections.py,sha256=2e55bLjZN7W4LFUCkyxekcDfLwZodMaU4JG5NQ3RS54,10946
8
- impy/core.py,sha256=UcMY7vQpp9l1CW_hukexqx92RZcEBWR48Ce_bVrQv0U,25809
8
+ impy/core.py,sha256=itTwflodeyUJf5A4mK-XyrrQ1TGiFz0QU4w8Eel5iFg,25615
9
9
  impy/correlation.py,sha256=Yw1T_0eL9FmsMcnCysc49oRJQMn8ho5z9bAzNg5i59Y,28232
10
- impy/random.py,sha256=RJZAgXp3gkOcCsKbAbuMI1pDdA4_atY3mausFxPNWpk,6973
10
+ impy/random.py,sha256=c9zlFn8M1ugZyfYlEVOqg0u4DGHS-EnnyrKfjPXOaxU,7004
11
11
  impy/roi.py,sha256=p9ttjBl5SGHHXj0xg5UjPlg_V9cY3MnNZxFfYIjTYsg,14164
12
12
  impy/arrays/__init__.py,sha256=IHpTBIJysomS64rOZsv960YBmM1vc4M-asTSs1OJBWg,454
13
13
  impy/arrays/_imshow.py,sha256=6mJ_PDqmE4UZO9e9SUgyY_YrzQdR2QKlTG7KF_aC_tI,6949
14
14
  impy/arrays/axesmixin.py,sha256=9PK6kMZAfNVipTL65aF5-yR3qt2fy4ATl1OACXLYrAE,10596
15
15
  impy/arrays/big.py,sha256=tHNijyPgyIfTltLP3hQwZdHOpSX3IwG5DHPamajZ8Kg,2745
16
- impy/arrays/imgarray.py,sha256=MxPVVdxnsJDqNVawSykNkFr2y6Cb1ESVYeCzAQXzrN4,159129
16
+ impy/arrays/imgarray.py,sha256=Rg1HVIWE1JwCQbDpRTxQb89HoF77gxvXVOqZh6mY5i0,159103
17
17
  impy/arrays/label.py,sha256=l0SZXcZxU8qwUgj0QZPZ32XsNaoBtenlrn6hNR03SPI,6406
18
- impy/arrays/labeledarray.py,sha256=ZbwgP1Fk-lzFckQ12aQO7QnjNMxpmn_y6E3j3DMLCl0,57081
19
- impy/arrays/lazy.py,sha256=hYTZeaW6HEq0CgPcpfqLcLWSpBrJli6ZTN_ddH_56ro,59902
18
+ impy/arrays/labeledarray.py,sha256=vbWUONnMBOXwLZBHlO2fjl9zqF1nljVdq1y0EFc2ias,59456
19
+ impy/arrays/lazy.py,sha256=wBjWCeCHZpx5x1Xb9RFtyKhrMIeDeqBhSw3FkSA8b3E,60145
20
20
  impy/arrays/phasearray.py,sha256=IojWaNs5sEujn6Lhgqe00H0xF-4CZEFWt5cVW6U_DWQ,13981
21
21
  impy/arrays/specials.py,sha256=4sNg_zeJUce_rwnasPoyL2eZ0-gx_4Z-KwitmLB4a5k,7896
22
22
  impy/arrays/tiled.py,sha256=T44sS6v1Ovln1z1g61Eg8irgZR1Jmpb6BCY3nS6TmDE,9400
@@ -44,28 +44,28 @@ impy/axes/_slicer.py,sha256=Ts4m9V3PBlEb3xeHd6j1XdMEb1SwYGbBF5rnC9WWYZE,2657
44
44
  impy/frame/__init__.py,sha256=Z4XfXzFSDq49tMrVoeYx1ThnHyw43iLVSVcte6b6-as,65
45
45
  impy/frame/frames.py,sha256=7NxDeuaG8CxzMnzczarmLz6ANBpl1tZIhn8KwdvBYg8,12450
46
46
  impy/io/__init__.py,sha256=wp1EOl0O6anbkxpsh_lW2V898l-UPIKiOEkLw1q5r-I,303
47
- impy/io/_mrc.py,sha256=DTWVpRiG2aUd-nlheyAOl5uILfrC0nYnX8bdVRyeUZ8,3392
47
+ impy/io/_mrc.py,sha256=JiPIKar62GhMlZ8SRVbSPcLBbamdQ_2WfuG1_abI7Xg,3611
48
48
  impy/io/_nd2.py,sha256=Squ8-wbCquJ8WfROEUZka26jrCkNNE24OTg_ottY7IY,1380
49
49
  impy/io/_npy.py,sha256=G6fnjA2RkV7ohFV-R1-TA6o9FjdfcTBwLiccfYj-iVo,2222
50
50
  impy/io/_registry.py,sha256=xAD6M46uJhEm9aFO_B0ZFsvRAMNnfXPRd4fPz_awaJI,10251
51
- impy/io/_tiff.py,sha256=p2u1c0qx0wwcWQQhPXHy6fWpLkPHNeZYn3aMvCcyg5Y,6096
51
+ impy/io/_tiff.py,sha256=kfRB6H-fKBk-lrv_y6tY2fNbG_BEcPm2Ja41-0EtZ_8,6528
52
52
  impy/io/_utils.py,sha256=HHyuVqds52pod4Y-CyRG4FVBmonQVBm7OAFj4QqhRCw,3604
53
53
  impy/io/_zarr.py,sha256=Nfr5VJ3DzKN5d7nYoq_ZG9AG2GIDWHYJ33LpG9SwGcs,1336
54
54
  impy/lazy/__init__.py,sha256=hRjpE2zCy5qDAr_27imwRM9J0C7q-a_b5wfC3ux8ZLE,59
55
- impy/lazy/core.py,sha256=_B-ELfmy8dMoMNFiAyb7vtmravJEjtAHF-AxtwPCnzs,9828
55
+ impy/lazy/core.py,sha256=8pU0_T6IAN1rUNc7EbdORz2vqof0bFuUHQ7aJGztW7s,9637
56
56
  impy/lazy/random.py,sha256=2rwHRsHPOvi8tI9kTtGuZ5SzN0MA7yn-30bZSvHeLVc,7713
57
57
  impy/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
58
  impy/utils/axesop.py,sha256=c86XdNlUBFLrwHhAT2j0eELxopNe2QEVaNeOQhXr2do,3076
59
59
  impy/utils/deco.py,sha256=lItN0UdadZsjI9eW3fI402k7DNR9jcnD6ZgjdkYsDdg,5946
60
- impy/utils/gauss.py,sha256=_jvmaUYSRB8KvX9Qp36rhNaNw9lllf68g_43wshpAMo,4713
60
+ impy/utils/gauss.py,sha256=a5C-Ig3aX8SyjqLuQ8VwdjQHdbkNC0LAiKSikTBXZtU,4758
61
61
  impy/utils/misc.py,sha256=zV_NeqEaiTW4Rki5fqWfspQjczRaoTJ5MxTOUx6qstY,622
62
62
  impy/utils/slicer.py,sha256=otDrizWdzoUjFUMlsha0zNFSS4TkgAmLPOAotaTVaUA,4316
63
63
  impy/utils/utilcls.py,sha256=3Td9G2ZkU4C0BiW2LH0sq7RBjdco_BtyxNr-s-seLhs,437
64
64
  impy/viewer/__init__.py,sha256=MH-jhpFxP8JVJwUzbKMLRhhWSEYavVHuik9uOS3dDNU,292
65
65
  impy/viewer/utils.py,sha256=_RWV9LePbmYeC8qRBUBf3qG70BaLOndlzRLcvUYgTtE,12248
66
66
  impy/viewer/viewer.py,sha256=Sfq-obSLoHkBkIW0NDWCxEEaX7-YsC4ifAJ-nxpvJws,17632
67
- impy_array-2.4.7.dist-info/METADATA,sha256=pQoD1_kxoBzLFncPKdriWz4-mLvI2DUt_jo3u7Pl0CA,7547
68
- impy_array-2.4.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
69
- impy_array-2.4.7.dist-info/entry_points.txt,sha256=reyrgy4odXvi1CcPOIIyRYBmsNGG2tO7ZkFOdG5CBkU,44
70
- impy_array-2.4.7.dist-info/licenses/LICENSE,sha256=rpxKafH9r42sxLLYYB5VbZBHOdtYeLuYJjVU1LBwrxk,1546
71
- impy_array-2.4.7.dist-info/RECORD,,
67
+ impy_array-2.4.8.dist-info/METADATA,sha256=PlwAqwu-GA82Idy3iz7sLzdrS47qkWGXoiTfzs7lqAY,7567
68
+ impy_array-2.4.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
69
+ impy_array-2.4.8.dist-info/entry_points.txt,sha256=reyrgy4odXvi1CcPOIIyRYBmsNGG2tO7ZkFOdG5CBkU,44
70
+ impy_array-2.4.8.dist-info/licenses/LICENSE,sha256=rpxKafH9r42sxLLYYB5VbZBHOdtYeLuYJjVU1LBwrxk,1546
71
+ impy_array-2.4.8.dist-info/RECORD,,