Esempio n. 1
0
    def fillAcceptance(self):
        '''
    This is to calculate the acceptance of the sample
    '''
        if debug: print('Info in Sample.fillAcceptance()')
        #f = TFile.Open(self.infileName)
        #t = f.Get(self.treeName)
        #if not t:
        #  raise RuntimeError( 'ERROR: no tree in file %s' % self.infileName)
        chain = TChain(self.treeName)
        for fn in self.infileNames:
            chain.Add(fn)

        self.effnum = ROOT.TH1F(
            'effnum', 'effnum', 1, 0, 13000
        )  #dict([(k, ROOT.TH1F('effnum_%s' % k, 'effnum_%s' % k, 1, 0, 1)) for k in self.settings])
        self.effden = ROOT.TH1F('effden', 'effden', 1, 0, 13000)

        if doInclusive:
            cutsnum = '(l0_pt>{mp} && abs(l0_eta)<1.5'.format(mp=muTrigPt)
        else:
            cutsnum = '(l0_pt>{mp} && abs(l0_eta)<1.5 && k_pt>1 && abs(k_eta)<2.5 && pi_pt>1 && abs(pi_eta)<2.5'.format(
                mp=muTrigPt)
        if doSkipDispl:
            cutsnum += ''
        else:
            cutsnum += '&& Lxy < 1000'
        if doSkipHNLptEta:
            cutsnum += ''
        else:
            cutsnum += '&& l1_pt>3 && abs(l1_eta)<2.5 && pi1_pt>0.8 && abs(pi1_eta)<2.5'

        cutsnum += ')'

        cutsden = '(l0_pt>{mp} && abs(l0_eta)<1.5)'.format(mp=muTrigPt)

        chain.Draw('hnl_pt>>effnum', cutsnum + '*' + self.evt_w, 'goff')
        chain.Draw('hnl_pt>>effden', cutsden + '*' + self.evt_w, 'goff')

        if TEfficiency.CheckConsistency(self.effnum, self.effden):
            peff = TEfficiency(self.effnum, self.effden)

            self.acc = peff.GetEfficiency(1)
            self.acc_errup = peff.GetEfficiencyErrorUp(1)
            self.acc_errdn = peff.GetEfficiencyErrorLow(1)

        # for debugging purposes
        self.num = self.effnum.GetEntries()
        if self.num == 0: print('**** 0 entries for mass={}'.format(self.mass))
        self.den = self.effden.GetEntries()
Esempio n. 2
0
    def fillFilterEff(self, dostamp=True):
        '''
    To retrieve and save the filter efficiency - from the minigentree
    TODO: retrieve the cross-section => for that you would need to run without separate jobs
    '''
        if debug: print('Info in Sample.fillFilterEff()')

        efffnum = ROOT.TH1F('efffnum', 'efffnum', 1, 0, 13000)
        efffden = ROOT.TH1F('efffden', 'efffden', 1, 0, 13000)

        chain = TChain(self.treeName)
        for fn in self.infileNames:
            chain.Add(fn)

        efffnum.SetBinContent(1, chain.GetEntries())
        efffnum.SetBinError(1, ROOT.TMath.Sqrt(chain.GetEntries()))

        # denominator = number of events that were run in the first place # access storage element...
        #self.ngenevts_succ_afterfilter=0
        self.njobs_succ = 0
        path = '/pnfs/psi.ch/cms/trivcat/store/user/{u}/BHNLsGen/{pl}/mass{m}_ctau{ctau}/step1*root'.format(
            u=os.environ['USER'], pl=self.label, m=self.mass, ctau=self.ctau)
        for fname in glob(path):
            if debug: print 'fname=', fname
            f = TFile.Open(fname)
            if f.GetListOfKeys().Contains('Events'):
                self.njobs_succ += 1

        #njobs_succ = len(glob(path))
        self.ngenevts_succ = float(self.ngenevts) / float(self.njobs) * float(
            self.njobs_succ)

        efffden.SetBinContent(1, self.ngenevts_succ)
        efffden.SetBinError(1, ROOT.TMath.Sqrt(self.ngenevts_succ))

        if TEfficiency.CheckConsistency(efffnum, efffden):
            geneff = TEfficiency(efffnum, efffden)
            self.effFilter = geneff.GetEfficiency(1)
            self.effFilter_errup = geneff.GetEfficiencyErrorUp(1)
            self.effFilter_errdn = geneff.GetEfficiencyErrorLow(1)

        # stamp basic info about filter eff
        if dostamp:            print('mass={m}GeV, VV={vv:.1e}, nTot={nt}, nSucc={ns}, nSuccAfterFilter={nsf}, effFilter={ef:.3f}%, errup={eu:.3f}%, errdn={ed:.3f}% '.format( \
            m=self.mass,vv=self.vv,nt=self.ngenevts,ns=self.ngenevts_succ,nsf=efffnum.GetBinContent(1),ef=self.effFilter*100,eu=self.effFilter_errup*100,ed=self.effFilter_errdn*100))
