12 #include "oneapi/tbb/task_arena.h"
13 #include "oneapi/tbb.h"
15 using namespace hgcal_clustering;
21 points_.resize(2 * (maxlayer_ + 1));
22 minpos_.resize(2 * (maxlayer_ + 1), {{0.0f, 0.0f}});
23 maxpos_.resize(2 * (maxlayer_ + 1), {{0.0f, 0.0f}});
35 std::vector<bool> firstHit(2 * (maxlayer_ + 1),
true);
36 for (
unsigned int i = 0;
i < hits.
size(); ++
i) {
39 unsigned int layer = rhtools_.getLayerWithOffset(detid);
43 float sigmaNoise = 1.f;
45 thickness = rhtools_.getSiThickness(detid);
46 int thickness_index = rhtools_.getSiThickIndex(detid);
47 if (thickness_index == -1)
49 double storedThreshold = thresholds_[layer - 1][thickness_index];
50 sigmaNoise = sigmaNoise_[layer - 1][thickness_index];
52 if (hgrh.
energy() < storedThreshold)
56 if (!dependSensor_ && hgrh.
energy() < ecut_)
61 layer += int(rhtools_.zside(detid) > 0) * (maxlayer_ + 1);
64 bool isHalf = rhtools_.isHalfCell(detid);
69 points_[
layer].emplace_back(
74 if (firstHit[layer]) {
79 firstHit[
layer] =
false;
94 layerClustersPerLayer_.resize(2 * maxlayer_ + 2);
96 tbb::this_task_arena::isolate([&] {
97 tbb::parallel_for(
size_t(0),
size_t(2 * maxlayer_ + 2), [&](
size_t i) {
98 KDTreeBox bounds(minpos_[i][0], maxpos_[i][0], minpos_[i][1], maxpos_[i][1]);
100 hit_kdtree.
build(points_[i], bounds);
102 unsigned int actualLayer =
103 i > maxlayer_ ? (i - (maxlayer_ + 1)) :
i;
105 double maxdensity = calculateLocalDensity(points_[i], hit_kdtree, actualLayer);
109 calculateDistanceToHigher(points_[i]);
110 findAndAssignClusters(points_[i], hit_kdtree, maxdensity, bounds, actualLayer, layerClustersPerLayer_[i]);
114 for (
auto const &
p : points_) {
121 std::vector<std::pair<DetId, float>> thisCluster;
122 for (
auto &clsOnLayer : layerClustersPerLayer_) {
123 for (
unsigned int i = 0;
i < clsOnLayer.size(); ++
i) {
131 std::vector<unsigned>
seeds = findLocalMaximaInCluster(clsOnLayer[i]);
134 std::vector<std::vector<double>> fractions;
136 shareEnergy(clsOnLayer[i], seeds, fractions);
141 for (
unsigned isub = 0; isub < fractions.size(); ++isub) {
142 double effective_hits = 0.0;
143 double energy = calculateEnergyWithFraction(clsOnLayer[i], fractions[isub]);
144 Point position = calculatePositionWithFraction(clsOnLayer[i], fractions[isub]);
146 for (
unsigned ihit = 0; ihit < fractions[isub].size(); ++ihit) {
147 const double fraction = fractions[isub][ihit];
148 if (fraction > 1
e-7) {
150 thisCluster.emplace_back(clsOnLayer[i][ihit].
data.detid, fraction);
154 if (verbosity_ < pINFO) {
155 std::cout <<
"\t******** NEW CLUSTER (SHARING) ********" << std::endl;
156 std::cout <<
"\tEff. No. of cells = " << effective_hits << std::endl;
157 std::cout <<
"\t Energy = " << energy << std::endl;
158 std::cout <<
"\t Phi = " << position.phi() << std::endl;
159 std::cout <<
"\t Eta = " << position.eta() << std::endl;
160 std::cout <<
"\t*****************************" << std::endl;
162 clusters_v_.emplace_back(energy, position, caloID, thisCluster, algoId_);
163 if (!clusters_v_.empty()) {
164 clusters_v_.back().setSeed(clsOnLayer[i][rsmax].
data.detid);
171 for (
auto &it : clsOnLayer[i]) {
172 energy += it.data.isHalo ? 0. : it.data.weight;
174 thisCluster.emplace_back(it.data.detid, (it.data.isHalo ? 0.f : 1.f));
176 if (verbosity_ < pINFO) {
177 std::cout <<
"******** NEW CLUSTER (HGCIA) ********" << std::endl;
179 std::cout <<
"No. of cells = " << clsOnLayer[
i].size() << std::endl;
180 std::cout <<
" Energy = " << energy << std::endl;
181 std::cout <<
" Phi = " << position.phi() << std::endl;
182 std::cout <<
" Eta = " << position.eta() << std::endl;
183 std::cout <<
"*****************************" << std::endl;
185 clusters_v_.emplace_back(energy, position, caloID, thisCluster, algoId_);
186 if (!clusters_v_.empty()) {
187 clusters_v_.back().setSeed(clsOnLayer[i][rsmax].
data.detid);
197 float total_weight = 0.f;
201 unsigned int v_size = v.size();
202 unsigned int maxEnergyIndex = 0;
203 float maxEnergyValue = 0;
207 for (
unsigned int i = 0;
i < v_size;
i++) {
208 if (v[
i].
data.weight > maxEnergyValue) {
209 maxEnergyValue = v[
i].data.weight;
215 int thick = rhtools_.getSiThickIndex(v[maxEnergyIndex].
data.detid);
220 std::vector<unsigned int> innerIndices;
221 for (
unsigned int i = 0;
i < v_size;
i++) {
222 if (thick == -1 || distance2(v[
i].
data, v[maxEnergyIndex].data) < positionDeltaRho_c_[thick]) {
223 innerIndices.push_back(
i);
225 float rhEnergy = v[
i].data.weight;
226 total_weight += rhEnergy;
230 x += v[
i].data.x * rhEnergy;
231 y += v[
i].data.y * rhEnergy;
237 if (thick != -1 && total_weight != 0.) {
238 float total_weight_log = 0.f;
241 for (
auto idx : innerIndices) {
242 float rhEnergy = v[idx].data.weight;
245 float Wi =
std::max(thresholdW0_[thick] +
log(rhEnergy / total_weight), 0.);
246 x_log += v[idx].data.x * Wi;
247 y_log += v[idx].data.y * Wi;
248 total_weight_log += Wi;
250 total_weight = total_weight_log;
255 if (total_weight != 0.) {
256 auto inv_tot_weight = 1. / total_weight;
257 return math::XYZPoint(x * inv_tot_weight, y * inv_tot_weight, v[maxEnergyIndex].
data.z);
263 double maxdensity = 0.;
266 if (layer <= lastLayerEE_)
267 delta_c = vecDeltas_[0];
268 else if (layer < firstLayerBH_)
269 delta_c = vecDeltas_[1];
271 delta_c = vecDeltas_[2];
274 for (
unsigned int i = 0;
i < nd.size(); ++
i) {
277 nd[
i].dims[0] - delta_c, nd[
i].dims[0] + delta_c, nd[
i].dims[1] - delta_c, nd[
i].dims[1] + delta_c);
278 std::vector<Hexel>
found;
279 lp.
search(search_box, found);
280 const unsigned int found_size = found.size();
281 for (
unsigned int j = 0;
j < found_size;
j++) {
283 nd[
i].data.rho += found[
j].weight;
284 maxdensity =
std::max(maxdensity, nd[
i].data.rho);
295 double maxdensity = 0.0;
296 int nearestHigher = -1;
299 maxdensity = nd[rs[0]].
data.rho;
307 double tmp = distance2(nd[rs[0]].
data,
j.data);
312 nd[rs[0]].data.nearestHigher = nearestHigher;
315 const double max_dist2 = dist2;
316 const unsigned int nd_size = nd.size();
318 for (
unsigned int oi = 1; oi < nd_size; ++oi) {
320 unsigned int i = rs[oi];
325 for (
unsigned int oj = 0; oj < oi; ++oj) {
326 unsigned int j = rs[oj];
328 if ((nd[i].
data.x - nd[j].data.x) * (nd[i].data.x - nd[j].data.x) > dist2)
330 if ((nd[i].
data.y - nd[j].data.y) * (nd[i].data.y - nd[j].data.y) > dist2)
332 double tmp = distance2(nd[i].
data, nd[j].data);
340 nd[
i].data.nearestHigher = nearestHigher;
348 const unsigned int layer,
349 std::vector<std::vector<KDNode>> &clustersOnLayer)
const {
355 unsigned int nClustersOnLayer = 0;
357 if (layer <= lastLayerEE_)
358 delta_c = vecDeltas_[0];
359 else if (layer < firstLayerBH_)
360 delta_c = vecDeltas_[1];
362 delta_c = vecDeltas_[2];
365 std::vector<size_t> ds = sort_by_delta(nd);
367 const unsigned int nd_size = nd.size();
368 for (
unsigned int i = 0;
i < nd_size; ++
i) {
369 if (nd[ds[
i]].
data.delta < delta_c)
372 float rho_c = kappa_ * nd[ds[
i]].data.sigmaNoise;
373 if (nd[ds[
i]].
data.rho < rho_c)
376 }
else if (nd[ds[
i]].
data.rho * kappa_ < maxdensity)
379 nd[ds[
i]].data.clusterIndex = nClustersOnLayer;
380 if (verbosity_ < pINFO) {
381 std::cout <<
"Adding new cluster with index " << nClustersOnLayer << std::endl;
382 std::cout <<
"Cluster center is hit " << ds[
i] << std::endl;
389 if (nClustersOnLayer == 0)
390 return nClustersOnLayer;
395 for (
unsigned int oi = 1; oi < nd_size; ++oi) {
396 unsigned int i = rs[oi];
397 int ci = nd[
i].data.clusterIndex;
399 nd[
i].data.clusterIndex = nd[nd[
i].data.nearestHigher].data.clusterIndex;
406 if (verbosity_ < pINFO) {
407 std::cout <<
"resizing cluster vector by " << nClustersOnLayer << std::endl;
409 clustersOnLayer.resize(nClustersOnLayer);
413 std::vector<double> rho_b(nClustersOnLayer, 0.);
415 lp.
build(nd, bounds);
418 for (
unsigned int i = 0;
i < nd_size; ++
i) {
419 int ci = nd[
i].data.clusterIndex;
420 bool flag_isolated =
true;
423 nd[
i].dims[0] - delta_c, nd[
i].dims[0] + delta_c, nd[
i].dims[1] - delta_c, nd[
i].dims[1] + delta_c);
424 std::vector<Hexel>
found;
425 lp.
search(search_box, found);
427 const unsigned int found_size = found.size();
428 for (
unsigned int j = 0;
j < found_size;
j++) {
430 if (found[
j].clusterIndex != -1) {
432 if (dist < delta_c && found[j].clusterIndex != ci) {
434 nd[
i].data.isBorder =
true;
440 if (dist < delta_c && dist != 0. && found[j].clusterIndex == ci) {
444 flag_isolated =
false;
449 nd[
i].data.isBorder =
true;
453 if (nd[
i].
data.isBorder && rho_b[ci] < nd[
i].data.rho)
454 rho_b[ci] = nd[
i].data.rho;
459 for (
unsigned int i = 0;
i < nd_size; ++
i) {
460 int ci = nd[
i].data.clusterIndex;
462 if (nd[
i].
data.rho <= rho_b[ci])
463 nd[
i].data.isHalo =
true;
464 clustersOnLayer[ci].push_back(nd[
i]);
465 if (verbosity_ < pINFO) {
466 std::cout <<
"Pushing hit " << i <<
" into cluster with index " << ci << std::endl;
472 if (verbosity_ < pINFO) {
473 std::cout <<
"moving cluster offset by " << nClustersOnLayer << std::endl;
475 return nClustersOnLayer;
480 std::vector<unsigned>
result;
481 std::vector<bool>
seed(cluster.size(),
true);
484 for (
unsigned i = 0;
i < cluster.size(); ++
i) {
485 for (
unsigned j = 0;
j < cluster.size(); ++
j) {
487 if (cluster[
i].data.weight < cluster[
j].data.weight) {
495 for (
unsigned i = 0;
i < cluster.size(); ++
i) {
508 const std::vector<double> &fractions) {
509 double norm(0.0),
x(0.0), y(0.0), z(0.0);
510 for (
unsigned i = 0;
i < hits.size(); ++
i) {
511 const double weight = fractions[
i] * hits[
i].data.weight;
513 x += weight * hits[
i].data.x;
514 y += weight * hits[
i].data.y;
515 z += weight * hits[
i].data.z;
523 const std::vector<double> &fractions) {
525 for (
unsigned i = 0;
i < hits.size(); ++
i) {
526 result += fractions[
i] * hits[
i].data.weight;
532 const std::vector<unsigned> &
seeds,
534 std::vector<bool> isaseed(incluster.size(),
false);
536 outclusters.resize(seeds.size());
537 std::vector<Point> centroids(seeds.size());
538 std::vector<double> energies(seeds.size());
540 if (seeds.size() == 1) {
541 outclusters[0].clear();
542 outclusters[0].resize(incluster.size(), 1.0);
549 for (
unsigned i = 0;
i < seeds.size(); ++
i) {
550 isaseed[seeds[
i]] =
true;
557 for (
unsigned i = 0;
i < seeds.size(); ++
i) {
558 outclusters[
i].resize(incluster.size(), 0.0);
559 for (
unsigned j = 0;
j < incluster.size(); ++
j) {
561 outclusters[
i][
j] = 1.0;
563 energies[
i] = incluster[
j].data.weight;
570 const double minFracTot = 1
e-20;
572 const unsigned iterMax = 50;
574 const double stoppingTolerance = 1
e-8;
575 const auto numberOfSeeds = seeds.size();
576 auto toleranceScaling = numberOfSeeds > 2 ? (numberOfSeeds - 1) * (numberOfSeeds - 1) : 1;
577 std::vector<Point> prevCentroids;
578 std::vector<double>
frac(numberOfSeeds), dist2(numberOfSeeds);
579 while (iter++ < iterMax && diff > stoppingTolerance * toleranceScaling) {
580 for (
unsigned i = 0;
i < incluster.size(); ++
i) {
581 const Hexel &ihit = incluster[
i].data;
583 for (
unsigned j = 0;
j < numberOfSeeds; ++
j) {
585 double d2 = (
std::pow(ihit.
x - centroids[
j].x(), 2.0) +
std::pow(ihit.
y - centroids[
j].y(), 2.0) +
592 }
else if (isaseed[
i]) {
595 fraction = energies[
j] *
std::exp(-0.5 * d2);
602 for (
unsigned j = 0;
j < numberOfSeeds; ++
j) {
603 if (fracTot > minFracTot || (
i == seeds[
j] && fracTot > 0.0)) {
604 outclusters[
j][
i] =
frac[
j] / fracTot;
606 outclusters[
j][
i] = 0.0;
614 centroids.resize(numberOfSeeds);
616 for (
unsigned i = 0;
i < numberOfSeeds; ++
i) {
617 centroids[
i] = calculatePositionWithFraction(incluster, outclusters[
i]);
618 energies[
i] = calculateEnergyWithFraction(incluster, outclusters[i]);
620 const double delta2 = (prevCentroids[
i] - centroids[
i]).
perp2();
641 std::vector<double> dummy;
642 const unsigned maxNumberOfThickIndices = 3;
643 dummy.resize(maxNumberOfThickIndices + 1, 0);
644 thresholds_.resize(maxlayer_, dummy);
645 sigmaNoise_.resize(maxlayer_, dummy);
647 for (
unsigned ilayer = 1; ilayer <= maxlayer_; ++ilayer) {
648 for (
unsigned ithick = 0; ithick < maxNumberOfThickIndices; ++ithick) {
649 float sigmaNoise = 0.001f * fcPerEle_ * nonAgedNoises_[ithick] * dEdXweights_[ilayer] /
650 (fcPerMip_[ithick] * thicknessCorrection_[ithick]);
651 thresholds_[ilayer - 1][ithick] = sigmaNoise * ecut_;
652 sigmaNoise_[ilayer - 1][ithick] = sigmaNoise;
654 float scintillators_sigmaNoise = 0.001f * noiseMip_ * dEdXweights_[ilayer];
655 thresholds_[ilayer - 1][maxNumberOfThickIndices] = ecut_ * scintillators_sigmaNoise;
656 sigmaNoise_[ilayer - 1][maxNumberOfThickIndices] = scintillators_sigmaNoise;
663 density_[
i.data.detid] =
i.data.rho;
constexpr float energy() const
int findAndAssignClusters(std::vector< KDNode > &, KDTree &, double, KDTreeBox< 2 > &, const unsigned int, std::vector< std::vector< KDNode >> &) const
void getEventSetupPerAlgorithm(const edm::EventSetup &es) override
double calculateEnergyWithFraction(const std::vector< KDNode > &, const std::vector< double > &)
math::XYZPoint calculatePositionWithFraction(const std::vector< KDNode > &, const std::vector< double > &)
static std::vector< std::string > checklist log
double calculateLocalDensity(std::vector< KDNode > &, KDTree &, const unsigned int) const
void search(const KDTreeBox< DIM > &searchBox, std::vector< DATA > &resRecHitList)
constexpr const DetId & detid() const
void shareEnergy(const std::vector< KDNode > &, const std::vector< unsigned > &, std::vector< std::vector< double >> &)
Exp< T >::type exp(const T &t)
std::vector< reco::BasicCluster > getClusters(bool) override
void makeClusters() override
constexpr std::array< uint8_t, layerIndexSize > layer
std::map< DetId, float > Density
std::vector< size_t > sorted_indices(const std::vector< T > &v)
void setDensity(const std::vector< KDNode > &nd)
void build(std::vector< KDTreeNodeInfo< DATA, DIM > > &eltList, const KDTreeBox< DIM > ®ion)
std::vector< unsigned > findLocalMaximaInCluster(const std::vector< KDNode > &)
Density getDensity() override
for(Iditer=Id.begin();Iditer!=Id.end();Iditer++)
void populate(const HGCRecHitCollection &hits) override
XYZPointD XYZPoint
point in space with cartesian internal representation
T perp2() const
Squared magnitude of transverse component.
std::pair< double, double > calculatePosition(TVirtualPad *myPad, int boundary)
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)