Exemple #1
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")
Exemple #2
0
def MakeCutPlot(c,cal,var,eb,elo,ehi,vb,vlo,vhi,d2Cut,d1Cut,outPlot,fastMode):
    """ Creates a channel-specific energy calibration plot. """

    # Calculate cut vals (assumes plot range is correct)
    h1 = wl.H1D(cal,vb,vlo,vhi,var,d1Cut)
    h1Sum = h1.Integral()
    if h1Sum == 0:
        print "Error: Failed %s, histogram sum is 0 so cannot normalize, setting to [0,0,0,0,0]"%(var)
        return 0,0,0,0,0
    h1.Scale(1/h1Sum)
    try:
        cut99,cut95,cut01,cut05,cut90 = wl.GetIntegralPoints(h1)
    except:
        print "Error: Failed %s using cut %s, setting to [0,0,0,0,0]"%(var,d1Cut)
        return 0,0,0,0,0
    if fastMode:
        print "Returning fastMode output: ", cut99,cut95,cut01,cut05,cut90
        return cut99,cut95,cut01,cut05,cut90

    # Generate the plot for inspection.
    c.cd(2)
    gPad.SetLogy(0)
    h1.GetXaxis().SetRangeUser(cut01-abs(0.25*cut01), cut99 + abs(0.25*cut99) )
    h1.SetTitle("")
    h1.GetXaxis().SetTitle(var)
    h1.Draw("hist")

    c.cd(1)
    gPad.SetLogy(0)
    cal.Draw("%s:trapENFCal>>b(%d,%d,%d,%d,%.3E,%.3E)"%(var,eb+10,elo-5,ehi+5,vb,cut01-abs(0.25*cut01),cut99+abs(0.25*cut99)) ,d2Cut)

    l1, l2, l3 = TLine(), TLine(), TLine()
    l1.SetLineColor(ROOT.kGreen)
    l2.SetLineColor(ROOT.kRed)
    l3.SetLineColor(ROOT.kMagenta)

    l1.DrawLine(elo-5, cut99, ehi+5, cut99)
    l2.DrawLine(elo-5, cut95, ehi+5, cut95)
    l2.DrawLine(elo-5, cut05, ehi+5, cut05)
    l1.DrawLine(elo-5, cut01, ehi+5, cut01)

    c.cd(3)
    x_h1, y_h1 = wl.npTH1D(h1)
    int_h1 = wl.integFunc(y_h1)
    g2 = TGraph(len(x_h1), x_h1, int_h1)
    g2.GetXaxis().SetRangeUser(cut01-abs(0.3*cut01), cut99 + abs(0.3*cut99) )
    g2.SetTitle("")
    g2.GetXaxis().SetTitle(var)
    g2.GetYaxis().SetTitle("Percentile")
    g2.Draw("ACP")
    l1.DrawLine(cut99, 0, cut99, 1)
    l2.DrawLine(cut95, 0, cut95, 1)
    l1.DrawLine(cut01, 0, cut01, 1)
    l2.DrawLine(cut05, 0, cut05, 1)

    c.Print(outPlot)
    return cut99,cut95,cut01,cut05,cut90
Exemple #3
0
def sp_correction():

    from ROOT import TFile, TH1D

    tf = TFile("../data/lat-expo-efficiency-corr.root")
    surfPerc = tf.Get("surfPerc")

    xSp, ySp, xpb = wl.npTH1D(surfPerc)

    plt.plot(xSp, ySp, ls='steps')

    # plt.show()

    # brian's cal_det_pairs data directory
    "/global/projecta/projectdirs/majorana/users/bxyzhu/LATv2"
Exemple #4
0
def MakeCutPlot(c, cal, var, eb, elo, ehi, vb, vlo, vhi, d2Draw, d2Cut, d1Cut,
                outPlot, fastMode):
    """ Repeated code is the DEVIL.  Even if you have to pass in 1,000,000 arguments. """

    # Calculate cut vals (assumes plot range is correct)
    h1 = wl.H1D(cal, vb, vlo, vhi, var, d1Cut)
    h1Sum = h1.Integral()
    if h1Sum == 0:
        return 0, 0, 0, 0, 0
    h1.Scale(1 / h1Sum)
    cut99, cut95, cut01, cut05, cut90 = wl.GetIntegralPoints(h1)
    if fastMode:
        return cut99, cut95, cut01, cut05, cut90

    # Generate the plot for inspection.
    c.cd(2)
    gPad.SetLogy(0)
    h1.Draw("hist")

    c.cd(1)
    gPad.SetLogy(0)
    cal.Draw(d2Draw, d2Cut)

    l1, l2 = TLine(), TLine()
    l1.SetLineColor(ROOT.kGreen)
    l2.SetLineColor(ROOT.kRed)

    l1.DrawLine(elo, cut99, ehi, cut99)
    l2.DrawLine(elo, cut95, ehi, cut95)
    l2.DrawLine(elo, cut05, ehi, cut05)
    l1.DrawLine(elo, cut01, ehi, cut01)

    c.cd(3)
    x_h1, y_h1 = wl.npTH1D(h1)
    int_h1 = wl.integFunc(y_h1)
    g2 = TGraph(len(x_h1), x_h1, int_h1)
    g2.Draw("ACP")
    l1.DrawLine(cut99, 0, cut99, 1)
    l2.DrawLine(cut95, 0, cut95, 1)
    l1.DrawLine(cut01, 0, cut01, 1)
    l2.DrawLine(cut05, 0, cut05, 1)

    c.Print(outPlot)
    return cut99, cut95, cut01, cut05, cut90
