12 #include "oneapi/tbb/task_arena.h" 13 #include "oneapi/tbb.h" 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) {
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];
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;
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;
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;
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;
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;
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)
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.);
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;
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;
523 const std::vector<double> &fractions) {
525 for (
unsigned i = 0;
i <
hits.size(); ++
i) {
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) {
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;
572 const unsigned iterMax = 50;
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);
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]) {
602 for (
unsigned j = 0;
j < numberOfSeeds; ++
j) {
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;
644 thresholds_.resize(maxlayer_,
dummy);
645 sigmaNoise_.resize(maxlayer_,
dummy);
647 for (
unsigned ilayer = 1; ilayer <= maxlayer_; ++ilayer) {
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];
663 density_[
i.data.detid] =
i.data.rho;
math::XYZPoint calculatePosition(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 > &)
constexpr const DetId & detid() const
void search(const KDTreeBox< DIM > &searchBox, std::vector< DATA > &resRecHitList)
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
void shareEnergy(const std::vector< KDNode > &, const std::vector< unsigned > &, std::vector< std::vector< double >> &)
std::vector< reco::BasicCluster > getClusters(bool) override
void makeClusters() override
constexpr float energy() const
T perp2() const
Squared magnitude of transverse component.
std::map< DetId, float > Density
std::vector< size_t > sorted_indices(const std::vector< T > &v)
double calculateLocalDensity(std::vector< KDNode > &, KDTree &, const unsigned int) const
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
void populate(const HGCRecHitCollection &hits) override
int findAndAssignClusters(std::vector< KDNode > &, KDTree &, double, KDTreeBox< 2 > &, const unsigned int, std::vector< std::vector< KDNode >> &) const
XYZPointD XYZPoint
point in space with cartesian internal representation
std::pair< double, double > calculatePosition(TVirtualPad *myPad, int boundary)
char data[epos_bytes_allocation]
Structure Point Contains parameters of Gaussian fits to DMRs.
static int position[264][3]
size_t max_index(const std::vector< T > &v)
double calculateDistanceToHigher(std::vector< KDNode > &) const
Power< A, B >::type pow(const A &a, const B &b)