def makeEoverEtrueAnalysis(inputfile, det, et, iseeding, igathering, nevts,
                           outputdir):

    print '*******************************************'
    print 'Starting analysis for det={}, Et={}, seed thrs={}, gather thrs={}'.format(
        det, et, iseeding, igathering)
    print 'inputfile={}'.format(inputfile)
    print '*******************************************'

    result = EoverEtrueAnalysisResult()
    if not os.path.isfile(inputfile):
        return False, result

    ###################
    # READ
    ##################
    histoname = 'h_PFclusters_genMatched_{det}_eOverEtrue_{Et}'.format(det=det,
                                                                       Et=et)
    inputdir = 'ecalnoisestudy'
    subdir = 'EtBinnedQuantities'
    f = TFile(inputfile, 'READ')
    histo = f.Get('{}/{}/{}'.format(inputdir, subdir, histoname))
    if not histo: return False, result

    histo.SetMarkerStyle(20)
    histo.GetXaxis().SetTitle(
        'E_{{PFcluster}} / E_{{True}} (GeV)'.format(det=det))
    histo.GetYaxis().SetTitle('Entries')
    histo.GetXaxis().SetRangeUser(0, 2)
    if det == 'EB':
        histo.GetYaxis().SetRangeUser(0, 500)
    else:
        histo.GetYaxis().SetRangeUser(0, 150)
    histo.Rebin(2)
    #histo.GetYaxis().SetRangeUser(0., 1600)
    #if 'EE' in det:
    #  histo.GetYaxis().SetRangeUser(0., 600)

    # better to avoid setting the range, since the mean calculation changes
    #histo.GetXaxis().SetRangeUser(xrange[0], xrange[1])

    ###################
    # FIT
    ##################
    #f1 = TF1('f1','crystalball',0.4, 2.)
    #f1.SetParameters(200, 1, 0.05, 3, 2) # my guess: constant (normalization)=integral, mean = 1, sigma = 0.1, alpha (quanto lontano dal picco si innesta la coda) = 0.7, N = 0.5 (lunghezza della coda(?)
    #f1.SetLineColor(kRed)
    f1 = TF1('f1', 'gaus', 0.4, 2.)
    f1.SetParameter(0, 200)
    f1.SetParameter(1, histo.GetMean())
    f1.SetParameter(2, histo.GetRMS())

    # do one first fit on the full range
    fitresult = histo.Fit(f1, 'RM')  # L for loglikelihood ,
    mean = f1.GetParameter(1)
    sigma = f1.GetParameter(2)
    f1.SetParameter(1, mean)
    f1.SetParameter(2, sigma)
    f1.SetRange(mean - 3 * sigma, mean + 3 * sigma)
    fitresult = histo.Fit(f1, 'SRM')

    c = TCanvas()
    histo.Draw('PE')
    #fitresult = histo.Fit(f1, 'RS')
    f1.Draw('same')
    # save later

    #fo.cd()
    #fitresult.Write()
    #fo.Close()

    # Get the fitted function parameters and write them to txt file
    #fit_params = [ ('Param {}'.format(i),'{:.2f}'.format(f1.GetParameter(i)), '{:.2f}'.format(f1.GetParError(i)) ) for i in range(0,5)]
    #ffitout = open(det + '_' + fitoutfile , 'a')
    #ffitout.write('\n\nFit results for seeding={} gathering={} subdet={}:\n'.format(iseeding, igathering, det))
    #ffitout.write('\nChi2/Ndf=' + str(f1.GetChisquare()) + '/' + str(f1.GetNDF()) + '\n')
    #par_string = '\n'.join("%s: val=%s  err=%s" % tup for tup in fit_params)
    #ffitout.write(par_string)

    ###################
    # Efficiency
    ##################
    hpass = TH1F('hpass', 'hpass', 1, 0., 1.)
    #Npass = histo.GetEntries()
    # compute efficiency only in +-3 sigma fitted peak
    Npass = histo.Integral(6,
                           histo.FindLastBinAbove(0.))  # 0.2 cut in EoverEtrue
    for i in range(0, int(Npass)):
        hpass.Fill(0.5)

    #htot = f.Get('{}/{}/{}'.format(inputdir,'general', 'h_genP_pt_{d}'.format(d=det)))
    htot = TH1F('htot', 'htot', 1, 0., 1.)
    histoname = 'h_genP_{det}_nEvts_{Et}'.format(det=det, Et=et)
    h_genP = f.Get('{}/{}/{}'.format(inputdir, subdir, histoname))
    Ntot = h_genP.GetEntries()
    for i in range(0, int(Ntot)):
        htot.Fill(0.5)

    print 'eff calculated from npass {} over ntot {}'.format(
        hpass.GetEntries(), htot.GetEntries())

    if TEfficiency.CheckConsistency(hpass, htot):
        pEff = TEfficiency(hpass,
                           htot)  # default stat option is clopper pearson
        eff = pEff.GetEfficiency(1)
        erru = pEff.GetEfficiencyErrorUp(1)
        errd = pEff.GetEfficiencyErrorLow(1)
    else:
        eff = 1.0
        erru = 1.0
        errd = 1.0
    eff_label = '{:.4f}+/-{:.4f}'.format(eff,
                                         erru)  # erru and errd are the same
    #fout = open(det + '_' + outfile, 'a')
    #fout.write('Total efficiency for seeding={} gathering={}:  {} \n'.format(iseeding,igathering,eff_label))
    #fout.close()

    eff_label = 'N_{{reco}}/N_{{gen}}={}'.format(eff_label)
    defaultLabels([eff_label],
                  x=0.62,
                  y=0.65,
                  spacing=0.04,
                  size=0.06,
                  dx=0.12)

    sample_label = '#gamma#gamma, no tracker'
    et_label = 'Et=({},{})GeV'.format(et.split('_')[0], et.split('_')[1])
    det_label = 'Region={}'.format(det)
    defaultLabels([sample_label, et_label, det_label],
                  x=0.25,
                  y=0.85,
                  spacing=0.04,
                  size=0.06,
                  dx=0.12)

    ###################
    # RESULTS
    ##################
    c.SaveAs('{o}/EoverEtrue_{det}_Et{et}_seed{s}_gather{g}.pdf'.format(
        o=outputdir, det=det, s=iseeding, g=igathering, et=et))
    c.SaveAs('{o}/EoverEtrue_{det}_Et{et}_seed{s}_gather{g}.png'.format(
        o=outputdir, det=det, s=iseeding, g=igathering, et=et))

    return True, EoverEtrueAnalysisResult(det=det,
                                          et=et,
                                          eff=eff,
                                          erreff=erru,
                                          mean=f1.GetParameter(1),
                                          errmean=f1.GetParError(1),
                                          sigma=f1.GetParameter(2),
                                          errsigma=f1.GetParError(2),
                                          rms=histo.GetRMS(),
                                          errrms=histo.GetRMSError(),
                                          iseeding=iseeding,
                                          igathering=igathering)
