CMS 3D CMS Logo

RecoTauVertexAssociator.cc
Go to the documentation of this file.
2 
3 #include <functional>
4 #include <boost/foreach.hpp>
5 
13 
14 #include <TMath.h>
15 
16 namespace reco { namespace tau {
17 
18 // Get the highest pt track in a jet.
19 // Get the KF track if it exists. Otherwise, see if it has a GSF track.
21 {
22  std::vector<PFCandidatePtr> chargedPFCands = pfChargedCands(jet, true);
23  if ( verbosity_ >= 1 ) {
24  std::cout << "<RecoTauVertexAssociator::getLeadTrack>:" << std::endl;
25  std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
26  std::cout << " num. chargedPFCands = " << chargedPFCands.size() << std::endl;
27  std::cout << " vxTrkFiltering = " << vxTrkFiltering_ << std::endl;
28  }
29 
30  if ( chargedPFCands.empty() ) {
31  return reco::TrackBaseRef();
32  }
33 
34  std::vector<PFCandidatePtr> selectedPFCands;
35  if ( vxTrkFiltering_ ) {
36  selectedPFCands = qcuts_->filterCandRefs(chargedPFCands);
37  } else {
38  selectedPFCands = chargedPFCands;
39  }
40  if ( verbosity_ >= 1 ) {
41  std::cout << " num. selectedPFCands = " << selectedPFCands.size() << std::endl;
42  }
43 
45  if ( !selectedPFCands.empty() ) {
46  double leadTrackPt = 0.;
47  if ( leadingTrkOrPFCandOption_ == kFirstTrack){ leadPFCand=selectedPFCands[0];}
48  else
49  {
50  for ( std::vector<PFCandidatePtr>::const_iterator pfCand = selectedPFCands.begin();
51  pfCand != selectedPFCands.end(); ++pfCand ) {
52  const reco::Track* track = nullptr;
53  if ( (*pfCand)->trackRef().isNonnull() ) track = (*pfCand)->trackRef().get();
54  else if ( (*pfCand)->gsfTrackRef().isNonnull() ) track = (*pfCand)->gsfTrackRef().get();
55  if ( !track ) continue;
56  double trackPt = 0.;
58  //double trackPt = track->pt();
59  trackPt = track->pt() - 2.*track->ptError();
60  } else if ( leadingTrkOrPFCandOption_ == kLeadPFCand ) {
61  trackPt = (*pfCand)->pt();
63  trackPt = TMath::Min(track->pt(), (double)(*pfCand)->pt());
64  } else assert(0);
65  if ( trackPt > leadTrackPt ) {
66  leadPFCand = (*pfCand);
67  leadTrackPt = trackPt;
68  }
69  }
70  }
71  }
72  if ( leadPFCand.isNull() ) {
73  if ( recoverLeadingTrk_ ) {
74  leadPFCand = chargedPFCands[0];
75  } else {
76  return reco::TrackBaseRef();
77  }
78  }
79  if ( verbosity_ >= 1 ) {
80  std::cout << "leadPFCand: Pt = " << leadPFCand->pt() << ", eta = " << leadPFCand->eta() << ", phi = " << leadPFCand->phi() << std::endl;
81  }
82 
83  if ( leadPFCand->trackRef().isNonnull() ) {
84  return reco::TrackBaseRef(leadPFCand->trackRef());
85  } else if ( leadPFCand->gsfTrackRef().isNonnull() ) {
86  return reco::TrackBaseRef(leadPFCand->gsfTrackRef());
87  }
88  return reco::TrackBaseRef();
89 }
90 
91 namespace {
92  // Define functors which extract the relevant information from a collection of
93  // vertices.
94  double dzToTrack(const reco::VertexRef& vtx, const reco::TrackBaseRef& trk)
95  {
96  if ( !trk || !vtx ) {
98  }
99  return std::abs(trk->dz(vtx->position()));
100  }
101 
102  double trackWeightInVertex(const reco::VertexRef& vtx, const reco::TrackBaseRef& trk)
103  {
104  if ( !trk || !vtx ) {
105  return 0.0;
106  }
107  return vtx->trackWeight(trk);
108  }
109 }
110 
113  qcuts_(nullptr),
115  lastEvent_(0)
116 {
117  //std::cout << "<RecoTauVertexAssociator::RecoTauVertexAssociator>:" << std::endl;
118 
119  vertexTag_ = edm::InputTag("offlinePrimaryVertices", "");
120  algorithm_ = "highestPtInEvent";
121  // Sanity check, will remove once HLT module configs are updated.
122  if ( !pset.exists("primaryVertexSrc") || !pset.exists("pvFindingAlgo") ) {
123  edm::LogWarning("NoVertexFindingMethodSpecified")
124  << "The PSet passed to the RecoTauVertexAssociator was incorrectly configured."
125  << " The vertex will be taken as the highest Pt vertex from the 'offlinePrimaryVertices' collection."
126  << std::endl;
127  } else {
128  vertexTag_ = pset.getParameter<edm::InputTag>("primaryVertexSrc");
129  algorithm_ = pset.getParameter<std::string>("pvFindingAlgo");
130  }
131 
132  if ( pset.exists("vxAssocQualityCuts") ) {
133  //std::cout << " reading 'vxAssocQualityCuts'" << std::endl;
134  qcuts_ = new RecoTauQualityCuts(pset.getParameterSet("vxAssocQualityCuts"));
135  } else {
136  //std::cout << " reading 'signalQualityCuts'" << std::endl;
137  qcuts_ = new RecoTauQualityCuts(pset.getParameterSet("signalQualityCuts"));
138  }
139  assert(qcuts_);
140 
141  vxTrkFiltering_ = false;
142  if ( !pset.exists("vertexTrackFiltering") && pset.exists("vxAssocQualityCuts") ) {
143  edm::LogWarning("NoVertexTrackFilteringSpecified")
144  << "The PSet passed to the RecoTauVertexAssociator was incorrectly configured."
145  << " Please define vertexTrackFiltering in config file."
146  << " No filtering of tracks to vertices will be applied."
147  << std::endl;
148  } else {
149  vxTrkFiltering_ = pset.exists("vertexTrackFiltering") ?
150  pset.getParameter<bool>("vertexTrackFiltering") : false;
151  }
152  if ( pset.exists("vertexSelection") ) {
153  std::string vertexSelection = pset.getParameter<std::string>("vertexSelection");
154  if ( !vertexSelection.empty() ) {
156  }
157  }
158 
159  if ( algorithm_ == "highestPtInEvent" ) {
161  } else if ( algorithm_ == "closestInDeltaZ" ) {
163  } else if ( algorithm_ == "highestWeightForLeadTrack" ) {
165  } else if ( algorithm_ == "combined" ) {
166  algo_ = kCombined;
167  } else {
168  throw cms::Exception("BadVertexAssociatorConfig")
169  << "Invalid Configuration parameter 'algorithm' " << algorithm_ << "."
170  << " Valid options are: 'highestPtInEvent', 'closestInDeltaZ', 'highestWeightForLeadTrack' and 'combined'.\n";
171  }
172 
174 
175  recoverLeadingTrk_ = pset.exists("recoverLeadingTrk") ?
176  pset.getParameter<bool>("recoverLeadingTrk") : false;
177 
178  std::string leadingTrkOrPFCandOption_string = pset.exists("leadingTrkOrPFCandOption") ? pset.getParameter<std::string>("leadingTrkOrPFCandOption") : "firstTrack" ;
179  if ( leadingTrkOrPFCandOption_string == "leadTrack" ) leadingTrkOrPFCandOption_ = kLeadTrack;
180  else if ( leadingTrkOrPFCandOption_string == "leadPFCand" ) leadingTrkOrPFCandOption_ = kLeadPFCand;
181  else if ( leadingTrkOrPFCandOption_string == "minLeadTrackOrPFCand" ) leadingTrkOrPFCandOption_ = kMinLeadTrackOrPFCand;
182  else if ( leadingTrkOrPFCandOption_string == "firstTrack" ) leadingTrkOrPFCandOption_ = kFirstTrack;
183  else throw cms::Exception("BadVertexAssociatorConfig")
184  << "Invalid Configuration parameter 'leadingTrkOrPFCandOption' " << leadingTrkOrPFCandOption_string << "."
185  << " Valid options are: 'leadTrack', 'leadPFCand', 'firstTrack'.\n";
186 
187  verbosity_ = ( pset.exists("verbosity") ) ?
188  pset.getParameter<int>("verbosity") : 0;
189 }
190 
192 {
193  delete vertexSelector_;
194  delete qcuts_;
196 }
197 
199 {
201  evt.getByToken(vxToken_, vertices);
202  selectedVertices_.clear();
203  selectedVertices_.reserve(vertices->size());
204  for ( size_t idxVertex = 0; idxVertex < vertices->size(); ++idxVertex ) {
205  reco::VertexRef vertex(vertices, idxVertex);
206  if ( vertexSelector_ && !(*vertexSelector_)(*vertex) ) continue;
207  selectedVertices_.push_back(vertex);
208  }
209  if ( !selectedVertices_.empty() ) {
211  }
212  edm::EventNumber_t currentEvent = evt.id().event();
213  if ( currentEvent != lastEvent_ || !jetToVertexAssociation_ ) {
214  if ( !jetToVertexAssociation_ ) jetToVertexAssociation_ = new std::map<const reco::PFJet*, reco::VertexRef>;
215  else jetToVertexAssociation_->clear();
216  lastEvent_ = currentEvent;
217  }
218 }
219 
222 {
223 
224  if ( !useJet ) {
225  if ( tau.leadPFChargedHadrCand().isNonnull() ) {
226  if ( tau.leadPFChargedHadrCand()->trackRef().isNonnull() )
227  return associatedVertex( reco::TrackBaseRef( tau.leadPFChargedHadrCand()->trackRef() ) );
228  else if ( tau.leadPFChargedHadrCand()->gsfTrackRef().isNonnull() )
229  return associatedVertex( reco::TrackBaseRef( tau.leadPFChargedHadrCand()->gsfTrackRef() ) );
230  }
231  }
232  // MB: use vertex associated to a given jet if explicitely requested or in case of missing leading track
233  reco::PFJetRef jetRef = tau.jetRef();
234  // FIXME workaround for HLT which does not use updated data format
235  if ( jetRef.isNull() ) jetRef = tau.pfTauTagInfoRef()->pfjetRef();
236  return associatedVertex(*jetRef);
237 }
238 
241 {
242 
243  reco::VertexRef trkVertex = ( !selectedVertices_.empty() ) ? selectedVertices_[0] : reco::VertexRef();
244 
245  if ( algo_ == kHighestPtInEvent ) {
246  if ( !selectedVertices_.empty() ) trkVertex = selectedVertices_[0];
247  } else if ( algo_ == kClosestDeltaZ ) {
248  if ( track.isNonnull() ) {
249  double closestDistance = 1.e+6;
250  // Find the vertex that has the lowest dZ to the track
251  int idxVertex = 0;
252  for ( std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
253  selectedVertex != selectedVertices_.end(); ++selectedVertex ) {
254  double dZ = dzToTrack(*selectedVertex, track);
255  if ( verbosity_ ) {
256  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x() << ", y = " << (*selectedVertex)->position().y() << ", z = " << (*selectedVertex)->position().z()
257  << " --> dZ = " << dZ << std::endl;
258  }
259  if ( dZ < closestDistance ) {
260  trkVertex = (*selectedVertex);
261  closestDistance = dZ;
262  }
263  ++idxVertex;
264  }
265  }
266  } else if ( algo_ == kHighestWeigtForLeadTrack || algo_ == kCombined ) {
267  if ( track.isNonnull() ) {
268  double largestWeight = -1.;
269  // Find the vertex that has the highest association probability to the track
270  int idxVertex = 0;
271  for ( std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
272  selectedVertex != selectedVertices_.end(); ++selectedVertex ) {
273  double weight = trackWeightInVertex(*selectedVertex, track);
274  if ( verbosity_ ) {
275  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x() << ", y = " << (*selectedVertex)->position().y() << ", z = " << (*selectedVertex)->position().z()
276  << " --> weight = " << weight << std::endl;
277  }
278  if ( weight > largestWeight ) {
279  trkVertex = (*selectedVertex);
280  largestWeight = weight;
281  }
282  ++idxVertex;
283  }
284  // the weight was never larger than zero
285  if ( algo_ == kCombined && largestWeight < 1.e-7 ) {
286  if ( verbosity_ ) {
287  std::cout << "No vertex had positive weight! Trying dZ instead... " << std::endl;
288  }
289  double closestDistance = 1.e+6;
290  // Find the vertex that has the lowest dZ to the leading track
291  int idxVertex = 0;
292  for ( std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
293  selectedVertex != selectedVertices_.end(); ++selectedVertex ) {
294  double dZ = dzToTrack(*selectedVertex, track);
295  if ( verbosity_ ) {
296  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x() << ", y = " << (*selectedVertex)->position().y() << ", z = " << (*selectedVertex)->position().z()
297  << " --> dZ = " << dZ << std::endl;
298  }
299  if ( dZ < closestDistance ) {
300  trkVertex = (*selectedVertex);
301  closestDistance = dZ;
302  }
303  ++idxVertex;
304  }
305  }
306  }
307  }
308 
309  if ( verbosity_ >= 1 ) {
310  std::cout << "--> returning vertex: x = " << trkVertex->position().x() << ", y = " << trkVertex->position().y() << ", z = " << trkVertex->position().z() << std::endl;
311  }
312 
313  return trkVertex;
314 }
315 
318 {
319  if ( verbosity_ >= 1 ) {
320  std::cout << "<RecoTauVertexAssociator::associatedVertex>:" << std::endl;
321  std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
322  std::cout << " num. Vertices = " << selectedVertices_.size() << std::endl;
323  std::cout << " size(jetToVertexAssociation) = " << jetToVertexAssociation_->size() << std::endl;
324  std::cout << " vertexTag = " << vertexTag_ << std::endl;
325  std::cout << " algorithm = " << algorithm_ << std::endl;
326  std::cout << " recoverLeadingTrk = " << recoverLeadingTrk_ << std::endl;
327  }
328 
329  reco::VertexRef jetVertex = ( !selectedVertices_.empty() ) ? selectedVertices_[0] : reco::VertexRef();
330  const PFJet* jetPtr = &jet;
331 
332  // check if jet-vertex association has been determined for this jet before
333  std::map<const reco::PFJet*, reco::VertexRef>::iterator vertexPtr = jetToVertexAssociation_->find(jetPtr);
334  if ( vertexPtr != jetToVertexAssociation_->end() ) {
335  jetVertex = vertexPtr->second;
336  } else {
337  // no jet-vertex association exists for this jet yet, compute it!
338  if ( algo_ == kHighestPtInEvent ) {
339  if ( !selectedVertices_.empty() ) jetVertex = selectedVertices_[0];
340  } else if ( algo_ == kClosestDeltaZ ||
342  algo_ == kCombined ) {
343  // find "leading" (highest Pt) track in jet
345  if ( verbosity_ ) {
346  if ( leadTrack.isNonnull() ) std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta() << ", phi = " << leadTrack->phi() << std::endl;
347  else std::cout << "leadTrack: N/A" << std::endl;
348  }
349  if ( leadTrack.isNonnull() ) {
350  jetVertex = associatedVertex(leadTrack);
351  }
352  }
353 
354  jetToVertexAssociation_->insert(std::pair<const PFJet*, reco::VertexRef>(jetPtr, jetVertex));
355  }
356 
357  if ( verbosity_ >= 1 ) {
358  std::cout << "--> returning vertex: x = " << jetVertex->position().x() << ", y = " << jetVertex->position().y() << ", z = " << jetVertex->position().z() << std::endl;
359  }
360 
361  return jetVertex;
362 }
363 
364 }}
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
const PFJetRef & jetRef() const
Definition: PFTau.cc:58
double eta() const final
momentum pseudorapidity
const PFCandidatePtr & leadPFChargedHadrCand() const
Definition: PFTau.cc:67
Coll filterCandRefs(const Coll &refcoll, bool invert=false) const
Filter a ref vector of PFCandidates.
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:579
reco::VertexRef associatedVertex(const PFJet &jet) const
bool exists(std::string const &parameterName) const
checks if a parameter exists
unsigned long long EventNumber_t
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:678
double pt() const final
transverse momentum
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 isNonnull() const
Checks for non-null.
Definition: RefToBase.h:340
reco::TrackBaseRef getLeadTrack(const PFJet &jet) const
T Min(T a, T b)
Definition: MathUtil.h:39
#define nullptr
Jets made from PFObjects.
Definition: PFJet.h:21
std::vector< reco::VertexRef > selectedVertices_
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:684
edm::RefToBase< reco::Track > TrackBaseRef
persistent reference to a Track, using views
Definition: TrackFwd.h:32
void setPV(const reco::VertexRef &vtx) const
Update the primary vertex.
double pt() const
track transverse momentum
Definition: TrackBase.h:654
double ptError() const
error on Pt (set to 1000 TeV if charge==0 for safety)
Definition: TrackBase.h:808
bool isNull() const
Checks for null.
Definition: Ptr.h:164
const double infinity
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool isNull() const
Checks for null.
Definition: Ref.h:248
InputIterator leadPFCand(InputIterator begin, InputIterator end)
StringCutObjectSelector< reco::Vertex > * vertexSelector_
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:168
RecoTauVertexAssociator(const edm::ParameterSet &pset, edm::ConsumesCollector &&iC)
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:642
const PFTauTagInfoRef & pfTauTagInfoRef() const
Definition: PFTau.cc:61
ParameterSet const & getParameterSet(std::string const &) const
edm::EDGetTokenT< reco::VertexCollection > vxToken_
edm::EventID id() const
Definition: EventBase.h:60
fixed size matrix
std::vector< PFCandidatePtr > pfChargedCands(const PFJet &jet, bool sort=true)
Extract all non-neutral candidates from a PFJet.
leadTrackPt
Definition: jets_cff.py:82
double phi() const final
momentum azimuthal angle
std::map< const reco::PFJet *, reco::VertexRef > * jetToVertexAssociation_