2 gSystem->Load("libSTAT.so");
5 .L $ALICE_ROOT/TPC/fastSimul/AliTPCclusterFast.cxx+
7 AliTPCclusterFast::fPRF = new TF1("fprf","gausn",-5,5);
8 AliTPCclusterFast::fTRF = new TF1("ftrf","gausn",-5,5);
9 AliTPCclusterFast::fPRF->SetParameters(1,0,0.5);
10 AliTPCclusterFast::fTRF->SetParameters(1,0,0.5);
13 AliTPCtrackFast::Simul("trackerSimul.root",100);
14 // AliTPCclusterFast::Simul("cluterSimul.root",20000);
24 #include "THnSparse.h"
25 #include "TClonesArray.h"
26 #include "TTreeStream.h"
28 class AliTPCclusterFast: public TObject {
31 virtual ~AliTPCclusterFast();
32 void SetParam(Float_t mnprim, Float_t diff, Float_t y, Float_t z, Float_t ky, Float_t kz);
33 void GenerElectrons();
35 Double_t GetQtot(Float_t gain,Float_t thr, Float_t noise, Bool_t rounding=kTRUE, Bool_t addPedestal=kTRUE);
36 Double_t GetQmax(Float_t gain,Float_t thr, Float_t noise, Bool_t rounding=kTRUE, Bool_t addPedestal=kTRUE);
37 Double_t GetQmaxCorr(Float_t rmsy0, Float_t rmsz0);
38 Double_t GetQtotCorr(Float_t rmsy0, Float_t rmsz0, Float_t gain, Float_t thr);
41 static void Simul(const char* simul, Int_t npoints);
42 static Double_t GaussConvolution(Double_t x0, Double_t x1, Double_t k0, Double_t k1, Double_t s0, Double_t s1);
43 static Double_t GaussExpConvolution(Double_t x0, Double_t s0,Double_t t1);
44 static Double_t GaussGamma4(Double_t x, Double_t s0, Double_t p1);
45 static Double_t Gamma4(Double_t x, Double_t p0, Double_t p1);
47 Float_t fMNprim; // mean number of primary electrons
48 // //electrons part input
49 Int_t fNprim; // mean number of primary electrons
50 Int_t fNtot; // total number of electrons
51 Float_t fQtot; // total charge - Gas gain flucuation taken into account
53 Float_t fDiff; // diffusion sigma
54 Float_t fY; // y position
55 Float_t fZ; // z postion
56 Float_t fAngleY; // y angle - tan(y)
57 Float_t fAngleZ; // z angle - tan z
60 // // electron part simul
61 TVectorD fSec; //! number of secondary electrons
62 TVectorD fPosY; //! position y for each electron
63 TVectorD fPosZ; //! position z for each electron
64 TVectorD fGain; //! gg for each electron
66 TVectorD fStatY; //!stat Y
67 TVectorD fStatZ; //!stat Y
71 TMatrixD fDigits; // response matrix
72 static TF1* fPRF; // Pad response
73 static TF1* fTRF; // Time response function
74 ClassDef(AliTPCclusterFast,1) // container for
78 class AliTPCtrackFast: public TObject {
81 void Add(AliTPCtrackFast &track2);
83 void UpdatedEdxHisto();
85 static void Simul(const char* simul, Int_t ntracks);
86 Double_t CookdEdxNtot(Double_t f0,Float_t f1);
87 Double_t CookdEdxQtot(Double_t f0,Float_t f1);
89 Double_t CookdEdxDtot(Double_t f0,Float_t f1, Float_t gain,Float_t thr, Float_t noise, Bool_t corr = kTRUE);
90 Double_t CookdEdxDmax(Double_t f0,Float_t f1,Float_t gain,Float_t thr, Float_t noise, Bool_t corr=kTRUE);
92 Double_t CookdEdx(Int_t npoints, Double_t *amp, Double_t f0,Float_t f1);
94 Float_t fMNprim; // mean number of primary electrons
95 Float_t fAngleY; // y angle - tan(y)
96 Float_t fAngleZ; // z angle - tan z
97 Float_t fDiff; // diffusion
98 Int_t fN; // number of clusters
99 TClonesArray *fCl; // array of clusters
101 Bool_t fInit; // initialization flag
102 THnSparse *fHistoNtot; // histograms of trunc mean Ntot
103 THnSparse *fHistoQtot; // histograms of trunc mean Qtot
104 THnSparse *fHistoQNtot; // histograms of trunc mean Qtot/Ntot
106 THnSparse *fHistoDtot; // histograms of trunc mean digit tot
107 THnSparse *fHistoDmax; // histograms of trunc mean digit max
108 THnSparse *fHistoDtotRaw; // histograms of trunc mean digit tot
109 THnSparse *fHistoDmaxRaw; // histograms of trunc mean digit max
113 ClassDef(AliTPCtrackFast,2) // container for
118 ClassImp(AliTPCclusterFast)
119 ClassImp(AliTPCtrackFast)
125 TF1 *AliTPCclusterFast::fPRF=0;
126 TF1 *AliTPCclusterFast::fTRF=0;
129 AliTPCtrackFast::AliTPCtrackFast():
150 void AliTPCtrackFast::Add(AliTPCtrackFast &track2){
151 if (!track2.fInit) return;
153 fHistoNtot->Add(track2.fHistoNtot); // histograms of trunc mean Ntot
154 fHistoQtot->Add(track2.fHistoQtot); // histograms of trunc mean Qtot
155 fHistoQNtot->Add(track2.fHistoQNtot); // histograms of trunc mean Qtot/Ntot
157 fHistoDtot->Add(track2.fHistoDtot); // histograms of trunc mean digit tot
158 fHistoDmax->Add(track2.fHistoDmax); // histograms of trunc mean digit max
159 fHistoDtotRaw->Add(track2.fHistoDtotRaw); // histograms of trunc mean digit tot
160 fHistoDmaxRaw->Add(track2.fHistoDmaxRaw); // histograms of trunc mean digit max
163 void AliTPCtrackFast::MakeHisto(){
165 // make default histo
167 // dEdx histogram THnSparse
169 // 1 - fMNprim - number of generated primaries
176 Double_t xmin[7], xmax[7];
180 nbins[1] = 10; xmin[1]=10; xmax[1]=30; // fMNprim
181 nbins[2] = 8; xmin[2]=80; xmax[2]=160; // fNPoints
182 nbins[3] = 6; xmin[3]=0.45; xmax[3]=1.05; // trunc mean fraction
184 nbins[4] = 5; xmin[4]=0.0; xmax[4]=0.4; // fDiff
185 nbins[5] = 10; xmin[5]=0; xmax[5]=2; // fAngleY
186 nbins[6] = 10; xmin[6]=0; xmax[6]=2; // fAngleZ
188 nbins[0] =100; xmin[0]=2; xmax[0]=8;
189 fHistoNtot = new THnSparseF("dNdxall/dNdxprim","dNdxall/dNdxprim", 4, nbins, xmin,xmax);
190 nbins[0] =100; xmin[0]=2; xmax[0]=8;
191 fHistoQtot = new THnSparseF("dQdx/dNdxprim","dQdxall/dNdxprim", 4, nbins, xmin,xmax);
192 nbins[0] =100; xmin[0]=0.5; xmax[0]=1.5;
193 fHistoQNtot = new THnSparseF("dQdx/dNdxprim","dQdxprim/dNdxprim", 4, nbins, xmin,xmax);
195 nbins[0] =100; xmin[0]=0.05; xmax[0]=8;
196 fHistoDtot = new THnSparseF("dQtotdx/dNdxprim","dQtotdx/dNdx", 7, nbins, xmin,xmax);
197 fHistoDmax = new THnSparseF("dQmaxdx/dNdxprim","dQmaxdx/dNdx", 7, nbins, xmin,xmax);
198 fHistoDtotRaw = new THnSparseF("raw dQtotdx/dNdxprim","raw dQtotdx/dNdx", 7, nbins, xmin,xmax);
199 fHistoDmaxRaw = new THnSparseF("raw dQmaxdx/dNdxprim","raw dQmaxdx/dNdx", 7, nbins, xmin,xmax);
203 void AliTPCtrackFast::UpdatedEdxHisto(){
207 if (!fInit) MakeHisto();
213 x[5] = TMath::Abs(fAngleY);
214 x[6] = TMath::Abs(fAngleZ);
216 for (Int_t i=0;i<7;i++){
217 Float_t frac = 0.5+Float_t(i)*0.1;
219 Double_t cNtot = CookdEdxNtot(0.01,frac);
220 Double_t cQtot = CookdEdxQtot(0.01,frac);
222 x[0] = cNtot/fMNprim;
224 x[0] = cQtot/fMNprim;
227 fHistoQNtot->Fill(x);
229 Double_t dQtot = CookdEdxDtot(0.01,frac,1,2.5,1,kTRUE);
230 Double_t dQmax = CookdEdxDmax(0.01,frac,1,2.5,1,kTRUE);
231 Double_t dQrawtot = CookdEdxDtot(0.01,frac,1,2.5,1,kFALSE);
232 Double_t dQrawmax = CookdEdxDmax(0.01,frac,1,2.5,1,kFALSE);
233 x[0] = dQtot/fMNprim;
235 x[0] = dQmax/fMNprim;
237 x[0] = dQrawtot/fMNprim;
238 fHistoDtotRaw->Fill(x);
239 x[0] = dQrawmax/fMNprim;
240 fHistoDmaxRaw->Fill(x);
244 void AliTPCtrackFast::MakeTrack(){
248 if (!fCl) fCl = new TClonesArray("AliTPCclusterFast",160);
249 for (Int_t i=0;i<fN;i++){
250 Double_t tY = i*fAngleY;
251 Double_t tZ = i*fAngleZ;
252 AliTPCclusterFast * cluster = (AliTPCclusterFast*) fCl->UncheckedAt(i);
253 if (!cluster) cluster = new ((*fCl)[i]) AliTPCclusterFast;
255 Double_t posY = tY-TMath::Nint(tY);
256 Double_t posZ = tZ-TMath::Nint(tZ);
257 cluster->SetParam(fMNprim,fDiff,posY,posZ,fAngleY,fAngleZ);
259 cluster->GenerElectrons();
265 Double_t AliTPCtrackFast::CookdEdxNtot(Double_t f0,Float_t f1){
268 for (Int_t i=0;i<fN;i++){
269 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
270 amp[i]=cluster->fNtot;
272 return CookdEdx(fN,amp,f0,f1);
275 Double_t AliTPCtrackFast::CookdEdxQtot(Double_t f0,Float_t f1){
278 for (Int_t i=0;i<fN;i++){
279 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
280 amp[i]=cluster->fQtot;
282 return CookdEdx(fN,amp,f0,f1);
285 Double_t AliTPCtrackFast::CookdEdxDtot(Double_t f0,Float_t f1, Float_t gain,Float_t thr, Float_t noise, Bool_t doCorr){
291 for (Int_t i=0;i<fN;i++){
292 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
293 Float_t camp = cluster->GetQtot(gain,thr,noise);
294 if (camp==0) continue;
296 if (doCorr) corr = cluster->GetQtotCorr(0.5,0.5,gain,thr);
300 return CookdEdx(over,amp,f0,f1);
304 Double_t AliTPCtrackFast::CookdEdxDmax(Double_t f0,Float_t f1, Float_t gain,Float_t thr, Float_t noise, Bool_t doCorr){
310 for (Int_t i=0;i<fN;i++){
311 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
312 Float_t camp = cluster->GetQmax(gain,thr,noise);
313 if (camp==0) continue;
315 if (doCorr) corr = cluster->GetQmaxCorr(0.5,0.5);
319 return CookdEdx(over,amp,f0,f1);
324 Double_t AliTPCtrackFast::CookdEdx(Int_t npoints, Double_t *amp,Double_t f0,Float_t f1){
329 TMath::Sort(npoints,amp,index,kFALSE);
330 Float_t sum0=0, sum1=0,sum2=0;
331 for (Int_t i=0;i<npoints;i++){
332 if (i<npoints*f0) continue;
333 if (i>npoints*f1) continue;
335 sum1+= amp[index[i]];
336 sum2+= amp[index[i]];
338 if (sum0<=0) return 0;
342 void AliTPCtrackFast::Simul(const char* fname, Int_t ntracks){
346 AliTPCtrackFast fast;
347 TTreeSRedirector cstream(fname);
348 for (Int_t itr=0; itr<ntracks; itr++){
350 fast.fMNprim=(5+50*gRandom->Rndm());
351 fast.fDiff =0.01 +0.35*gRandom->Rndm();
353 fast.fAngleY = 4.0*(gRandom->Rndm()-0.5);
354 fast.fAngleZ = 4.0*(gRandom->Rndm()-0.5);
355 fast.fN = TMath::Nint(80.+gRandom->Rndm()*80.);
357 if (itr%100==0) printf("%d\n",itr);
358 cstream<<"simulTrack"<<
367 AliTPCclusterFast::AliTPCclusterFast(){
370 fDigits.ResizeTo(5,7);
373 AliTPCclusterFast::~AliTPCclusterFast(){
377 void AliTPCclusterFast::SetParam(Float_t mnprim, Float_t diff, Float_t y, Float_t z, Float_t ky, Float_t kz){
380 fMNprim = mnprim; fDiff = diff;
382 fAngleY=ky; fAngleZ=kz;
384 Double_t AliTPCclusterFast::GetNsec(){
386 // Generate number of secondary electrons
387 // copy of procedure implemented in geant
389 const Double_t FPOT=20.77E-9, EEND=10E-6, EEXPO=2.2, EEND1=1E-6;
390 const Double_t XEXPO=-EEXPO+1, YEXPO=1/XEXPO;
391 const Double_t W=20.77E-9;
392 Float_t RAN = gRandom->Rndm();
393 //Double_t edep = TMath::Power((TMath::Power(FPOT,XEXPO)*(1-RAN)+TMath::Power(EEND,XEXPO)*RAN),YEXPO);
394 //edep = TMath::Min(edep, EEND);
395 //return TMath::Nint(edep/W);
396 return TMath::Nint(TMath::Power((TMath::Power(FPOT,XEXPO)*(1-RAN)+TMath::Power(EEND,XEXPO)*RAN),YEXPO)/W);
399 void AliTPCclusterFast::GenerElectrons(){
404 const Int_t knMax=1000;
405 if (fPosY.GetNrows()<knMax){
406 fPosY.ResizeTo(knMax);
407 fPosZ.ResizeTo(knMax);
408 fGain.ResizeTo(knMax);
409 fSec.ResizeTo(knMax);
413 fNprim = gRandom->Poisson(fMNprim); //number of primary electrons
414 fNtot=0; //total number of electrons
415 fQtot=0; //total number of electrons after gain multiplification
422 for (Int_t i=0;i<knMax;i++){
425 for (Int_t iprim=0; iprim<fNprim;iprim++){
426 Float_t dN = GetNsec();
428 Double_t yc = fY+(gRandom->Rndm()-0.5)*fAngleY;
429 Double_t zc = fZ+(gRandom->Rndm()-0.5)*fAngleZ;
430 for (Int_t isec=0;isec<=dN;isec++){
433 Double_t y = gRandom->Gaus(0,fDiff)+yc;
434 Double_t z = gRandom->Gaus(0,fDiff)+zc;
435 Double_t gg = -TMath::Log(gRandom->Rndm());
446 if (fNtot>=knMax) break;
448 if (fNtot>=knMax) break;
452 fStatY[1]=sumYQ/sumQ;
453 fStatY[2]=sumY2Q/sumQ-fStatY[1]*fStatY[1];
455 fStatZ[1]=sumZQ/sumQ;
456 fStatZ[2]=sumZ2Q/sumQ-fStatZ[1]*fStatZ[1];
460 void AliTPCclusterFast::Digitize(){
465 for (Int_t i=0; i<5;i++)
466 for (Int_t j=0; j<7;j++){
471 for (Int_t iel = 0; iel<fNtot; iel++){
472 for (Int_t di=-2; di<=2;di++)
473 for (Int_t dj=-3; dj<=3;dj++){
474 Float_t fac = fPRF->Eval(di-fPosY[iel])*fTRF->Eval(dj-fPosZ[iel]);
476 fDigits(2+di,3+dj)+=fac;
484 void AliTPCclusterFast::Simul(const char* fname, Int_t npoints){
488 AliTPCclusterFast fast;
489 TTreeSRedirector cstream(fname);
490 for (Int_t icl=0; icl<npoints; icl++){
491 Float_t nprim=(10+20*gRandom->Rndm());
492 Float_t diff =0.01 +0.35*gRandom->Rndm();
493 Float_t posY = gRandom->Rndm()-0.5;
494 Float_t posZ = gRandom->Rndm()-0.5;
496 Float_t ky = 4.0*(gRandom->Rndm()-0.5);
497 Float_t kz = 4.0*(gRandom->Rndm()-0.5);
498 fast.SetParam(nprim,diff,posY,posZ,ky,kz);
499 fast.GenerElectrons();
501 if (icl%10000==0) printf("%d\n",icl);
509 Double_t AliTPCclusterFast::GetQtot(Float_t gain, Float_t thr, Float_t noise, Bool_t brounding, Bool_t baddPedestal){
514 for (Int_t ip=0;ip<5;ip++){
515 Float_t pedestal=gRandom->Rndm()-0.5; //pedestal offset different for each pad
516 for (Int_t it=0;it<7;it++){
517 Float_t amp = gain*fDigits(ip,it)+gRandom->Gaus()*noise;
518 if (baddPedestal) amp+=pedestal;
519 if (brounding) amp=TMath::Nint(amp);
520 if (amp>thr) sum+=amp;
526 Double_t AliTPCclusterFast::GetQmax(Float_t gain, Float_t thr, Float_t noise, Bool_t brounding, Bool_t baddPedestal){
531 for (Int_t ip=0;ip<5;ip++){
532 Float_t pedestal=gRandom->Rndm()-0.5; //pedestal offset different for each pad
533 for (Int_t it=0;it<7;it++){
534 Float_t amp = gain*fDigits(ip,it)+gRandom->Gaus()*noise;
535 if (baddPedestal) amp+=pedestal;
536 if (brounding) amp=TMath::Nint(amp);
537 if (amp>max && amp>thr) max=amp;
545 Double_t AliTPCclusterFast::GetQmaxCorr(Float_t rmsy0, Float_t rmsz0){
547 // Gaus distribution convolueted with rectangular
548 // Gaus width sy and sz is determined by RF width and diffusion
549 // Integral of Q is equal 1
550 // Q max is calculated at position fY,fX
554 Double_t sy = TMath::Sqrt(rmsy0*rmsy0+fDiff*fDiff);
555 Double_t sz = TMath::Sqrt(rmsz0*rmsz0+fDiff*fDiff);
556 return GaussConvolution(fY,fZ, fAngleY,fAngleZ,sy,sz);
560 Double_t AliTPCclusterFast::GetQtotCorr(Float_t rmsy0, Float_t rmsz0, Float_t gain, Float_t thr){
562 // Calculates the fraction of the charge over threshol to total charge
563 // The response function
565 Double_t sy = TMath::Sqrt(rmsy0*rmsy0+fDiff*fDiff);
566 Double_t sz = TMath::Sqrt(rmsz0*rmsz0+fDiff*fDiff);
567 Double_t sumAll=0,sumThr=0;
568 Double_t qtot = GetQtot(gain,thr,0); // sum of signal over threshold
572 for (Int_t iter=0;iter<2;iter++){
573 for (Int_t iy=-2;iy<=2;iy++)
574 for (Int_t iz=-2;iz<=2;iz++){
575 Double_t val = GaussConvolution(fY-iy,fZ-iz, fAngleY,fAngleZ,sy,sz);
576 Double_t qlocal =TMath::Nint(qnorm*val);
577 if (qlocal>thr) sumThr+=qlocal;
580 if (sumAll>0&&sumThr>0) corr=(sumThr)/sumAll;
582 if (corr>0) qnorm=qtot/corr;
592 Double_t AliTPCclusterFast::GaussConvolution(Double_t x0, Double_t x1, Double_t k0, Double_t k1, Double_t s0, Double_t s1){
594 // 2 D gaus convoluted with angular effect
595 // See in mathematica:
596 //Simplify[Integrate[Exp[-(x0-k0*xd)*(x0-k0*xd)/(2*s0*s0)-(x1-k1*xd)*(x1-k1*xd)/(2*s1*s1)]/(s0*s1),{xd,-1/2,1/2}]]
598 //TF1 f1("f1","AliTPCclusterFast::GaussConvolution(x,0,1,0,0.1,0.1)",-2,2)
599 //TF2 f2("f2","AliTPCclusterFast::GaussConvolution(x,y,1,1,0.1,0.1)",-2,2,-2,2)
601 const Float_t kEpsilon = 0.0001;
602 if ((TMath::Abs(k0)+TMath::Abs(k1))<kEpsilon*(s0+s1)){
603 // small angular effect
604 Double_t val = (TMath::Gaus(x0,0,s0)*TMath::Gaus(x1,0,s1))/(s0*s1*2.*TMath::Pi());
608 Double_t sigma2 = k1*k1*s0*s0+k0*k0*s1*s1;
609 Double_t exp0 = TMath::Exp(-(k1*x0-k0*x1)*(k1*x0-k0*x1)/(2*sigma2));
611 Double_t sigmaErf = 2*s0*s1*TMath::Sqrt(2*sigma2);
612 Double_t erf0 = TMath::Erf( (k0*s1*s1*(k0-2*x0)+k1*s0*s0*(k1-2*x1))/sigmaErf);
613 Double_t erf1 = TMath::Erf( (k0*s1*s1*(k0+2*x0)+k1*s0*s0*(k1+2*x1))/sigmaErf);
614 Double_t norm = 1./TMath::Sqrt(sigma2);
615 norm/=2.*TMath::Sqrt(2.*TMath::Pi());
616 Double_t val = norm*exp0*(erf0+erf1);
622 Double_t AliTPCclusterFast::GaussExpConvolution(Double_t x0, Double_t s0,Double_t t1){
624 // 2 D gaus convoluted with exponential
625 // Integral nomalized to 1
626 // See in mathematica:
627 //Simplify[Integrate[Exp[-(x0-x1)*(x0-x1)/(2*s0*s0)]*Exp[-x1*t1],{x1,0,Infinity}]]
628 // TF1 fgexp("fgexp","AliTPCclusterFast::GaussExpConvolution(x,0.5,1)",-2,2)
629 Double_t exp1 = (s0*s0*t1-2*x0)*t1/2.;
630 exp1 = TMath::Exp(exp1);
631 Double_t erf = 1+TMath::Erf((-s0*s0*t1+x0)/(s0*TMath::Sqrt(2.)));
632 Double_t val = exp1*erf;
639 Double_t AliTPCclusterFast::Gamma4(Double_t x, Double_t p0, Double_t p1){
641 // Gamma 4 Time response function of ALTRO
644 Double_t g1 = TMath::Exp(-4.*x/p1);
645 Double_t g2 = TMath::Power(x/p1,4);
651 Double_t AliTPCclusterFast::GaussGamma4(Double_t x, Double_t s0, Double_t p1){
653 // Gamma 4 Time response function of ALTRO convoluted with Gauss
654 // Simplify[Integrate[Exp[-(x0-x1)*(x0-x1)/(2*s0*s0)]*Exp[-4*x1/p1]*(x/p1)^4/s0,{x1,0,Infinity}]]
655 //TF1 fgg4("fgg4","AliTPCclusterFast::GaussGamma4(x,0.5,0.5)",-2,2)
657 Double_t exp1 = (8*s0*s0-4.*p1*x)/(p1*p1);
658 exp1 = TMath::Exp(exp1);
659 Double_t erf1 = 1+TMath::Erf((-4*s0/p1+x/s0)/TMath::Sqrt(2));
660 // Double_t xp14 = TMath::Power(TMath::Abs((x/p1)),4);
666 // Analytical sollution only in 1D - too long expression
667 // Simplify[Integrate[Exp[-(x0-(x1-k*x2))*(x0-(x1-k*x2))/(2*s0*s0)]*Exp[-(x1*t1-k*x2)],{x2,-1,1}]]
670 // No analytical solution
672 //Simplify[Integrate[Exp[-(x0-k0*xd)*(x0-k0*xd)/(2*s0*s0)-(x1-xt-k1*xd)*(x1-xt-k1*xd)/(2*s1*s1)]*Exp[-kt*xt]/(s0*s1),{xd,-1/2,1/2},{xt,0,Infinity}]]