12 #include "tbb/task_arena.h" 26 std::vector<bool> firstHit(2 * (maxlayer + 1),
true);
27 for (
unsigned int i = 0;
i < hits.
size(); ++
i) {
31 unsigned int layer = rhtools_.getLayerWithOffset(detid);
32 float thickness = 0.f;
35 float sigmaNoise = 1.f;
37 thickness = rhtools_.getSiThickness(detid);
38 int thickness_index = rhtools_.getSiThickIndex(detid);
39 if (thickness_index == -1)
41 double storedThreshold = thresholds_[layer - 1][thickness_index];
42 sigmaNoise = sigmaNoise_[layer - 1][thickness_index];
44 if (hgrh.
energy() < storedThreshold)
48 if (!dependSensor_ && hgrh.
energy() < ecut_)
53 layer +=
int(rhtools_.zside(detid) > 0) * (maxlayer + 1);
56 bool isHalf = rhtools_.isHalfCell(detid);
61 points_[layer].emplace_back(
62 Hexel(hgrh, detid, isHalf, sigmaNoise, thickness, &rhtools_),
67 if (firstHit[layer]) {
72 firstHit[layer] =
false;
87 layerClustersPerLayer_.resize(2 * maxlayer + 2);
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]);
93 hit_kdtree.
build(points_[i], bounds);
95 unsigned int actualLayer =
97 ? (i - (maxlayer + 1))
100 double maxdensity = calculateLocalDensity(
101 points_[i], hit_kdtree, actualLayer);
105 calculateDistanceToHigher(points_[i]);
106 findAndAssignClusters(points_[i], hit_kdtree, maxdensity, bounds,
107 actualLayer, layerClustersPerLayer_[i]);
111 for(
auto const&
p: points_) { setDensity(
p); }
117 std::vector<std::pair<DetId, float>> thisCluster;
118 for (
auto &clsOnLayer : layerClustersPerLayer_) {
119 for (
unsigned int i = 0;
i < clsOnLayer.size(); ++
i) {
128 std::vector<unsigned> seeds = findLocalMaximaInCluster(clsOnLayer[i]);
131 std::vector<std::vector<double>> fractions;
133 shareEnergy(clsOnLayer[i], seeds, fractions);
138 for (
unsigned isub = 0; isub < fractions.size(); ++isub) {
139 double effective_hits = 0.0;
141 calculateEnergyWithFraction(clsOnLayer[i], fractions[isub]);
143 calculatePositionWithFraction(clsOnLayer[i], fractions[isub]);
145 for (
unsigned ihit = 0; ihit < fractions[isub].size(); ++ihit) {
146 const double fraction = fractions[isub][ihit];
147 if (fraction > 1
e-7) {
149 thisCluster.emplace_back(clsOnLayer[i][ihit].
data.detid,
154 if (verbosity_ < pINFO) {
155 std::cout <<
"\t******** NEW CLUSTER (SHARING) ********" 157 std::cout <<
"\tEff. No. of cells = " << effective_hits
159 std::cout <<
"\t Energy = " << energy << std::endl;
160 std::cout <<
"\t Phi = " << position.phi()
162 std::cout <<
"\t Eta = " << position.eta()
164 std::cout <<
"\t*****************************" << std::endl;
166 clusters_v_.emplace_back(energy, position, caloID, thisCluster,
168 if (!clusters_v_.empty()){ clusters_v_.back().setSeed( clsOnLayer[i][rsmax].
data.detid); }
174 for (
auto &it : clsOnLayer[i]) {
175 energy += it.data.isHalo ? 0. : it.data.weight;
177 thisCluster.emplace_back(it.data.detid, (it.data.isHalo ? 0.f : 1.f));
179 if (verbosity_ < pINFO) {
180 std::cout <<
"******** NEW CLUSTER (HGCIA) ********" << std::endl;
182 std::cout <<
"No. of cells = " << clsOnLayer[
i].size() << std::endl;
183 std::cout <<
" Energy = " << energy << std::endl;
184 std::cout <<
" Phi = " << position.phi() << std::endl;
185 std::cout <<
" Eta = " << position.eta() << std::endl;
186 std::cout <<
"*****************************" << std::endl;
188 clusters_v_.emplace_back(energy, position, caloID, thisCluster, algoId_);
189 if (!clusters_v_.empty()){ clusters_v_.back().setSeed( clsOnLayer[i][rsmax].
data.detid); }
199 float total_weight = 0.f;
203 unsigned int v_size = v.size();
204 unsigned int maxEnergyIndex = 0;
205 float maxEnergyValue = 0;
209 for (
unsigned int i = 0;
i < v_size;
i++) {
210 if (v[
i].
data.weight > maxEnergyValue) {
211 maxEnergyValue = v[
i].data.weight;
217 int thick = rhtools_.getSiThickIndex(v[maxEnergyIndex].
data.detid);
222 std::vector<unsigned int> innerIndices;
223 for (
unsigned int i = 0;
i < v_size;
i++) {
225 distance2(v[
i].
data, v[maxEnergyIndex].data) < positionDeltaRho_c_[thick]){
226 innerIndices.push_back(
i);
228 float rhEnergy = v[
i].data.weight;
229 total_weight += rhEnergy;
233 x += v[
i].data.x * rhEnergy;
234 y += v[
i].data.y * rhEnergy;
240 if(thick != -1 && total_weight != 0.){
241 float total_weight_log = 0.f;
244 for (
auto idx : innerIndices) {
245 float rhEnergy = v[
idx].data.weight;
246 if(rhEnergy == 0.)
continue;
247 float Wi =
std::max(thresholdW0_[thick] +
log(rhEnergy/total_weight), 0.);
248 x_log += v[
idx].data.x * Wi;
249 y_log += v[
idx].data.y * Wi;
250 total_weight_log += Wi;
252 total_weight = total_weight_log;
257 if (total_weight != 0.) {
258 auto inv_tot_weight = 1. / total_weight;
261 v[maxEnergyIndex].
data.z);
268 const unsigned int layer)
const {
270 double maxdensity = 0.;
273 if (layer <= lastLayerEE)
274 delta_c = vecDeltas_[0];
275 else if (layer <= lastLayerFH)
276 delta_c = vecDeltas_[1];
278 delta_c = vecDeltas_[2];
281 for (
unsigned int i = 0;
i < nd.size(); ++
i) {
283 KDTreeBox search_box(nd[
i].dims[0] - delta_c, nd[
i].dims[0] + delta_c,
284 nd[
i].dims[1] - delta_c, nd[
i].dims[1] + delta_c);
285 std::vector<KDNode>
found;
286 lp.
search(search_box, found);
287 const unsigned int found_size = found.size();
288 for (
unsigned int j = 0; j < found_size; j++) {
290 nd[
i].data.rho += found[j].data.weight;
291 maxdensity =
std::max(maxdensity, nd[
i].data.rho);
304 double maxdensity = 0.0;
305 int nearestHigher = -1;
308 maxdensity = nd[rs[0]].
data.rho;
316 double tmp = distance2(nd[rs[0]].
data, j.data);
321 nd[rs[0]].data.nearestHigher = nearestHigher;
324 const double max_dist2 = dist2;
325 const unsigned int nd_size = nd.size();
327 for (
unsigned int oi = 1; oi < nd_size;
330 unsigned int i = rs[oi];
335 for (
unsigned int oj = 0; oj < oi; ++oj) {
336 unsigned int j = rs[oj];
338 if ((nd[i].
data.x - nd[j].data.x)*(nd[i].data.x - nd[j].data.x) > dist2)
continue;
339 if ((nd[i].
data.y - nd[j].data.y)*(nd[i].data.y - nd[j].data.y) > dist2)
continue;
340 double tmp = distance2(nd[i].
data, nd[j].data);
348 nd[
i].data.nearestHigher =
354 std::vector<KDNode> &nd,
KDTree &lp,
double maxdensity,
KDTreeBox &bounds,
355 const unsigned int layer,
356 std::vector<std::vector<KDNode>> &clustersOnLayer)
const {
363 unsigned int nClustersOnLayer = 0;
365 if (layer <= lastLayerEE)
366 delta_c = vecDeltas_[0];
367 else if (layer <= lastLayerFH)
368 delta_c = vecDeltas_[1];
370 delta_c = vecDeltas_[2];
372 std::vector<size_t> rs =
374 std::vector<size_t> ds =
377 const unsigned int nd_size = nd.size();
378 for (
unsigned int i = 0;
i < nd_size; ++
i) {
380 if (nd[ds[
i]].
data.delta < delta_c)
384 float rho_c = kappa_ * nd[ds[
i]].data.sigmaNoise;
385 if (nd[ds[
i]].
data.rho < rho_c)
388 }
else if (nd[ds[
i]].
data.rho * kappa_ < maxdensity)
391 nd[ds[
i]].data.clusterIndex = nClustersOnLayer;
392 if (verbosity_ < pINFO) {
393 std::cout <<
"Adding new cluster with index " << nClustersOnLayer
395 std::cout <<
"Cluster center is hit " << ds[
i] << std::endl;
402 if (nClustersOnLayer == 0)
403 return nClustersOnLayer;
408 for (
unsigned int oi = 1; oi < nd_size; ++oi) {
409 unsigned int i = rs[oi];
410 int ci = nd[
i].data.clusterIndex;
413 nd[
i].data.clusterIndex = nd[nd[
i].data.nearestHigher].data.clusterIndex;
420 if (verbosity_ < pINFO) {
421 std::cout <<
"resizing cluster vector by " << nClustersOnLayer << std::endl;
423 clustersOnLayer.resize(nClustersOnLayer);
427 std::vector<double> rho_b(nClustersOnLayer, 0.);
429 lp.
build(nd, bounds);
432 for (
unsigned int i = 0;
i < nd_size; ++
i) {
433 int ci = nd[
i].data.clusterIndex;
434 bool flag_isolated =
true;
436 KDTreeBox search_box(nd[
i].dims[0] - delta_c, nd[
i].dims[0] + delta_c,
437 nd[
i].dims[1] - delta_c, nd[
i].dims[1] + delta_c);
438 std::vector<KDNode>
found;
439 lp.
search(search_box, found);
441 const unsigned int found_size = found.size();
442 for (
unsigned int j = 0; j < found_size;
445 if (found[j].
data.clusterIndex != -1) {
447 if (dist < delta_c && found[j].data.clusterIndex != ci) {
449 nd[
i].data.isBorder =
true;
455 if (dist < delta_c && dist != 0. &&
456 found[j].data.clusterIndex == ci) {
460 flag_isolated =
false;
465 nd[
i].data.isBorder =
470 if (nd[
i].
data.isBorder && rho_b[ci] < nd[
i].data.rho)
471 rho_b[ci] = nd[
i].data.rho;
476 for (
unsigned int i = 0;
i < nd_size; ++
i) {
477 int ci = nd[
i].data.clusterIndex;
479 if (nd[
i].
data.rho <= rho_b[ci])
480 nd[
i].data.isHalo =
true;
481 clustersOnLayer[ci].push_back(nd[
i]);
482 if (verbosity_ < pINFO) {
483 std::cout <<
"Pushing hit " << i <<
" into cluster with index " << ci
490 if (verbosity_ < pINFO) {
491 std::cout <<
"moving cluster offset by " << nClustersOnLayer << std::endl;
493 return nClustersOnLayer;
497 std::vector<unsigned>
499 std::vector<unsigned>
result;
500 std::vector<bool>
seed(cluster.size(),
true);
503 for (
unsigned i = 0;
i < cluster.size(); ++
i) {
504 for (
unsigned j = 0; j < cluster.size(); ++j) {
505 if (
i != j and
distance(cluster[
i].
data, cluster[j].data) < delta_c) {
506 if (cluster[
i].data.weight < cluster[j].data.weight) {
514 for (
unsigned i = 0;
i < cluster.size(); ++
i) {
527 const std::vector<KDNode> &
hits,
const std::vector<double> &fractions) {
528 double norm(0.0), x(0.0), y(0.0), z(0.0);
529 for (
unsigned i = 0;
i < hits.size(); ++
i) {
530 const double weight = fractions[
i] * hits[
i].data.weight;
532 x += weight * hits[
i].data.x;
533 y += weight * hits[
i].data.y;
534 z += weight * hits[
i].data.z;
542 const std::vector<KDNode> &
hits,
const std::vector<double> &fractions) {
544 for (
unsigned i = 0;
i < hits.size(); ++
i) {
545 result += fractions[
i] * hits[
i].data.weight;
551 const std::vector<KDNode> &incluster,
const std::vector<unsigned> &seeds,
552 std::vector<std::vector<double>> &outclusters) {
553 std::vector<bool> isaseed(incluster.size(),
false);
555 outclusters.resize(seeds.size());
556 std::vector<Point> centroids(seeds.size());
557 std::vector<double> energies(seeds.size());
559 if (seeds.size() == 1) {
560 outclusters[0].clear();
561 outclusters[0].resize(incluster.size(), 1.0);
568 for (
unsigned i = 0;
i < seeds.size(); ++
i) {
569 isaseed[seeds[
i]] =
true;
576 for (
unsigned i = 0;
i < seeds.size(); ++
i) {
577 outclusters[
i].resize(incluster.size(), 0.0);
578 for (
unsigned j = 0; j < incluster.size(); ++j) {
580 outclusters[
i][j] = 1.0;
582 incluster[j].data.z);
583 energies[
i] = incluster[j].data.weight;
592 const unsigned iterMax = 50;
595 const auto numberOfSeeds = seeds.size();
596 auto toleranceScaling =
597 numberOfSeeds > 2 ? (numberOfSeeds - 1) * (numberOfSeeds - 1) : 1;
598 std::vector<Point> prevCentroids;
599 std::vector<double>
frac(numberOfSeeds), dist2(numberOfSeeds);
600 while (iter++ < iterMax && diff > stoppingTolerance * toleranceScaling) {
601 for (
unsigned i = 0;
i < incluster.size(); ++
i) {
602 const Hexel &ihit = incluster[
i].data;
604 for (
unsigned j = 0; j < numberOfSeeds; ++j) {
606 double d2 = (
std::pow(ihit.
x - centroids[j].x(), 2.0) +
607 std::pow(ihit.
y - centroids[j].y(), 2.0) +
608 std::pow(ihit.
z - centroids[j].z(), 2.0)) /
614 }
else if (isaseed[
i]) {
617 fraction = energies[j] *
std::exp(-0.5 * d2);
624 for (
unsigned j = 0; j < numberOfSeeds; ++j) {
625 if (fracTot > minFracTot || (
i == seeds[j] && fracTot > 0.0)) {
626 outclusters[j][
i] =
frac[j] / fracTot;
628 outclusters[j][
i] = 0.0;
636 centroids.resize(numberOfSeeds);
638 for (
unsigned i = 0;
i < numberOfSeeds; ++
i) {
639 centroids[
i] = calculatePositionWithFraction(incluster, outclusters[
i]);
640 energies[
i] = calculateEnergyWithFraction(incluster, outclusters[i]);
642 const double delta2 = (prevCentroids[
i] - centroids[
i]).
perp2();
663 std::vector<double>
dummy;
664 const unsigned maxNumberOfThickIndices = 3;
665 dummy.resize(maxNumberOfThickIndices + 1, 0);
666 thresholds_.resize(maxlayer, dummy);
667 sigmaNoise_.resize(maxlayer, dummy);
669 for (
unsigned ilayer = 1; ilayer <= maxlayer; ++ilayer) {
670 for (
unsigned ithick = 0; ithick < maxNumberOfThickIndices; ++ithick) {
672 0.001f * fcPerEle_ * nonAgedNoises_[ithick] * dEdXweights_[ilayer] /
673 (fcPerMip_[ithick] * thicknessCorrection_[ithick]);
674 thresholds_[ilayer - 1][ithick] = sigmaNoise * ecut_;
675 sigmaNoise_[ilayer - 1][ithick] = sigmaNoise;
677 float scintillators_sigmaNoise = 0.001f * noiseMip_ * dEdXweights_[ilayer];
678 thresholds_[ilayer - 1][maxNumberOfThickIndices] = ecut_ * scintillators_sigmaNoise;
679 sigmaNoise_[ilayer -1][maxNumberOfThickIndices] = scintillators_sigmaNoise;
688 density_[
i.data.detid ] =
i.data.rho ;
constexpr float energy() const
double calculateEnergyWithFraction(const std::vector< KDNode > &, const std::vector< double > &)
math::XYZPoint calculatePositionWithFraction(const std::vector< KDNode > &, const std::vector< double > &)
double calculateLocalDensity(std::vector< KDNode > &, KDTree &, const unsigned int) const
constexpr const DetId & detid() const
std::vector< reco::BasicCluster > getClusters(bool) override
void makeClusters() override
hgcal_clustering::Density Density
void shareEnergy(const std::vector< KDNode > &, const std::vector< unsigned > &, std::vector< std::vector< double > > &)
std::pair< double, double > calculatePosition(TVirtualPad *myPad, int boundary)
std::vector< size_t > sorted_indices(const std::vector< T > &v)
void search(const KDTreeBox &searchBox, std::vector< DATA > &resRecHitList)
void setDensity(const std::vector< KDNode > &nd)
std::vector< unsigned > findLocalMaximaInCluster(const std::vector< KDNode > &)
Density getDensity() override
void populate(const HGCRecHitCollection &hits) override
void build(std::vector< KDTreeNodeInfo< DATA > > &eltList, const KDTreeBox ®ion)
XYZPointD XYZPoint
point in space with cartesian internal representation
T perp2() const
Squared magnitude of transverse component.
std::vector< std::vector< double > > tmp
char data[epos_bytes_allocation]
double calculateDistanceToHigher(std::vector< KDNode > &) const
Structure Point Contains parameters of Gaussian fits to DMRs.
static int position[264][3]
math::XYZPoint calculatePosition(std::vector< KDNode > &) const
size_t max_index(const std::vector< T > &v)
Power< A, B >::type pow(const A &a, const B &b)
int findAndAssignClusters(std::vector< KDNode > &, KDTree &, double, KDTreeBox &, const unsigned int, std::vector< std::vector< KDNode > > &) const