def get_reflectance(paf1="air", paf2="", wl_um=[], um_range=[0.3, 0.6], a_deg=[], a_range=(0, 90), n_steps=100, interpolate_kind="default", verbose=0): """ Import a file from RefractiveIndex.info and output the refractive index for the desired wavelengths. INPUT: paf (str): path and filename wl_um (ndarray): wavelength axis, in micrometer um_range (list with 2 elements): if wl_um is not given, it will plot a range. n_steps (int): number of steps to plot the range. ax (plt axis): if False, it will make a new figure interpolate_kind (str): for tabulated data, the type of interpolation """ if len(wl_um) == 0: wl_um = numpy.linspace(um_range[0], um_range[1], num=n_steps) # material 1 if paf1 in ["", "air"]: n1 = numpy.ones(len(wl_um)) elif type(paf1) == float: n1 = numpy.ones(len(wl_um)) * paf1 else: temp = paf1.split("/") DEBUG.verbose("Importing data for %s by %s" % (temp[-2], temp[-1][:-4]), verbose_level=1) db_record = RIRY.import_refractive_index(paf=paf1, verbose=verbose) DEBUG.verbose(" Imported data", verbose_level=0) n1 = ri_for_wavelengths(db_record, wl_um, verbose=verbose) # material 1 if paf2 in ["", "air"]: n2 = numpy.ones(len(wl_um)) elif type(paf2) == float: n2 = numpy.ones(len(wl_um)) * paf2 else: temp = paf2.split("/") DEBUG.verbose("Importing data for %s by %s" % (temp[-2], temp[-1][:-4]), verbose_level=1) db_record = RIRY.import_refractive_index(paf=paf2, verbose=verbose) DEBUG.verbose(" Imported data", verbose_level=0) n2 = ri_for_wavelengths(db_record, wl_um, verbose=verbose) a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_deg=[], a_range=a_range, n_steps=-1) return wl_um, a_deg, Rs, Rp
def test_a_deg_simple(self): """ Basic test using a_deg """ n = 10 n1 = numpy.ones(n) n2 = numpy.linspace(1.1, 1.5, num=n) a_deg = [0, 10] a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_deg=a_deg) self.assertTrue(numpy.shape(a_deg) == (2, )) self.assertTrue(numpy.shape(Rs) == (2, 10)) self.assertTrue(numpy.shape(Rp) == (2, 10))
def test_list_inputs(self): """ use integer inputs for a_deg, n1 and n2 """ n1 = [1, 1, 1, 1, 1] n2 = [1.1, 1.2, 1.3, 1.4, 1.5] a_deg = [0, 10] a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_deg=a_deg) # print(numpy.count_nonzero(numpy.isnan(Rs))) self.assertTrue(numpy.shape(a_deg) == (2, )) self.assertTrue(numpy.shape(Rs) == (2, 5)) self.assertTrue(numpy.shape(Rp) == (2, 5))
def test_int_inputs(self): """ use integer inputs for a_deg, n1 and n2 """ n1 = 0 n2 = 1.5 a_deg = 0 a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_deg=a_deg) # print(numpy.count_nonzero(numpy.isnan(Rs))) self.assertTrue(numpy.shape(a_deg) == (1, )) self.assertTrue(numpy.shape(Rs) == (1, 1)) self.assertTrue(numpy.shape(Rp) == (1, 1))
def test_arange_simple(self): """ Basic test using a_range """ n = 10 n1 = numpy.ones(n) n2 = numpy.linspace(1.1, 1.5, num=n) a_range = (0, 90) a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_range=a_range) self.assertTrue(numpy.shape(a_deg) == (91, )) self.assertTrue(numpy.shape(Rs) == (91, 10)) self.assertTrue(numpy.shape(Rp) == (91, 10)) self.assertTrue(numpy.count_nonzero(numpy.isnan(Rs)) == 0)
def test_arange_critical_angle_2(self): """ Check if the critical angle is handled properly (it should give NaN) """ n = 10 n1 = numpy.ones(n) n2 = numpy.linspace(0.5, 1.5, num=n) a_range = (0, 90) a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_range=a_range) # print(numpy.count_nonzero(numpy.isnan(Rs))) self.assertTrue(numpy.shape(a_deg) == (91, )) self.assertTrue(numpy.shape(Rs) == (91, 10)) self.assertTrue(numpy.shape(Rp) == (91, 10)) self.assertTrue(numpy.count_nonzero(numpy.isnan(Rs)) == 211)
def test_arange_no_critical_angle(self): """ Check if the critical angle is handled properly (it should give NaN) This tests for between 0 and 40 degrees, none should be NaN """ n = 10 n2 = numpy.ones(n) n1 = numpy.linspace(1.1, 1.5, num=n) a_range = (0, 40) a_deg, Rs, Rp = EQ.reflectance(n1, n2, a_range=a_range) # print(numpy.count_nonzero(numpy.isnan(Rs))) self.assertTrue(numpy.shape(a_deg) == (41, )) self.assertTrue(numpy.shape(Rs) == (41, 10)) self.assertTrue(numpy.shape(Rp) == (41, 10)) self.assertTrue(numpy.count_nonzero(numpy.isnan(Rs)) == 0)
def test_correct(self): A = [0, 1, 1, 0] t = numpy.arange(5) res = EQ.rb_cos(A, t) check = numpy.ones(5) self.assertTrue(numpy.all(res == check))
def test_t_as_list(self): A = [0, 1] t = [0, 0, 0, 0, 0] res = EQ.quadratic(A, t) check = numpy.array([0, 0, 0, 0, 0]) self.assertTrue(numpy.all(res == check))
def test_A_as_int(self): A = 0 t = numpy.arange(5) res = EQ.quadratic(A, t) check = numpy.array([0, 0, 0, 0, 0]) self.assertTrue(numpy.all(res == check))
def test_correct(self): A = [0, 1] t = numpy.arange(5) res = EQ.quadratic(A, t) check = numpy.array([0, 1, 2, 3, 4]) self.assertTrue(numpy.all(res == check))
def gaussian_beam_diameter(position, intensity, ax=False, label="", flag_interpolate=True, interpolate_kind="linear", interpolate_step=-1, position_unit="mm", center_plot_on_zero=True): """ Calculate the diameter of a gaussian beam. INPUT: - position (list, ndarray): list with positions - intensity (list, ndarray): list with intensities corresponding to the positions - ax (axis object, or False): if False, the result will not be plotted - label (string): label used in the fit - flag_interpolate (BOOL, True): if the positions are not equidistant, then it has to be interpolated. - interpolate_kind - interpolate_step (number): stepsize of the interpolation. If the value is negative, that is the number of steps that will be used. If the value is 0, 100 steps will be used. - position_unit (string, mm): unit of the position - center_plot_on_zero (BOOL, True): Subtract the mean position from the position. """ print("--- %s ---" % label) if position[1] < position[0]: position = position[::-1] intensity = intensity[::-1] if flag_interpolate: if interpolate_step == 0: x = numpy.linspace(position[0], position[-1], num=100) elif interpolate_step < 0: x = numpy.linspace(position[0], position[-1], num=-interpolate_step) else: x = numpy.arange(position[0], position[-1], interpolate_step) f = interp1d(position, intensity, kind=interpolate_kind) y = f(x) else: x = numpy.copy(position) y = numpy.copy(intensity) dx = x[1] - x[0] mean_guess = x[numpy.argmax(y)] A = [1, mean_guess, 1, 1] A_final = MATH.fit(x, y, EQ.rb_gaussian, A) if center_plot_on_zero: print("Mean: %2.3f %s (shifted in plot)" % (A_final[1], position_unit)) else: print("Mean: %2.3f %s" % (A_final[1], position_unit)) y_fit = EQ.rb_gaussian(A_final, x) if center_plot_on_zero: x -= A_final[1] A_final[1] = 0 temp = numpy.where(y_fit > (0.135 * numpy.amax(y_fit)))[0] print("1/e2: %2.3f %s" % (x[temp[-1]] - x[temp[0]], position_unit)) temp = numpy.where(y_fit > (0.5 * numpy.amax(y_fit)))[0] print("FWHM: %2.3f %s" % (x[temp[-1]] - x[temp[0]], position_unit)) y_fit -= numpy.amin(y_fit) y /= numpy.amax(y_fit) y_fit /= numpy.amax(y_fit) s = label ax.plot(x, y, label=s) s = label + " fit" ax.plot(x, y_fit, label=s) ax.set_xlabel("Position (%s, shifted)" % position_unit) ax.set_ylabel("Intensity (norm)") ax.legend() print("Stepsize positions: %2.3f" % dx) print("Fitting parameters:") print(" Sigma:", A_final[0]) print(" Mean:", A_final[1]) print(" Y-offset:", A_final[2]) print(" Scale:", A_final[3])
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