phasorpy 0.3__cp313-cp313-win_arm64.whl → 0.5__cp313-cp313-win_arm64.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.
phasorpy/plot.py CHANGED
@@ -11,14 +11,17 @@ from __future__ import annotations
11
11
  __all__ = [
12
12
  'PhasorPlot',
13
13
  'PhasorPlotFret',
14
+ 'plot_histograms',
15
+ 'plot_image',
14
16
  'plot_phasor',
15
17
  'plot_phasor_image',
16
- 'plot_signal_image',
17
18
  'plot_polar_frequency',
19
+ 'plot_signal_image',
18
20
  ]
19
21
 
20
22
  import math
21
23
  import os
24
+ import warnings
22
25
  from collections.abc import Sequence
23
26
  from typing import TYPE_CHECKING
24
27
 
@@ -43,6 +46,7 @@ from ._phasorpy import _intersection_circle_circle, _intersection_circle_line
43
46
  from ._utils import (
44
47
  dilate_coordinates,
45
48
  parse_kwargs,
49
+ parse_signal_axis,
46
50
  phasor_from_polar_scalar,
47
51
  phasor_to_polar_scalar,
48
52
  sort_coordinates,
@@ -74,7 +78,7 @@ class PhasorPlot:
74
78
  Parameters
75
79
  ----------
76
80
  allquadrants : bool, optional
77
- Show all quandrants of phasor space.
81
+ Show all quadrants of phasor space.
78
82
  By default, only the first quadrant with universal semicircle is shown.
79
83
  ax : matplotlib axes, optional
80
84
  Matplotlib axes used for plotting.
@@ -82,7 +86,7 @@ class PhasorPlot:
82
86
  frequency : float, optional
83
87
  Laser pulse or modulation frequency in MHz.
84
88
  grid : bool, optional, default: True
85
- Display polar grid or semicircle.
89
+ Display polar grid or universal semicircle.
86
90
  **kwargs
87
91
  Additional properties to set on `ax`.
88
92
 
@@ -217,10 +221,10 @@ class PhasorPlot:
217
221
  /,
218
222
  fmt: str = 'o',
219
223
  *,
220
- label: str | Sequence[str] | None = None,
224
+ label: Sequence[str] | None = None,
221
225
  **kwargs: Any,
222
226
  ) -> list[Line2D]:
223
- """Plot imag versus real coordinates as markers and/or lines.
227
+ """Plot imaginary versus real coordinates as markers or lines.
224
228
 
225
229
  Parameters
226
230
  ----------
@@ -232,7 +236,7 @@ class PhasorPlot:
232
236
  Must be of same shape as `real`.
233
237
  fmt : str, optional, default: 'o'
234
238
  Matplotlib style format string.
235
- label : str or sequence of str, optional
239
+ label : sequence of str, optional
236
240
  Plot label.
237
241
  May be a sequence if phasor coordinates are two dimensional arrays.
238
242
  **kwargs
@@ -285,7 +289,7 @@ class PhasorPlot:
285
289
  /,
286
290
  **kwargs: Any,
287
291
  ) -> tuple[NDArray[Any], NDArray[Any], NDArray[Any]]:
288
- """Return 2D histogram of imag versus real coordinates."""
292
+ """Return two-dimensional histogram of imag versus real coordinates."""
289
293
  update_kwargs(kwargs, range=self._limits)
290
294
  (xmin, xmax), (ymin, ymax) = kwargs['range']
291
295
  assert xmax > xmin and ymax > ymin
@@ -318,7 +322,7 @@ class PhasorPlot:
318
322
  /,
319
323
  **kwargs: Any,
320
324
  ) -> None:
321
- """Plot 2D histogram of imag versus real coordinates.
325
+ """Plot two-dimensional histogram of imag versus real coordinates.
322
326
 
323
327
  Parameters
324
328
  ----------
@@ -368,7 +372,9 @@ class PhasorPlot:
368
372
  and :py:meth:`matplotlib.axes.Axes.contour`.
369
373
 
