Esempio n. 1
0
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()
Esempio n. 2
0
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()
Esempio n. 3
0
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)
Esempio n. 4
0
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)
Esempio n. 5
0
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")
Esempio n. 6
0
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)
Esempio n. 7
0
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
Esempio n. 8
0
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")
Esempio n. 9
0
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)
Esempio n. 10
0
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()
Esempio n. 11
0
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()
Esempio n. 12
0
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)
Esempio n. 13
0
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()
Esempio n. 14
0
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)
Esempio n. 15
0
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']))
Esempio n. 16
0
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")
Esempio n. 17
0
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")
Esempio n. 18
0
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()
Esempio n. 19
0
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()
Esempio n. 20
0
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()
Esempio n. 21
0
File: lat2.py Progetto: gothman5/LAT
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)
Esempio n. 22
0
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")
Esempio n. 23
0
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)
Esempio n. 24
0
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")
Esempio n. 25
0
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()
Esempio n. 26
0
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()
Esempio n. 27
0
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()