Bug fix with indexRange array fixed using AliITSTable class, Update of
[u/mrichter/AliRoot.git] / ITS / AliITSsimulationSSD.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 /* $Id$ */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <iostream.h>
20 #include <iomanip.h>
21 #include <TObjArray.h>
22 #include <TParticle.h>
23 #include <TRandom.h>
24 #include <TMath.h>
25 #include <TH1.h>
26
27 #include "AliITSmodule.h"
28 #include "AliITSMapA2.h"
29 #include "AliITSpList.h"
30 #include "AliITSresponseSSD.h"
31 #include "AliITSsegmentationSSD.h"
32 #include "AliITSdcsSSD.h"
33 #include "AliITS.h"
34 #include "AliRun.h"
35 #include "AliITSgeom.h"
36 #include "AliITSsimulationSSD.h"
37 #include "AliITSTableSSD.h"
38
39 ClassImp(AliITSsimulationSSD);
40 ////////////////////////////////////////////////////////////////////////
41 // Version: 0
42 // Written by Enrico Fragiacomo
43 // July 2000
44 //
45 // AliITSsimulationSSD is the simulation of SSDs.
46
47 //----------------------------------------------------------------------
48 AliITSsimulationSSD::AliITSsimulationSSD(){
49   //default Constructor
50
51   fDCS     = 0;
52   fDifConst[0] = fDifConst[1] = 0.0;
53   fDriftVel[0] = fDriftVel[1] = 0.0;
54   fMapA2   = 0;
55 }
56 //----------------------------------------------------------------------
57 AliITSsimulationSSD::AliITSsimulationSSD(AliITSsegmentation *seg,
58                                          AliITSresponse *resp){
59   // Constructor
60
61   fDCS     = 0;
62   fDifConst[0] = fDifConst[1] = 0.0;
63   fDriftVel[0] = fDriftVel[1] = 0.0;
64   fMapA2   = 0;
65   Init((AliITSsegmentationSSD*)seg,(AliITSresponseSSD*)resp);
66 }
67 //----------------------------------------------------------------------
68 void AliITSsimulationSSD::Init(AliITSsegmentationSSD *seg,
69                                AliITSresponseSSD *resp){
70   // Constructor
71
72   fSegmentation    = seg;
73   fResponse        = resp;
74   Float_t noise[2] = {0.,0.};
75   fResponse->GetNoiseParam(noise[0],noise[1]); // retrieves noise parameters
76   fDCS             = new AliITSdcsSSD(seg,resp); 
77
78   SetDriftVelocity(); // use default values in .h file
79   SetIonizeE();       // use default values in .h file
80   SetDiffConst();     // use default values in .h file
81   fMapA2           = new AliITSMapA2(fSegmentation);
82
83 }
84 //______________________________________________________________________
85 AliITSsimulationSSD& AliITSsimulationSSD::operator=(
86                                                     const AliITSsimulationSSD &s){
87   // Operator =
88
89   if(this==&s) return *this;
90
91   this->fDCS         = new AliITSdcsSSD(*(s.fDCS));
92   this->fMapA2       = s.fMapA2;
93   this->fIonE        = s.fIonE;
94   this->fDifConst[0] = s.fDifConst[0];
95   this->fDifConst[1] = s.fDifConst[1];
96   this->fDriftVel[0] = s.fDriftVel[0];
97   this->fDriftVel[1] = s.fDriftVel[1];
98   return *this;
99 }
100 //______________________________________________________________________
101 AliITSsimulationSSD::AliITSsimulationSSD(const AliITSsimulationSSD &source){
102   // copy constructor
103
104   *this = source;
105 }
106 //______________________________________________________________________
107 AliITSsimulationSSD::~AliITSsimulationSSD() {
108   // destructor
109   delete fMapA2;
110   delete fDCS;
111 }
112 //______________________________________________________________________
113 void AliITSsimulationSSD::DigitiseModule(AliITSmodule *mod,
114                                          Int_t dummy0,Int_t dummy1) {
115   // Digitizes hits for one SSD module
116   Int_t module     = mod->GetIndex();
117   AliITSpList *pList = new AliITSpList(2,GetNStrips());
118
119   HitsToAnalogDigits(mod,pList);
120   SDigitToDigit(module,pList);
121
122   delete pList;
123   fMapA2->ClearMap();
124 }
125 //______________________________________________________________________
126 void AliITSsimulationSSD::SDigitiseModule(AliITSmodule *mod,Int_t dummy0,
127                                           Int_t dummy1) {
128   // Produces Summable/Analog digits and writes them to the SDigit tree.
129   AliITSpList *pList = new AliITSpList(2,GetNStrips()); 
130
131   HitsToAnalogDigits(mod,pList);
132
133   WriteSDigits(pList);
134
135   delete pList;
136   fMapA2->ClearMap();
137 }
138 //______________________________________________________________________
139 void AliITSsimulationSSD::SDigitToDigit(Int_t module,AliITSpList *pList){
140   // Takes the pList and finishes the digitization.
141                                
142   //    FillMapFrompList(pList);  //commented out to avoid double counting of the
143                                 //charge
144
145   ApplyNoise(pList,module);
146   ApplyCoupling(pList,module);
147
148   ChargeToSignal(pList);
149 }
150 //______________________________________________________________________
151 void AliITSsimulationSSD::HitsToAnalogDigits(AliITSmodule *mod,
152                                              AliITSpList *pList){
153   // Loops over all hits to produce Analog/floating point digits. This
154   // is also the first task in producing standard digits.
155   Int_t lasttrack     = -2;
156   Int_t idtrack       = -2;
157   Double_t x0=0.0, y0=0.0, z0=0.0;
158   Double_t x1=0.0, y1=0.0, z1=0.0;
159   Double_t de=0.0;
160   Int_t module = mod->GetIndex();
161
162   TObjArray *hits = mod->GetHits();
163   Int_t nhits     = hits->GetEntriesFast();
164   if (nhits<=0) return;
165   AliITSTableSSD * tav = new AliITSTableSSD(GetNStrips());
166   module = mod->GetIndex();
167   if ( mod->GetLayer() == 6 ) GetSegmentation()->SetLayer(6);
168   if ( mod->GetLayer() == 5 ) GetSegmentation()->SetLayer(5);
169   for(Int_t i=0; i<nhits; i++) {    
170         // LineSegmentL returns 0 if the hit is entering
171         // If hits is exiting returns positions of entering and exiting hits
172         // Returns also energy loss
173
174         if (mod->LineSegmentL(i, x0, x1, y0, y1, z0, z1, de, idtrack)) {
175       HitToDigit(module, x0, y0, z0, x1, y1, z1, de,tav);
176
177       if (lasttrack != idtrack || i==(nhits-1)) {
178           GetList(idtrack,i,module,pList,tav);
179       } // end if
180       lasttrack=idtrack;
181         } // end if
182   }  // end loop over hits
183   delete tav; tav=0;
184   return;
185 }
186 //----------------------------------------------------------------------
187 void AliITSsimulationSSD::HitToDigit(Int_t module, Double_t x0, Double_t y0, 
188                                      Double_t z0, Double_t x1, Double_t y1, 
189                                      Double_t z1, Double_t de,
190                                      AliITSTableSSD *tav) {
191   // Turns hits in SSD module into one or more digits.
192
193   Float_t tang[2] = {0.0,0.0};
194   GetSegmentation()->Angles(tang[0], tang[1]);//stereo<<->tan(stereo)~=stereo
195   Double_t x, y, z;
196   Double_t dex=0.0, dey=0.0, dez=0.0; 
197   Double_t pairs; // pair generation energy per step.
198   Double_t sigma[2] = {0.,0.};// standard deviation of the diffusion gaussian
199   Double_t tdrift[2] = {0.,0.}; // time of drift
200   Double_t w;
201   Double_t inf[2], sup[2], par0[2];                 
202
203   // Steps in the module are determined "manually" (i.e. No Geant)
204   // NumOfSteps divide path between entering and exiting hits in steps 
205   Int_t numOfSteps = NumOfSteps(x1, y1, z1, dex, dey, dez);
206   // Enery loss is equally distributed among steps
207   de    = de/numOfSteps;
208   pairs = de/GetIonizeE(); // e-h pairs generated
209   for(Int_t j=0; j<numOfSteps; j++) {     // stepping
210         x = x0 + (j+0.5)*dex;
211         y = y0 + (j+0.5)*dey;
212         if ( y > (GetSegmentation()->Dy()/2+10)*1.0E-4 ) {
213       // check if particle is within the detector
214       Warning("HitToDigit","hit out of detector y0=%e,y=%e,dey=%e,j =%e",
215               y0,y,dey,j);
216       return;
217         } // end if
218         z = z0 + (j+0.5)*dez;
219
220         // calculate drift time
221         // y is the minimum path
222         tdrift[0] = (y+(GetSegmentation()->Dy()*1.0E-4)/2)/GetDriftVelocity(0);
223         tdrift[1] = ((GetSegmentation()->Dy()*1.0E-4)/2-y)/GetDriftVelocity(1);
224
225         for(Int_t k=0; k<2; k++) {   // both sides    remember: 0=Pside 1=Nside
226
227       tang[k]=TMath::Tan(tang[k]);
228
229       // w is the coord. perpendicular to the strips
230       if(k==0) {
231                 w = (x+(GetSegmentation()->Dx()*1.0E-4)/2) -
232           (z+(GetSegmentation()->Dz()*1.0E-4)/2)*tang[k]; 
233       }else{
234                 w = (x+(GetSegmentation()->Dx()*1.0E-4)/2) + 
235           (z-(GetSegmentation()->Dz()*1.0E-4)/2)*tang[k];
236       } // end if
237       w /= (GetStripPitch()*1.0E-4); // w is converted in units of pitch
238
239       if((w<(-0.5)) || (w>(GetNStrips()-0.5))) {
240                 // this check rejects hits in regions not covered by strips
241                 // 0.5 takes into account boundaries 
242                 return; // There are dead region on the SSD sensitive volume.
243                 /*
244           if(k==0) Warning("HitToDigit",
245           "no strip in this region of P side");
246           else Warning"HitToDigit","no strip in this region of N side");
247           return;
248                 */
249       } // end if
250
251       // sigma is the standard deviation of the diffusion gaussian
252       if(tdrift[k]<0) return;
253       sigma[k] = TMath::Sqrt(2*GetDiffConst(k)*tdrift[k]);
254       sigma[k] /= (GetStripPitch()*1.0E-4);  //units of Pitch
255       if(sigma[k]==0.0) {       
256                 Error("HitToDigit"," sigma[%d]=0",k);
257                 exit(0);
258       } // end if
259
260       par0[k] = pairs;
261       // we integrate the diffusion gaussian from -3sigma to 3sigma 
262       inf[k] = w - 3*sigma[k]; // 3 sigma from the gaussian average  
263       sup[k] = w + 3*sigma[k]; // 3 sigma from the gaussian average
264       // IntegrateGaussian does the actual
265       // integration of diffusion gaussian
266       IntegrateGaussian(k, par0[k], w, sigma[k], inf[k], sup[k],tav);
267         }  // end for loop over side (0=Pside, 1=Nside)      
268   } // end stepping
269   //delete seg;
270 }
271 //______________________________________________________________________
272 void AliITSsimulationSSD::ApplyNoise(AliITSpList *pList,Int_t module){
273   // Apply Noise.
274   Int_t    k,ix;
275   Double_t signal,noise;
276   Double_t noiseP[2] = {0.,0.};
277   Float_t a,b;
278
279   fResponse->GetNoiseParam(a,b); // retrieves noise parameters
280   noiseP[0] = (Double_t) a; noiseP[1] = (Double_t) b;
281   for(k=0;k<2;k++){                    // both sides (0=Pside, 1=Nside)
282         for(ix=0;ix<GetNStrips();ix++){      // loop over strips
283       noise  = gRandom->Gaus(0,noiseP[k]);// get noise to signal
284       signal = noise + fMapA2->GetSignal(k,ix);//get signal from map
285       if(signal<0.) signal=0.0;           // in case noise is negative...
286       fMapA2->SetHit(k,ix,signal); // give back signal to map
287       if(signal>0.0) pList->AddNoise(k,ix,module,noise);
288         } // loop over strip 
289   } // loop over k (P or N side)
290 }
291 //______________________________________________________________________
292 void AliITSsimulationSSD::ApplyCoupling(AliITSpList *pList,Int_t module) {
293   // Apply the effect of electronic coupling between channels
294   Int_t ix;
295   Double_t signalLeft=0, signalRight=0,signal=0;
296
297   for(ix=0;ix<GetNStrips();ix++){
298         // P side coupling
299         if(ix>0.)signalLeft = fMapA2->GetSignal(0,ix-1)*fDCS->GetCouplingPL();
300         else signalLeft = 0.0;
301         if(ix<(GetNStrips()-1)) signalRight = fMapA2->GetSignal(0,ix+1)*
302                               fDCS->GetCouplingPR();
303         else signalRight = 0.0;
304         signal = signalLeft + signalRight;
305         fMapA2->AddSignal(0,ix,signal);
306         if(signal>0.0) pList->AddNoise(0,ix,module,signal);
307
308         signalLeft = signalRight = signal = 0.0;
309         // N side coupling
310         if(ix>0.) signalLeft = fMapA2->GetSignal(1,ix-1)*fDCS->GetCouplingNL();
311         else signalLeft = 0.0;
312         if(ix<(GetNStrips()-1)) signalRight = fMapA2->GetSignal(1,ix+1)*
313                               fDCS->GetCouplingNR();
314         else signalRight = 0.0;
315         signal = signalLeft + signalRight;
316         fMapA2->AddSignal(1,ix,signal);
317         if(signal>0.0) pList->AddNoise(1,ix,module,signal);
318   } // loop over strips 
319 }
320 //______________________________________________________________________
321 Float_t AliITSsimulationSSD::F(Float_t av, Float_t x, Float_t s) {
322   // Computes the integral of a gaussian using Error Function
323   Float_t sqrt2 = TMath::Sqrt(2.0);
324   Float_t sigm2 = sqrt2*s;
325   Float_t integral;
326
327   integral = 0.5 * TMath::Erf( (x - av) / sigm2);
328   return integral;
329 }
330 //______________________________________________________________________
331 void AliITSsimulationSSD::IntegrateGaussian(Int_t k,Double_t par, Double_t w,
332                                             Double_t sigma, 
333                                             Double_t inf, Double_t sup,
334                                             AliITSTableSSD *tav) {
335   // integrate the diffusion gaussian
336   // remind: inf and sup are w-3sigma and w+3sigma
337   //         we could define them here instead of passing them
338   //         this way we are free to introduce asimmetry
339
340   Double_t a=0.0, b=0.0;
341   Double_t dXCharge1 = 0.0, dXCharge2 = 0.0;
342   // dXCharge1 and 2 are the charge to two neighbouring strips
343   // Watch that we only involve at least two strips
344   // Numbers greater than 2 of strips in a cluster depend on
345   //  geometry of the track and delta rays, not charge diffusion!   
346   
347   Double_t strip = TMath::Floor(w);         // closest strip on the left
348
349   if ( TMath::Abs((strip - w)) < 0.5) { 
350         // gaussian mean is closer to strip on the left
351         a = inf;                         // integration starting point
352         if((strip+0.5)<=sup) {
353       // this means that the tail of the gaussian goes beyond
354       // the middle point between strips ---> part of the signal
355       // is given to the strip on the right
356       b = strip + 0.5;               // integration stopping point
357       dXCharge1 = F( w, b, sigma) - F(w, a, sigma);
358       dXCharge2 = F( w, sup, sigma) - F(w ,b, sigma); 
359         }else { 
360       // this means that all the charge is given to the strip on the left
361       b = sup;
362       dXCharge1 = 0.9973;   // gaussian integral at 3 sigmas
363       dXCharge2 = 0.0;
364         } // end if
365         dXCharge1 = par * dXCharge1;// normalize by mean of number of carriers
366         dXCharge2 = par * dXCharge2;
367
368         // for the time being, signal is the charge
369         // in ChargeToSignal signal is converted in ADC channel
370         fMapA2->AddSignal(k,(Int_t)strip,dXCharge1);
371     tav->Add(k,(Int_t)strip);
372         if(((Int_t) strip) < (GetNStrips()-1)) {
373       // strip doesn't have to be the last (remind: last=GetNStrips()-1)
374       // otherwise part of the charge is lost
375       fMapA2->AddSignal(k,((Int_t)strip+1),dXCharge2);
376       tav->Add(k,((Int_t)(strip+1)));
377         } // end if
378     
379
380   }else{
381         // gaussian mean is closer to strip on the right
382         strip++;     // move to strip on the rigth
383         b = sup;     // now you know where to stop integrating
384         if((strip-0.5)>=inf) { 
385       // tail of diffusion gaussian on the left goes left of
386       // middle point between strips
387       a = strip - 0.5;        // integration starting point
388       dXCharge1 = F(w, b, sigma) - F(w, a, sigma);
389       dXCharge2 = F(w, a, sigma) - F(w, inf, sigma);
390         }else {
391       a = inf;
392       dXCharge1 = 0.9973;   // gaussian integral at 3 sigmas
393       dXCharge2 = 0.0;
394         } // end if
395         dXCharge1 = par * dXCharge1;    // normalize by means of carriers
396         dXCharge2 = par * dXCharge2;
397
398         // for the time being, signal is the charge
399         // in ChargeToSignal signal is converted in ADC channel
400         fMapA2->AddSignal(k,(Int_t)strip,dXCharge1);
401     tav->Add(k,(Int_t)strip);
402         if(((Int_t) strip) > 0) {
403       // strip doesn't have to be the first
404       // otherwise part of the charge is lost
405       fMapA2->AddSignal(k,((Int_t)strip-1),dXCharge2);
406       tav->Add(k,((Int_t)(strip-1)));
407         } // end if
408     
409
410   } // end if
411 }
412 //______________________________________________________________________
413 Int_t AliITSsimulationSSD::NumOfSteps(Double_t x, Double_t y, Double_t z,
414                                       Double_t & dex,Double_t & dey,Double_t & dez){
415   // number of steps
416   // it also returns steps for each coord
417   //AliITSsegmentationSSD *seg = new AliITSsegmentationSSD();
418
419   Double_t step = 25E-4;
420   //step = (Double_t) seg->GetStepSize();  // step size (cm)
421   Int_t numOfSteps = (Int_t) (TMath::Sqrt(x*x+y*y+z*z)/step); 
422
423   if (numOfSteps < 1) numOfSteps = 1;       // one step, at least
424
425     // we could condition the stepping depending on the incident angle
426     // of the track
427   dex = x/numOfSteps;
428   dey = y/numOfSteps;
429   dez = z/numOfSteps;
430
431   return numOfSteps;
432 }
433 //----------------------------------------------------------------------
434 void AliITSsimulationSSD::GetList(Int_t label,Int_t hit,Int_t mod,
435                                   AliITSpList *pList,AliITSTableSSD *tav) {
436   // loop over nonzero digits
437   Int_t ix,i;
438   Double_t signal=0.;
439
440   for(Int_t k=0; k<2; k++) {
441     ix=tav->Use(k);
442     while(ix>-1){
443       signal = fMapA2->GetSignal(k,ix);
444       if(signal==0.0) {
445         ix=tav->Use(k);
446         continue;
447       }
448       // check the signal magnitude
449       for(i=0;i<pList->GetNSignals(k,ix);i++){
450         signal -= pList->GetTSignal(k,ix,i);
451       } 
452       //  compare the new signal with already existing list
453       if(signal>0)pList->AddSignal(k,ix,label,hit,mod,signal);
454       ix=tav->Use(k);
455         } // end of loop on strips
456   } // end of loop on P/N side
457   tav->Clear();
458 }
459 //----------------------------------------------------------------------
460 void AliITSsimulationSSD::ChargeToSignal(AliITSpList *pList) {
461   // charge to signal
462   static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
463   Float_t threshold = 0.;
464   Int_t   digits[3], tracks[3],hits[3],j1;
465   Float_t charges[3] = {0.0,0.0,0.0};
466   Float_t signal;
467   Float_t noise[2] = {0.,0.};
468
469   ((AliITSresponseSSD*)fResponse)->GetNoiseParam(noise[0],noise[1]);
470
471   for(Int_t k=0;k<2;k++){         // both sides (0=Pside, 1=Nside)
472         // Threshold for zero-suppression
473         // It can be defined in AliITSresponseSSD
474         //             threshold = (Float_t)fResponse->MinVal(k);
475         // I prefer to think adjusting the threshold "manually", looking
476         // at the scope, and considering noise standard deviation
477         threshold = 4.0*noise[k]; // 4 times noise is a choice
478         for(Int_t ix=0;ix<GetNStrips();ix++){     // loop over strips
479       if(fMapA2->GetSignal(k,ix) <= threshold)continue;
480       // convert to ADC signal
481       signal = ((AliITSresponseSSD*)fResponse)->DEvToADC(
482                                                       fMapA2->GetSignal(k,ix));
483       if(signal>1024.) signal = 1024.;//if exceeding, accumulate last one
484       digits[0] = k;
485       digits[1] = ix;
486       digits[2] = (Int_t) signal;
487       for(j1=0;j1<3;j1++){ // only three in digit.
488                 tracks[j1]  = pList->GetTrack(k,ix,j1);
489                 hits[j1]    = pList->GetHit(k,ix,j1);
490       } // end for j1
491       // finally add digit
492       aliITS->AddSimDigit(2,0,digits,tracks,hits,charges);
493         } // end for ix
494   } // end for k
495 }
496 //______________________________________________________________________
497 void AliITSsimulationSSD::WriteSDigits(AliITSpList *pList){
498   // Fills the Summable digits Tree
499   Int_t i,ni,j,nj;
500   static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
501
502   pList->GetMaxMapIndex(ni,nj);
503   for(i=0;i<ni;i++)for(j=0;j<nj;j++){
504         if(pList->GetSignalOnly(i,j)>0.0){
505       aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
506       //            cout << "pListSSD: " << *(pList->GetpListItem(i,j)) << endl;
507         } // end if
508   } // end for i,j
509   return;
510 }
511 //______________________________________________________________________
512 void AliITSsimulationSSD::FillMapFrompList(AliITSpList *pList){
513   // Fills fMap2A from the pList of Summable digits
514   Int_t k,ix;
515
516   for(k=0;k<2;k++)for(ix=0;ix<GetNStrips();ix++) 
517         fMapA2->AddSignal(k,ix,pList->GetSignal(k,ix));
518   return;
519 }
520 //______________________________________________________________________
521 void AliITSsimulationSSD::Print(ostream *os){
522   //Standard output format for this class
523
524   //AliITSsimulation::Print(os);
525   *os << fIonE <<",";
526   *os << fDifConst[0] <<","<< fDifConst[1] <<",";
527   *os << fDriftVel[0] <<","<< fDriftVel[1];
528   //*os <<","; fDCS->Print(os);
529   //*os <<","; fMapA2->Print(os);
530 }
531 //______________________________________________________________________
532 void AliITSsimulationSSD::Read(istream *is){
533   // Standard output streaming function.
534
535   //AliITSsimulation::Read(is);
536   *is >> fIonE;
537   *is >> fDifConst[0] >> fDifConst[1];
538   *is >> fDriftVel[0] >> fDriftVel[1];
539   //fDCS->Read(is);
540   //fMapA2->Read(is);
541 }
542 //______________________________________________________________________
543 ostream &operator<<(ostream &os,AliITSsimulationSSD &source){
544   // Standard output streaming function.
545
546   source.Print(&os);
547   return os;
548 }
549 //______________________________________________________________________
550 istream &operator>>(istream &os,AliITSsimulationSSD &source){
551   // Standard output streaming function.
552
553   source.Read(&os);
554   return os;
555 }
556 //______________________________________________________________________
557
558
559
560
561