Spaces:
Sleeping
Sleeping
dataset generation
Browse files- .gitignore +2 -1
- fraunhofer_test.py +27 -21
- generate_dataset.py +113 -0
- optic.py +129 -0
- zern_generator.py +28 -23
.gitignore
CHANGED
|
@@ -1,3 +1,4 @@
|
|
| 1 |
venv
|
| 2 |
.idea
|
| 3 |
-
__pycache__
|
|
|
|
|
|
| 1 |
venv
|
| 2 |
.idea
|
| 3 |
+
__pycache__
|
| 4 |
+
screens
|
fraunhofer_test.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
| 1 |
import matplotlib.pyplot as plt
|
|
|
|
| 2 |
import numpy as np
|
| 3 |
import math
|
| 4 |
-
from scipy.fft import fft2, fftshift, ifftshift
|
| 5 |
from zern_generator import Zernike
|
| 6 |
|
| 7 |
|
|
@@ -17,40 +18,45 @@ class Fraunhofer:
|
|
| 17 |
self.span = (-(10 ** -2), 10 ** -2)
|
| 18 |
self.wavelength = 500 * 10 ** -9
|
| 19 |
self.k = 2*math.pi/self.wavelength
|
| 20 |
-
|
| 21 |
self.zernike = zernike
|
| 22 |
-
|
| 23 |
-
def _denoise(screen: np.ndarray):
|
| 24 |
-
|
| 25 |
-
|
| 26 |
def get_focal_point(self,input_screen):
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
U_fraun =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
|
| 32 |
-
I_fraun = np.abs(U_fraun)**2
|
| 33 |
-
return I_fraun / np.max(I_fraun)
|
| 34 |
-
|
| 35 |
-
|
| 36 |
def generate_diff(self, defocus_amount, *zernikes):
|
| 37 |
zernikes = list(zernikes)
|
| 38 |
if len(zernikes) < 5:
|
| 39 |
zernikes += [0] * (5-len(zernikes))
|
| 40 |
-
|
| 41 |
|
| 42 |
-
|
| 43 |
wf = self.zernike.generate_zern_screen([1], self.radius)
|
| 44 |
-
|
| 45 |
|
| 46 |
f_plus = self.zernike.generate_zern_screen(self.zernike.add_defocus(defocus_amount,zernikes), norm_radius=self.radius)
|
| 47 |
f_minus = self.zernike.generate_zern_screen(self.zernike.add_defocus(-defocus_amount,zernikes), norm_radius=self.radius)
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
-
return focal_image_plus, focal_image_minus, focal_image_plus-focal_image_minus
|
| 53 |
-
|
| 54 |
|
| 55 |
|
| 56 |
-
|
|
|
|
| 1 |
import matplotlib.pyplot as plt
|
| 2 |
+
import cupy as cp
|
| 3 |
import numpy as np
|
| 4 |
import math
|
| 5 |
+
from cupyx.scipy.fft import fft2, fftshift, ifftshift
|
| 6 |
from zern_generator import Zernike
|
| 7 |
|
| 8 |
|
|
|
|
| 18 |
self.span = (-(10 ** -2), 10 ** -2)
|
| 19 |
self.wavelength = 500 * 10 ** -9
|
| 20 |
self.k = 2*math.pi/self.wavelength
|
| 21 |
+
|
| 22 |
self.zernike = zernike
|
| 23 |
+
|
| 24 |
+
# def _denoise(screen: np.ndarray):
|
| 25 |
+
# return np.where(np.abs(screen) < 1e-4, 0, screen)
|
| 26 |
+
|
| 27 |
def get_focal_point(self,input_screen):
|
| 28 |
+
input_screen_gpu = cp.asarray(input_screen)
|
| 29 |
+
#phase_mul = ((cp.exp(1j*self.k*self.distance) * cp.exp(1j*self.k*(self.zernike.xv**2 + self.zernike.yv**2)/(2*self.distance)))/(1j*self.wavelength*self.distance))
|
| 30 |
+
U_fraun = fft2(ifftshift(input_screen_gpu), overwrite_x=True)
|
| 31 |
+
#U_fraun = fftshift(U_fraun * phase_mul)
|
| 32 |
+
U_fraun = fftshift(U_fraun)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
I_fraun = cp.abs(U_fraun)**2
|
| 36 |
+
return I_fraun / cp.max(I_fraun)
|
| 37 |
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
def generate_diff(self, defocus_amount, *zernikes):
|
| 40 |
zernikes = list(zernikes)
|
| 41 |
if len(zernikes) < 5:
|
| 42 |
zernikes += [0] * (5-len(zernikes))
|
|
|
|
| 43 |
|
|
|
|
| 44 |
wf = self.zernike.generate_zern_screen([1], self.radius)
|
|
|
|
| 45 |
|
| 46 |
f_plus = self.zernike.generate_zern_screen(self.zernike.add_defocus(defocus_amount,zernikes), norm_radius=self.radius)
|
| 47 |
f_minus = self.zernike.generate_zern_screen(self.zernike.add_defocus(-defocus_amount,zernikes), norm_radius=self.radius)
|
| 48 |
|
| 49 |
+
wf_c = cp.asarray(wf)
|
| 50 |
+
f_plus_c = cp.asarray(f_plus)
|
| 51 |
+
f_minus_c = cp.asarray(f_minus)
|
| 52 |
+
focal_image_plus = denoise(self.get_focal_point(wf_c*cp.exp(f_plus_c * 1j)))
|
| 53 |
+
focal_image_minus = denoise(self.get_focal_point(wf_c*cp.exp(f_minus_c * 1j)))
|
| 54 |
+
|
| 55 |
+
return (
|
| 56 |
+
cp.asnumpy(focal_image_plus),
|
| 57 |
+
cp.asnumpy(focal_image_minus),
|
| 58 |
+
cp.asnumpy(focal_image_plus - focal_image_minus)
|
| 59 |
+
)
|
| 60 |
|
|
|
|
|
|
|
| 61 |
|
| 62 |
|
|
|
generate_dataset.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from zern_generator import Zernike
|
| 2 |
+
from PIL import Image
|
| 3 |
+
from fraunhofer_test import Fraunhofer
|
| 4 |
+
import cupy as cp
|
| 5 |
+
import matplotlib.pyplot as plt
|
| 6 |
+
import itertools
|
| 7 |
+
from time import time
|
| 8 |
+
from pprint import pprint
|
| 9 |
+
import os
|
| 10 |
+
from multiprocessing import Pool, cpu_count
|
| 11 |
+
import numpy as np
|
| 12 |
+
|
| 13 |
+
zernike = Zernike()
|
| 14 |
+
zernike.set_image_params(npix=2 ** 8)
|
| 15 |
+
fraunhofer = Fraunhofer(zernike)
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def generate_image(z):
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
start_time = time()
|
| 22 |
+
arr = fraunhofer.generate_diff(1, 0, *z)
|
| 23 |
+
a = cp.min(arr[2])
|
| 24 |
+
b = cp.max(arr[2])
|
| 25 |
+
img_arr = ((arr[2] - a) / (b - a) * 255).astype(cp.uint8)
|
| 26 |
+
img = Image.fromarray(np.stack([img_arr] * 3, axis=-1), mode='RGB')
|
| 27 |
+
generation_end_time = time()
|
| 28 |
+
if True:
|
| 29 |
+
coeffs = '_'.join([f'{x:.2f}' for x in z[2:]])
|
| 30 |
+
if not os.path.exists(f'./screens_gpu/{z[0]}/{z[1]}'):
|
| 31 |
+
try:
|
| 32 |
+
os.makedirs(f'./screens_gpu/{z[0]}/{z[1]}')
|
| 33 |
+
except:
|
| 34 |
+
pass
|
| 35 |
+
filename = f'./screens_gpu/{z[0]}/{z[1]}/{coeffs}_.png'
|
| 36 |
+
img.save(filename)
|
| 37 |
+
save_end_time = time()
|
| 38 |
+
else:
|
| 39 |
+
plt.imshow(img)
|
| 40 |
+
plt.colorbar()
|
| 41 |
+
plt.show()
|
| 42 |
+
return generation_end_time - start_time, save_end_time - generation_end_time
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def generate_dataset(zs):
|
| 46 |
+
c = 0
|
| 47 |
+
window_size = 50
|
| 48 |
+
times = []
|
| 49 |
+
start_time = time()
|
| 50 |
+
total_images = len(zs)
|
| 51 |
+
num_workers = 24
|
| 52 |
+
if num_workers is None:
|
| 53 |
+
num_workers = cpu_count()
|
| 54 |
+
|
| 55 |
+
with Pool(num_workers) as pool:
|
| 56 |
+
results = []
|
| 57 |
+
|
| 58 |
+
for result in pool.imap_unordered(generate_image, zs):
|
| 59 |
+
c += 1
|
| 60 |
+
|
| 61 |
+
results.append(result)
|
| 62 |
+
|
| 63 |
+
current_time = time()
|
| 64 |
+
iteration_time = current_time - start_time
|
| 65 |
+
times.append(iteration_time)
|
| 66 |
+
if len(times) > window_size:
|
| 67 |
+
times.pop(0)
|
| 68 |
+
avg_iteration_time = sum(times) / len(times)
|
| 69 |
+
|
| 70 |
+
# if c % 10 == 0:
|
| 71 |
+
# os.system('cls')
|
| 72 |
+
# print(f"Generated {c}/{total_images}")
|
| 73 |
+
# elapsed_time = current_time - start_time
|
| 74 |
+
# print(f"Elapsed time: {elapsed_time:.2f} s")
|
| 75 |
+
# remaining_images = total_images - c
|
| 76 |
+
# estimated_remaining_time = avg_iteration_time * remaining_images
|
| 77 |
+
# print(f"Estimated remaining time: {estimated_remaining_time:.2f} s")
|
| 78 |
+
for result in results:
|
| 79 |
+
result.get()
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def generate_dataset_gpu(zs):
|
| 83 |
+
c = 0
|
| 84 |
+
window_size = 50
|
| 85 |
+
times = []
|
| 86 |
+
start_time = time()
|
| 87 |
+
total_images = len(zs)
|
| 88 |
+
num_workers = 24
|
| 89 |
+
if num_workers is None:
|
| 90 |
+
num_workers = cpu_count()
|
| 91 |
+
|
| 92 |
+
for z in zs:
|
| 93 |
+
|
| 94 |
+
generate_image(z)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
if __name__ == '__main__':
|
| 98 |
+
rng = (-5, 5)
|
| 99 |
+
step = 0.5
|
| 100 |
+
points = tuple(np.linspace(*rng, int((rng[1] - rng[0]) / step + 1)))
|
| 101 |
+
points_as_tuples = tuple(float(x) for x in points)
|
| 102 |
+
|
| 103 |
+
zernikes = np.array(list(set(itertools.product(points_as_tuples, repeat=3))))
|
| 104 |
+
|
| 105 |
+
# print("Total images: ", len(zernikes))
|
| 106 |
+
# total_gen_time, total_save_time = 0, 0
|
| 107 |
+
# for z in zernikes:
|
| 108 |
+
# gen_time, save_time = generate_image(z)
|
| 109 |
+
# total_save_time += save_time
|
| 110 |
+
# total_gen_time += gen_time
|
| 111 |
+
# print("Average generation time: ", total_gen_time/len(zernikes))
|
| 112 |
+
# print("Average save time: ", total_save_time/len(zernikes))
|
| 113 |
+
generate_dataset(zernikes)
|
optic.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import astropy.units as u
|
| 2 |
+
import pyoptica as po
|
| 3 |
+
import matplotlib.pyplot as plt
|
| 4 |
+
import numpy as np
|
| 5 |
+
import math
|
| 6 |
+
import os
|
| 7 |
+
from scipy.fft import fft2, ifft2, fftshift, ifftshift
|
| 8 |
+
import aotools.opticalpropagation as op
|
| 9 |
+
import scipy.special as sc
|
| 10 |
+
import time
|
| 11 |
+
import multiprocessing
|
| 12 |
+
from multiprocessing import Pool
|
| 13 |
+
from zern_generator import generate_zern_wavefront, generate_zern_wavefront_fig
|
| 14 |
+
from scipy.ndimage import zoom
|
| 15 |
+
|
| 16 |
+
fig, (ax1, ax2) = plt.subplots(2,1)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
#f2.show()
|
| 20 |
+
|
| 21 |
+
f = 100 * 10 ** -3 # Форкусное расстояние линзы
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
radius = 5 * 10 ** -3 # Радиус линзы
|
| 26 |
+
span = (-(2*radius), 2*radius)
|
| 27 |
+
lens = po.ThinLens(radius, f)
|
| 28 |
+
|
| 29 |
+
z = 100 * 10 ** -3 # Расстояние
|
| 30 |
+
|
| 31 |
+
wavelength = 500 * 10 ** -9 # Длина волны
|
| 32 |
+
pixel_scale = 250 * 10 ** -4 # Размер пикселя
|
| 33 |
+
npix = 2**9 # Размер сетки
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
ddx = np.linspace(*span, npix)
|
| 37 |
+
ddy = np.linspace(*span, npix)
|
| 38 |
+
xv, yv = np.meshgrid(ddx, ddy)
|
| 39 |
+
f2 = generate_zern_wavefront(xv, yv, [0,0,0,1,0,0], norm_radius=radius)
|
| 40 |
+
dist_from_center = np.sqrt(xv**2 + yv**2)
|
| 41 |
+
mask = dist_from_center <= radius
|
| 42 |
+
f2[mask==0] = 0
|
| 43 |
+
f2[np.isnan(f2)] = 0
|
| 44 |
+
k = 2*math.pi/wavelength
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
wf = np.zeros((npix, npix), dtype=np.complex64)
|
| 48 |
+
|
| 49 |
+
wf[mask] = 1 + 0j
|
| 50 |
+
|
| 51 |
+
wf += f2 * 1j
|
| 52 |
+
|
| 53 |
+
wf = fftshift(fft2(wf))
|
| 54 |
+
|
| 55 |
+
phase_mul = ((np.exp(1j*k*z) * np.exp(1j*k*(xv**2 + yv**2)/(2*z)))/(1j*wavelength*z))
|
| 56 |
+
|
| 57 |
+
#wf = wf * phase_mul
|
| 58 |
+
wf= np.abs(wf)**2
|
| 59 |
+
#wf = np.log10(wf)
|
| 60 |
+
|
| 61 |
+
crop = 20
|
| 62 |
+
center = npix//2
|
| 63 |
+
vx = np.linspace(*span, npix)
|
| 64 |
+
ax1.imshow(wf, extent = (*span, *span), cmap="gray")
|
| 65 |
+
#ax2.plot(vx, wf[npix//2])
|
| 66 |
+
ax2.imshow(f2, extent = (*span, *span),cmap="gray")
|
| 67 |
+
print(np.ptp(wf))
|
| 68 |
+
plt.show()
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# amp = np.array(wf.amplitude)
|
| 75 |
+
|
| 76 |
+
# a = fftshift(fft2(wf.amplitude))
|
| 77 |
+
# a = np.abs(a)**2
|
| 78 |
+
# print(a)
|
| 79 |
+
# ax.imshow(a, extent=(-npix*pixel_scale/2, npix*pixel_scale/2,-npix*pixel_scale/2, npix*pixel_scale/2))
|
| 80 |
+
# plt.show()
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
# # Двойной интеграл из 4.13
|
| 84 |
+
# def calc_point_fourier(x,y, uxy):
|
| 85 |
+
# res = 0 + 0j
|
| 86 |
+
# for x0 in range(npix):
|
| 87 |
+
# x_r = to_real(x0)
|
| 88 |
+
# for y0 in range(npix):
|
| 89 |
+
# y_r = to_real(y0)
|
| 90 |
+
# res += uxy * np.exp(-1j*k*(x*x_r + y*y_r)/z)
|
| 91 |
+
# return res
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
# # Считает точку по 4.13
|
| 95 |
+
# def calc_point(x,y):
|
| 96 |
+
# x_r = to_real(x)
|
| 97 |
+
# y_r = to_real(y)
|
| 98 |
+
# if y%100 == 1:
|
| 99 |
+
# os.system('cls')
|
| 100 |
+
# print(f"{npix*x + y}/{npix**2}")
|
| 101 |
+
# return ((np.exp(1j*k*z) * np.exp(1j*k*(x_r**2 + y_r**2)/(2*z)))/(1j*wavelength*z)) * calc_point_fourier(x_r, y_r, amp[x][y])
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
# if __name__ == "__main__":
|
| 107 |
+
# pairs = []
|
| 108 |
+
# for x in range(npix):
|
| 109 |
+
# for y in range(npix):
|
| 110 |
+
# pairs.append((x,y))
|
| 111 |
+
# multiprocessing.freeze_support()
|
| 112 |
+
# with Pool(20) as p:
|
| 113 |
+
# res = p.starmap_async(calc_point, pairs)
|
| 114 |
+
# a = res.get()
|
| 115 |
+
# a = np.abs(a)**2
|
| 116 |
+
# a = a.reshape((npix, npix))
|
| 117 |
+
# a /= np.max(a)
|
| 118 |
+
# ax.imshow(a, extent=(-npix*pixel_scale/2, npix*pixel_scale/2,-npix*pixel_scale/2, npix*pixel_scale/2))
|
| 119 |
+
# plt.show()
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
try:
|
| 127 |
+
pass
|
| 128 |
+
except KeyError:
|
| 129 |
+
|
zern_generator.py
CHANGED
|
@@ -2,6 +2,7 @@ import math
|
|
| 2 |
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
import numpy as np
|
|
|
|
| 5 |
from zernike import RZern
|
| 6 |
import utils
|
| 7 |
|
|
@@ -9,7 +10,6 @@ SAMPLE_SIZE = 256
|
|
| 9 |
span = (-1, 1)
|
| 10 |
|
| 11 |
|
| 12 |
-
|
| 13 |
class Zernike:
|
| 14 |
def __init__(self):
|
| 15 |
self.set_image_params()
|
|
@@ -29,33 +29,37 @@ class Zernike:
|
|
| 29 |
"P-SPHERICAL",
|
| 30 |
"V-SC-ASTIGMATISM",
|
| 31 |
"V-QUADRAFOIL",
|
| 32 |
-
|
| 33 |
# "V-SC-COMA",
|
| 34 |
# "H-SC-COMA",
|
| 35 |
# "V-SC-TREFOIL",
|
| 36 |
# "O-SC-TREFOIL",
|
| 37 |
# "O-PENTAFOIL",
|
| 38 |
# "V-PENTAFOIL"
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
def set_image_params(self, span
|
| 42 |
self.span = span
|
| 43 |
self.npix = npix
|
| 44 |
ddx = np.linspace(*self.span, self.npix)
|
| 45 |
ddy = np.linspace(*self.span, self.npix)
|
| 46 |
-
self.xv, self.yv = np.meshgrid(ddx, ddy)
|
| 47 |
-
|
| 48 |
-
def generate_zern_screen(self, zerns, norm_radius
|
|
|
|
|
|
|
|
|
|
| 49 |
zerns = self._osa_to_noll_list(zerns)
|
| 50 |
num_zerns = len(zerns)
|
| 51 |
mask = utils.circle_mask(self.xv, self.yv, norm_radius)
|
| 52 |
-
|
| 53 |
-
|
| 54 |
degree = math.ceil((-3 + math.sqrt(8 * num_zerns + 1)) / 2)
|
| 55 |
zerns = list(zerns) + [0] * int((((degree + 1) * (degree + 2) / 2) - len(zerns)))
|
| 56 |
cart = RZern(degree)
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
| 59 |
screen[mask == 0] = 0
|
| 60 |
screen[np.isnan(screen)] = 0
|
| 61 |
return screen
|
|
@@ -70,17 +74,17 @@ class Zernike:
|
|
| 70 |
fig_2d.colorbar(a)
|
| 71 |
plt.show()
|
| 72 |
return fig_2d, fig_3d
|
| 73 |
-
|
| 74 |
def add_defocus(self, defocus_value, zernikes):
|
|
|
|
| 75 |
zernikes = list(zernikes)
|
| 76 |
if len(zernikes) < 5:
|
| 77 |
-
zernikes += [0] * (5-len(zernikes))
|
| 78 |
zernikes[4] += defocus_value
|
| 79 |
return zernikes
|
| 80 |
|
| 81 |
-
|
| 82 |
def generate_batch(self, resolution):
|
| 83 |
-
#term = ["PISTON","V-TILT","H-TILT","DEFOCUS","O-PR-ASTIGMATISM","V-PR-ASTIGMATISM","V-PR-COMA","H-PR-COMA","V-TREFOIL","O-TREFOIL","P-SPHERICAL","O-SC-ASTIGMATISM","V-SC-ASTIGMATISM","V-QUADRAFOIL","O-QUADRAFOIL","V-SC-COMA","H-SC-COMA","V-SC-TREFOIL","O-SC-TREFOIL","O-PENTAFOIL","V-PENTAFOIL"]
|
| 84 |
fig = plt.figure()
|
| 85 |
fig.set_figwidth(30)
|
| 86 |
fig.set_figheight(20)
|
|
@@ -92,15 +96,14 @@ class Zernike:
|
|
| 92 |
|
| 93 |
zern = [0] * (zern_index - 1) + [1]
|
| 94 |
ax = plt.subplot2grid((5, 6), (i, j))
|
| 95 |
-
Phi = self.generate_zern_screen(zern, norm_radius=self.span[1]/2)
|
| 96 |
-
ax.set_title(f" \n Zernike {zern_index-1} — {self.term[zern_index-1]} ")
|
| 97 |
ax.imshow(Phi, extent=(*span, *span), cmap='gray')
|
| 98 |
|
| 99 |
zern_index += 1
|
| 100 |
plt.show()
|
| 101 |
return fig
|
| 102 |
|
| 103 |
-
|
| 104 |
def _osa_to_mn(self, idx):
|
| 105 |
n = math.ceil((-3 + math.sqrt((9 + 8 * idx))) / 2)
|
| 106 |
m = 2 * idx - n * (n + 2)
|
|
@@ -122,7 +125,6 @@ class Zernike:
|
|
| 122 |
j = first + second + third
|
| 123 |
return j
|
| 124 |
|
| 125 |
-
|
| 126 |
def _osa_to_noll(self, idx):
|
| 127 |
return self._mn_to_noll(*self._osa_to_mn(idx))
|
| 128 |
|
|
@@ -130,8 +132,11 @@ class Zernike:
|
|
| 130 |
indexed_zerns = sorted(map(lambda x: (self._osa_to_noll(x[0]), x[1]), enumerate(zernikes)), key=lambda x: x[0])
|
| 131 |
used_indeces = [x for x, _ in indexed_zerns]
|
| 132 |
mn, mx = min(used_indeces), max(used_indeces)
|
| 133 |
-
missing_indeces = set(range(mn, mx+1)) - set(used_indeces)
|
| 134 |
return [x[1] for x in list(sorted(indexed_zerns + [(x, 0) for x in missing_indeces]))]
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
import numpy as np
|
| 5 |
+
import cupy as cp
|
| 6 |
from zernike import RZern
|
| 7 |
import utils
|
| 8 |
|
|
|
|
| 10 |
span = (-1, 1)
|
| 11 |
|
| 12 |
|
|
|
|
| 13 |
class Zernike:
|
| 14 |
def __init__(self):
|
| 15 |
self.set_image_params()
|
|
|
|
| 29 |
"P-SPHERICAL",
|
| 30 |
"V-SC-ASTIGMATISM",
|
| 31 |
"V-QUADRAFOIL",
|
| 32 |
+
|
| 33 |
# "V-SC-COMA",
|
| 34 |
# "H-SC-COMA",
|
| 35 |
# "V-SC-TREFOIL",
|
| 36 |
# "O-SC-TREFOIL",
|
| 37 |
# "O-PENTAFOIL",
|
| 38 |
# "V-PENTAFOIL"
|
| 39 |
+
]
|
| 40 |
+
|
| 41 |
+
def set_image_params(self, span=(-(10 ** -2), 10 ** -2), npix=2 ** 8):
|
| 42 |
self.span = span
|
| 43 |
self.npix = npix
|
| 44 |
ddx = np.linspace(*self.span, self.npix)
|
| 45 |
ddy = np.linspace(*self.span, self.npix)
|
| 46 |
+
self.xv, self.yv = np.meshgrid(ddx, ddy)
|
| 47 |
+
|
| 48 |
+
def generate_zern_screen(self, zerns, norm_radius=1):
|
| 49 |
+
|
| 50 |
+
if isinstance(zerns, cp.ndarray):
|
| 51 |
+
zerns = zerns.get()
|
| 52 |
zerns = self._osa_to_noll_list(zerns)
|
| 53 |
num_zerns = len(zerns)
|
| 54 |
mask = utils.circle_mask(self.xv, self.yv, norm_radius)
|
| 55 |
+
|
|
|
|
| 56 |
degree = math.ceil((-3 + math.sqrt(8 * num_zerns + 1)) / 2)
|
| 57 |
zerns = list(zerns) + [0] * int((((degree + 1) * (degree + 2) / 2) - len(zerns)))
|
| 58 |
cart = RZern(degree)
|
| 59 |
+
|
| 60 |
+
cart.make_cart_grid(self.xv / norm_radius, self.yv / norm_radius)
|
| 61 |
+
|
| 62 |
+
screen = np.array(cart.eval_grid(np.array(zerns), matrix=True))
|
| 63 |
screen[mask == 0] = 0
|
| 64 |
screen[np.isnan(screen)] = 0
|
| 65 |
return screen
|
|
|
|
| 74 |
fig_2d.colorbar(a)
|
| 75 |
plt.show()
|
| 76 |
return fig_2d, fig_3d
|
| 77 |
+
|
| 78 |
def add_defocus(self, defocus_value, zernikes):
|
| 79 |
+
|
| 80 |
zernikes = list(zernikes)
|
| 81 |
if len(zernikes) < 5:
|
| 82 |
+
zernikes += [0] * (5 - len(zernikes))
|
| 83 |
zernikes[4] += defocus_value
|
| 84 |
return zernikes
|
| 85 |
|
|
|
|
| 86 |
def generate_batch(self, resolution):
|
| 87 |
+
# term = ["PISTON","V-TILT","H-TILT","DEFOCUS","O-PR-ASTIGMATISM","V-PR-ASTIGMATISM","V-PR-COMA","H-PR-COMA","V-TREFOIL","O-TREFOIL","P-SPHERICAL","O-SC-ASTIGMATISM","V-SC-ASTIGMATISM","V-QUADRAFOIL","O-QUADRAFOIL","V-SC-COMA","H-SC-COMA","V-SC-TREFOIL","O-SC-TREFOIL","O-PENTAFOIL","V-PENTAFOIL"]
|
| 88 |
fig = plt.figure()
|
| 89 |
fig.set_figwidth(30)
|
| 90 |
fig.set_figheight(20)
|
|
|
|
| 96 |
|
| 97 |
zern = [0] * (zern_index - 1) + [1]
|
| 98 |
ax = plt.subplot2grid((5, 6), (i, j))
|
| 99 |
+
Phi = self.generate_zern_screen(zern, norm_radius=self.span[1] / 2)
|
| 100 |
+
ax.set_title(f" \n Zernike {zern_index - 1} — {self.term[zern_index - 1]} ")
|
| 101 |
ax.imshow(Phi, extent=(*span, *span), cmap='gray')
|
| 102 |
|
| 103 |
zern_index += 1
|
| 104 |
plt.show()
|
| 105 |
return fig
|
| 106 |
|
|
|
|
| 107 |
def _osa_to_mn(self, idx):
|
| 108 |
n = math.ceil((-3 + math.sqrt((9 + 8 * idx))) / 2)
|
| 109 |
m = 2 * idx - n * (n + 2)
|
|
|
|
| 125 |
j = first + second + third
|
| 126 |
return j
|
| 127 |
|
|
|
|
| 128 |
def _osa_to_noll(self, idx):
|
| 129 |
return self._mn_to_noll(*self._osa_to_mn(idx))
|
| 130 |
|
|
|
|
| 132 |
indexed_zerns = sorted(map(lambda x: (self._osa_to_noll(x[0]), x[1]), enumerate(zernikes)), key=lambda x: x[0])
|
| 133 |
used_indeces = [x for x, _ in indexed_zerns]
|
| 134 |
mn, mx = min(used_indeces), max(used_indeces)
|
| 135 |
+
missing_indeces = set(range(mn, mx + 1)) - set(used_indeces)
|
| 136 |
return [x[1] for x in list(sorted(indexed_zerns + [(x, 0) for x in missing_indeces]))]
|
| 137 |
|
| 138 |
+
|
| 139 |
+
term = ["PISTON", "V-TILT", "H-TILT", "DEFOCUS", "O-PR-ASTIGMATISM", "V-PR-ASTIGMATISM", "V-PR-COMA", "H-PR-COMA",
|
| 140 |
+
"V-TREFOIL", "O-TREFOIL", "P-SPHERICAL", "O-SC-ASTIGMATISM", "V-SC-ASTIGMATISM", "V-QUADRAFOIL", "O-QUADRAFOIL",
|
| 141 |
+
"V-SC-COMA", "H-SC-COMA", "V-SC-TREFOIL", "O-SC-TREFOIL", "O-PENTAFOIL", "V-PENTAFOIL"]
|
| 142 |
+
print(Zernike()._osa_to_noll_list(list(range(0, 15))))
|