Reconstruct the best estimate of the hit position for pixel clusters.
91 const float fracpix = 0.45f;
93 const int nilist = 9, njlist = 5;
94 const float ilist[nilist] = {0.f, -1.f, -0.75f, -0.5f, -0.25f, 0.25f, 0.5f, 0.75f, 1.f};
95 const float jlist[njlist] = {0.f, -0.5f, -0.25f, 0.25f, 0.5f};
100 if(
id > 0) {
if(!templ2D.
interpolate(
id, cotalpha, cotbeta, locBz, locBx))
return 4;}
106 for(
int i=0;
i<3; ++
i) {fbin[
i] = templ2D.
fbin(
i);}
108 float q50 = templ2D.
s50();
109 float pseudopix = 0.2f*q50;
110 float pseudopix2 = q50*q50;
115 float qscale = templ2D.
qscale();
119 int nclusx = cluster.
mrow;
120 int nclusy = (
int)cluster.
mcol;
121 bool * xdouble = cluster.
xdouble;
122 bool * ydouble = cluster.
ydouble;
126 int imin=
BYM2, imax=0, jmin=
BXM2, jmax=0;
127 for(
int k=0;
k<nclusx*nclusy; ++
k) {
131 int i =
k - j*nclusy;
133 if(j < jmin) {jmin = j;}
134 if(j > jmax) {jmax = j;}
135 if(i < imin) {imin =
i;}
136 if(i > imax) {imax =
i;}
142 int shiftx =
THXP1 - (jmin+jmax)/2;
143 int shifty =
THYP1 - (imin+imax)/2;
145 if(shiftx < 1) shiftx = 1;
146 if(shifty < 1) shifty = 1;
155 float fq0 = qtotal/templ2D.
qavg();
161 for(
int j=0; j<
BXM2; ++j) {
for(
int i=0; i<
BYM2; ++
i) {clusxy[j][
i] = 0.f;}}
163 const unsigned int NPIXMAX = 200;
165 int indexxy[2][NPIXMAX];
166 float pixel[NPIXMAX];
167 float sigma2[NPIXMAX];
168 float minmax = templ2D.
pixmax();
169 float ylow0 = 0.f, yhigh0 = 0.f, xlow0 = 0.f, xhigh0 = 0.f;
176 for(
int i=0; i<
BYM2; ++
i) {ysum[
i] = 0.f; yd[
i] =
false;}
177 for(
int j=0; j<
BXM2; ++j) {xd[j] =
false;}
178 for(
int i=0; i<nclusy; ++
i) {
181 if(iy > -1 && iy < BYM2) yd[iy] =
true;
184 for(
int j=0; j<nclusx; ++j) {
187 if(jx > -1 && jx < BXM2) xd[jx] =
true;
193 for(
int i=0; i<
BYM2; ++
i) {
194 float ypitch =
ysize;
195 if(yd[i]) {ypitch +=
ysize;}
196 ye[i+1] = ye[
i] + ypitch;
197 ypos[
i] = ye[
i] + ypitch/2.;
199 for(
int j=0; j<
BXM2; ++j) {
200 float xpitch =
xsize;
201 if(xd[j]) {xpitch +=
xsize;}
202 xe[j+1] = xe[j] + xpitch;
203 xpos[j] = xe[j] + xpitch/2.;
206 for(
int i=0; i<nclusy; ++
i) {
209 if(ydouble[i]) {maxpix *=2.f;}
210 if(iy > -1 && iy < BYM2) {
211 for(
int j=0; j<nclusx; ++j) {
213 if(jx > -1 && jx < BXM2) {
214 if(cluster(j,i) > maxpix) {
217 clusxy[jx][iy] = cluster(j,i);
219 if(clusxy[jx][iy] > 0.
f) {
220 ysum[iy] += clusxy[jx][iy];
221 indexxy[0][npixel] = jx;
222 indexxy[1][npixel] = iy;
223 pixel[npixel] = clusxy[jx][iy];
238 int ypixoff =
T2HYP1 - (imin+imax)/2;
239 for(
int k=0;
k<npixel; ++
k) {
240 int ypixeff = ypixoff + indexxy[1][
k];
241 templ2D.
xysigma2(pixel[
k], ypixeff, sigma2[k]);
247 int imisslow = -1, imisshigh = -1, jmisslow = -1, jmisshigh = -1;
248 float ylow = -1.f, yhigh = -1.f;
249 float hmaxpix = fracpix*templ2D.
sxymax();
250 for(
int i=imin; i<=imax; ++
i) {
251 if(ysum[i] > hmaxpix && ysum[i-1] < hmaxpix && ylow < 0.
f) {
252 ylow = ypos[i-1] + (ypos[
i]-ypos[i-1])*(hmaxpix-ysum[i-1])/(ysum[
i]-ysum[i-1]);
255 if(imisslow < 0) imisslow =
i;
258 if(ysum[i] > hmaxpix && ysum[i+1] < hmaxpix) {
259 yhigh = ypos[
i] + (ypos[i+1]-ypos[
i])*(ysum[i]-hmaxpix)/(ysum[
i]-ysum[i+1]);
262 if(ylow < 0.
f || yhigh < 0.
f) {
267 float templeny = templ2D.
clsleny();
268 deltay = templeny - (yhigh - ylow)/ysize;
273 float x0 = 0.5f*(xlow0 + xhigh0) - templ2D.
lorxdrift();
274 float y0 = 0.5f*(ylow + yhigh) - templ2D.
lorydrift();
301 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 302 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco3D::illegal edgeflagy = " << edgeflagy << std::endl;
304 std::cout <<
"PixelTemplate:3D:illegal edgeflagy = " << edgeflagy << std::endl;
320 #ifndef SI_PIXEL_TEMPLATE_STANDALONE 321 throw cms::Exception(
"DataCorrupt") <<
"PixelTemplateReco3D::illegal edgeflagx = " << edgeflagx << std::endl;
323 std::cout <<
"PixelTemplate:3D:illegal edgeflagx = " << edgeflagx << std::endl;
330 float chi2min[2], xerr2[2], yerr2[2];
331 float x2D0[2], y2D0[2], qtfrac0[2];
335 for(ipass = 0; ipass < npass; ++ipass) {
344 for(
int k=npixel;
k<tpixel; ++
k) {
345 int j = indexxy[0][
k];
346 int i = indexxy[1][
k];
354 for(
int k=0;
k<npixel; ++
k) {
355 int j = indexxy[0][
k];
356 int i = indexxy[1][
k];
357 if((j-1) != jmisshigh) {
358 if(clusxy[j-1][i] < pseudopix) {
359 indexxy[0][tpixel] = j-1;
360 indexxy[1][tpixel] =
i;
361 clusxy[j-1][
i] = pseudopix;
362 pixel[tpixel] = pseudopix;
363 sigma2[tpixel] = pseudopix2;
367 if((j+1) != jmisslow) {
368 if(clusxy[j+1][i] < pseudopix) {
369 indexxy[0][tpixel] = j+1;
370 indexxy[1][tpixel] =
i;
371 clusxy[j+1][
i] = pseudopix;
372 pixel[tpixel] = pseudopix;
373 sigma2[tpixel] = pseudopix2;
378 if((i+1) != imisslow) {
379 if((j-1) != jmisshigh) {
380 if(clusxy[j-1][i+1] < pseudopix) {
381 indexxy[0][tpixel] = j-1;
382 indexxy[1][tpixel] = i+1;
383 clusxy[j-1][i+1] = pseudopix;
384 pixel[tpixel] = pseudopix;
385 sigma2[tpixel] = pseudopix2;
389 if(clusxy[j][i+1] < pseudopix) {
390 indexxy[0][tpixel] = j;
391 indexxy[1][tpixel] = i+1;
392 clusxy[j][i+1] = pseudopix;
393 pixel[tpixel] = pseudopix;
394 sigma2[tpixel] = pseudopix2;
397 if((j+1) != jmisslow) {
398 if(clusxy[j+1][i+1] < pseudopix) {
399 indexxy[0][tpixel] = j+1;
400 indexxy[1][tpixel] = i+1;
401 clusxy[j+1][i+1] = pseudopix;
402 pixel[tpixel] = pseudopix;
403 sigma2[tpixel] = pseudopix2;
409 if((i-1) != imisshigh) {
410 if((j-1) != jmisshigh) {
411 if(clusxy[j-1][i-1] < pseudopix) {
412 indexxy[0][tpixel] = j-1;
413 indexxy[1][tpixel] = i-1;
414 clusxy[j-1][i-1] = pseudopix;
415 pixel[tpixel] = pseudopix;
416 sigma2[tpixel] = pseudopix2;
420 if(clusxy[j][i-1] < pseudopix) {
421 indexxy[0][tpixel] = j;
422 indexxy[1][tpixel] = i-1;
423 clusxy[j][i-1] = pseudopix;
424 pixel[tpixel] = pseudopix;
425 sigma2[tpixel] = pseudopix2;
428 if((j+1) != jmisslow) {
429 if(clusxy[j+1][i-1] < pseudopix) {
430 indexxy[0][tpixel] = j+1;
431 indexxy[1][tpixel] = i-1;
432 clusxy[j+1][i-1] = pseudopix;
433 pixel[tpixel] = pseudopix;
434 sigma2[tpixel] = pseudopix2;
444 chi2min[ipass] = 1000000.f;
445 float chi2, qtemplate, qactive, qtfrac = 0.f, x2D = 0.f, y2D = 0.f;
447 for(
int is = 0; is<nilist; ++is) {
448 for(
int js = 0; js<njlist; ++js) {
449 float xtry = x0 + jlist[js]*
xsize;
450 float ytry = y0 + ilist[is]*
ysize;
453 for(
int j=0; j<
BXM2; ++j) {
for(
int i=0; i<
BYM2; ++
i) {template2d[j][
i] = 0.f;}}
454 templ2D.
xytemp(xtry, ytry, yd, xd, template2d,
false, dpdx2d, qtemplate);
455 for(
int k=0;
k<tpixel; ++
k) {
456 int jpix = indexxy[0][
k];
457 int ipix = indexxy[1][
k];
458 float qtpixel = template2d[jpix][ipix];
459 float pt = pixel[
k]-qtpixel;
460 chi2 += pt*pt/sigma2[
k];
461 if(
k < npixel) {qactive += qtpixel;}
463 if(chi2 < chi2min[ipass]) {
464 chi2min[ipass] =
chi2;
467 qtfrac = qactive/qtemplate;
473 float xstep = 1.0f, ystep = 1.0f;
474 float minv11 = 1000.f, minv12 = 1000.f, minv22 = 1000.f;
475 chi2 = chi2min[ipass];
477 while(chi2 <= chi2min[ipass] && niter < 15 && (niter < 2 || (fabs(xstep) > 0.2 && fabs(ystep) > 0.2))) {
482 qtfrac0[ipass] = qtfrac;
483 xerr2[ipass] = minv11;
484 yerr2[ipass] = minv22;
485 chi2min[ipass] =
chi2;
489 for(
int j=0; j<
BXM2; ++j) {
for(
int i=0; i<
BYM2; ++
i) {template2d[j][
i] = 0.f;}}
490 templ2D.
xytemp(x2D, y2D, yd, xd, template2d,
true, dpdx2d, qtemplate);
492 float sumptdt1 = 0., sumptdt2 = 0.;
493 float sumdtdt11 = 0., sumdtdt12 = 0., sumdtdt22 = 0.;
498 for(
int k=0;
k<tpixel; ++
k) {
499 int jpix = indexxy[0][
k];
500 int ipix = indexxy[1][
k];
501 float qtpixel = template2d[jpix][ipix];
502 float pt = pixel[
k]-qtpixel;
503 float dtdx = dpdx2d[0][jpix][ipix];
504 float dtdy = dpdx2d[1][jpix][ipix];
505 chi2 += pt*pt/sigma2[
k];
506 sumptdt1 += pt*dtdx/sigma2[
k];
507 sumptdt2 += pt*dtdy/sigma2[
k];
508 sumdtdt11 += dtdx*dtdx/sigma2[
k];
509 sumdtdt12 += dtdx*dtdy/sigma2[
k];
510 sumdtdt22 += dtdy*dtdy/sigma2[
k];
511 if(
k < npixel) {qactive += qtpixel;}
516 float D = sumdtdt11*sumdtdt22 - sumdtdt12*sumdtdt12;
520 if(fabs(D) > 1.
e-3) {
522 minv11 = sumdtdt22/
D;
523 minv12 = -sumdtdt12/
D;
524 minv22 = sumdtdt11/
D;
526 qtfrac = qactive/qtemplate;
530 xstep = minv11*sumptdt1 + minv12*sumptdt2;
531 ystep = minv12*sumptdt1 + minv22*sumptdt2;
535 xstep = sumptdt1/sumdtdt11;
536 ystep = sumptdt2/sumdtdt22;
540 if(fabs(xstep) > 2.*xsize || fabs(ystep) > 2.*ysize)
break;
567 if(chi2min[1] < chi2min[0]) {ipass = 1;}
576 if(qtfrac0[ipass] < 0.10
f || qtfrac0[ipass] > 1.
f) {qtfrac0[ipass] = 1.f;}
577 fq = fq0/qtfrac0[ipass];
597 float scalex = templ2D.
scalex(qbin);
598 float scaley = templ2D.
scaley(qbin);
599 float offsetx = templ2D.
offsetx(qbin);
600 float offsety = templ2D.
offsety(qbin);
606 xrec = x2D0[ipass] - xpos[shiftx] - offsetx;
607 yrec = y2D0[ipass] - ypos[shifty] - offsety;
608 if(xerr2[ipass] > 0.
f) {
609 sigmax = scalex*
sqrt(xerr2[ipass]);
610 if(sigmax < 3.
f) sigmax = 3.f;
614 if(yerr2[ipass] > 0.
f) {
615 sigmay = scaley*
sqrt(yerr2[ipass]);
616 if(sigmay < 3.
f) sigmay = 3.f;
622 double meanxy = (double)(npixel*templ2D.
chi2ppix());
623 double chi2scale = (double)templ2D.
chi2scale();
624 if(meanxy < 0.01) {meanxy = 0.01;}
625 double hndof = meanxy/2.f;
626 double hchi2 = chi2scale*chi2min[ipass]/2.f;
629 float mpv = templ2D.
mpvvav();
632 float xvav = (qtotal/qtfrac0[ipass]-mpv)/sigmaQ;
635 VVIObjF vvidist(kappa, beta2, 1);
636 float prvav = vvidist.fcn(xvav);
639 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
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