CMS 3D CMS Logo

SiPixelTemplateReco.cc

Go to the documentation of this file.
00001 //
00002 //  SiPixelTemplateReco.cc (Version 5.01)
00003 //
00004 //  Add goodness-of-fit to algorithm, include single pixel clusters in chi2 calculation
00005 //  Try "decapitation" of large single pixels
00006 //  Add correction for (Q_F-Q_L)/(Q_F+Q_L) bias
00007 //  Add cot(beta) reflection to reduce y-entries and more sophisticated x-interpolation
00008 //  Fix small double pixel bug with decapitation (2.41 5-Mar-2007).
00009 //  Fix pseudopixel bug causing possible memory overwrite (2.42 12-Mar-2007)
00010 //  Adjust template binning to span 3 (or 4) central pixels and implement improved (faster) chi2min search
00011 //  Replace internal containers with static arrays
00012 //  Add external threshold to calls to ysigma2 and xsigma2, use sorted signal heights to guarrantee min clust size = 2
00013 //  Use denser search over larger bin range for clusters with big pixels.
00014 //  Use single calls to template object to load template arrays (had been many)
00015 //  Add speed switch to trade-off speed and robustness
00016 //  Add qmin and re-define qbin to flag low-q clusters
00017 //  Add qscale to match charge scales
00018 //  Return error if no pixels in cluster
00019 //  Replace 4 cout's with LogError's
00020 //  Add LogDebug I/O to report various common errors
00021 //  Incorporate "cluster repair" to handle dead pixels
00022 //  Take truncation size from new pixmax information
00023 //  Change to allow template sizes to be changed at compile time
00024 //  Move interpolation range error to LogDebug
00025 //
00026 //  Created by Morris Swartz on 10/27/06.
00027 //  Copyright 2006 __TheJohnsHopkinsUniversity__. All rights reserved.
00028 //
00029 //
00030 
00031 #include <math.h>
00032 #include <algorithm>
00033 #include <vector>
00034 #include <utility>
00035 #include <iostream>
00036 // ROOT::Math has a c++ function that does the probability calc, but only in v5.12 and later
00037 //#include "Math/DistFunc.h"
00038 #include "TMath.h"
00039 // Use current version of gsl instead of ROOT::Math
00040 //#include <gsl/gsl_cdf.h>
00041 
00042 #ifndef SI_PIXEL_TEMPLATE_STANDALONE
00043 #include "RecoLocalTracker/SiPixelRecHits/interface/SiPixelTemplateReco.h"
00044 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00045 #define LOGERROR(x) edm::LogError(x)
00046 #define LOGDEBUG(x) LogDebug(x)
00047 #define ENDL " "
00048 #else
00049 #include "SiPixelTemplateReco.h"
00050 //static int theVerboseLevel = {2};
00051 #define LOGERROR(x) std::cout << x << ": "
00052 #define LOGDEBUG(x) std::cout << x << ": "
00053 #define ENDL std::endl
00054 #endif
00055 
00056 static int theVerboseLevel = {2};
00057 
00058 using namespace SiPixelTemplateReco;
00059 
00060 // *************************************************************************************************************************************
00087 // *************************************************************************************************************************************
00088 int SiPixelTemplateReco::PixelTempReco2D(int id, bool fpix, float cotalpha, float cotbeta, array_2d cluster, 
00089                     std::vector<bool> ydouble, std::vector<bool> xdouble, 
00090                     SiPixelTemplate& templ, 
00091                     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)
00092                         
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;
00870 } // PixelTempReco2D 
00871 
00872 // *************************************************************************************************************************************
00873 //  Overload parameter list for compatibility with older versions
00898 // *************************************************************************************************************************************
00899 int SiPixelTemplateReco::PixelTempReco2D(int id, bool fpix, float cotalpha, float cotbeta, array_2d cluster, 
00900                     std::vector<bool> ydouble, std::vector<bool> xdouble, 
00901                     SiPixelTemplate& templ, 
00902                     float& yrec, float& sigmay, float& proby, float& xrec, float& sigmax, float& probx, int& qbin, int speed)
00903                         
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 
00912 } // PixelTempReco2D

Generated on Tue Jun 9 17:43:59 2009 for CMSSW by  doxygen 1.5.4