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  //std::cout << "<RecoTauConstructor::addPFCand>:" << std::endl;
52  //std::cout << " region = " << region << ", type = " << type << ": Pt = " << ref->pt() << ", eta = " << ref->eta() << ", phi = " << ref->phi() << std::endl;
53  if ( region == kSignal ) {
54  // Keep track of the four vector of the signal vector products added so far.
55  // If a photon add it if we are not using PiZeros to build the gammas
56  if ( ((type != kGamma) || !copyGammas_) && !skipAddToP4 ) {
57  //std::cout << "--> adding PFCand to tauP4." << std::endl;
58  p4_ += ref->p4();
59  }
60  }
61  getSortedCollection(region, type)->push_back(edm::refToPtr<PFCandidateCollection>(ref));
62  // Add to global collection
63  getSortedCollection(region, kAll)->push_back(edm::refToPtr<PFCandidateCollection>(ref));
64 }
65 
66 void RecoTauConstructor::addPFCand(Region region, ParticleType type, const PFCandidatePtr& ptr, bool skipAddToP4) {
67  //std::cout << "<RecoTauConstructor::addPFCand>:" << std::endl;
68  //std::cout << " region = " << region << ", type = " << type << ": Pt = " << ptr->pt() << ", eta = " << ptr->eta() << ", phi = " << ptr->phi() << std::endl;
69  if ( region == kSignal ) {
70  // Keep track of the four vector of the signal vector products added so far.
71  // If a photon add it if we are not using PiZeros to build the gammas
72  if ( ((type != kGamma) || !copyGammas_) && !skipAddToP4 ) {
73  //std::cout << "--> adding PFCand to tauP4." << std::endl;
74  p4_ += ptr->p4();
75  }
76  }
77  getSortedCollection(region, type)->push_back(ptr);
78  // Add to global collection
79  getSortedCollection(region, kAll)->push_back(ptr);
80 }
81 
83  getSortedCollection(region, type)->reserve(size);
84  getCollection(region, type)->reserve(size);
85  // Reserve global collection as well
86  getSortedCollection(region, kAll)->reserve(
87  getSortedCollection(region, kAll)->size() + size);
88  getCollection(region, kAll)->reserve(
89  getCollection(region, kAll)->size() + size);
90 }
91 
93 {
94  if ( region == kSignal ) {
95  tau_->signalTauChargedHadronCandidates_.reserve(size);
96  tau_->selectedSignalPFChargedHadrCands_.reserve(size);
97  } else {
98  tau_->isolationTauChargedHadronCandidates_.reserve(size);
99  tau_->selectedIsolationPFChargedHadrCands_.reserve(size);
100  }
101 }
102 
103 namespace
104 {
105  void checkOverlap(const PFCandidatePtr& neutral, const std::vector<PFCandidatePtr>& pfGammas, bool& isUnique)
106  {
107  //std::cout << "checkOverlap (PFGamma)>:" << std::endl;
108  //std::cout << " pfGammas: #entries = " << pfGammas.size() << std::endl;
109  for ( std::vector<PFCandidatePtr>::const_iterator pfGamma = pfGammas.begin();
110  pfGamma != pfGammas.end(); ++pfGamma ) {
111  //std::cout << "pfGamma = " << pfGamma->id() << ":" << pfGamma->key() << std::endl;
112  if ( (*pfGamma) == neutral ) isUnique = false;
113  }
114  }
115 
116  void checkOverlap(const PFCandidatePtr& neutral, const std::vector<reco::RecoTauPiZero>& piZeros, bool& isUnique)
117  {
118  //std::cout << "checkOverlap (RecoTauPiZero)>:" << std::endl;
119  //std::cout << " piZeros: #entries = " << piZeros.size() << std::endl;
120  for ( std::vector<reco::RecoTauPiZero>::const_iterator piZero = piZeros.begin();
121  piZero != piZeros.end(); ++piZero ) {
122  size_t numPFGammas = piZero->numberOfDaughters();
123  for ( size_t iPFGamma = 0; iPFGamma < numPFGammas; ++iPFGamma ) {
124  reco::CandidatePtr pfGamma = piZero->daughterPtr(iPFGamma);
125  //std::cout << "pfGamma = " << pfGamma.id() << ":" << pfGamma.key() << std::endl;
126  if ( pfGamma.id() == neutral.id() && pfGamma.key() == neutral.key() ) isUnique = false;
127  }
128  }
129  }
130 }
131 
133 {
134  //std::cout << "<RecoTauConstructor::addTauChargedHadron>:" << std::endl;
135  //std::cout << " region = " << region << ": Pt = " << chargedHadron.pt() << ", eta = " << chargedHadron.eta() << ", phi = " << chargedHadron.phi() << std::endl;
136  // CV: need to make sure that PFGammas merged with ChargedHadrons are not part of PiZeros
137  const std::vector<PFCandidatePtr>& neutrals = chargedHadron.getNeutralPFCandidates();
138  std::vector<PFCandidatePtr> neutrals_cleaned;
139  for ( std::vector<PFCandidatePtr>::const_iterator neutral = neutrals.begin();
140  neutral != neutrals.end(); ++neutral ) {
141  //std::cout << "neutral = " << neutral->id() << ":" << neutral->key() << std::endl;
142  bool isUnique = true;
143  if ( copyGammas_ ) checkOverlap(*neutral, *getSortedCollection(kSignal, kGamma), isUnique);
144  else checkOverlap(*neutral, tau_->signalPiZeroCandidates_, isUnique);
145  if ( region == kIsolation ) {
146  if ( copyGammas_ ) checkOverlap(*neutral, *getSortedCollection(kIsolation, kGamma), isUnique);
147  else checkOverlap(*neutral, tau_->isolationPiZeroCandidates_, isUnique);
148  }
149  //std::cout << "--> isUnique = " << isUnique << std::endl;
150  if ( isUnique ) neutrals_cleaned.push_back(*neutral);
151  }
152  PFRecoTauChargedHadron chargedHadron_cleaned = chargedHadron;
153  if ( neutrals_cleaned.size() != neutrals.size() ) {
154  chargedHadron_cleaned.neutralPFCandidates_ = neutrals_cleaned;
155  setChargedHadronP4(chargedHadron_cleaned);
156  }
157  if ( region == kSignal ) {
158  tau_->signalTauChargedHadronCandidates_.push_back(chargedHadron_cleaned);
159  p4_ += chargedHadron_cleaned.p4();
160  if ( chargedHadron_cleaned.getChargedPFCandidate().isNonnull() ) {
161  addPFCand(kSignal, kChargedHadron, chargedHadron_cleaned.getChargedPFCandidate(), true);
162  }
163  const std::vector<PFCandidatePtr>& neutrals = chargedHadron_cleaned.getNeutralPFCandidates();
164  for ( std::vector<PFCandidatePtr>::const_iterator neutral = neutrals.begin();
165  neutral != neutrals.end(); ++neutral ) {
166  if ( (*neutral)->particleId() == reco::PFCandidate::gamma ) addPFCand(kSignal, kGamma, *neutral, true);
167  else if ( (*neutral)->particleId() == reco::PFCandidate::h0 ) addPFCand(kSignal, kNeutralHadron, *neutral, true);
168  };
169  } else {
170  tau_->isolationTauChargedHadronCandidates_.push_back(chargedHadron_cleaned);
171  if ( chargedHadron_cleaned.getChargedPFCandidate().isNonnull() ) {
172  if ( chargedHadron_cleaned.getChargedPFCandidate()->particleId() == reco::PFCandidate::h ) addPFCand(kIsolation, kChargedHadron, chargedHadron_cleaned.getChargedPFCandidate());
173  else if ( chargedHadron_cleaned.getChargedPFCandidate()->particleId() == reco::PFCandidate::h0 ) addPFCand(kIsolation, kNeutralHadron, chargedHadron_cleaned.getChargedPFCandidate());
174  }
175  const std::vector<PFCandidatePtr>& neutrals = chargedHadron_cleaned.getNeutralPFCandidates();
176  for ( std::vector<PFCandidatePtr>::const_iterator neutral = neutrals.begin();
177  neutral != neutrals.end(); ++neutral ) {
178  if ( (*neutral)->particleId() == reco::PFCandidate::gamma ) addPFCand(kIsolation, kGamma, *neutral);
179  else if ( (*neutral)->particleId() == reco::PFCandidate::h0 ) addPFCand(kIsolation, kNeutralHadron, *neutral);
180  };
181  }
182 }
183 
185 {
186  if ( region == kSignal ) {
187  tau_->signalPiZeroCandidates_.reserve(size);
188  // If we are building the gammas with the pizeros, resize that
189  // vector as well
190  if ( copyGammas_ ) reserve(kSignal, kGamma, 2*size);
191  } else {
192  tau_->isolationPiZeroCandidates_.reserve(size);
193  if ( copyGammas_ ) reserve(kIsolation, kGamma, 2*size);
194  }
195 }
196 
198 {
199  //std::cout << "<RecoTauConstructor::addPiZero>:" << std::endl;
200  //std::cout << " region = " << region << ": Pt = " << piZero.pt() << ", eta = " << piZero.eta() << ", phi = " << piZero.phi() << std::endl;
201  if ( region == kSignal ) {
202  tau_->signalPiZeroCandidates_.push_back(piZero);
203  // Copy the daughter gammas into the gamma collection if desired
204  if ( copyGammas_ ) {
205  // If we are using the pizeros to build the gammas, make sure we update
206  // the four vector correctly.
207  p4_ += piZero.p4();
208  addPFCands(kSignal, kGamma, piZero.daughterPtrVector().begin(),
209  piZero.daughterPtrVector().end());
210  }
211  } else {
212  tau_->isolationPiZeroCandidates_.push_back(piZero);
213  if ( copyGammas_ ) {
214  addPFCands(kIsolation, kGamma, piZero.daughterPtrVector().begin(),
215  piZero.daughterPtrVector().end());
216  }
217  }
218 }
219 
220 std::vector<PFCandidatePtr>*
222  return collections_[std::make_pair(region, type)];
223 }
224 
227  return sortedCollections_[std::make_pair(region, type)];
228 }
229 
230 // Trivial converter needed for polymorphism
232  const PFCandidatePtr& pfPtr) const {
233  return pfPtr;
234 }
235 
236 namespace {
237 // Make sure the two products come from the same EDM source
238 template<typename T1, typename T2>
239 void checkMatchedProductIds(const T1& t1, const T2& t2) {
240  if (t1.id() != t2.id()) {
241  throw cms::Exception("MismatchedPFCandSrc") << "Error: the input tag"
242  << " for the PF candidate collection provided to the RecoTauBuilder "
243  << " does not match the one that was used to build the source jets."
244  << " Please update the pfCandSrc paramters for the PFTau builders.";
245  }
246 }
247 }
248 
250  const PFCandidateRef& pfRef) const {
251  if(pfRef.isNonnull()) {
252  checkMatchedProductIds(pfRef, pfCands_);
253  return PFCandidatePtr(pfCands_, pfRef.key());
254  } else return PFCandidatePtr();
255 }
256 
257 // Convert from a CandidateRef to a Ptr
259  const CandidatePtr& candPtr) const {
260  if(candPtr.isNonnull()) {
261  checkMatchedProductIds(candPtr, pfCands_);
262  return PFCandidatePtr(pfCands_, candPtr.key());
263  } else return PFCandidatePtr();
264 }
265 
266 namespace {
267 template<typename T> bool ptDescending(const T& a, const T& b) {
268  return a.pt() > b.pt();
269 }
270 template<typename T> bool ptDescendingPtr(const T& a, const T& b) {
271  return a->pt() > b->pt();
272 }
273 }
274 
276  // The charged hadrons and pizeros are a special case, as we can sort them in situ
277  std::sort(tau_->signalTauChargedHadronCandidates_.begin(),
278  tau_->signalTauChargedHadronCandidates_.end(),
279  ptDescending<PFRecoTauChargedHadron>);
280  std::sort(tau_->isolationTauChargedHadronCandidates_.begin(),
281  tau_->isolationTauChargedHadronCandidates_.end(),
282  ptDescending<PFRecoTauChargedHadron>);
283  std::sort(tau_->signalPiZeroCandidates_.begin(),
284  tau_->signalPiZeroCandidates_.end(),
285  ptDescending<RecoTauPiZero>);
286  std::sort(tau_->isolationPiZeroCandidates_.begin(),
287  tau_->isolationPiZeroCandidates_.end(),
288  ptDescending<RecoTauPiZero>);
289 
290  // Sort each of our sortable collections, and copy them into the final
291  // tau RefVector.
292  BOOST_FOREACH ( const CollectionMap::value_type& colkey, collections_ ) {
293  SortedListPtr sortedCollection = sortedCollections_[colkey.first];
294  std::sort(sortedCollection->begin(),
295  sortedCollection->end(),
296  ptDescendingPtr<PFCandidatePtr>);
297  // Copy into the real tau collection
298  for ( std::vector<PFCandidatePtr>::const_iterator particle = sortedCollection->begin();
299  particle != sortedCollection->end(); ++particle ) {
300  colkey.second->push_back(*particle);
301  }
302  }
303 }
304 
305 std::auto_ptr<reco::PFTau> RecoTauConstructor::get(bool setupLeadingObjects)
306 {
307  //std::cout << "<RecoTauConstructor::get>:" << std::endl;
308 
309  // Copy the sorted collections into the interal tau refvectors
311 
312  // Setup all the important member variables of the tau
313  // Set charge of tau
314 // tau_->setCharge(
315 // sumPFCandCharge(getCollection(kSignal, kChargedHadron)->begin(),
316 // getCollection(kSignal, kChargedHadron)->end()));
317  // CV: take charge of highest pT charged hadron as charge of tau,
318  // in case tau does not have three reconstructed tracks
319  // (either because tau is reconstructed as 2prong or because PFRecoTauChargedHadron is built from a PFNeutralHadron)
320  unsigned int nCharged = 0;
321  int charge = 0;
322  double leadChargedHadronPt = 0.;
323  int leadChargedHadronCharge = 0;
324  for ( std::vector<PFRecoTauChargedHadron>::const_iterator chargedHadron = tau_->signalTauChargedHadronCandidates_.begin();
325  chargedHadron != tau_->signalTauChargedHadronCandidates_.end(); ++chargedHadron ) {
326  if ( chargedHadron->algoIs(PFRecoTauChargedHadron::kChargedPFCandidate) || chargedHadron->algoIs(PFRecoTauChargedHadron::kTrack) ) {
327  ++nCharged;
328  charge += chargedHadron->charge();
329  if ( chargedHadron->pt() > leadChargedHadronPt ) {
330  leadChargedHadronPt = chargedHadron->pt();
331  leadChargedHadronCharge = chargedHadron->charge();
332  }
333  }
334  }
335  if ( nCharged == 3 ) tau_->setCharge(charge);
336  else tau_->setCharge(leadChargedHadronCharge);
337 
338  // Set PDG id
339  tau_->setPdgId(tau_->charge() < 0 ? 15 : -15);
340 
341  // Set P4
342  tau_->setP4(p4_);
343 // tau_->setP4(
344 // sumPFCandP4(
345 // getCollection(kSignal, kAll)->begin(),
346 // getCollection(kSignal, kAll)->end()
347 // )
348 // );
349  //std::cout << "Pt = " << tau_->pt() << ", eta = " << tau_->eta() << ", phi = " << tau_->phi() << ", mass = " << tau_->mass() << std::endl;
350 
351  // Set charged isolation quantities
352  tau_->setisolationPFChargedHadrCandsPtSum(
353  sumPFCandPt(
356 
357  // Set gamma isolation quantities
358  tau_->setisolationPFGammaCandsEtSum(
359  sumPFCandPt(
362 
363  // Set em fraction
364  tau_->setemFraction(sumPFCandPt(
366  getCollection(kSignal, kGamma)->end()) / tau_->pt());
367 
368  if ( setupLeadingObjects ) {
369  typedef std::vector<PFCandidatePtr>::const_iterator Iter;
370  // Find the highest PT object in the signal cone
371  Iter leadingCand = leadPFCand(
374 
375  if ( leadingCand != getCollection(kSignal, kAll)->end() )
376  tau_->setleadPFCand(*leadingCand);
377 
378  // Hardest charged object in signal cone
379  Iter leadingChargedCand = leadPFCand(
382 
383  if ( leadingChargedCand != getCollection(kSignal, kChargedHadron)->end() )
384  tau_->setleadPFChargedHadrCand(*leadingChargedCand);
385 
386  // Hardest gamma object in signal cone
387  Iter leadingGammaCand = leadPFCand(
390 
391  if(leadingGammaCand != getCollection(kSignal, kGamma)->end())
392  tau_->setleadPFNeutralCand(*leadingGammaCand);
393  }
394  return tau_;
395 }
396 }} // end namespace reco::tau
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)
void reserve(Region region, ParticleType type, size_t size)
Reserve a set amount of space for a given RefVector.
double sumPFCandPt(InputIterator begin, InputIterator end)
Sum the pT of a collection of PFCandidates.
virtual const LorentzVector & p4() const GCC11_FINAL
four-momentum Lorentz vector
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.
double charge(const std::vector< uint8_t > &Ampls)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
SortedCollectionMap sortedCollections_
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:152
const edm::Handle< PFCandidateCollection > & pfCands_
auto const T2 &decltype(t1.eta()) t2
Definition: deltaR.h:18
SortedListPtr getSortedCollection(Region region, ParticleType type)
ProductID id() const
Accessor for product ID.
Definition: Ptr.h:164
#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)
PFCandidatePtr convertToPtr(const PFCandidatePtr &pfPtr) const
key_type key() const
Definition: Ptr.h:169
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
key_type key() const
Accessor for product key.
Definition: Ref.h:266
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_
#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
tuple size
Write out results.
const PFCandidatePtr & getChargedPFCandidate() const
reference to &quot;charged&quot; PFCandidate (either charged PFCandidate or PFNeutralHadron) ...