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): """ This is the one function that all "ATLASStudent"s must implement. """ datatype = self.metadata.datatype year = self.metadata.year verbose = self.args.verbose OutputModel = C3POEvent if datatype == datasets.MC: # only create truth branches for MC OutputModel += ( FourVectModel.prefix('resonance_') + TrueTau.prefix('truetau1_') + TrueTau.prefix('truetau2_')) onfilechange = [] count_funcs = {} if datatype in (datasets.MC, datasets.EMBED): def mc_weight_count(event): return event.mc_event_weight count_funcs = { 'mc_weight': mc_weight_count, } trigger_config = None if datatype != datasets.EMBED: # trigger config tool to read trigger info in the ntuples trigger_config = get_trigger_config() # update the trigger config maps on every file change onfilechange.append((update_trigger_config, (trigger_config,))) if datatype == datasets.DATA: merged_grl = GRL() def update_grl(student, grl, name, file, tree): grl |= str(file.Get('Lumi/%s' % student.metadata.treename).GetString()) onfilechange.append((update_grl, (self, merged_grl,))) if datatype == datasets.DATA: merged_cutflow = Hist(1, 0, 1, name='cutflow', type='D') else: merged_cutflow = Hist(2, 0, 2, name='cutflow', type='D') def update_cutflow(student, cutflow, name, file, tree): year = student.metadata.year datatype = student.metadata.datatype if datatype == datasets.MC: cutflow[0] += file.cutflow_event[0] cutflow[1] += file.cutflow_event_mc_weight[0] else: cutflow[0] += file.cutflow_event[0] onfilechange.append((update_cutflow, (self, merged_cutflow,))) # 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, read_branches_on_demand=True, cache=True, 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([ CoreFlags( count_funcs=count_funcs), TauSelected(2, count_funcs=count_funcs), TruthMatching( passthrough=datatype != datasets.MC, count_funcs=count_funcs), MCWeight( datatype=datatype, tree=tree, passthrough=datatype != datasets.MC, count_funcs=count_funcs) ]) self.filters['event'] = event_filters chain._filters += event_filters define_objects(chain, year, skim=False) # define tree objects taus = [ tree.define_object(name='tau1', prefix='tau1_'), tree.define_object(name='tau2', prefix='tau2_')] if datatype == datasets.MC: truetaus = [ tree.define_object(name='truetau1', prefix='truetau1_'), tree.define_object(name='truetau2', prefix='truetau2_')] tree.define_object(name='resonance', prefix='resonance_') # entering the main event loop... for event in chain: # sort taus and jets in decreasing order by pT event.taus.sort(key=lambda tau: tau.pt, reverse=True) tau1, tau2 = event.taus # MET METx = event.MET.etx METy = event.MET.ety MET_vect = Vector2(METx, METy) MET = event.MET.et MET_phi = event.MET.phi tree.MET = MET tree.MET_x = METx tree.MET_y = METy tree.MET_phi = MET_phi sumET = event.MET.sumet tree.sumET = sumET if sumET != 0: tree.MET_sig = ((2. * MET / GeV) / (utils.sign(sumET) * sqrt(abs(sumET / GeV)))) else: tree.MET_sig = -1. # use MMC values from skim mmc_mass = event.tau_MMC_mass mmc_resonance = event.tau_MMC_resonance mmc_met = Vector2(event.tau_MMC_MET_x, event.tau_MMC_MET_y) tree.mass_mmc_tau1_tau2 = mmc_mass tree.mmc_resonance.copy_from(mmc_resonance) if mmc_mass > 0: tree.mmc_resonance_pt = mmc_resonance.Pt() tree.MET_mmc = mmc_met.Mod() tree.MET_mmc_x = mmc_met.X() tree.MET_mmc_y = mmc_met.Y() tree.MET_mmc_phi = math.pi - mmc_met.Phi() # truth matching if datatype == datasets.MC: resonance, tau_decays = get_taus(event) if resonance is not None: FourVectModel.set(tree.resonance, resonance) matched_taus = [] decays = tau_decays[:] for itau, tau in enumerate(event.taus): for idecay, tau_decay in enumerate(decays): if tau.matches_vect(tau_decay.fourvect_visible): tau_decay.matched = True tau_decay.matched_object = tau tau.matched = True tau.matched_object = tau_decay TrueTau.set(truetaus[itau], tau_decay, verbose=verbose) decays.pop(idecay) matched_taus.append(itau) break if len(decays) > 0: for idecay, decay in enumerate(decays): reco_idx = -1 remaining_idx = range(2) for imatched in remaining_idx: if imatched not in matched_taus: reco_idx = imatched remaining_idx.remove(imatched) break TrueTau.set(truetaus[reco_idx], tau_decay, verbose=verbose) if len(tau_decays) == 2: # write truth met fourvect_missing = (tau_decays[0].fourvect_missing + tau_decays[1].fourvect_missing) tree.MET_true = fourvect_missing.Pt() tree.MET_phi_true = fourvect_missing.Phi() tree.MET_x_true = tree.MET_true * math.cos(tree.MET_phi_true) tree.MET_y_true = tree.MET_true * math.sin(tree.MET_phi_true) tree.MET_phi_diff = Vector2.Phi_mpi_pi(tree.MET_phi_true - MET_phi) # tau - vertex association tree.tau_same_vertex = ( tau1.privtx_x == tau2.privtx_x and tau1.privtx_y == tau2.privtx_y and tau1.privtx_z == tau2.privtx_z) # fill tau block for outtau, intau in zip(taus, event.taus): RecoTau.set(outtau, intau, verbose=verbose) # fill output ntuple tree.Fill(reset=True) self.output.cd() tree.FlushBaskets() tree.Write() if datatype == datasets.DATA: xml_string = ROOT.TObjString(merged_grl.str()) xml_string.Write('lumi') merged_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()