CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00002 #include "CondFormats/PhysicsToolsObjects/interface/PerformancePayloadFromTFormula.h"
00003 #include <TMath.h>
00004 #include <math.h>
00005 #include <vector>
00006 #include <TF1.h>
00007 #include <map>
00008 #include <algorithm>
00009 
00010 using namespace std;
00011 
00012 PFEnergyCalibration::PFEnergyCalibration() : pfCalibrations(0)
00013 {
00014   initializeCalibrationFunctions();
00015 }
00016 
00017 PFEnergyCalibration::~PFEnergyCalibration() 
00018 {
00019 
00020   delete faBarrel;
00021   delete fbBarrel;
00022   delete fcBarrel;
00023   delete faEtaBarrel;
00024   delete fbEtaBarrel;
00025   delete faEndcap;
00026   delete fbEndcap;
00027   delete fcEndcap;
00028   delete faEtaEndcap;
00029   delete fbEtaEndcap;
00030 
00031 }
00032 
00033 void
00034 PFEnergyCalibration::initializeCalibrationFunctions() {
00035 
00036   // NEW NEW with HCAL pre-calibration
00037 
00038   threshE = 3.5;
00039   threshH = 2.5;
00040 
00041   // Barrel (fit made with |eta| < 1.2)
00042   faBarrel = new TF1("faBarrel","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00043   fbBarrel = new TF1("fbBarrel","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00044   fcBarrel = new TF1("fcBarrel","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00045   faEtaBarrel = new TF1("faEtaBarrel","[0]+[1]*exp(-x/[2])",1.,1000.);
00046   fbEtaBarrel = new TF1("fbEtaBarrel","[0]+[1]*exp(-x/[2])+[3]*[3]*exp(-x*x/([4]*[4]))",1.,1000.);
00047   faBarrel->SetParameter(0,1.15665);
00048   fbBarrel->SetParameter(0,0.994603);
00049   fcBarrel->SetParameter(0,0.956544);
00050   faEtaBarrel->SetParameter(0,0.014664);
00051   fbEtaBarrel->SetParameter(0,0.00975451);
00052   faBarrel->SetParameter(1,0.165627);
00053   fbBarrel->SetParameter(1,0.13632);
00054   fcBarrel->SetParameter(1,0.0857207);
00055   faEtaBarrel->SetParameter(1,-0.0426776);
00056   fbEtaBarrel->SetParameter(1,0.102247);
00057   faBarrel->SetParameter(2,0.827718);
00058   fbBarrel->SetParameter(2,-0.758013);
00059   fcBarrel->SetParameter(2,-0.44347);
00060   faEtaBarrel->SetParameter(2,431.054);
00061   fbEtaBarrel->SetParameter(2,436.21);
00062   faBarrel->SetParameter(3,231.339);
00063   fbBarrel->SetParameter(3,183.627);
00064   fcBarrel->SetParameter(3,63.3479);
00065   faBarrel->SetParameter(4,2.45332);
00066   fbBarrel->SetParameter(4,1);
00067   fcBarrel->SetParameter(4,1.24174);
00068   faBarrel->SetParameter(5,29.6603);
00069   fbBarrel->SetParameter(5,39.6784);
00070   fcBarrel->SetParameter(5,12.322);
00071 
00072   // End-caps (fit made with eta 
00073   faEndcap = new TF1("faEndcap","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00074   fbEndcap = new TF1("fbEndcap","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00075   fcEndcap = new TF1("fcEndcap","[0]+([1]+[2]/sqrt(x))*exp(-x/[3])-[4]*exp(-x*x/[5])",1.,1000.);
00076   faEtaEndcap = new TF1("faEtaEndcap","[0]+[1]*exp(-x/[2])",1.,1000.);
00077   fbEtaEndcap = new TF1("fbEtaEndcap","[0]+[1]*exp(-x/[2])+[3]*[3]*exp(-x*x/([4]*[4]))",1.,1000.);
00078   faEndcap->SetParameter(0,1.1272);
00079   fbEndcap->SetParameter(0,0.982824);
00080   fcEndcap->SetParameter(0,0.950244);
00081   faEtaEndcap->SetParameter(0,-0.000582903);
00082   fbEtaEndcap->SetParameter(0,0.0267319);
00083   faEndcap->SetParameter(1,0.258536);
00084   fbEndcap->SetParameter(1,0.0977533);
00085   fcEndcap->SetParameter(1,0.00564779);
00086   faEtaEndcap->SetParameter(1,-0.000482148);
00087   fbEtaEndcap->SetParameter(1,-0.554552);
00088   faEndcap->SetParameter(2,0.808071);
00089   fbEndcap->SetParameter(2,0.155416);
00090   fcEndcap->SetParameter(2,0.227162);
00091   faEtaEndcap->SetParameter(2,209.466);
00092   fbEtaEndcap->SetParameter(2,1.71188);
00093   faEndcap->SetParameter(3,214.039);
00094   fbEndcap->SetParameter(3,240.379);
00095   fcEndcap->SetParameter(3,207.786);
00096   fbEtaEndcap->SetParameter(3,0.235834);
00097   faEndcap->SetParameter(4,2);
00098   fbEndcap->SetParameter(4,1.2);
00099   fcEndcap->SetParameter(4,1.32824);
00100   fbEtaEndcap->SetParameter(4,-135.431);
00101   faEndcap->SetParameter(5,47.2602);
00102   fbEndcap->SetParameter(5,78.3083);
00103   fcEndcap->SetParameter(5,22.1825);
00104   
00105 }
00106 
00107 void 
00108 PFEnergyCalibration::energyEmHad(double t, double& e, double&h, double eta, double phi) const { 
00109  
00110   
00111   // Use calorimetric energy as true energy for neutral particles
00112   double tt = t;
00113   double ee = e;
00114   double hh = h;
00115   double a = 1.;
00116   double b = 1.;
00117   double etaCorrE = 1.;
00118   double etaCorrH = 1.;
00119   t = min(999.9,max(tt,e+h));
00120   if ( t < 1. ) return;
00121 
00122   // Barrel calibration
00123   if ( fabs(eta) < 1.48 ) { 
00124 
00125     // The energy correction
00126     a = e>0. ? aBarrel(t) : 1.;
00127     b = e>0. ? bBarrel(t) : cBarrel(t);
00128     double thresh = e > 0. ? threshE : threshH;
00129 
00130     // Protection against negative calibration - to be tuned
00131     if ( a < -0.25 || b < -0.25 ) { 
00132       a = 1.;
00133       b = 1.;
00134       thresh = 0.;
00135     }
00136 
00137     // The new estimate of the true energy
00138     t = min(999.9,max(tt, thresh+a*e+b*h));
00139 
00140     // The angular correction for ECAL hadronic deposits
00141     etaCorrE = 1. + aEtaBarrel(t) + bEtaBarrel(t)*fabs(eta)*fabs(eta);
00142     etaCorrH = 1.;
00143     // etaCorr = 1.;
00144     t = max(tt, thresh+etaCorrE*a*e+etaCorrH*b*h);
00145 
00146     if ( e > 0. && thresh > 0. ) 
00147       e = h > 0. ? threshE-threshH + etaCorrE * a * e : threshE + etaCorrE * a * e;
00148     if ( h > 0. && thresh > 0. ) 
00149       h = threshH + etaCorrH * b * h;
00150 
00151     /*
00152     if ( e < 0. || h < 0. ) { 
00153       std::cout << "Warning : Energy correction ! " << std::endl
00154                 << "eta,tt,e,h,a,b = " << eta << " " << tt << " " 
00155                 << ee << "/" << e << " " << hh << "/" << h << " " << a << " " << b << std::endl;
00156     }
00157       
00158     if ( etaCorrE > 2. || etaCorrE < 0.5 || 
00159          etaCorrH > 2. || etaCorrH < 0.5 ) 
00160       std::cout << "Warning : Angular correction ! " << std::endl
00161                 << "etaCorrE,etaCorrH,eta,t = " 
00162                 << etaCorrE << " " << etaCorrH << " " << eta << " " << t << std::endl;
00163     */
00164 
00165   // Endcap calibration   
00166   } else {
00167 
00168     // The energy correction
00169     a = e>0. ? aEndcap(t) : 1.;
00170     b = e>0. ? bEndcap(t) : cEndcap(t);
00171     double thresh = e > 0. ? threshE : threshH;
00172 
00173     if ( a < -0.25 || b < -0.25 ) { 
00174       a = 1.;
00175       b = 1.;
00176       thresh = 0.;
00177     }
00178 
00179     // The new estimate of the true energy
00180     t = min(999.9,max(tt, thresh+a*e+b*h));
00181     
00182     // The angular correction
00183     double dEta = fabs ( fabs(eta) - 1.5 );
00184     double etaPow = dEta * dEta * dEta * dEta;
00185     //etaCorrE = 1. + aEtaEndcap(t) + 0.5*bEtaEndcap(t)*etaPow;
00186     etaCorrE = 1. + aEtaEndcap(t) + bEtaEndcap(t)*etaPow;
00187     etaCorrH = 1. + aEtaEndcap(t) + bEtaEndcap(t)*etaPow;
00188     /*
00189     if ( etaCorr > 2. || etaCorr < 0.5 ) 
00190       std::cout << "Warning : Angular correction ! " << std::endl
00191                 << "etaCorr,eta,t = " << etaCorr << " " << eta << " " << tt 
00192                 << " ee,hh,e,h = " << e << " " << h << " " << a*e << " " << b*h  
00193                 << std::endl;
00194     */
00195 
00196     t = min(999.9,max(tt, thresh + etaCorrE*a*e + etaCorrH*b*h));
00197 
00198     if ( e > 0. && thresh > 0. ) 
00199       e = h > 0. ? threshE-threshH + etaCorrE * a * e : threshE + etaCorrE * a * e;
00200     if ( h > 0. && thresh > 0. ) 
00201       h = threshH + b * etaCorrH * h;
00202 
00203 
00204   }
00205 
00206   // Protection
00207   if ( e < 0. || h < 0. ) {
00208     /*
00209     std::cout << "Warning : Energy correction ! " << std::endl
00210               << "eta,tt,e,h,a,b = " << eta << " " << tt << " " 
00211               << ee << "/" << e << " " << hh << "/" << h << " " << a << " " << b << std::endl;
00212     */
00213     // Some protection against crazy calibration
00214     if ( e < 0. ) e = ee;
00215     if ( h < 0. ) h = hh;
00216   }
00217 
00218   // And that's it !
00219 
00220   
00221 }
00222 
00223 // The calibration functions
00224 double 
00225 PFEnergyCalibration::aBarrel(double x) const { 
00226 
00227   if ( pfCalibrations ) { 
00228 
00229     BinningPointByMap point;
00230     point.insert(BinningVariables::JetEt, x);
00231     return pfCalibrations->getResult(PerformanceResult::PFfa_BARREL,point); 
00232 
00233   } else { 
00234 
00235     return faBarrel->Eval(x); 
00236 
00237   }
00238 }
00239 
00240 double 
00241 PFEnergyCalibration::bBarrel(double x) const { 
00242 
00243   if ( pfCalibrations ) { 
00244 
00245     BinningPointByMap point;
00246     point.insert(BinningVariables::JetEt, x);
00247     return pfCalibrations->getResult(PerformanceResult::PFfb_BARREL,point); 
00248 
00249   } else { 
00250 
00251     return fbBarrel->Eval(x); 
00252 
00253   }
00254 }
00255 
00256 double 
00257 PFEnergyCalibration::cBarrel(double x) const { 
00258 
00259   if ( pfCalibrations ) { 
00260 
00261     BinningPointByMap point;
00262     point.insert(BinningVariables::JetEt, x);
00263     return pfCalibrations->getResult(PerformanceResult::PFfc_BARREL,point); 
00264 
00265   } else { 
00266 
00267     return fcBarrel->Eval(x); 
00268 
00269   }
00270 }
00271 
00272 double 
00273 PFEnergyCalibration::aEtaBarrel(double x) const { 
00274 
00275   if ( pfCalibrations ) { 
00276 
00277     BinningPointByMap point;
00278     point.insert(BinningVariables::JetEt, x);
00279     return pfCalibrations->getResult(PerformanceResult::PFfaEta_BARREL,point); 
00280 
00281   } else { 
00282 
00283     return faEtaBarrel->Eval(x); 
00284 
00285   }
00286 }
00287 
00288 double 
00289 PFEnergyCalibration::bEtaBarrel(double x) const { 
00290 
00291   if ( pfCalibrations ) { 
00292 
00293     BinningPointByMap point;
00294     point.insert(BinningVariables::JetEt, x);
00295     return pfCalibrations->getResult(PerformanceResult::PFfbEta_BARREL,point); 
00296 
00297   } else { 
00298 
00299     return fbEtaBarrel->Eval(x); 
00300 
00301   }
00302 }
00303 
00304 double 
00305 PFEnergyCalibration::aEndcap(double x) const { 
00306 
00307   if ( pfCalibrations ) { 
00308 
00309     BinningPointByMap point;
00310     point.insert(BinningVariables::JetEt, x);
00311     return pfCalibrations->getResult(PerformanceResult::PFfa_ENDCAP,point); 
00312 
00313   } else { 
00314 
00315     return faEndcap->Eval(x); 
00316 
00317   }
00318 }
00319 
00320 double 
00321 PFEnergyCalibration::bEndcap(double x) const { 
00322 
00323   if ( pfCalibrations ) { 
00324 
00325     BinningPointByMap point;
00326     point.insert(BinningVariables::JetEt, x);
00327     return pfCalibrations->getResult(PerformanceResult::PFfb_ENDCAP,point); 
00328 
00329   } else { 
00330 
00331     return fbEndcap->Eval(x); 
00332 
00333   }
00334 }
00335 
00336 double 
00337 PFEnergyCalibration::cEndcap(double x) const { 
00338 
00339   if ( pfCalibrations ) { 
00340 
00341     BinningPointByMap point;
00342     point.insert(BinningVariables::JetEt, x);
00343     return pfCalibrations->getResult(PerformanceResult::PFfc_ENDCAP,point); 
00344 
00345   } else { 
00346 
00347     return fcEndcap->Eval(x); 
00348 
00349   }
00350 }
00351 
00352 double 
00353 PFEnergyCalibration::aEtaEndcap(double x) const { 
00354 
00355   if ( pfCalibrations ) { 
00356 
00357     BinningPointByMap point;
00358     point.insert(BinningVariables::JetEt, x);
00359     return pfCalibrations->getResult(PerformanceResult::PFfaEta_ENDCAP,point); 
00360 
00361   } else { 
00362 
00363     return faEtaEndcap->Eval(x); 
00364 
00365   }
00366 }
00367 
00368 double 
00369 PFEnergyCalibration::bEtaEndcap(double x) const { 
00370 
00371   if ( pfCalibrations ) { 
00372 
00373     BinningPointByMap point;
00374     point.insert(BinningVariables::JetEt, x);
00375     return pfCalibrations->getResult(PerformanceResult::PFfbEta_ENDCAP,point); 
00376 
00377   } else { 
00378 
00379     return fbEtaEndcap->Eval(x); 
00380 
00381   }
00382 }
00383 
00384 
00385 double
00386 PFEnergyCalibration::energyEm(const reco::PFCluster& clusterEcal,
00387                               std::vector<double> &EclustersPS1,
00388                               std::vector<double> &EclustersPS2,
00389                               bool crackCorrection ){
00390   double ePS1(std::accumulate(EclustersPS1.begin(), EclustersPS1.end(), 0.0));
00391   double ePS2(std::accumulate(EclustersPS2.begin(), EclustersPS2.end(), 0.0));
00392   return energyEm(clusterEcal, ePS1, ePS2, crackCorrection);
00393 }
00394 
00395 double
00396 PFEnergyCalibration::energyEm(const reco::PFCluster& clusterEcal,
00397                               double ePS1,
00398                               double ePS2,
00399                               bool crackCorrection ){
00400   double eEcal = clusterEcal.energy();
00401   //temporaty ugly fix
00402   reco::PFCluster myPFCluster=clusterEcal;
00403   myPFCluster.calculatePositionREP();
00404   double eta = myPFCluster.positionREP().eta();
00405   double phi = myPFCluster.positionREP().phi();
00406 
00407   double calibrated = Ecorr(eEcal,ePS1,ePS2,eta,phi, crackCorrection);
00408   if(eEcal!=0 && calibrated==0) std::cout<<"Eecal = "<<eEcal<<"  eta = "<<eta<<"  phi = "<<phi<<std::endl; 
00409   return calibrated; 
00410 }
00411 
00412 double PFEnergyCalibration::energyEm(const reco::PFCluster& clusterEcal,
00413                                      std::vector<double> &EclustersPS1,
00414                                      std::vector<double> &EclustersPS2,
00415                                      double& ps1,double& ps2,
00416                                      bool crackCorrection){
00417   double ePS1(std::accumulate(EclustersPS1.begin(), EclustersPS1.end(), 0.0));
00418   double ePS2(std::accumulate(EclustersPS2.begin(), EclustersPS2.end(), 0.0));
00419   return energyEm(clusterEcal, ePS1, ePS2, ps1, ps2, crackCorrection);
00420 }
00421 double PFEnergyCalibration::energyEm(const reco::PFCluster& clusterEcal,
00422                                      double ePS1, double ePS2,
00423                                      double& ps1,double& ps2,
00424                                      bool crackCorrection){
00425   double eEcal = clusterEcal.energy();
00426   //temporaty ugly fix
00427   reco::PFCluster myPFCluster=clusterEcal;
00428   myPFCluster.calculatePositionREP();
00429   double eta = myPFCluster.positionREP().eta();
00430   double phi = myPFCluster.positionREP().phi();
00431 
00432   double calibrated = Ecorr(eEcal,ePS1,ePS2,eta,phi,ps1,ps2,crackCorrection);
00433   if(eEcal!=0 && calibrated==0) std::cout<<"Eecal = "<<eEcal<<"  eta = "<<eta<<"  phi = "<<phi<<std::endl; 
00434   return calibrated; 
00435 }
00436 
00437 
00438 std::ostream& operator<<(std::ostream& out,
00439                          const PFEnergyCalibration& calib) {
00440 
00441   if(!out ) return out;
00442 
00443   out<<"PFEnergyCalibration -- "<<endl;
00444 
00445   if ( calib.pfCalibrations ) { 
00446 
00447     std::cout << "Functions taken from the global tags : " << std::endl;
00448 
00449     static std::map<std::string, PerformanceResult::ResultType> functType;
00450 
00451     functType["PFfa_BARREL"] = PerformanceResult::PFfa_BARREL;
00452     functType["PFfa_ENDCAP"] = PerformanceResult::PFfa_ENDCAP;
00453     functType["PFfb_BARREL"] = PerformanceResult::PFfb_BARREL;
00454     functType["PFfb_ENDCAP"] = PerformanceResult::PFfb_ENDCAP;
00455     functType["PFfc_BARREL"] = PerformanceResult::PFfc_BARREL;
00456     functType["PFfc_ENDCAP"] = PerformanceResult::PFfc_ENDCAP;
00457     functType["PFfaEta_BARREL"] = PerformanceResult::PFfaEta_BARREL;
00458     functType["PFfaEta_ENDCAP"] = PerformanceResult::PFfaEta_ENDCAP;
00459     functType["PFfbEta_BARREL"] = PerformanceResult::PFfbEta_BARREL;
00460     functType["PFfbEta_ENDCAP"] = PerformanceResult::PFfbEta_ENDCAP;
00461     
00462     for(std::map<std::string,PerformanceResult::ResultType>::const_iterator 
00463           func = functType.begin(); 
00464         func != functType.end(); 
00465         ++func) {    
00466       
00467       cout << "Function: " << func->first << endl;
00468       PerformanceResult::ResultType fType = func->second;
00469       calib.pfCalibrations->printFormula(fType);
00470     }
00471 
00472   } else { 
00473     
00474     std::cout << "Default calibration functions : " << std::endl;
00475     
00476     calib.faBarrel->Print();
00477     calib.fbBarrel->Print();
00478     calib.fcBarrel->Print();
00479     calib.faEtaBarrel->Print();
00480     calib.fbEtaBarrel->Print();
00481     calib.faEndcap->Print();
00482     calib.fbEndcap->Print();
00483     calib.fcEndcap->Print();
00484     calib.faEtaEndcap->Print();
00485     calib.fbEtaEndcap->Print();
00486   }
00487     
00488   return out;
00489 }
00490 
00491 
00492 
00493 
00506 
00507 
00508 
00514 
00515 
00516 //useful to compute the signed distance to the closest crack in the barrel
00517 double
00518 PFEnergyCalibration::minimum(double a,double b){
00519   if(TMath::Abs(b)<TMath::Abs(a)) a=b;
00520   return a;
00521 }
00522 
00523 
00524 //compute the unsigned distance to the closest phi-crack in the barrel
00525 double
00526 PFEnergyCalibration::dCrackPhi(double phi, double eta){
00527 
00528   constexpr double pi= M_PI;// 3.14159265358979323846;
00529   
00530   //Location of the 18 phi-cracks
00531   static std::vector<double> cPhi;
00532   if(cPhi.size()==0)
00533     {
00534       cPhi.resize(18,0);
00535       cPhi[0]=2.97025;
00536       for(unsigned i=1;i<=17;++i) cPhi[i]=cPhi[0]-2*i*pi/18;
00537     }
00538 
00539   //Shift of this location if eta<0
00540   constexpr double delta_cPhi=0.00638;
00541 
00542   double m; //the result
00543 
00544   //the location is shifted
00545   if(eta<0) phi +=delta_cPhi;
00546 
00547   if (phi>=-pi && phi<=pi){
00548 
00549     //the problem of the extrema
00550     if (phi<cPhi[17] || phi>=cPhi[0]){
00551       if (phi<0) phi+= 2*pi;
00552       m = minimum(phi -cPhi[0],phi-cPhi[17]-2*pi);              
00553     }
00554 
00555     //between these extrema...
00556     else{
00557       bool OK = false;
00558       unsigned i=16;
00559       while(!OK){
00560         if (phi<cPhi[i]){
00561           m=minimum(phi-cPhi[i+1],phi-cPhi[i]);
00562           OK=true;
00563         }
00564         else i-=1;
00565       }
00566     }
00567   }
00568   else{
00569     m=0.;        //if there is a problem, we assum that we are in a crack
00570     std::cout<<"Problem in dminphi"<<std::endl;
00571   }
00572   if(eta<0) m=-m;   //because of the disymetry
00573   return m;
00574 }
00575 
00576 // corrects the effect of phi-cracks
00577 double
00578 PFEnergyCalibration::CorrPhi(double phi, double eta) {
00579 
00580   // we use 3 gaussians to correct the phi-cracks effect
00581   constexpr double p1=   5.59379e-01;
00582   constexpr double p2=   -1.26607e-03;
00583   constexpr double p3=  9.61133e-04;
00584 
00585   constexpr double p4=   1.81691e-01;
00586   constexpr double p5=   -4.97535e-03;
00587   constexpr double p6=   1.31006e-03;
00588 
00589   constexpr double p7=   1.38498e-01;
00590   constexpr double p8=   1.18599e-04;
00591   constexpr double p9= 2.01858e-03;
00592   
00593 
00594   double dminphi = dCrackPhi(phi,eta);
00595   
00596   double result = (1+p1*TMath::Gaus(dminphi,p2,p3)+p4*TMath::Gaus(dminphi,p5,p6)+p7*TMath::Gaus(dminphi,p8,p9));
00597 
00598   return result;
00599 }   
00600 
00601 
00602 // corrects the effect of  |eta|-cracks
00603 double
00604 PFEnergyCalibration::CorrEta(double eta){
00605   
00606   // we use a gaussian with a screwness for each of the 5 |eta|-cracks
00607   constexpr double a[] = {6.13349e-01, 5.08146e-01, 4.44480e-01, 3.3487e-01, 7.65627e-01}; // amplitude
00608   constexpr double m[] = {-1.79514e-02, 4.44747e-01, 7.92824e-01, 1.14090e+00, 1.47464e+00}; // mean
00609   constexpr double s[] = {7.92382e-03, 3.06028e-03, 3.36139e-03, 3.94521e-03, 8.63950e-04}; // sigma
00610   constexpr double sa[] = {1.27228e+01, 3.81517e-02, 1.63507e-01, -6.56480e-02, 1.87160e-01}; // screwness amplitude
00611   constexpr double ss[] = {5.48753e-02, -1.00223e-02, 2.22866e-03, 4.26288e-04, 2.67937e-03}; // screwness sigma
00612   double result = 1;
00613 
00614   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]));
00615 
00616   return result;
00617 }
00618 
00619 
00620 //corrects the global behaviour in the barrel
00621 double
00622 PFEnergyCalibration::CorrBarrel(double E, double eta) {
00623 
00624   //Energy dependency
00625   /*
00626   //YM Parameters 52XX:
00627   constexpr double p0=1.00000e+00;
00628   constexpr double p1=3.27753e+01;
00629   constexpr double p2=2.28552e-02;
00630   constexpr double p3=3.06139e+00;
00631   constexpr double p4=2.25135e-01;
00632   constexpr double p5=1.47824e+00;
00633   constexpr double p6=1.09e-02;
00634   constexpr double p7=4.19343e+01;
00635   */
00636   constexpr double p0 = 0.9944;
00637   constexpr double p1 = 9.827;
00638   constexpr double p2 = 1.503;
00639   constexpr double p3 = 1.196;
00640   constexpr double p4 = 0.3349;
00641   constexpr double p5 = 0.89;
00642   constexpr double p6 = 0.004361;
00643   constexpr double p7 = 51.51;
00644   //Eta dependency
00645   constexpr double p8=2.705593e-03;
00646   
00647   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);
00648 
00649   return result;
00650 }
00651 
00652 
00653 
00662 
00663 
00664 //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
00665 // Etot = Beta*eEcal + Gamma*(ePS1 + Alpha*ePS2) 
00666 
00667 double
00668 PFEnergyCalibration::Alpha(double eta) {
00669 
00670   //Energy dependency
00671   constexpr double p0 = 5.97621e-01;
00672 
00673   //Eta dependency
00674   constexpr double p1 =-1.86407e-01;
00675   constexpr double p2 = 3.85197e-01; 
00676 
00677   //so that <feta()> = 1
00678   constexpr double norm = (p1+p2*(2.6+1.656)/2);
00679 
00680   double result = p0*(p1+p2*eta)/norm;
00681 
00682   return result;
00683 }
00684 
00685 double
00686 PFEnergyCalibration::Beta(double E, double eta) {
00687 
00688  //Energy dependency
00689   constexpr double p0 = 0.032;
00690   constexpr double p1 = 9.70394e-02;
00691   constexpr double p2 = 2.23072e+01;
00692   constexpr double p3 = 100;
00693 
00694   //Eta dependency
00695   constexpr double p4 = 1.02496e+00 ;
00696   constexpr double p5 = -4.40176e-03 ;
00697 
00698   //so that <feta()> = 1
00699   constexpr double norm = (p4+p5*(2.6+1.656)/2);
00700 
00701   double result = (1.0012+p0*TMath::Exp(-E/p3)+p1*TMath::Exp(-E/p2))*(p4+p5*eta)/norm;                    
00702   return result;
00703 }
00704 
00705 
00706 double
00707 PFEnergyCalibration::Gamma(double etaEcal) {
00708 
00709  //Energy dependency
00710   constexpr double p0 = 2.49752e-02;
00711 
00712   //Eta dependency
00713   constexpr double p1 = 6.48816e-02;
00714   constexpr double p2 = -1.59517e-02; 
00715  
00716   //so that <feta()> = 1
00717   constexpr double norm = (p1+p2*(2.6+1.656)/2);
00718 
00719   double result = p0*(p1+p2*etaEcal)/norm;                                        
00720 
00721   return result;
00722 }
00723 
00724 
00725 
00731 
00732 
00733 // returns the corrected energy in the barrel (0,1.48)
00734 // Global Behaviour, phi and eta cracks are taken into account
00735 double
00736 PFEnergyCalibration::EcorrBarrel(double E, double eta, double phi,
00737                                  bool crackCorrection ){
00738 
00739   // double result = E*CorrBarrel(E,eta)*CorrEta(eta)*CorrPhi(phi,eta);
00740   double correction = crackCorrection ? std::max(CorrEta(eta),CorrPhi(phi,eta)) : 1.;
00741   double result = E * CorrBarrel(E,eta) * correction;
00742 
00743   return result;
00744 }
00745 
00746 
00747 // returns the corrected energy in the area between the barrel and the PS (1.48,1.65)
00748 double
00749 PFEnergyCalibration::EcorrZoneBeforePS(double E, double eta){
00750 
00751  //Energy dependency
00752   constexpr double p0 =1; 
00753   constexpr double p1 =0.18;
00754   constexpr double p2 =8.;
00755 
00756   //Eta dependency
00757   constexpr double p3 =0.3;
00758   constexpr double p4 =1.11;
00759   constexpr double p5 =0.025;
00760   constexpr double p6 =1.49;
00761   constexpr double p7 =0.6;
00762 
00763   //so that <feta()> = 1
00764   constexpr double norm = 1.21;
00765 
00766   double result = E*(p0+p1*TMath::Exp(-E/p2))*(p3+p4*TMath::Gaus(eta,p6,p5)+p7*eta)/norm;
00767 
00768   return result;
00769 }
00770 
00771 
00772 // returns the corrected energy in the PS (1.65,2.6)
00773 // only when (ePS1>0)||(ePS2>0)
00774 double
00775 PFEnergyCalibration::EcorrPS(double eEcal,double ePS1,double ePS2,double etaEcal) {
00776 
00777   // gives the good weights to each subdetector
00778   double E = Beta(1.0155*eEcal+0.025*(ePS1+0.5976*ePS2)/9e-5,etaEcal)*eEcal+Gamma(etaEcal)*(ePS1+Alpha(etaEcal)*ePS2)/9e-5 ;
00779 
00780   //Correction of the residual energy dependency
00781   constexpr double p0 = 1.00;
00782   constexpr double p1 = 2.18;
00783   constexpr double p2 =1.94;
00784   constexpr double p3 =4.13;
00785   constexpr double p4 =1.127;
00786 
00787   double result = E*(p0+p1*TMath::Exp(-E/p2)-p3*TMath::Exp(-E/p4));
00788 
00789   return result;
00790 } 
00791 
00792 // returns the corrected energy in the PS (1.65,2.6)
00793 // only when (ePS1>0)||(ePS2>0)
00794 double
00795 PFEnergyCalibration::EcorrPS(double eEcal,double ePS1,double ePS2,double etaEcal,double & outputPS1, double & outputPS2) {
00796 
00797   // gives the good weights to each subdetector
00798   double gammaprime=Gamma(etaEcal)/9e-5;
00799   outputPS1=gammaprime*ePS1;
00800   outputPS2=gammaprime*Alpha(etaEcal)*ePS2;
00801   double E = Beta(1.0155*eEcal+0.025*(ePS1+0.5976*ePS2)/9e-5,etaEcal)*eEcal+outputPS1+outputPS2;
00802 
00803   //Correction of the residual energy dependency
00804   constexpr double p0 = 1.00;
00805   constexpr double p1 = 2.18;
00806   constexpr double p2 =1.94;
00807   constexpr double p3 =4.13;
00808   constexpr double p4 =1.127;
00809   
00810   double corrfac=(p0+p1*TMath::Exp(-E/p2)-p3*TMath::Exp(-E/p4));
00811   outputPS1*=corrfac;
00812   outputPS2*=corrfac;
00813   double result = E*corrfac;
00814 
00815   return result;
00816 } 
00817 
00818 
00819 // returns the corrected energy in the PS (1.65,2.6)
00820 // only when (ePS1=0)&&(ePS2=0)
00821 double 
00822 PFEnergyCalibration::EcorrPS_ePSNil(double eEcal,double eta){
00823 
00824   //Energy dependency
00825   constexpr double p0= 1.02;
00826   constexpr double p1= 0.165;
00827   constexpr double p2= 6.5 ;
00828   constexpr double p3=  2.1 ;
00829 
00830   //Eta dependency
00831   constexpr double p4 = 1.02496e+00 ;
00832   constexpr double p5 = -4.40176e-03 ;
00833 
00834   //so that <feta()> = 1
00835   constexpr double norm = (p4+p5*(2.6+1.656)/2);
00836 
00837   double result = eEcal*(p0+p1*TMath::Exp(-TMath::Abs(eEcal-p3)/p2))*(p4+p5*eta)/norm;
00838                   
00839   return result;
00840 }
00841 
00842 
00843 // returns the corrected energy in the area between the end of the PS and the end of the endcap (2.6,2.98)
00844 double
00845 PFEnergyCalibration::EcorrZoneAfterPS(double E, double eta){
00846 
00847   //Energy dependency
00848   constexpr double p0 =1; 
00849   constexpr double p1 = 0.058;
00850   constexpr double p2 =12.5;
00851   constexpr double p3 =-1.05444e+00;
00852   constexpr double p4 =-5.39557e+00;
00853   constexpr double p5 =8.38444e+00;
00854   constexpr double p6 = 6.10998e-01  ;
00855 
00856   //Eta dependency
00857   constexpr double p7 =1.06161e+00;
00858   constexpr double p8 = 0.41;
00859   constexpr double p9 =2.918;
00860   constexpr double p10 =0.0181;
00861   constexpr double p11= 2.05;
00862   constexpr double p12 =2.99;
00863   constexpr double p13=0.0287;
00864 
00865   //so that <feta()> = 1
00866   constexpr double norm=1.045;
00867 
00868   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;
00869   return result;
00870 }
00871 
00872 
00873 
00874 
00875 // returns the corrected energy everywhere
00876 // this work should be improved between 1.479 and 1.52 (junction barrel-endcap)
00877 double
00878 PFEnergyCalibration::Ecorr(double eEcal,double ePS1,double ePS2,
00879                            double eta,double phi,
00880                            bool crackCorrection ) {
00881 
00882   constexpr double endBarrel=1.48;
00883   constexpr double beginingPS=1.65;
00884   constexpr double endPS=2.6;
00885   constexpr double endEndCap=2.98;
00886  
00887   double result=0;
00888 
00889   eta=TMath::Abs(eta);
00890 
00891   if(eEcal>0){
00892     if(eta <= endBarrel)                         result = EcorrBarrel(eEcal,eta,phi,crackCorrection);
00893     else if(eta <= beginingPS)                   result = EcorrZoneBeforePS(eEcal,eta);
00894     else if((eta < endPS) && ePS1==0 && ePS2==0) result = EcorrPS_ePSNil(eEcal,eta);
00895     else if(eta < endPS)                         result = EcorrPS(eEcal,ePS1,ePS2,eta);
00896     else if(eta < endEndCap)                     result = EcorrZoneAfterPS(eEcal,eta); 
00897     else result =eEcal;
00898   }
00899   else result = eEcal;// useful if eEcal=0 or eta>2.98
00900   //protection
00901   if(result<eEcal) result=eEcal;
00902   return result;
00903 }
00904 
00905 // returns the corrected energy everywhere
00906 // this work should be improved between 1.479 and 1.52 (junction barrel-endcap)
00907 double
00908 PFEnergyCalibration::Ecorr(double eEcal,double ePS1,double ePS2,double eta,double phi,double& ps1,double&ps2,bool crackCorrection)  {
00909 
00910   constexpr double endBarrel=1.48;
00911   constexpr double beginingPS=1.65;
00912   constexpr double endPS=2.6;
00913   constexpr double endEndCap=2.98;
00914  
00915   double result=0;
00916 
00917   eta=TMath::Abs(eta);
00918 
00919   if(eEcal>0){
00920     if(eta <= endBarrel)                         result = EcorrBarrel(eEcal,eta,phi,crackCorrection);
00921     else if(eta <= beginingPS)                   result = EcorrZoneBeforePS(eEcal,eta);
00922     else if((eta < endPS) && ePS1==0 && ePS2==0) result = EcorrPS_ePSNil(eEcal,eta);
00923     else if(eta < endPS)                         result = EcorrPS(eEcal,ePS1,ePS2,eta,ps1,ps2);
00924     else if(eta < endEndCap)                     result = EcorrZoneAfterPS(eEcal,eta); 
00925     else result =eEcal;
00926   }
00927   else result = eEcal;// useful if eEcal=0 or eta>2.98
00928   // protection
00929   if(result<eEcal) result=eEcal;
00930   return result;
00931 }