Source code for opticalmaterialspy.material

# -*- coding: utf-8 -*-

import numpy as np
from scipy import constants as spc
from scipy import interpolate as spi
from ._material_base import _Material
import urllib.request
import os
import json

[docs]class Data(_Material): ''' An object that facilitates importing materials from lists. Args: wls (list): List of wavelengths. ns (list): List of refractive indices at the corresponding `wls`. Should be the same size as `wls`. ''' def __init__(self, wls, ns): assert len(wls) == len(ns), ('There should be the same amount of ' 'wavelengths as refractive index values.') wls *= 1e3 wl_min = wls[0] wl_max = wls[-1] n_func = spi.interp1d(wls, ns) self._n = lambda wavelength: n_func(wavelength) _Material.__init__(self, wl_min, wl_max) def _eps(self, wavelength): return self._n(wavelength)**2
[docs]class RefractiveIndexWeb(Data): ''' Object to create a `_Material` based on data from https://refractiveindex.info/. Args: web_link (str): The web link to the material. As an example, for GaAs by Aspnes et al. 1986 the one should use 'https://refractiveindex.info/?shelf=main&book=GaAs&page=Aspnes'. ''' def __init__(self, web_link): self._web_link = web_link path = os.path.dirname(__file__) fn_cache = path + '/.material.cache' if not os.path.exists(fn_cache): # If cache file does not yet exist. # Get web data and dump it to the newly created cache file. fields = self._parse_weblink(web_link) data = self._get_csv(fields) cache = {web_link: data.tolist()} with open(fn_cache, 'w') as fs: json.dump(cache, fs) else: # Otherwise, load the cache and check if the weblink is in there. with open(fn_cache, 'r') as fs: cache = json.load(fs) try: data = np.array(cache[web_link]) except KeyError: fields = self._parse_weblink(web_link) data = self._get_csv(fields) cache[web_link] = data.tolist() with open(fn_cache, 'w') as fs: json.dump(cache, fs) Data.__init__(self, data[0], data[1]) def _parse_weblink(self, link): prefix = 'https://refractiveindex.info/?' suffix = link[len(prefix):] info = suffix.split('&') fields = dict([f.split('=') for f in info]) return fields def _get_csv(self, fields): csv_url = 'https://refractiveindex.info/data_csv.php?datafile=data/%s/%s/%s.yml' \ % (fields['shelf'], fields['book'], fields['page']) data = urllib.request.urlopen(csv_url).read().decode().split('\r\n')[1:-1] data = np.array([[float(x) for x in d.split(',')] for d in data]).T return data
[docs]class Air(_Material): def __init__(self): _Material.__init__(self) def _eps(self, wavelength=None): return 1.
# http://www.opticsinfobase.org/view_article.cfm?gotourl=http%3A%2F%2Fwww.opticsinfobase.org%2FDirectPDFAccess%2FEEE59E78-F228-BD74-8B64990932FFCE71_69785%2Fao-41-24-5040.pdf%3Fda%3D1%26id%3D69785%26seq%3D0%26mobile%3Dno&org=Royal%20Melbourne%20Institute%20of%20Technology%20Swanston
[docs]class Ktp(_Material): def __init__(self, axis): _Material.__init__(self) assert(axis in ['x', 'y', 'z']) self.A = [None]*5 if axis is 'x': self.A[0] = 3.29100 self.A[1] = 0.04140 self.A[2] = 0.03978 self.A[3] = 9.35522 self.A[4] = 31.45571 elif axis is 'y': self.A[0] = 3.45018 self.A[1] = 0.04341 self.A[2] = 0.04597 self.A[3] = 16.98825 self.A[4] = 39.43799 elif axis is 'z': self.A[0] = 4.59423 self.A[1] = 0.06206 self.A[2] = 0.04763 self.A[3] = 110.80672 self.A[4] = 86.12171 # Permittivity def _eps(self, wavelength): A = self.A wavelengthUm = wavelength * 1.e-3 # [nm] -> [um] return A[0] + A[1] / (wavelengthUm**2 - A[2]) + A[3] / (wavelengthUm**2 - A[4])
# http://www.goochandhousego.com/wp-content/pdfs/LNmatProperties.pdf
[docs]class Ln(_Material): def __init__(self, axis, temperatureCelcius=20.): _Material.__init__(self) assert(axis in ['o', 'e']) self.T = temperatureCelcius self.F = (self.T - 24.5) * (self.T + 570.5) self.A = [None]*4 self.B = [None]*3 if axis is 'e': self.A[0] = 4.582 self.A[1] = 9.921e4 self.A[2] = 2.109e2 self.A[3] = 2.194e-8 self.B[0] = 5.2716e-2 self.B[1] = -4.9143e-5 self.B[2] = 2.2971e-7 elif axis is 'o': self.A[0] = 4.9048 self.A[1] = 1.1775e5 self.A[2] = 2.1802e2 self.A[3] = 2.7153e-8 self.B[0] = 2.2314e-2 self.B[1] = -2.9671e-5 self.B[2] = 2.1429e-8 # Permittivity def _eps(self, wavelength): A, B, F = self.A, self.B, self.F return A[0] + (A[1] + B[0]*F) / (wavelength**2 - (A[2] + B[1]*F)**2) + \ B[2]*F - A[3]*wavelength**2
[docs]class Tfln(Ln): def __init__(self, axis, temperatureCelcius=20.): Ln.__init__(self, axis, temperatureCelcius) eps_1550_orig = super(Tfln, self)._eps(1550) if axis == 'o': no_1550 = 2.20600 epso_1550 = no_1550**2 self._deps = epso_1550 - eps_1550_orig elif axis == 'e': ne_1550 = 2.14455 epse_1550 = ne_1550**2 self._deps = epse_1550 - eps_1550_orig def _eps(self, wavelength): e = super(Tfln, self)._eps(wavelength) e += self._deps return e
[docs]class LnMg(_Material): def __init__(self, axis): _Material.__init__(self) assert(axis in ['o', 'e']) self.A = [None]*6 if axis is 'e': self.A[0] = 2.2454 self.A[1] = 0.01242 self.A[2] = 1.3005 self.A[3] = 0.05313 self.A[4] = 6.8972 self.A[5] = 331.33 elif axis is 'o': self.A[0] = 2.4272 self.A[1] = 0.01478 self.A[2] = 1.4617 self.A[3] = 0.05612 self.A[4] = 9.6536 self.A[5] = 371.216 # Permittivity def _eps(self, wavelength): A = self.A wavelengthUm = wavelength * 1.e-3 # [nm] -> [um] e = wavelengthUm**2*(A[0]/(-A[1] + wavelengthUm**2) + \ A[2]/(-A[3] + wavelengthUm**2) + \ A[4]/(-A[5] + wavelengthUm**2)) + \ 1. return e
# Gayer, 2008, Temperature and wavelength dependent refractive index equations for MgO-doped congruent and stoichiometric LiNbO3
[docs]class LnMgTemp(_Material): def __init__(self, axis, temperatureCelcius=20.): _Material.__init__(self) assert(axis in ['o', 'e']) self.T = temperatureCelcius self.F = (self.T - 24.5) * (self.T + 570.82) self.A = [None]*6 self.B = [None]*6 if axis is 'e': self.A[0] = 5.756 self.A[1] = 0.0983 self.A[2] = 0.2020 self.A[3] = 189.32 self.A[4] = 12.52 self.A[5] = 1.32e-2 self.B[0] = 2.860e-6 self.B[1] = 4.700e-8 self.B[2] = 6.113e-8 self.B[3] = 1.516e-4 elif axis is 'o': self.A[0] = 5.653 self.A[1] = 0.1185 self.A[2] = 0.2091 self.A[3] = 89.61 self.A[4] = 10.85 self.A[5] = 1.97e-2 self.B[0] = 7.941e-7 self.B[1] = 3.3134e-8 self.B[2] = -4.641e-9 self.B[3] = -2.188e-6 # Permittivity def _eps(self, wavelength): a = self.A b = self.B wavelengthUm = wavelength * 1.e-3 # [nm] -> [um] e = a[0] + b[0]*self.F + \ (a[1] + b[1]*self.F) / (wavelengthUm**2 - (a[2] + b[2]*self.F)**2) + \ (a[3] + b[3]*self.F) / (wavelengthUm**2 - a[4]**2) - \ a[5]*wavelengthUm**2 return e
# https://www.coherent.com/downloads/BBO_DS.pdf
[docs]class Bbo(_Material): def __init__(self, axis): _Material.__init__(self) assert(axis in ['o', 'e']) self.A = [None]*4 if axis is 'e': self.A[0] = 2.3730 self.A[1] = 0.0128 self.A[2] = 0.0156 self.A[3] = 0.0044 elif axis is 'o': self.A[0] = 2.7405 self.A[1] = 0.0184 self.A[2] = 0.0179 self.A[3] = 0.0155 # Permittivity def _eps(self, wavelength): A = self.A wavelengthUm = wavelength * 1.e-3 # [nm] -> [um] e = A[0] + A[1]/(wavelengthUm**2 - A[2]) - A[3]*wavelengthUm**2 return e
# https://books.google.com.au/books?id=zKI4hdtEVHwC&pg=PA216&lpg=PA216&dq=bibo+refractive+index+sellmeier&source=bl&ots=lyfLo24tVp&sig=z-shFbjI1HXynIKkS0XZENjoxOw&hl=en&sa=X&ei=KpNuVbjyJ8rz8gWk-YKIDg&ved=0CDoQ6AEwBQ#v=onepage&q=bibo%20refractive%20index%20sellmeier&f=false
[docs]class Bibo(Bbo): def __init__(self, axis): _Material.__init__(self) assert(axis in ['x', 'y', 'z']) self.A = [None]*5 if axis is 'x': self.A[0] = 3.0722 self.A[1] = 0.0324 self.A[2] = 0.0315 self.A[3] = 0.0133 elif axis is 'y': self.A[0] = 3.1669 self.A[1] = 0.0372 self.A[2] = 0.0348 self.A[3] = 0.0175 elif axis is 'z': self.A[0] = 3.6525 self.A[1] = 0.0511 self.A[2] = 0.0370 self.A[3] = 0.0226
# Linear optical characterization of chalcogenide glasses # G. Boudebs, S. Cherukulappurath, M. Guignard, J. Troles, F. Smektala, F. Sanchez
[docs]class Chalcogenide(_Material): def __init__(self, chalcogenideType): _Material.__init__(self) self.chalcogenideType = chalcogenideType cauchyCoefs = { 'As2S3' : [5.41, 0.20, 0.14] , 'As2Se3' : [7.56, 1.03, 0.12] , 'GeSe4' : [5.73, 0.80, -0.18] , 'Ge10As10Se80' : [5.73, 0.80, -0.18] } self.A = cauchyCoefs[self.chalcogenideType] def _eps(self, wavelength): A = self.A wavelengthUm = wavelength * 1.e-3 e = A[0] + A[1] / wavelengthUm**2 + A[2] / wavelengthUm**4 return e
[docs]class SiO2(_Material): def __init__(self): _Material.__init__(self) def _eps(self, wavelength): x = wavelength * 1.e-3 e = 1+0.6961663/(1-np.power(0.0684043/x,2))+0.4079426/(1-np.power(0.1162414/x,2))+\ 0.8974794/(1-np.power(9.896161/x,2)) return e
[docs]class Su8(_Material): def __init__(self): _Material.__init__(self) self.coefs = [1.5525, 0.00629, 0.0004] def _eps(self, wavelength): wavelength /= 1000. n = _Material._cauchy_equation(wavelength, self.coefs) eps = n**2 return eps
# https://refractiveindex.info/?shelf=main&book=Al2O3&page=Malitson-o
[docs]class Al2O3(_Material): def __init__(self, axis): _Material.__init__(self) assert(axis in ['o', 'e']) if axis == 'o': self._eps_e_o = self._eps_o elif axis == 'e': self._eps_e_o = self._eps_e def _eps_o(self, wavelength): x = wavelength * 1.e-3 e = 1+1.4313493/(1-np.power(0.0726631/x,2))+ \ 0.65054713/(1-np.power(0.1193242/x,2))+ \ 5.3414021/(1-np.power(18.028251/x,2)) return e def _eps_e(self, wavelength): x = wavelength * 1.e-3 e = 1+1.5039759/(1-np.power(0.0740288/x,2))+ \ 0.55069141/(1-np.power(0.1216529/x,2))+ \ 6.5927379/(1-np.power(20.072248/x,2)) return e def _eps(self, wavelength): return self._eps_e_o(wavelength)
# https://refractiveindex.info/?shelf=main&book=TiO2&page=Devore-o
[docs]class TiO2(_Material): def __init__(self, axis): _Material.__init__(self) assert(axis in ['o', 'e']) if axis == 'o': self._eps_e_o = self._eps_o elif axis == 'e': self._eps_e_o = self._eps_e def _eps_o(self, wavelength): x = wavelength * 1.e-3 e = 5.913+0.2441/(np.power(x,2)-0.0803) return e def _eps_e(self, wavelength): x = wavelength * 1.e-3 e = 7.197+0.3322/(np.power(x,2)-0.0843) return e def _eps(self, wavelength): return self._eps_e_o(wavelength)