Exemple #5
0
def getProfile(idx=None, update=False):
    from ROOT import TFile, TCanvas
    from ROOT import RooStats as RS

    f = TFile("%s/data/fitWorkspace.root" % dsi.latSWDir)
    fitWorkspace = f.Get("fitWorkspace")
    fData = fitWorkspace.allData().front()
    hitE = fitWorkspace.var("trapENFCal")
    model = fitWorkspace.pdf("model")
    fitResult = fitWorkspace.allGenericObjects().front()
    fPars = fitResult.floatParsFinal()
    nPars = fPars.getSize()

    # === 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]
            fitVals[name] = [fitVal, fitErr, name.split('-')[1]]

    # for f in fitVals:
    # print(f, fitVals[f])

    # === get "true" counts (reverse efficiency correction based on fit value) ===
    hAx = getHistList("axion")
    x, y, xpb = wl.npTH1D(hAx)
    x, y = normPDF(x, y, eLo, eHi)
    nCts, nErr, _ = fitVals["amp-axion"]  # fit result
    yc = nCts * getEffCorr(x, y, inv=True)
    nCorr = np.sum(yc)
    effCorr = nCorr / nCts
    print("nCts %d  nCorr %.2f  effCorr %.2f" % (nCts, nCorr, effCorr))

    # thesis plot, don't delete
    # plt.step(x, y * nCts * (epb/xpb), c='r', lw=2, label="Eff-weighted: %.1f" % (nCts))
    # plt.step(x, yc * (epb/xpb), c='b', lw=2, label="True counts: %.1f" % (nCorr))
    # plt.xlabel("Energy (keV)", ha='right', x=1)
    # plt.ylabel("Counts / keV", ha='right', y=1)
    # plt.legend(loc=1)
    # plt.tight_layout()
    # plt.show()

    tMode = "UPDATE" if update else "RECREATE"
    tOut = TFile("%s/data/rs-plc.root" % dsi.latSWDir, "UPDATE")

    start = time.clock()

    name = "amp-axion"
    fitVal = fitVals[name][0]
    thisVar = fitWorkspace.var(name)

    pCL = 0.9
    plc = RS.ProfileLikelihoodCalculator(fData, model, ROOT.RooArgSet(thisVar))
    plc.SetConfidenceLevel(0.90)
    interval = plc.GetInterval()
    lower = interval.LowerLimit(thisVar)
    upper = interval.UpperLimit(thisVar)
    plot = RS.LikelihoodIntervalPlot(interval)
    plot.SetNPoints(50)
    plot.Draw("tf1")

    pName = "hP_%d" if idx is not None else "hP"
    hProfile = plot.GetPlottedObject()
    hProfile.SetName(pName)
    hProfile.SetTitle("PL %.2f  %s  lo %.3f  mid %.3f  hi %.3f  eC %.3f" %
                      (pCL, name, lower, fitVal, upper, effCorr))
    hProfile.Write()
    print(hProfile.GetTitle())

    tOut.Close()

    print("elapsed:", time.clock() - start)
