CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/RecoLocalTracker/SiPixelRecHits/src/PixelCPETemplateReco.cc

Go to the documentation of this file.
00001 // Include our own header first
00002 #include "RecoLocalTracker/SiPixelRecHits/interface/PixelCPETemplateReco.h"
00003 
00004 // Geometry services
00005 #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h"
00006 #include "Geometry/TrackerGeometryBuilder/interface/RectangularPixelTopology.h"
00007 
00008 //#define DEBUG
00009 
00010 // MessageLogger
00011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00012 
00013 // Magnetic field
00014 #include "MagneticField/Engine/interface/MagneticField.h"
00015 
00016 // The template header files
00017 #include "RecoLocalTracker/SiPixelRecHits/interface/SiPixelTemplateReco.h"
00018 
00019 #include "RecoLocalTracker/SiPixelRecHits/interface/SiPixelTemplateSplit.h"
00020 
00021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00022 
00023 #include <vector>
00024 #include "boost/multi_array.hpp"
00025 
00026 #include <iostream>
00027 
00028 using namespace SiPixelTemplateReco;
00029 //using namespace SiPixelTemplateSplit;
00030 using namespace std;
00031 
00032 const float PI = 3.141593;
00033 const float HALFPI = PI * 0.5;
00034 const float degsPerRad = 57.29578;
00035 
00036 // &&& need a class const
00037 const float micronsToCm = 1.0e-4;
00038 
00039 const int cluster_matrix_size_x = 13;
00040 const int cluster_matrix_size_y = 21;
00041 
00042 //-----------------------------------------------------------------------------
00043 //  Constructor.  All detUnit-dependent quantities will be initialized later,
00044 //  in setTheDet().  Here we only load the templates into the template store templ_ .
00045 //-----------------------------------------------------------------------------
00046 PixelCPETemplateReco::PixelCPETemplateReco(edm::ParameterSet const & conf, 
00047                                            const MagneticField * mag, const SiPixelLorentzAngle * lorentzAngle, 
00048                                            const SiPixelTemplateDBObject * templateDBobject) 
00049   : PixelCPEBase(conf, mag, lorentzAngle, 0, templateDBobject)
00050 {
00051   //cout << endl;
00052   //cout << "Constructing PixelCPETemplateReco::PixelCPETemplateReco(...)................................................." << endl;
00053   //cout << endl;
00054 
00055   // &&& initialize the templates, etc.
00056   
00057   //-- Use Magnetic field at (0,0,0) to select a template ID [Morris, 6/25/08] (temporary until we implement DB access)
00058   
00059   DoCosmics_ = conf.getParameter<bool>("DoCosmics");
00060   LoadTemplatesFromDB_ = conf.getParameter<bool>("LoadTemplatesFromDB");
00061   //cout << " PixelCPETemplateReco : (int)LoadTemplatesFromDB_ = " << (int)LoadTemplatesFromDB_ << endl;
00062   //cout << "field_magnitude = " << field_magnitude << endl;
00063   
00064   // ggiurgiu@fnal.gov, 12/17/2008: use configuration parameter to decide between DB or text file template access
00065   if ( LoadTemplatesFromDB_ )
00066     {
00067       //cout << "PixelCPETemplateReco: Loading templates from database (DB) ------------------------------- " << endl;
00068       
00069       // Initialize template store to the selected ID [Morris, 6/25/08]  
00070       if ( !templ_.pushfile( *templateDBobject_) )
00071         throw cms::Exception("PixelCPETemplateReco") 
00072           << "\nERROR: Templates not filled correctly. Check the sqlite file. Using SiPixelTemplateDBObject version " 
00073           << (*templateDBobject_).version() << "\n\n";
00074     }
00075   else 
00076     {
00077       //cout << "PixelCPETemplateReco : Loading templates 40 and 41 from ASCII files ------------------------" << endl;
00078 
00079       if ( !templ_.pushfile( 40 ) )
00080         throw cms::Exception("PixelCPETemplateReco") 
00081           << "\nERROR: Templates 40 not loaded correctly from text file. Reconstruction will fail.\n\n";
00082     
00083       if ( !templ_.pushfile( 41 ) )
00084         throw cms::Exception("PixelCPETemplateReco") 
00085           << "\nERROR: Templates 41 not loaded correctly from text file. Reconstruction will fail.\n\n";
00086     }
00087   
00088   speed_ = conf.getParameter<int>( "speed");
00089   LogDebug("PixelCPETemplateReco::PixelCPETemplateReco:") <<
00090     "Template speed = " << speed_ << "\n";
00091   
00092   UseClusterSplitter_ = conf.getParameter<bool>("UseClusterSplitter");
00093   
00094 }
00095 
00096 //-----------------------------------------------------------------------------
00097 //  Clean up.
00098 //-----------------------------------------------------------------------------
00099 PixelCPETemplateReco::~PixelCPETemplateReco()
00100 {
00101   // &&& delete template store?
00102 }
00103 
00104 
00105 
00106 //------------------------------------------------------------------
00107 //  Public methods mandated by the base class.
00108 //------------------------------------------------------------------
00109 
00110 //------------------------------------------------------------------
00111 //  The main call to the template code.
00112 //------------------------------------------------------------------
00113 LocalPoint
00114 PixelCPETemplateReco::localPosition(const SiPixelCluster& cluster, const GeomDetUnit & det) const 
00115 {
00116   setTheDet( det, cluster );
00117   
00118   bool fpix;  //  barrel(false) or forward(true)
00119   if ( thePart == GeomDetEnumerators::PixelBarrel )   
00120     fpix = false;    // no, it's not forward -- it's barrel
00121   else                                              
00122     fpix = true;     // yes, it's forward
00123   
00124   int ID = -9999;
00125 
00126   if ( LoadTemplatesFromDB_ )
00127     {
00128       ID = templateDBobject_->getTemplateID(theDet->geographicalId());
00129     }
00130   else
00131     {
00132       if ( !fpix )
00133         ID = 40; // barrel
00134       else 
00135         ID = 41; // endcap
00136     }
00137   
00138   //cout << "PixelCPETemplateReco : ID = " << ID << endl;
00139   
00140 
00141   // Make from cluster (a SiPixelCluster) a boost multi_array_2d called 
00142   // clust_array_2d.
00143   boost::multi_array<float, 2> clust_array_2d(boost::extents[cluster_matrix_size_x][cluster_matrix_size_y]);
00144   
00145   // Preparing to retrieve ADC counts from the SiPixelCluster.  In the cluster,
00146   // we have the following:
00147   //   int minPixelRow(); // Minimum pixel index in the x direction (low edge).
00148   //   int maxPixelRow(); // Maximum pixel index in the x direction (top edge).
00149   //   int minPixelCol(); // Minimum pixel index in the y direction (left edge).
00150   //   int maxPixelCol(); // Maximum pixel index in the y direction (right edge).
00151   // So the pixels from minPixelRow() will go into clust_array_2d[0][*],
00152   // and the pixels from minPixelCol() will go into clust_array_2d[*][0].
00153 
00154   int row_offset = cluster.minPixelRow();
00155   int col_offset = cluster.minPixelCol();
00156   
00157   // Store the coordinates of the center of the (0,0) pixel of the array that 
00158   // gets passed to PixelTempReco2D
00159   // Will add these values to the output of  PixelTempReco2D
00160   float tmp_x = float(row_offset) + 0.5f;
00161   float tmp_y = float(col_offset) + 0.5f;
00162   
00163   // Store these offsets (to be added later) in a LocalPoint after tranforming 
00164   // them from measurement units (pixel units) to local coordinates (cm)
00165 
00166   // ggiurgiu@jhu.edu 12/09/2010 : update call with trk angles needed for bow/kink corrections
00167   LocalPoint lp;
00168   
00169   if ( with_track_angle )
00170     lp = theTopol->localPosition( MeasurementPoint(tmp_x, tmp_y), loc_trk_pred_ );
00171   else
00172     {
00173       edm::LogError("PixelCPETemplateReco") 
00174         << "@SUB = PixelCPETemplateReco::localPosition" 
00175         << "Should never be here. PixelCPETemplateReco should always be called with track angles. This is a bad error !!! ";
00176       
00177       lp = theTopol->localPosition( MeasurementPoint(tmp_x, tmp_y) );
00178     }
00179     
00180   
00181   // Visualize large clusters ---------------------------------------------------------
00182   // From Petar: maybe this should be moved into a method in the base class?
00183   /*
00184     char cluster_matrix[100][100];
00185     for (int i=0; i<100; i++)
00186     for (int j=0; j<100; j++)
00187     cluster_matrix[i][j] = '.';
00188     
00189     if ( cluster.sizeX()>cluster_matrix_size_x || cluster.sizeY()>cluster_matrix_size_y )
00190     {           
00191     cout << "cluster.size()  = " << cluster.size()  << endl;
00192     cout << "cluster.sizeX() = " << cluster.sizeX() << endl;
00193     cout << "cluster.sizeY() = " << cluster.sizeY() << endl;
00194     
00195     for ( std::vector<SiPixelCluster::Pixel>::const_iterator pix = pixVec.begin(); pix != pixVec.end(); ++pix )
00196     {
00197     int i = (int)(pix->x) - row_offset;
00198     int j = (int)(pix->y) - col_offset;
00199     cluster_matrix[i][j] = '*';
00200     }
00201     
00202     for (int i=0; i<(int)cluster.sizeX()+2; i++)
00203     {
00204     for (int j=0; j<(int)cluster.sizeY()+2; j++)
00205     cout << cluster_matrix[i][j];
00206     cout << endl;
00207     }
00208     } // if ( cluster.sizeX()>cluster_matrix_size_x || cluster.sizeY()>cluster_matrix_size_y )
00209   */
00210   // End Visualize clusters ---------------------------------------------------------
00211   
00212 
00213   // Copy clust's pixels (calibrated in electrons) into clust_array_2d;
00214   for (int i=0 ; i!=cluster.size(); ++i ) 
00215     {
00216       auto pix = cluster.pixel(i);
00217       // *pixIter dereferences to Pixel struct, with public vars x, y, adc (all float)
00218       // 02/13/2008 ggiurgiu@fnal.gov: type of x, y and adc has been changed to unsigned char, unsigned short, unsigned short
00219       // in DataFormats/SiPixelCluster/interface/SiPixelCluster.h so the type cast to int is redundant. Leave it there, it 
00220       // won't hurt. 
00221       int irow = int(pix.x) - row_offset;   // &&& do we need +0.5 ???
00222       int icol = int(pix.y) - col_offset;   // &&& do we need +0.5 ???
00223       
00224       // Gavril : what do we do here if the row/column is larger than cluster_matrix_size_x/cluster_matrix_size_y = 7/21 ?
00225       // Ignore them for the moment...
00226       if ( irow<cluster_matrix_size_x && icol<cluster_matrix_size_y )
00227         // 02/13/2008 ggiurgiu@fnal.gov typecast pixIter->adc to float
00228         clust_array_2d[irow][icol] = (float)pix.adc;
00229     }
00230   
00231   // Make and fill the bool arrays flagging double pixels
00232   std::vector<bool> ydouble(cluster_matrix_size_y), xdouble(cluster_matrix_size_x);
00233   // x directions (shorter), rows
00234   for (int irow = 0; irow < cluster_matrix_size_x; ++irow)
00235     {
00236       xdouble[irow] = theRecTopol->isItBigPixelInX( irow+row_offset );
00237     }
00238       
00239   // y directions (longer), columns
00240   for (int icol = 0; icol < cluster_matrix_size_y; ++icol) 
00241     {
00242       ydouble[icol] = theRecTopol->isItBigPixelInY( icol+col_offset );
00243     }
00244 
00245   // Output:
00246   float nonsense = -99999.9f; // nonsense init value
00247   templXrec_ = templYrec_ = templSigmaX_ = templSigmaY_ = nonsense;
00248   // If the template recontruction fails, we want to return 1.0 for now
00249   templProbY_ = templProbX_ = templProbQ_ = 1.0f;
00250   templQbin_ = 0;
00251   // We have a boolean denoting whether the reco failed or not
00252   hasFilledProb_ = false;
00253         
00254   float templYrec1_ = nonsense;
00255   float templXrec1_ = nonsense;
00256   float templYrec2_ = nonsense;
00257   float templXrec2_ = nonsense;
00258 
00259   // ******************************************************************
00260   // Do it! Use cotalpha_ and cotbeta_ calculated in PixelCPEBase
00261 
00262  
00263   float locBz = (*theParam).bz;
00264     
00265   ierr =
00266     PixelTempReco2D( ID, cotalpha_, cotbeta_,
00267                      locBz, 
00268                      clust_array_2d, ydouble, xdouble,
00269                      templ_,
00270                      templYrec_, templSigmaY_, templProbY_,
00271                      templXrec_, templSigmaX_, templProbX_, 
00272                      templQbin_, 
00273                      speed_,
00274                      templProbQ_
00275                      );
00276 
00277   // ******************************************************************
00278 
00279   // Check exit status
00280   if unlikely( ierr != 0 ) 
00281     {
00282       LogDebug("PixelCPETemplateReco::localPosition") <<
00283         "reconstruction failed with error " << ierr << "\n";
00284 
00285       // Gavril: what do we do in this case ? For now, just return the cluster center of gravity in microns
00286       // In the x case, apply a rough Lorentz drift average correction
00287       // To do: call PixelCPEGeneric whenever PixelTempReco2D fails
00288       float lorentz_drift = -999.9;
00289       if ( thePart == GeomDetEnumerators::PixelBarrel )
00290         lorentz_drift = 60.0f; // in microns
00291       else if ( thePart == GeomDetEnumerators::PixelEndcap )
00292         lorentz_drift = 10.0f; // in microns
00293       else 
00294         throw cms::Exception("PixelCPETemplateReco::localPosition :") 
00295           << "A non-pixel detector type in here?" << "\n";
00296       // ggiurgiu@jhu.edu, 21/09/2010 : trk angles needed to correct for bows/kinks
00297       if ( with_track_angle )
00298         {
00299           templXrec_ = theTopol->localX( cluster.x(), loc_trk_pred_ ) - lorentz_drift * micronsToCm; // rough Lorentz drift correction
00300           templYrec_ = theTopol->localY( cluster.y(), loc_trk_pred_ ); 
00301         }
00302       else
00303         {
00304           edm::LogError("PixelCPETemplateReco") 
00305             << "@SUB = PixelCPETemplateReco::localPosition" 
00306             << "Should never be here. PixelCPETemplateReco should always be called with track angles. This is a bad error !!! ";
00307           
00308           templXrec_ = theTopol->localX( cluster.x() ) - lorentz_drift * micronsToCm; // rough Lorentz drift correction
00309           templYrec_ = theTopol->localY( cluster.y() );
00310         }
00311     }
00312   else if unlikely( UseClusterSplitter_ && templQbin_ == 0 )
00313     {
00314       cout << " PixelCPETemplateReco : We should never be here !!!!!!!!!!!!!!!!!!!!!!" << endl;
00315       cout << "                 (int)UseClusterSplitter_ = " << (int)UseClusterSplitter_ << endl;
00316 
00317       //ierr = 
00318       //PixelTempSplit( ID, fpix, cotalpha_, cotbeta_, 
00319       //                clust_array_2d, ydouble, xdouble, 
00320       //                templ_, 
00321       //                templYrec1_, templYrec2_, templSigmaY_, templProbY_,
00322       //                templXrec1_, templXrec2_, templSigmaX_, templProbX_, 
00323       //                templQbin_ );
00324 
00325 
00326       float dchisq;
00327       float templProbQ_;
00328       SiPixelTemplate2D templ2D_;
00329       templ2D_.pushfile(ID);
00330         
00331       ierr =
00332         SiPixelTemplateSplit::PixelTempSplit( ID, cotalpha_, cotbeta_,
00333                                               clust_array_2d, 
00334                                               ydouble, xdouble,
00335                                               templ_,
00336                                               templYrec1_, templYrec2_, templSigmaY_, templProbY_,
00337                                               templXrec1_, templXrec2_, templSigmaX_, templProbX_,
00338                                               templQbin_, 
00339                                               templProbQ_,
00340                                               true, 
00341                                               dchisq, 
00342                                               templ2D_ );
00343       
00344 
00345       if ( ierr != 0 )
00346         {
00347           LogDebug("PixelCPETemplateReco::localPosition") <<
00348             "reconstruction failed with error " << ierr << "\n";
00349           
00350           // Gavril: what do we do in this case ? For now, just return the cluster center of gravity in microns
00351           // In the x case, apply a rough Lorentz drift average correction
00352           // To do: call PixelCPEGeneric whenever PixelTempReco2D fails
00353           float lorentz_drift = -999.9f;
00354           if ( thePart == GeomDetEnumerators::PixelBarrel )
00355             lorentz_drift = 60.0f; // in microns
00356           else if ( thePart == GeomDetEnumerators::PixelEndcap )
00357             lorentz_drift = 10.0f; // in microns
00358           else 
00359             throw cms::Exception("PixelCPETemplateReco::localPosition :") 
00360               << "A non-pixel detector type in here?" << "\n";
00361 
00362           // ggiurgiu@jhu.edu, 12/09/2010 : trk angles needed to correct for bows/kinks
00363           if ( with_track_angle )
00364             {
00365               templXrec_ = theTopol->localX( cluster.x(),loc_trk_pred_ ) - lorentz_drift * micronsToCm; // rough Lorentz drift correction
00366               templYrec_ = theTopol->localY( cluster.y(),loc_trk_pred_ );
00367             }
00368           else
00369             {
00370               edm::LogError("PixelCPETemplateReco") 
00371                 << "@SUB = PixelCPETemplateReco::localPosition" 
00372                 << "Should never be here. PixelCPETemplateReco should always be called with track angles. This is a bad error !!! ";
00373               
00374               templXrec_ = theTopol->localX( cluster.x() ) - lorentz_drift * micronsToCm; // very rough Lorentz drift correction
00375               templYrec_ = theTopol->localY( cluster.y() );
00376               
00377             }
00378         }
00379       else
00380         {
00381           // go from micrometer to centimeter      
00382           templXrec1_ *= micronsToCm;
00383           templYrec1_ *= micronsToCm;     
00384           templXrec2_ *= micronsToCm;
00385           templYrec2_ *= micronsToCm;
00386       
00387           // go back to the module coordinate system   
00388           templXrec1_ += lp.x();
00389           templYrec1_ += lp.y();
00390           templXrec2_ += lp.x();
00391           templYrec2_ += lp.y();
00392       
00393           // calculate distance from each hit to the track and choose the 
00394           // hit closest to the track
00395           float distance11 = sqrt( (templXrec1_ - trk_lp_x)*(templXrec1_ - trk_lp_x) + 
00396                                    (templYrec1_ - trk_lp_y)*(templYrec1_ - trk_lp_y) );
00397           
00398           float distance12 = sqrt( (templXrec1_ - trk_lp_x)*(templXrec1_ - trk_lp_x) + 
00399                                    (templYrec2_ - trk_lp_y)*(templYrec2_ - trk_lp_y) );
00400           
00401           float distance21 = sqrt( (templXrec2_ - trk_lp_x)*(templXrec2_ - trk_lp_x) + 
00402                                    (templYrec1_ - trk_lp_y)*(templYrec1_ - trk_lp_y) );
00403           
00404           float distance22 = sqrt( (templXrec2_ - trk_lp_x)*(templXrec2_ - trk_lp_x) + 
00405                                    (templYrec2_ - trk_lp_y)*(templYrec2_ - trk_lp_y) );
00406           
00407           float min_templXrec_ = -999.9;
00408           float min_templYrec_ = -999.9;
00409           float distance_min = 9999999999.9;
00410           if ( distance11 < distance_min )
00411             {
00412               distance_min = distance11;
00413               min_templXrec_ = templXrec1_;
00414               min_templYrec_ = templYrec1_;
00415             }
00416           if ( distance12 < distance_min )
00417             {
00418               distance_min = distance12;
00419               min_templXrec_ = templXrec1_;
00420               min_templYrec_ = templYrec2_;
00421             }
00422           if ( distance21 < distance_min )
00423             {
00424               distance_min = distance21;
00425               min_templXrec_ = templXrec2_;
00426               min_templYrec_ = templYrec1_;
00427             }
00428           if ( distance22 < distance_min )
00429             {
00430               distance_min = distance22;
00431               min_templXrec_ = templXrec2_;
00432               min_templYrec_ = templYrec2_;
00433             }
00434                   
00435           templXrec_ = min_templXrec_;
00436           templYrec_ = min_templYrec_;
00437         }
00438     } // else if ( UseClusterSplitter_ && templQbin_ == 0 )
00439 
00440   else // apparenly this is he good one!
00441     {
00442       // go from micrometer to centimeter      
00443       templXrec_ *= micronsToCm;
00444       templYrec_ *= micronsToCm;
00445       
00446       // go back to the module coordinate system 
00447       templXrec_ += lp.x();
00448       templYrec_ += lp.y();
00449     }
00450     
00451   // Save probabilities and qBin in the quantities given to us by the base class
00452   // (for which there are also inline getters).  &&& templProbX_ etc. should be retired...
00453   probabilityX_  = templProbX_;
00454   probabilityY_  = templProbY_;
00455   probabilityQ_  = templProbQ_;
00456   qBin_          = templQbin_;
00457   
00458   if ( ierr == 0 ) // always true here
00459     hasFilledProb_ = true;
00460   
00461   return LocalPoint( templXrec_, templYrec_ );      
00462   
00463 }
00464   
00465 //------------------------------------------------------------------
00466 //  localError() relies on localPosition() being called FIRST!!!
00467 //------------------------------------------------------------------
00468 LocalError  
00469 PixelCPETemplateReco::localError( const SiPixelCluster& cluster, 
00470                                   const GeomDetUnit& det ) const 
00471 {
00472   //cout << endl;
00473   //cout << "Set PixelCPETemplate errors .............................................." << endl;
00474 
00475   //cout << "CPETemplate : " << endl;
00476 
00477   //--- Default is the maximum error used for edge clusters.
00478   const float sig12 = 1./sqrt(12.0);
00479   float xerr = thePitchX *sig12;
00480   float yerr = thePitchY *sig12;
00481   
00482   // Check if the errors were already set at the clusters splitting level
00483   if ( cluster.getSplitClusterErrorX() > 0.0f && cluster.getSplitClusterErrorX() < 7777.7f && 
00484        cluster.getSplitClusterErrorY() > 0.0f && cluster.getSplitClusterErrorY() < 7777.7f )
00485     {
00486       xerr = cluster.getSplitClusterErrorX() * micronsToCm;
00487       yerr = cluster.getSplitClusterErrorY() * micronsToCm;
00488 
00489       //cout << "Errors set at cluster splitting level : " << endl;
00490       //cout << "xerr = " << xerr << endl;
00491       //cout << "yerr = " << yerr << endl;
00492     }
00493   else
00494     {
00495       // If errors are not split at the cluster splitting level, set the errors here
00496 
00497       //cout  << "Errors are not split at the cluster splitting level, set the errors here : " << endl; 
00498   
00499       setTheDet( det, cluster );
00500       
00501       int maxPixelCol = cluster.maxPixelCol();
00502       int maxPixelRow = cluster.maxPixelRow();
00503       int minPixelCol = cluster.minPixelCol();
00504       int minPixelRow = cluster.minPixelRow();
00505       
00506       //--- Are we near either of the edges?
00507       bool edgex = ( theRecTopol->isItEdgePixelInX( minPixelRow ) || theRecTopol->isItEdgePixelInX( maxPixelRow ) );
00508       bool edgey = ( theRecTopol->isItEdgePixelInY( minPixelCol ) || theRecTopol->isItEdgePixelInY( maxPixelCol ) );
00509       
00510       if ( ierr !=0 ) 
00511         {
00512           // If reconstruction fails the hit position is calculated from cluster center of gravity 
00513           // corrected in x by average Lorentz drift. Assign huge errors.
00514           //xerr = 10.0 * (float)cluster.sizeX() * xerr;
00515           //yerr = 10.0 * (float)cluster.sizeX() * yerr;
00516           
00517           // Assign better errors based on the residuals for failed template cases
00518           if ( thePart == GeomDetEnumerators::PixelBarrel )
00519             {
00520               xerr = 55.0f * micronsToCm;
00521               yerr = 36.0f * micronsToCm;
00522             }
00523           else if ( thePart == GeomDetEnumerators::PixelEndcap )
00524             {
00525               xerr = 42.0f * micronsToCm;
00526               yerr = 39.0f * micronsToCm;
00527             }
00528           else 
00529             throw cms::Exception("PixelCPETemplateReco::localError :") << "A non-pixel detector type in here?" ;
00530 
00531           //cout << "xerr = " << xerr << endl;
00532           //cout << "yerr = " << yerr << endl;
00533           
00534           //return LocalError(xerr*xerr, 0, yerr*yerr);
00535         }
00536       else if ( edgex || edgey )
00537         {
00538           // for edge pixels assign errors according to observed residual RMS 
00539           if      ( edgex && !edgey )
00540             {
00541               xerr = 23.0f * micronsToCm;
00542               yerr = 39.0f * micronsToCm;
00543             }
00544           else if ( !edgex && edgey )
00545             {
00546               xerr = 24.0f * micronsToCm;
00547               yerr = 96.0f * micronsToCm;
00548             }
00549           else if ( edgex && edgey )
00550             {
00551               xerr = 31.0f * micronsToCm;
00552               yerr = 90.0f * micronsToCm;
00553             }
00554           else
00555             {
00556               throw cms::Exception(" PixelCPETemplateReco::localError: Something wrong with pixel edge flag !!!");
00557             }
00558 
00559           //cout << "xerr = " << xerr << endl;
00560           //cout << "yerr = " << yerr << endl;
00561         }
00562       else 
00563         {
00564           // &&& need a class const
00565           //const float micronsToCm = 1.0e-4;
00566           
00567           xerr = templSigmaX_ * micronsToCm;
00568           yerr = templSigmaY_ * micronsToCm;
00569           
00570           //cout << "xerr = " << xerr << endl;
00571           //cout << "yerr = " << yerr << endl;
00572 
00573           // &&& should also check ierr (saved as class variable) and return
00574           // &&& nonsense (another class static) if the template fit failed.
00575         }       
00576       
00577       if (theVerboseLevel > 9) 
00578         {
00579           LogDebug("PixelCPETemplateReco") <<
00580             " Sizex = " << cluster.sizeX() << " Sizey = " << cluster.sizeY() << " Edgex = " << edgex << " Edgey = " << edgey << 
00581             " ErrX  = " << xerr            << " ErrY  = " << yerr;
00582         }
00583 
00584     } // else
00585   
00586   if ( !(xerr > 0.0f) )
00587     throw cms::Exception("PixelCPETemplateReco::localError") 
00588       << "\nERROR: Negative pixel error xerr = " << xerr << "\n\n";
00589   
00590   if ( !(yerr > 0.0f) )
00591     throw cms::Exception("PixelCPETemplateReco::localError") 
00592       << "\nERROR: Negative pixel error yerr = " << yerr << "\n\n";
00593 
00594   //cout << "Final errors set to: " << endl;
00595   //cout << "xerr = " << xerr << endl;
00596   //cout << "yerr = " << yerr << endl;
00597   //cout << "Out of PixelCPETemplateREco..........................................................................." << endl;
00598   //cout << endl;
00599 
00600   return LocalError(xerr*xerr, 0, yerr*yerr);
00601 }
00602