CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PFRecoTauChargedHadronProducer.cc
Go to the documentation of this file.
1 /*
2  * PFRecoTauChargedHadronProducer
3  *
4  * Author: Christian Veelken, LLR
5  *
6  * Associates reconstructed ChargedHadrons to PFJets. The ChargedHadrons are built using one
7  * or more RecoTauBuilder plugins. Any overlaps (ChargedHadrons sharing tracks)
8  * are removed, with the best ChargedHadron candidates taken. The 'best' are defined
9  * via the input list of PFRecoTauChargedHadronQualityPlugins, which form a
10  * lexicograpical ranking.
11  *
12  */
13 
18 
21 
26 
37 
39 
40 #include <boost/ptr_container/ptr_vector.hpp>
41 #include <boost/ptr_container/ptr_list.hpp>
42 #include <boost/foreach.hpp>
43 
44 #include <string>
45 #include <vector>
46 #include <list>
47 #include <set>
48 #include <algorithm>
49 #include <functional>
50 #include <math.h>
51 
53 {
54 public:
57 
60  void produce(edm::Event& evt, const edm::EventSetup& es);
61  template <typename T>
62  void print(const T& chargedHadrons);
63 
64  private:
65  typedef boost::ptr_vector<Builder> builderList;
66  typedef boost::ptr_vector<Ranker> rankerList;
67  typedef boost::ptr_vector<reco::PFRecoTauChargedHadron> ChargedHadronVector;
68  typedef boost::ptr_list<reco::PFRecoTauChargedHadron> ChargedHadronList;
69 
71 
73 
74  // input jet collection
77 
78  // plugins for building and ranking ChargedHadron candidates
81 
82  std::auto_ptr<ChargedHadronPredicate> predicate_;
83 
84  // output selector
85  std::auto_ptr<StringCutObjectSelector<reco::PFRecoTauChargedHadron> > outputSelector_;
86 
87  // flag to enable/disable debug print-out
89 };
90 
92  : moduleLabel_(cfg.getParameter<std::string>("@module_label"))
93 {
94  srcJets_ = cfg.getParameter<edm::InputTag>("jetSrc");
95  Jets_token = consumes<reco::CandidateView>(srcJets_);
96  verbosity_ = ( cfg.exists("verbosity") ) ?
97  cfg.getParameter<int>("verbosity") : 0;
98 
99  // get set of ChargedHadron builder plugins
100  edm::VParameterSet psets_builders = cfg.getParameter<edm::VParameterSet>("builders");
101  for ( edm::VParameterSet::const_iterator pset = psets_builders.begin();
102  pset != psets_builders.end(); ++pset ) {
103  std::string pluginType = pset->getParameter<std::string>("plugin");
104  edm::ParameterSet pset_modified = (*pset);
105  pset_modified.addParameter<int>("verbosity", verbosity_);
106  builders_.push_back(PFRecoTauChargedHadronBuilderPluginFactory::get()->create(pluginType, pset_modified, consumesCollector()));
107  }
108 
109  // get set of plugins for ranking ChargedHadrons in quality
110  edm::VParameterSet psets_rankers = cfg.getParameter<edm::VParameterSet>("ranking");
111  for ( edm::VParameterSet::const_iterator pset = psets_rankers.begin();
112  pset != psets_rankers.end(); ++pset ) {
113  std::string pluginType = pset->getParameter<std::string>("plugin");
114  edm::ParameterSet pset_modified = (*pset);
115  pset_modified.addParameter<int>("verbosity", verbosity_);
116  rankers_.push_back(PFRecoTauChargedHadronQualityPluginFactory::get()->create(pluginType, pset_modified));
117  }
118 
119  // build the sorting predicate
120  predicate_ = std::auto_ptr<ChargedHadronPredicate>(new ChargedHadronPredicate(rankers_));
121 
122  // check if we want to apply a final output selection
123  if ( cfg.exists("outputSelection") ) {
124  std::string selection = cfg.getParameter<std::string>("outputSelection");
125  if ( selection != "" ) {
127  }
128  }
129 
130  produces<reco::PFJetChargedHadronAssociation>();
131 }
132 
134 {
135  if ( verbosity_ ) {
136  edm::LogPrint("PFRecoTauChHProducer")<< "<PFRecoTauChargedHadronProducer::produce>:" ;
137  edm::LogPrint("PFRecoTauChHProducer")<< " moduleLabel = " << moduleLabel_ ;
138  }
139 
140  // give each of our plugins a chance at doing something with the edm::Event
141  BOOST_FOREACH( Builder& builder, builders_ ) {
142  builder.setup(evt, es);
143  }
144 
145  // get a view of our jets via the base candidates
147  evt.getByToken(Jets_token, jets);
148 
149  // convert the view to a RefVector of actual PFJets
150  reco::PFJetRefVector pfJets = reco::tau::castView<reco::PFJetRefVector>(jets);
151 
152  // make our association
153  std::auto_ptr<reco::PFJetChargedHadronAssociation> pfJetChargedHadronAssociations;
154 
155  if ( pfJets.size() ) {
156  pfJetChargedHadronAssociations.reset(new reco::PFJetChargedHadronAssociation(reco::PFJetRefProd(pfJets)));
157  } else {
158  pfJetChargedHadronAssociations.reset(new reco::PFJetChargedHadronAssociation);
159  }
160 
161  // loop over our jets
162  BOOST_FOREACH( const reco::PFJetRef& pfJet, pfJets ) {
163 
164  // build global list of ChargedHadron candidates for each jet
165  ChargedHadronList uncleanedChargedHadrons;
166 
167  // merge candidates reconstructed by all desired algorithm plugins
168  BOOST_FOREACH( const Builder& builder, builders_ ) {
169  try {
170  ChargedHadronVector result(builder(*pfJet));
171  if ( verbosity_ ) {
172  edm::LogPrint("PFRecoTauChHProducer")<< "result of builder = " << builder.name() << ":" ;
173  print(result);
174  }
175  uncleanedChargedHadrons.transfer(uncleanedChargedHadrons.end(), result);
176  } catch ( cms::Exception& exception ) {
177  edm::LogError("BuilderPluginException")
178  << "Exception caught in builder plugin " << builder.name()
179  << ", rethrowing" << std::endl;
180  throw exception;
181  }
182  }
183 
184  // rank the candidates according to our quality plugins
185  uncleanedChargedHadrons.sort(*predicate_);
186 
187  // define collection of cleaned ChargedHadrons;
188  std::vector<reco::PFRecoTauChargedHadron> cleanedChargedHadrons;
189 
190  // keep track of neutral PFCandidates, charged PFCandidates and tracks "used" by ChargedHadron candidates in the clean collection
191  typedef std::pair<double, double> etaPhiPair;
192  std::list<etaPhiPair> tracksInCleanCollection;
193  std::set<reco::PFCandidatePtr> neutralPFCandsInCleanCollection;
194 
195  while ( uncleanedChargedHadrons.size() >= 1 ) {
196 
197  // get next best ChargedHadron candidate
198  std::auto_ptr<reco::PFRecoTauChargedHadron> nextChargedHadron(uncleanedChargedHadrons.pop_front().release());
199  if ( verbosity_ ) {
200  edm::LogPrint("PFRecoTauChHProducer")<< "processing nextChargedHadron:" ;
201  edm::LogPrint("PFRecoTauChHProducer")<< (*nextChargedHadron);
202  }
203 
204  // discard candidates which fail final output selection
205  if ( !(*outputSelector_)(*nextChargedHadron) ) continue;
206 
207  const reco::Track* track = 0;
208  if ( nextChargedHadron->getChargedPFCandidate().isNonnull() ) {
209  const reco::PFCandidatePtr& chargedPFCand = nextChargedHadron->getChargedPFCandidate();
210  if ( chargedPFCand->trackRef().isNonnull() ) track = chargedPFCand->trackRef().get();
211  else if ( chargedPFCand->muonRef().isNonnull() && chargedPFCand->muonRef()->innerTrack().isNonnull() ) track = chargedPFCand->muonRef()->innerTrack().get();
212  else if ( chargedPFCand->muonRef().isNonnull() && chargedPFCand->muonRef()->globalTrack().isNonnull() ) track = chargedPFCand->muonRef()->globalTrack().get();
213  else if ( chargedPFCand->muonRef().isNonnull() && chargedPFCand->muonRef()->outerTrack().isNonnull() ) track = chargedPFCand->muonRef()->outerTrack().get();
214  else if ( chargedPFCand->gsfTrackRef().isNonnull() ) track = chargedPFCand->gsfTrackRef().get();
215  }
216  if ( nextChargedHadron->getTrack().isNonnull() && !track ) {
217  track = nextChargedHadron->getTrack().get();
218  }
219 
220  // discard candidate in case its track is "used" by any ChargedHadron in the clean collection
221  bool isTrack_overlap = false;
222  if ( track ) {
223  double track_eta = track->eta();
224  double track_phi = track->phi();
225  for ( std::list<etaPhiPair>::const_iterator trackInCleanCollection = tracksInCleanCollection.begin();
226  trackInCleanCollection != tracksInCleanCollection.end(); ++trackInCleanCollection ) {
227  double dR = deltaR(track_eta, track_phi, trackInCleanCollection->first, trackInCleanCollection->second);
228  if ( dR < 1.e-4 ) isTrack_overlap = true;
229  }
230  }
231  if ( verbosity_ ) {
232  edm::LogPrint("PFRecoTauChHProducer")<< "isTrack_overlap = " << isTrack_overlap ;
233  }
234  if ( isTrack_overlap ) continue;
235 
236  // discard ChargedHadron candidates without track in case they are close to neutral PFCandidates "used" by ChargedHadron candidates in the clean collection
237  bool isNeutralPFCand_overlap = false;
238  if ( nextChargedHadron->algoIs(reco::PFRecoTauChargedHadron::kPFNeutralHadron) ) {
239  for ( std::set<reco::PFCandidatePtr>::const_iterator neutralPFCandInCleanCollection = neutralPFCandsInCleanCollection.begin();
240  neutralPFCandInCleanCollection != neutralPFCandsInCleanCollection.end(); ++neutralPFCandInCleanCollection ) {
241  if ( (*neutralPFCandInCleanCollection) == nextChargedHadron->getChargedPFCandidate() ) isNeutralPFCand_overlap = true;
242  }
243  }
244  if ( verbosity_ ) {
245  edm::LogPrint("PFRecoTauChHProducer")<< "isNeutralPFCand_overlap = " << isNeutralPFCand_overlap ;
246  }
247  if ( isNeutralPFCand_overlap ) continue;
248 
249  // find neutral PFCandidates that are not "used" by any ChargedHadron in the clean collection
250  std::vector<reco::PFCandidatePtr> uniqueNeutralPFCands;
251  std::set_difference(nextChargedHadron->getNeutralPFCandidates().begin(),
252  nextChargedHadron->getNeutralPFCandidates().end(),
253  neutralPFCandsInCleanCollection.begin(),
254  neutralPFCandsInCleanCollection.end(),
255  std::back_inserter(uniqueNeutralPFCands));
256 
257  if ( uniqueNeutralPFCands.size() == nextChargedHadron->getNeutralPFCandidates().size() ) { // all neutral PFCandidates are unique, add ChargedHadron candidate to clean collection
258  if ( track ) tracksInCleanCollection.push_back(std::make_pair(track->eta(), track->phi()));
259  neutralPFCandsInCleanCollection.insert(nextChargedHadron->getNeutralPFCandidates().begin(), nextChargedHadron->getNeutralPFCandidates().end());
260  if ( verbosity_ ) {
261  edm::LogPrint("PFRecoTauChHProducer")<< "--> adding nextChargedHadron to output collection." ;
262  }
263  cleanedChargedHadrons.push_back(*nextChargedHadron);
264  } else { // remove overlapping neutral PFCandidates, reevaluate ranking criterion and process ChargedHadron candidate again
265  nextChargedHadron->neutralPFCandidates_.clear();
266  BOOST_FOREACH( const reco::PFCandidatePtr& neutralPFCand, uniqueNeutralPFCands ) {
267  nextChargedHadron->neutralPFCandidates_.push_back(neutralPFCand);
268  }
269  // update ChargedHadron four-momentum
270  reco::tau::setChargedHadronP4(*nextChargedHadron);
271  // reinsert ChargedHadron candidate into list of uncleaned candidates,
272  // at position according to new rank
273  ChargedHadronList::iterator insertionPoint = std::lower_bound(uncleanedChargedHadrons.begin(), uncleanedChargedHadrons.end(), *nextChargedHadron, *predicate_);
274  if ( verbosity_ ) {
275  edm::LogPrint("PFRecoTauChHProducer")<< "--> removing non-unique neutral PFCandidates and reinserting nextChargedHadron in uncleaned collection." ;
276  }
277  uncleanedChargedHadrons.insert(insertionPoint, nextChargedHadron);
278  }
279  }
280 
281  if ( verbosity_ ) {
282  print(cleanedChargedHadrons);
283  }
284 
285  // add ChargedHadron-to-jet association
286  pfJetChargedHadronAssociations->setValue(pfJet.key(), cleanedChargedHadrons);
287  }
288 
289  evt.put(pfJetChargedHadronAssociations);
290 }
291 
292 template <typename T>
293 void PFRecoTauChargedHadronProducer::print(const T& chargedHadrons)
294 {
295  for ( typename T::const_iterator chargedHadron = chargedHadrons.begin();
296  chargedHadron != chargedHadrons.end(); ++chargedHadron ) {
297  edm::LogPrint("PFRecoTauChHProducer") << (*chargedHadron);
298  edm::LogPrint("PFRecoTauChHProducer") << "Rankers:" ;
299  for ( rankerList::const_iterator ranker = rankers_.begin();
300  ranker != rankers_.end(); ++ranker) {
301  const unsigned width = 25;
302  edm::LogPrint("PFRecoTauChHProducer") << " " << std::setiosflags(std::ios::left) << std::setw(width) << ranker->name()
303  << " " << std::resetiosflags(std::ios::left) << std::setprecision(3) << (*ranker)(*chargedHadron) << std::endl;
304  }
305  }
306 }
307 
309 
T getParameter(std::string const &) const
tuple cfg
Definition: looper.py:237
reco::tau::RecoTauLexicographicalRanking< rankerList, reco::PFRecoTauChargedHadron > ChargedHadronPredicate
void produce(edm::Event &evt, const edm::EventSetup &es)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:446
PFRecoTauChargedHadronProducer(const edm::ParameterSet &cfg)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
std::vector< ParameterSet > VParameterSet
Definition: ParameterSet.h:33
T const * get() const
Returns C++ pointer to the item.
Definition: Ptr.h:143
selection
main part
Definition: corrVsCorr.py:98
bool exists(std::string const &parameterName) const
checks if a parameter exists
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:693
key_type key() const
Accessor for product key.
Definition: Ref.h:266
edm::EDGetTokenT< reco::CandidateView > Jets_token
void setup(edm::Event &, const edm::EventSetup &)
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:699
reco::tau::PFRecoTauChargedHadronBuilderPlugin Builder
boost::ptr_vector< reco::PFRecoTauChargedHadron > ChargedHadronVector
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:113
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
std::auto_ptr< ChargedHadronPredicate > predicate_
vector< PseudoJet > jets
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:142
tuple result
Definition: query.py:137
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:152
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
reco::tau::PFRecoTauChargedHadronQualityPlugin Ranker
std::auto_ptr< StringCutObjectSelector< reco::PFRecoTauChargedHadron > > outputSelector_
boost::ptr_list< reco::PFRecoTauChargedHadron > ChargedHadronList
size_type size() const
Size of the RefVector.
Definition: RefVector.h:89
const std::string & name() const
void setChargedHadronP4(reco::PFRecoTauChargedHadron &chargedHadron, double scaleFactor_neutralPFCands=1.0)
moduleLabel_(iConfig.getParameter< string >("@module_label"))
long double T
tuple pfJets
Definition: pfJets_cff.py:8
SurfaceDeformation * create(int type, const std::vector< double > &params)
T get(const Candidate &c)
Definition: component.h:55