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 unsigned int index;
00024 unsigned int step;
00025 double value;
00026 double error;
00027 };
00028 struct Tmax {
00029 unsigned int index;
00030 unsigned 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 >&litudeFitParameters,
00051 std::pair < double, double >&timeFitLimits);
00052
00053
00054
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 > &litudeFitParameters);
00057 void computeAmplitude( std::vector< double > &litudeFitParameters );
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
00100
00101
00102
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
00124
00125
00126
00127 ampMaxError_ = 0;
00128 double ampMaxValue = -1000;
00129
00130
00131
00132
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
00144
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;
00159 sampleError = 1e+9;
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
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
00183
00184
00185
00186
00187
00188
00189
00190 bool result = false;
00191
00192 int GainIdPrev;
00193 int GainIdNext;
00194 for (int iSample = 1; iSample < C::MAXSAMPLES; iSample++) {
00195
00196
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 >&litudeFitParameters)
00216 {
00218
00219
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
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
00248 return;
00249 }
00250
00251
00252
00253
00254
00255
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
00267 double Rtmp = amplitudes_[i]/amplitudes_[j];
00268
00269
00270
00271
00272 double err1 = Rtmp*Rtmp*( (amplitudeErrors_[i]*amplitudeErrors_[i]/(amplitudes_[i]*amplitudes_[i])) + (amplitudeErrors_[j]*amplitudeErrors_[j]/(amplitudes_[j]*amplitudes_[j])) );
00273
00274
00275 double stat;
00276 if(num_>0) stat = num_;
00277 else stat = 1;
00278 double err2 = amplitudeErrors_[j]*(amplitudes_[i]-amplitudes_[j])/(amplitudes_[j]*amplitudes_[j])/sqrt(stat);
00279
00280
00281
00282 double err3 = 0.289/amplitudes_[j];
00283
00284 double totalError = sqrt(err1 + err2*err2 +err3*err3);
00285
00286
00287
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
00302 if(!ratios_.size() >0)
00303 return;
00304
00305
00306
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
00324 double tmax = 0.5 * (time1 + time2);
00325 double tmaxerr = 0.5 * sqrt( (time1 - time2)*(time1 - time2) );
00326
00327
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
00350
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
00358 if( !(timesAB_.size()> 0))
00359 return;
00360
00361
00362 double chi2min = 1.0e+9;
00363
00364
00365 for(unsigned int i = 0; i < timesAB_.size(); i++){
00366 if( timesAB_[i].chi2 <= chi2min ){
00367 chi2min = timesAB_[i].chi2;
00368
00369
00370 }
00371 }
00372
00373
00374
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
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
00408 return;
00409 }
00410
00411 }else{
00412
00413 return;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 if( ampMaxAlphaBeta/ampMaxError_ > 5.0 ){
00429
00430
00431
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
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
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
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
00480 if (time_wgt > 0) {
00481 tMaxRatio = time_max/time_wgt;
00482 tMaxErrorRatio = 1.0/sqrt(time_wgt);
00483
00484
00485
00486 if( ampMaxAlphaBeta/ampMaxError_ > 10.0 ){
00487
00488
00489 calculatedRechit_.timeMax = tMaxRatio;
00490 calculatedRechit_.timeError = tMaxErrorRatio;
00491
00492 }else{
00493
00494
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
00503 calculatedRechit_.timeMax = tMaxAlphaBeta;
00504 calculatedRechit_.timeError = tMaxErrorAlphaBeta;
00505
00506 }
00507
00508 }else{
00509
00510
00511 calculatedRechit_.timeMax = tMaxAlphaBeta;
00512 calculatedRechit_.timeError = tMaxErrorAlphaBeta;
00513
00514 }
00515 }
00516
00517 template<class C>
00518 void EcalUncalibRecHitRatioMethodAlgo<C>::computeAmplitude( std::vector< double > &litudeFitParameters )
00519 {
00521
00522
00523
00525
00526
00527 double alpha = amplitudeFitParameters[0];
00528 double beta = amplitudeFitParameters[1];
00529
00530
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
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 >&litudeFitParameters,
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
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 return EcalUncalibratedRecHit(dataFrame.id(),
00606 calculatedRechit_.amplitudeMax,
00607 pedestal_,
00608 calculatedRechit_.timeMax - 5,
00609 calculatedRechit_.timeError);
00610 }
00611 #endif