EventView

Introduction

EventView is an analysis framework within Athena that does a lot of handy things like overlap removal, cuts, particle combination, dumping NTuples... A lot of tools have already been written and you can do a pretty complicated analysis just by stitching these tools together in your job options, without having to compile any code. However, you are in no way limited to use the existing tools. EventView is extensible in that if there is not a tool to do what you want, you can easily develop your own. Besides overlap removal, the best thing about the EventView Framework is that it encourages a modular design to your analysis and the reusability of code. To know more about the philosophy and organization of the EventView Framework, I recommend that you read the EventView ATLAS Note.

One confusing thing, is that EventView can refer to the entire EventView Framework or the EventView class. In theses notes, I try to include the word "Framework" when appropriate. An EventView (EV) is a class that holds pointers to particles that represent a "view" of what an event was. The particle objects actually remain in the AOD containers held in StoreGate, but EV gives you a way to organize which particles pass your selection cuts and allows you to label them.

Back to top

The Start of EV Job Options

A Job Option using the EV Framework, should start with:

#-------------------------------------------------------------------------
# Athena imports
#-------------------------------------------------------------------------
from AthenaCommon.Constants import *
from AthenaCommon.AppMgr import theApp
from AthenaCommon.AppMgr import ServiceMgr
import AthenaPoolCnvSvc.ReadAthenaPool
from AthenaCommon.AlgSequence import AlgSequence
theJob = AlgSequence()


#-------------------------------------------------------------------------
# EventView imports
#-------------------------------------------------------------------------
from EventViewBuilderAlgs.EventViewBuilderAlgsConf import *
from EventViewInserters.EventViewInsertersConf import *
from EventViewUserData.EventViewUserDataConf import *
from EventViewDumpers.EventViewDumpersConf import *
from EventViewCombiners.EventViewCombinersConf import *
from EventViewConfiguration.DefaultModules.AANtupleFromUserData_module import * # for AANtupleFromUserData


#-------------------------------------------------------------------------
# Message Service
#-------------------------------------------------------------------------
# Set output level threshold (2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, 6=FATAL )
ServiceMgr.MessageSvc.OutputLevel = WARNING
import AthenaServices
AthenaServices.AthenaServicesConf.AthenaEventLoopMgr.OutputLevel = WARNING


#-------------------------------------------------------------------------
# Input Datasets
#-------------------------------------------------------------------------
ServiceMgr.EventSelector.InputCollections = [
    '/usatlas/u/rreece/workarea/data/13/Zee/AOD.016450._00017.pool.root.2',
    '/usatlas/u/rreece/workarea/data/13/Zee/AOD.016450._00293.pool.root.4']
theApp.EvtMax = 20 # -1 means all events

This sets up Athena, imports things for the EV Framework, sets the Output Level of the Message Service, and specifies the input datasets.

Back to top

EventView Tool Looper

Next, you should add an EV Tool Looper to the job. The EV Tool Looper is the main algorithm of the EV Framework that you add to the Athena algorithm sequence of a job. It holds the collection of EVs created for a single event and runs the list of EV tools added to it. An EV tool is like a small algorithm that runs and does something to the EV, like inserting particles into the EV or combining particles to make inferred particles. You add an EV Tool Looper by:

#-------------------------------------------------------------------------
# Algorithms
#-------------------------------------------------------------------------
theJob += EVMultipleOutputToolLooper('theToolLooper',
        EventViewCollectionOutputName = 'myEventViewCollection',
        OutputLevel = WARNING)

Back to top

Inserting Particles

You add tools to the EVMultipleOutputToolLooper by using +=, just like adding algorithms to theJob. Your first tool should probably be one that inserts particles into the EV. For example, to insert electrons, use the EVElectronInserter tool:

#-------------------------------------------------------------------------
# EventView Tools
#-------------------------------------------------------------------------
theToolLooper = theJob.theToolLooper

