Source code for paos.util.material

import matplotlib.pyplot as plt
import numpy as np

from paos import logger
from paos.core.plot import do_legend


[docs] class Material: """ Class for handling different optical materials for use in ``PAOS`` """ def __init__(self, wl, Tambient=-218.0, Pambient=1.0, materials=None): """ Parameters ---------- Tambient: scalar Ambient temperature during operation (:math:`^{\\circ} C`) Pambient: scalar Ambient pressure during operation (atm) wl: scalar or array wavelength in microns materials: dict library of materials for optical use """ self.wl = wl self.Tambient = Tambient self.Pambient = Pambient if materials is None: from .lib import materials logger.trace("Using default library of optical materials") self.materials = materials
[docs] def sellmeier(self, par): """ Implements the Sellmeier 1 equation to estimate the glass index of refraction relative to air at the glass reference temperature :math:`T_{ref} = 20 ^{\\circ}C` and pressure :math:`P_{ref} = 1 \\ atm`. The Sellmeier 1 equation consists of three terms and is given as :math:`\\displaystyle n^{2}(\\lambda )=1+{\\frac {K_{1}\\lambda ^{2}}{\\lambda ^{2}-L_{1}}}+ {\\frac {K_{2}\\lambda ^{2}}{\\lambda ^{2}-L_{2}}}+{\\frac {K_{3}\\lambda ^{2}}{\\lambda ^{2}-L_{3}}}` Parameters ---------- par: dict dictionary containing the :math:`K_1`, :math:`L_1`, :math:`K_2`, :math:`L_2`, :math:`K_3`, :math:`L_3` parameters of the Sellmeier 1 model Returns ------- out: scalar or array (same shape as wl) the refractive index """ wl2 = self.wl**2 n2_1 = par["K1"] * wl2 / (wl2 - par["L1"]) n2_1 += par["K2"] * wl2 / (wl2 - par["L2"]) n2_1 += par["K3"] * wl2 / (wl2 - par["L3"]) return np.sqrt(n2_1 + 1.0)
[docs] @staticmethod def nT(n, D0, delta_T): """ Estimate the change in the glass absolute index of refraction with temperature as :math:`n(\\Delta T) = \\Delta n_{abs} + n` where :math:`\\Delta n_{abs} = \\frac{n^2 - 1}{2 n} D_0 \\Delta T` Parameters ---------- n: scalar or array relative index at the reference temperature of the glass D0: scalar model parameter (constant provided by the glass manufacturer to describe the glass thermal behaviour) delta_T: scalar change in temperature relative to the reference temperature of the glass. It is positive if the temperature is greater than the reference temperature of the glass Returns ------- out: scalar or array (same shape as n) the scaled relative index """ dnabs = (n**2 - 1.0) / (2.0 * n) * D0 * delta_T return n + dnabs
[docs] def nair(self, T, P=1.0): """ Estimate the air index of refraction at wavelength :math:`\\lambda`, temperature :math:`T`, and relative pressure :math:`P` as :math:`n_{air} = 1 + \\frac{\\left(n_{ref} - 1\\right) P}{1.0 + (T - 15) \\cdot (3.4785 \\times 10^{-3}) }` where :math:`n_{ref} = 1 + \\left[6432.8 + \\frac{2949810 \\lambda^{2}}{146 \\lambda^{2} - 1} + \\frac{25540 \\lambda^{2}}{41 \\lambda^{2} - 1} \\right] \\cdot 10^{-8}` This formula for the index of air is from F. Kohlrausch, Praktische Physik, 1968, Vol 1, page 408. Parameters ---------- T: scalar temperature in :math:`^{\\circ} C` P: scalar relative pressure in atmospheres (dimensionless in the formula). Defaults to 1 atm. Returns ------- out: scalar or array (same shape as wl) the air index of refraction Note ---- 1) Air at the system temperature and pressure is defined to be 1.0, all other indices are relative 2) ``PAOS`` can easily model systems used in a vacuum by changing the air pressure to zero """ wl2 = self.wl**2 nref = 1.0 + 1.0e-8 * ( 6432.8 + 2949810.0 * wl2 / (146.0 * wl2 - 1.0) + 25540.0 * wl2 / (41.0 * wl2 - 1.0) ) nair = 1.0 + (nref - 1.0) * P / (1.0 + 3.4785e-3 * (T - 15)) return nair
[docs] def nmat(self, name): """ Given the name of an optical glass, returns the index of refraction in vacuum as a function of wavelength. Parameters ---------- name: str name of the optical glass Returns ------- out: tuple(scalar, scalar) or tuple(array, array) returns two arrays for the glass index of refraction at the given wavelengths: the index of refraction at :math:`T_{ref} = 20^{\\circ} C` (nmat0) and the index of refraction at :math:`T_{amb}` (nmat) """ name = name.upper() if name not in self.materials.keys(): logger.error(f"Glass {name} currently not supported.") material = self.materials[name] logger.trace(f'Glass name: {name} -- T ref: {material["Tref"]}') nmat0 = self.sellmeier(par=material["sellmeier"]) * self.nair( T=material["Tref"], P=self.Pambient ) nmat = self.nT( n=nmat0, D0=material["Tmodel"]["D0"], delta_T=self.Tambient - material["Tref"], ) return nmat0, nmat
[docs] def plot_relative_index(self, material_list=None, ncols=2, figname=None): """ Given a list of materials for optical use, plots the relative index in function of wavelength, at the reference and operating temperature. Parameters ---------- material_list: list a list of materials, e.g. ['SF11', 'ZNSE'] ncols: int number of columns for the subplots figname: str name of figure to save Returns ------- out: None displays the plot output or stores it to the indicated plot path Examples -------- >>> from paos.util.material import Material >>> Material(wl = np.linspace(1.8, 8.0, 1024)).plot_relative_index(material_list=['Caf2', 'Sf11', 'Sapphire']) """ i, j = None, None if material_list is None: material_list = [] n_subplots = len(material_list) if ncols > n_subplots: ncols = n_subplots nrows = n_subplots // ncols if n_subplots % ncols: nrows += 1 figsize = (8 * ncols, 6 * nrows) fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=figsize) fig.patch.set_facecolor("white") plt.subplots_adjust(hspace=0.3, wspace=0.5) for k, name in enumerate(material_list): if n_subplots == 1: axis = ax elif n_subplots == 2: axis = ax[k] else: i = k % ncols j = k // ncols axis = ax[j, i] nmat0, nmat = self.nmat(name) axis.plot(self.wl, nmat0, "--", label=r"T$_{ref}$") axis.plot(self.wl, nmat, label=r"T$_{oper}$") axis.set_title(name) do_legend(axis=axis, ncol=2) axis.set_xlabel("Wavelength [micron]") axis.set_ylabel("Relative index") axis.grid() if n_subplots % ncols and k == n_subplots - 1: for col in range(i + 1, ncols): ax[j, col].set_visible(False) if figname is not None: fig.savefig(figname, bbox_inches="tight", dpi=150) plt.close() else: fig.tight_layout() plt.show() return