/************************************************************************** * 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. * **************************************************************************/ // // TRD dEdx base utils // xx // xx // xx // xx // // Xianguo Lu // lu@physi.uni-heidelberg.de // Xianguo.Lu@cern.ch // // #include "TF1.h" #include "TFile.h" #include "TH1D.h" #include "TH2D.h" #include "THnSparse.h" #include "TMath.h" #include "TMatrixD.h" #include "TMinuit.h" #include "TObjArray.h" #include "TRandom3.h" #include "TStopwatch.h" #include "TVectorD.h" #include "TTreeStream.h" #include "AliESDEvent.h" #include "AliESDfriendTrack.h" #include "AliESDtrack.h" #include "AliTRDtrackV1.h" #include "AliTRDdEdxBaseUtils.h" #define EPSILON 1e-8 Double_t AliTRDdEdxBaseUtils::fgQ0Frac = 0.55; Double_t AliTRDdEdxBaseUtils::fgQ1Frac = 0.5; Double_t AliTRDdEdxBaseUtils::fgTimeBinCountCut = 0.0; Int_t AliTRDdEdxBaseUtils::fgCalibTPCnclsCut = 70; Bool_t AliTRDdEdxBaseUtils::fgExBOn = kTRUE; Bool_t AliTRDdEdxBaseUtils::fgPadGainOn = kTRUE; Double_t AliTRDdEdxBaseUtils::fgQScale = 50; //=================================================================================== // Math and Histogram //=================================================================================== void AliTRDdEdxBaseUtils::BinLogX(TAxis *axis) { // // Method for the correct logarithmic binning of histograms // copied and modified from AliTPCcalibBase const Int_t bins = axis->GetNbins(); const Double_t from = axis->GetXmin(); const Double_t to = axis->GetXmax(); if (fromSet(bins, new_bins); delete [] new_bins; } void AliTRDdEdxBaseUtils::GetCDFCuts(const TH1D *hh, Int_t ncut, Double_t cuts[], const Double_t cdfs[], Double_t thres) { // //counts of hh is sorted // for(Int_t ii=0; iiGetNbinsX(); Double_t datas[nbin]; for(Int_t ii=1; ii<=nbin; ii++){ const Double_t res = hh->GetBinContent(ii); if(res1){ printf("AliTRDdEdxBaseUtils::GetCDFCuts error cdfs[%d] %15f out of range!\n", ii, icdf); exit(1); } cuts[ii] = datas[id[Int_t(icdf*nsel)]]; } } Double_t AliTRDdEdxBaseUtils::GetMeanRMS(Double_t nn, Double_t sum, Double_t w2s, Double_t * grms, Double_t * gerr) { // //calculate mean (with error) and rms from sum, w2s, nn //if nn=0, mean, error, and rms all = 0 // Double_t tmean = 0, trms = 0, terr = 0; if(nn>EPSILON){ tmean = sum/nn; const Double_t arg = w2s/nn-tmean*tmean; if(TMath::Abs(arg)_{low-high according to x} // /* //test-> for(Int_t ii=0; iiGetNbinsX()+1; itmp++){ const Double_t be = hh->GetBinError(itmp); const Double_t bc = hh->GetBinContent(itmp); if(beEPSILON){ printf("AliTRDdEdxBaseUtils::TruncatedMean (hist) error %e %e %d\n", bc, be, itmp); exit(1); } continue; } npreTrunc += bc*bc/be/be; } const Double_t nstart = npreTrunc*lowfrac; const Double_t nstop = npreTrunc*highfrac; //with Double_t this should also handle normalized hist Double_t ntot = 0; Double_t nused = 0; Double_t sum = 0; Double_t w2s = 0; for(Int_t itmp=0; itmp<=hh->GetNbinsX()+1; itmp++){ const Double_t be = hh->GetBinError(itmp); const Double_t bc = hh->GetBinContent(itmp); if(beEPSILON){ printf("AliTRDdEdxBaseUtils::TruncatedMean (hist) error %e %e %d\n", bc, be, itmp); exit(1); } continue; } const Double_t weight = bc*bc/be/be; ntot+=weight; //<= correct, because when high=1, nstop has to be included if(ntot>nstart && ntot<=nstop){ const Double_t val = hh->GetBinCenter(itmp); sum += weight*val; w2s += weight*val*val; nused += weight; //printf("test %d %f %f --- %f %f -- %f %f\n", itmp, weight, val, sum, w2s, nused, nsample); } else if(ntot>nstop){ if(itmp>=hh->GetNbinsX()){ printf("AliTRDdEdxBaseUtils::TruncatedMean warning hist range too small %s %f %f %d %d, %15f %15f %15f; nused w2s sum set to 0\n", hh->GetName(), hh->GetBinLowEdge(1), hh->GetBinLowEdge(itmp), itmp, hh->GetNbinsX(), hh->GetBinContent(hh->GetNbinsX())/hh->Integral(0,hh->GetNbinsX()+1), hh->GetBinContent(hh->GetNbinsX()), hh->Integral(0,hh->GetNbinsX()+1)); //exit(1); nused = 0; w2s = sum = 0; } break; } } return GetMeanRMS(nused, sum, w2s, grms, gerr); } void AliTRDdEdxBaseUtils::FitSlicesY(const TH2D *hh, TH1D *&hnor, TH1D *&hmpv, TH1D *&hwid, TH1D *&hres, Double_t thres, Double_t lowfrac, Double_t highfrac) { // //fit slices of hh using truncation // const Int_t x0 = hh->GetXaxis()->GetFirst(); const Int_t x1 = hh->GetXaxis()->GetLast(); const Int_t y0 = hh->GetYaxis()->GetFirst(); const Int_t y1 = hh->GetYaxis()->GetLast(); const Int_t nx = hh->GetNbinsX(); const Int_t ny = hh->GetNbinsY(); const Double_t xmin = hh->GetXaxis()->GetXmin(); const Double_t xmax = hh->GetXaxis()->GetXmax(); const Double_t ymin = hh->GetYaxis()->GetXmin(); const Double_t ymax = hh->GetYaxis()->GetXmax(); hnor = new TH1D(Form("%s_amp",hh->GetName()), "", nx, xmin, xmax); hmpv = new TH1D(Form("%s_mpv",hh->GetName()), "", nx, xmin, xmax); hwid = new TH1D(Form("%s_wid",hh->GetName()), "", nx, xmin, xmax); hres = new TH1D(Form("%s_res",hh->GetName()), "", nx, xmin, xmax); Double_t newbins[ny+1]; for(Int_t ii=1; ii<=ny+1; ii++){ const Double_t lowx= hh->GetYaxis()->GetBinLowEdge(ii); newbins[ii-1]=lowx; } for(Int_t ix=x0; ix<=x1; ix++){ //to speed up const Double_t rawcount = hh->Integral(ix,ix,0, ny+1); if(rawcountGetName(), ix),"",ny, ymin, ymax); htmp->GetXaxis()->Set(ny, newbins); Double_t ntot = 0; for(Int_t iy=y0; iy<=y1; iy++){ const Double_t be = hh->GetBinError(ix,iy); const Double_t bc = hh->GetBinContent(ix, iy); if(beEPSILON){ printf("AliTRDdEdxBaseUtils::FitSlicesY error %d %d %e %e\n", ix, iy, be, bc); exit(1); } continue; } htmp->SetBinContent(iy, bc); htmp->SetBinError(iy, be); ntot += (bc/be)*(bc/be); //if(be) printf("test %d %d : %f %f %f\n", ix, iy, bc, be, pow(bc/be,2)); } hnor->SetBinContent(ix, ntot); hnor->SetBinError( ix, 0); if(ntotGetRMS()Draw(); Double_t trms = -999, terr = -999; const Double_t tmean = TruncatedMean(htmp, lowfrac, highfrac, &trms, &terr); hmpv->SetBinContent(ix, tmean); hmpv->SetBinError( ix, terr); hwid->SetBinContent(ix, trms); hwid->SetBinError( ix, 0); hres->SetBinContent(ix, tmean>EPSILON ? trms/tmean:0); hres->SetBinError( ix, 0); delete htmp; } TH1 *hhs[]={hnor, hmpv, hwid, hres}; const TString yt[]={"N", "MPV", "#sigma", "#sigma/MPV"}; const Int_t nh = sizeof(hhs)/sizeof(TH1*); for(Int_t ii=0; iiSetYTitle(Form("%s of %s", yt[ii].Data(), hh->GetYaxis()->GetTitle())); hhs[ii]->SetXTitle(hh->GetXaxis()->GetTitle()); hhs[ii]->GetYaxis()->SetTitleOffset(hh->GetYaxis()->GetTitleOffset()); hhs[ii]->SetTitle(hh->GetTitle()); } } //=================================================================================== // TRD Analysis Fast Tool //=================================================================================== Int_t AliTRDdEdxBaseUtils::GetNtracklet(const AliESDEvent *esd) { // //number of trd tracklet in one esd event // const Int_t ntrk0 = esd->GetNumberOfTracks(); Int_t ntrdv1=0; for(Int_t ii=0; iiGetTrack(ii)->GetTRDntracklets(); } return ntrdv1; } AliTRDtrackV1 * AliTRDdEdxBaseUtils::GetTRDtrackV1(const AliESDtrack * esdtrack) { // //Get TRD friend track // AliESDfriendTrack * friendtrk = (AliESDfriendTrack *)esdtrack->GetFriendTrack(); if(!friendtrk){ //printf("xlulog AliAnalysisTaskCosmicTRD::GetTRDtrack no friend!!\n"); exit(1); return 0x0; } TObject *calibObject=0x0; AliTRDtrackV1 * trdtrack=0x0; for(Int_t l=0; (calibObject=friendtrk->GetCalibObject(l)); l++) { if( (trdtrack=dynamic_cast(calibObject)) ) break; } return trdtrack; } Bool_t AliTRDdEdxBaseUtils::IsInSameStack(const AliTRDtrackV1 *trdtrack) { // // to check if all tracklets are in the same stack, useful in cosmic // TVectorD secs(18), stks(5); for(Int_t ilayer = 0; ilayer < 6; ilayer++){ AliTRDseedV1 *tracklet=trdtrack->GetTracklet(ilayer); if(!tracklet) continue; const Int_t det = tracklet->GetDetector(); const Int_t isector = AliTRDgeometry::GetSector(det); const Int_t istack = AliTRDgeometry::GetStack(det); secs[isector] = 1; stks[istack] = 1; } if(secs.Sum()!=1 || stks.Sum()!=1){ return kFALSE; } else return kTRUE; } Double_t AliTRDdEdxBaseUtils::GetRedefinedPhi(Double_t phi) { // //redefine phi in pi/2 - pi/2 + 2pi // if(phi>0 && phi < TMath::Pi()/2){ phi += 2*TMath::Pi(); } return phi; } Double_t AliTRDdEdxBaseUtils::Getdydx(const AliTRDseedV1 *tracklet) { // //get dydx // if(tracklet) return tracklet->GetYref(1); else return -999; } Double_t AliTRDdEdxBaseUtils::Getdzdx(const AliTRDseedV1 *tracklet) { // //get dzdx // if(tracklet) return tracklet->GetZref(1); else return -999; } Double_t AliTRDdEdxBaseUtils::Getdldx(const AliTRDseedV1 *tracklet) { // //return angular normalization factor = dldx // if(tracklet) return TMath::Sqrt(1+tracklet->GetYref(1)*tracklet->GetYref(1)+tracklet->GetZref(1)*tracklet->GetZref(1)); else return -999; } AliTRDseedV1 * AliTRDdEdxBaseUtils::GetFirstTracklet(const AliTRDtrackV1 *trdtrack) { // //as function name // AliTRDseedV1 *tracklet = 0x0; for(Int_t ilayer = 0; ilayer < 6; ilayer++){ tracklet=trdtrack->GetTracklet(ilayer); if(!tracklet) continue; break; } return tracklet; } AliTRDseedV1 * AliTRDdEdxBaseUtils::GetLastTracklet(const AliTRDtrackV1 *trdtrack) { // //get last tracklet // AliTRDseedV1 *tracklet = 0x0; for(Int_t ilayer = 5; ilayer >= 0; ilayer--){ tracklet=trdtrack->GetTracklet(ilayer); if(!tracklet) continue; break; } return tracklet; } void AliTRDdEdxBaseUtils::GetFirstSectorStackMomentum(const AliTRDtrackV1 *trdtrack, Int_t & isec, Int_t & istk, Double_t & mom) { // //as function name // isec = istk = -999; mom = -999; AliTRDseedV1 *tracklet = GetFirstTracklet(trdtrack); if(tracklet){ const Int_t det = tracklet->GetDetector(); isec = AliTRDgeometry::GetSector(det); istk = AliTRDgeometry::GetStack(det); mom = tracklet->GetMomentum(); } return; } //=================================================================================== // Detector and Data Constant //=================================================================================== Int_t AliTRDdEdxBaseUtils::ToDetector(Int_t gtb) { // //gtb = det*Ntb+itb // return gtb/AliTRDseedV1::kNtb; } Int_t AliTRDdEdxBaseUtils::ToTimeBin(Int_t gtb) { // //gtb = det*Ntb+itb // return gtb%AliTRDseedV1::kNtb; } Int_t AliTRDdEdxBaseUtils::ToSector(Int_t gtb) { // //return sector // return AliTRDgeometry::GetSector(ToDetector(gtb)); } Int_t AliTRDdEdxBaseUtils::ToStack(Int_t gtb) { // //return stack // return AliTRDgeometry::GetStack(ToDetector(gtb)); } Int_t AliTRDdEdxBaseUtils::ToLayer(Int_t gtb) { // //return layer // return AliTRDgeometry::GetLayer(ToDetector(gtb)); } void AliTRDdEdxBaseUtils::CheckRunB(TString listrun1kg, Int_t run, TString & type) { // //check run b field // if(listrun1kg.Contains(Form("%d",run))){ type+="1kG"; } else { type+="5kG"; } } TString AliTRDdEdxBaseUtils::GetRunType(Int_t run) { // //return run type // TString type; if(run>=121527 && run<= 126460)//LHC10d type="2010ppLHC10d"; else if(run>=126461 && run<= 130930)//LHC10e type="2010ppLHC10e"; else if(run>=136782 && run <= 139846)//LHC10h type="2010PbPbLHC10h"; else if(run>= 143224 && run<= 143237)//2011Feb type="2011cosmicFeb"; else if(run>= 150587 && run<= 154930){ type="2011cosmicMayJun"; CheckRunB("154601 154602 154629 154634 154636 154639 154643", run, type); } else if(run>=173047 && run<=180164){ type="2012cosmic"; CheckRunB("173047 173049 173050 173065 173070 173092 173095 173113 173131 173160 174154 174156 174192 174194", run, type); } else{ type="unknown"; } type.ToUpper(); return type; } void AliTRDdEdxBaseUtils::PrintControl() { // //print out control variable // printf("\nAliTRDdEdxBaseUtils::PrintControl Q0Frac %.2f, Q1Frac %.2f, TimeBinCountCut %.2f, CalibTPCnclsCut %d, IsExBOn %d, IsPadGainOn %d, QScale %.2f\n\n", Q0Frac(), Q1Frac(), TimeBinCountCut(), CalibTPCnclsCut(), IsExBOn(), IsPadGainOn(), QScale()); } //=================================================================================== // dEdx Parameterization //=================================================================================== void AliTRDdEdxBaseUtils::FastFitdEdxTR(TH1 * hh) { // //fit dedx tr from mean // TF1 *ff=new TF1("ff", MeandEdxTRLogx, -0.5, 4.5, 8); Double_t par[8]; par[0]= 2.397001e-01; par[1]= 1.334697e+00; par[2]= 6.967470e+00; par[3]= 9.055289e-02; par[4]= 9.388760e+00; par[5]= 9.452742e-04; par[6]= -1.866091e+00; par[7]= 1.403545e+00; ff->SetParameters(par); hh->Fit(ff,"N"); for(int ii=0; ii<8; ii++){ printf("par[%d]=%e;\n", ii, ff->GetParameter(ii)); } TFile *fout=new TFile("fastfit.root","recreate"); hh->Write(); ff->Write(); fout->Save(); fout->Close(); delete fout; delete ff; } Double_t AliTRDdEdxBaseUtils::Q0MeanTRDpp(Double_t bg) { // //truncated Mean Q_{xx} in TRD // Double_t par[8]; Double_t scale = 1; //2012-0605 /u/xlu/.task/CommondEdx/myAnaData/newTune_r56595/inuse/plot/fastFit scale = 0.9257; par[0]=8.316476e-01; par[1]=1.600907e+00; par[2]=7.728447e+00; par[3]=6.235622e-02; par[4]=1.136209e+01; par[5]=-1.495764e-06; par[6]=-2.536119e+00; par[7]=3.416031e+00; return scale*MeandEdxTR(&bg, par); } Double_t AliTRDdEdxBaseUtils::Q0MeanTRDPbPb(Double_t bg) { // //truncated Mean Q_{xx} in TRD // Double_t par[8]; //03132012161259 //opt: PbPbQ0 par[0]= 1.844912e-01; par[1]= 2.509702e+00; par[2]= 6.744031e+00; par[3]= 7.355123e-02; par[4]= 1.166023e+01; par[5]= 1.736186e-04; par[6]= -1.716063e+00; par[7]= 1.611366e+00; ///u/xlu/.task/CommondEdx/myAnaData/Optimum/check11/Merged/LHC10e_plot/Separation/see4.log:hhtype4Q0b2c2 scale 0.460994 at ltbg 0.650000 return 0.460994*MeandEdxTR(&bg, par); } Double_t AliTRDdEdxBaseUtils::Q1MeanTRDpp(Double_t bg) { // //truncated Mean 1/(1/Q)_{xx} in TRD // Double_t par[8]; //So 4. Mär 13:30:51 CET 2012 //opt: trdppQ1 par[0]= 2.434646e-01; par[1]= 1.400211e+00; par[2]= 6.937471e+00; par[3]= 7.758118e-02; par[4]= 1.097372e+01; par[5]= 4.297518e-04; par[6]= -1.806266e+00; par[7]= 1.543811e+00; //hhtype2Q1b2c2 scale 0.418629 at ltbg 0.650000 return 0.418629*MeandEdxTR(&bg, par); } Double_t AliTRDdEdxBaseUtils::Q1MeanTRDPbPb(Double_t bg) { // //truncated Mean 1/(1/Q)_{xx} in TRD // Double_t par[8]; //So 4. Mär 13:30:52 CET 2012 //opt: trdPbPbQ1 par[0]= 2.193660e-01; par[1]= 2.051864e+00; par[2]= 6.825112e+00; par[3]= 6.151693e-02; par[4]= 1.390343e+01; par[5]= 6.010032e-05; par[6]= -1.676324e+00; par[7]= 1.838873e+00; //hhtype4Q1b2c2 scale 0.457988 at ltbg 0.650000 return 0.457988*MeandEdxTR(&bg, par); } Double_t AliTRDdEdxBaseUtils::QMeanTPC(Double_t bg) { // //bethe bloch in TPC // Double_t par[5]; //Mi 15. Feb 14:48:05 CET 2012 //train_2012-02-13_1214.12001, tpcsig par[0]= 4.401269; par[1]= 9.725370; par[2]= 0.000178; par[3]= 1.904962; par[4]= 1.426576; return MeandEdx(&bg, par); } Double_t AliTRDdEdxBaseUtils::MeandEdxTR(const Double_t * xx, const Double_t * pin) { // //ALEPH+LOGISTIC parametrization for dEdx+TR, in unit of MIP //npar = 8 = 3+5 // Double_t ptr[4]={0}; for(int ii=0; ii<3; ii++){ ptr[ii+1]=pin[ii]; } return MeanTR(xx,ptr) + MeandEdx(xx,&(pin[3])); } Double_t AliTRDdEdxBaseUtils::MeanTR(const Double_t * xx, const Double_t * par) { // //ALEPH+LOGISTIC parametrization for dEdx+TR, in unit of MIP //npar = 4 // const Double_t bg = xx[0]; const Double_t gamma = sqrt(1+bg*bg); const Double_t p0 = TMath::Abs(par[1]); const Double_t p1 = TMath::Abs(par[2]); const Double_t p2 = TMath::Abs(par[3]); const Double_t zz = TMath::Log(gamma); const Double_t tryield = p0/( 1 + TMath::Exp(-p1*(zz-p2)) ); return par[0]+tryield; } Double_t AliTRDdEdxBaseUtils::MeandEdx(const Double_t * xx, const Double_t * par) { return ALEPH(xx, par); } Double_t AliTRDdEdxBaseUtils::ALEPH(const Double_t * xx, const Double_t * par) { // //ALEPH parametrization for dEdx //npar = 5 // const Double_t bg = xx[0]; const Double_t beta = bg/TMath::Sqrt(1.+ bg*bg); const Double_t p0 = TMath::Abs(par[0]); const Double_t p1 = TMath::Abs(par[1]); //after redefining p2 (<0) -> ln P2 //const Double_t p2 = par[2]; //restore back const Double_t p2 = TMath::Abs(par[2]); const Double_t p3 = TMath::Abs(par[3]); const Double_t p4 = TMath::Abs(par[4]); const Double_t aa = TMath::Power(beta, p3); //numerically very bad when p2~1e-15, bg~1e3, p4~5. const Double_t bb = TMath::Log( p2 + TMath::Power(1./bg, p4) ); //+1 to avoid the singularity when bg<1 and p4>>1 //very^inf important! with this hesse NOTPOS->OK and no nan or inf in migrad //i.e. numerically very stable //the reason is when bg<1 ln blows up very fast with p4>>1 and nan/inf appears in migrad search //the fitting will adjust the parameters as if bg is not shifted, the fitted curve looks fine!! //-- 2012 Aug 8 //----> fail for 10h, not used, restore back! //const Double_t lbg = TMath::Log(bg); //redefine p2(<0) -> ln P2 //corresponds to alephFit.C fAlephOPt = 11 //const Double_t bb = p2 + TMath::Log( 1 + TMath::Exp(-p2-p4*lbg) ); //printf("test----- %f %f -- %f %f %f %f %f --- %f %f %f\n", bg, beta, p0, p1, p2, p3, p4, p0/aa, aa, bb); return (p1-aa-bb)*p0/aa; } Double_t AliTRDdEdxBaseUtils::ToLogx(FFunc func, const Double_t * xx, const Double_t * par) { // //f(x)-> f(y) with y=log10(x) // const Double_t x2[]={TMath::Power(10, xx[0])}; return func(x2, par); }