![]() |
![]() |
Typedefs | |
typedef boost::multi_array < float, 2 > | array_2d |
typedef boost::multi_array < float, 3 > | array_3d |
Functions | |
int | PixelTempReco2D (int id, bool fpix, float cotalpha, float cotbeta, array_2d cluster, std::vector< bool > ydouble, std::vector< bool > xdouble, SiPixelTemplate &templ, float &yrec, float &sigmay, float &proby, float &xrec, float &sigmax, float &probx, int &qbin, int speed) |
Reconstruct the best estimate of the hit position for pixel clusters. | |
int | PixelTempReco2D (int id, bool fpix, float cotalpha, float cotbeta, array_2d cluster, std::vector< bool > ydouble, std::vector< bool > xdouble, SiPixelTemplate &templ, float &yrec, float &sigmay, float &proby, float &xrec, float &sigmax, float &probx, int &qbin, int speed, bool deadpix, std::vector< std::pair< int, int > > zeropix) |
Reconstruct the best estimate of the hit position for pixel clusters. | |
int | PixelTempSplit (int id, bool fpix, float cotalpha, float cotbeta, array_2d cluster, std::vector< bool > ydouble, std::vector< bool > xdouble, SiPixelTemplate &templ, float &yrec1, float &yrec2, float &sigmay, float &proby, float &xrec1, float &xrec2, float &sigmax, float &probx, int &qbin) |
Reconstruct the best estimate of the hit positions for pixel clusters. | |
int | PixelTempSplit (int id, bool fpix, float cotalpha, float cotbeta, array_2d cluster, std::vector< bool > ydouble, std::vector< bool > xdouble, SiPixelTemplate &templ, float &yrec1, float &yrec2, float &sigmay, float &proby, float &xrec1, float &xrec2, float &sigmax, float &probx, int &qbin, bool deadpix, std::vector< std::pair< int, int > > zeropix) |
Reconstruct the best estimate of the hit positions for pixel clusters. |
typedef boost::multi_array< float, 2 > SiPixelTemplateReco::array_2d |
Definition at line 56 of file SiPixelTemplateReco.h.
typedef boost::multi_array<float, 3> SiPixelTemplateReco::array_3d |
Definition at line 42 of file SiPixelTemplateSplit.h.
int SiPixelTemplateReco::PixelTempReco2D | ( | int | id, | |
bool | fpix, | |||
float | cotalpha, | |||
float | cotbeta, | |||
array_2d | cluster, | |||
std::vector< bool > | ydouble, | |||
std::vector< bool > | xdouble, | |||
SiPixelTemplate & | templ, | |||
float & | yrec, | |||
float & | sigmay, | |||
float & | proby, | |||
float & | xrec, | |||
float & | sigmax, | |||
float & | probx, | |||
int & | qbin, | |||
int | speed | |||
) |
Reconstruct the best estimate of the hit position for pixel clusters.
id | - (input) identifier of the template to use | |
fpix | - (input) logical input indicating whether to use FPix templates (true) or Barrel templates (false) | |
cotalpha | - (input) the cotangent of the alpha track angle (see CMS IN 2004/014) | |
cotbeta | - (input) the cotangent of the beta track angle (see CMS IN 2004/014) | |
cluster | - (input) boost multi_array container of 7x21 array of pixel signals, origin of local coords (0,0) at center of pixel cluster[0][0]. | |
ydouble | - (input) STL vector of 21 element array to flag a double-pixel | |
xdouble | - (input) STL vector of 7 element array to flag a double-pixel | |
templ | - (input) the template used in the reconstruction | |
yrec | - (output) best estimate of y-coordinate of hit in microns | |
sigmay | - (output) best estimate of uncertainty on yrec in microns | |
proby | - (output) probability describing goodness-of-fit for y-reco | |
xrec | - (output) best estimate of x-coordinate of hit in microns | |
sigmax | - (output) best estimate of uncertainty on xrec in microns | |
probx | - (output) probability describing goodness-of-fit for x-reco | |
qbin | - (output) index (0-4) describing the charge of the cluster [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] | |
speed | - (input) switch (0-4) trading speed vs robustness 0 totally bombproof, searches the entire 41 bin range at full density (equiv to V2_4) 1 faster, searches reduced 25 bin range (no big pix) + 33 bins (big pix at ends) at full density 2 faster yet, searches same range as 1 but at 1/2 density 3 fastest, searches same range as 1 but at 1/4 density (no big pix) and 1/2 density (big pix in cluster) |
Definition at line 898 of file SiPixelTemplateReco.cc.
References PixelTempReco2D().
Referenced by PixelCPETemplateReco::localPosition().
00904 { 00905 // Local variables 00906 const bool deadpix = false; 00907 std::vector<std::pair<int, int> > zeropix; 00908 00909 return SiPixelTemplateReco::PixelTempReco2D(id, fpix, cotalpha, cotbeta, cluster, ydouble, xdouble, templ, 00910 yrec, sigmay, proby, xrec, sigmax, probx, qbin, speed, deadpix, zeropix); 00911
int SiPixelTemplateReco::PixelTempReco2D | ( | int | id, | |
bool | fpix, | |||
float | cotalpha, | |||
float | cotbeta, | |||
array_2d | cluster, | |||
std::vector< bool > | ydouble, | |||
std::vector< bool > | xdouble, | |||
SiPixelTemplate & | templ, | |||
float & | yrec, | |||
float & | sigmay, | |||
float & | proby, | |||
float & | xrec, | |||
float & | sigmax, | |||
float & | probx, | |||
int & | qbin, | |||
int | speed, | |||
bool | deadpix, | |||
std::vector< std::pair< int, int > > | zeropix | |||
) |
Reconstruct the best estimate of the hit position for pixel clusters.
id | - (input) identifier of the template to use | |
fpix | - (input) logical input indicating whether to use FPix templates (true) or Barrel templates (false) | |
cotalpha | - (input) the cotangent of the alpha track angle (see CMS IN 2004/014) | |
cotbeta | - (input) the cotangent of the beta track angle (see CMS IN 2004/014) | |
cluster | - (input) boost multi_array container of 7x21 array of pixel signals, origin of local coords (0,0) at center of pixel cluster[0][0]. Set dead pixels to small non-zero values (0.1 e). | |
ydouble | - (input) STL vector of 21 element array to flag a double-pixel | |
xdouble | - (input) STL vector of 7 element array to flag a double-pixel | |
templ | - (input) the template used in the reconstruction | |
yrec | - (output) best estimate of y-coordinate of hit in microns | |
sigmay | - (output) best estimate of uncertainty on yrec in microns | |
proby | - (output) probability describing goodness-of-fit for y-reco | |
xrec | - (output) best estimate of x-coordinate of hit in microns | |
sigmax | - (output) best estimate of uncertainty on xrec in microns | |
probx | - (output) probability describing goodness-of-fit for x-reco | |
qbin | - (output) index (0-4) describing the charge of the cluster [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] | |
speed | - (input) switch (0-4) trading speed vs robustness 0 totally bombproof, searches the entire 41 bin range at full density (equiv to V2_4) 1 faster, searches reduced 25 bin range (no big pix) + 33 bins (big pix at ends) at full density 2 faster yet, searches same range as 1 but at 1/2 density 3 fastest, searches same range as 1 but at 1/4 density (no big pix) and 1/2 density (big pix in cluster) | |
deadpix | - (input) bool to indicate that there are dead pixels to be included in the analysis | |
zeropix | - (input) vector of index pairs pointing to the dead pixels |
Definition at line 87 of file SiPixelTemplateReco.cc.
References BHX, BHY, bias, BXM1, BXM2, BXSIZE, BYM1, BYM2, BYM3, BYSIZE, SiPixelTemplate::chi2xavg(), SiPixelTemplate::chi2xmin(), SiPixelTemplate::chi2yavg(), SiPixelTemplate::chi2ymin(), SiPixelTemplate::dxone(), SiPixelTemplate::dxtwo(), SiPixelTemplate::dyone(), SiPixelTemplate::dytwo(), ENDL, err, i, SiPixelTemplate::interpolate(), j, k, LOGDEBUG, LOGERROR, SiPixelTemplate::pixmax(), SiPixelTemplate::qavg(), SiPixelTemplate::qmin(), SiPixelTemplate::qscale(), SiPixelTemplate::s50(), python::multivaluedict::sort(), SiPixelTemplate::sxmax(), SiPixelTemplate::sxone(), SiPixelTemplate::sxtwo(), SiPixelTemplate::symax(), SiPixelTemplate::syone(), SiPixelTemplate::sytwo(), theVerboseLevel, TXSIZE, TYSIZE, SiPixelTemplate::xavg(), SiPixelTemplate::xflcorr(), SiPixelTemplate::xrms(), SiPixelTemplate::xsigma2(), SiPixelTemplate::xtemp(), SiPixelTemplate::yavg(), SiPixelTemplate::yflcorr(), SiPixelTemplate::yrms(), SiPixelTemplate::ysigma2(), and SiPixelTemplate::ytemp().
Referenced by PixelTempReco2D().
00093 { 00094 // Local variables 00095 static int i, j, k, minbin, binl, binh, binq, midpix, fypix, nypix, lypix, logypx; 00096 static int fxpix, nxpix, lxpix, logxpx, shifty, shiftx, nyzero[TYSIZE]; 00097 static unsigned int nclusx, nclusy; 00098 static int deltaj, jmin, jmax, fxbin, lxbin, fybin, lybin, djy, djx; 00099 static float sythr, sxthr, rnorm, delta, sigma, sigavg, pseudopix, qscale; 00100 static float ss2, ssa, sa2, ssba, saba, sba2, rat, fq, qtotal, qpixel; 00101 static float originx, originy, qfy, qly, qfx, qlx, bias, err, maxpix, minmax; 00102 static double chi2x, meanx, chi2y, meany, chi2ymin, chi2xmin, chi2; 00103 static double hchi2, hndof; 00104 static float ytemp[41][BYSIZE], xtemp[41][BXSIZE], ysum[BYSIZE], xsum[BXSIZE], ysort[BYSIZE], xsort[BXSIZE]; 00105 static float chi2ybin[41], chi2xbin[41], ysig2[BYSIZE], xsig2[BXSIZE]; 00106 static bool yd[BYSIZE], xd[BXSIZE], anyyd, anyxd; 00107 const float ysize={150.}, xsize={100.}; 00108 00109 // The minimum chi2 for a valid one pixel cluster = pseudopixel contribution only 00110 00111 const double mean1pix={0.100}, chi21min={0.160}; 00112 00113 // First, interpolate the template needed to analyze this cluster 00114 // check to see of the track direction is in the physical range of the loaded template 00115 00116 if(!templ.interpolate(id, fpix, cotalpha, cotbeta)) { 00117 LOGDEBUG("SiPixelTemplateReco") << "input cluster direction cot(alpha) = " << cotalpha << ", cot(beta) = " << cotbeta << " is not within the acceptance of fpix = " 00118 << fpix << ", template ID = " << id << ", no reconstruction performed" << ENDL; 00119 return 20; 00120 } 00121 00122 // Define size of pseudopixel 00123 00124 pseudopix = 0.2*templ.s50(); 00125 00126 // Get charge scaling factor 00127 00128 qscale = templ.qscale(); 00129 00130 // Check that the cluster container is (up to) a 7x21 matrix and matches the dimensions of the double pixel flags 00131 00132 if(cluster.num_dimensions() != 2) { 00133 LOGERROR("SiPixelTemplateReco") << "input cluster container (BOOST Multiarray) has wrong number of dimensions" << ENDL; 00134 return 3; 00135 } 00136 nclusx = cluster.shape()[0]; 00137 nclusy = cluster.shape()[1]; 00138 if(nclusx != xdouble.size()) { 00139 LOGERROR("SiPixelTemplateReco") << "input cluster container x-size is not equal to double pixel flag container size" << ENDL; 00140 return 4; 00141 } 00142 if(nclusy != ydouble.size()) { 00143 LOGERROR("SiPixelTemplateReco") << "input cluster container y-size is not equal to double pixel flag container size" << ENDL; 00144 return 5; 00145 } 00146 00147 // enforce maximum size 00148 00149 if(nclusx > TXSIZE) {nclusx = TXSIZE;} 00150 if(nclusy > TYSIZE) {nclusy = TYSIZE;} 00151 00152 // First, rescale all pixel charges 00153 00154 for(i=0; i<nclusy; ++i) { 00155 for(j=0; j<nclusx; ++j) { 00156 if(cluster[j][i] > 0) {cluster[j][i] *= qscale;} 00157 } 00158 } 00159 00160 // Next, sum the total charge and "decapitate" big pixels 00161 00162 qtotal = 0.; 00163 minmax = templ.pixmax(); 00164 for(i=0; i<nclusy; ++i) { 00165 maxpix = minmax; 00166 if(ydouble[i]) {maxpix *=2.;} 00167 for(j=0; j<nclusx; ++j) { 00168 qtotal += cluster[j][i]; 00169 if(cluster[j][i] > maxpix) {cluster[j][i] = maxpix;} 00170 } 00171 } 00172 00173 // Do the cluster repair here 00174 00175 if(deadpix) { 00176 fypix = BYM3; lypix = -1; 00177 for(i=0; i<nclusy; ++i) { 00178 ysum[i] = 0.; nyzero[i] = 0; 00179 // Do preliminary cluster projection in y 00180 for(j=0; j<nclusx; ++j) { 00181 ysum[i] += cluster[j][i]; 00182 } 00183 if(ysum[i] > 0.) { 00184 // identify ends of cluster to determine what the missing charge should be 00185 if(i < fypix) {fypix = i;} 00186 if(i > lypix) {lypix = i;} 00187 } 00188 } 00189 00190 // Now loop over dead pixel list and "fix" everything 00191 00192 //First see if the cluster ends are redefined and that we have only one dead pixel per column 00193 00194 std::vector<std::pair<int, int> >::const_iterator zeroIter = zeropix.begin(), zeroEnd = zeropix.end(); 00195 for ( ; zeroIter != zeroEnd; ++zeroIter ) { 00196 i = zeroIter->second; 00197 if(i<0 || i>TYSIZE-1) {LOGERROR("SiPixelTemplateReco") << "dead pixel column y-index " << i << ", no reconstruction performed" << ENDL; 00198 return 11;} 00199 00200 // count the number of dead pixels in each column 00201 ++nyzero[i]; 00202 // allow them to redefine the cluster ends 00203 if(i < fypix) {fypix = i;} 00204 if(i > lypix) {lypix = i;} 00205 } 00206 00207 nypix = lypix-fypix+1; 00208 00209 // Now adjust the charge in the dead pixels to sum to 0.5*truncation value in the end columns and the truncation value in the interior columns 00210 00211 for (zeroIter = zeropix.begin(); zeroIter != zeroEnd; ++zeroIter ) { 00212 i = zeroIter->second; j = zeroIter->first; 00213 if(j<0 || j>TXSIZE-1) {LOGERROR("SiPixelTemplateReco") << "dead pixel column x-index " << j << ", no reconstruction performed" << ENDL; 00214 return 12;} 00215 if((i == fypix || i == lypix) && nypix > 1) {maxpix = templ.symax()/2.;} else {maxpix = templ.symax();} 00216 if(ydouble[i]) {maxpix *=2.;} 00217 if(nyzero[i] > 0 && nyzero[i] < 3) {qpixel = (maxpix - ysum[i])/(float)nyzero[i];} else {qpixel = 1.;} 00218 if(qpixel < 1.) {qpixel = 1.;} 00219 cluster[j][i] = qpixel; 00220 // Adjust the total cluster charge to reflect the charge of the "repaired" cluster 00221 qtotal += qpixel; 00222 } 00223 // End of cluster repair section 00224 } 00225 00226 // Next, make y-projection of the cluster and copy the double pixel flags into a 25 element container 00227 00228 for(i=0; i<BYSIZE; ++i) { ysum[i] = 0.; yd[i] = false;} 00229 k=0; 00230 anyyd = false; 00231 for(i=0; i<nclusy; ++i) { 00232 for(j=0; j<nclusx; ++j) { 00233 ysum[k] += cluster[j][i]; 00234 } 00235 00236 // If this is a double pixel, put 1/2 of the charge in 2 consective single pixels 00237 00238 if(ydouble[i]) { 00239 ysum[k] /= 2.; 00240 ysum[k+1] = ysum[k]; 00241 yd[k] = true; 00242 yd[k+1] = false; 00243 k=k+2; 00244 anyyd = true; 00245 } else { 00246 yd[k] = false; 00247 ++k; 00248 } 00249 if(k > BYM1) {break;} 00250 } 00251 00252 // Next, make x-projection of the cluster and copy the double pixel flags into an 11 element container 00253 00254 for(i=0; i<BXSIZE; ++i) { xsum[i] = 0.; xd[i] = false;} 00255 k=0; 00256 anyxd = false; 00257 for(j=0; j<nclusx; ++j) { 00258 for(i=0; i<nclusy; ++i) { 00259 xsum[k] += cluster[j][i]; 00260 } 00261 00262 // If this is a double pixel, put 1/2 of the charge in 2 consective single pixels 00263 00264 if(xdouble[j]) { 00265 xsum[k] /= 2.; 00266 xsum[k+1] = xsum[k]; 00267 xd[k]=true; 00268 xd[k+1]=false; 00269 k=k+2; 00270 anyxd = true; 00271 } else { 00272 xd[k]=false; 00273 ++k; 00274 } 00275 if(k > BXM1) {break;} 00276 } 00277 00278 // next, identify the y-cluster ends, count total pixels, nypix, and logical pixels, logypx 00279 00280 fypix=-1; 00281 nypix=0; 00282 lypix=0; 00283 logypx=0; 00284 for(i=0; i<BYSIZE; ++i) { 00285 if(ysum[i] > 0.) { 00286 if(fypix == -1) {fypix = i;} 00287 if(!yd[i]) { 00288 ysort[logypx] = ysum[i]; 00289 ++logypx; 00290 } 00291 ++nypix; 00292 lypix = i; 00293 } 00294 } 00295 00296 // dlengthy = (float)nypix - templ.clsleny(); 00297 00298 // Make sure cluster is continuous 00299 00300 if((lypix-fypix+1) != nypix || nypix == 0) { 00301 LOGDEBUG("SiPixelTemplateReco") << "y-length of pixel cluster doesn't agree with number of pixels above threshold" << ENDL; 00302 if (theVerboseLevel > 2) { 00303 LOGDEBUG("SiPixelTemplateReco") << "ysum[] = "; 00304 for(i=0; i<BYSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << ysum[i] << ", ";} 00305 LOGDEBUG("SiPixelTemplateReco") << ysum[BYSIZE-1] << ENDL; 00306 } 00307 00308 return 1; 00309 } 00310 00311 // If cluster is longer than max template size, technique fails 00312 00313 if(nypix > TYSIZE) { 00314 LOGDEBUG("SiPixelTemplateReco") << "y-length of pixel cluster is larger than maximum template size" << ENDL; 00315 if (theVerboseLevel > 2) { 00316 LOGDEBUG("SiPixelTemplateReco") << "ysum[] = "; 00317 for(i=0; i<BYSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << ysum[i] << ", ";} 00318 LOGDEBUG("SiPixelTemplateReco") << ysum[BYSIZE-1] << ENDL; 00319 } 00320 00321 return 6; 00322 } 00323 00324 // next, center the cluster on pixel 12 if necessary 00325 00326 midpix = (fypix+lypix)/2; 00327 shifty = BHY - midpix; 00328 if(shifty > 0) { 00329 for(i=lypix; i>=fypix; --i) { 00330 ysum[i+shifty] = ysum[i]; 00331 ysum[i] = 0.; 00332 yd[i+shifty] = yd[i]; 00333 yd[i] = false; 00334 } 00335 } else if (shifty < 0) { 00336 for(i=fypix; i<=lypix; ++i) { 00337 ysum[i+shifty] = ysum[i]; 00338 ysum[i] = 0.; 00339 yd[i+shifty] = yd[i]; 00340 yd[i] = false; 00341 } 00342 } 00343 lypix +=shifty; 00344 fypix +=shifty; 00345 00346 // If the cluster boundaries are OK, add pesudopixels, otherwise quit 00347 00348 if(fypix > 1 && fypix < BYM2) { 00349 ysum[fypix-1] = pseudopix; 00350 ysum[fypix-2] = pseudopix; 00351 } else {return 8;} 00352 if(lypix > 1 && lypix < BYM2) { 00353 ysum[lypix+1] = pseudopix; 00354 ysum[lypix+2] = pseudopix; 00355 } else {return 8;} 00356 00357 // finally, determine if pixel[0] is a double pixel and make an origin correction if it is 00358 00359 if(ydouble[0]) { 00360 originy = -0.5; 00361 } else { 00362 originy = 0.; 00363 } 00364 00365 // next, identify the x-cluster ends, count total pixels, nxpix, and logical pixels, logxpx 00366 00367 fxpix=-1; 00368 nxpix=0; 00369 lxpix=0; 00370 logxpx=0; 00371 for(i=0; i<BXSIZE; ++i) { 00372 if(xsum[i] > 0.) { 00373 if(fxpix == -1) {fxpix = i;} 00374 if(!xd[i]) { 00375 xsort[logxpx] = xsum[i]; 00376 ++logxpx; 00377 } 00378 ++nxpix; 00379 lxpix = i; 00380 } 00381 } 00382 00383 // dlengthx = (float)nxpix - templ.clslenx(); 00384 00385 // Make sure cluster is continuous 00386 00387 if((lxpix-fxpix+1) != nxpix) { 00388 00389 LOGDEBUG("SiPixelTemplateReco") << "x-length of pixel cluster doesn't agree with number of pixels above threshold" << ENDL; 00390 if (theVerboseLevel > 2) { 00391 LOGDEBUG("SiPixelTemplateReco") << "xsum[] = "; 00392 for(i=0; i<BXSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << xsum[i] << ", ";} 00393 LOGDEBUG("SiPixelTemplateReco") << ysum[BXSIZE-1] << ENDL; 00394 } 00395 00396 return 2; 00397 } 00398 00399 // If cluster is longer than max template size, technique fails 00400 00401 if(nxpix > TXSIZE) { 00402 00403 LOGDEBUG("SiPixelTemplateReco") << "x-length of pixel cluster is larger than maximum template size" << ENDL; 00404 if (theVerboseLevel > 2) { 00405 LOGDEBUG("SiPixelTemplateReco") << "xsum[] = "; 00406 for(i=0; i<BXSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << xsum[i] << ", ";} 00407 LOGDEBUG("SiPixelTemplateReco") << ysum[BXSIZE-1] << ENDL; 00408 } 00409 00410 return 7; 00411 } 00412 00413 // next, center the cluster on pixel 5 if necessary 00414 00415 midpix = (fxpix+lxpix)/2; 00416 shiftx = BHX - midpix; 00417 if(shiftx > 0) { 00418 for(i=lxpix; i>=fxpix; --i) { 00419 xsum[i+shiftx] = xsum[i]; 00420 xsum[i] = 0.; 00421 xd[i+shiftx] = xd[i]; 00422 xd[i] = false; 00423 } 00424 } else if (shiftx < 0) { 00425 for(i=fxpix; i<=lxpix; ++i) { 00426 xsum[i+shiftx] = xsum[i]; 00427 xsum[i] = 0.; 00428 xd[i+shiftx] = xd[i]; 00429 xd[i] = false; 00430 } 00431 } 00432 lxpix +=shiftx; 00433 fxpix +=shiftx; 00434 00435 // If the cluster boundaries are OK, add pesudopixels, otherwise quit 00436 00437 if(fxpix > 1 && fxpix < BXM2) { 00438 xsum[fxpix-1] = pseudopix; 00439 xsum[fxpix-2] = pseudopix; 00440 } else {return 9;} 00441 if(lxpix > 1 && lxpix < BXM2) { 00442 xsum[lxpix+1] = pseudopix; 00443 xsum[lxpix+2] = pseudopix; 00444 } else {return 9;} 00445 00446 // finally, determine if pixel[0] is a double pixel and make an origin correction if it is 00447 00448 if(xdouble[0]) { 00449 originx = -0.5; 00450 } else { 00451 originx = 0.; 00452 } 00453 00454 // uncertainty and final corrections depend upon total charge bin 00455 00456 fq = qtotal/templ.qavg(); 00457 if(fq > 1.5) { 00458 binq=0; 00459 } else { 00460 if(fq > 1.0) { 00461 binq=1; 00462 } else { 00463 if(fq > 0.85) { 00464 binq=2; 00465 } else { 00466 binq=3; 00467 } 00468 } 00469 } 00470 00471 // Return the charge bin via the parameter list unless the charge is too small (then flag it) 00472 00473 qbin = binq; 00474 if(!deadpix && qtotal < 0.95*templ.qmin()) {qbin = 4;} else {qbin = binq;} 00475 00476 if (theVerboseLevel > 9) { 00477 LOGDEBUG("SiPixelTemplateReco") << 00478 "ID = " << id << " FPix = " << fpix << 00479 " cot(alpha) = " << cotalpha << " cot(beta) = " << cotbeta << 00480 " nclusx = " << nclusx << " nclusy = " << nclusy << ENDL; 00481 } 00482 00483 00484 // Next, copy the y- and x-templates to local arrays 00485 00486 // First, decide on chi^2 min search parameters 00487 00488 assert(speed >= 0 && speed < 4); 00489 fybin = 0; lybin = 40; fxbin = 0; lxbin = 40; djy = 1; djx = 1; 00490 if(speed > 0) { 00491 fybin = 8; lybin = 32; 00492 if(yd[fypix]) {fybin = 4; lybin = 36;} 00493 if(lypix > fypix) { 00494 if(yd[lypix-1]) {fybin = 4; lybin = 36;} 00495 } 00496 fxbin = 8; lxbin = 32; 00497 if(xd[fxpix]) {fxbin = 4; lxbin = 36;} 00498 if(lxpix > fxpix) { 00499 if(xd[lxpix-1]) {fxbin = 4; lxbin = 36;} 00500 } 00501 } 00502 00503 if(speed > 1) { 00504 djy = 2; djx = 2; 00505 if(speed > 2) { 00506 if(!anyyd) {djy = 4;} 00507 if(!anyxd) {djx = 4;} 00508 } 00509 } 00510 00511 if (theVerboseLevel > 9) { 00512 LOGDEBUG("SiPixelTemplateReco") << 00513 "fypix " << fypix << " lypix = " << lypix << 00514 " fybin = " << fybin << " lybin = " << lybin << 00515 " djy = " << djy << " logypx = " << logypx << ENDL; 00516 LOGDEBUG("SiPixelTemplateReco") << 00517 "fxpix " << fxpix << " lxpix = " << lxpix << 00518 " fxbin = " << fxbin << " lxbin = " << lxbin << 00519 " djx = " << djx << " logxpx = " << logxpx << ENDL; 00520 } 00521 00522 // Now do the copies 00523 00524 templ.ytemp(fybin, lybin, ytemp); 00525 00526 templ.xtemp(fxbin, lxbin, xtemp); 00527 00528 // Do the y-reconstruction first 00529 00530 // Apply the first-pass template algorithm to all clusters 00531 00532 // Modify the template if double pixels are present 00533 00534 if(nypix > logypx) { 00535 i=fypix; 00536 while(i < lypix) { 00537 if(yd[i] && !yd[i+1]) { 00538 for(j=fybin; j<=lybin; ++j) { 00539 00540 // Sum the adjacent cells and put the average signal in both 00541 00542 sigavg = (ytemp[j][i] + ytemp[j][i+1])/2.; 00543 ytemp[j][i] = sigavg; 00544 ytemp[j][i+1] = sigavg; 00545 } 00546 i += 2; 00547 } else { 00548 ++i; 00549 } 00550 } 00551 } 00552 00553 // Define the maximum signal to allow before de-weighting a pixel 00554 00555 sythr = 1.1*(templ.symax()); 00556 00557 // Make sure that there will be at least two pixels that are not de-weighted 00558 00559 std::sort(&ysort[0], &ysort[logypx]); 00560 if(logypx == 1) {sythr = 1.01*ysort[0];} else { 00561 if (ysort[1] > sythr) { sythr = 1.01*ysort[1]; } 00562 } 00563 00564 // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis 00565 00566 for(i=0; i<BYSIZE; ++i) { ysig2[i] = 0.;} 00567 templ.ysigma2(fypix, lypix, sythr, ysum, ysig2); 00568 00569 // Find the template bin that minimizes the Chi^2 00570 00571 chi2ymin = 1.e15; 00572 for(i=fybin; i<=lybin; ++i) { chi2ybin[i] = -1.e15;} 00573 minbin = -1; 00574 deltaj = djy; 00575 jmin = fybin; 00576 jmax = lybin; 00577 while(deltaj > 0) { 00578 for(j=jmin; j<=jmax; j+=deltaj) { 00579 if(chi2ybin[j] < -100.) { 00580 ss2 = 0.; 00581 ssa = 0.; 00582 sa2 = 0.; 00583 for(i=fypix-2; i<=lypix+2; ++i) { 00584 ss2 += ysum[i]*ysum[i]/ysig2[i]; 00585 ssa += ysum[i]*ytemp[j][i]/ysig2[i]; 00586 sa2 += ytemp[j][i]*ytemp[j][i]/ysig2[i]; 00587 } 00588 rat=ssa/ss2; 00589 if(rat <= 0.) {LOGERROR("SiPixelTemplateReco") << "illegal chi2ymin normalization = " << rat << ENDL; rat = 1.;} 00590 chi2ybin[j]=ss2-2.*ssa/rat+sa2/(rat*rat); 00591 } 00592 if(chi2ybin[j] < chi2ymin) { 00593 chi2ymin = chi2ybin[j]; 00594 minbin = j; 00595 } 00596 } 00597 deltaj /= 2; 00598 if(minbin > fybin) {jmin = minbin - deltaj;} else {jmin = fybin;} 00599 if(minbin < lybin) {jmax = minbin + deltaj;} else {jmax = lybin;} 00600 } 00601 00602 if (theVerboseLevel > 9) { 00603 LOGDEBUG("SiPixelTemplateReco") << 00604 "minbin " << minbin << " chi2ymin = " << chi2ymin << ENDL; 00605 } 00606 00607 // Do not apply final template pass to 1-pixel clusters (use calibrated offset) 00608 00609 if(logypx == 1) { 00610 00611 if(nypix ==1) { 00612 delta = templ.dyone(); 00613 sigma = templ.syone(); 00614 } else { 00615 delta = templ.dytwo(); 00616 sigma = templ.sytwo(); 00617 } 00618 00619 yrec = 0.5*(fypix+lypix-2*shifty+2.*originy)*ysize-delta; 00620 00621 if(sigma <= 0.) { 00622 sigmay = 43.3; 00623 } else { 00624 sigmay = sigma; 00625 } 00626 00627 // Do probability calculation for one-pixel clusters 00628 00629 chi2ymin -=chi21min; 00630 if(chi2ymin < 0.) {chi2ymin = 0.;} 00631 // proby = gsl_cdf_chisq_Q(chi2ymin, mean1pix); 00632 hchi2 = chi2ymin/2.; hndof = mean1pix/2.; 00633 proby = 1. - TMath::Gamma(hndof, hchi2); 00634 00635 } else { 00636 00637 // For cluster > 1 pix, make the second, interpolating pass with the templates 00638 00639 binl = minbin - 1; 00640 binh = binl + 2; 00641 if(binl < fybin) { binl = fybin;} 00642 if(binh > lybin) { binh = lybin;} 00643 ss2 = 0.; 00644 ssa = 0.; 00645 sa2 = 0.; 00646 ssba = 0.; 00647 saba = 0.; 00648 sba2 = 0.; 00649 for(i=fypix-2; i<=lypix+2; ++i) { 00650 ss2 += ysum[i]*ysum[i]/ysig2[i]; 00651 ssa += ysum[i]*ytemp[binl][i]/ysig2[i]; 00652 sa2 += ytemp[binl][i]*ytemp[binl][i]/ysig2[i]; 00653 ssba += ysum[i]*(ytemp[binh][i] - ytemp[binl][i])/ysig2[i]; 00654 saba += ytemp[binl][i]*(ytemp[binh][i] - ytemp[binl][i])/ysig2[i]; 00655 sba2 += (ytemp[binh][i] - ytemp[binl][i])*(ytemp[binh][i] - ytemp[binl][i])/ysig2[i]; 00656 } 00657 00658 // rat is the fraction of the "distance" from template a to template b 00659 00660 rat=(ssba*ssa-ss2*saba)/(ss2*sba2-ssba*ssba); 00661 if(rat < 0.) {rat=0.;} 00662 if(rat > 1.) {rat=1.0;} 00663 rnorm = (ssa+rat*ssba)/ss2; 00664 00665 // Calculate the charges in the first and last pixels 00666 00667 qfy = ysum[fypix]; 00668 if(yd[fypix]) {qfy+=ysum[fypix+1];} 00669 if(logypx > 1) { 00670 qly=ysum[lypix]; 00671 if(yd[lypix-1]) {qly+=ysum[lypix-1];} 00672 } else { 00673 qly = qfy; 00674 } 00675 00676 // Now calculate the mean bias correction and uncertainties 00677 00678 float qyfrac = (qfy-qly)/(qfy+qly); 00679 bias = templ.yflcorr(binq,qyfrac)+templ.yavg(binq); 00680 00681 // uncertainty and final correction depend upon charge bin 00682 00683 yrec = (0.125*binl+BHY-2.5+rat*(binh-binl)*0.125-(float)shifty+originy)*ysize - bias; 00684 sigmay = templ.yrms(binq); 00685 00686 // Do goodness of fit test in y 00687 00688 if(rnorm <= 0.) {LOGERROR("SiPixelTemplateReco") << "illegal chi2y normalization = " << rnorm << ENDL; rnorm = 1.;} 00689 chi2y=ss2-2./rnorm*ssa-2./rnorm*rat*ssba+(sa2+2.*rat*saba+rat*rat*sba2)/(rnorm*rnorm)-templ.chi2ymin(binq); 00690 if(chi2y < 0.0) {chi2y = 0.0;} 00691 meany = templ.chi2yavg(binq); 00692 if(meany < 0.01) {meany = 0.01;} 00693 // gsl function that calculates the chi^2 tail prob for non-integral dof 00694 // proby = gsl_cdf_chisq_Q(chi2y, meany); 00695 // proby = ROOT::Math::chisquared_cdf_c(chi2y, meany); 00696 hchi2 = chi2y/2.; hndof = meany/2.; 00697 proby = 1. - TMath::Gamma(hndof, hchi2); 00698 } 00699 00700 // Do the x-reconstruction next 00701 00702 // Apply the first-pass template algorithm to all clusters 00703 00704 // Modify the template if double pixels are present 00705 00706 if(nxpix > logxpx) { 00707 i=fxpix; 00708 while(i < lxpix) { 00709 if(xd[i] && !xd[i+1]) { 00710 for(j=fxbin; j<=lxbin; ++j) { 00711 00712 // Sum the adjacent cells and put the average signal in both 00713 00714 sigavg = (xtemp[j][i] + xtemp[j][i+1])/2.; 00715 xtemp[j][i] = sigavg; 00716 xtemp[j][i+1] = sigavg; 00717 } 00718 i += 2; 00719 } else { 00720 ++i; 00721 } 00722 } 00723 } 00724 00725 // Define the maximum signal to allow before de-weighting a pixel 00726 00727 sxthr = 1.1*templ.sxmax(); 00728 00729 // Make sure that there will be at least two pixels that are not de-weighted 00730 std::sort(&xsort[0], &xsort[logxpx]); 00731 if(logxpx == 1) {sxthr = 1.01*xsort[0];} else { 00732 if (xsort[1] > sxthr) { sxthr = 1.01*xsort[1]; } 00733 } 00734 00735 // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis 00736 00737 for(i=0; i<BXSIZE; ++i) { xsig2[i] = 0.; } 00738 templ.xsigma2(fxpix, lxpix, sxthr, xsum, xsig2); 00739 00740 // Find the template bin that minimizes the Chi^2 00741 00742 chi2xmin = 1.e15; 00743 for(i=fxbin; i<=lxbin; ++i) { chi2xbin[i] = -1.e15;} 00744 minbin = -1; 00745 deltaj = djx; 00746 jmin = fxbin; 00747 jmax = lxbin; 00748 while(deltaj > 0) { 00749 for(j=jmin; j<=jmax; j+=deltaj) { 00750 if(chi2xbin[j] < -100.) { 00751 ss2 = 0.; 00752 ssa = 0.; 00753 sa2 = 0.; 00754 for(i=fxpix-2; i<=lxpix+2; ++i) { 00755 ss2 += xsum[i]*xsum[i]/xsig2[i]; 00756 ssa += xsum[i]*xtemp[j][i]/xsig2[i]; 00757 sa2 += xtemp[j][i]*xtemp[j][i]/xsig2[i]; 00758 } 00759 rat=ssa/ss2; 00760 if(rat <= 0.) {LOGERROR("SiPixelTemplateReco") << "illegal chi2ymin normalization = " << rat << ENDL; rat = 1.;} 00761 chi2xbin[j]=ss2-2.*ssa/rat+sa2/(rat*rat); 00762 } 00763 if(chi2xbin[j] < chi2xmin) { 00764 chi2xmin = chi2xbin[j]; 00765 minbin = j; 00766 } 00767 } 00768 deltaj /= 2; 00769 if(minbin > fxbin) {jmin = minbin - deltaj;} else {jmin = fxbin;} 00770 if(minbin < lxbin) {jmax = minbin + deltaj;} else {jmax = lxbin;} 00771 } 00772 00773 if (theVerboseLevel > 9) { 00774 LOGDEBUG("SiPixelTemplateReco") << 00775 "minbin " << minbin << " chi2xmin = " << chi2xmin << ENDL; 00776 } 00777 00778 // Do not apply final template pass to 1-pixel clusters (use calibrated offset) 00779 00780 if(logxpx == 1) { 00781 00782 if(nxpix ==1) { 00783 delta = templ.dxone(); 00784 sigma = templ.sxone(); 00785 } else { 00786 delta = templ.dxtwo(); 00787 sigma = templ.sxtwo(); 00788 } 00789 xrec = 0.5*(fxpix+lxpix-2*shiftx+2.*originx)*xsize-delta; 00790 if(sigma <= 0.) { 00791 sigmax = 28.9; 00792 } else { 00793 sigmax = sigma; 00794 } 00795 00796 // Do probability calculation for one-pixel clusters 00797 00798 chi2xmin -=chi21min; 00799 if(chi2xmin < 0.) {chi2xmin = 0.;} 00800 // probx = gsl_cdf_chisq_Q(chi2xmin, mean1pix); 00801 hchi2 = chi2xmin/2.; hndof = mean1pix/2.; 00802 probx = 1. - TMath::Gamma(hndof, hchi2); 00803 00804 } else { 00805 00806 // Now make the second, interpolating pass with the templates 00807 00808 binl = minbin - 1; 00809 binh = binl + 2; 00810 if(binl < fxbin) { binl = fxbin;} 00811 if(binh > lxbin) { binh = lxbin;} 00812 ss2 = 0.; 00813 ssa = 0.; 00814 sa2 = 0.; 00815 ssba = 0.; 00816 saba = 0.; 00817 sba2 = 0.; 00818 for(i=fxpix-2; i<=lxpix+2; ++i) { 00819 ss2 += xsum[i]*xsum[i]/xsig2[i]; 00820 ssa += xsum[i]*xtemp[binl][i]/xsig2[i]; 00821 sa2 += xtemp[binl][i]*xtemp[binl][i]/xsig2[i]; 00822 ssba += xsum[i]*(xtemp[binh][i] - xtemp[binl][i])/xsig2[i]; 00823 saba += xtemp[binl][i]*(xtemp[binh][i] - xtemp[binl][i])/xsig2[i]; 00824 sba2 += (xtemp[binh][i] - xtemp[binl][i])*(xtemp[binh][i] - xtemp[binl][i])/xsig2[i]; 00825 } 00826 00827 // rat is the fraction of the "distance" from template a to template b 00828 00829 rat=(ssba*ssa-ss2*saba)/(ss2*sba2-ssba*ssba); 00830 if(rat < 0.) {rat=0.;} 00831 if(rat > 1.) {rat=1.0;} 00832 rnorm = (ssa+rat*ssba)/ss2; 00833 00834 // Calculate the charges in the first and last pixels 00835 00836 qfx = xsum[fxpix]; 00837 if(xd[fxpix]) {qfx+=xsum[fxpix+1];} 00838 if(logxpx > 1) { 00839 qlx=xsum[lxpix]; 00840 if(xd[lxpix-1]) {qlx+=xsum[lxpix-1];} 00841 } else { 00842 qlx = qfx; 00843 } 00844 00845 // Now calculate the mean bias correction and uncertainties 00846 00847 float qxfrac = (qfx-qlx)/(qfx+qlx); 00848 bias = templ.xflcorr(binq,qxfrac)+templ.xavg(binq); 00849 00850 // uncertainty and final correction depend upon charge bin 00851 00852 xrec = (0.125*binl+BHX-2.5+rat*(binh-binl)*0.125-(float)shiftx+originx)*xsize - bias; 00853 sigmax = templ.xrms(binq); 00854 00855 // Do goodness of fit test in x 00856 00857 if(rnorm <= 0.) {LOGERROR("SiPixelTemplateReco") << "illegal chi2x normalization = " << rnorm << ENDL; rnorm = 1.;} 00858 chi2x=ss2-2./rnorm*ssa-2./rnorm*rat*ssba+(sa2+2.*rat*saba+rat*rat*sba2)/(rnorm*rnorm)-templ.chi2xmin(binq); 00859 if(chi2x < 0.0) {chi2x = 0.0;} 00860 meanx = templ.chi2xavg(binq); 00861 if(meanx < 0.01) {meanx = 0.01;} 00862 // gsl function that calculates the chi^2 tail prob for non-integral dof 00863 // probx = gsl_cdf_chisq_Q(chi2x, meanx); 00864 // probx = ROOT::Math::chisquared_cdf_c(chi2x, meanx, trx0); 00865 hchi2 = chi2x/2.; hndof = meanx/2.; 00866 probx = 1. - TMath::Gamma(hndof, hchi2); 00867 } 00868 00869 return 0;
int SiPixelTemplateReco::PixelTempSplit | ( | int | id, | |
bool | fpix, | |||
float | cotalpha, | |||
float | cotbeta, | |||
array_2d | cluster, | |||
std::vector< bool > | ydouble, | |||
std::vector< bool > | xdouble, | |||
SiPixelTemplate & | templ, | |||
float & | yrec1, | |||
float & | yrec2, | |||
float & | sigmay, | |||
float & | proby, | |||
float & | xrec1, | |||
float & | xrec2, | |||
float & | sigmax, | |||
float & | probx, | |||
int & | qbin | |||
) |
Reconstruct the best estimate of the hit positions for pixel clusters.
id | - (input) identifier of the template to use | |
fpix | - (input) logical input indicating whether to use FPix templates (true) or Barrel templates (false) | |
cotalpha | - (input) the cotangent of the alpha track angle (see CMS IN 2004/014) | |
cotbeta | - (input) the cotangent of the beta track angle (see CMS IN 2004/014) | |
cluster | - (input) boost multi_array container of 7x21 array of pixel signals, origin of local coords (0,0) at center of pixel cluster[0][0]. | |
ydouble | - (input) STL vector of 21 element array to flag a double-pixel | |
xdouble | - (input) STL vector of 7 element array to flag a double-pixel | |
templ | - (input) the template used in the reconstruction | |
yrec1 | - (output) best estimate of first y-coordinate of hit in microns | |
yrec2 | - (output) best estimate of second y-coordinate of hit in microns | |
sigmay | - (output) best estimate of uncertainty on yrec in microns | |
proby | - (output) probability describing goodness-of-fit for y-reco | |
xrec1 | - (output) best estimate of first x-coordinate of hit in microns | |
xrec2 | - (output) best estimate of second x-coordinate of hit in microns | |
sigmax | - (output) best estimate of uncertainty on xrec in microns | |
probx | - (output) probability describing goodness-of-fit for x-reco | |
qbin | - (output) index (0-4) describing the charge of the cluster [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] |
Definition at line 787 of file SiPixelTemplateSplit.cc.
References PixelTempSplit().
Referenced by PixelCPETemplateReco::localPosition().
00793 { 00794 // Local variables 00795 const bool deadpix = false; 00796 std::vector<std::pair<int, int> > zeropix; 00797 00798 return SiPixelTemplateReco::PixelTempSplit(id, fpix, cotalpha, cotbeta, cluster, ydouble, xdouble, templ, 00799 yrec1, yrec2, sigmay, proby, xrec1, xrec2, sigmax, probx, qbin, deadpix, zeropix); 00800
int SiPixelTemplateReco::PixelTempSplit | ( | int | id, | |
bool | fpix, | |||
float | cotalpha, | |||
float | cotbeta, | |||
array_2d | cluster, | |||
std::vector< bool > | ydouble, | |||
std::vector< bool > | xdouble, | |||
SiPixelTemplate & | templ, | |||
float & | yrec1, | |||
float & | yrec2, | |||
float & | sigmay, | |||
float & | proby, | |||
float & | xrec1, | |||
float & | xrec2, | |||
float & | sigmax, | |||
float & | probx, | |||
int & | qbin, | |||
bool | deadpix, | |||
std::vector< std::pair< int, int > > | zeropix | |||
) |
Reconstruct the best estimate of the hit positions for pixel clusters.
id | - (input) identifier of the template to use | |
fpix | - (input) logical input indicating whether to use FPix templates (true) or Barrel templates (false) | |
cotalpha | - (input) the cotangent of the alpha track angle (see CMS IN 2004/014) | |
cotbeta | - (input) the cotangent of the beta track angle (see CMS IN 2004/014) | |
cluster | - (input) boost multi_array container of 7x21 array of pixel signals, origin of local coords (0,0) at center of pixel cluster[0][0]. | |
ydouble | - (input) STL vector of 21 element array to flag a double-pixel | |
xdouble | - (input) STL vector of 7 element array to flag a double-pixel | |
templ | - (input) the template used in the reconstruction | |
yrec1 | - (output) best estimate of first y-coordinate of hit in microns | |
yrec2 | - (output) best estimate of second y-coordinate of hit in microns | |
sigmay | - (output) best estimate of uncertainty on yrec in microns | |
proby | - (output) probability describing goodness-of-fit for y-reco | |
xrec1 | - (output) best estimate of first x-coordinate of hit in microns | |
xrec2 | - (output) best estimate of second x-coordinate of hit in microns | |
sigmax | - (output) best estimate of uncertainty on xrec in microns | |
probx | - (output) probability describing goodness-of-fit for x-reco | |
qbin | - (output) index (0-4) describing the charge of the cluster [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] | |
deadpix | - (input) bool to indicate that there are dead pixels to be included in the analysis | |
zeropix | - (input) vector of index pairs pointing to the dead pixels |
Definition at line 68 of file SiPixelTemplateSplit.cc.
References BHX, BHY, bias, BXM1, BXM2, BXSIZE, BYM1, BYM2, BYM3, BYSIZE, SiPixelTemplate::chi2xavg(), SiPixelTemplate::chi2yavg(), SiPixelTemplate::dxone(), SiPixelTemplate::dxtwo(), SiPixelTemplate::dyone(), SiPixelTemplate::dytwo(), ENDL, err, i, SiPixelTemplate::interpolate(), j, k, LOGDEBUG, LOGERROR, max, min, SiPixelTemplate::pixmax(), SiPixelTemplate::qavg(), SiPixelTemplate::qmin(), SiPixelTemplate::qscale(), SiPixelTemplate::s50(), python::multivaluedict::sort(), SiPixelTemplate::sxmax(), SiPixelTemplate::sxone(), SiPixelTemplate::sxtwo(), SiPixelTemplate::symax(), SiPixelTemplate::syone(), SiPixelTemplate::sytwo(), theVerboseLevel, TXSIZE, TYSIZE, SiPixelTemplate::xavgc2m(), SiPixelTemplate::xrmsc2m(), SiPixelTemplate::xsigma2(), SiPixelTemplate::xtemp3d(), SiPixelTemplate::yavgc2m(), SiPixelTemplate::yrmsc2m(), SiPixelTemplate::ysigma2(), and SiPixelTemplate::ytemp3d().
Referenced by PixelTempSplit().
00075 { 00076 // Local variables 00077 static int i, j, k, minbin, binl, binh, binq, midpix, fypix, nypix, lypix, logypx; 00078 static int fxpix, nxpix, lxpix, logxpx, shifty, shiftx, nyzero[TYSIZE]; 00079 static unsigned int nclusx, nclusy; 00080 static int nybin, ycbin, nxbin, xcbin, minbinj, minbink; 00081 static float sythr, sxthr, rnorm, delta, sigma, sigavg, pseudopix, qscale; 00082 static float ss2, ssa, sa2, ssba, saba, sba2, rat, fq, qtotal, qpixel; 00083 static float originx, originy, qfy, qly, qfx, qlx, bias, err, maxpix, minmax; 00084 static double chi2x, meanx, chi2y, meany, chi2ymin, chi2xmin, chi2; 00085 static double hchi2, hndof; 00086 static float ysum[BYSIZE], xsum[BXSIZE], ysort[BYSIZE], xsort[BXSIZE]; 00087 static float ysig2[BYSIZE], xsig2[BXSIZE]; 00088 static bool yd[BYSIZE], xd[BXSIZE], anyyd, anyxd; 00089 const float ysize={150.}, xsize={100.}, sqrt2={2.}; 00090 // const float sqrt2={1.41421356}; 00091 00092 // The minimum chi2 for a valid one pixel cluster = pseudopixel contribution only 00093 00094 const double mean1pix={0.100}, chi21min={0.160}; 00095 00096 // First, interpolate the template needed to analyze this cluster 00097 // check to see of the track direction is in the physical range of the loaded template 00098 00099 if(!templ.interpolate(id, fpix, cotalpha, cotbeta)) { 00100 LOGDEBUG("SiPixelTemplateReco") << "input cluster direction cot(alpha) = " << cotalpha << ", cot(beta) = " << cotbeta << " is not within the acceptance of fpix = " 00101 << fpix << ", template ID = " << id << ", no reconstruction performed" << ENDL; 00102 return 20; 00103 } 00104 00105 // Define size of pseudopixel 00106 00107 pseudopix = templ.s50(); 00108 00109 // Get charge scaling factor 00110 00111 qscale = templ.qscale(); 00112 00113 // Check that the cluster container is (up to) a 7x21 matrix and matches the dimensions of the double pixel flags 00114 00115 if(cluster.num_dimensions() != 2) { 00116 LOGERROR("SiPixelTemplateReco") << "input cluster container (BOOST Multiarray) has wrong number of dimensions" << ENDL; 00117 return 3; 00118 } 00119 nclusx = cluster.size(); 00120 nclusy = cluster.num_elements()/nclusx; 00121 if(nclusx != xdouble.size()) { 00122 LOGERROR("SiPixelTemplateReco") << "input cluster container x-size is not equal to double pixel flag container size" << ENDL; 00123 return 4; 00124 } 00125 if(nclusy != ydouble.size()) { 00126 LOGERROR("SiPixelTemplateReco") << "input cluster container y-size is not equal to double pixel flag container size" << ENDL; 00127 return 5; 00128 } 00129 00130 // enforce maximum size 00131 00132 if(nclusx > TXSIZE) {nclusx = TXSIZE;} 00133 if(nclusy > TYSIZE) {nclusy = TYSIZE;} 00134 00135 // First, rescale all pixel charges 00136 00137 for(i=0; i<nclusy; ++i) { 00138 for(j=0; j<nclusx; ++j) { 00139 if(cluster[j][i] > 0) {cluster[j][i] *= qscale;} 00140 } 00141 } 00142 00143 // Next, sum the total charge and "decapitate" big pixels 00144 00145 qtotal = 0.; 00146 minmax = 2.*templ.pixmax(); 00147 for(i=0; i<nclusy; ++i) { 00148 maxpix = minmax; 00149 if(ydouble[i]) {maxpix *=2.;} 00150 for(j=0; j<nclusx; ++j) { 00151 qtotal += cluster[j][i]; 00152 if(cluster[j][i] > maxpix) {cluster[j][i] = maxpix;} 00153 } 00154 } 00155 00156 // Do the cluster repair here 00157 00158 if(deadpix) { 00159 fypix = BYM3; lypix = -1; 00160 for(i=0; i<nclusy; ++i) { 00161 ysum[i] = 0.; nyzero[i] = 0; 00162 // Do preliminary cluster projection in y 00163 for(j=0; j<nclusx; ++j) { 00164 ysum[i] += cluster[j][i]; 00165 } 00166 if(ysum[i] > 0.) { 00167 // identify ends of cluster to determine what the missing charge should be 00168 if(i < fypix) {fypix = i;} 00169 if(i > lypix) {lypix = i;} 00170 } 00171 } 00172 00173 // Now loop over dead pixel list and "fix" everything 00174 00175 //First see if the cluster ends are redefined and that we have only one dead pixel per column 00176 00177 std::vector<std::pair<int, int> >::const_iterator zeroIter = zeropix.begin(), zeroEnd = zeropix.end(); 00178 for ( ; zeroIter != zeroEnd; ++zeroIter ) { 00179 i = zeroIter->second; 00180 if(i<0 || i>TYSIZE-1) {LOGERROR("SiPixelTemplateReco") << "dead pixel column y-index " << i << ", no reconstruction performed" << ENDL; 00181 return 11;} 00182 00183 // count the number of dead pixels in each column 00184 ++nyzero[i]; 00185 // allow them to redefine the cluster ends 00186 if(i < fypix) {fypix = i;} 00187 if(i > lypix) {lypix = i;} 00188 } 00189 00190 nypix = lypix-fypix+1; 00191 00192 // Now adjust the charge in the dead pixels to sum to 0.5*truncation value in the end columns and the truncation value in the interior columns 00193 00194 for (zeroIter = zeropix.begin(); zeroIter != zeroEnd; ++zeroIter ) { 00195 i = zeroIter->second; j = zeroIter->first; 00196 if(j<0 || j>TXSIZE-1) {LOGERROR("SiPixelTemplateReco") << "dead pixel column x-index " << j << ", no reconstruction performed" << ENDL; 00197 return 12;} 00198 if((i == fypix || i == lypix) && nypix > 1) {maxpix = templ.symax()/2.;} else {maxpix = templ.symax();} 00199 if(ydouble[i]) {maxpix *=2.;} 00200 if(nyzero[i] > 0 && nyzero[i] < 3) {qpixel = (maxpix - ysum[i])/(float)nyzero[i];} else {qpixel = 1.;} 00201 if(qpixel < 1.) {qpixel = 1.;} 00202 cluster[j][i] = qpixel; 00203 // Adjust the total cluster charge to reflect the charge of the "repaired" cluster 00204 qtotal += qpixel; 00205 } 00206 // End of cluster repair section 00207 } 00208 00209 // Next, make y-projection of the cluster and copy the double pixel flags into a 25 element container 00210 00211 for(i=0; i<BYSIZE; ++i) { ysum[i] = 0.; yd[i] = false;} 00212 k=0; 00213 anyyd = false; 00214 for(i=0; i<nclusy; ++i) { 00215 for(j=0; j<nclusx; ++j) { 00216 ysum[k] += cluster[j][i]; 00217 } 00218 00219 // If this is a double pixel, put 1/2 of the charge in 2 consective single pixels 00220 00221 if(ydouble[i]) { 00222 ysum[k] /= 2.; 00223 ysum[k+1] = ysum[k]; 00224 yd[k] = true; 00225 yd[k+1] = false; 00226 k=k+2; 00227 anyyd = true; 00228 } else { 00229 yd[k] = false; 00230 ++k; 00231 } 00232 if(k > BYM1) {break;} 00233 } 00234 00235 // Next, make x-projection of the cluster and copy the double pixel flags into an 11 element container 00236 00237 for(i=0; i<BXSIZE; ++i) { xsum[i] = 0.; xd[i] = false;} 00238 k=0; 00239 anyxd = false; 00240 for(j=0; j<nclusx; ++j) { 00241 for(i=0; i<nclusy; ++i) { 00242 xsum[k] += cluster[j][i]; 00243 } 00244 00245 // If this is a double pixel, put 1/2 of the charge in 2 consective single pixels 00246 00247 if(xdouble[j]) { 00248 xsum[k] /= 2.; 00249 xsum[k+1] = xsum[k]; 00250 xd[k]=true; 00251 xd[k+1]=false; 00252 k=k+2; 00253 anyxd = true; 00254 } else { 00255 xd[k]=false; 00256 ++k; 00257 } 00258 if(k > BXM1) {break;} 00259 } 00260 00261 // next, identify the y-cluster ends, count total pixels, nypix, and logical pixels, logypx 00262 00263 fypix=-1; 00264 nypix=0; 00265 lypix=0; 00266 logypx=0; 00267 for(i=0; i<BYSIZE; ++i) { 00268 if(ysum[i] > 0.) { 00269 if(fypix == -1) {fypix = i;} 00270 if(!yd[i]) { 00271 ysort[logypx] = ysum[i]; 00272 ++logypx; 00273 } 00274 ++nypix; 00275 lypix = i; 00276 } 00277 } 00278 00279 // Make sure cluster is continuous 00280 00281 if((lypix-fypix+1) != nypix || nypix == 0) { 00282 LOGDEBUG("SiPixelTemplateReco") << "y-length of pixel cluster doesn't agree with number of pixels above threshold" << ENDL; 00283 if (theVerboseLevel > 2) { 00284 LOGDEBUG("SiPixelTemplateReco") << "ysum[] = "; 00285 for(i=0; i<BYSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << ysum[i] << ", ";} 00286 LOGDEBUG("SiPixelTemplateReco") << ysum[BYSIZE-1] << ENDL; 00287 } 00288 00289 return 1; 00290 } 00291 00292 // If cluster is longer than max template size, technique fails 00293 00294 if(nypix > TYSIZE) { 00295 LOGDEBUG("SiPixelTemplateReco") << "y-length of pixel cluster is larger than maximum template size" << ENDL; 00296 if (theVerboseLevel > 2) { 00297 LOGDEBUG("SiPixelTemplateReco") << "ysum[] = "; 00298 for(i=0; i<BYSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << ysum[i] << ", ";} 00299 LOGDEBUG("SiPixelTemplateReco") << ysum[BYSIZE-1] << ENDL; 00300 } 00301 00302 return 6; 00303 } 00304 00305 // next, center the cluster on pixel 12 if necessary 00306 00307 midpix = (fypix+lypix)/2; 00308 shifty = BHY - midpix; 00309 if(shifty > 0) { 00310 for(i=lypix; i>=fypix; --i) { 00311 ysum[i+shifty] = ysum[i]; 00312 ysum[i] = 0.; 00313 yd[i+shifty] = yd[i]; 00314 yd[i] = false; 00315 } 00316 } else if (shifty < 0) { 00317 for(i=fypix; i<=lypix; ++i) { 00318 ysum[i+shifty] = ysum[i]; 00319 ysum[i] = 0.; 00320 yd[i+shifty] = yd[i]; 00321 yd[i] = false; 00322 } 00323 } 00324 lypix +=shifty; 00325 fypix +=shifty; 00326 00327 // If the cluster boundaries are OK, add pesudopixels, otherwise quit 00328 00329 if(fypix > 1 && fypix < BYM2) { 00330 ysum[fypix-1] = pseudopix; 00331 ysum[fypix-2] = 0.2*pseudopix; 00332 } else {return 8;} 00333 if(lypix > 1 && lypix < BYM2) { 00334 ysum[lypix+1] = pseudopix; 00335 ysum[lypix+2] = 0.2*pseudopix; 00336 } else {return 8;} 00337 00338 // finally, determine if pixel[0] is a double pixel and make an origin correction if it is 00339 00340 if(ydouble[0]) { 00341 originy = -0.5; 00342 } else { 00343 originy = 0.; 00344 } 00345 00346 // next, identify the x-cluster ends, count total pixels, nxpix, and logical pixels, logxpx 00347 00348 fxpix=-1; 00349 nxpix=0; 00350 lxpix=0; 00351 logxpx=0; 00352 for(i=0; i<BXSIZE; ++i) { 00353 if(xsum[i] > 0.) { 00354 if(fxpix == -1) {fxpix = i;} 00355 if(!xd[i]) { 00356 xsort[logxpx] = xsum[i]; 00357 ++logxpx; 00358 } 00359 ++nxpix; 00360 lxpix = i; 00361 } 00362 } 00363 00364 // Make sure cluster is continuous 00365 00366 if((lxpix-fxpix+1) != nxpix) { 00367 00368 LOGDEBUG("SiPixelTemplateReco") << "x-length of pixel cluster doesn't agree with number of pixels above threshold" << ENDL; 00369 if (theVerboseLevel > 2) { 00370 LOGDEBUG("SiPixelTemplateReco") << "xsum[] = "; 00371 for(i=0; i<BXSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << xsum[i] << ", ";} 00372 LOGDEBUG("SiPixelTemplateReco") << ysum[BXSIZE-1] << ENDL; 00373 } 00374 00375 return 2; 00376 } 00377 00378 // If cluster is longer than max template size, technique fails 00379 00380 if(nxpix > TXSIZE) { 00381 00382 LOGDEBUG("SiPixelTemplateReco") << "x-length of pixel cluster is larger than maximum template size" << ENDL; 00383 if (theVerboseLevel > 2) { 00384 LOGDEBUG("SiPixelTemplateReco") << "xsum[] = "; 00385 for(i=0; i<BXSIZE-1; ++i) {LOGDEBUG("SiPixelTemplateReco") << xsum[i] << ", ";} 00386 LOGDEBUG("SiPixelTemplateReco") << ysum[BXSIZE-1] << ENDL; 00387 } 00388 00389 return 7; 00390 } 00391 00392 // next, center the cluster on pixel 5 if necessary 00393 00394 midpix = (fxpix+lxpix)/2; 00395 shiftx = BHX - midpix; 00396 if(shiftx > 0) { 00397 for(i=lxpix; i>=fxpix; --i) { 00398 xsum[i+shiftx] = xsum[i]; 00399 xsum[i] = 0.; 00400 xd[i+shiftx] = xd[i]; 00401 xd[i] = false; 00402 } 00403 } else if (shiftx < 0) { 00404 for(i=fxpix; i<=lxpix; ++i) { 00405 xsum[i+shiftx] = xsum[i]; 00406 xsum[i] = 0.; 00407 xd[i+shiftx] = xd[i]; 00408 xd[i] = false; 00409 } 00410 } 00411 lxpix +=shiftx; 00412 fxpix +=shiftx; 00413 00414 // If the cluster boundaries are OK, add pesudopixels, otherwise quit 00415 00416 if(fxpix > 1 && fxpix <BXM2) { 00417 xsum[fxpix-1] = pseudopix; 00418 xsum[fxpix-2] = 0.2*pseudopix; 00419 } else {return 9;} 00420 if(lxpix > 1 && lxpix < BXM2) { 00421 xsum[lxpix+1] = pseudopix; 00422 xsum[lxpix+2] = 0.2*pseudopix; 00423 } else {return 9;} 00424 00425 // finally, determine if pixel[0] is a double pixel and make an origin correction if it is 00426 00427 if(xdouble[0]) { 00428 originx = -0.5; 00429 } else { 00430 originx = 0.; 00431 } 00432 00433 // uncertainty and final corrections depend upon total charge bin 00434 00435 fq = qtotal/templ.qavg(); 00436 if(fq > 3.0) { 00437 binq=0; 00438 } else { 00439 if(fq > 2.0) { 00440 binq=1; 00441 } else { 00442 if(fq > 1.70) { 00443 binq=2; 00444 } else { 00445 binq=3; 00446 } 00447 } 00448 } 00449 00450 // Return the charge bin via the parameter list unless the charge is too small (then flag it) 00451 00452 qbin = binq; 00453 if(!deadpix && qtotal < 0.95*templ.qmin()) {qbin = 4;} 00454 00455 if (theVerboseLevel > 9) { 00456 LOGDEBUG("SiPixelTemplateReco") << 00457 "ID = " << id << " FPix = " << fpix << 00458 " cot(alpha) = " << cotalpha << " cot(beta) = " << cotbeta << 00459 " nclusx = " << nclusx << " nclusy = " << nclusy << ENDL; 00460 } 00461 00462 00463 // Next, generate the 3d y- and x-templates 00464 00465 array_3d ytemp; 00466 templ.ytemp3d(nypix, ytemp); 00467 00468 array_3d xtemp; 00469 templ.xtemp3d(nxpix, xtemp); 00470 00471 // Do the y-reconstruction first 00472 00473 // retrieve the number of y-bins 00474 00475 nybin = ytemp.shape()[0]; ycbin = nybin/2; 00476 00477 // Modify the template if double pixels are present 00478 00479 if(nypix > logypx) { 00480 i=fypix; 00481 while(i < lypix) { 00482 if(yd[i] && !yd[i+1]) { 00483 for(j=0; j<nybin; ++j) { 00484 for(k=0; k<=j; ++k) { 00485 00486 // Sum the adjacent cells and put the average signal in both 00487 00488 sigavg = (ytemp[j][k][i] + ytemp[j][k][i+1])/2.; 00489 ytemp[j][k][i] = sigavg; 00490 ytemp[j][k][i+1] = sigavg; 00491 } 00492 } 00493 i += 2; 00494 } else { 00495 ++i; 00496 } 00497 } 00498 } 00499 00500 // Define the maximum signal to allow before de-weighting a pixel 00501 00502 sythr = 2.1*(templ.symax()); 00503 00504 // Make sure that there will be at least two pixels that are not de-weighted 00505 00506 std::sort(&ysort[0], &ysort[logypx]); 00507 if(logypx == 1) {sythr = 1.01*ysort[0];} else { 00508 if (ysort[1] > sythr) { sythr = 1.01*ysort[1]; } 00509 } 00510 00511 // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis 00512 00513 for(i=0; i<BYSIZE; ++i) { ysig2[i] = 0.;} 00514 templ.ysigma2(fypix, lypix, sythr, ysum, ysig2); 00515 00516 // Find the template bin that minimizes the Chi^2 00517 00518 chi2ymin = 1.e15; 00519 minbinj = -1; 00520 minbink = -1; 00521 for(j=0; j<nybin; ++j) { 00522 for(k=0; k<=j; ++k) { 00523 ss2 = 0.; 00524 ssa = 0.; 00525 sa2 = 0.; 00526 for(i=fypix-2; i<=lypix+2; ++i) { 00527 ss2 += ysum[i]*ysum[i]/ysig2[i]; 00528 ssa += ysum[i]*ytemp[j][k][i]/ysig2[i]; 00529 sa2 += ytemp[j][k][i]*ytemp[j][k][i]/ysig2[i]; 00530 } 00531 rat=ssa/ss2; 00532 if(rat <= 0.) {LOGERROR("SiPixelTemplateReco") << "illegal chi2ymin normalization = " << rat << ENDL; rat = 1.;} 00533 chi2y=ss2-2.*ssa/rat+sa2/(rat*rat); 00534 if(chi2y < chi2ymin) { 00535 chi2ymin = chi2y; 00536 minbinj = j; 00537 minbink = k; 00538 } 00539 } 00540 } 00541 00542 if (theVerboseLevel > 9) { 00543 LOGDEBUG("SiPixelTemplateReco") << 00544 "minbins " << minbinj << "," << minbink << " chi2ymin = " << chi2ymin << ENDL; 00545 } 00546 00547 // Do not apply final template pass to 1-pixel clusters (use calibrated offset) 00548 00549 if(logypx == 1) { 00550 00551 if(nypix ==1) { 00552 delta = templ.dyone(); 00553 sigma = templ.syone(); 00554 } else { 00555 delta = templ.dytwo(); 00556 sigma = templ.sytwo(); 00557 } 00558 00559 yrec1 = 0.5*(fypix+lypix-2*shifty+2.*originy)*ysize-delta; 00560 yrec2 = yrec1; 00561 00562 if(sigma <= 0.) { 00563 sigmay = 43.3; 00564 } else { 00565 sigmay = sigma; 00566 } 00567 00568 // Do probability calculation for one-pixel clusters 00569 00570 chi2ymin -=chi21min; 00571 if(chi2ymin < 0.) {chi2ymin = 0.;} 00572 // proby = gsl_cdf_chisq_Q(chi2ymin, mean1pix); 00573 hchi2 = chi2ymin/2.; hndof = mean1pix/2.; 00574 proby = 1. - TMath::Gamma(hndof, hchi2); 00575 00576 } else { 00577 00578 // For cluster > 1 pix, use chi^2 minimm to recontruct the two y-positions 00579 00580 // at small eta, the templates won't actually work on two pixel y-clusters so just return the pixel centers 00581 00582 if(logypx == 2 && fabsf(cotbeta) < 0.25) { 00583 switch(nypix) { 00584 case 2: 00585 // Both pixels are small 00586 yrec1 = (fypix-shifty+originy)*ysize; 00587 yrec2 = (lypix-shifty+originy)*ysize; 00588 sigmay = 43.3; 00589 break; 00590 case 3: 00591 // One big pixel and one small pixel 00592 if(yd[fypix]) { 00593 yrec1 = (fypix+0.5-shifty+originy)*ysize; 00594 yrec2 = (lypix-shifty+originy)*ysize; 00595 sigmay = 43.3; 00596 } else { 00597 yrec1 = (fypix-shifty+originy)*ysize; 00598 yrec2 = (lypix-0.5-shifty+originy)*ysize; 00599 sigmay = 65.; 00600 } 00601 break; 00602 case 4: 00603 // Two big pixels 00604 yrec1 = (fypix+0.5-shifty+originy)*ysize; 00605 yrec2 = (lypix-0.5-shifty+originy)*ysize; 00606 sigmay = 86.6; 00607 break; 00608 default: 00609 // Something is screwy ... 00610 LOGERROR("SiPixelTemplateReco") << "weird problem: logical y-pixels = " << logypx << ", total ysize in normal pixels = " << nypix << ENDL; 00611 return 10; 00612 } 00613 } else { 00614 00615 // uncertainty and final correction depend upon charge bin 00616 00617 bias = templ.yavgc2m(binq); 00618 yrec1 = (0.125*(minbink-ycbin)+BHY-(float)shifty+originy)*ysize - bias; 00619 yrec2 = (0.125*(minbinj-ycbin)+BHY-(float)shifty+originy)*ysize - bias; 00620 sigmay = sqrt2*templ.yrmsc2m(binq); 00621 00622 } 00623 00624 // Do goodness of fit test in y 00625 00626 if(chi2ymin < 0.0) {chi2ymin = 0.0;} 00627 meany = 2.*templ.chi2yavg(binq); 00628 if(meany < 0.01) {meany = 0.01;} 00629 // gsl function that calculates the chi^2 tail prob for non-integral dof 00630 // proby = gsl_cdf_chisq_Q(chi2y, meany); 00631 // proby = ROOT::Math::chisquared_cdf_c(chi2y, meany); 00632 hchi2 = chi2ymin/2.; hndof = meany/2.; 00633 proby = 1. - TMath::Gamma(hndof, hchi2); 00634 } 00635 00636 // Do the x-reconstruction next 00637 00638 // retrieve the number of x-bins 00639 00640 nxbin = xtemp.shape()[0]; xcbin = nxbin/2; 00641 00642 // Modify the template if double pixels are present 00643 00644 if(nxpix > logxpx) { 00645 i=fxpix; 00646 while(i < lxpix) { 00647 if(xd[i] && !xd[i+1]) { 00648 for(j=0; j<nxbin; ++j) { 00649 for(k=0; k<=j; ++k) { 00650 00651 // Sum the adjacent cells and put the average signal in both 00652 00653 sigavg = (xtemp[j][k][i] + xtemp[j][k][i+1])/2.; 00654 xtemp[j][k][i] = sigavg; 00655 xtemp[j][k][i+1] = sigavg; 00656 } 00657 } 00658 i += 2; 00659 } else { 00660 ++i; 00661 } 00662 } 00663 } 00664 00665 // Define the maximum signal to allow before de-weighting a pixel 00666 00667 sxthr = 2.1*templ.sxmax(); 00668 00669 // Make sure that there will be at least two pixels that are not de-weighted 00670 std::sort(&xsort[0], &xsort[logxpx]); 00671 if(logxpx == 1) {sxthr = 1.01*xsort[0];} else { 00672 if (xsort[1] > sxthr) { sxthr = 1.01*xsort[1]; } 00673 } 00674 00675 // Evaluate pixel-by-pixel uncertainties (weights) for the templ analysis 00676 00677 for(i=0; i<BYSIZE; ++i) { xsig2[i] = 0.; } 00678 templ.xsigma2(fxpix, lxpix, sxthr, xsum, xsig2); 00679 00680 // Find the template bin that minimizes the Chi^2 00681 00682 chi2xmin = 1.e15; 00683 minbinj = -1; 00684 minbink = -1; 00685 for(j=0; j<nxbin; ++j) { 00686 for(k=0; k<=j; ++k) { 00687 ss2 = 0.; 00688 ssa = 0.; 00689 sa2 = 0.; 00690 for(i=fxpix-2; i<=lxpix+2; ++i) { 00691 ss2 += xsum[i]*xsum[i]/xsig2[i]; 00692 ssa += xsum[i]*xtemp[j][k][i]/xsig2[i]; 00693 sa2 += xtemp[j][k][i]*xtemp[j][k][i]/xsig2[i]; 00694 } 00695 rat=ssa/ss2; 00696 if(rat <= 0.) {LOGERROR("SiPixelTemplateReco") << "illegal chi2ymin normalization = " << rat << ENDL; rat = 1.;} 00697 chi2x=ss2-2.*ssa/rat+sa2/(rat*rat); 00698 if(chi2x < chi2xmin) { 00699 chi2xmin = chi2x; 00700 minbinj = j; 00701 minbink = k; 00702 } 00703 } 00704 } 00705 00706 if (theVerboseLevel > 9) { 00707 LOGDEBUG("SiPixelTemplateReco") << 00708 "minbin " << minbin << " chi2xmin = " << chi2xmin << ENDL; 00709 } 00710 00711 // Do not apply final template pass to 1-pixel clusters (use calibrated offset) 00712 00713 if(logxpx == 1) { 00714 00715 if(nxpix ==1) { 00716 delta = templ.dxone(); 00717 sigma = templ.sxone(); 00718 } else { 00719 delta = templ.dxtwo(); 00720 sigma = templ.sxtwo(); 00721 } 00722 xrec1 = 0.5*(fxpix+lxpix-2*shiftx+2.*originx)*xsize-delta; 00723 xrec2 = xrec1; 00724 if(sigma <= 0.) { 00725 sigmax = 28.9; 00726 } else { 00727 sigmax = sigma; 00728 } 00729 00730 // Do probability calculation for one-pixel clusters 00731 00732 chi2xmin -=chi21min; 00733 if(chi2xmin < 0.) {chi2xmin = 0.;} 00734 // probx = gsl_cdf_chisq_Q(chi2xmin, mean1pix); 00735 hchi2 = chi2xmin/2.; hndof = mean1pix/2.; 00736 probx = 1. - TMath::Gamma(hndof, hchi2); 00737 00738 } else { 00739 00740 // For cluster > 1 pix, use chi^2 minimm to recontruct the two x-positions 00741 00742 // uncertainty and final correction depend upon charge bin 00743 00744 bias = templ.xavgc2m(binq); 00745 k = std::min(minbink, minbinj); 00746 j = std::max(minbink, minbinj); 00747 xrec1 = (0.125*(minbink-xcbin)+BHX-(float)shiftx+originx)*xsize - bias; 00748 xrec2 = (0.125*(minbinj-xcbin)+BHX-(float)shiftx+originx)*xsize - bias; 00749 sigmax = sqrt2*templ.xrmsc2m(binq); 00750 00751 // Do goodness of fit test in y 00752 00753 if(chi2xmin < 0.0) {chi2xmin = 0.0;} 00754 meanx = 2.*templ.chi2xavg(binq); 00755 if(meanx < 0.01) {meanx = 0.01;} 00756 hchi2 = chi2xmin/2.; hndof = meanx/2.; 00757 probx = 1. - TMath::Gamma(hndof, hchi2); 00758 } 00759 00760 return 0;