CMS 3D CMS Logo

CaloClusterer.h
Go to the documentation of this file.
1 #ifndef L1Trigger_Phase2L1ParticleFlow_CALOCLUSTERER_H
2 #define L1Trigger_Phase2L1ParticleFlow_CALOCLUSTERER_H
3 
7 // fwd declarations
8 namespace edm {
9  class ParameterSet;
10 }
11 
12 // real includes
13 #include <cstdint>
14 #include <cmath>
15 #include <vector>
16 #include <array>
17 #include <algorithm>
20 
21 namespace l1tpf_calo {
22  class Grid {
23  public:
24  virtual ~Grid() {}
25  unsigned int size() const { return ncells_; }
26  virtual int find_cell(float eta, float phi) const = 0;
27  int neighbour(int icell, unsigned int idx) const { return neighbours_[icell][idx]; }
28  float eta(int icell) const { return eta_[icell]; }
29  float phi(int icell) const { return phi_[icell]; }
30  float etaWidth(int icell) const { return etaWidth_[icell]; }
31  float phiWidth(int icell) const { return phiWidth_[icell]; }
32  int ieta(int icell) const { return ieta_[icell]; }
33  int iphi(int icell) const { return iphi_[icell]; }
34 
35  protected:
36  Grid(unsigned int size)
37  : ncells_(size),
38  eta_(size),
39  etaWidth_(size),
40  phi_(size),
41  phiWidth_(size),
42  ieta_(size),
43  iphi_(size),
44  neighbours_(size) {}
45  unsigned int ncells_;
46  std::vector<float> eta_, etaWidth_, phi_, phiWidth_;
47  std::vector<int> ieta_, iphi_;
48  std::vector<std::array<int, 8>> neighbours_; // indices of the neigbours, -1 = none
49  };
50 
51  class Phase1GridBase : public Grid {
52  public:
53  Phase1GridBase(int nEta, int nPhi, int ietaCoarse, int ietaVeryCoarse, const float *towerEtas);
54 
55  int find_cell(float eta, float phi) const override;
56  int ifind_cell(int ieta, int iphi) const { return cell_map_[(ieta + nEta_) + 2 * nEta_ * (iphi - 1)]; }
57 
58  protected:
60  const float *towerEtas_;
61  std::vector<int> cell_map_;
62  // valid ieta, iphi (does not check for outside bounds, only for non-existence of ieta=0, iphi=0, and coarser towers at high eta)
63  bool valid_ieta_iphi(int ieta, int iphi) const {
64  if (ieta == 0 || iphi == 0)
65  return false;
66  if (std::abs(ieta) >= ietaVeryCoarse_ && (iphi % 4 != 1))
67  return false;
68  if (std::abs(ieta) >= ietaCoarse_ && (iphi % 2 != 1))
69  return false;
70  return true;
71  }
72  // move by +/-1 around a cell; return icell or -1 if not available
73  int imove(int ieta, int iphi, int deta, int dphi);
74  };
75 
76  class Phase1Grid : public Phase1GridBase {
77  public:
80 
81  protected:
82  static const int phase1_nEta_ = 41, phase1_nPhi_ = 72, phase1_ietaCoarse_ = 29, phase1_ietaVeryCoarse_ = 40;
83  static const float phase1_towerEtas_[phase1_nEta_];
84  };
85  class Phase2Grid : public Phase1GridBase {
86  public:
89 
90  protected:
91  static const int phase2_nEta_ = 48, phase2_nPhi_ = 72, phase2_ietaCoarse_ = 36, phase2_ietaVeryCoarse_ = 47;
92  static const float phase2_towerEtas_[phase2_nEta_];
93  };
94 
95  template <typename T>
96  class GridData {
97  public:
98  GridData() : grid_(nullptr), data_(), empty_() {}
99  GridData(const Grid &grid) : grid_(&grid), data_(grid.size()), empty_() {}
100 
101  T &operator()(float eta, float phi) { return data_[grid_->find_cell(eta, phi)]; }
102  const T &operator()(float eta, float phi) const { return data_[grid_->find_cell(eta, phi)]; }
103 
104  float eta(float eta, float phi) const { return grid().eta(grid_->find_cell(eta, phi)); }
105  float phi(float eta, float phi) const { return grid().phi(grid_->find_cell(eta, phi)); }
106 
107  const Grid &grid() const { return *grid_; }
108 
109  unsigned int size() const { return data_.size(); }
110 
111  float eta(int icell) const { return grid().eta(icell); }
112  float phi(int icell) const { return grid().phi(icell); }
113  int ieta(int icell) const { return grid().ieta(icell); }
114  int iphi(int icell) const { return grid().iphi(icell); }
115 
116  T &operator[](int icell) { return data_[icell]; }
117  const T &operator[](int icell) const { return data_[icell]; }
118 
119  const T &neigh(int icell, unsigned int idx) const {
120  int ineigh = grid_->neighbour(icell, idx);
121  return (ineigh < 0 ? empty_ : data_[ineigh]);
122  }
123 
125  assert(grid_ == other.grid_);
126  data_ = other.data_;
127  return *this;
128  }
130  assert(grid_ == other.grid_);
131  for (unsigned int i = 0, n = data_.size(); i < n; ++i) {
132  data_[i] += other.data_[i];
133  }
134  return *this;
135  }
136 
137  // always defined
138  void fill(const T &val) { std::fill(data_.begin(), data_.end(), val); }
139  void zero() { fill(T()); }
140 
141  // defined only if T has a 'clear' method
142  void clear() {
143  for (T &t : data_)
144  t.clear();
145  }
146 
147  private:
148  const Grid *grid_;
149  std::vector<T> data_;
150  const T empty_;
151  };
155 
156  struct PreCluster {
158  float ptLocalMax; // pt if it's a local max, zero otherwise
159  float ptOverNeighLocalMaxSum; // pt / (sum of ptLocalMax of neighbours); zero if no neighbours
161  };
163 
164  struct Cluster {
165  Cluster() : et(0), eta(0), phi(0) {}
166  float et, eta, phi;
167  std::vector<std::pair<int, float>> constituents;
168  void clear() {
169  et = eta = phi = 0;
170  constituents.clear();
171  }
172  };
173 
174  struct CombinedCluster : public Cluster {
175  float ecal_et, hcal_et;
177  void clear() {
178  Cluster::clear();
179  ecal_et = hcal_et = 0;
180  ecal_eta = ecal_phi = 0;
181  }
182  };
183 
184  const Grid *getGrid(const std::string &type);
185 
187  public:
190  void clear();
191  void add(const reco::Candidate &c) { add(c.pt(), c.eta(), c.phi()); }
192  void add(float pt, float eta, float phi) {
193  rawet_(eta, phi) += pt;
194  if (preciseEtaPhi_) {
195  float newet = rawet_(eta, phi);
196  float prevw = (newet - pt) / newet;
197  float nextw = pt / newet;
198  eta_center_(eta, phi) = eta_center_(eta, phi) * prevw + eta * nextw;
199  phi_center_(eta, phi) = phi_center_(eta, phi) * prevw + phi * nextw;
200  }
201  }
202  void run();
203 
205  // note: there can be some double-counting as the same unclustered energy can go into more clusters
206  void grow();
207 
208  const EtGrid &raw() const { return rawet_; }
209  const EtaPhiCenterGrid &etaCenter() const { return eta_center_; }
210  const EtaPhiCenterGrid &phiCenter() const { return phi_center_; }
211  const IndexGrid &indexGrid() const { return clusterIndex_; }
212  const std::vector<Cluster> &clusters() const { return clusters_; }
213  const Cluster &cluster(int i) const {
214  return (i == -1 || clusterIndex_[i] == -1) ? nullCluster_ : clusters_[clusterIndex_[i]];
215  }
216 
218  EtGrid &raw() { return rawet_; }
221 
222  // for the moment, generic interface that takes a cluster and returns the corrected pt
223  template <typename Corrector>
224  void correct(const Corrector &corrector) {
225  for (Cluster &c : clusters_) {
226  c.et = corrector(c);
227  }
228  }
229 
230  std::unique_ptr<l1t::PFClusterCollection> fetchCells(bool unclusteredOnly = false, float ptMin = 0.) const;
231 
232  std::unique_ptr<l1t::PFClusterCollection> fetch(float ptMin = 0.) const;
233  std::unique_ptr<l1t::PFClusterCollection> fetch(const edm::OrphanHandle<l1t::PFClusterCollection> &cells,
234  float ptMin = 0.) const;
235 
236  private:
237  enum class EnergyShareAlgo {
238  Fractions, /* each local maximum neighbour takes a share proportional to its value */
239  None, /* each local maximum neighbour takes all the value (double counting!) */
240  Greedy, /* assing cell to the highest local maximum neighbour */
241  Crude
242  }; /* if there's more than one local maximum neighbour, they all take half of the value (no fp division) */
243  const Grid *grid_;
250  std::vector<double> etaBounds_;
251  std::vector<double> phiBounds_;
252  std::vector<unsigned int> maxClustersEtaPhi_; //eta x phi
253  std::vector<Cluster> clusters_;
257  bool energyWeightedPosition_; // do the energy-weighted cluster position instead of the cell center
258  std::vector<int> neighborCells_;
259  };
260 
262  public:
264  const SingleCaloClusterer &ecal,
265  const SingleCaloClusterer &hcal);
266  virtual ~SimpleCaloLinkerBase();
267  virtual void clear() { clearBase(); }
268  virtual void run() = 0;
269  void clearBase() {
270  clusters_.clear();
271  clusterIndex_.fill(-1);
272  }
273 
274  // for the moment, generic interface that takes a cluster and returns the corrected pt
275  template <typename Corrector>
276  void correct(const Corrector &corrector) {
277  for (CombinedCluster &c : clusters_) {
278  c.et = corrector(c);
279  }
280  }
281 
282  std::unique_ptr<l1t::PFClusterCollection> fetch() const;
283  std::unique_ptr<l1t::PFClusterCollection> fetch(const edm::OrphanHandle<l1t::PFClusterCollection> &ecal,
285 
286  protected:
287  const Grid *grid_;
290  std::vector<CombinedCluster> clusters_;
291  std::vector<double> etaBounds_;
292  std::vector<double> phiBounds_;
293  std::vector<unsigned int> maxClustersEtaPhi_; //eta x phi
296  };
297 
299  public:
301  ~SimpleCaloLinker() override;
302  void clear() override;
303  void run() override;
304 
305  protected:
307  };
309  public:
311  ~FlatCaloLinker() override;
312  void clear() override;
313  void run() override;
314 
315  protected:
317  };
318 
320  public:
322  ~CombinedCaloLinker() override;
323  void clear() override;
324  void run() override;
325 
326  protected:
328  };
329 
330  class GridSelector {
331  public:
332  GridSelector(std::vector<double> etaBounds, std::vector<double> phiBounds, std::vector<unsigned int> maxClusters);
334  void fill(float pt, float eta, float phi, unsigned int index);
335  std::vector<unsigned int> returnSorted();
336 
337  private:
338  const std::vector<double> etaBounds_;
339  const std::vector<double> phiBounds_;
340  const std::vector<unsigned int> maxClustersEtaPhi_;
341  std::vector<std::vector<std::pair<float, unsigned int>>> regionPtIndices_; //pt and index pairs in each region
342  };
343 
344  // makes a calo linker (pointer will be owned by the callee)
345  std::unique_ptr<SimpleCaloLinkerBase> makeCaloLinker(const edm::ParameterSet &pset,
346  const SingleCaloClusterer &ecal,
347  const SingleCaloClusterer &hcal);
348 
349 } // namespace l1tpf_calo
350 
351 #endif
Phase1GridBase(int nEta, int nPhi, int ietaCoarse, int ietaVeryCoarse, const float *towerEtas)
std::vector< CombinedCluster > clusters_
int iphi(int icell) const
Definition: CaloClusterer.h:33
GridData< float > EtGrid
int imove(int ieta, int iphi, int deta, int dphi)
std::vector< double > etaBounds_
float eta(int icell) const
Definition: CaloClusterer.h:28
GridData< float > EtaPhiCenterGrid
std::vector< float > eta_
Definition: CaloClusterer.h:46
std::vector< unsigned int > maxClustersEtaPhi_
const Grid & grid() const
T & operator()(float eta, float phi)
int ieta(int icell) const
Definition: CaloClusterer.h:32
void fill(const T &val)
const EtaPhiCenterGrid & phiCenter() const
SimpleCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
const SingleCaloClusterer & hcal_
SingleCaloClusterer(const edm::ParameterSet &pset)
const std::vector< unsigned int > maxClustersEtaPhi_
constexpr float ptMin
void fill(float pt, float eta, float phi, unsigned int index)
const IndexGrid & indexGrid() const
int iphi(int icell) const
std::vector< unsigned int > maxClustersEtaPhi_
std::unique_ptr< SimpleCaloLinkerBase > makeCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
assert(be >=bs)
int ieta(int icell) const
CombinedCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
GridData< PreCluster > PreClusterGrid
void add(const reco::Candidate &c)
unsigned int ncells_
Definition: CaloClusterer.h:45
static const int phase1_ietaVeryCoarse_
Definition: CaloClusterer.h:82
std::vector< float > etaWidth_
Definition: CaloClusterer.h:46
std::vector< Cluster > clusters_
const T & operator[](int icell) const
FlatCaloLinker(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
SimpleCaloLinkerBase(const edm::ParameterSet &pset, const SingleCaloClusterer &ecal, const SingleCaloClusterer &hcal)
T & operator[](int icell)
const Grid * getGrid(const std::string &type)
GridData(const Grid &grid)
Definition: CaloClusterer.h:99
bool valid_ieta_iphi(int ieta, int iphi) const
Definition: CaloClusterer.h:63
int ifind_cell(int ieta, int iphi) const
Definition: CaloClusterer.h:56
std::unique_ptr< l1t::PFClusterCollection > fetch() const
SingleCaloClusterer combClusterer_
int find_cell(float eta, float phi) const override
std::vector< int > cell_map_
Definition: CaloClusterer.h:61
int neighbour(int icell, unsigned int idx) const
Definition: CaloClusterer.h:27
std::vector< float > phiWidth_
Definition: CaloClusterer.h:46
static const int phase1_nEta_
Definition: CaloClusterer.h:82
float phi(int icell) const
Definition: CaloClusterer.h:29
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static const int phase2_ietaCoarse_
Definition: CaloClusterer.h:91
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::vector< std::pair< float, unsigned int > > > regionPtIndices_
std::vector< std::pair< int, float > > constituents
std::vector< unsigned int > returnSorted()
const T & operator()(float eta, float phi) const
std::vector< double > phiBounds_
void add(float pt, float eta, float phi)
float phi(float eta, float phi) const
void correct(const Corrector &corrector)
const SingleCaloClusterer & ecal_
const T & neigh(int icell, unsigned int idx) const
static const int phase2_ietaVeryCoarse_
Definition: CaloClusterer.h:91
unsigned int size() const
void correct(const Corrector &corrector)
void grow()
possibly grow clusters by adding unclustered energy on the sides
const std::vector< double > phiBounds_
EtGrid & raw()
non-const access to the energy: be careful to use it only before &#39;run()&#39;
float etaWidth(int icell) const
Definition: CaloClusterer.h:30
std::vector< double > phiBounds_
static const int phase1_ietaCoarse_
Definition: CaloClusterer.h:82
std::vector< T > data_
const EtGrid & raw() const
const std::vector< double > etaBounds_
GridSelector(std::vector< double > etaBounds, std::vector< double > phiBounds, std::vector< unsigned int > maxClusters)
static const int phase2_nPhi_
Definition: CaloClusterer.h:91
std::vector< double > etaBounds_
EtaPhiCenterGrid & phiCenter()
float eta(int icell) const
std::unique_ptr< l1t::PFClusterCollection > fetch(float ptMin=0.) const
const EtaPhiCenterGrid & etaCenter() const
EtaPhiCenterGrid & etaCenter()
float phi(int icell) const
GridData< T > & operator+=(const GridData< T > &other)
SingleCaloClusterer combClusterer_
HLT enums.
float eta(float eta, float phi) const
GridData< int > IndexGrid
std::vector< int > ieta_
Definition: CaloClusterer.h:47
virtual int find_cell(float eta, float phi) const =0
std::vector< int > iphi_
Definition: CaloClusterer.h:47
GridData< T > & operator=(const GridData< T > &other)
Grid(unsigned int size)
Definition: CaloClusterer.h:36
const Cluster & cluster(int i) const
unsigned int size() const
Definition: CaloClusterer.h:25
std::vector< std::array< int, 8 > > neighbours_
Definition: CaloClusterer.h:48
std::vector< int > neighborCells_
long double T
static const float phase1_towerEtas_[phase1_nEta_]
Definition: CaloClusterer.h:83
static const float phase2_towerEtas_[phase2_nEta_]
Definition: CaloClusterer.h:92
const std::vector< Cluster > & clusters() const
float phiWidth(int icell) const
Definition: CaloClusterer.h:31
static const int phase1_nPhi_
Definition: CaloClusterer.h:82