CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitRatioMethodAlgo.h

Go to the documentation of this file.
00001 #ifndef RecoLocalCalo_EcalRecAlgos_EcalUncalibRecHitRatioMethodAlgo_HH
00002 #define RecoLocalCalo_EcalRecAlgos_EcalUncalibRecHitRatioMethodAlgo_HH
00003 
00014 #include "Math/SVector.h"
00015 #include "Math/SMatrix.h"
00016 #include "RecoLocalCalo/EcalRecAlgos/interface/EcalUncalibRecHitRecAbsAlgo.h"
00017 #include "CondFormats/EcalObjects/interface/EcalSampleMask.h"
00018 #include <vector>
00019 
00020 template < class C > class EcalUncalibRecHitRatioMethodAlgo {
00021       public:
00022         struct Ratio {
00023                 int index;
00024                 int step;
00025                 double value;
00026                 double error;
00027         };
00028         struct Tmax {
00029                 int index;
00030                 int step;
00031                 double value;
00032                 double error;
00033                 double amplitude;
00034                 double chi2;
00035         };
00036         struct CalculatedRecHit {
00037                 double amplitudeMax;
00038                 double timeMax;
00039                 double timeError;
00040                 double chi2;
00041         };
00042 
00043         virtual ~ EcalUncalibRecHitRatioMethodAlgo < C > () { };
00044         virtual EcalUncalibratedRecHit makeRecHit(const C & dataFrame,
00045                                                   const EcalSampleMask & sampleMask,
00046                                                   const double *pedestals,
00047                                                   const double* pedestalRMSes,
00048                                                   const double *gainRatios,
00049                                                   std::vector < double >&timeFitParameters,
00050                                                   std::vector < double >&amplitudeFitParameters,
00051                                                   std::pair < double, double >&timeFitLimits);
00052 
00053         // more function to be able to compute
00054         // amplitude and time separately
00055         void init( const C &dataFrame, const EcalSampleMask &sampleMask, const double * pedestals, const double * pedestalRMSes, const double * gainRatios );
00056         void computeTime(std::vector < double >&timeFitParameters, std::pair < double, double >&timeFitLimits, std::vector< double > &amplitudeFitParameters);
00057         void computeAmplitude( std::vector< double > &amplitudeFitParameters );
00058         CalculatedRecHit getCalculatedRecHit() { return calculatedRechit_; };
00059         bool fixMGPAslew( const C &dataFrame );
00060 
00061       protected:
00062         
00063         EcalSampleMask sampleMask_;
00064         DetId          theDetId_;
00065         std::vector < double > amplitudes_;
00066         std::vector < double > amplitudeErrors_;
00067         std::vector < Ratio > ratios_;
00068         std::vector < Tmax > times_;
00069         std::vector < Tmax > timesAB_;
00070 
00071         double pedestal_;
00072         int    num_;
00073         double ampMaxError_;
00074 
00075         CalculatedRecHit calculatedRechit_;
00076 };
00077 
00078 template <class C>
00079 void EcalUncalibRecHitRatioMethodAlgo<C>::init( const C &dataFrame, const EcalSampleMask &sampleMask, 
00080                                                 const double * pedestals, const double * pedestalRMSes, const double * gainRatios )
00081 {
00082         sampleMask_ = sampleMask;
00083         theDetId_ = DetId(dataFrame.id().rawId());  
00084 
00085         calculatedRechit_.timeMax = 5;
00086         calculatedRechit_.amplitudeMax = 0;
00087         calculatedRechit_.timeError = -999;
00088         amplitudes_.clear();
00089         amplitudes_.reserve(C::MAXSAMPLES);
00090         amplitudeErrors_.clear();
00091         amplitudeErrors_.reserve(C::MAXSAMPLES);
00092         ratios_.clear();
00093         ratios_.reserve(C::MAXSAMPLES*(C::MAXSAMPLES-1)/2);
00094         times_.clear();
00095         times_.reserve(C::MAXSAMPLES*(C::MAXSAMPLES-1)/2);
00096         timesAB_.clear();
00097         timesAB_.reserve(C::MAXSAMPLES*(C::MAXSAMPLES-1)/2);
00098         
00099         // to obtain gain 12 pedestal:
00100         // -> if it's in gain 12, use first sample
00101         // --> average it with second sample if in gain 12 and 3-sigma-noise compatible (better LF noise cancellation)
00102         // -> else use pedestal from database
00103         pedestal_ = 0;
00104         num_      = 0;
00105         if (dataFrame.sample(0).gainId() == 1 &&
00106             sampleMask_.useSample(0, theDetId_ ) 
00107             ) {
00108           pedestal_ += double (dataFrame.sample(0).adc());
00109           num_++;
00110         }
00111         if (num_!=0 &&
00112             dataFrame.sample(1).gainId() == 1 && 
00113             sampleMask_.useSample(1, theDetId_) &&
00114             fabs(dataFrame.sample(1).adc()-dataFrame.sample(0).adc())<3*pedestalRMSes[0]) {
00115                 pedestal_ += double (dataFrame.sample(1).adc());
00116                 num_++;
00117         }
00118         if (num_ != 0)
00119                 pedestal_ /= num_;
00120         else
00121                 pedestal_ = pedestals[0];
00122 
00123         // fill vector of amplitudes, pedestal subtracted and vector
00124         // of amplitude uncertainties Also, find the uncertainty of a
00125         // sample with max amplitude. We will use it later.
00126 
00127         ampMaxError_ = 0;
00128         double ampMaxValue = -1000;
00129 
00130         // ped-subtracted and gain-renormalized samples. It is VERY
00131         // IMPORTANT to have samples one clock apart which means to
00132         // have vector size equal to MAXSAMPLES
00133         double sample;
00134         double sampleError;
00135         int GainId;
00136         for (int iSample = 0; iSample < C::MAXSAMPLES; iSample++) {
00137           
00138 
00139 
00140           GainId = dataFrame.sample(iSample).gainId();
00141           
00142           
00143           // only use normally samples which are desired; if sample not to be used
00144           // inflate error so won't generate ratio considered for the measurement
00145           if (!sampleMask_.useSample(iSample, theDetId_ ) ) {
00146             sample      = 1e-9;
00147             sampleError = 1e+9;
00148           }
00149           else if (GainId == 1) {
00150             sample      = double (dataFrame.sample(iSample).adc() - pedestal_);
00151             sampleError = pedestalRMSes[0];
00152           } 
00153           else if (GainId == 2 || GainId == 3){
00154             sample      = (double (dataFrame.sample(iSample).adc() - pedestals[GainId - 1])) *gainRatios[GainId - 1];
00155             sampleError = pedestalRMSes[GainId-1]*gainRatios[GainId-1];
00156           } 
00157           else {
00158             sample      = 1e-9;  // GainId=0 case falls here, from saturation
00159             sampleError = 1e+9;  // inflate error so won't generate ratio considered for the measurement 
00160           }
00161           
00162 
00163           if(sampleError>0){
00164             amplitudes_.push_back(sample);
00165             amplitudeErrors_.push_back(sampleError);
00166             if(ampMaxValue < sample){
00167               ampMaxValue = sample;
00168               ampMaxError_ = sampleError;
00169             }
00170           }else{
00171             // inflate error for useless samples
00172             amplitudes_.push_back(sample);
00173             amplitudeErrors_.push_back(1e+9);
00174           }
00175         }
00176 }
00177 
00178 template <class C>
00179 bool EcalUncalibRecHitRatioMethodAlgo<C>::fixMGPAslew( const C &dataFrame )
00180 {
00181 
00182   // This fuction finds sample(s) preceeding gain switching and
00183   // inflates errors on this sample, therefore, making this sample
00184   // invisible for Ratio Method. Only gain switching DOWN is
00185   // considered Only gainID=1,2,3 are considered. In case of the
00186   // saturation (gainID=0), we keep "distorted" sample because it is
00187   // the only chance to make time measurement; the qualilty of it will
00188   // be bad anyway.
00189 
00190   bool result = false;
00191 
00192   int GainIdPrev;
00193   int GainIdNext;
00194   for (int iSample = 1; iSample < C::MAXSAMPLES; iSample++) {
00195 
00196     // only use samples which are desired
00197     if (!sampleMask_.useSample(iSample, theDetId_) ) continue;
00198     
00199     GainIdPrev = dataFrame.sample(iSample-1).gainId();
00200     GainIdNext = dataFrame.sample(iSample).gainId();
00201     if( GainIdPrev>=1 && GainIdPrev<=3 && 
00202         GainIdNext>=1 && GainIdNext<=3 && 
00203         GainIdPrev<GainIdNext ){
00204       amplitudes_[iSample-1]=1e-9;
00205       amplitudeErrors_[iSample-1]=1e+9;
00206       result = true;      
00207     }
00208   }
00209   return result;
00210 
00211 }
00212 
00213 template<class C>
00214 void EcalUncalibRecHitRatioMethodAlgo<C>::computeTime(std::vector < double >&timeFitParameters,
00215             std::pair < double, double >&timeFitLimits, std::vector < double >&amplitudeFitParameters)
00216 {
00218   //                                                          //
00219   //              RATIO METHOD FOR TIME STARTS HERE           //
00220   //                                                          //
00222   double ampMaxAlphaBeta = 0;
00223   double tMaxAlphaBeta = 5;
00224   double tMaxErrorAlphaBeta = 999;
00225   double tMaxRatio = 5;
00226   double tMaxErrorRatio = 999;
00227 
00228   double sumAA = 0;
00229   double sumA  = 0;
00230   double sum1  = 0;
00231   double sum0  = 0;
00232   double sumAf = 0;
00233   double sumff = 0;
00234   double NullChi2 = 0;
00235 
00236   // null hypothesis = no pulse, pedestal only
00237   for(unsigned int i = 0; i < amplitudes_.size(); i++){
00238     double err2 = amplitudeErrors_[i]*amplitudeErrors_[i];
00239     sum0  += 1;
00240     sum1  += 1/err2;
00241     sumA  += amplitudes_[i]/err2;
00242     sumAA += amplitudes_[i]*amplitudes_[i]/err2;
00243   }
00244   if(sum0>0){
00245     NullChi2 = (sumAA - sumA*sumA/sum1)/sum0;
00246   }else{
00247     // not enough samples to reconstruct the pulse
00248     return;
00249   }
00250 
00251   // Make all possible Ratio's based on any pair of samples i and j
00252   // (j>i) with positive amplitudes_
00253   //
00254   //       Ratio[k] = Amp[i]/Amp[j]
00255   //       where Amp[i] is pedestal subtracted ADC value in a time sample [i]
00256   //
00257   double alphabeta = amplitudeFitParameters[0]*amplitudeFitParameters[1];
00258   double alpha = amplitudeFitParameters[0];
00259   double beta = amplitudeFitParameters[1];
00260 
00261   for(unsigned int i = 0; i < amplitudes_.size()-1; i++){
00262     for(unsigned int j = i+1; j < amplitudes_.size(); j++){
00263 
00264       if(amplitudes_[i]>1 && amplitudes_[j]>1){
00265 
00266         // ratio
00267         double Rtmp = amplitudes_[i]/amplitudes_[j];
00268 
00269         // error^2 due to stat fluctuations of time samples
00270         // (uncorrelated for both samples)
00271 
00272         double err1 = Rtmp*Rtmp*( (amplitudeErrors_[i]*amplitudeErrors_[i]/(amplitudes_[i]*amplitudes_[i])) + (amplitudeErrors_[j]*amplitudeErrors_[j]/(amplitudes_[j]*amplitudes_[j])) );
00273 
00274         // error due to fluctuations of pedestal (common to both samples)
00275         double stat;
00276         if(num_>0) stat = num_;      // num presampeles used to compute pedestal
00277         else       stat = 1;         // pedestal from db
00278         double err2 = amplitudeErrors_[j]*(amplitudes_[i]-amplitudes_[j])/(amplitudes_[j]*amplitudes_[j])/sqrt(stat);
00279 
00280         //error due to integer round-down. It is relevant to low
00281         //amplitudes_ in gainID=1 and negligible otherwise.
00282         double err3 = 0.289/amplitudes_[j];
00283 
00284         double totalError = sqrt(err1 + err2*err2 +err3*err3);
00285 
00286 
00287         // don't include useless ratios
00288         if(totalError < 1.0
00289            && Rtmp>0.001
00290            && Rtmp<exp(double(j-i)/beta)-0.001
00291            ){
00292           Ratio currentRatio = { i, (j-i), Rtmp, totalError };
00293           ratios_.push_back(currentRatio);
00294         }
00295 
00296       }
00297 
00298     }
00299   }
00300 
00301   // No useful ratios, return zero amplitude and no time measurement
00302   if(!ratios_.size() >0)
00303     return;
00304 
00305   // make a vector of Tmax measurements that correspond to each ratio
00306   // and based on Alpha-Beta parameterization of the pulse shape
00307 
00308   for(unsigned int i = 0; i < ratios_.size(); i++){
00309 
00310     double stepOverBeta = double(ratios_[i].step)/beta;
00311     double offset = double(ratios_[i].index) + alphabeta;
00312 
00313     double Rmin = ratios_[i].value - ratios_[i].error;
00314     if(Rmin<0.001) Rmin=0.001;
00315 
00316     double Rmax = ratios_[i].value + ratios_[i].error;
00317     double RLimit = exp(stepOverBeta)-0.001;
00318     if( Rmax > RLimit ) Rmax = RLimit;
00319 
00320     double time1 = offset - ratios_[i].step/(exp((stepOverBeta-log(Rmin))/alpha)-1.0);
00321     double time2 = offset - ratios_[i].step/(exp((stepOverBeta-log(Rmax))/alpha)-1.0);
00322 
00323     // this is the time measurement based on the ratios[i]
00324     double tmax = 0.5 * (time1 + time2);
00325     double tmaxerr = 0.5 * sqrt( (time1 - time2)*(time1 - time2) );
00326 
00327     // calculate chi2
00328     sumAf = 0;
00329     sumff = 0;
00330     for(unsigned int it = 0; it < amplitudes_.size(); it++){
00331       double err2 = amplitudeErrors_[it]*amplitudeErrors_[it];
00332       double offset = (double(it) - tmax)/alphabeta;
00333       double term1 = 1.0 + offset;
00334       if(term1>1e-6){
00335         double f = exp( alpha*(log(1.0+offset) - offset) );
00336         sumAf += amplitudes_[it]*f/err2;
00337         sumff += f*f/err2;
00338       }
00339     }
00340 
00341     double chi2 = sumAA;
00342     double amp = 0;
00343     if( sumff > 0 ){
00344       chi2 = sumAA - sumAf*sumAf/sumff;
00345       amp = sumAf/sumff;
00346     }
00347     chi2 /= sum0;
00348 
00349     // choose reasonable measurements. One might argue what is
00350     // reasonable and what is not.
00351     if(chi2 > 0 && tmaxerr > 0 && tmax > 0){
00352       Tmax currentTmax={ ratios_[i].index, ratios_[i].step, tmax, tmaxerr, amp, chi2 };
00353       timesAB_.push_back(currentTmax);
00354     }
00355   }
00356 
00357   // no reasonable time measurements!
00358   if( !(timesAB_.size()> 0))
00359     return;
00360 
00361   // find minimum chi2
00362   double chi2min = 1.0e+9;
00363   //double timeMinimum = 5;
00364   //double errorMinimum = 999;
00365   for(unsigned int i = 0; i < timesAB_.size(); i++){
00366     if( timesAB_[i].chi2 <= chi2min ){
00367       chi2min = timesAB_[i].chi2;
00368       //timeMinimum = timesAB_[i].value;
00369       //errorMinimum = timesAB_[i].error;
00370     }
00371   }
00372 
00373   // make a weighted average of tmax measurements with "small" chi2
00374   // (within 1 sigma of statistical uncertainty :-)
00375   double chi2Limit = chi2min + 1.0;
00376   double time_max = 0;
00377   double time_wgt = 0;
00378   for(unsigned int i = 0; i < timesAB_.size(); i++){
00379     if(  timesAB_[i].chi2 < chi2Limit  ){
00380       double inverseSigmaSquared = 1.0/(timesAB_[i].error*timesAB_[i].error);
00381       time_wgt += inverseSigmaSquared;
00382       time_max += timesAB_[i].value*inverseSigmaSquared;
00383     }
00384   }
00385 
00386   tMaxAlphaBeta =  time_max/time_wgt;
00387   tMaxErrorAlphaBeta = 1.0/sqrt(time_wgt);
00388 
00389   // find amplitude and chi2
00390   sumAf = 0;
00391   sumff = 0;
00392   for(unsigned int i = 0; i < amplitudes_.size(); i++){
00393     double err2 = amplitudeErrors_[i]*amplitudeErrors_[i];
00394     double offset = (double(i) - tMaxAlphaBeta)/alphabeta;
00395     double term1 = 1.0 + offset;
00396     if(term1>1e-6){
00397       double f = exp( alpha*(log(1.0+offset) - offset) );
00398       sumAf += amplitudes_[i]*f/err2;
00399       sumff += f*f/err2;
00400     }
00401   }
00402 
00403   if( sumff > 0 ){
00404     ampMaxAlphaBeta  = sumAf/sumff;
00405     double chi2AlphaBeta = (sumAA - sumAf*sumAf/sumff)/sum0;
00406     if(chi2AlphaBeta > NullChi2){
00407       // null hypothesis is better
00408       return;
00409     }
00410 
00411   }else{
00412     // no visible pulse here
00413     return;
00414   }
00415 
00416   // if we got to this point, we have a reconstructied Tmax
00417   // using RatioAlphaBeta Method. To summarize:
00418   //
00419   //     tMaxAlphaBeta      - Tmax value
00420   //     tMaxErrorAlphaBeta - error on Tmax, but I would not trust it
00421   //     ampMaxAlphaBeta    - amplitude of the pulse
00422   //     ampMaxError_        - uncertainty of the time sample with max amplitude
00423   //
00424 
00425 
00426 
00427   // Do Ratio's Method with "large" pulses
00428   if( ampMaxAlphaBeta/ampMaxError_ > 5.0 ){
00429 
00430         // make a vector of Tmax measurements that correspond to each
00431         // ratio. Each measurement have it's value and the error
00432 
00433         double time_max = 0;
00434         double time_wgt = 0;
00435 
00436 
00437         for (unsigned int i = 0; i < ratios_.size(); i++) {
00438 
00439           if(ratios_[i].step == 1
00440               && ratios_[i].value >= timeFitLimits.first
00441               && ratios_[i].value <= timeFitLimits.second
00442             ){
00443 
00444                 double time_max_i = ratios_[i].index;
00445 
00446                 // calculate polynomial for Tmax
00447 
00448                 double u = timeFitParameters[timeFitParameters.size() - 1];
00449                 for (int k = timeFitParameters.size() - 2; k >= 0; k--) {
00450                         u = u * ratios_[i].value + timeFitParameters[k];
00451                 }
00452 
00453                 // calculate derivative for Tmax error
00454                 double du =
00455                     (timeFitParameters.size() -
00456                      1) * timeFitParameters[timeFitParameters.size() - 1];
00457                 for (int k = timeFitParameters.size() - 2; k >= 1; k--) {
00458                         du = du * ratios_[i].value + k * timeFitParameters[k];
00459                 }
00460 
00461 
00462                 // running sums for weighted average
00463                 double errorsquared =
00464                     ratios_[i].error * ratios_[i].error * du * du;
00465                 if (errorsquared > 0) {
00466 
00467                         time_max += (time_max_i - u) / errorsquared;
00468                         time_wgt += 1.0 / errorsquared;
00469                         Tmax currentTmax =
00470                             { ratios_[i].index, 1, (time_max_i - u),
00471                      sqrt(errorsquared),0,1 };
00472                         times_.push_back(currentTmax);
00473 
00474                 }
00475           }
00476         }
00477 
00478 
00479         // calculate weighted average of all Tmax measurements
00480         if (time_wgt > 0) {
00481           tMaxRatio = time_max/time_wgt;
00482           tMaxErrorRatio = 1.0/sqrt(time_wgt);
00483 
00484           // combine RatioAlphaBeta and Ratio Methods
00485 
00486           if( ampMaxAlphaBeta/ampMaxError_ > 10.0 ){
00487 
00488             // use pure Ratio Method
00489             calculatedRechit_.timeMax = tMaxRatio;
00490             calculatedRechit_.timeError = tMaxErrorRatio;
00491 
00492           }else{
00493 
00494             // combine two methods
00495             calculatedRechit_.timeMax = ( tMaxAlphaBeta*(10.0-ampMaxAlphaBeta/ampMaxError_) + tMaxRatio*(ampMaxAlphaBeta/ampMaxError_ - 5.0) )/5.0;
00496             calculatedRechit_.timeError = ( tMaxErrorAlphaBeta*(10.0-ampMaxAlphaBeta/ampMaxError_) + tMaxErrorRatio*(ampMaxAlphaBeta/ampMaxError_ - 5.0) )/5.0;
00497 
00498           }
00499 
00500         }else{
00501 
00502           // use RatioAlphaBeta Method
00503           calculatedRechit_.timeMax = tMaxAlphaBeta;
00504           calculatedRechit_.timeError = tMaxErrorAlphaBeta;
00505 
00506         }
00507 
00508   }else{
00509 
00510     // use RatioAlphaBeta Method
00511     calculatedRechit_.timeMax = tMaxAlphaBeta;
00512     calculatedRechit_.timeError = tMaxErrorAlphaBeta;
00513 
00514   }
00515 }
00516 
00517 template<class C>
00518 void EcalUncalibRecHitRatioMethodAlgo<C>::computeAmplitude( std::vector< double > &amplitudeFitParameters )
00519 {
00521         //                                                            //
00522         //             CALCULATE AMPLITUDE                            //
00523         //                                                            //
00525 
00526 
00527         double alpha = amplitudeFitParameters[0];
00528         double beta = amplitudeFitParameters[1];
00529 
00530         // calculate pedestal, again
00531 
00532         double pedestalLimit = calculatedRechit_.timeMax - (alpha * beta) - 1.0;
00533         double sumA = 0;
00534         double sumF = 0;
00535         double sumAF = 0;
00536         double sumFF = 0;
00537         double sum1 = 0;
00538         for (unsigned int i = 0; i < amplitudes_.size(); i++) {
00539                 double err2 = amplitudeErrors_[i]*amplitudeErrors_[i];
00540                 double f = 0;
00541                 double termOne = 1 + (i - calculatedRechit_.timeMax) / (alpha * beta);
00542                 if (termOne > 1.e-5) f = exp(alpha * log(termOne)) * exp(-(i - calculatedRechit_.timeMax) / beta);
00543 
00544                 // apply range of interesting samples
00545 
00546                 if ( (i < pedestalLimit)
00547                      || (f > 0.6 && i <= calculatedRechit_.timeMax)
00548                      || (f > 0.4 && i >= calculatedRechit_.timeMax)) {
00549                           sum1  += 1/err2;
00550                           sumA  += amplitudes_[i]/err2;
00551                           sumF  += f/err2;
00552                           sumAF += f*amplitudes_[i]/err2;
00553                           sumFF += f*f/err2;
00554                 }
00555         }
00556 
00557         calculatedRechit_.amplitudeMax = 0;
00558         if(sum1 > 0){
00559           double denom = sumFF*sum1 - sumF*sumF;
00560           if(fabs(denom)>1.0e-20){
00561             calculatedRechit_.amplitudeMax = (sumAF*sum1 - sumA*sumF)/denom;
00562           }
00563         }
00564 }
00565 
00566 
00567 
00568 template < class C > EcalUncalibratedRecHit
00569     EcalUncalibRecHitRatioMethodAlgo < C >::makeRecHit(const C & dataFrame,
00570                                                        const EcalSampleMask & sampleMask,
00571                                                        const double *pedestals,
00572                                                        const double *pedestalRMSes,
00573                                                        const double *gainRatios,
00574                                                        std::vector < double >&timeFitParameters,
00575                                                        std::vector < double >&amplitudeFitParameters,
00576                                                        std::pair < double, double >&timeFitLimits)
00577 {
00578 
00579         init( dataFrame, sampleMask, pedestals, pedestalRMSes, gainRatios );
00580         computeTime( timeFitParameters, timeFitLimits, amplitudeFitParameters );
00581         computeAmplitude( amplitudeFitParameters );
00582 
00583         // 1st parameters is id
00584         //
00585         // 2nd parameters is amplitude. It is calculated by this method.
00586         //
00587         // 3rd parameter is pedestal. It is not calculated. This method
00588         // relies on input parameters for pedestals and gain ratio. Return
00589         // zero.
00590         //
00591         // 4th parameter is jitter which is a bad choice to call Tmax. It is
00592         // calculated by this method (in 25 nsec clock units)
00593         //
00594         // GF subtract 5 so that jitter==0 corresponds to synchronous hit
00595         //
00596         //
00597         // 5th parameter is chi2. It is possible to calculate chi2 for
00598         // Tmax. It is possible to calculate chi2 for Amax. However, these
00599         // values are not very useful without TmaxErr and AmaxErr. This
00600         // method can return one value for chi2 but there are 4 different
00601         // parameters that have useful information about the quality of Amax
00602         // ans Tmax. For now we can return TmaxErr. The quality of Tmax and
00603         // Amax can be judged from the magnitude of TmaxErr
00604 
00605         return EcalUncalibratedRecHit(dataFrame.id(),
00606                                       calculatedRechit_.amplitudeMax,
00607                                       pedestal_,
00608                                       calculatedRechit_.timeMax - 5,
00609                                       calculatedRechit_.timeError);
00610 }
00611 #endif