Exemple #6
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)
Exemple #7
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()
Exemple #8
0
def getUnscaledPDFs(ma=0, makePlots=False):
    """ Generate a set of TH1D's to be turned into RooDataHist objects.
    Be careful they have the same axis limits and binning as the RooDataSet.
    Takes axion mass (in keV) as a parameter.
    """
    from ROOT import TFile, TH1D

    # output files
    rOut = "%s/data/specPDFs.root" % dsi.latSWDir
    tf = TFile(rOut, "RECREATE")
    td = gROOT.CurrentDirectory()

    # print("Generating unscaled PDFs, eLo %.1f  eHi %.1f  epb %.2f: %s" % (eLo, eHi, epb, rOut))

    # === 1. axion flux

    # axion flux scale.
    # NOTE: to do the fit and set a new limit, we set g_ae=1.
    # To plot an expected flux, we would use a real value.
    # Redondo's note: I calculated the flux using gae = 0.511*10^-10
    # for other values of gae use: FLUX = Table*[gae/(0.511*10^-10)]^2
    gae = 1
    gRat = (gae / 5.11e-11)
    redondoScale = 1e19 * gRat**2  # convert table to [flux / (keV cm^2 d)]

    axData = []
    with open("%s/data/redondoFlux.txt" % dsi.latSWDir) as f1:  # 23577 entries
        lines = f1.readlines()[11:]
        for line in lines:
            data = line.split()
            axData.append([float(data[0]), float(data[1])])
    axData = np.array(axData)

    def sig_ae(E, m):
        """ E, m are in units of keV.  must multiply result by sig_pe """
        beta = (1 - m**2. / E**2.)**(1. / 2)
        return (1 -
                (1. / 3.) * beta**(2. / 3.)) * (3. * E**2.) / (16. * np.pi *
                                                               (1. / 137.) *
                                                               511.**2. * beta)

    # === 2. ge photoelectric xs
    phoData = []
    with open("%s/data/ge76peXS.txt" %
              dsi.latSWDir) as f2:  # 2499 entries, 0.01 kev intervals
        lines = f2.readlines()
        for line in lines:
            data = line.split()
            phoData.append([float(data[0]), float(data[1])])
    phoData = np.array(phoData)

    # === 3. tritium
    tritData = []
    with open("%s/data/TritiumSpectrum.txt" %
              dsi.latSWDir) as f3:  # 20000 entries
        lines = f3.readlines()[1:]
        for line in lines:
            data = line.split()
            conv = float(data[2])  # raw spectrum convolved w/ ge cross section
            if conv < 0: conv = 0.
            tritData.append([float(data[1]), conv])
    tritData = np.array(tritData)

    # NOTE: check sandbox/th1.py for examples of manually filling TH1D's and verifying wl.GetHisto and wl.npTH1D.

    # ROOT output
    h1 = TH1D("h1", "photoelectric", nBP, pLo, pHi)  # [cm^2 / kg]
    h2 = TH1D("h2", "axioelectric", nBP, pLo, pHi)  # [cm^2 / kg]
    h3 = TH1D("h3", "axion flux, gae=1", nBP, pLo, pHi)  # [cts / (keV cm^2 d)]
    h4 = TH1D("h4", "convolved flux", nBP, pLo, pHi)  # [cts / (keV d kg)]
    h5 = TH1D("h5", "tritium", nBP, pLo, pHi)  # [cts] (normalized to 1)

    # manually fill ROOT histos (don't normalize yet)
    for iB in range(nBP + 1):
        ctr = (iB + 0.5) * ppb + pLo
        bLo, bHi = ctr - ppb / 2, ctr + ppb / 2
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", category=RuntimeWarning)

            # if ma>0, we ignore entries with E <= m.

            # photoelectric x-section [cm^2 / kg]
            idx = np.where((phoData[:, 0] >= bLo) & (phoData[:, 0] < bHi))
            pho = np.mean(phoData[idx][:, 1]) * 1000
            if np.isnan(pho) or len(phoData[idx][:, 1]) == 0: pho = 0.
            if phoData[idx][:, 1].any() <= ma: pho = 0.
            h1.SetBinContent(iB + 1, pho)

            # axioelectric x-section [cm^2 / kg]
            if ctr > ma: axio = pho * sig_ae(ctr, ma)
            else: axio = 0.
            h2.SetBinContent(iB + 1, axio)

            # axion flux [flux / (cm^2 d keV)]
            idx = np.where((axData[:, 0] >= bLo) & (axData[:, 0] < bHi))
            flux = np.mean(axData[idx][:, 1]) * redondoScale
            if np.isnan(flux): flux = 0.
            h3.SetBinContent(iB + 1, flux)
            # YES, adding 1 here. keeps the 6.6 keV line in the proper place for all binnings.
            # it must have to do w/ the way i'm reading in the data from the text files ...

            # axion flux PDF [flux / (keV d kg)]
            axConv = axio * flux
            h4.SetBinContent(iB + 1, axConv)

            # tritium
            idx = np.where((tritData[:, 0] >= bLo) & (tritData[:, 0] <= bHi))
            trit = np.mean(tritData[idx][:, 1])
            if np.isnan(trit): trit = 0.
            h5.SetBinContent(iB + 1, trit)

    # Pb210 (from separate file)
    tf2 = TFile("%s/data/Pb210PDFs.root" % dsi.latSWDir)
    h6 = tf2.Get("hPb210TDL")  # with TDL
    h7 = tf2.Get("hPb210")  # without TDL
    h6.SetName("h6")
    h7.SetName("h7")

    if makePlots:

        # === 1. verify the numpy histogram and ROOT histogram give the same output. OK

        x, h210, xpb = wl.npTH1D(h7)
        iE = np.where((x > 45) & (x < 48))
        plt.plot(x[iE], h210[iE], ls='steps', lw=3, c='b')
        plt.xlabel("Energy (keV)", ha='right', x=1)
        plt.tight_layout()
        plt.savefig("%s/plots/sf-pk210.pdf" % dsi.latSWDir)

        from ROOT import TCanvas
        c = TCanvas()
        h7.GetXaxis().SetTitle("Energy (keV)")
        h7.GetXaxis().SetRangeUser(45, 48)
        h7.Draw('hist')
        c.Print('%s/plots/sf-pb210th1d.pdf' % dsi.latSWDir)

        # === 2. print ROOT histos to match w/ numpy histos

        c.Clear()
        h1.Draw("hist")
        c.Print("%s/plots/root-sigGe.pdf" % dsi.latSWDir)
        c.Clear()
        h2.Draw("hist")
        c.Print("%s/plots/root-sigAe.pdf" % dsi.latSWDir)
        c.Clear()
        h3.Draw("hist")
        c.Print("%s/plots/root-axFlux.pdf" % dsi.latSWDir)
        c.Clear()
        h4.Draw("hist")
        c.Print("%s/plots/root-axPDF.pdf" % dsi.latSWDir)
        c.Clear()
        h5.Draw("hist")
        c.Print("%s/plots/root-trit.pdf" % dsi.latSWDir)
        c.Clear()
        h6.Draw("hist")
        c.Print("%s/plots/root-pb210TDL.pdf" % dsi.latSWDir)
        c.Clear()
        h7.Draw("hist")
        c.Print("%s/plots/root-pb210.pdf" % dsi.latSWDir)

    gROOT.cd(td.GetPath())
    h1.Write()
    h2.Write()
    h3.Write()
    h4.Write()
    h5.Write()
    h6.Write()
    h7.Write()
    tf.Close()
