CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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.size() == 0 ) {
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.size() >= 1 ) {
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 = 0;
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  class DZtoTrack : public std::unary_function<double, reco::VertexRef>
95  {
96  public:
97  DZtoTrack(const reco::TrackBaseRef& trk)
98  : trk_(trk)
99  {}
100  double operator()(const reco::VertexRef& vtx) const
101  {
102  if ( !trk_ || !vtx ) {
104  }
105  return std::abs(trk_->dz(vtx->position()));
106  }
107  private:
109  };
110 
111  class TrackWeightInVertex : public std::unary_function<double, reco::VertexRef>
112  {
113  public:
114  TrackWeightInVertex(const reco::TrackBaseRef& trk)
115  : trk_(trk)
116  {}
117  double operator()(const reco::VertexRef& vtx) const
118  {
119  if ( !trk_ || !vtx ) {
120  return 0.0;
121  }
122  return vtx->trackWeight(trk_);
123  }
124  private:
125  const reco::TrackBaseRef trk_;
126  };
127 }
128 
130  : vertexSelector_(0),
131  qcuts_(0),
132  jetToVertexAssociation_(0),
133  lastEvent_(0)
134 {
135  //std::cout << "<RecoTauVertexAssociator::RecoTauVertexAssociator>:" << std::endl;
136 
137  vertexTag_ = edm::InputTag("offlinePrimaryVertices", "");
138  algorithm_ = "highestPtInEvent";
139  // Sanity check, will remove once HLT module configs are updated.
140  if ( !pset.exists("primaryVertexSrc") || !pset.exists("pvFindingAlgo") ) {
141  edm::LogWarning("NoVertexFindingMethodSpecified")
142  << "The PSet passed to the RecoTauVertexAssociator was incorrectly configured."
143  << " The vertex will be taken as the highest Pt vertex from the 'offlinePrimaryVertices' collection."
144  << std::endl;
145  } else {
146  vertexTag_ = pset.getParameter<edm::InputTag>("primaryVertexSrc");
147  algorithm_ = pset.getParameter<std::string>("pvFindingAlgo");
148  }
149 
150  if ( pset.exists("vxAssocQualityCuts") ) {
151  //std::cout << " reading 'vxAssocQualityCuts'" << std::endl;
152  qcuts_ = new RecoTauQualityCuts(pset.getParameterSet("vxAssocQualityCuts"));
153  } else {
154  //std::cout << " reading 'signalQualityCuts'" << std::endl;
155  qcuts_ = new RecoTauQualityCuts(pset.getParameterSet("signalQualityCuts"));
156  }
157  assert(qcuts_);
158 
159  vxTrkFiltering_ = false;
160  if ( !pset.exists("vertexTrackFiltering") && pset.exists("vxAssocQualityCuts") ) {
161  edm::LogWarning("NoVertexTrackFilteringSpecified")
162  << "The PSet passed to the RecoTauVertexAssociator was incorrectly configured."
163  << " Please define vertexTrackFiltering in config file."
164  << " No filtering of tracks to vertices will be applied."
165  << std::endl;
166  } else {
167  vxTrkFiltering_ = pset.exists("vertexTrackFiltering") ?
168  pset.getParameter<bool>("vertexTrackFiltering") : false;
169  }
170  if ( pset.exists("vertexSelection") ) {
171  std::string vertexSelection = pset.getParameter<std::string>("vertexSelection");
172  if ( vertexSelection != "" ) {
174  }
175  }
176 
177  if ( algorithm_ == "highestPtInEvent" ) {
179  } else if ( algorithm_ == "closestInDeltaZ" ) {
181  } else if ( algorithm_ == "highestWeightForLeadTrack" ) {
183  } else if ( algorithm_ == "combined" ) {
184  algo_ = kCombined;
185  } else {
186  throw cms::Exception("BadVertexAssociatorConfig")
187  << "Invalid Configuration parameter 'algorithm' " << algorithm_ << "."
188  << " Valid options are: 'highestPtInEvent', 'closestInDeltaZ', 'highestWeightForLeadTrack' and 'combined'.\n";
189  }
190 
192 
193  recoverLeadingTrk_ = pset.exists("recoverLeadingTrk") ?
194  pset.getParameter<bool>("recoverLeadingTrk") : false;
195 
196  std::string leadingTrkOrPFCandOption_string = pset.exists("leadingTrkOrPFCandOption") ? pset.getParameter<std::string>("leadingTrkOrPFCandOption") : "firstTrack" ;
197  if ( leadingTrkOrPFCandOption_string == "leadTrack" ) leadingTrkOrPFCandOption_ = kLeadTrack;
198  else if ( leadingTrkOrPFCandOption_string == "leadPFCand" ) leadingTrkOrPFCandOption_ = kLeadPFCand;
199  else if ( leadingTrkOrPFCandOption_string == "minLeadTrackOrPFCand" ) leadingTrkOrPFCandOption_ = kMinLeadTrackOrPFCand;
200  else if ( leadingTrkOrPFCandOption_string == "firstTrack" ) leadingTrkOrPFCandOption_ = kFirstTrack;
201  else throw cms::Exception("BadVertexAssociatorConfig")
202  << "Invalid Configuration parameter 'leadingTrkOrPFCandOption' " << leadingTrkOrPFCandOption_string << "."
203  << " Valid options are: 'leadTrack', 'leadPFCand', 'firstTrack'.\n";
204 
205  verbosity_ = ( pset.exists("verbosity") ) ?
206  pset.getParameter<int>("verbosity") : 0;
207 }
208 
210 {
211  delete vertexSelector_;
212  delete qcuts_;
214 }
215 
217 {
219  evt.getByToken(vxToken_, vertices);
220  selectedVertices_.clear();
221  selectedVertices_.reserve(vertices->size());
222  for ( size_t idxVertex = 0; idxVertex < vertices->size(); ++idxVertex ) {
223  reco::VertexRef vertex(vertices, idxVertex);
224  if ( vertexSelector_ && !(*vertexSelector_)(*vertex) ) continue;
225  selectedVertices_.push_back(vertex);
226  }
227  if ( selectedVertices_.size() > 0 ) {
229  }
230  edm::EventNumber_t currentEvent = evt.id().event();
231  if ( currentEvent != lastEvent_ || !jetToVertexAssociation_ ) {
232  if ( !jetToVertexAssociation_ ) jetToVertexAssociation_ = new std::map<const reco::PFJet*, reco::VertexRef>;
233  else jetToVertexAssociation_->clear();
234  lastEvent_ = currentEvent;
235  }
236 }
237 
240 {
241  reco::PFJetRef jetRef = tau.jetRef();
242  // FIXME workaround for HLT which does not use updated data format
243  if ( jetRef.isNull() ) jetRef = tau.pfTauTagInfoRef()->pfjetRef();
244  return associatedVertex(*jetRef);
245 }
246 
249 {
250  if ( verbosity_ >= 1 ) {
251  std::cout << "<RecoTauVertexAssociator::associatedVertex>:" << std::endl;
252  std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
253  std::cout << " num. Vertices = " << selectedVertices_.size() << std::endl;
254  std::cout << " size(jetToVertexAssociation) = " << jetToVertexAssociation_->size() << std::endl;
255  std::cout << " vertexTag = " << vertexTag_ << std::endl;
256  std::cout << " algorithm = " << algorithm_ << std::endl;
257  std::cout << " recoverLeadingTrk = " << recoverLeadingTrk_ << std::endl;
258  }
259 
260  reco::VertexRef jetVertex = ( selectedVertices_.size() > 0 ) ? selectedVertices_[0] : reco::VertexRef();
261  const PFJet* jetPtr = &jet;
262 
263  // check if jet-vertex association has been determined for this jet before
264  std::map<const reco::PFJet*, reco::VertexRef>::iterator vertexPtr = jetToVertexAssociation_->find(jetPtr);
265  if ( vertexPtr != jetToVertexAssociation_->end() ) {
266  jetVertex = vertexPtr->second;
267  } else {
268  // no jet-vertex association exists for this jet yet, compute it!
269  if ( algo_ == kHighestPtInEvent ) {
270  if ( selectedVertices_.size() > 0 ) jetVertex = selectedVertices_[0];
271  } else if ( algo_ == kClosestDeltaZ ) {
272  // find "leading" (highest Pt) track in jet
274  if ( verbosity_ ) {
275  if ( leadTrack.isNonnull() ) std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta() << ", phi = " << leadTrack->phi() << std::endl;
276  else std::cout << "leadTrack: N/A" << std::endl;
277  }
278  if ( leadTrack.isNonnull() ) {
279  double closestDistance = 1.e+6;
280  DZtoTrack dzComputer(leadTrack);
281  // Find the vertex that has the lowest dZ to the leading track
282  int idxVertex = 0;
283  for ( std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
284  selectedVertex != selectedVertices_.end(); ++selectedVertex ) {
285  double dZ = dzComputer(*selectedVertex);
286  if ( verbosity_ ) {
287  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x() << ", y = " << (*selectedVertex)->position().y() << ", z = " << (*selectedVertex)->position().z()
288  << " --> dZ = " << dZ << std::endl;
289  }
290  if ( dZ < closestDistance ) {
291  jetVertex = (*selectedVertex);
292  closestDistance = dZ;
293  }
294  ++idxVertex;
295  }
296  }
297  } else if ( algo_ == kHighestWeigtForLeadTrack || algo_ == kCombined ) {
299  if ( verbosity_ ) {
300  if ( leadTrack.isNonnull() ) std::cout << "leadTrack: Pt = " << leadTrack->pt() << ", eta = " << leadTrack->eta() << ", phi = " << leadTrack->phi() << std::endl;
301  else std::cout << "leadTrack: N/A" << std::endl;
302  }
303  if ( leadTrack.isNonnull() ) {
304  double largestWeight = -1.;
305  // Find the vertex that has the highest association probability to the leading track
306  TrackWeightInVertex weightComputer(leadTrack);
307  int idxVertex = 0;
308  for ( std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
309  selectedVertex != selectedVertices_.end(); ++selectedVertex ) {
310  double weight = weightComputer(*selectedVertex);
311  if ( verbosity_ ) {
312  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x() << ", y = " << (*selectedVertex)->position().y() << ", z = " << (*selectedVertex)->position().z()
313  << " --> weight = " << weight << std::endl;
314  }
315  if ( weight > largestWeight ) {
316  jetVertex = (*selectedVertex);
317  largestWeight = weight;
318  }
319  ++idxVertex;
320  }
321  // the weight was never larger than zero
322  if ( algo_ == kCombined && largestWeight < 1.e-7 ) {
323  if ( verbosity_ ) {
324  std::cout << "No vertex had positive weight! Trying dZ instead... " << std::endl;
325  }
326  double closestDistance = 1.e+6;
327  DZtoTrack dzComputer(leadTrack);
328  // Find the vertex that has the lowest dZ to the leading track
329  int idxVertex = 0;
330  for ( std::vector<reco::VertexRef>::const_iterator selectedVertex = selectedVertices_.begin();
331  selectedVertex != selectedVertices_.end(); ++selectedVertex ) {
332  double dZ = dzComputer(*selectedVertex);
333  if ( verbosity_ ) {
334  std::cout << "vertex #" << idxVertex << ": x = " << (*selectedVertex)->position().x() << ", y = " << (*selectedVertex)->position().y() << ", z = " << (*selectedVertex)->position().z()
335  << " --> dZ = " << dZ << std::endl;
336  }
337  if ( dZ < closestDistance ) {
338  jetVertex = (*selectedVertex);
339  closestDistance = dZ;
340  }
341  ++idxVertex;
342  }
343  }
344  }
345  }
346 
347  jetToVertexAssociation_->insert(std::pair<const PFJet*, reco::VertexRef>(jetPtr, jetVertex));
348  }
349 
350  if ( verbosity_ >= 1 ) {
351  std::cout << "--> returning vertex: x = " << jetVertex->position().x() << ", y = " << jetVertex->position().y() << ", z = " << jetVertex->position().z() << std::endl;
352  }
353 
354  return jetVertex;
355 }
356 
357 }}
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
const PFJetRef & jetRef() const
Definition: PFTau.cc:58
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:462
tuple trackPt
Definition: listHistos.py:120
assert(m_qm.get())
reco::VertexRef associatedVertex(const PFJet &jet) const
bool exists(std::string const &parameterName) const
checks if a parameter exists
unsigned long long EventNumber_t
virtual double phi() const final
momentum azimuthal angle
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:640
std::vector< Vertex > VertexCollection
collection of Vertex objects
Definition: VertexFwd.h:9
void setEvent(const edm::Event &evt)
Load the vertices from the event.
bool isNonnull() const
Checks for non-null.
Definition: RefToBase.h:337
reco::TrackBaseRef getLeadTrack(const PFJet &jet) const
T Min(T a, T b)
Definition: MathUtil.h:39
Jets made from PFObjects.
Definition: PFJet.h:21
std::vector< reco::VertexRef > selectedVertices_
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:646
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:616
double ptError() const
error on Pt (set to 1000 TeV if charge==0 for safety)
Definition: TrackBase.h:758
bool isNull() const
Checks for null.
Definition: Ptr.h:165
const double infinity
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool isNull() const
Checks for null.
Definition: Ref.h:249
InputIterator leadPFCand(InputIterator begin, InputIterator end)
StringCutObjectSelector< reco::Vertex > * vertexSelector_
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:169
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:604
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:59
std::vector< PFCandidatePtr > pfChargedCands(const PFJet &jet, bool sort=true)
Extract all non-neutral candidates from a PFJet.
tuple cout
Definition: gather_cfg.py:145
virtual double eta() const final
momentum pseudorapidity
int weight
Definition: histoStyle.py:50
const reco::TrackBaseRef trk_
std::map< const reco::PFJet *, reco::VertexRef > * jetToVertexAssociation_
virtual double pt() const final
transverse momentum