def calibrate(): """ do a rough energy calibration "automatic": based on finding ratios """ from scipy.signal import medfilt, find_peaks_cwt from scipy.stats import linregress pks_lit = [239, 911, 1460.820, 1764, 2614.511] # ds = DataSet(11, md='./runDB.json', tier_dir=tier_dir) ds = DataSet(run=204, md='./runDB.json', tier_dir=tier_dir) t2df = ds.get_t2df() rt = ds.get_runtime() / 3600 # hrs ene = t2df["e_ftp"] xlo, xhi, xpb = 0, 10000, 10 # damn, need to remove the overflow peak nbins = int((xhi - xlo) / xpb) hE, xE, _ = get_hist(ene, nbins, (xlo, xhi)) # xE, hE = get_hist(ene, xlo, xhi, xpb) # -- pygama's cal routine needs some work ... -- # need to manually remove the overflow peak? # data_peaks = get_most_prominent_peaks(ene, xlo, xhi, xpb, test=True) # ene_peaks = get_calibration_energies("uwmjlab") # ene_peaks = get_calibration_energies("th228") # best_m, best_b = match_peaks(data_peaks, ene_peaks) # ecal = best_m * t2df["trap_max"] + best_b # -- test out a rough automatic calibration here -- npks = 15 hE_med = medfilt(hE, 21) hE_filt = hE - hE_med pk_width = np.arange(1, 10, 0.1) pk_idxs = find_peaks_cwt(hE_filt, pk_width, min_snr=5) pks_data = xE[pk_idxs] pk_counts = hE[pk_idxs] idx_sorted = np.argsort(pk_counts) pk_idx_max = pk_idxs[idx_sorted[-npks:]] pks_data = np.sort(xE[pk_idx_max]) r0 = pks_lit[4] / pks_lit[2] # this is pretty ad hoc, should use more of the match_peaks function found_match = False for pk1 in pks_data: for pk2 in pks_data: r = pk1 / pk2 if np.fabs(r - r0) < 0.005: print("found match to peak list:\n " "r0 {:.3f} r {:.3f} pk1 {:.0f} pk2 {:.0f}".format( r0, r, pk1, pk2)) found_match = True # be careful, there might be more than one break if found_match: break # # check uncalibrated spectrum # plt.plot(xE, hE, ls='steps', lw=1, c='b') # # plt.plot(xE, hE_filt, ls='steps', lw=1, c='b') # # for pk in pks_data: # # plt.axvline(pk, color='r', lw=1, alpha=0.6) # plt.axvline(pk1, color='r', lw=1) # plt.axvline(pk2, color='r', lw=1) # plt.show() # exit() # two-point calibration data = np.array(sorted([pk1, pk2])) lit = np.array([pks_lit[2], pks_lit[4]]) m, b, _, _, _ = linregress(data, y=lit) print("Paste this into runDB.json:\n ", m, b) # err = np.sum((lit - (m * data + b))**2) # plt.plot(data, lit, '.b', label="E = {:.2e} x + {:.2e}".format(m, b)) # xf = np.arange(data[0], data[1], 1) # plt.plot(xf, m * xf + b, "-r") # plt.legend() # plt.show() # apply calibration ecal = m * ene + b # # check calibrated spectrum xlo, xhi, xpb = 0, 3000, 1 hC, xC, _ = get_hist(ecal, int((xhi - xlo) / xpb), (xlo, xhi)) hC = np.concatenate( (hC, [0])) # FIXME: annoying - have to add an extra zero plt.semilogy(xC, hC / rt, c='b', ls='steps', lw=1, label="MJ60 data, {:.2f} hrs".format(rt)) plt.axvline(pks_lit[2], c='r', lw=3, alpha=0.7, label="40K, 1460.820 keV") plt.axvline(pks_lit[4], c='m', lw=3, alpha=0.7, label="208Tl, 2614.511 keV") plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / hr / {:.2f} keV".format(xpb), ha='right', y=1) plt.legend() plt.tight_layout() # plt.show() plt.savefig("./plots/surface_spec.pdf") # exit() # check low-e spectrum plt.figure() xlo, xhi, xpb = 0, 50, 0.1 hC, xC, _ = get_hist(ecal, int((xhi - xlo) / xpb), (xlo, xhi)) hC = np.concatenate( (hC, [0])) # FIXME: annoying - have to add an extra zero plt.plot(xC, hC, c='b', ls='steps', lw=1, label="Kr83 data") plt.axvline(9.4057, color='r', lw=1.5, alpha=0.6, label="9.4057 keV") # kr83 lines plt.axvline(12.651, color='g', lw=1.5, alpha=0.6, label="12.651 keV") # kr83 lines plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / {:.2f} keV".format(xpb), ha='right', y=1) plt.legend() plt.tight_layout() # plt.show() plt.savefig("./plots/test_kr83_cal.pdf")
def resolution(): """ fit the 208Tl 2615 keV peak and give me the resolution test out pygama's peak fitting routines """ ds_num = 11 ds = DataSet(ds_num, md='./runDB.json', tier_dir=tier_dir) t2df = ds.get_t2df() ene = t2df["energy"].values rt = ds.get_runtime() / 3600 # hrs # apply calibration cal = runDB["cal_onboard"][str(ds_num)] m, b = cal[0], cal[1] ene = m * ene + b # zoom in to the area around the 2615 peak xlo, xhi, xpb = 2565, 2665, 0.5 ene2 = ene[np.where((ene > xlo) & (ene < xhi))] xE, hE = get_hist(ene, xlo, xhi, xpb) # set peak bounds guess_ene = 2615 guess_sig = 5 idxpk = np.where((xE > guess_ene - guess_sig) & (xE > guess_ene + guess_sig)) guess_area = np.sum(hE[idxpk]) # radford_peak function pars: mu, sigma, hstep, htail, tau, bg0, a p0 = [guess_ene, guess_sig, 1E-3, 0.7, 5, 0, guess_area] bnd = [[0.9 * guess_ene, 0.5 * guess_sig, 0, 0, 0, 0, 0], [1.1 * guess_ene, 2 * guess_sig, 0.1, 0.75, 10, 10, 5 * guess_area]] pars = fit_binned(radford_peak, hE, xE, p0) #, bounds=bnd) print("mu:", pars[0], "\n", "sig", pars[1], "\n", "hstep:", pars[2], "\n", "htail:", pars[3], "\n", "tau:", pars[4], "\n", "bg0:", pars[5], "\n", "a:", pars[6]) plt.plot(xE, hE, c='b', ls='steps', lw=1, label="MJ60 data, {:.2f} hrs".format(rt)) plt.plot(xE, radford_peak(xE, *pars), color="r", alpha=0.7, label=r"Radford peak, $\sigma$={:.2f} keV".format(pars[1])) plt.axvline(2614.511, color='r', alpha=0.6, lw=1, label=r"$E_{lit}$=2614.511") plt.axvline(pars[0], color='g', alpha=0.6, lw=1, label=r"$E_{fit}$=%.3f" % (pars[0])) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / {:.2f} keV".format(xpb), ha='right', y=1) plt.legend() plt.tight_layout() # plt.show() plt.savefig("./plots/kr83_resolution.pdf")
def get_multiple_spectra(): # energy (onboard) # xlo, xhi, xpb = 0, 2000000, 1000 # xlo, xhi, xpb = 0, 500000, 1000 # xlo, xhi, xpb = 0, 50000, 100 # energy (onboard, calibrated) xlo, xhi, xpb = 0, 40, 0.1 # trap_max # xlo, xhi, xpb = 0, 10000, 10 # xlo, xhi, xpb = 0, 300, 0.3 # xlo, xhi, xpb = 0, 80, 0.2 # xlo, xhi, xpb = 0, 40, 0.1 # ds = DataSet(run=147, md='./runDB.json', tier_dir=tier_dir) # get calibration cal = runDB["cal_onboard"]["11"] m, b = cal[0], cal[1] ds = DataSet(10, md='./runDB.json', tier_dir=tier_dir) rt1 = ds.get_runtime() / 3600 t2df = ds.get_t2df() ene1 = m * t2df["energy"] + b x, h1 = get_hist(ene1, xlo, xhi, xpb) # x, h1 = get_hist(t2df["trap_max"], xlo, xhi, xpb) h1 = np.divide(h1, rt1) ds2 = DataSet(11, md='./runDB.json', tier_dir=tier_dir) t2df2 = ds2.get_t2df() rt2 = ds2.get_runtime() / 3600 ene2 = m * t2df2["energy"] + b x, h2 = get_hist(ene2, xlo, xhi, xpb) # x, h2 = get_hist(t2df2["trap_max"], xlo, xhi, xpb) h2 = np.divide(h2, rt2) plt.figure(figsize=(7, 5)) plt.plot(x, h1, ls='steps', lw=1, c='b', label="bkg, {:.2f} hrs".format(rt1)) plt.plot(x, h2, ls='steps', lw=1, c='r', label="Kr83, {:.2f} hrs".format(rt2)) plt.axvline(9.4057, color='m', lw=2, alpha=0.4, label="9.4057 keV") # kr83 lines plt.axvline(12.651, color='g', lw=2, alpha=0.4, label="12.651 keV") # kr83 lines plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / hr / {:.2f} keV".format(xpb), ha='right', y=1) plt.legend() plt.tight_layout() # plt.show() # plt.savefig("./plots/krSpec_{:.0f}_{:.0f}_onboard.pdf".format(xlo,xhi)) # plt.savefig("./plots/krSpec_{:.0f}_{:.0f}_uncal.pdf".format(xlo,xhi)) plt.savefig("./plots/krSpec_{:.0f}_{:.0f}_cal.pdf".format(xlo, xhi))