theToolLooper += EVElectronInserter('theElectronInserter',
        InsertedLabels = ['Electron'],
        etCut = 15*GeV,
        EtaMaxCut = 2.0,
        makeEtaCuts = True )

This makes some selection cuts on the electrons in the AOD. Those that pass the cuts and do no overlap with anything already inserted into the EV are inserted into the Final State (FS) particles of the EV and labeled with the the labels specified by InsertedLabels. Labels are important because we will use them later to refer to these particles in other tools.

In the terminal output, aftering running the job, you should see a cut flow table summarizing the particle insertion.

theToolLooper.t...   INFO 
CUT RESULTS: ElectronAODCollection
==============================================================================
= Cut                           Num Passed     Cut Effic.     Cut Flow Eff.  =
=----------------------------------------------------------------------------=
= All                           4403           1              1              =
= EtaMaxCut                     3722           0.845          0.845          =
= EtaMinCut                     3722           1              0.845          =
= ptCut                         3722           1              0.845          =
= etCut                         2296           0.617          0.521          =
= eCut                          2296           1              0.521          =
= authorCut                     2296           1              0.521          =
= isolationCut                  2296           1              0.521          =
= caloCut                       2228           0.97           0.506          =
= track Quality Cut             2188           0.982          0.497          =
= All_Preselection              2188           1              0.497          =
= Overlap                       2162           0.988          0.491          =
= Inserted                      2162           1              0.491          =
==============================================================================

Back to top

Screen Dumping

After inserting particles into your EV, you may want to check to see that they are there. You can dump the EV information to the screen by adding the following to your job option and running it in Athena.
theToolLooper += EVScreenDumper('theScreenDumper', PrintUserData = False)

The argument PrintUserData = False turns off the printing of the names of UD variables, since as your analysis matures, you can often have many variables.

Back to top

Athena Aware Ntuple (AAN) Dumping

You can dump data from EVs into a TTree in a ROOT file, but first, you have to save that data as User Data (UD) in the EVs. For that you need to schedule an EVUDFinalStateLooper to the EVMultipleOutputToolLooper, a looper within a looper. The EVMultipleOutputToolLooper loops over each event creating EVs and running the scheduled tools over them. The EVUDFinalStateLooper is one of those tools. It loops over the FS particles in a single EV and runs the tools schedules on it. You can schedule the EVUDKinCalc tool to the EVUDFinalStateLooper, and it will dump the the FS particles' kinetic variables like energy, momentum, eta... into UD. This is done by adding the following to your job options.
DumpLooper = EVUDFinalStateLooper('myDumpLooper',
            Prefix = 'Electron_',
            RequireLabels = ['Electron'] )
DumpLooper += EVUDKinCalc('myEVUDKinCalc')
theToolLooper +=DumpLooper

I like to generalize this by defining the following function in my job options:

def DumpFSKin(ToolLooper, PrefixArg,
        LabelsArg=[], RequireLabelsArg=[], RejectLabelsArg=[]):
    DumpLooper = EVUDFinalStateLooper(PrefixArg + 'DumpLooper',
            Prefix = PrefixArg,
            Labels = LabelsArg,
            RequireLabels = RequireLabelsArg,
            RejectLabels = RejectLabelsArg )
    DumpLooper += EVUDKinCalc(PrefixArg + 'EVUDKinCalc')
    ToolLooper += DumpLooper

And then calling it by:

DumpFSKin(theToolLooper, 'Electron_', RequireLabelsArg=['Electron'])

Similarly, one can loop over Inferred Objects, explained below, and dump their kinematics into UD:

def DumpIOKin(ToolLooper, PrefixArg,
        LabelsArg=[], RequireLabelsArg=[], RejectLabelsArg=[]):
    DumpLooper = EVUDInferredObjectLooper(PrefixArg + 'DumpLooper',
            Prefix = PrefixArg,
            Labels = LabelsArg,
            RequireLabels = RequireLabelsArg,
            RejectLabels = RejectLabelsArg )
    DumpLooper += EVUDKinCalc(PrefixArg + 'EVUDKinCalc')
    ToolLooper += DumpLooper

