# some very basic job options to be set by the farm potentially (or fallback default) try: MyOutput except NameError: MyOutput = 'TestNtupleOutput.root' try: MyEvents except NameError: MyEvents = 250 ## LivZBosonExample_topOptions.py ## This set of job options demonstrates some basic functionality of the code in LiverpoolAnalysis. ## It allows you to: ## - Perform particle preselection (defined in LivZBosonExample_preselection.py) ## - Write/Read a DPD of these preselected particles if desired ## - Makes combinations of electrons to form Z candidates ## - Dumps Z candidates, preselected electrons, all electrons, various trigger decisions and Z->ee truth ## This uses various scripts from LivTools and LivZAnalysis, some of which take configuration flags. ## There are many algorithms used in this example. For full documentation, refer to Doxygen for each specific class. ## Generally, particles are "transmitted" from one algorithm to the next via StoreGate. ## Say you have these lines in the job options: ## ## from LivAlgorithms.LivAlgorithmsConf import Analysis__Combine2Particles ## FindZee = Analysis__Combine2Particles(name = 'ZeeCandidates') ## ## This creates the python equivalent of the Analysis::Combine2Particles class from LivAlgorithms. ## It is generally a good idea to always pass in an explicit name parameter to the constructor. Then, ## when you do: ## ## jobSequence += FindZee ## ## you can the always access this algorithm downstream as jobSequence.ZeeCandidates ## Note, 'FindZee' is only a temporary, local name for the algo. The same comments apply to tools. ## The job structure is very flexible - this example shows one possibility. ## For illustration, each "dumper" (except the trigger ones) records its output in a unique tree. ## To change this, simply change the TreeName property of the relevant algorithms. ## -------- Beginning of job options ## Standard job configuration from LivTools ## This sets up an AlgSequence called 'job', and an AthSequence called 'jobSequence' as its first element. ## An AthSequence is like an AlgSequence, but if an algorithm it contains reports that a filter has failed, ## the subsequent algorithms in that AthSequence are not run. ## In this example, the AthSequence is used for the "computational" sections, while the AlgSequence is used ## for the ntuple dumpers (as well as holding the AthSequence). ## This ensures that the dumpers are run every event, and all the different trees will remain in synch. ## attaching them (at relevant points) to the AthSequence would be more efficient, but this needs careful treatment ## to avoid mistakes. ## Note: In this specific example, none of the algorithms attached to the AthSequence will ever "fail" their filter. ## It's a 1 line addition to enable this behaviour. include("LivTools/LivTools_jobConfig.py") ## Helpful utilities from LivTools: ## This line does nothing in itself, but it defines several useful python functions. include("LivTools/LivTools_jobUtils.py") ## Trigger setup (comment if not needed) ## If you want to read files made in 13.0.30.X (or earlier), uncomment the following line ## Anything 13.0.40 or later should be fine #readV13030 = True ## If you want to read FDR (1 or 2) files, set this switch before the trigger configuration #UseFDRMode = True include("LivTools/LivTools_triggerConfig.py") ## Flags to control job flow ReadAOD = True # AOD input DumpDPD = False # AOD input and DPD output (after preselection) ReadDPD = False # DPD input (no nead to rerun preselection) DumpNtuple = True # Ntuple output (may be as well as/instead of DPD) #outputFileName = 'TestNtupleOutput.root' # Ntuple output file name outputFileName = MyOutput # Ntuple output file name myOutputLevel = WARNING # Logging level ##myOutputLevel = INFO # Logging level ## Input files and number of events. if ReadAOD: # filePath = 'SAMPLEDIR' filePath = '/hepstore/store2/jkretz/valid1.005144.PythiaZee.recon.AOD.e322_s461_r597_tid030017/' # filePath = '/hepstore/store2/jkretz/mc08.106020.PythiaWenu_1Lepton.recon.AOD.e352_s462_r541_tid028691' else: filePath = '.' ## getFileList is defined in LivTools/LivTools_jobUtils.py svcMgr.EventSelector.InputCollections = getFileList(filePath, '*AOD*') ## Number of events to process. ##theApp.EvtMax = -1 theApp.EvtMax = MyEvents ## Step 1: If we're reading from AOD (ie not DPD), do the preselection. if ReadAOD: include("LivZBoson_preselection.py") ## Step 2: If we're writing the DPD, dump the preselected electrons. if DumpDPD: include("LivZAnalysis/LivZBosonExample_DPDWriter.py") ## Step 3: If we're writing an ntuple, do e+e combinations and dump the rest of the information. if DumpNtuple: ## LivAlgorithms/Combine2Particles: used to make the Z candidates ## calculated from AOD or DPD contents ## This algorithm is booked and configured in 3 stages, called A, B and C in what follows. ## The subsequent algorithms follow the same pattern. ## Step A: Import and construct the algorithm from LivAlgorithms.LivAlgorithmsConf import Analysis__Combine2Particles FindZee = Analysis__Combine2Particles(name = 'ZeeCandidates') ## Step B: Configure it correctly ## Combine2Particles is a very general algorithm, we need to tell it exactly what to expect ## and how to classify the output (ie as a Z boson) FindZee.PdgId = 23 FindZee.MinMass = 70*Units.GeV ## Mass cut: a charge cut can also be applied FindZee.MaxMass = 110*Units.GeV FindZee.OutputLevel = myOutputLevel FindZee.FirstInputParticleContainer ='PreselectedElectronCollection' ## Use the preselected electrons as input. ## Combine2Particles writes a CompositeParticleContainer to StoreGate - we need to provide a name for it. FindZee.OutputCombinationContainer ='ZeeContainer' ## Step C: Add this to the AthSequence. jobSequence += FindZee ## Ntuple algorithms. ## Now all the containers we need have been made. ## This leaves us free to dump the ones we want in any order we like, but it's probably best to keep it fairly logical! ## Electron and trigger dumping. ## As an example we'll dump the 'raw' AOD electrons as well as the preselected ones. ## This, and the trigger decision, need the full AOD in this setup. ## We need DumpEgamma later as well, so let's import outside the if statement. from LivDumpers.LivDumpersConf import Analysis__DumpEgamma # Selection of Tiggers to "worry" about # These are the "standard" (startup) e triggers, gamma for checks, higher lumi # Selection is slightly "future proof" as of January 2009 info triggers = ['e10_medium','e15_medium','e20_loose','e20i_loose', 'e5_medium','g20','g20i', ## 'g20_loose','g20i_loose', 'e22i_tight','em105_passHLT'] ## triggers = ['e15_medium','e20_loose'] TrigMatchToolList = setupEMTrigMatchTools(triggers, outputLevel=myOutputLevel) if ReadAOD: # Example of an ntupling stage before preselection DumpAllE = Analysis__DumpEgamma(name = 'AllElectronDump') ## Note the name parameter ## Input collection: AOD electrons w/ soft preselection! DumpAllE.EgammaContainer = 'SoftPreselectedElectronCollection' DumpAllE.TreeName = 'RawElectronTree' ## Output tree DumpAllE.OutputBranchPrefix = 'electron' ## Branches will be called 'electron_X' # explicitly set the dumper options DumpAllE.Do4Mom = True DumpAllE.DoCluster4Mom = True DumpAllE.DoTrack4Mom = True DumpAllE.DoAuthorID = True DumpAllE.DoTrackMatch = True DumpAllE.DoShower = True DumpAllE.DoConversion = False DumpAllE.DoBremFit = False DumpAllE.DoPointing = True DumpAllE.DoEgammaID = True DumpAllE.DoEGTruth = True DumpAllE.OutputLevel = myOutputLevel ## Logging level. job += DumpAllE ## Add to job (the AlgSequence) so we dump every event. ## full trigger dumping here on all electrons! from LivDumpers.LivDumpersConf import Analysis__DumpSimpleMatches DumpTriggerMatches = Analysis__DumpSimpleMatches(name = 'TrigMatchDumpRaw') DumpTriggerMatches.InputContainer = 'SoftPreselectedElectronCollection' DumpTriggerMatches.TreeName = 'RawElectronTree' DumpTriggerMatches.MatchingTools = TrigMatchToolList DumpTriggerMatches.OutputLevel = myOutputLevel job += DumpTriggerMatches ## Trigger decision section, using LivDumpers/DumpTriggerResult. ## This dumps the L1, L2, EF decisions for one given EF chain. ## This example shows how several instances of this algorithm can be configured. ## This is global only! - DumpEgamma can be asked to dump RoI matching DeltaR values! from LivDumpers.LivDumpersConf import Analysis__DumpTriggerResult ## All the trigger dumping is made to one tree in this example. triggerTreeName = 'TrigResultTree' ## Python loop over the triggers. for item in triggers: ## Make a new instance - note how the name parameter is always unique. trig = Analysis__DumpTriggerResult(name = 'ExampleTrigger_'+item) ## Tool configuration. trig.TrigDecisionTool = ToolSvc.TrigDecisionTool trig.TreeName = triggerTreeName trig.DoPrescales = True ## Normally, LivDumpers/DumpTriggerResult only needs the EF chain name. ## Levels 1 and 2 should only have to be configured manually in exceptional circumstances: ## eg, when reading 13.0.30 AOD, each Level 1 item needs to be given too. trig.EFTriggerChain = item job += trig ## Dump preselected electrons. ## Let's use another instance of Analysis__DumpEgamma which was imported above. ## Compare the configuration with that of 'AllElectronDump'. DumpE = Analysis__DumpEgamma(name = 'ExampleElectronDump') DumpE.EgammaContainer = 'PreselectedElectronCollection' DumpE.TreeName = 'PreselectedElectronTree' ## Branch prefix: the same as in AllElectronDump, but we have a new tree so there is no conflict. DumpE.OutputBranchPrefix = 'electron' # explicitly set the dumper options DumpE.Do4Mom = True DumpE.DoCluster4Mom = True DumpE.DoTrack4Mom = True DumpE.DoAuthorID = True DumpE.DoTrackMatch = True DumpE.DoShower = True DumpE.DoConversion = False DumpE.DoBremFit = False DumpE.DoPointing = True DumpE.DoEgammaID = True DumpE.DoEGTruth = True DumpE.OutputLevel = myOutputLevel job += DumpE ## full trigger dumping here on preselected electrons! from LivDumpers.LivDumpersConf import Analysis__DumpSimpleMatches DumpTriggerMatches = Analysis__DumpSimpleMatches(name = 'TrigMatchDumpSel') DumpTriggerMatches.InputContainer = 'PreselectedElectronCollection' DumpTriggerMatches.TreeName = 'PreselectedElectronTree' DumpTriggerMatches.MatchingTools = TrigMatchToolList DumpTriggerMatches.OutputLevel = myOutputLevel job += DumpTriggerMatches ## LivDumpers/DumpEventInfo dumps some useful information for real data (lumi block, for example). ## It's not really needed for MC, as the event and run numbers are added to each tree by default. ## On very recent AOD, it can also dump pdf information, but this is off by default. ## This algo is small, it doesn't need much configuration. from LivDumpers.LivDumpersConf import Analysis__DumpEventInfo DumpEI = Analysis__DumpEventInfo(name = 'EventInfoDump') DumpEI.TreeName = 'EventInfoTree' DumpEI.DoPDFInfo = True DumpEI.OutputLevel = myOutputLevel job += DumpEI ## Now dump the Z candidates using LivDumpers/DumpCombinedParticle. ## This takes the CompositeParticleContainer output by the FindZee algo (note the FindZee name is still in scope). ## It dumps information on the Z four-momentum, charge and pdg code, ## and the same information for each of its constituents. from LivDumpers.LivDumpersConf import Analysis__DumpCombinedParticle DumpZ = Analysis__DumpCombinedParticle(name = 'ZDump') DumpZ.CombinedParticleContainer = FindZee.OutputCombinationContainer DumpZ.TreeName = 'ZeeTree' DumpZ.OutputBranchPrefix = 'Zee' DumpZ.OutputLevel = myOutputLevel job += DumpZ ## Finally, let's dump some Z->ee and W->enu truth information using LivDumpers/DumpSingleBosonTruth. ## The algo can do (almost) any 1->2 signature, it has to be configured for each one. ## And we'll use the filtered truth container defined in the preselection. ## Configure Z->ee tool from LivTools.LivToolsConf import Analysis__SingleBosonTruthTool TruthTool = Analysis__SingleBosonTruthTool(name = 'TruthToolZee') TruthTool.TruthContainer = TruthFilter.OutputTruthContainer ## TruthFilter is the truth tool in the preselection TruthTool.BosonPDG = 23 ## We're looking for Z bosons .. TruthTool.DecayProduct1PDG = 11 ## .. that decay to electrons TruthTool.OutputLevel = myOutputLevel ## Logging level ## TruthTool is a "public" tool: add it to ToolSvc, configure the dumper ToolSvc += TruthTool from LivDumpers.LivDumpersConf import Analysis__DumpSingleBosonTruth DumpTruth = Analysis__DumpSingleBosonTruth(name = 'ZeeTruthDump') DumpTruth.TruthTool = TruthTool ## This is the tool we just configured DumpTruth.TreeName = 'ZeeTruth' ## The output tree name DumpTruth.OutputLevel = myOutputLevel ## Logging level DumpTruth.OutputBranchPrefix = 'Zee' ## There's no conflict with ZDump here - it's a different tree DumpTruth.DoDocuParticles = True ## The documentary particles are pre-FSR DumpTruth.DoBosonParents = True ## this is pre-ISR? job += DumpTruth ## Configure W->enu tool from LivTools.LivToolsConf import Analysis__SingleBosonTruthTool TruthTool = Analysis__SingleBosonTruthTool(name = 'TruthToolWenu') TruthTool.TruthContainer = TruthFilter.OutputTruthContainer ## TruthFilter is the truth tool in the preselection TruthTool.BosonPDG = 24 ## We're looking for W bosons .. TruthTool.DecayProduct1PDG = 11 ## .. that decay to electron TruthTool.DecayProduct2PDG = 12 ## .. and electron neutrino TruthTool.OutputLevel = myOutputLevel ## Logging level ToolSvc += TruthTool from LivDumpers.LivDumpersConf import Analysis__DumpSingleBosonTruth DumpTruth = Analysis__DumpSingleBosonTruth(name = 'WenuTruthDump') DumpTruth.TruthTool = TruthTool ## This is the tool we just configured DumpTruth.TreeName = 'WenuTruth' ## The output tree name DumpTruth.OutputLevel = myOutputLevel ## Logging level DumpTruth.OutputBranchPrefix = 'Wenu' ## There's no conflict with ZDump here - it's a different tree DumpTruth.DoDocuParticles = True ## The documentary particles are pre-FSR DumpTruth.DoBosonParents = True ## this is pre-ISR? job += DumpTruth # Dump Missing Et Info (Thomas version) DumpAllMET = True DumpTruthMET = True include("LivDumpers/DumpMET_jobOptions.py") ## we also dump the jets as preselected in container PreselectedJets (Cone4H1TowerJets) from LivDumpers.LivDumpersConf import Analysis__DumpJets DumpJets = Analysis__DumpJets(name = 'JetDump') DumpJets.JetContainer = 'PreselectedJets' DumpJets.TreeName = 'PreselectedJetTree' DumpJets.OutputLevel = myOutputLevel job += DumpJets ## Generic CBNT setup, function defined in LivTools/LivTools_jobUtils.py ## Most of this is hidden by the athena framework, but the "Dumper" algorithms don't write directly to file. ## They write to a stream - this function defines streams for each unique TreeName in the job. ## If some/all of the Dumpers were attached to jobSequence, you'd need to call addStreams(jobSequence, outputFilename) ## as well as/instead of this function call. addStreams(job, outputFileName) ## This just does some general output formatting. svcMgr.MessageSvc.OutputLevel = WARNING svcMgr.MessageSvc.Format = "% F%50W%S%7W%R%T %0W%M" ## If you want to get rid of the event-by-event messages from AthenaEventLoopMgr, ## uncomment the next two lines #from AthenaServices.AthenaServicesConf import AthenaEventLoopMgr #AthenaEventLoopMgr.OutputLevel = WARNING ## Uncommenting some or all of these can help debugging. #print job #print svcMgr #print ToolSvc