def calc_radium_range(): peak = { 35: (1100, 1800), 35.5: (1000, 1700), 36: (900, 1600), 36.5: (800, 1500), 37: (600, 1400), 37.5: (500, 1200), 38: (300, 1000), 38.5: (100, 700) } distances = [] error_distances = [] integrals = [] error_integrals = [] for distanceStr in ("35_0", "35_5", "36_0", "36_5", "37_0", "37_5", "38_0", "38_5"): filename = "data/Radium%s.TKA" % distanceStr distance = ufloat(float(distanceStr.replace("_", ".")), 0.05) tka = TkaFile(filename) lower, upper = peak[distance.n] data = tka.data[lower:upper] distance = distance - 35 + ufloat(3.17, 0.17) integral = ufloat(data.sum(), math.sqrt((data + 1).sum())) integral_fixed = integral * distance**2 print( "$({:L}) \\unit{{cm}}$ & {:d} & {:d} & ${:dL}$ & ${:dL} \\unit{{cm^2}}$ \\\\" .format(distance, lower, upper, integral, integral_fixed)) distances.append(distance.n) error_distances.append(distance.s) integrals.append(integral_fixed.n) error_integrals.append(integral_fixed.s) distances = np.array(distances) integrals = np.array(integrals) error_distances = np.array(error_distances) error_integrals = np.array(error_integrals) plt.clf() plt.minorticks_on() plt.errorbar(distances, integrals, xerr=error_distances, yerr=error_integrals, fmt="s") #plt.plot(distances, integrals, 's') plt.xlabel("Distanz / cm") plt.ylabel("korrigierte Summe / cm^2") plt.ylim(0, plt.ylim()[1]) plt.savefig("out/radium_range." + SAVETYPE) #plt.show() plt.clf() plt.minorticks_on() scale = 1 / integrals[0:3].mean() fit = Fit(LINEAR) fit.set_params(offset=1, slope=-0.5) fit.set_data(xdata=distances[1:], ydata=integrals[1:] * scale, xerrors=error_distances[1:], yerrors=error_integrals[1:] * scale) fit.set_labels(xlabel="Distanz / cm", ylabel="Intensität") fit.iterative_fit(5) fit.plot(plot_data=True, plot_fit=True, box="bl", units={"slope": "1/cm"}) plt.ylim(0, plt.ylim()[1]) plt.savefig("out/radium_range_fit." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="tr") plt.savefig("out/radium_range_residual." + SAVETYPE) r = (0.5 - fit.uvalue("offset")) / fit.uvalue("slope") print("Range:", r, "cm")
def plot_ionisation_raw(): distances, voltages, error_voltages = np.loadtxt( "data/radium_ionisationskammer.txt", unpack=True) # discard 38.80cm distances = distances[:-1] voltages = voltages[:-1] error_voltages = error_voltages[:-1] for distance, voltage, error_voltage in zip(distances, voltages, error_voltages): distance = ufloat(distance, 0.05) voltage = ufloat(voltage, error_voltage) print("$({:L}) \\unit{{cm}}$ & $({:L}) \\unit{{mV}}$ \\\\".format( distance, voltage)) plt.clf() plt.minorticks_on() plt.errorbar(distances, voltages, xerr=0.05, yerr=error_voltages, fmt=',') plt.xlabel("Distanz / cm") plt.ylabel("Spannung / mV") plt.savefig("out/radium_ionisation_raw." + SAVETYPE) plt.clf() plt.minorticks_on() currents = [] error_currents = [] for voltage, error_voltage in zip(voltages, error_voltages): current = ufloat(voltage, error_voltage) #+ ufloat(5, 3) currents.append(current.n) error_currents.append(current.s) currents = np.array(currents) error_currents = np.array(error_currents) distances -= 39 plt.clf() plt.minorticks_on() plt.errorbar(distances, currents, xerr=0.05, yerr=error_currents, fmt=',') plt.xlabel("Distanz / cm") plt.ylabel("Strom / nA") plt.savefig("out/radium_ionisation." + SAVETYPE) plt.clf() plt.minorticks_on() x = distances[1:] + np.abs(np.diff(distances) / 2) y = -np.diff(currents) / np.diff(distances) plt.plot(x, y, 's-') plt.xlabel("Distanz / cm") plt.ylabel("- Änderung des Stromes / nA / cm") plt.savefig("out/radium_ionisation_diff." + SAVETYPE) plt.clf() plt.minorticks_on() fit = Fit(LINEAR) fit.set_data(xdata=(7.42, 6.92, 6.42), ydata=currents[9:12], xerrors=0.25, yerrors=error_currents[9:12]) fit.set_labels(xlabel="Distanz / cm", ylabel="Strom / nA") fit.iterative_fit(5) fit.plot(box="tr", units={"slope": "nA/cm", "offset": "nA"}) plt.savefig("out/radium_ionisation_po_fit." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="tl") plt.savefig("out/radium_ionisation_po_residual." + SAVETYPE) middle = (ufloat(currents[9], error_currents[9]) + ufloat(currents[11], error_currents[11])) / 2 print("Middle:", middle, "nA") r = (middle - fit.uvalue("offset")) / fit.uvalue("slope") print("Range:", r, "cm")
def fit_radium_calib(): energies = [3.953, 5.332, 7.02] # MeV error_energies = np.array([0.001, 0.001, 0.01]) / math.sqrt(12) channels = [240, 815, 1495] error_channels = [10, 10, 8] fit = Fit(LINEAR) fit.set_data(xdata=channels, xerrors=error_channels, ydata=energies, yerrors=error_energies) fit.set_labels(xlabel="Kanal", ylabel="Energie / MeV") fit.iterative_fit(5) plt.clf() plt.minorticks_on() fit.plot(box="tl", units={ "slope": "keV/Kanal", "offset": "MeV" }, factors={"slope": 1000}) plt.savefig("out/radium_calib_fit." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="bl") plt.savefig("out/radium_calib_residual." + SAVETYPE)
def radium_calib_2(): E, proj_range = np.loadtxt("ranges.txt", unpack=True) real_range = proj_range / 1.184e-3 energy_from_range = interp1d(real_range, E, kind='cubic') energies = [] error_energies = [] for distance in (0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5): distance = ufloat(35 + distance, 0.05) total_distance = (distance - 35) + ufloat(3.17, 0.17) for peak in (3.52, 4.99, 7.18): peak = ufloat(peak, 0.01) rest = peak - total_distance try: upper = energy_from_range(rest.n + rest.s) lower = energy_from_range(rest.n - rest.s) value = energy_from_range(rest.n) except ValueError as e: #print(e) #print("orig distance:", peak, "cm ", "rest distance:", rest, "cm ") pass else: error = max(upper - value, value - lower) energy = ufloat(value, error) #print("orig distance:", peak, "cm ", "total distance:", total_distance, "cm ", "rest distance:", rest, "cm ", "rest energy:", energy, "MeV") print( "$({:L}) \\unit{{cm}}$ & $({:L}) \\unit{{cm}}$ & $({:L}) \\unit{{cm}}$ & $({:L}) \\unit{{cm}}$ & $({:L}) \\unit{{MeV}}$ \\\\" .format(peak, distance, total_distance, rest, energy)) energies.append(value) error_energies.append(error) # PART2 !!! channels = [ 220, 780, 1460, 620, 1340, 450, 1260, 150, 1170, 990, 820, 620, 390 ] error_channels = [20, 20, 20, 20, 20, 20, 20, 100, 20, 20, 20, 20, 30] energies = energies[:len(channels)] error_energies = error_energies[:len(channels)] for energy, error_energy, channel, error_channel in zip( energies, error_energies, channels, error_channels): e = ufloat(energy, error_energy) c = ufloat(channel, error_channel) print("$({:L}) \\unit{{MeV}}$ & ${:L}$ \\\\".format(e, c)) fit = Fit(LINEAR) fit.set_data(xdata=channels, xerrors=error_channels, ydata=energies, yerrors=error_energies) fit.set_labels(xlabel="Kanal", ylabel="Energie / MeV") fit.iterative_fit(5) plt.clf() plt.minorticks_on() fit.plot(box="tl", units={ "slope": "keV/Kanal", "offset": "MeV" }, factors={"slope": 1000}) plt.savefig("out/radium_calib2_fit." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="tr") plt.savefig("out/radium_calib2_residual." + SAVETYPE)
def plot_qswitch(): frequency, error_frequency, power = np.loadtxt("data/frequenz_qswitch.txt", unpack=True) error_power = 1 / math.sqrt(12) power /= 1000 error_power /= 1000 plt.clf() plt.errorbar(frequency, power, xerr=error_frequency, yerr=error_power, fmt=',', color="black") plt.xlabel("Frequenz / Hz") plt.ylabel("Leistung / mW") plt.savefig("out/qswitch_raw." + SAVETYPE) #power -= power[0] fit = Fit(POLY3) fit.set_data(xdata=frequency, ydata=power, xerrors=error_frequency, yerrors=error_power) fit.set_params(a0=380, a1=0.005, a2=-7e-8) fit.set_labels(xlabel="Frequenz / Hz", ylabel="Leistung / mW") subfit = fit.filtered(np.logical_and(frequency < 20e3, frequency > 1e3)) subfit.iterative_fit(5) plt.clf() subfit.plot(box="br", units={ "a3": "mW/Hz^3", "a2": "mW/Hz^2", "a1": "mW/Hz", "a0": "mW" }) plt.savefig("out/qswitch_power_fit." + SAVETYPE) plt.clf() subfit.plot_residual(box="tr") plt.savefig("out/qswitch_power_residual." + SAVETYPE) plt.clf() time, voltage = _load_oscilloscope_csv("data/ALL0023/F0023CH2.CSV") time *= 1E6 time -= -935 plt.plot(time, voltage, ".", color="black") pause = np.logical_and(time > 300, time < 900) one_period = np.logical_and(time > 0, time < 1000) print(one_period, one_period.sum()) mean_voltage = ufloat(voltage[one_period].mean(), voltage[pause].std() / math.sqrt(one_period.sum())) peak_voltage = ufloat(voltage[one_period].max(), voltage[pause].std()) print("ErrorL:", voltage[pause].std()) print("Mean voltage:", mean_voltage, "V") print("Peak voltage:", peak_voltage, "V") frequency = 1.01798e3 # Hz mean_power = subfit.ueval(frequency) print("Mean power:", mean_power * 1000, "uW") peak_power = mean_power * peak_voltage / mean_voltage print("Peak power:", peak_power * 1000, "uW") plt.axhline(mean_voltage.n, color="red", linewidth=2) plt.axhline(peak_voltage.n, color="red", linewidth=2) plt.xlabel("Zeit / us") plt.ylabel("Spannung / V") plt.savefig("out/qswitch_osci." + SAVETYPE)
def plot_diode_kennlinie(): current, power = np.loadtxt("data/kennlinie_diode.txt", unpack=True) error_current = 1 / math.sqrt(12) error_power = 1 / math.sqrt(12) plt.clf() plt.errorbar(current, power, xerr=error_current, yerr=error_power, fmt=',', color="black") plt.xlabel("Strom / mA") plt.ylabel("Leistung / mW") plt.savefig("out/kennlinie_diode_raw." + SAVETYPE) fit_indices_list = [] fit_indices_list.append(current > 200) valid = current > 200 valid[current > 410] = False fit_indices_list.append(valid) valid = current > 410 fit_indices_list.append(valid) zero_power = power[current < 150] background = zero_power.mean() print("Background:", background, "mW") power -= background func = lambda x, slope, threshold: (x - threshold) * slope fit = Fit(func) fit.set_params(slope=0.85, threshold=190) fit.set_data(xdata=current, ydata=power, xerrors=error_current, yerrors=error_power) fit.set_labels(xlabel="Strom / mA", ylabel="Leistung / mW") for i, fit_indices in enumerate(fit_indices_list): subfit = fit.filtered(fit_indices) plt.clf() plt.errorbar(current, power, xerr=error_current, yerr=error_power, fmt=',', color="black") subfit.iterative_fit(5) #plt.axhline(background, color="blue") #plt.axvline(subfit.value("threshold"), color="blue") print("Threshold:", formatUFloat(subfit.uvalue("threshold"), unit="mA")) print("Slope:", formatUFloat(subfit.uvalue("slope"), unit="W/A")) print("Chi^2/ndf:", subfit.chi2ndf) print("===") subfit.plot(range=(subfit.value("threshold"), current.max()), color="black", plot_fit=False, plot_data=True, fmt="s") subfit.plot(range=(subfit.value("threshold"), current.max()), box="tl", color="red", plot_data=False, units={ "threshold": "mA", "slope": "W/A" }) plt.savefig("out/kennlinie_diode_%d_fit." % i + SAVETYPE) plt.clf() subfit.plot_residual(box="br", color="black", fmt="s") plt.savefig("out/kennlinie_diode_%d_residual." % i + SAVETYPE)
def plot_yag_kennlinie(): current, power, error_power = np.loadtxt("data/kennlinie_yag2.txt", unpack=True) error_current = 1 / math.sqrt(12) plt.clf() plt.errorbar(current, power, xerr=error_current, yerr=error_power, fmt=',', color="black") plt.xlabel("Strom / mA") plt.ylabel("Leistung / mW") plt.xlim(0, 700) plt.savefig("out/kennlinie_yag_raw." + SAVETYPE) lower = np.logical_and(current > 182.10, current < 410) upper = current >= 410 fit_indices_list = [] fit_indices_list.append(power > 0.10) #fit_indices_list.append(np.logical_and(power > 0.10, lower)) #fit_indices_list.append(np.logical_and(power > 0.10, upper)) diode_power, error_diode_power = current2diode_power( current, error_current) zero_power = power[current < 150] background = zero_power.mean() print("Background:", background, "mW") power -= background plt.clf() plt.errorbar(diode_power, power, xerr=error_diode_power, yerr=error_power, fmt=',', color="black") plt.xlabel("Diodenleistung / mW") plt.ylabel("Laserleistung / mW") plt.savefig("out/kennlinie_yag_raw2." + SAVETYPE) func = lambda x, slope, threshold: (x - threshold) * slope fit = Fit(func) fit.set_params(slope=0.016, threshold=16) fit.set_data(xdata=diode_power, ydata=power, xerrors=error_diode_power, yerrors=error_power) fit.set_labels(xlabel="Diodenleistung / mW", ylabel="Laserleistung / mW") fit.iterative_fit(1) plt.clf() fit.plot(plot_data=True, plot_fit=True, box="tr") plt.savefig("out/kennlinie_yag_linear_fit." + SAVETYPE) plt.clf() fit.plot_residual(box="br", fmt="s") plt.savefig("out/kennlinie_yag_linear_residual." + SAVETYPE) fit = Fit(POLY2) fit.set_data(xdata=diode_power, ydata=power, xerrors=error_diode_power, yerrors=error_power) fit.set_labels(xlabel="Diodenleistung / mW", ylabel="Laserleistung / mW") fit.iterative_fit(5) for i, fit_indices in enumerate(fit_indices_list): plt.clf() fit.plot(plot_fit=False) subfit = fit[fit_indices] subfit.iterative_fit(5) #zero_power = power[power < 0.03] #zero = umean(zero_power) #plt.axhline(zero.n, color="blue") print(subfit) x = 200 try: i_threshold = solve_quadratic(subfit.uvalue("a0"), subfit.uvalue("a1"), subfit.uvalue("a2")) i_slope = 2 * x * subfit.uvalue("a2") + subfit.uvalue("a1") except ValueError: print("no solution", i) else: print("Threshold:", formatUFloat(i_threshold, unit="mW")) print("Efficiency:", formatUFloat(i_slope * 100, unit="%")) lines = "threshold = " + formatUFloat( i_threshold, unit="mW" ) + "\n" + "efficiency at %d mW = " % x + formatUFloat( i_slope * 100, unit="%") info_box(lines, location="tl") subfit.plot(plot_data=False) plt.savefig("out/kennlinie_yag_%d_fit." % i + SAVETYPE) plt.clf() subfit.plot_residual(box="br", color="black", fmt="s") plt.savefig("out/kennlinie_yag_%d_residual." % i + SAVETYPE) plt.clf() x = diode_power[diode_power > i_threshold.n] plt.plot(x, 100 * (2 * x * subfit.value("a2") + subfit.value("a1")), color="black") #x_new = diode_power - i_threshold.n #plt.plot(diode_power, 100*(x_new*subfit.value("a2") + subfit.value("a1") + subfit.value("a0")/x_new), color="red") plt.xlabel("Diodenleistung / mW") plt.ylabel("Effizienz / %") plt.savefig("out/kennlinie_yag_%d_efficiency." % i + SAVETYPE)
def plot_delay_spectrum(): x1, y1 = np.loadtxt("data/pm1_delay.txt", unpack=True) x2, y2 = np.loadtxt("data/pm2_delay.txt", unpack=True) time = np.hstack((-x1, x2)) count = np.hstack((y1, y2)) error_count = np.sqrt(count + 1) plt.clf() plt.errorbar(time, count, yerr=error_count, fmt='s', color="black") func = lambda x, offset, mu, sigma, A: offset + GAUSS(x, mu, sigma, A) fit = Fit(func) fit.offset = 0 fit.mu = -45 fit.sigma = 60 fit.fit(time, count, error_count) fit.plot(box="tr", units={"mu": "ns", "sigma": "ns"}, color="red") print(fit) plt.xlabel(r"$\Delta T / \textrm{ns}$") plt.ylabel("Count") plt.savefig("out/delay_fit." + SAVETYPE) plt.clf() fit.plot_residual(time, count, error_count, fmt="s", box="br", color="black") plt.xlabel(r"$\Delta T / \textrm{ns}$") plt.ylabel("Count") plt.savefig("out/delay_residual." + SAVETYPE)
def plot_energy_spectra(): mus = [] widths = [] energies = [] #leer = TkaFile("data/EnergiespektrumLeer.TKA") with LatexTable("out/calib_peaks.tex") as peaktable, LatexTable( "out/rates.tex") as ratetable: peaktable.header("El.", "Höhe", r"Channel $x_\textrm{max}$", r"Breite $\Delta x$", r'$\chi^2/\textrm{ndf}$', "Energie / keV", lineafter=1) ratetable.header("El.", "Events", "Messzeit", "Rate") for filename, meta in energy_spectra.items(): peaktable.hline() tka = TkaFile("data/" + filename) x = np.arange(len(tka)) #y = tka.data - leer.data y = tka.data #errors = np.sqrt(tka.data + leer.data + 2) errors = np.sqrt(tka.data + 1) plt.clf() plt.plot(x, y, ',', color="black") for i, (mu0, sigma0, energy, sigma_energy) in enumerate(meta["peaks"], 1): fit = local_fit(x, y, errors, mu=mu0, sigma=sigma0) fit.plot(fit.mu - 5 * fit.sigma, fit.mu + 5 * fit.sigma, 1000, zorder=10000, color="red") mus.append((fit.mu, fit.error_mu)) if meta["element"] in ("Na", "Cs"): E_gamma = 0.09863 * fit.mu - 19.056 m_electron = 511 # keV E_compton = E_gamma / (1 + m_electron / (2 * E_gamma)) c_compton = (E_compton + 19.056) / 0.09863 plt.axvline(c_compton, color="red", linestyle="--") peaktable.row((meta["element"], len(meta["peaks"])), formatQuantityLatex(fit.A, fit.error_A), formatQuantityLatex(fit.mu, fit.error_mu), formatQuantityLatex(fit.sigma, fit.error_sigma), "%.2f" % fit.chi2ndf, formatQuantityLatex(energy, sigma_energy)) widths.append((fit.sigma, fit.error_sigma)) energies.append((energy, sigma_energy)) #print(meta["element"], i, fit) plt.xlabel("Kanal") plt.ylabel("Count") plt.xlim(0, 2**14) plt.title(meta["title"]) plt.savefig("out/" + clean_filename(filename) + "_all." + SAVETYPE) N = ufloat(y.sum(), errors.sum()) t = ufloat(tka.real_time, 1 / math.sqrt(12)) m = N / t # Hz/Bq r = ufloat(91.5, 0.01) # mm A = ufloat(*meta["activity"]) * 1000 # Bq I_g = 1 r = ufloat(15, 5) F_D = ufloat(7.45, 0.05) * ufloat(80.75, 0.05) # mm^2 efficiency = 4 * math.pi * r**2 * m / (F_D * A * I_g) print("Efficiency:", meta["element"], efficiency) ratetable.row(meta["element"], formatUFloatLatex(N), formatUFloatLatex(t, unit="s"), formatUFloatLatex(m, unit="1/s")) mus, error_mus = np.array(mus).T widths, error_widths = np.array(widths).T energies, error_energies = np.array(energies).T # Kalibration plt.clf() fit = Fit(LINEAR) fit.slope = 0.1 fit.offset = -20 for i in range(5): errors = fit.combine_errors(mus, error_mus, error_energies) fit.fit(mus, energies, errors) plt.errorbar(mus, energies, xerr=error_mus, yerr=error_energies, fmt=',', color="black") fit.plot(box='tl', units={ "slope": "eV / Channel", "offset": "eV" }, factors={ "slope": 1000, "offset": 1000 }, color="red") plt.xlabel("Kanal") plt.ylabel("Energie / keV") plt.savefig("out/calib_fit." + SAVETYPE) plt.clf() errs = fit.combine_errors(mus, xerr=error_mus, yerr=error_energies) fit.plot_residual(mus, energies, errs, box='tl', fmt=',', color="black") plt.xlabel("Kanal") plt.ylabel("Energie / keV") plt.savefig("out/calibresiduum." + SAVETYPE) s = formatQuantityLatex(fit.slope * 1000, fit.error_slope * 1000, unit="eV / Kanal", math=False) o = formatQuantityLatex(fit.offset * 1000, fit.error_offset * 1000, unit="eV", math=False) with open('out/calib.tex', 'w') as file: file.write( r'Die in diesem Versuch verwendeten Einstellungen f\"uhren zu einer Einteilung von \[ ' + s + r' \] wobei der erste Kanal die Energie \[ ' + o + r' \] besitzt.') # Energieauflösung error_widths = np.sqrt( np.power(fit.error_slope * widths, 2) + np.power(error_widths * fit.slope, 2)) widths = widths * fit.slope error_energies = np.sqrt( np.power(fit.error_offset, 2) + np.power(mus * fit.error_slope, 2) + np.power(fit.slope * error_mus, 2)) energies = fit.slope * mus + fit.offset X = energies Y = widths SX = error_energies SY = error_widths func = lambda E, a, b: np.sqrt(np.power(a * E, 2) + np.power(b, 2) * E) fit = Fit(func) fit.a = 0.01 fit.b = 0.01 for _ in range(10): err = fit.combine_errors(X, SX, SY) fit.fit(X, Y, err) plt.clf() plt.errorbar(X, Y, xerr=SX, yerr=SY, fmt=',', color="black") fit.plot(box='br', units={'b': r'\sqrt{\textrm{keV}}'}, color="red") plt.xlabel(r"$ E $ / keV") plt.ylabel(r"$ \Delta E / keV$") plt.title( r'Energieauflösung: Fit zu $ \Delta E = \sqrt{\left(a E\right)^2 + b^2 E} $' ) plt.savefig("out/energyresolution_fit." + SAVETYPE) print("a =", formatQuantity(fit.a, fit.error_a)) print("b =", formatQuantity(fit.b, fit.error_b)) plt.clf() err = fit.combine_errors(X, SX, SY) fit.plot_residual(X, Y, err, box='tr', fmt=",", color="black") plt.xlabel(r"$ E $ / keV") plt.ylabel(r"$ \Delta E / keV$") plt.title("Energieauflösung: Residuen") plt.savefig("out/energyresolution_residual." + SAVETYPE) with LatexTable("out/energyresolution.tex") as table: table.header("Parameter", "Wert") table.row("$a$", formatQuantityLatex(fit.a, fit.error_a)) table.row("$b$", formatQuantityLatex(fit.b, fit.error_b, unit="\sqrt{keV}"))
def plot_yag_lifetime(): time, voltage = _load_oscilloscope_csv("data/ALL0010/F0010CH2.CSV") time *= 1E6 # us voltage *= 1000 # mV error_voltage = voltage[time < 0].std() print("Fehler:", error_voltage, "mV") fit = Fit(EXPONENTIAL_DECAY) fit.set_data(xdata=time, ydata=voltage, yerrors=error_voltage) fit.set_labels(xlabel="Zeit / us", ylabel="Spannung / mV") fit = fit.filtered(np.logical_and(time > 0, time < 1500)) fit.set_params(A=0.1, offset=0.20, T=250) fit.iterative_fit(1) print("Lebensdauer:", formatUFloat(fit.uvalue("T"), "us"), "- Chi^2:", fit.chi2, "- ndf:", fit.ndf, "- Chi^2/ndf:", fit.chi2ndf) plt.clf() fit.plot(box="tr", units={"T": "us", "A": "mV", "offset": "mV"}) plt.savefig("out/yag_lifetime." + SAVETYPE)
def plot_coincidence_co(): angle, count = np.loadtxt("data/winkel_cobalt3.txt", unpack=True) error_angle = 0.3 error_count = np.sqrt(count + 1) plt.clf() plt.errorbar(angle, count, xerr=error_angle, yerr=error_count, fmt='s', color="black") W = lambda theta, A, a2, a4: A * (1 + a2 * np.power( np.cos(np.radians(theta)), 2) + a4 * np.power( np.cos(np.radians(theta)), 4)) fit = Fit(W) fit.A = count.mean() fit.a2 = 0 fit.a4 = 0 for i in range(5): errors = fit.combine_errors(angle, error_angle, error_count) fit.fit(angle, count, errors) fit.plot(-90, 90, box="br", color="red") plt.xlim(-90, 90) plt.xlabel("Winkel / Grad") plt.ylabel("Count") plt.savefig("out/coincidence_co_fit." + SAVETYPE) plt.clf() fit.plot_residual(angle, count, errors, fmt="s", box="br", color="black") plt.xlabel("Winkel / Grad") plt.ylabel("Count") plt.savefig("out/coincidence_co_residual." + SAVETYPE) plt.clf() plt.errorbar(angle, count, xerr=error_angle, yerr=error_count, fmt='s', color="black") fit = Fit(CONSTANT) fit.c = count.mean() for i in range(5): errors = fit.combine_errors(angle, error_angle, error_count) fit.fit(angle, count, errors) fit.plot(-90, 90, box="br", color="red") plt.xlim(-90, 90) plt.xlabel("Winkel / Grad") plt.ylabel("Count") plt.savefig("out/coincidence_co_fitc." + SAVETYPE) plt.clf() fit.plot_residual(angle, count, errors, fmt="s", box="br", color="black") plt.xlabel("Winkel / Grad") plt.ylabel("Count") plt.savefig("out/coincidence_co_residualc." + SAVETYPE)
def local_fit(x, y, errors, mu, sigma): func = lambda x, mu, sigma, A, a0, a1: GAUSS(x, mu, sigma, A) + a0 + a1 * x fit = Fit(func) fit.mu = _simple_peak(y, mu, sigma) fit.sigma = sigma fit.A = y[fit.mu] fit.a0 = 0 fit.a1 = 0 for i in range(5): lower = max(fit.mu - 5 * fit.sigma, 0) upper = min(fit.mu + 5 * fit.sigma, len(x)) lx = x[lower:upper] ly = y[lower:upper] lerrors = errors[lower:upper] if i <= 2: fit.fit(lx, ly, lerrors, solver="curve_fit") else: fit.fit(lx, ly, lerrors, solver="minuit", method="migrad") return fit
def plot_coincidence_na(): for spalte in (1, 2): columns = np.loadtxt("data/natrium_winkel.txt", unpack=True) angle = columns[0] count = columns[spalte] error_angle = 0.3 error_count = np.sqrt(count + 1) plt.clf() plt.errorbar(angle, count, xerr=error_angle, yerr=error_count, fmt=',', color="black") fit = Fit(GAUSS) fit.mu = 0 fit.sigma = 10 for i in range(5): errors = fit.combine_errors(angle, error_angle, error_count) fit.fit(angle, count, errors) fit.plot(fit.mu - 5 * fit.sigma, fit.mu + 5 * fit.sigma, box="bl", color="red") plt.ylim(0, plt.ylim()[1]) plt.xlabel("Winkel / Grad") plt.ylabel("Count") plt.savefig("out/coincidence_na_%d_fit." % spalte + SAVETYPE) plt.clf() fit.plot_residual(angle, count, errors, fmt="s", box="br", color="black") plt.xlabel("Winkel / Grad") plt.ylabel("Count") plt.savefig("out/coincidence_na_%d_residual." % spalte + SAVETYPE)
def plot_caesium_absorber(): depth, events, slabs = np.loadtxt("data/caesium_bleiabschirmung.txt", unpack=True) error_depth = np.sqrt(slabs) * 0.1 error_events = np.sqrt(events + 1) plt.clf() plt.minorticks_on() plt.errorbar(depth, events, xerr=error_depth, yerr=error_events, fmt=',') plt.xlabel("Tiefe / mm") plt.ylabel("ln(Anzahl)") plt.savefig("out/caesium_absorber_nolog." + SAVETYPE) ln_events = np.log(events) error_ln_events = np.abs(1 / events) * error_events depth /= 10 # mm=>cm error_depth /= 10 plt.clf() plt.minorticks_on() func = lambda x, mu, lnI0: -x * mu + lnI0 fit = Fit(func) fit.set_data(xdata=depth, ydata=ln_events, xerrors=error_depth, yerrors=error_ln_events) fit.set_labels(xlabel="Tiefe / cm", ylabel="ln(Anzahl)") fit.iterative_fit(5) fit.plot(box="tr", units={"mu": "1/cm"}) plt.savefig("out/caesium_absorber_fit." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="tr") plt.savefig("out/caesium_absorber_residual." + SAVETYPE) plt.clf() plt.minorticks_on() fit = fit.filtered(depth <= 2) fit.iterative_fit(5) fit.plot(box="tr", units={"mu": "1/cm"}) plt.savefig("out/caesium_absorber_fit2." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="tr") plt.savefig("out/caesium_absorber_residual2." + SAVETYPE) mu = fit.uvalue("mu") print("Absorptionskoeffizient:", mu, "1/cm") mu1 = mu / ufloat(11.342, 0.001) print("Massenabsorptionskoeffizient:", mu1, "cm^2/g")
def plot_ktp(): current, power, error_power = np.loadtxt("data/ktp_kristall.txt", unpack=True) error_current = 1 / math.sqrt(12) # uW -> mW power /= 1000 error_power /= 1000 plt.clf() plt.errorbar(current, power, xerr=error_current, yerr=error_power, fmt=',', color="black") plt.xlabel("Strom / mA") plt.ylabel("Leistung mit KTP / mW") plt.xlim(0, 700) plt.savefig("out/ktp_raw." + SAVETYPE) lower = np.logical_and(current > 182.10, current < 410) upper = current >= 410 diode_power, error_diode_power = current2diode_power( current, error_current) plt.clf() plt.errorbar(diode_power, power, xerr=error_diode_power, yerr=error_power, fmt=',', color="black") plt.xlabel("Diodenleistung / mW") plt.ylabel("Laserleistung mit KTP / mW") plt.savefig("out/ktp_raw2." + SAVETYPE) yag_power, error_yag_power = diode_power2yag_power(diode_power, error_diode_power) plt.clf() plt.errorbar(yag_power, power, xerr=error_yag_power, yerr=error_power, fmt=',', color="black") plt.xlabel("Laserleistung ohne KTP / mW") plt.ylabel("Laserleistung mit KTP / mW") plt.xlim(0, 10) plt.savefig("out/ktp_raw3." + SAVETYPE) plt.clf() fit = Fit(POLY2) fit.set_data(xdata=yag_power, ydata=power, xerrors=error_yag_power, yerrors=error_power) fit.set_labels(xlabel="Laserleistung ohne KTP / mW", ylabel="Laserleistung mit KTP / mW") fit = fit.filtered(yag_power > 2) fit.iterative_fit(5) fit.plot(box="tl", units={"a2": "1/mW", "a0": "mW"}) plt.savefig("out/ktp_fit." + SAVETYPE) plt.clf() fit.plot_residual(box="tl") plt.savefig("out/ktp_residual." + SAVETYPE)
def plot_strontium(): m = { 0: 0, 5: 0.03, 6: 0.04, 7: 0.05, 8: 0.08, 9: 0.10, 10: 0.17, 11: 0.25, 12: 0.37, 13: 0.50, 14: 0.64, 15: 0.83, 16: 1.01, 17: 1.23, 18: 1.39, 19: 1.57, 20: 1.88, 21: 2.29, 22: 2.79, 23: 3.46, } nr, count = np.loadtxt("data/strontium_alu.txt", unpack=True) absorb = np.zeros_like(nr) for i, x in enumerate(nr): absorb[i] = m[x] / 10 scale = 1 / count[0] error_count = np.sqrt(count + 1) error_absorb = 0.01 / 10 count *= scale error_count *= scale func = lambda x, A, mu, offset: A * np.exp(-x * mu) + offset fit = Fit(func) fit.set_data(xdata=absorb, ydata=count, xerrors=error_absorb, yerrors=error_count) fit.set_params(A=1, mu=1, offset=0) fit.set_labels(xlabel="Dicke / cm", ylabel="Anteil") fit.iterative_fit(5) plt.clf() plt.minorticks_on() plt.xlim(0, .35) fit.plot(box="tr", units={"mu": "1/cm"}) plt.savefig("out/strontium_fit." + SAVETYPE) plt.clf() plt.minorticks_on() fit.plot_residual(box="tr") plt.savefig("out/strontium_residual." + SAVETYPE) rho = ufloat(2.7, 0.1) mu = fit.uvalue("mu") print("Absorptionskoeffizient:", mu, "1/cm") mu1 = mu / rho print("Massenabsorptionskoeffizient:", mu1, "cm^2/g") E = umath.pow(17 / mu1, 1 / 1.14) print("Maximalenergie:", E, "MeV") R1 = 0.412 * umath.pow(E, 1.265 - 0.0954 * umath.log(E)) R = R1 / rho print("Reichweite:", R1, "g/cm^2") print("Reichweite:", R, "cm")
def energieaufloesung(calibration, plot=True): print("##### ENERGY RESOLUTION #####") energies = [] widths = [] sigma_energies = [] sigma_widths = [] for filename, meta in kalib.items(): experiment = Experiment("data/" + filename, title=meta["title"], calibration=calibration) for peak in meta["peaks"]: mu0, sigma0 = peak[0], peak[1] fit = experiment.find_peak(mu0, sigma0, plot=False) energies.append(experiment.channel2energy(fit.mu)) widths.append(experiment.channelwidth2energywidth(fit.sigma)) sigma_energies.append( experiment.channelwidth2energywidth(fit.sigma_mu)) sigma_widths.append( experiment.channelwidth2energywidth(fit.sigma_sigma)) for filename, meta in data.items(): experiment = Experiment("data/" + filename, title=filename, calibration=calibration) experiment.subtract_empty("data/G20_Leer.mca", 0.5) for peak in meta["peaks"]: mu0, sigma0 = peak[0], peak[1] fit = experiment.find_peak(mu0, sigma0, plot=False) energies.append(experiment.channel2energy(fit.mu)) widths.append(experiment.channelwidth2energywidth(fit.sigma)) sigma_energies.append( experiment.channelwidth2energywidth(fit.sigma_mu)) sigma_widths.append( experiment.channelwidth2energywidth(fit.sigma_sigma)) energies = np.array(energies) widths = np.array(widths) sigma_energies = np.array(sigma_energies) sigma_widths = np.array(sigma_widths) X = energies Y = np.power(widths, 2) SX = sigma_energies SY = 2 * widths * sigma_widths func = lambda x, a0, a1, : a0 + x * a1 #+np.power(x,2)*a2 fit = Fit(func) fit.a0 = 1 fit.a1 = 1 for _ in range(10): err = fit.combine_errors(X, SX, SY) fit.fit(X, Y, err) if plot: plt.clf() plt.errorbar(X, Y, xerr=SX, yerr=SY, fmt=',') fit.plot(np.min(X), np.max(X), box='br', units={ 'a0': 'keV', 'a1': r'\sqrt{keV}' }) plt.xlabel(r"$ E $ / keV") plt.ylabel(r"$ \Delta E^2 / keV^2$") plt.title(r'Energieauflösung: Fit zu $ \Delta E^2 = a_0 + a_1 E $' ) # \oplus \frac{c}{E} plt.savefig("out/energyresolution_fit." + SAVETYPE) plt.clf() err = fit.combine_errors(X, SX, SY) fit.plot_residuums(X, Y, err, box='tr', fmt=",") plt.xlabel(r"$ E $ / keV") plt.ylabel(r"$ \Delta E^2 / keV^2$") plt.title("Energieauflösung: Residuen") plt.savefig("out/energyresolution_residuum." + SAVETYPE) with LatexTable("out/energyresolution.tex") as table: table.header("Parameter", "Wert") table.row("$a_0$", format_error(fit.a0, fit.sigma_a0, unit="keV^2")) table.row("$a_1$", format_error(fit.a1, fit.sigma_a1, unit="keV")) table.hline() a = math.sqrt(fit.a0) b = math.sqrt(fit.a1) sa = 0.5 * fit.sigma_a0 / a sb = 0.5 * fit.sigma_a1 / b table.row("$a$", format_error(a, sa, unit="keV")) table.row("$b$", format_error(b, sb, unit="\sqrt{keV}")) with LatexTable("out/energyresolution_examples.tex") as table: energies = np.linspace(10, 60, 6) sigmas = np.sqrt(fit.apply(energies)) deltas = sigmas * 2 * math.sqrt(2 * math.log(2)) table.header("Energie", "Auflösung", "Relative Auflösung", "FWHM", lineafter=0) table.row("$E$", "$\sigma$", "$\sigma / E$", "$2 \sqrt{2 \ln{2}} \sigma$") table.hline(2) for energy, sigma, delta in zip(energies, sigmas, deltas): e = "%d keV" % energy s = _n(sigma * 1000) + " eV" d = "%d eV" % (delta * 1000) table.row(e, s, _n(sigma / energy * 100) + r"\%", d)