CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
RecoTauConstructor.cc
Go to the documentation of this file.
2 
5 
7 
8 #include <boost/foreach.hpp>
9 #include <boost/bind.hpp>
10 
11 namespace reco { namespace tau {
12 
14  : pfCands_(pfCands)
15 {
16  // Initialize tau
17  tau_.reset(new PFTau());
18 
19  copyGammas_ = copyGammasFromPiZeros;
20  // Initialize our Accessors
21  collections_[std::make_pair(kSignal, kChargedHadron)] =
22  &tau_->selectedSignalPFChargedHadrCands_;
23  collections_[std::make_pair(kSignal, kGamma)] =
24  &tau_->selectedSignalPFGammaCands_;
25  collections_[std::make_pair(kSignal, kNeutralHadron)] =
26  &tau_->selectedSignalPFNeutrHadrCands_;
27  collections_[std::make_pair(kSignal, kAll)] =
28  &tau_->selectedSignalPFCands_;
29 
30  collections_[std::make_pair(kIsolation, kChargedHadron)] =
31  &tau_->selectedIsolationPFChargedHadrCands_;
32  collections_[std::make_pair(kIsolation, kGamma)] =
33  &tau_->selectedIsolationPFGammaCands_;
34  collections_[std::make_pair(kIsolation, kNeutralHadron)] =
35  &tau_->selectedIsolationPFNeutrHadrCands_;
36  collections_[std::make_pair(kIsolation, kAll)] =
37  &tau_->selectedIsolationPFCands_;
38 
39  // Build our temporary sorted collections, since you can't use stl sorts on
40  // RefVectors
41  BOOST_FOREACH(const CollectionMap::value_type& colkey, collections_) {
42  // Build an empty list for each collection
43  sortedCollections_[colkey.first] = SortedListPtr(
44  new SortedListPtr::element_type);
45  }
46 
47  tau_->setjetRef(jet);
48 }
49 
50 void RecoTauConstructor::addPFCand(Region region, ParticleType type, const PFCandidateRef& ref, bool skipAddToP4) {
51  LogDebug("TauConstructorAddPFCand") << " region = " << region << ", type = " << type << ": Pt = " << ref->pt() << ", eta = " << ref->eta() << ", phi = " << ref->phi();
52  if ( region == kSignal ) {
53  // Keep track of the four vector of the signal vector products added so far.
54  // If a photon add it if we are not using PiZeros to build the gammas
55  if ( ((type != kGamma) || !copyGammas_) && !skipAddToP4 ) {
56  LogDebug("TauConstructorAddPFCand") << "--> adding PFCand to tauP4." ;
57  p4_ += ref->p4();
58  }
59  }
60  getSortedCollection(region, type)->push_back(edm::refToPtr<PFCandidateCollection>(ref));
61  // Add to global collection
62  getSortedCollection(region, kAll)->push_back(edm::refToPtr<PFCandidateCollection>(ref));
63 }
64 
65 void RecoTauConstructor::addPFCand(Region region, ParticleType type, const PFCandidatePtr& ptr, bool skipAddToP4) {
66  LogDebug("TauConstructorAddPFCand") << " region = " << region << ", type = " << type << ": Pt = " << ptr->pt() << ", eta = " << ptr->eta() << ", phi = " << ptr->phi();
67  if ( region == kSignal ) {
68  // Keep track of the four vector of the signal vector products added so far.
69  // If a photon add it if we are not using PiZeros to build the gammas
70  if ( ((type != kGamma) || !copyGammas_) && !skipAddToP4 ) {
71  LogDebug("TauConstructorAddPFCand") << "--> adding PFCand to tauP4." ;
72  p4_ += ptr->p4();
73  }
74  }
75  getSortedCollection(region, type)->push_back(ptr);
76  // Add to global collection
77  getSortedCollection(region, kAll)->push_back(ptr);
78 }
79 
81  getSortedCollection(region, type)->reserve(size);
82  getCollection(region, type)->reserve(size);
83  // Reserve global collection as well
84  getSortedCollection(region, kAll)->reserve(
85  getSortedCollection(region, kAll)->size() + size);
86  getCollection(region, kAll)->reserve(
87  getCollection(region, kAll)->size() + size);
88 }
89 
91 {
92  if ( region == kSignal ) {
93  tau_->signalTauChargedHadronCandidates_.reserve(size);
94  tau_->selectedSignalPFChargedHadrCands_.reserve(size);
95  } else {
96  tau_->isolationTauChargedHadronCandidates_.reserve(size);
97  tau_->selectedIsolationPFChargedHadrCands_.reserve(size);
98  }
99 }
100 
101 namespace
102 {
103  void checkOverlap(const PFCandidatePtr& neutral, const std::vector<PFCandidatePtr>& pfGammas, bool& isUnique)
104  {
105  LogDebug("TauConstructorCheckOverlap") << " pfGammas: #entries = " << pfGammas.size();
106  for ( std::vector<PFCandidatePtr>::const_iterator pfGamma = pfGammas.begin();
107  pfGamma != pfGammas.end(); ++pfGamma ) {
108  LogDebug("TauConstructorCheckOverlap") << "pfGamma = " << pfGamma->id() << ":" << pfGamma->key();
109  if ( (*pfGamma) == neutral ) isUnique = false;
110  }
111  }
112 
113  void checkOverlap(const PFCandidatePtr& neutral, const std::vector<reco::RecoTauPiZero>& piZeros, bool& isUnique)
114  {
115  LogDebug("TauConstructorCheckOverlap") << " piZeros: #entries = " << piZeros.size();
116  for ( std::vector<reco::RecoTauPiZero>::const_iterator piZero = piZeros.begin();
117  piZero != piZeros.end(); ++piZero ) {
118  size_t numPFGammas = piZero->numberOfDaughters();
119  for ( size_t iPFGamma = 0; iPFGamma < numPFGammas; ++iPFGamma ) {
120  reco::CandidatePtr pfGamma = piZero->daughterPtr(iPFGamma);
121  LogDebug("TauConstructorCheckOverlap") << "pfGamma = " << pfGamma.id() << ":" << pfGamma.key();
122  if ( pfGamma.id() == neutral.id() && pfGamma.key() == neutral.key() ) isUnique = false;
123  }
124  }
125  }
126 }
127 
129 {
130  LogDebug("TauConstructorAddChH") << " region = " << region << ": Pt = " << chargedHadron.pt() << ", eta = " << chargedHadron.eta() << ", phi = " << chargedHadron.phi();
131  // CV: need to make sure that PFGammas merged with ChargedHadrons are not part of PiZeros
132  const std::vector<PFCandidatePtr>& neutrals = chargedHadron.getNeutralPFCandidates();
133  std::vector<PFCandidatePtr> neutrals_cleaned;
134  for ( std::vector<PFCandidatePtr>::const_iterator neutral = neutrals.begin();
135  neutral != neutrals.end(); ++neutral ) {
136  LogDebug("TauConstructorAddChH") << "neutral = " << neutral->id() << ":" << neutral->key();
137  bool isUnique = true;
138  if ( copyGammas_ ) checkOverlap(*neutral, *getSortedCollection(kSignal, kGamma), isUnique);
139  else checkOverlap(*neutral, tau_->signalPiZeroCandidates_, isUnique);
140  if ( region == kIsolation ) {
141  if ( copyGammas_ ) checkOverlap(*neutral, *getSortedCollection(kIsolation, kGamma), isUnique);
142  else checkOverlap(*neutral, tau_->isolationPiZeroCandidates_, isUnique);
143  }
144  LogDebug("TauConstructorAddChH") << "--> isUnique = " << isUnique;
145  if ( isUnique ) neutrals_cleaned.push_back(*neutral);
146  }
147  PFRecoTauChargedHadron chargedHadron_cleaned = chargedHadron;
148  if ( neutrals_cleaned.size() != neutrals.size() ) {
149  chargedHadron_cleaned.neutralPFCandidates_ = neutrals_cleaned;
150  setChargedHadronP4(chargedHadron_cleaned);
151  }
152  if ( region == kSignal ) {
153  tau_->signalTauChargedHadronCandidates_.push_back(chargedHadron_cleaned);
154  p4_ += chargedHadron_cleaned.p4();
155  if ( chargedHadron_cleaned.getChargedPFCandidate().isNonnull() ) {
156  addPFCand(kSignal, kChargedHadron, chargedHadron_cleaned.getChargedPFCandidate(), true);
157  }
158  const std::vector<PFCandidatePtr>& neutrals = chargedHadron_cleaned.getNeutralPFCandidates();
159  for ( std::vector<PFCandidatePtr>::const_iterator neutral = neutrals.begin();
160  neutral != neutrals.end(); ++neutral ) {
161  if ( (*neutral)->particleId() == reco::PFCandidate::gamma ) addPFCand(kSignal, kGamma, *neutral, true);
162  else if ( (*neutral)->particleId() == reco::PFCandidate::h0 ) addPFCand(kSignal, kNeutralHadron, *neutral, true);
163  };
164  } else {
165  tau_->isolationTauChargedHadronCandidates_.push_back(chargedHadron_cleaned);
166  if ( chargedHadron_cleaned.getChargedPFCandidate().isNonnull() ) {
167  if ( chargedHadron_cleaned.getChargedPFCandidate()->particleId() == reco::PFCandidate::h ) addPFCand(kIsolation, kChargedHadron, chargedHadron_cleaned.getChargedPFCandidate());
168  else if ( chargedHadron_cleaned.getChargedPFCandidate()->particleId() == reco::PFCandidate::h0 ) addPFCand(kIsolation, kNeutralHadron, chargedHadron_cleaned.getChargedPFCandidate());
169  }
170  const std::vector<PFCandidatePtr>& neutrals = chargedHadron_cleaned.getNeutralPFCandidates();
171  for ( std::vector<PFCandidatePtr>::const_iterator neutral = neutrals.begin();
172  neutral != neutrals.end(); ++neutral ) {
173  if ( (*neutral)->particleId() == reco::PFCandidate::gamma ) addPFCand(kIsolation, kGamma, *neutral);
174  else if ( (*neutral)->particleId() == reco::PFCandidate::h0 ) addPFCand(kIsolation, kNeutralHadron, *neutral);
175  };
176  }
177 }
178 
180 {
181  if ( region == kSignal ) {
182  tau_->signalPiZeroCandidates_.reserve(size);
183  // If we are building the gammas with the pizeros, resize that
184  // vector as well
185  if ( copyGammas_ ) reserve(kSignal, kGamma, 2*size);
186  } else {
187  tau_->isolationPiZeroCandidates_.reserve(size);
188  if ( copyGammas_ ) reserve(kIsolation, kGamma, 2*size);
189  }
190 }
191 
193 {
194  LogDebug("TauConstructorAddPi0") << " region = " << region << ": Pt = " << piZero.pt() << ", eta = " << piZero.eta() << ", phi = " << piZero.phi();
195  if ( region == kSignal ) {
196  tau_->signalPiZeroCandidates_.push_back(piZero);
197  // Copy the daughter gammas into the gamma collection if desired
198  if ( copyGammas_ ) {
199  // If we are using the pizeros to build the gammas, make sure we update
200  // the four vector correctly.
201  p4_ += piZero.p4();
202  addPFCands(kSignal, kGamma, piZero.daughterPtrVector().begin(),
203  piZero.daughterPtrVector().end());
204  }
205  } else {
206  tau_->isolationPiZeroCandidates_.push_back(piZero);
207  if ( copyGammas_ ) {
208  addPFCands(kIsolation, kGamma, piZero.daughterPtrVector().begin(),
209  piZero.daughterPtrVector().end());
210  }
211  }
212 }
213 
214 std::vector<PFCandidatePtr>*
216  return collections_[std::make_pair(region, type)];
217 }
218 
221  return sortedCollections_[std::make_pair(region, type)];
222 }
223 
224 // Trivial converter needed for polymorphism
226  const PFCandidatePtr& pfPtr) const {
227  return pfPtr;
228 }
229 
230 namespace {
231 // Make sure the two products come from the same EDM source
232 template<typename T1, typename T2>
233 void checkMatchedProductIds(const T1& t1, const T2& t2) {
234  if (t1.id() != t2.id()) {
235  throw cms::Exception("MismatchedPFCandSrc") << "Error: the input tag"
236  << " for the PF candidate collection provided to the RecoTauBuilder "
237  << " does not match the one that was used to build the source jets."
238  << " Please update the pfCandSrc paramters for the PFTau builders.";
239  }
240 }
241 }
242 
244  const PFCandidateRef& pfRef) const {
245  if(pfRef.isNonnull()) {
246  checkMatchedProductIds(pfRef, pfCands_);
247  return PFCandidatePtr(pfCands_, pfRef.key());
248  } else return PFCandidatePtr();
249 }
250 
251 // Convert from a CandidateRef to a Ptr
253  const CandidatePtr& candPtr) const {
254  if(candPtr.isNonnull()) {
255  checkMatchedProductIds(candPtr, pfCands_);
256  return PFCandidatePtr(pfCands_, candPtr.key());
257  } else return PFCandidatePtr();
258 }
259 
260 namespace {
261 template<typename T> bool ptDescending(const T& a, const T& b) {
262  return a.pt() > b.pt();
263 }
264 template<typename T> bool ptDescendingPtr(const T& a, const T& b) {
265  return a->pt() > b->pt();
266 }
267 }
268 
270  // The charged hadrons and pizeros are a special case, as we can sort them in situ
271  std::sort(tau_->signalTauChargedHadronCandidates_.begin(),
272  tau_->signalTauChargedHadronCandidates_.end(),
273  ptDescending<PFRecoTauChargedHadron>);
274  std::sort(tau_->isolationTauChargedHadronCandidates_.begin(),
275  tau_->isolationTauChargedHadronCandidates_.end(),
276  ptDescending<PFRecoTauChargedHadron>);
277  std::sort(tau_->signalPiZeroCandidates_.begin(),
278  tau_->signalPiZeroCandidates_.end(),
279  ptDescending<RecoTauPiZero>);
280  std::sort(tau_->isolationPiZeroCandidates_.begin(),
281  tau_->isolationPiZeroCandidates_.end(),
282  ptDescending<RecoTauPiZero>);
283 
284  // Sort each of our sortable collections, and copy them into the final
285  // tau RefVector.
286  BOOST_FOREACH ( const CollectionMap::value_type& colkey, collections_ ) {
287  SortedListPtr sortedCollection = sortedCollections_[colkey.first];
288  std::sort(sortedCollection->begin(),
289  sortedCollection->end(),
290  ptDescendingPtr<PFCandidatePtr>);
291  // Copy into the real tau collection
292  for ( std::vector<PFCandidatePtr>::const_iterator particle = sortedCollection->begin();
293  particle != sortedCollection->end(); ++particle ) {
294  colkey.second->push_back(*particle);
295  }
296  }
297 }
298 
299 std::auto_ptr<reco::PFTau> RecoTauConstructor::get(bool setupLeadingObjects)
300 {
301  LogDebug("TauConstructorGet") << "Start getting" ;
302 
303  // Copy the sorted collections into the interal tau refvectors
305 
306  // Setup all the important member variables of the tau
307  // Set charge of tau
308 // tau_->setCharge(
309 // sumPFCandCharge(getCollection(kSignal, kChargedHadron)->begin(),
310 // getCollection(kSignal, kChargedHadron)->end()));
311  // CV: take charge of highest pT charged hadron as charge of tau,
312  // in case tau does not have three reconstructed tracks
313  // (either because tau is reconstructed as 2prong or because PFRecoTauChargedHadron is built from a PFNeutralHadron)
314  unsigned int nCharged = 0;
315  int charge = 0;
316  double leadChargedHadronPt = 0.;
317  int leadChargedHadronCharge = 0;
318  for ( std::vector<PFRecoTauChargedHadron>::const_iterator chargedHadron = tau_->signalTauChargedHadronCandidates_.begin();
319  chargedHadron != tau_->signalTauChargedHadronCandidates_.end(); ++chargedHadron ) {
320  if ( chargedHadron->algoIs(PFRecoTauChargedHadron::kChargedPFCandidate) || chargedHadron->algoIs(PFRecoTauChargedHadron::kTrack) ) {
321  ++nCharged;
322  charge += chargedHadron->charge();
323  if ( chargedHadron->pt() > leadChargedHadronPt ) {
324  leadChargedHadronPt = chargedHadron->pt();
325  leadChargedHadronCharge = chargedHadron->charge();
326  }
327  }
328  }
329  if ( nCharged == 3 ) tau_->setCharge(charge);
330  else tau_->setCharge(leadChargedHadronCharge);
331 
332  // Set PDG id
333  tau_->setPdgId(tau_->charge() < 0 ? 15 : -15);
334 
335  // Set P4
336  tau_->setP4(p4_);
337 // tau_->setP4(
338 // sumPFCandP4(
339 // getCollection(kSignal, kAll)->begin(),
340 // getCollection(kSignal, kAll)->end()
341 // )
342 // );
343  // Set Decay Mode
344  PFTau::hadronicDecayMode dm = tau_->calculateDecayMode();
345  tau_->setDecayMode(dm);
346 
347  LogDebug("TauConstructorGet") << "Pt = " << tau_->pt() << ", eta = " << tau_->eta() << ", phi = " << tau_->phi() << ", mass = " << tau_->mass() << ", dm = " << tau_->decayMode() ;
348 
349  // Set charged isolation quantities
350  tau_->setisolationPFChargedHadrCandsPtSum(
351  sumPFCandPt(
354 
355  // Set gamma isolation quantities
356  tau_->setisolationPFGammaCandsEtSum(
357  sumPFCandPt(
360 
361  // Set em fraction
362  tau_->setemFraction(sumPFCandPt(
364  getCollection(kSignal, kGamma)->end()) / tau_->pt());
365 
366  if ( setupLeadingObjects ) {
367  typedef std::vector<PFCandidatePtr>::const_iterator Iter;
368  // Find the highest PT object in the signal cone
369  Iter leadingCand = leadPFCand(
372 
373  if ( leadingCand != getCollection(kSignal, kAll)->end() )
374  tau_->setleadPFCand(*leadingCand);
375 
376  // Hardest charged object in signal cone
377  Iter leadingChargedCand = leadPFCand(
380 
381  if ( leadingChargedCand != getCollection(kSignal, kChargedHadron)->end() )
382  tau_->setleadPFChargedHadrCand(*leadingChargedCand);
383 
384  // Hardest gamma object in signal cone
385  Iter leadingGammaCand = leadPFCand(
388 
389  if(leadingGammaCand != getCollection(kSignal, kGamma)->end())
390  tau_->setleadPFNeutralCand(*leadingGammaCand);
391  }
392  return tau_;
393 }
394 }} // end namespace reco::tau
#define LogDebug(id)
type
Definition: HCALResponse.h:21
void addPFCand(Region region, ParticleType type, const PFCandidateRef &ref, bool skipAddToP4=false)
Append a PFCandidateRef/Ptr to a given collection.
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)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
void reserve(Region region, ParticleType type, size_t size)
Reserve a set amount of space for a given RefVector.
virtual float pt() const
transverse momentum
double sumPFCandPt(InputIterator begin, InputIterator end)
Sum the pT of a collection of PFCandidates.
key_type key() const
Definition: Ptr.h:169
boost::shared_ptr< std::vector< PFCandidatePtr > > SortedListPtr
std::vector< PFCandidatePtr > * getCollection(Region region, ParticleType type)
std::vector< PFCandidatePtr > pfGammas(const PFJet &jet, bool sort=true)
Extract all pfGammas from a PFJet.
virtual float phi() const
momentum azimuthal angle
key_type key() const
Accessor for product key.
Definition: Ref.h:266
SortedCollectionMap sortedCollections_
const edm::Handle< PFCandidateCollection > & pfCands_
SortedListPtr getSortedCollection(Region region, ParticleType type)
virtual float eta() const
momentum pseudorapidity
#define end
Definition: vmac.h:37
Container::value_type value_type
void addPFCands(Region region, ParticleType type, const InputIterator &begin, const InputIterator &end)
InputIterator leadPFCand(InputIterator begin, InputIterator end)
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:152
PFCandidatePtr convertToPtr(const PFCandidatePtr &pfPtr) const
unsigned int nCharged(const GenJet &jet)
std::auto_ptr< reco::PFTau > tau_
void reserveTauChargedHadron(Region region, size_t size)
Reserve a set amount of space for the ChargedHadrons.
const std::vector< PFCandidatePtr > & getNeutralPFCandidates() const
references to additional neutral PFCandidates
void reservePiZero(Region region, size_t size)
Reserve a set amount of space for the PiZeros.
double b
Definition: hdecay.h:120
std::vector< PFCandidatePtr > neutralPFCandidates_
ProductID id() const
Accessor for product ID.
Definition: Ptr.h:164
hadronicDecayMode
Definition: PFTau.h:35
#define begin
Definition: vmac.h:30
RecoTauConstructor(const PFJetRef &jetRef, const edm::Handle< PFCandidateCollection > &pfCands, bool copyGammasFromPiZeros=false)
Constructor with PFCandidate Handle.
double a
Definition: hdecay.h:121
const daughters & daughterPtrVector() const
references to daughtes
void addPiZero(Region region, const RecoTauPiZero &piZero)
Add a PiZero to the given collection.
ProductIndex id() const
Definition: ProductID.h:38
void setChargedHadronP4(reco::PFRecoTauChargedHadron &chargedHadron, double scaleFactor_neutralPFCands=1.0)
long double T
edm::Ptr< PFCandidate > PFCandidatePtr
persistent Ptr to a PFCandidate
virtual const LorentzVector & p4() const
four-momentum Lorentz vector
tuple size
Write out results.
const PFCandidatePtr & getChargedPFCandidate() const
reference to &quot;charged&quot; PFCandidate (either charged PFCandidate or PFNeutralHadron) ...