def makeEoverEtrueAnalysis(inputfile,
                           eta,
                           et,
                           iseeding,
                           igathering,
                           nevts,
                           outputdir,
                           doCBfit=False):

    gROOT.SetBatch(True)
    gROOT.ProcessLine('.L /work/mratti/CMS_style/tdrstyleGraph.C')
    gROOT.ProcessLine('setTDRStyle()')

    print '*******************************************'
    print 'Starting analysis for Eta={}, Et={}, seed thrs={}, gather thrs={}'.format(
        eta, et, iseeding, igathering)
    print 'inputfile={}'.format(inputfile)
    print '*******************************************'

    result = EoverEtrueAnalysisResult()
    if not os.path.isfile(inputfile):
        print 'ERROR: did not find inputfile', inputfile
        return False, result

    ###################
    # READ
    ##################
    #histoname = 'h_PFclusters_genMatched_eOverEtrue_Eta{eta}_Et{et}'.format(eta=eta, et=et)
    #histoname = 'h_superClusters_genMatched_eOverEtrue_Eta{eta}_Et{et}'.format(eta=eta, et=et)
    histonameFull = histoname + '_Eta{eta}_Et{et}'.format(eta=eta, et=et)
    inputdir = 'ecalnoisestudy'
    subdir = 'EtaEtBinnedQuantities'
    f = TFile(inputfile, 'READ')
    histo = f.Get('{}/{}/{}'.format(inputdir, subdir, histonameFull))
    if not histo:
        print 'ERROR: did not find histogram', inputdir, subdir, histonameFull
        return False, result

    histo.SetMarkerStyle(20)
    histo.GetXaxis().SetTitle(
        'E_{{PFcluster}} / E_{{True}} (GeV)'.format(eta=eta))
    histo.GetYaxis().SetTitle('Entries')
    histo.GetXaxis().SetRangeUser(0, 2)
    #histo.GetYaxis().SetRangeUser(0,1500)

    if eta == "0p00_0p50" and et == "1_20":
        if '450ifb_nominal' in outputdir:
            histo.Rebin(2)

    #histo.GetYaxis().SetRangeUser(0., 1600)
    #if 'EE' in det:
    #  histo.GetYaxis().SetRangeUser(0., 600)

    # better to avoid setting the range, since the mean calculation changes
    #histo.GetXaxis().SetRangeUser(xrange[0], xrange[1])

    ###################
    # FIT
    ##################

    if doCBfit:

        # first fit a gaussian starting from reasonable parameters
        f0 = TF1('f1', 'gaus', 0.4, 2.)
        #f0.SetParameter(0, 200)
        f0.SetParameter(1, histo.GetMean())
        f0.SetParameter(2, histo.GetRMS())
        fitresult = histo.Fit(f0, 'SRM')
        mean = f0.GetParameter(1)
        sigma = f0.GetParameter(2)

        # refit to gaussian, just to make sure
        f0.SetParameter(1, mean)
        f0.SetParameter(2, sigma)
        f0.SetRange(mean - 3 * sigma, mean + 3 * sigma)
        fitresult = histo.Fit(f0, 'SRM')
        mean = f0.GetParameter(1)
        sigma = f0.GetParameter(2)

        # then restrict yourself to +/- 3 sigma and fit a crystal ball there
        f1 = TF1('f1', 'crystalball', 0.4, 2.)
        Nsigma = 4
        if (eta == "1p48_2p00" and et != "1_20") or (eta == "2p50_3p00"
                                                     and et == "40_60"):
            Nsigma = 3
        f1.SetRange(mean - Nsigma * sigma, mean + Nsigma * sigma)
        f1.SetParameters(
            200, 1, 0.05, 3, 2
        )  # my guess: constant (normalization)=integral, mean = 1, sigma = 0.1, alpha (quanto lontano dal picco si innesta la coda) = 0.7, N = 0.5 (lunghezza della coda(?)
        f1.SetLineColor(kRed)
        fitresult = histo.Fit(f1, 'SRM')

        # fit it one more time, starting from fitted parameters
        f1.SetParameters(f1.GetParameters())
        fitresult = histo.Fit(f1, 'SRM')
        # ... and one more time
        f1.SetParameters(f1.GetParameters())
        fitresult = histo.Fit(f1, 'SRM')
        # ... and one more time
        f1.SetParameters(f1.GetParameters())
        fitresult = histo.Fit(f1, 'SRM')

    else:
        # do one first fit on the full range
        f1 = TF1('f1', 'gaus', 0.4, 2.)
        f1.SetParameter(0, 200)
        f1.SetParameter(1, histo.GetMean())
        f1.SetParameter(2, histo.GetRMS())
        fitresult = histo.Fit(f1, 'SRM')

        # then set the initial parameters to the fit parameters and restrict to +/- 3 sigma
        mean = f1.GetParameter(1)
        sigma = f1.GetParameter(2)
        f1.SetParameter(1, mean)
        f1.SetParameter(2, sigma)
        f1.SetRange(mean - 3 * sigma, mean + 3 * sigma)
        fitresult = histo.Fit(f1, 'SRM')

        # then re-set the initial parameters to the fit parameters and restrict to +/- 2 sigma
        mean = f1.GetParameter(1)
        sigma = f1.GetParameter(2)
        f1.SetParameter(1, mean)
        f1.SetParameter(2, sigma)
        f1.SetRange(mean - 2 * sigma, mean + 2 * sigma)
        fitresult = histo.Fit(f1, 'SRM')