Exemple #9
0
def burstCut(dsNum):
    """ ./tuneCuts.py [dsNum] -burst """

    # rates = {0:(30,5), 1:(20,5), 3:(50,5), 4:(20,3), 5:(150.,5.)} # v1 - before fitSLo
    rates = {
        0: (20, 5),
        1: (20, 5),
        3: (20, 5),
        4: (20, 5),
        5: (40., 5)
    }  # v2 - after fitSlo

    chList = ds.GetGoodChanList(dsNum)
    nDets = len(chList)
    maxRate = rates[dsNum][0]
    maxChanRate = rates[dsNum][0] * rates[dsNum][1] / float(nDets)

    print "maxRate %d  nDets %d  factor %d  maxChanRate %.2f" % (
        rates[dsNum][0], nDets, rates[dsNum][1], maxChanRate)
    energyCut = "trapENFCal >= 1"

    ignoreList = {0: [656], 3: [592, 692], 4: [1332], 5: [692, 1232, 1124]}
    bkg = ROOT.TChain("skimTree")
    for ch in chList:
        if ch not in ignoreList[dsNum]:
            f = "~/project/latskim/latSkimDS%d_ch%d.root" % (dsNum, ch)
            print "Added", f
            bkg.Add(f)

    # append to the text file (input to ds_livetime.cc)
    ds_livetimeList = open("burstCut_v1.txt", 'a')
    for key in ignoreList:
        killChs = ""
        for val in ignoreList[key]:
            killChs += " %d " % val
        ds_livetimeList.write("%s %s \n" % (key, killChs))

    c0 = ROOT.TCanvas("c0", "c0", 1000, 600)

    rlo, rhi = ds.dsRanges[dsNum][0], ds.dsRanges[dsNum][1]

    clo, chi = 570, 700
    if dsNum == 4: clo, chi = 1100, 1400
    if dsNum == 5: clo, chi = 570, 1400

    h0 = wl.H2D(bkg, rhi - rlo, rlo, rhi, chi - clo, clo, chi, "channel:run",
                energyCut, "Run Number", "Channel")
    h0.Draw("colz")
    c0.SetLogz(1)

    c0.Print("./plots/burst/channelRateDS%d.pdf" % dsNum)

    c1 = ROOT.TCanvas("c", "c", 1600, 600)
    c1.Divide(2, 1, 0)

    c1.cd(1)
    ROOT.gPad.SetLogy(1)

    h1 = wl.H1D(bkg, rhi - rlo, rlo, rhi, "run", energyCut, "Run Number",
                "Counts")
    h1.SetLineColor(ROOT.kRed)
    h1.Draw()

    # Run & channel-based burst cut.

    runs, rates = wl.npTH1D(h1, "i")
    idx = np.where(rates > maxRate)
    print "Noisy runs:", runs[idx]

    burstCut, invBurstCut = energyCut + " && ", energyCut + " && ("

    print "maxChanRate:", maxChanRate
    for i, run in enumerate(runs[idx]):

        runCut = " && run==%d" % run
        # h2.append(ROOT.TH1D())

        h2 = wl.H1D(bkg, chi - clo, clo, chi, "channel", energyCut + runCut,
                    "channel", "Counts")

        if h2.GetEntries() == 0:
            continue

        chans, chRates = wl.npTH1D(h2, "i")
        idx2 = np.where(chRates > maxChanRate)
        print "run", int(run), "noisy chans", chans[idx2], "rates", chRates[
            idx2], "total entries", h2.GetEntries(
            ), "runCut:", energyCut + runCut

        # Write run + channel groups to the file (input to ds_livetime.cc)
        noisyChans = ""
        for ch in chans[idx2]:
            noisyChans += "%d " % ch
        ds_livetimeList.write("%d %s \n" % (run, noisyChans))

        # Make the TCut
        runBurst = "&& !(run==%d && (" % run
        invBurst = "|| (run==%d && (" % run
        if i == 0:
            runBurst = runBurst[3:]
            invBurst = invBurst[3:]

        for ch in chans[idx2]:
            runBurst += "channel==%d|| " % ch
            invBurst += "channel==%d|| " % ch
        runBurst = runBurst[:-3] + ")) "
        invBurst = invBurst[:-3] + ")) "
        burstCut += runBurst
        invBurstCut += invBurst

    invBurstCut += ")"

    ds_livetimeList.close()

    if len(runs[idx]) == 0:
        burstCut, invBurstCut = energyCut, energyCut

    # add the dead channels back in
    for ch in ignoreList[dsNum]:
        burstCut += " && channel!=%d" % ch

    print "\nBURST CUT:"
    print burstCut

    print "\nINVERSE BURST CUT:"
    print invBurstCut
    print ""

    h1a = wl.H1D(bkg, rhi - rlo, rlo, rhi, "run", burstCut)
    h1a.SetLineColor(ROOT.kBlue)
    h1a.Draw("same")

    c1.cd(2)
    ROOT.gPad.SetLogy(1)

    h1.Draw("hist")

    h1b = wl.H1D(bkg, rhi - rlo, rlo, rhi, "run", invBurstCut)
    h1b.SetLineColor(ROOT.kBlue)
    h1b.Draw("hist same")

    c1.Print("./plots/burst/burstCutDS%d.pdf" % dsNum)

    c2 = TCanvas("c2", "c2", 1000, 600)
    c2.SetLogy(1)

    eb, elo, ehi = 150, 0, 30  # 5 bins/kev

    h2 = wl.H1D(bkg, eb, elo, ehi, "trapENFCal", "", "Energy", "Counts")
    h2.SetLineColor(ROOT.kRed)

    h3 = wl.H1D(bkg, eb, elo, ehi, "trapENFCal", burstCut)
    h3.SetLineColor(ROOT.kBlue)

    h2.Draw("hist")
    h3.Draw("hist same")

    c2.Print("./plots/burst/energySpecDS%d.pdf" % dsNum)
