import numpy as np
from skcomponents.optics.component import OpticalComponent
[docs]class LinearPolarizer(OpticalComponent):
def __init__(self, orientation: float,
wavelength_nm: np.array = None,
contrast_ratio: np.array = None,
transmission: np.array = None):
"""
Linear polarizer
Parameters
----------
orientation : float
Orientation of the polarizer in degrees. 0 is horizontal, 90 is vertical
"""
self._theta = orientation
if contrast_ratio is not None:
if len(wavelength_nm) != len(contrast_ratio):
raise ValueError('wavelength_nm and contrast_ratio must be the same length')
self._k1 = contrast_ratio / (1 + contrast_ratio)
self._k2 = 1 / (1 + contrast_ratio)
if transmission is not None:
if len(wavelength_nm) != len(transmission):
raise ValueError('wavelength_nm and transmission must be the same length')
self._transmission = transmission
self._contrast_ratio = contrast_ratio
self._wavelength_nm = wavelength_nm
@property
def orientation(self):
return self._theta
@orientation.setter
def orientation(self, value):
self._theta = value
@property
def wavelength_nm(self):
return self._wavelength_nm
def contrast_ratio(self, wavelength):
if self._contrast_ratio is None:
return np.inf
else:
return np.interp(wavelength, self._wavelength_nm, self._contrast_ratio)
def transmission(self, wavelength):
if self._transmission is None:
return 1.0
else:
return np.interp(wavelength, self._wavelength_nm, self._transmission,
left=self._transmission[0], right=self._transmission[-1])
def px(self, wavelength):
if self._contrast_ratio is None:
return 1
else:
return np.sqrt(np.interp(wavelength, self._wavelength_nm, self._k1,
left=self._k1[0], right=self._k1[-1]))
def py(self, wavelength):
if self._contrast_ratio is None:
return 0
else:
return np.sqrt(np.interp(wavelength, self._wavelength_nm, self._k2,
left=self._k2[0], right=self._k2[-1]))
def _mueller_matrix(self, wavelength):
px = self.px(wavelength)
py = self.py(wavelength)
m11 = px ** 2 + py ** 2
m12 = px ** 2 - py ** 2
m21 = m12
m22 = m11
m33 = 2 * px * py
m44 = m33
t = self.transmission(wavelength)
return t * 0.5 * np.array([[m11, m12, 0, 0],
[m21, m22, 0, 0],
[0, 0, m33, 0],
[0, 0, 0, m44]])
[docs] def matrix(self, wavelength):
return self.rotation_matrix(self._theta) @ self._mueller_matrix(wavelength) @ self.rotation_matrix(-self._theta)
@staticmethod
def rotation_matrix(theta):
theta = 2 * theta * np.pi / 180
return np.array([[1, 0, 0, 0],
[0, np.cos(theta), np.sin(theta), 0],
[0, -np.sin(theta), np.cos(theta), 0],
[0, 0, 0, 1]])
[docs]class IdealLinearPolarizer(LinearPolarizer):
def _mueller_matrix(self, wavelength):
return 0.5 * np.array([[1, 1, 0, 0],
[1, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
[docs]class VerticalPolarizer(LinearPolarizer):
def __init__(self, **kwargs):
super().__init__(90.0, **kwargs)
[docs]class HorizontalPolarizer(LinearPolarizer):
def __init__(self, **kwargs):
super().__init__(0.0, **kwargs)