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/_version.py +1 -1
- waveorder/models/inplane_oriented_thick_pol3d.py +12 -12
- waveorder/models/isotropic_fluorescent_thick_3d.py +34 -70
- waveorder/models/isotropic_thin_3d.py +32 -94
- waveorder/models/phase_thick_3d.py +43 -94
- waveorder/optics.py +22 -232
- waveorder/util.py +2 -54
- waveorder/{visuals/jupyter_visuals.py → visual.py} +6 -2
- waveorder/waveorder_reconstructor.py +7 -8
- waveorder-2.2.0rc0.dist-info/METADATA +147 -0
- waveorder-2.2.0rc0.dist-info/RECORD +20 -0
- {waveorder-2.2.0.dist-info → waveorder-2.2.0rc0.dist-info}/WHEEL +1 -1
- waveorder/models/inplane_oriented_thick_pol3d_vector.py +0 -351
- waveorder/sampling.py +0 -94
- waveorder/visuals/matplotlib_visuals.py +0 -335
- waveorder/visuals/napari_visuals.py +0 -77
- waveorder/visuals/utils.py +0 -31
- waveorder-2.2.0.dist-info/METADATA +0 -186
- waveorder-2.2.0.dist-info/RECORD +0 -25
- {waveorder-2.2.0.dist-info → waveorder-2.2.0rc0.dist-info}/LICENSE +0 -0
- {waveorder-2.2.0.dist-info → waveorder-2.2.0rc0.dist-info}/top_level.txt +0 -0
waveorder/_version.py
CHANGED
|
@@ -7,7 +7,7 @@ from torch import Tensor
|
|
|
7
7
|
from waveorder import correction, stokes, util
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
def generate_test_phantom(yx_shape
|
|
10
|
+
def generate_test_phantom(yx_shape):
|
|
11
11
|
star, theta, _ = util.generate_star_target(yx_shape, blur_px=0.1)
|
|
12
12
|
retardance = 0.25 * star
|
|
13
13
|
orientation = (theta % np.pi) * (star > 1e-3)
|
|
@@ -17,13 +17,13 @@ def generate_test_phantom(yx_shape: Tuple[int, int]) -> Tuple[Tensor, Tensor, Te
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def calculate_transfer_function(
|
|
20
|
-
swing
|
|
21
|
-
scheme
|
|
22
|
-
)
|
|
20
|
+
swing,
|
|
21
|
+
scheme,
|
|
22
|
+
):
|
|
23
23
|
return stokes.calculate_intensity_to_stokes_matrix(swing, scheme=scheme)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def visualize_transfer_function(viewer, intensity_to_stokes_matrix
|
|
26
|
+
def visualize_transfer_function(viewer, intensity_to_stokes_matrix):
|
|
27
27
|
viewer.add_image(
|
|
28
28
|
intensity_to_stokes_matrix.cpu().numpy(),
|
|
29
29
|
name="Intensity to stokes matrix",
|
|
@@ -31,12 +31,12 @@ def visualize_transfer_function(viewer, intensity_to_stokes_matrix: Tensor) -> N
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def apply_transfer_function(
|
|
34
|
-
retardance
|
|
35
|
-
orientation
|
|
36
|
-
transmittance
|
|
37
|
-
depolarization
|
|
38
|
-
intensity_to_stokes_matrix
|
|
39
|
-
)
|
|
34
|
+
retardance,
|
|
35
|
+
orientation,
|
|
36
|
+
transmittance,
|
|
37
|
+
depolarization,
|
|
38
|
+
intensity_to_stokes_matrix,
|
|
39
|
+
):
|
|
40
40
|
stokes_params = stokes.stokes_after_adr(
|
|
41
41
|
retardance, orientation, transmittance, depolarization
|
|
42
42
|
)
|
|
@@ -59,7 +59,7 @@ def apply_inverse_transfer_function(
|
|
|
59
59
|
project_stokes_to_2d: bool = False,
|
|
60
60
|
flip_orientation: bool = False,
|
|
61
61
|
rotate_orientation: bool = False,
|
|
62
|
-
) -> Tuple[Tensor
|
|
62
|
+
) -> Tuple[Tensor]:
|
|
63
63
|
"""Reconstructs retardance, orientation, transmittance, and depolarization
|
|
64
64
|
from czyx_data and an intensity_to_stokes_matrix, providing options for
|
|
65
65
|
background correction, projection, and orientation transformations.
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
from typing import Literal
|
|
2
2
|
|
|
3
|
-
import numpy as np
|
|
4
3
|
import torch
|
|
5
4
|
from torch import Tensor
|
|
6
5
|
|
|
7
|
-
from waveorder import optics,
|
|
8
|
-
from waveorder.visuals.napari_visuals import add_transfer_function_to_viewer
|
|
6
|
+
from waveorder import optics, util
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
def generate_test_phantom(
|
|
12
|
-
zyx_shape
|
|
13
|
-
yx_pixel_size
|
|
14
|
-
z_pixel_size
|
|
15
|
-
sphere_radius
|
|
16
|
-
)
|
|
10
|
+
zyx_shape,
|
|
11
|
+
yx_pixel_size,
|
|
12
|
+
z_pixel_size,
|
|
13
|
+
sphere_radius,
|
|
14
|
+
):
|
|
17
15
|
sphere, _, _ = util.generate_sphere_target(
|
|
18
16
|
zyx_shape, yx_pixel_size, z_pixel_size, sphere_radius
|
|
19
17
|
)
|
|
@@ -22,57 +20,14 @@ def generate_test_phantom(
|
|
|
22
20
|
|
|
23
21
|
|
|
24
22
|
def calculate_transfer_function(
|
|
25
|
-
zyx_shape
|
|
26
|
-
yx_pixel_size
|
|
27
|
-
z_pixel_size
|
|
28
|
-
wavelength_emission
|
|
29
|
-
z_padding
|
|
30
|
-
index_of_refraction_media
|
|
31
|
-
numerical_aperture_detection
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
transverse_nyquist = sampling.transverse_nyquist(
|
|
35
|
-
wavelength_emission,
|
|
36
|
-
numerical_aperture_detection, # ill = det for fluorescence
|
|
37
|
-
numerical_aperture_detection,
|
|
38
|
-
)
|
|
39
|
-
axial_nyquist = sampling.axial_nyquist(
|
|
40
|
-
wavelength_emission,
|
|
41
|
-
numerical_aperture_detection,
|
|
42
|
-
index_of_refraction_media,
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
yx_factor = int(np.ceil(yx_pixel_size / transverse_nyquist))
|
|
46
|
-
z_factor = int(np.ceil(z_pixel_size / axial_nyquist))
|
|
47
|
-
|
|
48
|
-
optical_transfer_function = _calculate_wrap_unsafe_transfer_function(
|
|
49
|
-
(
|
|
50
|
-
zyx_shape[0] * z_factor,
|
|
51
|
-
zyx_shape[1] * yx_factor,
|
|
52
|
-
zyx_shape[2] * yx_factor,
|
|
53
|
-
),
|
|
54
|
-
yx_pixel_size / yx_factor,
|
|
55
|
-
z_pixel_size / z_factor,
|
|
56
|
-
wavelength_emission,
|
|
57
|
-
z_padding,
|
|
58
|
-
index_of_refraction_media,
|
|
59
|
-
numerical_aperture_detection,
|
|
60
|
-
)
|
|
61
|
-
zyx_out_shape = (zyx_shape[0] + 2 * z_padding,) + zyx_shape[1:]
|
|
62
|
-
return sampling.nd_fourier_central_cuboid(
|
|
63
|
-
optical_transfer_function, zyx_out_shape
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def _calculate_wrap_unsafe_transfer_function(
|
|
68
|
-
zyx_shape: tuple[int, int, int],
|
|
69
|
-
yx_pixel_size: float,
|
|
70
|
-
z_pixel_size: float,
|
|
71
|
-
wavelength_emission: float,
|
|
72
|
-
z_padding: int,
|
|
73
|
-
index_of_refraction_media: float,
|
|
74
|
-
numerical_aperture_detection: float,
|
|
75
|
-
) -> Tensor:
|
|
23
|
+
zyx_shape,
|
|
24
|
+
yx_pixel_size,
|
|
25
|
+
z_pixel_size,
|
|
26
|
+
wavelength_emission,
|
|
27
|
+
z_padding,
|
|
28
|
+
index_of_refraction_media,
|
|
29
|
+
numerical_aperture_detection,
|
|
30
|
+
):
|
|
76
31
|
radial_frequencies = util.generate_radial_frequencies(
|
|
77
32
|
zyx_shape[1:], yx_pixel_size
|
|
78
33
|
)
|
|
@@ -108,18 +63,27 @@ def _calculate_wrap_unsafe_transfer_function(
|
|
|
108
63
|
return optical_transfer_function
|
|
109
64
|
|
|
110
65
|
|
|
111
|
-
def visualize_transfer_function(viewer, optical_transfer_function
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
torch.real(optical_transfer_function),
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
66
|
+
def visualize_transfer_function(viewer, optical_transfer_function, zyx_scale):
|
|
67
|
+
arrays = [
|
|
68
|
+
(torch.imag(optical_transfer_function), "Im(OTF)"),
|
|
69
|
+
(torch.real(optical_transfer_function), "Re(OTF)"),
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
for array in arrays:
|
|
73
|
+
lim = 0.1 * torch.max(torch.abs(array[0]))
|
|
74
|
+
viewer.add_image(
|
|
75
|
+
torch.fft.ifftshift(array[0]).cpu().numpy(),
|
|
76
|
+
name=array[1],
|
|
77
|
+
colormap="bwr",
|
|
78
|
+
contrast_limits=(-lim, lim),
|
|
79
|
+
scale=1 / zyx_scale,
|
|
80
|
+
)
|
|
81
|
+
viewer.dims.order = (0, 1, 2)
|
|
118
82
|
|
|
119
83
|
|
|
120
84
|
def apply_transfer_function(
|
|
121
|
-
zyx_object
|
|
122
|
-
)
|
|
85
|
+
zyx_object, optical_transfer_function, z_padding, background=10
|
|
86
|
+
):
|
|
123
87
|
"""Simulate imaging by applying a transfer function
|
|
124
88
|
|
|
125
89
|
Parameters
|
|
@@ -133,7 +97,7 @@ def apply_transfer_function(
|
|
|
133
97
|
Returns
|
|
134
98
|
-------
|
|
135
99
|
Simulated data : torch.Tensor
|
|
136
|
-
|
|
100
|
+
|
|
137
101
|
"""
|
|
138
102
|
if (
|
|
139
103
|
zyx_object.shape[0] + 2 * z_padding
|
|
@@ -164,7 +128,7 @@ def apply_inverse_transfer_function(
|
|
|
164
128
|
regularization_strength: float = 1e-3,
|
|
165
129
|
TV_rho_strength: float = 1e-3,
|
|
166
130
|
TV_iterations: int = 10,
|
|
167
|
-
)
|
|
131
|
+
):
|
|
168
132
|
"""Reconstructs fluorescence density from zyx_data and
|
|
169
133
|
an optical_transfer_function, providing options for z padding and
|
|
170
134
|
reconstruction algorithms.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
from typing import Literal, Tuple
|
|
2
2
|
|
|
3
|
-
import numpy as np
|
|
4
3
|
import torch
|
|
5
4
|
from torch import Tensor
|
|
6
5
|
|
|
7
|
-
from waveorder import optics,
|
|
6
|
+
from waveorder import optics, util
|
|
7
|
+
|
|
8
8
|
|
|
9
9
|
def generate_test_phantom(
|
|
10
|
-
yx_shape
|
|
11
|
-
yx_pixel_size
|
|
12
|
-
wavelength_illumination
|
|
13
|
-
index_of_refraction_media
|
|
14
|
-
index_of_refraction_sample
|
|
15
|
-
sphere_radius
|
|
16
|
-
)
|
|
10
|
+
yx_shape,
|
|
11
|
+
yx_pixel_size,
|
|
12
|
+
wavelength_illumination,
|
|
13
|
+
index_of_refraction_media,
|
|
14
|
+
index_of_refraction_sample,
|
|
15
|
+
sphere_radius,
|
|
16
|
+
):
|
|
17
17
|
sphere, _, _ = util.generate_sphere_target(
|
|
18
18
|
(3,) + yx_shape,
|
|
19
19
|
yx_pixel_size,
|
|
@@ -34,73 +34,15 @@ def generate_test_phantom(
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def calculate_transfer_function(
|
|
37
|
-
yx_shape
|
|
38
|
-
yx_pixel_size
|
|
39
|
-
z_position_list
|
|
40
|
-
wavelength_illumination
|
|
41
|
-
index_of_refraction_media
|
|
42
|
-
numerical_aperture_illumination
|
|
43
|
-
numerical_aperture_detection
|
|
44
|
-
invert_phase_contrast
|
|
45
|
-
)
|
|
46
|
-
transverse_nyquist = sampling.transverse_nyquist(
|
|
47
|
-
wavelength_illumination,
|
|
48
|
-
numerical_aperture_illumination,
|
|
49
|
-
numerical_aperture_detection,
|
|
50
|
-
)
|
|
51
|
-
yx_factor = int(np.ceil(yx_pixel_size / transverse_nyquist))
|
|
52
|
-
|
|
53
|
-
absorption_2d_to_3d_transfer_function, phase_2d_to_3d_transfer_function = (
|
|
54
|
-
_calculate_wrap_unsafe_transfer_function(
|
|
55
|
-
(
|
|
56
|
-
yx_shape[0] * yx_factor,
|
|
57
|
-
yx_shape[1] * yx_factor,
|
|
58
|
-
),
|
|
59
|
-
yx_pixel_size / yx_factor,
|
|
60
|
-
z_position_list,
|
|
61
|
-
wavelength_illumination,
|
|
62
|
-
index_of_refraction_media,
|
|
63
|
-
numerical_aperture_illumination,
|
|
64
|
-
numerical_aperture_detection,
|
|
65
|
-
invert_phase_contrast=invert_phase_contrast,
|
|
66
|
-
)
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
absorption_2d_to_3d_transfer_function_out = torch.zeros(
|
|
70
|
-
(len(z_position_list),) + tuple(yx_shape), dtype=torch.complex64
|
|
71
|
-
)
|
|
72
|
-
phase_2d_to_3d_transfer_function_out = torch.zeros(
|
|
73
|
-
(len(z_position_list),) + tuple(yx_shape), dtype=torch.complex64
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
for z in range(len(z_position_list)):
|
|
77
|
-
absorption_2d_to_3d_transfer_function_out[z] = (
|
|
78
|
-
sampling.nd_fourier_central_cuboid(
|
|
79
|
-
absorption_2d_to_3d_transfer_function[z], yx_shape
|
|
80
|
-
)
|
|
81
|
-
)
|
|
82
|
-
phase_2d_to_3d_transfer_function_out[z] = (
|
|
83
|
-
sampling.nd_fourier_central_cuboid(
|
|
84
|
-
phase_2d_to_3d_transfer_function[z], yx_shape
|
|
85
|
-
)
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
absorption_2d_to_3d_transfer_function_out,
|
|
90
|
-
phase_2d_to_3d_transfer_function_out,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
def _calculate_wrap_unsafe_transfer_function(
|
|
95
|
-
yx_shape: Tuple[int, int],
|
|
96
|
-
yx_pixel_size: float,
|
|
97
|
-
z_position_list: list,
|
|
98
|
-
wavelength_illumination: float,
|
|
99
|
-
index_of_refraction_media: float,
|
|
100
|
-
numerical_aperture_illumination: float,
|
|
101
|
-
numerical_aperture_detection: float,
|
|
102
|
-
invert_phase_contrast: bool = False,
|
|
103
|
-
) -> Tuple[Tensor, Tensor]:
|
|
37
|
+
yx_shape,
|
|
38
|
+
yx_pixel_size,
|
|
39
|
+
z_position_list,
|
|
40
|
+
wavelength_illumination,
|
|
41
|
+
index_of_refraction_media,
|
|
42
|
+
numerical_aperture_illumination,
|
|
43
|
+
numerical_aperture_detection,
|
|
44
|
+
invert_phase_contrast=False,
|
|
45
|
+
):
|
|
104
46
|
if invert_phase_contrast:
|
|
105
47
|
z_position_list = torch.flip(torch.tensor(z_position_list), dims=(0,))
|
|
106
48
|
|
|
@@ -148,14 +90,10 @@ def _calculate_wrap_unsafe_transfer_function(
|
|
|
148
90
|
|
|
149
91
|
def visualize_transfer_function(
|
|
150
92
|
viewer,
|
|
151
|
-
absorption_2d_to_3d_transfer_function
|
|
152
|
-
phase_2d_to_3d_transfer_function
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
function is a mixed 3D-to-2D transfer function, so it cannot reuse
|
|
156
|
-
util.add_transfer_function_to_viewer. If more 3D-to-2D transfer functions
|
|
157
|
-
are added, consider refactoring.
|
|
158
|
-
"""
|
|
93
|
+
absorption_2d_to_3d_transfer_function,
|
|
94
|
+
phase_2d_to_3d_transfer_function,
|
|
95
|
+
):
|
|
96
|
+
# TODO: consider generalizing w/ phase_thick_3d.visualize_transfer_function
|
|
159
97
|
arrays = [
|
|
160
98
|
(torch.imag(absorption_2d_to_3d_transfer_function), "Im(absorb TF)"),
|
|
161
99
|
(torch.real(absorption_2d_to_3d_transfer_function), "Re(absorb TF)"),
|
|
@@ -172,14 +110,14 @@ def visualize_transfer_function(
|
|
|
172
110
|
contrast_limits=(-lim, lim),
|
|
173
111
|
scale=(1, 1, 1),
|
|
174
112
|
)
|
|
175
|
-
viewer.dims.order = (
|
|
113
|
+
viewer.dims.order = (0, 1, 2)
|
|
176
114
|
|
|
177
115
|
|
|
178
116
|
def visualize_point_spread_function(
|
|
179
117
|
viewer,
|
|
180
|
-
absorption_2d_to_3d_transfer_function
|
|
181
|
-
phase_2d_to_3d_transfer_function
|
|
182
|
-
)
|
|
118
|
+
absorption_2d_to_3d_transfer_function,
|
|
119
|
+
phase_2d_to_3d_transfer_function,
|
|
120
|
+
):
|
|
183
121
|
arrays = [
|
|
184
122
|
(torch.fft.ifftn(absorption_2d_to_3d_transfer_function), "absorb PSF"),
|
|
185
123
|
(torch.fft.ifftn(phase_2d_to_3d_transfer_function), "phase PSF"),
|
|
@@ -198,11 +136,11 @@ def visualize_point_spread_function(
|
|
|
198
136
|
|
|
199
137
|
|
|
200
138
|
def apply_transfer_function(
|
|
201
|
-
yx_absorption
|
|
202
|
-
yx_phase
|
|
203
|
-
phase_2d_to_3d_transfer_function
|
|
204
|
-
absorption_2d_to_3d_transfer_function
|
|
205
|
-
)
|
|
139
|
+
yx_absorption,
|
|
140
|
+
yx_phase,
|
|
141
|
+
phase_2d_to_3d_transfer_function,
|
|
142
|
+
absorption_2d_to_3d_transfer_function,
|
|
143
|
+
):
|
|
206
144
|
# Very simple simulation, consider adding noise and bkg knobs
|
|
207
145
|
|
|
208
146
|
# simulate absorbing object
|
|
@@ -239,7 +177,7 @@ def apply_inverse_transfer_function(
|
|
|
239
177
|
TV_rho_strength: float = 1e-3,
|
|
240
178
|
TV_iterations: int = 10,
|
|
241
179
|
bg_filter: bool = True,
|
|
242
|
-
) -> Tuple[Tensor
|
|
180
|
+
) -> Tuple[Tensor]:
|
|
243
181
|
"""Reconstructs absorption and phase from zyx_data and a pair of
|
|
244
182
|
3D-to-2D transfer functions named absorption_2d_to_3d_transfer_function and
|
|
245
183
|
phase_2d_to_3d_transfer_function, providing options for reconstruction
|
|
@@ -4,19 +4,18 @@ import numpy as np
|
|
|
4
4
|
import torch
|
|
5
5
|
from torch import Tensor
|
|
6
6
|
|
|
7
|
-
from waveorder import optics,
|
|
7
|
+
from waveorder import optics, util
|
|
8
8
|
from waveorder.models import isotropic_fluorescent_thick_3d
|
|
9
|
-
from waveorder.visuals.napari_visuals import add_transfer_function_to_viewer
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def generate_test_phantom(
|
|
13
|
-
zyx_shape
|
|
14
|
-
yx_pixel_size
|
|
15
|
-
z_pixel_size
|
|
16
|
-
index_of_refraction_media
|
|
17
|
-
index_of_refraction_sample
|
|
18
|
-
sphere_radius
|
|
19
|
-
)
|
|
12
|
+
zyx_shape,
|
|
13
|
+
yx_pixel_size,
|
|
14
|
+
z_pixel_size,
|
|
15
|
+
index_of_refraction_media,
|
|
16
|
+
index_of_refraction_sample,
|
|
17
|
+
sphere_radius,
|
|
18
|
+
):
|
|
20
19
|
sphere, _, _ = util.generate_sphere_target(
|
|
21
20
|
zyx_shape,
|
|
22
21
|
yx_pixel_size,
|
|
@@ -32,70 +31,16 @@ def generate_test_phantom(
|
|
|
32
31
|
|
|
33
32
|
|
|
34
33
|
def calculate_transfer_function(
|
|
35
|
-
zyx_shape
|
|
36
|
-
yx_pixel_size
|
|
37
|
-
z_pixel_size
|
|
38
|
-
wavelength_illumination
|
|
39
|
-
z_padding
|
|
40
|
-
index_of_refraction_media
|
|
41
|
-
numerical_aperture_illumination
|
|
42
|
-
numerical_aperture_detection
|
|
43
|
-
invert_phase_contrast
|
|
44
|
-
)
|
|
45
|
-
transverse_nyquist = sampling.transverse_nyquist(
|
|
46
|
-
wavelength_illumination,
|
|
47
|
-
numerical_aperture_illumination,
|
|
48
|
-
numerical_aperture_detection,
|
|
49
|
-
)
|
|
50
|
-
axial_nyquist = sampling.axial_nyquist(
|
|
51
|
-
wavelength_illumination,
|
|
52
|
-
numerical_aperture_detection,
|
|
53
|
-
index_of_refraction_media,
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
yx_factor = int(np.ceil(yx_pixel_size / transverse_nyquist))
|
|
57
|
-
z_factor = int(np.ceil(z_pixel_size / axial_nyquist))
|
|
58
|
-
|
|
59
|
-
real_potential_transfer_function, imag_potential_transfer_function = (
|
|
60
|
-
_calculate_wrap_unsafe_transfer_function(
|
|
61
|
-
(
|
|
62
|
-
zyx_shape[0] * z_factor,
|
|
63
|
-
zyx_shape[1] * yx_factor,
|
|
64
|
-
zyx_shape[2] * yx_factor,
|
|
65
|
-
),
|
|
66
|
-
yx_pixel_size / yx_factor,
|
|
67
|
-
z_pixel_size / z_factor,
|
|
68
|
-
wavelength_illumination,
|
|
69
|
-
z_padding,
|
|
70
|
-
index_of_refraction_media,
|
|
71
|
-
numerical_aperture_illumination,
|
|
72
|
-
numerical_aperture_detection,
|
|
73
|
-
invert_phase_contrast=invert_phase_contrast,
|
|
74
|
-
)
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
zyx_out_shape = (zyx_shape[0] + 2 * z_padding,) + zyx_shape[1:]
|
|
78
|
-
return (
|
|
79
|
-
sampling.nd_fourier_central_cuboid(
|
|
80
|
-
real_potential_transfer_function, zyx_out_shape
|
|
81
|
-
),
|
|
82
|
-
sampling.nd_fourier_central_cuboid(
|
|
83
|
-
imag_potential_transfer_function, zyx_out_shape
|
|
84
|
-
),
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def _calculate_wrap_unsafe_transfer_function(
|
|
89
|
-
zyx_shape: tuple[int, int, int],
|
|
90
|
-
yx_pixel_size: float,
|
|
91
|
-
z_pixel_size: float,
|
|
92
|
-
wavelength_illumination: float,
|
|
93
|
-
z_padding: int,
|
|
94
|
-
index_of_refraction_media: float,
|
|
95
|
-
numerical_aperture_illumination: float,
|
|
96
|
-
numerical_aperture_detection: float,
|
|
97
|
-
invert_phase_contrast: bool = False,
|
|
98
|
-
) -> tuple[np.ndarray, np.ndarray]:
|
|
34
|
+
zyx_shape,
|
|
35
|
+
yx_pixel_size,
|
|
36
|
+
z_pixel_size,
|
|
37
|
+
wavelength_illumination,
|
|
38
|
+
z_padding,
|
|
39
|
+
index_of_refraction_media,
|
|
40
|
+
numerical_aperture_illumination,
|
|
41
|
+
numerical_aperture_detection,
|
|
42
|
+
invert_phase_contrast=False,
|
|
43
|
+
):
|
|
99
44
|
radial_frequencies = util.generate_radial_frequencies(
|
|
100
45
|
zyx_shape[1:], yx_pixel_size
|
|
101
46
|
)
|
|
@@ -127,7 +72,6 @@ def _calculate_wrap_unsafe_transfer_function(
|
|
|
127
72
|
det_pupil,
|
|
128
73
|
wavelength_illumination / index_of_refraction_media,
|
|
129
74
|
z_position_list,
|
|
130
|
-
axially_even=False,
|
|
131
75
|
)
|
|
132
76
|
|
|
133
77
|
(
|
|
@@ -147,28 +91,33 @@ def _calculate_wrap_unsafe_transfer_function(
|
|
|
147
91
|
|
|
148
92
|
def visualize_transfer_function(
|
|
149
93
|
viewer,
|
|
150
|
-
real_potential_transfer_function
|
|
151
|
-
imag_potential_transfer_function
|
|
152
|
-
zyx_scale
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
imag_potential_transfer_function,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
94
|
+
real_potential_transfer_function,
|
|
95
|
+
imag_potential_transfer_function,
|
|
96
|
+
zyx_scale,
|
|
97
|
+
):
|
|
98
|
+
# TODO: consider generalizing w/ phase2Dto3D.visualize_TF
|
|
99
|
+
arrays = [
|
|
100
|
+
(torch.real(imag_potential_transfer_function), "Re(imag pot. TF)"),
|
|
101
|
+
(torch.imag(imag_potential_transfer_function), "Im(imag pot. TF)"),
|
|
102
|
+
(torch.real(real_potential_transfer_function), "Re(real pot. TF)"),
|
|
103
|
+
(torch.imag(real_potential_transfer_function), "Im(real pot. TF)"),
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
for array in arrays:
|
|
107
|
+
lim = 0.5 * torch.max(torch.abs(array[0]))
|
|
108
|
+
viewer.add_image(
|
|
109
|
+
torch.fft.ifftshift(array[0]).cpu().numpy(),
|
|
110
|
+
name=array[1],
|
|
111
|
+
colormap="bwr",
|
|
112
|
+
contrast_limits=(-lim, lim),
|
|
113
|
+
scale=1 / zyx_scale,
|
|
114
|
+
)
|
|
115
|
+
viewer.dims.order = (0, 1, 2)
|
|
167
116
|
|
|
168
117
|
|
|
169
118
|
def apply_transfer_function(
|
|
170
|
-
zyx_object
|
|
171
|
-
)
|
|
119
|
+
zyx_object, real_potential_transfer_function, z_padding, brightness
|
|
120
|
+
):
|
|
172
121
|
# This simplified forward model only handles phase, so it resuses the fluorescence forward model
|
|
173
122
|
# TODO: extend to absorption
|
|
174
123
|
return (
|
|
@@ -193,7 +142,7 @@ def apply_inverse_transfer_function(
|
|
|
193
142
|
regularization_strength: float = 1e-3,
|
|
194
143
|
TV_rho_strength: float = 1e-3,
|
|
195
144
|
TV_iterations: int = 10,
|
|
196
|
-
)
|
|
145
|
+
):
|
|
197
146
|
"""Reconstructs 3D phase from labelfree defocus zyx_data and a pair of
|
|
198
147
|
complex 3D transfer functions real_potential_transfer_function and
|
|
199
148
|
imag_potential_transfer_function, providing options for reconstruction
|