CMS 3D CMS Logo

PFDisplacedVertexCandidateFinder.cc
Go to the documentation of this file.
1 #include <memory>
2 
4 
8 
10 
11 using namespace std;
12 using namespace reco;
13 
14 //for debug only
15 //#define PFLOW_DEBUG
16 
18  : vertexCandidates_(new PFDisplacedVertexCandidateCollection),
19  dcaCut_(1000),
20  primaryVertexCut2_(0.0),
21  dcaPInnerHitCut2_(1000.0),
22  vertexCandidatesSize_(50),
23  theMinimum_(TwoTrackMinimumDistance::SlowMode),
24  debug_(false),
25  magField_(nullptr) {}
26 
28  LogDebug("PFDisplacedVertexCandidateFinder")
29  << "~PFDisplacedVertexCandidateFinder - number of remaining elements: " << eventTracks_.size();
30 }
31 
33  edm::Handle<reco::BeamSpot> beamSpotHandle) {
34  const math::XYZPoint beamSpot = beamSpotHandle.isValid()
35  ? math::XYZPoint(beamSpotHandle->x0(), beamSpotHandle->y0(), beamSpotHandle->z0())
36  : math::XYZPoint(0, 0, 0);
37 
38  // The primary vertex is taken from the refitted list,
39  // if does not exist from the average offline beam spot position
40  // if does not exist (0,0,0) is used
41  pvtx_ = mainVertexHandle.isValid()
43  mainVertexHandle->begin()->x(), mainVertexHandle->begin()->y(), mainVertexHandle->begin()->z())
44  : beamSpot;
45 }
46 
47 // Set the imput collection of tracks and calculate their
48 // trajectory parameters the Global Trajectory Parameters
50  const MagneticField* magField) {
51  magField_ = magField;
52  trackMask_.clear();
53  trackMask_.resize(trackh->size());
55  eventTrackTrajectories_.resize(trackh->size());
56 
57  for (unsigned i = 0; i < trackMask_.size(); i++)
58  trackMask_[i] = true;
59 
60  eventTracks_.clear();
61  if (trackh.isValid()) {
62  for (unsigned i = 0; i < trackh->size(); i++) {
63  TrackRef tref(trackh, i);
64  TrackBaseRef tbref(tref);
65 
66  if (!isSelected(tbref)) {
67  trackMask_[i] = false;
68  continue;
69  }
70 
71  const Track* trk = tref.get();
72  eventTracks_.push_back(tbref);
74  }
75  }
77 }
78 
79 // -------- Main function which find vertices -------- //
80 
82  LogDebug("PFDisplacedVertexCandidateFinder") << "========= Start Finding Displaced Vertex Candidates =========";
83 
84  // The vertexCandidates have not been passed to the event, and need to be cleared
85  if (vertexCandidates_.get())
86  vertexCandidates_->clear();
87  else
88  vertexCandidates_ = std::make_unique<PFDisplacedVertexCandidateCollection>();
89 
91  for (IE ie = eventTracks_.begin(); ie != eventTracks_.end();) {
92  // Run the recursive procedure to find all tracks link together
93  // In one blob called Candidate
94 
95  PFDisplacedVertexCandidate tempVertexCandidate;
96 
97  ie = associate(eventTracks_.end(), ie, tempVertexCandidate);
98  LogDebug("PFDisplacedVertexCandidateFinder") << "elements=" << tempVertexCandidate.elements().size();
99 
100  // Build remaining links in current block
101  if (tempVertexCandidate.isValid()) {
102  packLinks(tempVertexCandidate);
103  vertexCandidates_->push_back(tempVertexCandidate);
104  }
105  }
106 
107  LogDebug("PFDisplacedVertexCandidateFinder") << "========= End Finding Displaced Vertex Candidates =========";
108 }
109 
111  IE last, IE next, PFDisplacedVertexCandidate& tempVertexCandidate) {
112  LogDebug("PFDisplacedVertexCandidateFinder") << "== Start the association procedure ==";
113 
114  if (last != eventTracks_.end()) {
115  double dist = -1;
116  GlobalPoint crossingPoint(0, 0, 0);
118  link(*last, *next, dist, crossingPoint, linktest);
119 
120  if (dist < -0.5) {
121  LogDebug("PFDisplacedVertexCandidateFinder") << "link failed";
122 
123  return ++next; // association failed
124  } else {
125  // add next element to the current pflowblock
126  LogDebug("PFDisplacedVertexCandidateFinder")
127  << "adding element " << (*next).key() << " to PFDisplacedVertexCandidate with "
128  << tempVertexCandidate.elements().size() << " elements";
129  tempVertexCandidate.addElement((*next));
130  trackMask_[(*next).key()] = false;
131 
132  LogDebug("PFDisplacedVertexCandidateFinder")
133  << "link parameters "
134  << " *next = " << (*next).key() << " *last = " << (*last).key() << " dist = " << crossingPoint
135  << " P.x = " << crossingPoint.x() << " P.y = " << crossingPoint.y() << " P.z = " << crossingPoint.z();
136  }
137  } else {
138  // add next element to this eflowblock
139  LogDebug("PFDisplacedVertexCandidateFinder") << "adding to block element " << (*next).key();
140  tempVertexCandidate.addElement((*next));
141  trackMask_[(*next).key()] = false;
142  }
143 
144  // recursive call: associate next and other unused elements
145 #ifdef EDM_ML_DEBUG
146  for (unsigned i = 0; i < trackMask_.size(); i++)
147  LogTrace("PFDisplacedVertexCandidateFinder") << " Mask[" << i << "] = " << trackMask_[i];
148 #endif
149 
150  for (IE ie = eventTracks_.begin(); ie != eventTracks_.end();) {
151  if (ie == last || ie == next) {
152  ++ie;
153  continue;
154  }
155 
156  // *ie already included to a block
157  if (!trackMask_[(*ie).key()]) {
158  ++ie;
159  continue;
160  }
161 
162  LogDebug("PFDisplacedVertexCandidateFinder") << "calling associate " << (*next).key() << " & " << (*ie).key();
163  ie = associate(next, ie, tempVertexCandidate);
164  }
165 
166  LogDebug("PFDisplacedVertexCandidateFinder") << "**** removing element ";
167 
168  IE iteratorToNextFreeElement = eventTracks_.erase(next);
169 
170  LogDebug("PFDisplacedVertexCandidateFinder") << "== End the association procedure ==";
171 
172  return iteratorToNextFreeElement;
173 }
174 
176  const TrackBaseRef& el2,
177  double& dist,
178  GlobalPoint& crossingPoint,
180  using namespace edm::soa::col;
181  const auto iel1 = el1.key();
182  const auto iel2 = el2.key();
183  const auto pt1 = track_table_.get<Pt>(iel1);
184  const auto pt2 = track_table_.get<Pt>(iel2);
185  const auto eta1 = track_table_.get<Eta>(iel1);
186  const auto eta2 = track_table_.get<Eta>(iel2);
187  const auto phi1 = track_table_.get<Phi>(iel1);
188  const auto phi2 = track_table_.get<Phi>(iel2);
189 
190  if (std::abs(eta1 - eta2) > 1) {
191  dist = -1;
192  return;
193  }
194  if (pt1 > 2 && pt2 > 2 && std::abs(phi1 - phi2) > 1) {
195  dist = -1;
196  return;
197  }
198 
201 
202  // Closest approach
203  theMinimum_.calculate(gt1, gt2);
204 
205  // Fill the parameters
206  dist = theMinimum_.distance();
207  LogDebug("PFDisplacedVertexCandidateFinder") << "link iel1=" << iel1 << " iel2=" << iel2 << " dist=" << dist;
208  crossingPoint = theMinimum_.crossingPoint();
209 
210  vertexLinkTest = PFDisplacedVertexCandidate::LINKTEST_DCA; //rechit by default
211 
212  // Check if the link test fails
213  if (dist > dcaCut_) {
214  dist = -1;
215  return;
216  }
217 
218  // Check if the closses approach point is too close to the primary vertex/beam pipe
219  double rho2 = crossingPoint.x() * crossingPoint.x() + crossingPoint.y() * crossingPoint.y();
220 
221  if (rho2 < primaryVertexCut2_) {
222  dist = -1;
223  return;
224  }
225 
226  // Check if the closses approach point is out of range of the tracker
227 
228  double tob_rho_limit2 = 10000;
229  double tec_z_limit = 270;
230 
231  if (rho2 > tob_rho_limit2) {
232  dist = -1;
233  return;
234  }
235  if (std::abs(crossingPoint.z()) > tec_z_limit) {
236  dist = -1;
237  return;
238  }
239 
240  return;
241 
242  /*
243  // Check if the inner hit of one of the tracks is not too far away from the vertex
244  double dx = el1->innerPosition().x()-P.x();
245  double dy = el1->innerPosition().y()-P.y();
246  double dz = el1->innerPosition().z()-P.z();
247  double dist2 = dx*dx+dy*dy+dz*dz;
248 
249  if (dist2 > dcaPInnerHitCut2_) {
250  dist = -1;
251  if (debug_) cout << "track " << el1.key() << " dist to vertex " << sqrt(dist2) << endl;
252  return;
253  }
254 
255  dx = el2->innerPosition().x()-P.x();
256  dy = el2->innerPosition().y()-P.y();
257  dz = el2->innerPosition().z()-P.z();
258  dist2 = dx*dx+dy*dy+dz*dz;
259 
260  if (dist2 > dcaPInnerHitCut2_) {
261  dist = -1;
262  if (debug_) cout << "track " << el2.key() << " dist to vertex " << sqrt(dist2) << endl;
263  return;
264  }
265  */
266 }
267 
268 // Build up a matrix of all the links between different tracks in
269 // In the Candidate
271  const vector<TrackBaseRef>& els = vertexCandidate.elements();
272 
273  //First Loop: update all link data
274  for (unsigned i1 = 0; i1 < els.size(); i1++) {
275  for (unsigned i2 = i1 + 1; i2 < els.size(); i2++) {
276  // no reflexive link
277  if (i1 == i2)
278  continue;
279 
280  double dist = -1;
281  GlobalPoint crossingPoint(0, 0, 0);
283 
284  link(els[i1], els[i2], dist, crossingPoint, linktest);
285  LogDebug("PFDisplacedVertexCandidateFinder")
286  << "Setting link between elements " << i1 << " key " << els[i1].key() << " and " << i2 << " key "
287  << els[i2].key() << " of dist =" << dist << " computed from link test " << linktest;
288 
289  if (dist > -0.5)
290  vertexCandidate.setLink(i1, i2, dist, crossingPoint, linktest);
291  }
292  }
293 }
294 
295 // --------------- TOOLS -------------- //
296 
297 // This tool is a copy from VZeroFinder
299  const GlobalPoint position(track->vx(), track->vy(), track->vz());
300 
301  const GlobalVector momentum(track->momentum().x(), track->momentum().y(), track->momentum().z());
302 
303  GlobalTrajectoryParameters gtp(position, momentum, track->charge(), magField_);
304 
305  return gtp;
306 }
307 
308 // This tool allow to pre-select the track for the displaced vertex finder
310  double nChi2 = trackref->normalizedChi2();
311  double pt = trackref->pt();
312  double dpt = trackref->ptError();
313  double dxy = trackref->dxy(pvtx_);
314 
315  double pt_error = dpt / pt * 100;
316 
317  LogDebug("PFDisplacedVertexCandidateFinder")
318  << " PFDisplacedVertexFinder: PFrecTrack->Track Pt= " << pt << " dPt/Pt = " << pt_error << "% nChi2 = " << nChi2;
319  if (nChi2 > nChi2_max_ || pt < pt_min_) {
320  LogDebug("PFDisplacedVertexCandidateFinder") << " PFBlockAlgo: skip badly measured or low pt track"
321  << " nChi2_cut = " << 5 << " pt_cut = " << 0.2;
322  return false;
323  }
324  // cout << "dxy = " << dxy << endl;
325  if (std::abs(dxy) < dxy_ && pt < pt_min_prim_)
326  return false;
327  // if (fabs(dxy) < 0.2 && pt < 0.8) return false;
328 
329  return true;
330 }
331 
332 ostream& operator<<(std::ostream& out, const PFDisplacedVertexCandidateFinder& a) {
333  if (!out)
334  return out;
335 
336  out << "====== Particle Flow Block Algorithm ======= ";
337  out << endl;
338  out << "number of unassociated elements : " << a.eventTracks_.size() << endl;
339  out << endl;
340 
341  out << " Tracks selection based on " << std::endl;
342  out << " pvtx_ = " << a.pvtx_ << std::endl;
343  out << " std::abs(dxy) < " << a.dxy_ << " and pt < " << a.pt_min_prim_ << std::endl;
344  out << " nChi2 < " << a.nChi2_max_ << " and pt < " << a.pt_min_ << std::endl;
345 
346  out << endl;
347 
348  for (PFDisplacedVertexCandidateFinder::IEC ie = a.eventTracks_.begin(); ie != a.eventTracks_.end(); ie++) {
349  double pt = (*ie).get()->pt();
350 
351  math::XYZPoint Pi = (*ie).get()->innerPosition();
352  math::XYZPoint Po = (*ie).get()->outerPosition();
353 
354  double innermost_radius = sqrt(Pi.x() * Pi.x() + Pi.y() * Pi.y() + Pi.z() * Pi.z());
355  double outermost_radius = sqrt(Po.x() * Po.x() + Po.y() * Po.y() + Po.z() * Po.z());
356  double innermost_rho = sqrt(Pi.x() * Pi.x() + Pi.y() * Pi.y());
357  double outermost_rho = sqrt(Po.x() * Po.x() + Po.y() * Po.y());
358 
359  out << "ie = " << (*ie).key() << " pt = " << pt << " innermost hit radius = " << innermost_radius
360  << " rho = " << innermost_rho << " outermost hit radius = " << outermost_radius << " rho = " << outermost_rho
361  << endl;
362  }
363 
364  const std::unique_ptr<reco::PFDisplacedVertexCandidateCollection>& vertexCandidates = std::move(a.vertexCandidates());
365 
366  if (!vertexCandidates.get()) {
367  out << "vertexCandidates already transfered" << endl;
368  } else {
369  out << "number of vertexCandidates : " << vertexCandidates->size() << endl;
370  out << endl;
371 
373  ib->Dump();
374  }
375 
376  return out;
377 }
void setInput(const edm::Handle< reco::TrackCollection > &trackh, const MagneticField *magField)
const double Pi
void addElement(const TrackBaseRef)
add a track Reference to the current Candidate
std::vector< PFDisplacedVertexCandidate > PFDisplacedVertexCandidateCollection
collection of PFDisplacedVertexCandidate objects
GlobalTrajectoryParameters getGlobalTrajectoryParameters(const reco::Track *) const
--—— TOOLS --—— //
A block of tracks linked together.
double ptError() const
error on Pt (set to 1000 TeV if charge==0 for safety)
Definition: TrackBase.h:754
T z() const
Definition: PV3DBase.h:61
const std::unique_ptr< reco::PFDisplacedVertexCandidateCollection > & vertexCandidates() const
IE associate(IE next, IE last, reco::PFDisplacedVertexCandidate &tempVertexCandidate)
--—— Different steps of the finder algorithm --—— ///
void setPrimaryVertex(edm::Handle< reco::VertexCollection > mainVertexHandle, edm::Handle< reco::BeamSpot > beamSpotHandle)
bool isValid() const
A Vertex Candidate is valid if it has at least two tracks.
GlobalPoint crossingPoint() const override
friend std::ostream & operator<<(std::ostream &, const PFDisplacedVertexCandidateFinder &)
std::list< reco::TrackBaseRef > eventTracks_
The track refs.
#define LogTrace(id)
bool calculate(const TrajectoryStateOnSurface &sta, const TrajectoryStateOnSurface &stb) override
double x0() const
x coordinate
Definition: BeamSpot.h:61
void link(const reco::TrackBaseRef &el1, const reco::TrackBaseRef &el2, double &dist, GlobalPoint &crossing_point, reco::PFDisplacedVertexCandidate::VertexLinkTest &linktest)
Check whether 2 elements are linked and fill the link parameters.
double pt() const
track transverse momentum
Definition: TrackBase.h:637
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
void setLink(unsigned i1, unsigned i2, const float dist, const GlobalPoint &dcaPoint, const VertexLinkTest test=LINKTEST_DCA)
std::list< reco::TrackBaseRef >::iterator IE
T sqrt(T t)
Definition: SSEVec.h:19
edm::soa::AddColumns_t< EtaPhiTable, std::tuple< col::Pt > > PtEtaPhiTable
double dcaCut_
–— Algo parameters for the vertex finder -— ///
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double y0() const
y coordinate
Definition: BeamSpot.h:63
std::unique_ptr< reco::PFDisplacedVertexCandidateCollection > vertexCandidates_
-----— Members -----— ///
const std::vector< TrackBaseRef > & elements() const
std::vector< GlobalTrajectoryParameters > eventTrackTrajectories_
size_t key() const
Definition: RefToBase.h:219
reco::PFDisplacedVertexCandidateCollection::const_iterator IBC
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
double normalizedChi2() const
chi-squared divided by n.d.o.f. (or chi-squared * 1e6 if n.d.o.f. is zero)
Definition: TrackBase.h:593
bool isValid() const
Definition: HandleBase.h:70
bool isSelected(const reco::TrackBaseRef &trackref)
double z0() const
z coordinate
Definition: BeamSpot.h:65
std::list< reco::TrackBaseRef >::const_iterator IEC
fixed size matrix
double a
Definition: hdecay.h:119
static int position[264][3]
Definition: ReadPGInfo.cc:289
void packLinks(reco::PFDisplacedVertexCandidate &vertexCandidate)
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
void findDisplacedVertexCandidates()
-----— Main function which find vertices -----— ///
double primaryVertexCut2_
Do not reconstruct vertices wich are too close to the beam pipe.
float distance() const override
bool goodPtResolution(const reco::TrackBaseRef &trackref) const
Quality Criterion on the Pt resolution to select a Track.
def move(src, dest)
Definition: eostools.py:511
ib
Definition: cuy.py:661
double dxy() const
dxy parameter. (This is the transverse impact parameter w.r.t. to (0,0,0) ONLY if refPoint is close t...
Definition: TrackBase.h:608
#define LogDebug(id)