def compareEnergy_MJD(): from ROOT import TFile, TTree run = 36854 gFile = "./data/mjd_run%d.root" % run tf = TFile(gFile) tt = tf.Get("mjdTree") n = tt.Draw("trapE", "", "goff") trapE = tt.GetV1() trapE = np.asarray([trapE[i] for i in range(n)]) x1, h1 = wl.GetHisto(trapE, 0, 10000, 10) print("ROOT file has {} hits".format(len(trapE))) df = pd.read_hdf("%s/t2_run%d.h5" % (data_dir, run)) print("pygama file has {} hits".format(len(df))) x2, h2 = wl.GetHisto(df['onboard_energy'], 0, 10000, 10) x3, h3 = wl.GetHisto(df['trap_max'], 0, 10000, 10) x4, h4 = wl.GetHisto(df['trap_ft'], 0, 100, 1) plt.semilogy(x1, h1, ls='steps', c='b', lw=2, label="majorcaroot trapE") plt.semilogy(x2, h2, ls='steps', c='r', lw=2, label="pygama onboard") plt.semilogy(x3, h3, ls='steps', c='g', lw=2, label="pygama trap_max") # plt.semilogy(x4, h4, ls='steps', c='m', lw=2, label="pygama trap_ft") plt.xlabel("Energy (uncalib.)", ha='right', x=1) plt.legend(loc=1) plt.show()
def compareEnergy_MJ60(): from ROOT import TFile, TTree run = 72 gFile = "./data/mjd_run%d.root" % run tf = TFile(gFile) tt = tf.Get("mjdTree") n = tt.Draw("trapE", "", "goff") trapE = tt.GetV1() trapE = np.asarray([trapE[i] for i in range(n)]) x1, h1 = wl.GetHisto(trapE, 0, 10000, 10) print("ROOT file has {} hits".format(len(trapE))) df = pd.read_hdf("%s/t2_run%d.h5" % (data_dir, run)) x2, h2 = wl.GetHisto(df['onboard_energy'], 0, 3500000, 4000) x3, h3 = wl.GetHisto(df['trap_max'], 0, 1000000, 1000) x4, h4 = wl.GetHisto(df['trap_ft'], 0, 100, 1) print("pygama file has {} hits".format(len(df['onboard_energy']))) # print(df.columns) 'channel', 'onboard_energy', 'bl_slope', 'bl_int', 'trap_max', 'trap_ft' energyK40 = 1460.820 onboardE_K40 = 1.37958e6 x2Cal = x2 * (energyK40 / onboardE_K40) trapE_K40 = 3626.64 x1Cal = x1 * (energyK40 / trapE_K40) print("majorcaroot: {:.2f} kev/bin pygama: {:.2f} kev/bin".format( x1Cal[1] - x1Cal[0], x2Cal[1] - x2Cal[0])) plt.semilogy(x1Cal, h1, ls='steps', c='b', lw=2, label="majorcaroot trapE (rough cal)") plt.semilogy(x2Cal, h2, ls='steps', c='r', lw=2, label="pygama onboard (rough cal)") print("majorcaroot evt sum: {} pygama evt sum: {}".format( np.sum(h1), np.sum(h2))) # plt.semilogy(x1, h1, ls='steps', c='b', lw=2, label="majorcaroot trapE") # plt.semilogy(x2, h2, ls='steps', c='r', lw=2, label="pygama onboard") # plt.semilogy(x3, h3, ls='steps', c='g', lw=2, label="pygama trap_max") # plt.semilogy(x4, h4, ls='steps', c='m', lw=2, label="pygama trap_ft") plt.xlabel("Energy (uncalib.)", ha='right', x=1) plt.legend(loc=1) plt.show()
def getFinal(): """ ./cut-spec.py -f """ from ROOT import TFile, TTree dsList = [0, 1, 2, 3, 4, "5A", "5B", "5C"] # dsList = ["5B"] # cutType = "final90" cutType = "final95t" # <-- use this one # histo output for each ds xLo, xHi, xpb = 0, 100, 0.1 nbx = int((xHi - xLo) / xpb) xTot = np.arange(xLo, xHi, xpb) hTot = {ds: np.zeros(len(xTot) + 1) for ds in dsList} # these 100% match w/ wl.GetHisto's output for ds in dsList: tf = TFile("%s/%s/%s_DS%s.root" % (dsi.cutDir, cutType, cutType, str(ds))) tt = tf.Get("skimTree") n = tt.Draw("trapENFCal", "", "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] xF, hF = wl.GetHisto(hitE, xLo, xHi, xpb) hTot[ds] = np.add(hTot[ds], hF) tf.Close() np.savez("./data/lat-cut-%s-spec.npz" % cutType, xTot, hTot)
def getCut(cutType): """ ./cut-spec.py -c [cutType] """ fPrefix = { "th": "%s/th/th" % dsi.cutDir, # thresholds only. ok # "fs" : "%s/fs/fs" % dsi.cutDir, # can't use this one, it was an old version of the 90% cut "fr95": "%s/fr95/fr" % dsi.cutDir, # this is sort of PSA amalgalm, ok "frb95": "%s/frb95/frb95" % dsi.cutDir # this is with burst cut, ok } from ROOT import TFile, TTree dsList = [0, 1, 2, 3, 4, "5A", "5B", "5C"] # dsList = ["5B"] # histo output for each ds xLo, xHi, xpb = 0, 100, 0.1 nbx = int((xHi - xLo) / xpb) xTot = np.arange(xLo, xHi, xpb) hTot = {ds: np.zeros(len(xTot) + 1) for ds in dsList} # these 100% match w/ wl.GetHisto's output for ds in dsList: print("Scanning DS-%s" % (str(ds))) dsNum = int(ds[0]) if isinstance(ds, str) else ds fList = [] if ds not in ["5A", "5B", "5C"]: fList = glob.glob("%s_ds%d_*" % (fPrefix[cutType], dsNum)) else: if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 for bIdx in range(bLo, bHi + 1): fList.extend( glob.glob("%s_ds%d_%d_*" % (fPrefix[cutType], dsNum, bIdx))) for idx, f in enumerate(fList): fr = np.fabs(100 * idx / len(fList) % 10) if fr < 0.5: print("%d/%d (file %s) %.1f%% done." % (idx, len(fList), f, 100 * idx / len(fList))) tf = TFile(f) tt = tf.Get("skimTree") n = tt.Draw("trapENFCal", "", "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] xF, hF = wl.GetHisto(hitE, xLo, xHi, xpb) hTot[ds] = np.add(hTot[ds], hF) tf.Close() np.savez("./data/lat-cut-%s-spec.npz" % cutType, xTot, hTot)
def main(): """ Make sure that the numpy histograms I'm using match the ROOT histogram class output. Examples: - Matching wl.GetHisto to a TH1D - Matching wl.npTH1D to a TH1D - Filling the bins of a TH1D manually """ # start with 100 random values, from 0 to 10 r = 10 * np.random.rand(100) # bin from 0 to 10 in intervals of 1 (11 bins. nB = 10 b/c it is 0-indexed) xLo, xHi, xpb = 0, 10, 1 nB = int((xHi - xLo) / xpb) # make the TH1D purely w/ ROOT stuff c = TCanvas() th1 = TH1D("th", "", nB, xLo, xHi) for v in r: th1.Fill(v) # 1. getHisto and npTH1D x1, y1 = wl.GetHisto(r, xLo, xHi, xpb, shift=False) plt.plot(x1, y1, ls='steps', c='b', lw=6) plt.axvline(1, c='g', lw=1) x2, y2, xpb2 = wl.npTH1D(th1) plt.plot(x2, y2, ls='steps', c='r', lw=4) # 2. manually fill each histogram bin to match some known curve (used for pdfs) th2 = TH1D("t2", "t2", nB, xLo, xHi) # the +1 is very important, it covers the last bin for iB in range(nB + 1): ctr = (iB + 0.5) * xpb + xLo bLo, bHi = ctr - xpb / 2, ctr + xpb / 2 idx = np.where((x2 >= bLo) & (x2 < bHi)) hCts = np.sum(y2[idx]) th2.SetBinContent(iB, hCts) th1.SetLineColor(ROOT.kBlue) th2.SetLineColor(ROOT.kRed) th1.SetLineWidth(2) th1.Draw("hist") th2.Draw("hist same") c.Print("../plots/htmp.pdf") x3, y3, xpb3 = wl.npTH1D(th2) plt.plot(x3, y3, ls='steps', c='g', lw=2) plt.xlim(xLo, xHi) plt.tight_layout() plt.savefig("../plots/hnp.pdf")
def getLAT(): from ROOT import TFile, TTree dsList = [0, 1, 2, 3, 4, "5A", "5B", "5C"] # histo output for each ds xLo, xHi, xpb = 0, 100, 0.1 nbx = int((xHi - xLo) / xpb) xTot = np.arange(xLo, xHi, xpb) hTot = {ds: np.zeros(len(xTot) + 1) for ds in dsList} # these 100% match w/ wl.GetHisto's output for ds in dsList: print("Scanning DS-%s" % (str(ds))) dsNum = int(ds[0]) if isinstance(ds, str) else ds fList = [] if ds not in ["5A", "5B", "5C"]: fList = glob.glob("%s/latSkimDS%d*" % (dsi.latDir, ds)) else: if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 for bIdx in range(bLo, bHi + 1): fList.extend( glob.glob("%s/latSkimDS%d_%d_*" % (dsi.latDir, dsNum, bIdx))) for idx, f in enumerate(fList): fr = np.fabs(100 * idx / len(fList) % 10) if fr < 0.5: print("%d/%d (file %s) %.1f%% done." % (idx, len(fList), f, 100 * idx / len(fList))) tf = TFile(f) tt = tf.Get("skimTree") n = tt.Draw("trapENFCal", "", "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] xF, hF = wl.GetHisto(hitE, xLo, xHi, xpb) hTot[ds] = np.add(hTot[ds], hF) tf.Close() np.savez("./data/lat-cutspec.npz", xTot, hTot)
def getTot(yVals, pctLo=1, pctHi=91, cutTot=None): """ take an array of fitSlo values and find the 90% value """ # method 1 -- cool xgauss fit # fLo, fHi = np.percentile(yVals,pctLo) * 1.2, np.percentile(yVals,pctHi) * 1.2 # nb = 30 # fpb = (fHi-fLo)/nb # x, h = wl.GetHisto(yVals, fLo, fHi, fpb, shift=False) # fMax = x[np.argmax(h)] # tau, mu, sig, amp = 10, fMax, 10, 10000 # bnd = [[0,-np.inf,0,0],[np.inf, np.inf, np.inf, np.inf]] # np.seterr(invalid='ignore', over='ignore') # try: # popt,_ = curve_fit(xGaussPDF, x, h, p0=(tau, mu, sig, amp), bounds=bnd) # tau, mu, sig, amp # except RuntimeError: # popt = 0, 0, 0, 0 # pass # np.seterr(invalid='warn', over='warn') # xFunc = np.arange(fLo, fHi, 0.01) # xgInt = xGaussCDF(xFunc, *popt) # # xgTot = 0 # idx = np.where(xgInt > 0.9) # if len(idx[0])!=0: # xgTot = xFunc[idx][0] # # if cutTot is not None: # effTot = xGaussCDF(cutTot, *popt) # return xgTot, effTot # # return xgTot # method 2 -- percentiles pctPass = np.percentile(yVals, pctTot) fShiftLo, fShiftHi, fpbShift = -100, 1000, 1 # this is better ... x, h = wl.GetHisto(yVals, fShiftLo, fShiftHi, fpbShift) tmp = np.cumsum(h) / np.sum(h) idx = np.where(x >= cutTot) effTot = tmp[idx][0] if cutTot is not None: return pctPass, effTot return pctPass
def compareData(): """ Make sure I can match the data points of a RooPlot """ from ROOT import TFile, TCanvas # === matplotlib style tf2 = TFile("./data/latDS%s.root" % ''.join([str(d) for d in dsList])) tt = tf2.Get("skimTree") tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hData = wl.GetHisto(hitE, eLo, eHi, epb) hErr = np.asarray([np.sqrt(h) for h in hData]) # statistical error plt.figure(figsize=(7,5)) # plt.plot(x, hData, ls='steps', c='b') # normal histo plt.errorbar(x, hData, yerr=hErr, c='k', ms=10, linewidth=0.8, fmt='.', capsize=2) # pretty convincing rooplot fake plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Events / %.1f keV" % epb, ha='right', y=1) plt.xlim(eLo, eHi) plt.tight_layout() # plt.show() plt.savefig("./plots/sf-data-np.pdf") # === roofit style f = TFile("./data/fitWorkspace.root") fitWorkspace = f.Get("fitWorkspace") fData = fitWorkspace.allData().front() fitResult = fitWorkspace.allGenericObjects().front() nPars = fitResult.floatParsFinal().getSize() fEnergy = fitWorkspace.var("trapENFCal") modelPDF = fitWorkspace.pdf("model") nBins = int((eHi-eLo)/epb + 0.5) fSpec = fEnergy.frame(RF.Range(eLo,eHi), RF.Bins(nBins)) fData.plotOn(fSpec) c = TCanvas() fSpec.Draw() c.Print("./plots/sf-data-rp.pdf")
def plotFit(): from ROOT import TFile, TCanvas, TH1D f = TFile("%s/data/fitWorkspace.root" % dsi.latSWDir) fitWorkspace = f.Get("fitWorkspace") fData = fitWorkspace.allData().front() fitResult = fitWorkspace.allGenericObjects().front() nPars = fitResult.floatParsFinal().getSize() hitE = fitWorkspace.var("trapENFCal") model = fitWorkspace.pdf("model") # fitWorkspace.Print() # plot data fSpec = hitE.frame(RF.Range(eLo,eHi), RF.Bins(nB)) fData.plotOn(fSpec) # plot model and components model.plotOn(fSpec, RF.LineColor(ROOT.kRed), RF.Name("FullModel")) c = TCanvas("c","c", 1400, 1000) fSpec.SetTitle("") fSpec.Draw() c.Print("%s/plots/spectrum-after.pdf" % dsi.latSWDir) c.Clear() # get fit results fitVals = {} for i in range(nPars): fp = fitResult.floatParsFinal() name = fp.at(i).GetName() fitVal = fp.at(i).getValV() fitErr = fp.at(i).getError() print("%s fitVal %.2f error %.2f" % (name, fitVal, fitErr)) if name == "amp-68GeK": nPk = fitVal if name == "amp-bkg": nBk = fitVal if name == "amp-trit": nTr = fitVal # === duplicate the rooplot in matplotlib === plt.close() tf = TFile("%s/data/latDS%s.root" % (dsi.latSWDir,''.join([str(d) for d in dsList]))) tt = tf.Get("skimTree") tCut = "isEnr==1" if enr is True else "isEnr==0" tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") trapE = tt.GetV1() trapE = [trapE[i] for i in range(n)] x, hData = wl.GetHisto(trapE, eLo, eHi, epb) # plt.plot(x, hData, ls='steps', c='b') # normal histo hErr = np.asarray([np.sqrt(h) for h in hData]) # statistical error plt.errorbar(x, hData, yerr=hErr, c='k', ms=5, linewidth=0.5, fmt='.', capsize=1, zorder=1) # pretty convincing rooplot fake # plot the model components and total tf2 = TFile("%s/data/specPDFs.root" % dsi.latSWDir) # get (eff-corrected) histos and normalize to 1 in the global energy range hTr = tf2.Get("h5") if eff: hTr = getEffCorrTH1D(hTr, pLo, pHi, nBP) hBkg = getBkgPDF(eff) hPk = peakPDF(10.37, getSigma(10.37), "68GeK", eff) x1, y1, xpb1 = wl.npTH1D(hTr) x2, y2, xpb2 = wl.npTH1D(hBkg) x3, y3, xpb3 = wl.npTH1D(hPk) x1, y1 = normPDF(x1, y1, eLo, eHi) x2, y2 = normPDF(x2, y2, eLo, eHi) x3, y3 = normPDF(x3, y3, eLo, eHi) nTot = nTr + nBk + nPk if abs(nTr - np.sum(y1 * nTr)) > 3: print("Error in trit: nTr %d cts in curve %d" % (nTr, np.sum(y1*nTr))) if abs(nTr - np.sum(y2 * nTr)) > 3: print("Error in bkg: nTr %d cts in curve %d" % (nTr, np.sum(y2*nTr))) if abs(nTr - np.sum(y3 * nTr)) > 3: print("Error in peak: nTr %d cts in curve %d" % (nTr, np.sum(y3*nTr))) # === reverse the efficiency correction to get the "true" number of counts y1c = nTr * getEffCorr(x1, y1, inv=True) y2c = nBk * getEffCorr(x2, y2, inv=True) y3c = nPk * getEffCorr(x3, y3, inv=True) nTotC = np.sum(y1c) + np.sum(y2c) + np.sum(y3c) # === plot total model pdfs = [[x1,y1,xpb1,nTr],[x2,y2,xpb2,nBk],[x3,y3,xpb3,nPk]] xT, yT = getTotalModel(pdfs, eLo, eHi, epb, smooth=True) plt.step(xT, yT, c='b', lw=2, label="Raw (no eff. corr): %d cts" % nTot) # === plot components of the (uncorrected) model # *** NOTE: to plot after the fit, multiply by (global bin width / bin width when generated). to integrate, don't. *** plt.step(x1, y1 * nTr * (epb/ppb), c='m', lw=2, alpha=0.7, label="Tritium: %d cts" % nTr) plt.step(x2, y2 * nBk * (epb/epb), c='g', lw=2, alpha=0.7, label="Bkg: %d cts" % nBk) plt.step(x3, y3 * nPk * (epb/ppb), c='c', lw=2, alpha=0.7, label="68GeK %d cts" % nPk) # === plot efficiency corrected final model pdfs = [[x1,y1c,xpb1,nTr],[x2,y2c,xpb2,nBk],[x3,y3c,xpb3,nPk]] xTc, yTc = getTotalModel(pdfs, eLo, eHi, epb, smooth=True, amp=False) plt.step(xTc, yTc, c='r', lw=3, label="Efficiency corrected: %d cts" % nTotC) # === plot components of the corrected model # plt.step(x1, y1c * (epb/ppb), c='orange', lw=2, alpha=0.7, label="trit fit: %d corr: %d" % (nTr, np.sum(y1c))) # plt.step(x2, y2c * (epb/epb), c='orange', lw=2, alpha=0.7, label="bkg fit: %d corr: %d" % (nBk, np.sum(y2c))) # plt.step(x3, y3c * (epb/ppb), c='orange', lw=2, alpha=0.7, label="peak fit: %d corr: %d" % (nPk, np.sum(y3c))) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / %.1f keV" % epb, ha='right', y=1) plt.legend(loc=1, fontsize=12) plt.xlim(eLo, eHi) plt.ylim(ymin=0) plt.tight_layout() # plt.show() plt.savefig("%s/plots/sf4-mplafter.pdf" % dsi.latSWDir)
def plotModel(): from ROOT import TFile, TH1D tf = TFile("%s/data/latDS%s.root" % (dsi.latSWDir,''.join([str(d) for d in dsList]))) tt = tf.Get("skimTree") tCut = "isEnr==1" if enr is True else "isEnr==0" hitE = ROOT.RooRealVar("trapENFCal", "Energy", eLo, eHi, "keV") hEnr = ROOT.RooRealVar("isEnr", "isEnr", 0, 1, "") # hitW = ROOT.RooRealVar("weight", "weight", 1, 1000, "") fData = ROOT.RooDataSet("data", "data", tt, ROOT.RooArgSet(hitE, hEnr), tCut) # fData = ROOT.RooDataSet("data", "data", tt, ROOT.RooArgSet(hitE, hEnr, hitW), "", "weight") nData = fData.numEntries() fitWorkspace = ROOT.RooWorkspace("fitWorkspace","Fit Workspace") getattr(fitWorkspace,'import')(hitE) getattr(fitWorkspace,'import')(fData) # getattr(fitWorkspace,'import')(fWeight) tf2 = TFile("%s/data/specPDFs.root" % dsi.latSWDir) pdfList = ROOT.RooArgList("shapes") # tritium nTr = 1000 hTr = tf2.Get("h5") if eff: hTr = getEffCorrTH1D(hTr, pLo, pHi, nBP) trNum = ROOT.RooRealVar("amp-trit", "amp-trit", nTr, 0., 50000.) trDH = ROOT.RooDataHist("tr", "tr", ROOT.RooArgList(hitE), RF.Import(hTr)) hitE.setRange(eLo, eHi) trPdf = ROOT.RooHistPdf("trPdf", "trPdf", ROOT.RooArgSet(hitE), trDH, 2) trExt = ROOT.RooExtendPdf("ext-trit", "ext-trit", trPdf, trNum) pdfList.add(trExt) # flat bg nBk = 1000 hBkg = getBkgPDF(eff) bkgNum = ROOT.RooRealVar("amp-bkg", "amp-bkg", nBk, 0., 10000.) bkgDH = ROOT.RooDataHist("bkg", "bkg", ROOT.RooArgList(hitE), RF.Import(hBkg)) hitE.setRange(eLo, eHi) bkgPdf = ROOT.RooHistPdf("bkgPdf", "bkgPdf", ROOT.RooArgSet(hitE), bkgDH, 2) bkgExt = ROOT.RooExtendPdf("ext-bkg", "ext-bkg", bkgPdf, bkgNum) pdfList.add(bkgExt) # 68ge peak nPk = 100 hPk = peakPDF(10.37, getSigma(10.37), "68GeK", eff) pkDH = ROOT.RooDataHist("pk", "pk", ROOT.RooArgList(hitE), RF.Import(hPk)) hitE.setRange(eLo, eHi) pkPdf = ROOT.RooHistPdf("pkPdf", "pkPdf", ROOT.RooArgSet(hitE), pkDH, 2) pkNum = ROOT.RooRealVar("amp-68GeK", "amp-68GeK", nPk, 0.0, 1000.) pkExt = ROOT.RooExtendPdf("ext-68GeK", "ext-68GeK", pkPdf, pkNum) pdfList.add(pkExt) model = ROOT.RooAddPdf("model","total pdf",pdfList) # rooplot before fitting fSpec = hitE.frame(RF.Range(eLo,eHi), RF.Bins(int((eHi-eLo)/epb))) # wouter's note: DON'T DELETE # "the default behavior is when you plot a p.d.f. on an empty frame it is # plotted with unit normalization. When you plot it on a frame with data in # it, it will normalize to the number of events in that dataset." # (then after you do a fit, the pdf normalization changes again ...) fData.plotOn(fSpec) # bkgExt.plotOn(fSpec) # pkExt.plotOn(fSpec) # 1 -- individual components at their initial fit values # use this one for one component (you have to divide by (bin width of orig pdf) in numpy when you plot, but not when you integrate) trExt.plotOn(fSpec, RF.LineColor(ROOT.kMagenta), RF.Normalization(nTr, ROOT.RooAbsReal.Raw)) bkgExt.plotOn(fSpec, RF.LineColor(ROOT.kGreen), RF.Normalization(nBk, ROOT.RooAbsReal.Raw)) pkExt.plotOn(fSpec, RF.LineColor(ROOT.kBlue), RF.Normalization(nPk, ROOT.RooAbsReal.Raw)) # 2 -- the model, normalized according to the total number of counts in a really fking stupid way # model.plotOn(fSpec, RF.LineColor(ROOT.kRed)) # model.plotOn(fSpec, RF.Components("ext-trit"), RF.LineColor(ROOT.kMagenta), RF.Name("ext-trit")) # model.plotOn(fSpec, RF.Components("ext-bkg"), RF.LineColor(ROOT.kGreen), RF.Name("ext-bkg")) # model.plotOn(fSpec, RF.Components("ext-68GeK"), RF.LineColor(ROOT.kBlue), RF.Name("ext-68GeK")) from ROOT import TCanvas c = TCanvas("c","c", 1400, 1000) fSpec.SetTitle("") fSpec.Draw() c.Print("%s/plots/spectrum-before.pdf" % dsi.latSWDir) c.Clear() # === replicate the rooplot with numpy (no weights) === tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") trapE = tt.GetV1() trapE = [trapE[i] for i in range(n)] x, hData = wl.GetHisto(trapE, eLo, eHi, epb) # plt.plot(x, hData, ls='steps', c='b') # normal histo hErr = np.asarray([np.sqrt(h) for h in hData]) # statistical error plt.errorbar(x, hData, yerr=hErr, c='k', ms=5, linewidth=0.5, fmt='.', capsize=1, zorder=1) # pretty convincing rooplot fake # get (eff-corrected) histos and normalize them to the global energy range x1, y1, _ = wl.npTH1D(hTr) x2, y2, _ = wl.npTH1D(hBkg) x3, y3, _ = wl.npTH1D(hPk) x1, y1 = normPDF(x1, y1, eLo, eHi) x2, y2 = normPDF(x2, y2, eLo, eHi) x3, y3 = normPDF(x3, y3, eLo, eHi) # === 1. plot individual components of the model # *** NOTE: to plot, divide by (bin width when generated). to integrate, don't. *** plt.plot(x1, y1 * nTr / ppb, ls='steps', c='m', lw=2, label="trit init: %d int: %d" % (nTr, np.sum(y1 * nTr))) plt.plot(x2, y2 * nBk / epb, ls='steps', c='g', lw=2, label="bkg init: %d int: %d" % (nBk, np.sum(y2 * nBk))) plt.plot(x3, y3 * nPk / ppb, ls='steps', c='b', lw=2, label="68GeK init: %d int: %d" % (nPk, np.sum(y3 * nPk))) # === 2. replicate the stupid way a rooplot normalizes multiple pdf's based on the number of data counts (before a fit) # nModel = 3 # yTot = np.add(y1, y2, y3) # yTot *= nData/nModel # plt.plot(x1, yTot, ls='steps', c='r', lw=2, label="total, nData %d sum %d max %.1f" % (nData, int(np.sum(yTot)), np.amax(yTot))) # plt.plot(x1, y1 * nData/2, ls='steps', c='b', lw=2, label="tritium") # plt.plot(x2, y2 * nData/2, ls='steps', c='g', lw=2, label="bkg") # === 3. check a peak which was generated with a different binning than the global binning # print(np.sum(y3)) # this is 1 # print(np.sum(y3 * (epb/xpb3))) # this is bigger than 1, but matches the way rooplot normalizes it when plotted by itself. fk rooplot # print(np.sum(y3 * nPk)) # plt.plot(x3, y3 * nPk / xpb3, ls='steps', label="pk init value: %d int: %d" % (nPk, np.sum(y3 * nPk))) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / %.1f keV" % epb, ha='right', y=1) plt.legend(loc=1) plt.xlim(eLo, eHi) plt.ylim(ymin=0) plt.tight_layout() # plt.show() plt.savefig("%s/plots/sf4-mplplot.pdf" % dsi.latSWDir) # === alright, now run the fit and check the plot again minimizer = ROOT.RooMinimizer( model.createNLL(fData, RF.NumCPU(2,0), RF.Extended(True)) ) minimizer.setPrintLevel(-1) minimizer.setStrategy(2) minimizer.migrad() fitResult = minimizer.save() # according to the internet, covQual==3 is a good indicator that it converged print("Fitter is done. Fit Cov Qual:", fitResult.covQual()) # save workspace to a TFile getattr(fitWorkspace,'import')(fitResult) getattr(fitWorkspace,'import')(model) tf3 = TFile("%s/data/fitWorkspace.root" % dsi.latSWDir,"RECREATE") fitWorkspace.Write() tf3.Close()
def ext_pulser_width(): f = np.load("../data/lat-extPulser.npz") extData = f['arr_0'].item() # {run: [pIdx, runTime, extChan, hitE, fSlo]} extInfo = { 624: [7236, 74.75, 'r'], 688: [7249, 67.25, 'g'], 674: [7220, 65.75, 'b'] } def xGaussPDF(x, k, loc, scale, amp): """ amp=overall multip factor, loc=mu, sc=sigma, k=tau """ from scipy.stats import exponnorm return amp * exponnorm.pdf(x, k, loc, scale) def xGaussCDF(x, k, loc, scale, amp): from scipy.stats import exponnorm return exponnorm.cdf(x, k, loc, scale) fsMax, fsLo, fsHi, fsE, fsR = [], [], [], [], [] xgFits = {} for i, run in enumerate(extData): ch = extData[run][2] cpd = det.getChanCPD(0, ch) # if ch != 674: continue # if i != 14: continue if run in [7233]: continue hitE = extData[run][3] fSlo = extData[run][4] idx = np.where(np.isfinite(hitE)) hitE, fSlo = hitE[idx], fSlo[idx] muE = np.average(hitE) sdE = np.std(hitE) if muE < 1.: continue if muE > 100: continue runTime = extData[run][1] / 1e9 # elogs: 20 Hz, 150 sec runs pulseRate = 20 # Hz nExp = int(runTime * pulseRate) nTot = len(hitE) tEff = nTot / nExp # fSlo = extData[run][4] # unshifted fSlo = [fs - extInfo[ch][1] for fs in extData[run][4]] # shifted fLo, fHi = np.percentile(fSlo, 1) * 1.2, np.percentile(fSlo, 97) * 1.2 if fHi > 50: fHi = 50 nb = 100 fpb = (fHi - fLo) / nb x, h = wl.GetHisto(fSlo, fLo, fHi, fpb, shift=False) fMax = x[np.argmax(h)] pct = [] for p in [10, 90]: tmp = np.cumsum(h) / np.sum(h) * 100 idx = np.where(tmp > p) pct.append(x[idx][0]) wid = pct[1] - pct[0] fsMax.append(fMax) fsLo.append(pct[0]) fsHi.append(pct[1]) fsE.append(muE) fsR.append(run) tau, mu, sig, amp = 10, fMax, 10, 10000 np.seterr(invalid='ignore', over='ignore') popt, _ = curve_fit(xGaussPDF, x, h, p0=(tau, mu, sig, amp)) # tau, mu, sig, amp np.seterr(invalid='warn', over='warn') xgFits[run] = [muE, popt] # print("%d %d %d lo %.2f hi %.2f fpb %.2f E %-5.1f rt %.1f %d/%d (%.3f) FS 10%% %-5.1f max %-5.1f 90%% %-5.1f W %.1f" % (i, run, ch, fLo, fHi, fpb, muE, runTime, nTot, nExp, tEff, pct[0], fMax, pct[1], wid)) # plt.plot(x, h, ls='steps-mid', c=extInfo[ch][2], label="C%sP%sD%s, E %.1f Max %.1f Wid %.1f" % \ # (cpd[0],cpd[1],cpd[2],muE, fMax,wid)) # xFunc = np.arange(fLo, fHi, 0.01) # tau, mu, sig, amp = popt # xgFit = xGaussPDF(xFunc, *popt) # xgMax = xFunc[np.argmax(xgFit)] # plt.plot(xFunc, xgFit, '-b', label = "xGaus, tau %.1f mu %.1f sig %.1f amp %.1f" % (tau, mu, sig, amp)) # # get CDF # # xgInt = xGaussCDF(xFunc, *popt) # # distMax = np.amax(xgFit) # # plt.plot(xFunc, xgInt, '-k', label = "xGauss CDF") # # plt.axvline(xgMax, c='m', label='xg max %.1f' % xgMax) # # plt.axvline(fMax, c='k') # plt.axvline(pct[0], c='b') # plt.axvline(pct[1], c='g') # plt.xlabel("fitSlo (shifted)", ha='right', x=1) # plt.legend(loc=1, fontsize=10) # plt.tight_layout() # plt.show() # return # ======== plot the fast pulse envelope ======== fig = plt.figure(figsize=(8, 7)) p1 = plt.subplot(211) p2 = plt.subplot(212) # set the starting 90% value # i 12 muE 18.511 run 7251 run90 = 7251 chan90 = extData[run90][2] hitE90 = extData[run90][3] fSlo90 = [fs - extInfo[chan90][1] for fs in extData[run90][4]] # shifted fLo, fHi, fpb = -20, 20, 0.1 x, h = wl.GetHisto(fSlo90, fLo, fHi, fpb, shift=False) fMax = x[np.argmax(h)] tmp = np.cumsum(h) / np.sum(h) * 100 idx = np.where(tmp > 90) pct90 = x[idx][0] # plt.plot(x, h, ls='steps') # plt.axvline(fMax,c='r') # plt.axvline(pct90,c='g') # plt.show() # return p1.axhline(pct90, c='orange') # plot the acceptance of each CDF for i, run in enumerate(xgFits): muE = xgFits[run][0] if muE > 30: continue # print(i, muE, run) popt = xgFits[run][1] tau, mu, sig, amp = popt yFunc = np.arange(-80, 150, 0.1) # get the cdf and suppress the errors np.seterr(invalid='ignore', over='ignore') yCDF = xGaussCDF(yFunc, *popt) yCDF[np.where((np.isnan(yCDF)) | (yCDF < 1e-5))] = 0 # fix bad values np.seterr(invalid='warn', over='warn') # plt.plot(yFunc, yCDF) # plt.show() # return # plot each CDF as a color gradient y1 = yFunc[np.where(yCDF > 0.005)][0] y2 = mu y3 = yFunc[np.where(yCDF > 0.95)][0] y90 = yFunc[np.where(yCDF > 0.9)][0] nPts = 50 lineX = muE * np.ones(nPts) lineY = np.arange(y1, y3, (y3 - y1) / nPts) if len(lineY) > nPts: lineY = lineY[:nPts] cmap = plt.cm.get_cmap('inferno', nPts) for i in range(nPts): col = xGaussCDF(lineY[i], *popt) p1.plot(lineX[i:i + 2], lineY[i:i + 2], c=cmap(col)) p1.plot(muE, y2, ".k") p1.plot(muE, y90, '.r', ms=10) # calculate the acceptance for the given 90% value acc90 = xGaussCDF(pct90, *popt) print("%i pct90 %.2f muE %.2f acc90 %.2f" % (i, pct90, muE, acc90)) p2.plot(muE, acc90, '.k') p2.set_xlabel("Energy (keV)", ha='right', x=1) p1.set_ylabel("fitSlo (shifted)", ha='right', y=1) p2.set_ylabel("acc90", ha='right', y=1) plt.tight_layout() plt.show()
def acceptance_study(): """ 3 fast pulse acceptance plots: ext pulser, simulated wf, and m2s238 All for C1P6D3. Finally, plot the 3 efficiencies on the same plot. """ xLo, xHi = 0, 50 yLo, yHi = -100, 220 xPassLo, xPassHi, xpbPass = xLo, xHi, 1 # "low energy" region fShiftLo, fShiftHi, fpbShift = -100, 1000, 1 # this is what LAT2 uses # fShiftLo, fShiftHi, fpbShift = -100, 20, 1 # debug # save the acc/efficiency and plot them below accExtPulser, accSimWF, effM2S238, effM2S238Corr = [], [], [], [] fig = plt.figure(figsize=(8, 8)) p1 = plt.subplot(311) p2 = plt.subplot(312) p3 = plt.subplot(313) # ====== 1. ext pulser ====== f = np.load("../data/lat-extPulser.npz") extData = f['arr_0'].item() # {run: [pIdx, runTime, extChan, hitE, fSlo]} extInfo = { 624: [7236, 74.75, 'r'], 688: [7249, 67.25, 'g'], 674: [7220, 65.75, 'b'] } xVal, yVal = [], [] fsAll = [] for run in extData: ch = extData[run][2] cpd = det.getChanCPD(0, ch) if cpd != '163': continue if run in [7233]: continue hitE = extData[run][3] muE = np.average(hitE) if muE < 1.: continue if muE > xHi: continue fSlo = [fs - extInfo[ch][1] for fs in extData[run][4]] # shifted fsAll.extend(fSlo) # find the (pctTot)% value the way we do it in lat2 xSloExt, hSloExt = wl.GetHisto(fsAll, fShiftLo, fShiftHi, fpbShift) max, avg, std, pct, wid = wl.getHistInfo(xSloExt, hSloExt) if pctTot == 90: fsShiftCutExt = pct[2] elif pctTot == 95: fsShiftCutExt = pct[3] else: print("WTF are you doing??") exit() # plot the slices for i, run in enumerate(extData): ch = extData[run][2] cpd = det.getChanCPD(0, ch) if cpd != '163': continue if run in [7233]: continue hitE = extData[run][3] fSlo = extData[run][4] muE = np.average(hitE) sdE = np.std(hitE) if muE < 1.: continue if muE > xHi: continue xE = muE * np.ones(len(fSlo)) fSlo = [fs - extInfo[ch][1] for fs in extData[run][4]] # shifted p1.plot(xE, fSlo, '.b', ms=2) xgTot, accTot = getTot(fSlo, cutTot=fsShiftCutExt) p1.plot(muE, xgTot, '.r', ms=10) xT, yT = wl.GetHisto(fSlo, fShiftLo, fShiftHi, fpbShift) fCtr = xT[np.argmax(yT)] p1.plot(muE, fCtr, '.c', ms=10) xVal.append(xE) yVal.append(fSlo) p1.plot(np.nan, np.nan, ".b", ms=10, label="Ext.Pulser, C1P6D3") p1.axhline(fsShiftCutExt, c='orange', label="%d%% Overall Cut: %.1f" % (pctTot, fsShiftCutExt)) # try histogram pass/fail method from LAT2 hitExt, sloExt = [], [] for i in range(len(xVal)): hitExt.extend(xVal[i]) sloExt.extend(yVal[i]) hitPass, hitFail = [], [] for i in range(len(sloExt)): if sloExt[i] <= fsShiftCutExt: hitPass.append(hitExt[i]) else: hitFail.append(hitExt[i]) hitPass, hitFail = np.asarray(hitPass), np.asarray(hitFail) xELow, hPass = wl.GetHisto(hitPass, xPassLo, xPassHi, xpbPass, shift=False) xELow, hFail = wl.GetHisto(hitFail, xPassLo, xPassHi, xpbPass, shift=False) hTot = np.add(hPass, hFail) for i in range(len(xELow)): if hTot[i] == 0: continue effTot = hPass[i] / hTot[i] xTot = xELow[i] - xpbPass / 2 accExtPulser.append([xTot, effTot]) # plt.close() # plt.plot(xELow, hTot, ls='steps', c='k') # plt.plot(xELow, hPass, ls='steps', c='b') # plt.plot(xELow, hFail, ls='steps', c='r') # plt.show() # return # ====== 2. simulated wfs ====== import pandas as pd dfSig = pd.read_hdf('../data/SimPSA_P42574A.h5') # dfSig['Distance'] = dfSig['R'] * dfSig['R'] + dfSig['Z'] + dfSig['Z'] dfSig['trapENFCal'] = dfSig['Amp'] * 0.3959 # find center value xt, yt = wl.GetHisto(dfSig['fitSlo'], fShiftLo, fShiftHi, fpbShift) simShift = xt[np.argmax(yt)] # it's 65.5 dfSig['fitSloShift'] = dfSig['fitSlo'] - simShift # plt.close() # plt.plot(xt, yt, ls='steps') # plt.axvline(simShift, c='r') # xt, yt = wl.GetHisto(dfSig['fitSloShift'], fShiftLo, fShiftHi, fpbShift) # plt.plot(xt, yt, ls='steps') # plt.show() # return dfCut = dfSig.loc[(dfSig['fitSlo'] > 3) & (dfSig['Amp'] > 2)] p2.plot(dfCut['trapENFCal'], dfCut['fitSloShift'], '.b', ms=2, label="") p2.plot(np.nan, np.nan, ".b", ms=10, label="Simulated WFs, C1P6D3") # find the (pctTot)% value the way we do it in lat2 xSloSim, hSloSim = wl.GetHisto(dfCut['fitSloShift'].values, fShiftLo, fShiftHi, fpbShift) max, avg, std, pct, wid = wl.getHistInfo(xSloSim, hSloSim) if pctTot == 90: fsShiftCutSim = pct[2] elif pctTot == 95: fsShiftCutSim = pct[3] else: print("WTF are you doing??") exit() # plot the (pctTot)% values for each slice and the centroids # xVals = sorted(list(set(dfCut['trapENFCal']))) xVals = np.unique(dfCut['trapENFCal']) for xE in xVals: dfSlice = dfCut.loc[dfCut['trapENFCal'] == xE] yVals = dfSlice['fitSloShift'] xgTot, accTot = getTot(yVals, pctLo=1, pctHi=98, cutTot=fsShiftCutSim) p2.plot(xE, xgTot, '.r', ms=10) xT, yT = wl.GetHisto(yVals, fShiftLo, fShiftHi, fpbShift) fCtr = xT[np.argmax(yT)] p2.plot(xE, fCtr, '.c', ms=10) p2.axhline(fsShiftCutSim, c='orange', label="%d%% Overall Cut: %.1f" % (pctTot, fsShiftCutSim)) # try histogram pass/fail method from LAT2 hitPass, hitFail = [], [] hitVals, sloVals = dfCut['trapENFCal'].values, dfCut['fitSloShift'].values for i in range(len(sloVals)): if sloVals[i] <= fsShiftCutSim: hitPass.append(hitVals[i]) else: hitFail.append(hitVals[i]) hitPass, hitFail = np.asarray(hitPass), np.asarray(hitFail) xELow, hPass = wl.GetHisto(hitPass, xPassLo, xPassHi, xpbPass, shift=False) xELow, hFail = wl.GetHisto(hitFail, xPassLo, xPassHi, xpbPass, shift=False) hTot = np.add(hPass, hFail) for i in range(len(xELow)): if hTot[i] == 0: continue effTot = hPass[i] / hTot[i] xTot = xELow[i] - xpbPass / 2 accSimWF.append([xTot, effTot]) # plt.close() # plt.plot(xELow, hTot, ls='steps', c='k') # plt.plot(xELow, hPass, ls='steps', c='b') # plt.plot(xELow, hFail, ls='steps', c='r') # plt.show() # return # ====== 3. m2s238 data ====== cpd = '163' f2 = np.load("../data/slo2-m2s238-hits.npz") hitE, fSlo, shiftVals = f2['arr_0'].item(), f2['arr_1'].item( ), f2['arr_2'].item() eSlice = np.arange(xLo, xHi + 1, 2) # 2 keV slices, 0 - 250 xVal, yVal = [], [] for i in range(len(eSlice) - 1): eLo = eSlice[i] eHi = eSlice[i + 1] idx = np.where((hitE[cpd] >= eLo) & (hitE[cpd] <= eHi)) xVal.append((eHi - eLo) / 2 + eLo) yVal.append(fSlo[cpd][idx]) # find the (pctTot)% value the way we do it in lat2 xSloData, hSloData = wl.GetHisto(fSlo[cpd], fShiftLo, fShiftHi, fpbShift) max, avg, std, pct, wid = wl.getHistInfo(xSloData, hSloData) if pctTot == 90: fsShiftCutData = pct[2] elif pctTot == 95: fsShiftCutData = pct[3] else: print("WTF are you doing??") exit() # plot the slices, (pctTot)% dots, and centroid dots for i in range(len(xVal)): xV = xVal[i] * np.ones(len(yVal[i])) p3.plot(xV, yVal[i], ".b", ms=3.) xgTot, effTot = getTot(yVal[i], cutTot=fsShiftCutData) p3.plot(xVal[i], xgTot, '.r', ms=10) # effM2S238.append([xVal[i],effTot]) xT, yT = wl.GetHisto(yVal[i], fShiftLo, fShiftHi, fpbShift) fCtr = xT[np.argmax(yT)] p3.plot(xVal[i], fCtr, '.c', ms=10) # try histogram pass/fail method from LAT2 hitPass, hitFail = [], [] for i in range(len(fSlo[cpd])): if fSlo[cpd][i] <= fsShiftCutData: hitPass.append(hitE[cpd][i]) else: hitFail.append(hitE[cpd][i]) hitPass, hitFail = np.asarray(hitPass), np.asarray(hitFail) xELow, hPass = wl.GetHisto(hitPass, xPassLo, xPassHi, xpbPass, shift=False) xELow, hFail = wl.GetHisto(hitFail, xPassLo, xPassHi, xpbPass, shift=False) hTot = np.add(hPass, hFail) for i in range(len(xELow)): if hTot[i] == 0: continue effTot = hPass[i] / hTot[i] xTot = xELow[i] - xpbPass / 2 effM2S238.append([xTot, effTot]) p3.plot(np.nan, np.nan, ".b", ms=10, label="m2s238 Events, C1P6D3") p3.axhline(fsShiftCutData, c='orange', label="%d%% Overall Cut: %.1f" % (pctTot, fsShiftCutData)) # special -- load slowness fraction fS = np.load('../data/efficiency-corr2.npz') simHists = fS['arr_3'].item() xLo, xHi, xpb = 0, 50, 1 hTotSim, hSurfSim, xTotSim = simHists[cpd] hFracSim = np.divide(hSurfSim, hTotSim, dtype=float) for i in range(len(xELow)): if hTot[i] == 0: continue effTotCorr = (hPass[i] / (1 - hFracSim[i])) / hTot[i] xTot = xELow[i] - xpbPass / 2 effM2S238Corr.append([xTot, effTotCorr]) # thesis plot, don't delete # plt.close() # plt.plot(xELow, hTot, ls='steps', c='k', label='total, m2s238 C1P6D3') # plt.plot(xELow, hPass, ls='steps', c='b', label='pass') # plt.plot(xELow, hFail, ls='steps', c='r', label='fail') # plt.plot(xTotSim, hFracSim * hTot, ls='steps', c='m', label='sim, slow fraction of total') # plt.plot(xTotSim, hPass/(1-hFracSim), ls='steps', c='g', label='pass, sim-corrected') # plt.legend(loc=1, bbox_to_anchor=(0., 0.5, 1, 0.2)) # plt.xlabel("Energy (keV)", ha='right', x=1) # plt.ylabel("Counts", ha='right', y=1) # plt.tight_layout() # # plt.show() # plt.savefig("../plots/lat-sloFrac-%s.pdf" % cpd) # return p1.plot(np.nan, np.nan, ".r", label="%d%% of slice" % pctTot) p2.plot(np.nan, np.nan, ".r", label="%d%% of slice" % pctTot) p3.plot(np.nan, np.nan, ".r", label="%d%% of slice" % pctTot) p1.plot(np.nan, np.nan, ".c", label="Max of slice") p2.plot(np.nan, np.nan, ".c", label="Max of slice") p3.plot(np.nan, np.nan, ".c", label="Max of slice") p1.legend(loc=1, fontsize=14) p2.legend(loc=1, fontsize=14) p3.legend(loc=1, fontsize=14) p1.set_xlim(xLo, xHi) p1.set_ylim(yLo, yHi) p2.set_xlim(xLo, xHi) p2.set_ylim(yLo, yHi) p3.set_xlim(xLo, xHi) p3.set_ylim(yLo, 700) p1.set_ylabel("fitSlo (shifted)", ha='right', y=1) p3.set_xlabel("Energy (keV)", ha='right', x=1) p1.set_yticks([-80, 0, 100, 200]) p2.set_yticks([-80, 0, 100, 200]) p3.set_yticks([-80, 0, 200, 400, 600]) plt.tight_layout() fig.subplots_adjust(hspace=0.05) plt.setp(p1.get_xticklabels(), visible=False) plt.setp(p2.get_xticklabels(), visible=False) # plt.show() plt.savefig('../plots/lat-acceptance-study.png', dpi=300) return # ========= acceptance / efficiency plot ========= # return plt.close() fig = plt.figure() accExtPulser = np.asarray(accExtPulser) accSimWF = np.asarray(accSimWF) effM2S238 = np.asarray(effM2S238) effM2S238Corr = np.asarray(effM2S238Corr) # plt.plot(accExtPulser[:,0], accExtPulser[:,1], '-r', ls='steps', ms=10, label="Ext. Pulser Acc.") # plt.plot(accSimWF[:,0], accSimWF[:,1], '-g', ls='steps', ms=10, label="Sim WF Acc.") plt.plot(effM2S238[:, 0], effM2S238[:, 1], '-c', ls='steps', ms=10, label="m2s238, C1P6D3") plt.plot(effM2S238Corr[:, 0], effM2S238Corr[:, 1], '-m', ls='steps', ms=10, label="Sim-corrected") # now you're back to the figure plt.xlim(xLo, xHi) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Acceptance", ha='right', y=1) plt.legend(loc=4) plt.tight_layout() # plt.show() plt.savefig("../plots/lat-acceptance-vals.pdf") return # ===== plot the fitSlo distributions for all events with their (pctTot)% cuts ===== plt.close() plt.semilogy(xSloExt, hSloExt / np.amax(hSloExt), c='r', lw=2, ls='steps', label='Ext. Pulser') plt.axvline(fsShiftCutExt, c='m', lw=2, label="Ext %d%%: %.1f" % (pctTot, fsShiftCutExt)) plt.semilogy(xSloSim, hSloSim / np.amax(hSloSim), c='g', lw=2, ls='steps', alpha=0.8, label='Simulated WFs') plt.axvline(fsShiftCutSim, c='k', lw=2, label="Simulated %d%%: %.1f" % (pctTot, fsShiftCutSim)) plt.semilogy(xSloData, hSloData / np.amax(hSloData), c='b', lw=2, ls='steps', alpha=0.7, label='m2s238 Data') plt.axvline(fsShiftCutData, c='c', lw=2, label="m2s238 %d%%: %.1f" % (pctTot, fsShiftCutData)) plt.legend() plt.xlabel("fitSlo (shifted)", ha='right', x=1) plt.ylabel("Cts (Normalized)", ha='right', y=1) plt.tight_layout() # plt.show() plt.savefig("../plots/lat-acceptance-slo.pdf") # === fit the "new (pctTot)%" efficiency to weibull and recreate the "standard" efficiency plot === plt.close() # plt.plot(effM2S238[:,0], effM2S238[:,1], '-c', ls='steps',ms=10, label="m2s238 Efficiency") # this is the new, corrected efficiency idxP = np.where(hPass > 0) sloEff = hPass[idxP] / hTot[idxP] xEff = xELow[idxP] ci_low, ci_upp = proportion.proportion_confint(hPass[idxP], hTot[idxP], alpha=0.1, method='beta') idxE = np.where((xEff < xPassHi) & (xEff > 1)) xEff, sloEff, ci_low, ci_upp = xEff[idxE], sloEff[idxE], ci_low[ idxE], ci_upp[idxE] xEff -= xpbPass / 2. eFitHi = 30 fitBnd = ((1, -20, 0, 0.5), (np.inf, np.inf, np.inf, 0.99)) idxF = np.where(xEff <= eFitHi) popt, pcov = curve_fit(wl.weibull, xEff[idxF], sloEff[idxF], bounds=fitBnd) perr = np.sqrt(np.diag(pcov)) c, loc, sc, amp = popt cE, locE, scE, ampE = perr eff1 = wl.weibull(1., *popt) plt.plot(xEff, sloEff, '.b', ms=10., label='C%sP%sD%s' % (cpd[0], cpd[1], cpd[2])) plt.errorbar(xEff, sloEff, yerr=[sloEff - ci_low, ci_upp - sloEff], color='k', linewidth=0.8, fmt='none') xFunc = np.arange(xPassLo, xPassHi, 0.1) plt.plot(xFunc, wl.weibull(xFunc, *popt), 'm-', label=r'Weibull CDF') # NOTE: this is wrong, just plotting it to see the diff between old and new # plot the old "official" m2s238 efficiency on top -- this is wrong b/c of the wrong fitSlo 90% limit # this is a condensed version of lat-plots.py::fitSlo_det_efficiencies # cpd = '163' # f = np.load('../data/lat2-eff-data.npz') # effData = f['arr_0'].item() # xPassLo, xPassHi, xpbPass = 0, 50, 1 # xPassLo, xPassHi = xLo, xHi # xEff, sloEff, ci_low, ci_upp = effData[cpd][0], effData[cpd][1], effData[cpd][2], effData[cpd][3] # hPass, hFail, hTot, xELow = effData[cpd][4], effData[cpd][5], effData[cpd][6], effData[cpd][7] # idxP = np.where(hPass > 0) # sloEff = hPass[idxP] / hTot[idxP] # xEff = xELow[idxP] # ci_low, ci_upp = proportion.proportion_confint(hPass[idxP], hTot[idxP], alpha=0.1, method='beta') # idxE = np.where((xEff < xPassHi) & (xEff > 1)) # xEff, sloEff, ci_low, ci_upp = xEff[idxE], sloEff[idxE], ci_low[idxE], ci_upp[idxE] # xEff -= xpbPass/2. # b3 = ((0,-15,0,0),(np.inf,np.inf,np.inf,1.)) # this one is working best # popt, pcov = curve_fit(wl.weibull, xEff, sloEff, bounds=b3) # perr = np.sqrt(np.diag(pcov)) # c, loc, sc, amp = popt # cE, locE, scE, ampE = perr # eff1 = wl.weibull(1.,*popt) # plt.plot(xEff, sloEff, '.b', ms=10., label='C%sP%sD%s' % (cpd[0],cpd[1],cpd[2])) # plt.errorbar(xEff, sloEff, yerr=[sloEff - ci_low, ci_upp - sloEff], color='k', linewidth=0.8, fmt='none') # xFunc = np.arange(xPassLo, xPassHi, 0.1) # plt.plot(xFunc, wl.weibull(xFunc, *popt), 'r-', label=r'Weibull CDF') plt.axvline(1., color='b', lw=1., label='1.0 keV efficiency: %.2f' % wl.weibull(1., *popt)) plt.xlim(xLo, xHi) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Efficiency", ha='right', y=1) plt.legend(loc=4) plt.tight_layout() # plt.show() plt.savefig("../plots/lat-efficiency-weibull-%s.pdf" % cpd)
def fitModel(makePlots=False): from ROOT import TFile, TH1D, TCanvas, TLegend, gStyle # === load data into workspace === tf = TFile("%s/data/latDS%s.root" % (dsi.latSWDir, ''.join([str(d) for d in dsList]))) tt = tf.Get("skimTree") tCut = "isEnr==1" if enr is True else "isEnr==0" hitE = ROOT.RooRealVar("trapENFCal", "Energy", eLo, eHi, "keV") hEnr = ROOT.RooRealVar("isEnr", "isEnr", 0, 1, "") # hitW = ROOT.RooRealVar("weight", "weight", 1, 1000, "") fData = ROOT.RooDataSet("data", "data", tt, ROOT.RooArgSet(hitE, hEnr), tCut) # fData = ROOT.RooDataSet("data", "data", tt, ROOT.RooArgSet(hitE, hEnr, hitW), "", "weight") fitWorkspace = ROOT.RooWorkspace("fitWorkspace", "Fit Workspace") getattr(fitWorkspace, 'import')(hitE) getattr(fitWorkspace, 'import')(fData) # getattr(fitWorkspace,'import')(fWeight) tf2 = TFile("%s/data/specPDFs.root" % dsi.latSWDir) pdfList = ROOT.RooArgList("shapes") # === background model === hList = getHistList() bkgList = [] for h in hList: hB, name = h[0], h[1] pars = bkgVals[name] bkN = ROOT.RooRealVar("amp-" + name, "amp-" + name, pars[1], pars[2], pars[3]) bkDH = ROOT.RooDataHist("dh-" + name, "dh-" + name, ROOT.RooArgList(hitE), RF.Import(hB)) bkPDF = ROOT.RooHistPdf("pdf-" + name, "pdf-" + name, ROOT.RooArgSet(hitE), bkDH, 2) bkExt = ROOT.RooExtendPdf("ext-" + name, "ext-" + name, bkPDF, bkN) hitE.setRange(eLo, eHi) bkgList.append([bkExt, name, bkN, bkDH, bkPDF]) # this is separate b/c all the RooVars have to remain in memory for bkg in bkgList: pdfList.add(bkg[0]) model = ROOT.RooAddPdf("model", "total PDF", pdfList) if makePlots: # === make a rooplot of the initial guess parameters, don't let roofit normalize automatically leg = TLegend(0.83, 0.5, 0.97, 0.9) gStyle.SetPalette(ROOT.kRainBow) nCol = float(gStyle.GetNumberOfColors()) fSpec = hitE.frame(RF.Range(eLo, eHi), RF.Bins(nB)) fData.plotOn(fSpec) # wouter's note: DON'T DELETE # "the default behavior is when you plot a p.d.f. on an empty frame it is # plotted with unit normalization. When you plot it on a frame with data in # it, it will normalize to the number of events in that dataset." # (then after you do a fit, the pdf normalization changes again ...) nData = fData.numEntries() nTot = 0 for i, ext in enumerate(bkgList): extPDF, name = ext[0], ext[1] col = gStyle.GetColorPalette(int(nCol / len(bkgList) * i)) extPDF.plotOn( fSpec, RF.LineColor(col), RF.Normalization(bkgVals[name][1], ROOT.RooAbsReal.Raw), RF.Name(name)) leg.AddEntry(fSpec.findObject(name), name, "l") nTot += bkgVals[name][1] model.plotOn(fSpec, RF.LineColor(ROOT.kRed), RF.Name("fmodel"), RF.Normalization(nTot, ROOT.RooAbsReal.Raw)) leg.AddEntry(fSpec.findObject("fmodel"), "Full Model", "l") c = TCanvas("c", "c", 1400, 1000) fSpec.SetTitle("") fSpec.Draw() leg.Draw("same") c.Print("%s/plots/sf-before.pdf" % dsi.latSWDir) c.Clear() # === make a pyplot of the same thing tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") trapE = tt.GetV1() trapE = [trapE[i] for i in range(n)] x, hData = wl.GetHisto(trapE, eLo, eHi, epb) hErr = np.asarray([np.sqrt(h) for h in hData]) plt.errorbar(x, hData, yerr=hErr, c='k', ms=5, linewidth=0.5, fmt='.', capsize=1, zorder=1) # pretty convincing rooplot fake cmap = plt.cm.get_cmap('jet', len(hList) + 2) pdfs = [] for i, h in enumerate(hList): name = h[1] x, y, xpb = wl.npTH1D(h[0]) x, y = normPDF(x, y, eLo, eHi) nCts = bkgVals[h[1]][1] # the initial guess if abs(nCts - np.sum(y * nCts)) > 2: print("norm error, %s nCts %d y*nCts %d" % (name, nCts, np.sum(y * nCts))) # plt.step(x, y * nCts / xpb, c=cmap(i), lw=2, label="%s init cts: %d" % (name, nCts)) # plot the histo xS = np.arange(eLo, eHi, 0.001) # plot a smoothed version yS = spline(x - xpb / 2, y, xS) plt.plot(xS, yS * nCts / xpb, c=cmap(i), lw=2, label="%s init cts: %d" % (name, nCts)) pdfs.append([x, y, xpb, nCts]) xT, yT = getTotalModel(pdfs, eLo, eHi, epb, smooth=True) plt.step(xT, yT / epb, c='r', lw=2, label="Raw (no eff. corr): %d cts" % nTot) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / %.1f keV" % epb, ha='right', y=1) plt.legend(loc=1, fontsize=12) plt.xlim(eLo, eHi) plt.ylim(ymin=0) plt.tight_layout() # plt.show() plt.savefig("%s/plots/sf-before-mpl.pdf" % dsi.latSWDir) # === alright, now run the fit and output to the workspace minimizer = ROOT.RooMinimizer( model.createNLL(fData, RF.NumCPU(2, 0), RF.Extended(True))) minimizer.setPrintLevel(-1) minimizer.setStrategy(2) minimizer.migrad() fitResult = minimizer.save() # according to the internet, covQual==3 is a good indicator that it converged print("Fitter is done. Fit Cov Qual:", fitResult.covQual()) # save workspace to a TFile getattr(fitWorkspace, 'import')(fitResult) getattr(fitWorkspace, 'import')(model) tf3 = TFile("%s/data/fitWorkspace.root" % dsi.latSWDir, "RECREATE") fitWorkspace.Write() tf3.Close()
def plotFit(plotRate=False): from ROOT import TFile, TCanvas, TH1D, TLegend, gStyle f = TFile("%s/data/fitWorkspace.root" % dsi.latSWDir) fitWorkspace = f.Get("fitWorkspace") fData = fitWorkspace.allData().front() fitResult = fitWorkspace.allGenericObjects().front() nPars = fitResult.floatParsFinal().getSize() hitE = fitWorkspace.var("trapENFCal") model = fitWorkspace.pdf("model") nData = fData.numEntries() fCov = fitResult.covQual() # fitWorkspace.Print() # === get fit results: {name : [nCts, err]} === fitVals = {} for i in range(nPars): fp = fitResult.floatParsFinal() name = fp.at(i).GetName() fitVal, fitErr = fp.at(i).getValV(), fp.at(i).getError() if "amp" in name: fitVals[name.split('-')[1]] = [fitVal, fitErr] # for f in fitVals: # print(f, fitVals[f]) # === make a rooplot of the fit === leg = TLegend(0.83, 0.5, 0.97, 0.9) gStyle.SetPalette(ROOT.kRainBow) nCol = float(gStyle.GetNumberOfColors()) fSpec = hitE.frame(RF.Range(eLo, eHi), RF.Bins(nB)) fData.plotOn(fSpec) for i, name in enumerate(bkgModel): pdfName = "ext-" + name col = gStyle.GetColorPalette(int(nCol / len(bkgModel) * i)) model.plotOn(fSpec, RF.Components(pdfName), RF.LineColor(col), RF.LineStyle(ROOT.kDashed), RF.Name(name)) leg.AddEntry(fSpec.findObject(name), name, "l") chiSquare = fSpec.chiSquare(nPars) model.plotOn(fSpec, RF.LineColor(ROOT.kRed), RF.Name("fmodel")) leg.AddEntry(fSpec.findObject("fmodel"), "Full Model, #chi^{2}/NDF = %.3f" % chiSquare, "l") c = TCanvas("c", "c", 1400, 1000) fSpec.SetTitle("") fSpec.Draw() leg.Draw("same") c.Print("%s/plots/sf-after.pdf" % dsi.latSWDir) c.Clear() # === duplicate the rooplot in matplotlib === plt.close() tf = TFile("%s/data/latDS%s.root" % (dsi.latSWDir, ''.join([str(d) for d in dsList]))) tt = tf.Get("skimTree") tCut = "isEnr==1" if enr is True else "isEnr==0" tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") trapE = tt.GetV1() trapE = [trapE[i] for i in range(n)] x, hData = wl.GetHisto(trapE, eLo, eHi, epb) if plotRate: hErr = np.asarray([np.sqrt(h) / detExp for h in hData]) # statistical error plt.errorbar(x, hData / detExp, yerr=hErr, c='k', ms=5, linewidth=0.5, fmt='.', capsize=1, zorder=1) else: hErr = np.asarray([np.sqrt(h) for h in hData]) # statistical error plt.errorbar(x, hData, yerr=hErr, c='k', ms=5, linewidth=0.5, fmt='.', capsize=1, zorder=1) # get the list of histograms and plot the components hList = getHistList() cmap = plt.cm.get_cmap('jet', len(hList) + 2) pdfs, pdfsCorr, nTot, nTotC = [], [], 0, 0 for i, h in enumerate(hList): name = h[1] x, y, xpb = wl.npTH1D(h[0]) x, y = normPDF(x, y, eLo, eHi) nCts, nErr = fitVals[name] # final result yc = nCts * getEffCorr(x, y, inv=True) if abs(nCts - np.sum(y * nCts)) > 2: print("norm error, %s nCts %d y*nCts %d" % (name, nCts, np.sum(y * nCts))) # plt.step(x, y * nCts * (epb/xpb), c=cmap(i), lw=2, label="%s cts: %.2f±%.2f" % (name, nCts, nErr)) # plot the histo xS = np.arange(eLo, eHi, 0.001) # plot a smoothed version yS = spline(x - xpb / 2, y, xS) if plotRate: plt.plot(xS, yS * nCts * (epb / xpb) / detExp, "--", c=cmap(i), lw=2, label="%s %.2f ± %.2f" % (name, nCts / detExp, nErr / detExp)) else: plt.plot(xS, yS * nCts * (epb / xpb), c=cmap(i), lw=2, label="%s cts: %d" % (name, nCts)) pdfs.append([x, y, xpb, nCts]) pdfsCorr.append([x, yc, xpb, nCts]) nTot += nCts nTotC += np.sum( yc ) # reverse the efficiency correction to get the "true" number of counts # get the fit model, and the efficiency-corrected final model xT, yT = getTotalModel(pdfs, eLo, eHi, epb, smooth=True) xTc, yTc = getTotalModel(pdfsCorr, eLo, eHi, epb, smooth=True, amp=False) if plotRate: plt.plot(xT, yT / detExp, 'r', lw=2, alpha=0.7, label="Rate: %.2f" % (nTot / detExp)) plt.plot(xTc, yTc / detExp, c='m', lw=3, alpha=0.7, label="Eff.corr: %.2f " % (nTotC / detExp)) plt.ylabel("Counts / keV / kg-d", ha='right', y=1) else: plt.plot(xT, yT, 'r', lw=2, alpha=0.7, label="Raw (no eff. corr): %d cts" % nTot) plt.plot(xTc, yTc, c='m', lw=3, alpha=0.7, label="Efficiency corrected: %d cts" % nTotC) plt.ylabel("Counts / %.1f keV" % epb, ha='right', y=1) plt.xlabel("Energy (keV)", ha='right', x=1) plt.legend(loc=1, fontsize=12) plt.xticks(np.arange(int(eLo) - 1, eHi + 1, 5)) plt.xlim(eLo, eHi) plt.ylim(ymin=0) plt.tight_layout() # plt.show() plt.savefig("%s/plots/sf-after-mpl.pdf" % dsi.latSWDir)
def combineDSEff(): xLo, xHi, xpbE = 0, 30, 0.5 xE, hPassAll = wl.GetHisto([], xLo, xHi, xpbE) dfList = [] # loop over multiple ds's for ds in [0]: for key in cal.GetKeys(ds)[:1]: # get channels in this DS and map back to CPD chList = det.getGoodChanList(ds) mod = -1 if "m1" in key: mod = 1 chList = [ch for ch in chList if ch < 1000] if "m2" in key: mod = 2 chList = [ch for ch in chList if ch > 1000] cpdList = [det.getChanCPD(ds, ch) for ch in chList] chMap = {det.getChanCPD(ds, ch): ch for ch in chList} dfList.append(loadScanData(key)) dfTot = pd.concat(dfList) # Create Pass/Fail column dfTot['Pass'] = np.where((dfTot['T/E'] > 1.2) & (dfTot['T/E'] < 2.1), 'Pass', 'Fail') print(dfTot.head(10)) g1 = sns.FacetGrid(dfTot, col='channel', hue="Pass", col_wrap=7) g1 = g1.map(plt.hist, "Energy (keV)", bins=xE, alpha=0.7) g1.add_legend() # dfTot fig1, ax1 = plt.subplots(figsize=(10, 7)) for ch in sorted(chList): ax1.cla() dfCut = dfTot.loc[dfTot['channel'] == ch] dfPass = dfCut.loc[dfCut['Pass'] == 'Pass'] dfFail = dfCut.loc[dfCut['Pass'] == 'Fail'] hTotal, hTotalEdges = np.histogram(dfCut['Energy (keV)'].values, bins=xE) hPass, hPassEdges = np.histogram(dfPass['Energy (keV)'].values, bins=xE) hFail, hFailEdges = np.histogram(dfFail['Energy (keV)'].values, bins=xE) binCenters = hTotalEdges[:-1] + xpbE / 2 chEff = np.divide(hPass, hTotal, dtype=float) ci_low, ci_upp = proportion.proportion_confint(hPass, hTotal, alpha=0.1, method='beta') ax1.errorbar(binCenters, chEff, yerr=[chEff - ci_low, ci_upp - chEff], fmt='o', capsize=5) ax1.set_title('T/E Efficiency (ch {})'.format(ch)) ax1.set_ylabel('Efficiency') ax1.set_xlabel('Energy (keV)') fig1.savefig('{}/plots/CutEfficiencies/Eff_DS0_ToE_ch{}.png'.format( os.environ['LATDIR'], ch)) g1.set(yscale='log') g1.savefig('{}/plots/CutEfficiencies/DS0_ToE_Spectrum.png'.format( os.environ['LATDIR']))
def plotTrigEff(): """ Plot the noise gaussian, trigger crossing gaussian, and the efficiency function. """ f = np.load("../data/trapOutput.npz") trapOutput, eTrapTS = f['arr_0'], f['arr_1'] sampNoise, sampTrig = [], [] for eTrap in trapOutput: idx = np.where(eTrap != 0) if eTrapTS[idx][0] != 9800: print("wtffff, return") return hitADC = np.amax(eTrap) if -1 < hitADC < 10: sampTrig.append(eTrap[idx][8]) if hitADC > 50: sampNoise.append(eTrap[idx][0]) fig = plt.figure(figsize=(9, 5)) p1 = plt.subplot(121) p2 = plt.subplot(122) x, hNoise = wl.GetHisto(sampNoise, -1, 2, 0.01) x, hTrig = wl.GetHisto(sampTrig, -1, 2, 0.01) p1.plot(x, hNoise, 'b', ls='steps', label="Noise Sample") p1.plot(x, hTrig, 'r', ls='steps', label="Trigger Sample") xF = np.arange(-1, 2, 0.01) pNoise, _ = curve_fit(wl.gauss_function, x, hNoise, p0=[1, np.mean(sampNoise), np.std(sampNoise)]) fitSig = pNoise[2] p1.plot(xF, wl.gauss_function(xF, *pNoise), '-m', alpha=0.7, label='Noise, %s = %.2f' % (r'$\sigma$', fitSig)) pTrig, _ = curve_fit(wl.gauss_function, x, hTrig, p0=[1, np.mean(sampTrig), np.std(sampTrig)]) fitMu = pTrig[1] p1.plot(xF, wl.gauss_function(xF, *pTrig), '-k', alpha=0.5, label='Trigger, %s = %.2f' % (r'$\mu$', fitMu)) p1.set_xlabel("Trap Output (ADC)", ha='right', x=1) p1.set_ylabel("Counts", ha='right', y=1) p1.legend(loc=2) xE = np.arange(0, 4, 0.01) p2.plot(xE, effFunc(xE, pTrig[1], pNoise[2]), '-b') p2.axvline(fitMu, color="k", alpha=0.5) p2.set_xlabel("Energy (ADC, uncalibrated)", ha='right', x=1) p2.set_ylabel("Efficiency", ha='right', y=1) # plt.show() plt.savefig("../plots/trig-effic.pdf")
def plot_ext_pulser(): """ The ext pulser data doesn't have the same centroid as the physics data since it wasn't tuned quite right. So we find the centroid of a higher-E set for each channel and plot the other ones relative to that. """ ds, cIdx, bIdx, sIdx = 0, 33, 75, 0 # runs 6887-6963, closest to this one # calDB = db.TinyDB('./calDB.json') # pars = db.Query() # fsD = dsi.getDBRecord("fitSlo_%s_idx%d_m2s238" % ("ds0_m1", cIdx), False, calDB, pars) # thD = dsi.getDBRecord("thresh_ds%d_bkg%d_sub%d" % (ds, bIdx, sIdx), False, calDB, pars) f = np.load("./data/lat-extPulser.npz") extData = f['arr_0'].item() # {run: [pIdx, runTime, extChan, hitE, fSlo]} # get centroids # for run in extData: # ch = extData[run][2] # muE = np.mean(extData[run][3]) # stdE = np.std(extData[run][3]) # muFS = np.mean(extData[run][4]) # stdFS = np.std(extData[run][4]) # print("run %d ch %d E %.2f pm %.2f FS %.2f pm %.2f" % (run, ch, muE, stdE, muFS, stdFS)) # run 7236 ch 624 E 54.78 pm 0.14 FS 74.80 pm 1.41 # run 7249 ch 688 E 46.83 pm 0.11 FS 67.14 pm 1.81 # run 7220 ch 674 E 71.53 pm 1.30 FS 67.56 pm 95.30 # runMap = {7236:624, 7249:688, 7220:674} # cent = {} # for run in extData: # if run not in runMap: continue # ch = extData[run][2] # fLo, fHi, fpb = 50, 100, 0.5 # x, hist = wl.GetHisto(extData[run][4], fLo, fHi, fpb) # fMax = x[np.argmax(hist)] # cent[ch] = fMax # # plt.plot(x, hist, ls='steps') # # plt.axvline(fMax, c='r') # # plt.show() # this is the result of the above block centMap = {624: 74.75, 688: 67.25, 674: 65.75} fig = plt.figure(figsize=(8, 6)) p1 = plt.subplot(211) p2 = plt.subplot(212) # hitE, fSlo = [], [] cols = {624: 'r', 688: 'g', 674: 'b'} for run in extData: ch = extData[run][2] hitE = extData[run][3] # fSlo = extData[run][4] # unshifted fSlo = [fs - centMap[ch] for fs in extData[run][4]] # shifted p1.plot(hitE, fSlo, '.', c=cols[ch], ms=0.5, alpha=0.7) fLo, fHi, fpb = -50, 200, 2 x, hist = wl.GetHisto(fSlo, fLo, fHi, fpb) fMax = x[np.argmax(hist)] muE = np.mean(hitE) p2.plot(muE, fMax, ".", c=cols[ch], ms=10) for ch in cols: cpd = det.getChanCPD(ds, ch) p1.plot(np.nan, np.nan, '.', c=cols[ch], label="C%sP%sD%s" % (cpd[0], cpd[1], cpd[2])) p2.plot(np.nan, np.nan, '.', c=cols[ch], label="C%sP%sD%s" % (cpd[0], cpd[1], cpd[2])) p1.set_ylim(-100, 150) # shifted # p1.set_ylim(0, 200) # unshifted p1.set_xlim(0, 20) p2.set_xlim(0, 20) p2.legend() p2.set_xlabel("Energy (keV)", ha='right', x=1) p2.set_ylabel("fitSlo Centroid", ha='right', y=1) p1.set_ylabel("fitSlo", ha='right', y=1) plt.tight_layout() # plt.show() plt.savefig("./plots/lat-extPulser-centroid.pdf")
def combineSpectra(): from ROOT import TChain, TFile, TTree # this makes a combined enr/nat spectrum for all these combinations and energy ranges specList = [[[0, 1, 2, 3, 4, "5A", "5B", "5C", 6], [0, 20, 0.1]], [[0, 1, 2, 3, 4, "5A", "5B", "5C", 6], [0, 50, 0.1]], [[1, 2, 3, 4, "5A", "5B", "5C", 6], [0, 20, 0.1]], [[1, 2, 3, 4, "5A", "5B", "5C", 6], [0, 50, 0.1]], [[1, 2, 3, 4, "5B", "5C", 6], [0, 20, 0.1]], [[1, 2, 3, 4, "5B", "5C", 6], [0, 50, 0.1]]] for spec in specList: dsList = spec[0] xLo, xHi, xpb = spec[1] plotName = "./plots/lat3-ds-e%d-" % pctTot for ds in dsList: plotName += str(ds) plotName += "-%.1fkev.pdf" % xHi # cType = "fr" # before burst cut cType = "frb%d" % pctTot # after burst cut <---- use this one # cType = "frb2" # after pass 2 burst cut tt = TChain("skimTree") for ds in dsList: dsNum = int(ds[0]) if isinstance(ds, str) else ds nBkg = bkg.dsMap()[dsNum] bLo, bHi = 0, nBkg if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 fList = [ "%s/bkg/cut/%s/%s_ds%d_%d_*.root" % (dsi.dataDir, cType, cType, dsNum, bIdx) for bIdx in range(bLo, bHi + 1) ] for f in fList: tt.Add(f) fig = plt.figure(figsize=(8, 7)) p0 = plt.subplot(211) p1 = plt.subplot(212) tCut = "!isEnr" n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hNat = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p0.plot(x, hNat, lw=2, ls='steps', c='b', label='Natural') p0.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p0.axvline(2., c='m', lw=2, alpha=0.5, label="2.0 keV") p0.set_ylabel("Counts/%.1f keV" % xpb, ha='right', y=1) p0.legend() tCut = "isEnr" n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hEnr = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hA = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p1.plot(x, hEnr, lw=2, ls='steps', c='b', label='Enriched') p1.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p1.axvline(2., c='m', lw=2, alpha=0.5, label="2.0 keV") p1.set_xlabel("Energy (keV)", ha='right', x=1) p1.legend() plt.tight_layout() # plt.show() plt.savefig(plotName) tt.Reset()
def plotSpecBeforeAfter(): from ROOT import TChain dsList = [0, 1, 2, 3, 4, "5A", "5B", "5C"] # dsList = ["5C"] for ds in dsList: tB = TChain("skimTree") # before tA = TChain("skimTree") # after # for ds in dsList: dsNum = int(ds[0]) if isinstance(ds, str) else ds nBkg = bkg.dsMap()[dsNum] bLo, bHi = 0, nBkg if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 fB = [ "%s/bkg/cut/fr/fr_ds%d_%d_*.root" % (dsi.dataDir, dsNum, bIdx) for bIdx in range(bLo, bHi + 1) ] for f in fB: tB.Add(f) fA = [ "%s/bkg/cut/frc/frc_ds%d_%d_*.root" % (dsi.dataDir, dsNum, bIdx) for bIdx in range(bLo, bHi + 1) ] for f in fA: tA.Add(f) print("before", tB.GetEntries(), "after", tA.GetEntries()) xLo, xHi, xpb = 0, 20, 0.1 fig = plt.figure(figsize=(8, 7)) p0 = plt.subplot(211) p1 = plt.subplot(212) tCut = "!isEnr" n = tB.Draw("trapENFCal", tCut, "goff") hitE = tB.GetV1() hitE = [hitE[i] for i in range(n)] x, hB = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) n = tA.Draw("trapENFCal", tCut, "goff") hitE = tA.GetV1() hitE = [hitE[i] for i in range(n)] x, hA = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p0.semilogy(x, hB, lw=2, ls='steps', c='r', label='Natural, Before') p0.semilogy(x, hA, lw=2, ls='steps', c='b', label='Natural, After') p0.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p0.set_ylabel("Counts", ha='right', y=1) p0.legend() tCut = "isEnr" n = tB.Draw("trapENFCal", tCut, "goff") hitE = tB.GetV1() hitE = [hitE[i] for i in range(n)] x, hB = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) n = tA.Draw("trapENFCal", tCut, "goff") hitE = tA.GetV1() hitE = [hitE[i] for i in range(n)] x, hA = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p1.semilogy(x, hB, lw=2, ls='steps', c='r', label='Enriched, Before') p1.semilogy(x, hA, lw=2, ls='steps', c='b', label='Enriched, After') p1.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p1.set_xlabel("Energy (keV)", ha='right', x=1) p1.legend() plt.tight_layout() # plt.show() plt.savefig("../plots/cs4-comp-DS%s.pdf" % ds) tB.Reset() tA.Reset()
def plotFit(): from ROOT import TFile tf1 = TFile("./data/fitWorkspace.root") fitWorkspace = tf1.Get("fitWorkspace") fitResult = fitWorkspace.allGenericObjects().front() # -- print fit results -- print("-- spec-fit RESULTS -- ") # print("%-10s = %.3f" % ("chiSq",chiSquare)) fitValsFinal = getRooArgDict( fitResult.floatParsFinal() ) bgr = {b:{} for b in bkgModel} # results for name in sorted(fitValsFinal): # find the part of the model this corresponds to for b in bkgModel: if b in name: break fitVal = fitValsFinal[name] error = fitWorkspace.var(name).getError() if "amp" in name: print("%-10s = best %-7.3f error %.3f (w/o profile)" % (name, fitVal, error)) bgr[b]["amp"] = [fitVal, error] elif "mu" in name: # compare the energy offset pkName = name[3:] pct = 100*(1 - fitVal/pkList[pkName]) print("%-10s : fit %-6.3f lit %-6.3f (%.3f%%)" % (name, fitVal, pkList[pkName], pct)) bgr[b]["mu"] = [fitVal, error] elif "sig" in name: # compare the sigma difference pkName = name[4:] pct = 100*(1 - fitVal/getSigma(pkList[pkName])) print("%-10s : fit %-6.3f func %-6.3f (%.3f%%)" % (name, fitVal, getSigma(pkList[pkName]), pct)) bgr[b]["sig"] = [fitVal, error] elif "bkg" in name: print("%s = %.4f" % (name, fitVal)) bgr[b]["bkg"] = [fitVal, error] for b in bgr: print(b, bgr[b]) tf2 = TFile("./data/latDS%s.root" % ''.join([str(d) for d in dsList])) tt = tf2.Get("skimTree") tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hData = wl.GetHisto(hitE, eLo, eHi, epb) # plt.plot(x, hData, ls='steps', c='b') # normal histo hErr = np.asarray([np.sqrt(h) for h in hData]) # statistical error plt.errorbar(x, hData, yerr=hErr, c='k', ms=10, linewidth=0.8, fmt='.', capsize=2) # pretty convincing rooplot fake # plot tritium f = np.load("./data/scaledPDFs.npz") pdfRaw, pdfNorm, pdfEff, pdfEffN = f['arr_0'].item(), f['arr_1'].item(), f['arr_2'].item(), f['arr_3'].item() # xn, hn, xbn = pdfNorm["trit"] xen, hen, xben = pdfEffN["trit"] henc = getEffCorr(xen, hen, inv=True) # plt.plot(xn, hn, ls='steps', c='r', lw=3, label="Tritium, norm. PDF") # plt.plot(xen, hen * bgr["trit"]["amp"][0] * 4, ls='steps', c='b', lw=3, label="w/ normalized efficiency correction") plt.plot(xen, henc * bgr["trit"]["amp"][0], ls='steps', c='b', lw=3, label="w/ normalized efficiency correction") # plt.plot(xen, henc, ls='steps', c='g', lw=2, label="Final") plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Events / %.1f keV" % epb, ha='right', y=1) plt.xlim(eLo, eHi) plt.tight_layout() plt.show()
def scanRuns(ds, key, mod, cIdx): from ROOT import TFile, TTree # load file and channel list fileList = [] calRuns = cal.GetCalList(key,cIdx) for run in calRuns: latList = dsi.getSplitList("%s/latSkimDS%d_run%d*" % (dsi.calLatDir, ds, run), run) tmpList = [f for idx, f in sorted(latList.items())] fileList.extend(tmpList) chList = det.getGoodChanList(ds) print("Scanning DS:%d calIdx %d mod %d key %s nFiles:%d" % (ds, cIdx, mod, key, len(fileList)), time.strftime('%X %x %Z')) outFile = "%s/eff_%s_c%d.npz" % (dsi.effDir, key, cIdx) print("Saving output in:",outFile) # declare the output stuff evtIdx, evtSumET, evtHitE, evtChans, evtSlo, evtRise = [], [], [], [], [], [] thrCal = {ch:[] for ch in chList} fLo, fHi, fpb = -200, 400, 1 nbf = int((fHi-fLo)/fpb)+1 fSloSpec = {ch:[np.zeros(nbf) for i in range(3)] for ch in chList} # 0-10, 10-200, 236-240 # loop over LAT cal files scanStart = time.time() prevRun = 0 evtCtr, totCtr, totRunTime = 0, 0, 0 for iF, f in enumerate(fileList): print("%d/%d %s" % (iF, len(fileList), f)) tf = TFile(f) tt = tf.Get("skimTree") # histogram these for each file (and then add to total) fs10 = {ch:[] for ch in chList} fs200 = {ch:[] for ch in chList} fs238 = {ch:[] for ch in chList} # increment the run time and fill the output dict of thresholds tt.GetEntry(0) run = tt.run if run!=prevRun: start = tt.startTime_s stop = tt.stopTime_s runTime = stop-start if runTime < 0 or runTime > 9999: print("run time error, run",run,"start",start,"stop") else: totRunTime += runTime # find thresholds for this run, # to calculate sumET and mHT in the loop. # save them into the output dict (so we can compare w/ DB later). n = tt.Draw("channel:threshKeV:threshSigma","","goff") chan, thrM, thrS = tt.GetV1(), tt.GetV2(), tt.GetV3() tmpThresh = {} for i in range(n): if chan[i] not in chList: continue if chan[i] in tmpThresh.keys(): continue if thrM[i] < 9999: thrK = thrM[i] + 3*thrS[i] tmpThresh[chan[i]] = [run,thrM[i],thrS[i],thrK] for ch in chList: if ch not in tmpThresh.keys(): tmpThresh[ch] = [-1,-1,-1,-1] # fill the output dict for ch in tmpThresh: thrCal[ch].append(tmpThresh[ch]) # [run, thrM, thrS, thrK] prevRun = run # continue # loop over tree for iE in range(tt.GetEntries()): tt.GetEntry(iE) if tt.EventDC1Bits != 0: continue totCtr += 1 n = tt.channel.size() chTmp = np.asarray([tt.channel.at(i) for i in range(n)]) idxRaw = [i for i in range(tt.channel.size()) if tt.channel.at(i) in chList] hitERaw = np.asarray([tt.trapENFCal.at(i) for i in idxRaw]) # get indexes of hits above threshold (use thresholds from THIS CAL RUN) idxList = [i for i in range(tt.channel.size()) if tt.channel.at(i) in chList and tt.trapENFCal.at(i) > tmpThresh[tt.channel.at(i)][3] and 0.7 < tt.trapENFCal.at(i) < 9999 ] hitE = np.asarray([tt.trapENFCal.at(i) for i in idxList]) # calculate mHT and sumET mHT, sumET = len(hitE), sum(hitE) # save fitSlo data for 0-10 and 10-200 kev ranges for each channel for i in idxList: en = tt.trapENFCal.at(i) ch = tt.channel.at(i) fs = tt.fitSlo.at(i) if fLo < fs < fHi: if 0 < en < 10: fs10[ch].append(fs) if 10 < en < 200: fs200[ch].append(fs) if 236 < en < 240: fs238[ch].append(fs) # Save m2s238 events to output, skip everything else if mHT!=2: continue if not 237.28 < sumET < 239.46: continue hitChans = np.asarray([tt.channel.at(i) for i in idxList]) hitSlo = np.asarray([tt.fitSlo.at(i) for i in idxList]) hitRise = np.asarray([tt.riseNoise.at(i) for i in idxList]) evtIdx.append([run,iE]) evtSumET.append(sumET) evtHitE.append(hitE) evtChans.append(hitChans) evtSlo.append(hitSlo) evtRise.append(hitRise) evtCtr += 1 # fill the fitSlo histograms w/ the events from this file for ch in chList: x, h1 = wl.GetHisto(fs10[ch],fLo,fHi,fpb) x, h2 = wl.GetHisto(fs200[ch],fLo,fHi,fpb) x, h3 = wl.GetHisto(fs238[ch],fLo,fHi,fpb) fSloSpec[ch][0] = np.sum([fSloSpec[ch][0], h1], axis=0) fSloSpec[ch][1] = np.sum([fSloSpec[ch][1], h2], axis=0) fSloSpec[ch][2] = np.sum([fSloSpec[ch][2], h3], axis=0) # n1 = np.sum(fSloSpec[ch][0]) # n2 = np.sum(fSloSpec[ch][1]) # n3 = np.sum(fSloSpec[ch][2]) # print("ch:%d n10 %d n200 %d n238 %d" % (ch, n1, n2, n3)) # get average threshold for each channel in this file list thrFinal = {chan:[] for chan in thrCal} for chan in thrCal: thrVals = [] for iT in range(len(thrCal[chan])): run, thrM, thrS, thrK = thrCal[chan][iT] # print("%d %d %.3f %.3f %.3f" % (chan,run,thrM,thrS,thrK)) if thrK > -1: thrVals.append(thrK) thrVals = np.asarray(thrVals) thrAvg = np.mean(thrVals) thrDev = np.std(thrVals) # print("%d %.3f %.3f" % (chan, thrAvg, thrDev)) thrFinal[chan] = [thrAvg,thrDev] # print to screen the final thresholds, stdev, and an error message if necessary print("Detector Thresholds:") for chan in sorted(thrFinal): thKeV = thrFinal[chan][0] thE = thrFinal[chan][1] errString = "" if thE/thKeV > 0.5: errString = ">50pct error: thE/thKeV=%.2f" % (thE/thKeV) if thKeV > 2: errString = ">2kev" print("%d %.3f %.3f %s" % (chan,thKeV,thE,errString)) # save output np.savez(outFile, evtIdx, evtSumET, evtHitE, evtChans, thrCal, thrFinal, evtCtr, totCtr, totRunTime, fSloSpec, x, evtSlo, evtRise) # output stats print("Done:",time.strftime('%X %x %Z'),", %.2f sec/file." % ((time.time()-scanStart)/len(fileList))) print(" m2s238 evts:",evtCtr, "total evts:",totCtr, "runTime:",totRunTime)
def runFit(): from ROOT import TFile, TH1D tf = TFile("../data/latDS%s.root" % ''.join([str(d) for d in dsList])) tt = tf.Get("skimTree") tCut = "isEnr==1" if enr is True else "isEnr==0" hitE = ROOT.RooRealVar("trapENFCal", "Energy", eLo, eHi, "keV") hEnr = ROOT.RooRealVar("isEnr", "isEnr", 0, 1, "") # hitW = ROOT.RooRealVar("weight", "weight", 1, 1000, "") fData = ROOT.RooDataSet("data", "data", tt, ROOT.RooArgSet(hitE, hEnr), tCut) # # fData = ROOT.RooDataSet("data", "data", tt, ROOT.RooArgSet(hitE, hEnr, hitW), "", "weight") nData = fData.numEntries() tf2 = TFile("../data/specPDFs.root") trVal = 1000 trTH1D = tf2.Get("h5") trNum = ROOT.RooRealVar("amp-trit", "amp-trit", trVal) trDataHist = ROOT.RooDataHist("tr", "tr", ROOT.RooArgList(hitE), RF.Import(trTH1D)) hitE.setRange(eLo, eHi) trPdf = ROOT.RooHistPdf("trPdf", "trPdf", ROOT.RooArgSet(hitE), trDataHist, 0) trExt = ROOT.RooExtendPdf("ext-trit", "ext-trit", trPdf, trNum) # rooplot before fitting fSpec = hitE.frame(RF.Range(eLo, eHi), RF.Bins(int((eHi - eLo) / epb))) # wouter's note: DON'T DELETE # "the default behavior is when you plot a p.d.f. on an empty frame it is # plotted with unit normalization. When you plot it on a frame with data in # it, it will normalize to the number of events in that dataset." fData.plotOn(fSpec) # trExt.plotOn(fSpec) # default normalization: 1 if no data, nData if data # trExt.plotOn(fSpec, RF.Normalization(1, ROOT.RooAbsReal.Relative)) # this is relative to total counts, don't use it # trExt.plotOn(fSpec, RF.LineColor(ROOT.kBlue), RF.Normalization(trVal/epb, ROOT.RooAbsReal.NumEvent)) # equivalent to the Raw way # use this one (you have to divide by epb in numpy when you plot, but not when you integrate) trExt.plotOn(fSpec, RF.LineColor(ROOT.kMagenta), RF.Normalization(trVal, ROOT.RooAbsReal.Raw)) from ROOT import TCanvas c = TCanvas("c", "c", 1400, 1000) fSpec.SetTitle("") fSpec.Draw() c.Print("../plots/spectrum-before.pdf") # replicate the rooplot with numpy (no weights) tCut = "isEnr" if enr else "!isEnr" tCut += " && trapENFCal >= %.1f && trapENFCal <= %.1f" % (eLo, eHi) n = tt.Draw("trapENFCal", tCut, "goff") trapE = tt.GetV1() trapE = [trapE[i] for i in range(n)] x, hData = wl.GetHisto(trapE, eLo, eHi, epb) # plt.plot(x, hData, ls='steps', c='b') # normal histo hErr = np.asarray([np.sqrt(h) for h in hData]) # statistical error plt.errorbar(x, hData, yerr=hErr, c='k', ms=10, linewidth=0.8, fmt='.', capsize=2, zorder=1) # pretty convincing rooplot fake x, y, xpb = wl.npTH1D(trTH1D) # yn = np.divide(y, np.sum(y)) # plt.step(x, np.cumsum(yn)) # yn = np.divide(y, np.sum(y[np.where((x >= eLo) & (x <= eHi))] * xpb)) < -- this makes the norm != 1 # yn = np.divide(y, np.sum(y[np.where((x >= eLo) & (x <= eHi))])) # < -- this one works w/ no data # yn = np.multiply(yn, nData) # <-- this one works w/ data # plt.plot(x, yn, ls='steps', c='b', lw=2, label="tritium, nData %d sum %d max %.1f" % (nData, int(np.sum(yn)), np.amax(yn))) # NOTE: to plot to a set number of counts, divide by epb. to integrate, don't. plt.plot(x1, y1 * trVal / epb, ls='steps', c='m', lw=2, label="trit init value: %d int: %d" % (trVal, np.sum(y1 * trVal))) plt.xlabel("Energy (keV)", ha='right', x=1) plt.ylabel("Counts / %.1f keV" % epb, ha='right', y=1) plt.legend(loc=1) plt.tight_layout() # plt.show() plt.savefig("../plots/sf3-mplplot.pdf")
def plotOffset(): ds, run = 1, 13387 det = dsi.DetInfo() f = np.load("../data/tOff-%d.npz" % run) chDiff = f['arr_0'].item() chNoPair = f['arr_1'].item() tLo, tHi, tpb = -5000, 500, 10 xTot, hTot = wl.GetHisto([], tLo, tHi, tpb) # remember, diffs are HG - LG # ==== 1. plot tOffset_HG - tOffset_LG ==== cmap = plt.cm.get_cmap('jet', len(chDiff) + 1) for i, ch in enumerate(chDiff): # print(ch, len(chDiff[ch])) x, hDiff = wl.GetHisto(chDiff[ch], tLo, tHi, tpb) hTot = np.add(hTot, hDiff) cpd = det.getChanCPD(ds, ch) plt.semilogy(x, hDiff, ls='steps', lw=2, c=cmap(i), alpha=0.5, label="C%sP%sD%s" % (cpd[0], cpd[1], cpd[2])) p = 99.9 tmp = np.cumsum(hTot) / np.sum(hTot) * 100 idx = np.where(tmp > p) x99 = xTot[idx][0] plt.plot(xTot, hTot, "k", ls='steps', label="Total, run %d" % run) plt.axvline(x99, c='r', lw=5, label="99.9%% value: %d" % x99) plt.legend(loc=2, ncol=3, fontsize=12) plt.xlabel("HG-LG tOffset (10ns)", ha='right', x=1) plt.ylabel("Counts", ha='right', y=1) plt.tight_layout() # plt.show() plt.savefig("../plots/tOffset-run%d.pdf" % run) # ==== 2. plot tOffset_HG of any HG hits w/o a paired LG hit ==== plt.close() tLo, tHi, tpb = 0, 10000, 50 xTot, hTot = wl.GetHisto([], tLo, tHi, tpb) for i, ch in enumerate(chNoPair): cpd = det.getChanCPD(ds, ch) if cpd in ['173', '112']: continue print(ch, cpd) x, hNoPair = wl.GetHisto(chNoPair[ch], tLo, tHi, tpb) hTot = np.add(hTot, hNoPair) plt.semilogy(x, hNoPair, ls='steps', lw=2, c=cmap(i), alpha=0.7, label="C%sP%sD%s" % (cpd[0], cpd[1], cpd[2])) pctTot = 99 tmp = np.cumsum(hTot) / np.sum(hTot) * 100 idx = np.where(tmp > pctTot) xPctVal = xTot[idx][0] plt.plot(xTot, hTot, "k", ls='steps', label="Total, run %d" % run) plt.axvline(xPctVal, c='r', lw=5, label="%d%% value: %d" % (pctTot, xPctVal)) plt.legend(loc=1, ncol=3, fontsize=10) plt.xlabel("Unpaired tOffset_HG (10ns)", ha='right', x=1) plt.ylabel("Counts", ha='right', y=1) plt.tight_layout() # plt.show() plt.savefig("../plots/tOffset-unpaired-run%d.pdf" % run)
def plotStats(): # load data from testStats f = np.load('../plots/slo-m2s238-test.npz') evtIdx, evtSumET, evtHitE, evtChans = f['arr_0'], f['arr_1'], f[ 'arr_2'], f['arr_3'] thrCal = f['arr_4'].item() evtCtr, totCtr, runTime = f['arr_5'], f['arr_6'], f['arr_7'] # load threshKeV values from bkg/auto-thrsh/db calDB = db.TinyDB("%s/calDB-v2.json" % dsi.latSWDir) pars = db.Query() threshDB = dsi.getDBRecord("thresh_ds1_bkg35_sub0", calDB=calDB, pars=pars) # throw a threshold warning if any det is above 1 keV (and by how much) for ch in thrCal: thrChan = np.asarray([val[3] for val in thrCal[ch]]) thrMean, thrStd = np.mean(thrChan), np.std(thrChan) thrDB = threshDB[ch][0] + 3 * threshDB[ch][1] errString = "Above 1" if thrMean > 1.0 else "" # print("ch %d DB %.3f CAL %.3f keV (%.3f), nRuns %d %s" % (ch, thrDB, thrMean, thrStd, len(thrChan), errString)) # fill hit arrays hitE, chan = [], [] for iE in range(len(evtHitE)): hitE.extend(evtHitE[iE]) chan.extend(evtChans[iE]) # map channels chMap = list(sorted(set(chan))) chDict = {chMap[i]: i for i in range(len(chMap))} chan = [chDict[chan] for chan in chan] # -- plot 1 - hit E spectrum fig = plt.figure() xLo, xHi, xpb = 0, 250, 1 x, hE = wl.GetHisto(hitE, xLo, xHi, xpb) plt.plot(x, hE, ls='steps', lw=1.5, c='b', label='m=2,s=238 hits') plt.xlabel("Energy (keV)", ha='right', x=1.) plt.ylabel("Counts", ha='right', y=1.) plt.legend(loc=1) plt.savefig("../plots/slo-hitE-test.png") # -- plot 2 - counts per channel vs E (2d), low-E region plt.cla() xLo, xHi, xpb = 0.5, 5, 0.2 yLo, yHi = 0, len(chMap) nbx, nby = int((xHi - xLo) / xpb), len(chMap) h1, _, _ = np.histogram2d(hitE, chan, bins=[nbx, nby], range=[[xLo, xHi], [yLo, yHi]]) h1 = h1.T im1 = plt.imshow( h1, cmap='jet') #,aspect='auto')#),vmin=hMin,vmax=hMax)#,norm=LogNorm()) xticklabels = ["%.1f" % t for t in np.arange(0, 5.5, 0.5)] yticks = np.arange(0, len(chMap)) plt.xlabel("Energy (keV)", ha='right', x=1.) plt.gca().set_xticklabels(xticklabels) plt.ylabel("channel", ha='right', y=1.) plt.yticks(yticks) plt.gca().set_yticklabels(chMap, fontsize=12) # note: can control z axis limits w/ code in LAT/sandbox/sea-plot.py fig.colorbar(im1, ax=plt.gca(), fraction=len(chMap) / 941, pad=0.04) plt.tight_layout() plt.savefig("../plots/slo-fsVsHitE-test.png") # -- output: counts in each detector under 5 keV cLo, cHi, nbx = 0, len(chMap), len(chMap) x, hC = wl.GetHisto(chan, cLo, cHi, 1) hLow = [0] for idx, ch in enumerate(chMap): nTot = hC[idx + 1] # 0-250 kev nLow = np.sum(h1[idx, :]) # 0-5 keV hLow.append(nLow) nCPB = nLow / (xHi - xLo) / xpb # avg counts per bin, assume flat for now. rTot = nTot / runTime rLow = nLow / runTime rCPB = nCPB / nbx / runTime # counts/bin/runTime rt100Cts = (100 / rCPB) / 3600. if rCPB != 0 else -1 print( "rt %d ch %d rTot %.2f rLow %.4f rCPB %.4f / %.1f keV need RT:%d hrs" % (runTime, ch, rTot, rLow, rCPB, xpb, rt100Cts)) # -- plot 3 - counts per channel (1d), and a few different energy regions plt.cla() plt.bar(x - 0.5, hC, 0.95, color='b', label='all hits %d-%d' % (0, 250)) plt.bar(x - 0.5, hLow, 0.95, color='r', label='hits %d-%d' % (xLo, xHi)) plt.xlabel("channel", ha='right', x=1.) xticks = np.arange(0, len(chMap)) plt.xticks(xticks) plt.gca().set_xticklabels(chMap, fontsize=12, rotation=90) plt.ylabel("Counts, mHT=2, sumET=238 hits", ha='right', x=1.) plt.legend(loc=1) plt.savefig("../plots/slo-chans-test.png")
def compareSim(): # plt.close(fig) inDir = os.environ['LATDIR'] + '/data' dfSig = pd.read_hdf('{}/SimPSA_P42574A.h5'.format(inDir)) dfSig['Distance'] = dfSig['R'] * dfSig['R'] + dfSig['Z'] + dfSig['Z'] dfSig['fitSloShift'] = dfSig['fitSlo'] - 84.5 dfSig['trapENFCal'] = dfSig['Amp'] * 0.3959 dfCut = dfSig.loc[(dfSig['fitSlo'] > 3) & (dfSig['Amp'] > 2)] # dfCut = dfSig.loc[(dfSig['Amp'] < 14) & (dfSig['fitSlo'] > 2)] # g1 = sns.lmplot(x='Amp', y='fitSlo', data=dfCut, fit_reg=False, size=7, scatter_kws={'alpha':0.3}, legend_out=False) # g1.set(yscale='log') # plt.subplots_adjust(top=0.95) # g1.fig.suptitle('fitSlo vs Amplitude (Simulated Waveforms)') # g1.set_axis_labels('Amplitude (ADC)', 'fitSlo') # g2 = sns.FacetGrid(dfCut,size=7) # g2 = g2.map(plt.hist, 'fitSloShift', bins=np.linspace(-200,200,200), alpha=0.50) # g2.set(yscale='log') fig3, (ax3, ax4, ax5) = plt.subplots(nrows=3, figsize=(10, 7)) fLo, fHi, fpb = -100, 150, 2 centList, cutList = [], [] accList = [] diffList = [] eRangesList = [[1, 2], [2, 4], [4, 5], [5, 8]] for amp in np.unique(dfCut['trapENFCal']): # for idx, [emin, emax] in enumerate(eRangesList): dfCh = dfCut.loc[(dfCut['trapENFCal'] == amp)] # dfCh = dfCut.loc[(dfCut['trapENFCal'] >= emin) & (dfCut['trapENFCal'] <= emax)] fSlo = dfCh['fitSloShift'].values x, h = wl.GetHisto(fSlo, fLo, fHi, fpb, shift=False) fMax = x[np.argmax(h)] n90 = np.percentile(fSlo, 90.) # print(amp, fMax, n90) centList.append(fMax) cutList.append(n90) diffList.append(n90 - fMax) # Average the last 10 values cutVal = cutList[-1] for amp in np.unique(dfCut['trapENFCal']): dfCh = dfCut.loc[(dfCut['trapENFCal'] == amp)] fSlo = dfCh['fitSloShift'].values nKeep = len(np.where(fSlo < cutVal)[0]) accList.append(100. * nKeep / len(fSlo)) ax3.plot(np.unique(dfCut['trapENFCal']), cutList, 'o', color='r', label='90%') ax3.plot(np.unique(dfCut['trapENFCal']), centList, 'o', color='b', label='Centroid') ax3.set_title('fitSlo vs Energy') ax3.set_xlabel('trapENFCal (keV)') ax3.set_ylabel('fitSlo (shifted)') ax3.legend() ax4.plot(np.unique(dfCut['trapENFCal']), diffList, '-', color='b', label='Difference') ax4.set_ylabel('fitSlo difference') ax4.set_xlabel('trapENFCal (keV)') ax4.legend() ax5.plot(np.unique(dfCut['trapENFCal']), accList, '-', color='b', label='Fast Pulse Acceptance') ax5.set_ylabel('Acceptance (%)') ax5.set_xlabel('trapENFCal (keV)') ax5.set_ylim(0, 100) ax5.legend() # print(accList) print(np.unique(dfCut['trapENFCal']).tolist()) plt.tight_layout() plt.show()
def plotSpectraAfter(): from ROOT import TChain # dsList = [1,2,3,4,"5A","5B","5C"] dsList = [1, 2, 3, 4, "5B", "5C"] # dsList = [0] plotName = "../plots/cs4-spec-DS-14-5BC.pdf" xLo, xHi, xpb = 0, 20, 0.2 # xLo, xHi, xpb = 0, 50, 0.1 # for ds in dsList: tt = TChain("skimTree") for ds in dsList: # indent this block dsNum = int(ds[0]) if isinstance(ds, str) else ds nBkg = bkg.dsMap()[dsNum] bLo, bHi = 0, nBkg if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 fList = [ "%s/bkg/cut/frc/frc_ds%d_%d_*.root" % (dsi.dataDir, dsNum, bIdx) for bIdx in range(bLo, bHi + 1) ] for f in fList: tt.Add(f) fig = plt.figure(figsize=(8, 7)) p0 = plt.subplot(211) p1 = plt.subplot(212) tCut = "!isEnr" n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hNat = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p0.plot(x, hNat, lw=2, ls='steps', c='b', label='Natural') p0.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p0.set_ylabel("Counts", ha='right', y=1) p0.legend() tCut = "isEnr" n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hEnr = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hA = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p1.plot(x, hEnr, lw=2, ls='steps', c='b', label='Enriched') p1.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p1.set_xlabel("Energy (keV)", ha='right', x=1) p1.legend() plt.tight_layout() # plt.show() plt.savefig(plotName) tt.Reset()
def plotSpectraAfter(): from ROOT import TChain, TFile, TTree from matplotlib import colors dsList = [0, 1, 2, 3, 4, "5A", "5B", "5C", 6] # dsList = ["5A","5B","5C"] # cType = "fr" # before burst cut cType = "frb%d" % pctTot # after burst cut <-- use this one # cType = "frb2" # after pass 2 burst cut for ds in dsList: plotName1 = "./plots/lat3-%s-DS%s-spec.pdf" % (cType, ds) plotName2 = "./plots/lat3-%s-DS%s-vsch.pdf" % (cType, ds) plotName3 = "./plots/lat3-%s-DS%s-rvsc.pdf" % (cType, ds) tt = TChain("skimTree") # for ds in dsList: # indent this block dsNum = int(ds[0]) if isinstance(ds, str) else ds nBkg = bkg.dsMap()[dsNum] bLo, bHi = 0, nBkg if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 fList = [ "%s/bkg/cut/%s/%s_ds%d_%d_*.root" % (dsi.dataDir, cType, cType, dsNum, bIdx) for bIdx in range(bLo, bHi + 1) ] for f in fList: tt.Add(f) fig = plt.figure(figsize=(8, 7)) p0 = plt.subplot(211) p1 = plt.subplot(212) eSpec = True eVsCh = True rVsCh = True # ====================== 1. energy spectra ====================== if eSpec: xLo, xHi, xpb = 0, 20, 0.1 # xLo, xHi, xpb = 0, 50, 0.1 tCut = "!isEnr" n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hNat = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p0.plot(x, hNat, lw=2, ls='steps', c='b', label='Natural') p0.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p0.set_ylabel("Counts", ha='right', y=1) p0.legend() tCut = "isEnr" n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hEnr = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) n = tt.Draw("trapENFCal", tCut, "goff") hitE = tt.GetV1() hitE = [hitE[i] for i in range(n)] x, hA = wl.GetHisto(hitE, xLo, xHi, xpb, shift=False) p1.plot(x, hEnr, lw=2, ls='steps', c='b', label='Enriched') p1.axvline(1., c='g', lw=2, alpha=0.5, label="1.0 keV") p1.set_xlabel("Energy (keV)", ha='right', x=1) p1.legend() plt.tight_layout() # plt.show() plt.savefig(plotName1) # ====================== 2. energy vs channel counts (2d) ====================== if eVsCh: dsTmp = int(ds[0]) if isinstance( ds, str) else ds # this is used for getGoodChanList chList = det.getGoodChanList(dsTmp) p0.cla() tCut = "!isEnr" natList = [ c for c in chList if det.getDetIDChan(dsTmp, c) < 100000 ] # natural chLabels = [ "%s/%s" % (det.getChanCPD(dsTmp, ch), ch) for ch in natList ] chMap = {natList[i]: i for i in range(len(natList))} xLo, xHi, xpb = 0, 20., 0.2 yLo, yHi = 0, len(natList) nbx, nby = int((xHi - xLo) / xpb), len(natList) n = tt.Draw("trapENFCal:channel", tCut, "goff") hitE, hitC = tt.GetV1(), tt.GetV2() hitE = [hitE[i] for i in range(n)] hitC = [chMap[hitC[i]] for i in range(n)] p0.hist2d(hitE, hitC, bins=[nbx, nby], range=[[xLo, xHi], [yLo, yHi]], cmap='jet') # p0.set_xlabel("Energy (keV)", ha='right', x=1.) p0.set_xticks(np.arange(xLo, xHi + 1, 1.0)) p0.set_ylabel("cpd/channel", ha='right', y=1.) p0.set_yticks(np.arange(0, len(natList)) + 0.5) p0.set_yticklabels(chLabels, fontsize=8) p1.cla() tCut = "isEnr" enrList = [ c for c in chList if det.getDetIDChan(dsTmp, c) > 100000 ] # enriched chLabels = [ "%s/%s" % (det.getChanCPD(dsTmp, ch), ch) for ch in enrList ] chMap = {enrList[i]: i for i in range(len(enrList))} xLo, xHi, xpb = 0, 20., 0.2 yLo, yHi = 0, len(enrList) nbx, nby = int((xHi - xLo) / xpb), len(enrList) n = tt.Draw("trapENFCal:channel", tCut, "goff") hitE, hitC = tt.GetV1(), tt.GetV2() hitE = [hitE[i] for i in range(n)] hitC = [chMap[hitC[i]] for i in range(n)] p1.hist2d(hitE, hitC, bins=[nbx, nby], range=[[xLo, xHi], [yLo, yHi]], cmap='jet') p1.set_xlabel("Energy (keV)", ha='right', x=1.) p1.set_xticks(np.arange(xLo, xHi + 1, 1.0)) # p1.set_ylabel("cpd/channel", ha='right', y=1.) p1.set_yticks(np.arange(0, len(enrList)) + 0.5) p1.set_yticklabels(chLabels, fontsize=8) plt.tight_layout() # plt.show() plt.savefig(plotName2) # ====================== 3. rate @ 0-5 kev, channel vs. bIdx (2d) ====================== if rVsCh: dsTmp = int(ds[0]) if isinstance( ds, str) else ds # this is used for getGoodChanList nBkg = bkg.dsMap()[dsNum] bLo, bHi = 0, nBkg if ds == "5A": bLo, bHi = 0, 79 if ds == "5B": bLo, bHi = 80, 112 if ds == "5C": bLo, bHi = 113, 121 chList = det.getGoodChanList(dsTmp) runRanges = bkg.getRanges(dsNum) tl = TFile("./data/ds_%s_livetime.root" % str(ds)) lt = tl.Get("dsTree") # calculate weights for each chan/bkgIdx expo = {} for bIdx in range(bLo, bHi + 1): livetime = {ch: 0 for ch in chList} rLo, rHi = runRanges[bIdx][0], runRanges[bIdx][-1] m = lt.Draw("run:channel:livetime", "run>=%d && run<=%d" % (rLo, rHi), 'goff') ltRun, ltChan, ltLive = lt.GetV1(), lt.GetV2(), lt.GetV3() for i in range(m): livetime[ltChan[i]] += ltLive[i] for ch in chList: cpd = det.getChanCPD(dsNum, ch) detID = det.getDetIDChan(dsNum, ch) aMass = det.allActiveMasses[detID] expo["%d/%d" % (ch, bIdx)] = livetime[ch] * aMass / 86400 / 1000 # expo["%d/%d" % (ch,bIdx)] = livetime[ch]*aMass/86400/1000 p0.cla() tCut = "!isEnr && trapENFCal >= %.1f && trapENFCal <= %.1f" % ( rateWin1[0], rateWin1[1]) chNat = [c for c in chList if det.getDetIDChan(dsTmp, c) < 100000] # natural chLabels = [ "%s/%s" % (det.getChanCPD(dsTmp, ch), ch) for ch in chNat ] chMap = {chNat[i]: i for i in range(len(chNat))} xLo, xHi, xpb = bLo, bHi + 1, 1 yLo, yHi = 0, len(chNat) nbx, nby = int((xHi - xLo) / xpb), len(chNat) n = tt.Draw("run:channel", tCut, "goff") hitR, hitC = tt.GetV1(), tt.GetV2() hitB = [bkg.GetBkgIdx(dsTmp, hitR[i]) for i in range(n)] hitCh = [hitC[i] for i in range(n) ] # raw channels, used in weighting function hitC = [chMap[hitC[i]] for i in range(n)] # mapped channels, used in plotting hitW = [ 1 / expo["%d/%d" % (hitCh[i], hitB[i])] / (rateWin1[1] - rateWin1[0]) for i in range(n) ] # h0,_,_,im0 = p0.hist2d(hitB, hitC, bins=[nbx, nby], range=[[xLo,xHi],[yLo,yHi]], cmap='jet') h0, _, _, im0 = p0.hist2d(hitB, hitC, weights=hitW, bins=[nbx, nby], range=[[xLo, xHi], [yLo, yHi]], cmap='jet') # p0.set_xlabel("bkgIdx, DS-%d" % ds, ha='right', x=1.) p0.set_xticks(np.arange(bLo, bHi, 5) + 0.5) p0.set_xticklabels(np.arange(bLo, bHi, 5)) p0.set_ylabel("cpd/channel", ha='right', y=1.) p0.set_yticks(np.arange(0, len(chNat)) + 0.5) p0.set_yticklabels(chLabels, fontsize=8) p1.cla() tCut = "isEnr && trapENFCal >= %.1f && trapENFCal <= %.1f" % ( rateWin1[0], rateWin1[1]) chEnr = [c for c in chList if det.getDetIDChan(dsTmp, c) > 100000] # enriched chLabels = [ "%s/%s" % (det.getChanCPD(dsTmp, ch), ch) for ch in chEnr ] chMap = {chEnr[i]: i for i in range(len(chEnr))} xLo, xHi, xpb = bLo, bHi + 1, 1 yLo, yHi = 0, len(chEnr) nbx, nby = int((xHi - xLo) / xpb), len(chEnr) n = tt.Draw("run:channel", tCut, "goff") hitR, hitC = tt.GetV1(), tt.GetV2() hitB = [bkg.GetBkgIdx(dsTmp, hitR[i]) for i in range(n)] hitCh = [hitC[i] for i in range(n) ] # raw channels, used in weighting function hitC = [chMap[hitC[i]] for i in range(n)] # mapped channels, used in plotting hitW = [ 1 / expo["%d/%d" % (hitCh[i], hitB[i])] / (rateWin1[1] - rateWin1[0]) for i in range(n) ] # h1,_,_,im1 = p1.hist2d(hitB, hitC, bins=[nbx, nby], range=[[xLo,xHi],[yLo,yHi]], cmap='jet') h1, _, _, im1 = p1.hist2d(hitB, hitC, weights=hitW, bins=[nbx, nby], range=[[xLo, xHi], [yLo, yHi]], cmap='jet') # DEBUG: print the rate for a channel # print(h1.shape) # idx, ch = 11, 690 # for i,v in enumerate(h1[:,idx]): # bIdx = i # rate = v # exp = expo["%d/%d" % (ch,bIdx)] # print("%d %.2f %.2f" % (bIdx, rate, exp)) # return p1.set_xlabel("bkgIdx, DS-%s" % ds, ha='right', x=1.) p1.set_xticks(np.arange(bLo, bHi, 5) + 0.5) p1.set_xticklabels(np.arange(bLo, bHi, 5)) # p1.set_ylabel("cpd/channel", ha='right', y=1.) p1.set_yticks(np.arange(0, len(chEnr)) + 0.5) p1.set_yticklabels(chLabels, fontsize=8) cb0 = fig.colorbar(im0, ax=p0) cb1 = fig.colorbar(im1, ax=p1) cb0.set_label('cts/kg/d/keV', ha='right', rotation=270, labelpad=20) plt.tight_layout() # plt.show() plt.savefig(plotName3) tt.Reset()