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.
waveorder/optics.py CHANGED
@@ -133,7 +133,7 @@ def generate_pupil(frr, NA, lamb_in):
133
133
  numerical aperture of the pupil function (normalized by the refractive index of the immersion media)
134
134
 
135
135
  lamb_in : float
136
- wavelength of the light in free space
136
+ wavelength of the light (inside the immersion media)
137
137
  in units of length (inverse of frr's units)
138
138
 
139
139
  Returns
@@ -225,103 +225,6 @@ def gen_sector_Pupil(fxx, fyy, NA, lamb_in, sector_angle, rotation_angle):
225
225
  return Pupil_sector
226
226
 
227
227
 
228
- def rotation_matrix(nu_z, nu_y, nu_x, wavelength):
229
- nu_perp_squared = nu_x**2 + nu_y**2
230
- nu_zz = wavelength * nu_z - 1
231
-
232
- R_xx = (wavelength * nu_x**2 * nu_z + nu_y**2) / nu_perp_squared
233
- R_yy = (wavelength * nu_y**2 * nu_z + nu_x**2) / nu_perp_squared
234
- R_xy = nu_x * nu_y * nu_zz / nu_perp_squared
235
-
236
- row0 = torch.stack((-wavelength * nu_y, -wavelength * nu_x), dim=0)
237
- row1 = torch.stack((R_yy, R_xy), dim=0)
238
- row2 = torch.stack((R_xy, R_xx), dim=0)
239
-
240
- out = torch.stack((row0, row1, row2), dim=0)
241
-
242
- # KLUDGE: fix the DC term manually, avoiding nan
243
- out[..., 0, 0] = torch.tensor([[0, 0], [1, 0], [0, 1]])[..., None]
244
-
245
- return torch.nan_to_num(out, nan=0.0)
246
-
247
-
248
- def generate_vector_source_defocus_pupil(
249
- x_frequencies,
250
- y_frequencies,
251
- z_position_list,
252
- defocus_pupil,
253
- input_jones,
254
- ill_pupil,
255
- wavelength,
256
- ):
257
- ill_pupil_3d = torch.einsum(
258
- "zyx,yx->zyx", torch.fft.fft(defocus_pupil, dim=0), ill_pupil
259
- ).abs() # make this real
260
-
261
- freq_shape = z_position_list.shape + x_frequencies.shape
262
-
263
- y_broadcast = torch.broadcast_to(y_frequencies[None, :, :], freq_shape)
264
- x_broadcast = torch.broadcast_to(x_frequencies[None, :, :], freq_shape)
265
- z_broadcast = np.sqrt(wavelength ** (-2) - x_broadcast**2 - y_broadcast**2)
266
-
267
- # Calculate rotation matrix
268
- rotations = rotation_matrix(
269
- z_broadcast, y_broadcast, x_broadcast, wavelength
270
- ).type(torch.complex64)
271
-
272
- # TEMPORARY SIMPLIFY ROTATIONS "TURN OFF ROTATIONS"
273
- # 3x2 IDENTITY MATRIX
274
- rotations = torch.zeros_like(rotations)
275
- rotations[1, 0, ...] = 1
276
- rotations[2, 1, ...] = 1
277
-
278
- # Main calculation in the frequency domain
279
- source_pupil = torch.einsum(
280
- "ijzyx,j,zyx->izyx", rotations, input_jones, ill_pupil_3d
281
- )
282
-
283
- # Convert back to defocus pupil
284
- source_defocus_pupil = torch.fft.ifft(source_pupil, dim=-3)
285
-
286
- return source_defocus_pupil
287
-
288
-
289
- def generate_vector_detection_defocus_pupil(
290
- x_frequencies,
291
- y_frequencies,
292
- z_position_list,
293
- det_defocus_pupil,
294
- det_pupil,
295
- wavelength,
296
- ):
297
- # TODO: refactor redundancy with illumination pupil
298
- det_pupil_3d = torch.einsum(
299
- "zyx,yx->zyx", torch.fft.ifft(det_defocus_pupil, dim=0), det_pupil
300
- )
301
-
302
- # Calculate zyx_frequency grid (inelegant)
303
- z_frequencies = torch.fft.ifft(z_position_list)
304
- freq_shape = z_frequencies.shape + x_frequencies.shape
305
- z_broadcast = torch.broadcast_to(z_frequencies[:, None, None], freq_shape)
306
- y_broadcast = torch.broadcast_to(y_frequencies[None, :, :], freq_shape)
307
- x_broadcast = torch.broadcast_to(x_frequencies[None, :, :], freq_shape)
308
-
309
- # Calculate rotation matrix
310
- rotations = rotation_matrix(
311
- z_broadcast, y_broadcast, x_broadcast, wavelength
312
- ).type(torch.complex64)
313
-
314
- # Main calculation in the frequency domain
315
- vector_detection_pupil = torch.einsum(
316
- "jizyx,zyx->ijzyx", rotations, det_pupil_3d
317
- )
318
-
319
- # Convert back to defocus pupil
320
- detection_defocus_pupil = torch.fft.fft(vector_detection_pupil, dim=-3)
321
-
322
- return detection_defocus_pupil
323
-
324
-
325
228
  def Source_subsample(Source_cont, NAx_coord, NAy_coord, subsampled_NA=0.1):
326
229
  """
327
230
 
@@ -397,7 +300,7 @@ def generate_propagation_kernel(
397
300
  wavelength : float
398
301
  wavelength of the light in the immersion media
399
302
 
400
- z_position_list : torch.tensor
303
+ z_position_list : torch.tensor or list
401
304
  1D array of defocused z positions with the size of (Z)
402
305
 
403
306
  Returns
@@ -407,16 +310,15 @@ def generate_propagation_kernel(
407
310
 
408
311
  """
409
312
 
410
- oblique_factor = ((1 - wavelength**2 * radial_frequencies**2)) ** (
411
- 1 / 2
412
- ) / wavelength
413
- oblique_factor = torch.nan_to_num(oblique_factor, nan=0.0)
313
+ oblique_factor = (
314
+ (1 - wavelength**2 * radial_frequencies**2) * pupil_support
315
+ ) ** (1 / 2) / wavelength
414
316
 
415
317
  propagation_kernel = pupil_support[None, :, :] * torch.exp(
416
318
  1j
417
319
  * 2
418
320
  * np.pi
419
- * z_position_list[:, None, None]
321
+ * torch.tensor(z_position_list)[:, None, None]
420
322
  * oblique_factor[None, :, :]
421
323
  )
422
324
 
@@ -424,11 +326,7 @@ def generate_propagation_kernel(
424
326
 
425
327
 
426
328
  def generate_greens_function_z(
427
- radial_frequencies,
428
- pupil_support,
429
- wavelength_illumination,
430
- z_position_list,
431
- axially_even=True,
329
+ radial_frequencies, pupil_support, wavelength_illumination, z_position_list
432
330
  ):
433
331
  """
434
332
 
@@ -445,14 +343,9 @@ def generate_greens_function_z(
445
343
  wavelength_illumination : float
446
344
  wavelength of the light in the immersion media
447
345
 
448
- z_position_list : torch.tensor
346
+ z_position_list : torch.tensor or list
449
347
  1D array of defocused z position with the size of (Z,)
450
348
 
451
- axially_even : bool
452
- For backwards compatibility with legacy phase reconstruction.
453
- Ideally the legacy phase reconstruction should be unified with
454
- the new reconstructions, and this parameter should be removed.
455
-
456
349
  Returns
457
350
  -------
458
351
  greens_function_z : torch.tensor
@@ -465,96 +358,46 @@ def generate_greens_function_z(
465
358
  * pupil_support
466
359
  ) ** (1 / 2) / wavelength_illumination
467
360
 
468
- if axially_even:
469
- z_positions = torch.abs(z_position_list[:, None, None])
470
- else:
471
- z_positions = z_position_list[:, None, None]
472
-
473
361
  greens_function_z = (
474
362
  -1j
475
363
  / 4
476
364
  / np.pi
477
365
  * pupil_support[None, :, :]
478
- * torch.exp(1j * 2 * np.pi * z_positions * oblique_factor[None, :, :])
366
+ * torch.exp(
367
+ 1j
368
+ * 2
369
+ * np.pi
370
+ * torch.tensor(z_position_list)[:, None, None]
371
+ * oblique_factor[None, :, :]
372
+ )
479
373
  / (oblique_factor[None, :, :] + 1e-15)
480
374
  )
481
375
 
482
376
  return greens_function_z
483
377
 
484
378
 
485
- def generate_defocus_greens_tensor(
486
- fxx, fyy, G_fun_z, Pupil_support, lambda_in
487
- ):
488
- """
489
-
490
- generate forward dyadic Green's function in u_x, u_y, z space
491
-
492
- Parameters
493
- ----------
494
- fxx : tensor.Tensor
495
- x component of 2D spatial frequency array with the size of (Ny, Nx)
496
-
497
- fyy : tensor.Tensor
498
- y component of 2D spatial frequency array with the size of (Ny, Nx)
499
-
500
- G_fun_z : tensor.Tensor
501
- forward Green's function in u_x, u_y, z space with size of (Nz, Ny, Nx)
502
-
503
- Pupil_support : tensor.Tensor
504
- the array that defines the support of the pupil function with the size of (Ny, Nx)
505
-
506
- lambda_in : float
507
- wavelength of the light in the immersion media
508
-
509
- Returns
510
- -------
511
- G_tensor_z : tensor.Tensor
512
- forward dyadic Green's function in u_x, u_y, z space with the size of (3, 3, Nz, Ny, Nx)
513
- """
514
-
515
- fr = (fxx**2 + fyy**2) ** (1 / 2)
516
- oblique_factor = ((1 - lambda_in**2 * fr**2) * Pupil_support) ** (
517
- 1 / 2
518
- ) / lambda_in
519
-
520
- diff_filter = torch.zeros((3,) + G_fun_z.shape, dtype=torch.complex64)
521
- diff_filter[0] = (1j * 2 * np.pi * oblique_factor)[None, ...]
522
- diff_filter[1] = (1j * 2 * np.pi * fyy * Pupil_support)[None, ...]
523
- diff_filter[2] = (1j * 2 * np.pi * fxx * Pupil_support)[None, ...]
524
-
525
- G_tensor_z = torch.zeros((3, 3) + G_fun_z.shape, dtype=torch.complex64)
526
-
527
- for i in range(3):
528
- for j in range(3):
529
- G_tensor_z[i, j] = (
530
- G_fun_z
531
- * diff_filter[i]
532
- * diff_filter[j]
533
- / (2 * np.pi / lambda_in) ** 2
534
- )
535
- if i == j:
536
- G_tensor_z[i, i] += G_fun_z
537
-
538
- return G_tensor_z
539
-
540
-
541
379
  def gen_dyadic_Greens_tensor_z(fxx, fyy, G_fun_z, Pupil_support, lambda_in):
542
380
  """
543
- keeping for backwards compatibility
544
381
 
545
382
  generate forward dyadic Green's function in u_x, u_y, z space
383
+
546
384
  Parameters
547
385
  ----------
548
386
  fxx : numpy.ndarray
549
387
  x component of 2D spatial frequency array with the size of (Ny, Nx)
388
+
550
389
  fyy : numpy.ndarray
551
390
  y component of 2D spatial frequency array with the size of (Ny, Nx)
391
+
552
392
  G_fun_z : numpy.ndarray
553
393
  forward Green's function in u_x, u_y, z space with size of (Ny, Nx, Nz)
394
+
554
395
  Pupil_support : numpy.ndarray
555
396
  the array that defines the support of the pupil function with the size of (Ny, Nx)
397
+
556
398
  lambda_in : float
557
399
  wavelength of the light in the immersion media
400
+
558
401
  Returns
559
402
  -------
560
403
  G_tensor_z : numpy.ndarray
@@ -584,6 +427,7 @@ def gen_dyadic_Greens_tensor_z(fxx, fyy, G_fun_z, Pupil_support, lambda_in):
584
427
  )
585
428
  if i == j:
586
429
  G_tensor_z[i, i] += G_fun_z
430
+
587
431
  return G_tensor_z
588
432
 
589
433
 
@@ -717,60 +561,6 @@ def gen_dyadic_Greens_tensor(G_real, ps, psz, lambda_in, space="real"):
717
561
  )
