Reconstruct the best estimate of the hit position for pixel clusters.
108 const float fracpix = 0.45f;
110 const int nilist = 9, njlist = 5;
111 const float ilist[nilist] = {0.f, -1.f, -0.75f, -0.5f, -0.25f, 0.25f, 0.5f, 0.75f, 1.f};
112 const float jlist[njlist] = {0.f, -0.5f, -0.25f, 0.25f, 0.50f};
117 if (!templ2D.
interpolate(
id, cotalpha, cotbeta, locBz, locBx))
125 for (
int i = 0;
i < 3; ++
i) {
126 fbin[
i] = templ2D.
fbin(
i);
129 float q50 = templ2D.
s50();
130 float pseudopix = 0.2f * q50;
131 float pseudopix2 = q50 * q50;
135 float qscale = templ2D.
qscale();
139 int nclusx = cluster.
mrow;
140 int nclusy = (
int)cluster.
mcol;
141 bool* xdouble = cluster.
xdouble;
142 bool* ydouble = cluster.
ydouble;
146 int imin =
BYM2, imax = 0, jmin =
BXM2, jmax = 0;
147 for (
int k = 0;
k < nclusx * nclusy; ++
k) {
151 int i =
k - j * nclusy;
170 int shiftx =
THXP1 - (jmin + jmax) / 2;
171 int shifty =
THYP1 - (imin + imax) / 2;
185 float fq0 = qtotal / templ2D.
qavg();
191 for (
int j = 0; j <
BXM2; ++
j) {
192 for (
int i = 0; i <
BYM2; ++
i) {
197 const unsigned int NPIXMAX = 200;
199 int indexxy[2][NPIXMAX];
200 float pixel[NPIXMAX];
201 float sigma2[NPIXMAX];
202 float minmax = templ2D.
pixmax();
203 float ylow0 = 0.f, yhigh0 = 0.f, xlow0 = 0.f, xhigh0 = 0.f;
210 for (
int i = 0; i <
BYM2; ++
i) {
214 for (
int j = 0; j <
BXM2; ++
j) {
217 for (
int i = 0; i < nclusy; ++
i) {
220 if (iy > -1 && iy < BYM2)
224 for (
int j = 0; j < nclusx; ++
j) {
227 if (jx > -1 && jx < BXM2)
234 for (
int i = 0; i <
BYM2; ++
i) {
235 float ypitch =
ysize;
239 ye[i + 1] = ye[
i] + ypitch;
240 ypos[
i] = ye[
i] + ypitch / 2.;
242 for (
int j = 0; j <
BXM2; ++
j) {
243 float xpitch =
xsize;
247 xe[j + 1] = xe[
j] + xpitch;
248 xpos[
j] = xe[
j] + xpitch / 2.;
251 for (
int i = 0; i < nclusy; ++
i) {
257 if (iy > -1 && iy < BYM2) {
258 for (
int j = 0; j < nclusx; ++
j) {
260 if (jx > -1 && jx < BXM2) {
261 if (cluster(j, i) > maxpix) {
264 clusxy[jx][iy] = cluster(j, i);
266 if (clusxy[jx][iy] > 0.
f) {
267 ysum[iy] += clusxy[jx][iy];
268 indexxy[0][npixel] = jx;
269 indexxy[1][npixel] = iy;
270 pixel[npixel] = clusxy[jx][iy];
280 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 281 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco2D::number of pixels above threshold = " << npixel
284 std::cout <<
"PixelTemplateReco2D::number of pixels above threshold = " << npixel << std::endl;
291 xhigh0 = xe[jmax + 1];
293 yhigh0 = ye[imax + 1];
297 int ypixoff =
T2HYP1 - (imin + imax) / 2;
298 for (
int k = 0;
k < npixel; ++
k) {
299 int ypixeff = ypixoff + indexxy[1][
k];
300 templ2D.
xysigma2(pixel[
k], ypixeff, sigma2[k]);
306 int imisslow = -1, imisshigh = -1, jmisslow = -1, jmisshigh = -1;
307 float ylow = -1.f, yhigh = -1.f;
308 float hmaxpix = fracpix * templ2D.
sxymax();
309 for (
int i = imin; i <= imax; ++
i) {
310 if (ysum[i] > hmaxpix && ysum[i - 1] < hmaxpix && ylow < 0.
f) {
311 ylow = ypos[i - 1] + (ypos[
i] - ypos[i - 1]) * (hmaxpix - ysum[i - 1]) / (ysum[
i] - ysum[i - 1]);
318 if (ysum[i] > hmaxpix && ysum[i + 1] < hmaxpix) {
319 yhigh = ypos[
i] + (ypos[i + 1] - ypos[
i]) * (ysum[i] - hmaxpix) / (ysum[
i] - ysum[i + 1]);
322 if (ylow < 0.
f || yhigh < 0.
f) {
327 float templeny = templ2D.
clsleny();
328 deltay = templeny - (yhigh - ylow) / ysize;
332 float x0 = 0.5f * (xlow0 + xhigh0) - templ2D.
lorxdrift();
333 float y0 = 0.5f * (ylow + yhigh) - templ2D.
lorydrift();
347 imisshigh = imin - 1;
355 imisshigh = imin - 1;
360 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 361 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco2D::illegal edgeflagy = " << edgeflagy << std::endl;
363 std::cout <<
"PixelTemplate:2D:illegal edgeflagy = " << edgeflagy << std::endl;
371 jmisshigh = jmin - 1;
379 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 380 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco2D::illegal edgeflagx = " << edgeflagx << std::endl;
382 std::cout <<
"PixelTemplate:2D:illegal edgeflagx = " << edgeflagx << std::endl;
388 float chi2min[2], xerr2[2], yerr2[2];
389 float x2D0[2], y2D0[2], qtfrac0[2];
393 for (ipass = 0; ipass < npass; ++ipass) {
400 for (
int k = npixel;
k < tpixel; ++
k) {
401 int j = indexxy[0][
k];
402 int i = indexxy[1][
k];
410 for (
int k = 0;
k < npixel; ++
k) {
411 int j = indexxy[0][
k];
412 int i = indexxy[1][
k];
413 if ((j - 1) != jmisshigh) {
414 if (clusxy[j - 1][i] < pseudopix) {
415 indexxy[0][tpixel] = j - 1;
416 indexxy[1][tpixel] =
i;
417 clusxy[j - 1][
i] = pseudopix;
418 pixel[tpixel] = pseudopix;
419 sigma2[tpixel] = pseudopix2;
423 if ((j + 1) != jmisslow) {
424 if (clusxy[j + 1][i] < pseudopix) {
425 indexxy[0][tpixel] = j + 1;
426 indexxy[1][tpixel] =
i;
427 clusxy[j + 1][
i] = pseudopix;
428 pixel[tpixel] = pseudopix;
429 sigma2[tpixel] = pseudopix2;
434 if ((i + 1) != imisslow) {
435 if ((j - 1) != jmisshigh) {
436 if (clusxy[j - 1][i + 1] < pseudopix) {
437 indexxy[0][tpixel] = j - 1;
438 indexxy[1][tpixel] = i + 1;
439 clusxy[j - 1][i + 1] = pseudopix;
440 pixel[tpixel] = pseudopix;
441 sigma2[tpixel] = pseudopix2;
445 if (clusxy[j][i + 1] < pseudopix) {
446 indexxy[0][tpixel] =
j;
447 indexxy[1][tpixel] = i + 1;
448 clusxy[
j][i + 1] = pseudopix;
449 pixel[tpixel] = pseudopix;
450 sigma2[tpixel] = pseudopix2;
453 if ((j + 1) != jmisslow) {
454 if (clusxy[j + 1][i + 1] < pseudopix) {
455 indexxy[0][tpixel] = j + 1;
456 indexxy[1][tpixel] = i + 1;
457 clusxy[j + 1][i + 1] = pseudopix;
458 pixel[tpixel] = pseudopix;
459 sigma2[tpixel] = pseudopix2;
465 if ((i - 1) != imisshigh) {
466 if ((j - 1) != jmisshigh) {
467 if (clusxy[j - 1][i - 1] < pseudopix) {
468 indexxy[0][tpixel] = j - 1;
469 indexxy[1][tpixel] = i - 1;
470 clusxy[j - 1][i - 1] = pseudopix;
471 pixel[tpixel] = pseudopix;
472 sigma2[tpixel] = pseudopix2;
476 if (clusxy[j][i - 1] < pseudopix) {
477 indexxy[0][tpixel] =
j;
478 indexxy[1][tpixel] = i - 1;
479 clusxy[
j][i - 1] = pseudopix;
480 pixel[tpixel] = pseudopix;
481 sigma2[tpixel] = pseudopix2;
484 if ((j + 1) != jmisslow) {
485 if (clusxy[j + 1][i - 1] < pseudopix) {
486 indexxy[0][tpixel] = j + 1;
487 indexxy[1][tpixel] = i - 1;
488 clusxy[j + 1][i - 1] = pseudopix;
489 pixel[tpixel] = pseudopix;
490 sigma2[tpixel] = pseudopix2;
499 chi2min[ipass] = 1000000.f;
500 float chi2, qtemplate, qactive, qtfrac = 0.f, x2D = 0.f, y2D = 0.f;
502 float ygridscale = 0.271 * cotbeta;
503 if (ygridscale < 1.
f)
505 for (
int is = 0; is < nilist; ++is) {
506 for (
int js = 0; js < njlist; ++js) {
507 float xtry = x0 + jlist[js] *
xsize;
508 float ytry = y0 + ilist[is] * ygridscale *
ysize;
511 for (
int j = 0; j <
BXM2; ++
j) {
512 for (
int i = 0; i <
BYM2; ++
i) {
513 template2d[
j][
i] = 0.f;
516 templ2D.
xytemp(xtry, ytry, yd, xd, template2d,
false, dpdx2d, qtemplate);
517 for (
int k = 0;
k < tpixel; ++
k) {
518 int jpix = indexxy[0][
k];
519 int ipix = indexxy[1][
k];
520 float qtpixel = template2d[jpix][ipix];
521 float pt = pixel[
k] - qtpixel;
522 chi2 += pt * pt / sigma2[
k];
527 if (chi2 < chi2min[ipass]) {
528 chi2min[ipass] =
chi2;
531 qtfrac = qactive / qtemplate;
537 float xstep = 1.0f, ystep = 1.0f;
538 float minv11 = 1000.f, minv12 = 1000.f, minv22 = 1000.f;
539 chi2 = chi2min[ipass];
540 while (chi2 <= chi2min[ipass] && niter < 15 && (niter < 2 || (
std::abs(xstep) > 0.2 ||
std::abs(ystep) > 0.2))) {
544 qtfrac0[ipass] = qtfrac;
545 xerr2[ipass] = minv11;
546 yerr2[ipass] = minv22;
547 chi2min[ipass] =
chi2;
552 for (
int j = 0; j <
BXM2; ++
j) {
553 for (
int i = 0; i <
BYM2; ++
i) {
554 template2d[
j][
i] = 0.f;
557 templ2D.
xytemp(x2D, y2D, yd, xd, template2d,
true, dpdx2d, qtemplate);
559 float sumptdt1 = 0., sumptdt2 = 0.;
560 float sumdtdt11 = 0., sumdtdt12 = 0., sumdtdt22 = 0.;
565 for (
int k = 0;
k < tpixel; ++
k) {
566 int jpix = indexxy[0][
k];
567 int ipix = indexxy[1][
k];
568 float qtpixel = template2d[jpix][ipix];
569 float pt = pixel[
k] - qtpixel;
570 float dtdx = dpdx2d[0][jpix][ipix];
571 float dtdy = dpdx2d[1][jpix][ipix];
572 chi2 += pt * pt / sigma2[
k];
573 sumptdt1 += pt * dtdx / sigma2[
k];
574 sumptdt2 += pt * dtdy / sigma2[
k];
575 sumdtdt11 += dtdx * dtdx / sigma2[
k];
576 sumdtdt12 += dtdx * dtdy / sigma2[
k];
577 sumdtdt22 += dtdy * dtdy / sigma2[
k];
585 float D = sumdtdt11 * sumdtdt22 - sumdtdt12 * sumdtdt12;
590 minv11 = sumdtdt22 /
D;
591 minv12 = -sumdtdt12 /
D;
592 minv22 = sumdtdt11 /
D;
594 qtfrac = qactive / qtemplate;
598 xstep = minv11 * sumptdt1 + minv12 * sumptdt2;
599 ystep = minv12 * sumptdt1 + minv22 * sumptdt2;
603 if (sumdtdt11 > 0.0001
f) {
604 xstep = sumptdt1 / sumdtdt11;
608 if (sumdtdt22 > 0.0001
f) {
609 ystep = sumptdt2 / sumdtdt22;
628 if (chi2min[1] < chi2min[0]) {
636 if (qtfrac0[ipass] < 0.10
f || qtfrac0[ipass] > 1.
f) {
637 qtfrac0[ipass] = 1.f;
639 fq = fq0 / qtfrac0[ipass];
659 float scalex = templ2D.
scalex(qbin);
660 float scaley = templ2D.
scaley(qbin);
661 float offsetx = templ2D.
offsetx(qbin);
662 float offsety = templ2D.
offsety(qbin);
668 xrec = x2D0[ipass] - xpos[shiftx] - offsetx;
669 yrec = y2D0[ipass] - ypos[shifty] - offsety;
670 if (xerr2[ipass] > 0.
f) {
671 sigmax = scalex *
sqrt(xerr2[ipass]);
677 if (yerr2[ipass] > 0.
f) {
678 sigmay = scaley *
sqrt(yerr2[ipass]);
686 double meanxy = (double)(npixel * templ2D.
chi2ppix());
687 double chi2scale = (double)templ2D.
chi2scale();
691 double hndof = meanxy / 2.f;
692 double hchi2 = chi2scale * chi2min[ipass] / 2.f;
693 probxy = (
float)(1. - TMath::Gamma(hndof, hchi2));
695 float mpv = templ2D.
mpvvav();
698 float xvav = (qtotal / qtfrac0[ipass] - mpv) / sigmaQ;
701 VVIObjF vvidist(kappa, beta2, 1);
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)
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.
static const G4double kappa
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