#    mean = f1.GetParameter(1)
#    sigma = f1.GetParameter(2)
#    f1.SetParameter(1, mean)
#    f1.SetParameter(2, sigma)
#    f1.SetRange(mean-2*sigma, mean+2*sigma)
#    fitresult = histo.Fit(f1, 'SRM')

    c = TCanvas()
    histo.Draw('PE')
    #fitresult = histo.Fit(f1, 'RS')
    f1.Draw('same')
    # save later

    ###################
    # Efficiency
    ##################
    hpass = TH1F('hpass', 'hpass', 1, 0., 1.)
    #Npass = histo.GetEntries()
    #Npass = histo.Integral(6,histo.FindLastBinAbove(0.)) # 0.2 cut in EoverEtrue
    Npass = histo.Integral(histo.FindBin(0.4), histo.FindBin(1.4))

    # does it make sense to instead compute efficiency only in +-3 sigma fitted peak
    for i in range(0, int(Npass)):
        hpass.Fill(0.5)

    htot = TH1F('htot', 'htot', 1, 0., 1.)
    histonameFull = 'h_genP_nEvts_Eta{eta}_Et{Et}'.format(eta=eta, Et=et)
    h_genP = f.Get('{}/{}/{}'.format(inputdir, subdir, histonameFull))
    Ntot = h_genP.GetEntries()
    for i in range(0, int(Ntot)):
        htot.Fill(0.5)

    print 'eff calculated from npass {} over ntot {}'.format(
        hpass.GetEntries(), htot.GetEntries())

    if TEfficiency.CheckConsistency(hpass, htot):
        pEff = TEfficiency(hpass,
                           htot)  # default stat option is clopper pearson
        eff = pEff.GetEfficiency(1)
        erru = pEff.GetEfficiencyErrorUp(1)
        errd = pEff.GetEfficiencyErrorLow(1)
    else:
        eff = 1.0
        erru = 1.0
        errd = 1.0
    eff_label = '{:.4f}+/-{:.4f}'.format(eff,
                                         erru)  # erru and errd are the same
    #fout = open(det + '_' + outfile, 'a')
    #fout.write('Total efficiency for seeding={} gathering={}:  {} \n'.format(iseeding,igathering,eff_label))
    #fout.close()

    eff_label = 'N_{{reco}}/N_{{gen}}={}'.format(eff_label)
    defaultLabels([eff_label],
                  x=0.62,
                  y=0.65,
                  spacing=0.04,
                  size=0.06,
                  dx=0.12)

    #sample_label = '#gamma#gamma, no tracker'
    sample_label = anaLabel
    et_label = 'Et=({},{})GeV'.format(et.split('_')[0], et.split('_')[1])
    eta_label = 'Region=({},{})'.format(eta.split('_')[0], eta.split('_')[1])
    defaultLabels([sample_label, et_label, eta_label],
                  x=0.25,
                  y=0.85,
                  spacing=0.04,
                  size=0.06,
                  dx=0.12)

    ###################
    # RESULTS
    ##################
    c.SaveAs('{o}/EoverEtrue_Eta{eta}_Et{et}_s{s}_g{g}.pdf'.format(
        o=outputdir, eta=eta, s=iseeding, g=igathering, et=et))
    c.SaveAs('{o}/EoverEtrue_Eta{eta}_Et{et}_s{s}_g{g}.png'.format(
        o=outputdir, eta=eta, s=iseeding, g=igathering, et=et))

    return True, EoverEtrueAnalysisResult(eta=eta,
                                          et=et,
                                          eff=eff,
                                          erreff=erru,
                                          mean=f1.GetParameter(1),
                                          errmean=f1.GetParError(1),
                                          sigma=f1.GetParameter(2),
                                          errsigma=f1.GetParError(2),
                                          rms=histo.GetRMS(),
                                          errrms=histo.GetRMSError(),
                                          iseeding=iseeding,
                                          igathering=igathering)
