CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/RecoLocalMuon/CSCRecHitD/src/CSCFindPeakTime.cc

Go to the documentation of this file.
00001 // This is CSCFindPeakTime
00002 
00003 #include <RecoLocalMuon/CSCRecHitD/src/CSCFindPeakTime.h>
00004 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00005 
00006 #include <cmath>
00007 
00008 CSCFindPeakTime::CSCFindPeakTime( const edm::ParameterSet& ps ): 
00009   useAverageTime(false), useParabolaFit(false), useFivePoleFit(false) {
00010 
00011   useAverageTime = ps.getParameter<bool>("UseAverageTime");
00012   useParabolaFit = ps.getParameter<bool>("UseParabolaFit");
00013   useFivePoleFit = ps.getParameter<bool>("UseFivePoleFit");
00014   LogTrace("CSCRecHit|CSCFindPeakTime") << "CSCFindPeakTime: useAverageTime=" << useAverageTime <<
00015     ", useParabolaFit=" << useParabolaFit << ", useFivePoleFit=" << useFivePoleFit;
00016 }
00017 
00018 float CSCFindPeakTime::peakTime( int tmax, const float* adc, float t_peak){
00019   if ( useAverageTime ) {
00020     return averageTime( tmax, adc );
00021   }
00022   else if ( useParabolaFit ) {
00023     return parabolaFitTime( tmax, adc );
00024   }
00025   else if ( useFivePoleFit ) {
00026      return fivePoleFitTime( tmax, adc, t_peak);
00027   }
00028   else {
00029   // return something, anyway.. may as well be average
00030     return averageTime( tmax, adc );
00031   }
00032 }
00033 
00034 float CSCFindPeakTime::averageTime( int tmax, const float* adc ) {
00035    float sum  = 0.;
00036    float sumt = 0.;
00037    for (size_t i=0; i<4; ++i){
00038      sum  += adc[i];
00039      sumt += adc[i] * ( tmax - 1 + i );
00040 
00041    }
00042    return sumt/sum * 50.; //@@ in ns. May be some bin width offset things to handle here?
00043 }
00044 
00045 float CSCFindPeakTime::parabolaFitTime( int tmax, const float* adc ) {
00046   // 3-point parabolic fit, from Andy Kubik
00047  
00048   // We calculate offset to tmax by finding the peak of a parabola through three points
00049    float tpeak = tmax;
00050    float tcorr = 0;
00051 
00052    // By construction, input array adc is for bins tmax-1 to tmax+2
00053    float y1 = adc[0];
00054    float y2 = adc[1];
00055    float y3 = adc[2];
00056 
00057    // Checked and simplified... Tim Cox 08-Apr-2009
00058    // Denominator is not zero unless we fed in nonsense values with y2 not the peak!
00059    if ( (y1+y3) < 2.*y2 ) tcorr =  0.5 * ( y1 - y3 ) / ( y1 - 2.*y2 + y3 );
00060    tpeak += tcorr;
00061 
00062    LogTrace("CSCRecHit|CSCFindPeakTime") << "CSCFindPeakTime: tmax=" << tmax 
00063      << ", parabolic peak time is tmax+" << tcorr <<" bins, or " << tpeak*50. << " ns";
00064    
00065    return tpeak * 50.; // convert to ns.
00066 }
00067 
00068 float CSCFindPeakTime::fivePoleFitTime( int tmax, const float* adc, float t_peak ) {
00069 
00070   // Input is 
00071   // tmax   = bin# 0-7 containing max SCA pulse height  
00072   // adc    = 4-dim array containing SCA pulse heights in bins tmax-1 to tmax+2
00073   // t_peak = input estimate for SCA peak time
00074 
00075   // Returned value is improved (we hope) estimate for SCA peak time
00076 
00077   // Algorithm is to fit five-pole Semi-Gaussian function for start time of SCA pulse, t0
00078   // (The SCA peak is assumed to be 133 ns from t0.)
00079   // Note that t^4 in time domain corresponds to 1/t^5 in frequency domain (that's the 5 poles).
00080 
00081   // Initialize parameters to sensible (?) values
00082 
00083   float fpNorm   = adc[1]; // this is tmax bin
00084   float t0       = 0.;
00085   float t0peak   = 133.;   // this is offset of peak from start time t0
00086   float p0       = 4./t0peak;
00087 
00088   // Require that tmax is in range 2-6 of bins the eight SCA time bins 0-7
00089   // (Bins 0, 1 used for dynamic ped)
00090 
00091   if ( tmax < 2 || tmax > 6 ) return t_peak; //@@ Just return the input value
00092 
00093   // Set up time bins to match adc[4] input
00094 
00095   float tb[4];
00096   for ( int time=0; time<4; ++time ){
00097     tb[time] = (tmax + time -1) * 50.;
00098   }
00099 
00100   // How many time bins are we fitting?
00101 
00102   int n_fit  = 4;
00103   if ( tmax == 6 ) n_fit = 3;
00104 
00105   float chi_min  = 1.e10;
00106   float chi_last = 1.e10;
00107   float tt0      = 0.;
00108   float chi2     = 0.;
00109   float del_t    = 100.;
00110 
00111   float x[4];
00112   float sx2 = 0.;
00113   float sxy = 0.;
00114   float fN  = 0.;
00115 
00116   while ( del_t > 1. ) {
00117     sx2 = 0.;
00118     sxy = 0.;
00119         
00120     for ( int j=0; j < n_fit; ++j ) {
00121       float tdif = tb[j] - tt0;
00122       x[j] = tdif * tdif * tdif * tdif * exp( -p0 * tdif );
00123       sx2 += x[j] * x[j];
00124       sxy += x[j] * adc[j];
00125     }
00126     fN = sxy / sx2; // least squares fit over time bins i to adc[i] = fN * fivePoleFunction[i]
00127     
00128     // Compute chi^2
00129     chi2 = 0.0;
00130     for (int j=0; j < n_fit; ++j) chi2 += (adc[j] - fN * x[j]) * (adc[j] - fN * x[j]);
00131 
00132     // Test on chi^2 to decide what to do    
00133     if ( chi_last > chi2 ) {
00134       if (chi2 < chi_min ){
00135         t0      = tt0;
00136         fpNorm  = fN;
00137       }
00138       chi_last  = chi2;
00139       tt0       = tt0 + del_t;
00140     } else {
00141       tt0      = tt0 - 2. * del_t;
00142       del_t    = del_t / 2.;
00143       tt0      = tt0 + del_t;
00144       chi_last = 1.0e10;
00145     }
00146   }
00147 
00148   return t0 + t0peak;
00149 }
00150 
00151 
00152 
00153 void CSCFindPeakTime::fivePoleFitCharge( int tmax, const float* adc, const float& t_zero, const float& t_peak, std::vector<float>& adcsFit ) {
00154 
00155   //@@ This code can certainly be replaced by fivePoleFitTime above, but I haven't time to do that now (Tim).
00156 
00157   float p0  = 4./t_peak;
00158   float tt0 = t_zero;
00159   int n_fit = 4;
00160   if ( tmax == 6 ) n_fit=3;
00161   
00162   float tb[4], y[4];
00163   for ( int t = 0; t < 4; ++t ){
00164     tb[t] = (tmax + t - 1) * 50.;
00165     y[t] = adc[t];
00166   }
00167 
00168   // Find the normalization factor for the function
00169   float x[4];    
00170   float sx2 = 0.;
00171   float sxy = 0.;
00172   for ( int j=0; j < n_fit; ++j ) {
00173     float t = tb[j];
00174     x[j] = (t-tt0)*(t-tt0)*(t-tt0)*(t-tt0) * exp( -p0 * (t-tt0) );
00175     sx2  = sx2 + x[j] * x[j];
00176     sxy  = sxy + x[j] * y[j];
00177   }
00178   float N = sxy / sx2;
00179     
00180 
00181   // Now compute charge for a given t  --> only need charges at: t_peak-50, t_peak and t_peak+50
00182   for ( int i = 0; i < 3; ++i ) {
00183     float t = t_peak + (i - 1) * 50.;
00184     float q_fitted = N * (t-tt0)*(t-tt0)*(t-tt0)*(t-tt0) * exp( -p0 * (t-tt0) );
00185     adcsFit.push_back(q_fitted);
00186   }
00187   return;
00188 }
00189 
00190