Files
cdtools/CDTools/tools/plotting/polarized_plotting.py
T
2021-08-27 05:16:48 -04:00

343 lines
13 KiB
Python

import torch as t
from matplotlib import pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import hsv_to_rgb
from matplotlib.widgets import Slider
from matplotlib import ticker, patheffects
from CDTools.tools.polarization import polarization
all = ['visualize_components_amplitudes',
'visualize_attenuations',
'visualize_fast_axes',
'visualize_global_axes',
'visualize_phase_ret',
'visualize_probe']
def iterator(a, b):
'''
A helper function we can use to facilitate to process of iterating over 2D arrays
'''
x, y = t.arange(a), t.arange(b)
x, y = t.meshgrid(x, y)
x, y = t.ravel(x), t.ravel(y)
return (x, y)
def plot_probe_ellipse(a=1, b=1, phase_ret=0, scale=1, x0=4, y0=5):
'''
Given a probe vector at a point (x0, y0), visualizes ellipticity
of its polarization
Parameters:
-----------
a : 1D np.array
An amplitude of the horizontal component of the probe vector
b : 1D np.array
An amplitude of the vertical component of the probe vector
phase_ret : 1D np.array
A phase difference in radians bettween the phases of the y and x components
scale : int
A scaling factor
x0, y0: 1D np.array or float
Defines the location of the vector to be plotted
Returns:
--------
x, y set of points to plot a single ellipse
'''
theta = np.linspace(0, 2*np.pi, 20)
x = x0 + scale * a * np.real(np.exp(1j * theta))
y = y0 + scale * b * np.real(np.exp(1j * (theta + phase_ret)))
return x, y
def plot_attenuations(atten_slow=1, atten_fast=1, fast_ax_angle=0, scale=1, x0=4, y0=4):
'''
Plots attenuations along the fast and slow axes
Parameters:
-----------
atten_slow: 1D np.array
Attenuation along the slow axis
atten_fast: 1D np.array
Attenuation along the fast axis
fast_ax_angle: 1D np.array
An angle between the fast horizontal and fast axes
phase_ret: 1D np.array
A difference in phases gained by the slow and the fast components
The most clockwise axis is always considered to be the fast one
scale: 1D np.array
A scaling factor
x0, y0: 1D np.array or float
Defines the location to be plotted at
Returns:
--------
x, y set of points to plot a single Jones matrix of the object
'''
angle = fast_ax_angle
theta = np.linspace(0, 2*np.pi, 20)
# collection of points to plot a fast axis
print('angle', np.rad2deg(angle))
x = x0 + scale * atten_fast * np.real(np.exp(1j * theta))
x_f = x0 + (x - x0) * np.cos(angle)
y_f = y0 + (x - x0) * np.sin(angle)
# collection of point to plot a slow axis
y = y0 + scale * atten_slow * np.real(np.exp(1j * theta))
x_s = x0 - (y - y0) * np.sin(angle)
y_s = y0 + (y - y0) * np.cos(angle)
return x_f, y_f, x_s, y_s
def plot_fast_axis(fast_ax_angle=0, scale=1, x0=4, y0=4):
'''
Plots directions of the fast axes only
'''
xf, yf, xs, ys = plot_attenuations(fast_ax_angle=fast_ax_angle, atten_fast=1, atten_slow=0, scale=scale, x0=x0, y0=y0)
return xf, yf
def plot_figures(shape, num_of_el_along_x=20, num_of_el_along_y=20,
phases=None, fast_ax_angles=None,
atten_fast=None, atten_slow=None, scale=5,
probe=False, attenuations=False, fast_axes=False):
"""
All the parameters - np.arrays of shape (shape)
"""
x_centers = np.linspace(1, shape[0] - 1, num_of_el_along_x)
y_centers = np.linspace(1, shape[1] - 1, num_of_el_along_y)
X, Y = np.meshgrid(x_centers, y_centers)
X, Y = np.ravel(X), np.ravel(Y)
xs, ys = np.array([]), np.array([])
for x, y in zip(X, Y):
k, m = int(x), int(y)
if probe:
xx, yy = plot_probe_ellipse(a=atten_fast[k, m], b=atten_slow[k, m],
phase_ret=phases[k, m], scale=scale, x0=x, y0=y)
title = 'Polarized Probe'
elif attenuations:
xf, yf, xs, ys = plot_attenuations(atten_slow=atten_slow[k, m], atten_fast=atten_fast[k, m],
fast_ax_angle=fast_ax_angles[k, m], scale=scale, x0=x, y0=y)
elif fast_axes:
xx, yy = plot_fast_axis(fast_ax_angle=fast_ax_angles[k, m], scale=scale, x0=x, y0=y)
title = 'Fast Axes'
if attenuations:
plt.plot(xf, yf, c='b')
plt.plot(xs, ys, c='b')
plt.axis('equal')
plt.title('Attenuations')
else:
plt.plot(xx, yy, c='b')
plt.axis('equal')
plt.title(title)
"""
VISUALIZATION FUNCTIONS (and helper functions)
"""
def determine_fast_axis(angle0, angle1):
# in radians
w0, w1 = t.as_tensor(angle0, dtype=t.float32), t.as_tensor(angle1, dtype=t.float32)
diff = (w0 - w1) % (2 * np.pi)
if t.tensor(0, dtype=t.float32) <= diff and diff <= t.tensor(np.pi, dtype=t.float32):
fast = 1
phase_ret = (w0 - w1) % (2 * np.pi)
gl_phase = w1
else:
fast = 0
phase_ret = (w1 - w0) % (2 * np.pi)
gl_phase = w0
if t.allclose((w0 - w1) % (2 * np.pi), phase_ret):
gl_phase = w1
fast = 1
return fast, phase_ret, gl_phase
def retrieve_obj_info(obj):
obj_t = obj.transpose(-1, -3).transpose(-2, -4)
w, v = t.linalg.eig(obj_t)
b = obj.shape[-1]
a = obj.shape[-2]
eigenvectors = t.empty(a, b, 2, dtype=t.cfloat)
ret_phases = t.empty(a, b, dtype=t.float32)
global_phases = t.empty(a, b, dtype=t.float32)
atten_fast = t.empty(a, b, dtype=t.float32)
atten_slow = t.empty(a, b, dtype=t.float32)
fast_ax_angles = t.empty(a, b, dtype=t.float32)
for k, m in zip(*iterator(a, b)):
angle0, angle1 = t.angle(w[k, m, 0]).to(dtype=t.float32), t.angle(w[k, m, 1]).to(dtype=t.float32)
fst, phase_ret, gl_phase = determine_fast_axis(angle0, angle1)
atten0, atten1 = t.abs(w[k, m, 0]), t.abs(w[k, m, 1])
ret_phases[k, m] = phase_ret
def fast(b):
if b == 0:
eigenvectors[k, m, :] = v[k, m, 0, :]
atten_fast[k, m] = atten0
atten_slow[k, m] = atten1
global_phases[k, m] = angle0
elif b == 1:
eigenvectors[k, m, :] = v[k, m, 1, :]
atten_fast[k, m] = atten1
atten_slow[k, m] = atten0
global_phases[k, m] = angle1
if t.allclose(angle0, angle1):
# then it's a linear polarizer, fast ax - the one for which attenuation is bigger
if atten0 > atten1:
fst = 0
else:
fst = 1
fast(fst)
cos = np.abs(eigenvectors[k, m, 0])
sin = np.abs(eigenvectors[k, m, 1])
if t.allclose(cos, t.zeros(1, dtype=t.float32)):
fast_ax_angles[k, m] = 90
else:
fast_ax_angles[k, m] = t.atan(sin/cos)
fast_ax_angles = np.asarray(fast_ax_angles, dtype=np.float32)
ret_phases = np.asarray(ret_phases, dtype=np.float32)
global_phases = np.asarray(global_phases, dtype=np.float32)
atten_fast = np.asarray(atten_fast, dtype=np.float32)
atten_slow = np.asarray(atten_slow, dtype=np.float32)
return fast_ax_angles, ret_phases, global_phases, atten_fast, atten_slow
def visualize_components_amplitudes(obj, rot_angle=0, logarithmic=False):
# coord_rot angle is the only angle in degrees here
def coord_rot(angle):
angle = t.as_tensor(angle, dtype=t.float32)
angle = t.deg2rad(angle)
a = t.stack((t.cos(angle), t.sin(angle)), dim=-1)
b = t.stack((-t.sin(angle), t.cos(angle)), dim=-1)
return t.stack((a, b), dim=-2).to(dtype=t.cfloat)
for k, m in zip(*iterator(obj.shape[-2], obj.shape[-1])):
obj[:, :, k, m] = t.matmul(coord_rot(rot_angle), obj[:, :, k, m])
components = [obj[i, j, :, :] for i, j in zip(*iterator(2, 2))]
if logarithmic:
components = [np.log(comp)/np.log(10) for comp in components]
titles = ['Amptlitudes of the a components', 'Amplitudes of the b components',
'Amplitudes of the c components', 'Amplitudes of the d components']
for i in range(4):
amplitude = np.abs(components[i])
plt.imshow(module)
plt.colorbar()
plt.title(titles[i])
def visualize_phase_ret(obj, logarithmic=False):
print('DHSBCUYLIWGBCGLWIYV')
fast_ax_angles, ret_phases, global_phases, atten_fast, atten_slow = retrieve_obj_info(obj)
if logarithmic:
ret_phases = np.log(ret_phases)/np.log(10)
plt.imshow(ret_phases)
plt.colorbar()
plt.show()
def visuallize_global_phases(obj, logarithmic=False):
fast_ax_angles, ret_phases, global_phases, atten_fast, atten_slow = retrieve_obj_info(obj)
if logarithmic:
global_phases = np.log(global_phases)/np.log(10)
plt.imshow(global_phases)
plt.colorbar()
plt.show()
def visualize_fast_axes(obj, num_of_el_along_x=20, num_of_el_along_y=20, scale=1):
fast_ax_angles, ret_phases, global_phases, atten_fast, atten_slow = retrieve_obj_info(obj)
A, B = obj.shape[-2], obj.shape[-1]
plot_figures((A, B), num_of_el_along_x=num_of_el_along_x, num_of_el_along_y=num_of_el_along_y,
fast_ax_angles=fast_ax_angles, scale=scale, fast_axes=True)
def visualize_attenuations(obj, num_of_el_along_x=20, num_of_el_along_y=20, scale=1):
fast_ax_angles, ret_phases, global_phases, atten_fast, atten_slow = retrieve_obj_info(obj)
A, B = obj.shape[-2], obj.shape[-1]
plot_figures((A, B), num_of_el_along_x=num_of_el_along_x, num_of_el_along_y=num_of_el_along_y,
phases=ret_phases, atten_slow=atten_slow, atten_fast=atten_fast,
fast_ax_angles=fast_ax_angles, scale=scale, attenuations=True)
def visualize_probe(probe, scale=1, num_of_el_along_x=20, num_of_el_along_y=20):
a = np.abs(probe[..., 0, :, :])
b = np.abs(probe[..., 1, :, :])
phases = np.angle(probe[..., 1, :, :]) - np.angle(probe[..., 0, :, :])
A, B = np.asarray(probe.shape[-2]), np.asarray(probe.shape[-1])
plot_figures((A, B), num_of_el_along_x=num_of_el_along_x, num_of_el_along_y=num_of_el_along_y,
phases=phases, atten_fast=a, atten_slow=b, scale=scale,
probe=True)
#
# def object_from_components(a, b, c, d):
# ab = t.stack((a, b), dim=-3)
# cd = t.stack((c, d), dim=-3)
# return t.stack((ab, cd), dim=-4)
#
# def object_from_quarters(a, b, c, d):
# ab = t.cat((a, b), dim=-1)
# cd = t.cat((c, d), dim=-1)
# return t.cat((ab, cd), dim=-2)
#
# def generate_birefringent_obj(shape, func_axes=None, func_ret_phases=None, func_global_phases=None, fast_axes=[0, 0, 90, 90], phases=[0, 18, 40, 18]):
# ret = [polarization.generate_birefringent_obj(fast_axis=i, phase_ret=j) for i, j in zip(fast_axes, phases)]
# A = shape[0]
# B = shape[1]
# def to_rad(angle):
# angle = t.as_tensor(angle)
# return t.deg2rad(angle)
#
# if func_axes is None:
# # 4 sets of components for each quarter
# components = [[ret[i][j][k].repeat(A//2, B//2) for j, k in zip(*iterator(2, 2))] for i in range(4)]
# # build the quarters from the components
# quarters = [object_from_components(*comp) for comp in components]
# obj = object_from_quarters(*quarters)
# else:
# X, Y = t.arange(A), t.arange(B)
# X, Y = t.meshgrid(X, Y)
# obj = t.empty(2, 2, A, B, dtype=t.cfloat)
# for i, j in zip(*iterator(A, B)):
# x, y = X[i, j], Y[i, j]
# axis = func_axes(x, y)
# ret = func_ret_phases(x, y)
# gl = func_global_phases(x, y)
# obj[:, :, i, j] = polarization.generate_birefringent_obj(fast_axis=axis, phase_ret=ret, global_phase=gl)
# w, v = t.linalg.eig(obj[:, :, i, j])
#
# # t.tensor of shape (2, 2, A, B)
# return obj
#
# def axes(x, y):
# # return (x-25)**2 + (y-25)**2
# return x * 20
#
# def phases(x, y):
# # return ((x - 5) ** 2 + (y - 5) ** 2) * 20
# return (x) * 10
#
# def glob(x, y):
# return x * 10
#
# def amp(x, y):
# return 1 + 0.05 * (x + y)
#
# def build_probe(shape, phase_ret_func=None, amps_func=None):
# probe = t.empty(2, shape[0], shape[1], dtype=t.cfloat)
# for x, y in zip(*iterator(probe.shape[-2], probe.shape[-1])):
# phase = phase_ret_func(x, y)
# phase = t.deg2rad(phase).to(dtype=t.cfloat)
# abs = amps_func(x, y).to(dtype=t.cfloat)
# probe[0, x, y] = abs
# probe[1, x, y] = abs * t.exp(phase * 1j)
#
# return probe
#
#
# obj = generate_birefringent_obj((10, 10), func_axes=axes, func_ret_phases=phases, func_global_phases=glob)
# probe = build_probe((10, 10), phase_ret_func=phases, amps_func=amp)
# # visualize_probe(probe, num_of_el_along_x=10, num_of_el_along_y=10, scale=0.1)
# visualize_fast_axes(obj, num_of_el_along_x=10, num_of_el_along_y=10, scale=0.1)
# # visualize_phase_ret(obj)
# # visuallize_global_phases(obj)
# # visualize_attenuations(obj, num_of_el_along_x=10, num_of_el_along_y=10, scale=0.3)
# plt.show()