def getSignalEfficiency(self): ''' eff(bin) = N_flat(bin) / N_gen N_gen = N_reco / filter_efficiency ''' # get number of generated events f = ROOT.TFile.Open('root://t3dcachedb.psi.ch:1094/'+self.signal_file.filename, 'READ') n_reco = PlottingTools.getNminiAODEvts(self, f) n_gen = n_reco / self.signal_file.filter_efficiency # get number of selected reco events quantity = Quantity(name_flat='hnl_mass', nbins=1, bin_min=0, bin_max=1000) hist_flat_bin = PlottingTools.createHisto(self, f, 'signal_tree', quantity, branchname='flat', selection='ismatched==1' if self.selection=='' else 'ismatched==1 && '+self.selection) n_selected_bin = hist_flat_bin.GetBinContent(1) #print 'n_selected_bin',n_selected_bin efficiency = n_selected_bin / n_gen #print 'efficiency',efficiency return efficiency
def computeWeightQCDMCtoData(self, lumi_data): ''' weight = lumi_data / lumi_mc ''' # get lumi mc lumi_mc = 0 for ifile, qcd_file in enumerate(self.qcd_files): if qcd_file.label not in self.white_list: continue f_mc = ROOT.TFile.Open('root://t3dcachedb.psi.ch:1094/'+qcd_file.filename, 'READ') weight = PlottingTools.computeQCDMCWeight(self, PlottingTools.getTree(self, f_mc, 'signal_tree'), qcd_file.cross_section, qcd_file.filter_efficiency) weight_mc = 1./weight lumi_mc += weight_mc weight = lumi_data / lumi_mc err = 0. return weight, err
def computeApproxWeightQCDMCtoData(self, quantity, selection): ''' weight = lumi_data / lumi_mc = N_data * sigma_mc / (N_mc * sigma_data) estimated as N_data / N_mc ''' f_data = ROOT.TFile.Open('root://t3dcachedb.psi.ch:1094/'+self.data_file.filename, 'READ') hist_data = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=selection) hist_data.Sumw2() n_obs_data = hist_data.GetBinContent(1) n_err_data = math.sqrt(n_obs_data) #hist_data.GetBinError(1) hist_mc_tot = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=selection) n_obs_mc = hist_mc_tot.GetBinContent(1) n_err_mc = math.sqrt(n_obs_mc) #hist_mc_tot.GetBinError(1) weight = n_obs_data / n_obs_mc if n_obs_data != 0 and n_obs_mc != 0: err = weight* (n_err_data / n_obs_data + n_err_mc / n_obs_mc) else: err = 0 return weight, err
def computeCrossRatioFromQCDMC(self): ''' Study the correlation of two variables computing the ratio r = N_A * ND / N_B * N_C ''' quantity = Quantity(name_flat='hnl_mass', nbins=1, bin_min=0, bin_max=5.4) #hist_mc_tot_A = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge==0') #hist_mc_tot_A = self.getHistoMC(quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && hnl_charge==0') #hist_mc_tot_A = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge==0') hist_mc_tot_A = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && sv_prob>0.05') #hist_mc_tot_B = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge!=0') #hist_mc_tot_B = self.getHistoMC(quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && hnl_charge!=0') #hist_mc_tot_B = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge!=0') hist_mc_tot_B = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && sv_prob<0.05') #hist_mc_tot_C = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge==0') #hist_mc_tot_C = self.getHistoMC(quantity=quantity, selection=self.selection+' && hnl_cos2d<0.993 && hnl_charge==0') #hist_mc_tot_C = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge==0') hist_mc_tot_C = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d<0.993 && sv_prob>0.05') #hist_mc_tot_D = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge!=0') #hist_mc_tot_D = self.getHistoMC(quantity=quantity, selection=self.selection+' && hnl_cos2d<0.993 && hnl_charge!=0') #hist_mc_tot_D = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge!=0') hist_mc_tot_D = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d<0.993 && sv_prob<0.05') n_obs_mc_A = hist_mc_tot_A.GetBinContent(1) n_obs_mc_B = hist_mc_tot_B.GetBinContent(1) n_obs_mc_C = hist_mc_tot_C.GetBinContent(1) n_obs_mc_D = hist_mc_tot_D.GetBinContent(1) n_err_mc_A = hist_mc_tot_A.GetBinError(1) #math.sqrt(n_obs_mc_A) n_err_mc_B = hist_mc_tot_B.GetBinError(1) #math.sqrt(n_obs_mc_B) n_err_mc_C = hist_mc_tot_C.GetBinError(1) #math.sqrt(n_obs_mc_C) n_err_mc_D = hist_mc_tot_D.GetBinError(1) #math.sqrt(n_obs_mc_D) ratio = n_obs_mc_A*n_obs_mc_D/(n_obs_mc_B*n_obs_mc_C) err = ratio * (n_err_mc_A/n_obs_mc_A + n_err_mc_B/n_obs_mc_B + n_err_mc_C/n_obs_mc_C + n_err_mc_D/n_obs_mc_D) return ratio, err
def computeBkgYieldsFromABCDData(self): ''' Estimate background yields from data using the ABCD method A = b_mass < 6.27 && hnl_charge == 0 (SR) B = b_mass < 6.27 && hnl_charge != 0 C = b_mass > 6.27 && hnl_charge == 0 D = b_mass > 6.27 && hnl_charge != 0 N_A = N_B * N_C/N_D ''' f_data = ROOT.TFile.Open('root://t3dcachedb.psi.ch:1094/'+self.data_file.filename, 'READ') #quantity = Quantity(name_flat='hnl_mass', nbins=1, bin_min=0, bin_max=1000) quantity = Quantity(name_flat='hnl_mass', nbins=1, bin_min=2.83268, bin_max=3.13932) bin_selection = self.selection #hist_data_B = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=bin_selection+' && b_mass<6.27 && hnl_charge!=0') #hist_data_C = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=bin_selection+' && b_mass>6.27 && hnl_charge==0') #hist_data_D = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=bin_selection+' && b_mass>6.27 && hnl_charge!=0') hist_data_B = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=bin_selection+' && hnl_cos2d>0.993 && sv_prob<0.05') hist_data_C = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=bin_selection+' && hnl_cos2d<0.993 && sv_prob>0.05') hist_data_D = PlottingTools.createHisto(self, f_data, 'signal_tree', quantity, branchname='flat', selection=bin_selection+' && hnl_cos2d<0.993 && sv_prob<0.05') #hist_data.Sumw2() n_obs_data_B = hist_data_B.GetBinContent(1) n_obs_data_C = hist_data_C.GetBinContent(1) n_obs_data_D = hist_data_D.GetBinContent(1) n_err_data_B = math.sqrt(hist_data_B.GetBinContent(1)) n_err_data_C = math.sqrt(hist_data_C.GetBinContent(1)) n_err_data_D = math.sqrt(hist_data_D.GetBinContent(1)) n_obs_data_A = n_obs_data_B * (n_obs_data_C / n_obs_data_D) n_err_data_A = n_obs_data_A * (n_err_data_B / n_obs_data_B + n_err_data_C / n_obs_data_C + n_err_data_D / n_obs_data_D) return int(n_obs_data_A), int(n_err_data_A)
def __init__(self, filename, treename='Events', matchings=None, cuts=None, displacement_bins=None, pt_bins=None, title='', outdirlabel='default'): self.filename = filename self.treename = treename self.matchings = matchings self.displacement_bins = displacement_bins self.pt_bins = pt_bins #self.bins = bins # for 1D plot bins can either be in displacement or in pt self.cuts = cuts self.title = title self.outdirlabel = outdirlabel self.outputdir = PlottingTools.getOutDir(self, './myPlots/efficiency', self.outdirlabel)
def computeBkgYieldsFromMC(self): ''' QCD MC (background) yields are computed as N_exp(SR) = N_obs(SR) * weight(CR) ''' #quantity = Quantity(name_flat='hnl_mass', nbins=1, bin_min=0, bin_max=1000) quantity = Quantity(name_flat='hnl_mass', nbins=1, bin_min=2.83268, bin_max=3.13932) selection_extra = self.selection # we compute the weight in the control region weight, err_weight = self.computeApproxWeightQCDMCtoData(quantity, selection=('hnl_charge!=0' if selection_extra=='' else 'hnl_charge!=0 &&' + selection_extra)) #weight, err_weight = self.computeWeightQCDMCtoData(lumi_data=774) #hist_mc_tot = self.getHistoMC(quantity=quantity, selection='hnl_charge==0' if selection_extra=='' else 'hnl_charge==0 &&' + selection_extra) hist_mc_tot = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection='hnl_charge==0' if selection_extra=='' else 'hnl_charge==0 &&' + selection_extra) n_obs_mc = hist_mc_tot.GetBinContent(1) n_err_mc = math.sqrt(n_obs_mc) #hist_mc_tot.GetBinError(1) n_exp_mc = n_obs_mc * weight err = n_exp_mc * (n_err_mc / n_obs_mc + err_weight / weight) return int(n_exp_mc), int(err), weight
def validateABCDOnQCDMC(self, plot_name='closure', label=''): ''' Get mupi mass ditribution from data using the ABCD method A = b_mass < 6.27 && hnl_charge == 0 (SR) B = b_mass < 6.27 && hnl_charge != 0 C = b_mass > 6.27 && hnl_charge == 0 D = b_mass > 6.27 && hnl_charge != 0 and compare it to the actual distribution in the SR ''' #quantity = Quantity(name_flat='hnl_mass', nbins=100, bin_min=0, bin_max=5.6) quantity = Quantity(name_flat='hnl_mass', nbins=50, bin_min=0, bin_max=5.37) bin_selection = self.selection #hist_mc_tot_A = self.getHistoMC(quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && sv_prob>0.05') #hist_mc_tot_B = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge!=0') #hist_mc_tot_C = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge==0') #hist_mc_tot_D = self.getHistoMC(quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge!=0') #hist_mc_tot_A = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge==0') #hist_mc_tot_B = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass<6.27 && hnl_charge!=0') #hist_mc_tot_C = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge==0') #hist_mc_tot_D = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && b_mass>6.27 && hnl_charge!=0') hist_mc_tot_A = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && sv_prob>0.05') hist_mc_tot_B = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d>0.993 && sv_prob<0.05') hist_mc_tot_C = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d<0.993 && sv_prob>0.05') hist_mc_tot_D = PlottingTools.createWeightedHistoQCDMC(self, self.qcd_files, self.white_list, quantity=quantity, selection=self.selection+' && hnl_cos2d<0.993 && sv_prob<0.05') #hist_estimate = ROOT.TH1D('hist_estimate', 'hist_estimate', 100, 0, 5.6) hist_estimate = ROOT.TH1D('hist_estimate', 'hist_estimate', 50, 0, 5.37) for ibin in range(1, hist_mc_tot_B.GetNbinsX()+1): n_obs_mc_B = hist_mc_tot_B.GetBinContent(ibin) n_obs_mc_C = hist_mc_tot_C.GetBinContent(ibin) n_obs_mc_D = hist_mc_tot_D.GetBinContent(ibin) n_err_mc_B = hist_mc_tot_B.GetBinError(ibin) n_err_mc_C = hist_mc_tot_C.GetBinError(ibin) n_err_mc_D = hist_mc_tot_D.GetBinError(ibin) content = n_obs_mc_B * (n_obs_mc_C / n_obs_mc_D) if n_obs_mc_C != 0 and n_obs_mc_D != 0 else 0 err = content * (n_err_mc_B / n_obs_mc_B + n_err_mc_C / n_obs_mc_C + n_err_mc_D / n_obs_mc_D) if n_obs_mc_B!=0 and n_obs_mc_C!=0 and n_obs_mc_D!=0 else 0 hist_estimate.SetBinContent(ibin, content) hist_estimate.SetBinError(ibin, err) ROOT.gStyle.SetOptStat(0) canv = PlottingTools.getTCanvas(self, 'canv', 800, 900) pad_up = ROOT.TPad("pad_up","pad_up",0,0.25,1,1) pad_up.SetBottomMargin(0.03) pad_up.Draw() canv.cd() pad_down = ROOT.TPad("pad_down","pad_down",0,0,1,0.25) pad_down.SetBottomMargin(0.25) pad_down.Draw() hist_estimate.SetLineWidth(3) hist_estimate.SetLineColor(ROOT.kOrange) #hist_estimate.SetTitle('Closure of the ABCD method in the Signal Region') hist_estimate.SetTitle('') #hist_estimate.GetXaxis().SetTitle('#mu#pi invariant mass [GeV]') hist_estimate.GetXaxis().SetLabelSize(0.0) hist_estimate.GetXaxis().SetTitleSize(0.0) #hist_estimate.GetXaxis().SetTitleOffset(1.1) hist_estimate.GetYaxis().SetTitle('Entries') hist_estimate.GetYaxis().SetLabelSize(0.037) hist_estimate.GetYaxis().SetTitleSize(0.042) hist_estimate.GetYaxis().SetTitleOffset(1.1) #hist_estimate.GetYaxis().SetRangeUser(1e-9, self.getMaxRangeY(hist_estimate, hist_mc_stack, do_log)) hist_mc_tot_A.SetLineWidth(3) hist_mc_tot_A.SetLineColor(ROOT.kBlue) int_estimate = hist_estimate.Integral() hist_estimate.Scale(1/int_estimate) int_A = hist_mc_tot_A.Integral() hist_mc_tot_A.Scale(1/int_A) pad_up.cd() hist_estimate.Draw('histo') hist_mc_tot_A.Draw('histo same') legend = PlottingTools.getRootTLegend(self, xmin=0.55, ymin=0.65, xmax=0.8, ymax=0.85, size=0.043) legend.AddEntry(hist_estimate, 'QCD ABCD estimate') legend.AddEntry(hist_mc_tot_A, 'QCD true') legend.Draw() label_box = ROOT.TPaveText(0.65,0.4,0.8,0.6, "brNDC") label_box.SetBorderSize(0) label_box.SetFillColor(ROOT.kWhite) label_box.SetTextSize(0.042) label_box.SetTextAlign(11) label_box.SetTextFont(42) label_box.AddText(label) label_box.Draw() pad_down.cd() hist_ratio = PlottingTools.getRatioHistogram(self, hist_estimate, hist_mc_tot_A) hist_ratio.Sumw2() for ibin in range(0, hist_ratio.GetNbinsX()+1): if hist_estimate.GetBinContent(ibin) != 0 and hist_mc_tot_A.GetBinContent(ibin) != 0: #err = hist_ratio.GetBinContent(ibin) * (math.sqrt(hist_data.GetBinContent(ibin))/hist_data.GetBinContent(ibin) + math.sqrt(hist_mc_tot.GetBinContent(ibin))/hist_mc_tot.GetBinContent(ibin)) #err = math.sqrt((math.sqrt(hist_data.GetBinContent(ibin))/hist_mc_tot.GetBinContent(ibin))**2 + (math.sqrt(hist_mc_tot.GetBinContent(ibin))*hist_data.GetBinContent(ibin)/(hist_mc_tot.GetBinContent(ibin))**2)**2) #err = math.sqrt((hist_data.GetBinError(ibin)/hist_mc_tot.GetBinContent(ibin))**2 + (hist_mc_tot.GetBinError(ibin)*hist_data.GetBinContent(ibin)/(hist_mc_tot.GetBinContent(ibin))**2)**2) err = hist_ratio.GetBinContent(ibin) * (hist_estimate.GetBinError(ibin) / hist_estimate.GetBinContent(ibin) + hist_mc_tot_A.GetBinError(ibin) / hist_mc_tot_A.GetBinContent(ibin)) else: err = 0 if hist_ratio.GetBinContent(ibin) != 0: hist_ratio.SetBinError(ibin, err) hist_ratio.SetLineWidth(2) hist_ratio.SetLineColor(ROOT.kBlack) hist_ratio.SetMarkerStyle(20) hist_ratio.SetTitle('') hist_ratio.GetXaxis().SetTitle('#mu#pi invariant mass [GeV]') hist_ratio.GetXaxis().SetLabelSize(0.1) hist_ratio.GetXaxis().SetTitleSize(0.15) hist_ratio.GetXaxis().SetTitleOffset(0.73) hist_ratio.GetYaxis().SetTitle('Estimate/True') hist_ratio.GetYaxis().SetLabelSize(0.1) hist_ratio.GetYaxis().SetTitleSize(0.13) hist_ratio.GetYaxis().SetTitleOffset(0.345) #val_min = hist_ratio.GetBinContent(hist_ratio.GetMinimumBin()) #val_max = hist_ratio.GetBinContent(hist_ratio.GetMaximumBin()) hist_ratio.GetYaxis().SetRangeUser(-1, 3) hist_ratio.Draw('PE') line = ROOT.TLine(0, 1, 5.6, 1) line.SetLineColor(4) line.SetLineWidth(2) line.Draw('same') canv.cd() if not path.exists('./myPlots/ABCDClosure'): os.system('mkdir -p ./myPlots/ABCDClosure') canv.SaveAs('./myPlots/ABCDClosure/{}.png'.format(plot_name)) canv.SaveAs('./myPlots/ABCDClosure/{}.pdf'.format(plot_name)) canv.SaveAs('./myPlots/ABCDClosure/{}.C'.format(plot_name))
def getEfficiency(self, displacement_bins=None, pt_bins=None): f = ROOT.TFile.Open('root://t3dcachedb.psi.ch:1094/' + self.filename, 'READ') tree = PlottingTools.getTree(self, f, self.treename) if displacement_bins != None and pt_bins != None: n_num = np.zeros( (len(displacement_bins), len(pt_bins), len(self.matchings) )) #[[0] * len(displacement_bins)] * len(pt_bins) n_deno = np.zeros( (len(displacement_bins), len(pt_bins), len(self.matchings) )) #[[0] * len(displacement_bins)] * len(pt_bins) efficiency = np.zeros( (len(displacement_bins), len(pt_bins), len(self.matchings) )) #[[0] * len(displacement_bins)] * len(pt_bins) error = np.zeros( (len(displacement_bins), len(pt_bins), len(self.matchings) )) #[[0] * len(displacement_bins)] * len(pt_bins) else: n_num = np.zeros(len(self.cuts)) n_deno = np.zeros(len(self.cuts)) efficiency = np.zeros(len(self.cuts)) error = np.zeros(len(self.cuts)) for entry in tree: # only consider events with at least one candidate if entry.nBToMuMuPi == 0: continue #print '\n' # retrieve candidate matching information trgmu_ismatched = 0 mu_ismatched = 0 pi_ismatched = 0 cand_ismatched = 0 matched_idx = -1 for icand in range(0, entry.nBToMuMuPi): if entry.BToMuMuPi_trg_mu_isMatched[icand] == 1: trgmu_ismatched = 1 if entry.BToMuMuPi_sel_mu_isMatched[icand] == 1: mu_ismatched = 1 if entry.BToMuMuPi_pi_isMatched[icand] == 1: pi_ismatched = 1 if entry.BToMuMuPi_isMatched[icand] == 1: matched_idx = icand cand_ismatched = 1 matching_cond = {} matching_cond['candidate'] = cand_ismatched == 1 matching_cond['trigger_muon'] = trgmu_ismatched == 1 matching_cond['muon'] = mu_ismatched == 1 matching_cond['pion'] = pi_ismatched == 1 hnl_idx = -1 mother_idx = -1 trgmu_idx = -1 mu_idx = -1 pi_idx = -1 # search for hnl and its mother for igen in range(0, entry.nGenPart): if entry.GenPart_pdgId[igen] == 9900015: hnl_idx = igen mother_idx = entry.GenPart_genPartIdxMother[hnl_idx] # search for trigger muon and hnl daughters for igen in range(0, entry.nGenPart): if abs( entry.GenPart_pdgId[igen] ) == 13 and entry.GenPart_genPartIdxMother[igen] == mother_idx: trgmu_idx = igen if abs(entry.GenPart_pdgId[igen] ) == 13 and entry.GenPart_pdgId[ entry.GenPart_genPartIdxMother[igen]] == 9900015: mu_idx = igen if abs(entry.GenPart_pdgId[igen] ) == 211 and entry.GenPart_pdgId[ entry.GenPart_genPartIdxMother[igen]] == 9900015: pi_idx = igen # remove e-channel if mu_idx == -1: continue for imatch, matching in enumerate(self.matchings): if displacement_bins != None and pt_bins != None: # fetch n_deno and n_num with acceptance cuts if entry.GenPart_pt[mu_idx] > 1.5 and abs(entry.GenPart_eta[mu_idx]) < 2.5 \ and entry.GenPart_pt[pi_idx] > 0.7 and abs(entry.GenPart_eta[pi_idx]) < 2.5 \ and entry.GenPart_pt[trgmu_idx] > 7.5: #if entry.GenPart_pt[mu_idx] > 3.5 and abs(entry.GenPart_eta[mu_idx]) < 2.5 \ # and entry.GenPart_pt[pi_idx] > 0.7 and abs(entry.GenPart_eta[pi_idx]) < 2.5 \ # and entry.GenPart_pt[trgmu_idx] > 9.5: #if entry.GenPart_pt[mu_idx] > 0: displacement = math.sqrt( pow( entry.GenPart_vx[mu_idx] - entry.GenPart_vx[trgmu_idx], 2) + pow( entry.GenPart_vy[mu_idx] - entry.GenPart_vy[trgmu_idx], 2)) if matching == 'candidate': obj_pt = entry.GenPart_pt[hnl_idx] elif matching == 'trigger_muon': obj_pt = entry.GenPart_pt[trgmu_idx] elif matching == 'muon': obj_pt = entry.GenPart_pt[mu_idx] elif matching == 'pion': obj_pt = entry.GenPart_pt[pi_idx] for ibin_disp, displacement_bin in enumerate( displacement_bins): for ibin_pt, pt_bin in enumerate(pt_bins): bin_min_disp, bin_max_disp = displacement_bin bin_min_pt, bin_max_pt = pt_bin if displacement > bin_min_disp and displacement < bin_max_disp and obj_pt > bin_min_pt and obj_pt < bin_max_pt: n_deno[ibin_disp][ibin_pt][ imatch] = n_deno[ibin_disp][ibin_pt][ imatch] + 1 #print '{} {}'.format(matching, matching_cond[matching]) if matching_cond[matching]: n_num[ibin_disp][ibin_pt][ imatch] = n_num[ibin_disp][ ibin_pt][imatch] + 1 else: for icut, cut in enumerate(self.cuts): # fetch n_deno and n_num with acceptance cuts #if entry.GenPart_pt[mu_idx] > float(cut) and abs(entry.GenPart_eta[mu_idx]) < 2.5: # \ if entry.GenPart_pt[mu_idx] > 1.5 and abs(entry.GenPart_eta[mu_idx]) < 2.5 \ and entry.GenPart_pt[pi_idx] > 0.7 and abs(entry.GenPart_eta[pi_idx]) < 2.5 \ and entry.GenPart_pt[trgmu_idx] > float(cut): n_deno[icut] = n_deno[icut] + 1 if matching == 'candidate' and cand_ismatched == 1: n_num[icut] = n_num[icut] + 1 elif matching == 'trigger_muon' and trgmu_ismatched == 1: n_num[icut] = n_num[icut] + 1 elif matching == 'muon' and mu_ismatched == 1: n_num[icut] = n_num[icut] + 1 elif matching == 'pion' and pi_ismatched == 1: n_num[icut] = n_num[icut] + 1 # compute efficiency if displacement_bins != None and pt_bins != None: for imatch, matching in enumerate(self.matchings): for ibin_disp, displacement_bin in enumerate( displacement_bins): for ibin_pt, pt_bin in enumerate(pt_bins): efficiency[ibin_disp][ibin_pt][imatch] = float( n_num[ibin_disp][ibin_pt][imatch] ) / float(n_deno[ibin_disp][ibin_pt][imatch]) if float( n_deno[ibin_disp][ibin_pt][imatch]) != 0. else 0. if n_num[ibin_disp][ibin_pt][imatch] == 0: n_num[ibin_disp][ibin_pt][imatch] = 1e-11 if float(n_num[ibin_disp][ibin_pt] [imatch]) != 0 and float( n_deno[ibin_disp][ibin_pt][imatch]) != 0: error[ibin_disp][ibin_pt][imatch] = efficiency[ ibin_disp][ibin_pt][imatch] * ( math.sqrt( float(n_num[ibin_disp][ibin_pt] [imatch])) / float(n_num[ibin_disp][ibin_pt][imatch]) + math.sqrt( float(n_deno[ibin_disp][ibin_pt] [imatch])) / float(n_deno[ibin_disp][ibin_pt][imatch])) else: error[ibin_disp][ibin_pt][imatch] = 0 # for aesthetics if efficiency[ibin_disp][ibin_pt][imatch] == 0.: efficiency[ibin_disp][ibin_pt][imatch] = 1e-9 for imatch, matching in enumerate(self.matchings): print '\n' for ibin_disp, displacement_bin in enumerate( displacement_bins): for ibin_pt, pt_bin in enumerate(pt_bins): print '{} {} {} {} {} {}+-{}'.format( matching, displacement_bin, pt_bin, n_deno[ibin_disp][ibin_pt][imatch], n_num[ibin_disp][ibin_pt][imatch], efficiency[ibin_disp][ibin_pt][imatch], error[ibin_disp][ibin_pt][imatch]) else: for icut, cut in enumerate(self.cuts): efficiency[icut] = float(n_num[icut]) / float( n_deno[icut]) if float(n_deno[icut]) != 0. else 0. error[icut] = efficiency[icut] * ( math.sqrt(n_num[icut]) / n_num[icut] + math.sqrt(n_deno[icut]) / n_deno[icut]) #for icut, cut in enumerate(self.cuts): # print '{} {} {} {}'.format(cut, n_deno[icut], n_num[icut], efficiency[icut]) return efficiency, error