CMS 3D CMS Logo

CaloClusterer.cc
Go to the documentation of this file.
2 
3 #include <cassert>
4 
9 
11  0, 0.087, 0.174, 0.261, 0.348, 0.435, 0.522, 0.609, 0.696, 0.783, 0.870, 0.957, 1.044, 1.131,
12  1.218, 1.305, 1.392, 1.479, 1.566, 1.653, 1.740, 1.830, 1.930, 2.043, 2.172, 2.322, 2.5, 2.650,
13  2.853, 3.139, 3.314, 3.489, 3.664, 3.839, 4.013, 4.191, 4.363, 4.538, 4.716, 4.889, 5.191};
15  0, 0.087, 0.174, 0.261, 0.348, 0.435, 0.522, 0.609, 0.696, 0.783, 0.870, 0.957, 1.044, 1.131, 1.218, 1.305,
16  1.392, 1.479, 1.564, 1.648, 1.732, 1.817, 1.901, 1.986, 2.071, 2.155, 2.240, 2.324, 2.409, 2.493, 2.577, 2.662,
17  2.747, 2.831, 2.915, 3.0, 3.139, 3.314, 3.489, 3.664, 3.839, 4.013, 4.191, 4.363, 4.538, 4.716, 4.889, 5.191};
18 
20  int nEta, int nPhi, int ietaCoarse, int ietaVeryCoarse, const float *towerEtas)
21  : Grid(2 * ((ietaCoarse - 1) * nPhi + (ietaVeryCoarse - ietaCoarse) * (nPhi / 2) +
22  (nEta - ietaVeryCoarse + 1) * (nPhi / 4))),
23  nEta_(nEta),
24  nPhi_(nPhi),
25  ietaCoarse_(ietaCoarse),
26  ietaVeryCoarse_(ietaVeryCoarse),
27  towerEtas_(towerEtas),
28  cell_map_(2 * nEta * nPhi, -1) {
29  int icell = 0;
30  for (int ie = -nEta_; ie <= nEta_; ++ie) {
31  int absie = std::abs(ie);
32  for (int iph = 1; iph <= nPhi_; ++iph) {
33  if (!valid_ieta_iphi(ie, iph))
34  continue;
35  ieta_[icell] = ie;
36  iphi_[icell] = iph;
37  float etaLo = (absie < nEta_ ? towerEtas_[absie - 1] : towerEtas_[absie - 2]);
38  float etaHi = (absie < nEta_ ? towerEtas_[absie] : towerEtas_[absie - 1]);
39  eta_[icell] = (ie > 0 ? 0.5 : -0.5) * (etaLo + etaHi);
40  etaWidth_[icell] = (etaHi - etaLo);
41  phiWidth_[icell] = 2 * M_PI / nPhi_;
42  if (absie >= ietaVeryCoarse_)
43  phiWidth_[icell] *= 4;
44  else if (absie >= ietaCoarse_)
45  phiWidth_[icell] *= 2;
46  phi_[icell] = (iph - 1) * 2 * M_PI / nPhi_ + 0.5 * phiWidth_[icell];
47  if (phi_[icell] > M_PI)
48  phi_[icell] -= 2 * M_PI;
49  std::fill(neighbours_[icell].begin(), neighbours_[icell].end(), -1);
50  cell_map_[(ie + nEta_) + 2 * nEta_ * (iph - 1)] = icell;
51  icell++;
52  }
53  }
54  assert(unsigned(icell) == ncells_);
55  // now link the cells
56  for (icell = 0; icell < int(ncells_); ++icell) {
57  int ie = ieta_[icell], iph = iphi_[icell];
58  int ineigh = 0;
59  for (int deta = -1; deta <= +1; ++deta) {
60  for (int dphi = -1; dphi <= +1; ++dphi) {
61  if (deta == 0 && dphi == 0)
62  continue;
63  neighbours_[icell][ineigh++] = imove(ie, iph, deta, dphi);
64  }
65  }
66  }
69  //for (float teta = 0; teta <= 5.0; teta += 0.02) {
70  // for (float tphi = -M_PI; tphi <= M_PI; tphi += 0.02) {
71  // find_cell(+teta, tphi);
72  // find_cell(-teta, tphi);
73  // }
74  //}
75 }
76 
77 int l1tpf_calo::Phase1GridBase::find_cell(float eta, float phi) const {
78  int ieta =
79  (eta != 0) ? std::distance(towerEtas_, std::lower_bound(towerEtas_, towerEtas_ + nEta_, std::abs(eta))) : 1;
80  if (ieta == nEta_)
81  return -1; // outside bounds
82  assert(ieta > 0 && ieta < nEta_);
83  if (ieta > nEta_)
84  ieta = nEta_;
85  if (eta < 0)
86  ieta = -ieta;
87  phi = reco::reduceRange(phi); // [-PI, PI]
88  if (phi < 0) // then bring to [0, 2*PI]
89  phi += 2 * M_PI;
90  int iphi = std::floor(phi * nPhi_ / (2 * M_PI));
91  if (phi >= 2 * M_PI)
92  iphi = nPhi_ - 1; // fix corner case due to roundings etc
93  assert(iphi < nPhi_);
94  if (std::abs(ieta) >= ietaVeryCoarse_)
95  iphi -= (iphi % 4);
96  else if (std::abs(ieta) >= ietaCoarse_)
97  iphi -= (iphi % 2);
98  iphi += 1;
100  //if (!valid_ieta_iphi(ieta,iphi)) {
101  // printf("Error in finding cell for eta %+7.4f phi %+7.4f, got ieta = %+3d iphi %2d which is not valid\n",
102  // eta, phi, ieta, iphi);
103  //}
104  assert(valid_ieta_iphi(ieta, iphi));
105  int icell = ifind_cell(ieta, iphi);
106  assert(icell != -1);
107 
109  //if (std::abs(eta - eta_[icell]) > 0.501*etaWidth_[icell] || std::abs(deltaPhi(phi, phi_[icell])) > 0.501*phiWidth_[icell]) {
110  // printf("Mismatch in finding cell for eta %+7.4f phi %+7.4f, got ieta = %+3d iphi %2d which has eta %+7.4f +- %.4f phi %+7.4f +- %.4f ; deta = %+7.4f dphi = %+7.4f\n",
111  // eta, phi, ieta, iphi, eta_[icell], etaWidth_[icell], phi_[icell], phiWidth_[icell], eta - eta_[icell], deltaPhi(phi, phi_[icell]));
112  //}
113  //assert(std::abs(eta - eta_[icell]) <= 0.5*etaWidth_[icell]);
114  //assert(std::abs(deltaPhi(phi, phi_[icell])) <= 0.5*phiWidth_[icell]);
115  return icell;
116 }
117 
118 int l1tpf_calo::Phase1GridBase::imove(int ieta, int iphi, int deta, int dphi) {
119  int ie = ieta, iph = iphi;
120  switch (deta) {
121  case -1:
122  ie = (ie == -nEta_ ? 0 : (ie == +1 ? -1 : ie - 1));
123  break;
124  case +1:
125  ie = (ie == +nEta_ ? 0 : (ie == -1 ? +1 : ie + 1));
126  break;
127  case 0:
128  break;
129  default:
130  assert(false);
131  };
132  if (ie == 0)
133  return -1;
134  switch (dphi) {
135  case -1:
136  iph = (iph == 1 ? nPhi_ : iph - 1);
137  break;
138  case +1:
139  iph = (iph == nPhi_ ? 1 : iph + 1);
140  break;
141  case 0:
142  break;
143  default:
144  assert(false);
145  };
146  if (!valid_ieta_iphi(ie, iph))
147  return -1;
148  int icell = ifind_cell(ie, iph);
149  assert(!(ie == ieta && iph == iphi));
150  assert(icell != -1);
151  assert(icell != ifind_cell(ieta, iphi));
152  return icell;
153 }
154 
156  static const Phase1Grid _phase1Grid;
157  static const Phase2Grid _phase2Grid;
158  if (type == "phase1")
159  return &_phase1Grid;
160  else if (type == "phase2")
161  return &_phase2Grid;
162  else
163  throw cms::Exception("Configuration") << "Unsupported grid type '" << type << "'\n";
164 }
165 
167  : grid_(getGrid(pset.getParameter<std::string>("grid"))),
168  rawet_(*grid_),
169  unclustered_(*grid_),
170  eta_center_(*grid_),
171  phi_center_(*grid_),
172  precluster_(*grid_),
173  clusterIndex_(*grid_),
174  cellKey_(*grid_),
175  preciseEtaPhi_(pset.existsAs<bool>("usePreciseEtaPhi") ? pset.getParameter<bool>("usePreciseEtaPhi") : false),
176  etaBounds_(pset.getParameter<std::vector<double>>("etaBounds")),
177  phiBounds_(pset.getParameter<std::vector<double>>("phiBounds")),
178  maxClustersEtaPhi_(pset.getParameter<std::vector<unsigned int>>("maxClustersEtaPhi")),
179  clusters_(),
180  nullCluster_(),
181  zsEt_(pset.getParameter<double>("zsEt")),
182  seedEt_(pset.getParameter<double>("seedEt")),
183  minClusterEt_(pset.getParameter<double>("minClusterEt")),
184  minEtToGrow_(pset.existsAs<double>("minEtToGrow") ? pset.getParameter<double>("minEtToGrow") : -1),
185  energyWeightedPosition_(pset.getParameter<bool>("energyWeightedPosition")) {
186  std::string energyShareAlgo = pset.getParameter<std::string>("energyShareAlgo");
187  if (energyShareAlgo == "fractions")
189  else if (energyShareAlgo == "none")
191  else if (energyShareAlgo == "greedy")
193  else if (energyShareAlgo == "crude")
195  else
196  throw cms::Exception("Configuration") << "Unsupported energyShareAlgo '" << energyShareAlgo << "'\n";
197  if (pset.existsAs<std::vector<int>>("neighborCells")) {
198  neighborCells_ = pset.getParameter<std::vector<int>>(
199  "neighborCells"); //anything other than 3x3 is incompatible with grow() I think...
200  } else {
201  neighborCells_ = std::vector<int>({0, 1, 2, 3, 4, 5, 6, 7}); //default to 3x3
202  // in relative eta,phi: 5 = (+1, 0), 6 = (+1, 0), 7 = (+1,+1)
203  // 3 = ( 0,-1), 4 = ( 0,+1),
204  // 0 = (-1,-1), 1 = (-1, 0), 2 = (-1,+1),
205  }
206  if ((etaBounds_.size() - 1) * (phiBounds_.size() - 1) != maxClustersEtaPhi_.size()) {
207  throw cms::Exception("Configuration")
208  << "Size mismatch between eta/phi bounds and max clusters: " << (etaBounds_.size() - 1) << " x "
209  << (phiBounds_.size() - 1) << " != " << maxClustersEtaPhi_.size() << "\n";
210  }
211  if (!std::is_sorted(etaBounds_.begin(), etaBounds_.end())) {
212  throw cms::Exception("Configuration") << "etaBounds is not sorted\n";
213  }
214  if (!std::is_sorted(phiBounds_.begin(), phiBounds_.end())) {
215  throw cms::Exception("Configuration") << "phiBounds is not sorted\n";
216  }
217 }
218 
220 
222  rawet_.zero();
223  eta_center_.zero();
224  phi_center_.zero();
225  clusters_.clear();
226  clusterIndex_.fill(-1);
227 }
228 
230  unsigned int i, ncells = grid_->size();
231 
232  // kill zeros. count non-zeros, for linking later
233  cellKey_.fill(-1);
234  int key = 0;
235  for (i = 0; i < ncells; ++i) {
236  if (rawet_[i] < zsEt_) {
237  rawet_[i] = 0;
238  } else {
239  cellKey_[i] = key++;
240  }
241  }
242 
243  precluster_.clear();
244  // pre-cluster step 1: at each cell, set the value equal to itself if it's a local maxima, zero otherwise
245  // can be done in parallel on all cells
246  for (i = 0; i < ncells; ++i) {
247  if (rawet_[i] > seedEt_) {
248  precluster_[i].ptLocalMax = rawet_[i];
250  //printf(" candidate precluster pt %7.2f at %4d (ieta %+3d iphi %2d)\n", rawet_[i], i, grid_->ieta(i), grid_->iphi(i));
251  for (const auto &ineigh : neighborCells_) {
252  if (ineigh >= 4)
253  continue;
254  if (rawet_.neigh(i, ineigh) > rawet_[i])
255  precluster_[i].ptLocalMax = 0;
257  //int ncell = grid_->neighbour(i,ineigh);
258  //if (ncell == -1) printf(" \t neigh %d is null\n", ineigh);
259  //else printf(" \t neigh %d at %4d (ieta %+3d iphi %2d) has pt %7.2f: comparison %1d \n", ineigh, ncell, grid_->ieta(ncell), grid_->iphi(ncell), rawet_[ncell], precluster_[i].ptLocalMax > 0);
260  }
261  for (const auto &ineigh : neighborCells_) {
262  if (ineigh < 4)
263  continue;
264  if (rawet_.neigh(i, ineigh) >= rawet_[i])
265  precluster_[i].ptLocalMax = 0;
267  //int ncell = grid_->neighbour(i,ineigh);
268  //if (ncell == -1) printf(" \t neigh %d is null\n", ineigh);
269  //else printf(" \t neigh %d at %4d (ieta %+3d iphi %2d) has pt %7.2f: comparison %1d \n", ineigh, ncell, grid_->ieta(ncell), grid_->iphi(ncell), rawet_[ncell], precluster_[i].ptLocalMax > 0);
270  }
271  }
272  }
273  // pre-cluster step 2: compute information from neighbouring local max, for energy sharing purposes
274  for (i = 0; i < ncells; ++i) {
275  if (precluster_[i].ptLocalMax == 0) {
276  switch (energyShareAlgo_) {
277  case EnergyShareAlgo::Fractions: {
278  float tot = 0;
279  for (const auto &ineigh : neighborCells_) {
280  tot += precluster_.neigh(i, ineigh).ptLocalMax;
281  }
282  precluster_[i].ptOverNeighLocalMaxSum = tot ? rawet_[i] / tot : 0;
283  } break;
285  precluster_[i].ptOverNeighLocalMaxSum = rawet_[i];
286  break;
287  case EnergyShareAlgo::Greedy: {
288  float maxet = 0;
289  for (const auto &ineigh : neighborCells_) {
290  maxet = std::max(maxet, precluster_.neigh(i, ineigh).ptLocalMax);
291  }
292  precluster_[i].ptOverNeighLocalMaxSum = maxet;
293  } break;
294  case EnergyShareAlgo::Crude: {
295  int number = 0;
296  for (const auto &ineigh : neighborCells_) {
297  number += (precluster_.neigh(i, ineigh).ptLocalMax > 0);
298  }
299  precluster_[i].ptOverNeighLocalMaxSum = (number > 1 ? 0.5 : 1.0) * rawet_[i];
300  } break;
301  }
302  }
303  }
304 
305  clusterIndex_.fill(-1);
306  clusters_.clear();
307  unclustered_ = rawet_;
308  // cluster: at each localMax cell, take itself plus the weighted contributions of the neighbours
309  Cluster cluster;
310  for (i = 0; i < ncells; ++i) {
311  if (precluster_[i].ptLocalMax > 0) {
312  float myet = rawet_[i];
313  float tot = myet;
314  float avg_eta = 0;
315  float avg_phi = 0;
316  cluster.clear();
317  cluster.constituents.emplace_back(i, 1.0);
318  for (const auto &ineigh : neighborCells_) {
319  int ineighcell = grid_->neighbour(i, ineigh);
320  if (ineighcell == -1)
321  continue; // skip dummy cells
322  float fracet = 0;
323  switch (energyShareAlgo_) {
324  case EnergyShareAlgo::Fractions:
325  fracet = myet * precluster_.neigh(i, ineigh).ptOverNeighLocalMaxSum;
326  break;
328  fracet = precluster_.neigh(i, ineigh).ptOverNeighLocalMaxSum;
329  break;
330  case EnergyShareAlgo::Greedy:
331  fracet = (myet == precluster_.neigh(i, ineigh).ptOverNeighLocalMaxSum ? rawet_.neigh(i, ineigh) : 0);
332  break;
333  case EnergyShareAlgo::Crude:
334  fracet = precluster_.neigh(i, ineigh).ptOverNeighLocalMaxSum;
335  break;
336  }
337  if (fracet == 0)
338  continue;
339  tot += fracet;
340  cluster.constituents.emplace_back(ineighcell, fracet / rawet_.neigh(i, ineigh));
341  if (energyWeightedPosition_) {
342  avg_eta += fracet * (grid_->eta(ineighcell) - grid_->eta(i));
343  avg_phi += fracet * deltaPhi(grid_->phi(ineighcell), grid_->phi(i));
344  }
345  }
346  if (tot > minClusterEt_) {
347  cluster.et = tot;
348  unclustered_[i] = 0;
349  for (const auto &ineigh : neighborCells_) {
350  int ineighcell = grid_->neighbour(i, ineigh);
351  if (ineighcell == -1)
352  continue; // skip dummy cells
353  unclustered_[ineighcell] = 0;
354  }
355  if (energyWeightedPosition_) {
356  cluster.eta = grid_->eta(i) + avg_eta / tot;
357  cluster.phi = grid_->phi(i) + avg_phi / tot;
358  // wrap around phi
359  cluster.phi = reco::reduceRange(cluster.phi);
360  } else {
361  cluster.eta = grid_->eta(i);
362  cluster.phi = grid_->phi(i);
363  }
364  clusterIndex_[i] = clusters_.size();
365  clusters_.push_back(cluster);
366  }
367  }
368  }
369  if (minEtToGrow_ > 0)
370  grow();
371 }
372 
374  int selneighs[4] = {1, 3, 4, 6}; // -eta, -phi, +phi, +eta
375  std::vector<int> toreset;
376  for (Cluster &cluster : clusters_) {
377  if (cluster.et > minEtToGrow_) {
378  int i = cluster.constituents.front().first;
379  for (int side = 0; side < 4; ++side) {
380  int neigh = grid_->neighbour(i, selneighs[side]);
381  if (neigh == -1)
382  continue;
383  for (int in = 0; in < 8; ++in) {
384  int n2 = grid_->neighbour(neigh, in);
385  if (n2 == -1)
386  continue;
387  cluster.et += unclustered_[n2];
388  if (unclustered_[n2]) {
389  cluster.constituents.emplace_back(n2, 1.0);
390  toreset.push_back(n2);
391  }
392  }
393  }
394  }
395  }
396  for (int i : toreset)
397  unclustered_[i] = 0;
398 }
399 
400 std::unique_ptr<l1t::PFClusterCollection> l1tpf_calo::SingleCaloClusterer::fetchCells(bool unclusteredOnly,
401  float ptMin) const {
402  auto ret = std::make_unique<l1t::PFClusterCollection>();
403  const EtGrid &src = (unclusteredOnly ? unclustered_ : rawet_);
404  const EtaPhiCenterGrid &eta_shift = eta_center_;
405  const EtaPhiCenterGrid &phi_shift = phi_center_;
406  l1tpf_calo::GridSelector selector = l1tpf_calo::GridSelector(etaBounds_, phiBounds_, maxClustersEtaPhi_);
407  int totalClusters = 0;
408  for (unsigned int i = 0, ncells = grid_->size(); i < ncells; ++i) {
409  if (src[i] <= ptMin)
410  continue;
411  if ((unclusteredOnly == false) && (ptMin == 0)) {
412  assert(cellKey_[i] == totalClusters);
413  }
414  totalClusters++;
415  selector.fill(src[i], grid_->eta(i), grid_->phi(i), i);
416  }
417  std::vector<unsigned int> indices = selector.returnSorted();
418  for (unsigned int ii = 0; ii < indices.size(); ii++) {
419  unsigned int theIndex = indices[ii];
420  ret->emplace_back(
421  src[theIndex], grid_->eta(theIndex) + eta_shift[theIndex], grid_->phi(theIndex) + phi_shift[theIndex]);
422  ret->back().setHwEta(grid_->ieta(theIndex));
423  ret->back().setHwPhi(grid_->iphi(theIndex));
424  }
425  return ret;
426 }
427 
428 std::unique_ptr<l1t::PFClusterCollection> l1tpf_calo::SingleCaloClusterer::fetch(float ptMin) const {
429  auto ret = std::make_unique<l1t::PFClusterCollection>();
430  for (const Cluster &cluster : clusters_) {
431  if (cluster.et > ptMin) {
432  ret->emplace_back(cluster.et, cluster.eta, cluster.phi);
433  }
434  }
435  return ret;
436 }
437 
438 std::unique_ptr<l1t::PFClusterCollection> l1tpf_calo::SingleCaloClusterer::fetch(
440  auto ret = std::make_unique<l1t::PFClusterCollection>();
441  for (const Cluster &cluster : clusters_) {
442  if (cluster.et > ptMin) {
443  ret->emplace_back(cluster.et, cluster.eta, cluster.phi);
444  for (const auto &pair : cluster.constituents) {
445  edm::Ptr<l1t::PFCluster> ref(cells, cellKey_[pair.first]);
446  ret->back().addConstituent(ref, pair.second);
447  }
448  }
449  }
450  return ret;
451 }
452 
454  const SingleCaloClusterer &ecal,
455  const SingleCaloClusterer &hcal)
456  : grid_(getGrid(pset.getParameter<std::string>("grid"))),
457  ecal_(ecal),
458  hcal_(hcal),
459  clusterIndex_(*grid_),
460  clusters_(),
461  etaBounds_(pset.getParameter<std::vector<double>>("etaBounds")),
462  phiBounds_(pset.getParameter<std::vector<double>>("phiBounds")),
463  maxClustersEtaPhi_(pset.getParameter<std::vector<unsigned int>>("maxClustersEtaPhi")),
464  hoeCut_(pset.getParameter<double>("hoeCut")),
465  minPhotonEt_(pset.getParameter<double>("minPhotonEt")),
466  minHadronRawEt_(pset.getParameter<double>("minHadronRawEt")),
467  minHadronEt_(pset.getParameter<double>("minHadronEt")),
468  noEmInHGC_(pset.getParameter<bool>("noEmInHGC")) {
469  if (grid_ != &ecal.raw().grid())
470  throw cms::Exception("LogicError", "Inconsistent grid between ecal and linker\n");
471  if (grid_ != &hcal.raw().grid())
472  throw cms::Exception("LogicError", "Inconsistent grid between hcal and linker\n");
473  if ((etaBounds_.size() - 1) * (phiBounds_.size() - 1) != maxClustersEtaPhi_.size()) {
474  throw cms::Exception("Configuration")
475  << "Size mismatch between eta/phi bounds and max clusters: " << (etaBounds_.size() - 1) << " x "
476  << (phiBounds_.size() - 1) << " != " << maxClustersEtaPhi_.size() << "\n";
477  }
478  if (!std::is_sorted(etaBounds_.begin(), etaBounds_.end())) {
479  throw cms::Exception("Configuration") << "etaBounds is not sorted\n";
480  }
481  if (!std::is_sorted(phiBounds_.begin(), phiBounds_.end())) {
482  throw cms::Exception("Configuration") << "phiBounds is not sorted\n";
483  }
484 }
485 
487 
488 std::unique_ptr<l1t::PFClusterCollection> l1tpf_calo::SimpleCaloLinkerBase::fetch() const {
490  return fetch(ecal, hcal);
491 }
492 
493 std::unique_ptr<l1t::PFClusterCollection> l1tpf_calo::SimpleCaloLinkerBase::fetch(
496  bool setRefs = (ecal.isValid() && hcal.isValid());
497  auto ret = std::make_unique<l1t::PFClusterCollection>();
498  l1tpf_calo::GridSelector selector = l1tpf_calo::GridSelector(etaBounds_, phiBounds_, maxClustersEtaPhi_);
499  unsigned int index = 0;
500  for (const CombinedCluster &cluster : clusters_) {
501  index++;
502  if (cluster.et > 0) {
503  bool photon = (cluster.hcal_et < hoeCut_ * cluster.ecal_et);
504  if (photon && noEmInHGC_) {
505  if (std::abs(cluster.eta) > 1.5 && std::abs(cluster.eta) < 3.0) { // 1.5-3 = eta range of HGCal
506  continue;
507  }
508  }
509  selector.fill(cluster.et, cluster.eta, cluster.phi, index - 1);
510  }
511  }
512  std::vector<unsigned int> indices = selector.returnSorted();
513  for (unsigned int ii = 0; ii < indices.size(); ii++) {
514  unsigned int theIndex = indices[ii];
515  const CombinedCluster &cluster = clusters_[theIndex];
516  bool photon = (cluster.hcal_et < hoeCut_ * cluster.ecal_et);
517  if (cluster.et > (photon ? minPhotonEt_ : minHadronEt_)) {
518  ret->emplace_back(cluster.et,
519  photon ? cluster.ecal_eta : cluster.eta,
520  photon ? cluster.ecal_phi : cluster.phi,
521  cluster.ecal_et > 0 ? std::max(cluster.et - cluster.ecal_et, 0.f) / cluster.ecal_et : -1,
522  photon);
523  if (setRefs) {
524  for (const auto &pair : cluster.constituents) {
525  assert(pair.first != 0);
526  if (pair.first > 0) { // 1+hcal index
527  ret->back().addConstituent(edm::Ptr<l1t::PFCluster>(hcal, +pair.first - 1), pair.second);
528  } else { // -1-ecal index
529  ret->back().addConstituent(edm::Ptr<l1t::PFCluster>(ecal, -pair.first + 1), pair.second);
530  }
531  }
532  }
533  }
534  }
535  return ret;
536 }
537 
539  const SingleCaloClusterer &ecal,
540  const SingleCaloClusterer &hcal)
541  : SimpleCaloLinkerBase(pset, ecal, hcal), ecalToHCal_(*grid_) {}
542 
544 
546  clearBase();
547  ecalToHCal_.clear();
548 }
549 
551  unsigned int i, ncells = grid_->size();
552 
553  const EtGrid &hraw = hcal_.raw();
554  const IndexGrid &ecals = ecal_.indexGrid();
555  const IndexGrid &hcals = hcal_.indexGrid();
556 
557  // for each ECal cluster, get the corresponding HCal cluster and the sum of the neighbour HCal clusters
558  ecalToHCal_.clear();
559  for (i = 0; i < ncells; ++i) {
560  if (ecals[i] >= 0) {
561  if (hcals[i] >= 0) {
562  ecalToHCal_[i].ptLocalMax = hcal_.cluster(i).et;
563  } else {
564  float tot = 0;
565  for (int ineigh = 0; ineigh < 8; ++ineigh) {
566  tot += hcal_.cluster(grid_->neighbour(i, ineigh)).et;
567  }
568  ecalToHCal_[i].ptOverNeighLocalMaxSum = tot ? ecal_.cluster(i).et / tot : 0;
569  }
570  }
571  }
572 
573  clusterIndex_.fill(-1);
574  clusters_.clear();
575  CombinedCluster cluster;
576  // promote HCal clusters to final clusters
577  for (i = 0; i < ncells; ++i) {
578  if (hcals[i] >= 0) {
579  const Cluster &hcal = hcal_.cluster(i);
580  cluster.clear();
581  cluster.constituents.emplace_back(+i + 1, 1);
582  if (ecalToHCal_[i].ptLocalMax > 0) {
583  // direct linking is easy
584  const Cluster &ecal = ecal_.cluster(i);
585  if (ecal.et + hcal.et > minHadronRawEt_) {
586  cluster.ecal_et = ecal.et;
587  cluster.hcal_et = hcal.et;
588  cluster.et = cluster.ecal_et + cluster.hcal_et;
589  float wecal = cluster.ecal_et / cluster.et, whcal = 1.0 - wecal;
590  cluster.eta = ecal.eta * wecal + hcal.eta * whcal;
591  cluster.phi = ecal.phi * wecal + hcal.phi * whcal;
592  cluster.ecal_eta = cluster.eta;
593  cluster.ecal_phi = cluster.phi;
594  // wrap around phi
595  cluster.phi = reco::reduceRange(cluster.phi);
596  cluster.constituents.emplace_back(-i - 1, 1);
597  }
598  } else {
599  // sidewas linking is more annonying
600  float myet = hcal.et;
601  float etot = 0;
602  float avg_eta = 0;
603  float avg_phi = 0;
604  for (int ineigh = 0; ineigh < 8; ++ineigh) {
605  int ineighcell = grid_->neighbour(i, ineigh);
606  if (ineighcell == -1)
607  continue; // skip dummy cells
608  float fracet = myet * ecalToHCal_.neigh(i, ineigh).ptOverNeighLocalMaxSum;
609  if (fracet == 0)
610  continue;
611  etot += fracet;
612  avg_eta += fracet * (grid_->eta(ineighcell) - grid_->eta(i));
613  avg_phi += fracet * deltaPhi(grid_->phi(ineighcell), grid_->phi(i));
614  cluster.constituents.emplace_back(-i - 1, fracet / ecal_.cluster(ineighcell).et);
615  }
616  if (myet + etot > minHadronRawEt_) {
617  cluster.hcal_et = hcal.et;
618  cluster.ecal_et = etot;
619  cluster.et = myet + etot;
620  cluster.eta = hcal.eta + avg_eta / cluster.et;
621  cluster.phi = hcal.phi + avg_phi / cluster.et;
622  cluster.ecal_eta = cluster.eta;
623  cluster.ecal_phi = cluster.phi;
624  // wrap around phi
625  cluster.phi = reco::reduceRange(cluster.phi);
626  }
627  }
628  if (cluster.et > 0) {
629  clusterIndex_[i] = clusters_.size();
630  clusters_.push_back(cluster);
631  }
632  }
633  }
634 
635  // promote Unlinked ECal clusters to final clusters
636  for (i = 0; i < ncells; ++i) {
637  if (ecals[i] >= 0 && ecalToHCal_[i].ptLocalMax == 0 && ecalToHCal_[i].ptOverNeighLocalMaxSum == 0) {
638  cluster.clear();
639  const Cluster &ecal = ecal_.cluster(i);
640  cluster.ecal_et = ecal.et;
641  cluster.hcal_et = hraw[i];
642  cluster.et = cluster.ecal_et + cluster.hcal_et;
643  cluster.eta = ecal.eta;
644  cluster.phi = ecal.phi;
645  cluster.constituents.emplace_back(-i - 1, 1);
646  clusterIndex_[i] = clusters_.size();
647  clusters_.push_back(cluster);
648  }
649  }
650 }
651 
653  const SingleCaloClusterer &ecal,
654  const SingleCaloClusterer &hcal)
655  : SimpleCaloLinkerBase(pset, ecal, hcal), combClusterer_(pset) {}
656 
658 
660  clearBase();
661  combClusterer_.clear();
662 }
663 
665  combClusterer_.clear();
666 
667  const EtGrid &hraw = hcal_.raw();
668  const EtGrid &eraw = ecal_.raw();
669  combClusterer_.raw() = eraw;
670  combClusterer_.raw() += hraw;
671 
672  combClusterer_.run();
673  clusterIndex_ = combClusterer_.indexGrid();
674  const std::vector<Cluster> &clustersSrc = combClusterer_.clusters();
675  unsigned int nclust = clustersSrc.size();
676  clusters_.resize(nclust);
677  for (unsigned int ic = 0; ic < nclust; ++ic) {
678  const Cluster &src = clustersSrc[ic];
679  CombinedCluster &dst = clusters_[ic];
680  dst.et = src.et;
681  dst.eta = src.eta;
682  dst.phi = src.phi;
683  dst.ecal_eta = src.eta;
684  dst.ecal_phi = src.phi;
685  dst.ecal_et = 0;
686  dst.hcal_et = 0;
687  for (const auto &pair : src.constituents) {
688  if (eraw[pair.first]) {
689  dst.ecal_et += pair.second * eraw[pair.first];
690  dst.constituents.emplace_back(-pair.first - 1, pair.second);
691  }
692  if (hraw[pair.first]) {
693  dst.hcal_et += pair.second * hraw[pair.first];
694  dst.constituents.emplace_back(+pair.first + 1, pair.second);
695  }
696  }
697  }
698 }
699 
701  const SingleCaloClusterer &ecal,
702  const SingleCaloClusterer &hcal)
703  : SimpleCaloLinkerBase(pset, ecal, hcal), combClusterer_(pset) {}
704 
706 
708  clearBase();
709  combClusterer_.clear();
710 }
711 
713  combClusterer_.clear();
714 
715  const EtGrid &hraw = hcal_.raw();
716  const EtGrid &eraw = ecal_.raw();
717  const EtaPhiCenterGrid &eeta = ecal_.etaCenter();
718  const EtaPhiCenterGrid &ephi = ecal_.phiCenter();
719  combClusterer_.raw() = eraw;
720  combClusterer_.raw() += hraw;
721 
722  combClusterer_.run();
723  clusterIndex_ = combClusterer_.indexGrid();
724  const std::vector<Cluster> &clustersSrc = combClusterer_.clusters();
725  unsigned int nclust = clustersSrc.size();
726  clusters_.resize(nclust);
727  for (unsigned int ic = 0; ic < nclust; ++ic) {
728  const Cluster &src = clustersSrc[ic];
729  CombinedCluster &dst = clusters_[ic];
730  dst.et = src.et;
731  dst.eta = src.eta;
732  dst.phi = src.phi;
733  dst.ecal_et = 0;
734  dst.hcal_et = 0;
735  float pt_max = 0.;
736  float eta_ecal = 0.;
737  float phi_ecal = 0.;
738  for (const auto &pair : src.constituents) {
739  if (eraw[pair.first]) {
740  float ept = pair.second * eraw[pair.first];
741  dst.ecal_et += ept;
742  dst.constituents.emplace_back(-pair.first - 1, pair.second);
743  if (ept > pt_max) {
744  eta_ecal = eeta[pair.first];
745  phi_ecal = ephi[pair.first];
746  pt_max = ept;
747  }
748  }
749  if (hraw[pair.first]) {
750  dst.hcal_et += pair.second * hraw[pair.first];
751  dst.constituents.emplace_back(+pair.first + 1, pair.second);
752  }
753  }
754  dst.ecal_eta = eta_ecal;
755  dst.ecal_phi = phi_ecal;
756  }
757 }
758 
760  std::vector<double> phiBounds,
761  std::vector<unsigned int> maxClusters)
762  : etaBounds_(etaBounds),
763  phiBounds_(phiBounds),
764  maxClustersEtaPhi_(maxClusters),
765  regionPtIndices_(!maxClusters.empty() ? maxClusters.size() : 1) {}
766 
767 void l1tpf_calo::GridSelector::fill(float pt, float eta, float phi, unsigned int index) {
768  if (!maxClustersEtaPhi_.empty()) {
769  unsigned int etai = etaBounds_.size();
770  for (unsigned int ie = 0; ie < etaBounds_.size() - 1; ie++) {
771  if (eta >= etaBounds_[ie] && eta < etaBounds_[ie + 1]) {
772  etai = ie;
773  break;
774  }
775  }
776  unsigned int phii = phiBounds_.size();
777  for (unsigned int ip = 0; ip < phiBounds_.size() - 1; ip++) {
778  if (phi >= phiBounds_[ip] && phi < phiBounds_[ip + 1]) {
779  phii = ip;
780  break;
781  }
782  }
783  if (etai < etaBounds_.size() && phii < phiBounds_.size()) {
784  regionPtIndices_[etai * (phiBounds_.size() - 1) + phii].emplace_back(pt, index);
785  }
786  } else {
787  regionPtIndices_[0].emplace_back(pt, index);
788  }
789 }
790 
791 std::vector<unsigned int> l1tpf_calo::GridSelector::returnSorted() {
792  std::vector<unsigned int> indices;
793  for (auto &regionPtIndex : regionPtIndices_) {
794  std::sort(regionPtIndex.begin(), regionPtIndex.end(), std::greater<std::pair<float, unsigned int>>());
795  for (const auto &p : regionPtIndex) {
796  indices.push_back(p.second);
797  }
798  }
799  return indices;
800 }
801 
802 std::unique_ptr<l1tpf_calo::SimpleCaloLinkerBase> l1tpf_calo::makeCaloLinker(const edm::ParameterSet &pset,
803  const SingleCaloClusterer &ecal,
804  const SingleCaloClusterer &hcal) {
805  const std::string &algo = pset.getParameter<std::string>("algo");
806  if (algo == "simple") {
807  return std::make_unique<l1tpf_calo::SimpleCaloLinker>(pset, ecal, hcal);
808  } else if (algo == "flat") {
809  return std::make_unique<l1tpf_calo::FlatCaloLinker>(pset, ecal, hcal);
810  } else if (algo == "combined") {
811  return std::make_unique<l1tpf_calo::CombinedCaloLinker>(pset, ecal, hcal);
812  } else {
813  throw cms::Exception("Configuration") << "Unsupported linker algo '" << algo << "'\n";
814  }
815 }
Phase1GridBase(int nEta, int nPhi, int ietaCoarse, int ietaVeryCoarse, const float *towerEtas)
int imove(int ieta, int iphi, int deta, int dphi)
std::vector< double > etaBounds_
std::vector< float > eta_
Definition: CaloClusterer.h:46
std::vector< unsigned int > maxClustersEtaPhi_
constexpr T reduceRange(T x)
Definition: deltaPhi.h:18
ret
prodAgent to be discontinued
SimpleCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
SingleCaloClusterer(const edm::ParameterSet &pset)
constexpr float ptMin
void fill(float pt, float eta, float phi, unsigned int index)
std::vector< unsigned int > maxClustersEtaPhi_
std::unique_ptr< SimpleCaloLinkerBase > makeCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
assert(be >=bs)
CombinedCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
unsigned int ncells_
Definition: CaloClusterer.h:45
std::vector< float > etaWidth_
Definition: CaloClusterer.h:46
FlatCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
SimpleCaloLinkerBase(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
const Grid * getGrid(const std::string &type)
bool valid_ieta_iphi(int ieta, int iphi) const
Definition: CaloClusterer.h:63
std::unique_ptr< l1t::PFClusterCollection > fetch() const
int find_cell(float eta, float phi) const override
std::vector< int > cell_map_
Definition: CaloClusterer.h:61
std::vector< float > phiWidth_
Definition: CaloClusterer.h:46
static const int phase1_nEta_
Definition: CaloClusterer.h:82
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::unique_ptr< l1t::PFClusterCollection > fetchCells(bool unclusteredOnly=false, float ptMin=0.) const
static const int phase2_nEta_
Definition: CaloClusterer.h:91
std::vector< float > phi_
Definition: CaloClusterer.h:46
std::vector< std::pair< int, float > > constituents
std::vector< unsigned int > returnSorted()
std::vector< double > phiBounds_
float phi(float eta, float phi) const
ii
Definition: cuy.py:589
#define M_PI
void grow()
possibly grow clusters by adding unclustered energy on the sides
std::vector< double > phiBounds_
constexpr void M2 & dst
GridSelector(std::vector< double > etaBounds, std::vector< double > phiBounds, std::vector< unsigned int > maxClusters)
std::vector< double > etaBounds_
std::unique_ptr< l1t::PFClusterCollection > fetch(float ptMin=0.) const
std::vector< int > ieta_
Definition: CaloClusterer.h:47
std::vector< int > iphi_
Definition: CaloClusterer.h:47
std::vector< std::array< int, 8 > > neighbours_
Definition: CaloClusterer.h:48
std::vector< int > neighborCells_
std::pair< std::string, std::shared_ptr< void > > fetch(const cond::Hash &payloadId, Session &session)
Definition: CondDBFetch.cc:346
static const float phase1_towerEtas_[phase1_nEta_]
Definition: CaloClusterer.h:83
static const float phase2_towerEtas_[phase2_nEta_]
Definition: CaloClusterer.h:92