Skip to content

Commit d815c31

Browse files
committed
1 parent 7577253 commit d815c31

182 files changed

Lines changed: 36567 additions & 35422 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/main/_downloads/08259e68fc838871e73e49dc5a3a2eb1/phasorpy_cursor.ipynb

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"cell_type": "markdown",
3030
"metadata": {},
3131
"source": [
32-
"Open a hyperspectral dataset used throughout this tutorial:\n\n"
32+
"Load a hyperspectral dataset used throughout this tutorial:\n\n"
3333
]
3434
},
3535
{
@@ -47,7 +47,7 @@
4747
"cell_type": "markdown",
4848
"metadata": {},
4949
"source": [
50-
"## Circular cursors\n\nUse circular cursors to mask regions of interest in the phasor space:\n\n"
50+
"## Circular cursors\n\nUse circular cursors to mask regions of interest in the phasor space.\nDefine two cursors by specifying their real and imaginary coordinates\nand radii:\n\n"
5151
]
5252
},
5353
{
@@ -83,7 +83,7 @@
8383
"cell_type": "markdown",
8484
"metadata": {},
8585
"source": [
86-
"The cursor masks can be blended to produce a pseudo-colored image:\n\n"
86+
"The cursor masks can be blended to produce a pseudo-colored image.\nEach cursor's region is assigned a different color:\n\n"
8787
]
8888
},
8989
{
@@ -101,7 +101,14 @@
101101
"cell_type": "markdown",
102102
"metadata": {},
103103
"source": [
104-
"## Elliptic cursors\n\nUse elliptic cursors to mask more defined regions of interest in the\nphasor space:\n\n"
104+
"The pseudo-color image is numpy array with values between 0 and 1 (RGB)\nthat can be further processed or saved as needed.\n\n"
105+
]
106+
},
107+
{
108+
"cell_type": "markdown",
109+
"metadata": {},
110+
"source": [
111+
"## Elliptical cursors\n\nUse elliptical cursors to mask better-defined regions of interest in the\nphasor space. Elliptical cursors allow independent control of the radii,\nwhich can better match elongated clusters in phasor space:\n\n"
105112
]
106113
},
107114
{
@@ -112,14 +119,14 @@
112119
},
113120
"outputs": [],
114121
"source": [
115-
"radius = [0.1, 0.06]\nradius_minor = [0.3, 0.25]\n\nelliptic_mask = mask_from_elliptic_cursor(\n real,\n imag,\n cursor_real,\n cursor_imag,\n radius=radius,\n radius_minor=radius_minor,\n)"
122+
"radius = [0.1, 0.06] # major axis\nradius_minor = [0.3, 0.25] # minor axis\n\nelliptic_mask = mask_from_elliptic_cursor(\n real,\n imag,\n cursor_real,\n cursor_imag,\n radius=radius,\n radius_minor=radius_minor,\n)"
116123
]
117124
},
118125
{
119126
"cell_type": "markdown",
120127
"metadata": {},
121128
"source": [
122-
"Show the elliptic cursors in a phasor plot:\n\n"
129+
"Show the elliptical cursors in a phasor plot:\n\n"
123130
]
124131
},
125132
{
@@ -130,14 +137,14 @@
130137
},
131138
"outputs": [],
132139
"source": [
133-
"plot = PhasorPlot(allquadrants=True, title='Elliptic cursors')\nplot.hist2d(real, imag, cmap='Greys')\nplot.cursor(\n cursor_real,\n cursor_imag,\n radius=radius,\n radius_minor=radius_minor,\n color=CATEGORICAL[:2],\n label=['cursor 0', 'cursor 1'],\n)\nplot.show()"
140+
"plot = PhasorPlot(allquadrants=True, title='Elliptical cursors')\nplot.hist2d(real, imag, cmap='Greys')\nplot.cursor(\n cursor_real,\n cursor_imag,\n radius=radius,\n radius_minor=radius_minor,\n color=CATEGORICAL[:2],\n label=['cursor 0', 'cursor 1'],\n)\nplot.show()"
134141
]
135142
},
136143
{
137144
"cell_type": "markdown",
138145
"metadata": {},
139146
"source": [
140-
"The mean intensity image can be used as a base layer to overlay\nthe masks from the elliptic cursors:\n\n"
147+
"The mean intensity image can be used as a base layer to overlay\nthe masks from the elliptical cursors:\n\n"
141148
]
142149
},
143150
{
@@ -148,14 +155,14 @@
148155
},
149156
"outputs": [],
150157
"source": [
151-
"pseudo_color_image = pseudo_color(*elliptic_mask, intensity=mean)\n\nplot_image(\n pseudo_color_image,\n title='Pseudo-color image from elliptic cursors and intensity',\n)"
158+
"pseudo_color_image = pseudo_color(*elliptic_mask, intensity=mean)\n\nplot_image(\n pseudo_color_image,\n title='Pseudo-color image from elliptical cursors and intensity',\n)"
152159
]
153160
},
154161
{
155162
"cell_type": "markdown",
156163
"metadata": {},
157164
"source": [
158-
"## Polar cursors\n\nCreate a mask with two ranges of phase and modulation values:\n\n"
165+
"## Polar cursors\n\nUse polar cursors to select regions of interest in the phasor space based\non phase and modulation ranges:\n\n"
159166
]
160167
},
161168
{
@@ -184,7 +191,7 @@
184191
},
185192
"outputs": [],
186193
"source": [
187-
"plot = PhasorPlot(allquadrants=True, title='Polar cursors')\nplot.hist2d(real, imag, cmap='Greys')\nplot.polar_cursor(\n phase=phase_min,\n phase_limit=phase_max,\n modulation=modulation_min,\n modulation_limit=modulation_max,\n color=CATEGORICAL[2:4],\n label=['cursor 0', 'cursor 1'],\n)\nplot.show()"
194+
"plot = PhasorPlot(allquadrants=True, title='Polar cursors')\nplot.hist2d(real, imag, cmap='Greys')\nplot.polar_cursor(\n phase=phase_min,\n phase_limit=phase_max,\n modulation=modulation_min,\n modulation_limit=modulation_max,\n color=CATEGORICAL[2:4], # use different colors\n label=['cursor 0', 'cursor 1'],\n)\nplot.show()"
188195
]
189196
},
190197
{
@@ -204,13 +211,6 @@
204211
"source": [
205212
"pseudo_color_image = pseudo_color(\n *polar_mask, intensity=mean_thresholded, colors=CATEGORICAL[2:]\n)\n\nplot_image(\n pseudo_color_image,\n title='Pseudo-color image from\\npolar cursors and thresholded intensity',\n)"
206213
]
207-
},
208-
{
209-
"cell_type": "markdown",
210-
"metadata": {},
211-
"source": [
212-
"sphinx_gallery_thumbnail_number = 1\nmypy: allow-untyped-defs, allow-untyped-calls\nmypy: disable-error-code=\"arg-type\"\n\n"
213-
]
214214
}
215215
],
216216
"metadata": {

docs/main/_downloads/08c44fd02fe5378fc05e9aecf2e433ce/phasorpy_phasor_from_signal.ipynb

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"\n# Benchmark phasor_from_signal\n\nBenchmark the ``phasor_from_signal`` function.\n\nThe :py:func:`phasorpy.phasor.phasor_from_signal` function to calculate phasor\ncoordinates from time-resolved or spectral signals can operate in two modes:\n\n- using an internal Cython function optimized for calculating a small number\n of harmonics, optionally using multiple threads.\n\n- using a real forward Fast Fourier Transform (FFT), ``numpy.fft.rfft`` or\n a drop-in replacement function like ``scipy.fft.rfft``\n or ``mkl_fft.interfaces.numpy_fft.rfft``.\n\nThis tutorial compares the performance of the two modes.\n\nImport required modules and functions:\n"
7+
"\n# Benchmark phasor_from_signal\n\nBenchmark the ``phasor_from_signal`` function.\n\nThe :py:func:`phasorpy.phasor.phasor_from_signal` function used to calculate\nphasor coordinates from time-resolved or spectral signals can operate in\ntwo modes:\n\n- using an internal Cython function optimized for calculating a small number\n of harmonics, optionally using multiple threads.\n\n- using a real forward Fast Fourier Transform (FFT), ``numpy.fft.rfft`` or\n a drop-in replacement function like ``scipy.fft.rfft``\n or ``mkl_fft.interfaces.numpy_fft.rfft``.\n\nThis tutorial compares the performance of the two modes.\n\nImport required modules and functions:\n"
88
]
99
},
1010
{
@@ -15,14 +15,14 @@
1515
},
1616
"outputs": [],
1717
"source": [
18-
"from timeit import timeit\n\nimport numpy\nfrom numpy.fft import rfft as numpy_fft # noqa\n\nfrom phasorpy.phasor import phasor_from_signal # noqa\nfrom phasorpy.utils import number_threads\n\ntry:\n from scipy.fft import rfft as scipy_fft\nexcept ImportError:\n scipy_fft = None\n\ntry:\n from mkl_fft.interfaces.numpy_fft import rfft as mkl_fft\nexcept ImportError:\n mkl_fft = None"
18+
"from timeit import timeit\n\nimport numpy\nfrom numpy.fft import rfft as numpy_fft # noqa: F401\n\nfrom phasorpy.phasor import phasor_from_signal # noqa: F401\nfrom phasorpy.utils import number_threads\n\ntry:\n from scipy.fft import rfft as scipy_fft\nexcept ImportError:\n scipy_fft = None\n\ntry:\n from mkl_fft.interfaces.numpy_fft import rfft as mkl_fft\nexcept ImportError:\n mkl_fft = None\n\nrng = numpy.random.default_rng(42) # initialize random number generator"
1919
]
2020
},
2121
{
2222
"cell_type": "markdown",
2323
"metadata": {},
2424
"source": [
25-
"## Run benchmark\n\nCreate a random signal with a size and dtype similar to real world data:\n\n"
25+
"## Run benchmark\n\nCreate a random signal with a size and dtype similar to real-world data:\n\n"
2626
]
2727
},
2828
{
@@ -33,7 +33,7 @@
3333
},
3434
"outputs": [],
3535
"source": [
36-
"signal = numpy.random.default_rng(1).random((384, 384, 384))\nsignal += 1.1\nsignal *= 3723 # ~12 bit\nsignal = signal.astype(numpy.uint16) # 108 MB\nsignal[signal < 0.05] = 0.0 # 5% no signal"
36+
"signal = rng.random((384, 384, 384))\nsignal += 1.1\nsignal *= 3723 # ~12 bit\nsignal = signal.astype(numpy.uint16) # 108 MB\nsignal[signal < 0.05] = 0.0 # 5% no signal"
3737
]
3838
},
3939
{
@@ -58,32 +58,21 @@
5858
"cell_type": "markdown",
5959
"metadata": {},
6060
"source": [
61-
"For reference, the results on a Core i7-14700K CPU, Windows 11,\nPython 3.14.0, numpy 2.3.5, scipy 1.16.3, mkl-fft 2.1.1::\n\n harmonics 1\n axis -1\n not_fft 0.034s 1.00\n not_fft (6 threads) 0.006s 0.17\n numpy_fft 0.274s 8.03\n scipy_fft 0.240s 7.04\n mkl_fft 0.141s 4.14\n axis 0\n not_fft 0.162s 4.75\n not_fft (6 threads) 0.038s 1.13\n numpy_fft 0.697s 20.44\n scipy_fft 0.496s 14.54\n mkl_fft 0.167s 4.90\n axis 2\n not_fft 0.038s 1.12\n not_fft (6 threads) 0.006s 0.16\n numpy_fft 0.272s 7.99\n scipy_fft 0.240s 7.04\n mkl_fft 0.130s 3.83\n harmonics 8\n axis -1\n not_fft 0.287s 8.43\n not_fft (6 threads) 0.040s 1.17\n numpy_fft 0.288s 8.45\n scipy_fft 0.253s 7.43\n mkl_fft 0.161s 4.74\n axis 0\n not_fft 1.161s 34.04\n not_fft (6 threads) 0.425s 12.47\n numpy_fft 0.715s 20.97\n scipy_fft 0.541s 15.88\n mkl_fft 0.183s 5.38\n axis 2\n not_fft 0.282s 8.27\n not_fft (6 threads) 0.038s 1.13\n numpy_fft 0.288s 8.46\n scipy_fft 0.255s 7.49\n mkl_fft 0.155s 4.56\n\n"
61+
"For reference, the results on a Core i7-14700K CPU, Windows 11,\nPython 3.14.0, numpy 2.3.5, scipy 1.16.3, mkl_fft 2.1.1::\n\n harmonics 1\n axis -1\n not_fft 0.034s 1.00\n not_fft (6 threads) 0.006s 0.17\n numpy_fft 0.274s 8.03\n scipy_fft 0.240s 7.04\n mkl_fft 0.141s 4.14\n axis 0\n not_fft 0.162s 4.75\n not_fft (6 threads) 0.038s 1.13\n numpy_fft 0.697s 20.44\n scipy_fft 0.496s 14.54\n mkl_fft 0.167s 4.90\n axis 2\n not_fft 0.038s 1.12\n not_fft (6 threads) 0.006s 0.16\n numpy_fft 0.272s 7.99\n scipy_fft 0.240s 7.04\n mkl_fft 0.130s 3.83\n harmonics 8\n axis -1\n not_fft 0.287s 8.43\n not_fft (6 threads) 0.040s 1.17\n numpy_fft 0.288s 8.45\n scipy_fft 0.253s 7.43\n mkl_fft 0.161s 4.74\n axis 0\n not_fft 1.161s 34.04\n not_fft (6 threads) 0.425s 12.47\n numpy_fft 0.715s 20.97\n scipy_fft 0.541s 15.88\n mkl_fft 0.183s 5.38\n axis 2\n not_fft 0.282s 8.27\n not_fft (6 threads) 0.038s 1.13\n numpy_fft 0.288s 8.46\n scipy_fft 0.255s 7.49\n mkl_fft 0.155s 4.56\n\n"
6262
]
6363
},
6464
{
6565
"cell_type": "markdown",
6666
"metadata": {},
6767
"source": [
68-
"## Results\n\n- Using the Cython implementation is significantly faster than using the\n ``numpy.fft`` based implementation for single harmonics.\n- Using multiple threads can significantly speed up the Cython mode.\n- The FFT functions from ``scipy`` and ``mkl_fft`` outperform numpy.fft.\n Specifically, ``mkl_fft`` is very performant.\n- Using FFT becomes more competitive when calculating larger number of\n harmonics.\n- Computing over the last axis is significantly faster compared to the first\n axis. That is because the samples in the last dimension are contiguous,\n closer together in memory.\n\nNote that these results were obtained on a single dataset of random numbers.\n\n"
68+
"## Results\n\n- Using the Cython implementation is significantly faster than using the\n ``numpy.fft``-based implementation for single harmonics.\n- Using multiple threads can significantly speed up the Cython mode.\n- The FFT functions from ``scipy`` and ``mkl_fft`` outperform the\n ``numpy.fft`` function. Specifically, ``mkl_fft`` is very performant.\n- Using FFT becomes more competitive when calculating a larger number of\n harmonics.\n- Computing over the last axis is significantly faster compared to the first\n axis. That is because the samples in the last dimension are contiguous in\n memory.\n\nNote that these results were obtained on a single dataset of random numbers.\n\n"
6969
]
7070
},
7171
{
7272
"cell_type": "markdown",
7373
"metadata": {},
7474
"source": [
75-
"## Conclusions\n\nUsing the Cython implementation is a reasonable default when calculating\na few harmonics. Using FFT is a better choice when computing large number\nof harmonics, especially with an optimized FFT function.\n\n"
76-
]
77-
},
78-
{
79-
"cell_type": "code",
80-
"execution_count": null,
81-
"metadata": {
82-
"collapsed": false
83-
},
84-
"outputs": [],
85-
"source": [
86-
"# mypy: allow-untyped-defs, allow-untyped-calls\n# mypy: disable-error-code=\"arg-type\""
75+
"## Conclusions\n\nUsing the Cython implementation is a reasonable default when calculating\na few harmonics. Using FFT is a better choice when computing a large number\nof harmonics, especially with an optimized FFT function.\n\n"
8776
]
8877
}
8978
],

0 commit comments

Comments
 (0)