12 #include "tbb/task_arena.h"
21 numberOfClustersPerLayer_.clear();
22 cells_.resize(2 * (maxlayer_ + 1));
23 numberOfClustersPerLayer_.resize(2 * (maxlayer_ + 1), 0);
36 for (
unsigned int i = 0;
i <
hits.size(); ++
i) {
39 unsigned int layerOnSide = (rhtools_.getLayerWithOffset(detid) - 1);
43 float sigmaNoise = 1.f;
45 int thickness_index = rhtools_.getSiThickIndex(detid);
46 if (thickness_index == -1)
48 double storedThreshold = thresholds_[layerOnSide][thickness_index];
49 sigmaNoise = v_sigmaNoise_[layerOnSide][thickness_index];
51 if (hgrh.
energy() < storedThreshold)
55 if (!dependSensor_ && hgrh.
energy() < ecut_)
58 int offset = ((rhtools_.zside(detid) + 1) >> 1) * maxlayer_;
59 int layer = layerOnSide +
offset;
61 cells_[layer].detid.emplace_back(detid);
62 cells_[layer].x.emplace_back(
position.x());
63 cells_[layer].y.emplace_back(
position.y());
64 if (!rhtools_.isOnlySilicon(layer)) {
65 cells_[layer].isSi.emplace_back(rhtools_.isSilicon(detid));
66 cells_[layer].eta.emplace_back(
position.eta());
67 cells_[layer].phi.emplace_back(
position.phi());
69 cells_[layer].weight.emplace_back(hgrh.
energy());
70 cells_[layer].sigmaNoise.emplace_back(sigmaNoise);
76 auto cellsSize = cells_[
l].detid.size();
77 cells_[
l].rho.resize(cellsSize, 0.
f);
78 cells_[
l].delta.resize(cellsSize, 9999999);
79 cells_[
l].nearestHigher.resize(cellsSize, -1);
80 cells_[
l].clusterIndex.resize(cellsSize, -1);
81 cells_[
l].followers.resize(cellsSize);
82 cells_[
l].isSeed.resize(cellsSize,
false);
83 if (rhtools_.isOnlySilicon(
l)) {
84 cells_[
l].isSi.resize(cellsSize,
true);
85 cells_[
l].eta.resize(cellsSize, 0.
f);
86 cells_[
l].phi.resize(cellsSize, 0.
f);
97 tbb::this_task_arena::isolate([&] {
98 tbb::parallel_for(
size_t(0),
size_t(2 * maxlayer_ + 2), [&](
size_t i) {
99 prepareDataStructures(
i);
102 lt.fill(cells_[
i].x, cells_[
i].y, cells_[
i].
eta, cells_[
i].phi, cells_[
i].isSi);
105 if (
i % maxlayer_ < lastLayerEE_)
106 delta_c = vecDeltas_[0];
107 else if (
i % maxlayer_ < (firstLayerBH_ - 1))
108 delta_c = vecDeltas_[1];
110 delta_c = vecDeltas_[2];
112 LogDebug(
"HGCalCLUEAlgo") <<
"maxlayer: " << maxlayer_ <<
" lastLayerEE: " << lastLayerEE_
113 <<
" firstLayerBH: " << firstLayerBH_ <<
"\n";
115 calculateLocalDensity(lt,
i, delta_c,
delta_r);
116 calculateDistanceToHigher(lt,
i, delta_c,
delta_r);
117 numberOfClustersPerLayer_[
i] = findAndAssignClusters(
i, delta_c,
delta_r);
121 for (
unsigned int i = 0;
i < 2 * maxlayer_ + 2; ++
i) {
126 template <
typename T>
128 std::vector<int>
offsets(numberOfClustersPerLayer_.size(), 0);
130 int maxClustersOnLayer = numberOfClustersPerLayer_[0];
132 for (
unsigned layerId = 1; layerId <
offsets.size(); ++layerId) {
133 offsets[layerId] =
offsets[layerId - 1] + numberOfClustersPerLayer_[layerId - 1];
135 maxClustersOnLayer =
std::max(maxClustersOnLayer, numberOfClustersPerLayer_[layerId]);
138 auto totalNumberOfClusters =
offsets.back() + numberOfClustersPerLayer_.back();
139 clusters_v_.resize(totalNumberOfClusters);
140 std::vector<std::vector<int>> cellsIdInCluster;
141 cellsIdInCluster.reserve(maxClustersOnLayer);
143 for (
unsigned int layerId = 0; layerId < 2 * maxlayer_ + 2; ++layerId) {
144 cellsIdInCluster.resize(numberOfClustersPerLayer_[layerId]);
145 auto& cellsOnLayer = cells_[layerId];
146 unsigned int numberOfCells = cellsOnLayer.detid.size();
147 auto firstClusterIdx =
offsets[layerId];
149 for (
unsigned int i = 0;
i < numberOfCells; ++
i) {
150 auto clusterIndex = cellsOnLayer.clusterIndex[
i];
151 if (clusterIndex != -1)
152 cellsIdInCluster[clusterIndex].push_back(
i);
155 std::vector<std::pair<DetId, float>> thisCluster;
157 for (
auto&
cl : cellsIdInCluster) {
162 for (
auto cellIdx :
cl) {
163 energy += cellsOnLayer.weight[cellIdx];
164 thisCluster.emplace_back(cellsOnLayer.detid[cellIdx], 1.f);
165 if (cellsOnLayer.isSeed[cellIdx]) {
166 seedDetId = cellsOnLayer.detid[cellIdx];
169 auto globalClusterIndex = cellsOnLayer.clusterIndex[
cl[0]] + firstClusterIdx;
171 clusters_v_[globalClusterIndex] =
173 clusters_v_[globalClusterIndex].setSeed(seedDetId);
177 cellsIdInCluster.clear();
182 template <
typename T>
184 float total_weight = 0.f;
188 unsigned int maxEnergyIndex = 0;
189 float maxEnergyValue = 0.f;
191 auto& cellsOnLayer = cells_[layerId];
196 total_weight += cellsOnLayer.weight[
i];
197 if (cellsOnLayer.weight[
i] > maxEnergyValue) {
198 maxEnergyValue = cellsOnLayer.weight[
i];
204 auto thick = rhtools_.getSiThickIndex(cellsOnLayer.detid[maxEnergyIndex]);
205 bool isSiliconCell = (thick != -1);
209 float total_weight_log = 0.f;
213 float rhEnergy = cellsOnLayer.weight[
i];
214 float Wi =
std::max(thresholdW0_[thick] +
std::log(rhEnergy / total_weight), 0.);
215 x_log += cellsOnLayer.x[
i] * Wi;
216 y_log += cellsOnLayer.y[
i] * Wi;
217 total_weight_log += Wi;
220 total_weight = total_weight_log;
225 float rhEnergy = cellsOnLayer.weight[
i];
227 x += cellsOnLayer.x[
i] * rhEnergy;
228 y += cellsOnLayer.y[
i] * rhEnergy;
231 if (total_weight != 0.) {
232 float inv_tot_weight = 1.f / total_weight;
234 x * inv_tot_weight, y * inv_tot_weight, rhtools_.getPosition(cellsOnLayer.detid[maxEnergyIndex]).z());
239 template <
typename T>
241 auto& cellsOnLayer = cells_[layerId];
242 unsigned int numberOfCells = cellsOnLayer.detid.size();
243 bool isOnlySi(
false);
244 if (rhtools_.isOnlySilicon(layerId))
247 for (
unsigned int i = 0;
i < numberOfCells;
i++) {
248 bool isSi = isOnlySi || cellsOnLayer.isSi[
i];
250 float delta = delta_c;
251 std::array<int, 4> search_box = lt.searchBox(
254 for (
int xBin = search_box[0];
xBin < search_box[1] + 1; ++
xBin) {
255 for (
int yBin = search_box[2];
yBin < search_box[3] + 1; ++
yBin) {
256 int binId = lt.getGlobalBinByBin(
xBin,
yBin);
257 size_t binSize = lt[binId].size();
259 for (
unsigned int j = 0;
j < binSize;
j++) {
260 unsigned int otherId = lt[binId][
j];
261 bool otherSi = isOnlySi || cellsOnLayer.isSi[otherId];
264 cellsOnLayer.rho[
i] += (
i == otherId ? 1.f : 0.5f) * cellsOnLayer.weight[otherId];
272 std::array<int, 4> search_box = lt.searchBoxEtaPhi(cellsOnLayer.eta[
i] -
delta,
273 cellsOnLayer.eta[
i] +
delta,
274 cellsOnLayer.phi[
i] -
delta,
275 cellsOnLayer.phi[
i] +
delta);
276 cellsOnLayer.rho[
i] += cellsOnLayer.weight[
i];
277 float northeast(0), northwest(0), southeast(0), southwest(0),
all(0);
282 size_t binSize = lt[binId].size();
284 for (
unsigned int j = 0;
j < binSize;
j++) {
285 unsigned int otherId = lt[binId][
j];
286 if (!cellsOnLayer.isSi[otherId]) {
292 int dIPhi = otherIPhi - iPhi;
293 dIPhi +=
abs(dIPhi) < 2
295 : dIPhi < 0 ? scintMaxIphi_
297 int dIEta = otherIEta -
iEta;
298 LogDebug(
"HGCalCLUEAlgo") <<
" Debugging calculateLocalDensity for Scintillator: \n"
299 <<
" cell: " << otherId <<
" energy: " << cellsOnLayer.weight[otherId]
300 <<
" otherIPhi: " << otherIPhi <<
" iPhi: " << iPhi
301 <<
" otherIEta: " << otherIEta <<
" iEta: " <<
iEta <<
"\n";
304 auto neighborCellContribution = 0.5f * cellsOnLayer.weight[otherId];
305 all += neighborCellContribution;
306 if (dIPhi >= 0 && dIEta >= 0)
307 northeast += neighborCellContribution;
308 if (dIPhi <= 0 && dIEta >= 0)
309 southeast += neighborCellContribution;
310 if (dIPhi >= 0 && dIEta <= 0)
311 northwest += neighborCellContribution;
312 if (dIPhi <= 0 && dIEta <= 0)
313 southwest += neighborCellContribution;
315 LogDebug(
"HGCalCLUEAlgo") <<
" Debugging calculateLocalDensity for Scintillator: \n"
316 <<
" northeast: " << northeast <<
" southeast: " << southeast
317 <<
" northwest: " << northwest <<
" southwest: " << southwest <<
"\n";
323 float neighborsval = (
std::max(northeast, northwest) >
std::max(southeast, southwest))
327 cellsOnLayer.rho[
i] += neighborsval;
329 cellsOnLayer.rho[
i] +=
all;
331 LogDebug(
"HGCalCLUEAlgo") <<
"Debugging calculateLocalDensity: \n"
332 <<
" cell: " <<
i <<
" isSilicon: " << cellsOnLayer.isSi[
i]
333 <<
" eta: " << cellsOnLayer.eta[
i] <<
" phi: " << cellsOnLayer.phi[
i]
334 <<
" energy: " << cellsOnLayer.weight[
i] <<
" density: " << cellsOnLayer.rho[
i] <<
"\n";
338 template <
typename T>
340 const unsigned int layerId,
343 auto& cellsOnLayer = cells_[layerId];
344 unsigned int numberOfCells = cellsOnLayer.detid.size();
345 bool isOnlySi(
false);
346 if (rhtools_.isOnlySilicon(layerId))
349 for (
unsigned int i = 0;
i < numberOfCells;
i++) {
350 bool isSi = isOnlySi || cellsOnLayer.isSi[
i];
354 int i_nearestHigher = -1;
356 float delta = delta_c;
360 std::array<int, 4> search_box = lt.searchBox(
363 for (
int xBin = search_box[0];
xBin < search_box[1] + 1; ++
xBin) {
364 for (
int yBin = search_box[2];
yBin < search_box[3] + 1; ++
yBin) {
366 size_t binId = lt.getGlobalBinByBin(
xBin,
yBin);
368 size_t binSize = lt[binId].size();
371 for (
unsigned int j = 0;
j < binSize;
j++) {
372 unsigned int otherId = lt[binId][
j];
373 bool otherSi = isOnlySi || cellsOnLayer.isSi[otherId];
375 float dist =
distance(
i, otherId, layerId,
false);
376 bool foundHigher = (cellsOnLayer.rho[otherId] > cellsOnLayer.rho[
i]) ||
377 (cellsOnLayer.rho[otherId] == cellsOnLayer.rho[
i] &&
378 cellsOnLayer.detid[otherId] > cellsOnLayer.detid[
i]);
380 if (foundHigher && dist <= i_delta) {
384 i_nearestHigher = otherId;
391 bool foundNearestHigherInSearchBox = (i_delta !=
maxDelta);
392 if (foundNearestHigherInSearchBox) {
393 cellsOnLayer.delta[
i] = i_delta;
394 cellsOnLayer.nearestHigher[
i] = i_nearestHigher;
399 cellsOnLayer.nearestHigher[
i] = -1;
405 std::array<int, 4> search_box = lt.searchBoxEtaPhi(cellsOnLayer.eta[
i] -
range,
406 cellsOnLayer.eta[
i] +
range,
407 cellsOnLayer.phi[
i] -
range,
408 cellsOnLayer.phi[
i] +
range);
410 for (
int xBin = search_box[0];
xBin < search_box[1] + 1; ++
xBin) {
411 for (
int yBin = search_box[2];
yBin < search_box[3] + 1; ++
yBin) {
413 size_t binId = lt.getGlobalBinByBinEtaPhi(
xBin,
yBin);
415 size_t binSize = lt[binId].size();
418 for (
unsigned int j = 0;
j < binSize;
j++) {
419 unsigned int otherId = lt[binId][
j];
420 if (!cellsOnLayer.isSi[otherId]) {
421 float dist =
distance(
i, otherId, layerId,
true);
422 bool foundHigher = (cellsOnLayer.rho[otherId] > cellsOnLayer.rho[
i]) ||
423 (cellsOnLayer.rho[otherId] == cellsOnLayer.rho[
i] &&
424 cellsOnLayer.detid[otherId] > cellsOnLayer.detid[
i]);
426 if (foundHigher && dist <= i_delta) {
430 i_nearestHigher = otherId;
437 bool foundNearestHigherInSearchBox = (i_delta !=
maxDelta);
438 if (foundNearestHigherInSearchBox) {
439 cellsOnLayer.delta[
i] = i_delta;
440 cellsOnLayer.nearestHigher[
i] = i_nearestHigher;
445 cellsOnLayer.nearestHigher[
i] = -1;
448 LogDebug(
"HGCalCLUEAlgo") <<
"Debugging calculateDistanceToHigher: \n"
449 <<
" cell: " <<
i <<
" isSilicon: " << cellsOnLayer.isSi[
i]
450 <<
" eta: " << cellsOnLayer.eta[
i] <<
" phi: " << cellsOnLayer.phi[
i]
451 <<
" energy: " << cellsOnLayer.weight[
i] <<
" density: " << cellsOnLayer.rho[
i]
452 <<
" nearest higher: " << cellsOnLayer.nearestHigher[
i]
453 <<
" distance: " << cellsOnLayer.delta[
i] <<
"\n";
457 template <
typename T>
463 unsigned int nClustersOnLayer = 0;
464 auto& cellsOnLayer = cells_[layerId];
465 unsigned int numberOfCells = cellsOnLayer.detid.size();
466 std::vector<int> localStack;
468 for (
unsigned int i = 0;
i < numberOfCells;
i++) {
469 float rho_c = kappa_ * cellsOnLayer.sigmaNoise[
i];
470 bool isSi = rhtools_.isOnlySilicon(layerId) || cellsOnLayer.isSi[
i];
474 cellsOnLayer.clusterIndex[
i] = -1;
475 bool isSeed = (cellsOnLayer.delta[
i] >
delta) && (cellsOnLayer.rho[
i] >= rho_c);
476 bool isOutlier = (cellsOnLayer.delta[
i] > outlierDeltaFactor_ *
delta) && (cellsOnLayer.rho[
i] < rho_c);
478 cellsOnLayer.clusterIndex[
i] = nClustersOnLayer;
479 cellsOnLayer.isSeed[
i] =
true;
481 localStack.push_back(
i);
483 }
else if (!isOutlier) {
484 cellsOnLayer.followers[cellsOnLayer.nearestHigher[
i]].push_back(
i);
489 while (!localStack.empty()) {
490 int endStack = localStack.back();
491 auto& thisSeed = cellsOnLayer.followers[endStack];
492 localStack.pop_back();
495 for (
int j : thisSeed) {
497 cellsOnLayer.clusterIndex[
j] = cellsOnLayer.clusterIndex[endStack];
499 localStack.push_back(
j);
502 return nClustersOnLayer;
505 template <
typename T>
519 std::vector<double>
dummy;
520 const unsigned maxNumberOfThickIndices = 3;
521 dummy.resize(maxNumberOfThickIndices + !isNose_, 0);
522 thresholds_.resize(maxlayer_,
dummy);
523 v_sigmaNoise_.resize(maxlayer_,
dummy);
525 for (
unsigned ilayer = 1; ilayer <= maxlayer_; ++ilayer) {
526 for (
unsigned ithick = 0; ithick < maxNumberOfThickIndices; ++ithick) {
527 float sigmaNoise = 0.001f * fcPerEle_ * nonAgedNoises_[ithick] * dEdXweights_[ilayer] /
528 (fcPerMip_[ithick] * thicknessCorrection_[ithick]);
529 thresholds_[ilayer - 1][ithick] = sigmaNoise * ecut_;
530 v_sigmaNoise_[ilayer - 1][ithick] = sigmaNoise;
531 LogDebug(
"HGCalCLUEAlgo") <<
"ilayer: " << ilayer <<
" nonAgedNoises: " << nonAgedNoises_[ithick]
532 <<
" fcPerEle: " << fcPerEle_ <<
" fcPerMip: " << fcPerMip_[ithick]
533 <<
" noiseMip: " << fcPerEle_ * nonAgedNoises_[ithick] / fcPerMip_[ithick]
534 <<
" sigmaNoise: " << sigmaNoise <<
"\n";
538 float scintillators_sigmaNoise = 0.001f * noiseMip_ * dEdXweights_[ilayer];
539 thresholds_[ilayer - 1][maxNumberOfThickIndices] = ecut_ * scintillators_sigmaNoise;
540 v_sigmaNoise_[ilayer - 1][maxNumberOfThickIndices] = scintillators_sigmaNoise;
541 LogDebug(
"HGCalCLUEAlgo") <<
"ilayer: " << ilayer <<
" noiseMip: " << noiseMip_
542 <<
" scintillators_sigmaNoise: " << scintillators_sigmaNoise <<
"\n";
547 template <
typename T>
549 auto& cellsOnLayer = cells_[layerId];
550 unsigned int numberOfCells = cellsOnLayer.detid.size();
551 for (
unsigned int i = 0;
i < numberOfCells; ++
i)
552 density_[cellsOnLayer.detid[
i]] = cellsOnLayer.rho[
i];
555 template <
typename T>