CMS 3D CMS Logo

L1Clustering.h
Go to the documentation of this file.
1 #ifndef L1Trigger_L1TTrackMatch_L1Clustering_HH
2 #define L1Trigger_L1TTrackMatch_L1Clustering_HH
3 #include <cmath>
4 #include <cstdlib>
5 #include <vector>
6 #include <algorithm>
7 
8 //Each individual box in the eta and phi dimension.
9 // Also used to store final cluster data for each zbin.
10 struct EtaPhiBin {
11  float pTtot = 0;
12  int numtracks = 0;
13  int numttrks = 0;
14  int numtdtrks = 0;
15  int numttdtrks = 0;
16  bool used = false;
17  float phi; //average phi value (halfway b/t min and max)
18  float eta; //average eta value
19  std::vector<unsigned int> trackidx;
20 };
21 
22 //store important information for plots
23 struct MaxZBin {
24  int znum; //Numbered from 0 to nzbins (16, 32, or 64) in order
25  int nclust; //number of clusters in this bin
26  float zbincenter;
27  std::vector<EtaPhiBin> clusters; //list of all the clusters in this bin
28  float ht; //sum of all cluster pTs--only the zbin with the maximum ht is stored
29 };
30 
31 inline std::vector<EtaPhiBin> L1_clustering(EtaPhiBin *phislice, int etaBins_, float etaStep_) {
32  std::vector<EtaPhiBin> clusters;
33  // Find eta-phibin with maxpT, make center of cluster, add neighbors if not already used
34  int nclust = 0;
35 
36  // get tracks in eta bins in increasing eta order
37  for (int etabin = 0; etabin < etaBins_; ++etabin) {
38  float my_pt = 0, previousbin_pt = 0; //, nextbin_pt=0, next2bin_pt=0;
39  float nextbin_pt = 0, nextbin2_pt = 0;
40 
41  // skip (already) used tracks
42  if (phislice[etabin].used)
43  continue;
44  my_pt = phislice[etabin].pTtot;
45  if (my_pt == 0)
46  continue;
47  //get previous bin pT
48  if (etabin > 0 && !phislice[etabin - 1].used)
49  previousbin_pt = phislice[etabin - 1].pTtot;
50 
51  // get next bins pt
52  if (etabin < etaBins_ - 1 && !phislice[etabin + 1].used) {
53  nextbin_pt = phislice[etabin + 1].pTtot;
54  if (etabin < etaBins_ - 2 && !phislice[etabin + 2].used) {
55  nextbin2_pt = phislice[etabin + 2].pTtot;
56  }
57  }
58  // check if pT of current cluster is higher than neighbors
59  if (my_pt < previousbin_pt || my_pt <= nextbin_pt) {
60  // if unused pT in the left neighbor, spit it out as a cluster
61  if (previousbin_pt > 0) {
62  clusters.push_back(phislice[etabin - 1]);
63  phislice[etabin - 1].used = true;
64  nclust++;
65  }
66  continue; //if it is not the local max pT skip
67  }
68  // here reach only unused local max clusters
69  clusters.push_back(phislice[etabin]);
70  phislice[etabin].used = true; //if current bin a cluster
71  if (previousbin_pt > 0) {
72  clusters[nclust].pTtot += previousbin_pt;
73  clusters[nclust].numtracks += phislice[etabin - 1].numtracks;
74  clusters[nclust].numtdtrks += phislice[etabin - 1].numtdtrks;
75  for (unsigned int itrk = 0; itrk < phislice[etabin - 1].trackidx.size(); itrk++)
76  clusters[nclust].trackidx.push_back(phislice[etabin - 1].trackidx[itrk]);
77  }
78 
79  if (my_pt >= nextbin2_pt && nextbin_pt > 0) {
80  clusters[nclust].pTtot += nextbin_pt;
81  clusters[nclust].numtracks += phislice[etabin + 1].numtracks;
82  clusters[nclust].numtdtrks += phislice[etabin + 1].numtdtrks;
83  for (unsigned int itrk = 0; itrk < phislice[etabin + 1].trackidx.size(); itrk++)
84  clusters[nclust].trackidx.push_back(phislice[etabin + 1].trackidx[itrk]);
85  phislice[etabin + 1].used = true;
86  }
87 
88  nclust++;
89 
90  } // for each etabin
91 
92  // Merge close-by clusters
93  for (int m = 0; m < nclust - 1; ++m) {
94  if (std::abs(clusters[m + 1].eta - clusters[m].eta) < 1.5 * etaStep_) {
95  if (clusters[m + 1].pTtot > clusters[m].pTtot) {
96  clusters[m].eta = clusters[m + 1].eta;
97  }
98  clusters[m].pTtot += clusters[m + 1].pTtot;
99  clusters[m].numtracks += clusters[m + 1].numtracks; // total ntrk
100  clusters[m].numtdtrks += clusters[m + 1].numtdtrks; // total ndisp
101  for (unsigned int itrk = 0; itrk < clusters[m + 1].trackidx.size(); itrk++)
102  clusters[m].trackidx.push_back(clusters[m + 1].trackidx[itrk]);
103 
104  // if remove the merged cluster - all the others must be closer to 0
105  for (int m1 = m + 1; m1 < nclust - 1; ++m1) {
106  clusters[m1] = clusters[m1 + 1];
107  //clusters.erase(clusters.begin()+m1);
108  }
109  // clusters[m1] = clusters[m1 + 1];
110  clusters.erase(clusters.begin() + nclust);
111  nclust--;
112  m = -1;
113  } // end if clusters neighbor in eta
114  } // end for (m) loop
115 
116  return clusters;
117 }
118 
119 inline void Fill_L2Cluster(EtaPhiBin &bin, float pt, int ntrk, int ndtrk, std::vector<unsigned int> trkidx) {
120  bin.pTtot += pt;
121  bin.numtracks += ntrk;
122  bin.numtdtrks += ndtrk;
123  for (unsigned int itrk = 0; itrk < trkidx.size(); itrk++)
124  bin.trackidx.push_back(trkidx[itrk]);
125 }
126 
127 inline float DPhi(float phi1, float phi2) {
128  float x = phi1 - phi2;
129  if (x >= M_PI)
130  x -= 2 * M_PI;
131  if (x < -1 * M_PI)
132  x += 2 * M_PI;
133  return x;
134 }
135 
136 inline std::vector<EtaPhiBin> L2_clustering(std::vector<std::vector<EtaPhiBin>> &L1clusters,
137  int phiBins_,
138  float phiStep_,
139  float etaStep_) {
140  std::vector<EtaPhiBin> clusters;
141  for (int phibin = 0; phibin < phiBins_; ++phibin) { //Find eta-phibin with highest pT
142  if (L1clusters[phibin].empty())
143  continue;
144 
145  // sort L1 clusters max -> min
146  sort(L1clusters[phibin].begin(), L1clusters[phibin].end(), [](struct EtaPhiBin &a, struct EtaPhiBin &b) {
147  return a.pTtot > b.pTtot;
148  });
149  for (unsigned int imax = 0; imax < L1clusters[phibin].size(); ++imax) {
150  if (L1clusters[phibin][imax].used)
151  continue;
152  float pt_current = L1clusters[phibin][imax].pTtot; //current cluster (pt0)
153  float pt_next = 0; // next phi bin (pt1)
154  float pt_next2 = 0; // next to next phi bin2 (pt2)
155  int trk1 = 0;
156  int trk2 = 0;
157  int tdtrk1 = 0;
158  int tdtrk2 = 0;
159  std::vector<unsigned int> trkidx1;
160  std::vector<unsigned int> trkidx2;
161  clusters.push_back(L1clusters[phibin][imax]);
162 
163  L1clusters[phibin][imax].used = true;
164 
165  // if we are in the last phi bin, dont check phi+1 phi+2
166  if (phibin == phiBins_ - 1)
167  continue;
168  std::vector<unsigned int> used_already; //keep phi+1 clusters that have been used
169  for (unsigned int icluster = 0; icluster < L1clusters[phibin + 1].size(); ++icluster) {
170  if (L1clusters[phibin + 1][icluster].used)
171  continue;
172  if (std::abs(L1clusters[phibin + 1][icluster].eta - L1clusters[phibin][imax].eta) > 1.5 * etaStep_)
173  continue;
174  pt_next += L1clusters[phibin + 1][icluster].pTtot;
175  trk1 += L1clusters[phibin + 1][icluster].numtracks;
176  tdtrk1 += L1clusters[phibin + 1][icluster].numtdtrks;
177  for (unsigned int itrk = 0; itrk < L1clusters[phibin + 1][icluster].trackidx.size(); itrk++)
178  trkidx1.push_back(L1clusters[phibin + 1][icluster].trackidx[itrk]);
179  used_already.push_back(icluster);
180  }
181 
182  if (pt_next < pt_current) { // if pt1<pt1, merge both clusters
183  Fill_L2Cluster(clusters[clusters.size() - 1], pt_next, trk1, tdtrk1, trkidx1);
184  for (unsigned int iused : used_already)
185  L1clusters[phibin + 1][iused].used = true;
186  continue;
187  }
188  // if phi = next to last bin there is no "next to next"
189  if (phibin == phiBins_ - 2) {
190  Fill_L2Cluster(clusters[clusters.size() - 1], pt_next, trk1, tdtrk1, trkidx1);
191  clusters[clusters.size() - 1].phi = L1clusters[phibin + 1][used_already[0]].phi;
192  for (unsigned int iused : used_already)
193  L1clusters[phibin + 1][iused].used = true;
194  continue;
195  }
196  std::vector<int> used_already2; //keep used clusters in phi+2
197  for (unsigned int icluster = 0; icluster < L1clusters[phibin + 2].size(); ++icluster) {
198  if (L1clusters[phibin + 2][icluster].used)
199  continue;
200  if (std::abs(L1clusters[phibin + 2][icluster].eta - L1clusters[phibin][imax].eta) > 1.5 * etaStep_)
201  continue;
202  pt_next2 += L1clusters[phibin + 2][icluster].pTtot;
203  trk2 += L1clusters[phibin + 2][icluster].numtracks;
204  tdtrk2 += L1clusters[phibin + 2][icluster].numtdtrks;
205  for (unsigned int itrk = 0; itrk < L1clusters[phibin + 2][icluster].trackidx.size(); itrk++)
206  trkidx2.push_back(L1clusters[phibin + 2][icluster].trackidx[itrk]);
207  used_already2.push_back(icluster);
208  }
209  if (pt_next2 < pt_next) {
210  std::vector<unsigned int> trkidx_both;
211  trkidx_both.reserve(trkidx1.size() + trkidx2.size());
212  trkidx_both.insert(trkidx_both.end(), trkidx1.begin(), trkidx1.end());
213  trkidx_both.insert(trkidx_both.end(), trkidx2.begin(), trkidx2.end());
214  Fill_L2Cluster(clusters[clusters.size() - 1], pt_next + pt_next2, trk1 + trk2, tdtrk1 + tdtrk2, trkidx_both);
215  clusters[clusters.size() - 1].phi = L1clusters[phibin + 1][used_already[0]].phi;
216  for (unsigned int iused : used_already)
217  L1clusters[phibin + 1][iused].used = true;
218  for (unsigned int iused : used_already2)
219  L1clusters[phibin + 2][iused].used = true;
220  }
221  } // for each L1 cluster
222  } // for each phibin
223 
224  int nclust = clusters.size();
225 
226  // merge close-by clusters
227  for (int m = 0; m < nclust - 1; ++m) {
228  for (int n = m + 1; n < nclust; ++n) {
229  if (clusters[n].eta != clusters[m].eta)
230  continue;
231  if (std::abs(DPhi(clusters[n].phi, clusters[m].phi)) > 1.5 * phiStep_)
232  continue;
233 
234  if (clusters[n].pTtot > clusters[m].pTtot)
235  clusters[m].phi = clusters[n].phi;
236 
237  clusters[m].pTtot += clusters[n].pTtot;
238  clusters[m].numtracks += clusters[n].numtracks;
239  clusters[m].numtdtrks += clusters[n].numtdtrks;
240  for (unsigned int itrk = 0; itrk < clusters[n].trackidx.size(); itrk++)
241  clusters[m].trackidx.push_back(clusters[n].trackidx[itrk]);
242  for (int m1 = n; m1 < nclust - 1; ++m1)
243  clusters[m1] = clusters[m1 + 1];
244  clusters.erase(clusters.begin() + nclust);
245 
246  nclust--;
247  } // end of n-loop
248  } // end of m-loop
249  return clusters;
250 }
251 #endif
std::vector< EtaPhiBin > L2_clustering(std::vector< std::vector< EtaPhiBin >> &L1clusters, int phiBins_, float phiStep_, float etaStep_)
Definition: L1Clustering.h:136
void Fill_L2Cluster(EtaPhiBin &bin, float pt, int ntrk, int ndtrk, std::vector< unsigned int > trkidx)
Definition: L1Clustering.h:119
int numttdtrks
Definition: L1Clustering.h:15
float phi
Definition: L1Clustering.h:17
std::vector< unsigned int > trackidx
Definition: L1Clustering.h:19
float ht
Definition: L1Clustering.h:28
int nclust
Definition: L1Clustering.h:25
float zbincenter
Definition: L1Clustering.h:26
int numttrks
Definition: L1Clustering.h:13
std::vector< EtaPhiBin > L1_clustering(EtaPhiBin *phislice, int etaBins_, float etaStep_)
Definition: L1Clustering.h:31
float pTtot
Definition: L1Clustering.h:11
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int numtdtrks
Definition: L1Clustering.h:14
#define M_PI
float eta
Definition: L1Clustering.h:18
int numtracks
Definition: L1Clustering.h:12
double b
Definition: hdecay.h:118
double a
Definition: hdecay.h:119
float x
float DPhi(float phi1, float phi2)
Definition: L1Clustering.h:127
std::vector< EtaPhiBin > clusters
Definition: L1Clustering.h:27
int znum
Definition: L1Clustering.h:24