Skip to content

Commit 614ac6d

Browse files
pure topological discovery optical table for sharp focus and sted microscopy
1 parent 04b0ddc commit 614ac6d

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Setting the path for XLuminA modules:
2+
import os
3+
import sys
4+
current_path = os.path.abspath(os.path.join('..'))
5+
dir_path = os.path.dirname(current_path)
6+
module_path = os.path.join(dir_path)
7+
if module_path not in sys.path:
8+
sys.path.append(module_path)
9+
10+
from xlumina.__init__ import um, nm, cm, mm
11+
from xlumina.vectorized_optics import *
12+
from xlumina.optical_elements import hybrid_setup_fixed_slms_fluorophores, hybrid_setup_fixed_slms
13+
from xlumina.loss_functions import vectorized_loss_hybrid
14+
from xlumina.toolbox import space, softmin
15+
import jax.numpy as jnp
16+
17+
"""
18+
Large-scale setup using fixed phase masks in random positions:
19+
20+
3x3 initial setup - light gets detected across 6 detectors.
21+
22+
This script is valid for rediscovering
23+
24+
(1) Dorn, Quabis and Leuchs (2004) - use hybrid_setup_fixed_slms() in the loss function,
25+
26+
(2) STED microscopy - use hybrid_setup_fixed_slms_fluorophores() in the loss function.
27+
"""
28+
29+
# 1. System specs:
30+
sensor_lateral_size = 824 # Resolution
31+
wavelength_1 = 632.8*nm
32+
wavelength_2 = 530*nm
33+
x_total = 2500*um
34+
x, y = space(x_total, sensor_lateral_size)
35+
shape = jnp.shape(x)[0]
36+
37+
# 2. Define the optical functions: two orthogonally polarized beams:
38+
w0 = (1200*um, 1200*um)
39+
ls1 = PolarizedLightSource(x, y, wavelength_1)
40+
ls1.gaussian_beam(w0=w0, jones_vector=(1, 1))
41+
ls2 = PolarizedLightSource(x, y, wavelength_2)
42+
ls2.gaussian_beam(w0=w0, jones_vector=(1, 1))
43+
44+
# 3. Define the output (High Resolution) detection:
45+
x_out, y_out = jnp.array(space(10*um, 400))
46+
X, Y = jnp.meshgrid(x,y)
47+
48+
# 4. High NA objective lens specs:
49+
NA = 0.9
50+
radius_lens = 3.6*mm/2
51+
f_lens = radius_lens / NA
52+
53+
# 4.1 Fixed phase masks:
54+
# Polarization converter in Dorn, Quabis, Leuchs (2004):
55+
pi_half = (jnp.pi - jnp.pi/2) * jnp.ones(shape=(sensor_lateral_size // 2, sensor_lateral_size // 2))
56+
minus_pi_half = - jnp.pi/2 * jnp.ones(shape=(sensor_lateral_size // 2, sensor_lateral_size // 2))
57+
PM1_1 = jnp.concatenate((jnp.concatenate((minus_pi_half, pi_half), axis=1), jnp.concatenate((minus_pi_half, pi_half), axis=1)), axis=0)
58+
PM1_2 = jnp.concatenate((jnp.concatenate((minus_pi_half, minus_pi_half), axis=1), jnp.concatenate((pi_half, pi_half), axis=1)), axis=0)
59+
# Spiral phase (STED microscopy)
60+
PM2 = jnp.arctan2(Y,X)
61+
# Forked grating
62+
PM3 = jnp.cos(2 * PM2 - 2 * jnp.pi * X/1000) * jnp.pi
63+
# Linear grating
64+
PM4_1 = jnp.sin(2*jnp.pi * Y/1000) * jnp.pi
65+
PM4_2 = jnp.sin(2*jnp.pi * X/1000) * jnp.pi
66+
67+
# 5. Static parameters - don't change during optimization:
68+
fixed_params = [radius_lens, f_lens, x_out, y_out, PM1_1, PM1_2, PM2, PM3, PM4_1, PM4_2]
69+
70+
# 6. Define the loss function:
71+
def loss_hybrid_fixed_PM(parameters):
72+
# Output from hybrid_setup is jnp.array(6, N, N): for 6 detectors
73+
74+
# Use (1) for Dorn, Quabis and Leuchs benchmark / Use (2) for STED microscopy benchmark
75+
76+
# (1):
77+
# detected_z_intensities, _ = hybrid_setup_fixed_slms(ls1, ls1, ls1, ls1, ls1, ls1, parameters, fixed_params)
78+
79+
# (2):
80+
i_effective = hybrid_setup_fixed_slms_fluorophores(ls1, ls2, ls1, ls2, ls1, ls2, parameters, fixed_params)
81+
82+
# Get the minimum value within loss value array of shape (6, 1, 1)
83+
loss_val = softmin(vectorized_loss_hybrid(i_effective))
84+
85+
return loss_val

0 commit comments

Comments
 (0)