import os
import numpy as np
import cv2
from .utils import inv_sinc
[docs]
def generate_oam_superposition(res, pixel_pitch, beam_w0, l_modes, weights):
""" Creat E field of superimposed OAM mode (Interferogram method)
Args:
res (list[int]): resolution of SLM. [x resolution, y resolution]
pixel_pitch (float): pixel size. specified at device document
beam_w0 (float): beam-waist at z=0.
l_modes (list[int]): selected l indices for superposion. list with length 1 for eigen mode
weights (list[float]): weights for selected l modes.
Returns:
np.ndarray[float], np.ndarray[float], np.ndarray[float], np.ndarray[float]: information about E field and meshgrid i.e. superimosed
Example:
>>> res = [1920, 1080]
>>> pixel_pitch = 8e-1
>>> beam_w0 = 0.8e-3
>>> l_modes = [-3, -1, 1, 3]
>>> weights = [0.4, 0.03, 0.07, 0.5]
>>> amp, phase, X, Y = generate_oam_superposition(res, pixel_pitch, beam_w0, l_modes, weights)
"""
x = np.linspace(-res[0] * pixel_pitch / 2, res[0] * pixel_pitch / 2, res[0])
y = np.linspace(-res[1] * pixel_pitch / 2, res[1] * pixel_pitch / 2, res[1])
X, Y = np.meshgrid(x, y)
R = np.sqrt(X ** 2 + Y ** 2)
Phi = np.arctan2(Y, X)
R[R == 0] = 1e-10
E_total = np.zeros_like(Phi, dtype=complex)
for l, w in zip(l_modes, weights):
# E = (sqrt(2)r/w)^|l| * exp(-r^2/w^2) * exp(il*phi)
E_total += w * (np.sqrt(2) * R / beam_w0) ** abs(l) * np.exp(-R ** 2 / beam_w0 ** 2) * np.exp(1j * l * Phi)
Amp = np.abs(E_total)
Phase = np.angle(E_total)
Amp = Amp / np.max(Amp)
return Amp, Phase, X, Y
[docs]
def encode_hologram(Amp, Phase, X, Y, pixel_pitch, d, N_steps=0, M=1, prepare=False, measure=False, save=False, path="", name=""):
"""phase mask for given amplitude and phase map of superimposed OAM mode.
입력받은 위상, 진폭 정보를 논문 공식에 대입하여 이 상태를 인코딩하는 SLM 홀로그램을 생성합니다.
Fundamental Gaussian 모드와의 분리를 위해서 간격이 d 픽셀인 그레이팅이 적용됩니다.
상태 준비에 사용될지, 측정에 사용될지에 따라서 그레이팅의 방향이 바뀝니다. 변수 parity가 이것을 반영합니다.
생성된 홀로그램을 저장할 수 있습니다.
Args:
Amp (np.ndarray[float]): amplitude map of superimposed OAM mode. 0. <= *Amp <= 1.
Phase (np.ndarray[float]): phase map of superimposed OAM mode. -pi < *Phase <= pi
X (np.ndarray[float]): x dependent meshgrid.
Y (np.ndarray[float]): y dependent meshgrid.
pixel_pitch (float): pixel size. specified at device document
d (float): grating width. dimension in # of pixel
N_steps (float): number of steps per grating with period d. N_steps=0 is equal to N_steps=d (continuous)
M (int): phase depth. M is basically 1
prepare (bool): decide whether to prepare.
measure (bool): decide whether to measure.
save (bool): decide whether to save.
path (string): directory path for images. needed only when arg save is True
name (string): filename of this image. needed only when arg save is True
Return:
np.ndarray[float] or None: returns carculated hologram.
if arg save is False(default), a hologram in numpy ndarray. And if not, hologram is saved in the directory addording to arg path.
Example:
>>> res = [1920, 1080]
>>> pixel_pitch = 8e-1
>>> beam_w0 = 0.8e-3
>>> l_modes = [-3, -1, 1, 3]
>>> weights = [0.4, 0.03, 0.07, 0.5]
>>> amp, phase, X, Y = generate_oam_superposition(res, pixel_pitch, beam_w0, l_modes, weights)
>>> encode_hologram(amp, phase, X, Y, pixel_pitch, 16, 0, prepare=True, save=True, path="./images", name="l8_dim16")
"""
modified_amp = 1 + (1/np.pi)*inv_sinc(Amp)
modified_amp = modified_amp / np.max(modified_amp)
modified_phase = Phase - np.pi*modified_amp
parity = 0
if prepare: parity = -1
elif measure: parity = 1
if N_steps==0: N_steps = d
res = np.shape(X)[1]
X_normalized = (X + (res*pixel_pitch/2))/(pixel_pitch*d*M)
X_grating = X_normalized - X_normalized.astype(int)
X_stepped = np.floor(X_grating * N_steps)
X_final = cv2.normalize(X_stepped, X_stepped, 0, 1, cv2.NORM_MINMAX)
hologram = modified_amp * np.mod(modified_phase + (parity * 2*np.pi * X_final), 2*np.pi)
hologram_final = hologram
if not save:
return hologram_final
elif save:
if not os.path.exists(path):
os.mkdir(path)
hologram_final = cv2.normalize(hologram_final, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
cv2.imwrite(path+"/"+name+".png", hologram_final)
return 0
else:
return 0
if __name__ == '__main__':
res = [1920, 1080]
pixel_pitch = 8e-6
beam_w0 = 8e-4
l_modes = [-3, -1, 1, 3]
weights = [0.4, 0.03, 0.07, 0.5]
amp, phase, X, Y = generate_oam_superposition(
res=res,
pixel_pitch=pixel_pitch,
beam_w0=beam_w0,
l_modes=l_modes,
weights=weights
)
d = 8
N_steps = 8
experiments = {
"prepare": encode_hologram(
Amp=amp,
Phase=phase,
X=X,
Y=Y,
pixel_pitch=pixel_pitch,
d=d,
N_steps=N_steps,
M=3,
prepare=True,
save=True,
path="./outputs",
name="l=-16_prepare_step"
),
"measure": encode_hologram(
Amp=amp,
Phase=phase,
X=X,
Y=Y,
pixel_pitch=pixel_pitch,
d=d,
N_steps=N_steps,
measure=True,
save=True,
path="./outputs",
name="l=-16_measure_step"
)
}
print(experiments)