def effect_gvd(wl_um, gvd, t_fs, d_mm): """ Calculates the effect the group velocity dispersion has on an unchirped Gaussian pulse. Source: http://www.rp-photonics.com/chromatic_dispersion.html numpy.log() is natural log CHANGELOG: 20170315/RB: started function. INPUT: wl_um (ndarray): wavelengths in micron gvd: group velocity dispersion in fs^2/mm t: pulse durations d: thicknesses of material OUTPUT: t_out (ndarray): 3D array with pulse lengths wl_um x t x d """ t_fs = CF.make_numpy_ndarray(t_fs) d_mm = CF.make_numpy_ndarray(d_mm) W, T, D = numpy.meshgrid(wl_um, t_fs, d_mm, indexing="ij") G, dump, dump = numpy.meshgrid(gvd, t_fs, d_mm, indexing="ij") t_out = T * numpy.sqrt(1 + (4 * numpy.log(2) * G * D / T**2)**2) return t_out
def interpolate_two_datasets(x1, y1, x2, y2, x_step = 1, interpolation_kind = "default", verbose = 0): """ Take datasets 1 and 2 and unify the x-axis, interpolate the y-values of both for the new axis. The new x-axis will be only where x1 and x2 overlap. INPUTS: x1, x2 (ndarray, list): x-axes of the data y1, y2 (ndarray, list): y values of the data x_step (number): step size of the x-axis of the interpolated data interpolation_kind (string): Specifies the kind of interpolation as a string ('linear', 'nearest', 'zero', 'slinear', 'quadratic, 'cubic', where 'slinear', 'quadratic' and 'cubic' refer to a spline interpolation of first, second or third order) or as an integer specifying the order of the spline interpolator to use. Default is 'linear' OUTPUTS: new_x (ndarray): new x-axis new_y1, new_y2 (ndarray): the interpolated values of y1 and y2 """ if interpolation_kind == "default": interpolation_kind = "linear" x1 = CF.make_numpy_ndarray(x1) y1 = CF.make_numpy_ndarray(y1) x2 = CF.make_numpy_ndarray(x2) y2 = CF.make_numpy_ndarray(y2) if x1[0] > x1[-1]: x1 = x1[::-1] y1 = y1[::-1] if x2[0] > x2[-1]: x2 = x2[::-1] y2 = y2[::-1] if x1[0] > x2[0]: start = x1[0] else: start = x2[0] if x1[-1] < x2[-1]: finish = x1[-1] else: finish = x2[-1] if verbose > 0: print(start, finish) new_x = numpy.arange(start, finish, step = x_step) f = interp1d(x1, y1, kind = interpolation_kind) new_y1 = f(new_x) f = interp1d(x2, y2, kind = interpolation_kind) new_y2 = f(new_x) return new_x, new_y1, new_y2
def quadratic(A, t): """ sum_i A[i] * t**i """ A = CF.make_numpy_ndarray(A) t = CF.make_numpy_ndarray(t) res = 0 for i in range(len(A)): res += A[i] * t**(i) return res
def absorption_for_gas(ev, absorption, mbars, cms, evs=[], interpolation_kind=""): """ INPUTS: x_ev (ndarray): energies, x-axis y_ab (ndarray): absorption, y-axis mbars (list): list with pressures, in mbar cms (list): list with pathlengths, in cm evs (list): list with specific wavelengths to calculate the transmission for. If length is zero, all energies will be calculated. OUTPUT: ev (ndarray): """ mbars = CF.make_numpy_ndarray(mbars) cms = CF.make_numpy_ndarray(cms) evs = CF.make_numpy_ndarray(evs) if len(evs) != 0: y_ab = interpolate_absorption(ev=ev, ab=absorption, x=evs, interpolation_kind=interpolation_kind) x_ev = evs n_evs = len(evs) else: y_ab = absorption[:] x_ev = ev[:] n_evs = len(y_ab) n_mbars = len(mbars) n_cms = len(cms) ab = numpy.zeros((n_evs, n_mbars, n_cms)) for i in range(n_evs): ab[i, :, :] = y_ab[i] for i in range(n_mbars): ab[:, i, :] *= mbars[i] for i in range(n_cms): ab[:, :, i] *= cms[i] tr = 10**ab return ev, ab, tr
def transmission_for_compound(wl_nm, abs_mm, R, thickness_mms, wl_nms=[], interpolation_kind="default"): """ INPUTS: wl_nm (ndarray): wavelength axis of the imported data abs_mm (ndarray): pure absorption component R (ndarray): reflection component thickness_mms (int, list, ndarray): list with thicknesses in mm wl_nms (int, list, ndarray): list with wavelengths of interest, can be empty, then wl_nm is used. mms (list): list with pathlengths, in mm l_nms (list): list with specific wavelengths to calculate the transmission for. If length is zero, all energies will be calculated. OUTPUT: ev (ndarray): """ thickness_mms = CF.make_numpy_ndarray(thickness_mms) n_thick = len(thickness_mms) wl_nms = CF.make_numpy_ndarray(wl_nms) if len(wl_nms) != 0: y_abs_mm = MATH.interpolate_data(original_x=wl_nm, original_y=abs_mm, new_x=wl_nms, interpolate_kind=interpolation_kind) R = MATH.interpolate_data(original_x=wl_nm, original_y=R, new_x=wl_nms, interpolate_kind=interpolation_kind) n_nms = len(wl_nms) else: y_abs_mm = abs_mm[:] wl_nms = wl_nm[:] n_nms = len(abs_mm) ABS, TH = numpy.meshgrid(y_abs_mm, thickness_mms) R, dump = numpy.meshgrid(R, thickness_mms) _R = (1 - R)**2 transmission = 10**(-ABS * TH) * (_R) return wl_nms, thickness_mms, transmission
def transmission_for_compound(e_ev, tr_norm, ums, evs=[], interpolation_kind="default"): """ INPUTS: ev (ndarray): ev axis of the imported data x_ev (ndarray): energies, x-axis y_tr (ndarray): absorption, y-axis ums (list): list with pathlengths, in um evs (list): list with specific wavelengths to calculate the transmission for. If length is zero, all energies will be calculated. OUTPUT: ev (ndarray): """ ums = CF.make_numpy_ndarray(ums) evs = CF.make_numpy_ndarray(evs) if len(evs) != 0: y_tr = MATH.interpolate_data(original_x=ev, original_y=transmission, new_x=evs, interpolate_kind=interpolation_kind) x_ev = evs n_evs = len(evs) else: y_tr = transmission[:] x_ev = ev[:] n_evs = len(y_tr) n_ums = len(ums) tr = numpy.zeros((n_evs, n_ums)) for i in range(n_evs): tr[i, :] = y_tr[i] ab = numpy.log10(tr) for i in range(n_ums): ab[:, i] *= ums[i] tr = 10**ab return ev, tr
def rb_cos(A, t): """ 4 parameters function: A[0] + A[1] * numpy.cos(2 * numpy.pi * A[2] * t + A[3]) A[0]: offset A[1]: amplitude A[2]: frequency A[3]: phase """ A = CF.make_numpy_ndarray(A) if len(A) != 4: raise IndexError("rb_cos(): you should enter 4 parameters in list A.") t = CF.make_numpy_ndarray(t) return A[0] + A[1] * numpy.cos(2 * numpy.pi * A[2] * t + numpy.pi * A[3])
def reflectance(n1, n2, a_deg=[], a_range=(0, 90), n_steps=-1): """ It is calculated for what? - a_deg > a_range """ n1 = CF.make_numpy_ndarray(n1) n2 = CF.make_numpy_ndarray(n2) a_deg = CF.make_numpy_ndarray(a_deg) if len(a_deg) == 0: if n_steps == -1: n_steps = int(a_range[1] - a_range[0]) + 1 if n_steps < 5: n_steps = 5 a_deg = numpy.linspace(a_range[0], a_range[1], num=n_steps) a_rad = a_deg * numpy.pi / 180 N1, A = numpy.meshgrid(n1, a_rad) N2, A = numpy.meshgrid(n2, a_rad) # when n2 > n1, there is a critical angle. Here angles > critical angles are set to nan. temp = ((N1 * numpy.sin(A)) / (N2))**2 numpy.putmask(temp, temp >= 1, numpy.nan) x = numpy.sqrt(1 - temp) a = N1 * numpy.cos(A) b = N2 * x Rs = numpy.abs((a - b) / (a + b))**2 a = N1 * x b = N2 * numpy.cos(A) Rp = numpy.abs((a - b) / (a + b))**2 return a_deg, Rs, Rp
def n_k_for_wavelengths(db_record, wl_um, interpolate_kind="default", verbose=0): """ Calculate the refractive index and extinction coefficient for wavelengths wl_um. The input is the data from refractiveindex.info and comes as one of 9 equations (not all of them are implemented) or as a table of values. For the latter interpolation will be used to get the values for the asked wavelengths. db_record is the dictionary. """ if "type" not in db_record: raise KeyError( "ri_for_wavelengths(): The database record does not have a key 'type'." ) wl_um = CF.make_numpy_ndarray(wl_um) if db_record["type"] == "tabulated nk": if wl_um[0] < db_record["data"][:, 0][0]: raise ValueError( "Error, wavelength %1.2f micron is too low! It should be above %1.2f micron." % (wl_um[0], db_record["data"][:, 0][0])) elif wl_um[-1] > db_record["data"][:, 0][-1]: raise ValueError( "Error, wavelength %1.2f micron is too high! It should be below %1.2f micron." % (wl_um[-1], db_record["data"][:, 0][-1])) DEBUG.verbose(" Tabulated data (type nk)", verbose_level=1) n = MATH.interpolate_data(db_record["data"][:, 0], db_record["data"][:, 1], wl_um) k = MATH.interpolate_data(db_record["data"][:, 0], db_record["data"][:, 2], wl_um) else: raise NotImplementedError( "Importing n and k are only implemented for tabulated records.") return n, k
def make_coordinates(inch_per_unit, x_units, y_units, left, bottom, width, height, flag_verbose = False): """ matplotlib.figure.add_axes() requires coordinates (left, bottom, width, height) for each axes instance. The values are between 0 and 1. There are two problems. First is that the aspect ratio may be off. If the figure is a rectangle and the subplot is 0.5 wide and 0.5 high, the subplot is also a rectangle. Second is that if the figure size changes all the carefully planned margins are lost. This function works with units. The x-axis is x_units long. Each unit has a defined length inch_per_unit. The left edges are at [left]. This solves the two problems. If your plot is N units wide and N units high, it will be a square. When you resize the figure (change x_units) the margins, which are in units, will remain the same. INPUT: - inch_per_unit (number): used to scale to inches - x_units, y_units (number): width and height of the figure, in units - left, bottom, width, height (numpy.ndarray with ints and/or floats, also accepts list or int or float): the positions of the axes. The longest list determines the number of plots. Shorter lists are cycled. OUTPUT: - figsize: tuple that is accepted by plt.figure(figsize = figsize) - coords, a list with tuples with (l,b,w,h). The tuples are accepted by fig.add_axes((l,b,w,h)). EXAMPLE 1: Three plots next to each other. 01234567 1 x x x 0xxxxxxx x_units = 8 y_units = 3 left = [1,3,6] # bottom = 1 # [1], [1,1], [1,1,1] # not [1,1,1,1], that gives extra subplot width = [1,2] # [1,2,1] height = 1 # [1], [1,1], [1,1,1] EXAMPLE 2: Four equally sized and spaced plots. 01234 3 x x 2xxxx 1 x x 0xxxx inch_per_unit = 1.0 x_units = 5 y_units = 5 left = [1,3] # [1,3,1,3] # not [1,3,1], that would give: [1,3,1,1] bottom = [3,3,1,1] # width = 1 # [1], [1,1], [1,1,1], [1,1,1,1] height = 1 # [1], [1,1], [1,1,1], [1,1,1,1] EXAMPLE 3: A complex arrangement. All coordinates are explicitly given. 01234567 6 x x 5 x x 4xxxx x 3 xxxxx 2 x x 1 x x 0xxxxxxx x_units = 8 y_units = 8 left = [1,5,1,4] bottom = [5,4,1,1] width = [3,2,2,3] height = [2,3,3,2] CHANGELOG: 20130317/RB: started """ # calculate figure size figsize = (x_units * inch_per_unit, y_units * inch_per_unit) # change all values to values between 0 and 1 left = CF.make_numpy_ndarray(left) / x_units bottom = CF.make_numpy_ndarray(bottom) / y_units width = CF.make_numpy_ndarray(width) / x_units height = CF.make_numpy_ndarray(height) / y_units # find longest list, determines number of sub plots N = find_longest_list(left, bottom, width, height) # determine the coordinates coords = [] for i in range(N): l = left[i % len(left)] b = bottom[i % len(bottom)] w = width[i % len(width)] h = height[i % len(height)] coords.append((l,b,w,h)) return figsize, coords
def test_dict(self): result = CF.make_numpy_ndarray({"a": 1, "b": 2})
def test_list_1(self): result = CF.make_numpy_ndarray([1,2]) self.assertEqual(type(result), numpy.ndarray) self.assertTrue(numpy.all(numpy.array([1,2]) == result))
def test_string_2(self): result = CF.make_numpy_ndarray(["fiets", "auto"]) self.assertEqual(type(result), numpy.ndarray) self.assertTrue(numpy.all(numpy.array(["fiets", "auto"]) == result))
def test_string_1(self): result = CF.make_numpy_ndarray("fiets") self.assertEqual(type(result), numpy.ndarray) self.assertEqual(result, ["fiets"]) self.assertTrue(result[0] == "fiets")
def test_float_1(self): result = CF.make_numpy_ndarray(1) self.assertEqual(type(result), numpy.ndarray) self.assertEqual(result, numpy.array(1))
def ri_for_wavelengths(db_record, wl_um, interpolate_kind="default", verbose=0): """ Calculate the refractive index for wavelengths wl_um. The input is the data from refractiveindex.info and comes as one of 9 equations (not all of them are implemented) or as a table of values. For the latter interpolation will be used to get the values for the asked wavelengths. db_record is the dictionary. """ if "type" not in db_record: raise KeyError( "ri_for_wavelengths(): The database record does not have a key 'type'." ) wl_um = CF.make_numpy_ndarray(wl_um) error_string = "Calculation of the refractive index is not implemented for " # check the range if "formula" in db_record["type"]: # temp = numpy.where(wl_um < db_record["range"][0])[0] # print(temp) # wl_um[temp] = numpy.nan # # temp = numpy.where(wl_um > db_record["range"][1])[0] # print(temp) # wl_um[temp] = numpy.nan print(db_record["range"][0]) if wl_um[0] < db_record["range"][0]: raise ValueError( "Error, wavelength %1.2f micron is too low! It should be above %1.2f micron." % (wl_um[0], db_record["range"][0])) elif wl_um[-1] > db_record["range"][1]: raise ValueError( "Error, wavelength %1.2f micron is too high! It should be below %1.2f micron." % (wl_um[-1], db_record["range"][-1])) if "tabulated" in db_record["type"]: if wl_um[0] < db_record["data"][:, 0][0]: raise ValueError( "Error, wavelength %1.2f micron is too low! It should be above %1.2f micron." % (wl_um[0], db_record["data"][:, 0][0])) elif wl_um[-1] > db_record["data"][:, 0][-1]: raise ValueError( "Error, wavelength %1.2f micron is too high! It should be below %1.2f micron." % (wl_um[-1], db_record["data"][:, 0][-1])) if db_record["type"] == "formula 1": DEBUG.verbose(" Using formula 1 to calculate refractive indices", verbose_level=1) n_terms = int(len(db_record["coefficients"]) / 2 - 0.5) ri = numpy.ones(len(wl_um)) + db_record["coefficients"][0] l = wl_um**2 for i in range(n_terms): ri += (db_record["coefficients"][2 * i + 1] * l) / (l - db_record["coefficients"][2 * i + 2]**2) ri = numpy.sqrt(ri) if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 2": DEBUG.verbose(" Using formula 2 to calculate refractive indices", verbose_level=1) n_terms = int(len(db_record["coefficients"]) / 2 - 0.5) ri = numpy.ones(len(wl_um)) + db_record["coefficients"][0] l = wl_um**2 for i in range(n_terms): ri += (db_record["coefficients"][2 * i + 1] * l) / (l - db_record["coefficients"][2 * i + 2]) ri = numpy.sqrt(ri) if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 3": DEBUG.verbose(" Using formula 3 to calculate refractive indices", verbose_level=1) n_terms = int(len(db_record["coefficients"]) / 2 - 0.5) ri = numpy.zeros(len(wl_um)) + db_record["coefficients"][0] for i in range(n_terms): ri += db_record["coefficients"][ 2 * i + 1] * wl_um**db_record["coefficients"][2 * i + 2] ri = numpy.sqrt(ri) if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 4": DEBUG.verbose(" Using formula 4 to calculate refractive indices", verbose_level=1) ri = numpy.zeros(len(wl_um)) + db_record["coefficients"][0] n_coeff = len(db_record["coefficients"]) if n_coeff >= 5: ri += (db_record["coefficients"][1] * wl_um**db_record["coefficients"][2]) / ( wl_um**2 - db_record["coefficients"][3]** db_record["coefficients"][4]) if n_coeff >= 9: ri += (db_record["coefficients"][5] * wl_um**db_record["coefficients"][6]) / ( wl_um**2 - db_record["coefficients"][7]** db_record["coefficients"][8]) n_terms = int((len(db_record["coefficients"]) - 9) / 2) for i in range(n_terms): ri += db_record["coefficients"][ 2 * i + 9] * wl_um**db_record["coefficients"][2 * i + 10] ri = numpy.sqrt(ri) if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 5": DEBUG.verbose(" Using formula 5 to calculate refractive indices", verbose_level=1) n_terms = int(len(db_record["coefficients"]) / 2 - 0.5) ri = numpy.zeros(len(wl_um)) + db_record["coefficients"][0] for i in range(n_terms): ri += db_record["coefficients"][ 2 * i + 1] * wl_um**db_record["coefficients"][2 * i + 2] if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 6": DEBUG.verbose(" Using formula 6 to calculate refractive indices", verbose_level=1) n_terms = int(len(db_record["coefficients"]) / 2 - 0.5) ri = numpy.ones(len(wl_um)) + db_record["coefficients"][0] l = wl_um**-2 for i in range(n_terms): ri += (db_record["coefficients"][2 * i + 1]) / ( db_record["coefficients"][2 * i + 2] - l) if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 7": DEBUG.verbose(" Using formula 7 to calculate refractive indices", verbose_level=1) l = wl_um**2 n_terms = len(db_record["coefficients"]) - 3 t1 = db_record["coefficients"][1] / (l - 0.028) t2 = db_record["coefficients"][2] * (1 / (l - 0.028))**2 ri = db_record["coefficients"][0] + t1 + t2 for i in range(n_terms): ri += db_record["coefficients"][i + 3] * l**(i + 1) if verbose >= 1: for i in range(len(wl_um)): print(i, wl_um[i], ri[i]) elif db_record["type"] == "formula 8": raise NotImplementedError(error_string + "formula 8") elif db_record["type"] == "formula 9": raise NotImplementedError(error_string + "formula 9") elif db_record["type"] == "tabulated n": DEBUG.verbose(" Tabulated data (type n)", verbose_level=1) ri = MATH.interpolate_data(db_record["data"][:, 0], db_record["data"][:, 1], wl_um) elif db_record["type"] == "tabulated nk": DEBUG.verbose(" Tabulated data (type nk)", verbose_level=1) ri = MATH.interpolate_data(db_record["data"][:, 0], db_record["data"][:, 1], wl_um) else: raise ValueError( "The type of data in the database record is unknown (usually formula 1-9 or tabulated data). Type here is %s." % db_record["type"]) return ri
def gvd_for_wavelengths(db_record, wl_um, interpolate_kind="default", verbose=0): """ Calculate the GVD for wavelengths wl_um. The GVD is calculated as the second derivative of the refractive index with respect to the wavelength. The input is the data from refractiveindex.info and comes as one of 9 equations (not all of them are implemented) or as a table of values. For the equations, the second derivatives were calculated using WolframAlpha. """ if "type" not in db_record: raise KeyError( "gvd_for_wavelengths: The database record does not have a key 'type'." ) wl_um = CF.make_numpy_ndarray(wl_um) error_string = "GVD is not implemented for " # check the range if "formula" in db_record["type"]: if wl_um[0] < db_record["range"][0]: raise ValueError( "Error, wavelength %1.2f micron is too low! It should be above %1.2f micron." % (wl_um[0], db_record["range"][0])) elif wl_um[-1] > db_record["range"][1]: raise ValueError( "Error, wavelength %1.2f micron is too high! It should be below %1.2f micron." % (wl_um[-1], db_record["range"][-1])) if "tabulated" in db_record["type"]: raise NotImplementedError( "GVD can't be calculated for tabulated data.") if db_record["type"] == "formula 1": DEBUG.verbose( " Using formula 1 to calculate group velocity dispersion", verbose_level=1) gvd = EQ.gvd_formula_1(wl_um, db_record["coefficients"]) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 2": """ Formula 2 is the same as formula 1, but some given coefficients are already squared. The square root of these coefficients is taken and the GVD equation for formula 1 is used. """ DEBUG.verbose( " Using formula 2 to calculate group velocity dispersion", verbose_level=1) s = numpy.copy(db_record["coefficients"]) for i in range(len(s)): if i > 0 and i % 2 == 0: s[i] = numpy.sqrt(s[i]) gvd = EQ.gvd_formula_1(wl_um, s) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 3": DEBUG.verbose( " Using formula 3 to calculate group velocity dispersion", verbose_level=1) gvd = EQ.gvd_formula_3(wl_um, db_record["coefficients"]) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 4": DEBUG.verbose( " Using formula 4 to calculate group velocity dispersion", verbose_level=1) gvd = EQ.gvd_formula_4(wl_um, db_record["coefficients"]) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 5": DEBUG.verbose( " Using formula 5 to calculate group velocity dispersion", verbose_level=1) gvd = EQ.gvd_formula_5(wl_um, db_record["coefficients"]) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 6": DEBUG.verbose( " Using formula 6 to calculate group velocity dispersion", verbose_level=1) gvd = EQ.gvd_formula_6(wl_um, db_record["coefficients"]) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 7": DEBUG.verbose( " Using formula 7 to calculate group velocity dispersion", verbose_level=1) gvd = EQ.gvd_formula_7(wl_um, db_record["coefficients"]) gvd = (1e21 * gvd * wl_um**3) / (2 * numpy.pi * (CONST.c_ms)**2) elif db_record["type"] == "formula 8": raise NotImplementedError(error_string + "formula 8") elif db_record["type"] == "formula 9": raise NotImplementedError(error_string + "formula 9") else: raise ValueError( "The type of data in the database record is unknown (usually formula 1-9). Type here is %s." % db_record["type"]) return wl_um, gvd