718
562
 
719
563
 
720
- def generate_greens_tensor_spectrum(
721
- zyx_shape,
722
- zyx_pixel_size,
723
- wavelength,
724
- ):
725
- """
726
- Parameters
727
- ----------
728
- zyx_shape : tuple
729
- zyx_pixel_size : tuple
730
- wavelength : float
731
- wavelength in medium
732
-
733
- Returns
734
- -------
735
- torch.tensor
736
- Green's tensor spectrum
737
- """
738
- Z, Y, X = zyx_shape
739
- dZ, dY, dX = zyx_pixel_size
740
-
741
- z_step = torch.fft.ifftshift(
742
- (torch.arange(Z) - Z // 2) * dZ
743
- )
744
- y_step = torch.fft.ifftshift((torch.arange(Y) - Y // 2) * dY)
745
- x_step = torch.fft.ifftshift((torch.arange(X) - X // 2) * dX)
746
-
747
- zz = torch.broadcast_to(z_step[:, None, None], (Z, Y, X))
748
- yy = torch.broadcast_to(y_step[None, :, None], (Z, Y, X))
749
- xx = torch.broadcast_to(x_step[None, None, :], (Z, Y, X))
750
-
751
- rr = torch.sqrt(xx**2 + yy**2 + zz**2)
752
- rhat = torch.stack([zz, yy, xx], dim=0) / rr
753
-
754
- scalar_g = torch.exp(1j * 2 * torch.pi * rr / wavelength) / (
755
- 4 * torch.pi * rr
756
- )
757
-
758
- eye = torch.zeros((3, 3, Z, Y, X))
759
- eye[0, 0] = 1
760
- eye[1, 1] = 1
761
- eye[2, 2] = 1
762
-
763
- Q = eye - torch.einsum("izyx,jzyx->ijzyx", rhat, rhat)
764
- g_3d = Q * scalar_g
765
- g_3d = torch.nan_to_num(g_3d)
766
-
767
- G_3D = torch.fft.fftn(g_3d, dim=(-3, -2, -1))
768
- G_3D = torch.imag(G_3D) * 1j
769
- G_3D /= torch.amax(torch.abs(G_3D))
770
-
771
- return G_3D
772
-
773
-
774
564
  def compute_weak_object_transfer_function_2d(
775
565
  illumination_pupil, detection_pupil
776
566
  ):
waveorder/util.py CHANGED
@@ -331,15 +331,12 @@ def gen_coordinate(img_dim, ps):
331
331
  return (xx, yy, fxx, fyy)
332
332
 
333
333
 
334
- def generate_frequencies(img_dim, ps):
334
+ def generate_radial_frequencies(img_dim, ps):
335
335
  fy = torch.fft.fftfreq(img_dim[0], ps)
336
336
  fx = torch.fft.fftfreq(img_dim[1], ps)
337
- fyy, fxx = torch.meshgrid(fy, fx, indexing="ij")
338
- return fyy, fxx
339
337
 
338
+ fyy, fxx = torch.meshgrid(fy, fx, indexing="ij")
340
339
 
341
- def generate_radial_frequencies(img_dim, ps):
342
- fyy, fxx = generate_frequencies(img_dim, ps)
343
340
  return torch.sqrt(fyy**2 + fxx**2)
344
341
 
345
342
 
@@ -2242,52 +2239,3 @@ def orientation_3D_continuity_map(
2242
2239
  retardance_pr_avg /= np.max(retardance_pr_avg)
2243
2240
 
2244
2241
  return retardance_pr_avg
2245
-
2246
-
2247
- def pauli():
2248
- # yx order
2249
- # trace-orthogonal normalization
2250
- # torch.einsum("kij,lji->kl", pauli(), pauli()) == torch.eye(4)
2251
-
2252
- # intensity, x-y, +45-(-45), LCP-RCP
2253
- # yx
2254
- # yx
2255
- a = 2**-0.5
2256
- sigma = torch.tensor(
2257
- [
2258
- [[a, 0], [0, a]],
2259
- [[-a, 0], [0, a]],
2260
- [[0, a], [a, 0]],
2261
- [[0, 1j * a], [-1j * a, 0]],
2262
- ]
2263
- )
2264
- return sigma
2265
-
2266
-
2267
- def gellmann():
2268
- # zyx order
2269
- # trace-orthogonal normalization
2270
- # torch.einsum("kij,lji->kl", gellmann(), gellmann()) == torch.eye(9)
2271
- #
2272
- # lexicographical order of the Gell-Mann matrices
2273
- # 00, 1-1, 10, 11, 2-2, 2-1, 20, 21, 22
2274
- #
2275
- # zyx
2276
- # zyx
2277
- a = 3**-0.5
2278
- c = 2**-0.5
2279
- d = -(6**-0.5)
2280
- e = 2 * (6**-0.5)
2281
- return torch.tensor(
2282
- [
2283
- [[a, 0, 0], [0, a, 0], [0, 0, a]],
2284
- [[0, 0, -c], [0, 0, 0], [c, 0, 0]],
2285
- [[0, 0, 0], [0, 0, -c], [0, c, 0]],
2286
- [[0, -c, 0], [c, 0, 0], [0, 0, 0]],
2287
- [[0, 0, 0], [0, 0, c], [0, c, 0]], #
2288
- [[0, c, 0], [c, 0, 0], [0, 0, 0]],
2289
- [[e, 0, 0], [0, d, 0], [0, 0, d]],
2290
- [[0, 0, c], [0, 0, 0], [c, 0, 0]],
2291
- [[0, 0, 0], [0, -c, 0], [0, 0, c]], #
2292
- ], dtype=torch.complex64
2293
- )
@@ -8,7 +8,11 @@ from ipywidgets import (
8
8
  Image,
9
9
  Layout,
10
10
  interact,
11
+ interactive,
12
+ fixed,
13
+ interact_manual,
11
14
  HBox,
15
+ VBox,
12
16
  )
13
17
  from matplotlib.colors import hsv_to_rgb
14
18
  from matplotlib.colors import Normalize
@@ -172,7 +176,7 @@ def image_stack_viewer_fast(
172
176
  else:
173
177
  raise ValueError('origin can only be either "upper" or "lower"')
174
178
 
175
- im_wgt = Image(
179
+ im_wgt = Image(
176
180
  value=im_dict[0],
177
181
  layout=Layout(height=str(size[0]) + "px", width=str(size[1]) + "px"),
178
182
  )
@@ -1924,4 +1928,4 @@ def orientation_3D_hist(
1924
1928
  if colorbar:
1925
1929
  fig.colorbar(img, ax=ax[row_idx, col_idx])
1926
1930
 
1927
- return fig, ax
1931
+ return fig, ax
@@ -3,7 +3,6 @@ import matplotlib.pyplot as plt
3
3
  import itertools
4
4
  import time
5
5
  import os
6
- import warnings
7
6
  from numpy.fft import fft, ifft, fft2, ifft2, fftn, ifftn, fftshift, ifftshift
8
7
  from IPython import display
9
8
  from scipy.ndimage import uniform_filter
@@ -161,8 +160,8 @@ def instrument_matrix_calibration(I_cali_norm, I_meas):
161
160
 
162
161
 
163
162
  class waveorder_microscopy:
163
+
164
164
  """
165
- DEPRECATED: Please see `waveorder.models` for maintained alternatives.
166
165
 
167
166
  waveorder_microscopy contains reconstruction algorithms for label-free
168
167
  microscopy with various types of dataset:
@@ -368,10 +367,6 @@ class waveorder_microscopy:
368
367
  initialize the system parameters for phase and orders microscopy
369
368
 
370
369
  """
371
- warnings.warn(
372
- "Please see `waveorder.models` for maintained alternatives.",
373
- category=DeprecationWarning,
374
- )
375
370
 
376
371
  t0 = time.time()
377
372
 
@@ -737,7 +732,9 @@ class waveorder_microscopy:
737
732
  wave_vec_norm_x = self.lambda_illu * self.fxx
738
733
  wave_vec_norm_y = self.lambda_illu * self.fyy
739
734
  wave_vec_norm_z = (
740
- np.maximum(0, 1 - wave_vec_norm_x**2 - wave_vec_norm_y**2)
735
+ np.maximum(
736
+ 0, 1 - wave_vec_norm_x**2 - wave_vec_norm_y**2
737
+ )
741
738
  ) ** (0.5)
742
739
 
743
740
  incident_theta = np.arctan2(
@@ -4020,7 +4017,9 @@ class fluorescence_microscopy:
4020
4017
  S1_stack = cp.array(S1_stack)
4021
4018
  S2_stack = cp.array(S2_stack)
4022
4019
 
4023
- anisotropy = cp.asnumpy(0.5 * cp.sqrt(S1_stack**2 + S2_stack**2))
4020
+ anisotropy = cp.asnumpy(
4021
+ 0.5 * cp.sqrt(S1_stack**2 + S2_stack**2)
4022
+ )
4024
4023
  orientation = cp.asnumpy(
4025
4024
  (0.5 * cp.arctan2(S2_stack, S1_stack)) % np.pi
4026
4025
  )
@@ -0,0 +1,147 @@
1
+ Metadata-Version: 2.1
2
+ Name: waveorder
3
+ Version: 2.2.0rc0
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 <2,>=1.21
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.2.1
62
+ Provides-Extra: dev
63
+ Requires-Dist: pytest ; extra == 'dev'
64
+ Requires-Dist: pytest-cov ; extra == 'dev'
65
+
66
+ # waveorder
67
+
68
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/waveorder)
69
+ [![Downloads](https://pepy.tech/badge/waveorder)](https://pepy.tech/project/waveorder)
70
+ [![Python package index](https://img.shields.io/pypi/v/waveorder.svg)](https://pypi.org/project/waveorder)
71
+ [![Development Status](https://img.shields.io/pypi/status/napari.svg)](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha)
72
+
73
+ This computational imaging library enables wave-optical simulation and reconstruction of optical properties that report microscopic architectural order.
74
+
75
+ ## Computational label-free imaging
76
+
77
+ This vectorial wave simulator and reconstructor 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.
78
+
79
+ The acquisition, calibration, background correction, reconstruction, and applications of PTI are described in the following [preprint](https://doi.org/10.1101/2020.12.15.422951):
80
+
81
+ ```bibtex
82
+ L.-H. Yeh, I. E. Ivanov, B. B. Chhun, S.-M. Guo, E. Hashemi, J. R. Byrum, J. A. Pérez-Bermejo, H. Wang, Y. Yu, P. G. Kazansky, B. R. Conklin, M. H. Han, and S. B. Mehta, "uPTI: uniaxial permittivity tensor imaging of intrinsic density and anisotropy," bioRxiv 2020.12.15.422951 (2020).
83
+ ```
84
+
85
+ In addition to PTI, `waveorder` enables simulations and reconstructions of subsets of label-free measurements with subsets of the acquired data:
86
+
87
+ 1. Reconstruction of 2D or 3D phase, projected retardance, and in-plane orientation from a polarization-diverse volumetric brightfield acquisition ([QLIPP](https://elifesciences.org/articles/55502))
88
+
89
+ 2. Reconstruction of 2D or 3D phase from a volumetric brightfield acquisition ([2D](https://www.osapublishing.org/ao/abstract.cfm?uri=ao-54-28-8566)/[3D (PODT)](https://www.osapublishing.org/ao/abstract.cfm?uri=ao-57-1-a205) phase)
90
+
91
+ 3. Reconstruction of 2D or 3D 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)
92
+
93
+ 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:
94
+
95
+ ![Data_flow](https://github.com/mehta-lab/waveorder/blob/main/readme.png?raw=true)
96
+
97
+
98
+ The [examples](https://github.com/mehta-lab/waveorder/tree/main/examples) illustrate simulations and reconstruction for 2D QLIPP, 3D PODT, and 2D/3D PTI methods.
99
+
100
+ If you are interested in deploying QLIPP or PODT for label-free imaging at scale, checkout our [napari plugin](https://www.napari-hub.org/plugins/recOrder-napari), [`recOrder-napari`](https://github.com/mehta-lab/recOrder).
101
+
102
+ ## Correlative imaging
103
+
104
+ In addition to label-free reconstruction algorithms, `waveorder` also implements widefield fluorescence and fluorescence polarization reconstruction algorithms for correlative label-free and fluorescence imaging.
105
+
106
+ 1. Correlative measurements of biomolecular density and orientation from polarization-diverse widefield imaging ([multimodal Instant PolScope](https://opg.optica.org/boe/fulltext.cfm?uri=boe-13-5-3102&id=472350))
107
+
108
+ We provide an [example notebook](https://github.com/mehta-lab/waveorder/blob/main/examples/documentation/fluorescence_deconvolution/fluorescence_deconv.ipynb) for widefield fluorescence deconvolution.
109
+
110
+ ## Citation
111
+
112
+ 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.
113
+
114
+ ## Installation
115
+
116
+ (Optional but recommended) install [anaconda](https://www.anaconda.com/products/distribution) and create a virtual environment:
117
+
118
+ ```sh
119
+ conda create -y -n waveorder python=3.11
120
+ conda activate waveorder
121
+ ```
122
+
123
+ Install `waveorder` from PyPI:
124
+
125
+ ```sh
126
+ pip install waveorder
127
+ ```
128
+
129
+ Use `waveorder` in your scripts:
130
+
131
+ ```sh
132
+ python
133
+ >>> import waveorder
134
+ ```
135
+
136
+ (Optional) Download the repository, install `jupyter`, and experiment with the example notebooks
137
+
138
+ ```sh
139
+ git clone https://github.com/mehta-lab/waveorder.git
140
+ pip install jupyter
141
+ jupyter notebook ./waveorder/examples/
142
+ ```
143
+
144
+ (M1 users) `pytorch` has [incomplete GPU support](https://github.com/pytorch/pytorch/issues/77764),
145
+ so please use `export PYTORCH_ENABLE_MPS_FALLBACK=1`
146
+ to allow some operators to fallback to CPU
147
+ if you plan to use GPU acceleration for polarization reconstruction.
@@ -0,0 +1,20 @@
1
+ waveorder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ waveorder/_version.py,sha256=y62tGqTh86kx1L4FG_Wu91vm4c-zkqBUqEkv0mTr0sY,414
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=-mHYRMzDUNAz8kwF8xAR8RFuAEkWZzczKv2wnU5NuVs,37640
7
+ waveorder/stokes.py,sha256=Wk9ZimzICIZLh1CkB0kQSCSBLeugkDeydwXTPd-M-po,15186
8
+ waveorder/util.py,sha256=3k810fpb7pIEcc4fii6gP4wTerxCtFYgG82SiDzUTtQ,69898
9
+ waveorder/visual.py,sha256=SFzkQdMit3HyqTqrgzX4w5bRwz8QuwGumzVayi3DwDM,58171
10
+ waveorder/waveorder_reconstructor.py,sha256=5-jlbK8gcJqHbFhiWt-TcETV5cdLHSAXq9O3JupPXD0,151942
11
+ waveorder/waveorder_simulator.py,sha256=_HCmDZkACUGzgwnaI-q0PjsL1gRE55IQuaWw-wtAjCU,45856
12
+ waveorder/models/inplane_oriented_thick_pol3d.py,sha256=Z7rfufrDeEkUYf2MlZsXyvKsZWHIJWujK357_z1BBg0,5809
13
+ waveorder/models/isotropic_fluorescent_thick_3d.py,sha256=Pzi2kM1OGmwQIrI6b5h9OeIOGzHssG30Wv8zDi4n4PQ,5395
14
+ waveorder/models/isotropic_thin_3d.py,sha256=E__ly_xF6Tw_bHLSHHPpd3p60t01LhIPiFrqfd5u1r4,8493
15
+ waveorder/models/phase_thick_3d.py,sha256=itGav-JUDcs7YXxxtdtFK95CuaKR759o9ubL7ms8lBk,6590
16
+ waveorder-2.2.0rc0.dist-info/LICENSE,sha256=auz4oGH1A-xZtoiR2zuXIk-Hii4v9aGgFVBqn7nfpms,1509
17
+ waveorder-2.2.0rc0.dist-info/METADATA,sha256=KItkcQO-Bl3Gj-rutxx1V89YkVGYovr-QFo-OUPnAHI,8249
18
+ waveorder-2.2.0rc0.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
19
+ waveorder-2.2.0rc0.dist-info/top_level.txt,sha256=i3zReXiiMTnyPk93W7aEz_oEfsLnfR_Kzl7PW7kUslA,10
20
+ waveorder-2.2.0rc0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (70.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5