CMS 3D CMS Logo

RecoTauPiZeroProducer.cc
Go to the documentation of this file.
1 /*
2  * RecoTauPiZeroProducer
3  *
4  * Author: Evan K. Friis, UC Davis
5  *
6  * Associates reconstructed PiZeros to PFJets. The PiZeros are built using one
7  * or more RecoTauBuilder plugins. Any overlaps (PiZeros sharing constituents)
8  * are removed, with the best PiZero candidates taken. The 'best' are defined
9  * via the input list of RecoTauPiZeroQualityPlugins, which form a
10  * lexicograpical ranking.
11  *
12  */
13 
14 #include <boost/ptr_container/ptr_vector.hpp>
15 #include <boost/ptr_container/ptr_list.hpp>
16 #include <algorithm>
17 #include <functional>
18 
26 
30 
35 
38 
40  public:
43 
45  ~RecoTauPiZeroProducer() override {}
46  void produce(edm::Event& evt, const edm::EventSetup& es) override;
47  void print(const std::vector<reco::RecoTauPiZero>& piZeros,
48  std::ostream& out);
49 
50  private:
51  typedef boost::ptr_vector<Builder> builderList;
52  typedef boost::ptr_vector<Ranker> rankerList;
53  typedef boost::ptr_vector<reco::RecoTauPiZero> PiZeroVector;
54  typedef boost::ptr_list<reco::RecoTauPiZero> PiZeroList;
55 
58 
59  builderList builders_;
60  rankerList rankers_;
61  std::auto_ptr<PiZeroPredicate> predicate_;
62  double piZeroMass_;
63 
64  // Output selector
65  std::auto_ptr<StringCutObjectSelector<reco::RecoTauPiZero> >
67 
68  //consumes interface
70 
71  double minJetPt_;
72  double maxJetAbsEta_;
73 
75 };
76 
78 {
79  cand_token = consumes<reco::CandidateView>( pset.getParameter<edm::InputTag>("jetSrc"));
80  minJetPt_ = ( pset.exists("minJetPt") ) ? pset.getParameter<double>("minJetPt") : -1.0;
81  maxJetAbsEta_ = ( pset.exists("maxJetAbsEta") ) ? pset.getParameter<double>("maxJetAbsEta") : 99.0;
82 
83  typedef std::vector<edm::ParameterSet> VPSet;
84  // Get the mass hypothesis for the pizeros
85  piZeroMass_ = pset.getParameter<double>("massHypothesis");
86 
87  // Get each of our PiZero builders
88  const VPSet& builders = pset.getParameter<VPSet>("builders");
89 
90  for (VPSet::const_iterator builderPSet = builders.begin();
91  builderPSet != builders.end(); ++builderPSet) {
92  // Get plugin name
93  const std::string& pluginType =
94  builderPSet->getParameter<std::string>("plugin");
95  // Build the plugin
97  pluginType, *builderPSet, consumesCollector()));
98  }
99 
100  // Get each of our quality rankers
101  const VPSet& rankers = pset.getParameter<VPSet>("ranking");
102  for (VPSet::const_iterator rankerPSet = rankers.begin();
103  rankerPSet != rankers.end(); ++rankerPSet) {
104  const std::string& pluginType =
105  rankerPSet->getParameter<std::string>("plugin");
107  pluginType, *rankerPSet));
108  }
109 
110  // Build the sorting predicate
111  predicate_ = std::auto_ptr<PiZeroPredicate>(new PiZeroPredicate(rankers_));
112 
113  // Check if we want to apply a final output selection
114  if (pset.exists("outputSelection")) {
115  std::string selection = pset.getParameter<std::string>("outputSelection");
116  if (!selection.empty()) {
117  outputSelector_.reset(
119  }
120  }
121 
122  verbosity_ = ( pset.exists("verbosity") ) ?
123  pset.getParameter<int>("verbosity") : 0;
124 
125  produces<reco::JetPiZeroAssociation>();
126 }
127 
129 {
130  // Get a view of our jets via the base candidates
132  evt.getByToken(cand_token, jetView);
133 
134  // Give each of our plugins a chance at doing something with the edm::Event
135  for(auto& builder : builders_) {
136  builder.setup(evt, es);
137  }
138 
139  // Convert the view to a RefVector of actual PFJets
140  reco::PFJetRefVector jetRefs =
141  reco::tau::castView<reco::PFJetRefVector>(jetView);
142  // Make our association
143  std::unique_ptr<reco::JetPiZeroAssociation> association;
144 
145  if (!jetRefs.empty()) {
146  edm::Handle<reco::PFJetCollection> pfJetCollectionHandle;
147  evt.get(jetRefs.id(), pfJetCollectionHandle);
148  association = std::make_unique<reco::JetPiZeroAssociation>(reco::PFJetRefProd(pfJetCollectionHandle));
149  } else {
150  association = std::make_unique<reco::JetPiZeroAssociation>();
151  }
152 
153  // Loop over our jets
154  for(auto const& jet : jetRefs) {
155 
156  if(jet->pt() - minJetPt_ < 1e-5) continue;
157  if(std::abs(jet->eta()) - maxJetAbsEta_ > -1e-5) continue;
158  // Build our global list of RecoTauPiZero
159  PiZeroList dirtyPiZeros;
160 
161  // Compute the pi zeros from this jet for all the desired algorithms
162  for(auto const& builder : builders_) {
163  try {
164  PiZeroVector result(builder(*jet));
165  dirtyPiZeros.transfer(dirtyPiZeros.end(), result);
166  } catch ( cms::Exception &exception) {
167  edm::LogError("BuilderPluginException")
168  << "Exception caught in builder plugin " << builder.name()
169  << ", rethrowing" << std::endl;
170  throw exception;
171  }
172  }
173  // Rank the candidates according to our quality plugins
174  dirtyPiZeros.sort(*predicate_);
175 
176  // Keep track of the photons in the clean collection
177  std::vector<reco::RecoTauPiZero> cleanPiZeros;
178  std::set<reco::CandidatePtr> photonsInCleanCollection;
179  while (!dirtyPiZeros.empty()) {
180  // Pull our candidate pi zero from the front of the list
181  std::auto_ptr<reco::RecoTauPiZero> toAdd(
182  dirtyPiZeros.pop_front().release());
183  // If this doesn't pass our basic selection, discard it.
184  if (!(*outputSelector_)(*toAdd)) {
185  continue;
186  }
187  // Find the sub-gammas that are not already in the cleaned collection
188  std::vector<reco::CandidatePtr> uniqueGammas;
189  std::set_difference(toAdd->daughterPtrVector().begin(),
190  toAdd->daughterPtrVector().end(),
191  photonsInCleanCollection.begin(),
192  photonsInCleanCollection.end(),
193  std::back_inserter(uniqueGammas));
194  // If the pi zero has no unique gammas, discard it. Note toAdd is deleted
195  // when it goes out of scope.
196  if (uniqueGammas.empty()) {
197  continue;
198  } else if (uniqueGammas.size() == toAdd->daughterPtrVector().size()) {
199  // Check if it is composed entirely of unique gammas. In this case
200  // immediately add it to the clean collection.
201  photonsInCleanCollection.insert(toAdd->daughterPtrVector().begin(),
202  toAdd->daughterPtrVector().end());
203  cleanPiZeros.push_back(*toAdd);
204  } else {
205  // Otherwise update the pizero that contains only the unique gammas and
206  // add it back into the sorted list of dirty PiZeros
207  toAdd->clearDaughters();
208  // Add each of the unique daughters back to the pizero
209  for(auto const& gamma : uniqueGammas) {
210  toAdd->addDaughter(gamma);
211  }
212  // Update the four vector
213  AddFourMomenta p4Builder_;
214  p4Builder_.set(*toAdd);
215  // Put this pi zero back into the collection of sorted dirty pizeros
216  PiZeroList::iterator insertionPoint = std::lower_bound(
217  dirtyPiZeros.begin(), dirtyPiZeros.end(), *toAdd, *predicate_);
218  dirtyPiZeros.insert(insertionPoint, toAdd);
219  }
220  }
221  // Apply the mass hypothesis if desired
222  if (piZeroMass_ >= 0) {
223  for( auto& cleanPiZero: cleanPiZeros )
224  { cleanPiZero.setMass(this->piZeroMass_);};
225  }
226  // Add to association
227  if ( verbosity_ >= 2 ) {
228  print(cleanPiZeros, std::cout);
229  }
230  association->setValue(jet.key(), cleanPiZeros);
231  }
232  evt.put(std::move(association));
233 }
234 
235 // Print some helpful information
237  const std::vector<reco::RecoTauPiZero>& piZeros, std::ostream& out) {
238  const unsigned int width = 25;
239  for(auto const& piZero : piZeros) {
240  out << piZero;
241  out << "* Rankers:" << std::endl;
242  for (rankerList::const_iterator ranker = rankers_.begin();
243  ranker != rankers_.end(); ++ranker) {
244  out << "* " << std::setiosflags(std::ios::left)
245  << std::setw(width) << ranker->name()
246  << " " << std::resetiosflags(std::ios::left)
247  << std::setprecision(3) << (*ranker)(piZero);
248  out << std::endl;
249  }
250  }
251 }
252 
T getParameter(std::string const &) const
void produce(edm::Event &evt, const edm::EventSetup &es) override
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:137
def create(alignables, pedeDump, additionalData, outputFile, config)
edm::EDGetTokenT< reco::CandidateView > cand_token
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
reco::tau::RecoTauPiZeroQualityPlugin Ranker
selection
main part
Definition: corrVsCorr.py:99
bool exists(std::string const &parameterName) const
checks if a parameter exists
RecoTauPiZeroProducer(const edm::ParameterSet &pset)
reco::tau::RecoTauLexicographicalRanking< rankerList, reco::RecoTauPiZero > PiZeroPredicate
bool empty() const
Is the RefVector empty.
Definition: RefVector.h:104
void print(const std::vector< reco::RecoTauPiZero > &piZeros, std::ostream &out)
reco::tau::RecoTauPiZeroBuilderPlugin Builder
ProductID id() const
Accessor for product ID.
Definition: RefVector.h:122
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool get(ProductID const &oid, Handle< PROD > &result) const
Definition: Event.h:356
edm::RefProd< PFJetCollection > PFJetRefProd
boost::ptr_vector< reco::RecoTauPiZero > PiZeroVector
boost::ptr_vector< Builder > builderList
boost::ptr_list< reco::RecoTauPiZero > PiZeroList
boost::ptr_vector< Ranker > rankerList
void set(reco::Candidate &c) const
set up a candidate
std::auto_ptr< StringCutObjectSelector< reco::RecoTauPiZero > > outputSelector_
def move(src, dest)
Definition: eostools.py:511
T get(const Candidate &c)
Definition: component.h:55
std::auto_ptr< PiZeroPredicate > predicate_