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 <TMath.h>
38 
39 #include <string>
40 #include <iostream>
41 #include <iomanip>
42 
44 public:
47  void produce(edm::Event&, const edm::EventSetup&) override;
48 
49 private:
50  typedef edm::AssociationMap<edm::OneToMany<std::vector<reco::PFJet>, std::vector<reco::PFCandidate>, unsigned int> >
52 
54 
58 
61 };
62 
64  : moduleLabel_(cfg.getParameter<std::string>("@module_label")) {
65  srcSubjets_ = consumes<JetView>(cfg.getParameter<edm::InputTag>("subjetSrc"));
66  srcPFCandidates_ = consumes<reco::PFCandidateCollection>(cfg.getParameter<edm::InputTag>("pfCandidateSrc"));
67 
68  correctlyExcludeOverlap_ = (cfg.exists("correctlyExcludeOverlap")) ? cfg.getParameter<bool>("correctlyExcludeOverlap") : false;
70  edm::LogWarning("") << "The \"correctlyExcludeOverlap\" flag set to \"False\":\n"
71  << "=> module is working in a buggy backward compatibility mode; is it intended?";
72  }
73 
74  verbosity_ = (cfg.exists("verbosity")) ? cfg.getParameter<int>("verbosity") : 0;
75 
76  produces<reco::PFJetCollection>();
77  produces<JetToPFCandidateAssociation>("pfCandAssocMapForIsolation");
78  //produces<JetToPFCandidateAssociation>("pfCandAssocMapForIsoDepositVetos");
79 }
80 
81 namespace {
82  typedef std::vector<std::unordered_set<uint32_t> > JetToConstitMap;
83 
84  reco::PFJet convertToPFJet(const reco::Jet& jet, const reco::Jet::Constituents& jetConstituents) {
85  // CV: code for filling pfJetSpecific objects taken from
86  // RecoParticleFlow/PFRootEvent/src/JetMaker.cc
87  double chargedHadronEnergy = 0.;
88  double neutralHadronEnergy = 0.;
89  double chargedEmEnergy = 0.;
90  double neutralEmEnergy = 0.;
91  double chargedMuEnergy = 0.;
92  int chargedMultiplicity = 0;
93  int neutralMultiplicity = 0;
94  int muonMultiplicity = 0;
95  for (auto const& jetConstituent : jetConstituents) {
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()
125  << ", phi = " << pfCandidate->phi() << " has invalid particleID = " << pfCandidate->particleId()
126  << " !!" << std::endl;
127  break;
128  }
129  } else {
130  edm::LogWarning("convertToPFJet")
131  << "Jet constituent: Pt = " << jetConstituent->pt() << ", eta = " << jetConstituent->eta()
132  << ", phi = " << jetConstituent->phi() << " is not of type PFCandidate !!" << std::endl;
133  }
134  }
135  reco::PFJet::Specific pfJetSpecific;
136  pfJetSpecific.mChargedHadronEnergy = chargedHadronEnergy;
137  pfJetSpecific.mNeutralHadronEnergy = neutralHadronEnergy;
138  pfJetSpecific.mChargedEmEnergy = chargedEmEnergy;
139  pfJetSpecific.mChargedMuEnergy = chargedMuEnergy;
140  pfJetSpecific.mNeutralEmEnergy = neutralEmEnergy;
141  pfJetSpecific.mChargedMultiplicity = chargedMultiplicity;
142  pfJetSpecific.mNeutralMultiplicity = neutralMultiplicity;
143  pfJetSpecific.mMuonMultiplicity = muonMultiplicity;
144 
145  reco::PFJet pfJet(jet.p4(), jet.vertex(), pfJetSpecific, jetConstituents);
146  pfJet.setJetArea(jet.jetArea());
147 
148  return pfJet;
149  }
150 
151  void getJetConstituents(const reco::Jet& jet, reco::Jet::Constituents& jet_and_subjetConstituents) {
152  reco::Jet::Constituents jetConstituents = jet.getJetConstituents();
153  for (auto const& jetConstituent : jetConstituents) {
154  const reco::Jet* subjet = dynamic_cast<const reco::Jet*>(jetConstituent.get());
155  if (subjet) {
156  getJetConstituents(*subjet, jet_and_subjetConstituents);
157  } else {
158  jet_and_subjetConstituents.push_back(jetConstituent);
159  }
160  }
161  }
162 
163  std::vector<reco::PFCandidateRef> getPFCandidates_exclJetConstituents(
164  const reco::Jet& jet,
166  const JetToConstitMap::value_type& constitmap,
167  bool invert) {
168  auto const& collection_cand = (*pfCandidates);
169  std::vector<reco::PFCandidateRef> pfCandidates_exclJetConstituents;
170  size_t numPFCandidates = pfCandidates->size();
171  for (size_t pfCandidateIdx = 0; pfCandidateIdx < numPFCandidates; ++pfCandidateIdx) {
172  if (!(deltaR2(collection_cand[pfCandidateIdx], jet) < 1.0))
173  continue;
174  bool isJetConstituent = constitmap.count(pfCandidateIdx);
175  if (!(isJetConstituent ^ invert)) {
176  reco::PFCandidateRef pfCandidate(pfCandidates, pfCandidateIdx);
177  pfCandidates_exclJetConstituents.push_back(pfCandidate);
178  }
179  }
180  return pfCandidates_exclJetConstituents;
181  }
182 
183  void printJetConstituents(const std::string& label, const reco::Jet::Constituents& jetConstituents) {
184  std::cout << "#" << label << " = " << jetConstituents.size() << ":" << std::endl;
185  unsigned idx = 0;
186  for (auto const& jetConstituent : jetConstituents) {
187  std::cout << " jetConstituent #" << idx << ": Pt = " << (*jetConstituent).pt()
188  << ", eta = " << (*jetConstituent).eta() << ", phi = " << (*jetConstituent).phi() << std::endl;
189  ++idx;
190  }
191  }
192 } // namespace
193 
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 =
216  std::make_unique<JetToPFCandidateAssociation>(&evt.productGetter());
217  //auto selectedSubjetPFCandidateAssociationForIsoDepositVetos = std::make_unique<JetToPFCandidateAssociation>(&evt.productGetter());
218 
219  // cache for jet->pfcandidate
220  JetToConstitMap constitmap(subjets->size());
221 
222  // fill constituents map
223  const auto& thesubjets = *subjets;
224  for (unsigned i = 0; i < thesubjets.size(); ++i) {
225  for (unsigned j = 0; j < thesubjets[i].numberOfDaughters(); ++j) {
226  constitmap[i].emplace(thesubjets[i].daughterPtr(j).key());
227  }
228  }
229 
230  for (size_t idx = 0; idx < (subjets->size() / 2); ++idx) {
231  const reco::Jet* subjet1 = &subjets->at(2 * idx);
232  const reco::Jet* subjet2 = &subjets->at(2 * idx + 1);
233  assert(subjet1 && subjet2);
234  if (verbosity_ >= 1) {
235  std::cout << "processing jet #" << idx << ":" << std::endl;
236  std::cout << " subjet1: Pt = " << subjet1->pt() << ", eta = " << subjet1->eta() << ", phi = " << subjet1->phi()
237  << ", mass = " << subjet1->mass() << " (#constituents = " << subjet1->nConstituents()
238  << ", area = " << subjet1->jetArea() << ")" << std::endl;
239  std::cout << " subjet2: Pt = " << subjet2->pt() << ", eta = " << subjet2->eta() << ", phi = " << subjet2->phi()
240  << ", mass = " << subjet2->mass() << " (#constituents = " << subjet2->nConstituents()
241  << ", area = " << subjet2->jetArea() << ")" << std::endl;
242  }
243 
244  if (!(subjet1->nConstituents() >= 1 && subjet1->pt() > 1. && subjet2->nConstituents() >= 1 && subjet2->pt() > 1.))
245  continue; // CV: skip pathological cases
246 
247  // find PFCandidate constituents of each subjet
248  reco::Jet::Constituents subjetConstituents1;
249  getJetConstituents(*subjet1, subjetConstituents1);
250  reco::Jet::Constituents subjetConstituents2;
251  getJetConstituents(*subjet2, subjetConstituents2);
252  if (verbosity_ >= 1) {
253  printJetConstituents("subjetConstituents1", subjetConstituents1);
254  printJetConstituents("subjetConstituents2", subjetConstituents2);
255  }
256 
257  selectedSubjets->push_back(convertToPFJet(*subjet1, subjetConstituents1));
258  edm::Ref<reco::PFJetCollection> subjetRef1(selectedSubjetRefProd, selectedSubjets->size() - 1);
259  selectedSubjets->push_back(convertToPFJet(*subjet2, subjetConstituents2));
260  edm::Ref<reco::PFJetCollection> subjetRef2(selectedSubjetRefProd, selectedSubjets->size() - 1);
261 
262  // find all PFCandidates that are not constituents of the **other** subjet
263  std::vector<reco::PFCandidateRef> pfCandidatesNotInSubjet1, pfCandidatesNotInSubjet2;
264  //Overlapping constituents can be incorrectly selected as in previous
265  //buggy version of this module to fulfill non-changing policy in
266  //10_6_X release series.
268  pfCandidatesNotInSubjet1 = getPFCandidates_exclJetConstituents(*subjet1, pfCandidates, constitmap[2 * idx + 1], false);
269  pfCandidatesNotInSubjet2 = getPFCandidates_exclJetConstituents(*subjet2, pfCandidates, constitmap[2 * idx], false);
270  }
271  else {
272  pfCandidatesNotInSubjet1 = getPFCandidates_exclJetConstituents(*subjet1, pfCandidates, constitmap[2 * idx], false);
273  pfCandidatesNotInSubjet2 = getPFCandidates_exclJetConstituents(*subjet2, pfCandidates, constitmap[2 * idx + 1], false);
274  }
275  if (verbosity_ >= 1) {
276  std::cout << "#pfCandidatesNotInSubjet1 = " << pfCandidatesNotInSubjet1.size() << std::endl;
277  std::cout << "#pfCandidatesNotInSubjet2 = " << pfCandidatesNotInSubjet2.size() << std::endl;
278  }
279 
280  // build JetToPFCandidateAssociation
281  // (key = subjet, value = collection of PFCandidates that are not constituents of subjet)
282  for (auto const& pfCandidate : pfCandidatesNotInSubjet1) {
283  selectedSubjetPFCandidateAssociationForIsolation->insert(subjetRef1, pfCandidate);
284  }
285  for (auto const& pfCandidate : pfCandidatesNotInSubjet2) {
286  selectedSubjetPFCandidateAssociationForIsolation->insert(subjetRef2, pfCandidate);
287  }
288  }
289 
290  evt.put(std::move(selectedSubjets));
291  evt.put(std::move(selectedSubjetPFCandidateAssociationForIsolation), "pfCandAssocMapForIsolation");
292 }
293 
T getParameter(std::string const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
double eta() const final
momentum pseudorapidity
int mChargedMultiplicity
Definition: PFJet.h:75
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
Base class for all types of Jets.
Definition: Jet.h:20
EDProductGetter const & productGetter() const
Definition: Event.cc:93
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
char const * label
float mChargedEmEnergy
Definition: PFJet.h:72
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
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:150
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:511
double mass() const final
mass