CMS 3D CMS Logo

pixelCPEforGPU.h
Go to the documentation of this file.
1 #ifndef RecoLocalTracker_SiPixelRecHits_pixelCPEforGPU_h
2 #define RecoLocalTracker_SiPixelRecHits_pixelCPEforGPU_h
3 
4 #include <cassert>
5 #include <cmath>
6 #include <cstdint>
7 #include <iterator>
8 
14 
16  // From https://cmssdt.cern.ch/dxr/CMSSW/source/CondFormats/SiPixelTransient/src/SiPixelGenError.cc#485-486
17  // qbin: int (0-4) describing the charge of the cluster
18  // [0: 1.5<Q/Qavg, 1: 1<Q/Qavg<1.5, 2: 0.85<Q/Qavg<1, 3: 0.95Qmin<Q<0.85Qavg, 4: Q<0.95Qmin]
19  constexpr int kGenErrorQBins = 5;
20  // arbitrary number of bins for sampling errors
21  constexpr int kNumErrorBins = 16;
22 } // namespace CPEFastParametrisation
23 
24 namespace pixelCPEforGPU {
25 
29 
30  // all modules are identical!
31  struct CommonParams {
34  float thePitchX;
35  float thePitchY;
36 
37  bool isPhase2;
38  uint16_t maxModuleStride;
40  };
41 
42  struct DetParams {
43  bool isBarrel;
44  bool isPosZ;
45  uint16_t layer;
46  uint16_t index;
47  uint32_t rawId;
48 
49  float shiftX;
50  float shiftY;
51  float chargeWidthX;
52  float chargeWidthY;
53  uint16_t pixmx; // max pix charge
54 
55  uint16_t nRowsRoc; //we don't need 2^16 columns, is worth to use 15 + 1 for sign
56  uint16_t nColsRoc;
57  uint16_t nRows;
58  uint16_t nCols;
59 
60  uint32_t numPixsInModule;
61 
62  float x0, y0, z0; // the vertex in the local coord of the detector
63 
64  float apeXX, apeYY; // ape^2
65  uint8_t sx2, sy1, sy2;
70 
72  };
73 
75 
76  struct LayerGeometry {
79  uint16_t maxModuleStride;
80  };
81 
82  struct ParamsOnGPU {
87 
88  constexpr CommonParams const& __restrict__ commonParams() const {
89  CommonParams const* __restrict__ l = m_commonParams;
90  return *l;
91  }
92  constexpr DetParams const& __restrict__ detParams(int i) const {
93  DetParams const* __restrict__ l = m_detParams;
94  return l[i];
95  }
96  constexpr LayerGeometry const& __restrict__ layerGeometry() const { return *m_layerGeometry; }
97  constexpr AverageGeometry const& __restrict__ averageGeometry() const { return *m_averageGeometry; }
98 
99  __device__ uint8_t layer(uint16_t id) const {
101  };
102  };
103 
104  // SOA (on device)
105  template <uint32_t N>
106  struct ClusParamsT {
107  uint32_t minRow[N];
108  uint32_t maxRow[N];
109  uint32_t minCol[N];
110  uint32_t maxCol[N];
111 
112  int32_t q_f_X[N];
113  int32_t q_l_X[N];
114  int32_t q_f_Y[N];
115  int32_t q_l_Y[N];
116 
117  int32_t charge[N];
118 
119  float xpos[N];
120  float ypos[N];
121 
122  float xerr[N];
123  float yerr[N];
124 
125  int16_t xsize[N]; // (*8) clipped at 127 if negative is edge....
126  int16_t ysize[N];
127 
129  };
130 
133 
134  constexpr inline void computeAnglesFromDet(
135  DetParams const& __restrict__ detParams, float const x, float const y, float& cotalpha, float& cotbeta) {
136  // x,y local position on det
137  auto gvx = x - detParams.x0;
138  auto gvy = y - detParams.y0;
139  auto gvz = -1.f / detParams.z0;
140  // normalization not required as only ratio used...
141  // calculate angles
142  cotalpha = gvx * gvz;
143  cotbeta = gvy * gvz;
144  }
145 
146  constexpr inline float correction(int sizeM1,
147  int q_f,
148  int q_l,
149  uint16_t upper_edge_first_pix,
150  uint16_t lower_edge_last_pix,
151  float lorentz_shift,
152  float theThickness, //detector thickness
153  float cot_angle,
154  float pitch,
155  bool first_is_big,
156  bool last_is_big)
157  {
158  if (0 == sizeM1) // size 1
159  return 0;
160 
161  float w_eff = 0;
162  bool simple = true;
163  if (1 == sizeM1) { // size 2
164  //--- Width of the clusters minus the edge (first and last) pixels.
165  //--- In the note, they are denoted x_F and x_L (and y_F and y_L)
166  // assert(lower_edge_last_pix >= upper_edge_first_pix);
167  auto w_inner = pitch * float(lower_edge_last_pix - upper_edge_first_pix); // in cm
168 
169  //--- Predicted charge width from geometry
170  auto w_pred = theThickness * cot_angle // geometric correction (in cm)
171  - lorentz_shift; // (in cm) &&& check fpix!
172 
173  w_eff = std::abs(w_pred) - w_inner;
174 
175  //--- If the observed charge width is inconsistent with the expectations
176  //--- based on the track, do *not* use w_pred-w_inner. Instead, replace
177  //--- it with an *average* effective charge width, which is the average
178  //--- length of the edge pixels.
179 
180  // this can produce "large" regressions for very small numeric differences
181  simple = (w_eff < 0.0f) | (w_eff > pitch);
182  }
183 
184  if (simple) {
185  //--- Total length of the two edge pixels (first+last)
186  float sum_of_edge = 2.0f;
187  if (first_is_big)
188  sum_of_edge += 1.0f;
189  if (last_is_big)
190  sum_of_edge += 1.0f;
191  w_eff = pitch * 0.5f * sum_of_edge; // ave. length of edge pixels (first+last) (cm)
192  }
193 
194  //--- Finally, compute the position in this projection
195  float qdiff = q_l - q_f;
196  float qsum = q_l + q_f;
197 
198  //--- Temporary fix for clusters with both first and last pixel with charge = 0
199  if (qsum == 0)
200  qsum = 1.0f;
201 
202  return 0.5f * (qdiff / qsum) * w_eff;
203  }
204 
205  constexpr inline void position(CommonParams const& __restrict__ comParams,
206  DetParams const& __restrict__ detParams,
207  ClusParams& cp,
208  uint32_t ic) {
209  //--- Upper Right corner of Lower Left pixel -- in measurement frame
210  uint16_t llx = cp.minRow[ic] + 1;
211  uint16_t lly = cp.minCol[ic] + 1;
212 
213  //--- Lower Left corner of Upper Right pixel -- in measurement frame
214  uint16_t urx = cp.maxRow[ic];
215  uint16_t ury = cp.maxCol[ic];
216 
217  uint16_t llxl = llx, llyl = lly, urxl = urx, uryl = ury;
218  if (!comParams.isPhase2) //only in Phase1
219  {
220  llxl = phase1PixelTopology::localX(llx);
221  llyl = phase1PixelTopology::localY(lly);
222  urxl = phase1PixelTopology::localX(urx);
223  uryl = phase1PixelTopology::localY(ury);
224  }
225 
226  auto mx = llxl + urxl;
227  auto my = llyl + uryl;
228 
229  auto xsize = int(urxl) + 2 - int(llxl);
230  auto ysize = int(uryl) + 2 - int(llyl);
231  assert(xsize >= 0); // 0 if bixpix...
232  assert(ysize >= 0);
233 
234  if (!comParams.isPhase2) //Phase 1 big pixels
235  {
236  if (phase1PixelTopology::isBigPixX(cp.minRow[ic]))
237  ++xsize;
238  if (phase1PixelTopology::isBigPixX(cp.maxRow[ic]))
239  ++xsize;
240  if (phase1PixelTopology::isBigPixY(cp.minCol[ic]))
241  ++ysize;
242  if (phase1PixelTopology::isBigPixY(cp.maxCol[ic]))
243  ++ysize;
244  }
245 
246  int unbalanceX = 8.f * std::abs(float(cp.q_f_X[ic] - cp.q_l_X[ic])) / float(cp.q_f_X[ic] + cp.q_l_X[ic]);
247  int unbalanceY = 8.f * std::abs(float(cp.q_f_Y[ic] - cp.q_l_Y[ic])) / float(cp.q_f_Y[ic] + cp.q_l_Y[ic]);
248  xsize = 8 * xsize - unbalanceX;
249  ysize = 8 * ysize - unbalanceY;
250 
251  cp.xsize[ic] = std::min(xsize, comParams.isPhase2 ? 2047 : 1023);
252  cp.ysize[ic] = std::min(ysize, comParams.isPhase2 ? 2047 : 1023);
253 
254  if (cp.minRow[ic] == 0 || cp.maxRow[ic] == phase1PixelTopology::lastRowInModule)
255  cp.xsize[ic] = -cp.xsize[ic];
256  if (cp.minCol[ic] == 0 || cp.maxCol[ic] == phase1PixelTopology::lastColInModule)
257  cp.ysize[ic] = -cp.ysize[ic];
258 
259  // apply the lorentz offset correction
260  float xoff = 0.5f * float(detParams.nRows) * comParams.thePitchX;
261  float yoff = 0.5f * float(detParams.nCols) * comParams.thePitchY;
262 
263  if (!comParams.isPhase2) //correction for bigpixels for phase1
264  {
265  xoff = xoff + comParams.thePitchX;
266  yoff = yoff + 8.0f * comParams.thePitchY;
267  }
268  // apply the lorentz offset correction
269  auto xPos = detParams.shiftX + (comParams.thePitchX * 0.5f * float(mx)) - xoff;
270  auto yPos = detParams.shiftY + (comParams.thePitchY * 0.5f * float(my)) - yoff;
271 
272  float cotalpha = 0, cotbeta = 0;
273 
274  computeAnglesFromDet(detParams, xPos, yPos, cotalpha, cotbeta);
275 
276  auto thickness = detParams.isBarrel ? comParams.theThicknessB : comParams.theThicknessE;
277 
278  auto xcorr = correction(cp.maxRow[ic] - cp.minRow[ic],
279  cp.q_f_X[ic],
280  cp.q_l_X[ic],
281  llxl,
282  urxl,
283  detParams.chargeWidthX, // lorentz shift in cm
284  thickness,
285  cotalpha,
286  comParams.thePitchX,
287  comParams.isPhase2 ? false : phase1PixelTopology::isBigPixX(cp.minRow[ic]),
288  comParams.isPhase2 ? false : phase1PixelTopology::isBigPixX(cp.maxRow[ic]));
289 
290  auto ycorr = correction(cp.maxCol[ic] - cp.minCol[ic],
291  cp.q_f_Y[ic],
292  cp.q_l_Y[ic],
293  llyl,
294  uryl,
295  detParams.chargeWidthY, // lorentz shift in cm
296  thickness,
297  cotbeta,
298  comParams.thePitchY,
299  comParams.isPhase2 ? false : phase1PixelTopology::isBigPixY(cp.minCol[ic]),
300  comParams.isPhase2 ? false : phase1PixelTopology::isBigPixY(cp.maxCol[ic]));
301 
302  cp.xpos[ic] = xPos + xcorr;
303  cp.ypos[ic] = yPos + ycorr;
304  }
305 
306  constexpr inline void errorFromSize(CommonParams const& __restrict__ comParams,
307  DetParams const& __restrict__ detParams,
308  ClusParams& cp,
309  uint32_t ic) {
310  // Edge cluster errors
311  cp.xerr[ic] = 0.0050;
312  cp.yerr[ic] = 0.0085;
313 
314  // FIXME these are errors form Run1
315 
316  bool isPhase2 = comParams.isPhase2;
317  // FIXME these are errors form Run1
318  float xerr_barrel_l1_def = isPhase2 ? 0.00035 : 0.00200; // 0.01030;
319  float yerr_barrel_l1_def = isPhase2 ? 0.00125 : 0.00210;
320  float xerr_barrel_ln_def = isPhase2 ? 0.00035 : 0.00200; // 0.01030;
321  float yerr_barrel_ln_def = isPhase2 ? 0.00125 : 0.00210;
322  float xerr_endcap_def = isPhase2 ? 0.00060 : 0.0020;
323  float yerr_endcap_def = isPhase2 ? 0.00180 : 0.00210;
324 
325  constexpr float xerr_barrel_l1[] = {0.00115, 0.00120, 0.00088};
326  constexpr float yerr_barrel_l1[] = {
327  0.00375, 0.00230, 0.00250, 0.00250, 0.00230, 0.00230, 0.00210, 0.00210, 0.00240};
328  constexpr float xerr_barrel_ln[] = {0.00115, 0.00120, 0.00088};
329  constexpr float yerr_barrel_ln[] = {
330  0.00375, 0.00230, 0.00250, 0.00250, 0.00230, 0.00230, 0.00210, 0.00210, 0.00240};
331  constexpr float xerr_endcap[] = {0.0020, 0.0020};
332  constexpr float yerr_endcap[] = {0.00210};
333 
334  auto sx = cp.maxRow[ic] - cp.minRow[ic];
335  auto sy = cp.maxCol[ic] - cp.minCol[ic];
336 
337  // is edgy ?
338  bool isEdgeX = cp.xsize[ic] < 1;
339  bool isEdgeY = cp.ysize[ic] < 1;
340 
341  // is one and big?
342  bool isBig1X = isPhase2 ? false : ((0 == sx) && phase1PixelTopology::isBigPixX(cp.minRow[ic]));
343  bool isBig1Y = isPhase2 ? false : ((0 == sy) && phase1PixelTopology::isBigPixY(cp.minCol[ic]));
344 
345  if (!isPhase2) {
346  if (!isEdgeX && !isBig1X) {
347  if (not detParams.isBarrel) {
349  } else if (detParams.layer == 1) {
351  } else {
353  }
354  }
355 
356  if (!isEdgeY && !isBig1Y) {
357  if (not detParams.isBarrel) {
359  } else if (detParams.layer == 1) {
361  } else {
363  }
364  }
365  } else {
366  if (!isEdgeX) {
367  if (not detParams.isBarrel) {
369  } else if (detParams.layer == 1) {
371  } else {
373  }
374  }
375 
376  if (!isEdgeY) {
377  if (not detParams.isBarrel) {
379  } else if (detParams.layer == 1) {
381  } else {
383  }
384  }
385  }
386  }
387 
388  constexpr inline void errorFromDB(CommonParams const& __restrict__ comParams,
389  DetParams const& __restrict__ detParams,
390  ClusParams& cp,
391  uint32_t ic) {
392  // Edge cluster errors
393  cp.xerr[ic] = 0.0050f;
394  cp.yerr[ic] = 0.0085f;
395 
396  auto sx = cp.maxRow[ic] - cp.minRow[ic];
397  auto sy = cp.maxCol[ic] - cp.minCol[ic];
398 
399  // is edgy ? (size is set negative: see above)
400  bool isEdgeX = cp.xsize[ic] < 1;
401  bool isEdgeY = cp.ysize[ic] < 1;
402  // is one and big?
403  bool isOneX = (0 == sx);
404  bool isOneY = (0 == sy);
405  bool isBigX = comParams.isPhase2 ? false : phase1PixelTopology::isBigPixX(cp.minRow[ic]);
406  bool isBigY = comParams.isPhase2 ? false : phase1PixelTopology::isBigPixY(cp.minCol[ic]);
407 
408  auto ch = cp.charge[ic];
409  auto bin = 0;
411  // find first bin which minimum charge exceeds cluster charge
412  if (ch < detParams.minCh[bin + 1])
413  break;
414 
415  // in detParams qBins are reversed bin0 -> smallest charge, bin4-> largest charge
416  // whereas in CondFormats/SiPixelTransient/src/SiPixelGenError.cc it is the opposite
417  // so we reverse the bin here -> kGenErrorQBins - 1 - bin
418  cp.status[ic].qBin = CPEFastParametrisation::kGenErrorQBins - 1 - bin;
419  cp.status[ic].isOneX = isOneX;
420  cp.status[ic].isBigX = (isOneX & isBigX) | isEdgeX;
421  cp.status[ic].isOneY = isOneY;
422  cp.status[ic].isBigY = (isOneY & isBigY) | isEdgeY;
423 
424  auto xoff = -float(phase1PixelTopology::xOffset) * comParams.thePitchX;
425  int low_value = 0;
426  int high_value = CPEFastParametrisation::kNumErrorBins - 1;
427  int bin_value = float(CPEFastParametrisation::kNumErrorBins) * (cp.xpos[ic] + xoff) / (2 * xoff);
428  // return estimated bin value truncated to [0, 15]
429  int jx = std::clamp(bin_value, low_value, high_value);
430 
431  auto toCM = [](uint8_t x) { return float(x) * 1.e-4; };
432 
433  if (not isEdgeX) {
434  cp.xerr[ic] = isOneX ? toCM(isBigX ? detParams.sx2 : detParams.sigmax1[jx])
435  : detParams.xfact[bin] * toCM(detParams.sigmax[jx]);
436  }
437 
438  auto ey = cp.ysize[ic] > 8 ? detParams.sigmay[std::min(cp.ysize[ic] - 9, 15)] : detParams.sy1;
439  if (not isEdgeY) {
440  cp.yerr[ic] = isOneY ? toCM(isBigY ? detParams.sy2 : detParams.sy1) : detParams.yfact[bin] * toCM(ey);
441  }
442  }
443 
444 } // namespace pixelCPEforGPU
445 
446 #endif // RecoLocalTracker_SiPixelRecHits_pixelCPEforGPU_h
size
Write out results.
constexpr uint16_t lastRowInModule
uint8_t sigmax[CPEFastParametrisation::kNumErrorBins]
float xfact[CPEFastParametrisation::kGenErrorQBins]
uint8_t sigmax1[CPEFastParametrisation::kNumErrorBins]
DetParams const * m_detParams
constexpr uint16_t localY(uint16_t py)
constexpr void position(CommonParams const &__restrict__ comParams, DetParams const &__restrict__ detParams, ClusParams &cp, uint32_t ic)
constexpr int kGenErrorQBins
const Int_t ysize
constexpr uint16_t lastColInModule
constexpr DetParams const &__restrict__ detParams(int i) const
assert(be >=bs)
LayerGeometry const * m_layerGeometry
constexpr AverageGeometry const &__restrict__ averageGeometry() const
AverageGeometry const * m_averageGeometry
int minCh[CPEFastParametrisation::kGenErrorQBins]
constexpr uint32_t maxHitsInIter()
uint32_t layerStart[phase2PixelTopology::numberOfLayers+1]
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
constexpr bool isEdgeY(uint16_t py)
constexpr void computeAnglesFromDet(DetParams const &__restrict__ detParams, float const x, float const y, float &cotalpha, float &cotbeta)
constexpr bool isBigPixY(uint16_t py)
constexpr LayerGeometry const &__restrict__ layerGeometry() const
constexpr bool isEdgeX(uint16_t px)
constexpr CommonParams const &__restrict__ commonParams() const
#define N
Definition: blowfish.cc:9
constexpr bool isBigPixX(uint16_t px)
constexpr int16_t xOffset
CommonParams const * m_commonParams
constexpr uint16_t localX(uint16_t px)
T __ldg(T const *x)
Definition: cudaCompat.h:137
constexpr float correction(int sizeM1, int q_f, int q_l, uint16_t upper_edge_first_pix, uint16_t lower_edge_last_pix, float lorentz_shift, float theThickness, float cot_angle, float pitch, bool first_is_big, bool last_is_big)
float yfact[CPEFastParametrisation::kGenErrorQBins]
__device__ uint8_t layer(uint16_t id) const
constexpr uint8_t numberOfLayers
constexpr uint16_t layerIndexSize
constexpr void errorFromSize(CommonParams const &__restrict__ comParams, DetParams const &__restrict__ detParams, ClusParams &cp, uint32_t ic)
float x
constexpr void errorFromDB(CommonParams const &__restrict__ comParams, DetParams const &__restrict__ detParams, ClusParams &cp, uint32_t ic)
uint8_t layer[phase2PixelTopology::layerIndexSize]
uint8_t sigmay[CPEFastParametrisation::kNumErrorBins]
const Int_t xsize
#define __device__
constexpr int kNumErrorBins
constexpr int32_t MaxHitsInIter