CMS 3D CMS Logo

BoostedTauSeedsProducer.cc
Go to the documentation of this file.
1 
2 /* =============================================================================
3  * Filename: BoostedTauSeedsProducer.cc
4  *
5  * Description: Take the two subjets found by CMSBoostedTauSeedingAlgorithm
6  * and add the data-formats for
7  * o seeding the reconstruction of hadronic taus (PFJets, collection of PFCandidates not within subjet)
8  * o computation of electron and muon isolation Pt-sums, excluding the particles in the other subjet (collection of PFCandidates within subjet, used to define "Vetos")
9  *
10  * Created: 10/22/2013 16:05:00
11  *
12  * Authors: Christian Veelken (LLR)
13  *
14  * =============================================================================
15  */
16 
24 
36 
37 #include <boost/foreach.hpp>
38 
39 #include <TMath.h>
40 
41 #include <string>
42 #include <iostream>
43 #include <iomanip>
44 
46 {
47  public:
50  void produce(edm::Event&, const edm::EventSetup&) override;
51 
52  private:
53  typedef edm::AssociationMap<edm::OneToMany<std::vector<reco::PFJet>, std::vector<reco::PFCandidate>, unsigned int> > JetToPFCandidateAssociation;
54 
56 
60 
62 };
63 
65  : moduleLabel_(cfg.getParameter<std::string>("@module_label"))
66 {
67  srcSubjets_ = consumes<JetView>(cfg.getParameter<edm::InputTag>("subjetSrc"));
68  srcPFCandidates_ = consumes<reco::PFCandidateCollection>(cfg.getParameter<edm::InputTag>("pfCandidateSrc"));
69 
70  verbosity_ = ( cfg.exists("verbosity") ) ?
71  cfg.getParameter<int>("verbosity") : 0;
72 
73  produces<reco::PFJetCollection>();
74  produces<JetToPFCandidateAssociation>("pfCandAssocMapForIsolation");
75  //produces<JetToPFCandidateAssociation>("pfCandAssocMapForIsoDepositVetos");
76 }
77 
78 namespace
79 {
80  typedef std::vector<std::unordered_set<uint32_t> > JetToConstitMap;
81 
82  reco::PFJet convertToPFJet(const reco::Jet& jet, const reco::Jet::Constituents& jetConstituents)
83  {
84  // CV: code for filling pfJetSpecific objects taken from
85  // RecoParticleFlow/PFRootEvent/src/JetMaker.cc
86  double chargedHadronEnergy = 0.;
87  double neutralHadronEnergy = 0.;
88  double chargedEmEnergy = 0.;
89  double neutralEmEnergy = 0.;
90  double chargedMuEnergy = 0.;
91  int chargedMultiplicity = 0;
92  int neutralMultiplicity = 0;
93  int muonMultiplicity = 0;
94  for ( reco::Jet::Constituents::const_iterator jetConstituent = jetConstituents.begin();
95  jetConstituent != jetConstituents.end(); ++jetConstituent ) {
96  const reco::PFCandidate* pfCandidate = dynamic_cast<const reco::PFCandidate*>(jetConstituent->get());
97  if ( pfCandidate ) {
98  switch ( pfCandidate->particleId() ) {
99  case reco::PFCandidate::h : // charged hadron
100  chargedHadronEnergy += pfCandidate->energy();
101  ++chargedMultiplicity;
102  break;
103  case reco::PFCandidate::e : // electron
104  chargedEmEnergy += pfCandidate->energy();
105  ++chargedMultiplicity;
106  break;
107  case reco::PFCandidate::mu : // muon
108  chargedMuEnergy += pfCandidate->energy();
109  ++chargedMultiplicity;
111  break;
112  case reco::PFCandidate::gamma : // photon
113  case reco::PFCandidate::egamma_HF : // electromagnetic in HF
114  neutralEmEnergy += pfCandidate->energy();
115  ++neutralMultiplicity;
116  break;
117  case reco::PFCandidate::h0 : // neutral hadron
118  case reco::PFCandidate::h_HF : // hadron in HF
119  neutralHadronEnergy += pfCandidate->energy();
120  ++neutralMultiplicity;
121  break;
122  default:
123  edm::LogWarning("convertToPFJet")
124  << "PFCandidate: Pt = " << pfCandidate->pt() << ", eta = " << pfCandidate->eta() << ", phi = " << pfCandidate->phi()
125  << " has invalid particleID = " << pfCandidate->particleId() << " !!" << std::endl;
126  break;
127  }
128  } else {
129  edm::LogWarning("convertToPFJet")
130  << "Jet constituent: Pt = " << pfCandidate->pt() << ", eta = " << pfCandidate->eta() << ", phi = " << pfCandidate->phi()
131  << " is not of type PFCandidate !!" << std::endl;
132  }
133  }
134  reco::PFJet::Specific pfJetSpecific;
135  pfJetSpecific.mChargedHadronEnergy = chargedHadronEnergy;
136  pfJetSpecific.mNeutralHadronEnergy = neutralHadronEnergy;
137  pfJetSpecific.mChargedEmEnergy = chargedEmEnergy;
138  pfJetSpecific.mChargedMuEnergy = chargedMuEnergy;
139  pfJetSpecific.mNeutralEmEnergy = neutralEmEnergy;
140  pfJetSpecific.mChargedMultiplicity = chargedMultiplicity;
141  pfJetSpecific.mNeutralMultiplicity = neutralMultiplicity;
142  pfJetSpecific.mMuonMultiplicity = muonMultiplicity;
143 
144  reco::PFJet pfJet(jet.p4(), jet.vertex(), pfJetSpecific, jetConstituents);
145  pfJet.setJetArea(jet.jetArea());
146 
147  return pfJet;
148  }
149 
150  void getJetConstituents(const reco::Jet& jet, reco::Jet::Constituents& jet_and_subjetConstituents)
151  {
152  reco::Jet::Constituents jetConstituents = jet.getJetConstituents();
153  for ( reco::Jet::Constituents::const_iterator jetConstituent = jetConstituents.begin();
154  jetConstituent != jetConstituents.end(); ++jetConstituent ) {
155  const reco::Jet* subjet = dynamic_cast<const reco::Jet*>(jetConstituent->get());
156  if ( subjet ) {
157  getJetConstituents(*subjet, jet_and_subjetConstituents);
158  } else {
159  jet_and_subjetConstituents.push_back(*jetConstituent);
160  }
161  }
162  }
163 
164  std::vector<reco::PFCandidateRef> getPFCandidates_exclJetConstituents(const reco::Jet& jet, const edm::Handle<reco::PFCandidateCollection>& pfCandidates, const JetToConstitMap::value_type& constitmap, const reco::Jet::Constituents& jetConstituents, double /*dRmatch*/, bool invert)
165  {
166  //const double dRmatch2 = dRmatch*dRmatch; // comment out for now in case someone needs a dR-based search again
167  auto const & collection_cand = (*pfCandidates);
168  std::vector<reco::PFCandidateRef> pfCandidates_exclJetConstituents;
169  size_t numPFCandidates = pfCandidates->size();
170  for ( size_t pfCandidateIdx = 0; pfCandidateIdx < numPFCandidates; ++pfCandidateIdx ) {
171  if(!(deltaR2(collection_cand[pfCandidateIdx], jet)<1.0)) continue;
172  bool isJetConstituent = constitmap.count(pfCandidateIdx);
173  if ( !(isJetConstituent^invert) ) {
174  reco::PFCandidateRef pfCandidate(pfCandidates, pfCandidateIdx);
175  pfCandidates_exclJetConstituents.push_back(pfCandidate);
176  }
177  }
178  return pfCandidates_exclJetConstituents;
179  }
180 
181  void printJetConstituents(const std::string& label, const reco::Jet::Constituents& jetConstituents)
182  {
183  std::cout << "#" << label << " = " << jetConstituents.size() << ":" << std::endl;
184  int idx = 0;
185  for ( reco::Jet::Constituents::const_iterator jetConstituent = jetConstituents.begin();
186  jetConstituent != jetConstituents.end(); ++jetConstituent ) {
187  std::cout << " jetConstituent #" << idx << ": Pt = " << (*jetConstituent)->pt() << ", eta = " << (*jetConstituent)->eta() << ", phi = " << (*jetConstituent)->phi() << std::endl;
188  ++idx;
189  }
190  }
191 }
192 
194 {
195  if ( verbosity_ >= 1 ) {
196  std::cout << "<BoostedTauSeedsProducer::produce (moduleLabel = " << moduleLabel_ << ")>:" << std::endl;
197  }
198 
199  edm::Handle<JetView> subjets;
200  evt.getByToken(srcSubjets_, subjets);
201  if ( verbosity_ >= 1 ) {
202  std::cout << "#subjets = " << subjets->size() << std::endl;
203  }
204  assert((subjets->size() % 2) == 0); // CV: ensure that subjets come in pairs
205 
207  evt.getByToken(srcPFCandidates_, pfCandidates);
208  if ( verbosity_ >= 1 ) {
209  std::cout << "#pfCandidates = " << pfCandidates->size() << std::endl;
210  }
211 
212  auto selectedSubjets = std::make_unique<reco::PFJetCollection>();
214 
215  auto selectedSubjetPFCandidateAssociationForIsolation = std::make_unique<JetToPFCandidateAssociation>(&evt.productGetter());
216  //auto selectedSubjetPFCandidateAssociationForIsoDepositVetos = std::make_unique<JetToPFCandidateAssociation>(&evt.productGetter());
217 
218  // cache for jet->pfcandidate
219  JetToConstitMap constitmap(subjets->size());
220 
221  // fill constituents map
222  const auto& thesubjets = *subjets;
223  for( unsigned i = 0; i < thesubjets.size(); ++i ) {
224  for ( unsigned j = 0; j < thesubjets[i].numberOfDaughters(); ++j ) {
225  constitmap[i].emplace(thesubjets[i].daughterPtr(j).key());
226  }
227  }
228 
229  for ( size_t idx = 0; idx < (subjets->size() / 2); ++idx ) {
230  const reco::Jet* subjet1 = &subjets->at(2*idx);
231  const reco::Jet* subjet2 = &subjets->at(2*idx + 1);
232  assert(subjet1 && subjet2);
233  if ( verbosity_ >= 1 ) {
234  std::cout << "processing jet #" << idx << ":" << std::endl;
235  std::cout << " subjet1: Pt = " << subjet1->pt() << ", eta = " << subjet1->eta() << ", phi = " << subjet1->phi() << ", mass = " << subjet1->mass()
236  << " (#constituents = " << subjet1->nConstituents() << ", area = " << subjet1->jetArea() << ")" << std::endl;
237  std::cout << " subjet2: Pt = " << subjet2->pt() << ", eta = " << subjet2->eta() << ", phi = " << subjet2->phi() << ", mass = " << subjet2->mass()
238  << " (#constituents = " << subjet2->nConstituents() << ", area = " << subjet2->jetArea() << ")" << std::endl;
239  }
240 
241  if ( !(subjet1->nConstituents() >= 1 && subjet1->pt() > 1. &&
242  subjet2->nConstituents() >= 1 && subjet2->pt() > 1.) ) continue; // CV: skip pathological cases
243 
244  // find PFCandidate constituents of each subjet
245  reco::Jet::Constituents subjetConstituents1;
246  getJetConstituents(*subjet1, subjetConstituents1);
247  reco::Jet::Constituents subjetConstituents2;
248  getJetConstituents(*subjet2, subjetConstituents2);
249  if ( verbosity_ >= 1 ) {
250  printJetConstituents("subjetConstituents1", subjetConstituents1);
251  printJetConstituents("subjetConstituents2", subjetConstituents2);
252  }
253 
254  selectedSubjets->push_back(convertToPFJet(*subjet1, subjetConstituents1));
255  edm::Ref<reco::PFJetCollection> subjetRef1(selectedSubjetRefProd, selectedSubjets->size() - 1);
256  selectedSubjets->push_back(convertToPFJet(*subjet2, subjetConstituents2));
257  edm::Ref<reco::PFJetCollection> subjetRef2(selectedSubjetRefProd, selectedSubjets->size() - 1);
258 
259  // find all PFCandidates that are not constituents of the **other** subjet
260  std::vector<reco::PFCandidateRef> pfCandidatesNotInSubjet1 = getPFCandidates_exclJetConstituents(*subjet1, pfCandidates, constitmap[2*idx], subjetConstituents2, 1.e-4, false);
261  std::vector<reco::PFCandidateRef> pfCandidatesNotInSubjet2 = getPFCandidates_exclJetConstituents(*subjet2, pfCandidates, constitmap[2*idx+1], subjetConstituents1, 1.e-4, false);
262  if ( verbosity_ >= 1 ) {
263  std::cout << "#pfCandidatesNotInSubjet1 = " << pfCandidatesNotInSubjet1.size() << std::endl;
264  std::cout << "#pfCandidatesNotInSubjet2 = " << pfCandidatesNotInSubjet2.size() << std::endl;
265  }
266 
267  // build JetToPFCandidateAssociation
268  // (key = subjet, value = collection of PFCandidates that are not constituents of subjet)
269  BOOST_FOREACH( const reco::PFCandidateRef& pfCandidate, pfCandidatesNotInSubjet1 ) {
270  selectedSubjetPFCandidateAssociationForIsolation->insert(subjetRef1, pfCandidate);
271  }
272  BOOST_FOREACH( const reco::PFCandidateRef& pfCandidate, pfCandidatesNotInSubjet2 ) {
273  selectedSubjetPFCandidateAssociationForIsolation->insert(subjetRef2, pfCandidate);
274  }
275  }
276 
277  evt.put(std::move(selectedSubjets));
278  evt.put(std::move(selectedSubjetPFCandidateAssociationForIsolation), "pfCandAssocMapForIsolation");
279 }
280 
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:137
double eta() const final
momentum pseudorapidity
int mChargedMultiplicity
Definition: PFJet.h:75
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
Base class for all types of Jets.
Definition: Jet.h:20
EDProductGetter const & productGetter() const
Definition: Event.cc:104
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::vector< Constituent > Constituents
Definition: Jet.h:23
size_type size() const
double pt() const final
transverse momentum
float mNeutralHadronEnergy
Definition: PFJet.h:55
float mChargedMuEnergy
Definition: PFJet.h:73
virtual Constituents getJetConstituents() const
list of constituents
Jets made from PFObjects.
Definition: PFJet.h:21
float mChargedHadronEnergy
Definition: PFJet.h:54
BoostedTauSeedsProducer(const edm::ParameterSet &)
virtual void setJetArea(float fArea)
set jet area
Definition: Jet.h:103
float mChargedEmEnergy
Definition: PFJet.h:72
edm::View< reco::Jet > JetView
float mNeutralEmEnergy
Definition: PFJet.h:74
edm::EDGetTokenT< reco::PFCandidateCollection > srcPFCandidates_
const Point & vertex() const override
vertex position (overwritten by PF...)
double energy() const final
energy
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: LeafCandidate.h:99
RefProd< PROD > getRefBeforePut()
Definition: Event.h:167
edm::AssociationMap< edm::OneToMany< std::vector< reco::PFJet >, std::vector< reco::PFCandidate >, unsigned int > > JetToPFCandidateAssociation
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
int mNeutralMultiplicity
Definition: PFJet.h:76
std::vector< PFJet > PFJetCollection
collection of PFJet objects
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
virtual float jetArea() const
get jet area
Definition: Jet.h:105
virtual int nConstituents() const
of constituents
Definition: Jet.h:65
const_reference at(size_type pos) const
edm::EDGetTokenT< JetView > srcSubjets_
void produce(edm::Event &, const edm::EventSetup &) override
virtual ParticleType particleId() const
Definition: PFCandidate.h:374
double phi() const final
momentum azimuthal angle
def move(src, dest)
Definition: eostools.py:510
double mass() const final
mass