370
374
  """
371
- update_kwargs(kwargs, cmap='Blues', norm='log')
375
+ if 'cmap' not in kwargs and 'colors' not in kwargs:
376
+ kwargs['cmap'] = 'Blues'
377
+ update_kwargs(kwargs, norm='log')
372
378
  kwargs_hist2d = parse_kwargs(
373
379
  kwargs, 'bins', 'range', 'density', 'weights'
374
380
  )
@@ -968,9 +974,9 @@ class PhasorPlotFret(PhasorPlot):
968
974
  acceptor_lifetime : array_like
969
975
  Lifetime of acceptor in ns.
970
976
  fret_efficiency : array_like, optional, default 0
971
- FRET efficiency in range [0..1].
972
- donor_freting : array_like, optional, default 1
973
- Fraction of donors participating in FRET. Range [0..1].
977
+ FRET efficiency in range [0, 1].
978
+ donor_fretting : array_like, optional, default 1
979
+ Fraction of donors participating in FRET. Range [0, 1].
974
980
  donor_bleedthrough : array_like, optional, default 0
975
981
  Weight of donor fluorescence in acceptor channel
976
982
  relative to fluorescence of fully sensitized acceptor.
@@ -1021,7 +1027,7 @@ class PhasorPlotFret(PhasorPlot):
1021
1027
  _donor_lifetime_slider: Slider
1022
1028
  _acceptor_lifetime_slider: Slider
1023
1029
  _fret_efficiency_slider: Slider
1024
- _donor_freting_slider: Slider
1030
+ _donor_fretting_slider: Slider
1025
1031
  _donor_bleedthrough_slider: Slider
1026
1032
  _acceptor_bleedthrough_slider: Slider
1027
1033
  _acceptor_background_slider: Slider
@@ -1052,7 +1058,7 @@ class PhasorPlotFret(PhasorPlot):
1052
1058
  donor_lifetime: float = 4.2,
1053
1059
  acceptor_lifetime: float = 3.0,
1054
1060
  fret_efficiency: float = 0.5,
1055
- donor_freting: float = 1.0,
1061
+ donor_fretting: float = 1.0,
1056
1062
  donor_bleedthrough: float = 0.0,
1057
1063
  acceptor_bleedthrough: float = 0.0,
1058
1064
  acceptor_background: float = 0.0,
@@ -1102,7 +1108,7 @@ class PhasorPlotFret(PhasorPlot):
1102
1108
  frequency,
1103
1109
  donor_lifetime,
1104
1110
  fret_efficiency=self._fret_efficiencies,
1105
- donor_freting=donor_freting,
1111
+ donor_fretting=donor_fretting,
1106
1112
  donor_background=donor_background,
1107
1113
  background_real=background_real,
1108
1114
  background_imag=background_imag,
@@ -1115,7 +1121,7 @@ class PhasorPlotFret(PhasorPlot):
1115
1121
  donor_lifetime,
1116
1122
  acceptor_lifetime,
1117
1123
  fret_efficiency=self._fret_efficiencies,
1118
- donor_freting=donor_freting,
1124
+ donor_fretting=donor_fretting,
1119
1125
  donor_bleedthrough=donor_bleedthrough,
1120
1126
  acceptor_bleedthrough=acceptor_bleedthrough,
1121
1127
  acceptor_background=acceptor_background,
@@ -1134,7 +1140,7 @@ class PhasorPlotFret(PhasorPlot):
1134
1140
  )
1135
1141
  self._acceptor_semicircle_line = lines[0]
1136
1142
 
1137
- if donor_freting < 1.0 and donor_background == 0.0:
1143
+ if donor_fretting < 1.0 and donor_background == 0.0:
1138
1144
  lines = self.line(
1139
1145
  [donor_real, donor_fret_real],
1140
1146
  [donor_imag, donor_fret_imag],
@@ -1284,18 +1290,18 @@ class PhasorPlotFret(PhasorPlot):
1284
1290
  )
1285
1291
  self._fret_efficiency_slider.on_changed(self._on_changed)
1286
1292
 
1287
- self._donor_freting_slider = Slider(
1293
+ self._donor_fretting_slider = Slider(
1288
1294
  ax=axes[6],
1289
- label='Donors FRETing ',
1295
+ label='Donors fretting ',
1290
1296
  valfmt=' %.2f',
1291
1297
  valmin=0.0,
1292
1298
  valmax=1.0,
1293
1299
  valstep=0.01,
1294
- valinit=donor_freting,
1300
+ valinit=donor_fretting,
1295
1301
  # facecolor='tab:green',
1296
1302
  handle_style={'edgecolor': 'tab:green'},
1297
1303
  )
1298
- self._donor_freting_slider.on_changed(self._on_changed)
1304
+ self._donor_fretting_slider.on_changed(self._on_changed)
1299
1305
 
1300
1306
  self._donor_bleedthrough_slider = Slider(
1301
1307
  ax=axes[5],
@@ -1397,7 +1403,7 @@ class PhasorPlotFret(PhasorPlot):
1397
1403
  donor_lifetime = self._donor_lifetime_slider.val
1398
1404
  acceptor_lifetime = self._acceptor_lifetime_slider.val
1399
1405
  fret_efficiency = self._fret_efficiency_slider.val
1400
- donor_freting = self._donor_freting_slider.val
1406
+ donor_fretting = self._donor_fretting_slider.val
1401
1407
  donor_bleedthrough = self._donor_bleedthrough_slider.val
1402
1408
  acceptor_bleedthrough = self._acceptor_bleedthrough_slider.val
1403
1409
  acceptor_background = self._acceptor_background_slider.val
@@ -1419,7 +1425,7 @@ class PhasorPlotFret(PhasorPlot):
1419
1425
  frequency,
1420
1426
  donor_lifetime,
1421
1427
  fret_efficiency=self._fret_efficiencies,
1422
- donor_freting=donor_freting,
1428
+ donor_fretting=donor_fretting,
1423
1429
  donor_background=donor_background,
1424
1430
  background_real=background_real,
1425
1431
  background_imag=background_imag,
@@ -1432,7 +1438,7 @@ class PhasorPlotFret(PhasorPlot):
1432
1438
  donor_lifetime,
1433
1439
  acceptor_lifetime,
1434
1440
  fret_efficiency=self._fret_efficiencies,
1435
- donor_freting=donor_freting,
1441
+ donor_fretting=donor_fretting,
1436
1442
  donor_bleedthrough=donor_bleedthrough,
1437
1443
  acceptor_bleedthrough=acceptor_bleedthrough,
1438
1444
  acceptor_background=acceptor_background,
@@ -1448,7 +1454,7 @@ class PhasorPlotFret(PhasorPlot):
1448
1454
  else:
1449
1455
  self._donor_background_line.set_data([0.0, 0.0], [0.0, 0.0])
1450
1456
 
1451
- if donor_freting < 1.0 and donor_background == 0.0:
1457
+ if donor_fretting < 1.0 and donor_background == 0.0:
1452
1458
  self._donor_donor_line.set_data(
1453
1459
  [donor_real, donor_fret_real],
1454
1460
  [donor_imag, donor_fret_imag],
@@ -1718,7 +1724,7 @@ def plot_phasor_image(
1718
1724
  percentile : float, optional
1719
1725
  The (q, 100-q) percentiles of image data are covered by colormaps.
1720
1726
  By default, the complete value range of `mean` is covered,
1721
- for `real` and `imag` the range [-1..1].
1727
+ for `real` and `imag` the range [-1, 1].
1722
1728
  title : str, optional
1723
1729
  Figure title.
1724
1730
  show : bool, optional, default: True
@@ -1858,9 +1864,10 @@ def plot_signal_image(
1858
1864
  signal: ArrayLike,
1859
1865
  /,
1860
1866
  *,
1861
- axis: int | None = None,
1867
+ axis: int | str | None = None,
1862
1868
  percentile: float | Sequence[float] | None = None,
1863
1869
  title: str | None = None,
1870
+ xlabel: str | None = None,
1864
1871
  show: bool = True,
1865
1872
  **kwargs: Any,
1866
1873
  ) -> None:
@@ -1876,15 +1883,18 @@ def plot_signal_image(
1876
1883
  ----------
1877
1884
  signal : array_like
1878
1885
  Image stack. Must be three or more dimensional.
1879
- axis : int, optional, default: -1
1886
+ axis : int or str, optional
1880
1887
  Axis over which phasor coordinates would be computed.
1881
- The default is the last axis (-1).
1888
+ By default, the 'H' or 'C' axes if signal contains such dimension
1889
+ names, else the last axis (-1).
1882
1890
  percentile : float or [float, float], optional
1883
1891
  The [q, 100-q] percentiles of image data are covered by colormaps.
1884
1892
  By default, the complete value range of `mean` is covered,
1885
- for `real` and `imag` the range [-1..1].
1893
+ for `real` and `imag` the range [-1, 1].
1886
1894
  title : str, optional
1887
1895
  Figure title.
1896
+ xlabel : str, optional
1897
+ Label of axis over which phasor coordinates would be computed.
1888
1898
  show : bool, optional, default: True
1889
1899
  Display figure.
1890
1900
  **kwargs
@@ -1899,13 +1909,22 @@ def plot_signal_image(
1899
1909
  """
