CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
RecoTauBuilderCombinatoricPlugin.cc
Go to the documentation of this file.
1 #include <vector>
2 
5 
9 
16 
17 namespace reco { namespace tau {
18 
19 typedef std::vector<reco::PFRecoTauChargedHadron> ChargedHadronList;
21 typedef std::vector<RecoTauPiZero> PiZeroList;
23 
25 {
26  public:
29 
31  const reco::PFJetRef&,
32  const std::vector<reco::PFRecoTauChargedHadron>&,
33  const std::vector<RecoTauPiZero>&,
34  const std::vector<PFCandidatePtr>&) const override;
35 
36  private:
38 
40 
41  struct decayModeInfo
42  {
43  uint32_t maxPiZeros_;
44  uint32_t maxPFCHs_;
45  uint32_t nCharged_;
46  uint32_t nPiZeros_;
47  };
48  std::vector<decayModeInfo> decayModesToBuild_;
49 
51 };
52 
54  : RecoTauBuilderPlugin(pset,std::move(iC)),
55  qcuts_(pset.getParameterSet("qualityCuts").getParameterSet("signalQualityCuts")),
56  isolationConeSize_(pset.getParameter<double>("isolationConeSize"))
57 {
58  typedef std::vector<edm::ParameterSet> VPSet;
59  const VPSet& decayModes = pset.getParameter<VPSet>("decayModes");
60  for ( VPSet::const_iterator decayMode = decayModes.begin();
61  decayMode != decayModes.end(); ++decayMode ) {
63  info.nCharged_ = decayMode->getParameter<uint32_t>("nCharged");
64  info.nPiZeros_ = decayMode->getParameter<uint32_t>("nPiZeros");
65  info.maxPFCHs_ = decayMode->getParameter<uint32_t>("maxTracks");
66  info.maxPiZeros_ = decayMode->getParameter<uint32_t>("maxPiZeros");
67  decayModesToBuild_.push_back(info);
68  }
69 
70  verbosity_ = ( pset.exists("verbosity") ) ?
71  pset.getParameter<int>("verbosity") : 0;
72 }
73 
74 // define template specialization for cross-cleaning
75 namespace xclean
76 {
77  template<>
79  {
80  // Get the list of objects we need to clean
81  for ( ChargedHadronCombo::combo_iterator chargedHadron = chargedHadronsBegin; chargedHadron != chargedHadronsEnd; ++chargedHadron ) {
82  // CV: Remove PFGammas that are merged into TauChargedHadrons from isolation PiZeros, but not from signal PiZeros.
83  // The overlap between PFGammas contained in signal PiZeros and merged into TauChargedHadrons
84  // is resolved by RecoTauConstructor::addTauChargedHadron,
85  // which gives preference to PFGammas that are within PiZeros and removes those PFGammas from TauChargedHadrons.
86  if ( mode_ == kRemoveChargedDaughterOverlaps ) {
87  if ( chargedHadron->getChargedPFCandidate().isNonnull() ) toRemove_.insert(reco::CandidatePtr(chargedHadron->getChargedPFCandidate()));
88  } else if ( mode_ == kRemoveChargedAndNeutralDaughterOverlaps ) {
89  const reco::CompositePtrCandidate::daughters& daughters = chargedHadron->daughterPtrVector();
90  for ( reco::CompositePtrCandidate::daughters::const_iterator daughter = daughters.begin();
91  daughter != daughters.end(); ++daughter ) {
92  toRemove_.insert(reco::CandidatePtr(*daughter));
93  }
94  } else assert(0);
95  }
96  }
97 
98  template<>
99  inline void CrossCleanPtrs<PiZeroList::const_iterator>::initialize(const PiZeroList::const_iterator& piZerosBegin, const PiZeroList::const_iterator& piZerosEnd)
100  {
101  BOOST_FOREACH( const PFCandidatePtr &ptr, flattenPiZeros(piZerosBegin, piZerosEnd) ) {
102  toRemove_.insert(CandidatePtr(ptr));
103  }
104  }
105 
106  template<>
107  //inline void CrossCleanPtrs<ChargedHadronCombo::combo_iterator>::initialize(const ChargedHadronCombo::combo_iterator& chargedHadronsBegin, const ChargedHadronCombo::combo_iterator& chargedHadronsEnd)
108  inline void CrossCleanPtrs<ChargedHadronList::const_iterator>::initialize(const ChargedHadronList::const_iterator& chargedHadronsBegin, const ChargedHadronList::const_iterator& chargedHadronsEnd)
109  {
110  //std::cout << "<CrossCleanPtrs<ChargedHadronList>::initialize>:" << std::endl;
111  //for ( ChargedHadronCombo::combo_iterator chargedHadron = chargedHadronsBegin; chargedHadron != chargedHadronsEnd; ++chargedHadron ) {
112  for ( ChargedHadronList::const_iterator chargedHadron = chargedHadronsBegin; chargedHadron != chargedHadronsEnd; ++chargedHadron ) {
113  const reco::CompositePtrCandidate::daughters& daughters = chargedHadron->daughterPtrVector();
114  for ( reco::CompositePtrCandidate::daughters::const_iterator daughter = daughters.begin();
115  daughter != daughters.end(); ++daughter ) {
116  //std::cout << " adding PFCandidate = " << daughter->id() << ":" << daughter->key() << std::endl;
117  toRemove_.insert(reco::CandidatePtr(*daughter));
118  }
119  }
120  }
121 }
122 
123 namespace
124 {
125  // auxiliary class for sorting pizeros by descending transverse momentum
126  class SortPi0sDescendingPt
127  {
128  public:
129  bool operator()(const RecoTauPiZero& a, const RecoTauPiZero& b) const
130  {
131  return a.pt() > b.pt();
132  }
133  };
134 
135  std::string getPFCandidateType(reco::PFCandidate::ParticleType pfCandidateType)
136  {
137  if ( pfCandidateType == reco::PFCandidate::X ) return "undefined";
138  else if ( pfCandidateType == reco::PFCandidate::h ) return "PFChargedHadron";
139  else if ( pfCandidateType == reco::PFCandidate::e ) return "PFElectron";
140  else if ( pfCandidateType == reco::PFCandidate::mu ) return "PFMuon";
141  else if ( pfCandidateType == reco::PFCandidate::gamma ) return "PFGamma";
142  else if ( pfCandidateType == reco::PFCandidate::h0 ) return "PFNeutralHadron";
143  else if ( pfCandidateType == reco::PFCandidate::h_HF ) return "HF_had";
144  else if ( pfCandidateType == reco::PFCandidate::egamma_HF ) return "HF_em";
145  else assert(0);
146  }
147 }
148 
151  const reco::PFJetRef& jet,
152  const std::vector<reco::PFRecoTauChargedHadron>& chargedHadrons,
153  const std::vector<RecoTauPiZero>& piZeros,
154  const std::vector<PFCandidatePtr>& regionalExtras) const
155 {
156  if ( verbosity_ ) {
157  std::cout << "<RecoTauBuilderCombinatoricPlugin::operator()>:" << std::endl;
158  std::cout << " processing jet: Pt = " << jet->pt() << ", eta = " << jet->eta() << ", phi = " << jet->eta() << ","
159  << " mass = " << jet->mass() << ", area = " << jet->jetArea() << std::endl;
160  }
161 
162  // Define output.
164 
165  reco::VertexRef primaryVertexRef = primaryVertex(jet);
166 
167  // Update the primary vertex used by the quality cuts. The PV is supplied by
168  // the base class.
169  qcuts_.setPV(primaryVertexRef);
170 
171  typedef std::vector<PFCandidatePtr> PFCandPtrs;
172 
173  if ( verbosity_ ) {
174  std::cout << "#chargedHadrons = " << chargedHadrons.size() << std::endl;
175  int idx = 0;
176  for ( ChargedHadronList::const_iterator chargedHadron = chargedHadrons.begin();
177  chargedHadron != chargedHadrons.end(); ++chargedHadron ) {
178  std::cout << "chargedHadron #" << idx << ":" << std::endl;
179  chargedHadron->print(std::cout);
180  ++idx;
181  }
182  std::cout << "#piZeros = " << piZeros.size() << std::endl;
183  idx = 0;
184  for ( PiZeroList::const_iterator piZero = piZeros.begin();
185  piZero != piZeros.end(); ++piZero ) {
186  std::cout << "piZero #" << idx << ": Pt = " << piZero->pt() << ", eta = " << piZero->eta() << ", phi = " << piZero->phi() << std::endl;
187  size_t numDaughters = piZero->numberOfDaughters();
188  for ( size_t iDaughter = 0; iDaughter < numDaughters; ++iDaughter ) {
189  const reco::PFCandidate* daughter = dynamic_cast<const reco::PFCandidate*>(piZero->daughterPtr(iDaughter).get());
190  std::cout << " daughter #" << iDaughter << " (" << getPFCandidateType(daughter->particleId()) << "):"
191  << " Pt = " << daughter->pt() << ", eta = " << daughter->eta() << ", phi = " << daughter->phi() << std::endl;
192  }
193  ++idx;
194  }
195  }
196 
197  PFCandPtrs pfchs = qcuts_.filterCandRefs(pfChargedCands(*jet));
198  PFCandPtrs pfnhs = qcuts_.filterCandRefs(pfCandidates(*jet, reco::PFCandidate::h0));
199 
202  PFCandPtrs regionalJunk = qcuts_.filterCandRefs(regionalExtras);
203 
204  // Loop over the decay modes we want to build
205  for ( std::vector<decayModeInfo>::const_iterator decayMode = decayModesToBuild_.begin();
206  decayMode != decayModesToBuild_.end(); ++decayMode ) {
207  // Find how many piZeros are in this decay mode
208  size_t piZerosToBuild = decayMode->nPiZeros_;
209  // Find how many tracks are in this decay mode
210  size_t tracksToBuild = decayMode->nCharged_;
211  if ( verbosity_ ) {
212  std::cout << "piZerosToBuild = " << piZerosToBuild << std::endl;
213  std::cout << "tracksToBuild = " << tracksToBuild << std::endl;
214  }
215 
216  // Skip decay mode if jet doesn't have the multiplicity to support it
217  if ( chargedHadrons.size() < tracksToBuild ) continue;
218 
219  // Find the start and end of potential signal tracks
220  ChargedHadronList::const_iterator chargedHadron_begin = chargedHadrons.begin();
221  ChargedHadronList::const_iterator chargedHadron_end = chargedHadrons.end();
222  chargedHadron_end = takeNElements(chargedHadron_begin, chargedHadron_end, decayMode->maxPFCHs_);
223 
224  // Build our track combo generator
225  ChargedHadronCombo trackCombos(chargedHadron_begin, chargedHadron_end, tracksToBuild);
226 
227  PFCandPtrs::iterator pfch_end = pfchs.end();
228  pfch_end = takeNElements(pfchs.begin(), pfch_end, decayMode->maxPFCHs_);
229 
230  //-------------------------------------------------------
231  // Begin combinatoric loop for this decay mode
232  //-------------------------------------------------------
233 
234  // Loop over the different combinations of tracks
235  for ( ChargedHadronCombo::iterator trackCombo = trackCombos.begin();
236  trackCombo != trackCombos.end(); ++trackCombo ) {
238  trackCombo->combo_begin(), trackCombo->combo_end(),
240 
241  PiZeroList cleanSignalPiZeros = signalPiZeroXCleaner(piZeros);
242 
243  // CV: sort collection of cross-cleaned pi0s by descending Pt
244  std::sort(cleanSignalPiZeros.begin(), cleanSignalPiZeros.end(), SortPi0sDescendingPt());
245 
246  // Skip decay mode if we don't have enough remaining clean pizeros to
247  // build it.
248  if ( cleanSignalPiZeros.size() < piZerosToBuild ) continue;
249 
250  // Find the start and end of potential signal tracks
251  PiZeroList::iterator signalPiZero_begin = cleanSignalPiZeros.begin();
252  PiZeroList::iterator signalPiZero_end = cleanSignalPiZeros.end();
253  signalPiZero_end = takeNElements(signalPiZero_begin, signalPiZero_end, decayMode->maxPiZeros_);
254 
255  // Build our piZero combo generator
256  PiZeroCombo piZeroCombos(signalPiZero_begin, signalPiZero_end, piZerosToBuild);
257  // Loop over the different combinations of PiZeros
258  for ( PiZeroCombo::iterator piZeroCombo = piZeroCombos.begin();
259  piZeroCombo != piZeroCombos.end(); ++piZeroCombo ) {
260  // Output tau
261  RecoTauConstructor tau(jet, getPFCands(), true);
262  // Reserve space in our collections
263  tau.reserve(
265  RecoTauConstructor::kChargedHadron, tracksToBuild);
266  tau.reserve(
268  RecoTauConstructor::kGamma, 2*piZerosToBuild); // k-factor = 2
269  tau.reservePiZero(RecoTauConstructor::kSignal, piZerosToBuild);
270 
272  trackCombo->combo_begin(), trackCombo->combo_end(),
274 
275  PiZeroList precleanedIsolationPiZeros = isolationPiZeroXCleaner(piZeros);
276  std::set<reco::CandidatePtr> toRemove;
277  for ( PiZeroCombo::combo_iterator signalPiZero = piZeroCombo->combo_begin();
278  signalPiZero != piZeroCombo->combo_end(); ++signalPiZero ) {
279  toRemove.insert(signalPiZero->daughterPtrVector().begin(), signalPiZero->daughterPtrVector().end());
280  }
281  PiZeroList cleanIsolationPiZeros;
282  BOOST_FOREACH( const RecoTauPiZero& precleanedPiZero, precleanedIsolationPiZeros ) {
283  std::set<reco::CandidatePtr> toCheck(precleanedPiZero.daughterPtrVector().begin(), precleanedPiZero.daughterPtrVector().end());
284  std::vector<reco::CandidatePtr> cleanDaughters;
285  std::set_difference(toCheck.begin(), toCheck.end(), toRemove.begin(), toRemove.end(), std::back_inserter(cleanDaughters));
286  // CV: piZero is signal piZero if at least one daughter overlaps
287  if ( cleanDaughters.size() == precleanedPiZero.daughterPtrVector().size() ) {
288  cleanIsolationPiZeros.push_back(precleanedPiZero);
289  }
290  }
291 
292  // FIXME - are all these reserves okay? will they get propagated to the
293  // dataformat size if they are wrong?
294  tau.reserve(
296  RecoTauConstructor::kChargedHadron, chargedHadrons.size() - tracksToBuild);
297  tau.reserve(
300  (piZeros.size() - piZerosToBuild)*2);
301  tau.reservePiZero(
303  (piZeros.size() - piZerosToBuild));
304 
305  // Get signal PiZero constituents and add them to the tau.
306  // The sub-gammas are automatically added.
307  tau.addPiZeros(
309  piZeroCombo->combo_begin(), piZeroCombo->combo_end());
310 
311  // Set signal and isolation components for charged hadrons, after
312  // converting them to a PFCandidateRefVector
313  //
314  // NOTE: signal ChargedHadrons need to be added **after** signal PiZeros
315  // to avoid double-counting PFGammas as part of PiZero and merged with ChargedHadron
316  //
319  trackCombo->combo_begin(), trackCombo->combo_end());
320 
321  // Now build isolation collections
322  // Load our isolation tools
323  using namespace reco::tau::cone;
324  PFCandPtrDRFilter isolationConeFilter(tau.p4(), 0, isolationConeSize_);
325 
326  // Cross cleaning predicate. Remove any PFCandidatePtrs that are
327  // contained within existing ChargedHadrons or PiZeros. This predicate will return false
328  // for any object that overlaps with chargedHadrons or cleanPiZeros.
329  //xclean::CrossCleanPtrs<ChargedHadronCombo::combo_iterator> pfCandXCleaner_chargedHadrons(trackCombo->combo_begin(), trackCombo->combo_end());
330  xclean::CrossCleanPtrs<ChargedHadronList::const_iterator> pfCandXCleaner_chargedHadrons(chargedHadrons.begin(), chargedHadrons.end());
331  xclean::CrossCleanPtrs<PiZeroList::const_iterator> pfCandXCleaner_pizeros(cleanIsolationPiZeros.begin(), cleanIsolationPiZeros.end());
332  //typedef xclean::PredicateAND<xclean::CrossCleanPtrs<ChargedHadronCombo::combo_iterator>, xclean::CrossCleanPtrs<PiZeroList::const_iterator> > pfCandXCleanerType;
334  pfCandXCleanerType pfCandXCleaner(pfCandXCleaner_chargedHadrons, pfCandXCleaner_pizeros);
335  // And this cleaning filter predicate with our Iso cone filter
336  xclean::PredicateAND<PFCandPtrDRFilter, pfCandXCleanerType> pfCandFilter(isolationConeFilter, pfCandXCleaner);
337 
338  ChargedHadronDRFilter isolationConeFilterChargedHadron(tau.p4(), 0, isolationConeSize_);
339  PiZeroDRFilter isolationConeFilterPiZero(tau.p4(), 0, isolationConeSize_);
340 
341  // Additionally make predicates to select the different PF object types
342  // of the regional junk objects to add
344  PFCandPtrDRFilter> RegionalJunkConeAndIdFilter;
345 
347  pfchCandSelector(reco::PFCandidate::h);
349  pfgammaCandSelector(reco::PFCandidate::gamma);
351  pfnhCandSelector(reco::PFCandidate::h0);
352 
353  RegionalJunkConeAndIdFilter pfChargedJunk(
354  pfchCandSelector, // select charged stuff from junk
355  isolationConeFilter); // only take those in iso cone
356 
357  RegionalJunkConeAndIdFilter pfGammaJunk(
358  pfgammaCandSelector, // select gammas from junk
359  isolationConeFilter); // only take those in iso cone
360 
361  RegionalJunkConeAndIdFilter pfNeutralJunk(
362  pfnhCandSelector, // select neutral stuff from junk
363  isolationConeFilter); // select stuff in iso cone
364 
365  tau.addPiZeros(
367  boost::make_filter_iterator(
368  isolationConeFilterPiZero,
369  cleanIsolationPiZeros.begin(), cleanIsolationPiZeros.end()),
370  boost::make_filter_iterator(
371  isolationConeFilterPiZero,
372  cleanIsolationPiZeros.end(), cleanIsolationPiZeros.end()));
373 
374  // Filter the isolation candidates in a DR cone
375  //
376  // NOTE: isolation ChargedHadrons need to be added **after** signal and isolation PiZeros
377  // to avoid double-counting PFGammas as part of PiZero and merged with ChargedHadron
378  //
381  boost::make_filter_iterator(
382  isolationConeFilterChargedHadron,
383  trackCombo->remainder_begin(), trackCombo->remainder_end()),
384  boost::make_filter_iterator(
385  isolationConeFilterChargedHadron,
386  trackCombo->remainder_end(), trackCombo->remainder_end()));
387 
388  // Add all the candidates that weren't included in the combinatoric
389  // generation
390  tau.addPFCands(
392  boost::make_filter_iterator(
393  pfCandFilter,
394  pfch_end, pfchs.end()),
395  boost::make_filter_iterator(
396  pfCandFilter,
397  pfchs.end(), pfchs.end()));
398  // Add all charged candidates that are in the iso cone but weren't in the
399  // original PFJet
400  tau.addPFCands(
402  boost::make_filter_iterator(
403  pfChargedJunk, regionalJunk.begin(), regionalJunk.end()),
404  boost::make_filter_iterator(
405  pfChargedJunk, regionalJunk.end(), regionalJunk.end()));
406 
407  // Add all gammas that are in the iso cone but weren't in the
408  // orginal PFJet
409  tau.addPFCands(
411  boost::make_filter_iterator(
412  pfGammaJunk, regionalJunk.begin(), regionalJunk.end()),
413  boost::make_filter_iterator(
414  pfGammaJunk, regionalJunk.end(), regionalJunk.end()));
415 
416  // Add all the neutral hadron candidates to the isolation collection
417  tau.addPFCands(
419  boost::make_filter_iterator(
420  pfCandFilter,
421  pfnhs.begin(), pfnhs.end()),
422  boost::make_filter_iterator(
423  pfCandFilter,
424  pfnhs.end(), pfnhs.end()));
425  // Add all the neutral hadrons from the region collection that are in
426  // the iso cone to the tau
427  tau.addPFCands(
429  boost::make_filter_iterator(
430  pfNeutralJunk, regionalJunk.begin(), regionalJunk.end()),
431  boost::make_filter_iterator(
432  pfNeutralJunk, regionalJunk.end(), regionalJunk.end()));
433 
434  std::auto_ptr<reco::PFTau> tauPtr = tau.get(true);
435 
436  if ( primaryVertexRef.isNonnull() ) tauPtr->setVertex(primaryVertexRef->position());
437 
438  output.push_back(tauPtr);
439  }
440  }
441  }
442 
443  return output.release();
444 }
445 
446 }} // end namespace reco::tau
447 
451  "RecoTauBuilderCombinatoricPlugin");
T getParameter(std::string const &) const
const edm::Handle< PFCandidateCollection > & getPFCands() const
Hack to be able to convert Ptrs to Refs.
InputIterator takeNElements(const InputIterator &begin, const InputIterator &end, size_t N)
static const TGPicture * info(bool iBackgroundIsBlack)
ParticleType
particle types
Definition: PFCandidate.h:43
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.
void addTauChargedHadrons(Region region, const InputIterator &begin, const InputIterator &end)
Add a list of charged hadrons to the input collection.
CombinatoricIterator< T > end()
Coll filterCandRefs(const Coll &refcoll, bool invert=false) const
Filter a ref vector of PFCandidates.
std::vector< reco::PFRecoTauChargedHadron > ChargedHadronList
ParameterSet const & getParameterSet(ParameterSetID const &id)
std::vector< reco::PFCandidatePtr > PFCandPtrs
bool exists(std::string const &parameterName) const
checks if a parameter exists
boost::ptr_vector< reco::PFTau > output_type
std::auto_ptr< output_type > return_type
return_type operator()(const reco::PFJetRef &, const std::vector< reco::PFRecoTauChargedHadron > &, const std::vector< RecoTauPiZero > &, const std::vector< PFCandidatePtr > &) const override
RecoTauBuilderCombinatoricPlugin(const edm::ParameterSet &pset, edm::ConsumesCollector &&iC)
tau::CombinatoricGenerator< PiZeroList > PiZeroCombo
std::vector< PFCandidatePtr > pfCandidates(const PFJet &jet, int particleId, bool sort=true)
void addPiZeros(Region region, const InputIterator &begin, const InputIterator &end)
Add a list of pizeros to the input collection.
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
virtual float phi() const GCC11_FINAL
momentum azimuthal angle
reco::VertexRef primaryVertex(const reco::PFJetRef &jet) const
Get primary vertex associated to this jet.
void setPV(const reco::VertexRef &vtx) const
Update the primary vertex.
const reco::Candidate::LorentzVector & p4() const
void addPFCands(Region region, ParticleType type, const InputIterator &begin, const InputIterator &end)
void initialize(const PtrIter &chargedHadronsBegin, const PtrIter &chargedHadronsEnd)
tau::CombinatoricGenerator< ChargedHadronList > ChargedHadronCombo
virtual float eta() const GCC11_FINAL
momentum pseudorapidity
std::vector< PFCandidatePtr > flattenPiZeros(const std::vector< RecoTauPiZero >::const_iterator &, const std::vector< RecoTauPiZero >::const_iterator &)
Flatten a list of pi zeros into a list of there constituent PFCandidates.
std::vector< CandidatePtr > daughters
collection of references to daughters
edm::Ptr< Candidate > CandidatePtr
persistent reference to an object in a collection of Candidate objects
Definition: CandidateFwd.h:25
tuple idx
DEBUGGING if hasattr(process,&quot;trackMonIterativeTracking2012&quot;): print &quot;trackMonIterativeTracking2012 D...
void reservePiZero(Region region, size_t size)
Reserve a set amount of space for the PiZeros.
double b
Definition: hdecay.h:120
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:38
std::vector< PFCandidatePtr > pfChargedCands(const PFJet &jet, bool sort=true)
Extract all non-neutral candidates from a PFJet.
double a
Definition: hdecay.h:121
const daughters & daughterPtrVector() const
references to daughtes
tuple cout
Definition: gather_cfg.py:121
#define DEFINE_EDM_PLUGIN(factory, type, name)
virtual ParticleType particleId() const
Definition: PFCandidate.h:355
virtual float pt() const GCC11_FINAL
transverse momentum
void initialize(const PtrIter &particlesBegin, const PtrIter &particlesEnd)
std::vector< RecoTauPiZero > PiZeroList
iterator::value_type::ValueIter combo_iterator
Transform a pizero to remove given candidates.
CombinatoricIterator< T > begin()