+ //Double_t cnt = par[1] / (x*x) + par[2] / x + par[0] ;
+ Double_t cnt = par[0] + par[1] * x + par[2] * x * x ;
+ Double_t mean = par[4] / (x*x) + par[5] / x + par[3] ;
+ Double_t sigma = par[7] / (x*x) + par[8] / x + par[6] ;
+
+ if(TMath::Abs(sigma) > 1.e-10){
+ return cnt*TMath::Landau(y,mean,sigma);
+ }
+ else
+ return 0.;
+
+}
+//________________________________________________________________________
+Double_t AliPHOSPIDv1::LandauPol2(Double_t x, Double_t y, Double_t * par)
+{
+
+ //Given the energy x and the parameter y (tof, shower dispersion or cpv-emc distance),
+ //this method returns a density probability of this parameter, given by a landau
+ //function whose parameters depend with the energy like second order polinomial
+
+ Double_t cnt = par[2] * (x*x) + par[1] * x + par[0] ;
+ Double_t mean = par[5] * (x*x) + par[4] * x + par[3] ;
+ Double_t sigma = par[8] * (x*x) + par[7] * x + par[6] ;
+
+ if(TMath::Abs(sigma) > 1.e-10){
+ return cnt*TMath::Landau(y,mean,sigma);
+ }
+ else
+ return 0.;
+
+
+}
+// //________________________________________________________________________
+// Double_t AliPHOSPIDv1::ChargedHadronDistProb(Double_t x, Double_t y, Double_t * parg, Double_t * parl)
+// {
+// Double_t cnt = 0.0 ;
+// Double_t mean = 0.0 ;
+// Double_t sigma = 0.0 ;
+// Double_t arg = 0.0 ;
+// if (y < parl[4] / (x*x) + parl[5] / x + parl[3]){
+// cnt = parg[1] / (x*x) + parg[2] / x + parg[0] ;
+// mean = parg[4] / (x*x) + parg[5] / x + parg[3] ;
+// sigma = parg[7] / (x*x) + parg[8] / x + parg[6] ;
+// TF1 * f = new TF1("gaus","gaus",0.,100.);
+// f->SetParameters(cnt,mean,sigma);
+// arg = f->Eval(y) ;
+// }
+// else{
+// cnt = parl[1] / (x*x) + parl[2] / x + parl[0] ;
+// mean = parl[4] / (x*x) + parl[5] / x + parl[3] ;
+// sigma = parl[7] / (x*x) + parl[8] / x + parl[6] ;
+// TF1 * f = new TF1("landau","landau",0.,100.);
+// f->SetParameters(cnt,mean,sigma);
+// arg = f->Eval(y) ;
+// }
+// // Double_t mean = par[3] + par[4] * x + par[5] * x * x ;
+// // Double_t sigma = par[6] + par[7] * x + par[8] * x * x ;
+
+// //Double_t arg = -(y-mean)*(y-mean)/(2*sigma*sigma) ;
+// //return cnt * TMath::Exp(arg) ;
+
+// return arg;
+
+// }
+//____________________________________________________________________________
+void AliPHOSPIDv1::MakePID()
+{
+ // construct the PID weight from a Bayesian Method
+
+ const Int_t kSPECIES = AliPID::kSPECIESCN ;
+
+ Int_t nparticles = fRecParticles->GetEntriesFast() ;
+
+ if ( !fEMCRecPoints || !fCPVRecPoints || !fTrackSegments ) {
+ AliFatal("RecPoints or TrackSegments not found !") ;
+ }
+
+ TIter next(fTrackSegments) ;
+ AliPHOSTrackSegment * ts ;
+ Int_t index = 0 ;
+
+ Double_t * stof[kSPECIES] ;
+ Double_t * sdp [kSPECIES] ;
+ Double_t * scpv[kSPECIES] ;
+ Double_t * sw [kSPECIES] ;
+ //Info("MakePID","Begin MakePID");
+
+ for (Int_t i =0; i< kSPECIES; i++){
+ stof[i] = new Double_t[nparticles] ;
+ sdp [i] = new Double_t[nparticles] ;
+ scpv[i] = new Double_t[nparticles] ;
+ sw [i] = new Double_t[nparticles] ;
+ }
+
+
+ while ( (ts = (AliPHOSTrackSegment *)next()) ) {
+
+ //cout<<">>>>>> Bayesian Index "<<index<<endl;
+
+ AliPHOSEmcRecPoint * emc = 0 ;
+ if(ts->GetEmcIndex()>=0)
+ emc = (AliPHOSEmcRecPoint *) fEMCRecPoints->At(ts->GetEmcIndex()) ;
+
+// AliPHOSCpvRecPoint * cpv = 0 ;
+// if(ts->GetCpvIndex()>=0)
+// cpv = (AliPHOSCpvRecPoint *) cpvRecPoints->At(ts->GetCpvIndex()) ;
+//
+//// Int_t track = 0 ;
+//// track = ts->GetTrackIndex() ; //TPC tracks ?
+
+ if (!emc) {
+ AliFatal(Form("-> emc(%d)", ts->GetEmcIndex())) ;
+ }
+
+
+ // ############Tof#############################
+
+ // Info("MakePID", "TOF");
+ Float_t en = emc->GetEnergy();
+ Double_t time = emc->GetTime() ;
+ // cout<<">>>>>>>Energy "<<en<<"Time "<<time<<endl;
+
+ // now get the signals probability
+ // s(pid) in the Bayesian formulation
+
+ //Initialize anused species
+ for(Int_t iii=0; iii<kSPECIES; iii++)stof[iii][index]=0. ;
+
+ stof[AliPID::kPhoton][index] = 1.;
+ stof[AliPID::kElectron][index] = 1.;
+ stof[AliPID::kEleCon][index] = 1.;
+ //We assing the same prob to charged hadrons, sum is 1
+ stof[AliPID::kPion][index] = 1./3.;
+ stof[AliPID::kKaon][index] = 1./3.;
+ stof[AliPID::kProton][index] = 1./3.;
+ //We assing the same prob to neutral hadrons, sum is 1
+ stof[AliPID::kNeutron][index] = 1./2.;
+ stof[AliPID::kKaon0][index] = 1./2.;
+ stof[AliPID::kMuon][index] = 1.;
+
+ if(en < fTOFEnThreshold) {
+
+ Double_t pTofPion = fTFpiong ->Eval(time) ; //gaus distribution
+ Double_t pTofKaon = 0;
+
+ if(time < fTkaonl[1])
+ pTofKaon = fTFkaong ->Eval(time) ; //gaus distribution
+ else
+ pTofKaon = fTFkaonl ->Eval(time) ; //landau distribution
+
+ Double_t pTofNucleon = 0;
+
+ if(time < fThhadronl[1])
+ pTofNucleon = fTFhhadrong ->Eval(time) ; //gaus distribution
+ else
+ pTofNucleon = fTFhhadronl ->Eval(time) ; //landau distribution
+ //We assing the same prob to neutral hadrons, sum is the average prob
+ Double_t pTofNeHadron = (pTofKaon + pTofNucleon)/2. ;
+ //We assing the same prob to charged hadrons, sum is the average prob
+ Double_t pTofChHadron = (pTofPion + pTofKaon + pTofNucleon)/3. ;
+
+ stof[AliPID::kPhoton][index] = fTFphoton ->Eval(time) ;
+ //gaus distribution
+ stof[AliPID::kEleCon][index] = stof[AliPID::kPhoton][index] ;
+ //a conversion electron has the photon ToF
+ stof[AliPID::kMuon][index] = stof[AliPID::kPhoton][index] ;
+
+ stof[AliPID::kElectron][index] = pTofPion ;
+
+ stof[AliPID::kPion][index] = pTofChHadron ;
+ stof[AliPID::kKaon][index] = pTofChHadron ;
+ stof[AliPID::kProton][index] = pTofChHadron ;
+
+ stof[AliPID::kKaon0][index] = pTofNeHadron ;
+ stof[AliPID::kNeutron][index] = pTofNeHadron ;
+ }
+
+ // Info("MakePID", "Dispersion");
+
+ // ###########Shower shape: Dispersion####################
+ Float_t dispersion = emc->GetDispersion();
+ //DP: Correct for non-perpendicular incidence
+ //DP: still to be done
+
+ //dispersion is not well defined if the cluster is only in few crystals
+ //Initialize anused species
+ for(Int_t iii=0; iii<kSPECIES; iii++)sdp[iii][index]=0. ;
+
+ sdp[AliPID::kPhoton][index] = 1. ;
+ sdp[AliPID::kElectron][index] = 1. ;
+ sdp[AliPID::kPion][index] = 1. ;
+ sdp[AliPID::kKaon][index] = 1. ;
+ sdp[AliPID::kProton][index] = 1. ;
+ sdp[AliPID::kNeutron][index] = 1. ;
+ sdp[AliPID::kEleCon][index] = 1. ;
+ sdp[AliPID::kKaon0][index] = 1. ;
+ sdp[AliPID::kMuon][index] = 1. ;
+
+ if(en > fDispEnThreshold && emc->GetMultiplicity() > fDispMultThreshold){
+ sdp[AliPID::kPhoton][index] = GausF(en , dispersion, fDphoton) ;
+ sdp[AliPID::kElectron][index] = sdp[AliPID::kPhoton][index] ;
+ sdp[AliPID::kPion][index] = LandauF(en , dispersion, fDhadron ) ;
+ sdp[AliPID::kKaon][index] = sdp[AliPID::kPion][index] ;
+ sdp[AliPID::kProton][index] = sdp[AliPID::kPion][index] ;
+ sdp[AliPID::kNeutron][index] = sdp[AliPID::kPion][index] ;
+ sdp[AliPID::kEleCon][index] = sdp[AliPID::kPhoton][index];
+ sdp[AliPID::kKaon0][index] = sdp[AliPID::kPion][index] ;
+ sdp[AliPID::kMuon][index] = fDFmuon ->Eval(dispersion) ;
+ //landau distribution
+ }
+
+// Info("MakePID","multiplicity %d, dispersion %f", emc->GetMultiplicity(), dispersion);
+// Info("MakePID","ss: photon %f, hadron %f ", sdp[AliPID::kPhoton][index], sdp[AliPID::kPion][index]);
+// cout<<">>>>>multiplicity "<<emc->GetMultiplicity()<<", dispersion "<< dispersion<<endl ;
+// cout<<"<<<<<ss: photon "<<sdp[AliPID::kPhoton][index]<<", hadron "<<sdp[AliPID::kPion][index]<<endl;
+
+ //########## CPV-EMC Distance#######################
+ // Info("MakePID", "Distance");
+
+ Float_t x = TMath::Abs(ts->GetCpvDistance("X")) ;
+ Float_t z = ts->GetCpvDistance("Z") ;
+
+ Double_t pcpv = 0 ;
+ Double_t pcpvneutral = 0. ;
+
+ Double_t elprobx = GausF(en , x, fXelectron) ;
+ Double_t elprobz = GausF(en , z, fZelectron) ;
+ Double_t chprobx = GausF(en , x, fXcharged) ;
+ Double_t chprobz = GausF(en , z, fZcharged) ;
+ Double_t pcpvelectron = elprobx * elprobz;
+ Double_t pcpvcharged = chprobx * chprobz;
+
+// cout<<">>>>energy "<<en<<endl;
+// cout<<">>>>electron : x "<<x<<" xprob "<<elprobx<<" z "<<z<<" zprob "<<elprobz<<endl;
+// cout<<">>>>hadron : x "<<x<<" xprob "<<chprobx<<" z "<<z<<" zprob "<<chprobz<<endl;
+// cout<<">>>>electron : px*pz "<<pcpvelectron <<" hadron: px*pz "<<pcpvcharged<<endl;
+
+ // Is neutral or charged?
+ if(pcpvelectron >= pcpvcharged)
+ pcpv = pcpvelectron ;
+ else
+ pcpv = pcpvcharged ;
+
+ if(pcpv < fChargedNeutralThreshold)
+ {
+ pcpvneutral = 1. ;
+ pcpvcharged = 0. ;
+ pcpvelectron = 0. ;
+ }
+ // else
+ // cout<<">>>>>>>>>>>CHARGED>>>>>>>>>>>"<<endl;
+ //Initialize anused species
+ for(Int_t iii=0; iii<kSPECIES; iii++)scpv[iii][index]=0. ;
+
+ scpv[AliPID::kPion][index] = pcpvcharged ;
+ scpv[AliPID::kKaon][index] = pcpvcharged ;
+ scpv[AliPID::kProton][index] = pcpvcharged ;
+
+ scpv[AliPID::kMuon][index] = pcpvelectron ;
+ scpv[AliPID::kElectron][index] = pcpvelectron ;
+ scpv[AliPID::kEleCon][index] = pcpvelectron ;
+
+ scpv[AliPID::kPhoton][index] = pcpvneutral ;
+ scpv[AliPID::kNeutron][index] = pcpvneutral ;
+ scpv[AliPID::kKaon0][index] = pcpvneutral ;
+
+
+ // Info("MakePID", "CPV passed");
+
+ //############## Pi0 #############################
+ stof[AliPID::kPi0][index] = 0. ;
+ scpv[AliPID::kPi0][index] = 0. ;
+ sdp [AliPID::kPi0][index] = 0. ;
+
+ if(en > 30.){
+ // pi0 are detected via decay photon
+ stof[AliPID::kPi0][index] = stof[AliPID::kPhoton][index];
+ scpv[AliPID::kPi0][index] = pcpvneutral ;
+ if(emc->GetMultiplicity() > fDispMultThreshold)
+ sdp [AliPID::kPi0][index] = GausF(en , dispersion, fDpi0) ;
+ //sdp [AliPID::kPi0][index] = GausPol2(en , dispersion, fDpi0) ;
+// cout<<"E = "<<en<<" GeV; disp = "<<dispersion<<"; mult = "
+// <<emc->GetMultiplicity()<<endl;
+// cout<<"PDF: photon = "<<sdp [AliPID::kPhoton][index]<<"; pi0 = "
+// <<sdp [AliPID::kPi0][index]<<endl;
+ }
+
+
+
+
+ //############## muon #############################
+
+ if(en > 0.5){
+ //Muons deposit few energy
+ scpv[AliPID::kMuon][index] = 0 ;
+ stof[AliPID::kMuon][index] = 0 ;
+ sdp [AliPID::kMuon][index] = 0 ;
+ }
+
+ //Weight to apply to hadrons due to energy reconstruction
+ //Initialize anused species
+ for(Int_t iii=0; iii<kSPECIES; iii++)sw[iii][index]=1. ;
+
+ Float_t weight = fERecWeight ->Eval(en) ;
+
+ sw[AliPID::kPhoton][index] = 1. ;
+ sw[AliPID::kElectron][index] = 1. ;
+ sw[AliPID::kPion][index] = weight ;
+ sw[AliPID::kKaon][index] = weight ;
+ sw[AliPID::kProton][index] = weight ;
+ sw[AliPID::kNeutron][index] = weight ;
+ sw[AliPID::kEleCon][index] = 1. ;
+ sw[AliPID::kKaon0][index] = weight ;
+ sw[AliPID::kMuon][index] = weight ;
+ sw[AliPID::kPi0][index] = 1. ;
+
+// if(en > 0.5){
+// cout<<"######################################################"<<endl;
+// //cout<<"MakePID: energy "<<en<<", tof "<<time<<", distance "<<distance<<", dispersion "<<dispersion<<endl ;
+// cout<<"MakePID: energy "<<en<<", tof "<<time<<", dispersion "<<dispersion<<", x "<<x<<", z "<<z<<endl ;
+// cout<<">>>>>multiplicity "<<emc->GetMultiplicity()<<endl;
+// cout<<">>>>electron : xprob "<<elprobx<<" zprob "<<elprobz<<endl;
+// cout<<">>>>hadron : xprob "<<chprobx<<" zprob "<<chprobz<<endl;
+// cout<<">>>>electron : px*pz "<<pcpvelectron <<" hadron: px*pz "<<pcpvcharged<<endl;
+
+// cout<<"Photon , pid "<< fInitPID[AliPID::kPhoton]<<" tof "<<stof[AliPID::kPhoton][index]
+// <<", cpv "<<scpv[AliPID::kPhoton][index]<<", ss "<<sdp[AliPID::kPhoton][index]<<endl;
+// cout<<"EleCon , pid "<< fInitPID[AliPID::kEleCon]<<", tof "<<stof[AliPID::kEleCon][index]
+// <<", cpv "<<scpv[AliPID::kEleCon][index]<<" ss "<<sdp[AliPID::kEleCon][index]<<endl;
+// cout<<"Electron , pid "<< fInitPID[AliPID::kElectron]<<", tof "<<stof[AliPID::kElectron][index]
+// <<", cpv "<<scpv[AliPID::kElectron][index]<<" ss "<<sdp[AliPID::kElectron][index]<<endl;
+// cout<<"Muon , pid "<< fInitPID[AliPID::kMuon]<<", tof "<<stof[AliPID::kMuon][index]
+// <<", cpv "<<scpv[AliPID::kMuon][index]<<" ss "<<sdp[AliPID::kMuon][index]<<endl;
+// cout<<"Pi0 , pid "<< fInitPID[AliPID::kPi0]<<", tof "<<stof[AliPID::kPi0][index]
+// <<", cpv "<<scpv[AliPID::kPi0][index]<<" ss "<<sdp[AliPID::kPi0][index]<<endl;
+// cout<<"Pion , pid "<< fInitPID[AliPID::kPion]<<", tof "<<stof[AliPID::kPion][index]
+// <<", cpv "<<scpv[AliPID::kPion][index]<<" ss "<<sdp[AliPID::kPion][index]<<endl;
+// cout<<"Kaon0 , pid "<< fInitPID[AliPID::kKaon0]<<", tof "<<stof[AliPID::kKaon0][index]
+// <<", cpv "<<scpv[AliPID::kKaon0][index]<<" ss "<<sdp[AliPID::kKaon0][index]<<endl;
+// cout<<"Kaon , pid "<< fInitPID[AliPID::kKaon]<<", tof "<<stof[AliPID::kKaon][index]
+// <<", cpv "<<scpv[AliPID::kKaon][index]<<" ss "<<sdp[AliPID::kKaon][index]<<endl;
+// cout<<"Neutron , pid "<< fInitPID[AliPID::kNeutron]<<", tof "<<stof[AliPID::kNeutron][index]
+// <<", cpv "<<scpv[AliPID::kNeutron][index]<<" ss "<<sdp[AliPID::kNeutron][index]<<endl;
+// cout<<"Proton , pid "<< fInitPID[AliPID::kProton]<<", tof "<<stof[AliPID::kProton][index]
+// <<", cpv "<<scpv[AliPID::kProton][index]<<" ss "<<sdp[AliPID::kProton][index]<<endl;
+// cout<<"######################################################"<<endl;
+// }
+ index++;
+ }
+
+ //for (index = 0 ; index < kSPECIES ; index++)
+ // pid[index] /= nparticles ;
+
+
+ // Info("MakePID", "Total Probability calculation");
+
+ for(index = 0 ; index < nparticles ; index ++) {
+
+ AliPHOSRecParticle * recpar = static_cast<AliPHOSRecParticle *>(fRecParticles->At(index));
+
+ //Conversion electron?
+
+ if(recpar->IsEleCon()){
+ fInitPID[AliPID::kEleCon] = 1. ;
+ fInitPID[AliPID::kPhoton] = 0. ;
+ fInitPID[AliPID::kElectron] = 0. ;
+ }
+ else{
+ fInitPID[AliPID::kEleCon] = 0. ;
+ fInitPID[AliPID::kPhoton] = 1. ;
+ fInitPID[AliPID::kElectron] = 1. ;
+ }
+ // fInitPID[AliPID::kEleCon] = 0. ;
+
+
+ // calculates the Bayesian weight
+
+ Int_t jndex ;
+ Double_t wn = 0.0 ;
+ for (jndex = 0 ; jndex < kSPECIES ; jndex++)
+ wn += stof[jndex][index] * sdp[jndex][index] * scpv[jndex][index] *
+ sw[jndex][index] * fInitPID[jndex] ;
+
+ // cout<<"*************wn "<<wn<<endl;
+ if (TMath::Abs(wn)>0)
+ for (jndex = 0 ; jndex < kSPECIES ; jndex++) {
+ //cout<<"jndex "<<jndex<<" wn "<<wn<<" SetPID * wn"
+ //<<stof[jndex][index] * sdp[jndex][index] * pid[jndex] << endl;
+ //cout<<" tof "<<stof[jndex][index] << " disp " <<sdp[jndex][index] << " pid "<< fInitPID[jndex] << endl;
+ // if(jndex == AliPID::kPi0 || jndex == AliPID::kPhoton){
+ // cout<<"Particle "<<jndex<<" final prob * wn "
+ // <<stof[jndex][index] * sdp[jndex][index] * scpv[jndex][index] *
+ // fInitPID[jndex] <<" wn "<< wn<<endl;
+ // cout<<"pid "<< fInitPID[jndex]<<", tof "<<stof[jndex][index]
+ // <<", cpv "<<scpv[jndex][index]<<" ss "<<sdp[jndex][index]<<endl;
+ // }
+ recpar->SetPID(jndex, stof[jndex][index] * sdp[jndex][index] *
+ sw[jndex][index] * scpv[jndex][index] *
+ fInitPID[jndex] / wn) ;
+ }
+ }
+ // Info("MakePID", "Delete");
+
+ for (Int_t i =0; i< kSPECIES; i++){
+ delete [] stof[i];
+ delete [] sdp [i];
+ delete [] scpv[i];
+ delete [] sw [i];
+ }
+ // Info("MakePID","End MakePID");
+}
+
+//____________________________________________________________________________
+void AliPHOSPIDv1::MakeRecParticles()
+{
+ // Makes a RecParticle out of a TrackSegment
+
+ if ( !fEMCRecPoints || !fCPVRecPoints || !fTrackSegments ) {
+ AliFatal("RecPoints or TrackSegments not found !") ;
+ }
+ fRecParticles->Clear();
+
+ TIter next(fTrackSegments) ;
+ AliPHOSTrackSegment * ts ;