CMS 3D CMS Logo

RecoTauVertexAssociator.cc
Go to the documentation of this file.
2 
3 #include <functional>
4 
14 
15 namespace reco {
16  namespace tau {
17 
18  namespace {
19  inline const reco::Track* getTrack(const Candidate& cand) {
20  const PFCandidate* pfCandPtr = dynamic_cast<const PFCandidate*>(&cand);
21  if (pfCandPtr != nullptr) {
22  if (pfCandPtr->trackRef().isNonnull())
23  return pfCandPtr->trackRef().get();
24  else if (pfCandPtr->gsfTrackRef().isNonnull())
25  return pfCandPtr->gsfTrackRef().get();
26  else
27  return nullptr;
28  }
29  const pat::PackedCandidate* packedCand = dynamic_cast<const pat::PackedCandidate*>(&cand);
30  if (packedCand != nullptr && packedCand->hasTrackDetails())
31  return &packedCand->pseudoTrack();
32 
33  return nullptr;
34  }
35 
36  inline const reco::TrackBaseRef getTrackRef(const Candidate& cand) {
37  // TauReco@MiniAOD: This version does not work on top of MiniAOD, however,
38  // it is only used for non-default track-vertex associations
39  const PFCandidate* pfCandPtr = dynamic_cast<const PFCandidate*>(&cand);
40  if (pfCandPtr != nullptr) {
41  if (pfCandPtr->trackRef().isNonnull())
42  return reco::TrackBaseRef(pfCandPtr->trackRef());
43  else if (pfCandPtr->gsfTrackRef().isNonnull())
44  return reco::TrackBaseRef(pfCandPtr->gsfTrackRef());
45  else
46  return reco::TrackBaseRef();
47  }
48 
49  return reco::TrackBaseRef();
50  }
51  } // namespace
52 
53  // Get the highest pt track in a jet.
54  // Get the KF track if it exists. Otherwise, see if it has a GSF track.
56  std::vector<CandidatePtr> chargedPFCands = pfChargedCands(jet, true);
57  if (verbosity_ >= 1) {
58  std::cout << "<RecoTauVertexAssociator::getLeadTrack>:" << std::endl;
59  std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
60  std::cout << " num. chargedPFCands = " << chargedPFCands.size() << std::endl;
61  std::cout << " vxTrkFiltering = " << vxTrkFiltering_ << std::endl;
62  }
63 
64  if (chargedPFCands.empty()) {
65  return reco::CandidatePtr(nullptr, 0);
66  }
67 
68  std::vector<CandidatePtr> selectedPFCands;
69  if (vxTrkFiltering_) {
70  selectedPFCands = qcuts_->filterCandRefs(chargedPFCands);
71  } else {
72  selectedPFCands = chargedPFCands;
73  }
74  if (verbosity_ >= 1) {
75  std::cout << " num. selectedPFCands = " << selectedPFCands.size() << std::endl;
76  }
77 
79  if (!selectedPFCands.empty()) {
80  double leadTrackPt = 0.;
82  leadCand = selectedPFCands[0];
83  } else {
84  for (std::vector<CandidatePtr>::const_iterator pfCand = selectedPFCands.begin();
85  pfCand != selectedPFCands.end();
86  ++pfCand) {
87  const reco::Track* track = getTrack(**pfCand);
88  double actualTrackPt = 0., actualTrackPtError = 0.;
89  if (track != nullptr) {
90  actualTrackPt = track->pt();
91  actualTrackPtError = track->ptError();
92  }
93  double trackPt = 0.;
95  trackPt = actualTrackPt - 2. * actualTrackPtError;
96  } else if (leadingTrkOrPFCandOption_ == kLeadPFCand) {
97  trackPt = (*pfCand)->pt();
99  trackPt = std::min(actualTrackPt, (double)(*pfCand)->pt());
100  } else
101  assert(0);
102  if (trackPt > leadTrackPt) {
103  leadCand = (*pfCand);
105  }
106  }
107  }
108  }
109  if (leadCand.isNull()) {
110  if (recoverLeadingTrk_) {
111  leadCand = chargedPFCands[0];
112  } else {
113  return reco::CandidatePtr(nullptr, 0);
114  }
115  }
116  if (verbosity_ >= 1) {
117  std::cout << "leadCand: Pt = " << leadCand->pt() << ", eta = " << leadCand->eta()
118  << ", phi = " << leadCand->phi() << std::endl;
119  }
120  return leadCand;
121  }
122 
124  auto leadCand = getLeadCand(jet);
125  if (leadCand.isNull())
126  return nullptr;
127  const reco::Track* track = getTrack(*leadCand);
128  return track;
129  }
130 
132  auto leadCand = getLeadCand(jet);
133  if (leadCand.isNull())
134  return reco::TrackBaseRef();
135  return getTrackRef(*leadCand);
136  }
137 
138  namespace {
139  // Define functors which extract the relevant information from a collection of
140  // vertices.
141  double dzToTrack(const reco::VertexRef& vtx, const reco::Track* trk) {
142  if (!trk || !vtx) {
144  }
145  return std::abs(trk->dz(vtx->position()));
146  }
147 
148  double trackWeightInVertex(const reco::VertexRef& vtx, const reco::TrackBaseRef& trk) {
149  if (!trk || !vtx) {
150  return 0.0;
151  }
152  return vtx->trackWeight(trk);
153  }
154  } // namespace
155 
157  : vertexSelector_(nullptr), qcuts_(nullptr), jetToVertexAssociation_(nullptr), lastEvent_(0) {
158  //std::cout << "<RecoTauVertexAssociator::RecoTauVertexAssociator>:" << std::endl;
159 
160  vertexTag_ = edm::InputTag("offlinePrimaryVertices", "");
161  algorithm_ = "highestPtInEvent";
162  // Sanity check, will remove once HLT module configs are updated.
163  if (!pset.exists("primaryVertexSrc") || !pset.exists("pvFindingAlgo")) {
164  edm::LogWarning("NoVertexFindingMethodSpecified")
165  << "The PSet passed to the RecoTauVertexAssociator was incorrectly configured."
166  << " The vertex will be taken as the highest Pt vertex from the 'offlinePrimaryVertices' collection."
167  << std::endl;
168  } else {
169  vertexTag_ = pset.getParameter<edm::InputTag>("primaryVertexSrc");
170  algorithm_ = pset.getParameter<std::string>("pvFindingAlgo");
171  }
172 
173  if (pset.exists("vxAssocQualityCuts")) {
174  //std::cout << " reading 'vxAssocQualityCuts'" << std::endl;
175  qcuts_ = new RecoTauQualityCuts(pset.getParameterSet("vxAssocQualityCuts"));
176  } else {
177  //std::cout << " reading 'signalQualityCuts'" << std::endl;
178  qcuts_ = new RecoTauQualityCuts(pset.getParameterSet("signalQualityCuts"));
179  }
180  assert(qcuts_);
181 
182  vxTrkFiltering_ = false;
183  if (!pset.exists("vertexTrackFiltering") && pset.exists("vxAssocQualityCuts")) {
184  edm::LogWarning("NoVertexTrackFilteringSpecified")
185  << "The PSet passed to the RecoTauVertexAssociator was incorrectly configured."
186  << " Please define vertexTrackFiltering in config file."
187  << " No filtering of tracks to vertices will be applied." << std::endl;
188  } else {
189  vxTrkFiltering_ = pset.exists("vertexTrackFiltering") ? pset.getParameter<bool>("vertexTrackFiltering") : false;
190  }
191  if (pset.exists("vertexSelection")) {
192  std::string vertexSelection = pset.getParameter<std::string>("vertexSelection");
193  if (!vertexSelection.empty()) {
195  }
196  }
197 
198  if (algorithm_ == "highestPtInEvent") {
200  } else if (algorithm_ == "closestInDeltaZ") {
202  } else if (algorithm_ == "highestWeightForLeadTrack") {
204  } else if (algorithm_ == "combined") {
205  algo_ = kCombined;
206  } else {
207  throw cms::Exception("BadVertexAssociatorConfig")
208  << "Invalid Configuration parameter 'algorithm' " << algorithm_ << "."
209  << " Valid options are: 'highestPtInEvent', 'closestInDeltaZ', 'highestWeightForLeadTrack' and "
210  "'combined'.\n";
211  }
212 
214 
215  recoverLeadingTrk_ = pset.exists("recoverLeadingTrk") ? pset.getParameter<bool>("recoverLeadingTrk") : false;
216 
217  std::string leadingTrkOrPFCandOption_string = pset.exists("leadingTrkOrPFCandOption")
218  ? pset.getParameter<std::string>("leadingTrkOrPFCandOption")
219  : "firstTrack";
220  if (leadingTrkOrPFCandOption_string == "leadTrack")
222  else if (leadingTrkOrPFCandOption_string == "leadPFCand")
224  else if (leadingTrkOrPFCandOption_string == "minLeadTrackOrPFCand")
226  else if (leadingTrkOrPFCandOption_string == "firstTrack")
228  else
229  throw cms::Exception("BadVertexAssociatorConfig")
230  << "Invalid Configuration parameter 'leadingTrkOrPFCandOption' " << leadingTrkOrPFCandOption_string << "."
231  << " Valid options are: 'leadTrack', 'leadPFCand', 'firstTrack'.\n";
232 
233  verbosity_ = (pset.exists("verbosity")) ? pset.getParameter<int>("verbosity") : 0;
234  }
235 
237  delete vertexSelector_;
238  delete qcuts_;
240  }
241 
245  selectedVertices_.clear();
246  selectedVertices_.reserve(vertices->size());
247  for (size_t idxVertex = 0; idxVertex < vertices->size(); ++idxVertex) {
248  reco::VertexRef vertex(vertices, idxVertex);
250  continue;
251  selectedVertices_.push_back(vertex);
252  }
253  if (!selectedVertices_.empty()) {
255  }
256  edm::EventNumber_t currentEvent = evt.id().event();
257  if (currentEvent != lastEvent_ || !jetToVertexAssociation_) {
259  jetToVertexAssociation_ = new std::map<const reco::Jet*, reco::VertexRef>;
260  else
261  jetToVertexAssociation_->clear();
262  lastEvent_ = currentEvent;
263  }
264  }
265 
267  if (!useJet) {
268  if (tau.leadChargedHadrCand().isNonnull()) {
269  const reco::Track* track = getTrack(*tau.leadChargedHadrCand());
270  if (track != nullptr)
271  return associatedVertex(track);
272  }
273  }
274  // MB: use vertex associated to a given jet if explicitely requested or in case of missing leading track
275  reco::JetBaseRef jetRef = tau.jetRef();
276  // FIXME workaround for HLT which does not use updated data format
277  if (jetRef.isNull())
278  jetRef = tau.pfTauTagInfoRef()->pfjetRef();
279  return associatedVertex(*jetRef);
280  }
281 
283  reco::VertexRef trkVertex = (!selectedVertices_.empty()) ? selectedVertices_[0] : reco::VertexRef();
284 
285  // algos kHighestWeigtForLeadTrack and kCombined not supported
286  if (algo_ == kHighestPtInEvent) {
287  if (!selectedVertices_.empty())
288  trkVertex = selectedVertices_[0];
289  } else if (algo_ == kClosestDeltaZ) {
290  if (track) {
291  double closestDistance = 1.e+6;
292  // Find the vertex that has the lowest dZ to the track
293  int idxVertex = 0;
294  for (std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
295  selectedVertex != selectedVertices_.end();
296  ++selectedVertex) {
297  double dZ = dzToTrack(*selectedVertex, track);
298  if (verbosity_) {
299  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x()
300  << ", y = " << (*selectedVertex)->position().y()
301  << ", z = " << (*selectedVertex)->position().z() << " --> dZ = " << dZ << std::endl;
302  }
303  if (dZ < closestDistance) {
304  trkVertex = (*selectedVertex);
305  closestDistance = dZ;
306  }
307  ++idxVertex;
308  }
309  }
310  }
311 
312  if (verbosity_ >= 1) {
313  std::cout << "--> returning vertex: x = " << trkVertex->position().x() << ", y = " << trkVertex->position().y()
314  << ", z = " << trkVertex->position().z() << std::endl;
315  }
316 
317  return trkVertex;
318  }
319 
321  reco::VertexRef trkVertex = (!selectedVertices_.empty()) ? selectedVertices_[0] : reco::VertexRef();
322 
324  if (track.isNonnull()) {
325  double largestWeight = -1.;
326  // Find the vertex that has the highest association probability to the track
327  int idxVertex = 0;
328  for (std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
329  selectedVertex != selectedVertices_.end();
330  ++selectedVertex) {
331  double weight = trackWeightInVertex(*selectedVertex, track);
332  if (verbosity_) {
333  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x()
334  << ", y = " << (*selectedVertex)->position().y()
335  << ", z = " << (*selectedVertex)->position().z() << " --> weight = " << weight << std::endl;
336  }
337  if (weight > largestWeight) {
338  trkVertex = (*selectedVertex);
339  largestWeight = weight;
340  }
341  ++idxVertex;
342  }
343  // the weight was never larger than zero
344  if (algo_ == kCombined && largestWeight < 1.e-7) {
345  if (verbosity_) {
346  std::cout << "No vertex had positive weight! Trying dZ instead... " << std::endl;
347  }
348  double closestDistance = 1.e+6;
349  // Find the vertex that has the lowest dZ to the leading track
350  int idxVertex = 0;
351  for (std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
352  selectedVertex != selectedVertices_.end();
353  ++selectedVertex) {
354  double dZ = dzToTrack(*selectedVertex, track.get());
355  if (verbosity_) {
356  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x()
357  << ", y = " << (*selectedVertex)->position().y()
358  << ", z = " << (*selectedVertex)->position().z() << " --> dZ = " << dZ << std::endl;
359  }
360  if (dZ < closestDistance) {
361  trkVertex = (*selectedVertex);
362  closestDistance = dZ;
363  }
364  ++idxVertex;
365  }
366  }
367  }
368  }
369 
370  if (verbosity_ >= 1) {
371  std::cout << "--> returning vertex: x = " << trkVertex->position().x() << ", y = " << trkVertex->position().y()
372  << ", z = " << trkVertex->position().z() << std::endl;
373  }
374 
375  return trkVertex;
376  }
377 
379  if (verbosity_ >= 1) {
380  std::cout << "<RecoTauVertexAssociator::associatedVertex>:" << std::endl;
381  std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
382  std::cout << " num. Vertices = " << selectedVertices_.size() << std::endl;
383  std::cout << " size(jetToVertexAssociation) = " << jetToVertexAssociation_->size() << std::endl;
384  std::cout << " vertexTag = " << vertexTag_ << std::endl;
385  std::cout << " algorithm = " << algorithm_ << std::endl;
386  std::cout << " recoverLeadingTrk = " << recoverLeadingTrk_ << std::endl;
387  }
388 
389  reco::VertexRef jetVertex = (!selectedVertices_.empty()) ? selectedVertices_[0] : reco::VertexRef();
390  const Jet* jetPtr = &jet;
391 
392  // check if jet-vertex association has been determined for this jet before
393  std::map<const reco::Jet*, reco::VertexRef>::iterator vertexPtr = jetToVertexAssociation_->find(jetPtr);
394  if (vertexPtr != jetToVertexAssociation_->end()) {
395  jetVertex = vertexPtr->second;
396  } else {
397  // no jet-vertex association exists for this jet yet, compute it!
398  if (algo_ == kHighestPtInEvent) {
399  if (!selectedVertices_.empty())
400  jetVertex = selectedVertices_[0];
401  } else if (algo_ == kClosestDeltaZ) {
402  // find "leading" (highest Pt) track in jet
404  if (verbosity_) {
405  if (leadTrack != nullptr)
406  std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta()
407  << ", phi = " << leadTrack->phi() << std::endl;
408  else
409  std::cout << "leadTrack: N/A" << std::endl;
410  }
411  if (leadTrack != nullptr) {
412  jetVertex = associatedVertex(leadTrack);
413  }
414  } else if (algo_ == kHighestWeigtForLeadTrack || algo_ == kCombined) {
415  // find "leading" (highest Pt) track in jet
417  if (verbosity_) {
418  if (leadTrack.isNonnull())
419  std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta()
420  << ", phi = " << leadTrack->phi() << std::endl;
421  else
422  std::cout << "leadTrack: N/A" << std::endl;
423  }
424  if (leadTrack.isNonnull()) {
425  jetVertex = associatedVertex(leadTrack);
426  }
427  }
428 
429  jetToVertexAssociation_->insert(std::pair<const Jet*, reco::VertexRef>(jetPtr, jetVertex));
430  }
431 
432  if (verbosity_ >= 1) {
433  std::cout << "--> returning vertex: x = " << jetVertex->position().x() << ", y = " << jetVertex->position().y()
434  << ", z = " << jetVertex->position().z() << std::endl;
435  }
436 
437  return jetVertex;
438  }
439 
440  } // namespace tau
441 } // namespace reco
unsigned long long EventNumber_t
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
Definition: weight.py:1
void setEvent(const edm::Event &evt)
Load the vertices from the event.
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:539
assert(be >=bs)
std::vector< CandidatePtr > pfChargedCands(const Jet &jet, bool sort=true)
Extract all non-neutral candidates from a PFJet.
InputIterator leadCand(InputIterator begin, InputIterator end)
reco::VertexRef associatedVertex(const Jet &jet) const
std::vector< reco::VertexRef > selectedVertices_
double dz() const
dz parameter (= dsz/cos(lambda)). This is the track z0 w.r.t (0,0,0) only if the refPoint is close to...
Definition: TrackBase.h:622
edm::RefToBase< reco::Track > TrackBaseRef
persistent reference to a Track, using views
Definition: TrackFwd.h:35
Definition: Jet.py:1
const double infinity
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
edm::EventID id() const
Definition: EventBase.h:59
bool isNull() const
Checks for null.
Definition: RefToBase.h:295
const TrackBaseRef getLeadTrackRef(const Jet &) const
StringCutObjectSelector< reco::Vertex > * vertexSelector_
const Track * getLeadTrack(const Jet &) const
RecoTauVertexAssociator(const edm::ParameterSet &pset, edm::ConsumesCollector &&iC)
Coll filterCandRefs(const Coll &refcoll, bool invert=false) const
Filter a ref vector of Candidates.
std::map< const reco::Jet *, reco::VertexRef > * jetToVertexAssociation_
static const TrackGhostTrackState * getTrack(const BasicGhostTrackState *basic)
edm::Ptr< Candidate > CandidatePtr
persistent reference to an object in a collection of Candidate objects
Definition: CandidateFwd.h:25
edm::EDGetTokenT< reco::VertexCollection > vxToken_
fixed size matrix
Log< level::Warning, false > LogWarning
void setPV(const reco::VertexRef &vtx)
Update the primary vertex.
EventNumber_t event() const
Definition: EventID.h:40
const CandidatePtr getLeadCand(const Jet &) const
virtual const reco::Track & pseudoTrack() const
bool hasTrackDetails() const
Return true if a bestTrack can be extracted from this Candidate.