6 gSystem->Load("libSTAT.so");
9 .L $ALICE_ROOT/TPC/fastSimul/AliTPCclusterFast.cxx+
11 AliTPCclusterFast::fPRF = new TF1("fprf","gausn",-5,5);
12 AliTPCclusterFast::fTRF = new TF1("ftrf","gausn",-5,5);
13 AliTPCclusterFast::fPRF->SetParameters(1,0,0.5);
14 AliTPCclusterFast::fTRF->SetParameters(1,0,0.5);
17 AliTPCtrackFast::Simul("trackerSimul.root",100);
18 // AliTPCclusterFast::Simul("cluterSimul.root",20000);
26 1.) modigy mode ==> dEdxMode
27 2.) Create hardware setup class
28 (fNoise, fGain, fBRounding, fBAddpedestal, ....)
29 3.) Create arrays of registered hardware setups
30 4.) Extend on the fly functions to use registered hardware setups, identified by ID.
44 #include "TClonesArray.h"
45 #include "TTreeStream.h"
47 class AliTPCclusterFast: public TObject {
52 virtual ~AliTPCclusterFast();
53 void SetParam(Float_t mnprim, Float_t diff, Float_t diffL, Float_t y, Float_t z, Float_t ky, Float_t kz);
54 static void GenerElectrons(AliTPCclusterFast *cl0, AliTPCclusterFast *clm, AliTPCclusterFast *clp);
56 Double_t GetQtot(Float_t gain,Float_t thr, Float_t noise, Bool_t rounding=kTRUE, Bool_t addPedestal=kTRUE);
57 Double_t GetQmax(Float_t gain,Float_t thr, Float_t noise, Bool_t rounding=kTRUE, Bool_t addPedestal=kTRUE);
58 Double_t GetQmaxCorr(Float_t rmsy0, Float_t rmsz0);
59 Double_t GetQtotCorr(Float_t rmsy0, Float_t rmsz0, Float_t gain, Float_t thr);
62 //static void Simul(const char* simul, Int_t npoints);
63 static Double_t GaussConvolution(Double_t x0, Double_t x1, Double_t k0, Double_t k1, Double_t s0, Double_t s1);
64 static Double_t GaussExpConvolution(Double_t x0, Double_t s0,Double_t t1);
65 static Double_t GaussGamma4(Double_t x, Double_t s0, Double_t p1);
66 static Double_t Gamma4(Double_t x, Double_t p0, Double_t p1);
68 Float_t fMNprim; // mean number of primary electrons
69 // //electrons part input
70 Int_t fNprim; // mean number of primary electrons
71 Int_t fNtot; // total number of electrons
72 Float_t fQtot; // total charge - Gas gain flucuation taken into account
74 Float_t fDiff; // diffusion sigma
75 Float_t fDiffLong; // diffusion sigma longitudinal direction
76 Float_t fY; // y position
77 Float_t fZ; // z postion
78 Float_t fAngleY; // y angle - tan(y)
79 Float_t fAngleZ; // z angle - tan z
82 // // electron part simul
83 TVectorD fSec; //! number of secondary electrons
84 TVectorD fPosY; //! position y for each electron
85 TVectorD fPosZ; //! position z for each electron
86 TVectorD fGain; //! gg for each electron
88 TVectorD fStatY; //!stat Y
89 TVectorD fStatZ; //!stat Y
93 TMatrixD fDigits; // response matrix
94 static TF1* fPRF; // Pad response
95 static TF1* fTRF; // Time response function
96 ClassDef(AliTPCclusterFast,1) // container for
100 class AliTPCtrackFast: public TObject {
103 void Add(AliTPCtrackFast &track2);
105 static void Simul(const char* simul, Int_t ntracks);
106 Double_t CookdEdxNtot(Double_t f0,Float_t f1);
107 Double_t CookdEdxQtot(Double_t f0,Float_t f1);
108 Double_t CookdEdxNtotThr(Double_t f0,Float_t f1, Double_t thr, Int_t dEdxMode);
109 Double_t CookdEdxQtotThr(Double_t f0,Float_t f1, Double_t thr, Int_t dEdxMode);
111 Double_t CookdEdxDtot(Double_t f0,Float_t f1, Float_t gain,Float_t thr, Float_t noise, Bool_t corr, Int_t dEdxMode);
112 Double_t CookdEdxDmax(Double_t f0,Float_t f1,Float_t gain,Float_t thr, Float_t noise, Bool_t corr, Int_t dEdxMode);
114 Double_t CookdEdx(Int_t npoints, Double_t *amp, Double_t f0,Float_t f1, Int_t dEdxMode);
116 Float_t fMNprim; // mean number of primary electrons
117 Float_t fAngleY; // y angle - tan(y)
118 Float_t fAngleZ; // z angle - tan z
119 Float_t fDiff; // diffusion
120 Float_t fDiffLong; // diffusion sigma longitudinal direction
121 Int_t fN; // number of clusters
122 TClonesArray *fCl; // array of clusters
124 Bool_t fInit; // initialization flag
127 ClassDef(AliTPCtrackFast,2) // container for
132 ClassImp(AliTPCclusterFast)
133 ClassImp(AliTPCtrackFast)
139 TF1 *AliTPCclusterFast::fPRF=0;
140 TF1 *AliTPCclusterFast::fTRF=0;
143 AliTPCtrackFast::AliTPCtrackFast():
157 void AliTPCtrackFast::Add(AliTPCtrackFast &track2){
158 if (!track2.fInit) return;
164 void AliTPCtrackFast::MakeTrack(){
168 if (!fCl) fCl = new TClonesArray("AliTPCclusterFast",160);
169 for (Int_t i=0;i<fN;i++){
170 AliTPCclusterFast * cluster = (AliTPCclusterFast*) fCl->UncheckedAt(i);
171 if (!cluster) cluster = new ((*fCl)[i]) AliTPCclusterFast;
175 for (Int_t i=0;i<fN;i++){
176 Double_t tY = i*fAngleY;
177 Double_t tZ = i*fAngleZ;
178 AliTPCclusterFast * cluster = (AliTPCclusterFast*) fCl->UncheckedAt(i);
179 AliTPCclusterFast * clusterm = (AliTPCclusterFast*) fCl->UncheckedAt(TMath::Max(i-1,0));
180 AliTPCclusterFast * clusterp = (AliTPCclusterFast*) fCl->UncheckedAt(TMath::Min(i+1,159));
181 if (!cluster) cluster = new ((*fCl)[i]) AliTPCclusterFast;
183 Double_t posY = tY-TMath::Nint(tY);
184 Double_t posZ = tZ-TMath::Nint(tZ);
185 cluster->SetParam(fMNprim,fDiff, fDiffLong, posY,posZ,fAngleY,fAngleZ);
187 cluster->GenerElectrons(cluster, clusterm, clusterp);
192 Double_t AliTPCtrackFast::CookdEdxNtot(Double_t f0,Float_t f1){
194 // Double_t CookdEdxNtot(Double_t f0,Float_t f1); // dEdx_{hit} reconstructed meen number of electrons
197 for (Int_t i=0;i<fN;i++){
198 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
199 amp[i]=cluster->fNtot;
201 return CookdEdx(fN,amp,f0,f1,0);
204 Double_t AliTPCtrackFast::CookdEdxQtot(Double_t f0,Float_t f1){
206 // dEdx_{Q} reconstructed mean number of electronsxGain
209 for (Int_t i=0;i<fN;i++){
210 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
211 amp[i]=cluster->fQtot;
213 return CookdEdx(fN,amp,f0,f1,0);
217 Double_t AliTPCtrackFast::CookdEdxNtotThr(Double_t f0,Float_t f1, Double_t thr, Int_t dEdxMode){
219 // dEdx_{hit} reconstructed mean number of electrons
220 // thr = threshold in terms of the number of electrons
221 // dEdxMode = algorithm to deal with trhesold values replacing
226 Double_t minAbove=-1;
227 for (Int_t i=0;i<fN;i++){
228 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
229 Double_t clQ= cluster->fNtot;
234 if (minAbove<0) minAbove=clQ;
235 if (minAbove>clQ) minAbove=clQ;
238 if (dEdxMode==-1) return Double_t(nBellow)/Double_t(fN);
240 for (Int_t i=0;i<fN;i++){
241 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
242 Double_t clQ= cluster->fNtot;
244 if (dEdxMode==0) amp[i]=clQ; // dEdxMode0 - not threshold - keep default
247 if (dEdxMode==1 && clQ>thr) amp[i]=clQ; // dEdxMode1 - skip if bellow
248 if (dEdxMode==1 && clQ<thr) amp[i]=0; // dEdxMode1 - skip if bellow
251 if (dEdxMode==2 && clQ>thr) amp[i]=clQ; // dEdxMode2 - use 0 if below
252 if (dEdxMode==2 && clQ<thr) amp[i]=0; // dEdxMode2 - use 0 if below
255 if (dEdxMode==3) amp[i]=(clQ>thr)?clQ:thr; // dEdxMode3 - use thr if below
256 if (dEdxMode==4) amp[i]=(clQ>thr)?clQ:minAbove; // dEdxMode4 - use minimal above threshold if bellow thr
258 return CookdEdx(fN,amp,f0,f1, dEdxMode);
263 Double_t AliTPCtrackFast::CookdEdxQtotThr(Double_t f0,Float_t f1, Double_t thr, Int_t dEdxMode){
266 // dEdx_{Q} reconstructed mean number of electrons xgain
267 // thr = threshold in terms of the number of electrons
268 // dEdxMode = algorithm to deal with trhesold values replacing
275 Double_t minAbove=-1;
276 for (Int_t i=0;i<fN;i++){
277 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
278 Double_t clQ= cluster->fQtot;
283 if (minAbove<0) minAbove=clQ;
284 if (minAbove>clQ) minAbove=clQ;
287 if (dEdxMode==-1) return Double_t(nBellow)/Double_t(fN);
289 for (Int_t i=0;i<fN;i++){
290 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
291 Double_t clQ= cluster->fQtot;
293 if (dEdxMode==0) amp[i]=clQ; // dEdxMode0 - not threshold - keep default
296 if (dEdxMode==1 && clQ>thr) amp[i]=clQ; // dEdxMode1 - skip if bellow
297 if (dEdxMode==1 && clQ<thr) amp[i]=0; // dEdxMode1 - skip if bellow
300 if (dEdxMode==2 && clQ>thr) amp[i]=clQ; // dEdxMode2 - use 0 if below
301 if (dEdxMode==2 && clQ<thr) amp[i]=0; // dEdxMode2 - use 0 if below
304 if (dEdxMode==3) amp[i]=(clQ>thr)?clQ:thr; // dEdxMode3 - use thr if below
305 if (dEdxMode==4) amp[i]=(clQ>thr)?clQ:minAbove; // dEdxMode4 - use minimal above threshold if bellow thr
307 return CookdEdx(fN,amp,f0,f1, dEdxMode);
314 Double_t AliTPCtrackFast::CookdEdxDtot(Double_t f0,Float_t f1, Float_t gain,Float_t thr, Float_t noise, Bool_t doCorr, Int_t dEdxMode){
316 // total charge in the cluster (sum of the pad x time matrix ), hits were digitized before, but additional
317 // actions can be specified by switches // dEdx_{Qtot}
322 for (Int_t i=0;i<fN;i++){
323 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
325 if (dEdxMode==0) camp = cluster->GetQtot(gain,0,noise);
327 camp = cluster->GetQtot(gain,thr,noise);
329 if (doCorr) corr = cluster->GetQtotCorr(0.5,0.5,gain,thr);
333 if (minAmp <0) minAmp=camp;
334 if (minAmp >camp) minAmp=camp;
337 if (dEdxMode==3) for (Int_t i=0;i<fN;i++) if (amp[i]<=0) amp[i]=thr;
338 if (dEdxMode==4) for (Int_t i=0;i<fN;i++) if (amp[i]<=0) amp[i]=minAmp;
339 return CookdEdx(fN,amp,f0,f1, dEdxMode);
344 Double_t AliTPCtrackFast::CookdEdxDmax(Double_t f0,Float_t f1, Float_t gain,Float_t thr, Float_t noise, Bool_t doCorr, Int_t dEdxMode){
346 // maximal charge in the cluster (maximal amplitude in the digit matrix), hits were digitized before,
347 // but additional actions can be specified by switches
352 for (Int_t i=0;i<fN;i++){
353 AliTPCclusterFast * cluster = ( AliTPCclusterFast *)((*fCl)[i]);
355 if (dEdxMode==0) camp = cluster->GetQmax(gain,0,noise);
357 camp = cluster->GetQmax(gain,thr,noise);
359 if (doCorr) corr = cluster->GetQmaxCorr(0.5,0.5);
363 if (minAmp <0) minAmp=camp;
364 if (minAmp >camp) minAmp=camp;
367 if (dEdxMode==3) for (Int_t i=0;i<fN;i++) if (amp[i]<=0) amp[i]=thr;
368 if (dEdxMode==4) for (Int_t i=0;i<fN;i++) if (amp[i]<=0) amp[i]=minAmp;
369 return CookdEdx(fN,amp,f0,f1, dEdxMode);
373 Double_t AliTPCtrackFast::CookdEdx(Int_t npoints, Double_t *amp,Double_t f0,Float_t f1, Int_t dEdxMode){
375 // Calculate truncated mean
376 // npoints - number of points in array
377 // amp - array with points
378 // f0-f1 - truncation range
379 // dEdxMode - specify handling of the 0 clusters, actual handling - filling of amplitude defiend in algorithm above
380 // dEdxMode = 0 - accept everything
381 // dEdxMode = 1 - do not count 0 amplitudes
382 // dEdxMode = 2 - use 0 amplitude as it is
383 // dEdxMode = 3 - use amplitude as it is (in above function amp. replace by the thr)
384 // dEdxMode = 4 - use amplitude as it is (in above function amp. replace by the minimal amplitude)
388 // 0. sorted the array of amplitudes
391 TMath::Sort(npoints,amp,index,kFALSE);
393 // 1.) Calculate truncated mean from the selected range of the array (ranking statistic )
394 // dependening on the dEdxMode 0 amplitude can be skipped
395 Float_t sum0=0, sum1=0,sum2=0;
398 for (Int_t i=0;i<npoints;i++) if (amp[index[i]]>0) above++;
400 for (Int_t i=0;i<npoints;i++){
402 if (dEdxMode==1 && amp[index[i]]==0) {
405 if (accepted<npoints*f0) continue;
406 if (accepted>npoints*f1) continue;
408 sum1+= amp[index[i]];
409 sum2+= amp[index[i]];
412 if (dEdxMode==-1) return 1-Double_t(above)/Double_t(npoints);
413 if (sum0<=0) return 0;
417 void AliTPCtrackFast::Simul(const char* fname, Int_t ntracks){
421 AliTPCtrackFast fast;
422 TTreeSRedirector *pcstream = new TTreeSRedirector(fname,"recreate");
423 for (Int_t itr=0; itr<ntracks; itr++){
425 fast.fMNprim=(10.+100*gRandom->Rndm());
426 if (gRandom->Rndm()>0.5) fast.fMNprim=1./(0.00001+gRandom->Rndm()*0.1);
428 fast.fDiff =0.01 +0.35*gRandom->Rndm();
429 fast.fDiffLong = fast.fDiff*0.6/1.;
431 fast.fAngleY = 4.0*(gRandom->Rndm()-0.5);
432 fast.fAngleZ = 4.0*(gRandom->Rndm()-0.5);
435 if (itr%100==0) printf("%d\n",itr);
436 (*pcstream)<<"simulTrack"<<
446 AliTPCclusterFast::AliTPCclusterFast(){
449 fDigits.ResizeTo(5,7);
452 void AliTPCclusterFast::Init(){
454 // reset all counters
456 const Int_t knMax=1000;
457 fMNprim=0; // mean number of primary electrons
458 // //electrons part input
459 fNprim=0; // mean number of primary electrons
460 fNtot=0; // total number of electrons
461 fQtot=0; // total charge - Gas gain flucuation taken into account
463 fPosY.ResizeTo(knMax);
464 fPosZ.ResizeTo(knMax);
465 fGain.ResizeTo(knMax);
466 fSec.ResizeTo(knMax);
469 for (Int_t i=0; i<knMax; i++){
478 AliTPCclusterFast::~AliTPCclusterFast(){
482 void AliTPCclusterFast::SetParam(Float_t mnprim, Float_t diff, Float_t diffL,Float_t y, Float_t z, Float_t ky, Float_t kz){
485 fMNprim = mnprim; fDiff = diff; fDiffLong=diffL;
487 fAngleY=ky; fAngleZ=kz;
489 Double_t AliTPCclusterFast::GetNsec(){
491 // Generate number of secondary electrons
492 // copy of procedure implemented in geant
494 const Double_t FPOT=20.77E-9, EEND=10E-6, EEXPO=2.2, EEND1=1E-6;
495 const Double_t XEXPO=-EEXPO+1, YEXPO=1/XEXPO;
496 const Double_t W=20.77E-9;
497 Float_t RAN = gRandom->Rndm();
498 //Double_t edep = TMath::Power((TMath::Power(FPOT,XEXPO)*(1-RAN)+TMath::Power(EEND,XEXPO)*RAN),YEXPO);
499 //edep = TMath::Min(edep, EEND);
500 //return TMath::Nint(edep/W);
501 return TMath::Nint(TMath::Power((TMath::Power(FPOT,XEXPO)*(1-RAN)+TMath::Power(EEND,XEXPO)*RAN),YEXPO)/W);
504 void AliTPCclusterFast::GenerElectrons(AliTPCclusterFast *cl0, AliTPCclusterFast *clm, AliTPCclusterFast *clp){
509 const Int_t knMax=1000;
510 cl0->fNprim = gRandom->Poisson(cl0->fMNprim); //number of primary electrons
511 cl0->fNtot=0; //total number of electrons
512 cl0->fQtot=0; //total number of electrons after gain multiplification
519 for (Int_t i=0;i<knMax;i++){
522 for (Int_t iprim=0; iprim<cl0->fNprim;iprim++){
523 Float_t dN = cl0->GetNsec();
525 Double_t yc = cl0->fY+(gRandom->Rndm()-0.5)*cl0->fAngleY;
526 Double_t zc = cl0->fZ+(gRandom->Rndm()-0.5)*cl0->fAngleZ;
527 Double_t rc = (gRandom->Rndm()-0.5);
529 for (Int_t isec=0;isec<=dN;isec++){
532 Double_t y = gRandom->Gaus(0,cl0->fDiff)+yc;
533 Double_t z = gRandom->Gaus(0,cl0->fDiff)+zc;
534 Double_t r = gRandom->Gaus(0,cl0->fDiffLong)+rc;
536 AliTPCclusterFast *cl=cl0;
537 if (r<-0.5 &&cl) cl=clm;
538 if (r>0.5 &&cl) cl=clp;
540 Double_t gg = -TMath::Log(gRandom->Rndm());
541 cl->fPosY[cl->fNtot]=y;
542 cl->fPosZ[cl->fNtot]=z;
543 cl->fGain[cl->fNtot]=gg;
549 // cl->sumY2Q+=gg*y*y;
551 // cl->sumZ2Q+=gg*z*z;
552 if (cl->fNtot>=knMax) continue;
554 if (cl0->fNtot>=knMax) break;
559 // fStatY[1]=sumYQ/sumQ;
560 // fStatY[2]=sumY2Q/sumQ-fStatY[1]*fStatY[1];
562 // fStatZ[1]=sumZQ/sumQ;
563 // fStatZ[2]=sumZ2Q/sumQ-fStatZ[1]*fStatZ[1];
567 void AliTPCclusterFast::Digitize(){
572 for (Int_t i=0; i<5;i++)
573 for (Int_t j=0; j<7;j++){
578 for (Int_t iel = 0; iel<fNtot; iel++){
579 for (Int_t di=-2; di<=2;di++)
580 for (Int_t dj=-3; dj<=3;dj++){
581 Float_t fac = fPRF->Eval(di-fPosY[iel])*fTRF->Eval(dj-fPosZ[iel]);
583 fDigits(2+di,3+dj)+=fac;
593 // void AliTPCclusterFast::Simul(const char* fname, Int_t npoints){
597 // AliTPCclusterFast fast;
598 // TTreeSRedirector cstream(fname);
599 // for (Int_t icl=0; icl<npoints; icl++){
600 // Float_t nprim=(10+20*gRandom->Rndm());
601 // Float_t diff =0.01 +0.35*gRandom->Rndm();
602 // Float_t posY = gRandom->Rndm()-0.5;
603 // Float_t posZ = gRandom->Rndm()-0.5;
605 // Float_t ky = 4.0*(gRandom->Rndm()-0.5);
606 // Float_t kz = 4.0*(gRandom->Rndm()-0.5);
607 // fast.SetParam(nprim,diff,posY,posZ,ky,kz);
608 // fast.GenerElectrons();
610 // if (icl%10000==0) printf("%d\n",icl);
611 // cstream<<"simul"<<
618 Double_t AliTPCclusterFast::GetQtot(Float_t gain, Float_t thr, Float_t noise, Bool_t brounding, Bool_t baddPedestal){
623 for (Int_t ip=0;ip<5;ip++){
624 Float_t pedestal=gRandom->Rndm()-0.5; //pedestal offset different for each pad
625 for (Int_t it=0;it<7;it++){
626 Float_t amp = gain*fDigits(ip,it)+gRandom->Gaus()*noise;
627 if (baddPedestal) amp+=pedestal;
628 if (brounding) amp=TMath::Nint(amp);
629 if (amp>thr) sum+=amp;
635 Double_t AliTPCclusterFast::GetQmax(Float_t gain, Float_t thr, Float_t noise, Bool_t brounding, Bool_t baddPedestal){
640 for (Int_t ip=0;ip<5;ip++){
641 Float_t pedestal=gRandom->Rndm()-0.5; //pedestal offset different for each pad
642 for (Int_t it=0;it<7;it++){
643 Float_t amp = gain*fDigits(ip,it)+gRandom->Gaus()*noise;
644 if (baddPedestal) amp+=pedestal;
645 if (brounding) amp=TMath::Nint(amp);
646 if (amp>max && amp>thr) max=amp;
654 Double_t AliTPCclusterFast::GetQmaxCorr(Float_t rmsy0, Float_t rmsz0){
656 // Gaus distribution convolueted with rectangular
657 // Gaus width sy and sz is determined by RF width and diffusion
658 // Integral of Q is equal 1
659 // Q max is calculated at position fY,fX
663 Double_t sy = TMath::Sqrt(rmsy0*rmsy0+fDiff*fDiff);
664 Double_t sz = TMath::Sqrt(rmsz0*rmsz0+fDiff*fDiff);
665 return GaussConvolution(fY,fZ, fAngleY,fAngleZ,sy,sz);
669 Double_t AliTPCclusterFast::GetQtotCorr(Float_t rmsy0, Float_t rmsz0, Float_t gain, Float_t thr){
671 // Calculates the fraction of the charge over threshol to total charge
672 // The response function
674 Double_t sy = TMath::Sqrt(rmsy0*rmsy0+fDiff*fDiff);
675 Double_t sz = TMath::Sqrt(rmsz0*rmsz0+fDiff*fDiff);
676 Double_t sumAll=0,sumThr=0;
677 Double_t qtot = GetQtot(gain,thr,0); // sum of signal over threshold
681 for (Int_t iter=0;iter<2;iter++){
682 for (Int_t iy=-2;iy<=2;iy++)
683 for (Int_t iz=-2;iz<=2;iz++){
684 Double_t val = GaussConvolution(fY-iy,fZ-iz, fAngleY,fAngleZ,sy,sz);
685 Double_t qlocal =TMath::Nint(qnorm*val);
686 if (qlocal>thr) sumThr+=qlocal;
689 if (sumAll>0&&sumThr>0) corr=(sumThr)/sumAll;
691 if (corr>0) qnorm=qtot/corr;
701 Double_t AliTPCclusterFast::GaussConvolution(Double_t x0, Double_t x1, Double_t k0, Double_t k1, Double_t s0, Double_t s1){
703 // 2 D gaus convoluted with angular effect
704 // See in mathematica:
705 //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}]]
707 //TF1 f1("f1","AliTPCclusterFast::GaussConvolution(x,0,1,0,0.1,0.1)",-2,2)
708 //TF2 f2("f2","AliTPCclusterFast::GaussConvolution(x,y,1,1,0.1,0.1)",-2,2,-2,2)
710 const Float_t kEpsilon = 0.0001;
711 if ((TMath::Abs(k0)+TMath::Abs(k1))<kEpsilon*(s0+s1)){
712 // small angular effect
713 Double_t val = (TMath::Gaus(x0,0,s0)*TMath::Gaus(x1,0,s1))/(s0*s1*2.*TMath::Pi());
717 Double_t sigma2 = k1*k1*s0*s0+k0*k0*s1*s1;
718 Double_t exp0 = TMath::Exp(-(k1*x0-k0*x1)*(k1*x0-k0*x1)/(2*sigma2));
720 Double_t sigmaErf = 2*s0*s1*TMath::Sqrt(2*sigma2);
721 Double_t erf0 = TMath::Erf( (k0*s1*s1*(k0-2*x0)+k1*s0*s0*(k1-2*x1))/sigmaErf);
722 Double_t erf1 = TMath::Erf( (k0*s1*s1*(k0+2*x0)+k1*s0*s0*(k1+2*x1))/sigmaErf);
723 Double_t norm = 1./TMath::Sqrt(sigma2);
724 norm/=2.*TMath::Sqrt(2.*TMath::Pi());
725 Double_t val = norm*exp0*(erf0+erf1);
731 Double_t AliTPCclusterFast::GaussExpConvolution(Double_t x0, Double_t s0,Double_t t1){
733 // 2 D gaus convoluted with exponential
734 // Integral nomalized to 1
735 // See in mathematica:
736 //Simplify[Integrate[Exp[-(x0-x1)*(x0-x1)/(2*s0*s0)]*Exp[-x1*t1],{x1,0,Infinity}]]
737 // TF1 fgexp("fgexp","AliTPCclusterFast::GaussExpConvolution(x,0.5,1)",-2,2)
738 Double_t exp1 = (s0*s0*t1-2*x0)*t1/2.;
739 exp1 = TMath::Exp(exp1);
740 Double_t erf = 1+TMath::Erf((-s0*s0*t1+x0)/(s0*TMath::Sqrt(2.)));
741 Double_t val = exp1*erf;
748 Double_t AliTPCclusterFast::Gamma4(Double_t x, Double_t p0, Double_t p1){
750 // Gamma 4 Time response function of ALTRO
753 Double_t g1 = TMath::Exp(-4.*x/p1);
754 Double_t g2 = TMath::Power(x/p1,4);
760 Double_t AliTPCclusterFast::GaussGamma4(Double_t x, Double_t s0, Double_t p1){
762 // Gamma 4 Time response function of ALTRO convoluted with Gauss
763 // Simplify[Integrate[Exp[-(x0-x1)*(x0-x1)/(2*s0*s0)]*Exp[-4*x1/p1]*(x/p1)^4/s0,{x1,0,Infinity}]]
764 //TF1 fgg4("fgg4","AliTPCclusterFast::GaussGamma4(x,0.5,0.5)",-2,2)
766 Double_t exp1 = (8*s0*s0-4.*p1*x)/(p1*p1);
767 exp1 = TMath::Exp(exp1);
768 Double_t erf1 = 1+TMath::Erf((-4*s0/p1+x/s0)/TMath::Sqrt(2));
769 // Double_t xp14 = TMath::Power(TMath::Abs((x/p1)),4);
775 // Analytical sollution only in 1D - too long expression
776 // Simplify[Integrate[Exp[-(x0-(x1-k*x2))*(x0-(x1-k*x2))/(2*s0*s0)]*Exp[-(x1*t1-k*x2)],{x2,-1,1}]]
779 // No analytical solution
781 //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}]]