CMS 3D CMS Logo

SiPixelTemplateReco Namespace Reference


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 Documentation

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.


Function Documentation

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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;


Generated on Tue Jun 9 18:52:34 2009 for CMSSW by  doxygen 1.5.4