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 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 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_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_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 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 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 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_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_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_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_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)