CMS 3D CMS Logo

DAClusterizerInZT_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 using namespace std;
14 //#define VI_DEBUG
15 
17 
18  // hardcoded parameters
19  maxIterations_ = 100;
20  mintrkweight_ = 0.5; // conf.getParameter<double>("mintrkweight");
21 
22 
23  // configurable debug outptut debug output
24  verbose_ = conf.getUntrackedParameter<bool> ("verbose", false);
25  zdumpcenter_ = conf.getUntrackedParameter<double> ("zdumpcenter", 0.);
26  zdumpwidth_ = conf.getUntrackedParameter<double> ("zdumpwidth", 20.);
27 
28  // configurable parameters
29  double minT = conf.getParameter<double> ("Tmin");
30  double purgeT = conf.getParameter<double> ("Tpurge");
31  double stopT = conf.getParameter<double> ("Tstop");
32  vertexSize_ = conf.getParameter<double> ("vertexSize");
33  vertexSizeTime_ = conf.getParameter<double> ("vertexSizeTime");
34  coolingFactor_ = conf.getParameter<double> ("coolingFactor");
35  useTc_=true;
36  if(coolingFactor_<0){
37  coolingFactor_=-coolingFactor_;
38  useTc_=false;
39  }
40  d0CutOff_ = conf.getParameter<double> ("d0CutOff");
41  dzCutOff_ = conf.getParameter<double> ("dzCutOff");
42  dtCutOff_ = conf.getParameter<double> ("dtCutOff");
43  uniquetrkweight_ = conf.getParameter<double>("uniquetrkweight");
44  zmerge_ = conf.getParameter<double>("zmerge");
45  tmerge_ = conf.getParameter<double>("tmerge");
46 
47 #ifdef VI_DEBUG
48  if(verbose_){
49  std::cout << "DAClusterizerinZT_vect: mintrkweight = " << mintrkweight_ << std::endl;
50  std::cout << "DAClusterizerinZT_vect: uniquetrkweight = " << uniquetrkweight_ << std::endl;
51  std::cout << "DAClusterizerinZT_vect: zmerge = " << zmerge_ << std::endl;
52  std::cout << "DAClusterizerinZT_vect: tmerge = " << tmerge_ << std::endl;
53  std::cout << "DAClusterizerinZT_vect: Tmin = " << minT << std::endl;
54  std::cout << "DAClusterizerinZT_vect: Tpurge = " << purgeT << std::endl;
55  std::cout << "DAClusterizerinZT_vect: Tstop = " << stopT << std::endl;
56  std::cout << "DAClusterizerinZT_vect: vertexSize = " << vertexSize_ << std::endl;
57  std::cout << "DAClusterizerinZT_vect: vertexSizeTime = " << vertexSizeTime_ << std::endl;
58  std::cout << "DAClusterizerinZT_vect: coolingFactor = " << coolingFactor_ << std::endl;
59  std::cout << "DAClusterizerinZT_vect: d0CutOff = " << d0CutOff_ << std::endl;
60  std::cout << "DAClusterizerinZT_vect: dzCutOff = " << dzCutOff_ << std::endl;
61  std::cout << "DAClusterizerinZT_vect: dtCutoff = " << dtCutOff_ << std::endl;
62  }
63 #endif
64 
65 
66  if (minT == 0) {
67  edm::LogWarning("DAClusterizerinZT_vectorized") << "DAClusterizerInZT: invalid Tmin" << minT
68  << " reset do default " << 1. / betamax_;
69  } else {
70  betamax_ = 1. / minT;
71  }
72 
73 
74  if ((purgeT > minT) || (purgeT == 0)) {
75  edm::LogWarning("DAClusterizerinZT_vectorized") << "DAClusterizerInZT: invalid Tpurge" << purgeT
76  << " set to " << minT;
77  purgeT = minT;
78  }
79  betapurge_ = 1./purgeT;
80 
81 
82  if ((stopT > purgeT) || (stopT == 0)) {
83  edm::LogWarning("DAClusterizerinZT_vectorized") << "DAClusterizerInZT: invalid Tstop" << stopT
84  << " set to " << max(1., purgeT);
85  stopT = max(1., purgeT) ;
86  }
87  betastop_ = 1./stopT;
88 
89 }
90 
91 
92 namespace {
93  inline double local_exp( double const& inp) {
94  return vdt::fast_exp( inp );
95  }
96 
97  inline void local_exp_list( double const *arg_inp,
98  double *arg_out,
99  const unsigned arg_arr_size) {
100  for(unsigned i=0; i!=arg_arr_size; ++i ) arg_out[i]=vdt::fast_exp(arg_inp[i]);
101  }
102 
103 }
104 
105 //todo: use r-value possibility of c++11 here
107 DAClusterizerInZT_vect::fill(const vector<reco::TransientTrack> & tracks) const {
108 
109  // prepare track data for clustering
110  track_t tks;
111  for( const auto& tk : tracks ) {
112  if (!tk.isValid()) continue;
113  double t_pi=1.;
114  double t_z = tk.stateAtBeamLine().trackStateAtPCA().position().z();
115  double t_t = tk.timeExt();
116  if (std::fabs(t_z) > 1000.) continue;
117  auto const & t_mom = tk.stateAtBeamLine().trackStateAtPCA().momentum();
118  // get the beam-spot
119  reco::BeamSpot beamspot = tk.stateAtBeamLine().beamSpot();
120  double t_dz2 =
121  std::pow(tk.track().dzError(), 2) // track errror
122  + (std::pow(beamspot.BeamWidthX()*t_mom.x(),2)+std::pow(beamspot.BeamWidthY()*t_mom.y(),2))*std::pow(t_mom.z(),2)/std::pow(t_mom.perp2(),2) // beam spot width
123  + std::pow(vertexSize_, 2); // intrinsic vertex size, safer for outliers and short lived decays
124  t_dz2 = 1./ t_dz2;
125  if (edm::isNotFinite(t_dz2) || t_dz2 < std::numeric_limits<double>::min() ) continue;
126 
127 
128  double t_dt2 =std::pow(tk.dtErrorExt(),2.) + std::pow(vertexSizeTime_,2.); // the ~injected~ timing error, need to add a small minimum vertex size in time
129  if (tk.dtErrorExt()>0.3){
130  t_dt2 = 0; // tracks with no time measurement
131  }else{
132  t_dt2 = 1./t_dt2;
134  }
135 
136 
137  if (d0CutOff_ > 0) {
139  tk.stateAtBeamLine().transverseImpactParameter();// error contains beamspot
140  t_pi = 1. / (1. + local_exp(std::pow(atIP.value() / atIP.error(), 2) - std::pow(d0CutOff_, 2))); // reduce weight for high ip tracks
141  if (edm::isNotFinite(t_pi) || t_pi < std::numeric_limits<double>::epsilon()) continue; // usually is > 0.99
142  }
143  LogTrace("DAClusterizerinZT_vectorized") << t_z << ' ' << t_t <<' '<< t_dz2 << ' ' << t_dt2 <<' '<< t_pi;
144  tks.addItem(t_z, t_t, t_dz2, t_dt2, &tk, t_pi);
145  }
146  tks.extractRaw();
147 
148 #ifdef VI_DEBUG
149  if (verbose_) {
150  std::cout << "Track count " << tks.getSize() << std::endl;
151  }
152 #endif
153 
154  return tks;
155 }
156 
157 
158 namespace {
159  inline
160  double Eik(double t_z, double k_z, double t_dz2, double t_t, double k_t, double t_dt2) {
161  return std::pow(t_z - k_z, 2) * t_dz2 + std::pow(t_t - k_t,2) * t_dt2;
162  }
163 }
164 
165 double DAClusterizerInZT_vect::update(double beta, track_t & gtracks,
166  vertex_t & gvertices, bool useRho0, const double & rho0) const {
167 
168  //update weights and vertex positions
169  // mass constrained annealing without noise
170  // returns the squared sum of changes of vertex positions
171 
172  const unsigned int nt = gtracks.getSize();
173  const unsigned int nv = gvertices.getSize();
174 
175  //initialize sums
176  double sumpi = 0.;
177 
178  // to return how much the prototype moved
179  double delta = 0.;
180 
181 
182  // intial value of a sum
183  double Z_init = 0;
184  // independpent of loop
185  if ( useRho0 )
186  {
187  Z_init = rho0 * local_exp(-beta * dzCutOff_ * dzCutOff_); // cut-off
188  }
189 
190  // define kernels
191  auto kernel_calc_exp_arg = [ beta, nv ] ( const unsigned int itrack,
192  track_t const& tracks,
193  vertex_t const& vertices ) {
194 
195  const auto track_z = tracks.z_[itrack];
196  const auto track_t = tracks.t_[itrack];
197  const auto botrack_dz2 = -beta*tracks.dz2_[itrack];
198  const auto botrack_dt2 = -beta*tracks.dt2_[itrack];
199 
200  // auto-vectorized
201  for ( unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
202  const auto mult_resz = track_z - vertices.z_[ivertex];
203  const auto mult_rest = track_t - vertices.t_[ivertex];
204  vertices.ei_cache_[ivertex] = botrack_dz2 * ( mult_resz * mult_resz ) + botrack_dt2 * ( mult_rest * mult_rest );
205  }
206  };
207 
208  auto kernel_add_Z = [ nv, Z_init ] (vertex_t const& vertices) -> double
209  {
210  double ZTemp = Z_init;
211  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex) {
212  ZTemp += vertices.pk_[ivertex] * vertices.ei_[ivertex];
213  }
214  return ZTemp;
215  };
216 
217  auto kernel_calc_normalization = [ beta, nv ] (const unsigned int track_num,
218  track_t & tks_vec,
219  vertex_t & y_vec ) {
220  auto tmp_trk_pi = tks_vec.pi_[track_num];
221  auto o_trk_Z_sum = 1./tks_vec.Z_sum_[track_num];
222  auto o_trk_err_z = tks_vec.dz2_[track_num];
223  auto o_trk_err_t = tks_vec.dt2_[track_num];
224  auto tmp_trk_z = tks_vec.z_[track_num];
225  auto tmp_trk_t = tks_vec.t_[track_num];
226 
227 
228  // auto-vectorized
229  for (unsigned int k = 0; k < nv; ++k) {
230  // parens are important for numerical stability
231  y_vec.se_[k] += tmp_trk_pi*( y_vec.ei_[k] * o_trk_Z_sum );
232  const auto w = tmp_trk_pi * (y_vec.pk_[k] * y_vec.ei_[k] * o_trk_Z_sum); // p_{ik}
233  const auto wz = w * o_trk_err_z;
234  const auto wt = w * o_trk_err_t;
235  y_vec.nuz_[k] += wz;
236  y_vec.nut_[k] += wt;
237  y_vec.swz_[k] += wz * tmp_trk_z;
238  y_vec.swt_[k] += wt * tmp_trk_t;
239  /* this is really only needed when we want to get Tc too, mayb better to do it elsewhere? */
240  const auto dsz = (tmp_trk_z - y_vec.z[k]) * o_trk_err_z;
241  const auto dst = (tmp_trk_t - y_vec.t[k]) * o_trk_err_t;
242  y_vec.szz_[k] += w * dsz * dsz;
243  y_vec.stt_[k] += w * dst * dst;
244  y_vec.szt_[k] += w * dsz * dst;
245  }
246  };
247 
248 
249  for (auto ivertex = 0U; ivertex < nv; ++ivertex) {
250  gvertices.se_[ivertex] = 0.0;
251  gvertices.nuz_[ivertex] = 0.0;
252  gvertices.nut_[ivertex] = 0.0;
253  gvertices.swz_[ivertex] = 0.0;
254  gvertices.swt_[ivertex] = 0.0;
255  gvertices.szz_[ivertex] = 0.0;
256  gvertices.stt_[ivertex] = 0.0;
257  gvertices.szt_[ivertex] = 0.0;
258  }
259 
260 
261  // loop over tracks
262  for (auto itrack = 0U; itrack < nt; ++itrack) {
263  kernel_calc_exp_arg(itrack, gtracks, gvertices);
264  local_exp_list(gvertices.ei_cache_, gvertices.ei_, nv);
265 
266  gtracks.Z_sum_[itrack] = kernel_add_Z(gvertices);
267  if (edm::isNotFinite(gtracks.Z_sum_[itrack])) gtracks.Z_sum_[itrack] = 0.0;
268  // used in the next major loop to follow
269  sumpi += gtracks.pi_[itrack];
270 
271  if (gtracks.Z_sum_[itrack] > 1.e-100){
272  kernel_calc_normalization(itrack, gtracks, gvertices);
273  }
274  }
275 
276  // now update z, t, and pk
277  auto kernel_calc_zt = [ sumpi, nv, this, useRho0 ] (vertex_t & vertices ) -> double {
278 
279  double delta=0;
280 
281  // does not vectorizes
282  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex ) {
283 
284  if (vertices.nuz_[ivertex] > 0.) {
285  auto znew = vertices.swz_[ ivertex ] / vertices.nuz_[ ivertex ];
286  // prevents from vectorizing if
287  delta += std::pow( vertices.z_[ ivertex ] - znew, 2 );
288  vertices.z_[ ivertex ] = znew;
289  }
290 
291  if(vertices.nut_[ivertex] > 0.) {
292  auto tnew = vertices.swt_[ ivertex ] / vertices.nut_[ ivertex ];
293  // prevents from vectorizing if
294  delta += std::pow( vertices.t_[ ivertex ] - tnew, 2 );
295  vertices.t_[ ivertex ] = tnew;
296  }
297 
298 #ifdef VI_DEBUG
299  else {
300  edm::LogInfo("sumw") << "invalid sum of weights in fit: " << endl;//vertices.sw_[ivertex] << endl;
301  if (this->verbose_) {
302  std::cout << " a cluster melted away ? pk=" << vertices.pk_[ ivertex ] << " sumw="
303  << /*vertices.sw_[ivertex] << */ endl;
304  }
305  }
306 #endif
307  }
308 
309  auto osumpi = 1./sumpi;
310  for (unsigned int ivertex = 0; ivertex < nv; ++ivertex )
311  vertices.pk_[ ivertex ] = vertices.pk_[ ivertex ] * vertices.se_[ ivertex ] * osumpi;
312 
313  return delta;
314  };
315 
316  delta += kernel_calc_zt(gvertices);
317 
318  // return how much the prototypes moved
319  return delta;
320 }
321 
322 
323 
324 
325 
326 
328  const unsigned int nv = y.getSize();
329 
330  if (nv < 2) return;
331 
332 
333  bool reordering = true;
334  bool modified = false;
335 
336  while(reordering){
337  reordering = false;
338  for (unsigned int k = 0; (k + 1) < nv; k++) {
339  if ( y.z[k + 1] < y.z[k] ) {
340  auto ztemp = y.z[k]; y.z[k] = y.z[k+1]; y.z[k+1] = ztemp;
341  auto ttemp = y.t[k]; y.t[k] = y.t[k+1]; y.t[k+1] = ttemp;
342  auto ptemp = y.pk[k]; y.pk[k] = y.pk[k+1]; y.pk[k+1] = ptemp;
343  reordering = true;
344  }
345  }
346  modified |= reordering;
347  }
348 
349  if( modified ) y.extractRaw();
350 }
351 
352 
353 
354 bool DAClusterizerInZT_vect::find_nearest( double z, double t, vertex_t & y, unsigned int & k_min, double dz, double dt)const{
355  // find the cluster nearest to (z,t)
356  // distance measure is delta = (delta_z / dz )**2 + (delta_t/ d_t)**2
357  // assumes that clusters are ordered n z
358  // return value is false if o neighbour with distance < 1 is found
359 
360  unsigned int nv = y.getSize();
361 
362  // find nearest in z, binary search later
363  unsigned int k = 0;
364  for(unsigned int k0 = 1; k0 < nv; k0++){
365  if (std::abs( y.z_[k0]-z ) < std::abs( y.z_[k]-z )){
366  k = k0;
367  }
368  }
369 
370  double delta_min = 1.;
371 
372  //search left
373  unsigned int k1 = k;
374  while( ( k1 > 0) && ((y.z[k] - y.z[--k1]) < dz ) ){
375  auto delta = std::pow( (y.z_[k] - y.z_[k1]) / dz, 2)
376  +std::pow( (y.t_[k] - y.t_[k1]) / dt, 2);
377  if (delta < delta_min){
378  k_min = k1;
379  delta_min = delta;
380  }
381  }
382 
383  //search right
384  k1 = k;
385  while( ((++k1) < nv) && ((y.z[k1] - y.z[k]) < dz ) ){
386  auto delta = std::pow( (y.z_[k1] - y.z_[k]) / dz, 2)
387  +std::pow( (y.t_[k1] - y.t_[k]) / dt, 2);
388  if (delta < delta_min){
389  k_min = k1;
390  delta_min = delta;
391  }
392  }
393 
394  return (delta_min < 1.);
395 }
396 
397 
398 
399 
400 bool DAClusterizerInZT_vect::merge(vertex_t & y, double & beta)const{
401  // merge clusters that collapsed or never separated,
402  // return true if vertices were merged, false otherwise
403  const unsigned int nv = y.getSize();
404 
405  if (nv < 2)
406  return false;
407 
408  // merge the smallest distance clusters first
409  unsigned int k1_min = 0, k2_min = 0;
410  double delta_min = 0;
411 
412  for (unsigned int k1 = 0; (k1 + 1) < nv; k1++) {
413  unsigned int k2 = k1;
414  while( (++k2 < nv) && ( std::fabs(y.z[k2] - y.z_[k1] ) < zmerge_ ) ){
415  auto delta = std::pow( (y.z_[k2] - y.z_[k1]) / zmerge_, 2)
416  +std::pow( (y.t_[k2] - y.t_[k1]) / tmerge_, 2);
417  if ( (delta < delta_min) || (k1_min == k2_min) ){
418  k1_min = k1;
419  k2_min = k2;
420  delta_min = delta;
421  }
422  }
423  }
424 
425  if( (k1_min == k2_min) || (delta_min > 1) ){
426  return false;
427  }
428 
429 
430  double rho = y.pk_[k1_min] + y.pk_[k2_min];
431 #ifdef VI_DEBUG
432  if(verbose_){ std::cout << "merging (" << setw(8) << fixed << setprecision(4) << y.z_[k1_min] << ',' << y.t_[k1_min] << ") and (" << y.z_[k2_min] << ',' << y.t_[k2_min] << ")" << " idx=" << k1_min << "," << k2_min << std::endl;}
433 #endif
434  if(rho > 0){
435  y.z_[k1_min] = (y.pk_[k1_min] * y.z_[k1_min] + y.pk_[k2_min] * y.z_[k2_min])/rho;
436  y.t_[k1_min] = (y.pk_[k1_min] * y.t_[k1_min] + y.pk_[k2_min] * y.t_[k2_min])/rho;
437  }else{
438  y.z_[k1_min] = 0.5 * (y.z_[k1_min] + y.z_[k2_min]);
439  y.t_[k1_min] = 0.5 * (y.t_[k1_min] + y.t_[k2_min]);
440  }
441  y.pk_[k1_min] = rho;
442  y.removeItem(k2_min);
443  y.extractRaw();
444  return true;
445 }
446 
447 bool
448 DAClusterizerInZT_vect::purge(vertex_t & y, track_t & tks, double & rho0, const double beta) const {
449  constexpr double eps = 1.e-100;
450  // eliminate clusters with only one significant/unique track
451  const unsigned int nv = y.getSize();
452  const unsigned int nt = tks.getSize();
453 
454  if (nv < 2)
455  return false;
456 
457  double sumpmin = nt;
458  unsigned int k0 = nv;
459 
460  int nUnique = 0;
461  double sump = 0;
462 
463  std::vector<double> inverse_zsums(nt), arg_cache(nt), eik_cache(nt);
464  double * pinverse_zsums;
465  double * parg_cache;
466  double * peik_cache;
467  pinverse_zsums = inverse_zsums.data();
468  parg_cache = arg_cache.data();
469  peik_cache = eik_cache.data();
470  for(unsigned i = 0; i < nt; ++i) {
471  inverse_zsums[i] = tks.Z_sum_[i] > eps ? 1./tks.Z_sum_[i] : 0.0;
472  }
473 
474  for (unsigned int k = 0; k < nv; ++k) {
475 
476  nUnique = 0;
477  sump = 0;
478 
479  const double pmax = y.pk_[k] / (y.pk_[k] + rho0 * local_exp(-beta * dzCutOff_* dzCutOff_));
480  const double pcut = uniquetrkweight_ * pmax;
481  for(unsigned i = 0; i < nt; ++i) {
482  const auto track_z = tks.z_[i];
483  const auto track_t = tks.t_[i];
484  const auto botrack_dz2 = -beta*tks.dz2_[i];
485  const auto botrack_dt2 = -beta*tks.dt2_[i];
486 
487  const auto mult_resz = track_z - y.z_[k];
488  const auto mult_rest = track_t - y.t_[k];
489  parg_cache[i] = botrack_dz2 * ( mult_resz * mult_resz ) + botrack_dt2 * ( mult_rest * mult_rest );
490  }
491  local_exp_list(parg_cache, peik_cache, nt);
492  for (unsigned int i = 0; i < nt; ++i) {
493  const double p = y.pk_[k] * peik_cache[i] * pinverse_zsums[i];
494  sump += p;
495  nUnique += ( ( p > pcut ) & ( tks.pi_[i] > 0 ) );
496  }
497 
498  if ((nUnique < 2) && (sump < sumpmin)) {
499  sumpmin = sump;
500  k0 = k;
501  }
502 
503  }
504 
505  if (k0 != nv) {
506 #ifdef VI_DEBUG
507  if (verbose_) {
508  std::cout << "eliminating prototype at " << std::setw(10) << std::setprecision(4) << y.z_[k0] << "," << y.t_[k0]
509  << " with sump=" << sumpmin
510  << " rho*nt =" << y.pk_[k0]*nt
511  << endl;
512  }
513 #endif
514  y.removeItem(k0);
515  return true;
516  } else {
517  return false;
518  }
519 }
520 
521 
522 
523 
524 double
525 DAClusterizerInZT_vect::beta0(double betamax, track_t const & tks, vertex_t const & y) const {
526 
527  double T0 = 0; // max Tc for beta=0
528  // estimate critical temperature from beta=0 (T=inf)
529  const unsigned int nt = tks.getSize();
530  const unsigned int nv = y.getSize();
531 
532  for (unsigned int k = 0; k < nv; k++) {
533 
534  // vertex fit at T=inf
535  double sumwz = 0;
536  double sumwt = 0;
537  double sumw_z = 0;
538  double sumw_t = 0;
539  for (unsigned int i = 0; i < nt; i++) {
540  double w_z = tks.pi_[i] * tks.dz2_[i];
541  double w_t = tks.pi_[i] * tks.dt2_[i];
542  sumwz += w_z * tks.z_[i];
543  sumwt += w_t * tks.t_[i];
544  sumw_z += w_z;
545  sumw_t += w_t;
546  }
547  y.z_[k] = sumwz / sumw_z;
548  y.t_[k] = sumwt / sumw_t;
549 
550  // estimate Tc, eventually do this in the same loop
551  double szz = 0, stt = 0, szt = 0;
552  double nuz = 0, nut = 0;
553  for (unsigned int i = 0; i < nt; i++) {
554  double dz = (tks.z_[i] - y.z_[k]) * tks.dz2_[i];
555  double dt = (tks.t_[i] - y.t_[k]) * tks.dt2_[i];
556  double w = tks.pi_[i];
557  szz += w * dz * dz;
558  stt += w * dt * dt;
559  szt += w * dz * dt;
560  nuz += w * tks.dz2_[i];
561  nut += w * tks.dt2_[i];
562  }
563  double Tz = szz/nuz;
564  double Tt = stt/nut;
565  double Tc = Tz + Tt + sqrt( pow(Tz - Tt, 2) + 4 * szt * szt / nuz / nut);
566 
567  if (Tc > T0) T0 = Tc;
568  }// vertex loop (normally there should be only one vertex at beta=0)
569 
570 #ifdef VI_DEBUG
571  if(verbose_){
572  std::cout << "DAClustrizerInZT_vect.beta0: Tc = " << T0 << std::endl;
573  int coolingsteps = 1 - int(std::log(T0 * betamax) / std::log(coolingFactor_));
574  std::cout << "DAClustrizerInZT_vect.beta0: nstep = " << coolingsteps << std::endl;
575  }
576 #endif
577 
578 
579  if (T0 > 1. / betamax) {
580  return betamax / std::pow(coolingFactor_, int(std::log(T0 * betamax) / std::log(coolingFactor_)) - 1);
581  } else {
582  // ensure at least one annealing step
583  return betamax * coolingFactor_;
584  }
585 }
586 
587 double DAClusterizerInZT_vect::get_Tc(const vertex_t & y, int k)const{
588  double Tz = y.szz_[k]/y.nuz_[k]; // actually 0.5*Tc(z)
589  double Tt = y.stt_[k]/y.nut_[k];
590  double mx = y.szt_[k]/y.nuz_[k]*y.szt_[k]/y.nut_[k];
591  return Tz + Tt + sqrt(pow(Tz - Tt, 2) + 4 * mx);
592 }
593 
594 bool
595 DAClusterizerInZT_vect::split(const double beta, track_t &tks, vertex_t & y, double threshold ) const{
596  // split only critical vertices (Tc >~ T=1/beta <==> beta*Tc>~1)
597  // an update must have been made just before doing this (same beta, no merging)
598  // returns true if at least one cluster was split
599 
600  constexpr double epsilonz=1e-3; // minimum split size z
601  constexpr double epsilont=1e-2; // minimum split size t
602  unsigned int nv = y.getSize();
603  const double twoBeta = 2.0*beta;
604 
605  // avoid left-right biases by splitting highest Tc first
606 
607  std::vector<std::pair<double, unsigned int> > critical;
608  for(unsigned int k=0; k<nv; k++){
609  double Tc= get_Tc(y, k);
610  if (beta*Tc > threshold){
611  critical.push_back( make_pair(Tc, k));
612  }
613  }
614  if (critical.empty()) return false;
615 
616 
617  std::stable_sort(critical.begin(), critical.end(), std::greater<std::pair<double, unsigned int> >() );
618 
619  bool split=false;
620  const unsigned int nt = tks.getSize();
621 
622  for(unsigned int ic=0; ic<critical.size(); ic++){
623  unsigned int k=critical[ic].second;
624 
625  // split direction in the (z,t)-plane
626 
627  double Mzz = y.nuz_[k] - twoBeta*y.szz_[k];
628  double Mtt = y.nut_[k] - twoBeta*y.stt_[k];
629  double Mzt = - twoBeta*y.szt_[k];
630  const double twoMzt = 2.0*Mzt;
631  double D = sqrt( pow(Mtt-Mzz, 2) + twoMzt*twoMzt);
632  double q1 = atan2(-Mtt+Mzz+D, -twoMzt);
633  double l1 = 0.5*(-Mzz-Mtt+D);
634  double l2 = 0.5*(-Mzz-Mtt-D);
635  if( (std::abs(l1) < 1e-4)&&(std::abs(l2) < 1e-4) ){
636  edm::LogWarning("DAClusterizerInZT_vect") << "warning, bad eigenvalues! idx=" << k << " z= " << y.z_[k] << " Mzz=" << Mzz << " Mtt=" << Mtt << " Mzt=" << Mzt << endl;
637  }
638 
639  double qsplit = q1;
640  double cq = cos(qsplit);
641  double sq = sin(qsplit);
642  if(cq < 0){ cq=-cq; sq=-sq; } // prefer cq>0 to keep z-ordering
643 
644  // estimate subcluster positions and weight
645  double p1=0, z1=0, t1=0, wz1=0, wt1=0;
646  double p2=0, z2=0, t2=0, wz2=0, wt2=0;
647  for(unsigned int i=0; i<nt; ++i){
648  if (tks.Z_sum_[i] > 1.e-100) {
649  double lr = (tks.z_[i]-y.z_[k]) * cq + (tks.t[i] - y.t_[k]) * sq;
650  // winner-takes-all, usually overestimates splitting
651  double tl = lr < 0 ? 1.: 0.;
652  double tr = 1. - tl;
653 
654  // soften it, especially at low T
655  double arg = lr * std::sqrt(beta * ( cq*cq*tks.dz2_[i] + sq*sq*tks.dt2_[i] ) );
656  if(std::abs(arg) < 20){
657  double t = local_exp(-arg);
658  tl = t/(t+1.);
659  tr = 1/(t+1.);
660  }
661 
662  double p = y.pk_[k] * tks.pi_[i] * local_exp(-beta * Eik(tks.z_[i], y.z_[k], tks.dz2_[i],
663  tks.t_[i], y.t_[k], tks.dt2_[i])) / tks.Z_sum_[i];
664  double wz = p*tks.dz2_[i];
665  double wt = p*tks.dt2_[i];
666  p1 += p*tl; z1 += wz*tl*tks.z_[i]; t1 += wt*tl*tks.t_[i]; wz1 += wz*tl; wt1 += wt*tl;
667  p2 += p*tr; z2 += wz*tr*tks.z_[i]; t2 += wt*tr*tks.t_[i]; wz2 += wz*tr; wt2 += wt*tr;
668  }
669  }
670 
671  if(wz1 > 0){z1 /= wz1;} else {z1 = y.z_[k] - epsilonz * cq; edm::LogWarning("DAClusterizerInZT_vect") << "warning, wz1 = " << scientific << wz1 << endl;}
672  if(wt1 > 0){t1 /= wt1;} else {t1 = y.t_[k] - epsilont * sq; edm::LogWarning("DAClusterizerInZT_vect") << "warning, w11 = " << scientific << wt1 << endl;}
673  if(wz2 > 0){z2 /= wz2;} else {z2 = y.z_[k] + epsilonz * cq; edm::LogWarning("DAClusterizerInZT_vect") << "warning, wz2 = " << scientific << wz2 << endl;}
674  if(wt2 > 0){t2 /= wt2;} else {t2 = y.t_[k] + epsilont * sq; edm::LogWarning("DAClusterizerInZT_vect") << "warning, wt2 = " << scientific << wt2 << endl;}
675 
676  unsigned int k_min1 = k, k_min2 = k;
677  while( (find_nearest(z1, t1, y, k_min1, epsilonz, epsilont) && (k_min1 != k))
678  || (find_nearest(z2,t2, y, k_min2, epsilonz, epsilont) && (k_min2 !=k)) ){
679  z1 = 0.5*( z1 + y.z_[k]); t1 = 0.5*( t1 + y.t_[k]);
680  z2 = 0.5*( z2 + y.z_[k]); t2 = 0.5*( t2 + y.t_[k]);
681  }
682 
683 #ifdef VI_DEBUG
684  if(verbose_){
685  if (std::fabs(y.z_[k] - zdumpcenter_) < zdumpwidth_){
686  std::cout << " T= " << std::setw(10) << std::setprecision(1) << 1./beta
687  << " Tc= " << critical[ic].first
688  << " direction =" << std::setprecision(4) << qsplit
689  << " splitting (" << std::setw(8) << std::fixed << std::setprecision(4) << y.z_[k] <<"," << y.t_[k] << ")"
690  << " --> (" << z1 << ',' << t1<< "),(" << z2 << ',' << t2
691  << ") [" << p1 << "," << p2 << "]" ;
692  if (std::fabs(z2-z1) > epsilonz || std::fabs(t2-t1) > epsilont){
693  std::cout << std::endl;
694  }else{
695  std::cout << " rejected " << std::endl;
696  }
697  }
698  }
699 #endif
700 
701  if(z1>z2){
702  edm::LogInfo("DAClusterizerInZT") << "warning swapping z in split qsplit=" << qsplit << " cq=" << cq << " sq=" << sq << endl;
703  auto ztemp = z1;
704  auto ttemp = t1;
705  auto ptemp = p1;
706  z1 = z2; t1=t2; p1=p2;
707  z2 = ztemp; t2=ttemp; p2=ptemp;
708  }
709 
710 
711 
712 
713  // split if the new subclusters are significantly separated
714  if( std::fabs(z2-z1) > epsilonz || std::fabs(t2-t1) > epsilont){
715  split = true;
716  double pk1 = p1*y.pk_[k]/(p1+p2);
717  double pk2 = p2*y.pk_[k]/(p1+p2);
718 
719  // replace the original by (z2,t2)
720  y.removeItem(k);
721  unsigned int k2 = y.insertOrdered(z2, t2, pk2);
722  // adjust pointers if necessary
723  if( !(k == k2) ){
724  for(unsigned int jc=ic; jc < critical.size(); jc++){
725  if (critical[jc].second > k ) {critical[jc].second--;}
726  if (critical[jc].second >= k2) {critical[jc].second++;}
727  }
728  }
729 
730  // insert (z1,t1) where it belongs
731  unsigned int k1 = y.insertOrdered(z1, t1, pk1);
732  nv++;
733 
734  // adjust remaining pointers
735  for(unsigned int jc=ic; jc < critical.size(); jc++){
736  if (critical[jc].second >= k1) {critical[jc].second++;} // need to backport the ">-"?
737  }
738 
739  }else{
740 #ifdef VI_DEBUG
741  std::cout << "warning ! split rejected, too small." << endl;
742 #endif
743  }
744 
745  }
746  return split;
747 }
748 
749 
750 
752 
753  const unsigned int nv = y.getSize();
754 
755  constexpr double epsilonz = 1e-3; // split all single vertices by 10 um
756  constexpr double epsilont = 1e-2; // split all single vertices by 10 ps
757  constexpr double zsep = 2 * epsilonz; // split vertices that are isolated by at least zsep (vertices that haven't collapsed)
758  constexpr double tsep = 2 * epsilont;
759  vertex_t y1;
760 
761 #ifdef VI_DEBUG
762  if (verbose_) {
763  std::cout << "Before Split "<< std::endl;
764  y.debugOut();
765  }
766 #endif
767 
768  for (unsigned int k = 0; k < nv; k++) {
769  if (
770  ( ( (k == 0) || ( y.z_[k - 1] < (y.z_[k] - zsep)) ) &&
771  ( ((k + 1) == nv) || ( y.z_[k + 1] > (y.z_[k] + zsep)) ) ) )
772  {
773  // isolated prototype, split
774  double new_z = y.z[k] - epsilonz;
775  double new_t = y.t[k] - epsilont;
776  y.z[k] = y.z[k] + epsilonz;
777  y.t[k] = y.t[k] + epsilont;
778 
779  double new_pk = 0.5 * y.pk[k];
780  y.pk[k] = 0.5 * y.pk[k];
781 
782  y1.addItem(new_z, new_t, new_pk);
783  y1.addItem(y.z_[k], y.t_[k], y.pk_[k]);
784  }
785  else if ( (y1.getSize() == 0 ) ||
786  (y1.z_[y1.getSize() - 1] < (y.z_[k] - zsep) ) ||
787  (y1.t_[y1.getSize() - 1] < (y.t_[k] - tsep) ))
788  {
789  y1.addItem(y.z_[k], y.t_[k], y.pk_[k]);
790  }
791  else
792  {
793  y1.z_[y1.getSize() - 1] = y1.z_[y1.getSize() - 1] - epsilonz;
794  y1.t_[y1.getSize() - 1] = y1.t_[y1.getSize() - 1] - epsilont;
795  y.z_[k] = y.z_[k] + epsilonz;
796  y.t_[k] = y.t_[k] + epsilont;
797  y1.addItem( y.z_[k], y.t_[k] , y.pk_[k]);
798  }
799  }// vertex loop
800 
801  y = y1;
802  y.extractRaw();
803 
804 #ifdef VI_DEBUG
805  if (verbose_) {
806  std::cout << "After split " << std::endl;
807  y.debugOut();
808  }
809 #endif
810 }
811 
812 
813 
814 vector<TransientVertex>
815 DAClusterizerInZT_vect::vertices(const vector<reco::TransientTrack> & tracks, const int verbosity) const {
816  track_t && tks = fill(tracks);
817  tks.extractRaw();
818 
819  unsigned int nt = tks.getSize();
820  double rho0 = 0.0; // start with no outlier rejection
821 
822  vector<TransientVertex> clusters;
823  if (tks.getSize() == 0) return clusters;
824 
825  vertex_t y; // the vertex prototypes
826 
827  // initialize:single vertex at infinite temperature
828  y.addItem( 0, 0, 1.0);
829 
830  int niter = 0; // number of iterations
831 
832 
833  // estimate first critical temperature
834  double beta = beta0(betamax_, tks, y);
835 #ifdef VI_DEBUG
836  if ( verbose_) std::cout << "Beta0 is " << beta << std::endl;
837 #endif
838 
839  niter = 0;
840  while ((update(beta, tks, y, false, rho0) > 1.e-6) &&
841  (niter++ < maxIterations_)) {}
842 
843  // annealing loop, stop when T<minT (i.e. beta>1/minT)
844 
845  double betafreeze = betamax_ * sqrt(coolingFactor_);
846 
847  while (beta < betafreeze) {
848  if(useTc_){
849  update(beta, tks,y, false, rho0);
850  zorder(y);
851  while(merge(y, beta)){update(beta, tks, y, false, rho0);}
852  split(beta, tks, y);
853  beta=beta/coolingFactor_;
854  }else{
855  beta=beta/coolingFactor_;
856  splitAll(y);
857  }
858 
859  // make sure we are not too far from equilibrium before cooling further
860  niter = 0;
861  while ((update(beta, tks, y, false, rho0) > 1.e-6) &&
862  (niter++ < maxIterations_)) {}
863 
864 #ifdef VI_DEBUG
865  if(verbose_){ dump( beta, y, tks, 0); }
866 #endif
867  }
868 
869 
870  if(useTc_){
871  //last round of splitting, make sure no critical clusters are left
872 #ifdef VI_DEBUG
873  if(verbose_){ std::cout << "last spliting at " << 1./beta << std::endl; }
874 #endif
875  update(beta, tks,y, false, rho0);// make sure Tc is up-to-date
876  zorder(y);
877  while(merge(y,beta)){update(beta, tks,y, false, rho0);}
878  unsigned int ntry=0;
879  double threshold = 1.0;
880  while( split(beta, tks, y, threshold) && (ntry++<10) ){
881  niter=0;
882  while((update(beta, tks,y, false, rho0)>1.e-6) && (niter++ < maxIterations_)){}
883  zorder(y);
884 #ifdef VI_DEBUG
885  if(verbose_) dump(beta, y, tks, 2);
886 #endif
887 
888  while(merge(y,beta)){update(beta, tks,y, false, rho0);}
889 #ifdef VI_DEBUG
890  if(verbose_){
891  std::cout << "after final splitting, try " << ntry << std::endl;
892  dump(beta, y, tks, 2);
893  }
894 #endif
895  // relax splitting a bit to reduce multiple split-merge cycles of the same cluster
896  threshold *= 1.1;
897  }
898  }else{
899  // merge collapsed clusters
900  while(merge(y,beta)){update(beta, tks,y, false, rho0);}
901  }
902 
903 #ifdef VI_DEBUG
904  if (verbose_) {
905  update(beta, tks,y, false, rho0);
906  std::cout << "dump after 1st merging " << endl;
907  dump(beta, y, tks, 2);
908  }
909 #endif
910 
911 
912  // switch on outlier rejection at T=minT
913  if(dzCutOff_ > 0){
914  rho0 = 1./nt;
915  for(unsigned int a=0; a<10; a++){ update(beta, tks, y, true, a*rho0/10);} // adiabatic turn-on
916  }
917 
918  niter=0;
919  while ((update(beta, tks, y, true, rho0) > 1.e-8) && (niter++ < maxIterations_)) {};
920 #ifdef VI_DEBUG
921  if (verbose_) {
922  std::cout << "dump after noise-suppression, rho0=" << rho0 << " niter = " << niter << endl;
923  dump(beta, y, tks, 2);
924  }
925 #endif
926 
927  // merge again (some cluster split by outliers collapse here)
928  zorder(y);
929  while (merge(y, beta)) {update(beta, tks, y, true, rho0); }
930 #ifdef VI_DEBUG
931  if (verbose_) {
932  std::cout << "dump after merging " << endl;
933  dump(beta, y, tks, 2);
934  }
935 #endif
936 
937  // go down to the purging temperature (if it is lower than tmin)
938  while( beta < betapurge_ ){
939  beta = min( beta/coolingFactor_, betapurge_);
940  niter = 0;
941  while ((update(beta, tks, y, false, rho0) > 1.e-8) && (niter++ < maxIterations_)) {}
942  }
943 
944 
945  // eliminate insigificant vertices, this is more restrictive at higher T
946  while (purge(y, tks, rho0, beta)) {
947  niter = 0;
948  while (( update(beta, tks, y, true, rho0) > 1.e-6 ) && (niter++ < maxIterations_)) {
949  zorder(y);
950  }
951  }
952 
953 #ifdef VI_DEBUG
954  if (verbose_) {
955  update(beta, tks,y, true, rho0);
956  std::cout << " after purging " << std:: endl;
957  dump(beta, y, tks, 2);
958  }
959 #endif
960 
961  // optionally cool some more without doing anything, to make the assignment harder
962  while( beta < betastop_ ){
963  beta = min( beta/coolingFactor_, betastop_);
964  niter =0;
965  while ((update(beta, tks, y, true, rho0) > 1.e-8) && (niter++ < maxIterations_)) {}
966  zorder(y);
967  }
968 
969 #ifdef VI_DEBUG
970  if (verbose_) {
971  std::cout << "Final result, rho0=" << std::scientific << rho0 << endl;
972  dump(beta, y, tks, 2);
973  }
974 #endif
975 
976 
977  // new, merge here and not in "clusterize"
978  // final merging step
979  double betadummy = 1;
980  while( merge(y, betadummy) );
981 
982  // select significant tracks and use a TransientVertex as a container
983  GlobalError dummyError(0.01, 0, 0.01, 0., 0., 0.01);
984 
985  // ensure correct normalization of probabilities, should makes double assignment reasonably impossible
986  const unsigned int nv = y.getSize();
987  for (unsigned int k = 0; k < nv; k++)
988  if ( edm::isNotFinite(y.pk_[k]) || edm::isNotFinite(y.z_[k]) ) { y.pk_[k]=0; y.z_[k]=0;}
989 
990  for (unsigned int i = 0; i < nt; i++) // initialize
991  tks.Z_sum_[i] = rho0 * local_exp(-beta * dzCutOff_ * dzCutOff_);
992 
993  // improve vectorization (does not require reduction ....)
994  for (unsigned int k = 0; k < nv; k++) {
995  for (unsigned int i = 0; i < nt; i++)
996  tks.Z_sum_[i] += y.pk_[k] * local_exp(-beta * Eik(tks.z_[i], y.z_[k],tks.dz2_[i], tks.t_[i], y.t_[k],tks.dt2_[i]));
997  }
998 
999 
1000  for (unsigned int k = 0; k < nv; k++) {
1001  GlobalPoint pos(0, 0, y.z_[k]);
1002 
1003  vector<reco::TransientTrack> vertexTracks;
1004  for (unsigned int i = 0; i < nt; i++) {
1005  if (tks.Z_sum_[i] > 1e-100) {
1006 
1007  double p = y.pk_[k] * local_exp(-beta * Eik(tks.z_[i], y.z_[k], tks.dz2_[i],
1008  tks.t_[i], y.t_[k], tks.dt2_[i] )) / tks.Z_sum_[i];
1009  if ((tks.pi_[i] > 0) && (p > mintrkweight_)) {
1010  vertexTracks.push_back(*(tks.tt[i]));
1011  tks.Z_sum_[i] = 0; // setting Z=0 excludes double assignment
1012  }
1013  }
1014  }
1015  TransientVertex v(pos, y.t_[k], dummyError, vertexTracks, 0);
1016  clusters.push_back(v);
1017  }
1018 
1019  return clusters;
1020 
1021 }
1022 
1023 vector<vector<reco::TransientTrack> > DAClusterizerInZT_vect::clusterize(
1024  const vector<reco::TransientTrack> & tracks) const {
1025 
1026 #ifdef VI_DEBUG
1027  if (verbose_) {
1028  std::cout << "###################################################" << endl;
1029  std::cout << "# vectorized DAClusterizerInZT_vect::clusterize nt=" << tracks.size() << endl;
1030  std::cout << "###################################################" << endl;
1031  }
1032 #endif
1033 
1034  vector<vector<reco::TransientTrack> > clusters;
1035  vector<TransientVertex> && pv = vertices(tracks);
1036 
1037 #ifdef VI_DEBUG
1038  if (verbose_) {
1039  std::cout << "# DAClusterizerInZT::clusterize pv.size=" << pv.size() << endl;
1040  }
1041 #endif
1042 
1043  if (pv.empty()) {
1044  return clusters;
1045  }
1046 
1047  // fill into clusters, don't merge
1048  for (auto k = pv.begin(); k != pv.end(); k++) {
1049  vector<reco::TransientTrack> aCluster = k->originalTracks();
1050  if (aCluster.size()>1){
1051  clusters.push_back(aCluster);
1052  }
1053  }
1054 
1055  return clusters;
1056 
1057  /*
1058  //leaving the merging version here in case we want to turn it back on the future
1059  // needs optimization and validation
1060  // fill into clusters and merge
1061  vector<reco::TransientTrack> aCluster = pv.begin()->originalTracks();
1062 
1063  for (auto k = pv.begin() + 1; k != pv.end(); k++) {
1064  if ( (std::abs(k->position().z() - (k - 1)->position().z()) > (2 * vertexSize_))
1065  ||(std::abs(k->time() - (k - 1)->time() ) > (2 * vertexSizeTime_)) ){ // still not perfect
1066  // close a cluster
1067  if (aCluster.size()>1){
1068  clusters.push_back(aCluster);
1069  }else{
1070  #ifdef VI_DEBUG
1071  if(verbose_){
1072  std::cout << " one track cluster at " << k->position().z() << " suppressed" << std::endl;
1073  }
1074  #endif
1075  }
1076  aCluster.clear();
1077  }
1078  for (unsigned int i = 0; i < k->originalTracks().size(); i++) {
1079  aCluster.push_back(k->originalTracks()[i]);
1080  }
1081 
1082  }
1083  clusters.emplace_back(std::move(aCluster));
1084 
1085  return clusters;
1086  */
1087 }
1088 
1089 
1090 
1091 void DAClusterizerInZT_vect::dump(const double beta, const vertex_t & y,
1092  const track_t & tks, int verbosity) const {
1093 #ifdef VI_DEBUG
1094  const unsigned int nv = y.getSize();
1095  const unsigned int nt = tks.getSize();
1096 
1097  std::vector< unsigned int > iz;
1098  for(unsigned int j=0; j<nt; j++){ iz.push_back(j); }
1099  std::sort(iz.begin(), iz.end(), [tks](unsigned int a, unsigned int b){ return tks.z_[a]<tks.z_[b];} );
1100  std::cout << std::endl;
1101  std::cout << "-----DAClusterizerInZT::dump ----" << nv << " clusters " << std::endl;
1102  string h = " ";
1103  std::cout << h << " k= ";
1104  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1105  if (std::fabs(y.z_[ivertex]-zdumpcenter_) < zdumpwidth_){
1106  std::cout << setw(8) << fixed << ivertex;
1107  }
1108  }
1109  std::cout << endl;
1110 
1111  std::cout << h << " z= ";
1112  std::cout << setprecision(4);
1113  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1114  if (std::fabs(y.z_[ivertex]-zdumpcenter_) < zdumpwidth_){
1115  std::cout << setw(8) << fixed << y.z_[ivertex];
1116  }
1117  }
1118  std::cout << endl;
1119 
1120  std::cout << h << " t= ";
1121  std::cout << setprecision(4);
1122  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1123  if (std::fabs(y.z_[ivertex]-zdumpcenter_) < zdumpwidth_){
1124  std::cout << setw(8) << fixed << y.t_[ivertex];
1125  }
1126  }
1127  std::cout << endl;
1128 
1129  std::cout << "T=" << setw(15) << 1. / beta
1130  << " Tmin =" << setw(10) << 1./betamax_
1131  << " Tc= ";
1132  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1133  if (std::fabs(y.z_[ivertex]-zdumpcenter_) < zdumpwidth_){
1134  double Tc = get_Tc(y, ivertex);
1135  std::cout << setw(8) << fixed << setprecision(1) << Tc;
1136  }
1137  }
1138  std::cout << endl;
1139 
1140  std::cout << h << "pk= ";
1141  double sumpk = 0;
1142  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1143  sumpk += y.pk_[ivertex];
1144  if (std::fabs(y.z_[ivertex] - zdumpcenter_) > zdumpwidth_) continue;
1145  std::cout << setw(8) << setprecision(4) << fixed << y.pk_[ivertex];
1146  }
1147  std::cout << endl;
1148 
1149  std::cout << h << "nt= ";
1150  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1151  sumpk += y.pk_[ivertex];
1152  if (std::fabs(y.z_[ivertex] - zdumpcenter_) > zdumpwidth_) continue;
1153  std::cout << setw(8) << setprecision(1) << fixed << y.pk_[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
1161  << "---- z +/- dz t +/- dt ip +/-dip pt phi eta weights ----"
1162  << endl;
1163  std::cout << setprecision(4);
1164  for (unsigned int i0 = 0; i0 < nt; i0++) {
1165  unsigned int i = iz[i0];
1166  if (tks.Z_sum_[i] > 0) {
1167  F -= std::log(tks.Z_sum_[i]) / beta;
1168  }
1169  double tz = tks.z_[i];
1170 
1171  if( std::fabs(tz - zdumpcenter_) > zdumpwidth_) continue;
1172  std::cout << setw(4) << i << ")" << setw(8) << fixed << setprecision(4)
1173  << tz << " +/-" << setw(6) << sqrt(1./tks.dz2_[i]);
1174 
1175  if( tks.dt2_[i] >0){
1176  std::cout << setw(8) << fixed << setprecision(4)
1177  << tks.t_[i] << " +/-" << setw(6) << sqrt(1./tks.dt2_[i]);
1178  }else{
1179  std::cout << " ";
1180  }
1181 
1182  if (tks.tt[i]->track().quality(reco::TrackBase::highPurity)) {
1183  std::cout << " *";
1184  } else {
1185  std::cout << " ";
1186  }
1187  if (tks.tt[i]->track().hitPattern().hasValidHitInPixelLayer(PixelSubdetector::SubDetector::PixelBarrel, 1)) {
1188  std::cout << "+";
1189  } else {
1190  std::cout << "-";
1191  }
1192  std::cout << setw(1)
1193  << tks.tt[i]->track().hitPattern().pixelBarrelLayersWithMeasurement(); // see DataFormats/TrackReco/interface/HitPattern.h
1194  std::cout << setw(1)
1195  << tks.tt[i]->track().hitPattern().pixelEndcapLayersWithMeasurement();
1196  std::cout << setw(1) << hex
1197  << tks.tt[i]->track().hitPattern().trackerLayersWithMeasurement()
1198  - tks.tt[i]->track().hitPattern().pixelLayersWithMeasurement()
1199  << dec;
1200  std::cout << "=" << setw(1) << hex
1201  << tks.tt[i]->track().hitPattern().numberOfLostHits(reco::HitPattern::MISSING_OUTER_HITS)
1202  << dec;
1203 
1204  Measurement1D IP =
1205  tks.tt[i]->stateAtBeamLine().transverseImpactParameter();
1206  std::cout << setw(8) << IP.value() << "+/-" << setw(6) << IP.error();
1207  std::cout << " " << setw(6) << setprecision(2)
1208  << tks.tt[i]->track().pt() * tks.tt[i]->track().charge();
1209  std::cout << " " << setw(5) << setprecision(2)
1210  << tks.tt[i]->track().phi() << " " << setw(5)
1211  << setprecision(2) << tks.tt[i]->track().eta();
1212 
1213  double sump = 0.;
1214  for (unsigned int ivertex = 0; ivertex < nv; ++ ivertex) {
1215  if (std::fabs(y.z_[ivertex]-zdumpcenter_) > zdumpwidth_) continue;
1216 
1217  if ((tks.pi_[i] > 0) && (tks.Z_sum_[i] > 0)) {
1218  //double p=pik(beta,tks[i],*k);
1219  double p = y.pk_[ivertex] * exp(-beta * Eik(tks.z_[i], y.z_[ivertex], tks.dz2_[i],
1220  tks.t_[i], y.t_[ivertex], tks.dt2_[i] )) / tks.Z_sum_[i];
1221  if (p > 0.0001) {
1222  std::cout << setw(8) << setprecision(3) << p;
1223  } else {
1224  std::cout << " . ";
1225  }
1226  E += p * Eik(tks.z_[i], y.z_[ivertex], tks.dz2_[i],
1227  tks.t_[i], y.t_[ivertex], tks.dt2_[i] );
1228  sump += p;
1229  } else {
1230  std::cout << " ";
1231  }
1232  }
1233  std::cout << endl;
1234  }
1235  std::cout << endl << "T=" << 1 / beta << " E=" << E << " n=" << y.getSize()
1236  << " F= " << F << endl << "----------" << endl;
1237  }
1238 #endif
1239 }
dbl * delta
Definition: mlp_gen.cc:36
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
float dt
Definition: AMPTWrapper.h:126
unsigned int insertOrdered(double z, double t, double pk)
const double w
Definition: UKUtility.cc:23
FWCore Framework interface EventSetupRecordImplementation h
Helper function to determine trigger accepts.
std::vector< std::vector< reco::TransientTrack > > clusterize(const std::vector< reco::TransientTrack > &tracks) const override
bool split(const double beta, track_t &t, vertex_t &y, double threshold=1.) const
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
double error() const
Definition: Measurement1D.h:30
void splitAll(vertex_t &y) const
DAClusterizerInZT_vect(const edm::ParameterSet &conf)
bool merge(vertex_t &y, double &beta) const
void addItem(double new_z, double new_t, double new_dz2, double new_dt2, const reco::TransientTrack *new_tt, double new_pi)
std::vector< TransientVertex > vertices(const std::vector< reco::TransientTrack > &tracks, const int verbosity=0) const
A arg
Definition: Factorize.h:37
#define constexpr
void zorder(vertex_t &y) const
U second(std::pair< T, U > const &p)
double get_Tc(const vertex_t &y, int k) const
bool purge(vertex_t &, track_t &, double &, const double) const
bool isNotFinite(T x)
Definition: isFinite.h:10
T sqrt(T t)
Definition: SSEVec.h:18
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
def pv(vc)
Definition: MetAnalyzer.py:6
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
bool find_nearest(double z, double t, vertex_t &y, unsigned int &k_min, double dz, double dt) const
double BeamWidthX() const
beam width X
Definition: BeamSpot.h:86
T min(T a, T b)
Definition: MathUtil.h:58
double p2[4]
Definition: TauolaWrapper.h:90
#define LogTrace(id)
int nt
Definition: AMPTWrapper.h:32
double update(double beta, track_t &gtracks, vertex_t &gvertices, bool useRho0, const double &rho0) const
int k[5][pyjets_maxn]
DecomposeProduct< arg, typename Div::arg > D
Definition: Factorize.h:151
double q1[4]
Definition: TauolaWrapper.h:87
void addItem(double new_z, double new_t, double new_pk)
double BeamWidthY() const
beam width Y
Definition: BeamSpot.h:88
double b
Definition: hdecay.h:120
track_t fill(const std::vector< reco::TransientTrack > &tracks) const
double value() const
Definition: Measurement1D.h:28
double p1[4]
Definition: TauolaWrapper.h:89
#define update(a, b)
double a
Definition: hdecay.h:121
double beta0(const double betamax, track_t const &tks, vertex_t const &y) const
std::vector< const reco::TransientTrack * > tt
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:281
void dump(const double beta, const vertex_t &y, const track_t &tks, const int verbosity=0) const
double split
Definition: MVATrainer.cc:139
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
def merge(dictlist, TELL=False)
Definition: MatrixUtil.py:193