123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- import snlay as sn
- import numpy as np
- from scipy import interpolate
- from noise import pnoise1
- import random
- from tmm import coh_tmm
- import multiprocessing as mp
- matsdict = {
- 1: './materials/gold.dat',
- 2: './materials/silicon.dat',
- 3: './materials/silica.dat',
- 4: './materials/tio2.dat',
- 5: './materials/silver.dat'
- }
- def get_nk(datafile, wavelengths):
- """Reads the given file and returns the n+ik complex at
- the given wavelength after suitable interpolation
- :datafile: TODO
- :wavelength: TODO
- :returns: TODO
- """
- rawdisp = np.loadtxt(datafile)
- f_r = interpolate.interp1d(rawdisp[:,0], rawdisp[:,1])
- f_i = interpolate.interp1d(rawdisp[:,0], rawdisp[:,2])
- return f_r(wavelengths) + 1j*f_i(wavelengths)
- def nk_2_eps(n):
- """TODO: Docstring for nk_2_epsnk_2_eps.
- :returns: complex epsilon given n and kappa
- """
- eps_r = n.real**2 - n.imag**2
- eps_i = 2*n.real*n.imag
- return eps_r + 1j*eps_i
- def eps_2_nk(eps):
- """TODO: Docstring for nk_2_epsnk_2_eps.
- :returns: complex epsilon given n and kappa
- """
- modeps = np.abs(eps)
- n_r = np.sqrt(0.5*(modeps + eps.real))
- n_i = np.sqrt(0.5*(modeps - eps.real))
- return n_r + 1j*n_i
- def LL_mixing(fH, n_H, n_L):
- """TODO: Docstring for brugg_mixingbrugg_mixing.
- Given the volumne fraction of the higher index material, give the effective
- index of the layer
- :fH: volumne fraction from 0 to 1
- :n_H: ri of the higher index material
- :n_L: ri of the lower index material
- :returns: TODO
- """
- eH = nk_2_eps(n_H)
- eL = nk_2_eps(n_L)
- bigK = fH*(eH - 1)/(eH + 2) + (1 - fH)*(eL - 1)/(eL + 2)
- e_eff = (1 + 2*bigK)/(1 - bigK)
- return eps_2_nk(e_eff)
- def bet01(x):
- x = x - np.amin(x)
- x = x/np.amax(x)
- return x
- def make_qx(num_layers):
- """generate a random q_x array
- :num_layers: the number of layers
- :returns: a random function with bounds 0 and 1
- """
- uni = np.linspace(0, num_layers, num_layers, endpoint=False)
- rwalk = np.ones_like(uni)
- rwalk[0] = 0
- p_motion = random.random()
- pos_counter = 0
-
- for i in range(1,num_layers):
- test = random.random()
- if test >= p_motion:
- pos_counter += np.random.uniform(1,10)
- else:
- pos_counter -= np.random.uniform(1,10)
- rwalk[i] = pos_counter
- rwalk = bet01(rwalk)
-
- samps = int(np.random.uniform(int(num_layers/10)+2, int(9*num_layers/10), 1))
- scales = np.random.uniform(0.05, 0.75, 1)
- s = np.linspace(-1, num_layers + 1, samps)
- fr = np.clip(np.random.normal(loc=0.5, scale=scales, size=samps), 0, 1)
- fr_p = s - s
- for ctr, x in enumerate(s):
- octa = np.random.uniform(1, 8, 1)
- pers = np.random.uniform(0.5, 2.2, 1)
- fr_p[ctr] = np.clip((0.5 + pnoise1(x, octaves=octa, persistence=pers)), 0, 1)
-
-
- if np.random.randint(2):
- f = interpolate.interp1d(s, fr, kind="quadratic", assume_sorted=True)
- else:
- f = interpolate.interp1d(s, fr_p, kind="quadratic", assume_sorted=True)
- if random.random() >= 0.20:
- rwalk = np.clip(f(uni), 0, 1)
-
- return rwalk
- def tmm_eval2(
- qx,
- cthick,
- lam_low=400,
- lam_high=1200,
- lam_pts=100,
- ang_low=0,
- ang_high=90,
- ang_pts=25,
- n_subs=1.52,
- ):
- """TODO: Docstring for tmm_eval.
- :qx: TODO
- :lam_low: TODO
- :#in nm
- lam_high: TODO
- :lam_pts: TODO
- :ang_low: TODO
- :#degrees
- ang_high: TODO
- :ang_pts: TODO
- :returns: TODO
- """
- degree = np.pi/180
- lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)
- thetas = np.linspace(ang_high, ang_low, endpoint=True, num=ang_pts)
- Rs = np.zeros((thetas.size, lams.size))
- Rp = np.zeros((thetas.size, lams.size))
- for tidx, theta in enumerate(thetas):
- for lidx, lam in enumerate(lams):
- d_x, n_x = make_nxdx(qx=qx, cthick=cthick, wavelen=lam, n_substrate=n_subs)
- Rs[tidx, lidx] = 100*coh_tmm('s',n_x,d_x, th_0=theta*degree,lam_vac=lam)
- Rp[tidx, lidx] = 100*coh_tmm('p',n_x,d_x, th_0=theta*degree,lam_vac=lam)
- return Rs, Rp
- def tmm_eval(
- qx,
- cthick,
- lam_low=400,
- lam_high=1200,
- lam_pts=100,
- ang_low=0,
- ang_high=90,
- ang_pts=25,
- n_subs=1.52,
- ):
- """TODO: Docstring for tmm_eval.
- :qx: TODO
- :lam_low: TODO
- :#in nm
- lam_high: TODO
- :lam_pts: TODO
- :ang_low: TODO
- :#degrees
- ang_high: TODO
- :ang_pts: TODO
- :returns: TODO
- """
- degree = np.pi/180
- lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)
- thetas = np.linspace(ang_high, ang_low, endpoint=True, num=ang_pts)
- Rs = np.zeros((thetas.size, lams.size))
- Rp = np.zeros((thetas.size, lams.size))
- for tidx, theta in enumerate(thetas):
- for lidx, lam in enumerate(lams):
- d_x, n_x = make_nxdx(qx=qx, cthick=cthick, wavelen=lam, n_substrate=n_subs)
- Rs[tidx, lidx] = 100*coh_tmm('s',n_x,d_x, th_0=theta*degree,lam_vac=lam)
- Rp[tidx, lidx] = 100*coh_tmm('p',n_x,d_x, th_0=theta*degree,lam_vac=lam)
- return Rs, Rp
- def tmm_eval_wbk(
- qx,
- cthick,
- inc_ang,
- lam,
- n_subs=1.52
- ):
- """TODO: Docstring for tmm_eval.
- :qx: TODO
- :returns: TODO
- """
- degree = np.pi/180
- d_x, n_x = make_nxdx(qx=qx, cthick=cthick, wavelen=lam, n_substrate=n_subs)
- Rs = 100*mtmm.coh_tmm('s',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)
- return Rs
-
- def digitize_qx(q_x, dlevels=2):
- """TODO: Docstring for digitize_qx.
- :q_x: TODO
- :returns: TODO
- """
-
- bins = np.linspace(0,1, num=dlevels+1, endpoint=True)
- bins[0] = -0.02
- bins[-1] = 1.01
- dig = (np.digitize(q_x, bins, right=True)) - 1
- act_r = np.linspace(0, 1, num=dlevels, endpoint=True)
- return act_r[dig]
- def make_nxdx(qx, n_substrate=1.52):
- """TODO: Docstring for make_nxdx.
- :qx: TODO
- :n_substrate: TODO
- :layer_thickness: TODO
- :returns: TODO
- """
-
- d_x = [np.inf] + (qx/np.sum(qx)).tolist() + [np.inf]
-
-
-
-
- qtmp = np.zeros_like(qx)
- qtmp[::2] = qtmp[::2] + 1.0
- sde = 1.45 + (2.58 - 1.45)*qtmp
- n_x = [1.0] + sde.tolist() + [n_substrate]
- return d_x, n_x
- def vgdr_eval_wsweep(
- qx,
- inc_ang,
- lam_low=0.25,
- lam_high=1,
- lam_pts=256,
- n_subs=1.52,
- ):
- """TODO: Docstring for tmm_eval.
- """
- degree = np.pi/180
-
- lam_inv = np.linspace(1/lam_low, 1/lam_high, num=lam_pts, endpoint=True)
- lams = 1.0/lam_inv
- Rs = np.zeros(lams.size)
-
- for lidx, lam in enumerate(lams):
- d_x, n_x = make_nxdx(qx=qx, n_substrate=n_subs)
- Rs[lidx] = 100*coh_tmm('s',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)
-
-
- vgdr = 100*np.ones(lam_pts)
- for idx, lam in enumerate(lams):
- if lams[idx] <= lam_high/2.0:
- cuts = Rs[np.logical_and(lams >= lam, lams <= 2*lam)]
- vgdr[idx] = np.mean(cuts)
-
- return np.amin(vgdr)
-
- def vgdr2_eval_wsweep(
- qx,
- inc_ang,
- lam_low=0.25,
- lam_high=2,
- lam_pts=256,
- n_subs=1.52,
- ):
- """TODO: Docstring for tmm_eval.
- """
- degree = np.pi/180
-
- lam_inv = np.linspace(1/lam_low, 1/lam_high, num=lam_pts, endpoint=True)
- lams = 1.0/lam_inv
- Rs = np.zeros(lams.size)
-
- for lidx, lam in enumerate(lams):
- d_x, n_x = make_nxdx(qx=qx, n_substrate=n_subs)
- Rs[lidx] = 100*coh_tmm('s',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)
-
-
- vgdr = 100*np.ones(lam_pts)
- for idx, lam in enumerate(lams):
- if lams[idx] <= 1:
- cuts = Rs[np.logical_and(lams >= lam, lams <= 2*lam)]
- vgdr[idx] = np.mean(cuts)
-
- return np.amin(vgdr), 400/lams[np.argmin(vgdr)]
- def tmm_eval_wsweep(
- qx,
- inc_ang,
- lam_low=0.1,
- lam_high=10,
- lam_pts=100,
- n_subs=1.52,
- ):
- """TODO: Docstring for tmm_eval.
- """
- degree = np.pi/180
-
- lam_inv = np.linspace(1/lam_low, 1/lam_high, num=lam_pts, endpoint=True)
- lams = 1.0/lam_inv
- Rs = np.zeros(lams.size)
-
- for lidx, lam in enumerate(lams):
- d_x, n_x = make_nxdx(qx=qx, n_substrate=n_subs)
- Rs[lidx] = 100*coh_tmm('s',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)
-
- return Rs
-
-
-
-
-
|