qxnew.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import snlay as sn
  2. import numpy as np
  3. from scipy import interpolate
  4. from noise import pnoise1
  5. import random
  6. from tmm import coh_tmm
  7. import multiprocessing as mp
  8. import makeqx as mkq
  9. #import pyximport; pyximport.install(pyimport=True)
  10. #import mtmm as mtmm
  11. # make a materials dictionary
  12. matsdict = {
  13. 1: "./materials/gold.dat",
  14. 2: "./materials/silicon.dat",
  15. 3: "./materials/silica.dat",
  16. 4: "./materials/tio2.dat",
  17. 5: "./materials/silver.dat",
  18. }
  19. def get_nk(datafile, wavelengths):
  20. """Reads the given file and returns the n+ik complex at
  21. the given wavelength after suitable interpolation
  22. :datafile: TODO
  23. :wavelength: TODO
  24. :returns: TODO
  25. """
  26. rawdisp = np.loadtxt(datafile)
  27. f_r = interpolate.interp1d(rawdisp[:, 0], rawdisp[:, 1])
  28. f_i = interpolate.interp1d(rawdisp[:, 0], rawdisp[:, 2])
  29. return f_r(wavelengths) + 1j * f_i(wavelengths)
  30. def nk_2_eps(n):
  31. """TODO: Docstring for nk_2_epsnk_2_eps.
  32. :returns: complex epsilon given n and kappa
  33. """
  34. eps_r = n.real ** 2 - n.imag ** 2
  35. eps_i = 2 * n.real * n.imag
  36. return eps_r + 1j * eps_i
  37. def eps_2_nk(eps):
  38. """TODO: Docstring for nk_2_epsnk_2_eps.
  39. :returns: complex epsilon given n and kappa
  40. """
  41. modeps = np.abs(eps)
  42. n_r = np.sqrt(0.5 * (modeps + eps.real))
  43. n_i = np.sqrt(0.5 * (modeps - eps.real))
  44. return n_r + 1j * n_i
  45. def LL_mixing(fH, n_H, n_L):
  46. """TODO: Docstring for brugg_mixingbrugg_mixing.
  47. Given the volumne fraction of the higher index material, give the effective
  48. index of the layer
  49. :fH: volumne fraction from 0 to 1
  50. :n_H: ri of the higher index material
  51. :n_L: ri of the lower index material
  52. :returns: TODO
  53. """
  54. eH = nk_2_eps(n_H)
  55. eL = nk_2_eps(n_L)
  56. bigK = fH * (eH - 1) / (eH + 2) + (1 - fH) * (eL - 1) / (eL + 2)
  57. e_eff = (1 + 2 * bigK) / (1 - bigK)
  58. return eps_2_nk(e_eff)
  59. def make_qxn(num_layers, dlevels=0):
  60. """TODO: Docstring for make_qxn.
  61. :num_layers: TODO
  62. :returns: TODO
  63. """
  64. uni = np.linspace(0, 2*num_layers, 2*num_layers, endpoint=False)
  65. rwalk = np.zeros_like(uni).reshape((num_layers,2))
  66. rwalk[:,0] = mkq.make_qx(num_layers)
  67. if dlevels != 0:
  68. rwalk[:,1] = mkq.digitize_qx(mkq.make_qx(num_layers), dlevels)
  69. else:
  70. rwalk[:,1] = mkq.make_qx(num_layers)
  71. return rwalk.flatten()
  72. def make_nxdx(qx, d_min, d_max, wavelen=550, n_substrate=1.52):
  73. """TODO: Docstring for make_nxdx.
  74. :qx: TODO
  75. :n_substrate: TODO
  76. :layer_thickness: TODO
  77. :returns: TODO
  78. """
  79. num_layers = int(qx.size/2)
  80. qx = qx.reshape((num_layers, 2))
  81. #d_x = d_min + (d_max - d_min)*qx[:,0]
  82. d_x = qx[:,0]
  83. d_x = [np.inf] + d_x.tolist() + [np.inf]
  84. sde = LL_mixing(
  85. fH=qx[:,1], n_H=2.58, n_L=1.45 # get_nk(datafile=matsdict[3], wavelengths=wavelen),
  86. ) # get_nk(datafile=matsdict[4], wavelengths=wavelen
  87. # ))
  88. n_x = [1.0] + sde.tolist() + [n_substrate]
  89. return d_x, n_x
  90. # def tmm_eval2(
  91. # qx,
  92. # cthick,
  93. # lam_low=400, # in nm
  94. # lam_high=1200,
  95. # lam_pts=100,
  96. # ang_low=0, # degrees
  97. # ang_high=90,
  98. # ang_pts=25,
  99. # n_subs=1.52,
  100. # ):
  101. # """TODO: Docstring for tmm_eval.
  102. # :qx: TODO
  103. # :lam_low: TODO
  104. # :#in nm
  105. # lam_high: TODO
  106. # :lam_pts: TODO
  107. # :ang_low: TODO
  108. # :#degrees
  109. # ang_high: TODO
  110. # :ang_pts: TODO
  111. # :returns: TODO
  112. # """
  113. # degree = np.pi / 180
  114. # lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)
  115. # thetas = np.linspace(ang_high, ang_low, endpoint=True, num=ang_pts)
  116. # Rs = np.zeros((thetas.size, lams.size))
  117. # Rp = np.zeros((thetas.size, lams.size))
  118. # for tidx, theta in enumerate(thetas):
  119. # for lidx, lam in enumerate(lams):
  120. # d_x, n_x = make_nxdx(qx=qx, cthick=cthick, wavelen=lam, n_substrate=n_subs)
  121. # Rs[tidx, lidx] = 100 * coh_tmm(
  122. # "s", n_x, d_x, th_0=theta * degree, lam_vac=lam
  123. # )
  124. # Rp[tidx, lidx] = 100 * coh_tmm(
  125. # "p", n_x, d_x, th_0=theta * degree, lam_vac=lam
  126. # )
  127. # return Rs, Rp
  128. # def tmm_eval(
  129. # qx,
  130. # cthick,
  131. # lam_low=400, # in nm
  132. # lam_high=1200,
  133. # lam_pts=100,
  134. # ang_low=0, # degrees
  135. # ang_high=90,
  136. # ang_pts=25,
  137. # n_subs=1.52,
  138. # ):
  139. # """TODO: Docstring for tmm_eval.
  140. # :qx: TODO
  141. # :lam_low: TODO
  142. # :#in nm
  143. # lam_high: TODO
  144. # :lam_pts: TODO
  145. # :ang_low: TODO
  146. # :#degrees
  147. # ang_high: TODO
  148. # :ang_pts: TODO
  149. # :returns: TODO
  150. # """
  151. # degree = np.pi / 180
  152. # lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)
  153. # thetas = np.linspace(ang_high, ang_low, endpoint=True, num=ang_pts)
  154. # Rs = np.zeros((thetas.size, lams.size))
  155. # Rp = np.zeros((thetas.size, lams.size))
  156. # for tidx, theta in enumerate(thetas):
  157. # for lidx, lam in enumerate(lams):
  158. # d_x, n_x = make_nxdx(qx=qx, cthick=cthick, wavelen=lam, n_substrate=n_subs)
  159. # Rs[tidx, lidx] = 100 * coh_tmm(
  160. # "s", n_x, d_x, th_0=theta * degree, lam_vac=lam
  161. # )
  162. # Rp[tidx, lidx] = 100 * coh_tmm(
  163. # "p", n_x, d_x, th_0=theta * degree, lam_vac=lam
  164. # )
  165. # return Rs, Rp
  166. def tmm_eval_wbk(qx, d_min , d_max, inc_ang, lam, n_subs=1.52):
  167. """TODO: Docstring for tmm_eval.
  168. :qx: TODO
  169. :returns: TODO
  170. """
  171. degree = np.pi / 180
  172. d_x, n_x = make_nxdx(qx=qx, d_min=d_min, d_max=d_max, wavelen=lam, n_substrate=n_subs)
  173. Rs = 100 * coh_tmm("s", n_x, d_x, th_0=inc_ang * degree, lam_vac=lam)
  174. # Rp = 100*coh_tmm('p',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)
  175. return Rs
  176. def tmm_eval_wsweep(
  177. qx, d_min , d_max, inc_ang, lam_low=400, lam_high=800, lam_pts=50, n_subs=1.52 # in nm
  178. ):
  179. """TODO: Docstring for tmm_eval.
  180. :qx: TODO
  181. :lam_low: TODO
  182. lam_high: TODO
  183. :lam_pts: TODO
  184. :returns: TODO
  185. """
  186. degree = np.pi / 180
  187. lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)
  188. Rs = np.zeros(lams.size)
  189. # Rp = np.zeros(lams.size)
  190. for lidx, lam in enumerate(lams):
  191. d_x, n_x = make_nxdx(qx=qx, d_min=0, d_max=1, wavelen=lam, n_substrate=n_subs)
  192. Rs[lidx] = 100 * coh_tmm("s", n_x, d_x, th_0=inc_ang * degree, lam_vac=lam)
  193. # Rp[lidx] = 100*coh_tmm('p',n_x,d_x, th_0=inc_ang*degree,lam_vac=lam)
  194. return Rs
  195. # def tmm_wrapper2(arg):
  196. # args, kwargs = arg
  197. # return tmm_eval_wbk(*args, **kwargs)
  198. # def tmm_lam_parallel(
  199. # q_x, cthick, inc_ang, n_par=12, lam_low=400, lam_high=1200, lam_pts=100, **kwargs
  200. # ):
  201. # jobs = []
  202. # pool = mp.Pool(n_par)
  203. # lams = np.linspace(lam_low, lam_high, endpoint=True, num=lam_pts)
  204. # for lam in lams:
  205. # jobs.append((q_x, cthick, inc_ang, lam))
  206. # arg = [(j, kwargs) for j in jobs]
  207. # answ = np.array(pool.map(tmm_wrapper2, arg))
  208. # pool.close()
  209. # return answ[:, 0], answ[:, 1]
  210. # def tmm_wrapper(arg):
  211. # args, kwargs = arg
  212. # return tmm_eval_wsweep(*args, **kwargs)
  213. # def tmm_eval_parallel(q_x, cthick, n_ang=25, n_par=10, **kwargs):
  214. # jobs = []
  215. # pool = mp.Pool(n_par)
  216. # angs = np.linspace(90, 0, endpoint=True, num=n_ang)
  217. # for ang in angs:
  218. # jobs.append((q_x, cthick, ang))
  219. # arg = [(j, kwargs) for j in jobs]
  220. # answ = np.array(pool.map(tmm_wrapper, arg))
  221. # pool.close()
  222. # return answ[:, 0, :], answ[:, 1, :]