Exemple #10
0
def axionPeaks():
    """ placeholder: get the axion peak energies here. """
    from ROOT import TH1D

    gae = 1
    gRat = (gae / 5.11e-11)
    redondoScale = 1e19 * gRat**2 # convert table to [flux / (keV cm^2 d)]

    xLo, xHi, xpb = 0, 10, 0.1
    nB = int((xHi-xLo)/xpb)

    axData = []
    with open("./data/redondoFlux.txt") as f1: # 23577 entries
        lines = f1.readlines()[11:]
        for line in lines:
            data = line.split()
            axData.append([float(data[0]),float(data[1])])
    axData = np.array(axData)

    hAx = TH1D("hAx","axion flux, gae=1",nB,xLo,xHi)     # [cts / (keV cm^2 d)]
    for iB in range(nB+1):
        ctr = (iB + 0.5)*xpb + xLo
        bLo, bHi = ctr - xpb/2, ctr + xpb/2
        # print(iB, bLo, bHi)
        with warnings.catch_warnings():
            warnings.simplefilter("ignore",category=RuntimeWarning)

            # axion flux [flux / (cm^2 d keV)]
            idx = np.where((axData[:,0] >= bLo) & (axData[:,0] < bHi))
            flux = np.mean(axData[idx][:,1]) * redondoScale
            if np.isnan(flux): flux = 0.
            hAx.SetBinContent(iB+1, flux)

    xA, hA, xpb2 = wl.npTH1D(hAx)
    if xpb!=xpb2:
        print("WTF, error")
        exit(1)

    # make sure the saved PDF matches
    f = np.load("./data/specPDFs.npz")
    pdfs = f['arr_0'].item()
    xP, aP, xpb3 = pdfs["axFlux"]

    plt.plot(axData[:,0], axData[:,1] * redondoScale, '.k', ms=1, alpha=0.3, label='Raw Flux Data')
    plt.plot(xA, hA, ls='steps', c='r', lw=1, label='Flux, %.1f keV bins' % xpb)
    plt.plot(xP, aP, ls='steps', c='m', lw=1)
    plt.axvline(1, c='m', lw=1, label="1.0 keV")

    # try to locate the shifted peaks
    msList = []
    msThresh = 10
    maxtab,_ = wl.peakdet(hA, msThresh)
    for iMax in range(len(maxtab)):
        idx = int(maxtab[iMax][0])
        if not 1 <= xA[idx] <= 7 : continue
        val = maxtab[iMax][1]
        xPk = xA[idx]-xpb/2
        msList.append(xPk)
        print("%d  idx %d  ene %.2f  val %.2e  thresh %.2f" % (iMax, idx, xPk, val, msThresh))
        plt.axvline(xPk, lw=1, c='g', label="%.2f" % xPk)

    plt.legend()
    plt.xlabel("Energy (keV)", ha='right', x=1)
    plt.tight_layout()
    # plt.show()
    plt.savefig('./plots/sf-axFlux-binned.pdf')
