CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
15 namespace CPEFastParametrisation {
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 
38  struct DetParams {
39  bool isBarrel;
40  bool isPosZ;
41  uint16_t layer;
42  uint16_t index;
43  uint32_t rawId;
44 
45  float shiftX;
46  float shiftY;
47  float chargeWidthX;
48  float chargeWidthY;
49  uint16_t pixmx; // max pix charge
50 
51  float x0, y0, z0; // the vertex in the local coord of the detector
52 
53  float apeXX, apeYY; // ape^2
54  uint8_t sx2, sy1, sy2;
59 
61  };
62 
64 
65  struct LayerGeometry {
68  };
69 
70  struct ParamsOnGPU {
75 
76  constexpr CommonParams const& __restrict__ commonParams() const {
77  CommonParams const* __restrict__ l = m_commonParams;
78  return *l;
79  }
80  constexpr DetParams const& __restrict__ detParams(int i) const {
81  DetParams const* __restrict__ l = m_detParams;
82  return l[i];
83  }
84  constexpr LayerGeometry const& __restrict__ layerGeometry() const { return *m_layerGeometry; }
85  constexpr AverageGeometry const& __restrict__ averageGeometry() const { return *m_averageGeometry; }
86 
87  __device__ uint8_t layer(uint16_t id) const {
89  };
90  };
91 
92  // SOA (on device)
93  template <uint32_t N>
94  struct ClusParamsT {
95  uint32_t minRow[N];
96  uint32_t maxRow[N];
97  uint32_t minCol[N];
98  uint32_t maxCol[N];
99 
100  int32_t q_f_X[N];
101  int32_t q_l_X[N];
102  int32_t q_f_Y[N];
103  int32_t q_l_Y[N];
104 
105  int32_t charge[N];
106 
107  float xpos[N];
108  float ypos[N];
109 
110  float xerr[N];
111  float yerr[N];
112 
113  int16_t xsize[N]; // (*8) clipped at 127 if negative is edge....
114  int16_t ysize[N];
115 
117  };
118 
121 
122  constexpr inline void computeAnglesFromDet(
123  DetParams const& __restrict__ detParams, float const x, float const y, float& cotalpha, float& cotbeta) {
124  // x,y local position on det
125  auto gvx = x - detParams.x0;
126  auto gvy = y - detParams.y0;
127  auto gvz = -1.f / detParams.z0;
128  // normalization not required as only ratio used...
129  // calculate angles
130  cotalpha = gvx * gvz;
131  cotbeta = gvy * gvz;
132  }
133 
134  constexpr inline float correction(int sizeM1,
135  int q_f,
136  int q_l,
137  uint16_t upper_edge_first_pix,
138  uint16_t lower_edge_last_pix,
139  float lorentz_shift,
140  float theThickness, //detector thickness
141  float cot_angle,
142  float pitch,
143  bool first_is_big,
144  bool last_is_big)
145  {
146  if (0 == sizeM1) // size 1
147  return 0;
148 
149  float w_eff = 0;
150  bool simple = true;
151  if (1 == sizeM1) { // size 2
152  //--- Width of the clusters minus the edge (first and last) pixels.
153  //--- In the note, they are denoted x_F and x_L (and y_F and y_L)
154  // assert(lower_edge_last_pix >= upper_edge_first_pix);
155  auto w_inner = pitch * float(lower_edge_last_pix - upper_edge_first_pix); // in cm
156 
157  //--- Predicted charge width from geometry
158  auto w_pred = theThickness * cot_angle // geometric correction (in cm)
159  - lorentz_shift; // (in cm) &&& check fpix!
160 
161  w_eff = std::abs(w_pred) - w_inner;
162 
163  //--- If the observed charge width is inconsistent with the expectations
164  //--- based on the track, do *not* use w_pred-w_inner. Instead, replace
165  //--- it with an *average* effective charge width, which is the average
166  //--- length of the edge pixels.
167 
168  // this can produce "large" regressions for very small numeric differences
169  simple = (w_eff < 0.0f) | (w_eff > pitch);
170  }
171 
172  if (simple) {
173  //--- Total length of the two edge pixels (first+last)
174  float sum_of_edge = 2.0f;
175  if (first_is_big)
176  sum_of_edge += 1.0f;
177  if (last_is_big)
178  sum_of_edge += 1.0f;
179  w_eff = pitch * 0.5f * sum_of_edge; // ave. length of edge pixels (first+last) (cm)
180  }
181 
182  //--- Finally, compute the position in this projection
183  float qdiff = q_l - q_f;
184  float qsum = q_l + q_f;
185 
186  //--- Temporary fix for clusters with both first and last pixel with charge = 0
187  if (qsum == 0)
188  qsum = 1.0f;
189 
190  return 0.5f * (qdiff / qsum) * w_eff;
191  }
192 
193  constexpr inline void position(CommonParams const& __restrict__ comParams,
194  DetParams const& __restrict__ detParams,
195  ClusParams& cp,
196  uint32_t ic) {
197  //--- Upper Right corner of Lower Left pixel -- in measurement frame
198  uint16_t llx = cp.minRow[ic] + 1;
199  uint16_t lly = cp.minCol[ic] + 1;
200 
201  //--- Lower Left corner of Upper Right pixel -- in measurement frame
202  uint16_t urx = cp.maxRow[ic];
203  uint16_t ury = cp.maxCol[ic];
204 
205  auto llxl = phase1PixelTopology::localX(llx);
206  auto llyl = phase1PixelTopology::localY(lly);
207  auto urxl = phase1PixelTopology::localX(urx);
208  auto uryl = phase1PixelTopology::localY(ury);
209 
210  auto mx = llxl + urxl;
211  auto my = llyl + uryl;
212 
213  auto xsize = int(urxl) + 2 - int(llxl);
214  auto ysize = int(uryl) + 2 - int(llyl);
215  assert(xsize >= 0); // 0 if bixpix...
216  assert(ysize >= 0);
217 
219  ++xsize;
221  ++xsize;
223  ++ysize;
225  ++ysize;
226 
227  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]);
228  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]);
229  xsize = 8 * xsize - unbalanceX;
230  ysize = 8 * ysize - unbalanceY;
231 
232  cp.xsize[ic] = std::min(xsize, 1023);
233  cp.ysize[ic] = std::min(ysize, 1023);
234 
235  if (cp.minRow[ic] == 0 || cp.maxRow[ic] == phase1PixelTopology::lastRowInModule)
236  cp.xsize[ic] = -cp.xsize[ic];
237  if (cp.minCol[ic] == 0 || cp.maxCol[ic] == phase1PixelTopology::lastColInModule)
238  cp.ysize[ic] = -cp.ysize[ic];
239 
240  // apply the lorentz offset correction
241  auto xPos = detParams.shiftX + comParams.thePitchX * (0.5f * float(mx) + float(phase1PixelTopology::xOffset));
242  auto yPos = detParams.shiftY + comParams.thePitchY * (0.5f * float(my) + float(phase1PixelTopology::yOffset));
243 
244  float cotalpha = 0, cotbeta = 0;
245 
246  computeAnglesFromDet(detParams, xPos, yPos, cotalpha, cotbeta);
247 
248  auto thickness = detParams.isBarrel ? comParams.theThicknessB : comParams.theThicknessE;
249 
250  auto xcorr = correction(cp.maxRow[ic] - cp.minRow[ic],
251  cp.q_f_X[ic],
252  cp.q_l_X[ic],
253  llxl,
254  urxl,
255  detParams.chargeWidthX, // lorentz shift in cm
256  thickness,
257  cotalpha,
258  comParams.thePitchX,
261 
262  auto ycorr = correction(cp.maxCol[ic] - cp.minCol[ic],
263  cp.q_f_Y[ic],
264  cp.q_l_Y[ic],
265  llyl,
266  uryl,
267  detParams.chargeWidthY, // lorentz shift in cm
268  thickness,
269  cotbeta,
270  comParams.thePitchY,
273 
274  cp.xpos[ic] = xPos + xcorr;
275  cp.ypos[ic] = yPos + ycorr;
276  }
277 
278  constexpr inline void errorFromSize(CommonParams const& __restrict__ comParams,
279  DetParams const& __restrict__ detParams,
280  ClusParams& cp,
281  uint32_t ic) {
282  // Edge cluster errors
283  cp.xerr[ic] = 0.0050;
284  cp.yerr[ic] = 0.0085;
285 
286  // FIXME these are errors form Run1
287  constexpr float xerr_barrel_l1[] = {0.00115, 0.00120, 0.00088};
288  constexpr float xerr_barrel_l1_def = 0.00200; // 0.01030;
289  constexpr float yerr_barrel_l1[] = {
290  0.00375, 0.00230, 0.00250, 0.00250, 0.00230, 0.00230, 0.00210, 0.00210, 0.00240};
291  constexpr float yerr_barrel_l1_def = 0.00210;
292  constexpr float xerr_barrel_ln[] = {0.00115, 0.00120, 0.00088};
293  constexpr float xerr_barrel_ln_def = 0.00200; // 0.01030;
294  constexpr float yerr_barrel_ln[] = {
295  0.00375, 0.00230, 0.00250, 0.00250, 0.00230, 0.00230, 0.00210, 0.00210, 0.00240};
296  constexpr float yerr_barrel_ln_def = 0.00210;
297  constexpr float xerr_endcap[] = {0.0020, 0.0020};
298  constexpr float xerr_endcap_def = 0.0020;
299  constexpr float yerr_endcap[] = {0.00210};
300  constexpr float yerr_endcap_def = 0.00210;
301 
302  auto sx = cp.maxRow[ic] - cp.minRow[ic];
303  auto sy = cp.maxCol[ic] - cp.minCol[ic];
304 
305  // is edgy ?
306  bool isEdgeX = cp.xsize[ic] < 1;
307  bool isEdgeY = cp.ysize[ic] < 1;
308  // is one and big?
309  bool isBig1X = (0 == sx) && phase1PixelTopology::isBigPixX(cp.minRow[ic]);
310  bool isBig1Y = (0 == sy) && phase1PixelTopology::isBigPixY(cp.minCol[ic]);
311 
312  if (!isEdgeX && !isBig1X) {
313  if (not detParams.isBarrel) {
314  cp.xerr[ic] = sx < std::size(xerr_endcap) ? xerr_endcap[sx] : xerr_endcap_def;
315  } else if (detParams.layer == 1) {
316  cp.xerr[ic] = sx < std::size(xerr_barrel_l1) ? xerr_barrel_l1[sx] : xerr_barrel_l1_def;
317  } else {
318  cp.xerr[ic] = sx < std::size(xerr_barrel_ln) ? xerr_barrel_ln[sx] : xerr_barrel_ln_def;
319  }
320  }
321 
322  if (!isEdgeY && !isBig1Y) {
323  if (not detParams.isBarrel) {
324  cp.yerr[ic] = sy < std::size(yerr_endcap) ? yerr_endcap[sy] : yerr_endcap_def;
325  } else if (detParams.layer == 1) {
326  cp.yerr[ic] = sy < std::size(yerr_barrel_l1) ? yerr_barrel_l1[sy] : yerr_barrel_l1_def;
327  } else {
328  cp.yerr[ic] = sy < std::size(yerr_barrel_ln) ? yerr_barrel_ln[sy] : yerr_barrel_ln_def;
329  }
330  }
331  }
332 
333  constexpr inline void errorFromDB(CommonParams const& __restrict__ comParams,
334  DetParams const& __restrict__ detParams,
335  ClusParams& cp,
336  uint32_t ic) {
337  // Edge cluster errors
338  cp.xerr[ic] = 0.0050f;
339  cp.yerr[ic] = 0.0085f;
340 
341  auto sx = cp.maxRow[ic] - cp.minRow[ic];
342  auto sy = cp.maxCol[ic] - cp.minCol[ic];
343 
344  // is edgy ? (size is set negative: see above)
345  bool isEdgeX = cp.xsize[ic] < 1;
346  bool isEdgeY = cp.ysize[ic] < 1;
347  // is one and big?
348  bool isOneX = (0 == sx);
349  bool isOneY = (0 == sy);
350  bool isBigX = phase1PixelTopology::isBigPixX(cp.minRow[ic]);
351  bool isBigY = phase1PixelTopology::isBigPixY(cp.minCol[ic]);
352 
353  auto ch = cp.charge[ic];
354  auto bin = 0;
356  // find first bin which minimum charge exceeds cluster charge
357  if (ch < detParams.minCh[bin + 1])
358  break;
359 
360  // in detParams qBins are reversed bin0 -> smallest charge, bin4-> largest charge
361  // whereas in CondFormats/SiPixelTransient/src/SiPixelGenError.cc it is the opposite
362  // so we reverse the bin here -> kGenErrorQBins - 1 - bin
363  cp.status[ic].qBin = CPEFastParametrisation::kGenErrorQBins - 1 - bin;
364  cp.status[ic].isOneX = isOneX;
365  cp.status[ic].isBigX = (isOneX & isBigX) | isEdgeX;
366  cp.status[ic].isOneY = isOneY;
367  cp.status[ic].isBigY = (isOneY & isBigY) | isEdgeY;
368 
369  auto xoff = -float(phase1PixelTopology::xOffset) * comParams.thePitchX;
370  int low_value = 0;
371  int high_value = CPEFastParametrisation::kNumErrorBins - 1;
372  int bin_value = float(CPEFastParametrisation::kNumErrorBins) * (cp.xpos[ic] + xoff) / (2.f * xoff);
373  // return estimated bin value truncated to [0, 15]
374  int jx = std::clamp(bin_value, low_value, high_value);
375 
376  auto toCM = [](uint8_t x) { return float(x) * 1.e-4f; };
377 
378  if (not isEdgeX) {
379  cp.xerr[ic] = isOneX ? toCM(isBigX ? detParams.sx2 : detParams.sigmax1[jx])
380  : detParams.xfact[bin] * toCM(detParams.sigmax[jx]);
381  }
382 
383  auto ey = cp.ysize[ic] > 8 ? detParams.sigmay[std::min(cp.ysize[ic] - 9, 15)] : detParams.sy1;
384  if (not isEdgeY) {
385  cp.yerr[ic] = isOneY ? toCM(isBigY ? detParams.sy2 : detParams.sy1) : detParams.yfact[bin] * toCM(ey);
386  }
387  }
388 
389 } // namespace pixelCPEforGPU
390 
391 #endif // RecoLocalTracker_SiPixelRecHits_pixelCPEforGPU_h
tuple xerr_barrel_ln_def
tuple xerr_barrel_l1_def
tuple yerr_barrel_ln
__device__ uint8_t layer(uint16_t id) const
constexpr uint16_t lastRowInModule
uint8_t sigmax[CPEFastParametrisation::kNumErrorBins]
float xfact[CPEFastParametrisation::kGenErrorQBins]
uint8_t sigmax1[CPEFastParametrisation::kNumErrorBins]
constexpr AverageGeometry const &__restrict__ averageGeometry() const
tuple yerr_barrel_ln_def
constexpr uint32_t numberOfLayers
tuple xerr_endcap_def
DetParams const * m_detParams
constexpr uint16_t localY(uint16_t py)
uint32_t layerStart[phase1PixelTopology::numberOfLayers+1]
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
assert(be >=bs)
LayerGeometry const * m_layerGeometry
constexpr uint32_t layerIndexSize
AverageGeometry const * m_averageGeometry
int minCh[CPEFastParametrisation::kGenErrorQBins]
constexpr uint32_t maxHitsInIter()
constexpr CommonParams const &__restrict__ commonParams() const
tuple yerr_barrel_l1
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)
T min(T a, T b)
Definition: MathUtil.h:58
tuple xerr_barrel_l1
tuple yerr_endcap_def
constexpr bool isBigPixY(uint16_t py)
constexpr bool isEdgeX(uint16_t px)
#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:113
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)
constexpr uint32_t maxModuleStride
float yfact[CPEFastParametrisation::kGenErrorQBins]
constexpr void errorFromSize(CommonParams const &__restrict__ comParams, DetParams const &__restrict__ detParams, ClusParams &cp, uint32_t ic)
constexpr void errorFromDB(CommonParams const &__restrict__ comParams, DetParams const &__restrict__ detParams, ClusParams &cp, uint32_t ic)
uint8_t sigmay[CPEFastParametrisation::kNumErrorBins]
tuple xerr_barrel_ln
const Int_t xsize
#define __device__
constexpr DetParams const &__restrict__ detParams(int i) const
constexpr int16_t yOffset
tuple size
Write out results.
constexpr LayerGeometry const &__restrict__ layerGeometry() const
uint8_t layer[phase1PixelTopology::layerIndexSize]
constexpr int kNumErrorBins
tuple yerr_barrel_l1_def
constexpr int32_t MaxHitsInIter