CMS 3D CMS Logo

DAClusterizerInZ_vect.cc
Go to the documentation of this file.
5 
6 #include <cmath>
7 #include <cassert>
8 #include <limits>
9 #include <iomanip>
11 #include "vdt/vdtMath.h"
12 
13 #include <Math/SMatrix.h>
14 
15 using namespace std;
16 
17 //#define DEBUG
18 #ifdef DEBUG
19 #define DEBUGLEVEL 0
20 #endif
21 
23  // hardcoded parameters
24  maxIterations_ = 1000;
25  mintrkweight_ = 0.5;
26 
27  // configurable debug outptut debug output
28  verbose_ = conf.getUntrackedParameter<bool>("verbose", false);
29  zdumpcenter_ = conf.getUntrackedParameter<double>("zdumpcenter", 0.);
30  zdumpwidth_ = conf.getUntrackedParameter<double>("zdumpwidth", 20.);
31 
32  // configurable parameters
33  double Tmin = conf.getParameter<double>("Tmin");
34  double Tpurge = conf.getParameter<double>("Tpurge");
35  double Tstop = conf.getParameter<double>("Tstop");
36  vertexSize_ = conf.getParameter<double>("vertexSize");
37  coolingFactor_ = conf.getParameter<double>("coolingFactor");
38  d0CutOff_ = conf.getParameter<double>("d0CutOff");
39  dzCutOff_ = conf.getParameter<double>("dzCutOff");
40  uniquetrkweight_ = conf.getParameter<double>("uniquetrkweight");
41  zmerge_ = conf.getParameter<double>("zmerge");
42  sel_zrange_ = conf.getParameter<double>("zrange");
43  convergence_mode_ = conf.getParameter<int>("convergence_mode");
44  delta_lowT_ = conf.getParameter<double>("delta_lowT");
45  delta_highT_ = conf.getParameter<double>("delta_highT");
46 
47  if (verbose_) {
48  std::cout << "DAClusterizerinZ_vect: mintrkweight = " << mintrkweight_ << std::endl;
49  std::cout << "DAClusterizerinZ_vect: uniquetrkweight = " << uniquetrkweight_ << std::endl;
50  std::cout << "DAClusterizerinZ_vect: zmerge = " << zmerge_ << std::endl;
51  std::cout << "DAClusterizerinZ_vect: Tmin = " << Tmin << std::endl;
52  std::cout << "DAClusterizerinZ_vect: Tpurge = " << Tpurge << std::endl;
53  std::cout << "DAClusterizerinZ_vect: Tstop = " << Tstop << std::endl;
54  std::cout << "DAClusterizerinZ_vect: vertexSize = " << vertexSize_ << std::endl;
55  std::cout << "DAClusterizerinZ_vect: coolingFactor = " << coolingFactor_ << std::endl;
56  std::cout << "DAClusterizerinZ_vect: d0CutOff = " << d0CutOff_ << std::endl;
57  std::cout << "DAClusterizerinZ_vect: dzCutOff = " << dzCutOff_ << std::endl;
58  std::cout << "DAClusterizerInZ_vect: zrange = " << sel_zrange_ << std::endl;
59  std::cout << "DAClusterizerinZ_vect: convergence mode = " << convergence_mode_ << std::endl;
60  std::cout << "DAClusterizerinZ_vect: delta_highT = " << delta_highT_ << std::endl;
61  std::cout << "DAClusterizerinZ_vect: delta_lowT = " << delta_lowT_ << std::endl;
62  }
63 #ifdef DEBUG
64  std::cout << "DAClusterizerinZ_vect: DEBUGLEVEL " << DEBUGLEVEL << std::endl;
65 #endif
66 
67  if (convergence_mode_ > 1) {
68  edm::LogWarning("DAClusterizerinZ_vect")
69  << "DAClusterizerInZ_vect: invalid convergence_mode" << convergence_mode_ << " reset to default " << 0;
70  convergence_mode_ = 0;
71  }
72 
73  if (Tmin == 0) {
74  edm::LogWarning("DAClusterizerinZ_vect")
75  << "DAClusterizerInZ_vect: invalid Tmin" << Tmin << " reset to default " << 1. / betamax_;
76  } else {
77  betamax_ = 1. / Tmin;
78  }
79 
80  if ((Tpurge > Tmin) || (Tpurge == 0)) {
81  edm::LogWarning("DAClusterizerinZ_vect")
82  << "DAClusterizerInZ_vect: invalid Tpurge" << Tpurge << " set to " << Tmin;
83  Tpurge = Tmin;
84  }
85  betapurge_ = 1. / Tpurge;
86 
87  if ((Tstop > Tpurge) || (Tstop == 0)) {
88  edm::LogWarning("DAClusterizerinZ_vect")
89  << "DAClusterizerInZ_vect: invalid Tstop" << Tstop << " set to " << max(1., Tpurge);
90  Tstop = max(1., Tpurge);
91  }
92  betastop_ = 1. / Tstop;
93 }
94 
95 namespace {
96  inline double local_exp(double const& inp) { return vdt::fast_exp(inp); }
97 
98  inline void local_exp_list_range(double const* __restrict__ arg_inp,
99  double* __restrict__ arg_out,
100  const unsigned int kmin,
101  const unsigned int kmax) {
102  for (auto i = kmin; i != kmax; ++i)
103  arg_out[i] = vdt::fast_exp(arg_inp[i]);
104  }
105 
106 } // namespace
107 
108 void DAClusterizerInZ_vect::verify(const vertex_t& v, const track_t& tks, unsigned int nv, unsigned int nt) const {
109  if (!(nv == 999999)) {
110  assert(nv == v.getSize());
111  } else {
112  nv = v.getSize();
113  }
114 
115  if (!(nt == 999999)) {
116  assert(nt == tks.getSize());
117  } else {
118  nt = tks.getSize();
119  }
120 
121  assert(v.z.size() == nv);
122  assert(v.pk.size() == nv);
123  assert(v.swz.size() == nv);
124  assert(v.ei_cache.size() == nv);
125  assert(v.ei.size() == nv);
126  assert(v.se.size() == nv);
127  assert(v.swz.size() == nv);
128  assert(v.swE.size() == nv);
129 
130  assert(v.z_ptr == &v.z.front());
131  assert(v.pk_ptr == &v.pk.front());
132  assert(v.ei_cache_ptr == &v.ei_cache.front());
133  assert(v.swz_ptr == &v.swz.front());
134  assert(v.se_ptr == &v.se.front());
135  assert(v.swE_ptr == &v.swE.front());
136 
137  for (unsigned int k = 0; k < nv - 1; k++) {
138  if (v.z[k] <= v.z[k + 1])
139  continue;
140  cout << " Z, cluster z-ordering assertion failure z[" << k << "] =" << v.z[k] << " z[" << k + 1
141  << "] =" << v.z[k + 1] << endl;
142  }
143  //for(unsigned int k=0; k< nv-1; k++){
144  // assert( v.z[k] <= v.z[k+1]);
145  //}
146 
147  assert(nt == tks.z.size());
148  assert(nt == tks.dz2.size());
149  assert(nt == tks.tt.size());
150  assert(nt == tks.pi.size());
151  assert(nt == tks.Z_sum.size());
152  assert(nt == tks.kmin.size());
153  assert(nt == tks.kmax.size());
154 
155  assert(tks.z_ptr == &tks.z.front());
156  assert(tks.dz2_ptr == &tks.dz2.front());
157  assert(tks.pi_ptr == &tks.pi.front());
158  assert(tks.Z_sum_ptr == &tks.Z_sum.front());
159 
160  for (unsigned int i = 0; i < nt; i++) {
161  if ((tks.kmin[i] < tks.kmax[i]) && (tks.kmax[i] <= nv))
162  continue;
163  cout << "track vertex range assertion failure" << i << "/" << nt << " kmin,kmax=" << tks.kmin[i] << ", "
164  << tks.kmax[i] << " nv=" << nv << endl;
165  }
166 
167  for (unsigned int i = 0; i < nt; i++) {
168  assert((tks.kmin[i] < tks.kmax[i]) && (tks.kmax[i] <= nv));
169  }
170 }
171 
172 //todo: use r-value possibility of c++11 here
173 DAClusterizerInZ_vect::track_t DAClusterizerInZ_vect::fill(const vector<reco::TransientTrack>& tracks) const {
174  // prepare track data for clustering
175  track_t tks;
176  for (auto it = tracks.begin(); it != tracks.end(); it++) {
177  if (!(*it).isValid())
178  continue;
179  double t_pi = 1.;
180  double t_z = ((*it).stateAtBeamLine().trackStateAtPCA()).position().z();
181  if (std::fabs(t_z) > 1000.)
182  continue;
183  auto const& t_mom = (*it).stateAtBeamLine().trackStateAtPCA().momentum();
184  // get the beam-spot
185  reco::BeamSpot beamspot = (it->stateAtBeamLine()).beamSpot();
186  double t_dz2 = std::pow((*it).track().dzError(), 2) // track errror
187  + (std::pow(beamspot.BeamWidthX() * t_mom.x(), 2) + std::pow(beamspot.BeamWidthY() * t_mom.y(), 2)) *
188  std::pow(t_mom.z(), 2) / std::pow(t_mom.perp2(), 2) // beam spot width
189  + std::pow(vertexSize_, 2); // intrinsic vertex size, safer for outliers and short lived decays
190  t_dz2 = 1. / t_dz2;
191  if (edm::isNotFinite(t_dz2) || t_dz2 < std::numeric_limits<double>::min())
192  continue;
193  if (d0CutOff_ > 0) {
194  Measurement1D atIP = (*it).stateAtBeamLine().transverseImpactParameter(); // error contains beamspot
195  t_pi = 1. / (1. + local_exp(std::pow(atIP.value() / atIP.error(), 2) -
196  std::pow(d0CutOff_, 2))); // reduce weight for high ip tracks
198  continue; // usually is > 0.99
199  }
200  LogTrace("DAClusterizerinZ_vect") << t_z << ' ' << t_dz2 << ' ' << t_pi;
201  tks.addItemSorted(t_z, t_dz2, &(*it), t_pi);
202  }
203 
204  tks.extractRaw();
205 #ifdef DEBUG
206  if (DEBUGLEVEL > 0) {
207  std::cout << "Track count (Z) " << tks.getSize() << std::endl;
208  }
209 #endif
210 
211  return tks;
212 }
213 
214 namespace {
215  inline double Eik(double t_z, double k_z, double t_dz2) { return std::pow(t_z - k_z, 2) * t_dz2; }
216 } // namespace
217 
218 void DAClusterizerInZ_vect::set_vtx_range(double beta, track_t& gtracks, vertex_t& gvertices) const {
219  const unsigned int nv = gvertices.getSize();
220  const unsigned int nt = gtracks.getSize();
221 
222  if (nv == 0) {
223  edm::LogWarning("DAClusterizerinZ_vect") << "empty cluster list in set_vtx_range";
224  return;
225  }
226 
227  for (auto itrack = 0U; itrack < nt; ++itrack) {
228  double zrange = max(sel_zrange_ / sqrt(beta * gtracks.dz2[itrack]), zrange_min_);
229 
230  double zmin = gtracks.z[itrack] - zrange;
231  unsigned int kmin = min(nv - 1, gtracks.kmin[itrack]);
232  // find the smallest vertex_z that is larger than zmin
233  if (gvertices.z_ptr[kmin] > zmin) {
234  while ((kmin > 0) && (gvertices.z_ptr[kmin - 1] > zmin)) {
235  kmin--;
236  }
237  } else {
238  while ((kmin < (nv - 1)) && (gvertices.z_ptr[kmin] < zmin)) {
239  kmin++;
240  }
241  }
242 
243  double zmax = gtracks.z[itrack] + zrange;
244  unsigned int kmax = min(nv - 1, gtracks.kmax[itrack] - 1);
245  // note: kmax points to the last vertex in the range, while gtracks.kmax points to the entry BEHIND the last vertex
246  // find the largest vertex_z that is smaller than zmax
247  if (gvertices.z_ptr[kmax] < zmax) {
248  while ((kmax < (nv - 1)) && (gvertices.z_ptr[kmax + 1] < zmax)) {
249  kmax++;
250  }
251  } else {
252  while ((kmax > 0) && (gvertices.z_ptr[kmax] > zmax)) {
253  kmax--;
254  }
255  }
256 
257  if (kmin <= kmax) {
258  gtracks.kmin[itrack] = kmin;
259  gtracks.kmax[itrack] = kmax + 1;
260  } else {
261  gtracks.kmin[itrack] = max(0U, min(kmin, kmax));
262  gtracks.kmax[itrack] = min(nv, max(kmin, kmax) + 1);
263  }
264  }
265 }
266 
267 void DAClusterizerInZ_vect::clear_vtx_range(track_t& gtracks, vertex_t& gvertices) const {
268  const unsigned int nt = gtracks.getSize();
269  const unsigned int nv = gvertices.getSize();
270  for (auto itrack = 0U; itrack < nt; ++itrack) {
271  gtracks.kmin[itrack] = 0;
272  gtracks.kmax[itrack] = nv;
273  }
274 }
275 
276 double DAClusterizerInZ_vect::update(double beta, track_t& gtracks, vertex_t& gvertices, const double rho0) const {
277  //update weights and vertex positions
278  // mass constrained annealing without noise
279  // returns the maximum of changes of vertex positions
280  // identical to updateTC but without updating swE needed for Tc
281 
282  const unsigned int nt = gtracks.getSize();
283  const unsigned int nv = gvertices.getSize();
284 
285  //initialize sums
286  double sumpi = 0;
287 
288  // to return how much the prototype moved
289  double delta = 0;
290 
291  // intial value of a sum
292  double Z_init = 0;
293  // independpent of loop
294  if (rho0 > 0) {
295  Z_init = rho0 * local_exp(-beta * dzCutOff_ * dzCutOff_);
296  }
297 
298  // define kernels
299  auto kernel_calc_exp_arg_range = [beta](const unsigned int itrack,
300  track_t const& tracks,
301  vertex_t const& vertices,
302  const unsigned int kmin,
303  const unsigned int kmax) {
304  const double track_z = tracks.z_ptr[itrack];
305  const double botrack_dz2 = -beta * tracks.dz2_ptr[itrack];
306 
307  // auto-vectorized
308  for (unsigned int ivertex = kmin; ivertex < kmax; ++ivertex) {
309  auto mult_res = track_z - vertices.z_ptr[ivertex];
310  vertices.ei_cache_ptr[ivertex] = botrack_dz2 * (mult_res * mult_res);
311  }
312  };
313 
314  auto kernel_add_Z_range = [Z_init](
315  vertex_t const& vertices, const unsigned int kmin, const unsigned int kmax) -> double {
316  double ZTemp = Z_init;
317  for (unsigned int ivertex = kmin; ivertex < kmax; ++ivertex) {
318  ZTemp += vertices.pk_ptr[ivertex] * vertices.ei_ptr[ivertex];
319  }
320  return ZTemp;
321  };
322 
323  auto kernel_calc_normalization_range = [](const unsigned int track_num,
324  track_t& tks_vec,
325  vertex_t& y_vec,
326  const unsigned int kmin,
327  const unsigned int kmax) {
328  auto tmp_trk_pi = tks_vec.pi_ptr[track_num];
329  auto o_trk_Z_sum = 1. / tks_vec.Z_sum_ptr[track_num];
330  auto o_trk_dz2 = tks_vec.dz2_ptr[track_num];
331  auto tmp_trk_z = tks_vec.z_ptr[track_num];
332 
333  // auto-vectorized
334  for (unsigned int k = kmin; k < kmax; ++k) {
335  y_vec.se_ptr[k] += y_vec.ei_ptr[k] * (tmp_trk_pi * o_trk_Z_sum);
336  auto w = y_vec.pk_ptr[k] * y_vec.ei_ptr[k] * (tmp_trk_pi * o_trk_Z_sum * o_trk_dz2);
337  y_vec.sw_ptr[k] += w;
338  y_vec.swz_ptr[k] += w * tmp_trk_z;
339  }
340  };
341 
342  for (auto ivertex = 0U; ivertex < nv; ++ivertex) {
343  gvertices.se_ptr[ivertex] = 0.0;
344  gvertices.sw_ptr[ivertex] = 0.0;
345  gvertices.swz_ptr[ivertex] = 0.0;
346  }
347 
348  // loop over tracks
349  for (auto itrack = 0U; itrack < nt; ++itrack) {
350  unsigned int kmin = gtracks.kmin[itrack];
351  unsigned int kmax = gtracks.kmax[itrack];
352 
353 #ifdef DEBUG
354  assert((kmin < kmax) && (kmax <= nv));
355  assert(itrack < gtracks.Z_sum.size());
356 #endif
357 
358  kernel_calc_exp_arg_range(itrack, gtracks, gvertices, kmin, kmax);
359  local_exp_list_range(gvertices.ei_cache_ptr, gvertices.ei_ptr, kmin, kmax);
360  gtracks.Z_sum_ptr[itrack] = kernel_add_Z_range(gvertices, kmin, kmax);
361 
362  if (edm::isNotFinite(gtracks.Z_sum_ptr[itrack]))
363  gtracks.Z_sum_ptr[itrack] = 0.0;
364  // used in the next major loop to follow
365  sumpi += gtracks.pi_ptr[itrack];
366 
367  if (gtracks.Z_sum_ptr[itrack] > 1.e-100) {
368  kernel_calc_normalization_range(itrack, gtracks, gvertices, kmin, kmax);
369  }
370  }
371 
372  // now update z and pk
373  auto kernel_calc_z = [sumpi, nv](vertex_t& vertices) -> double {
374  double delta = 0;
375  // does not vectorize(?)
376  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
377  if (vertices.sw_ptr[ivertex] > 0) {
378  auto znew = vertices.swz_ptr[ivertex] / vertices.sw_ptr[ivertex];
379  delta = max(std::abs(vertices.z_ptr[ivertex] - znew), delta);
380  vertices.z_ptr[ivertex] = znew;
381  }
382  }
383 
384  auto osumpi = 1. / sumpi;
385  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex)
386  vertices.pk_ptr[ivertex] = vertices.pk_ptr[ivertex] * vertices.se_ptr[ivertex] * osumpi;
387 
388  return delta;
389  };
390 
391  delta = kernel_calc_z(gvertices);
392 
393  // return how much the prototypes moved
394  return delta;
395 }
396 
397 double DAClusterizerInZ_vect::updateTc(double beta, track_t& gtracks, vertex_t& gvertices, const double rho0) const {
398  // update weights and vertex positions and Tc input
399  // returns the squared sum of changes of vertex positions
400 
401  const unsigned int nt = gtracks.getSize();
402  const unsigned int nv = gvertices.getSize();
403 
404  //initialize sums
405  double sumpi = 0;
406 
407  // to return how much the prototype moved
408  double delta = 0;
409 
410  // independpent of loop
411  double Z_init = 0;
412  if (rho0 > 0) {
413  Z_init = rho0 * local_exp(-beta * dzCutOff_ * dzCutOff_); // cut-off
414  }
415 
416  // define kernels
417  auto kernel_calc_exp_arg_range = [beta](const unsigned int itrack,
418  track_t const& tracks,
419  vertex_t const& vertices,
420  const unsigned int kmin,
421  const unsigned int kmax) {
422  const double track_z = tracks.z_ptr[itrack];
423  const double botrack_dz2 = -beta * tracks.dz2_ptr[itrack];
424 
425  // auto-vectorized
426  for (unsigned int ivertex = kmin; ivertex < kmax; ++ivertex) {
427  auto mult_res = track_z - vertices.z_ptr[ivertex];
428  vertices.ei_cache_ptr[ivertex] = botrack_dz2 * (mult_res * mult_res);
429  }
430  };
431 
432  auto kernel_add_Z_range = [Z_init](
433  vertex_t const& vertices, const unsigned int kmin, const unsigned int kmax) -> double {
434  double ZTemp = Z_init;
435  for (unsigned int ivertex = kmin; ivertex < kmax; ++ivertex) {
436  ZTemp += vertices.pk_ptr[ivertex] * vertices.ei_ptr[ivertex];
437  }
438  return ZTemp;
439  };
440 
441  auto kernel_calc_normalization_range = [beta](const unsigned int track_num,
442  track_t& tks_vec,
443  vertex_t& y_vec,
444  const unsigned int kmin,
445  const unsigned int kmax) {
446  auto tmp_trk_pi = tks_vec.pi_ptr[track_num];
447  auto o_trk_Z_sum = 1. / tks_vec.Z_sum_ptr[track_num];
448  auto o_trk_dz2 = tks_vec.dz2_ptr[track_num];
449  auto tmp_trk_z = tks_vec.z_ptr[track_num];
450  auto obeta = -1. / beta;
451 
452  // auto-vectorized
453  for (unsigned int k = kmin; k < kmax; ++k) {
454  y_vec.se_ptr[k] += y_vec.ei_ptr[k] * (tmp_trk_pi * o_trk_Z_sum);
455  auto w = y_vec.pk_ptr[k] * y_vec.ei_ptr[k] * (tmp_trk_pi * o_trk_Z_sum * o_trk_dz2);
456  y_vec.sw_ptr[k] += w;
457  y_vec.swz_ptr[k] += w * tmp_trk_z;
458  y_vec.swE_ptr[k] += w * y_vec.ei_cache_ptr[k] * obeta;
459  }
460  };
461 
462  for (auto ivertex = 0U; ivertex < nv; ++ivertex) {
463  gvertices.se_ptr[ivertex] = 0.0;
464  gvertices.sw_ptr[ivertex] = 0.0;
465  gvertices.swz_ptr[ivertex] = 0.0;
466  gvertices.swE_ptr[ivertex] = 0.0;
467  }
468 
469  // loop over tracks
470  for (auto itrack = 0U; itrack < nt; ++itrack) {
471  unsigned int kmin = gtracks.kmin[itrack];
472  unsigned int kmax = gtracks.kmax[itrack];
473 
474  kernel_calc_exp_arg_range(itrack, gtracks, gvertices, kmin, kmax);
475  local_exp_list_range(gvertices.ei_cache_ptr, gvertices.ei_ptr, kmin, kmax);
476  gtracks.Z_sum_ptr[itrack] = kernel_add_Z_range(gvertices, kmin, kmax);
477 
478  if (edm::isNotFinite(gtracks.Z_sum_ptr[itrack]))
479  gtracks.Z_sum_ptr[itrack] = 0.0;
480  // used in the next major loop to follow
481  sumpi += gtracks.pi_ptr[itrack];
482 
483  if (gtracks.Z_sum_ptr[itrack] > 1.e-100) {
484  kernel_calc_normalization_range(itrack, gtracks, gvertices, kmin, kmax);
485  }
486  }
487 
488  // now update z and pk
489  auto kernel_calc_z = [sumpi, nv](vertex_t& vertices) -> double {
490  double delta = 0;
491  // does not vectorizes
492  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
493  if (vertices.sw_ptr[ivertex] > 0) {
494  auto znew = vertices.swz_ptr[ivertex] / vertices.sw_ptr[ivertex];
495  // prevents from vectorizing if
496  delta = max(std::abs(vertices.z_ptr[ivertex] - znew), delta);
497  vertices.z_ptr[ivertex] = znew;
498  }
499  }
500 
501  auto osumpi = 1. / sumpi;
502  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex)
503  vertices.pk_ptr[ivertex] = vertices.pk_ptr[ivertex] * vertices.se_ptr[ivertex] * osumpi;
504 
505  return delta;
506  };
507 
508  delta = kernel_calc_z(gvertices);
509 
510  // return how much the prototypes moved
511  return delta;
512 }
513 
514 double DAClusterizerInZ_vect::evalF(const double beta, track_t const& tks, vertex_t const& v) const {
515  // temporary : evaluate the original F
516  auto nt = tks.getSize();
517  auto nv = v.getSize();
518  double F = 0;
519  for (auto i = 0U; i < nt; i++) {
520  double Z = 0;
521  for (auto k = 0u; k < nv; k++) {
522  double Eik = (tks.z[k] - v.z[i]) * (tks.z[k] - v.z[i]) * tks.dz2[i];
523  if ((beta * Eik) < 30) {
524  Z += v.pk[k] * exp(-beta * Eik);
525  }
526  }
527  if (Z > 0) {
528  F += tks.pi[i] * log(Z);
529  }
530  }
531  std::cout << "F(full) = " << -F / beta << std::endl;
532  return -F / beta;
533 }
534 
536  double beta, track_t& tks, vertex_t& v, const double delta_max0, const double rho0) const {
537  unsigned int niter = 0;
538  double delta = 0;
539  double delta_max = delta_lowT_;
540 
541  if (convergence_mode_ == 0) {
542  delta_max = delta_max0;
543  } else if (convergence_mode_ == 1) {
544  delta_max = delta_lowT_ / sqrt(std::max(beta, 1.0));
545  }
546 
547  set_vtx_range(beta, tks, v);
548  double delta_sum_range = 0; // accumulate max(|delta-z|) as a lower bound
549  std::vector<double> z0 = v.z;
550 
551  while (niter++ < maxIterations_) {
552  delta = update(beta, tks, v, rho0);
553  delta_sum_range += delta;
554 
555  if (delta_sum_range > zrange_min_) {
556  for (unsigned int k = 0; k < v.getSize(); k++) {
557  if (std::abs(v.z[k] - z0[k]) > zrange_min_) {
558  set_vtx_range(beta, tks, v);
559  delta_sum_range = 0;
560  z0 = v.z;
561  break;
562  }
563  }
564  }
565 
566  if (delta < delta_max) {
567  break;
568  }
569  }
570 
571 #ifdef DEBUG
572  if (DEBUGLEVEL > 0) {
573  std::cout << "DAClusterizerInZ_vect.thermalize niter = " << niter << " at T = " << 1 / beta
574  << " nv = " << v.getSize() << std::endl;
575  if (DEBUGLEVEL > 2)
576  dump(beta, v, tks, 0);
577  }
578 #endif
579 
580  return niter;
581 }
582 
583 bool DAClusterizerInZ_vect::merge(vertex_t& y, track_t& tks, double& beta) const {
584  // merge clusters that collapsed or never separated,
585  // only merge if the estimated critical temperature of the merged vertex is below the current temperature
586  // return true if vertices were merged, false otherwise
587  const unsigned int nv = y.getSize();
588 
589  if (nv < 2)
590  return false;
591 
592  // merge the smallest distance clusters first
593  std::vector<std::pair<double, unsigned int> > critical;
594  for (unsigned int k = 0; (k + 1) < nv; k++) {
595  if (std::fabs(y.z_ptr[k + 1] - y.z_ptr[k]) < zmerge_) {
596  critical.push_back(make_pair(std::fabs(y.z_ptr[k + 1] - y.z_ptr[k]), k));
597  }
598  }
599  if (critical.empty())
600  return false;
601 
602  std::stable_sort(critical.begin(), critical.end(), std::less<std::pair<double, unsigned int> >());
603 
604  for (unsigned int ik = 0; ik < critical.size(); ik++) {
605  unsigned int k = critical[ik].second;
606  double rho = y.pk_ptr[k] + y.pk_ptr[k + 1];
607  double swE = y.swE_ptr[k] + y.swE_ptr[k + 1] -
608  y.pk_ptr[k] * y.pk_ptr[k + 1] / rho * std::pow(y.z_ptr[k + 1] - y.z_ptr[k], 2);
609  double Tc = 2 * swE / (y.sw_ptr[k] + y.sw_ptr[k + 1]);
610 
611  if (Tc * beta < 1) {
612 #ifdef DEBUG
613  assert((k + 1) < nv);
614  if (DEBUGLEVEL > 1) {
615  std::cout << "merging " << fixed << setprecision(4) << y.z_ptr[k + 1] << " and " << y.z_ptr[k]
616  << " Tc = " << Tc << " sw = " << y.sw_ptr[k] + y.sw_ptr[k + 1] << std::endl;
617  }
618 #endif
619 
620  if (rho > 0) {
621  y.z_ptr[k] = (y.pk_ptr[k] * y.z_ptr[k] + y.pk_ptr[k + 1] * y.z_ptr[k + 1]) / rho;
622  } else {
623  y.z_ptr[k] = 0.5 * (y.z_ptr[k] + y.z_ptr[k + 1]);
624  }
625  y.pk_ptr[k] = rho;
626  y.sw_ptr[k] += y.sw_ptr[k + 1];
627  y.swE_ptr[k] = swE;
628  y.removeItem(k + 1, tks);
629  set_vtx_range(beta, tks, y);
630  y.extractRaw();
631  return true;
632  }
633  }
634 
635  return false;
636 }
637 
638 bool DAClusterizerInZ_vect::purge(vertex_t& y, track_t& tks, double& rho0, const double beta) const {
639  // eliminate clusters with only one significant/unique track
640  const unsigned int nv = y.getSize();
641  const unsigned int nt = tks.getSize();
642 
643  if (nv < 2)
644  return false;
645 
646  double sumpmin = nt;
647  unsigned int k0 = nv;
648 
649  for (unsigned int k = 0; k < nv; k++) {
650  int nUnique = 0;
651  double sump = 0;
652 
653  double pmax = y.pk_ptr[k] / (y.pk_ptr[k] + rho0 * local_exp(-beta * dzCutOff_ * dzCutOff_));
654  for (unsigned int i = 0; i < nt; i++) {
655  //if (tks.tt[i]->track().pt() < 0.0) continue; // TEST count only pt>0.3 in nunique
656  if (tks.Z_sum_ptr[i] > 1.e-100) {
657  double p = y.pk_ptr[k] * local_exp(-beta * Eik(tks.z_ptr[i], y.z_ptr[k], tks.dz2_ptr[i])) / tks.Z_sum_ptr[i];
658  //double p = tks.pi_ptr[i] * y.pk_ptr[k] * local_exp(-beta * Eik(tks.z_ptr[i], y.z_ptr[k], tks.dz2_ptr[i])) / tks.Z_sum_ptr[i];
659  sump += p;
660  if ((p > uniquetrkweight_ * pmax) && (tks.pi_ptr[i] > 0)) {
661  nUnique++;
662  }
663  }
664  }
665 
666  if ((nUnique < 2) && (sump < sumpmin)) {
667  sumpmin = sump;
668  k0 = k;
669  }
670  }
671 
672  if (k0 != nv) {
673 #ifdef DEBUG
674  assert(k0 < y.getSize());
675  if (DEBUGLEVEL > 1) {
676  std::cout << "eliminating prototype at " << std::setw(10) << std::setprecision(4) << y.z_ptr[k0]
677  << " with sump=" << sumpmin << " rho*nt =" << y.pk_ptr[k0] * nt << endl;
678  }
679 #endif
680 
681  y.removeItem(k0, tks);
682  set_vtx_range(beta, tks, y);
683  return true;
684  } else {
685  return false;
686  }
687 }
688 
689 double DAClusterizerInZ_vect::beta0(double betamax, track_t const& tks, vertex_t const& y) const {
690  double T0 = 0; // max Tc for beta=0
691  // estimate critical temperature from beta=0 (T=inf)
692  const unsigned int nt = tks.getSize();
693  const unsigned int nv = y.getSize();
694 
695  for (unsigned int k = 0; k < nv; k++) {
696  // vertex fit at T=inf
697  double sumwz = 0;
698  double sumw = 0;
699  for (unsigned int i = 0; i < nt; i++) {
700  double w = tks.pi_ptr[i] * tks.dz2_ptr[i];
701  sumwz += w * tks.z_ptr[i];
702  sumw += w;
703  }
704 
705  y.z_ptr[k] = sumwz / sumw;
706 
707  // estimate Tcrit
708  double a = 0, b = 0;
709  for (unsigned int i = 0; i < nt; i++) {
710  double dx = tks.z_ptr[i] - y.z_ptr[k];
711  double w = tks.pi_ptr[i] * tks.dz2_ptr[i];
712  a += w * std::pow(dx, 2) * tks.dz2_ptr[i];
713  b += w;
714  }
715  double Tc = 2. * a / b; // the critical temperature of this vertex
716 
717  if (Tc > T0)
718  T0 = Tc;
719 
720  } // vertex loop (normally there should be only one vertex at beta=0)
721 
722 #ifdef DEBUG
723  if (DEBUGLEVEL > 0) {
724  std::cout << "DAClusterizerInZ_vect.beta0: Tc = " << T0 << std::endl;
725  int coolingsteps = 1 - int(std::log(T0 * betamax) / std::log(coolingFactor_));
726  std::cout << "DAClusterizerInZ_vect.beta0: nstep = " << coolingsteps << std::endl;
727  }
728 #endif
729 
730  if (T0 > 1. / betamax) {
731  int coolingsteps = 1 - int(std::log(T0 * betamax) / std::log(coolingFactor_));
732 
733  return betamax * std::pow(coolingFactor_, coolingsteps);
734  } else {
735  // ensure at least one annealing step
736  return betamax * coolingFactor_;
737  }
738 }
739 
740 bool DAClusterizerInZ_vect::split(const double beta, track_t& tks, vertex_t& y, double threshold) const {
741  // split only critical vertices (Tc >~ T=1/beta <==> beta*Tc>~1)
742  // an update must have been made just before doing this (same beta, no merging)
743  // returns true if at least one cluster was split
744 
745  constexpr double epsilon = 1e-3; // minimum split size
746  unsigned int nv = y.getSize();
747 
748  // avoid left-right biases by splitting highest Tc first
749 
750  std::vector<std::pair<double, unsigned int> > critical;
751  for (unsigned int k = 0; k < nv; k++) {
752  double Tc = 2 * y.swE_ptr[k] / y.sw_ptr[k];
753  if (beta * Tc > threshold) {
754  critical.push_back(make_pair(Tc, k));
755  }
756  }
757  if (critical.empty())
758  return false;
759 
760  std::stable_sort(critical.begin(), critical.end(), std::greater<std::pair<double, unsigned int> >());
761 
762  bool split = false;
763  const unsigned int nt = tks.getSize();
764 
765  for (unsigned int ic = 0; ic < critical.size(); ic++) {
766  unsigned int k = critical[ic].second;
767 
768  // estimate subcluster positions and weight
769  double p1 = 0, z1 = 0, w1 = 0;
770  double p2 = 0, z2 = 0, w2 = 0;
771  for (unsigned int i = 0; i < nt; i++) {
772  if (tks.Z_sum_ptr[i] > 1.e-100) {
773  // winner-takes-all, usually overestimates splitting
774  double tl = tks.z_ptr[i] < y.z_ptr[k] ? 1. : 0.;
775  double tr = 1. - tl;
776 
777  // soften it, especially at low T
778  double arg = (tks.z_ptr[i] - y.z_ptr[k]) * sqrt(beta * tks.dz2_ptr[i]);
779  if (std::fabs(arg) < 20) {
780  double t = local_exp(-arg);
781  tl = t / (t + 1.);
782  tr = 1 / (t + 1.);
783  }
784 
785  double p = y.pk_ptr[k] * tks.pi_ptr[i] * local_exp(-beta * Eik(tks.z_ptr[i], y.z_ptr[k], tks.dz2_ptr[i])) /
786  tks.Z_sum_ptr[i];
787  double w = p * tks.dz2_ptr[i];
788  p1 += p * tl;
789  z1 += w * tl * tks.z_ptr[i];
790  w1 += w * tl;
791  p2 += p * tr;
792  z2 += w * tr * tks.z_ptr[i];
793  w2 += w * tr;
794  }
795  }
796 
797  if (w1 > 0) {
798  z1 = z1 / w1;
799  } else {
800  z1 = y.z_ptr[k] - epsilon;
801  }
802  if (w2 > 0) {
803  z2 = z2 / w2;
804  } else {
805  z2 = y.z_ptr[k] + epsilon;
806  }
807 
808  // reduce split size if there is not enough room
809  if ((k > 0) && (z1 < (0.6 * y.z_ptr[k] + 0.4 * y.z_ptr[k - 1]))) {
810  z1 = 0.6 * y.z_ptr[k] + 0.4 * y.z_ptr[k - 1];
811  }
812  if ((k + 1 < nv) && (z2 > (0.6 * y.z_ptr[k] + 0.4 * y.z_ptr[k + 1]))) {
813  z2 = 0.6 * y.z_ptr[k] + 0.4 * y.z_ptr[k + 1];
814  }
815 
816 #ifdef DEBUG
817  assert(k < nv);
818  if (DEBUGLEVEL > 1) {
819  if (std::fabs(y.z_ptr[k] - zdumpcenter_) < zdumpwidth_) {
820  std::cout << " T= " << std::setw(8) << 1. / beta << " Tc= " << critical[ic].first << " splitting "
821  << std::fixed << std::setprecision(4) << y.z_ptr[k] << " --> " << z1 << "," << z2 << " [" << p1
822  << "," << p2 << "]";
823  if (std::fabs(z2 - z1) > epsilon) {
824  std::cout << std::endl;
825  } else {
826  std::cout << " rejected " << std::endl;
827  }
828  }
829  }
830 #endif
831 
832  // split if the new subclusters are significantly separated
833  if ((z2 - z1) > epsilon) {
834  split = true;
835  double pk1 = p1 * y.pk_ptr[k] / (p1 + p2);
836  double pk2 = p2 * y.pk_ptr[k] / (p1 + p2);
837  y.z_ptr[k] = z2;
838  y.pk_ptr[k] = pk2;
839  y.insertItem(k, z1, pk1, tks);
840  if (k == 0)
841  y.extractRaw();
842 
843  nv++;
844 
845  // adjust remaining pointers
846  for (unsigned int jc = ic; jc < critical.size(); jc++) {
847  if (critical[jc].second >= k) {
848  critical[jc].second++;
849  }
850  }
851  }
852  }
853 
854  return split;
855 }
856 
857 vector<TransientVertex> DAClusterizerInZ_vect::vertices(const vector<reco::TransientTrack>& tracks,
858  const int verbosity) const {
859  track_t&& tks = fill(tracks);
860  tks.extractRaw();
861 
862  unsigned int nt = tks.getSize();
863  double rho0 = 0.0; // start with no outlier rejection
864 
865  vector<TransientVertex> clusters;
866  if (tks.getSize() == 0)
867  return clusters;
868 
869  vertex_t y; // the vertex prototypes
870 
871  // initialize:single vertex at infinite temperature
872  y.addItem(0, 1.0);
873  clear_vtx_range(tks, y);
874 
875  // estimate first critical temperature
876  double beta = beta0(betamax_, tks, y);
877 #ifdef DEBUG
878  if (DEBUGLEVEL > 0)
879  std::cout << "Beta0 is " << beta << std::endl;
880 #endif
881 
882  thermalize(beta, tks, y, delta_highT_);
883 
884  // annealing loop, stop when T<Tmin (i.e. beta>1/Tmin)
885 
886  double betafreeze = betamax_ * sqrt(coolingFactor_);
887 
888  while (beta < betafreeze) {
889  updateTc(beta, tks, y, rho0);
890  while (merge(y, tks, beta)) {
891  updateTc(beta, tks, y, rho0);
892  }
893  split(beta, tks, y);
894 
895  beta = beta / coolingFactor_;
896  set_vtx_range(beta, tks, y);
897  thermalize(beta, tks, y, delta_highT_);
898  }
899 
900 #ifdef DEBUG
901  verify(y, tks);
902 
903  if (DEBUGLEVEL > 0) {
904  std::cout << "DAClusterizerInZ_vect::vertices :"
905  << "last round of splitting" << std::endl;
906  }
907 #endif
908 
909  set_vtx_range(beta, tks, y);
910  updateTc(beta, tks, y, rho0); // make sure Tc is up-to-date
911 
912  while (merge(y, tks, beta)) {
913  set_vtx_range(beta, tks, y);
914  updateTc(beta, tks, y, rho0);
915  }
916 
917  unsigned int ntry = 0;
918  double threshold = 1.0;
919  while (split(beta, tks, y, threshold) && (ntry++ < 10)) {
920  set_vtx_range(beta, tks, y);
921  thermalize(beta, tks, y, delta_highT_, 0.);
922  updateTc(beta, tks, y, rho0);
923  while (merge(y, tks, beta)) {
924  updateTc(beta, tks, y, rho0);
925  }
926 
927  // relax splitting a bit to reduce multiple split-merge cycles of the same cluster
928  threshold *= 1.1;
929  }
930 
931 #ifdef DEBUG
932  verify(y, tks);
933  if (DEBUGLEVEL > 0) {
934  std::cout << "DAClusterizerInZ_vect::vertices :"
935  << "turning on outlier rejection at T=" << 1 / beta << std::endl;
936  }
937 #endif
938 
939  // switch on outlier rejection at T=Tmin, doesn't do much at high PU
940  if (dzCutOff_ > 0) {
941  rho0 = 1. / nt; //1. / y.getSize();??
942  for (unsigned int a = 0; a < 5; a++) {
943  update(beta, tks, y, a * rho0 / 5.); // adiabatic turn-on
944  }
945  }
946 
947  thermalize(beta, tks, y, delta_lowT_, rho0);
948 
949 #ifdef DEBUG
950  verify(y, tks);
951  if (DEBUGLEVEL > 0) {
952  std::cout << "DAClusterizerInZ_vect::vertices :"
953  << "merging with outlier rejection at T=" << 1 / beta << std::endl;
954  }
955  if (DEBUGLEVEL > 2)
956  dump(beta, y, tks, 2);
957 #endif
958 
959  // merge again (some cluster split by outliers collapse here)
960  while (merge(y, tks, beta)) {
961  set_vtx_range(beta, tks, y);
962  update(beta, tks, y, rho0);
963  }
964 
965 #ifdef DEBUG
966  verify(y, tks);
967  if (DEBUGLEVEL > 0) {
968  std::cout << "DAClusterizerInZ_vect::vertices :"
969  << "after merging with outlier rejection at T=" << 1 / beta << std::endl;
970  }
971  if (DEBUGLEVEL > 2)
972  dump(beta, y, tks, 2);
973 #endif
974 
975  // go down to the purging temperature (if it is lower than tmin)
976  while (beta < betapurge_) {
977  beta = min(beta / coolingFactor_, betapurge_);
978  set_vtx_range(beta, tks, y);
979  thermalize(beta, tks, y, delta_lowT_, rho0);
980  }
981 
982 #ifdef DEBUG
983  verify(y, tks);
984  if (DEBUGLEVEL > 0) {
985  std::cout << "DAClusterizerInZ_vect::vertices :"
986  << "purging at T=" << 1 / beta << std::endl;
987  }
988 #endif
989 
990  // eliminate insigificant vertices, this is more restrictive at higher T
991  while (purge(y, tks, rho0, beta)) {
992  thermalize(beta, tks, y, delta_lowT_, rho0);
993  }
994 
995 #ifdef DEBUG
996  verify(y, tks);
997  if (DEBUGLEVEL > 0) {
998  std::cout << "DAClusterizerInZ_vect::vertices :"
999  << "last cooling T=" << 1 / beta << std::endl;
1000  }
1001 #endif
1002 
1003  // optionally cool some more without doing anything, to make the assignment harder
1004  while (beta < betastop_) {
1005  beta = min(beta / coolingFactor_, betastop_);
1006  thermalize(beta, tks, y, delta_lowT_, rho0);
1007  }
1008 
1009 #ifdef DEBUG
1010  verify(y, tks);
1011  if (DEBUGLEVEL > 0) {
1012  std::cout << "DAClusterizerInZ_vect::vertices :"
1013  << "stop cooling at T=" << 1 / beta << std::endl;
1014  }
1015  if (DEBUGLEVEL > 2)
1016  dump(beta, y, tks, 2);
1017 #endif
1018 
1019  // select significant tracks and use a TransientVertex as a container
1020  GlobalError dummyError(0.01, 0, 0.01, 0., 0., 0.01);
1021 
1022  // ensure correct normalization of probabilities, should makes double assignment reasonably impossible
1023  const unsigned int nv = y.getSize();
1024  for (unsigned int k = 0; k < nv; k++)
1025  if (edm::isNotFinite(y.pk_ptr[k]) || edm::isNotFinite(y.z_ptr[k])) {
1026  y.pk_ptr[k] = 0;
1027  y.z_ptr[k] = 0;
1028  }
1029 
1030  for (unsigned int i = 0; i < nt; i++) // initialize
1031  tks.Z_sum_ptr[i] = rho0 * local_exp(-beta * dzCutOff_ * dzCutOff_);
1032 
1033  // improve vectorization (does not require reduction ....)
1034  for (unsigned int k = 0; k < nv; k++) {
1035  for (unsigned int i = 0; i < nt; i++)
1036  tks.Z_sum_ptr[i] += y.pk_ptr[k] * local_exp(-beta * Eik(tks.z_ptr[i], y.z_ptr[k], tks.dz2_ptr[i]));
1037  }
1038 
1039  for (unsigned int k = 0; k < nv; k++) {
1040  GlobalPoint pos(0, 0, y.z_ptr[k]);
1041 
1042  vector<reco::TransientTrack> vertexTracks;
1043  for (unsigned int i = 0; i < nt; i++) {
1044  if (tks.Z_sum_ptr[i] > 1e-100) {
1045  double p = y.pk_ptr[k] * local_exp(-beta * Eik(tks.z_ptr[i], y.z_ptr[k], tks.dz2_ptr[i])) / tks.Z_sum_ptr[i];
1046  if ((tks.pi_ptr[i] > 0) && (p > mintrkweight_)) {
1047  vertexTracks.push_back(*(tks.tt[i]));
1048  tks.Z_sum_ptr[i] = 0; // setting Z=0 excludes double assignment
1049  }
1050  }
1051  }
1052  TransientVertex v(pos, dummyError, vertexTracks, 0);
1053  clusters.push_back(v);
1054  }
1055 
1056  return clusters;
1057 }
1058 
1059 vector<vector<reco::TransientTrack> > DAClusterizerInZ_vect::clusterize(
1060  const vector<reco::TransientTrack>& tracks) const {
1061  vector<vector<reco::TransientTrack> > clusters;
1062  vector<TransientVertex>&& pv = vertices(tracks);
1063 
1064 #ifdef DEBUG
1065  if (DEBUGLEVEL > 0) {
1066  std::cout << "###################################################" << endl;
1067  std::cout << "# vectorized DAClusterizerInZ_vect::clusterize nt=" << tracks.size() << endl;
1068  std::cout << "# DAClusterizerInZ_vect::clusterize pv.size=" << pv.size() << endl;
1069  std::cout << "###################################################" << endl;
1070  }
1071 #endif
1072 
1073  if (pv.empty()) {
1074  return clusters;
1075  }
1076 
1077  // fill into clusters and merge
1078  vector<reco::TransientTrack> aCluster = pv.begin()->originalTracks();
1079 
1080  for (auto k = pv.begin() + 1; k != pv.end(); k++) {
1081  if (std::abs(k->position().z() - (k - 1)->position().z()) > (2 * vertexSize_)) {
1082  // close a cluster
1083  if (aCluster.size() > 1) {
1084  clusters.push_back(aCluster);
1085  }
1086 #ifdef DEBUG
1087  else {
1088  std::cout << " one track cluster at " << k->position().z() << " suppressed" << std::endl;
1089  }
1090 #endif
1091  aCluster.clear();
1092  }
1093  for (unsigned int i = 0; i < k->originalTracks().size(); i++) {
1094  aCluster.push_back(k->originalTracks()[i]);
1095  }
1096  }
1097  clusters.emplace_back(std::move(aCluster));
1098 
1099  return clusters;
1100 }
1101 
1102 void DAClusterizerInZ_vect::dump(const double beta, const vertex_t& y, const track_t& tks, int verbosity) const {
1103 #ifdef DEBUG
1104  const unsigned int nv = y.getSize();
1105  const unsigned int nt = tks.getSize();
1106 
1107  std::vector<unsigned int> iz;
1108  for (unsigned int j = 0; j < nt; j++) {
1109  iz.push_back(j);
1110  }
1111  std::sort(iz.begin(), iz.end(), [tks](unsigned int a, unsigned int b) { return tks.z_ptr[a] < tks.z_ptr[b]; });
1112  std::cout << std::endl;
1113  std::cout << "-----DAClusterizerInZ::dump ----" << nv << " clusters " << std::endl;
1114  std::cout << " ";
1115  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1116  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) < zdumpwidth_) {
1117  std::cout << " " << setw(3) << ivertex << " ";
1118  }
1119  }
1120  std::cout << endl;
1121  std::cout << " z= ";
1122  std::cout << setprecision(4);
1123  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1124  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) < zdumpwidth_) {
1125  std::cout << setw(8) << fixed << y.z_ptr[ivertex];
1126  }
1127  }
1128  std::cout << endl
1129  << "T=" << setw(15) << 1. / beta << " Tmin =" << setw(10) << 1. / betamax_
1130  << " Tc= ";
1131  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1132  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) < zdumpwidth_) {
1133  double Tc = 2 * y.swE_ptr[ivertex] / y.sw_ptr[ivertex];
1134  std::cout << setw(8) << fixed << setprecision(1) << Tc;
1135  }
1136  }
1137  std::cout << endl;
1138 
1139  std::cout << " pk= ";
1140  double sumpk = 0;
1141  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1142  sumpk += y.pk_ptr[ivertex];
1143  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) > zdumpwidth_)
1144  continue;
1145  std::cout << setw(8) << setprecision(4) << fixed << y.pk_ptr[ivertex];
1146  }
1147  std::cout << endl;
1148 
1149  std::cout << " nt= ";
1150  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1151  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) > zdumpwidth_)
1152  continue;
1153  std::cout << setw(8) << setprecision(1) << fixed << y.pk_ptr[ivertex] * nt;
1154  }
1155  std::cout << endl;
1156 
1157  if (verbosity > 0) {
1158  double E = 0, F = 0;
1159  std::cout << endl;
1160  std::cout << "---- z +/- dz ip +/-dip pt phi eta weights ----" << endl;
1161  std::cout << setprecision(4);
1162  for (unsigned int i0 = 0; i0 < nt; i0++) {
1163  unsigned int i = iz[i0];
1164  if (tks.Z_sum_ptr[i] > 0) {
1165  F -= std::log(tks.Z_sum_ptr[i]) / beta;
1166  }
1167  double tz = tks.z_ptr[i];
1168 
1169  if (std::fabs(tz - zdumpcenter_) > zdumpwidth_)
1170  continue;
1171  std::cout << setw(4) << i << ")" << setw(8) << fixed << setprecision(4) << tz << " +/-" << setw(6)
1172  << sqrt(1. / tks.dz2_ptr[i]);
1173  if ((tks.tt[i] == nullptr)) {
1174  std::cout << " effective track ";
1175  } else {
1176  if (tks.tt[i]->track().quality(reco::TrackBase::highPurity)) {
1177  std::cout << " *";
1178  } else {
1179  std::cout << " ";
1180  }
1181  if (tks.tt[i]->track().hitPattern().hasValidHitInPixelLayer(PixelSubdetector::SubDetector::PixelBarrel, 1)) {
1182  std::cout << "+";
1183  } else {
1184  std::cout << "-";
1185  }
1186  std::cout << setw(1)
1187  << tks.tt[i]
1188  ->track()
1189  .hitPattern()
1190  .pixelBarrelLayersWithMeasurement(); // see DataFormats/TrackReco/interface/HitPattern.h
1191  std::cout << setw(1) << tks.tt[i]->track().hitPattern().pixelEndcapLayersWithMeasurement();
1192  std::cout << setw(1) << hex
1193  << tks.tt[i]->track().hitPattern().trackerLayersWithMeasurement() -
1194  tks.tt[i]->track().hitPattern().pixelLayersWithMeasurement()
1195  << dec;
1196  std::cout << "=" << setw(1) << hex
1197  << tks.tt[i]->track().hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS) << dec;
1198 
1199  Measurement1D IP = tks.tt[i]->stateAtBeamLine().transverseImpactParameter();
1200  std::cout << setw(8) << IP.value() << "+/-" << setw(6) << IP.error();
1201  std::cout << " " << setw(6) << setprecision(2) << tks.tt[i]->track().pt() * tks.tt[i]->track().charge();
1202  std::cout << " " << setw(5) << setprecision(2) << tks.tt[i]->track().phi() << " " << setw(5) << setprecision(2)
1203  << tks.tt[i]->track().eta();
1204  } // not a dummy track
1205 
1206  double sump = 0.;
1207  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1208  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) > zdumpwidth_)
1209  continue;
1210 
1211  if ((tks.pi_ptr[i] > 0) && (tks.Z_sum_ptr[i] > 0)) {
1212  //double p=pik(beta,tks[i],*k);
1213  double p =
1214  y.pk_ptr[ivertex] * exp(-beta * Eik(tks.z_ptr[i], y.z_ptr[ivertex], tks.dz2_ptr[i])) / tks.Z_sum_ptr[i];
1215  if (p > 0.0001) {
1216  std::cout << setw(8) << setprecision(3) << p;
1217  } else {
1218  std::cout << " . ";
1219  }
1220  E += p * Eik(tks.z_ptr[i], y.z_ptr[ivertex], tks.dz2_ptr[i]);
1221  sump += p;
1222  } else {
1223  std::cout << " ";
1224  }
1225  }
1226  std::cout << " ( " << std::setw(3) << tks.kmin[i] << "," << std::setw(3) << tks.kmax[i] - 1 << " ) ";
1227  std::cout << endl;
1228  }
1229  std::cout << " ";
1230  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1231  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) < zdumpwidth_) {
1232  std::cout << " " << setw(3) << ivertex << " ";
1233  }
1234  }
1235  std::cout << endl;
1236  std::cout << " z= ";
1237  std::cout << setprecision(4);
1238  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
1239  if (std::fabs(y.z_ptr[ivertex] - zdumpcenter_) < zdumpwidth_) {
1240  std::cout << setw(8) << fixed << y.z_ptr[ivertex];
1241  }
1242  }
1243  std::cout << endl;
1244  std::cout << endl
1245  << "T=" << 1 / beta << " E=" << E << " n=" << y.getSize() << " F= " << F << endl
1246  << "----------" << endl;
1247  }
1248 #endif
1249 }
HIPAlignmentAlgorithm_cfi.verbosity
verbosity
Definition: HIPAlignmentAlgorithm_cfi.py:7
reco::HitPattern::MISSING_OUTER_HITS
Definition: HitPattern.h:155
alignBH_cfg.fixed
fixed
Definition: alignBH_cfg.py:54
DAClusterizerInZ_vect::track_t::addItemSorted
void addItemSorted(double new_z, double new_dz2, const reco::TransientTrack *new_tt, double new_pi)
Definition: DAClusterizerInZ_vect.h:36
DAClusterizerInZ_vect::fill
track_t fill(const std::vector< reco::TransientTrack > &tracks) const
Definition: DAClusterizerInZ_vect.cc:173
PDWG_EXOHSCP_cff.tracks
tracks
Definition: PDWG_EXOHSCP_cff.py:28
Measurement1D
Definition: Measurement1D.h:11
w2
common ppss p3p6s2 common epss epspn46 common const1 w2
Definition: inclppp.h:1
mps_fire.i
i
Definition: mps_fire.py:355
pwdgSkimBPark_cfi.beamSpot
beamSpot
Definition: pwdgSkimBPark_cfi.py:5
DAClusterizerInZ_vect::vertices
std::vector< TransientVertex > vertices(const std::vector< reco::TransientTrack > &tracks, const int verbosity=0) const
Definition: DAClusterizerInZ_vect.cc:857
MessageLogger.h
DAClusterizerInZ_vect.h
TkClusParameters_cff.zrange
zrange
Definition: TkClusParameters_cff.py:7
DAClusterizerInZ_vect::vertex_t::ei_cache_ptr
double *__restrict__ ei_cache_ptr
Definition: DAClusterizerInZ_vect.h:196
reco::ParticleMasses::k0
const double k0
Definition: ParticleMasses.h:7
edm::isNotFinite
constexpr bool isNotFinite(T x)
Definition: isFinite.h:9
nt
int nt
Definition: AMPTWrapper.h:42
min
T min(T a, T b)
Definition: MathUtil.h:58
zMuMuMuonUserData.beta
beta
Definition: zMuMuMuonUserData.py:10
AlCaHLTBitMon_ParallelJobs.p
p
Definition: AlCaHLTBitMon_ParallelJobs.py:153
DAClusterizerInZ_vect::thermalize
unsigned int thermalize(double beta, track_t &gtracks, vertex_t &gvertices, const double delta_max, const double rho0=0.) const
Definition: DAClusterizerInZ_vect.cc:535
gather_cfg.cout
cout
Definition: gather_cfg.py:144
pos
Definition: PixelAliasList.h:18
AlignmentPI::t_z
Definition: AlignmentPayloadInspectorHelper.h:36
Measurement1D.h
DAClusterizerInZ_vect::vertex_t::sw_ptr
double *__restrict__ sw_ptr
Definition: DAClusterizerInZ_vect.h:198
DAClusterizerInZ_vect::vertex_t::swz_ptr
double *__restrict__ swz_ptr
Definition: DAClusterizerInZ_vect.h:199
DAClusterizerInZ_vect::DAClusterizerInZ_vect
DAClusterizerInZ_vect(const edm::ParameterSet &conf)
Definition: DAClusterizerInZ_vect.cc:22
cms::cuda::assert
assert(be >=bs)
edm::second
U second(std::pair< T, U > const &p)
Definition: ParameterSet.cc:215
DAClusterizerInZ_vect::track_t::tt
std::vector< const reco::TransientTrack * > tt
Definition: DAClusterizerInZ_vect.h:79
edm::ParameterSet::getUntrackedParameter
T getUntrackedParameter(std::string const &, T const &) const
DAClusterizerInZ_vect::set_vtx_range
void set_vtx_range(double beta, track_t &gtracks, vertex_t &gvertices) const
Definition: DAClusterizerInZ_vect.cc:218
cms::dd::split
std::vector< std::string_view > split(std::string_view, const char *)
findQualityFiles.v
v
Definition: findQualityFiles.py:179
DAClusterizerInZ_vect::track_t::extractRaw
void extractRaw()
Definition: DAClusterizerInZ_vect.h:60
DAClusterizerInZ_vect::verify
void verify(const vertex_t &v, const track_t &tks, unsigned int nv=999999, unsigned int nt=999999) const
Definition: DAClusterizerInZ_vect.cc:108
DAClusterizerInZ_vect::track_t::pi_ptr
double *__restrict__ pi_ptr
Definition: DAClusterizerInZ_vect.h:71
SiStripMonitorCluster_cfi.zmin
zmin
Definition: SiStripMonitorCluster_cfi.py:200
DAClusterizerInZ_vect::track_t::kmax
std::vector< unsigned int > kmax
Definition: DAClusterizerInZ_vect.h:78
DAClusterizerInZ_vect::track_t::kmin
std::vector< unsigned int > kmin
Definition: DAClusterizerInZ_vect.h:77
geometryDiff.epsilon
int epsilon
Definition: geometryDiff.py:26
DAClusterizerInZ_vect::vertex_t::se_ptr
double *__restrict__ se_ptr
Definition: DAClusterizerInZ_vect.h:200
DAClusterizerInZ_vect::track_t::Z_sum_ptr
double *__restrict__ Z_sum_ptr
Definition: DAClusterizerInZ_vect.h:70
F
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:163
testProducerWithPsetDescEmpty_cfi.z2
z2
Definition: testProducerWithPsetDescEmpty_cfi.py:41
DAClusterizerInZ_vect::split
bool split(const double beta, track_t &t, vertex_t &y, double threshold=1.) const
Definition: DAClusterizerInZ_vect.cc:740
DAClusterizerInZ_vect::vertex_t::z_ptr
double *__restrict__ z_ptr
Definition: DAClusterizerInZ_vect.h:193
GeomDetEnumerators::PixelBarrel
Definition: GeomDetEnumerators.h:11
DAClusterizerInZ_vect::update
double update(double beta, track_t &gtracks, vertex_t &gvertices, const double rho0=0) const
Definition: DAClusterizerInZ_vect.cc:276
DAClusterizerInZ_vect::vertex_t::ei_ptr
double *__restrict__ ei_ptr
Definition: DAClusterizerInZ_vect.h:197
SiStripMonitorCluster_cfi.zmax
zmax
Definition: SiStripMonitorCluster_cfi.py:201
w
const double w
Definition: UKUtility.cc:23
mathSSE::sqrt
T sqrt(T t)
Definition: SSEVec.h:19
reco::BeamSpot
Definition: BeamSpot.h:21
p2
double p2[4]
Definition: TauolaWrapper.h:90
beamspot
Definition: BeamSpotWrite2Txt.h:8
HLTMuonOfflineAnalyzer_cfi.z0
z0
Definition: HLTMuonOfflineAnalyzer_cfi.py:98
dqmdumpme.k
k
Definition: dqmdumpme.py:60
DAClusterizerInZ_vect::dump
void dump(const double beta, const vertex_t &y, const track_t &tks, const int verbosity=0) const
Definition: DAClusterizerInZ_vect.cc:1102
Point3DBase< float, GlobalTag >
OrderedSet.t
t
Definition: OrderedSet.py:90
b
double b
Definition: hdecay.h:118
DAClusterizerInZ_vect::updateTc
double updateTc(double beta, track_t &gtracks, vertex_t &gvertices, const double rho0=0) const
Definition: DAClusterizerInZ_vect.cc:397
mitigatedMETSequence_cff.U
U
Definition: mitigatedMETSequence_cff.py:36
DAClusterizerInZ_vect::beta0
double beta0(const double betamax, track_t const &tks, vertex_t const &y) const
Definition: DAClusterizerInZ_vect.cc:689
DAClusterizerInZ_vect::track_t
Definition: DAClusterizerInZ_vect.h:23
edm::LogWarning
Definition: MessageLogger.h:141
bsc_activity_cfg.clusters
clusters
Definition: bsc_activity_cfg.py:36
DAClusterizerInZ_vect::merge
bool merge(vertex_t &y, track_t &tks, double &beta) const
Definition: DAClusterizerInZ_vect.cc:583
listHistos.IP
IP
Definition: listHistos.py:76
ntuplemaker.fill
fill
Definition: ntuplemaker.py:304
DAClusterizerInZ_vect::track_t::dz2_ptr
double *__restrict__ dz2_ptr
Definition: DAClusterizerInZ_vect.h:68
edm::ParameterSet
Definition: ParameterSet.h:36
DAClusterizerInZ_vect::track_t::z
std::vector< double > z
Definition: DAClusterizerInZ_vect.h:73
a
double a
Definition: hdecay.h:119
SiStripPI::max
Definition: SiStripPayloadInspectorHelper.h:169
dumpMFGeometry_cfg.delta
delta
Definition: dumpMFGeometry_cfg.py:25
position
static int position[264][3]
Definition: ReadPGInfo.cc:289
FrontierConditions_GlobalTag_cff.dump
dump
Definition: FrontierConditions_GlobalTag_cff.py:12
DAClusterizerInZ_vect::evalF
double evalF(const double beta, track_t const &tks, vertex_t const &v) const
Definition: DAClusterizerInZ_vect.cc:514
createfilelist.int
int
Definition: createfilelist.py:10
DAClusterizerInZ_vect::vertex_t::getSize
unsigned int getSize() const
Definition: DAClusterizerInZ_vect.h:94
MetAnalyzer.pv
def pv(vc)
Definition: MetAnalyzer.py:7
DAClusterizerInZ_vect::track_t::getSize
unsigned int getSize() const
Definition: DAClusterizerInZ_vect.h:57
DAClusterizerInZ_vect::track_t::dz2
std::vector< double > dz2
Definition: DAClusterizerInZ_vect.h:74
hlt_jetmet_dqm_QT_fromfile_cfg.critical
critical
Definition: hlt_jetmet_dqm_QT_fromfile_cfg.py:109
DOFs::Z
Definition: AlignPCLThresholdsWriter.cc:37
HLT_2018_cff.Tmin
Tmin
Definition: HLT_2018_cff.py:33385
p1
double p1[4]
Definition: TauolaWrapper.h:89
GlobalErrorBase< double, ErrorMatrixTag >
DAClusterizerInZ_vect::clear_vtx_range
void clear_vtx_range(track_t &gtracks, vertex_t &gvertices) const
Definition: DAClusterizerInZ_vect.cc:267
TransientVertex
Definition: TransientVertex.h:18
DAClusterizerInZ_vect::clusterize
std::vector< std::vector< reco::TransientTrack > > clusterize(const std::vector< reco::TransientTrack > &tracks) const override
Definition: DAClusterizerInZ_vect.cc:1059
DAClusterizerInZ_vect::track_t::pi
std::vector< double > pi
Definition: DAClusterizerInZ_vect.h:76
edm::ParameterSet::getParameter
T getParameter(std::string const &) const
DAClusterizerInZ_vect::track_t::z_ptr
double *__restrict__ z_ptr
Definition: DAClusterizerInZ_vect.h:67
eostools.move
def move(src, dest)
Definition: eostools.py:511
std
Definition: JetResolutionObject.h:76
isFinite.h
DAClusterizerInZ_vect::purge
bool purge(vertex_t &, track_t &, double &, const double) const
Definition: DAClusterizerInZ_vect.cc:638
VertexException.h
dqm-mbProfile.log
log
Definition: dqm-mbProfile.py:17
HLT_2018_cff.Tpurge
Tpurge
Definition: HLT_2018_cff.py:33384
funct::arg
A arg
Definition: Factorize.h:36
funct::pow
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:30
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
LogTrace
#define LogTrace(id)
Definition: MessageLogger.h:671
DAClusterizerInZ_vect::vertex_t::swE_ptr
double *__restrict__ swE_ptr
Definition: DAClusterizerInZ_vect.h:201
dqmiolumiharvest.j
j
Definition: dqmiolumiharvest.py:66
JetChargeProducer_cfi.exp
exp
Definition: JetChargeProducer_cfi.py:6
remoteMonitoring_LED_IterMethod_cfg.threshold
threshold
Definition: remoteMonitoring_LED_IterMethod_cfg.py:426
MatrixUtil.merge
def merge(dictlist, TELL=False)
Definition: MatrixUtil.py:194
HLT_2018_cff.Tstop
Tstop
Definition: HLT_2018_cff.py:33379
HLT_2018_cff.atIP
atIP
Definition: HLT_2018_cff.py:44407
TauDecayModes.dec
dec
Definition: TauDecayModes.py:143
PVValHelper::dx
Definition: PVValidationHelpers.h:48
DAClusterizerInZ_vect::vertex_t
Definition: DAClusterizerInZ_vect.h:82
DAClusterizerInZ_vect::track_t::Z_sum
std::vector< double > Z_sum
Definition: DAClusterizerInZ_vect.h:75
update
#define update(a, b)
Definition: TrackClassifier.cc:10
pwdgSkimBPark_cfi.vertices
vertices
Definition: pwdgSkimBPark_cfi.py:7
MillePedeFileConverter_cfg.e
e
Definition: MillePedeFileConverter_cfg.py:37
reco::TrackBase::highPurity
Definition: TrackBase.h:154