CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/RecoParticleFlow/PFClusterTools/src/PFEnergyCalibration.cc

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00002 #include <TMath.h>
00003 #include <math.h>
00004 #include <vector>
00005 #include <TF1.h>
00006 
00007 using namespace std;
00008 
00009 PFEnergyCalibration::PFEnergyCalibration() {
00010 
00011 //--- initialize calibration parameters
00012 //    for energy correction applied to energy deposits of electrons 
00013 //    and photons in ECAL
00014 //  paramECAL_slope_ = 1.;
00015 //  paramECAL_offset_ = 0.;
00016 //  
00019 //  paramHCAL_slope_ = 2.17;
00020 //  paramHCAL_offset_ = 1.73;
00021 //  paramHCAL_damping_ = 2.49;
00022 //
00025 //  paramECALplusHCAL_slopeECAL_ = 1.05;
00026 //  paramECALplusHCAL_slopeHCAL_ = 1.06;
00027 //  paramECALplusHCAL_offset_ = 6.11;
00028         
00029   paramECAL_slope_ = 1.;
00030   paramECAL_offset_ = 0.;
00031   
00032 //--- initialize calibration parameters
00033 //    for energy correction applied to energy deposits of hadrons in HCAL
00034   paramHCAL_slope_ = 1.0;
00035   paramHCAL_offset_ = 0.0;
00036   paramHCAL_damping_ = 1.0;
00037 
00038 //--- initialize calibration parameters
00039 //    for energy correction applied to combined energy deposits of hadrons in HCAL and ECAL
00040   paramECALplusHCAL_slopeECAL_ = 1.0;
00041   paramECALplusHCAL_slopeHCAL_ = 1.0;
00042   paramECALplusHCAL_offset_ = 0.0;
00043 }
00044 
00045 
00046 PFEnergyCalibration::PFEnergyCalibration( double e_slope  , 
00047                                           double e_offset , 
00048                                           double eh_eslope,
00049                                           double eh_hslope,
00050                                           double eh_offset,
00051                                           double h_slope  ,
00052                                           double h_offset ,
00053                                           double h_damping,
00054                                           unsigned newCalib):
00055   
00056   paramECAL_slope_(e_slope),
00057   paramECAL_offset_(e_offset),
00058   paramECALplusHCAL_slopeECAL_(eh_eslope),
00059   paramECALplusHCAL_slopeHCAL_(eh_hslope),
00060   paramECALplusHCAL_offset_(eh_offset),
00061   paramHCAL_slope_(h_slope),
00062   paramHCAL_offset_(h_offset),
00063   paramHCAL_damping_(h_damping) 
00064 {
00065   if ( newCalib == 2 ) initializeCalibrationFunctions();
00066 }
00067 
00068 void
00069 PFEnergyCalibration::initializeCalibrationFunctions() {
00070 
00071   // New calibration with RespCorr factors
00072   // Thresholds
00073   threshE = 3.1;
00074   threshH = 2;
00075 
00076   // Barrel
00077   faBarrel = new TF1("faBarrel","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00078   fbBarrel = new TF1("fbBarrel","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00079   fcBarrel = new TF1("fcBarrel","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00080   faEtaBarrel = new TF1("faEtaBarrel","[0]+[1]*x+[2]*exp(-x/[3])+[4]*[4]*exp(-x*x/([5]*[5]))",1.,1000.);
00081   fbEtaBarrel = new TF1("fbEtaBarrel","[0]+[1]*x+[2]*exp(-x/[3])+[4]*[4]*exp(-x*x/([5]*[5]))",1.,1000.);
00082   faBarrel->SetParameter(0,1.10772);
00083   fbBarrel->SetParameter(0,1.06012);
00084   fcBarrel->SetParameter(0,0.979137);
00085   faEtaBarrel->SetParameter(0,0.02);
00086   fbEtaBarrel->SetParameter(0,-0.02);
00087   faBarrel->SetParameter(1,0.186273);
00088   fbBarrel->SetParameter(1,0.273149);
00089   fcBarrel->SetParameter(1,0.3488);
00090   faBarrel->SetParameter(2,-0.47812);
00091   fbBarrel->SetParameter(2,-0.41739);
00092   fcBarrel->SetParameter(2,-1.04486);
00093   faEtaBarrel->SetParameter(2,-0.102858);
00094   fbEtaBarrel->SetParameter(2,0.14503);
00095   faBarrel->SetParameter(3,62.5754);
00096   fbBarrel->SetParameter(3,46.0841);
00097   fcBarrel->SetParameter(3,18.6968);
00098   faEtaBarrel->SetParameter(3,337.536);
00099   fbEtaBarrel->SetParameter(3,273.008);
00100   faBarrel->SetParameter(4,1.31965);
00101   fbBarrel->SetParameter(4,1.40679);
00102   fcBarrel->SetParameter(4,0.68429);
00103   faEtaBarrel->SetParameter(4,0.653127);
00104   fbEtaBarrel->SetParameter(4,0.0967542);
00105   faBarrel->SetParameter(5,35.2559);
00106   fbBarrel->SetParameter(5,30.2377);
00107   fcBarrel->SetParameter(5,22.5488);
00108   faEtaBarrel->SetParameter(5,4.73068);
00109   fbEtaBarrel->SetParameter(5,36.6991);
00110 
00111   // Endcap
00112   faEndcap = new TF1("faEndcap","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00113   fbEndcap = new TF1("fbEndcap","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00114   fcEndcap = new TF1("fcEndcap","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00115   faEtaEndcap = new TF1("faEtaEndcap","[0]+[1]*exp(-x/[2])+[3]*[3]*exp(-x*x/([4]*[4]))",1.,1000.);
00116   fbEtaEndcap = new TF1("fbEtaEndcap","[0]+[1]*exp(-x/[2])+[3]*[3]*exp(-x*x/([4]*[4]))",1.,1000.);
00117   faEndcap->SetParameter(0,1.0877);
00118   fbEndcap->SetParameter(0,0.984949);
00119   fcEndcap->SetParameter(0,0.932945);
00120   faEtaEndcap->SetParameter(0,-0.0109133);
00121   fbEtaEndcap->SetParameter(0,0.025622);
00122   faEndcap->SetParameter(1,0.28939);
00123   fbEndcap->SetParameter(1,0.378368);
00124   fcEndcap->SetParameter(1,0.100645);
00125   faEtaEndcap->SetParameter(1,-0.103459);
00126   fbEtaEndcap->SetParameter(1,-2.58821);
00127   faEndcap->SetParameter(2,-0.57635);
00128   fbEndcap->SetParameter(2,-1.4482);
00129   fcEndcap->SetParameter(2,-0.0718337);
00130   faEtaEndcap->SetParameter(2,180.264);
00131   fbEtaEndcap->SetParameter(2,5.87477);
00132   faEndcap->SetParameter(3,86.5501);
00133   fbEndcap->SetParameter(3,68.4813);
00134   fcEndcap->SetParameter(3,46.8387);
00135   faEtaEndcap->SetParameter(3,0.642761);
00136   fbEtaEndcap->SetParameter(3,0.365089);
00137   faEndcap->SetParameter(4,1.02296);
00138   fbEndcap->SetParameter(4,0.596373);
00139   fcEndcap->SetParameter(4,0.809857);
00140   faEtaEndcap->SetParameter(4,14.9234);
00141   fbEtaEndcap->SetParameter(4,236.042);
00142   faEndcap->SetParameter(5,64.0116);
00143   fbEndcap->SetParameter(5,117.031);
00144   fcEndcap->SetParameter(5,57.1931);
00145 
00146 }
00147 
00148 void 
00149 PFEnergyCalibration::energyEmHad(double t, double& e, double&h, double eta, double phi) const { 
00150  
00151   
00152   // Use calorimetric energy as true energy for neutral particles
00153   double tt = t;
00154   double ee = e;
00155   double hh = h;
00156   double a = 1.;
00157   double b = 1.;
00158   double etaCorr = 1.;
00159   t = min(1000.,max(tt,e+h));
00160 
00161   // Barrel calibration
00162   if ( fabs(eta) < 1.48 ) { 
00163 
00164     // Fudge factors for fast sim 
00165     // Fudge factors in ECAL crack (correction#0, removed)
00166     /*
00167     if ( eta>1.4) h *=0.90;
00168     else if ( eta>1.3 ) h *=0.86;
00169     else if ( eta>1.2 ) h *=0.95;
00170     */
00171 
00172     // The energy correction
00173     a = e>0. ? faBarrel->Eval(t) : 1.;
00174     b = e>0. ? fbBarrel->Eval(t) : fcBarrel->Eval(t);
00175     double thresh = e > 0. ? threshE : threshH;
00176 
00177     // Protection against negative calibration - to be tuned
00178     if ( a < 0. || b < 0. ) { 
00179       a = 1.;
00180       b = 1.;
00181       thresh = 0.;
00182     }
00183 
00184     // The new estimate of the true energy
00185     t = min(1000.,max(tt, thresh+a*e+b*h));
00186 
00187     // The angular correction for ECAL hadronic deposits
00188     etaCorr = 1. + faEtaBarrel->Eval(t) + fbEtaBarrel->Eval(t)*fabs(eta);
00189     // etaCorr = 1.;
00190     t = max(tt, thresh+etaCorr*a*e+b*h);
00191 
00192     if ( e > 0. && thresh > 0. ) 
00193       e = h > 0. ? threshE-threshH + etaCorr * a * e : threshE + etaCorr * a * e;
00194     if ( h > 0. && thresh > 0. ) 
00195       h = threshH + b * h;
00196 
00197     if ( etaCorr > 2. || etaCorr < 0.5 ) 
00198       std::cout << "Warning : Angular correction ! " << std::endl
00199                 << "etaCorr,eta,t = " << etaCorr << " " << eta << " " << t << std::endl;
00200 
00201   // Endcap calibration   
00202   } else {
00203 
00204     // Fudge factor in endcap (correction #2)
00205 
00206     // The energy correction
00207     a = e>0. ? faEndcap->Eval(t) : 1.;
00208     b = e>0. ? fbEndcap->Eval(t) : fcEndcap->Eval(t);
00209     double thresh = e > 0. ? threshE : threshH;
00210 
00211     if ( a < 0. || b < 0. ) { 
00212       a = 1.;
00213       b = 1.;
00214       thresh = 0.;
00215     }
00216     // Fudge factor fast sim
00217     // b *= 1.03;
00218 
00219     // The new estimate of the true energy
00220     t = min(1000.,max(tt, thresh+a*e+b*h));
00221     
00222     // The angular correction
00223     // That's to compensate for a possible bug in HCALRespCorr's coefficients
00224     if ( fabs(eta)>2.0 && fabs(eta)<2.65 ) h *= (1+0.2*(fabs(eta)-2.0));
00225     // And that's the real eta dependence
00226     if ( fabs(eta) < 2.65 ) 
00227       etaCorr = 1. + faEtaEndcap->Eval(t) + fbEtaEndcap->Eval(t)*(fabs(eta)-1.48);
00228     /*
00229     if ( etaCorr > 2. || etaCorr < 0.5 ) 
00230       std::cout << "Warning : Angular correction ! " << std::endl
00231                 << "etaCorr,eta,t = " << etaCorr << " " << eta << " " << tt 
00232                 << " ee,hh,e,h = " << e << " " << h << " " << a*e << " " << b*h  
00233                 << std::endl;
00234     */
00235 
00236     t = min(1000.,max(tt, thresh+etaCorr*a*e+b*h));
00237 
00238     if ( e > 0. && thresh > 0. ) 
00239       e = h > 0. ? threshE-threshH + etaCorr * a * e : threshE + etaCorr * a * e;
00240     if ( h > 0. && thresh > 0. ) 
00241       h = threshH + b * h;
00242 
00243 
00244   }
00245 
00246   // Protection
00247   if ( e < 0. || h < 0. ) { 
00248     std::cout << "Warning : Energy correction ! " << std::endl
00249               << "eta,tt,e,h,a,b = " << eta << " " << tt << " " 
00250               << ee << "/" << e << " " << hh << "/" << h << " " << a << " " << b << std::endl;
00251     // Some protection against crazy calibration
00252     if ( e < 0. ) e = ee;
00253     if ( h < 0. ) h = hh;
00254   }
00255 
00256   // And that's it !
00257 
00258   
00259 }
00260 
00261 
00262 
00263 void PFEnergyCalibration::setCalibrationParametersEm(double paramECAL_slope, 
00264                                                      double paramECAL_offset) {
00265 
00266 //--- set calibration parameters for energy deposits of electrons 
00267 //    and photons in ECAL;
00268 //    this member function is needed by PFRootEvent
00269 
00270   paramECAL_slope_ = paramECAL_slope;
00271   paramECAL_offset_ = paramECAL_offset;
00272 }
00273 
00274 
00275 
00276 PFEnergyCalibration::~PFEnergyCalibration()
00277 {
00278 //--- nothing to be done yet  
00279 }
00280 
00281 
00282 double 
00283 PFEnergyCalibration::energyEm(double uncalibratedEnergyECAL, 
00284                               double eta, double phi) const {
00285 
00286   //--- apply calibration correction
00287   //    for energy deposits of electrons and photons in ECAL
00288   //    (eta and phi dependence not implemented yet)
00289   
00290   double calibrated = paramECAL_slope_*uncalibratedEnergyECAL;
00291   calibrated += paramECAL_offset_;
00292 
00293   return calibrated;
00294 }
00295 
00296 
00297 double
00298 PFEnergyCalibration::energyEm(const reco::PFCluster& clusterEcal,
00299                               std::vector<double> &EclustersPS1,
00300                               std::vector<double> &EclustersPS2,
00301                               bool crackCorrection ){
00302   double eEcal = clusterEcal.energy();
00303   //temporaty ugly fix
00304   reco::PFCluster myPFCluster=clusterEcal;
00305   myPFCluster.calculatePositionREP();
00306   double eta = myPFCluster.positionREP().eta();
00307   double phi = myPFCluster.positionREP().phi();
00308 
00309   double ePS1 = 0;
00310   double ePS2 = 0;
00311 
00312   for(unsigned i=0;i<EclustersPS1.size();i++) ePS1 += EclustersPS1[i];
00313   for(unsigned i=0;i<EclustersPS2.size();i++) ePS2 += EclustersPS2[i];
00314 
00315   double calibrated = Ecorr(eEcal,ePS1,ePS2,eta,phi, crackCorrection);
00316   if(eEcal!=0 && calibrated==0) std::cout<<"Eecal = "<<eEcal<<"  eta = "<<eta<<"  phi = "<<phi<<std::endl; 
00317   return calibrated; 
00318 }
00319 
00320 double PFEnergyCalibration::energyEm(const reco::PFCluster& clusterEcal,
00321                                      std::vector<double> &EclustersPS1,
00322                                      std::vector<double> &EclustersPS2,
00323                                      double& ps1,double& ps2,
00324                                      bool crackCorrection){
00325   double eEcal = clusterEcal.energy();
00326   //temporaty ugly fix
00327   reco::PFCluster myPFCluster=clusterEcal;
00328   myPFCluster.calculatePositionREP();
00329   double eta = myPFCluster.positionREP().eta();
00330   double phi = myPFCluster.positionREP().phi();
00331 
00332   double ePS1 = 0;
00333   double ePS2 = 0;
00334 
00335   for(unsigned i=0;i<EclustersPS1.size();i++) ePS1 += EclustersPS1[i];
00336   for(unsigned i=0;i<EclustersPS2.size();i++) ePS2 += EclustersPS2[i];
00337 
00338   double calibrated = Ecorr(eEcal,ePS1,ePS2,eta,phi,ps1,ps2,crackCorrection);
00339   if(eEcal!=0 && calibrated==0) std::cout<<"Eecal = "<<eEcal<<"  eta = "<<eta<<"  phi = "<<phi<<std::endl; 
00340   return calibrated; 
00341 }
00342 
00343 
00344 double 
00345 PFEnergyCalibration::energyHad(double uncalibratedEnergyHCAL, 
00346                                double eta, double phi) const {
00347   
00348   //--- apply calibration correction
00349   //    for energy deposits of hadrons in HCAL
00350   //    (eta and phi dependence not implemented yet)
00351   
00352   double numerator = paramHCAL_slope_*uncalibratedEnergyHCAL;
00353   numerator += paramHCAL_offset_;
00354 
00355   double denominator = 1 + exp(paramHCAL_damping_/uncalibratedEnergyHCAL);
00356 
00357 
00358   return numerator/denominator;
00359 }
00360 
00361 
00362 double 
00363 PFEnergyCalibration::energyEmHad(double uncalibratedEnergyECAL, 
00364                                  double uncalibratedEnergyHCAL, 
00365                                  double eta, double phi) const {
00366 //--- apply calibration correction
00367 //    for energy deposits of hadrons in ECAL and HCAL
00368 //    (eta and phi dependence not implemented yet)
00369 
00370   double calibrated = paramECALplusHCAL_slopeECAL_*uncalibratedEnergyECAL;
00371   calibrated += paramECALplusHCAL_slopeHCAL_*uncalibratedEnergyHCAL;
00372   calibrated += paramECALplusHCAL_offset_;
00373 
00374   return calibrated;
00375 }
00376   
00377 std::ostream& operator<<(std::ostream& out, 
00378                          const PFEnergyCalibration& calib) {
00379 
00380   if(!out ) return out;
00381 
00382   out<<"PFEnergyCalibration -- "<<endl;
00383   out<<"ecal      = "<<calib.paramECAL_slope_
00384      <<" x E + "<< calib.paramECAL_offset_<<endl;
00385   out<<"hcal only = <add formula>"
00386      <<calib.paramHCAL_slope_<<","
00387      <<calib.paramHCAL_offset_<<","
00388      <<calib.paramHCAL_damping_<<endl;
00389   out<<"ecal+hcal = "<<calib.paramECALplusHCAL_slopeECAL_<<" x E_e + "
00390      <<calib.paramECALplusHCAL_slopeHCAL_<<" x E_h + "
00391      <<calib.paramECALplusHCAL_offset_<<endl;
00392 
00393   return out;
00394 }
00395 
00396 
00397 
00398 
00411 
00412 
00413 
00419 
00420 
00421 //useful to compute the signed distance to the closest crack in the barrel
00422 double
00423 PFEnergyCalibration::minimum(double a,double b){
00424   if(TMath::Abs(b)<TMath::Abs(a)) a=b;
00425   return a;
00426 }
00427 
00428 
00429 //compute the unsigned distance to the closest phi-crack in the barrel
00430 double
00431 PFEnergyCalibration::dCrackPhi(double phi, double eta){
00432 
00433   static double pi= M_PI;// 3.14159265358979323846;
00434   
00435   //Location of the 18 phi-cracks
00436   static std::vector<double> cPhi;
00437   if(cPhi.size()==0)
00438     {
00439       cPhi.resize(18,0);
00440       cPhi[0]=2.97025;
00441       for(unsigned i=1;i<=17;++i) cPhi[i]=cPhi[0]-2*i*pi/18;
00442     }
00443 
00444   //Shift of this location if eta<0
00445   static double delta_cPhi=0.00638;
00446 
00447   double m; //the result
00448 
00449   //the location is shifted
00450   if(eta<0) phi +=delta_cPhi;
00451 
00452   if (phi>=-pi && phi<=pi){
00453 
00454     //the problem of the extrema
00455     if (phi<cPhi[17] || phi>=cPhi[0]){
00456       if (phi<0) phi+= 2*pi;
00457       m = minimum(phi -cPhi[0],phi-cPhi[17]-2*pi);              
00458     }
00459 
00460     //between these extrema...
00461     else{
00462       bool OK = false;
00463       unsigned i=16;
00464       while(!OK){
00465         if (phi<cPhi[i]){
00466           m=minimum(phi-cPhi[i+1],phi-cPhi[i]);
00467           OK=true;
00468         }
00469         else i-=1;
00470       }
00471     }
00472   }
00473   else{
00474     m=0.;        //if there is a problem, we assum that we are in a crack
00475     std::cout<<"Problem in dminphi"<<std::endl;
00476   }
00477   if(eta<0) m=-m;   //because of the disymetry
00478   return m;
00479 }
00480 
00481 // corrects the effect of phi-cracks
00482 double
00483 PFEnergyCalibration::CorrPhi(double phi, double eta) {
00484 
00485   // we use 3 gaussians to correct the phi-cracks effect
00486   static double p1=   5.59379e-01;
00487   static double p2=   -1.26607e-03;
00488   static double p3=  9.61133e-04;
00489 
00490   static double p4=   1.81691e-01;
00491   static double p5=   -4.97535e-03;
00492   static double p6=   1.31006e-03;
00493 
00494   static double p7=   1.38498e-01;
00495   static double p8=   1.18599e-04;
00496   static double p9= 2.01858e-03;
00497   
00498 
00499   double dminphi = dCrackPhi(phi,eta);
00500   
00501   double result = (1+p1*TMath::Gaus(dminphi,p2,p3)+p4*TMath::Gaus(dminphi,p5,p6)+p7*TMath::Gaus(dminphi,p8,p9));
00502 
00503   return result;
00504 }   
00505 
00506 
00507 // corrects the effect of  |eta|-cracks
00508 double
00509 PFEnergyCalibration::CorrEta(double eta){
00510   
00511   // we use a gaussian with a screwness for each of the 5 |eta|-cracks
00512   static std::vector<double> a;  //amplitude
00513   static std::vector<double> m;  //mean
00514   static std::vector<double> s;  //sigma
00515   static std::vector<double> sa; // screwness amplitude
00516   static std::vector<double> ss; // screwness sigma
00517 
00518   if(a.size()==0)
00519     {
00520       a.push_back(6.13349e-01) ;a.push_back(5.08146e-01)  ;a.push_back(4.44480e-01) ;a.push_back(3.3487e-01)   ;a.push_back(7.65627e-01) ;
00521       m.push_back(-1.79514e-02);m.push_back(4.44747e-01)  ;m.push_back(7.92824e-01) ;m.push_back(1.14090e+00)  ;m.push_back(1.47464e+00) ;
00522       s.push_back(7.92382e-03) ;s.push_back(3.06028e-03)  ;s.push_back(3.36139e-03) ;s.push_back(3.94521e-03)  ;s.push_back(8.63950e-04) ;
00523       sa.push_back(1.27228e+01);sa.push_back(3.81517e-02) ;sa.push_back(1.63507e-01);sa.push_back(-6.56480e-02);sa.push_back(1.87160e-01);
00524       ss.push_back(5.48753e-02);ss.push_back(-1.00223e-02);ss.push_back(2.22866e-03);ss.push_back(4.26288e-04) ;ss.push_back(2.67937e-03);
00525     }
00526  double result = 1;
00527 
00528  for(unsigned i=0;i<=4;i++) result+=a[i]*TMath::Gaus(eta,m[i],s[i])*(1+sa[i]*TMath::Sign(1.,eta-m[i])*TMath::Exp(-TMath::Abs(eta-m[i])/ss[i]));
00529 
00530   return result;
00531 }
00532 
00533 
00534 //corrects the global behaviour in the barrel
00535 double
00536 PFEnergyCalibration::CorrBarrel(double E, double eta) {
00537 
00538   //Energy dependency
00539   static double p0=1.00000e+00;
00540   static double p1=3.27753e+01;
00541   static double p2=2.28552e-02;
00542   static double p3=3.06139e+00;
00543   static double p4=2.25135e-01;
00544   static double p5=1.47824e+00;
00545   static double p6=1.09e-02;
00546   static double p7=4.19343e+01;
00547 
00548   //Eta dependency
00549   static double p8=2.705593e-03;
00550 
00551   double result = (p0+1/(p1+p2*TMath::Power(E,p3))+p4*TMath::Exp(-E/p5)+p6*TMath::Exp(-E*E/(p7*p7)))*(1+p8*eta*eta);
00552 
00553   return result;
00554 }
00555 
00556 
00557 
00566 
00567 
00568 //Alpha, Beta, Gamma give the weight of each sub-detector (PS layer1, PS layer2 and Ecal) in the areas of the endcaps where there is a PS
00569 // Etot = Beta*eEcal + Gamma*(ePS1 + Alpha*ePS2) 
00570 
00571 double
00572 PFEnergyCalibration::Alpha(double eta) {
00573 
00574   //Energy dependency
00575   static double p0 = 5.97621e-01;
00576 
00577   //Eta dependency
00578   static double p1 =-1.86407e-01;
00579   static double p2 = 3.85197e-01; 
00580 
00581   //so that <feta()> = 1
00582   static double norm = (p1+p2*(2.6+1.656)/2);
00583 
00584   double result = p0*(p1+p2*eta)/norm;
00585 
00586   return result;
00587 }
00588 
00589 double
00590 PFEnergyCalibration::Beta(double E, double eta) {
00591 
00592  //Energy dependency
00593   static double p0 = 0.032;
00594   static double p1 = 9.70394e-02;
00595   static double p2 = 2.23072e+01;
00596   static double p3 = 100;
00597 
00598   //Eta dependency
00599   static double p4 = 1.02496e+00 ;
00600   static double p5 = -4.40176e-03 ;
00601 
00602   //so that <feta()> = 1
00603   static double norm = (p4+p5*(2.6+1.656)/2);
00604 
00605   double result = (1.0012+p0*TMath::Exp(-E/p3)+p1*TMath::Exp(-E/p2))*(p4+p5*eta)/norm;                    
00606   return result;
00607 }
00608 
00609 
00610 double
00611 PFEnergyCalibration::Gamma(double etaEcal) {
00612 
00613  //Energy dependency
00614   static double p0 = 2.49752e-02;
00615 
00616   //Eta dependency
00617   static double p1 = 6.48816e-02;
00618   static double p2 = -1.59517e-02; 
00619  
00620   //so that <feta()> = 1
00621   static double norm = (p1+p2*(2.6+1.656)/2);
00622 
00623   double result = p0*(p1+p2*etaEcal)/norm;                                        
00624 
00625   return result;
00626 }
00627 
00628 
00629 
00635 
00636 
00637 // returns the corrected energy in the barrel (0,1.48)
00638 // Global Behaviour, phi and eta cracks are taken into account
00639 double
00640 PFEnergyCalibration::EcorrBarrel(double E, double eta, double phi,
00641                                  bool crackCorrection ){
00642 
00643   // double result = E*CorrBarrel(E,eta)*CorrEta(eta)*CorrPhi(phi,eta);
00644   double correction = crackCorrection ? std::max(CorrEta(eta),CorrPhi(phi,eta)) : 1.;
00645   double result = E * CorrBarrel(E,eta) * correction;
00646 
00647   return result;
00648 }
00649 
00650 
00651 // returns the corrected energy in the area between the barrel and the PS (1.48,1.65)
00652 double
00653 PFEnergyCalibration::EcorrZoneBeforePS(double E, double eta){
00654 
00655  //Energy dependency
00656   static double p0 =1; 
00657   static double p1 =0.18;
00658   static double p2 =8.;
00659 
00660   //Eta dependency
00661   static double p3 =0.3;
00662   static double p4 =1.11;
00663   static double p5 =0.025;
00664   static double p6 =1.49;
00665   static double p7 =0.6;
00666 
00667   //so that <feta()> = 1
00668   static double norm = 1.21;
00669 
00670   double result = E*(p0+p1*TMath::Exp(-E/p2))*(p3+p4*TMath::Gaus(eta,p6,p5)+p7*eta)/norm;
00671 
00672   return result;
00673 }
00674 
00675 
00676 // returns the corrected energy in the PS (1.65,2.6)
00677 // only when (ePS1>0)||(ePS2>0)
00678 double
00679 PFEnergyCalibration::EcorrPS(double eEcal,double ePS1,double ePS2,double etaEcal) {
00680 
00681   // gives the good weights to each subdetector
00682   double E = Beta(1.0155*eEcal+0.025*(ePS1+0.5976*ePS2)/9e-5,etaEcal)*eEcal+Gamma(etaEcal)*(ePS1+Alpha(etaEcal)*ePS2)/9e-5 ;
00683 
00684   //Correction of the residual energy dependency
00685   static double p0 = 1.00;
00686   static double p1 = 2.18;
00687   static double p2 =1.94;
00688   static double p3 =4.13;
00689   static double p4 =1.127;
00690 
00691   double result = E*(p0+p1*TMath::Exp(-E/p2)-p3*TMath::Exp(-E/p4));
00692 
00693   return result;
00694 } 
00695 
00696 // returns the corrected energy in the PS (1.65,2.6)
00697 // only when (ePS1>0)||(ePS2>0)
00698 double
00699 PFEnergyCalibration::EcorrPS(double eEcal,double ePS1,double ePS2,double etaEcal,double & outputPS1, double & outputPS2) {
00700 
00701   // gives the good weights to each subdetector
00702   double gammaprime=Gamma(etaEcal)/9e-5;
00703   outputPS1=gammaprime*ePS1;
00704   outputPS2=gammaprime*Alpha(etaEcal)*ePS2;
00705   double E = Beta(1.0155*eEcal+0.025*(ePS1+0.5976*ePS2)/9e-5,etaEcal)*eEcal+outputPS1+outputPS2;
00706 
00707   //Correction of the residual energy dependency
00708   static double p0 = 1.00;
00709   static double p1 = 2.18;
00710   static double p2 =1.94;
00711   static double p3 =4.13;
00712   static double p4 =1.127;
00713   
00714   double corrfac=(p0+p1*TMath::Exp(-E/p2)-p3*TMath::Exp(-E/p4));
00715   outputPS1*=corrfac;
00716   outputPS2*=corrfac;
00717   double result = E*corrfac;
00718 
00719   return result;
00720 } 
00721 
00722 
00723 // returns the corrected energy in the PS (1.65,2.6)
00724 // only when (ePS1=0)&&(ePS2=0)
00725 double 
00726 PFEnergyCalibration::EcorrPS_ePSNil(double eEcal,double eta){
00727 
00728   //Energy dependency
00729   static double p0= 1.02;
00730   static double p1= 0.165;
00731   static double p2= 6.5 ;
00732   static double p3=  2.1 ;
00733 
00734   //Eta dependency
00735   static double p4 = 1.02496e+00 ;
00736   static double p5 = -4.40176e-03 ;
00737 
00738   //so that <feta()> = 1
00739   static double norm = (p4+p5*(2.6+1.656)/2);
00740 
00741   double result = eEcal*(p0+p1*TMath::Exp(-TMath::Abs(eEcal-p3)/p2))*(p4+p5*eta)/norm;
00742                   
00743   return result;
00744 }
00745 
00746 
00747 // returns the corrected energy in the area between the end of the PS and the end of the endcap (2.6,2.98)
00748 double
00749 PFEnergyCalibration::EcorrZoneAfterPS(double E, double eta){
00750 
00751   //Energy dependency
00752   static double p0 =1; 
00753   static double p1 = 0.058;
00754   static double p2 =12.5;
00755   static double p3 =-1.05444e+00;
00756   static double p4 =-5.39557e+00;
00757   static double p5 =8.38444e+00;
00758   static double p6 = 6.10998e-01  ;
00759 
00760   //Eta dependency
00761   static double p7 =1.06161e+00;
00762   static double p8 = 0.41;
00763   static double p9 =2.918;
00764   static double p10 =0.0181;
00765   static double p11= 2.05;
00766   static double p12 =2.99;
00767   static double p13=0.0287;
00768 
00769   //so that <feta()> = 1
00770   static double norm=1.045;
00771 
00772   double result = E*(p0+p1*TMath::Exp(-(E-p3)/p2)+1/(p4+p5*TMath::Power(E,p6)))*(p7+p8*TMath::Gaus(eta,p9,p10)+p11*TMath::Gaus(eta,p12,p13))/norm;
00773   return result;
00774 }
00775 
00776 
00777 
00778 
00779 // returns the corrected energy everywhere
00780 // this work should be improved between 1.479 and 1.52 (junction barrel-endcap)
00781 double
00782 PFEnergyCalibration::Ecorr(double eEcal,double ePS1,double ePS2,
00783                            double eta,double phi,
00784                            bool crackCorrection ) {
00785 
00786   static double endBarrel=1.48;
00787   static double beginingPS=1.65;
00788   static double endPS=2.6;
00789   static double endEndCap=2.98;
00790  
00791   double result=0;
00792 
00793   eta=TMath::Abs(eta);
00794 
00795   if(eEcal>0){
00796     if(eta <= endBarrel)                         result = EcorrBarrel(eEcal,eta,phi,crackCorrection);
00797     else if(eta <= beginingPS)                   result = EcorrZoneBeforePS(eEcal,eta);
00798     else if((eta < endPS) && ePS1==0 && ePS2==0) result = EcorrPS_ePSNil(eEcal,eta);
00799     else if(eta < endPS)                         result = EcorrPS(eEcal,ePS1,ePS2,eta);
00800     else if(eta < endEndCap)                     result = EcorrZoneAfterPS(eEcal,eta); 
00801     else result =eEcal;
00802   }
00803   else result = eEcal;// useful if eEcal=0 or eta>2.98
00804   //protection
00805   if(result<eEcal) result=eEcal;
00806   return result;
00807 }
00808 
00809 // returns the corrected energy everywhere
00810 // this work should be improved between 1.479 and 1.52 (junction barrel-endcap)
00811 double
00812 PFEnergyCalibration::Ecorr(double eEcal,double ePS1,double ePS2,double eta,double phi,double& ps1,double&ps2,bool crackCorrection)  {
00813 
00814   static double endBarrel=1.48;
00815   static double beginingPS=1.65;
00816   static double endPS=2.6;
00817   static double endEndCap=2.98;
00818  
00819   double result=0;
00820 
00821   eta=TMath::Abs(eta);
00822 
00823   if(eEcal>0){
00824     if(eta <= endBarrel)                         result = EcorrBarrel(eEcal,eta,phi,crackCorrection);
00825     else if(eta <= beginingPS)                   result = EcorrZoneBeforePS(eEcal,eta);
00826     else if((eta < endPS) && ePS1==0 && ePS2==0) result = EcorrPS_ePSNil(eEcal,eta);
00827     else if(eta < endPS)                         result = EcorrPS(eEcal,ePS1,ePS2,eta,ps1,ps2);
00828     else if(eta < endEndCap)                     result = EcorrZoneAfterPS(eEcal,eta); 
00829     else result =eEcal;
00830   }
00831   else result = eEcal;// useful if eEcal=0 or eta>2.98
00832   // protection
00833   if(result<eEcal) result=eEcal;
00834   return result;
00835 }