CMS 3D CMS Logo

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PFRecoTauChargedHadronFromPFCandidatePlugin.cc
Go to the documentation of this file.
1 /*
2  * PFRecoTauChargedHadronFromPFCandidatePlugin
3  *
4  * Build PFRecoTauChargedHadron objects
5  * using charged PFCandidates and/or PFNeutralHadrons as input
6  *
7  * Author: Christian Veelken, LLR
8  *
9  */
10 
12 
27 
31 
36 
37 #include <memory>
38 
39 namespace reco {
40 
41  namespace tau {
42 
44  public:
47  // Return type is unique_ptr<ChargedHadronVector>
48  return_type operator()(const reco::Jet&) const override;
49  // Hook to update PV information
50  void beginEvent() override;
51 
52  private:
53  typedef std::vector<reco::CandidatePtr> CandPtrs;
54 
56 
57  std::unique_ptr<RecoTauQualityCuts> qcuts_;
58 
59  std::vector<int> inputParticleIds_; // type of candidates to clusterize
60 
76 
78  double bField_;
79 
81  };
82 
86  vertexAssociator_(pset.getParameter<edm::ParameterSet>("qualityCuts"), std::move(iC)),
87  qcuts_(nullptr),
88  bFieldToken_(iC.esConsumes()) {
89  edm::ParameterSet qcuts_pset = pset.getParameterSet("qualityCuts").getParameterSet("signalQualityCuts");
90  qcuts_ = std::make_unique<RecoTauQualityCuts>(qcuts_pset);
91 
92  inputParticleIds_ = pset.getParameter<std::vector<int> >("chargedHadronCandidatesParticleIds");
93 
94  dRmergeNeutralHadronWrtChargedHadron_ = pset.getParameter<double>("dRmergeNeutralHadronWrtChargedHadron");
95  dRmergeNeutralHadronWrtNeutralHadron_ = pset.getParameter<double>("dRmergeNeutralHadronWrtNeutralHadron");
96  dRmergeNeutralHadronWrtElectron_ = pset.getParameter<double>("dRmergeNeutralHadronWrtElectron");
97  dRmergeNeutralHadronWrtOther_ = pset.getParameter<double>("dRmergeNeutralHadronWrtOther");
98  minBlockElementMatchesNeutralHadron_ = pset.getParameter<int>("minBlockElementMatchesNeutralHadron");
99  maxUnmatchedBlockElementsNeutralHadron_ = pset.getParameter<int>("maxUnmatchedBlockElementsNeutralHadron");
100  dRmergePhotonWrtChargedHadron_ = pset.getParameter<double>("dRmergePhotonWrtChargedHadron");
101  dRmergePhotonWrtNeutralHadron_ = pset.getParameter<double>("dRmergePhotonWrtNeutralHadron");
102  dRmergePhotonWrtElectron_ = pset.getParameter<double>("dRmergePhotonWrtElectron");
103  dRmergePhotonWrtOther_ = pset.getParameter<double>("dRmergePhotonWrtOther");
104  minBlockElementMatchesPhoton_ = pset.getParameter<int>("minBlockElementMatchesPhoton");
105  maxUnmatchedBlockElementsPhoton_ = pset.getParameter<int>("maxUnmatchedBlockElementsPhoton");
106  minMergeNeutralHadronEt_ = pset.getParameter<double>("minMergeNeutralHadronEt");
107  minMergeGammaEt_ = pset.getParameter<double>("minMergeGammaEt");
108  minMergeChargedHadronPt_ = pset.getParameter<double>("minMergeChargedHadronPt");
109 
110  verbosity_ = pset.getParameter<int>("verbosity");
111  }
112 
113  // Update the primary vertex
116 
117  bField_ = evtSetup()->getData(bFieldToken_).inTesla(GlobalPoint(0, 0, 0)).z();
118  }
119 
120  namespace {
121  bool isMatchedByBlockElement(const reco::PFCandidate& pfCandidate1,
122  const reco::PFCandidate& pfCandidate2,
123  int minMatches1,
124  int minMatches2,
125  int maxUnmatchedBlockElements1plus2) {
126  reco::PFCandidate::ElementsInBlocks blockElements1 = pfCandidate1.elementsInBlocks();
127  int numBlocks1 = blockElements1.size();
128  reco::PFCandidate::ElementsInBlocks blockElements2 = pfCandidate2.elementsInBlocks();
129  int numBlocks2 = blockElements2.size();
130  int numBlocks_matched = 0;
131  for (reco::PFCandidate::ElementsInBlocks::const_iterator blockElement1 = blockElements1.begin();
132  blockElement1 != blockElements1.end();
133  ++blockElement1) {
134  bool isMatched = false;
135  for (reco::PFCandidate::ElementsInBlocks::const_iterator blockElement2 = blockElements2.begin();
136  blockElement2 != blockElements2.end();
137  ++blockElement2) {
138  if (blockElement1->first.id() == blockElement2->first.id() &&
139  blockElement1->first.key() == blockElement2->first.key() &&
140  blockElement1->second == blockElement2->second) {
141  isMatched = true;
142  }
143  }
144  if (isMatched)
145  ++numBlocks_matched;
146  }
147  assert(numBlocks_matched <= numBlocks1);
148  assert(numBlocks_matched <= numBlocks2);
149  if (numBlocks_matched >= minMatches1 && numBlocks_matched >= minMatches2 &&
150  ((numBlocks1 - numBlocks_matched) + (numBlocks2 - numBlocks_matched)) <= maxUnmatchedBlockElements1plus2) {
151  return true;
152  } else {
153  return false;
154  }
155  }
156  } // namespace
157 
159  const reco::Jet& jet) const {
160  if (verbosity_) {
161  edm::LogPrint("TauChHadronFromPF") << "<PFRecoTauChargedHadronFromPFCandidatePlugin::operator()>:";
162  edm::LogPrint("TauChHadronFromPF") << " pluginName = " << name();
163  }
164 
166 
167  // Get the candidates passing our quality cuts
169  CandPtrs candsVector = qcuts_->filterCandRefs(pfCandidates(jet, inputParticleIds_));
170 
171  for (CandPtrs::iterator cand = candsVector.begin(); cand != candsVector.end(); ++cand) {
172  if (verbosity_) {
173  edm::LogPrint("TauChHadronFromPF")
174  << "processing PFCandidate: Pt = " << (*cand)->pt() << ", eta = " << (*cand)->eta()
175  << ", phi = " << (*cand)->phi() << " (pdgId = " << (*cand)->pdgId() << ", charge = " << (*cand)->charge()
176  << ")";
177  }
178 
180  if (std::abs((*cand)->charge()) > 0.5)
182  else
184  auto chargedHadron = std::make_unique<PFRecoTauChargedHadron>(**cand, algo);
185 
186  const reco::PFCandidate* pfCand = dynamic_cast<const reco::PFCandidate*>(&**cand);
187  if (pfCand) {
188  if (pfCand->trackRef().isNonnull())
189  chargedHadron->track_ = edm::refToPtr(pfCand->trackRef());
190  else if (pfCand->muonRef().isNonnull() && pfCand->muonRef()->innerTrack().isNonnull())
191  chargedHadron->track_ = edm::refToPtr(pfCand->muonRef()->innerTrack());
192  else if (pfCand->muonRef().isNonnull() && pfCand->muonRef()->globalTrack().isNonnull())
193  chargedHadron->track_ = edm::refToPtr(pfCand->muonRef()->globalTrack());
194  else if (pfCand->muonRef().isNonnull() && pfCand->muonRef()->outerTrack().isNonnull())
195  chargedHadron->track_ = edm::refToPtr(pfCand->muonRef()->outerTrack());
196  else if (pfCand->gsfTrackRef().isNonnull())
197  chargedHadron->track_ = edm::refToPtr(pfCand->gsfTrackRef());
198  } // TauReco@MiniAOD: Tracks only available dynamically, so no possiblity to save ref here; checked by code downstream
199 
200  chargedHadron->positionAtECALEntrance_ = atECALEntrance(&**cand, bField_);
201  chargedHadron->chargedPFCandidate_ = (*cand);
202  chargedHadron->addDaughter(*cand);
203 
204  int pdgId = std::abs(chargedHadron->chargedPFCandidate_->pdgId());
205 
207  for (const auto& jetConstituent : jet.daughterPtrVector()) {
208  // CV: take care of not double-counting energy in case "charged" PFCandidate is in fact a PFNeutralHadron
209  if (jetConstituent == chargedHadron->chargedPFCandidate_)
210  continue;
211 
212  int jetConstituentPdgId = std::abs(jetConstituent->pdgId());
213  if (!(jetConstituentPdgId == 130 || jetConstituentPdgId == 22))
214  continue;
215 
216  double dR = deltaR(atECALEntrance(jetConstituent.get(), bField_),
217  atECALEntrance(chargedHadron->chargedPFCandidate_.get(), bField_));
218  double dRmerge = -1.;
219  int minBlockElementMatches = 1000;
220  int maxUnmatchedBlockElements = 0;
221  double minMergeEt = 1.e+6;
222  if (jetConstituentPdgId == 130) {
223  if (pdgId == 211)
225  else if (pdgId == 130)
227  else if (pdgId == 11)
229  else
231  minBlockElementMatches = minBlockElementMatchesNeutralHadron_;
232  maxUnmatchedBlockElements = maxUnmatchedBlockElementsNeutralHadron_;
233  minMergeEt = minMergeNeutralHadronEt_;
234  } else if (jetConstituentPdgId == 22) {
235  if (pdgId == 211)
237  else if (pdgId == 130)
239  else if (pdgId == 11)
240  dRmerge = dRmergePhotonWrtElectron_;
241  else
242  dRmerge = dRmergePhotonWrtOther_;
243  minBlockElementMatches = minBlockElementMatchesPhoton_;
244  maxUnmatchedBlockElements = maxUnmatchedBlockElementsPhoton_;
245  minMergeEt = minMergeGammaEt_;
246  }
247 
248  if (jetConstituent->et() > minMergeEt) {
249  if (dR < dRmerge) {
250  chargedHadron->neutralPFCandidates_.push_back(jetConstituent);
251  chargedHadron->addDaughter(jetConstituent);
252  } else {
253  // TauReco@MiniAOD: No access to PF blocks at MiniAOD level, but the code below seems to have very minor impact
254  const reco::PFCandidate* pfJetConstituent =
255  dynamic_cast<const reco::PFCandidate*>(jetConstituent.get());
256  if (pfCand != nullptr && pfJetConstituent != nullptr) {
257  if (isMatchedByBlockElement(*pfJetConstituent,
258  *pfCand,
259  minBlockElementMatches,
260  minBlockElementMatches,
261  maxUnmatchedBlockElements)) {
262  chargedHadron->neutralPFCandidates_.push_back(jetConstituent);
263  chargedHadron->addDaughter(jetConstituent);
264  }
265  }
266  }
267  }
268  }
269  }
270 
272 
273  if (verbosity_) {
274  edm::LogPrint("TauChHadronFromPF") << *chargedHadron;
275  }
276  // Update the vertex
277  if (chargedHadron->daughterPtr(0).isNonnull())
278  chargedHadron->setVertex(chargedHadron->daughterPtr(0)->vertex());
279  output.push_back(std::move(chargedHadron));
280  }
281 
282  return output;
283  }
284 
285  } // namespace tau
286 } // namespace reco
287 
289 
292  "PFRecoTauChargedHadronFromPFCandidatePlugin");
std::vector< CandidatePtr > pfCandidates(const Jet &jet, int particleId, bool sort=true)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
std::vector< std::unique_ptr< PFRecoTauChargedHadron > > ChargedHadronVector
math::XYZPointF atECALEntrance(const reco::Candidate *part, double bField)
Ptr< typename C::value_type > refToPtr(Ref< C, typename C::value_type, refhelper::FindUsingAdvance< C, typename C::value_type > > const &ref)
Definition: RefToPtr.h:18
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
return_type operator()(const reco::Jet &) const override
Build a collection of chargedHadrons from objects in the input jet.
const edm::EventSetup * evtSetup() const
Base class for all types of Jets.
Definition: Jet.h:20
PFRecoTauChargedHadronFromPFCandidatePlugin(const edm::ParameterSet &, edm::ConsumesCollector &&iC)
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
void setEvent(const edm::Event &evt)
Load the vertices from the event.
assert(be >=bs)
reco::VertexRef associatedVertex(const Jet &jet) const
std::vector< ElementInBlock > ElementsInBlocks
Definition: PFCandidate.h:404
const ElementsInBlocks & elementsInBlocks() const
Definition: PFCandidate.cc:665
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool isMatched(TrackingRecHit const &hit)
Log< level::Warning, true > LogPrint
constexpr auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:30
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
fixed size matrix
HLT enums.
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > bFieldToken_
const std::string & name() const
#define DEFINE_EDM_PLUGIN(factory, type, name)
Definition: output.py:1
void setChargedHadronP4(reco::PFRecoTauChargedHadron &chargedHadron, double scaleFactor_neutralPFCands=1.0)
void beginEvent() override
Hook called at the beginning of the event.
def move(src, dest)
Definition: eostools.py:511