CMS 3D CMS Logo

L1TrackJetClustering.h
Go to the documentation of this file.
1 #ifndef L1Trigger_L1TTrackMatch_L1TrackJetClustering_HH
2 #define L1Trigger_L1TTrackMatch_L1TrackJetClustering_HH
3 #include <iostream>
4 #include <fstream>
5 #include <cmath>
6 #include <cstdlib>
7 #include <string>
8 #include <cstdlib>
13 
14 namespace l1ttrackjet {
15  //For precision studies
16  const unsigned int PT_INTPART_BITS{9};
17  const unsigned int ETA_INTPART_BITS{3};
18  const unsigned int kExtraGlobalPhiBit{4};
19 
20  typedef ap_ufixed<TTTrack_TrackWord::TrackBitWidths::kRinvSize - 1, PT_INTPART_BITS, AP_TRN, AP_SAT> pt_intern;
21  typedef ap_fixed<TTTrack_TrackWord::TrackBitWidths::kTanlSize, ETA_INTPART_BITS, AP_TRN, AP_SAT> glbeta_intern;
22  typedef ap_int<TTTrack_TrackWord::TrackBitWidths::kPhiSize + kExtraGlobalPhiBit> glbphi_intern;
23  typedef ap_int<TTTrack_TrackWord::TrackBitWidths::kZ0Size> z0_intern; // 40cm / 0.1
24  typedef ap_uint<TTTrack_TrackWord::TrackBitWidths::kD0Size> d0_intern;
25 
26  inline const unsigned int DoubleToBit(double value, unsigned int maxBits, double step) {
27  unsigned int digitized_value = std::floor(std::abs(value) / step);
28  unsigned int digitized_maximum = (1 << (maxBits - 1)) - 1; // The remove 1 bit from nBits to account for the sign
29  if (digitized_value > digitized_maximum)
30  digitized_value = digitized_maximum;
31  if (value < 0)
32  digitized_value = (1 << maxBits) - digitized_value; // two's complement encoding
33  return digitized_value;
34  }
35  inline const double BitToDouble(unsigned int bits, unsigned int maxBits, double step) {
36  int isign = 1;
37  unsigned int digitized_maximum = (1 << maxBits) - 1;
38  if (bits & (1 << (maxBits - 1))) { // check the sign
39  isign = -1;
40  bits = (1 << (maxBits + 1)) - bits;
41  }
42  return (double(bits & digitized_maximum) + 0.5) * step * isign;
43  }
44 
45  // eta/phi clusters - simulation
46  struct EtaPhiBin {
47  float pTtot;
48  int ntracks;
49  int nxtracks;
50  bool used;
51  float phi; //average phi value (halfway b/t min and max)
52  float eta; //average eta value
53  std::vector<unsigned int> trackidx;
54  };
55  // z bin struct - simulation (used if z bin are many)
56  struct MaxZBin {
57  int znum; //Numbered from 0 to nzbins (16, 32, or 64) in order
58  int nclust; //number of clusters in this bin
59  float zbincenter;
60  std::vector<EtaPhiBin> clusters; //list of all the clusters in this bin
61  float ht; //sum of all cluster pTs--only the zbin with the maximum ht is stored
62  };
63 
64  // eta/phi clusters - emulation
69  bool used;
70  glbphi_intern phi; //average phi value (halfway b/t min and max)
71  glbeta_intern eta; //average eta value
72  std::vector<unsigned int> trackidx;
73  };
74 
75  // z bin struct - emulation (used if z bin are many)
77  int znum; //Numbered from 0 to nzbins (16, 32, or 64) in order
78  int nclust; //number of clusters in this bin
80  std::vector<TrackJetEmulationEtaPhiBin> clusters; //list of all the clusters in this bin
81  pt_intern ht; //sum of all cluster pTs--only the zbin with the maximum ht is stored
82  };
83 
84  // track quality cuts
85  inline bool TrackQualitySelection(int trk_nstub,
86  double trk_chi2,
87  double trk_bendchi2,
88  double nStubs4PromptBend_,
89  double nStubs5PromptBend_,
90  double nStubs4PromptChi2_,
91  double nStubs5PromptChi2_,
92  double nStubs4DisplacedBend_,
93  double nStubs5DisplacedBend_,
94  double nStubs4DisplacedChi2_,
95  double nStubs5DisplacedChi2_,
96  bool displaced_) {
97  bool PassQuality = false;
98  if (!displaced_) {
99  if (trk_nstub == 4 && trk_bendchi2 < nStubs4PromptBend_ &&
100  trk_chi2 < nStubs4PromptChi2_) // 4 stubs are the lowest track quality and have different cuts
101  PassQuality = true;
102  if (trk_nstub > 4 && trk_bendchi2 < nStubs5PromptBend_ &&
103  trk_chi2 < nStubs5PromptChi2_) // above 4 stubs diffent selection imposed (genrally looser)
104  PassQuality = true;
105  } else {
106  if (trk_nstub == 4 && trk_bendchi2 < nStubs4DisplacedBend_ &&
107  trk_chi2 < nStubs4DisplacedChi2_) // 4 stubs are the lowest track quality and have different cuts
108  PassQuality = true;
109  if (trk_nstub > 4 && trk_bendchi2 < nStubs5DisplacedBend_ &&
110  trk_chi2 < nStubs5DisplacedChi2_) // above 4 stubs diffent selection imposed (genrally looser)
111  PassQuality = true;
112  }
113  return PassQuality;
114  }
115 
116  // L1 clustering (in eta)
117  template <typename T, typename Pt, typename Eta, typename Phi>
118  inline std::vector<T> L1_clustering(T *phislice, int etaBins_, Eta etaStep_) {
119  std::vector<T> clusters;
120  // Find eta bin with maxpT, make center of cluster, add neighbors if not already used
121  int nclust = 0;
122 
123  // get tracks in eta bins in increasing eta order
124  for (int etabin = 0; etabin < etaBins_; ++etabin) {
125  Pt my_pt = 0;
126  Pt previousbin_pt = 0;
127  Pt nextbin_pt = 0;
128  Pt nextbin2_pt = 0;
129 
130  // skip (already) used tracks
131  if (phislice[etabin].used)
132  continue;
133 
134  my_pt = phislice[etabin].pTtot;
135  if (my_pt == 0)
136  continue;
137 
138  //get previous bin pT
139  if (etabin > 0 && !phislice[etabin - 1].used)
140  previousbin_pt = phislice[etabin - 1].pTtot;
141 
142  // get next bins pt
143  if (etabin < etaBins_ - 1 && !phislice[etabin + 1].used) {
144  nextbin_pt = phislice[etabin + 1].pTtot;
145  if (etabin < etaBins_ - 2 && !phislice[etabin + 2].used) {
146  nextbin2_pt = phislice[etabin + 2].pTtot;
147  }
148  }
149  // check if pT of current cluster is higher than neighbors
150  if (my_pt < previousbin_pt || my_pt <= nextbin_pt) {
151  // if unused pT in the left neighbor, spit it out as a cluster
152  if (previousbin_pt > 0) {
153  clusters.push_back(phislice[etabin - 1]);
154  phislice[etabin - 1].used = true;
155  nclust++;
156  }
157  continue; //if it is not the local max pT skip
158  }
159  // here reach only unused local max clusters
160  clusters.push_back(phislice[etabin]);
161  phislice[etabin].used = true; //if current bin a cluster
162  if (previousbin_pt > 0) {
163  clusters[nclust].pTtot += previousbin_pt;
164  clusters[nclust].ntracks += phislice[etabin - 1].ntracks;
165  clusters[nclust].nxtracks += phislice[etabin - 1].nxtracks;
166  for (unsigned int itrk = 0; itrk < phislice[etabin - 1].trackidx.size(); itrk++)
167  clusters[nclust].trackidx.push_back(phislice[etabin - 1].trackidx[itrk]);
168  }
169 
170  if (my_pt >= nextbin2_pt && nextbin_pt > 0) {
171  clusters[nclust].pTtot += nextbin_pt;
172  clusters[nclust].ntracks += phislice[etabin + 1].ntracks;
173  clusters[nclust].nxtracks += phislice[etabin + 1].nxtracks;
174  for (unsigned int itrk = 0; itrk < phislice[etabin + 1].trackidx.size(); itrk++)
175  clusters[nclust].trackidx.push_back(phislice[etabin + 1].trackidx[itrk]);
176  phislice[etabin + 1].used = true;
177  }
178 
179  nclust++;
180 
181  } // for each etabin
182 
183  // Merge close-by clusters
184  for (int m = 0; m < nclust - 1; ++m) {
185  if (((clusters[m + 1].eta - clusters[m].eta) < (3 * etaStep_) / 2) &&
186  (-(3 * etaStep_) / 2 < (clusters[m + 1].eta - clusters[m].eta))) {
187  if (clusters[m + 1].pTtot > clusters[m].pTtot) {
188  clusters[m].eta = clusters[m + 1].eta;
189  }
190  clusters[m].pTtot += clusters[m + 1].pTtot;
191  clusters[m].ntracks += clusters[m + 1].ntracks; // total ntrk
192  clusters[m].nxtracks += clusters[m + 1].nxtracks; // total ndisp
193  for (unsigned int itrk = 0; itrk < clusters[m + 1].trackidx.size(); itrk++)
194  clusters[m].trackidx.push_back(clusters[m + 1].trackidx[itrk]);
195 
196  // if remove the merged cluster - all the others must be closer to 0
197  for (int m1 = m + 1; m1 < nclust - 1; ++m1)
198  clusters[m1] = clusters[m1 + 1];
199 
200  clusters.erase(clusters.begin() + nclust);
201  nclust--;
202  } // end if for cluster merging
203  } // end for (m) loop
204 
205  return clusters;
206  }
207 
208  // Fill L2 clusters (helper function)
209  template <typename T, typename Pt>
210  inline void Fill_L2Cluster(T &bin, Pt pt, int ntrk, int ndtrk, std::vector<unsigned int> trkidx) {
211  bin.pTtot += pt;
212  bin.ntracks += ntrk;
213  bin.nxtracks += ndtrk;
214  for (unsigned int itrk = 0; itrk < trkidx.size(); itrk++)
215  bin.trackidx.push_back(trkidx[itrk]);
216  }
217 
219  glbphi_intern x = phi1 - phi2;
220  if (x >= DoubleToBit(
221  M_PI, TTTrack_TrackWord::TrackBitWidths::kPhiSize + kExtraGlobalPhiBit, TTTrack_TrackWord::stepPhi0))
222  x -= DoubleToBit(
223  2 * M_PI, TTTrack_TrackWord::TrackBitWidths::kPhiSize + kExtraGlobalPhiBit, TTTrack_TrackWord::stepPhi0);
224  if (x < DoubleToBit(-1 * M_PI,
225  TTTrack_TrackWord::TrackBitWidths::kPhiSize + kExtraGlobalPhiBit,
227  x += DoubleToBit(
228  2 * M_PI, TTTrack_TrackWord::TrackBitWidths::kPhiSize + kExtraGlobalPhiBit, TTTrack_TrackWord::stepPhi0);
229  return x;
230  }
231 
232  inline float DPhi(float phi1, float phi2) {
233  float x = phi1 - phi2;
234  if (x >= M_PI)
235  x -= 2 * M_PI;
236  if (x < -1 * M_PI)
237  x += 2 * M_PI;
238  return x;
239  }
240 
241  // L2 clustering (in phi)
242  template <typename T, typename Pt, typename Eta, typename Phi>
243  inline std::vector<T> L2_clustering(std::vector<std::vector<T> > &L1clusters,
244  int phiBins_,
245  Phi phiStep_,
246  Eta etaStep_) {
247  std::vector<T> clusters;
248  for (int phibin = 0; phibin < phiBins_; ++phibin) { //Find eta-phibin with highest pT
249  if (L1clusters[phibin].empty())
250  continue;
251 
252  // sort L1 clusters max -> min
253  sort(L1clusters[phibin].begin(), L1clusters[phibin].end(), [](T &a, T &b) { return a.pTtot > b.pTtot; });
254 
255  for (unsigned int imax = 0; imax < L1clusters[phibin].size(); ++imax) {
256  if (L1clusters[phibin][imax].used)
257  continue;
258  Pt pt_current = L1clusters[phibin][imax].pTtot; //current cluster (pt0)
259  Pt pt_next = 0; // next phi bin (pt1)
260  Pt pt_next2 = 0; // next to next phi bin2 (pt2)
261  int trk1 = 0;
262  int trk2 = 0;
263  int tdtrk1 = 0;
264  int tdtrk2 = 0;
265  std::vector<unsigned int> trkidx1;
266  std::vector<unsigned int> trkidx2;
267  clusters.push_back(L1clusters[phibin][imax]);
268 
269  L1clusters[phibin][imax].used = true;
270 
271  // if we are in the last phi bin, dont check phi+1 phi+2
272  if (phibin == phiBins_ - 1)
273  continue;
274 
275  std::vector<unsigned int> used_already; //keep phi+1 clusters that have been used
276  for (unsigned int icluster = 0; icluster < L1clusters[phibin + 1].size(); ++icluster) {
277  if (L1clusters[phibin + 1][icluster].used)
278  continue;
279 
280  if (((L1clusters[phibin + 1][icluster].eta - L1clusters[phibin][imax].eta) > (3 * etaStep_) / 2) ||
281  ((L1clusters[phibin + 1][icluster].eta - L1clusters[phibin][imax].eta) < -(3 * etaStep_) / 2))
282  continue;
283 
284  pt_next += L1clusters[phibin + 1][icluster].pTtot;
285  trk1 += L1clusters[phibin + 1][icluster].ntracks;
286  tdtrk1 += L1clusters[phibin + 1][icluster].nxtracks;
287 
288  for (unsigned int itrk = 0; itrk < L1clusters[phibin + 1][icluster].trackidx.size(); itrk++)
289  trkidx1.push_back(L1clusters[phibin + 1][icluster].trackidx[itrk]);
290  used_already.push_back(icluster);
291  }
292 
293  if (pt_next < pt_current) { // if pt1<pt1, merge both clusters
294  Fill_L2Cluster<T, Pt>(clusters[clusters.size() - 1], pt_next, trk1, tdtrk1, trkidx1);
295  for (unsigned int iused : used_already)
296  L1clusters[phibin + 1][iused].used = true;
297  continue;
298  }
299  // if phi = next to last bin there is no "next to next"
300  if (phibin == phiBins_ - 2) {
301  Fill_L2Cluster<T, Pt>(clusters[clusters.size() - 1], pt_next, trk1, tdtrk1, trkidx1);
302  clusters[clusters.size() - 1].phi = L1clusters[phibin + 1][used_already[0]].phi;
303  for (unsigned int iused : used_already)
304  L1clusters[phibin + 1][iused].used = true;
305  continue;
306  }
307  std::vector<int> used_already2; //keep used clusters in phi+2
308  for (unsigned int icluster = 0; icluster < L1clusters[phibin + 2].size(); ++icluster) {
309  if (L1clusters[phibin + 2][icluster].used)
310  continue;
311  if (((L1clusters[phibin + 2][icluster].eta - L1clusters[phibin][imax].eta) > (3 * etaStep_) / 2) ||
312  ((L1clusters[phibin + 2][icluster].eta - L1clusters[phibin][imax].eta) < -(3 * etaStep_) / 2))
313  continue;
314  pt_next2 += L1clusters[phibin + 2][icluster].pTtot;
315  trk2 += L1clusters[phibin + 2][icluster].ntracks;
316  tdtrk2 += L1clusters[phibin + 2][icluster].nxtracks;
317 
318  for (unsigned int itrk = 0; itrk < L1clusters[phibin + 2][icluster].trackidx.size(); itrk++)
319  trkidx2.push_back(L1clusters[phibin + 2][icluster].trackidx[itrk]);
320  used_already2.push_back(icluster);
321  }
322  if (pt_next2 < pt_next) {
323  std::vector<unsigned int> trkidx_both;
324  trkidx_both.reserve(trkidx1.size() + trkidx2.size());
325  trkidx_both.insert(trkidx_both.end(), trkidx1.begin(), trkidx1.end());
326  trkidx_both.insert(trkidx_both.end(), trkidx2.begin(), trkidx2.end());
327  Fill_L2Cluster<T, Pt>(
328  clusters[clusters.size() - 1], pt_next + pt_next2, trk1 + trk2, tdtrk1 + tdtrk2, trkidx_both);
329  clusters[clusters.size() - 1].phi = L1clusters[phibin + 1][used_already[0]].phi;
330  for (unsigned int iused : used_already)
331  L1clusters[phibin + 1][iused].used = true;
332  for (unsigned int iused : used_already2)
333  L1clusters[phibin + 2][iused].used = true;
334  }
335  } // for each L1 cluster
336  } // for each phibin
337 
338  int nclust = clusters.size();
339 
340  // merge close-by clusters
341  for (int m = 0; m < nclust - 1; ++m) {
342  for (int n = m + 1; n < nclust; ++n) {
343  if (clusters[n].eta != clusters[m].eta)
344  continue;
345  if ((DPhi(clusters[n].phi, clusters[m].phi) > (3 * phiStep_) / 2) ||
346  (DPhi(clusters[n].phi, clusters[m].phi) < -(3 * phiStep_) / 2))
347  continue;
348  if (clusters[n].pTtot > clusters[m].pTtot)
349  clusters[m].phi = clusters[n].phi;
350  clusters[m].pTtot += clusters[n].pTtot;
351  clusters[m].ntracks += clusters[n].ntracks;
352  clusters[m].nxtracks += clusters[n].nxtracks;
353  for (unsigned int itrk = 0; itrk < clusters[n].trackidx.size(); itrk++)
354  clusters[m].trackidx.push_back(clusters[n].trackidx[itrk]);
355  for (int m1 = n; m1 < nclust - 1; ++m1)
356  clusters[m1] = clusters[m1 + 1];
357  clusters.erase(clusters.begin() + nclust);
358 
359  nclust--;
360  } // end of n-loop
361  } // end of m-loop
362  return clusters;
363  }
364 } // namespace l1ttrackjet
365 #endif
ap_uint< TTTrack_TrackWord::TrackBitWidths::kD0Size > d0_intern
const unsigned int kExtraGlobalPhiBit
bool TrackQualitySelection(int trk_nstub, double trk_chi2, double trk_bendchi2, double nStubs4PromptBend_, double nStubs5PromptBend_, double nStubs4PromptChi2_, double nStubs5PromptChi2_, double nStubs4DisplacedBend_, double nStubs5DisplacedBend_, double nStubs4DisplacedChi2_, double nStubs5DisplacedChi2_, bool displaced_)
const unsigned int DoubleToBit(double value, unsigned int maxBits, double step)
std::vector< unsigned int > trackidx
const unsigned int ETA_INTPART_BITS
constexpr uint32_t bits
Definition: gpuClustering.h:25
const unsigned int PT_INTPART_BITS
const double BitToDouble(unsigned int bits, unsigned int maxBits, double step)
ap_fixed< TTTrack_TrackWord::TrackBitWidths::kTanlSize, ETA_INTPART_BITS, AP_TRN, AP_SAT > glbeta_intern
ap_ufixed< TTTrack_TrackWord::TrackBitWidths::kRinvSize - 1, PT_INTPART_BITS, AP_TRN, AP_SAT > pt_intern
std::vector< EtaPhiBin > clusters
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
ap_int< TTTrack_TrackWord::TrackBitWidths::kZ0Size > z0_intern
Definition: value.py:1
std::vector< TrackJetEmulationEtaPhiBin > clusters
ap_uint< kXtSize > nx_t
Definition: TkJetWord.h:63
#define M_PI
glbphi_intern DPhi(glbphi_intern phi1, glbphi_intern phi2)
void Fill_L2Cluster(T &bin, Pt pt, int ntrk, int ndtrk, std::vector< unsigned int > trkidx)
ap_int< TTTrack_TrackWord::TrackBitWidths::kPhiSize+kExtraGlobalPhiBit > glbphi_intern
double b
Definition: hdecay.h:120
static constexpr double stepPhi0
ap_uint< kNtSize > nt_t
Definition: TkJetWord.h:62
double a
Definition: hdecay.h:121
float x
std::vector< T > L2_clustering(std::vector< std::vector< T > > &L1clusters, int phiBins_, Phi phiStep_, Eta etaStep_)
step
Definition: StallMonitor.cc:83
std::vector< T > L1_clustering(T *phislice, int etaBins_, Eta etaStep_)
long double T