/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ /* $Id: AliEMCALPIDUtils.cxx 33808 2009-07-15 09:48:08Z gconesab $ */ // Compute PID weights for all the clusters that are in AliESDs.root file // the AliESDs.root have to be in the same directory as the class // // and do: // AliEMCALPIDUtils *pid = new AliEMCALPIDUtils(); // pid->SetPrintInfo(kTRUE); // pid->SetHighFluxParam(); // pid->SetLowFluxParam(); // // then in cluster loop do // pid->ComputePID(energy, lambda0); // // Compute PID Weight for all clusters in AliESDs.root file // keep this function for the moment for a simple verification, could be removed // // pid->GetPIDFinal(idx) gives the probabilities // // Double_t PIDFinal[AliPID::kSPECIESCN] is the standard PID for : // // kElectron : fPIDFinal[0] // kMuon : fPIDFinal[1] // kPion : fPIDFinal[2] // kKaon : fPIDFinal[3] // kProton : fPIDFinal[4] // kPhoton : fPIDFinal[5] // kPi0 : fPIDFinal[6] // kNeutron : fPIDFinal[7] // kKaon0 : fPIDFinal[8] // kEleCon : fPIDFinal[9] // kUnknown : fPIDFinal[10] // // // PID[3] is a simple PID for // Electron & Photon PID[0] // Pi0 PID[1] // Hadron PID[2] // // Author: Genole Bourdaud 2007 (SUBATECH) // Marie Germain 07/2009 (SUBATECH), new parametrization for low and high flux environment // Gustavo Conesa 08/2009 (LNF), divide class in AliEMCALPID and AliEMCALPIDUtils, PIDUtils belong to library EMCALUtils // --- standard c --- // standard C++ includes //#include // ROOT includes #include "TMath.h" #include "TArrayD.h" // STEER includes #include "AliEMCALPIDUtils.h" #include "AliLog.h" ClassImp(AliEMCALPIDUtils) //______________________________________________ AliEMCALPIDUtils::AliEMCALPIDUtils(): fPrintInfo(kFALSE), fProbGamma(0.),fProbPiZero(0.),fProbHadron(0.), fWeightHadronEnergy(1.), fWeightGammaEnergy(1.),fWeightPiZeroEnergy(1.) { // // Constructor. // Initialize all constant values which have to be used // during PID algorithm execution // InitParameters(); } //__________________________________________________________ void AliEMCALPIDUtils::ComputePID(Double_t energy, Double_t lambda0) { // // This is the main command, which uses the distributions computed and parametrised, // and gives the PID by the bayesian method. // Double_t weightGammaEnergy = DistEnergy(energy, 1); Double_t weightPiZeroEnergy = DistEnergy(energy, 2); Double_t weightHadronEnergy = DistEnergy(energy, 3); Double_t energyhadron=energy; if(energyhadron<1.)energyhadron=1.; // no energy dependance of parametrisation for hadrons below 1 GeV if (energy<2){energy =2;} // no energy dependance of parametrisation for gamma and pi0 below 2 GeV if (energy>55){ energy =55.; energyhadron=55.; } // same parametrisation for gamma and hadrons above 55 GeV // for the pi0 above 55GeV the 2 gammas supperposed no way to distinguish from real gamma PIDWeight[1]=0 TArrayD paramDistribGamma = DistLambda0(energy, 1); TArrayD paramDistribPiZero = DistLambda0(energy, 2); TArrayD paramDistribHadron = DistLambda0(energyhadron, 3); Bool_t norm = kFALSE; fProbGamma = TMath::Gaus(lambda0, paramDistribGamma[1], paramDistribGamma[2], norm) * paramDistribGamma[0]; fProbGamma += TMath::Landau(((1-paramDistribGamma[4])-lambda0),paramDistribGamma[4],paramDistribGamma[5],norm)* paramDistribGamma[3]; if(fProbGamma<0.)fProbGamma=0.; fProbGamma = fProbGamma*weightGammaEnergy; if(energy>10. || energy < 55.){ fProbPiZero = TMath::Gaus(lambda0, paramDistribPiZero[1], paramDistribPiZero[2], norm) * paramDistribPiZero[0]; fProbPiZero += TMath::Landau(lambda0, paramDistribPiZero[4], paramDistribPiZero[5], norm) * paramDistribPiZero[3]; if(fProbPiZero<0. || energy<5.)fProbPiZero=0.; fProbPiZero = fProbPiZero*weightPiZeroEnergy; } else { fProbPiZero = 0.; } fProbHadron = TMath::Gaus(lambda0, paramDistribHadron[1], paramDistribHadron[2], norm) * paramDistribHadron[0]; fProbHadron += TMath::Landau(lambda0, paramDistribHadron[4], paramDistribHadron[5], norm) * paramDistribHadron[3]; if(fProbHadron<0.)fProbHadron=0.; fProbHadron = fProbHadron*weightHadronEnergy; // to take into account the probability for a hadron to have a given reconstructed energy // compute PID Weight if( (fProbGamma + fProbPiZero + fProbHadron)>0.){ fPIDWeight[0] = fProbGamma / (fProbGamma + fProbPiZero + fProbHadron); fPIDWeight[1] = fProbPiZero / (fProbGamma+fProbPiZero+fProbHadron); fPIDWeight[2] = fProbHadron / (fProbGamma+fProbPiZero+fProbHadron); } else{ // cases where energy and lambda0 large, probably du to 2 clusters folded the clusters PID not assigned to hadron nor Pi0 nor gammas fPIDWeight[0] = 0.; fPIDWeight[1] = 0.; fPIDWeight[2] = 0.; } // cout << " PID[0] "<< fPIDWeight[0] << " PID[1] "<< fPIDWeight[1] << " PID[2] "<< fPIDWeight[2] << endl; SetPID(fPIDWeight[0], 0); SetPID(fPIDWeight[1], 1); SetPID(fPIDWeight[2], 2); // print pid Weight only for control if (fPrintInfo) { AliInfo(Form( "Energy in loop = %f", energy) ); AliInfo(Form( "Lambda0 in loop = %f", lambda0) ); AliInfo(Form( "fProbGamma in loop = %f", fProbGamma) ); AliInfo(Form( "fProbaPiZero = %f", fProbPiZero )); AliInfo(Form( "fProbaHadron = %f", fProbHadron) ); AliInfo(Form( "PIDWeight in loop = %f ||| %f ||| %f", fPIDWeight[0] , fPIDWeight[1], fPIDWeight[2]) ); AliInfo("********************************************************" ); } //default particles fPIDFinal[AliPID::kElectron] = fPIDWeight[0]/2; // photon fPIDFinal[AliPID::kMuon] = fPIDWeight[2]/8; fPIDFinal[AliPID::kPion] = fPIDWeight[2]/8; fPIDFinal[AliPID::kKaon] = fPIDWeight[2]/8; fPIDFinal[AliPID::kProton] = fPIDWeight[2]/8; //light nuclei fPIDFinal[AliPID::kDeuteron] = 0; fPIDFinal[AliPID::kTriton] = 0; fPIDFinal[AliPID::kHe3] = 0; fPIDFinal[AliPID::kAlpha] = 0; //neutral particles fPIDFinal[AliPID::kPhoton] = fPIDWeight[0]/2; // electron fPIDFinal[AliPID::kPi0] = fPIDWeight[1] ; // Pi0 fPIDFinal[AliPID::kNeutron] = fPIDWeight[2]/8; fPIDFinal[AliPID::kKaon0] = fPIDWeight[2]/8; fPIDFinal[AliPID::kEleCon] = fPIDWeight[2]/8; // fPIDFinal[AliPID::kUnknown] = fPIDWeight[2]/8; } //________________________________________________________ TArrayD AliEMCALPIDUtils::DistLambda0(const Double_t energy, const Int_t type) { // // Compute the values of the parametrised distributions using the data initialised before. // Double_t constGauss = 0., meanGauss = 0., sigmaGauss = 0.; Double_t constLandau=0., mpvLandau=0., sigmaLandau=0.; TArrayD distributionParam(6); switch (type) { case 1: constGauss = PolynomialMixed2(energy, fGamma[0]); meanGauss = PolynomialMixed2(energy, fGamma[1]); sigmaGauss = PolynomialMixed2(energy, fGamma[2]); constLandau = PolynomialMixed2(energy, fGamma[3]); mpvLandau = PolynomialMixed2(energy, fGamma[4]); sigmaLandau = PolynomialMixed2(energy, fGamma[5]); break; case 2: constGauss = PolynomialMixed2(energy, fPiZero[0]); meanGauss = PolynomialMixed2(energy, fPiZero[1]); sigmaGauss = PolynomialMixed2(energy, fPiZero[2]); constLandau = PolynomialMixed2(energy, fPiZero[3]); mpvLandau = PolynomialMixed2(energy, fPiZero[4]); sigmaLandau = PolynomialMixed2(energy, fPiZero[5]); break; case 3: constGauss = PolynomialMixed2(energy, fHadron[0]); meanGauss = PolynomialMixed2(energy, fHadron[1]); sigmaGauss = PolynomialMixed2(energy, fHadron[2]); constLandau = PolynomialMixed2(energy, fHadron[3]); mpvLandau = PolynomialMixed2(energy, fHadron[4]); sigmaLandau = PolynomialMixed2(energy, fHadron[5]); break; } distributionParam[0] = constGauss; distributionParam[1] = meanGauss; distributionParam[2] = sigmaGauss; distributionParam[3] = constLandau; distributionParam[4] = mpvLandau; distributionParam[5] = sigmaLandau; return distributionParam; } //________________________________________________________ Double_t AliEMCALPIDUtils::DistEnergy(const Double_t energy, const Int_t type) { // // Compute the values of the weigh for a given energy the parametrised distribution using the data initialised before. // Double_t constante = 0.; switch (type) { case 1: constante = 1.; break; case 2: constante = 1.; break; case 3: constante = PowerExp(energy, fHadronEnergyProb); break; } // cout << "Weight " << constante << " for energy "<< energy<< " GeV "<< endl; return constante; } //_______________________________________________________ Double_t AliEMCALPIDUtils::Polynomial(const Double_t x, const Double_t *params) const { // // Compute a polynomial for a given value of 'x' // with the array of parameters passed as the second arg // Double_t y = params[0]; y += params[1] * x; y += params[2] * x * x; y += params[3] * x * x * x; y += params[4] * x * x * x * x; y += params[5] * x * x * x * x * x; return y; } //_______________________________________________________ Double_t AliEMCALPIDUtils::Polynomial0(const Double_t *params) const { // // Compute a polynomial for a given value of 'x' // with the array of parameters passed as the second arg // Double_t y = params[0]; return y; } //_______________________________________________________ Double_t AliEMCALPIDUtils::Polynomialinv(const Double_t x, const Double_t *params) const { // // Compute a polynomial for a given value of 'x' // with the array of parameters passed as the second arg // Double_t y=0.; if(x>0){ y = params[0]; y += params[1] / x; y += params[2] / (x * x); y += params[3] / (x * x * x); y += params[4] / (x * x * x * x); y += params[5] / (x * x * x * x * x); } return y; } //_______________________________________________________ Double_t AliEMCALPIDUtils::PolynomialMixed1(const Double_t x, const Double_t *params) const { // // Compute a polynomial for a given value of 'x' // with the array of parameters passed as the second arg // Double_t y=0.; if(x>0){ y = params[0] / x; y += params[1] ; y += params[2] * x ; // y += params[3] * 0.; // y += params[4] * 0.; // y += params[5] * 0.; } return y; } //_______________________________________________________ Double_t AliEMCALPIDUtils::PolynomialMixed2(const Double_t x, const Double_t *params) const { // // Compute a polynomial for a given value of 'x' // with the array of parameters passed as the second arg // Double_t y=0.; if(x>0){ y = params[0] / ( x * x); y += params[1] / x; y += params[2] ; y += params[3] * x ; y += params[4] * x * x ; // y += params[5] * 0.; } return y; } //_______________________________________________________ Double_t AliEMCALPIDUtils::PowerExp(const Double_t x, const Double_t *params) const { // // Compute a polynomial for a given value of 'x' // with the array of parameters passed as the second arg // par[0]*TMath::Power(x[0],par[1]) // par[0]*TMath::Exp((x[0]-par[1])*par[2]); Double_t y = params[0] *TMath::Power( x,params[1]); y += params[2] *TMath::Exp((x-params[3])*params[4]); return y; } //_______________________________________________________ void AliEMCALPIDUtils::InitParameters() { // Initialize PID parameters, depending on the use or not of the reconstructor // and the kind of event type if the reconstructor is not used. // fWeightHadronEnergy=0.; // fWeightPiZeroEnergy=0.; // fWeightGammaEnergy=0.; fPIDWeight[0] = -1; fPIDWeight[1] = -1; fPIDWeight[2] = -1; for(Int_t i=0; i