And call it by:

DumpIOKin(theToolLooper, 'Z_', RequireLabelsArg=['Z'])

Now that the variables are in UD, you can add code to the job options to dump the UD into an AAN:

theToolLooper += AANtupleFromUserData('theNtupleDumper',
        filename='Zee.AAN.root', sequencer=theJob, EventTree=True,
        CandTree=False)

Athena release 13.0.40 uses ROOT version 5.14, but that version of ROOT has trouble with vector<double> being in branches of a TTree. Using ROOT version 5.17 avoids this problem. Changing your ROOT version in the same terminal that you run Athena, could cause troubles for Athena. It is recommended that you change your ROOT version in a different terminal, and do ROOT work there. I setup ROOT by using the following .bashrc function.

function setup_root {
    export ROOTSYS=/afs/usatlas.bnl.gov/cernsw/lcg/external/root/5.17.08/slc4_ia32_gcc34/root
    export PATH=$ROOTSYS/bin/:$PATH
    export LD_LIBRARY_PATH=${ROOTSYS}/lib:$LD_LIBRARY_PATH
    export PYTHONPATH=${ROOTSYS}/lib:$PYTHONPATH
}

Back to top

Combining Particles

You can use the EV Framework Combiner Tools to combine particles in an EV into Inferred Objects (IO), from which they decayed. For example, you can combine an electron and positron to make a Z boson. This is done by adding the following tool to the EVMultipleOutputToolLooper.

theToolLooper += EVSimpleCombo('ZeeCombo',
        Labels = ['Electron'],
        OutputLabel = 'Z',
        DaughterLabel = 'ZDaughter',
        LowMass = 0*GeV,
        HighMass = 10000*GeV,
        NDaughters = 2,
        CheckCharge = True,
        Charge = 0,
        SortParticles = True,
        PassOnNoCombo = True )

This combines every pair of electrons (specified by Labels = ['Electron'] and NDaughters = 2) that have opposite charge (CheckCharge = True, Charge = 0). The IO particle is labeled by OutputLabel = 'Z'. The electrons that were combined are labeled by DaughterLabel = 'ZDaughter'. If there is more than one possible pairing, each pairing is done in separate EVs for the same event, named EV0, EV1, EV2... Upon dumping into an AAN, the different EVs will be stored in separate trees.

If you need to combine two different types of particles (instead of pairs of the same type of particle like above), then you need to use EVGeneralCombo. The Following example shows the combination of a muon and a tau-jet, specified by Labels.

theToolLooper += EVGeneralCombo('OSMuTauCombo',
        Labels = ['Muon', 'TauJet'],
        OutputLabel = 'OSComboMuTau',
        DaughterLabel = 'OSDaughterMuTau',
        LowMass = 0*GeV,
        HighMass = 200*GeV,
        CheckCharge = True,
        Charge = 0,
        PassOnNoCombo = True )

Back to top

Example Analysis: Z → ee

Putting together all the tools discussed above, one can do a Z → ee analysis using EV Tools with the following job option, without having to write your own tools or compile any code.
#-------------------------------------------------------------------------
# Athena imports
#-------------------------------------------------------------------------
from AthenaCommon.Constants import *
from AthenaCommon.AppMgr import theApp
from AthenaCommon.AppMgr import ServiceMgr
import AthenaPoolCnvSvc.ReadAthenaPool
from AthenaCommon.AlgSequence import AlgSequence
theJob = AlgSequence()