Esempio n. 5
0
    # Read cached results from tsv file
    e, n = np.loadtxt(path, delimiter=" ").transpose()  # MeV, #
    # Determine bin width
    wvl = 4.135667516e-15 * 299792458.0 / e * 1e3
    wvl_min = min(wvl)
    wvl_max = max(wvl)
    nbins = int((wvl_max - wvl_min) / args.bin_width)
    eff = TEfficiency("%d-pass" % i, "%d-eff" % i, nbins, wvl_min, wvl_max)
    eff.SetUseWeightedEvents()
    eff.SetStatisticOption(TEfficiency.kFNormal)
    for wvli, ni in zip(wvl, n):
        eff.FillWeighted(True, ni, wvli)
        eff.FillWeighted(False, n_particles - ni, wvli)
    x = np.array(
        [eff.GetTotalHistogram().GetBinCenter(i) for i in xrange(nbins)])
    y = np.array([eff.GetEfficiency(i) for i in xrange(nbins)]) * 100.0
    yerr_low = np.array([
        eff.ClopperPearson(int(n_particles),
                           int(eff.GetEfficiency(i) * n_particles), 0.68,
                           False) for i in xrange(nbins)
    ]) * 100.0
    yerr_up = np.array([
        eff.ClopperPearson(int(n_particles),
                           int(eff.GetEfficiency(i) * n_particles), 0.68, True)
        for i in xrange(nbins)
    ]) * 100.0
    # Plot bin statistics.
    label = ("%s +%.1f V" % (name, v_ov * 1e6))
    # Plot PDE
    ax.errorbar(x, y, yerr=(y - yerr_low, yerr_up - y), fmt=".", label=label)
