waveorder 2.2.0__py3-none-any.whl → 2.2.0rc0__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.
@@ -1,335 +0,0 @@
1
- import matplotlib.pyplot as plt
2
- import numpy as np
3
-
4
-
5
- def plot_5d_ortho(
6
- rcCzyx_data: np.ndarray,
7
- filename: str,
8
- voxel_size: tuple[float, float, float],
9
- zyx_slice: tuple[int, int, int],
10
- color_funcs: list[list[callable]],
11
- row_labels: list[str] = None,
12
- column_labels: list[str] = None,
13
- rose_path: str = None,
14
- inches_per_column: float = 1.5,
15
- label_size: int = 1,
16
- ortho_line_width: float = 0.5,
17
- row_column_line_width: float = 0.5,
18
- xyz_labels: bool = True,
19
- background_color: str = "white",
20
- **kwargs: dict,
21
- ) -> None:
22
- """
23
- Plot 5D multi-channel data in a grid or ortho-slice views.
24
-
25
- Input data is a 6D array with (row, column, channels, Z, Y, X) dimensions.
26
-
27
- `color_funcs` permits different RGB color maps for each row and column.
28
-
29
- Parameters
30
- ----------
31
- rcCzyx_data : numpy.ndarray
32
- 5D array with shape (R, C, Ch, Z, Y, X) containing the data to plot.
33
- [r]ows and [c]olumns form a grid
34
- [C]hannels contain multiple color channels
35
- [ZYX] contain 3D volumes.
36
- filename : str
37
- Path to save the output plot.
38
- voxel_size : tuple[float, float, float]
39
- Size of each voxel in (Z, Y, X) dimensions.
40
- zyx_slice : tuple[int, int, int]
41
- Indices of the ortho-slices to plot in (Z, Y, X) indices.
42
- color_funcs : list[list[callable]]
43
- A list of lists of callables, one for each element of the plot grid,
44
- with len(color_funcs) == R and len(colors_funcs[0] == C).
45
- Each callable accepts [C]hannel arguments and returns RGB color values,
46
- enabling different RGB color maps for each member of the grid.
47
- row_labels : list[str], optional
48
- Labels for the rows, by default None.
49
- column_labels : list[str], optional
50
- Labels for the columns, by default None.
51
- rose_path : str, optional
52
- Path to an image to display in the top-left corner, by default None.
53
- inches_per_column : float, optional
54
- Width of each column in inches, by default 1.5.
55
- label_size : int, optional
56
- Size of the labels, by default 1.
57
- ortho_line_width : float, optional
58
- Width of the orthogonal lines, by default 0.5.
59
- row_column_line_width : float, optional
60
- Width of the lines between rows and columns, by default 0.5.
61
- xyz_labels : bool, optional
62
- Whether to display XYZ labels, by default True.
63
- background_color : str, optional
64
- Background color of the plot, by default "white".
65
- **kwargs : dict
66
- Additional keyword arguments passed to color_funcs.
67
- """
68
- R, C, Ch, Z, Y, X = rcCzyx_data.shape
69
-
70
- # Extent
71
- dZ, dY, dX = Z * voxel_size[0], Y * voxel_size[1], X * voxel_size[2]
72
-
73
- assert R == len(row_labels)
74
- assert C == len(column_labels)
75
- assert zyx_slice[0] < Z and zyx_slice[1] < Y and zyx_slice[2] < X
76
- assert zyx_slice[0] >= 0 and zyx_slice[1] >= 0 and zyx_slice[2] >= 0
77
-
78
- assert R == len(color_funcs)
79
- for color_func_row in color_funcs:
80
- if isinstance(color_func_row, list):
81
- assert len(color_func_row) == C
82
- else:
83
- color_func_row = [color_func_row] * C
84
-
85
- n_rows = 1 + (2 * R)
86
- n_cols = 1 + (2 * C)
87
-
88
- width_ratios = [label_size] + C * [1, dZ / dX]
89
- height_ratios = [label_size] + R * [dY / dX, dZ / dX]
90
-
91
- fig_width = np.array(width_ratios).sum() * inches_per_column
92
- fig_height = np.array(height_ratios).sum() * inches_per_column
93
-
94
- fig, axes = plt.subplots(
95
- n_rows,
96
- n_cols,
97
- figsize=(fig_width, fig_height),
98
- gridspec_kw={
99
- "wspace": 0.05,
100
- "hspace": 0.05,
101
- "width_ratios": width_ratios,
102
- "height_ratios": height_ratios,
103
- },
104
- )
105
- fig.patch.set_facecolor(background_color)
106
- for ax in axes.flat:
107
- ax.set_facecolor(background_color)
108
-
109
- if rose_path is not None:
110
- axes[0, 0].imshow(plt.imread(rose_path))
111
-
112
- for i in range(n_rows):
113
- for j in range(n_cols):
114
- # Add labels
115
- if (i == 0 and (j - 1) % 2 == 0) or (j == 0 and (i - 1) % 2 == 0):
116
- axes[i, j].text(
117
- 0.5,
118
- 0.5,
119
- index,
120
- horizontalalignment="center",
121
- verticalalignment="center",
122
- fontsize=10 * label_size,
123
- color="black",
124
- )
125
-
126
- # Add data
127
- if i > 0 and j > 0:
128
- color_func = color_funcs[int((i - 1) / 2)][int((j - 1) / 2)]
129
-
130
- Cyx_data = rcCzyx_data[
131
- int((i - 1) / 2), int((j - 1) / 2), :, zyx_slice[0]
132
- ]
133
- Cyz_data = rcCzyx_data[
134
- int((i - 1) / 2), int((j - 1) / 2), :, :, :, zyx_slice[2]
135
- ].transpose(0, 2, 1)
136
- Czx_data = rcCzyx_data[
137
- int((i - 1) / 2), int((j - 1) / 2), :, :, zyx_slice[1]
138
- ]
139
-
140
- # YX
141
- if (i - 1) % 2 == 0 and (j - 1) % 2 == 0:
142
- axes[i, j].imshow(
143
- color_func(*Cyx_data, **kwargs),
144
- aspect=voxel_size[1] / voxel_size[2],
145
- )
146
- # YZ
147
- elif (i - 1) % 2 == 0 and (j - 1) % 2 == 1:
148
- axes[i, j].imshow(
149
- color_func(*Cyz_data, **kwargs),
150
- aspect=voxel_size[1] / voxel_size[0],
151
- )
152
- # XZ
153
- elif (i - 1) % 2 == 1 and (j - 1) % 2 == 0:
154
- axes[i, j].imshow(
155
- color_func(*Czx_data, **kwargs),
156
- aspect=voxel_size[0] / voxel_size[2],
157
- )
158
-
159
- # Draw lines between rows and cols
160
- top = axes[0, 0].get_position().y1
161
- bottom = axes[-1, -1].get_position().y0
162
- left = axes[0, 0].get_position().x0
163
- right = axes[-1, -1].get_position().x1
164
- if i == 0 and (j - 1) % 2 == 0:
165
- left_edge = (
166
- axes[0, j].get_position().x0
167
- + axes[0, j - 1].get_position().x1
168
- ) / 2
169
- fig.add_artist(
170
- plt.Line2D(
171
- [left_edge, left_edge],
172
- [bottom, top],
173
- transform=fig.transFigure,
174
- color="black",
175
- lw=row_column_line_width,
176
- )
177
- )
178
- if j == 0 and (i - 1) % 2 == 0:
179
- top_edge = (
180
- axes[i, 0].get_position().y1
181
- + axes[i - 1, 0].get_position().y0
182
- ) / 2
183
- fig.add_artist(
184
- plt.Line2D(
185
- [left, right],
186
- [top_edge, top_edge],
187
- transform=fig.transFigure,
188
- color="black",
189
- lw=row_column_line_width,
190
- )
191
- )
192
-
193
- # Remove ticks and spines
194
- axes[i, j].tick_params(
195
- left=False, bottom=False, labelleft=False, labelbottom=False
196
- )
197
- axes[i, j].spines["top"].set_visible(False)
198
- axes[i, j].spines["right"].set_visible(False)
199
- axes[i, j].spines["bottom"].set_visible(False)
200
- axes[i, j].spines["left"].set_visible(False)
201
-
202
- yx_slice_color = "green"
203
- yz_slice_color = "red"
204
- zx_slice_color = "blue"
205
-
206
- # Label orthogonal slices
207
- add_ortho_lines_to_axis(
208
- axes[1, 1],
209
- (zyx_slice[1], zyx_slice[2]),
210
- ("y", "x") if xyz_labels else ("", ""),
211
- yx_slice_color,
212
- yz_slice_color,
213
- zx_slice_color,
214
- ortho_line_width,
215
- ) # YX axis
216
-
217
- add_ortho_lines_to_axis(
218
- axes[2, 1],
219
- (zyx_slice[0], zyx_slice[2]),
220
- ("z", "x") if xyz_labels else ("", ""),
221
- zx_slice_color,
222
- yz_slice_color,
223
- yx_slice_color,
224
- ortho_line_width,
225
- ) # ZX axis
226
-
227
- add_ortho_lines_to_axis(
228
- axes[1, 2],
229
- (zyx_slice[1], zyx_slice[0]),
230
- ("y", "z") if xyz_labels else ("", ""),
231
- yz_slice_color,
232
- yx_slice_color,
233
- zx_slice_color,
234
- ortho_line_width,
235
- ) # YZ axis
236
-
237
- print(f"Saving {filename}")
238
- fig.savefig(filename, dpi=400, format="pdf", bbox_inches="tight")
239
-
240
-
241
- def add_ortho_lines_to_axis(
242
- axis: plt.Axes,
243
- yx_slice: tuple[int, int],
244
- axis_labels: tuple[str, str],
245
- outer_color: str,
246
- vertical_color: str,
247
- horizontal_color: str,
248
- line_width: float = 0,
249
- text_color: str = "white",
250
- ) -> None:
251
- """
252
- Add orthogonal lines and labels to a given axis.
253
-
254
- Parameters
255
- ----------
256
- axis : matplotlib.axes.Axes
257
- The axis to which the orthogonal lines and labels will be added.
258
- yx_slice : tuple[int, int]
259
- The (Y, X) slice indices for the orthogonal lines.
260
- axis_labels : tuple[str, str]
261
- The labels for the Y and X axes.
262
- outer_color : str
263
- The color of the outer rectangle.
264
- vertical_color : str
265
- The color of the vertical line.
266
- horizontal_color : str
267
- The color of the horizontal line.
268
- line_width : float, optional
269
- The width of the lines, by default 0.
270
- text_color : str, optional
271
- The color of the text labels, by default "white".
272
- """
273
- xmin, xmax = axis.get_xlim()
274
- ymin, ymax = axis.get_ylim()
275
-
276
- # Axis labels
277
- horizontal_axis_label_pos = (0.1, 0.975)
278
- vertical_axis_label_pos = (0.025, 0.9)
279
- axis.text(
280
- horizontal_axis_label_pos[0],
281
- horizontal_axis_label_pos[1],
282
- axis_labels[1],
283
- horizontalalignment="left",
284
- verticalalignment="top",
285
- transform=axis.transAxes,
286
- fontsize=5,
287
- color=text_color,
288
- )
289
-
290
- axis.text(
291
- vertical_axis_label_pos[0],
292
- vertical_axis_label_pos[1],
293
- axis_labels[0],
294
- horizontalalignment="left",
295
- verticalalignment="top",
296
- transform=axis.transAxes,
297
- fontsize=5,
298
- color=text_color,
299
- )
300
-
301
- # Outer rectangle
302
- axis.add_artist(
303
- plt.Rectangle(
304
- (xmin, ymin),
305
- xmax - xmin,
306
- ymax - ymin,
307
- linewidth=line_width,
308
- edgecolor=outer_color,
309
- facecolor="none",
310
- transform=axis.transData,
311
- clip_on=False,
312
- )
313
- )
314
-
315
- # Horizontal line
316
- axis.add_artist(
317
- plt.Line2D(
318
- [xmin, xmax],
319
- [yx_slice[0], yx_slice[0]],
320
- transform=axis.transData,
321
- color=horizontal_color,
322
- lw=line_width,
323
- )
324
- )
325
-
326
- # Vertical line
327
- axis.add_artist(
328
- plt.Line2D(
329
- [yx_slice[1], yx_slice[1]],
330
- [ymin, ymax],
331
- transform=axis.transData,
332
- color=vertical_color,
333
- lw=line_width,
334
- )
335
- )
@@ -1,77 +0,0 @@
1
- from waveorder.visuals.utils import complex_tensor_to_rgb
2
- from typing import TYPE_CHECKING
3
-
4
- import numpy as np
5
- import torch
6
-
7
-
8
- def add_transfer_function_to_viewer(
9
- viewer: "napari.Viewer",
10
- transfer_function: torch.Tensor,
11
- zyx_scale: tuple[float, float, float],
12
- layer_name: str = "Transfer Function",
13
- clim_factor: float = 1.0,
14
- complex_rgb: bool = False,
15
- ):
16
- zyx_shape = transfer_function.shape[-3:]
17
- lim = torch.max(torch.abs(transfer_function)) * clim_factor
18
- voxel_scale = np.array(
19
- [
20
- zyx_shape[0] * zyx_scale[0],
21
- zyx_shape[1] * zyx_scale[1],
22
- zyx_shape[2] * zyx_scale[2],
23
- ]
24
- )
25
- shift_dims = (-3, -2, -1)
26
-
27
- if complex_rgb:
28
- rgb_transfer_function = complex_tensor_to_rgb(
29
- np.array(torch.fft.ifftshift(transfer_function, dim=shift_dims)),
30
- saturate_clim_fraction=clim_factor,
31
- )
32
- viewer.add_image(
33
- rgb_transfer_function,
34
- scale=1 / voxel_scale,
35
- name=layer_name,
36
- )
37
- else:
38
- viewer.add_image(
39
- torch.fft.ifftshift(torch.real(transfer_function), dim=shift_dims)
40
- .cpu()
41
- .numpy(),
42
- colormap="bwr",
43
- contrast_limits=(-lim, lim),
44
- scale=1 / voxel_scale,
45
- name="Re(" + layer_name + ")",
46
- )
47
- if transfer_function.dtype == torch.complex64:
48
- viewer.add_image(
49
- torch.fft.ifftshift(
50
- torch.imag(transfer_function), dim=shift_dims
51
- )
52
- .cpu()
53
- .numpy(),
54
- colormap="bwr",
55
- contrast_limits=(-lim, lim),
56
- scale=1 / voxel_scale,
57
- name="Im(" + layer_name + ")",
58
- )
59
-
60
- viewer.dims.current_step = (0,) * (transfer_function.ndim - 3) + (
61
- zyx_shape[0] // 2,
62
- zyx_shape[1] // 2,
63
- zyx_shape[2] // 2,
64
- )
65
-
66
- # Show XZ view by default, and only allow rolling between XY and XZ
67
- viewer.dims.order = list(range(transfer_function.ndim - 3)) + [
68
- transfer_function.ndim - 2,
69
- transfer_function.ndim - 3,
70
- transfer_function.ndim - 1,
71
- ]
72
- viewer.dims.rollable = (False,) * (transfer_function.ndim - 3) + (
73
- True,
74
- True,
75
- False,
76
- )
77
- viewer.dims.axis_labels = ("DATA", "OBJECT", "Z", "Y", "X")
@@ -1,31 +0,0 @@
1
- import numpy as np
2
- import matplotlib.colors as mcolors
3
-
4
-
5
- # Main function to convert a complex-valued torch tensor to RGB numpy array
6
- # with red at +1, green at +i, blue at -1, and purple at -i
7
- def complex_tensor_to_rgb(array, saturate_clim_fraction=1.0):
8
-
9
- # Calculate magnitude and phase for the entire array
10
- magnitude = np.abs(array)
11
- phase = np.angle(array)
12
-
13
- # Normalize phase to [0, 1]
14
- hue = (phase + np.pi) / (2 * np.pi)
15
- hue = np.mod(hue + 0.5, 1)
16
-
17
- # Normalize magnitude to [0, 1] for saturation
18
- if saturate_clim_fraction is not None:
19
- max_abs_val = np.amax(magnitude) * saturate_clim_fraction
20
- else:
21
- max_abs_val = 1.0
22
-
23
- sat = magnitude / max_abs_val if max_abs_val != 0 else magnitude
24
-
25
- # Create HSV array: hue, saturation, value (value is set to 1)
26
- hsv = np.stack((hue, sat, np.ones_like(sat)), axis=-1)
27
-
28
- # Convert the entire HSV array to RGB using vectorized conversion
29
- rgb_array = mcolors.hsv_to_rgb(hsv)
30
-
31
- return rgb_array
@@ -1,186 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: waveorder
3
- Version: 2.2.0
4
- Summary: Wave-optical simulations and deconvolution of optical properties
5
- Author-email: CZ Biohub SF <compmicro@czbiohub.org>
6
- Maintainer-email: Talon Chandler <talon.chandler@czbiohub.org>, Shalin Mehta <shalin.mehta@czbiohub.org>
7
- License: BSD 3-Clause License
8
-
9
- Copyright (c) 2019, Chan Zuckerberg Biohub
10
-
11
- Redistribution and use in source and binary forms, with or without
12
- modification, are permitted provided that the following conditions are met:
13
-
14
- 1. Redistributions of source code must retain the above copyright notice, this
15
- list of conditions and the following disclaimer.
16
-
17
- 2. Redistributions in binary form must reproduce the above copyright notice,
18
- this list of conditions and the following disclaimer in the documentation
19
- and/or other materials provided with the distribution.
20
-
21
- 3. Neither the name of the copyright holder nor the names of its
22
- contributors may be used to endorse or promote products derived from
23
- this software without specific prior written permission.
24
-
25
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
-
36
- Project-URL: Homepage, https://github.com/mehta-lab/waveorder
37
- Project-URL: Repository, https://github.com/mehta-lab/waveorder
38
- Project-URL: Issues, https://github.com/mehta-lab/waveorder/issues
39
- Keywords: simulation,optics,phase,scattering,polarization,label-free,permittivity,reconstruction-algorithm,qlipp,mipolscope,permittivity-tensor-imaging
40
- Classifier: Development Status :: 4 - Beta
41
- Classifier: Intended Audience :: Science/Research
42
- Classifier: License :: OSI Approved :: BSD License
43
- Classifier: Programming Language :: Python :: 3
44
- Classifier: Programming Language :: Python :: 3.10
45
- Classifier: Programming Language :: Python :: 3.11
46
- Classifier: Programming Language :: Python :: 3.12
47
- Classifier: Topic :: Scientific/Engineering
48
- Classifier: Topic :: Scientific/Engineering :: Image Processing
49
- Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
50
- Classifier: Operating System :: POSIX :: Linux
51
- Classifier: Operating System :: Microsoft :: Windows
52
- Classifier: Operating System :: MacOS
53
- Requires-Python: >=3.10
54
- Description-Content-Type: text/markdown
55
- License-File: LICENSE
56
- Requires-Dist: numpy>=1.24
57
- Requires-Dist: matplotlib>=3.1.1
58
- Requires-Dist: scipy>=1.3.0
59
- Requires-Dist: pywavelets>=1.1.1
60
- Requires-Dist: ipywidgets>=7.5.1
61
- Requires-Dist: torch>=2.4.1
62
- Provides-Extra: dev
63
- Requires-Dist: pytest; extra == "dev"
64
- Requires-Dist: pytest-cov; extra == "dev"
65
- Provides-Extra: examples
66
- Requires-Dist: napari[all]; extra == "examples"
67
- Requires-Dist: jupyter; extra == "examples"
68
-
69
- # waveorder
70
-
71
- [![Python package index](https://img.shields.io/pypi/v/waveorder.svg)](https://pypi.org/project/waveorder)
72
- [![PyPI monthly downloads](https://img.shields.io/pypi/dm/waveorder.svg)](https://pypistats.org/packages/waveorder)
73
- [![Total downloads](https://pepy.tech/badge/waveorder)](https://pepy.tech/project/waveorder)
74
- [![GitHub contributors](https://img.shields.io/github/contributors-anon/mehta-lab/waveorder)](https://github.com/mehta-lab/waveorder/graphs/contributors)
75
- ![GitHub Repo stars](https://img.shields.io/github/stars/mehta-lab/waveorder)
76
- ![GitHub forks](https://img.shields.io/github/forks/mehta-lab/waveorder)
77
- ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/waveorder)
78
-
79
-
80
- This computational imaging library enables wave-optical simulation and reconstruction of optical properties that report microscopic architectural order.
81
-
82
- ## Computational label-agnostic imaging
83
-
84
- https://github.com/user-attachments/assets/4f9969e5-94ce-4e08-9f30-68314a905db6
85
-
86
- `waveorder` enables simulations and reconstructions of label-agnostic microscopy data as described in the following [preprint](https://arxiv.org/abs/2412.09775)
87
- <details>
88
- <summary> Chandler et al. 2024 </summary>
89
- <pre><code>
90
- @article{chandler_2024,
91
- author = {Chandler, Talon and Hirata-Miyasaki, Eduardo and Ivanov, Ivan E. and Liu, Ziwen and Sundarraman, Deepika and Ryan, Allyson Quinn and Jacobo, Adrian and Balla, Keir and Mehta, Shalin B.},
92
- title = {waveOrder: generalist framework for label-agnostic computational microscopy},
93
- journal = {arXiv},
94
- year = {2024},
95
- month = dec,
96
- eprint = {2412.09775},
97
- doi = {10.48550/arXiv.2412.09775}
98
- }
99
- </code></pre>
100
- </details>
101
-
102
- Specifically, `waveorder` enables simulation and reconstruction of 2D or 3D:
103
-
104
- 1. __phase, projected retardance, and in-plane orientation__ from a polarization-diverse volumetric brightfield acquisition ([QLIPP](https://elifesciences.org/articles/55502)),
105
-
106
- 2. __phase__ from a volumetric brightfield acquisition ([2D phase](https://www.osapublishing.org/ao/abstract.cfm?uri=ao-54-28-8566)/[3D phase](https://www.osapublishing.org/ao/abstract.cfm?uri=ao-57-1-a205)),
107
-
108
- 3. __phase__ from an illumination-diverse volumetric acquisition ([2D](https://www.osapublishing.org/oe/fulltext.cfm?uri=oe-23-9-11394&id=315599)/[3D](https://www.osapublishing.org/boe/fulltext.cfm?uri=boe-7-10-3940&id=349951) differential phase contrast),
109
-
110
- 4. __fluorescence density__ from a widefield volumetric fluorescence acquisition (fluorescence deconvolution).
111
-
112
- The [examples](https://github.com/mehta-lab/waveorder/tree/main/examples) demonstrate simulations and reconstruction for 2D QLIPP, 3D PODT, 3D fluorescence deconvolution, and 2D/3D PTI methods.
113
-
114
- If you are interested in deploying QLIPP, phase from brightfield, or fluorescence deconvolution for label-agnostic imaging at scale, checkout our [napari plugin](https://www.napari-hub.org/plugins/recOrder-napari), [`recOrder-napari`](https://github.com/mehta-lab/recOrder).
115
-
116
- ## Permittivity tensor imaging
117
-
118
- Additionally, `waveorder` enabled the development of a new label-free imaging method, __permittivity tensor imaging (PTI)__, that measures density and 3D orientation of biomolecules with diffraction-limited resolution. These measurements are reconstructed from polarization-resolved images acquired with a sequence of oblique illuminations.
119
-
120
- The acquisition, calibration, background correction, reconstruction, and applications of PTI are described in the following [paper](https://doi.org/10.1101/2020.12.15.422951) published in Nature Methods:
121
-
122
- <details>
123
- <summary> Yeh et al. 2024 </summary>
124
- <pre><code>
125
- @article{yeh_2024,
126
- author = {Yeh, Li-Hao and Ivanov, Ivan E. and Chandler, Talon and Byrum, Janie R. and Chhun, Bryant B. and Guo, Syuan-Ming and Foltz, Cameron and Hashemi, Ezzat and Perez-Bermejo, Juan A. and Wang, Huijun and Yu, Yanhao and Kazansky, Peter G. and Conklin, Bruce R. and Han, May H. and Mehta, Shalin B.},
127
- title = {Permittivity tensor imaging: modular label-free imaging of 3D dry mass and 3D orientation at high resolution},
128
- journal = {Nature Methods},
129
- volume = {21},
130
- number = {7},
131
- pages = {1257--1274},
132
- year = {2024},
133
- month = jul,
134
- issn = {1548-7105},
135
- publisher = {Nature Publishing Group},
136
- doi = {10.1038/s41592-024-02291-w}
137
- }
138
- </code></pre>
139
- </details>
140
-
141
- PTI provides volumetric reconstructions of mean permittivity ($\propto$ material density), differential permittivity ($\propto$ material anisotropy), 3D orientation, and optic sign. The following figure summarizes PTI acquisition and reconstruction with a small optical section of the mouse brain tissue:
142
-
143
- ![Data_flow](https://github.com/mehta-lab/waveorder/blob/main/readme.png?raw=true)
144
-
145
- ## Examples
146
- The [examples](https://github.com/mehta-lab/waveorder/tree/main/examples) illustrate simulations and reconstruction for 2D QLIPP, 3D phase from brightfield, and 2D/3D PTI methods.
147
-
148
- If you are interested in deploying QLIPP or phase from brightbrield, or fluorescence deconvolution for label-agnostic imaging at scale, checkout our [napari plugin](https://www.napari-hub.org/plugins/recOrder-napari), [`recOrder-napari`](https://github.com/mehta-lab/recOrder).
149
-
150
- ## Citation
151
-
152
- Please cite this repository, along with the relevant preprint or paper, if you use or adapt this code. The citation information can be found by clicking "Cite this repository" button in the About section in the right sidebar.
153
-
154
- ## Installation
155
-
156
- Create a virtual environment:
157
-
158
- ```sh
159
- conda create -y -n waveorder python=3.10
160
- conda activate waveorder
161
- ```
162
-
163
- Install `waveorder` from PyPI:
164
-
165
- ```sh
166
- pip install waveorder
167
- ```
168
-
169
- Use `waveorder` in your scripts:
170
-
171
- ```sh
172
- python
173
- >>> import waveorder
174
- ```
175
-
176
- (Optional) Install example dependencies, clone the repository, and run an example script:
177
- ```sh
178
- pip install waveorder[examples]
179
- git clone https://github.com/mehta-lab/waveorder.git
180
- python waveorder/examples/models/phase_thick_3d.py
181
- ```
182
-
183
- (M1 users) `pytorch` has [incomplete GPU support](https://github.com/pytorch/pytorch/issues/77764),
184
- so please use `export PYTORCH_ENABLE_MPS_FALLBACK=1`
185
- to allow some operators to fallback to CPU
186
- if you plan to use GPU acceleration for polarization reconstruction.
@@ -1,25 +0,0 @@
1
- waveorder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- waveorder/_version.py,sha256=pbL_Q6fDSZl5UbKP04ZFdzrJpd1PO1gH7IwJCwLV7mk,411
3
- waveorder/background_estimator.py,sha256=gCIO6-232H0CGH4o6gnqW9KSYGOrXf5E9nD67WeF304,12399
4
- waveorder/correction.py,sha256=N0Ic6mqw3U7mqow4dKTOkNx2QYOLwedGNH7HiKV-M6s,3460
5
- waveorder/focus.py,sha256=4mg84Fe4V-oFplsuaU_VQU1_TEDoEfPggIAv6Is2dE4,6312
6
- waveorder/optics.py,sha256=Z0N9IN5AJ563eOISlFVJLS5K7lyfSjOcHVkzcLSKP1E,44325
7
- waveorder/sampling.py,sha256=OAqlfjEemX6tQV2a2S8X0wQx9JCSykcvVxvKr1CY3H0,2521
8
- waveorder/stokes.py,sha256=Wk9ZimzICIZLh1CkB0kQSCSBLeugkDeydwXTPd-M-po,15186
9
- waveorder/util.py,sha256=goT2OD6Zej4v3RT1tu_XAQtDWi94HiDlL4pJk2itt6s,71272
10
- waveorder/waveorder_reconstructor.py,sha256=SSSru4TOLB1VUOWMLHzMSboMbazgfslFXrjOpnwmqFk,152107
11
- waveorder/waveorder_simulator.py,sha256=_HCmDZkACUGzgwnaI-q0PjsL1gRE55IQuaWw-wtAjCU,45856
12
- waveorder/models/inplane_oriented_thick_pol3d.py,sha256=jEpMcAZ6tIg9Kg-lHpbH0vBAphSGZGUAqLyDc0hv_bs,5979
13
- waveorder/models/inplane_oriented_thick_pol3d_vector.py,sha256=09-Qu6Ka3S2GmkcmGIyVbQCYP1I_S9O1HvDBZDQ7AlQ,10817
14
- waveorder/models/isotropic_fluorescent_thick_3d.py,sha256=TuE5QlScy6pdCZyrWJifJ6UJMQT15lv8HhkNa_cQfFs,6713
15
- waveorder/models/isotropic_thin_3d.py,sha256=c-1eKknNWKxDiMNUi0wBf6YeXhUQiUR-zguH8M7En_k,10941
16
- waveorder/models/phase_thick_3d.py,sha256=2gq5pd6BPxDmkqnf9bvbOfraD2CeGBr0GU1s9cYBTms,8374
17
- waveorder/visuals/jupyter_visuals.py,sha256=w-vlMtfyl3I1ACNfYIW4fbS9TIMAVittNj3GbjlRYz4,58121
18
- waveorder/visuals/matplotlib_visuals.py,sha256=e-4LrHPFU--j3gbUoZrO8WHpDIYNZDFu8vqBZyhyiG4,10922
19
- waveorder/visuals/napari_visuals.py,sha256=gI420pgOzun4Elx__txdk1eEBcTIBB6Gpln-6n8Wo1k,2385
20
- waveorder/visuals/utils.py,sha256=6vdZmpvFGHwSwxeV8vCKWQ0MBOrDokSIJhjdBtJLHeM,1002
21
- waveorder-2.2.0.dist-info/LICENSE,sha256=auz4oGH1A-xZtoiR2zuXIk-Hii4v9aGgFVBqn7nfpms,1509
22
- waveorder-2.2.0.dist-info/METADATA,sha256=D7tFPrufseWBEz4-kPpR6pejV_GtA91ll7SsO4u3qas,9677
23
- waveorder-2.2.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
24
- waveorder-2.2.0.dist-info/top_level.txt,sha256=i3zReXiiMTnyPk93W7aEz_oEfsLnfR_Kzl7PW7kUslA,10
25
- waveorder-2.2.0.dist-info/RECORD,,