CMS 3D CMS Logo

HGCalImagingAlgo.cc
Go to the documentation of this file.
2 
3 // Geometry
8 
10 //
12 #include "tbb/task_arena.h"
13 #include "tbb/tbb.h"
14 
16  // loop over all hits and create the Hexel structure, skip energies below ecut
17 
18  if (dependSensor) {
19  // for each layer and wafer calculate the thresholds (sigmaNoise and energy)
20  // once
22  }
23 
24  std::vector<bool> firstHit(2 * (maxlayer + 1), true);
25  for (unsigned int i = 0; i < hits.size(); ++i) {
26 
27  const HGCRecHit &hgrh = hits[i];
28  DetId detid = hgrh.detid();
29  unsigned int layer = rhtools_.getLayerWithOffset(detid);
30  float thickness = 0.f;
31  // set sigmaNoise default value 1 to use kappa value directly in case of
32  // sensor-independent thresholds
33  float sigmaNoise = 1.f;
34  if (dependSensor) {
35  if (layer <= lastLayerFH) // only EE and FH have silicon sensors
36  thickness = rhtools_.getSiThickness(detid);
37  double storedThreshold =
38  thresholds[layer - 1]
39  [layer <= lastLayerFH ? rhtools_.getSiThickIndex(detid) : 0];
40  sigmaNoise =
41  v_sigmaNoise[layer - 1]
42  [layer <= lastLayerFH ? rhtools_.getSiThickIndex(detid) : 0];
43 
44  if (hgrh.energy() < storedThreshold)
45  continue; // this sets the ZS threshold at ecut times the sigma noise
46  // for the sensor
47  }
48  if (!dependSensor && hgrh.energy() < ecut)
49  continue;
50 
51  // map layers from positive endcap (z) to layer + maxlayer+1 to prevent
52  // mixing up hits from different sides
53  layer += int(rhtools_.zside(detid) > 0) * (maxlayer + 1);
54 
55  // determine whether this is a half-hexagon
56  bool isHalf = rhtools_.isHalfCell(detid);
58 
59  // here's were the KDNode is passed its dims arguments - note that these are
60  // *copied* from the Hexel
61  points[layer].emplace_back(
62  Hexel(hgrh, detid, isHalf, sigmaNoise, thickness, &rhtools_),
63  position.x(), position.y());
64 
65  // for each layer, store the minimum and maximum x and y coordinates for the
66  // KDTreeBox boundaries
67  if (firstHit[layer]) {
68  minpos[layer][0] = position.x();
69  minpos[layer][1] = position.y();
70  maxpos[layer][0] = position.x();
71  maxpos[layer][1] = position.y();
72  firstHit[layer] = false;
73  } else {
74  minpos[layer][0] = std::min((float)position.x(), minpos[layer][0]);
75  minpos[layer][1] = std::min((float)position.y(), minpos[layer][1]);
76  maxpos[layer][0] = std::max((float)position.x(), maxpos[layer][0]);
77  maxpos[layer][1] = std::max((float)position.y(), maxpos[layer][1]);
78  }
79 
80  } // end loop hits
81 }
82 // Create a vector of Hexels associated to one cluster from a collection of
83 // HGCalRecHits - this can be used directly to make the final cluster list -
84 // this method can be invoked multiple times for the same event with different
85 // input (reset should be called between events)
87  layerClustersPerLayer.resize(2 * maxlayer + 2);
88  // assign all hits in each layer to a cluster core or halo
89  tbb::this_task_arena::isolate([&] {
90  tbb::parallel_for(size_t(0), size_t(2 * maxlayer + 2), [&](size_t i) {
91  KDTreeBox bounds(minpos[i][0], maxpos[i][0], minpos[i][1], maxpos[i][1]);
92  KDTree hit_kdtree;
93  hit_kdtree.build(points[i], bounds);
94 
95  unsigned int actualLayer =
96  i > maxlayer
97  ? (i - (maxlayer + 1))
98  : i; // maps back from index used for KD trees to actual layer
99 
100  double maxdensity = calculateLocalDensity(
101  points[i], hit_kdtree, actualLayer); // also stores rho (energy
102  // density) for each point (node)
103  // calculate distance to nearest point with higher density storing
104  // distance (delta) and point's index
106  findAndAssignClusters(points[i], hit_kdtree, maxdensity, bounds,
107  actualLayer, layerClustersPerLayer[i]);
108  });
109  });
110 }
111 
112 std::vector<reco::BasicCluster> HGCalImagingAlgo::getClusters(bool doSharing) {
113 
115  std::vector<std::pair<DetId, float>> thisCluster;
116  for (auto &clsOnLayer : layerClustersPerLayer) {
117  for (unsigned int i = 0; i < clsOnLayer.size(); ++i) {
118  double energy = 0;
119  Point position;
120 
121  if (doSharing) {
122 
123  std::vector<unsigned> seeds = findLocalMaximaInCluster(clsOnLayer[i]);
124  // sharing found seeds.size() sub-cluster seeds in cluster i
125 
126  std::vector<std::vector<double>> fractions;
127  // first pass can have noise it in
128  shareEnergy(clsOnLayer[i], seeds, fractions);
129 
130  // reset and run second pass after vetoing seeds
131  // that result in trivial clusters (less than 2 effective cells)
132 
133  for (unsigned isub = 0; isub < fractions.size(); ++isub) {
134  double effective_hits = 0.0;
135  double energy =
136  calculateEnergyWithFraction(clsOnLayer[i], fractions[isub]);
137  Point position =
138  calculatePositionWithFraction(clsOnLayer[i], fractions[isub]);
139 
140  for (unsigned ihit = 0; ihit < fractions[isub].size(); ++ihit) {
141  const double fraction = fractions[isub][ihit];
142  if (fraction > 1e-7) {
143  effective_hits += fraction;
144  thisCluster.emplace_back(clsOnLayer[i][ihit].data.detid,
145  fraction);
146  }
147  }
148 
149  if (verbosity < pINFO) {
150  std::cout << "\t******** NEW CLUSTER (SHARING) ********"
151  << std::endl;
152  std::cout << "\tEff. No. of cells = " << effective_hits
153  << std::endl;
154  std::cout << "\t Energy = " << energy << std::endl;
155  std::cout << "\t Phi = " << position.phi()
156  << std::endl;
157  std::cout << "\t Eta = " << position.eta()
158  << std::endl;
159  std::cout << "\t*****************************" << std::endl;
160  }
161  clusters_v.emplace_back(energy, position, caloID, thisCluster,
162  algoId);
163  thisCluster.clear();
164  }
165  } else {
166  position = calculatePosition(clsOnLayer[i]); // energy-weighted position
167  // std::vector< KDNode >::iterator it;
168  for (auto &it : clsOnLayer[i]) {
169  energy += it.data.isHalo ? 0. : it.data.weight;
170  // use fraction to store whether this is a Halo hit or not
171  thisCluster.emplace_back(it.data.detid, (it.data.isHalo ? 0.f : 1.f));
172  }
173  if (verbosity < pINFO) {
174  std::cout << "******** NEW CLUSTER (HGCIA) ********" << std::endl;
175  std::cout << "Index " << i << std::endl;
176  std::cout << "No. of cells = " << clsOnLayer[i].size() << std::endl;
177  std::cout << " Energy = " << energy << std::endl;
178  std::cout << " Phi = " << position.phi() << std::endl;
179  std::cout << " Eta = " << position.eta() << std::endl;
180  std::cout << "*****************************" << std::endl;
181  }
182  clusters_v.emplace_back(energy, position, caloID, thisCluster, algoId);
183  thisCluster.clear();
184  }
185  }
186  }
187  return clusters_v;
188 }
189 
191 HGCalImagingAlgo::calculatePosition(std::vector<KDNode> &v) const {
192  float total_weight = 0.f;
193  float x = 0.f;
194  float y = 0.f;
195  float z = 0.f;
196  unsigned int v_size = v.size();
197  unsigned int maxEnergyIndex = 0;
198  float maxEnergyValue = 0;
199  bool haloOnlyCluster = true;
200 
201  // loop over hits in cluster candidate building up weight for
202  // energy-weighted position calculation and determining the maximum
203  // energy hit in case this is a halo-only cluster
204  for (unsigned int i = 0; i < v_size; i++) {
205  if (!v[i].data.isHalo) {
206  haloOnlyCluster = false;
207  total_weight += v[i].data.weight;
208  x += v[i].data.x * v[i].data.weight;
209  y += v[i].data.y * v[i].data.weight;
210  z += v[i].data.z * v[i].data.weight;
211  } else {
212  if (v[i].data.weight > maxEnergyValue) {
213  maxEnergyValue = v[i].data.weight;
214  maxEnergyIndex = i;
215  }
216  }
217  }
218 
219  if (!haloOnlyCluster) {
220  if (total_weight != 0) {
221  auto inv_tot_weight = 1. / total_weight;
222  return math::XYZPoint(x * inv_tot_weight, y * inv_tot_weight,
223  z * inv_tot_weight);
224  }
225  } else if (v_size > 0) {
226  // return position of hit with maximum energy
227  return math::XYZPoint(v[maxEnergyIndex].data.x, v[maxEnergyIndex].data.y,
228  v[maxEnergyIndex].data.z);
229  }
230  return math::XYZPoint(0, 0, 0);
231 }
232 
233 double HGCalImagingAlgo::calculateLocalDensity(std::vector<KDNode> &nd,
234  KDTree &lp,
235  const unsigned int layer) const {
236 
237  double maxdensity = 0.;
238  float delta_c; // maximum search distance (critical distance) for local
239  // density calculation
240  if (layer <= lastLayerEE)
241  delta_c = vecDeltas[0];
242  else if (layer <= lastLayerFH)
243  delta_c = vecDeltas[1];
244  else
245  delta_c = vecDeltas[2];
246 
247  // for each node calculate local density rho and store it
248  for (unsigned int i = 0; i < nd.size(); ++i) {
249  // speec up search by looking within +/- delta_c window only
250  KDTreeBox search_box(nd[i].dims[0] - delta_c, nd[i].dims[0] + delta_c,
251  nd[i].dims[1] - delta_c, nd[i].dims[1] + delta_c);
252  std::vector<KDNode> found;
253  lp.search(search_box, found);
254  const unsigned int found_size = found.size();
255  for (unsigned int j = 0; j < found_size; j++) {
256  if (distance(nd[i].data, found[j].data) < delta_c) {
257  nd[i].data.rho += found[j].data.weight;
258  maxdensity = std::max(maxdensity, nd[i].data.rho);
259  }
260  } // end loop found
261  } // end loop nodes
262  return maxdensity;
263 }
264 
265 double
266 HGCalImagingAlgo::calculateDistanceToHigher(std::vector<KDNode> &nd) const {
267 
268  // sort vector of Hexels by decreasing local density
269  std::vector<size_t> rs = sorted_indices(nd);
270 
271  double maxdensity = 0.0;
272  int nearestHigher = -1;
273 
274  if (!rs.empty())
275  maxdensity = nd[rs[0]].data.rho;
276  else
277  return maxdensity; // there are no hits
278  double dist2 = 0.;
279  // start by setting delta for the highest density hit to
280  // the most distant hit - this is a convention
281 
282  for (auto &j : nd) {
283  double tmp = distance2(nd[rs[0]].data, j.data);
284  if (tmp > dist2)
285  dist2 = tmp;
286  }
287  nd[rs[0]].data.delta = std::sqrt(dist2);
288  nd[rs[0]].data.nearestHigher = nearestHigher;
289 
290  // now we save the largest distance as a starting point
291  const double max_dist2 = dist2;
292  const unsigned int nd_size = nd.size();
293 
294  for (unsigned int oi = 1; oi < nd_size;
295  ++oi) { // start from second-highest density
296  dist2 = max_dist2;
297  unsigned int i = rs[oi];
298  // we only need to check up to oi since hits
299  // are ordered by decreasing density
300  // and all points coming BEFORE oi are guaranteed to have higher rho
301  // and the ones AFTER to have lower rho
302  for (unsigned int oj = 0; oj < oi; ++oj) {
303  unsigned int j = rs[oj];
304  double tmp = distance2(nd[i].data, nd[j].data);
305  if (tmp <= dist2) { // this "<=" instead of "<" addresses the (rare) case
306  // when there are only two hits
307  dist2 = tmp;
308  nearestHigher = j;
309  }
310  }
311  nd[i].data.delta = std::sqrt(dist2);
312  nd[i].data.nearestHigher =
313  nearestHigher; // this uses the original unsorted hitlist
314  }
315  return maxdensity;
316 }
318  std::vector<KDNode> &nd, KDTree &lp, double maxdensity, KDTreeBox &bounds,
319  const unsigned int layer,
320  std::vector<std::vector<KDNode>> &clustersOnLayer) const {
321 
322  // this is called once per layer and endcap...
323  // so when filling the cluster temporary vector of Hexels we resize each time
324  // by the number of clusters found. This is always equal to the number of
325  // cluster centers...
326 
327  unsigned int nClustersOnLayer = 0;
328  float delta_c; // critical distance
329  if (layer <= lastLayerEE)
330  delta_c = vecDeltas[0];
331  else if (layer <= lastLayerFH)
332  delta_c = vecDeltas[1];
333  else
334  delta_c = vecDeltas[2];
335 
336  std::vector<size_t> rs =
337  sorted_indices(nd); // indices sorted by decreasing rho
338  std::vector<size_t> ds =
339  sort_by_delta(nd); // sort in decreasing distance to higher
340 
341  const unsigned int nd_size = nd.size();
342  for (unsigned int i = 0; i < nd_size; ++i) {
343 
344  if (nd[ds[i]].data.delta < delta_c)
345  break; // no more cluster centers to be looked at
346  if (dependSensor) {
347 
348  float rho_c = kappa * nd[ds[i]].data.sigmaNoise;
349  if (nd[ds[i]].data.rho < rho_c)
350  continue; // set equal to kappa times noise threshold
351 
352  } else if (nd[ds[i]].data.rho * kappa < maxdensity)
353  continue;
354 
355  nd[ds[i]].data.clusterIndex = nClustersOnLayer;
356  if (verbosity < pINFO) {
357  std::cout << "Adding new cluster with index " << nClustersOnLayer
358  << std::endl;
359  std::cout << "Cluster center is hit " << ds[i] << std::endl;
360  }
361  nClustersOnLayer++;
362  }
363 
364  // at this point nClustersOnLayer is equal to the number of cluster centers -
365  // if it is zero we are done
366  if (nClustersOnLayer == 0)
367  return nClustersOnLayer;
368 
369  // assign remaining points to clusters, using the nearestHigher set from
370  // previous step (always set except
371  // for top density hit that is skipped...)
372  for (unsigned int oi = 1; oi < nd_size; ++oi) {
373  unsigned int i = rs[oi];
374  int ci = nd[i].data.clusterIndex;
375  if (ci ==
376  -1) { // clusterIndex is initialised with -1 if not yet used in cluster
377  nd[i].data.clusterIndex = nd[nd[i].data.nearestHigher].data.clusterIndex;
378  }
379  }
380 
381  // make room in the temporary cluster vector for the additional clusterIndex
382  // clusters
383  // from this layer
384  if (verbosity < pINFO) {
385  std::cout << "resizing cluster vector by " << nClustersOnLayer << std::endl;
386  }
387  clustersOnLayer.resize(nClustersOnLayer);
388 
389  // assign points closer than dc to other clusters to border region
390  // and find critical border density
391  std::vector<double> rho_b(nClustersOnLayer, 0.);
392  lp.clear();
393  lp.build(nd, bounds);
394  // now loop on all hits again :( and check: if there are hits from another
395  // cluster within d_c -> flag as border hit
396  for (unsigned int i = 0; i < nd_size; ++i) {
397  int ci = nd[i].data.clusterIndex;
398  bool flag_isolated = true;
399  if (ci != -1) {
400  KDTreeBox search_box(nd[i].dims[0] - delta_c, nd[i].dims[0] + delta_c,
401  nd[i].dims[1] - delta_c, nd[i].dims[1] + delta_c);
402  std::vector<KDNode> found;
403  lp.search(search_box, found);
404 
405  const unsigned int found_size = found.size();
406  for (unsigned int j = 0; j < found_size;
407  j++) { // start from 0 here instead of 1
408  // check if the hit is not within d_c of another cluster
409  if (found[j].data.clusterIndex != -1) {
410  float dist = distance(found[j].data, nd[i].data);
411  if (dist < delta_c && found[j].data.clusterIndex != ci) {
412  // in which case we assign it to the border
413  nd[i].data.isBorder = true;
414  break;
415  }
416  // because we are using two different containers, we have to make sure
417  // that we don't unflag the
418  // hit when it finds *itself* closer than delta_c
419  if (dist < delta_c && dist != 0. &&
420  found[j].data.clusterIndex == ci) {
421  // in this case it is not an isolated hit
422  // the dist!=0 is because the hit being looked at is also inside the
423  // search box and at dist==0
424  flag_isolated = false;
425  }
426  }
427  }
428  if (flag_isolated)
429  nd[i].data.isBorder =
430  true; // the hit is more than delta_c from any of its brethren
431  }
432  // check if this border hit has density larger than the current rho_b and
433  // update
434  if (nd[i].data.isBorder && rho_b[ci] < nd[i].data.rho)
435  rho_b[ci] = nd[i].data.rho;
436  } // end loop all hits
437 
438  // flag points in cluster with density < rho_b as halo points, then fill the
439  // cluster vector
440  for (unsigned int i = 0; i < nd_size; ++i) {
441  int ci = nd[i].data.clusterIndex;
442  if (ci != -1) {
443  if (nd[i].data.rho <= rho_b[ci])
444  nd[i].data.isHalo = true;
445  clustersOnLayer[ci].push_back(nd[i]);
446  if (verbosity < pINFO) {
447  std::cout << "Pushing hit " << i << " into cluster with index " << ci
448  << std::endl;
449  }
450  }
451  }
452 
453  // prepare the offset for the next layer if there is one
454  if (verbosity < pINFO) {
455  std::cout << "moving cluster offset by " << nClustersOnLayer << std::endl;
456  }
457  return nClustersOnLayer;
458 }
459 
460 // find local maxima within delta_c, marking the indices in the cluster
461 std::vector<unsigned>
462 HGCalImagingAlgo::findLocalMaximaInCluster(const std::vector<KDNode> &cluster) {
463  std::vector<unsigned> result;
464  std::vector<bool> seed(cluster.size(), true);
465  float delta_c = 2.;
466 
467  for (unsigned i = 0; i < cluster.size(); ++i) {
468  for (unsigned j = 0; j < cluster.size(); ++j) {
469  if (i != j and distance(cluster[i].data, cluster[j].data) < delta_c) {
470  if (cluster[i].data.weight < cluster[j].data.weight) {
471  seed[i] = false;
472  break;
473  }
474  }
475  }
476  }
477 
478  for (unsigned i = 0; i < cluster.size(); ++i) {
479  if (seed[i] && cluster[i].data.weight > 5e-4) {
480  // seed at i with energy cluster[i].weight
481  result.push_back(i);
482  }
483  }
484 
485  // Found result.size() sub-clusters in input cluster of length cluster.size()
486 
487  return result;
488 }
489 
491  const std::vector<KDNode> &hits, const std::vector<double> &fractions) {
492  double norm(0.0), x(0.0), y(0.0), z(0.0);
493  for (unsigned i = 0; i < hits.size(); ++i) {
494  const double weight = fractions[i] * hits[i].data.weight;
495  norm += weight;
496  x += weight * hits[i].data.x;
497  y += weight * hits[i].data.y;
498  z += weight * hits[i].data.z;
499  }
500  math::XYZPoint result(x, y, z);
501  result /= norm;
502  return result;
503 }
504 
506  const std::vector<KDNode> &hits, const std::vector<double> &fractions) {
507  double result = 0.0;
508  for (unsigned i = 0; i < hits.size(); ++i) {
509  result += fractions[i] * hits[i].data.weight;
510  }
511  return result;
512 }
513 
515  const std::vector<KDNode> &incluster, const std::vector<unsigned> &seeds,
516  std::vector<std::vector<double>> &outclusters) {
517  std::vector<bool> isaseed(incluster.size(), false);
518  outclusters.clear();
519  outclusters.resize(seeds.size());
520  std::vector<Point> centroids(seeds.size());
521  std::vector<double> energies(seeds.size());
522 
523  if (seeds.size() == 1) { // short circuit the case of a lone cluster
524  outclusters[0].clear();
525  outclusters[0].resize(incluster.size(), 1.0);
526  return;
527  }
528 
529  // saving seeds
530 
531  // create quick seed lookup
532  for (unsigned i = 0; i < seeds.size(); ++i) {
533  isaseed[seeds[i]] = true;
534  }
535 
536  // initialize clusters to be shared
537  // centroids start off at seed positions
538  // seeds always have fraction 1.0, to stabilize fit
539  // initializing fit
540  for (unsigned i = 0; i < seeds.size(); ++i) {
541  outclusters[i].resize(incluster.size(), 0.0);
542  for (unsigned j = 0; j < incluster.size(); ++j) {
543  if (j == seeds[i]) {
544  outclusters[i][j] = 1.0;
545  centroids[i] = math::XYZPoint(incluster[j].data.x, incluster[j].data.y,
546  incluster[j].data.z);
547  energies[i] = incluster[j].data.weight;
548  }
549  }
550  }
551 
552  // run the fit while we are less than max iterations, and clusters are still
553  // moving
554  const double minFracTot = 1e-20;
555  unsigned iter = 0;
556  const unsigned iterMax = 50;
558  const double stoppingTolerance = 1e-8;
559  const auto numberOfSeeds = seeds.size();
560  auto toleranceScaling =
561  numberOfSeeds > 2 ? (numberOfSeeds - 1) * (numberOfSeeds - 1) : 1;
562  std::vector<Point> prevCentroids;
563  std::vector<double> frac(numberOfSeeds), dist2(numberOfSeeds);
564  while (iter++ < iterMax && diff > stoppingTolerance * toleranceScaling) {
565  for (unsigned i = 0; i < incluster.size(); ++i) {
566  const Hexel &ihit = incluster[i].data;
567  double fracTot(0.0);
568  for (unsigned j = 0; j < numberOfSeeds; ++j) {
569  double fraction = 0.0;
570  double d2 = (std::pow(ihit.x - centroids[j].x(), 2.0) +
571  std::pow(ihit.y - centroids[j].y(), 2.0) +
572  std::pow(ihit.z - centroids[j].z(), 2.0)) /
573  sigma2;
574  dist2[j] = d2;
575  // now we set the fractions up based on hit type
576  if (i == seeds[j]) { // this cluster's seed
577  fraction = 1.0;
578  } else if (isaseed[i]) {
579  fraction = 0.0;
580  } else {
581  fraction = energies[j] * std::exp(-0.5 * d2);
582  }
583  fracTot += fraction;
584  frac[j] = fraction;
585  }
586  // now that we have calculated all fractions for all hits
587  // assign the new fractions
588  for (unsigned j = 0; j < numberOfSeeds; ++j) {
589  if (fracTot > minFracTot || (i == seeds[j] && fracTot > 0.0)) {
590  outclusters[j][i] = frac[j] / fracTot;
591  } else {
592  outclusters[j][i] = 0.0;
593  }
594  }
595  }
596 
597  // save previous centroids
598  prevCentroids = std::move(centroids);
599  // finally update the position of the centroids from the last iteration
600  centroids.resize(numberOfSeeds);
601  double diff2 = 0.0;
602  for (unsigned i = 0; i < numberOfSeeds; ++i) {
603  centroids[i] = calculatePositionWithFraction(incluster, outclusters[i]);
604  energies[i] = calculateEnergyWithFraction(incluster, outclusters[i]);
605  // calculate convergence parameters
606  const double delta2 = (prevCentroids[i] - centroids[i]).perp2();
607  diff2 = std::max(delta2, diff2);
608  }
609  // update convergance parameter outside loop
610  diff = std::sqrt(diff2);
611  }
612 }
613 
615 
616  if (initialized)
617  return; // only need to calculate thresholds once
618 
619  std::vector<double> dummy;
620  const unsigned maxNumberOfThickIndices = 3;
621  dummy.resize(maxNumberOfThickIndices, 0);
622  thresholds.resize(maxlayer, dummy);
623  v_sigmaNoise.resize(maxlayer, dummy);
624 
625  for (unsigned ilayer = 1; ilayer <= maxlayer; ++ilayer) {
626  for (unsigned ithick = 0; ithick < maxNumberOfThickIndices; ++ithick) {
627  float sigmaNoise =
628  0.001f * fcPerEle * nonAgedNoises[ithick] * dEdXweights[ilayer] /
629  (fcPerMip[ithick] * thicknessCorrection[ithick]);
630  thresholds[ilayer - 1][ithick] = sigmaNoise * ecut;
631  v_sigmaNoise[ilayer - 1][ithick] = sigmaNoise;
632  }
633  }
634 
635  // now BH, much faster
636  for (unsigned ilayer = lastLayerFH + 1; ilayer <= maxlayer; ++ilayer) {
637  float sigmaNoise = 0.001f * noiseMip * dEdXweights[ilayer];
638  std::vector<double> bhDummy_thresholds;
639  std::vector<double> bhDummy_sigmaNoise;
640  bhDummy_thresholds.push_back(sigmaNoise * ecut);
641  bhDummy_sigmaNoise.push_back(sigmaNoise);
642  thresholds[ilayer - 1] = bhDummy_thresholds;
643  v_sigmaNoise[ilayer - 1] = bhDummy_sigmaNoise;
644  }
645  initialized = true;
646 }
constexpr float energy() const
Definition: CaloRecHit.h:31
bool isHalfCell(const DetId &) const
Definition: RecHitTools.cc:332
double calculateEnergyWithFraction(const std::vector< KDNode > &, const std::vector< double > &)
hgcal::RecHitTools rhtools_
math::XYZPoint calculatePositionWithFraction(const std::vector< KDNode > &, const std::vector< double > &)
std::vector< double > dEdXweights
reco::CaloCluster::AlgoId algoId
static const unsigned int maxlayer
double calculateLocalDensity(std::vector< KDNode > &, KDTree &, const unsigned int) const
int zside(const DetId &id) const
Definition: RecHitTools.cc:146
std::vector< std::array< float, 2 > > minpos
std::vector< double > vecDeltas
std::vector< std::vector< double > > thresholds
std::vector< std::array< float, 2 > > maxpos
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > &region)
constexpr const DetId & detid() const
Definition: CaloRecHit.h:35
math::XYZPoint Point
point in the space
std::vector< double > thicknessCorrection
std::vector< double > nonAgedNoises
Definition: weight.py:1
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
double distance2(const Hexel &pt1, const Hexel &pt2) const
void shareEnergy(const std::vector< KDNode > &, const std::vector< unsigned > &, std::vector< std::vector< double > > &)
static const unsigned int lastLayerEE
double distance(const Hexel &pt1, const Hexel &pt2) const
T sqrt(T t)
Definition: SSEVec.h:18
static const unsigned int lastLayerFH
VerbosityLevel verbosity
T min(T a, T b)
Definition: MathUtil.h:58
std::vector< size_t > sorted_indices(const std::vector< T > &v)
std::vector< reco::BasicCluster > getClusters(bool)
std::vector< unsigned > findLocalMaximaInCluster(const std::vector< KDNode > &)
std::float_t getSiThickness(const DetId &) const
Definition: RecHitTools.cc:160
Definition: DetId.h:18
std::vector< std::vector< KDNode > > points
unsigned int getLayerWithOffset(const DetId &) const
Definition: RecHitTools.cc:294
int getSiThickIndex(const DetId &) const
Definition: RecHitTools.cc:179
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
T perp2() const
Squared magnitude of transverse component.
GlobalPoint getPosition(const DetId &id) const
Definition: RecHitTools.cc:116
std::vector< std::vector< double > > v_sigmaNoise
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
size_type size() const
double calculateDistanceToHigher(std::vector< KDNode > &) const
static int position[264][3]
Definition: ReadPGInfo.cc:509
math::XYZPoint calculatePosition(std::vector< KDNode > &) const
std::vector< std::vector< std::vector< KDNode > > > layerClustersPerLayer
std::vector< double > fcPerMip
void populate(const HGCRecHitCollection &hits)
std::vector< size_t > sort_by_delta(const std::vector< KDNode > &v) const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
def move(src, dest)
Definition: eostools.py:510
std::vector< reco::BasicCluster > clusters_v
int findAndAssignClusters(std::vector< KDNode > &, KDTree &, double, KDTreeBox &, const unsigned int, std::vector< std::vector< KDNode > > &) const