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_ = std::make_unique<RecoTauQualityCuts>(pset.getParameterSet("vxAssocQualityCuts"));
176  } else {
177  //std::cout << " reading 'signalQualityCuts'" << std::endl;
178  qcuts_ = std::make_unique<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()) {
194  vertexSelector_ = std::make_unique<StringCutObjectSelector<reco::Vertex>>(vertexSelection);
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 
239  selectedVertices_.clear();
240  selectedVertices_.reserve(vertices->size());
241  for (size_t idxVertex = 0; idxVertex < vertices->size(); ++idxVertex) {
242  reco::VertexRef vertex(vertices, idxVertex);
244  continue;
245  selectedVertices_.push_back(vertex);
246  }
247  if (!selectedVertices_.empty()) {
248  qcuts_->setPV(selectedVertices_[0]);
249  }
250  edm::EventNumber_t currentEvent = evt.id().event();
251  if (currentEvent != lastEvent_ || !jetToVertexAssociation_) {
253  jetToVertexAssociation_ = std::make_unique<JetToVtxAssoc>();
254  else
255  jetToVertexAssociation_->clear();
256  lastEvent_ = currentEvent;
257  }
258  }
259 
261  if (!useJet) {
262  if (tau.leadChargedHadrCand().isNonnull()) {
263  const reco::Track* track = getTrack(*tau.leadChargedHadrCand());
264  if (track != nullptr)
265  return associatedVertex(track);
266  }
267  }
268  // MB: use vertex associated to a given jet if explicitely requested or in case of missing leading track
269  reco::JetBaseRef jetRef = tau.jetRef();
270  // FIXME workaround for HLT which does not use updated data format
271  if (jetRef.isNull())
272  jetRef = tau.pfTauTagInfoRef()->pfjetRef();
273  return associatedVertex(*jetRef);
274  }
275 
277  reco::VertexRef trkVertex = (!selectedVertices_.empty()) ? selectedVertices_[0] : reco::VertexRef();
278 
279  // algos kHighestWeigtForLeadTrack and kCombined not supported
280  if (algo_ == kHighestPtInEvent) {
281  if (!selectedVertices_.empty())
282  trkVertex = selectedVertices_[0];
283  } else if (algo_ == kClosestDeltaZ) {
284  if (track) {
285  double closestDistance = 1.e+6;
286  // Find the vertex that has the lowest dZ to the track
287  int idxVertex = 0;
288  for (std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
289  selectedVertex != selectedVertices_.end();
290  ++selectedVertex) {
291  double dZ = dzToTrack(*selectedVertex, track);
292  if (verbosity_) {
293  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x()
294  << ", y = " << (*selectedVertex)->position().y()
295  << ", z = " << (*selectedVertex)->position().z() << " --> dZ = " << dZ << std::endl;
296  }
297  if (dZ < closestDistance) {
298  trkVertex = (*selectedVertex);
299  closestDistance = dZ;
300  }
301  ++idxVertex;
302  }
303  }
304  }
305 
306  if (verbosity_ >= 1) {
307  std::cout << "--> returning vertex: x = " << trkVertex->position().x() << ", y = " << trkVertex->position().y()
308  << ", z = " << trkVertex->position().z() << std::endl;
309  }
310 
311  return trkVertex;
312  }
313 
315  reco::VertexRef trkVertex = (!selectedVertices_.empty()) ? selectedVertices_[0] : reco::VertexRef();
316 
318  if (track.isNonnull()) {
319  double largestWeight = -1.;
320  // Find the vertex that has the highest association probability to the track
321  int idxVertex = 0;
322  for (std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
323  selectedVertex != selectedVertices_.end();
324  ++selectedVertex) {
325  double weight = trackWeightInVertex(*selectedVertex, track);
326  if (verbosity_) {
327  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x()
328  << ", y = " << (*selectedVertex)->position().y()
329  << ", z = " << (*selectedVertex)->position().z() << " --> weight = " << weight << std::endl;
330  }
331  if (weight > largestWeight) {
332  trkVertex = (*selectedVertex);
333  largestWeight = weight;
334  }
335  ++idxVertex;
336  }
337  // the weight was never larger than zero
338  if (algo_ == kCombined && largestWeight < 1.e-7) {
339  if (verbosity_) {
340  std::cout << "No vertex had positive weight! Trying dZ instead... " << std::endl;
341  }
342  double closestDistance = 1.e+6;
343  // Find the vertex that has the lowest dZ to the leading track
344  int idxVertex = 0;
345  for (std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
346  selectedVertex != selectedVertices_.end();
347  ++selectedVertex) {
348  double dZ = dzToTrack(*selectedVertex, track.get());
349  if (verbosity_) {
350  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x()
351  << ", y = " << (*selectedVertex)->position().y()
352  << ", z = " << (*selectedVertex)->position().z() << " --> dZ = " << dZ << std::endl;
353  }
354  if (dZ < closestDistance) {
355  trkVertex = (*selectedVertex);
356  closestDistance = dZ;
357  }
358  ++idxVertex;
359  }
360  }
361  }
362  }
363 
364  if (verbosity_ >= 1) {
365  std::cout << "--> returning vertex: x = " << trkVertex->position().x() << ", y = " << trkVertex->position().y()
366  << ", z = " << trkVertex->position().z() << std::endl;
367  }
368 
369  return trkVertex;
370  }
371 
373  if (verbosity_ >= 1) {
374  std::cout << "<RecoTauVertexAssociator::associatedVertex>:" << std::endl;
375  std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
376  std::cout << " num. Vertices = " << selectedVertices_.size() << std::endl;
377  std::cout << " size(jetToVertexAssociation) = " << jetToVertexAssociation_->size() << std::endl;
378  std::cout << " vertexTag = " << vertexTag_ << std::endl;
379  std::cout << " algorithm = " << algorithm_ << std::endl;
380  std::cout << " recoverLeadingTrk = " << recoverLeadingTrk_ << std::endl;
381  }
382 
383  reco::VertexRef jetVertex = (!selectedVertices_.empty()) ? selectedVertices_[0] : reco::VertexRef();
384  const Jet* jetPtr = &jet;
385 
386  // check if jet-vertex association has been determined for this jet before
387  auto vertexPtr = jetToVertexAssociation_->find(jetPtr);
388  if (vertexPtr != jetToVertexAssociation_->end()) {
389  jetVertex = vertexPtr->second;
390  } else {
391  // no jet-vertex association exists for this jet yet, compute it!
392  if (algo_ == kHighestPtInEvent) {
393  if (!selectedVertices_.empty())
394  jetVertex = selectedVertices_[0];
395  } else if (algo_ == kClosestDeltaZ) {
396  // find "leading" (highest Pt) track in jet
398  if (verbosity_) {
399  if (leadTrack != nullptr)
400  std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta()
401  << ", phi = " << leadTrack->phi() << std::endl;
402  else
403  std::cout << "leadTrack: N/A" << std::endl;
404  }
405  if (leadTrack != nullptr) {
406  jetVertex = associatedVertex(leadTrack);
407  }
408  } else if (algo_ == kHighestWeigtForLeadTrack || algo_ == kCombined) {
409  // find "leading" (highest Pt) track in jet
411  if (verbosity_) {
412  if (leadTrack.isNonnull())
413  std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta()
414  << ", phi = " << leadTrack->phi() << std::endl;
415  else
416  std::cout << "leadTrack: N/A" << std::endl;
417  }
418  if (leadTrack.isNonnull()) {
419  jetVertex = associatedVertex(leadTrack);
420  }
421  }
422 
423  jetToVertexAssociation_->insert({jetPtr, jetVertex});
424  }
425 
426  if (verbosity_ >= 1) {
427  std::cout << "--> returning vertex: x = " << jetVertex->position().x() << ", y = " << jetVertex->position().y()
428  << ", z = " << jetVertex->position().z() << std::endl;
429  }
430 
431  return jetVertex;
432  }
433 
434  } // namespace tau
435 } // namespace reco
std::unique_ptr< JetToVtxAssoc > jetToVertexAssociation_
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:526
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:63
bool isNull() const
Checks for null.
Definition: RefToBase.h:284
const TrackBaseRef getLeadTrackRef(const Jet &) const
const Track * getLeadTrack(const Jet &) const
RecoTauVertexAssociator(const edm::ParameterSet &pset, edm::ConsumesCollector &&iC)
static const TrackGhostTrackState * getTrack(const BasicGhostTrackState *basic)
std::unique_ptr< RecoTauQualityCuts > qcuts_
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
std::unique_ptr< StringCutObjectSelector< reco::Vertex > > vertexSelector_
Log< level::Warning, false > LogWarning
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.