Crombie Tools
EtaPhiMap.h
Go to the documentation of this file.
1 #ifndef CROMBIE_ETAPHIMAP_H
2 #define CROMBIE_ETAPHIMAP_H 1
3 
4 #include <vector>
5 #include <cmath>
6 #include <functional>
7 #include "TMath.h"
8 #include "TVector2.h"
9 
11 
12 template<typename T>
13 class EtaPhiMap {
14  public:
15  EtaPhiMap (double spacing, double maxeta = 5.0,
16  std::function<double(const T*)> eta = [](const T* p){ return p->eta(); },
17  std::function<double(const T*)> phi = [](const T* p){ return p->phi(); })
18  : _spacing{spacing}, _maxeta{maxeta},
19  n_etabins{2 * (static_cast<unsigned>(std::ceil(_maxeta/_spacing)) + 1)}, // Add one for over/underflow and times two for positive and negative
20  n_phibins{static_cast<unsigned>(std::ceil(TMath::TwoPi()/_spacing))}, // Always transform phi into [0, 2pi) in bin
21  geteta{eta}, getphi{phi} {
22 
23  particles.resize(n_etabins * n_phibins);
24 
25  }
26 
27  /// Add a collection of particles to the grid. Call once per event, because this gets cleared
28  template<typename C> void AddParticles (C& collection);
29 
30  /// Get particles within dr of a given eta, phi
31  std::vector<const T*> GetParticles(double eta, double phi, double dr) const;
32 
33  private:
34 
35  /// Stores all of the particles
36  std::vector<std::vector<const T*>> particles;
37  /// Spacing of each grid
38  double _spacing;
39  /// Max eta of grid (has overflow and underflow bins)
40  double _maxeta;
41 
42  /// Number of eta bins
43  unsigned n_etabins;
44  /// Number of phi bins
45  unsigned n_phibins;
46 
47  std::function<double(const T*)> geteta; ///< Function for getting eta from pointers
48  std::function<double(const T*)> getphi; ///< Function for getting phi from pointers
49 
50  /// Reset the particles in each grid point
51  void clear();
52  /// Get the bin number
53  unsigned bin(double eta, double phi) const;
54  unsigned bin(unsigned eta_bin, unsigned phi_bin) const;
55  /// Get eta bin
56  unsigned etabin(double eta) const;
57  /// Get phi bin
58  unsigned phibin(double phi) const;
59 
60 };
61 
62 
63 template<typename T>
64 template<typename C>
65 void EtaPhiMap<T>::AddParticles (C& collection) {
66 
67  // Only call this function when adding a full collection
68  clear();
69 
70  for (auto& cand : collection) {
71  auto* ptr = &cand;
72  particles[bin(geteta(ptr), getphi(ptr))].push_back(ptr);
73  }
74 
75 }
76 
77 
78 template<typename T>
79 std::vector<const T*> EtaPhiMap<T>::GetParticles(double eta, double phi, double dr) const {
80  double dr2 = std::pow(dr, 2);
81 
82  std::vector<const T*> output;
83 
84  auto min_eta = etabin(eta - dr);
85  auto max_eta = etabin(eta + dr);
86  auto min_phi = phibin(phi - dr);
87  auto max_phi = phibin(phi + dr);
88 
89  auto running_phi = min_phi;
90  while (true) {
91  for (auto running_eta = min_eta; running_eta <= max_eta; ++running_eta) {
92  for (auto* particle : particles[bin(running_eta, running_phi)]) {
93  if (deltaR2(eta, phi, geteta(particle), getphi(particle)) < dr2)
94  output.push_back(particle);
95  }
96  }
97  // If at the end of phi, break after processing
98  if (running_phi == max_phi)
99  break;
100  // Increment and go to zero if at the end of phi
101  if (++running_phi == n_phibins)
102  running_phi = 0;
103  }
104 
105  return output;
106 
107 }
108 
109 
110 template<typename T>
111 unsigned EtaPhiMap<T>::bin(double eta, double phi) const {
112  return bin(etabin(eta), phibin(phi));
113 }
114 
115 template<typename T>
116 unsigned EtaPhiMap<T>::bin(unsigned eta_bin, unsigned phi_bin) const {
117  return n_etabins * phi_bin + eta_bin;
118 }
119 
120 template<typename T>
121 unsigned EtaPhiMap<T>::etabin(double eta) const {
122  return std::max(0u, std::min(n_etabins - 1, n_etabins/2 + static_cast<unsigned>(eta/_spacing)));
123 }
124 
125 template<typename T>
126 unsigned EtaPhiMap<T>::phibin(double phi) const {
127  return TVector2::Phi_0_2pi(phi)/_spacing;
128 }
129 
130 
131 template<typename T>
133  for (auto& grid : particles)
134  grid.clear();
135 }
136 
137 
138 #endif