#-------------------------------------------------------------------------
# EventView imports
#-------------------------------------------------------------------------
from EventViewBuilderAlgs.EventViewBuilderAlgsConf import *
from EventViewInserters.EventViewInsertersConf import *
from EventViewUserData.EventViewUserDataConf import *
from EventViewDumpers.EventViewDumpersConf import *
from EventViewCombiners.EventViewCombinersConf import *
from EventViewConfiguration.DefaultModules.AANtupleFromUserData_module import * # for AANtupleFromUserData


#-------------------------------------------------------------------------
# Message Service
#-------------------------------------------------------------------------
# Set output level threshold (2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, 6=FATAL )
ServiceMgr.MessageSvc.OutputLevel = WARNING
import AthenaServices
AthenaServices.AthenaServicesConf.AthenaEventLoopMgr.OutputLevel = WARNING


#-------------------------------------------------------------------------
# Input Datasets
#-------------------------------------------------------------------------
ServiceMgr.EventSelector.InputCollections = [
    '/usatlas/u/rreece/workarea/data/13/Zee/AOD.016450._00017.pool.root.2',
    '/usatlas/u/rreece/workarea/data/13/Zee/AOD.016450._00293.pool.root.4']
theApp.EvtMax = -1 # -1 means all events


#-------------------------------------------------------------------------
# Algorithms
#-------------------------------------------------------------------------
theJob += EVMultipleOutputToolLooper('theToolLooper',
        EventViewCollectionOutputName = 'myEventViewCollection',
        OutputLevel = WARNING)


#-------------------------------------------------------------------------
# EventView Tools
#-------------------------------------------------------------------------
theToolLooper = theJob.theToolLooper

theToolLooper += EVElectronInserter('theElectronInserter',
        InsertedLabels = ['Electron'],
        etCut = 15*GeV,
        EtaMaxCut = 2.0,
        makeEtaCuts = True )

theToolLooper += EVSimpleCombo('ZeeCombo',
        Labels = ['Electron'],
        OutputLabel = 'Z',
        DaughterLabel = 'ZDaughter',
        LowMass = 0*GeV,
        HighMass = 10000*GeV,
        NDaughters = 2,
        CheckCharge = True,
        Charge = 0,
        SortParticles = True,
        PassOnNoCombo = True )


#-------------------------------------------------------------------------
# EventView Dumping
#-------------------------------------------------------------------------
def DumpFSKin(ToolLooper, PrefixArg,
        LabelsArg=[], RequireLabelsArg=[], RejectLabelsArg=[]):
    DumpLooper = EVUDFinalStateLooper(PrefixArg + 'DumpLooper',
            Prefix = PrefixArg,
            Labels = LabelsArg,
            RequireLabels = RequireLabelsArg,
            RejectLabels = RejectLabelsArg )
    DumpLooper += EVUDKinCalc(PrefixArg + 'EVUDKinCalc')
    ToolLooper += DumpLooper

def DumpIOKin(ToolLooper, PrefixArg,
        LabelsArg=[], RequireLabelsArg=[], RejectLabelsArg=[]):
    DumpLooper = EVUDInferredObjectLooper(PrefixArg + 'DumpLooper',
            Prefix = PrefixArg,
            Labels = LabelsArg,
            RequireLabels = RequireLabelsArg,
            RejectLabels = RejectLabelsArg )
    DumpLooper += EVUDKinCalc(PrefixArg + 'EVUDKinCalc')
    ToolLooper += DumpLooper

DumpFSKin(theToolLooper, 'Electron_', RequireLabelsArg=['Electron', 'ZDaughter'])
DumpIOKin(theToolLooper, 'Z_', RequireLabelsArg=['Z'])

#theToolLooper += EVScreenDumper('theScreenDumper')

theToolLooper += AANtupleFromUserData('theNtupleDumper',
        filename='Zee.AAN.root', sequencer=theJob, EventTree=True,
        CandTree=False)


print theJob

Back to top

Branching Tool

What if you want to run two analyses that are largely the same except for a few tools being different? Then you can fork your job into separate branches where each branch has a different set of tools. Before and after the branch, the analyses can share common tools.