Exemple #11
0
def plotPDFs():
    """ Final consistency check on PDFs before we use them in the fitter. """
    from ROOT import TFile

    tfU = TFile("./data/specPDFs.root")
    tfS = TFile("./data/scaledPDFs.root")
    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()

    # === 1. Ge photoelectric XS
    plt.close()
    xR, hR, _ = wl.npTH1D(tfU.Get("h1"))
    plt.semilogy(xR, hR, ls='steps', c='b', lw=3, label=r"$\sigma_{ge}$")
    plt.xlabel("Energy (keV)", ha='right', x=1)
    plt.ylabel(r"$\mathregular{cm^2/kg}$", ha='right', y=1)
    plt.legend()
    plt.tight_layout()
    # plt.show()
    plt.savefig("./plots/sf-gexs.pdf")

    # === 2. axioelectric XS
    plt.close()
    xR, hR, _ = wl.npTH1D(tfU.Get("h2"))
    plt.plot(xR, hR, ls='steps', c='b', lw=3, label=r"$\sigma_{ae}$")
    plt.xlabel("Energy (keV)", ha='right', x=1)
    plt.ylabel(r"$\mathregular{cm^2/kg}$", ha='right', y=1)
    plt.legend()
    plt.tight_layout()
    # plt.gca().yaxis.set_label_coords(-0.06, 1)
    # plt.show()
    plt.savefig("./plots/sf-axs.pdf")

    # === 3. axion flux, gae=1
    plt.close()
    xR, hR, _ = wl.npTH1D(tfU.Get("h3"))
    plt.plot(xR, hR, ls='steps', c='b', lw=3, label=r"$\Phi_a$")
    plt.xlabel("Energy (keV)", ha='right', x=1)
    plt.ylabel(r"Flux / (keV cm${}^2$ d)]", ha='right', y=1)
    plt.xlim(0,12)
    plt.legend()
    plt.tight_layout()
    # plt.show()
    plt.savefig("./plots/sf-axFlux.pdf")

    # === 4. solar axion PDF, gae=1 -- this is what we integrate to get N_exp
    plt.close()
    xR1, hR1, _ = wl.npTH1D(tfU.Get("h4"))
    xr, hr, xbr = pdfRaw["axion"]
    plt.plot(xR1, hR1, ls='steps', c='b', lw=3, label=r"$\Phi_a$")
    plt.plot(xr, hr, ls='steps', c='r', lw=1)
    plt.xlabel("Energy (keV)", ha='right', x=1)
    plt.ylabel("Flux / (keV d kg)", ha='right', y=1)
    plt.xlim(0,10)
    plt.legend()
    plt.tight_layout()
    # plt.show()
    plt.savefig("./plots/sf-axPDF.pdf")

    # === 5. normalized, efficiency corrected solar axion PDF, gae=1
    plt.close()
    xR2, hR2, _ = wl.npTH1D(tfS.Get("h4-e")) # this is normalized w/ efficiency - not what we want for N_exp
    xn, hn, xbn = pdfNorm["axion"]
    xe, he, xbe = pdfEff["axion"]
    xen, hen, xben = pdfEffN["axion"]
    # plt.plot(xR2, hR2, ls='steps', c='r', lw=3, label="root, eff. corrected, norm'd")
    plt.plot(xn, hn, ls='steps', c='m', lw=2, label="Normalized PDF")
    # plt.plot(xe, he, ls='steps', c='g', lw=2, label="numpy, eff. corrected")
    plt.plot(xen, hen, ls='steps', c='b', lw=2, label="Normalized Eff.Corr. PDF")

    henc = getEffCorr(xen, hen, inv=True)
    plt.plot(xen, henc, ls='steps', c='g', lw=2, label="Final")

    plt.xlabel("Energy (keV)", ha='right', x=1)
    plt.ylabel("Counts (norm)", ha='right', y=1)
    plt.xlim(0,10)
    plt.legend()
    plt.tight_layout()
    # plt.show()
    plt.savefig("./plots/sf-axPDF-effnorm.pdf")
    # return

    # # === 5. tritium
    plt.close()
    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, 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("Counts (norm)", ha='right', y=1)
    plt.legend()
    plt.xlim(0,20)
    plt.tight_layout()
    # plt.show()
    plt.savefig('./plots/sf-trit.pdf')

    # === 6. Pb210-TDL PDF
    plt.close()

    xn, hn, xbn = pdfNorm["Pb210-TDL"]
    xen, hen, xben = pdfEffN["Pb210-TDL"]
    henc = getEffCorr(xen, hen, inv=True)

    plt.plot(xn, hn, ls='steps', c='r', lw=2, label="Pb210TDL, norm. PDF")
    plt.plot(xen, hen, 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("Counts (norm)", ha='right', y=1)
    plt.legend(loc=2)
    plt.tight_layout()
    # plt.show()
    plt.savefig("./plots/sf-pb210.pdf")
Exemple #12
0
def scalePDFs(eff=False, makePlots=False):
    """ Create scaled (normalized to 1) PDFs (both ROOT and numpy output).
    RooFit does that automatically, but I also need the numpy histos to be correct.
    Optionally, apply the DS-specific efficiency correction, using the global variable 'dsList'.
    Be very careful when you apply efficiency -- RooFit will automatically normalize those too.
    """
    from ROOT import TFile, TH1D, gROOT

    rOut = "./data/scaledPDFs.root"
    tfOut = TFile(rOut,"RECREATE")
    td = gROOT.CurrentDirectory()

    npOut = "./data/scaledPDFs.npz"

    print("Generating scaled PDFs: %s" % (rOut))

    # load unscaled PDFs
    tf = TFile("./data/specPDFs.root")
    h4 = tf.Get('h4') # axion pdf
    h5 = tf.Get('h5') # tritium
    h6 = tf.Get('h6') # Pb210TDL
    h7 = tf.Get('h7') # Pb210

    x4, np4, xpb4 = wl.npTH1D(h4)
    x5, np5, xpb5 = wl.npTH1D(h5)
    x6, np6, xpb6 = wl.npTH1D(h6)
    x7, np7, xpb7 = wl.npTH1D(h7)

    # create a flat BG PDF over the current energy range
    nB = int((eHi-eLo)/0.05)
    h8 = TH1D("h8","flat BG",nB,eLo,eHi)
    for iB in range(nB+1):
        h8.SetBinContent(iB, 1) # the initial amplitude doesn't matter b/c we normalize to 1
    x8, np8, xpb8 = wl.npTH1D(h8)

    # normalize PDFs, in the energy range we're using for the fit (eLo, eHi)

    # root
    h4.Scale(1/h4.Integral(h4.FindBin(eLo), h4.FindBin(eHi), 'width')) # axion
    h5.Scale(1/h5.Integral(h5.FindBin(eLo), h5.FindBin(eHi), 'width')) # tritium
    h6.Scale(1/h6.Integral(h6.FindBin(eLo), h6.FindBin(eHi), 'width')) # pb210-tdl
    h7.Scale(1/h7.Integral(h7.FindBin(eLo), h7.FindBin(eHi), 'width')) # pb210
    h8.Scale(1/h8.Integral(h8.FindBin(eLo), h8.FindBin(eHi), 'width')) # flat bg

    # numpy
    np4n = np.divide(np4, np.sum(np4[np.where((x4 >= eLo) & (x4 <= eHi))] * xpb4))
    np5n = np.divide(np5, np.sum(np5[np.where((x5 >= eLo) & (x5 <= eHi))] * xpb5))
    np6n = np.divide(np6, np.sum(np6[np.where((x6 >= eLo) & (x6 <= eHi))] * xpb6))
    np7n = np.divide(np7, np.sum(np7[np.where((x7 >= eLo) & (x7 <= eHi))] * xpb7))
    np8n = np.divide(np8, np.sum(np8[np.where((x8 >= eLo) & (x8 <= eHi))] * xpb8))

    if makePlots:

        # === 1. make sure I normalized correctly
        xR, yR, xpbR = wl.npTH1D(h4)
        plt.plot(x4, np4n, ls='steps', lw=3, label="numpy normalized")
        plt.plot(xR, yR, ls='steps', lw=2, label="root normalized")
        plt.xlabel("Energy (keV)", ha='right', x=1)
        plt.ylabel("Counts (norm)", ha='right', y=1)
        plt.legend()
        plt.tight_layout()
        plt.savefig("./plots/sf-axionPDF-norm.pdf")
        # return

    # apply efficiency correction (to the scaled TH1D)
    if eff:
        h4e = getEffCorrTH1D(h4, h4.GetXaxis().GetXmin(), h4.GetXaxis().GetXmax()) # axion
        h5e = getEffCorrTH1D(h5, h5.GetXaxis().GetXmin(), h5.GetXaxis().GetXmax()) # tritium
        h6e = getEffCorrTH1D(h6, h6.GetXaxis().GetXmin(), h6.GetXaxis().GetXmax()) # pb210-tdl
        h7e = getEffCorrTH1D(h7, h7.GetXaxis().GetXmin(), h7.GetXaxis().GetXmax()) # pb210
        h8e = getEffCorrTH1D(h8, h8.GetXaxis().GetXmin(), h8.GetXaxis().GetXmax()) # flat

        np4ne = getEffCorr(x4, np4n)
        np5ne = getEffCorr(x5, np5n)
        np6ne = getEffCorr(x6, np6n)
        np7ne = getEffCorr(x7, np7n)
        np8ne = getEffCorr(x8, np8n)

        if makePlots:

            # === 2. make sure the efficiency correction is right
            plt.close()
            xR, yR, xpbR = wl.npTH1D(h4e)
            plt.plot(xR, yR, ls='steps', label="root eff-corr")
            plt.plot(x4, np4ne, ls='steps', label="np eff-corr")
            plt.legend()
            # plt.show()
            plt.savefig("./plots/sf-effCorr-axion.pdf")

        # finally, normalize and scale the efficiency-corrected histos

        # this is what RooFit will essentially use (automatically)
        h4e.Scale(1/h4e.Integral(h4e.FindBin(eLo), h4e.FindBin(eHi), 'width')) # axion
        h5e.Scale(1/h5e.Integral(h5e.FindBin(eLo), h5e.FindBin(eHi), 'width')) # tritium
        h6e.Scale(1/h6e.Integral(h6e.FindBin(eLo), h6e.FindBin(eHi), 'width')) # pb210-tdl
        h7e.Scale(1/h7e.Integral(h7e.FindBin(eLo), h7e.FindBin(eHi), 'width')) # pb210
        h8e.Scale(1/h8e.Integral(h8e.FindBin(eLo), h8e.FindBin(eHi), 'width')) # flat

        np4nen = np.divide(np4ne, np.sum(np4ne[np.where((x4 >= eLo) & (x4 <= eHi))] * xpb4))
        np5nen = np.divide(np5ne, np.sum(np5ne[np.where((x5 >= eLo) & (x5 <= eHi))] * xpb5))
        np6nen = np.divide(np6ne, np.sum(np6ne[np.where((x6 >= eLo) & (x6 <= eHi))] * xpb6))
        np7nen = np.divide(np7ne, np.sum(np7ne[np.where((x7 >= eLo) & (x7 <= eHi))] * xpb7))
        np8nen = np.divide(np8ne, np.sum(np8ne[np.where((x8 >= eLo) & (x8 <= eHi))] * xpb8))

        if makePlots:

            # === 3. make sure I normalized the efficiency-corrected histos correctly
            plt.close()
            xR, yR, xpbR = wl.npTH1D(h4e)
            plt.plot(xR, yR, ls='steps', lw=3, label="root normalized")
            plt.plot(x4, np4nen, ls='steps', lw=2, label="numpy normalized")
            plt.xlabel("Energy (keV)", ha='right', x=1)
            plt.ylabel("Counts (norm)", ha='right', y=1)
            plt.legend()
            plt.tight_layout()
            # plt.show()
            plt.savefig("./plots/sf-effCorr-axion-norm.pdf")

            # === 4. plot the different corrections together
            plt.close()
            plt.plot(x4, np4n, ls='steps', lw=3, label="normalized")
            plt.plot(x4, np4ne, ls='steps', lw=3, label="norm, eff.corr")
            plt.plot(x4, np4nen, ls='steps', lw=3, label="norm, eff.corr, norm'd again")
            plt.xlabel("Energy (keV)", ha='right', x=1)
            plt.ylabel("Counts (norm)", ha='right', y=1)
            plt.xlim(0, 12)
            plt.legend()
            plt.tight_layout()
            # plt.show()
            plt.savefig("./plots/sf-effCorr-axion-norm-2.pdf")

            # === 5. plot the efficiency-corrected flat bg
            plt.close()
            plt.plot(x8, np8n, ls='steps', lw=3, label="Flat BG, normalized")
            plt.plot(x8, np8nen, ls='steps', lw=3, label="Flat BG, efficiency corrected, normalized")

            # reverse the normalization
            np8nenc = getEffCorr(x8, np8nen, inv=True)
            plt.plot(x8, np8nenc, ls='steps', lw=3, label="Flat BG, reverted efficiency correction")

            plt.xlabel("Energy (keV)", ha='right', x=1)
            plt.ylabel("Counts (norm)", ha='right', y=1)
            plt.ylim(0, 0.05)
            plt.legend()
            plt.tight_layout()
            # plt.show()
            plt.savefig("./plots/sf-effCorr-flat.pdf")


    # save ROOT output (used by the fitter)
    gROOT.cd(td.GetPath())
    if eff:
        h4e.Write()
        h5e.Write()
        h6e.Write()
        h7e.Write()
        h8e.Write()
    else:
        h4.Write()
        h5.Write()
        h6.Write()
        h7.Write()
        h8.Write()
    tfOut.Close()

    # save numpy output
    pdfRaw = {
        # this is the unscaled pdf
        "axion" : [x4, np4, xpb4],
        "trit"  : [x5, np5, xpb5],
        "Pb210" : [x6, np6, xpb6],
        "Pb210-TDL" : [x7, np7, xpb7],
        "flat" : [x8, np8, xpb8]
    }
    pdfNorm = {
        # this is the normalized pdf
        "axion" : [x4, np4n, xpb4],
        "trit"  : [x5, np5n, xpb5],
        "Pb210" : [x6, np6n, xpb6],
        "Pb210-TDL" : [x7, np7n, xpb7],
        "flat" : [x8, np8n, xpb8]
    }
    pdfEff = {
        # this is the efficiency corrected normalized pdf
        "axion" : [x4, np4ne, xpb4],
        "trit"  : [x5, np5ne, xpb5],
        "Pb210" : [x6, np6ne, xpb6],
        "Pb210-TDL" : [x7, np7ne, xpb7],
        "flat" : [x8, np8ne, xpb8]
    }
    pdfEffN = {
        # this is the efficiency corrected normalized pdf, normalized again
        # b/c that's what roofit does automatically in a fit
        "axion" : [x4, np4nen, xpb4],
        "trit"  : [x5, np5nen, xpb5],
        "Pb210" : [x6, np6nen, xpb6],
        "Pb210-TDL" : [x7, np7nen, xpb7],
        "flat" : [x8, np8nen, xpb8]
    }
    np.savez(npOut, pdfRaw, pdfNorm, pdfEff, pdfEffN)
Exemple #13
0
def getEff():
    """ ./job-panda.py -getEff

    METHOD:
    open up the latskim file for each channel.
    loop over the good run ranges.
    for each good range, make an energy histogram.
    then calculate the efficiency curve based on the sigma value
    and convolve it with the histogram points.
    """
    import numpy as np
    import waveLibs as wl
    import scipy.special as spec
    import matplotlib.pyplot as plt
    from ROOT import TFile, TTree, TH1D, TF1, TCanvas, gROOT
    import ROOT, random

    gROOT.ProcessLine(".x ~/env/MJDClintPlotStyle.C")
    # gROOT.ProcessLine("gErrorIgnoreLevel = 3001;") # suppress ROOT messages

    bins, xlo, xhi = 50, 0, 15  # set it just high enough that the first bin center isn't negative

    hSumCorr = TH1D("hSumCorr", "hSumCorr", bins, xlo, xhi)
    hSumUncr = TH1D("hSumUncr", "hSumUncr", bins, xlo, xhi)

    dsNum = 1
    # ch = 578
    for ch in ds.GetGoodChanList(dsNum):

        inFile = TFile(homePath + "/project/latskim/latSkimDS%d_ch%d.root" %
                       (dsNum, ch))
        tree = inFile.Get("skimTree")
        fileCut = inFile.Get("theCut").GetTitle()

        _, _, goodRunErfs = ds.GetThreshDicts(dsNum)

        hUnc = wl.H1D(tree, bins, xlo, xhi, "trapENFCal", fileCut)
        hSumUncr.Add(hUnc)

        for erfs in goodRunErfs[ch]:

            runCut = " && run >= %d && run <= %d" % (erfs[0], erfs[1])
            theCut = fileCut + runCut

            h1 = wl.H1D(tree, bins, xlo, xhi, "trapENFCal", theCut)
            h1x, h1y = wl.npTH1D(h1)

            # calculate efficiency curve
            thisErf = TF1("thisErf",
                          "0.5*(1+TMath::Erf((x-[0])/(TMath::Sqrt(2)*[1]) ))")
            thisErf.SetParameter(0, erfs[2])  # mu
            thisErf.SetParameter(1, erfs[3])  # sigma
            h1.Divide(thisErf)

            # thisErf = 0.5 * (1 + spec.erf( (h1x - mu) / (np.sqrt(2) * sig) ))
            # h1yScaled = h1y / thisErf
            # nameStr = str(random.uniform(1.,2.))
            # h2 = TH1D(nameStr,nameStr,bins,xlo,xhi)
            # for i in range(bins):
            #     h2.SetBinContent(i,h1yScaled[i])

            hSumCorr.Add(h1)

    # eff-corrected spectrum.
    c = TCanvas("c", "c", 800, 600)
    c.SetLogy(1)

    hSumCorr.SetLineColor(ROOT.kBlue)
    hSumCorr.Draw("hist")

    hSumUncr.SetLineColor(ROOT.kRed)
    hSumUncr.Draw("hist same")

    # l1 = TLegend

    c.Print("./plots/effWeight/eff_DS%d.pdf" % dsNum)
Exemple #14
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)
Exemple #15
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()
Exemple #16
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")