WARNING: This twiki is outdated , please refer to the main PAT twiki SWGuidePAT
PAT - Layer 2
Complete:
Purpose
The purpose of the PAT Layer 2 is to provide hypothesis-specific interfaces to the PAT. The advantages of this are manyfold:
- Objects that use the PAT Layer 2 will have a similar "feel" to the users.
- Objects that use the PAT Layer 2 will be able to be automatically plotted by histogram utilities like the StarterKit
- Users can easily construct their own personal event hypotheses using the PAT Layer 2 functionality.
Overview
The design philosophy of the PAT Layer 2 was to provide generic "role" assignments to the user. That is, the event hypothesis should make intuitive sense and the user can assign specific labels to each of the daughters in a hypothesis. For instance, one event hypothesis could be
Z -> muon + muon
The roles would be trivial in this case, simply two muons, and the output (the Z, constructed from the two muon roles):
muon1 : muon
muon2 : muon
Z = muon1 + muon2
We can further build more complicated event hypotheses like
H -> (Z -> muon + muon) + (Z -> electron + electron)
The roles in this case would be the two muons, two electrons, the two Z's constructed from those leptons, and the Higgs constructed from those Z bosons.
muon1 : muon
muon2 : muon
electron1 : electron
electron2 : electron
Z1 = muon1 + muon2
Z2 = electron1 + electron2
H = Z1 + Z2
The user should be able to access the daughters by giving the string of the roles. This allows for more intuitive data access and more specific "human" control over the construction of the event hypothesis.
The PAT Layer 2 implements the role structure with two separate options available to the user.
- Flat Event Hypothesis
- Hierarchical Event Hypothesis
We now discuss these each in turn.
Flat Event Hypothesis
The
flat event hypothesis
declares the event hypothesis without automatically structuring the constituents. Therefore, the hypothesis shown above is precisely the way that the hypothesis is formed in the event. Each member is basically a "string to object map", which will input a string and give back the item corresponding to it. The simplest accessor in the interface is as follows:
const CandRefType & get(const std::string &role, int index=0) const ;
Here, we see that we are accessing the candidate by the role name, as well as an index should that role be part of a vector. This allows for accessing the "jets" in a "Z + jets" or a "ttbar + jets" event hypothesis.
There are many ways to navigate the event hypothesis here, including "loopers" which will loop over particles of the same role, or similar roles (as defined by regular expressions):
CandLooper loop(const std::string &roleRegexp) const;
The
looper
is able to access particles by
regular expressions
, and can navigate through those candidates. So, for instance, if your roles are named
muon1
and
muon2
, you can get all the muons by
Looper<Muon> looper = hyp.loop("muon[12]");
while( !looper() ) {
const Muon & mu = *looper;
fill( mu.pt() );
++looper;
}
Hierarchical Event Hypothesis
The hierarchical event hypothesis is based on
NamedCompositeCandidates. Instead of directly placing all objects in a flat structure, it instead stores them hierarchically as a decay chain. So, in the example above, the data storage would be
H -> (Z1 -> muon1 + muon2) + (Z2 -> electron1 + electron2)
The advantage of the hierarchical structure is that the nodes of the hypothesis are all
reco::Candidates
. There is no need to have a secondary access to get at the Candidate, because it is simply stored as the
reco::Candidates
themselves. For true decays, a hierarchical structure is also somewhat more intuitive and allows for easy generation of multiple hierarchies with little to no effort.
The way to construct such an event hypothesis would be as follows:
Muon & mu1 = ..., & mu2 = ...;
Electron & ele1 = ..., & ele2 = ...;
NamedCompositeCandidate Z1("Z1");
Z1.addDaughter( mu1, "muon1");
Z1.addDaughter( mu2, "muon2");
NamedCompositeCandidate Z2("Z2");
Z2.addDaughter( ele1, "electron1");
Z2.addDaughter( ele2, "electron2");
NamedCompositeCandidate H("H");
H.addDaughter( Z1, "Z1");
H.addDaughter( Z2, "Z2");
To access the daughters, one can do
const Candidate * Z1 = H.daughter("Z1");
Since these are based on
=reco::CompositeCandidates=, a host of tools are at the fingers of the user. For instance, one can create a
shallow clone candidate" and add it to the event hypothesis to avoid making a copy and thereby saving space and time. The user also has the full suite of
Candidate Utilities developed by the Physics Tools group available to them. Therefore the event hypothesis can be manipulated, selected upon, combined into other hypotheses, automatically plotted, streamed to the event record, and many other things.
Relative Advantages and Disadvantages.
- Flat Event Hypothesis
- Advantages:
- Simple to examine objects with the same type.
- Simple to loop over the entire event hypothesis.
- Able to naturally handle cases like
Z + jets
which are not strict decays.
- Disadvantages:
- No way to combine nodes in the hypothesis automatically.
- No tools available automatically (such as selectors, etc).
- The user must know what the hierarchy is in their brain, there is no way to glean this from the event hypothesis itself.
- Hierarchical Event Hypothesis
- Advantages:
- Trivial to combine nodes automatically.
- Has access to full suite of
Candidate
manipulations.
- More natural to handle "true" decays.
- Disadvantages:
- Does not naturally handle cases like
Z + jets
... the user cannot add the "plus jets" part into the hypothesis without making unphysical nodes (there is nothing special about the parent of the Z and the jets).
- Difficult to loop over single types (i.e. no regular expression looping mechanism).
- To access nodes, must loop through hierarchy.
Ultimately your analysis will be better served by one or the other of these. We provide both as alternatives to the user, who can decide which is more appropriate to their analysis.
Examples
Flat Event Hypothesis
Coming soon!
Hierarchical Event Hypothesis
Using Candidate Combiners
A functional code snippet to use the PAT Layer 1 objects in an event hypothesis is
### H->ZZ ###
module zToMuMu = NamedCandViewShallowCloneCombiner {
string decay = "selectedLayer1Muons@+ selectedLayer1Muons@-"
string cut = "0.0 < mass < 20000.0"
string name = "zToMuMu"
vstring roles = { 'muon1', 'muon2' }
}
module hToZZ = NamedCandViewCombiner {
string decay = "zToMuMu zToMuMu"
string cut = "0.0 < mass < 20000.0"
string name = "hToZZ"
vstring roles = { 'Z1', 'Z2' }
}
The first module will create
Z->mu + mu
candidates from
ShallowCloneCandidates
of PAT Layer 1 muons (which are input in a
View
), and output a
vector
. The second module will then use the output of the first to create Higgs candidates from
H -> Z1 + Z1
. These will be straight copies of the Z's from the first, since they are transient and can be safely discarded. To store the entire hierarchy, place the following snippet in your configuration file:
replace patEventContent.outputCommands += {
"keep *_hToZZ_*_*"
}
This will store the entire hierarchy of all the Higgs candidates in the event.
The
StarterKit has a full example of using this example
here.
Hierarchical Event Hypothesis in TQAF
The hierarchical event hypothesis is fully explointed and implemented in the complex environment of top analyses with help of the
TQAF. For more information on the implementation have a look to the
SWGuideTQAFClasses and the
SWGuideTQAFLayer2 description. For a step by step tutorial how to implement new event hypotheses with the help of TQAF and how to use and exploit them within the full framework and FWLite have a look to the
SWGuideTQAFTutorial
Using pre-existing Layer 2 in TQAF
It is also possible to modify existing event hypothesis, such as those in the
TQAF Layer 2. As a prototype we have modified the class
TtSemiEvtSolution
to include the following event hypothesis:
reco::NamedCompositeCandidate recoHyp_;
This is filled with a function in the
source file
:
void TtSemiEvtSolution::setupHyp()
{
AddFourMomenta addFourMomenta;
recoHyp_.clearDaughters();
recoHyp_.clearRoles();
// Setup transient references
reco::NamedCompositeCandidate recHadt;
reco::NamedCompositeCandidate recLept;
reco::NamedCompositeCandidate recHadW;
reco::NamedCompositeCandidate recLepW;
// Get refs to leaf nodes
reco::ShallowCloneCandidate hadp( reco::CandidateBaseRef( hadp_ ), hadp_->charge(), hadp_->p4(), hadp_->vertex() );
reco::ShallowCloneCandidate hadq( reco::CandidateBaseRef( hadq_ ), hadq_->charge(), hadq_->p4(), hadq_->vertex() );
reco::ShallowCloneCandidate hadb( reco::CandidateBaseRef( hadb_ ), hadb_->charge(), hadb_->p4(), hadb_->vertex() );
reco::ShallowCloneCandidate lepb( reco::CandidateBaseRef( lepb_ ), lepb_->charge(), lepb_->p4(), lepb_->vertex() );
reco::ShallowCloneCandidate neutrino( reco::CandidateBaseRef( neutrino_ ), neutrino_->charge(), neutrino_->p4(), neutrino_->vertex() );
recHadW.addDaughter( hadp, "hadp" );
recHadW.addDaughter( hadq, "hadq" );
addFourMomenta.set( recHadW );
recHadt.addDaughter( hadb, "hadb" );
recHadt.addDaughter( recHadW, "hadW" );
addFourMomenta.set( recHadt );
recLepW.addDaughter( neutrino,"neutrino" );
if ( getDecay() == "electron" ) {
reco::ShallowCloneCandidate electron ( reco::CandidateBaseRef( electron_), electron_->charge(), electron_->p4(), electron_->vertex() );
recLepW.addDaughter ( electron, "electron" );
} else if ( getDecay() == "muon" ) {
reco::ShallowCloneCandidate muon ( reco::CandidateBaseRef( muon_ ), muon_->charge(), muon_->p4(), muon_->vertex() );
recLepW.addDaughter ( muon, "muon" );
}
addFourMomenta.set( recLepW );
recLept.addDaughter( lepb, "lepb" );
recLept.addDaughter( recLepW, "lepW" );
addFourMomenta.set( recLept );
recoHyp_.addDaughter( recHadt, "hadt" );
recoHyp_.addDaughter( recLept, "lept" );
addFourMomenta.set( recoHyp_ );
}
This function creates
ShallowCloneCandidates
out of the objects of interest and creates a
ttbar
event hierarchy. This can be fed into plotting utilities like the
StarterKit. A fully worked example from the
StarterKit is shown
here.