Reconstruct the best estimate of the hit position for pixel clusters.
109 const float fracpix = 0.45f;
111 const int nilist = 9, njlist = 5;
112 const float ilist[nilist] = {0.f, -1.f, -0.75f, -0.5f, -0.25f, 0.25f, 0.5f, 0.75f, 1.f};
113 const float jlist[njlist] = {0.f, -0.5f, -0.25f, 0.25f, 0.50f};
118 if (!templ2D.
interpolate(
id, cotalpha, cotbeta, locBz, locBx))
126 for (
int i = 0;
i < 3; ++
i) {
127 fbin[
i] = templ2D.
fbin(
i);
130 float q50 = templ2D.
s50();
131 float pseudopix = 0.2f * q50;
132 float pseudopix2 = q50 * q50;
136 float qscale = templ2D.
qscale();
140 int nclusx = cluster.
mrow;
141 int nclusy = (
int)cluster.
mcol;
142 bool* xdouble = cluster.
xdouble;
143 bool* ydouble = cluster.
ydouble;
147 int imin =
BYM2, imax = 0, jmin =
BXM2, jmax = 0;
148 for (
int k = 0;
k < nclusx * nclusy; ++
k) {
152 int i =
k -
j * nclusy;
171 int shiftx =
THXP1 - (jmin + jmax) / 2;
172 int shifty =
THYP1 - (imin + imax) / 2;
186 float fq0 = qtotal / templ2D.
qavg();
192 for (
int j = 0;
j <
BXM2; ++
j) {
193 for (
int i = 0;
i <
BYM2; ++
i) {
198 const unsigned int NPIXMAX = 200;
200 int indexxy[2][NPIXMAX];
201 float pixel[NPIXMAX];
202 float sigma2[NPIXMAX];
203 float minmax = templ2D.
pixmax();
204 float ylow0 = 0.f, yhigh0 = 0.f, xlow0 = 0.f, xhigh0 = 0.f;
211 for (
int i = 0;
i <
BYM2; ++
i) {
215 for (
int j = 0;
j <
BXM2; ++
j) {
218 for (
int i = 0;
i < nclusy; ++
i) {
221 if (iy > -1 && iy <
BYM2)
225 for (
int j = 0;
j < nclusx; ++
j) {
228 if (jx > -1 && jx <
BXM2)
235 for (
int i = 0;
i <
BYM2; ++
i) {
236 float ypitch =
ysize;
240 ye[
i + 1] = ye[
i] + ypitch;
241 ypos[
i] = ye[
i] + ypitch / 2.;
243 for (
int j = 0;
j <
BXM2; ++
j) {
244 float xpitch =
xsize;
248 xe[
j + 1] = xe[
j] + xpitch;
249 xpos[
j] = xe[
j] + xpitch / 2.;
252 for (
int i = 0;
i < nclusy; ++
i) {
258 if (iy > -1 && iy <
BYM2) {
259 for (
int j = 0;
j < nclusx; ++
j) {
261 if (jx > -1 && jx <
BXM2) {
265 clusxy[jx][iy] = cluster(
j,
i);
267 if (clusxy[jx][iy] > 0.
f) {
268 ysum[iy] += clusxy[jx][iy];
269 indexxy[0][npixel] = jx;
270 indexxy[1][npixel] = iy;
271 pixel[npixel] = clusxy[jx][iy];
281 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 282 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco2D::number of pixels above threshold = " << npixel
285 std::cout <<
"PixelTemplateReco2D::number of pixels above threshold = " << npixel << std::endl;
292 xhigh0 = xe[jmax + 1];
294 yhigh0 = ye[imax + 1];
298 int ypixoff =
T2HYP1 - (imin + imax) / 2;
299 for (
int k = 0;
k < npixel; ++
k) {
300 int ypixeff = ypixoff + indexxy[1][
k];
307 int imisslow = -1, imisshigh = -1, jmisslow = -1, jmisshigh = -1;
308 float ylow = -1.f, yhigh = -1.f;
309 float hmaxpix = fracpix * templ2D.
sxymax();
310 for (
int i = imin;
i <= imax; ++
i) {
311 if (ysum[
i] > hmaxpix && ysum[
i - 1] < hmaxpix && ylow < 0.
f) {
312 ylow = ypos[
i - 1] + (ypos[
i] - ypos[
i - 1]) * (hmaxpix - ysum[
i - 1]) / (ysum[
i] - ysum[
i - 1]);
319 if (ysum[
i] > hmaxpix && ysum[
i + 1] < hmaxpix) {
320 yhigh = ypos[
i] + (ypos[
i + 1] - ypos[
i]) * (ysum[
i] - hmaxpix) / (ysum[
i] - ysum[
i + 1]);
323 if (ylow < 0.
f || yhigh < 0.
f) {
328 float templeny = templ2D.
clsleny();
329 deltay = templeny - (yhigh - ylow) /
ysize;
333 float x0 = 0.5f * (xlow0 + xhigh0) - templ2D.
lorxdrift();
334 float y0 = 0.5f * (ylow + yhigh) - templ2D.
lorydrift();
348 imisshigh = imin - 1;
356 imisshigh = imin - 1;
361 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 362 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco2D::illegal edgeflagy = " << edgeflagy << std::endl;
364 std::cout <<
"PixelTemplate:2D:illegal edgeflagy = " << edgeflagy << std::endl;
372 jmisshigh = jmin - 1;
380 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 381 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco2D::illegal edgeflagx = " << edgeflagx << std::endl;
383 std::cout <<
"PixelTemplate:2D:illegal edgeflagx = " << edgeflagx << std::endl;
389 float chi2min[2], xerr2[2], yerr2[2];
390 float x2D0[2], y2D0[2], qtfrac0[2];
394 for (ipass = 0; ipass < npass; ++ipass) {
401 for (
int k = npixel;
k < tpixel; ++
k) {
402 int j = indexxy[0][
k];
403 int i = indexxy[1][
k];
411 for (
int k = 0;
k < npixel; ++
k) {
412 int j = indexxy[0][
k];
413 int i = indexxy[1][
k];
414 if ((
j - 1) != jmisshigh) {
415 if (clusxy[
j - 1][
i] < pseudopix) {
416 indexxy[0][tpixel] =
j - 1;
417 indexxy[1][tpixel] =
i;
418 clusxy[
j - 1][
i] = pseudopix;
419 pixel[tpixel] = pseudopix;
420 sigma2[tpixel] = pseudopix2;
424 if ((
j + 1) != jmisslow) {
425 if (clusxy[
j + 1][
i] < pseudopix) {
426 indexxy[0][tpixel] =
j + 1;
427 indexxy[1][tpixel] =
i;
428 clusxy[
j + 1][
i] = pseudopix;
429 pixel[tpixel] = pseudopix;
430 sigma2[tpixel] = pseudopix2;
435 if ((
i + 1) != imisslow) {
436 if ((
j - 1) != jmisshigh) {
437 if (clusxy[
j - 1][
i + 1] < pseudopix) {
438 indexxy[0][tpixel] =
j - 1;
439 indexxy[1][tpixel] =
i + 1;
440 clusxy[
j - 1][
i + 1] = pseudopix;
441 pixel[tpixel] = pseudopix;
442 sigma2[tpixel] = pseudopix2;
446 if (clusxy[
j][
i + 1] < pseudopix) {
447 indexxy[0][tpixel] =
j;
448 indexxy[1][tpixel] =
i + 1;
449 clusxy[
j][
i + 1] = pseudopix;
450 pixel[tpixel] = pseudopix;
451 sigma2[tpixel] = pseudopix2;
454 if ((
j + 1) != jmisslow) {
455 if (clusxy[
j + 1][
i + 1] < pseudopix) {
456 indexxy[0][tpixel] =
j + 1;
457 indexxy[1][tpixel] =
i + 1;
458 clusxy[
j + 1][
i + 1] = pseudopix;
459 pixel[tpixel] = pseudopix;
460 sigma2[tpixel] = pseudopix2;
466 if ((
i - 1) != imisshigh) {
467 if ((
j - 1) != jmisshigh) {
468 if (clusxy[
j - 1][
i - 1] < pseudopix) {
469 indexxy[0][tpixel] =
j - 1;
470 indexxy[1][tpixel] =
i - 1;
471 clusxy[
j - 1][
i - 1] = pseudopix;
472 pixel[tpixel] = pseudopix;
473 sigma2[tpixel] = pseudopix2;
477 if (clusxy[
j][
i - 1] < pseudopix) {
478 indexxy[0][tpixel] =
j;
479 indexxy[1][tpixel] =
i - 1;
480 clusxy[
j][
i - 1] = pseudopix;
481 pixel[tpixel] = pseudopix;
482 sigma2[tpixel] = pseudopix2;
485 if ((
j + 1) != jmisslow) {
486 if (clusxy[
j + 1][
i - 1] < pseudopix) {
487 indexxy[0][tpixel] =
j + 1;
488 indexxy[1][tpixel] =
i - 1;
489 clusxy[
j + 1][
i - 1] = pseudopix;
490 pixel[tpixel] = pseudopix;
491 sigma2[tpixel] = pseudopix2;
500 chi2min[ipass] = 1000000.f;
501 float chi2, qtemplate, qactive, qtfrac = 0.f, x2D = 0.f, y2D = 0.f;
503 float ygridscale = 0.271 * cotbeta;
504 if (ygridscale < 1.
f)
506 for (
int is = 0; is < nilist; ++is) {
507 for (
int js = 0; js < njlist; ++js) {
508 float xtry =
x0 + jlist[js] *
xsize;
509 float ytry = y0 + ilist[is] * ygridscale *
ysize;
512 for (
int j = 0;
j <
BXM2; ++
j) {
513 for (
int i = 0;
i <
BYM2; ++
i) {
514 template2d[
j][
i] = 0.f;
517 templ2D.
xytemp(xtry, ytry, yd, xd, template2d,
false, dpdx2d, qtemplate);
518 for (
int k = 0;
k < tpixel; ++
k) {
519 int jpix = indexxy[0][
k];
520 int ipix = indexxy[1][
k];
521 float qtpixel = template2d[jpix][ipix];
528 if (
chi2 < chi2min[ipass]) {
529 chi2min[ipass] =
chi2;
532 qtfrac = qactive / qtemplate;
538 float xstep = 1.0f, ystep = 1.0f;
539 float minv11 = 1000.f, minv12 = 1000.f, minv22 = 1000.f;
540 chi2 = chi2min[ipass];
541 while (
chi2 <= chi2min[ipass] && niter < 15 && (niter < 2 || (
std::abs(xstep) > 0.2 ||
std::abs(ystep) > 0.2))) {
545 qtfrac0[ipass] = qtfrac;
546 xerr2[ipass] = minv11;
547 yerr2[ipass] = minv22;
548 chi2min[ipass] =
chi2;
553 for (
int j = 0;
j <
BXM2; ++
j) {
554 for (
int i = 0;
i <
BYM2; ++
i) {
555 template2d[
j][
i] = 0.f;
558 templ2D.
xytemp(x2D, y2D, yd, xd, template2d,
true, dpdx2d, qtemplate);
560 float sumptdt1 = 0., sumptdt2 = 0.;
561 float sumdtdt11 = 0., sumdtdt12 = 0., sumdtdt22 = 0.;
566 for (
int k = 0;
k < tpixel; ++
k) {
567 int jpix = indexxy[0][
k];
568 int ipix = indexxy[1][
k];
569 float qtpixel = template2d[jpix][ipix];
571 float dtdx = dpdx2d[0][jpix][ipix];
572 float dtdy = dpdx2d[1][jpix][ipix];
574 sumptdt1 +=
pt * dtdx / sigma2[
k];
575 sumptdt2 +=
pt * dtdy / sigma2[
k];
576 sumdtdt11 += dtdx * dtdx / sigma2[
k];
577 sumdtdt12 += dtdx * dtdy / sigma2[
k];
578 sumdtdt22 += dtdy * dtdy / sigma2[
k];
586 float D = sumdtdt11 * sumdtdt22 - sumdtdt12 * sumdtdt12;
591 minv11 = sumdtdt22 /
D;
592 minv12 = -sumdtdt12 /
D;
593 minv22 = sumdtdt11 /
D;
595 qtfrac = qactive / qtemplate;
599 xstep = minv11 * sumptdt1 + minv12 * sumptdt2;
600 ystep = minv12 * sumptdt1 + minv22 * sumptdt2;
604 if (sumdtdt11 > 0.0001
f) {
605 xstep = sumptdt1 / sumdtdt11;
609 if (sumdtdt22 > 0.0001
f) {
610 ystep = sumptdt2 / sumdtdt22;
629 if (chi2min[1] < chi2min[0]) {
637 if (qtfrac0[ipass] < 0.10
f || qtfrac0[ipass] > 1.
f) {
638 qtfrac0[ipass] = 1.f;
640 fq = fq0 / qtfrac0[ipass];
660 float scalex = templ2D.
scalex(qbin);
661 float scaley = templ2D.
scaley(qbin);
662 float offsetx = templ2D.
offsetx(qbin);
663 float offsety = templ2D.
offsety(qbin);
669 xrec = x2D0[ipass] - xpos[shiftx] - offsetx;
670 yrec = y2D0[ipass] - ypos[shifty] - offsety;
671 if (xerr2[ipass] > 0.
f) {
672 sigmax = scalex *
sqrt(xerr2[ipass]);
678 if (yerr2[ipass] > 0.
f) {
679 sigmay = scaley *
sqrt(yerr2[ipass]);
687 double meanxy = (double)(npixel * templ2D.
chi2ppix());
688 double chi2scale = (double)templ2D.
chi2scale();
692 double hndof = meanxy / 2.f;
693 double hchi2 = chi2scale * chi2min[ipass] / 2.f;
694 probxy = (
float)(1. - TMath::Gamma(hndof, hchi2));
696 float mpv = templ2D.
mpvvav();
699 float xvav = (qtotal / qtfrac0[ipass] - mpv) / sigmaQ;
702 float prvav = vvidist.fcn(xvav);
705 probxy = chi2min[ipass];
float xsize()
pixel x-size (microns)
bool xytemp(float xhit, float yhit, bool ydouble[21+2], bool xdouble[13+2], float template2d[13+2][21+2], bool dervatives, float dpdx2d[2][13+2][21+2], float &QTemplate)
float chi2ppix()
average chi^2 per struck pixel
void xysigma2(float qpixel, int index, float &xysig2)
for(int i=first, nt=offsets[nh];i< nt;i+=gridDim.x *blockDim.x)
float s50()
1/2 of the pixel threshold signal in adc units
float offsetx(int i)
x-offset in 4 charge bins
Abs< T >::type abs(const T &t)
float scalex(int i)
x-error scale factor in 4 charge bins
float chi2scale()
scale factor for chi^2 distribution
float lorxdrift()
signed lorentz x-width (microns)
bool interpolate(int id, float cotalpha, float cotbeta, float locBz, float locBx)
float mpvvav()
most probable Q in Vavilov distribution
DecomposeProduct< arg, typename Div::arg > D
float kappavav()
kappa parameter in Vavilov distribution
float pixmax()
maximum pixel charge
float lorydrift()
signed lorentz y-width (microns)
float sxymax()
max pixel signal for pixel error calculation
float ysize()
pixel y-size (microns)
float qscale()
charge scaling factor
float qavg()
average cluster charge for this set of track angles
float fbin(int i)
Return lower bound of Qbin definition.
float offsety(int i)
y-offset in 4 charge bins
float clsleny()
cluster y-size
float sigmavav()
scale factor in Vavilov distribution
float scaley(int i)
y-error scale factor in 4 charge bins