def load_tree(infiles): from rootpy.tree import TreeChain from rootpy.ROOT import gROOT gROOT.SetBatch(True) print('[INFO] Opening files: {0}'.format(infiles)) tree = TreeChain('ntupler/tree', infiles) tree.define_collection(name='hits', prefix='vh_', size='vh_size') tree.define_collection(name='simhits', prefix='vc_', size='vc_size') tree.define_collection(name='tracks', prefix='vt_', size='vt_size') tree.define_collection(name='particles', prefix='vp_', size='vp_size') return tree
class MuonTypeLJEvents(object): def __init__(self, files=None, type='MC', maxevents=-1): if type.upper() not in ['MC', 'DATA']: raise ValueError("Argument `type` need to be MC/DATA") self.Type = type self.MaxEvents = maxevents if not files: raise ValueError("Argument `files` need to be non-empty") if isinstance(files, str): files = [ files, ] self.Chain = TreeChain('ffNtuplizer/ffNtuple', files) ## register collections ### self.Chain.define_collection('pvs', prefix='pv_', size='pv_n') self.Chain.define_collection('muons', prefix='muon_', size='muon_n') self.Chain.define_collection('dsamuons', prefix='dsamuon_', size='dsamuon_n') self.Chain.define_collection('ak4jets', prefix='akjet_ak4PFJetsCHS_', size='akjet_ak4PFJetsCHS_n') self.Chain.define_collection('leptonjets', prefix='pfjet_', size='pfjet_n', mix=LeptonJetMix) self.Chain.define_collection('trigobjs', prefix='trigobj_', size='trigobj_n') self.Chain.define_object('hlt', prefix='HLT_') self.Chain.define_object('metfilters', prefix='metfilters_') self.Chain.define_object('cosmicveto', prefix='cosmicveto_') self.Histos = {} self.LookupWeight = root_open( os.path.join( os.getenv('CMSSW_BASE'), 'src/FireROOT/Analysis/data/puWeights_10x_56ifb.root')).Get( 'puWeights') self.Scale = 1. def bookHisto(self, name, hist): self.Histos[name] = hist def setScale(self, scale): self.Scale = scale def process(self): for i, event in enumerate(self.Chain): if self.MaxEvents > 0 and i > self.MaxEvents: break ## event-level mask ## if not event.cosmicveto.result: continue if not event.metfilters.PrimaryVertexFilter: continue aux = {} ## event weight ## aux['wgt'] = self.Scale if self.Type == 'MC': aux['wgt'] *= event.weight # gen weight aux['wgt'] *= self.LookupWeight.GetBinContent( self.LookupWeight.GetXaxis().FindBin( event.trueInteractionNum)) ## pileup correction leptonjets = [ lj for lj in event.leptonjets if lj.passSelection(event) ] leptonjets.sort(key=lambda lj: lj.p4.pt(), reverse=True) leptonjets = leptonjets[:2] muontypeljs = [lj for lj in leptonjets if lj.isMuonType()] egmtypeljs = [lj for lj in leptonjets if lj.isEgmType()] # if not muontypeljs: continue aux['muontype'] = muontypeljs aux['egmtype'] = egmtypeljs aux['leptonjets'] = leptonjets looseMuonIdx, mediumMuonIdx = [], [] for i, mu in enumerate(event.muons): if mu.p4.pt() < 5: continue if abs(mu.p4.eta()) > 2.4: continue if (mu.selectors & (1 << 0)) != (1 << 0): continue # ID-loose if (mu.selectors & (1 << 7)) != (1 << 7): continue # Iso-loose looseMuonIdx.append(i) if (mu.selectors & (1 << 1)) != (1 << 1): continue # ID-medium mediumMuonIdx.append(i) if not mediumMuonIdx: continue muonpairs = [] for m in mediumMuonIdx: for l in looseMuonIdx: if m == l: continue if (l, m) in muonpairs: continue muonpairs.append((m, l)) if not muonpairs: continue aux['muonpairs'] = muonpairs self.processEvent(event, aux) def processEvent(self, event, aux): """To be override by daughter class""" pass @property def histos(self): return self.Histos
class Events(object): def __init__(self, files=None, outname=None, type='MC', dtag='', maxevents=-1, channel=['4mu', '2mu2e'], ctau=None, chargedlj=False): if type.upper() not in ['MC', 'DATA']: raise ValueError("Argument `type` need to be MC/DATA") self.OutName = outname self.Type = type.upper() self.ChargedLJ = chargedlj self.MaxEvents = maxevents self.Channel = channel self.Dtag = dtag self.Ctau = ctau __signal_sample_param = dict( [substr.split('-') for substr in self.Dtag.split('_')]) self.SignalParam = { k.upper(): float(v.replace('p', '.')) for k, v in __signal_sample_param.items() } if not files: raise ValueError("Argument `files` need to be non-empty") if isinstance(files, str): files = [ files, ] self.Chain = TreeChain('ffNtuplizer/ffNtuple', files) ### register collections ### # self.Chain.define_collection('pvs', prefix='pv_', size='pv_n') self.Chain.define_collection('electrons', prefix='electron_', size='electron_n') self.Chain.define_collection('muons', prefix='muon_', size='muon_n') self.Chain.define_collection('dsamuons', prefix='dsamuon_', size='dsamuon_n') self.Chain.define_collection('photons', prefix='photon_', size='photon_n') self.Chain.define_collection('ak4jets', prefix='akjet_ak4PFJetsCHS_', size='akjet_ak4PFJetsCHS_n') self.Chain.define_collection('hftagscores', prefix='hftagscore_', size='hftagscore_n') self.Chain.define_collection('leptonjets', prefix='pfjet_', size='pfjet_n', mix=LeptonJetMix) self.Chain.define_collection('ljsources', prefix='ljsource_', size='ljsource_n') self.Chain.define_collection('cosmicmuons', prefix='cosmicmuon_', size='cosmicmuon_n') self.Chain.define_collection('trigobjs', prefix='trigobj_', size='trigobj_n') # self.Chain.define_collection('',) self.Chain.define_object('hlt', prefix='HLT_') self.Chain.define_object('metfilters', prefix='metfilters_') self.Chain.define_object('cosmicveto', prefix='cosmicveto_') self.Triggers = [ "DoubleL2Mu23NoVtx_2Cha", "DoubleL2Mu23NoVtx_2Cha_NoL2Matched", "DoubleL2Mu23NoVtx_2Cha_CosmicSeed", "DoubleL2Mu23NoVtx_2Cha_CosmicSeed_NoL2Matched", "DoubleL2Mu25NoVtx_2Cha_Eta2p4", "DoubleL2Mu25NoVtx_2Cha_CosmicSeed_Eta2p4", ] #self.addTRG = [ # "DoubleL2Mu23NoVtx_2Cha",] self.Histos = {} for chan in channel: self.Histos['{}/cutflow'.format(chan)] = ROOT.Hist( 20, 0, 20, title='cutflow', drawstyle='hist') self.KeepCutFlow = False self.RawCutFlow = False self.LookupWeight = root_open( os.path.join( os.getenv('CMSSW_BASE'), 'src/FireROOT/Analysis/data/PUWeights_2018.root')).Get( 'puWeights') self.LookupMuonSFLowpT = root_open( os.path.join(os.getenv('CMSSW_BASE'), 'src/FireROOT/Analysis/data/mu_Loose_pt7.root')).Get( 'ratio_syst') self.LookupMuonSF = root_open( os.path.join(os.getenv('CMSSW_BASE'), 'src/FireROOT/Analysis/data/RunABCD_SF_ID.root')).Get( 'NUM_LooseID_DEN_TrackerMuons_pt_abseta_syst') self.LookupElectronSF = root_open( os.path.join( os.getenv('CMSSW_BASE'), 'src/FireROOT/Analysis/data/2018_ElectronLoose.root')).Get( 'EGamma_SF2D') self.LookupPhotonSF = root_open( os.path.join( os.getenv('CMSSW_BASE'), 'src/FireROOT/Analysis/data/2018_PhotonsLoose.root')).Get( 'EGamma_SF2D') self.Scale = 1. def setTriggers(self, triggers): self.Triggers = triggers def addTrigger(self, trigger): self.Triggers.append(trigger) def bookHisto(self, name, hist): self.Histos[name] = hist def setScale(self, scale): self.Scale = scale def process(self): for i, event in enumerate(self.Chain): if self.MaxEvents > 0 and i > self.MaxEvents: break ## event weight ## aux = {} aux['wgt'] = self.Scale if self.Type == 'MC': aux['wgt'] *= event.weight # gen weight aux['wgt'] *= self.LookupWeight.GetBinContent( self.LookupWeight.GetXaxis().FindBin( event.trueInteractionNum)) ## pileup correction for ch in self.Channel: if self.RawCutFlow: self.Histos['{}/cutflow'.format(ch)].Fill(0) else: self.Histos['{}/cutflow'.format(ch)].Fill(0, aux['wgt']) ## trigger ## #if not any([getattr(event.hlt, t) for t in self.Triggers]): continue #if not any([getattr(event.hlt, t) for t in self.addTRG]): continue for ch in self.Channel: if self.RawCutFlow: self.Histos['{}/cutflow'.format(ch)].Fill(1) else: self.Histos['{}/cutflow'.format(ch)].Fill(1, aux['wgt']) ## 2 leptonjets in channel definition ## leptonjets = [lj for lj in event.leptonjets] if len(leptonjets) < 2: continue #print len(leptonjets)#js #LJ2 = none leptonjets.sort(key=lambda lj: lj.p4.pt(), reverse=True) LJ0 = leptonjets[0] LJ1 = leptonjets[1] #LJ2 = leptonjets[2] #if len(event.leptonjets)>2:# #LJ2 = leptonjets[2]# #aux['lj2'] = LJ2 if self.ChargedLJ: if not LJ0.passChargedSelection(event): continue if not LJ1.passChargedSelection(event): continue #if not LJ2.passChargedSelection(event): continue else: if not LJ0.passSelection(event): continue if not LJ1.passSelection(event): continue #if not LJ2.passSelection(event): continue if LJ0.isMuonType() and LJ1.isMuonType(): aux['channel'] = '4mu' elif LJ0.isMuonType() and LJ1.isEgmType(): aux['channel'] = '2mu2e' elif LJ0.isEgmType() and LJ1.isMuonType(): aux['channel'] = '2mu2e' else: continue aux['lj0'] = LJ0 aux['lj1'] = LJ1 #aux['lj2'] = LJ2 if self.Type == 'MC': aux['sf_electron'] = 1. aux['sf_electron_up'] = 1. aux['sf_electron_low'] = 1. aux['sf_photon'] = 1. aux['sf_photon_up'] = 1. aux['sf_photon_low'] = 1. aux['sf_pfmuon'] = 1. aux['sf_pfmuon_up'] = 1. aux['sf_pfmuon_low'] = 1. for lj in [LJ0, LJ1]: ## muon scale factor for i in lj.pfcand_pfmuonIdx: _pfmu_p4 = event.muons[i].p4 pt, eta = _pfmu_p4.pt(), _pfmu_p4.eta() if pt >= 20: xbin = self.LookupMuonSF.xaxis.FindBin(pt) xbin = min(max(xbin, 1), self.LookupMuonSF.nbins(0)) ybin = self.LookupMuonSF.yaxis.FindBin(abs(eta)) sf = self.LookupMuonSF.GetBinContent(xbin, ybin) err_up = self.LookupMuonSF.GetBinErrorUp( xbin, ybin) err_lo = self.LookupMuonSF.GetBinErrorLow( xbin, ybin) else: for i in range(self.LookupMuonSFLowpT.num_points): x = self.LookupMuonSFLowpT.x(i) xh = x + self.LookupMuonSFLowpT.xerrh(i) xl = x - self.LookupMuonSFLowpT.xerrl(i) if xl <= eta and eta <= xh: sf = self.LookupMuonSFLowpT.y(i) err_up = self.LookupMuonSFLowpT.yerrh(i) err_lo = self.LookupMuonSFLowpT.yerrl(i) break aux['wgt'] *= sf aux['sf_pfmuon'] *= sf aux['sf_pfmuon_up'] *= sf + err_up aux['sf_pfmuon_low'] *= sf - err_lo ## NOTE DSA scale factor, nothing for now for i in lj.pfcand_dsamuonIdx: #print dsamu.pt.P4() sf = 1. aux['wgt'] *= sf ## electron scale factor for i in lj.pfcand_electronIdx: _electron = event.electrons[i] xbin = self.LookupElectronSF.xaxis.FindBin( _electron.scEta) ybin = self.LookupElectronSF.xaxis.FindBin( _electron.p4.pt()) ybin = min(max(ybin, 1), self.LookupElectronSF.nbins(1)) sf = self.LookupElectronSF.GetBinContent(xbin, ybin) aux['wgt'] *= sf aux['sf_electron'] *= sf aux['sf_electron_up'] *= sf + self.LookupElectronSF.GetBinErrorUp( xbin, ybin) aux['sf_electron_low'] *= sf - self.LookupElectronSF.GetBinErrorLow( xbin, ybin) ## photon scale factor for i in lj.pfcand_photonIdx: _photon = event.photons[i] xbin = self.LookupPhotonSF.xaxis.FindBin(_photon.scEta) ybin = self.LookupPhotonSF.xaxis.FindBin( _photon.p4.pt()) ybin = min(max(ybin, 1), self.LookupPhotonSF.nbins(1)) sf = self.LookupPhotonSF.GetBinContent(xbin, ybin) aux['wgt'] *= sf aux['sf_photon'] *= sf aux['sf_photon_up'] *= sf + self.LookupPhotonSF.GetBinErrorUp( xbin, ybin) aux['sf_photon_low'] *= sf - self.LookupPhotonSF.GetBinErrorLow( xbin, ybin) aux['wgt_electron_up'] = aux['wgt'] / aux['sf_electron'] * aux[ 'sf_electron_up'] aux['wgt_electron_low'] = aux['wgt'] / aux[ 'sf_electron'] * aux['sf_electron_low'] aux['wgt_photon_up'] = aux['wgt'] / aux['sf_photon'] * aux[ 'sf_photon_up'] aux['wgt_photon_low'] = aux['wgt'] / aux['sf_photon'] * aux[ 'sf_photon_low'] aux['wgt_pfmuon_up'] = aux['wgt'] / aux['sf_pfmuon'] * aux[ 'sf_pfmuon_up'] aux['wgt_pfmuon_low'] = aux['wgt'] / aux['sf_pfmuon'] * aux[ 'sf_pfmuon_low'] # for t, pt, eta in zip(list(lj.pfcand_type), list(lj.pfcand_pt), list(lj.pfcand_eta)): # ## muon scale factor, DSA same as muon for now # if t==3 or t==8: # xbin = self.LookupMuonSF.xaxis.FindBin(pt) # xbin = min(max(xbin, 1), self.LookupMuonSF.nbins(0)) # ybin = self.LookupMuonSF.yaxis.FindBin(abs(eta)) # sf = self.LookupMuonSF.GetBinContent(xbin, ybin) # aux['wgt'] *= sf # ## electron scale factor, using eta instead of SC eta for now # if t==2: # xbin = self.LookupElectronSF.xaxis.FindBin(eta) # ybin = self.LookupElectronSF.xaxis.FindBin(pt) # ybin = min(max(ybin, 1), self.LookupElectronSF.nbins(1)) # sf = self.LookupElectronSF.GetBinContent(xbin, ybin) # aux['wgt'] *= sf # ## photon scale factor, using eta instead of SC eta for now # if t==4: # xbin = self.LookupPhotonSF.xaxis.FindBin(eta) # ybin = self.LookupPhotonSF.xaxis.FindBin(pt) # ybin = min(max(ybin, 1), self.LookupPhotonSF.nbins(1)) # sf = self.LookupPhotonSF.GetBinContent(xbin, ybin) # aux['wgt'] *= sf for ch in self.Channel: if self.RawCutFlow: self.Histos['{}/cutflow'.format(ch)].Fill(2) else: self.Histos['{}/cutflow'.format(ch)].Fill(2, aux['wgt']) ## event-level mask ## if not event.metfilters.PrimaryVertexFilter: continue for ch in self.Channel: if self.RawCutFlow: self.Histos['{}/cutflow'.format(ch)].Fill(3) else: self.Histos['{}/cutflow'.format(ch)].Fill(3, aux['wgt']) nppCOSMIC, cosmicShowerTagged = globalCosmicShower( event.cosmicmuons, aux['channel']) if cosmicShowerTagged: continue for ch in self.Channel: if self.RawCutFlow: self.Histos['{}/cutflow'.format(ch)].Fill(4) else: self.Histos['{}/cutflow'.format(ch)].Fill(4, aux['wgt']) self.processEvent(event, aux) def processEvent(self, event, aux): """To be override by daughter class""" pass def postProcess(self): if self.KeepCutFlow: labels = [ 'total', 'trigger_pass', 'leptonjet_ge2', 'pv_good', 'cosmicveto_pass' ] for ch in self.Channel: xaxis = self.Histos['{}/cutflow'.format(ch)].axis(0) for i, s in enumerate(labels, start=1): xaxis.SetBinLabel(i, s) # binNum., labAngel, labSize, labAlign, labColor, labFont, labText xaxis.ChangeLabel(i, 315, -1, 11, -1, -1, s) else: for ch in self.Channel: self.Histos.pop('{}/cutflow'.format(ch)) @property def histos(self): return self.Histos @property def channel(self): return self.Channel
elif mystate == 1: tree_name_i = '/home/jlow/L1MuonTrigger/CRAB3/P2_9_2_3_patch1/crab_projects/crab_ntuple_SingleNeutrino_PU200/results/ntuple_SingleNeutrino_PU200_%i.root' tree = TreeChain('ntupler/tree', [(tree_name_i % (i + 1)) for i in range(50)]) else: raise Exception("Unexpected state: %i" % mystate) maxEvents = -1 #maxEvents = 2000 # ROOT globals gROOT.SetBatch(batch_mode) # Define collection tree.define_collection(name='hits', prefix='vh_', size='vh_size') tree.define_collection(name='tracks', prefix='vt_', size='vt_size') tree.define_collection(name='genparticles', prefix='vp_', size='vp_size') # Enums kDT, kCSC, kRPC, kGEM, kTT = 0, 1, 2, 3, 20 # Lambdas deg_to_rad = lambda x: x * np.pi / 180. rad_to_deg = lambda x: x * 180. / np.pi # Functions def delta_phi(lhs, rhs): # in degrees deg = lhs - rhs
def work(self): # trigger config tool to read trigger info in the ntuples trigger_config = get_trigger_config() OutputModel = (RecoTauBlock + EventVariables + SkimExtraModel + TrueTauBlock) onfilechange = [] # update the trigger config maps on every file change onfilechange.append((update_trigger_config, (trigger_config,))) cutflow = Hist(2, 0, 2, name='cutflow', type='D') # initialize the TreeChain of all input files (each containing one tree named self.metadata.treename) chain = TreeChain(self.metadata.treename, files=self.files, events=self.events, cache=True, cache_size=10000000, learn_entries=30, onfilechange=onfilechange) # create output tree self.output.cd() tree = Tree(name='higgstautauhh', model=OutputModel) copied_variables = ['actualIntPerXing', 'averageIntPerXing', 'RunNumber', 'EventNumber', 'lbn'] tree.set_buffer( chain.buffer, branches=copied_variables, create_branches=True, visible=False) chain.always_read(copied_variables) # set the event filters event_filters = EventFilterList([ #Triggers( # datatype=self.metadata.datatype, # year=YEAR, # skim=False), PriVertex(), LArError(), LArHole(datatype=self.metadata.datatype), JetCleaning( datatype=self.metadata.datatype, year=YEAR), TauAuthor(1), TauHasTrack(1), TauPT(1, thresh=25 * GeV), TauEta(1), TauCrack(1), TauLArHole(1), #TauTriggerMatch( # config=trigger_config, # year=YEAR, # datatype=self.metadata.datatype, # skim=False, # tree=tree, # min_taus=1), ]) self.filters['event'] = event_filters chain.filters += event_filters # define tree collections chain.define_collection(name="taus", prefix="tau_", size="tau_n", mix=TauFourMomentum) chain.define_collection(name="taus_EF", prefix="trig_EF_tau_", size="trig_EF_tau_n", mix=TauFourMomentum) # jet_* etc. is AntiKt4LCTopo_* in tau-perf D3PDs chain.define_collection(name="jets", prefix="jet_", size="jet_n", mix=FourMomentum) chain.define_collection(name="truetaus", prefix="trueTau_", size="trueTau_n", mix=MCTauFourMomentum) chain.define_collection(name="mc", prefix="mc_", size="mc_n", mix=MCParticle) chain.define_collection(name="muons", prefix="mu_staco_", size="mu_staco_n") chain.define_collection(name="electrons", prefix="el_", size="el_n") chain.define_collection(name="vertices", prefix="vxp_", size="vxp_n") from externaltools import PileupReweighting from ROOT import Root # Initialize the pileup reweighting tool pileup_tool = Root.TPileupReweighting() if YEAR == 2011: pileup_tool.AddConfigFile(PileupReweighting.get_resource('mc11b_defaults.prw.root')) pileup_tool.AddLumiCalcFile('lumi/2011/hadhad/ilumicalc_histograms_None_178044-191933.root') elif YEAR == 2012: pileup_tool.AddConfigFile(PileupReweighting.get_resource('mc12a_defaults.prw.root')) pileup_tool.SetDataScaleFactors(1./1.11) pileup_tool.AddLumiCalcFile('lumi/2012/hadhad/ilumicalc_histograms_None_200841-205113.root') else: raise ValueError('No pileup reweighting defined for year %d' % YEAR) # discard unrepresented data (with mu not simulated in MC) pileup_tool.SetUnrepresentedDataAction(2) pileup_tool.Initialize() # entering the main event loop... for event in chain: tree.reset() event.vertices.select(vertex_selection) tree.number_of_good_vertices = len(event.vertices) # match only with visible true taus event.truetaus.select(lambda tau: tau.vis_Et > 10 * GeV and abs(tau.vis_eta) < 2.5) if len(event.truetaus) == 1: true_tau = event.truetaus[0] TrueTauBlock.set(tree, 1, true_tau) else: continue # Truth-matching matched_reco = None reco_index = true_tau.tauAssoc_index tau = event.taus.getitem(reco_index) if tau in event.taus: matched_reco = tau else: continue tree.MET = event.MET_RefFinal_BDTMedium_et # fill tau block RecoTauBlock.set(event, tree, matched_reco, None) # set the event weight tree.pileup_weight = pileup_tool.GetCombinedWeight(event.RunNumber, event.mc_channel_number, event.averageIntPerXing) tree.mc_weight = event.mc_event_weight tree.Fill(reset=True) self.output.cd() tree.FlushBaskets() tree.Write() total_events = event_filters[0].total cutflow[0] = total_events cutflow[1] = total_events cutflow.Write()
def work(self): D4PD_model = RecoTauBlock + RecoJetBlock + EventVariables + TrueTauBlock + PartonBlock # initialize the TreeChain of all input files (each containing one tree named self.metadata.treename) tree = TreeChain(self.metadata.treename, files=self.files, events=self.events, cache=True, cache_size=10000000, learn_entries=30) # create output tree self.output.cd() D4PD = Tree(name=self.metadata.name, model=D4PD_model) copied_variables = ['actualIntPerXing', 'averageIntPerXing'] copied_variables += mc_triggers D4PD.set_buffer(tree.buffer, variables=copied_variables, create_branches=True, visible=False) tree.always_read(copied_variables) # set the event filters # passthrough for MC for trigger acceptance studies self.event_filters = EventFilterList([ GRLFilter(self.grl, passthrough = self.metadata.datatype != datasets.DATA), PriVertex(), LArError(), JetCleaningLoose(passthrough = self.metadata.datatype != datasets.DATA), #JetCleaningMedium(passthrough = self.metadata.datatype != datasets.DATA), LArHole(), #JetCrackVeto(), ElectronVeto(), MuonVeto(), TauElectronVeto(), TauMuonVeto(), TauAuthorTrack(), ]) self.event_filters.insert(1, MCTriggers()) tree.filters += self.event_filters cutflow = Cutflow() # define tree collections tree.define_collection(name="taus", prefix="tau_", size="tau_n", mix=TauFourMomentum) # jet_eta etc is AntiKt4LCTopo in tau-perf D3PDs tree.define_collection(name="jets", prefix="jet_", size="jet_n", mix=FourMomentum) tree.define_collection(name="truetaus", prefix="trueTau_", size="trueTau_n", mix=MCTauFourMomentum) tree.define_collection(name="mc", prefix="mc_", size="mc_n", mix=MCParticle) tree.define_collection(name="muons", prefix="mu_staco_", size="mu_staco_n") tree.define_collection(name="electrons", prefix="el_", size="el_n") tree.define_collection(name="vertices", prefix="vxp_", size="vxp_n") # define tree objects D4PD.define_object(name='tau1', prefix='tau1_') D4PD.define_object(name='tau2', prefix='tau2_') D4PD.define_object(name='jet1', prefix='jet1_') D4PD.define_object(name='jet2', prefix='jet2_') """ tree.define_association(origin='taus', target='truetaus', prefix='trueTauAssoc_', link='index') tree.define_association(origin='truetaus', target='taus', prefix='tauAssoc_', link='index') """ # entering the main event loop... for event in tree: D4PD.reset() cutflow.reset() # tau selection event.taus.select(lambda tau: tau.pt > 15*GeV) # Jet selection event.jets.select(lambda jet: jet.fourvect.P() > 25*GeV and abs(jet.emscale_eta) < 4.5) """ Get VBF jets """ # get partons (already sorted by eta in hepmc) parton1, parton2 = hepmc.get_VBF_partons(event) PartonBlock.set(D4PD, parton1, parton2) D4PD.dR_quarks = parton1.fourvect.DeltaR(parton2.fourvect) """ Get true taus """ event.truetaus.select(lambda tau: tau.vis_Et > 10 * GeV and abs(tau.vis_eta) < 2.5) if len(event.truetaus) > 2: print "ERROR: too many true taus: %i" % len(event.truetaus) D4PD.error = 1 D4PD.Fill() continue elif len(event.truetaus) < 2: print "ERROR: too few true taus: %i" % len(event.truetaus) D4PD.error = 2 D4PD.Fill() continue """ fourvects = [] colors = [] radii = [] for thing in event.jets: fourvects.append(thing.fourvect) colors.append('blue') radii.append(.4) for parton in (parton1, parton2): fourvects.append(parton.fourvect) colors.append('green') radii.append(.1) for thing in event.taus: fourvects.append(thing.fourvect) colors.append('red') radii.append(.2) for tau in event.truetaus: fourvects.append(tau.fourvect) colors.append('purple') radii.append(.1) eventview.draw(event, fourvects, colors=colors, radii=radii) """ TrueTauBlock.set(D4PD, 1, event.truetaus[0]) TrueTauBlock.set(D4PD, 2, event.truetaus[1]) D4PD.dR_truetaus = event.truetaus[0].fourvect.DeltaR(event.truetaus[1].fourvect) D4PD.dR_quark_tau = min([ parton1.fourvect.DeltaR(event.truetaus[0].fourvect), parton2.fourvect.DeltaR(event.truetaus[0].fourvect), parton1.fourvect.DeltaR(event.truetaus[1].fourvect), parton2.fourvect.DeltaR(event.truetaus[1].fourvect), ]) taus = [] if event.taus: for truetau in event.truetaus: closest_tau = min(event.taus, key=lambda tau: utils.dR(tau.seedCalo_eta, tau.seedCalo_phi, truetau.vis_eta, truetau.vis_phi)) if utils.dR(closest_tau.seedCalo_eta, closest_tau.seedCalo_phi, truetau.vis_eta, truetau.vis_phi) < 0.2: if closest_tau in taus: # collision D4PD.error = 3 break taus.append(closest_tau) if len(taus) < 2: # collision D4PD.Fill() continue """ # Overlap removal between taus and jets event.jets.select(lambda jet: not any([tau for tau in taus if utils.dR(jet.emscale_eta, jet.emscale_phi, tau.seedCalo_eta, tau.seedCalo_phi) < .2])) """ jets = [] if event.jets: for quark in (parton1, parton2): closest_jet = min(event.jets, key=lambda jet: utils.dR(jet.eta, jet.phi, quark.eta, quark.phi)) if utils.dR(closest_jet.eta, closest_jet.phi, quark.eta, quark.phi) < 0.4: if closest_jet in jets: # collision D4PD.error = 4 break jets.append(closest_jet) if len(jets) < 2: # collision D4PD.Fill() continue """ Jet variables """ RecoJetBlock.set(D4PD, jets[0], jets[1]) """ Reco tau variables This must come after the RecoJetBlock is filled since that sets the jet_beta for boosting the taus """ RecoTauBlock.set(event, D4PD, taus[0], taus[1]) D4PD.true_Mvis_tau1_tau2 = (D4PD.trueTau1_fourvect_vis + D4PD.trueTau2_fourvect_vis).M() """ MET """ METx = event.MET_RefFinal_etx METy = event.MET_RefFinal_ety MET_vect = Vector2(METx, METy) MET_3vect = Vector3(METx, METy, 0.) D4PD.MET = event.MET_RefFinal_et D4PD.MET_phi = event.MET_RefFinal_phi # HT TODO: Fix sumET = event.MET_RefFinal_sumet D4PD.HT = sumET D4PD.numVertices = len([vtx for vtx in event.vertices if (vtx.type == 1 and vtx.nTracks >= 4) or (vtx.type == 3 and vtx.nTracks >= 2)]) # fill output ntuple # use reset=True to reset all variables to their defaults after the fill # to avoid any values from this event carrying over into the next D4PD.cutflow = cutflow.int() D4PD.Fill() self.output.cd() D4PD.FlushBaskets() D4PD.Write()