CMS 3D CMS Logo

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