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)
for(Iditer=Id.begin();Iditer!=Id.end();Iditer++)
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