| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 | import snlay as sn import numpy as np from scipy import interpolatefrom noise import pnoise1import randomfrom tmm import coh_tmmimport multiprocessing as mp#import pyximport; pyximport.install(pyimport=True)#import mtmm as mtmm#make a materials dictionarymatsdict = {  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_idef 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_idef 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 xdef 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    #Start the random walk.    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)    # some random number seeds    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, #in nm         lam_high=1200,        lam_pts=100,        ang_low=0,   #degrees        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, #in nm         lam_high=1200,        lam_pts=100,        ang_low=0,   #degrees        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)#     Rp = 100*coh_tmm('p',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.array([-0.02, 0.2, 0.4, 0.6, 0.8, 1.01])    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    """    #num_layers = int(qx.size/2)    d_x = [np.inf] + (qx/np.sum(qx)).tolist() + [np.inf]    #qtmp = qx[:,0]    #qtmp = digitize_qx(qx[:,1], dlevels=2)    #d_x = num_layers*[cthick/num_layers]    #d_x = [np.inf] + d_x + [np.inf]    qtmp = np.zeros_like(qx)    qtmp[::2] = qtmp[::2] + 1.0    sde = 1.45 + (2.58 - 1.45)*qtmp#     sde = LL_mixing(fH = qtmp, #                     n_H = 2.58, #get_nk(datafile=matsdict[3], wavelengths=wavelen), #                     n_L = 1.45) #get_nk(datafile=matsdict[4], wavelengths=wavelen#                #   ))    n_x = [1.0] + sde.tolist() + [n_substrate]    return d_x, n_xdef vgdr_eval_wsweep(        qx,         inc_ang,        lam_low=0.25, #in nm         lam_high=1,        lam_pts=256,        n_subs=1.52,        ):    """TODO: Docstring for tmm_eval.    """      degree = np.pi/180    #lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)    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)    #Rp = 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)            #Rp[lidx] = 100*coh_tmm('p',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)    #return Rs    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, #in nm         lam_high=2,        lam_pts=256,        n_subs=1.52,        ):    """TODO: Docstring for tmm_eval.    """      degree = np.pi/180    #lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)    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)    #Rp = 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)            #Rp[lidx] = 100*coh_tmm('p',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)    #return Rs    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, #in nm         lam_high=10,        lam_pts=100,        n_subs=1.52,        ):    """TODO: Docstring for tmm_eval.    """      degree = np.pi/180        #lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)    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)    #Rp = 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)            #Rp[lidx] = 100*coh_tmm('p',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)    return Rs        # def tmm_wrapper2(arg):#     args, kwargs = arg#     return tmm_eval_wbk(*args, **kwargs)# def tmm_lam_parallel(#     q_x, #     cthick,#     inc_ang, #     n_par=12,#     lam_low=400, #     lam_high=1200, #     lam_pts=100, #     **kwargs):    #     jobs = []#     pool=mp.Pool(n_par)#     lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)#     for lam in lams:#         jobs.append((q_x, cthick, inc_ang, lam))#     arg = [(j, kwargs) for j in jobs]#     answ = np.array(pool.map(tmm_wrapper2, arg))#     pool.close()#     return answ[:,0], answ[:,1]         # def tmm_wrapper(arg):#     args, kwargs = arg#     return tmm_eval_wsweep(*args, **kwargs)# def tmm_eval_parallel(q_x, cthick, n_ang= 25, n_par=10, **kwargs):#     jobs = []#     pool=mp.Pool(n_par)#     angs = np.linspace(90, 0, endpoint=True, num=n_ang)#     for ang in angs:#         jobs.append((q_x, cthick, ang))#     arg = [(j, kwargs) for j in jobs]#     answ = np.array(pool.map(tmm_wrapper, arg))#     pool.close()#     return answ[:,0,:], answ[:,1,:] 
 |