CMS 3D CMS Logo

RecoTauConstructor.cc
Go to the documentation of this file.
2 
5 
7 
9 
10 namespace reco::tau {
11 
13  bool copyGammasFromPiZeros,
17  : signalConeSize_(signalConeSize),
18  minAbsPhotonSumPt_insideSignalCone_(minAbsPhotonSumPt_insideSignalCone),
19  minRelPhotonSumPt_insideSignalCone_(minRelPhotonSumPt_insideSignalCone),
20  minAbsPhotonSumPt_outsideSignalCone_(minAbsPhotonSumPt_outsideSignalCone),
21  minRelPhotonSumPt_outsideSignalCone_(minRelPhotonSumPt_outsideSignalCone),
22  pfCands_(pfCands)
23 {
24  // Initialize tau
25  tau_.reset(new PFTau());
26 
27  copyGammas_ = copyGammasFromPiZeros;
28  // Initialize our Accessors
29  collections_[std::make_pair(kSignal, kChargedHadron)] =
30  &tau_->selectedSignalChargedHadrCands_;
31  collections_[std::make_pair(kSignal, kGamma)] =
32  &tau_->selectedSignalGammaCands_;
33  collections_[std::make_pair(kSignal, kNeutralHadron)] =
34  &tau_->selectedSignalNeutrHadrCands_;
35  collections_[std::make_pair(kSignal, kAll)] =
36  &tau_->selectedSignalCands_;
37 
38  collections_[std::make_pair(kIsolation, kChargedHadron)] =
39  &tau_->selectedIsolationChargedHadrCands_;
40  collections_[std::make_pair(kIsolation, kGamma)] =
41  &tau_->selectedIsolationGammaCands_;
42  collections_[std::make_pair(kIsolation, kNeutralHadron)] =
43  &tau_->selectedIsolationNeutrHadrCands_;
44  collections_[std::make_pair(kIsolation, kAll)] =
45  &tau_->selectedIsolationCands_;
46 
47  // Build our temporary sorted collections, since you can't use stl sorts on
48  // RefVectors
49  for(auto const& colkey : collections_) {
50  // Build an empty list for each collection
51  sortedCollections_[colkey.first] = SortedListPtr(
52  new SortedListPtr::element_type);
53  }
54 
55  tau_->setjetRef(jet);
56 }
57 
58 void RecoTauConstructor::addPFCand(Region region, ParticleType type, const CandidatePtr& ptr, bool skipAddToP4) {
59  LogDebug("TauConstructorAddPFCand") << " region = " << region << ", type = " << type << ": Pt = " << ptr->pt() << ", eta = " << ptr->eta() << ", phi = " << ptr->phi();
60  if ( region == kSignal ) {
61  // Keep track of the four vector of the signal vector products added so far.
62  // If a photon add it if we are not using PiZeros to build the gammas
63  if ( ((type != kGamma) || !copyGammas_) && !skipAddToP4 ) {
64  LogDebug("TauConstructorAddPFCand") << "--> adding PFCand to tauP4." ;
65  p4_ += ptr->p4();
66  }
67  }
68  getSortedCollection(region, type)->push_back(ptr);
69  // Add to global collection
70  getSortedCollection(region, kAll)->push_back(ptr);
71 }
72 
74  getSortedCollection(region, type)->reserve(size);
75  getCollection(region, type)->reserve(size);
76  // Reserve global collection as well
77  getSortedCollection(region, kAll)->reserve(
78  getSortedCollection(region, kAll)->size() + size);
79  getCollection(region, kAll)->reserve(
80  getCollection(region, kAll)->size() + size);
81 }
82 
84 {
85  if ( region == kSignal ) {
86  tau_->signalTauChargedHadronCandidatesRestricted().reserve(size);
87  tau_->selectedSignalChargedHadrCands_.reserve(size);
88  } else {
89  tau_->isolationTauChargedHadronCandidatesRestricted().reserve(size);
90  tau_->selectedIsolationChargedHadrCands_.reserve(size);
91  }
92 }
93 
94 namespace
95 {
96  void checkOverlap(const CandidatePtr& neutral, const std::vector<CandidatePtr>& pfGammas, bool& isUnique)
97  {
98  LogDebug("TauConstructorCheckOverlap") << " pfGammas: #entries = " << pfGammas.size();
99  for ( std::vector<CandidatePtr>::const_iterator pfGamma = pfGammas.begin();
100  pfGamma != pfGammas.end(); ++pfGamma ) {
101  LogDebug("TauConstructorCheckOverlap") << "pfGamma = " << pfGamma->id() << ":" << pfGamma->key();
102  if ( (*pfGamma).refCore() == neutral.refCore() && (*pfGamma).key() == neutral.key() ) isUnique = false;
103  }
104  }
105 
106 
107  void checkOverlap(const CandidatePtr& neutral, const std::vector<reco::RecoTauPiZero>& piZeros, bool& isUnique)
108  {
109  LogDebug("TauConstructorCheckOverlap") << " piZeros: #entries = " << piZeros.size();
110  for ( std::vector<reco::RecoTauPiZero>::const_iterator piZero = piZeros.begin();
111  piZero != piZeros.end(); ++piZero ) {
112  size_t numPFGammas = piZero->numberOfDaughters();
113  for ( size_t iPFGamma = 0; iPFGamma < numPFGammas; ++iPFGamma ) {
114  reco::CandidatePtr pfGamma = piZero->daughterPtr(iPFGamma);
115  LogDebug("TauConstructorCheckOverlap") << "pfGamma = " << pfGamma.id() << ":" << pfGamma.key();
116  if ( pfGamma.id() == neutral.id() && pfGamma.key() == neutral.key() ) isUnique = false;
117  }
118  }
119  }
120 }
121 
123 {
124  LogDebug("TauConstructorAddChH") << " region = " << region << ": Pt = " << chargedHadron.pt() << ", eta = " << chargedHadron.eta() << ", phi = " << chargedHadron.phi();
125  // CV: need to make sure that PFGammas merged with ChargedHadrons are not part of PiZeros
126  const std::vector<CandidatePtr>& neutrals = chargedHadron.getNeutralPFCandidates();
127  std::vector<CandidatePtr> neutrals_cleaned;
128  for ( std::vector<CandidatePtr>::const_iterator neutral = neutrals.begin();
129  neutral != neutrals.end(); ++neutral ) {
130  LogDebug("TauConstructorAddChH") << "neutral = " << neutral->id() << ":" << neutral->key();
131  bool isUnique = true;
132  if ( copyGammas_ ) checkOverlap(*neutral, *getSortedCollection(kSignal, kGamma), isUnique);
133  else checkOverlap(*neutral, tau_->signalPiZeroCandidatesRestricted(), isUnique);
134  if ( region == kIsolation ) {
135  if ( copyGammas_ ) checkOverlap(*neutral, *getSortedCollection(kIsolation, kGamma), isUnique);
136  else checkOverlap(*neutral, tau_->isolationPiZeroCandidatesRestricted(), isUnique);
137  }
138  LogDebug("TauConstructorAddChH") << "--> isUnique = " << isUnique;
139  if ( isUnique ) neutrals_cleaned.push_back(*neutral);
140  }
141  PFRecoTauChargedHadron chargedHadron_cleaned = chargedHadron;
142  if ( neutrals_cleaned.size() != neutrals.size() ) {
143  chargedHadron_cleaned.neutralPFCandidates_ = neutrals_cleaned;
144  setChargedHadronP4(chargedHadron_cleaned);
145  }
146  if ( region == kSignal ) {
147  tau_->signalTauChargedHadronCandidatesRestricted().push_back(chargedHadron_cleaned);
148  p4_ += chargedHadron_cleaned.p4();
149  if ( chargedHadron_cleaned.getChargedPFCandidate().isNonnull() ) {
150  addPFCand(kSignal, kChargedHadron, convertToPtr(chargedHadron_cleaned.getChargedPFCandidate()), true);
151  }
152  const std::vector<CandidatePtr>& neutrals = chargedHadron_cleaned.getNeutralPFCandidates();
153  for ( std::vector<CandidatePtr>::const_iterator neutral = neutrals.begin();
154  neutral != neutrals.end(); ++neutral ) {
155  if ( std::abs((*neutral)->pdgId()) == 22 ) addPFCand(kSignal, kGamma, convertToPtr(*neutral), true);
156  else if ( std::abs((*neutral)->pdgId()) == 130 ) addPFCand(kSignal, kNeutralHadron, convertToPtr(*neutral), true);
157  };
158  } else {
159  tau_->isolationTauChargedHadronCandidatesRestricted().push_back(chargedHadron_cleaned);
160  if ( chargedHadron_cleaned.getChargedPFCandidate().isNonnull() ) {
161  if ( std::abs(chargedHadron_cleaned.getChargedPFCandidate()->pdgId()) == 211 ) addPFCand(kIsolation, kChargedHadron, convertToPtr(chargedHadron_cleaned.getChargedPFCandidate()));
162  else if ( std::abs(chargedHadron_cleaned.getChargedPFCandidate()->pdgId()) == 130 ) addPFCand(kIsolation, kNeutralHadron, convertToPtr(chargedHadron_cleaned.getChargedPFCandidate()));
163  }
164  const std::vector<CandidatePtr>& neutrals = chargedHadron_cleaned.getNeutralPFCandidates();
165  for ( std::vector<CandidatePtr>::const_iterator neutral = neutrals.begin();
166  neutral != neutrals.end(); ++neutral ) {
167  if ( std::abs((*neutral)->pdgId()) == 22 ) addPFCand(kIsolation, kGamma, convertToPtr(*neutral));
168  else if ( std::abs((*neutral)->pdgId()) == 130 ) addPFCand(kIsolation, kNeutralHadron, convertToPtr(*neutral));
169  };
170  }
171 }
172 
174 {
175  if ( region == kSignal ) {
176  tau_->signalPiZeroCandidatesRestricted().reserve(size);
177  // If we are building the gammas with the pizeros, resize that
178  // vector as well
179  if ( copyGammas_ ) reserve(kSignal, kGamma, 2*size);
180  } else {
181  tau_->isolationPiZeroCandidatesRestricted().reserve(size);
182  if ( copyGammas_ ) reserve(kIsolation, kGamma, 2*size);
183  }
184 }
185 
187 {
188  LogDebug("TauConstructorAddPi0") << " region = " << region << ": Pt = " << piZero.pt() << ", eta = " << piZero.eta() << ", phi = " << piZero.phi();
189  if ( region == kSignal ) {
190  tau_->signalPiZeroCandidatesRestricted().push_back(piZero);
191  // Copy the daughter gammas into the gamma collection if desired
192  if ( copyGammas_ ) {
193  // If we are using the pizeros to build the gammas, make sure we update
194  // the four vector correctly.
195  p4_ += piZero.p4();
196  addPFCands(kSignal, kGamma, piZero.daughterPtrVector().begin(),
197  piZero.daughterPtrVector().end());
198  }
199  } else {
200  tau_->isolationPiZeroCandidatesRestricted().push_back(piZero);
201  if ( copyGammas_ ) {
202  addPFCands(kIsolation, kGamma, piZero.daughterPtrVector().begin(),
203  piZero.daughterPtrVector().end());
204  }
205  }
206 }
207 
208 std::vector<CandidatePtr>*
210  return collections_[std::make_pair(region, type)];
211 }
212 
215  return sortedCollections_[std::make_pair(region, type)];
216 }
217 
218 // Trivial converter needed for polymorphism
220  const CandidatePtr& pfPtr) const {
221  return pfPtr;
222 }
223 
224 namespace {
225 // Make sure the two products come from the same EDM source
226 template<typename T1, typename T2>
227 void checkMatchedProductIds(const T1& t1, const T2& t2) {
228  if (t1.id() != t2.id()) {
229  throw cms::Exception("MismatchedPFCandSrc") << "Error: the input tag"
230  << " for the PF candidate collection provided to the RecoTauBuilder "
231  << " does not match the one that was used to build the source jets."
232  << " Please update the pfCandSrc paramters for the PFTau builders.";
233  }
234 }
235 }
236 
237 // Convert from a CandidateRef to a Ptr
239  const PFCandidatePtr& candPtr) const {
240  if(candPtr.isNonnull()) {
241  checkMatchedProductIds(candPtr, pfCands_);
242  return CandidatePtr(pfCands_, candPtr.key());
243  } else return PFCandidatePtr();
244 }
245 
246 namespace {
247 template<typename T> bool ptDescending(const T& a, const T& b) {
248  return a.pt() > b.pt();
249 }
250 template<typename T> bool ptDescendingPtr(const T& a, const T& b) {
251  return a->pt() > b->pt();
252 }
253 }
254 
256  // The charged hadrons and pizeros are a special case, as we can sort them in situ
257  std::sort(tau_->signalTauChargedHadronCandidatesRestricted().begin(),
258  tau_->signalTauChargedHadronCandidatesRestricted().end(),
259  ptDescending<PFRecoTauChargedHadron>);
260  std::sort(tau_->isolationTauChargedHadronCandidatesRestricted().begin(),
261  tau_->isolationTauChargedHadronCandidatesRestricted().end(),
262  ptDescending<PFRecoTauChargedHadron>);
263  std::sort(tau_->signalPiZeroCandidatesRestricted().begin(),
264  tau_->signalPiZeroCandidatesRestricted().end(),
265  ptDescending<RecoTauPiZero>);
266  std::sort(tau_->isolationPiZeroCandidatesRestricted().begin(),
267  tau_->isolationPiZeroCandidatesRestricted().end(),
268  ptDescending<RecoTauPiZero>);
269 
270  // Sort each of our sortable collections, and copy them into the final
271  // tau RefVector.
272  for (auto const& colkey : collections_ ) {
273  SortedListPtr sortedCollection = sortedCollections_[colkey.first];
274  std::sort(sortedCollection->begin(),
275  sortedCollection->end(),
276  ptDescendingPtr<CandidatePtr>);
277  // Copy into the real tau collection
278  for ( std::vector<CandidatePtr>::const_iterator particle = sortedCollection->begin();
279  particle != sortedCollection->end(); ++particle ) {
280  colkey.second->push_back(*particle);
281  }
282  }
283 }
284 
285 namespace
286 {
287  PFTau::hadronicDecayMode calculateDecayMode(const reco::PFTau& tau, double dRsignalCone,
290  {
291  unsigned int nCharged = tau.signalTauChargedHadronCandidates().size();
292  // If no tracks exist, this is definitely not a tau!
293  if ( !nCharged ) return PFTau::kNull;
294 
295  unsigned int nPiZeros = 0;
296  const std::vector<RecoTauPiZero>& piZeros = tau.signalPiZeroCandidates();
297  for ( std::vector<RecoTauPiZero>::const_iterator piZero = piZeros.begin();
298  piZero != piZeros.end(); ++piZero ) {
299  double photonSumPt_insideSignalCone = 0.;
300  double photonSumPt_outsideSignalCone = 0.;
301  int numPhotons = piZero->numberOfDaughters();
302  for ( int idxPhoton = 0; idxPhoton < numPhotons; ++idxPhoton ) {
303  const reco::Candidate* photon = piZero->daughter(idxPhoton);
304  double dR = deltaR(photon->p4(), tau.p4());
305  if ( dR < dRsignalCone ) {
306  photonSumPt_insideSignalCone += photon->pt();
307  } else {
308  photonSumPt_outsideSignalCone += photon->pt();
309  }
310  }
311  if ( photonSumPt_insideSignalCone > minAbsPhotonSumPt_insideSignalCone || photonSumPt_insideSignalCone > (minRelPhotonSumPt_insideSignalCone*tau.pt()) ||
312  photonSumPt_outsideSignalCone > minAbsPhotonSumPt_outsideSignalCone || photonSumPt_outsideSignalCone > (minRelPhotonSumPt_outsideSignalCone*tau.pt()) ) ++nPiZeros;
313  }
314 
315  // Find the maximum number of PiZeros our parameterization can hold
316  const unsigned int maxPiZeros = PFTau::kOneProngNPiZero;
317 
318  // Determine our track index
319  unsigned int trackIndex = (nCharged - 1)*(maxPiZeros + 1);
320 
321  // Check if we handle the given number of tracks
322  if ( trackIndex >= PFTau::kRareDecayMode ) return PFTau::kRareDecayMode;
323 
324  if ( nPiZeros > maxPiZeros ) nPiZeros = maxPiZeros;
325  return static_cast<PFTau::hadronicDecayMode>(trackIndex + nPiZeros);
326  }
327 }
328 
329 std::auto_ptr<reco::PFTau> RecoTauConstructor::get(bool setupLeadingObjects)
330 {
331  LogDebug("TauConstructorGet") << "Start getting" ;
332 
333  // Copy the sorted collections into the interal tau refvectors
335 
336  // Setup all the important member variables of the tau
337  // Set charge of tau
338 // tau_->setCharge(
339 // sumPFCandCharge(getCollection(kSignal, kChargedHadron)->begin(),
340 // getCollection(kSignal, kChargedHadron)->end()));
341  // CV: take charge of highest pT charged hadron as charge of tau,
342  // in case tau does not have three reconstructed tracks
343  // (either because tau is reconstructed as 2prong or because PFRecoTauChargedHadron is built from a PFNeutralHadron)
344  unsigned int nCharged = 0;
345  int charge = 0;
346  double leadChargedHadronPt = 0.;
347  int leadChargedHadronCharge = 0;
348  for ( std::vector<PFRecoTauChargedHadron>::const_iterator chargedHadron = tau_->signalTauChargedHadronCandidatesRestricted().begin();
349  chargedHadron != tau_->signalTauChargedHadronCandidatesRestricted().end(); ++chargedHadron ) {
351  ++nCharged;
352  charge += chargedHadron->charge();
353  if ( chargedHadron->pt() > leadChargedHadronPt ) {
354  leadChargedHadronPt = chargedHadron->pt();
355  leadChargedHadronCharge = chargedHadron->charge();
356  }
357  }
358  }
359  if ( nCharged == 3 ) tau_->setCharge(charge);
360  else tau_->setCharge(leadChargedHadronCharge);
361 
362  // Set PDG id
363  tau_->setPdgId(tau_->charge() < 0 ? 15 : -15);
364 
365  // Set P4
366  tau_->setP4(p4_);
367 
368  // Set Decay Mode
369  double dRsignalCone = ( signalConeSize_ ) ? (*signalConeSize_)(*tau_) : 0.5;
370  tau_->setSignalConeSize(dRsignalCone);
371  PFTau::hadronicDecayMode dm = calculateDecayMode(
372  *tau_,
373  dRsignalCone,
375  tau_->setDecayMode(dm);
376 
377  LogDebug("TauConstructorGet") << "Pt = " << tau_->pt() << ", eta = " << tau_->eta() << ", phi = " << tau_->phi() << ", mass = " << tau_->mass() << ", dm = " << tau_->decayMode() ;
378 
379  // Set charged isolation quantities
380  tau_->setisolationPFChargedHadrCandsPtSum(
381  sumPFCandPt(
384 
385  // Set gamma isolation quantities
386  tau_->setisolationPFGammaCandsEtSum(
387  sumPFCandPt(
390 
391  // Set em fraction
392  tau_->setemFraction(sumPFCandPt(
394  getCollection(kSignal, kGamma)->end()) / tau_->pt());
395 
396  if ( setupLeadingObjects ) {
397  typedef std::vector<CandidatePtr>::const_iterator Iter;
398  // Find the highest PT object in the signal cone
399  Iter leadingCand = leadCand(
402 
403  if ( leadingCand != getCollection(kSignal, kAll)->end() )
404  tau_->setleadCand(*leadingCand);
405 
406  // Hardest charged object in signal cone
407  Iter leadingChargedCand = leadCand(
410 
411  if ( leadingChargedCand != getCollection(kSignal, kChargedHadron)->end() )
412  tau_->setleadChargedHadrCand(*leadingChargedCand);
413 
414  // Hardest gamma object in signal cone
415  Iter leadingGammaCand = leadCand(
418 
419  if(leadingGammaCand != getCollection(kSignal, kGamma)->end())
420  tau_->setleadNeutralCand(*leadingGammaCand);
421  }
422  return tau_;
423 }
424 } // end namespace reco::tau
#define LogDebug(id)
void addPFCand(Region region, ParticleType type, const CandidatePtr &ptr, bool skipAddToP4=false)
Append a PFCandidateRef/Ptr to a given collection.
size
Write out results.
type
Definition: HCALResponse.h:21
void addTauChargedHadron(Region region, const PFRecoTauChargedHadron &chargedHadron)
Add a ChargedHadron to the given collection.
reco::Candidate::LorentzVector p4_
std::auto_ptr< reco::PFTau > get(bool setupLeadingCandidates=true)
void reserve(Region region, ParticleType type, size_t size)
Reserve a set amount of space for a given RefVector.
double eta() const final
momentum pseudorapidity
double sumPFCandPt(InputIterator begin, InputIterator end)
Sum the pT of a collection of PFCandidates.
key_type key() const
Definition: Ptr.h:185
std::vector< CandidatePtr > * getCollection(Region region, ParticleType type)
double pt() const final
transverse momentum
InputIterator leadCand(InputIterator begin, InputIterator end)
virtual const daughters & daughterPtrVector() const
references to daughtes
const edm::Handle< edm::View< reco::Candidate > > & pfCands_
SortedCollectionMap sortedCollections_
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
const std::vector< RecoTauPiZero > & signalPiZeroCandidates() const
Retrieve the association of signal region gamma candidates into candidate PiZeros.
Definition: PFTau.cc:230
SortedListPtr getSortedCollection(Region region, ParticleType type)
RefCore const & refCore() const
Definition: Ptr.h:189
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: LeafCandidate.h:99
#define end
Definition: vmac.h:39
std::vector< CandidatePtr > neutralPFCandidates_
void addPFCands(Region region, ParticleType type, const InputIterator &begin, const InputIterator &end)
boost::shared_ptr< std::vector< CandidatePtr > > SortedListPtr
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:168
constexpr auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:28
edm::Ptr< Candidate > CandidatePtr
persistent reference to an object in a collection of Candidate objects
Definition: CandidateFwd.h:25
virtual double pt() const =0
transverse momentum
std::auto_ptr< reco::PFTau > tau_
void reserveTauChargedHadron(Region region, size_t size)
Reserve a set amount of space for the ChargedHadrons.
void reservePiZero(Region region, size_t size)
Reserve a set amount of space for the PiZeros.
double b
Definition: hdecay.h:120
ProductID id() const
Accessor for product ID.
Definition: Ptr.h:180
def checkOverlap(process)
hadronicDecayMode
Definition: PFTau.h:36
#define begin
Definition: vmac.h:32
double a
Definition: hdecay.h:121
const std::vector< PFRecoTauChargedHadron > & signalTauChargedHadronCandidates() const
Retrieve the association of signal region PF candidates into candidate PFRecoTauChargedHadrons.
Definition: PFTau.cc:277
void addPiZero(Region region, const RecoTauPiZero &piZero)
Add a PiZero to the given collection.
const StringObjectFunction< reco::PFTau > * signalConeSize_
void setChargedHadronP4(reco::PFRecoTauChargedHadron &chargedHadron, double scaleFactor_neutralPFCands=1.0)
CandidatePtr convertToPtr(const PFCandidatePtr &pfPtr) const
long double T
const CandidatePtr & getChargedPFCandidate() const
reference to "charged" PFCandidate (either charged PFCandidate or PFNeutralHadron) ...
edm::Ptr< PFCandidate > PFCandidatePtr
persistent Ptr to a PFCandidate
double phi() const final
momentum azimuthal angle
std::vector< CandidatePtr > pfGammas(const Jet &jet, bool sort=true)
Extract all pfGammas from a PFJet.
const std::vector< CandidatePtr > & getNeutralPFCandidates() const
references to additional neutral PFCandidates
RecoTauConstructor(const JetBaseRef &jetRef, const edm::Handle< edm::View< reco::Candidate > > &pfCands, bool copyGammasFromPiZeros=false, const StringObjectFunction< reco::PFTau > *signalConeSize=0, double minAbsPhotonSumPt_insideSignalCone=2.5, double minRelPhotonSumPt_insideSignalCone=0., double minAbsPhotonSumPt_outsideSignalCone=1.e+9, double minRelPhotonSumPt_outsideSignalCone=1.e+9)
Constructor with PFCandidate Handle.