Esempio n. 6
0
eff.SetMarkerColor(ROOT.kBlack)
eff.SetLineColor(ROOT.kBlack)
eff.SetMarkerStyle(20)

x = []
y = []
exl = []
exh = []
eyl = []
eyh = []

for i in xrange(hAll.GetNbinsX()):
    x.append(hAll.GetBinCenter(i + 1))
    exl.append(0)
    exh.append(0)
    y.append(eff.GetEfficiency(i + 1))
    eyl.append(eff.GetEfficiencyErrorLow(i + 1))
    eyh.append(eff.GetEfficiencyErrorUp(i + 1))

vx = array('d', x)
vy = array('d', y)
vexl = array('d', exl)
vexh = array('d', exh)
veyl = array('d', eyl)
veyh = array('d', eyh)

gEff = TGraphAsymmErrors(hAll.GetNbinsX(), vx, vy, vexl, vexh, veyl, veyh)

gEff.SetMarkerColor(ROOT.kBlack)
gEff.SetLineColor(ROOT.kBlack)
gEff.SetMarkerStyle(20)
def get_mean_efficiency(array_pass, array_total, method=0):
    ''' Function to calculate the mean and the error of the efficiency using different approaches.
    No good approach was found.

    Parameters
    ---------
    array_pass : numpy array
        Array with tracks that were seen by the DUT. Can be a masked array.
    array_total : numpy array
        Array with total tracks in the DUT. Can be a masked array.
    method: number
        Select the method to calculate the efficiency:
          1: Take mean and RMS of the efficiency per bin. Each bin is weightd by the number of total tracks.
             Results in symmetric unphysical error bars that cover also efficiencies > 100%
          2: Takes a correct binomial distribution and calculate the correct confidence interval after combining all pixels.
             Gives correct mean and correct statistical error bars. Systematic efficiency variations are not taken into account, thus
             the error bar is very small. Further info: https://root.cern.ch/doc/master/classTEfficiency.html
          3: As 2. but for each efficiency bin separately. Then the distribution is fitted by a constant using the
             asymmetric error bars. Gives too high efficiencies and small,  asymmetric error bars.
          4: Use a special Binomial efficiency fit. Gives best mean efficiency but unphysical symmetric error
             bars. Further info: https://root.cern.ch/doc/master/classTBinomialEfficiencyFitter.html
    '''

    n_bins = np.ma.count(array_pass)
    logging.info('Calculate the mean efficiency from %d pixels', n_bins)

    if method == 0:

        def weighted_avg_and_std(
            values, weights
        ):  # http://stackoverflow.com/questions/2413522/weighted-standard-deviation-in-numpy
            average = np.average(values, weights=weights)
            variance = np.average(
                (values - average)**2,
                weights=weights)  # Fast and numerically precise
            return (average, np.sqrt(variance))

        efficiency = np.ma.compressed(array_pass) / np.ma.compressed(
            array_total)
        return weighted_avg_and_std(efficiency, np.ma.compressed(array_total))
    else:  # Use CERN ROOT
        try:
            from ROOT import TH1D, TEfficiency, TF1, TBinomialEfficiencyFitter
        except ImportError:
            raise RuntimeError(
                'To use these method you have to install CERN ROOT with python bindings.'
            )

        # Convert not masked numpy array values to 1D ROOT double histogram
        def fill_1d_root_hist(array, name):
            length = np.ma.count(array_pass)
            root_hist = TH1D(name, "hist", length, 0, length)
            for index, value in enumerate(np.ma.compressed(array).ravel()):
                root_hist.SetBinContent(index, value)
            return root_hist

        if method == 1:
            # The following combines all pixel and gives correct
            # statistical errors but does not take the systematic
            # variations of within the  efficiency histogram parts into account
            # Thus gives very small error bars
            hist_pass = TH1D("hist_pass", "hist", 1, 0, 1)
            hist_total = TH1D("hist_total", "hist", 1, 0, 1)
            hist_pass.SetBinContent(0, np.ma.sum(array_pass))
            hist_total.SetBinContent(0, np.ma.sum(array_total))
            efficiency = TEfficiency(hist_pass, hist_total)
            return efficiency.GetEfficiency(
                0), efficiency.GetEfficiencyErrorLow(
                    0), efficiency.GetEfficiencyErrorUp(0)
        elif method == 2:
            # The following fits the efficiency with a constant but
            # it gives symmetric error bars, thus unphysical results
            # This is not understood yet and thus not used

            # Convert numpy array to ROOT hists
            hist_pass = fill_1d_root_hist(array_pass, 'h_pass')
            hist_total = fill_1d_root_hist(array_total, 'h_total')
            f1 = TF1("f1", "pol0(0)", 0, n_bins)
            fitter = TBinomialEfficiencyFitter(hist_pass, hist_total)
            r = fitter.Fit(f1, "SE")
            eff_err_low = r.LowerError(0)
            eff_err_up = r.UpperError(0)
            efficiency = r.GetParams()[0]
            return efficiency, eff_err_low, eff_err_up
        elif method == 3:
            # Fit point of each efficiency bin using asymmetric error bars
            # Parameters described here: https://root.cern.ch/doc/master/classTGraph.html#a61269bcd47a57296f0f1d57ceff8feeb
            # This gives too high efficiency and too small error

            # Convert numpy array to ROOT hists
            hist_pass = fill_1d_root_hist(array_pass, 'h_pass')
            hist_total = fill_1d_root_hist(array_total, 'h_total')
            efficiency = TEfficiency(hist_pass, hist_total)
            f1 = TF1("f1", "pol0(0)", 0, n_bins)
            fit_result = efficiency.CreateGraph().Fit(f1, "SFEM")
            eff_mean = fit_result.GetParams()[0]
            eff_err_low = fit_result.LowerError(0)
            eff_err_up = fit_result.UpperError(0)
            return eff_mean, eff_err_low, eff_err_up