1900
1910
  # TODO: add option to separate channels?
1901
1911
  # TODO: add option to plot non-images?
1912
+
1913
+ axis, axis_label = parse_signal_axis(signal, axis)
1914
+ if (
1915
+ axis_label
1916
+ and hasattr(signal, 'coords')
1917
+ and axis_label in signal.coords
1918
+ ):
1919
+ axis_coords = signal.coords[axis_label]
1920
+ else:
1921
+ axis_coords = None
1922
+
1902
1923
  update_kwargs(kwargs, interpolation='nearest')
1903
1924
  signal = numpy.asarray(signal)
1904
1925
  if signal.ndim < 3:
1905
1926
  raise ValueError(f'not an image stack {signal.ndim=} < 3')
1906
1927
 
1907
- if axis is None:
1908
- axis = -1
1909
1928
  axis %= signal.ndim
1910
1929
 
1911
1930
  # for MyPy
@@ -1922,8 +1941,18 @@ def plot_signal_image(
1922
1941
  axes = list(range(signal.ndim))
1923
1942
  del axes[axis]
1924
1943
  ax = fig.add_subplot(gs[0, 1])
1925
- ax.set_title(f'mean, axis {axis}')
1926
- ax.plot(numpy.nanmean(signal, axis=tuple(axes)))
1944
+
1945
+ if axis_coords is not None:
1946
+ ax.set_title(f'{axis=} {axis_label!r}')
1947
+ ax.plot(axis_coords, numpy.nanmean(signal, axis=tuple(axes)))
1948
+ else:
1949
+ ax.set_title(f'{axis=}')
1950
+ ax.plot(numpy.nanmean(signal, axis=tuple(axes)))
1951
+
1952
+ ax.set_ylim(kwargs.get('vmin', None), kwargs.get('vmax', None))
1953
+
1954
+ if xlabel is not None:
1955
+ ax.set_xlabel(xlabel)
1927
1956
 
1928
1957
  # image
1929
1958
  axes = list(sorted(axes[:-2] + [axis]))
@@ -1934,12 +1963,164 @@ def plot_signal_image(
1934
1963
  percentile=percentile,
1935
1964
  shrink=0.5,
1936
1965
  title='mean',
1966
+ **kwargs,
1937
1967
  )
1938
1968
 
1939
1969
  if show:
1940
1970
  pyplot.show()
1941
1971
 
1942
1972
 
1973
+ def plot_image(
1974
+ *images: ArrayLike,
1975
+ percentile: float | None = None,
1976
+ columns: int | None = None,
1977
+ title: str | None = None,
1978
+ labels: Sequence[str | None] | None = None,
1979
+ show: bool = True,
1980
+ **kwargs: Any,
1981
+ ) -> None:
1982
+ """Plot images.
1983
+
1984
+ Parameters
1985
+ ----------
1986
+ *images : array_like
1987
+ Images to be plotted. Must be two or more dimensional.
1988
+ The last two axes are assumed to be the image axes.
1989
+ Other axes are averaged for display.
1990
+ Three-dimensional images with last axis size of three or four
1991
+ are plotted as RGB(A) images.
1992
+ percentile : float, optional
1993
+ The (q, 100-q) percentiles of image data are covered by colormaps.
1994
+ By default, the complete value range is covered.
1995
+ Does not apply to RGB images.
1996
+ columns : int, optional
1997
+ Number of columns in figure.
1998
+ By default, up to four columns are used.
1999
+ title : str, optional
2000
+ Figure title.
2001
+ labels : sequence of str, optional
2002
+ Labels for each image.
2003
+ show : bool, optional, default: True
2004
+ Display figure.
2005
+ **kwargs
2006
+ Additional arguments passed to :func:`matplotlib.pyplot.imshow`.
2007
+
2008
+ Raises
2009
+ ------
2010
+ ValueError
2011
+ Percentile is out of range.
2012
+
2013
+ """
2014
+ update_kwargs(
2015
+ kwargs, interpolation='nearest', location='right', shrink=0.5
2016
+ )
2017
+ cmap = kwargs.pop('cmap', None)
2018
+ figsize = kwargs.pop('figsize', None)
2019
+ subplot_kw = kwargs.pop('subplot_kw', {})
2020
+ location = kwargs['location']
2021
+ allrgb = True
2022
+
2023
+ arrays = []
2024
+ shape = [1, 1]
2025
+ for image in images:
2026
+ image = numpy.asarray(image)
2027
+ if image.ndim < 2:
2028
+ raise ValueError(f'not an image {image.ndim=} < 2')
2029
+ if image.ndim == 3 and image.shape[2] in {3, 4}:
2030
+ # RGB(A)
2031
+ pass
2032
+ else:
2033
+ allrgb = False
2034
+ image = image.reshape(-1, *image.shape[-2:])
2035
+ if image.shape[0] == 1:
2036
+ image = image[0]
2037
+ else:
2038
+ with warnings.catch_warnings():
2039
+ warnings.filterwarnings('ignore', category=RuntimeWarning)
2040
+ image = numpy.nanmean(image, axis=0)
2041
+ assert isinstance(image, numpy.ndarray)
2042
+ for i in (-1, -2):
2043
+ if image.shape[i] > shape[i]:
2044
+ shape[i] = image.shape[i]
2045
+ arrays.append(image)
2046
+
2047
+ if columns is None:
2048
+ n = len(arrays)
2049
+ if n < 3:
2050
+ columns = n
2051
+ elif n < 5:
2052
+ columns = 2
2053
+ elif n < 7:
2054
+ columns = 3
2055
+ else:
2056
+ columns = 4
2057
+ rows = int(numpy.ceil(len(arrays) / columns))
2058
+
2059
+ vmin = None
2060
+ vmax = None
2061
+ if percentile is None:
2062
+ vmin = kwargs.pop('vmin', None)
2063
+ vmax = kwargs.pop('vmax', None)
2064
+ if vmin is None:
2065
+ vmin = numpy.inf
2066
+ for image in images:
2067
+ vmin = min(vmin, numpy.nanmin(image))
2068
+ if vmin == numpy.inf:
2069
+ vmin = None
2070
+ if vmax is None:
2071
+ vmax = -numpy.inf
2072
+ for image in images:
2073
+ vmax = max(vmax, numpy.nanmax(image))
2074
+ if vmax == -numpy.inf:
2075
+ vmax = None
2076
+
2077
+ # create figure with size depending on image aspect
2078
+ fig = pyplot.figure(layout='constrained', figsize=figsize)
2079
+ if figsize is None:
2080
+ # TODO: find optimal figure height as a function of
2081
+ # number of rows and columns, image shapes, labels, and colorbar
2082
+ # presence and placements.
2083
+ if allrgb:
2084
+ hadd = 0.0
2085
+ elif location == 'right':
2086
+ hadd = 0.5
2087
+ else:
2088
+ hadd = 1.2
2089
+ if labels is not None:
2090
+ hadd += 0.3 * rows
2091
+ w, h = fig.get_size_inches()
2092
+ aspect = min(1.0, max(0.5, shape[0] / shape[1]))
2093
+ fig.set_size_inches(
2094
+ w, h * 0.9 / columns * aspect * rows + h * 0.1 * aspect + hadd
2095
+ )
2096
+ gs = GridSpec(rows, columns, figure=fig)
2097
+ if title:
2098
+ fig.suptitle(title)
2099
+
2100
+ axs = []
2101
+ for i, image in enumerate(arrays):
2102
+ ax = fig.add_subplot(gs[i // columns, i % columns], **subplot_kw)
2103
+ ax.set_anchor('C')
2104
+ axs.append(ax)
2105
+ pos = _imshow(
2106
+ ax,
2107
+ image,
2108
+ percentile=percentile,
2109
+ vmin=vmin,
2110
+ vmax=vmax,
2111
+ cmap=cmap,
2112
+ colorbar=percentile is not None,
2113
+ axis=i == 0 and not subplot_kw,
2114
+ title=None if labels is None else labels[i],
2115
+ **kwargs,
2116
+ )
2117
+ if not allrgb and percentile is None:
2118
+ fig.colorbar(pos, ax=axs, shrink=kwargs['shrink'], location=location)
2119
+
2120
+ if show:
2121
+ pyplot.show()
2122
+
2123
+
1943
2124
  def plot_polar_frequency(
1944
2125
  frequency: ArrayLike,
1945
2126
  phase: ArrayLike,
@@ -2002,6 +2183,58 @@ def plot_polar_frequency(
2002
2183
  pyplot.show()
2003
2184
 
2004
2185
 
2186
+ def plot_histograms(
2187
+ *data: ArrayLike,
2188
+ title: str | None = None,
2189
+ xlabel: str | None = None,
2190
+ ylabel: str | None = None,
2191
+ labels: Sequence[str] | None = None,
2192
+ show: bool = True,
2193
+ **kwargs: Any,
2194
+ ) -> None:
2195
+ """Plot histograms of flattened data arrays.
2196
+
2197
+ Parameters
2198
+ ----------
2199
+ data: array_like
2200
+ Data arrays to be plotted as histograms.
2201
+ title : str, optional
2202
+ Figure title.
2203
+ xlabel : str, optional
2204
+ Label for x-axis.
2205
+ ylabel : str, optional
2206
+ Label for y-axis.
2207
+ labels: sequence of str, optional
2208
+ Labels for each data array.
2209
+ show : bool, optional, default: True
2210
+ Display figure.
2211
+ **kwargs
2212
+ Additional arguments passed to :func:`matplotlib.pyplot.hist`.
2213
+
2214
+ """
2215
+ ax = pyplot.subplots()[1]
2216
+ if kwargs.get('alpha') is None:
2217
+ ax.hist(
2218
+ [numpy.asarray(d).flatten() for d in data], label=labels, **kwargs
2219
+ )
2220
+ else:
2221
+ for d, label in zip(
2222
+ data, [None] * len(data) if labels is None else labels
2223
+ ):
2224
+ ax.hist(numpy.asarray(d).flatten(), label=label, **kwargs)
2225
+ if title is not None:
2226
+ ax.set_title(title)
2227
+ if xlabel is not None:
2228
+ ax.set_xlabel(xlabel)
2229
+ if ylabel is not None:
2230
+ ax.set_ylabel(ylabel)
2231
+ if labels is not None:
2232
+ ax.legend()
2233
+ pyplot.tight_layout()
2234
+ if show:
2235
+ pyplot.show()
2236
+
2237
+
2005
2238
  def _imshow(
2006
2239
  ax: Axes,
2007
2240
  image: NDArray[Any],
@@ -2022,6 +2255,13 @@ def _imshow(
2022
2255
 
2023
2256
  """
2024
2257
  update_kwargs(kwargs, interpolation='none')
2258
+ location = kwargs.pop('location', 'bottom')
2259
+ if image.ndim == 3 and image.shape[2] in {3, 4}:
2260
+ # RGB(A)
2261
+ vmin = None
2262
+ vmax = None
2263
+ percentile = None
2264
+ colorbar = False
2025
2265
  if percentile is not None:
2026
2266
  if isinstance(percentile, Sequence):
2027
2267
  percentile = percentile[0], percentile[1]
@@ -2034,7 +2274,7 @@ def _imshow(
2034
2274
  or percentile[1] > 100
2035
2275
  ):
2036
2276
  raise ValueError(f'{percentile=} out of range')
2037
- vmin, vmax = numpy.percentile(image, percentile)
2277
+ vmin, vmax = numpy.nanpercentile(image, percentile)
2038
2278
  pos = ax.imshow(image, vmin=vmin, vmax=vmax, **kwargs)
2039
2279
  if colorbar:
2040
2280
  if percentile is not None and vmin is not None and vmax is not None:
@@ -2045,7 +2285,7 @@ def _imshow(
2045
2285
  if fig is not None:
2046
2286
  if shrink is None:
2047
2287
  shrink = 0.8
2048
- fig.colorbar(pos, shrink=shrink, location='bottom', ticks=ticks)
2288
+ fig.colorbar(pos, shrink=shrink, location=location, ticks=ticks)
2049
2289
  if title:
2050
2290
  ax.set_title(title)
2051
2291
  if not axis:
phasorpy/utils.py CHANGED
@@ -104,7 +104,7 @@ def spectral_vector_denoise(
104
104
  .. [4] Harman RC, Lang RT, Kercher EM, Leven P, and Spring BQ.
105
105
  `Denoising multiplexed microscopy images in n-dimensional spectral space
106
106
  <https://doi.org/10.1364/BOE.463979>`_.
107
- *Biomedical Optics Express*, 13(8): 4298-4309 (2022)
107
+ *Biomed Opt Express*, 13(8): 4298-4309 (2022)
108
108
 
109
109
  Examples
110
110
  --------
@@ -201,7 +201,7 @@ def anscombe_transformation(
201
201
 
202
202
  Parameters
203
203
  ----------
204
- data: array_like
204
+ data : array_like
205
205
  Noisy Poisson-distributed data to be transformed.
206
206
  **kwargs
207
207
  Optional `arguments passed to numpy universal functions
@@ -250,9 +250,9 @@ def anscombe_transformation_inverse(
250
250
 
251
251
  Parameters
252
252
  ----------
253
- data: array_like
253
+ data : array_like
254
254
  Anscombe-transformed data.
255
- approx: bool, default: False
255
+ approx : bool, default: False
256
256
  If true, return approximation of exact unbiased inverse.
257
257
  **kwargs
258
258
  Optional `arguments passed to numpy universal functions
@@ -288,13 +288,13 @@ def anscombe_transformation_inverse(
288
288
  `A closed-form approximation of the exact unbiased inverse of the
289
289
  Anscombe variance-stabilizing transformation
290
290
  <https://doi.org/10.1109/TIP.2011.2121085>`_.
291
- IEEE Trans Image Process, 20(9): 2697-8 (2011).
291
+ *IEEE Trans Image Process*, 20(9): 2697-8 (2011).
292
292
 
293
293
  .. [3] Makitalo M, and Foi A
294
294
  `Optimal inversion of the generalized Anscombe transformation for
295
295
  Poisson-Gaussian noise
296
296
  <https://doi.org/10.1109/TIP.2012.2202675>`_,
297
- IEEE Trans Image Process, 22(1): 91-103 (2013)
297
+ *IEEE Trans Image Process*, 22(1): 91-103 (2013)
298
298
 
299
299
  Examples
300
300
  --------
@@ -317,7 +317,7 @@ def number_threads(
317
317
  max_threads: int | None = None,
318
318
  /,
319
319
  ) -> int:
320
- """Return number of threads for parallel computations on CPU cores.
320
+ """Return number of threads for parallel computations across CPU cores.
321
321
 
322
322
  This function is used to parse ``num_threads`` parameters.
323
323
 
@@ -332,6 +332,11 @@ def number_threads(
332
332
  max_threads : int, optional
333
333
  Maximum number of threads to return.
334
334
 
335
+ Returns
336
+ -------
337
+ int
338
+ Number of threads for parallel computations.
339
+
335
340
  Examples
336
341
  --------
337
342
  >>> number_threads()
phasorpy/version.py CHANGED
@@ -1,24 +1,32 @@
1
- """Version information."""
1
+ """Version information for PhasorPy and dependencies."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = '0.3'
5
+ __all__ = ['__version__', 'versions']
6
+
7
+ __version__ = '0.5'
6
8
 
7
9
 
8
10
  def versions(
9
11
  *, sep: str = '\n', dash: str = '-', verbose: bool = False
10
12
  ) -> str:
11
- """Return versions of installed packages that phasorpy depends on.
13
+ """Return version information for PhasorPy and its dependencies.
12
14
 
13
15
  Parameters
14
16
  ----------
15
17
  sep : str, optional
16
- Separator between version items. The default is a newline character.
18
+ Separator between version items. Defaults to newline.
17
19
  dash : str, optional
18
- Separator between module name and version.
20
+ Separator between module name and version. Defaults to dash.
19
21
  verbose : bool, optional
20
22
  Include paths to Python interpreter and modules.
21
23
 
24
+ Returns
25
+ -------
26
+ str
27
+ Formatted string containing version information.
28
+ Format: "<package><dash><version>[<space>(<path>)]<sep>"
29
+
22
30
  Example
23
31
  -------
24
32
  >>> print(versions())
@@ -44,6 +52,7 @@ def versions(
44
52
  'lfdfiles',
45
53
  'sdtfile',
46
54
  'ptufile',
55
+ 'liffile',
47
56
  'matplotlib',
48
57
  'scipy',
49
58
  'skimage',