#include "AliESDtrack.h"
#include "AliESDEvent.h"
#include "AliTOFT0v1.h"
#include "TBenchmark.h"
#include "AliPID.h"
#include "AliESDpid.h"
ClassImp(AliTOFT0v1)
AliTOFT0v1::AliTOFT0v1(AliESDpid *extPID):
TObject(),
fLowerMomBound(0.5),
fUpperMomBound(3),
fTimeCorr(0.),
fEvent(0x0),
fPIDesd(extPID),
fTracks(new TObjArray(10)),
fGTracks(new TObjArray(10)),
fTracksT0(new TObjArray(10)),
fOptFlag(kFALSE)
{
if(AliPID::ParticleMass(0) == 0) new AliPID();
if(!fPIDesd){
fPIDesd = new AliESDpid();
}
Init(NULL);
for (Int_t i=0; i<15; ++i) {
fLookupPowerThree[i]=ToCalculatePower(3,i);
}
}
AliTOFT0v1::AliTOFT0v1(AliESDEvent* event,AliESDpid *extPID):
TObject(),
fLowerMomBound(0.5),
fUpperMomBound(3.0),
fTimeCorr(0.),
fEvent(event),
fPIDesd(extPID),
fTracks(new TObjArray(10)),
fGTracks(new TObjArray(10)),
fTracksT0(new TObjArray(10)),
fOptFlag(kFALSE)
{
if(AliPID::ParticleMass(0) == 0) new AliPID();
if(!fPIDesd){
fPIDesd = new AliESDpid();
}
Init(event);
for (Int_t i=0; i<15; ++i) {
fLookupPowerThree[i]=Int_t(TMath::Power(3,i));
}
}
AliTOFT0v1& AliTOFT0v1::operator=(const AliTOFT0v1 &tzero)
{
if (this == &tzero)
return *this;
fLowerMomBound=tzero.fLowerMomBound;
fUpperMomBound=tzero.fUpperMomBound;
fTimeCorr=tzero.fTimeCorr;
fEvent=tzero.fEvent;
fT0SigmaT0def[0]=tzero.fT0SigmaT0def[0];
fT0SigmaT0def[1]=tzero.fT0SigmaT0def[1];
fT0SigmaT0def[2]=tzero.fT0SigmaT0def[2];
fT0SigmaT0def[3]=tzero.fT0SigmaT0def[3];
fTracks=tzero.fTracks;
fGTracks=tzero.fGTracks;
fTracksT0=tzero.fTracksT0;
for (Int_t ii=0; ii<tzero.fTracks->GetEntries(); ii++)
fTracks->AddLast(tzero.fTracks->At(ii));
for (Int_t ii=0; ii<tzero.fGTracks->GetEntries(); ii++)
fGTracks->AddLast(tzero.fGTracks->At(ii));
for (Int_t ii=0; ii<tzero.fTracksT0->GetEntries(); ii++)
fTracksT0->AddLast(tzero.fTracksT0->At(ii));
fOptFlag=tzero.fOptFlag;
return *this;
}
AliTOFT0v1::~AliTOFT0v1()
{
fEvent=NULL;
if (fTracks) {
fTracks->Clear();
delete fTracks;
fTracks=0x0;
}
if (fGTracks) {
fGTracks->Clear();
delete fGTracks;
fGTracks=0x0;
}
if (fTracksT0) {
fTracksT0->Clear();
delete fTracksT0;
fTracksT0=0x0;
}
}
void
AliTOFT0v1::Init(AliESDEvent *event)
{
fEvent = event;
fT0SigmaT0def[0]=0.;
fT0SigmaT0def[1]=0.6;
fT0SigmaT0def[2]=0.;
fT0SigmaT0def[3]=0.;
}
Double_t * AliTOFT0v1::DefineT0(Option_t *option,Float_t pMinCut,Float_t pMaxCut)
{
TBenchmark *bench=new TBenchmark();
bench->Start("t0computation");
fT0SigmaT0def[0]=0.;
fT0SigmaT0def[1]=0.600;
fT0SigmaT0def[2]=0.;
fT0SigmaT0def[3]=0.;
const Int_t nmaxtracksinsetMax=10;
Int_t nmaxtracksinset=10;
Int_t nsets=0;
Int_t nUsedTracks=0;
Int_t ngoodsetsSel= 0;
Float_t t0bestSel[300];
Float_t eT0bestSel[300];
Float_t chiSquarebestSel[300];
Float_t confLevelbestSel[300];
Float_t t0bestallSel=0.;
Float_t eT0bestallSel=0.;
Float_t sumWt0bestallSel=0.;
Float_t eMeanTzeroPi=0.;
Float_t meantzeropi=0.;
Float_t sumAllweightspi=0.;
Double_t t0def=-999;
Double_t deltat0def=999;
Int_t ngoodtrktrulyused=0;
Int_t ntracksinsetmyCut = 0;
Int_t ntrk=fEvent->GetNumberOfTracks();
Int_t ngoodtrk=0;
Int_t ngoodtrkt0 =0;
Float_t meantime =0;
fTracks->Clear();
for (Int_t itrk=0; itrk<ntrk; itrk++) {
AliESDtrack *t=fEvent->GetTrack(itrk);
Double_t momOld=t->GetP();
Double_t mom=momOld-0.0036*momOld;
if ((t->GetStatus()&AliESDtrack::kTIME)==0) continue;
if ((t->GetStatus()&AliESDtrack::kTOFout)==0) continue;
Double_t time=t->GetTOFsignal();
time*=1.E-3;
if (!(mom<=fUpperMomBound && mom>=fLowerMomBound))continue;
if (!AcceptTrack(t)) continue;
if(t->GetIntegratedLength() < 350)continue;
if(t->GetP() > pMinCut && t->GetP() < pMaxCut) continue;
meantime+=time;
fTracks->AddLast(t);
ngoodtrk++;
}
if(ngoodtrk > 1) meantime /= ngoodtrk;
if(ngoodtrk>22) nmaxtracksinset = 6;
fGTracks->Clear();
for (Int_t jtrk=0; jtrk< fTracks->GetEntries(); jtrk++) {
AliESDtrack *t=(AliESDtrack*)fTracks->At(jtrk);
fGTracks->AddLast(t);
ngoodtrkt0++;
}
fTracks->Clear();
Int_t nseteq = (ngoodtrkt0-1)/nmaxtracksinset + 1;
Int_t nmaxtracksinsetCurrent=ngoodtrkt0/nseteq;
if(nmaxtracksinsetCurrent*nseteq < ngoodtrkt0) nmaxtracksinsetCurrent++;
if(ngoodtrkt0<2){
t0def=-999;
deltat0def=0.600;
fT0SigmaT0def[0]=t0def;
fT0SigmaT0def[1]=deltat0def;
fT0SigmaT0def[2]=ngoodtrkt0;
fT0SigmaT0def[3]=ngoodtrkt0;
}
if(ngoodtrkt0>=2){
Int_t ntracksinset = std::min(ngoodtrkt0,nmaxtracksinsetCurrent);
Int_t nset=1;
if(ngoodtrkt0>nmaxtracksinsetCurrent) {nset= (Int_t)(ngoodtrkt0/ntracksinset)+1;}
if(nset>=1){
for (Int_t i=0; i< nset; i++) {
Float_t t0best=999.;
Float_t eT0best=999.;
Float_t chisquarebest=99999.;
Int_t npionbest=0;
fTracksT0->Clear();
Int_t ntracksinsetmy=0;
for (Int_t itrk=0; itrk<ntracksinset; itrk++) {
Int_t index = itrk+i*ntracksinset;
if(index < fGTracks->GetEntries()){
AliESDtrack *t=(AliESDtrack*)fGTracks->At(index);
fTracksT0->AddLast(t);
ntracksinsetmy++;
}
}
Int_t assparticle[nmaxtracksinsetMax];
Float_t exptof[nmaxtracksinsetMax][3];
Float_t momErr[nmaxtracksinsetMax][3];
Float_t timeofflight[nmaxtracksinsetMax];
Float_t momentum[nmaxtracksinsetMax];
Float_t timezero[nmaxtracksinsetMax];
Float_t weightedtimezero[nmaxtracksinsetMax];
Float_t beta[nmaxtracksinsetMax];
Float_t texp[nmaxtracksinsetMax];
Float_t dtexp[nmaxtracksinsetMax];
Float_t sqMomError[nmaxtracksinsetMax];
Float_t sqTrackError[nmaxtracksinsetMax];
Float_t massarray[3]={0.13957,0.493677,0.9382723};
Float_t tracktoflen[nmaxtracksinsetMax];
Float_t besttimezero[nmaxtracksinsetMax];
Float_t besttexp[nmaxtracksinsetMax];
Float_t besttimeofflight[nmaxtracksinsetMax];
Float_t bestmomentum[nmaxtracksinsetMax];
Float_t bestchisquare[nmaxtracksinsetMax];
Float_t bestweightedtimezero[nmaxtracksinsetMax];
Float_t bestsqTrackError[nmaxtracksinsetMax];
Int_t imass[nmaxtracksinsetMax];
for (Int_t j=0; j<ntracksinset; j++) {
assparticle[j] = 3;
timeofflight[j] = 0;
momentum[j] = 0;
timezero[j] = 0;
weightedtimezero[j] = 0;
beta[j] = 0;
texp[j] = 0;
dtexp[j] = 0;
sqMomError[j] = 0;
sqTrackError[j] = 0;
tracktoflen[j] = 0;
besttimezero[j] = 0;
besttexp[j] = 0;
besttimeofflight[j] = 0;
bestmomentum[j] = 0;
bestchisquare[j] = 0;
bestweightedtimezero[j] = 0;
bestsqTrackError[j] = 0;
imass[j] = 1;
}
for (Int_t j=0; j<fTracksT0->GetEntries(); j++) {
AliESDtrack *t=(AliESDtrack*)fTracksT0->At(j);
Double_t momOld=t->GetP();
Double_t mom=momOld-0.0036*momOld;
Double_t time=t->GetTOFsignal();
time*=1.E-3;
Double_t exptime[AliPID::kSPECIESC];
t->GetIntegratedTimes(exptime,AliPID::kSPECIESC);
Double_t toflen=t->GetIntegratedLength();
toflen=toflen/100.;
timeofflight[j]=time;
tracktoflen[j]=toflen;
exptof[j][0]=exptime[2]*1.E-3+fTimeCorr;
exptof[j][1]=exptime[3]*1.E-3+fTimeCorr;
exptof[j][2]=exptime[4]*1.E-3+fTimeCorr;
momentum[j]=mom;
assparticle[j]=3;
if (fOptFlag) {
momErr[j][0]=GetMomError(0, momentum[j], exptof[j][0]);
momErr[j][1]=GetMomError(1, momentum[j], exptof[j][1]);
momErr[j][2]=GetMomError(2, momentum[j], exptof[j][2]);
}
}
for (Int_t itz=0; itz<ntracksinsetmy;itz++) {
beta[itz]=momentum[itz]/sqrt(massarray[0]*massarray[0]
+momentum[itz]*momentum[itz]);
sqMomError[itz]= ((1.-beta[itz]*beta[itz])*0.01)*((1.-beta[itz]*beta[itz])*0.01)*(tracktoflen[itz]/(0.299792*beta[itz]))*(tracktoflen[itz]/(0.299792*beta[itz]));
sqTrackError[itz]=sqMomError[itz];
timezero[itz]=exptof[itz][0]-timeofflight[itz];
weightedtimezero[itz]=timezero[itz]/sqTrackError[itz];
sumAllweightspi+=1./sqTrackError[itz];
meantzeropi+=weightedtimezero[itz];
}
if(ntracksinsetmy<2 )break;
for (Int_t j=0; j<ntracksinsetmy; j++) {
imass[j] = 3;
}
Int_t ncombinatorial;
if (fOptFlag) ncombinatorial = fLookupPowerThree[ntracksinsetmy];
else ncombinatorial = ToCalculatePower(3,ntracksinsetmy);
for (Int_t k=0; k < ncombinatorial;k++) {
for (Int_t j=0; j<ntracksinsetmy; j++) {
imass[j] = (k % fLookupPowerThree[ntracksinsetmy-j])/fLookupPowerThree[ntracksinsetmy-j-1];
texp[j]=exptof[j][imass[j]];
if (fOptFlag) dtexp[j]=momErr[j][imass[j]];
else dtexp[j]=GetMomError(imass[j], momentum[j], texp[j]);
}
Float_t sumAllweights=0.;
Float_t meantzero=0.;
Float_t eMeanTzero=0.;
for (Int_t itz=0; itz<ntracksinsetmy;itz++) {
sqTrackError[itz]=dtexp[itz]*dtexp[itz]*1E-6;
timezero[itz]=texp[itz]-timeofflight[itz];
weightedtimezero[itz]=timezero[itz]/sqTrackError[itz];
sumAllweights+=1./sqTrackError[itz];
meantzero+=weightedtimezero[itz];
}
meantzero=meantzero/sumAllweights;
eMeanTzero=sqrt(1./sumAllweights);
Float_t chisquare=0.;
for (Int_t icsq=0; icsq<ntracksinsetmy;icsq++) {
chisquare+=(timezero[icsq]-meantzero)*(timezero[icsq]-meantzero)/sqTrackError[icsq];
}
if(chisquare<=chisquarebest){
for(Int_t iqsq = 0; iqsq<ntracksinsetmy; iqsq++) {
bestsqTrackError[iqsq]=sqTrackError[iqsq];
besttimezero[iqsq]=timezero[iqsq];
bestmomentum[iqsq]=momentum[iqsq];
besttimeofflight[iqsq]=timeofflight[iqsq];
besttexp[iqsq]=texp[iqsq];
bestweightedtimezero[iqsq]=weightedtimezero[iqsq];
bestchisquare[iqsq]=(timezero[iqsq]-meantzero)*(timezero[iqsq]-meantzero)/sqTrackError[iqsq];
}
Int_t npion=0;
for (Int_t j=0; j<ntracksinsetmy; j++) {
assparticle[j]=imass[j];
if(imass[j] == 0) npion++;
}
npionbest=npion;
chisquarebest=chisquare;
t0best=meantzero;
eT0best=eMeanTzero;
}
}
Double_t chi2cut[nmaxtracksinsetMax];
chi2cut[0] = 0;
chi2cut[1] = 6.6;
for (Int_t j=2; j<ntracksinset; j++) {
chi2cut[j] = chi2cut[1] * TMath::Sqrt(j*1.);
}
Double_t chi2singlecut = chi2cut[ntracksinsetmy-1]/ntracksinsetmy + TMath::Abs(chisquarebest-chi2cut[ntracksinsetmy-1])/ntracksinsetmy;
Bool_t kRedoT0 = kFALSE;
ntracksinsetmyCut = ntracksinsetmy;
Bool_t usetrack[nmaxtracksinsetMax];
for (Int_t icsq=0; icsq<ntracksinsetmy;icsq++) {
usetrack[icsq] = kTRUE;
if((bestchisquare[icsq] > chisquarebest*0.5 && ntracksinsetmy > 2) || (bestchisquare[icsq] > chi2singlecut)){
kRedoT0 = kTRUE;
ntracksinsetmyCut--;
usetrack[icsq] = kFALSE;
}
}
if(kRedoT0 && ntracksinsetmyCut > 1){
for (Int_t k=0; k < ncombinatorial;k++) {
for (Int_t j=0; j<ntracksinsetmy; j++) {
imass[j] = (k % fLookupPowerThree[ntracksinsetmy-j]) / fLookupPowerThree[ntracksinsetmy-j-1];
texp[j]=exptof[j][imass[j]];
if (fOptFlag) dtexp[j]=momErr[j][imass[j]];
else dtexp[j]=GetMomError(imass[j], momentum[j], texp[j]);
}
Float_t sumAllweights=0.;
Float_t meantzero=0.;
Float_t eMeanTzero=0.;
for (Int_t itz=0; itz<ntracksinsetmy;itz++) {
if(! usetrack[itz]) continue;
sqTrackError[itz]=dtexp[itz]*dtexp[itz]*1E-6;
timezero[itz]=texp[itz]-timeofflight[itz];
weightedtimezero[itz]=timezero[itz]/sqTrackError[itz];
sumAllweights+=1./sqTrackError[itz];
meantzero+=weightedtimezero[itz];
}
meantzero=meantzero/sumAllweights;
eMeanTzero=sqrt(1./sumAllweights);
Float_t chisquare=0.;
for (Int_t icsq=0; icsq<ntracksinsetmy;icsq++) {
if(! usetrack[icsq]) continue;
chisquare+=(timezero[icsq]-meantzero)*(timezero[icsq]-meantzero)/sqTrackError[icsq];
}
Int_t npion=0;
for (Int_t j=0; j<ntracksinsetmy; j++) {
assparticle[j]=imass[j];
if(imass[j] == 0) npion++;
}
if(chisquare<=chisquarebest && npion>0){
for(Int_t iqsq = 0; iqsq<ntracksinsetmy; iqsq++) {
if(! usetrack[iqsq]) continue;
bestsqTrackError[iqsq]=sqTrackError[iqsq];
besttimezero[iqsq]=timezero[iqsq];
bestmomentum[iqsq]=momentum[iqsq];
besttimeofflight[iqsq]=timeofflight[iqsq];
besttexp[iqsq]=texp[iqsq];
bestweightedtimezero[iqsq]=weightedtimezero[iqsq];
bestchisquare[iqsq]=(timezero[iqsq]-meantzero)*(timezero[iqsq]-meantzero)/sqTrackError[iqsq];
}
npionbest=npion;
chisquarebest=chisquare;
t0best=meantzero;
eT0best=eMeanTzero;
}
}
}
Float_t confLevel=999;
if(chisquarebest<999.){
Double_t dblechisquare=(Double_t)chisquarebest;
confLevel=(Float_t)TMath::Prob(dblechisquare,ntracksinsetmyCut-1);
Int_t ntrackincurrentsel=0;
for(Int_t icsq=0; icsq<ntracksinsetmy;icsq++){
if(! usetrack[icsq]) continue;
ntrackincurrentsel++;
}
if(confLevel>0.01 && ngoodsetsSel<200){
chiSquarebestSel[ngoodsetsSel]=chisquarebest;
confLevelbestSel[ngoodsetsSel]=confLevel;
t0bestSel[ngoodsetsSel]=t0best/eT0best/eT0best;
eT0bestSel[ngoodsetsSel]=1./eT0best/eT0best;
t0bestallSel += t0best/eT0best/eT0best;
sumWt0bestallSel += 1./eT0best/eT0best;
ngoodsetsSel++;
ngoodtrktrulyused+=ntracksinsetmyCut;
}
else{
}
}
fTracksT0->Clear();
nsets++;
}
if(ngoodsetsSel > 1){
Double_t t0BestStep1 = t0bestallSel/sumWt0bestallSel;
Int_t nsamples=ngoodsetsSel;
ngoodsetsSel=0;
t0bestallSel=0;
sumWt0bestallSel=0;
for (Int_t itz=0; itz<nsamples;itz++) {
if(TMath::Abs(t0bestSel[itz]/eT0bestSel[itz]-t0BestStep1)<1.0){
t0bestallSel += t0bestSel[itz];
sumWt0bestallSel += eT0bestSel[itz];
ngoodsetsSel++;
}
else{
}
}
}
if(ngoodsetsSel < 1){
sumWt0bestallSel = 0.0;
}
nUsedTracks = ngoodtrkt0;
if(strstr(option,"all")){
if(sumAllweightspi>0.){
meantzeropi=meantzeropi/sumAllweightspi;
eMeanTzeroPi=sqrt(1./sumAllweightspi);
}
if(sumWt0bestallSel>0){
t0bestallSel = t0bestallSel/sumWt0bestallSel;
eT0bestallSel = sqrt(1./sumWt0bestallSel);
}
}
t0def=t0bestallSel;
deltat0def=eT0bestallSel;
fT0SigmaT0def[0]=t0def;
fT0SigmaT0def[1]=TMath::Sqrt(deltat0def*deltat0def);
fT0SigmaT0def[2]=ngoodtrkt0;
fT0SigmaT0def[3]=ngoodtrktrulyused;
}
}
fGTracks->Clear();
if(fT0SigmaT0def[1] < 0.00001) fT0SigmaT0def[1] = 0.6;
bench->Stop("t0computation");
fT0SigmaT0def[4]=bench->GetRealTime("t0computation");
fT0SigmaT0def[5]=bench->GetCpuTime("t0computation");
delete bench;
bench=NULL;
return fT0SigmaT0def;
}
Float_t AliTOFT0v1::GetMomError(Int_t index, Float_t mom, Float_t texp) const
{
static const Double_t kMasses[]={
0.000511, 0.105658, 0.139570, 0.493677, 0.938272, 1.875613
};
Double_t mass=kMasses[index+2];
Float_t sigma = fPIDesd->GetTOFResponse().GetExpectedSigma(mom,texp,mass);
return sigma;
}
Bool_t AliTOFT0v1::AcceptTrack(AliESDtrack *track)
{
if (!(track->GetStatus() & AliESDtrack::kTPCrefit)) return kFALSE;
if (track->GetKinkIndex(0)>0) return kFALSE;
if (track->GetTPCclusters(0) < 50) return kFALSE;
if (track->GetTPCchi2()/Float_t(track->GetTPCclusters(0)) > 3.5) return kFALSE;
if (GetSigmaToVertex(track) > 4.) return kFALSE;
return kTRUE;
}
Float_t AliTOFT0v1::GetSigmaToVertex(AliESDtrack* esdTrack) const
{
Float_t b[2];
Float_t bRes[2];
Float_t bCov[3];
esdTrack->GetImpactParameters(b,bCov);
if (bCov[0]<=0 || bCov[2]<=0) {
bCov[0]=0; bCov[2]=0;
}
bRes[0] = TMath::Sqrt(bCov[0]);
bRes[1] = TMath::Sqrt(bCov[2]);
if (bRes[0] == 0 || bRes[1] ==0)
return -1;
Float_t d = TMath::Sqrt(ToCalculatePower(b[0]/bRes[0],2) + ToCalculatePower(b[1]/bRes[1],2));
if (TMath::Exp(-d * d / 2) < 1e-15)
return 1000;
Float_t nSigma = TMath::ErfInverse(1 - TMath::Exp(-d * d / 2)) * TMath::Sqrt(2);
return nSigma;
}
Bool_t AliTOFT0v1::CheckTPCMatching(AliESDtrack *track,Int_t imass) const{
Bool_t status = kFALSE;
Double_t exptimes[AliPID::kSPECIESC];
track->GetIntegratedTimes(exptimes,AliPID::kSPECIESC);
Float_t dedx = track->GetTPCsignal();
Double_t ptpc[3];
track->GetInnerPxPyPz(ptpc);
Float_t momtpc=TMath::Sqrt(ptpc[0]*ptpc[0] + ptpc[1]*ptpc[1] + ptpc[2]*ptpc[2]);
if(imass > 2 || imass < 0) return status;
Int_t i = imass+2;
AliPID::EParticleType type=AliPID::EParticleType(i);
Float_t dedxExp = fPIDesd->GetTPCResponse().GetExpectedSignal(momtpc,type);
Float_t resolutionTPC = fPIDesd->GetTPCResponse().GetExpectedSigma(momtpc,track->GetTPCsignalN(),type);
if(TMath::Abs(dedx - dedxExp) < 5 * resolutionTPC){
status = kTRUE;
}
return status;
}
Float_t AliTOFT0v1::ToCalculatePower(Float_t base, Int_t exponent) const
{
Float_t power=1.;
for (Int_t ii=exponent; ii>0; ii--)
power=power*base;
return power;
}
Int_t AliTOFT0v1::ToCalculatePower(Int_t base, Int_t exponent) const
{
Int_t power=1;
for (Int_t ii=exponent; ii>0; ii--)
power=power*base;
return power;
}