Esempio n. 8
0
  def fillAcceptance(self):
    '''
    This is to calculate the acceptance of the sample
    '''
    if debug: print('Info in Sample.fillAcceptance()')
    #f = TFile.Open(self.infileName)
    #t = f.Get(self.treeName)
    #if not t:
    #  raise RuntimeError( 'ERROR: no tree in file %s' % self.infileName)
    chain = TChain(self.treeName)
    for fn in self.infileNames:
      chain.Add(fn)

    self.effnum  = ROOT.TH1F('effnum', 'effnum', 1, 0, 13000) 
    self.effden  = ROOT.TH1F('effden', 'effden', 1, 0, 13000)
    self.effnumB = dict([(b, ROOT.TH1F('effnum_%s' % b, 'effnum_%s' % b, 1, 0, 13000)) for b in self.Bspecies])
    self.effdenB = dict([(b, ROOT.TH1F('effden_%s' % b, 'effden_%s' % b, 1, 0, 13000)) for b in self.Bspecies])

    #if doInclusive:
    cutsnum = '(l0_pt>{mp} && abs(l0_eta)<1.5'.format(mp=muTrigPt)
    #else: 
    #cutsnum = '(l0_pt>{mp} && abs(l0_eta)<1.5 && k_pt>1 && abs(k_eta)<2.5 && pi_pt>1 && abs(pi_eta)<2.5'.format(mp=muTrigPt) 
    if doSkipDispl:
      cutsnum += ''
    else:
      cutsnum += '&& Lxy < 500'
    if not doDisplZ:
      pass
    else:
      cutsnum += '&& Lz < 20'
    if doSkipHNLptEta:
      cutsnum += ''
    else:
      cutsnum += '&& l1_pt>3 && abs(l1_eta)<2.5 && pi1_pt>0.8 && abs(pi1_eta)<2.5'
    
    cutsnum += ')'


    cutsden = '(l0_pt>{mp} && abs(l0_eta)<1.5)'.format(mp=muTrigPt)

    
    ###### fill the total acceptance
    chain.Draw('hnl_pt>>effnum', cutsnum+'*'+self.evt_w, 'goff')
    chain.Draw('hnl_pt>>effden', cutsden, 'goff')
 
    if TEfficiency.CheckConsistency(self.effnum,self.effden): 
      peff = TEfficiency(self.effnum,self.effden)
     
      # check usage of TGraphAsymmetricErrors
      self.acc = peff.GetEfficiency(1)
      self.acc_errup = peff.GetEfficiencyErrorUp(1)
      self.acc_errdn = peff.GetEfficiencyErrorLow(1)

    tgra = TGraphAsymmErrors()
    tgra.BayesDivide(self.effnum, self.effden)
    self.acc_tg = tgra.GetY()[0]
    self.acc_errup_tg = tgra.GetErrorYhigh(0)
    self.acc_errdn_tg = tgra.GetErrorYlow(0)

    # for debugging purposes
    self.num = self.effnum.GetEntries()
    if self.num==0: print('**** 0 entries for mass={}'.format(self.mass))
    self.den = self.effden.GetEntries()

    ###### fill the partial acceptances 
    for ib,b in enumerate(self.Bspecies):
      bsel   = '(abs(b_pdgid)=={bid})'.format(bid=self.BpdgIds[ib])
      selnum = '(' + cutsnum + '&&' + bsel + ')' 
      selden = '(' + cutsden + '&&' + bsel + ')'
      chain.Draw('hnl_pt>>effnum_{b}'.format(b=b), selnum + '*' + self.evt_w, 'goff')
      chain.Draw('hnl_pt>>effden_{b}'.format(b=b), selden, 'goff')

      if TEfficiency.CheckConsistency(self.effnumB[b],self.effdenB[b]):
        peff = TEfficiency(self.effnumB[b],self.effdenB[b])
        
        self.accB[b]       = peff.GetEfficiency(1)
        self.accB_errup[b] = peff.GetEfficiencyErrorUp(1)
        self.accB_errdn[b] = peff.GetEfficiencyErrorLow(1)

      else:
        self.accB[b] = 0
        self.accB_errup[b] = 0
        self.accB_errdn[b] = 0