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()
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)
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) fit = TF1('fit',
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
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