Source code for tmm.examples

# -*- coding: utf-8 -*-
"""
Examples of plots and calculations using the tmm package.
"""

from __future__ import division, print_function, absolute_import

from .tmm_core import (coh_tmm, unpolarized_RT, ellips,
                       position_resolved, find_in_structure_with_inf)

from numpy import pi, linspace, inf, array
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

try:
    import colorpy.illuminants
    import colorpy.colormodels
    from . import color
    colors_were_imported = True
except ImportError:
    # without colorpy, you can't run sample5(), but everything else is fine.
    colors_were_imported = False


# "5 * degree" is 5 degrees expressed in radians
# "1.2 / degree" is 1.2 radians expressed in degrees
degree = pi/180

[docs]def sample1(): """ Here's a thin non-absorbing layer, on top of a thick absorbing layer, with air on both sides. Plotting reflected intensity versus wavenumber, at two different incident angles. """ # list of layer thicknesses in nm d_list = [inf, 100, 300, inf] # list of refractive indices n_list = [1, 2.2, 3.3+0.3j, 1] # list of wavenumbers to plot in nm^-1 ks = linspace(0.0001, .01, num=400) # initialize lists of y-values to plot Rnorm = [] R45 = [] for k in ks: # For normal incidence, s and p polarizations are identical. # I arbitrarily decided to use 's'. Rnorm.append(coh_tmm('s', n_list, d_list, 0, 1/k)['R']) R45.append(unpolarized_RT(n_list, d_list, 45*degree, 1/k)['R']) kcm = ks * 1e7 #ks in cm^-1 rather than nm^-1 plt.figure() plt.plot(kcm, Rnorm, 'blue', kcm, R45, 'purple') plt.xlabel('k (cm$^{-1}$)') plt.ylabel('Fraction reflected') plt.title('Reflection of unpolarized light at 0$^\circ$ incidence (blue), ' '45$^\circ$ (purple)')
[docs]def sample2(): """ Here's the transmitted intensity versus wavelength through a single-layer film which has some complicated wavelength-dependent index of refraction. (I made these numbers up, but in real life they could be read out of a graph / table published in the literature.) Air is on both sides of the film, and the light is normally incident. """ #index of refraction of my material: wavelength in nm versus index. material_nk_data = array([[200, 2.1+0.1j], [300, 2.4+0.3j], [400, 2.3+0.4j], [500, 2.2+0.4j], [750, 2.2+0.5j]]) material_nk_fn = interp1d(material_nk_data[:,0].real, material_nk_data[:,1], kind='quadratic') d_list = [inf, 300, inf] #in nm lambda_list = linspace(200, 750, 400) #in nm T_list = [] for lambda_vac in lambda_list: n_list = [1, material_nk_fn(lambda_vac), 1] T_list.append(coh_tmm('s', n_list, d_list, 0, lambda_vac)['T']) plt.figure() plt.plot(lambda_list, T_list) plt.xlabel('Wavelength (nm)') plt.ylabel('Fraction of power transmitted') plt.title('Transmission at normal incidence')
[docs]def sample3(): """ Here is a calculation of the psi and Delta parameters measured in ellipsometry. This reproduces Fig. 1.14 in Handbook of Ellipsometry by Tompkins, 2005. """ n_list = [1, 1.46, 3.87+0.02j] ds = linspace(0, 1000, num=100) #in nm psis = [] Deltas = [] for d in ds: e_data = ellips(n_list, [inf, d, inf], 70*degree, 633) #in nm psis.append(e_data['psi']/degree) # angle in degrees Deltas.append(e_data['Delta']/degree) # angle in degrees plt.figure() plt.plot(ds, psis, ds, Deltas) plt.xlabel('SiO2 thickness (nm)') plt.ylabel('Ellipsometric angles (degrees)') plt.title('Ellipsometric parameters for air/SiO2/Si, varying ' 'SiO2 thickness.\n' '@ 70$^\circ$, 633nm. ' 'Should agree with Handbook of Ellipsometry Fig. 1.14')
[docs]def sample4(): """ Here is an example where we plot absorption and Poynting vector as a function of depth. """ d_list = [inf, 100, 300, inf] #in nm n_list = [1, 2.2+0.2j, 3.3+0.3j, 1] th_0 = pi/4 lam_vac = 400 pol = 'p' coh_tmm_data = coh_tmm(pol, n_list, d_list, th_0, lam_vac) ds = linspace(-50, 400, num=1000) #position in structure poyn = [] absor = [] for d in ds: layer, d_in_layer = find_in_structure_with_inf(d_list, d) data = position_resolved(layer, d_in_layer, coh_tmm_data) poyn.append(data['poyn']) absor.append(data['absor']) # convert data to numpy arrays for easy scaling in the plot poyn = array(poyn) absor = array(absor) plt.figure() plt.plot(ds, poyn, 'blue', ds, 200*absor, 'purple') plt.xlabel('depth (nm)') plt.ylabel('AU') plt.title('Local absorption (purple), Poynting vector (blue)')
[docs]def sample5(): """ Color calculations: What color is a air / thin SiO2 / Si wafer? """ if not colors_were_imported: print('Colorpy was not detected (or perhaps an error occurred when', 'loading it). You cannot do color calculations, sorry!', 'Original version is at http://pypi.python.org/pypi/colorpy', 'A Python 3 compatible edit is at https://github.com/fish2000/ColorPy/') return # Crystalline silicon refractive index. Data from Palik via # http://refractiveindex.info, I haven't checked it, but this is just for # demonstration purposes anyway. Si_n_data = [[400, 5.57 + 0.387j], [450, 4.67 + 0.145j], [500, 4.30 + 7.28e-2j], [550, 4.08 + 4.06e-2j], [600, 3.95 + 2.57e-2j], [650, 3.85 + 1.64e-2j], [700, 3.78 + 1.26e-2j]] Si_n_data = array(Si_n_data) Si_n_fn = interp1d(Si_n_data[:,0], Si_n_data[:,1], kind='linear') # SiO2 refractive index (approximate): 1.46 regardless of wavelength SiO2_n_fn = lambda wavelength : 1.46 # air refractive index air_n_fn = lambda wavelength : 1 n_fn_list = [air_n_fn, SiO2_n_fn, Si_n_fn] th_0 = 0 # Print the colors, and show plots, for the special case of 300nm-thick SiO2 d_list = [inf, 300, inf] reflectances = color.calc_reflectances(n_fn_list, d_list, th_0) illuminant = colorpy.illuminants.get_illuminant_D65() spectrum = color.calc_spectrum(reflectances, illuminant) color_dict = color.calc_color(spectrum) print('air / 300nm SiO2 / Si --- rgb =', color_dict['rgb'], ', xyY =', color_dict['xyY']) plt.figure() color.plot_reflectances(reflectances, title='air / 300nm SiO2 / Si -- ' 'Fraction reflected at each wavelength') plt.figure() color.plot_spectrum(spectrum, title='air / 300nm SiO2 / Si -- ' 'Reflected spectrum under D65 illumination') # Calculate irgb color (i.e. gamma-corrected sRGB display color rounded to # integers 0-255) versus thickness of SiO2 max_SiO2_thickness = 600 SiO2_thickness_list = linspace(0, max_SiO2_thickness, num=80) irgb_list = [] for SiO2_d in SiO2_thickness_list: d_list = [inf, SiO2_d, inf] reflectances = color.calc_reflectances(n_fn_list, d_list, th_0) illuminant = colorpy.illuminants.get_illuminant_D65() spectrum = color.calc_spectrum(reflectances, illuminant) color_dict = color.calc_color(spectrum) irgb_list.append(color_dict['irgb']) # Plot those colors print('Making color vs SiO2 thickness graph. Compare to (for example)') print('http://www.htelabs.com/appnotes/sio2_color_chart_thermal_silicon_dioxide.htm') plt.figure() plt.plot([0, max_SiO2_thickness], [1, 1]) plt.xlim(0, max_SiO2_thickness) plt.ylim(0, 1) plt.xlabel('SiO2 thickness (nm)') plt.yticks([]) plt.title('Air / SiO2 / Si color vs SiO2 thickness') for i in range(len(SiO2_thickness_list)): # One strip of each color, centered at x=SiO2_thickness_list[i] if i == 0: x0 = 0 else: x0 = (SiO2_thickness_list[i] + SiO2_thickness_list[i-1]) / 2 if i == len(SiO2_thickness_list) - 1: x1 = max_SiO2_thickness else: x1 = (SiO2_thickness_list[i] + SiO2_thickness_list[i+1]) / 2 y0 = 0 y1 = 1 poly_x = [x0, x1, x1, x0] poly_y = [y0, y0, y1, y1] color_string = colorpy.colormodels.irgb_string_from_irgb(irgb_list[i]) plt.fill(poly_x, poly_y, color_string, edgecolor=color_string)
[docs]def sample6(): """ An example reflection plot with a surface plasmon resonance (SPR) dip. Compare with http://doi.org/10.2320/matertrans.M2010003 ("Spectral and Angular Responses of Surface Plasmon Resonance Based on the Kretschmann Prism Configuration") Fig 6a """ # list of layer thicknesses in nm d_list = [inf, 5, 30, inf] # list of refractive indices n_list = [1.517, 3.719+4.362j, 0.130+3.162j, 1] # wavelength in nm lam_vac = 633 # list of angles to plot theta_list = linspace(30*degree, 60*degree, num=300) # initialize lists of y-values to plot Rp = [] for theta in theta_list: Rp.append(coh_tmm('p', n_list, d_list, theta, lam_vac)['R']) plt.figure() plt.plot(theta_list/degree, Rp, 'blue') plt.xlabel('theta (degree)') plt.ylabel('Fraction reflected') plt.xlim(30, 60) plt.ylim(0, 1) plt.title('Reflection of p-polarized light with Surface Plasmon Resonance\n' 'Compare with http://doi.org/10.2320/matertrans.M2010003 Fig 6a')