The following example makes two branches that have different TauJetInserters

theToolLooper += some tools common to both branches

theToolLooper += EVMultiToolBranch('Branch',
        OutputLevel = WARNING)

theToolLooper.Branch += EVTauJetInserter('TauRecInserter',
        InsertedLabels = ['TauRec', 'TauJet'],
        DoPreselection = True,
        Require3orLessTracks = False,
        MultiTrackMassCut = 10000000,  #i.e. no cut
        HadronicEnergyFraction = -10000000,  #i.e. no cut
        ParamPID_CutList = [TauJetParameters.Likelihood],
        ParamPID_CutValues = [4.],
        ParamPID_CutIsGreaterThan = [True],
        etCut = 15*GeV,
        RequireChargeToBeOne = True,
        EtaMaxCut = 2.5,
        makeEtaCuts = True,
        ContainerKey = 'TauRecContainer' )

theToolLooper.Branch += EVTauJetInserter('Tau1P3PInserter',
        InsertedLabels = ['Tau1P3P', 'TauJet'],
        DoPreselection = True,
        Require3orLessTracks = False,
        MultiTrackMassCut = 10000000,  #i.e. no cut
        HadronicEnergyFraction = -10000000,  #i.e. no cut
        ParamPID_CutList = [TauJetParameters.DiscCut],
        ParamPID_CutValues = [0.5],
        ParamPID_CutIsGreaterThan = [True],
        ParamVetoFlags_CutList = [TauJetParameters.ElectronFlag, TauJetParameters.MuonFlag],
        etCut = 15*GeV,
        RequireChargeToBeOne = True,
        EtaMaxCut = 2.5,
        makeEtaCuts = True,
        ContainerKey = 'Tau1P3PContainer' )

theToolLooper.Branch.Groups = [1,1]
theToolLooper.Branch.EventViewNames = ['TauRecEV', 'Tau1P3PEV']

theToolLooper += some more tools common to both branches

The line with Groups = [1,1] partitions the tools added to Branch into separate branches. This means that the first tool is in one branch and the second tool in another. If I had added three tools and I wanted the first two in one branch and the last in a separate branch, then I would do Groups = [2,1]. The line with EventViewNames = ['TauRecEV', 'Tau1P3PEV'] names the branches.

You can then save the UD from different branches in separate TTrees by specifying Flags that correspond to EventViewNames.

theToolLooper += AANtupleFromUserData('theTauRecNtupleDumper',
        sequencer=theJob, EventTree=True, CandTree=False,
        filename=OUTPUT, Prefix='TauRec', Create=True, Flags=['TauRecEV'])

theToolLooper += AANtupleFromUserData('theTau1P3PNtupleDumper',
        sequencer=theJob, EventTree=True, CandTree=False,
        filename=OUTPUT, Prefix='Tau1P3P', Create=False, Flags=['Tau1P3PEV'])

Note that the second AANtupleFromUserData has Create = False because the ROOT file was already created by the first one.

Back to top

Missing Transverse Energy (MET)

Since there is no z-component information for MET, MET is not inserted like particles which have all four-momentum components. Instead, there is a tool to add MET directly to your UD.

theToolLooper += EVMissingEtUserData('METtoUD',
        MissingETKeys = ['MET_RefFinal'])
where MET_RefFinal is the StoreGate Key for the MET. After using AANtupleFromUserData, your TTree should include the following variables:
  • MET_RefFinal_et
  • MET_RefFinal_ex
  • MET_RefFinal_ey
  • MET_RefFinal_sumet

Back to top


-- RyanReece - 11 Jan 2008
-- RyanReece - 19 Mar 2008
Edit | Attach | Watch | Print version | History: r13 < r12 < r11 < r10 < r9 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r13 - 2008-10-08 - RyanReece
 
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    Sandbox All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2020 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback