8 #include "AliITSmodule.h"
9 #include "AliITSMapA2.h"
10 #include "AliITSsegmentationSSD.h"
11 #include "AliITSresponseSSD.h"
12 #include "AliITSsimulationSSD.h"
13 //#include "AliITSdictSSD.h"
14 #include "AliITSdcsSSD.h"
17 #include "AliITSgeom.h"
19 ClassImp(AliITSsimulationSSD);
20 ////////////////////////////////////////////////////////////////////////
22 // Written by Enrico Fragiacomo
25 // AliITSsimulationSSD is the simulation of SSDs.
27 //----------------------------------------------------------------------
28 AliITSsimulationSSD::AliITSsimulationSSD(AliITSsegmentation *seg,
29 AliITSresponse *resp){
34 Float_t noise[2] = {0.,0.};
35 fResponse->GetNoiseParam(noise[0],noise[1]); // retrieves noise parameters
36 fDCS = new AliITSdcsSSD(seg,resp);
38 fNstrips = fSegmentation->Npx();
39 fPitch = fSegmentation->Dpx(0);
40 fMapA2 = new AliITSMapA2(fSegmentation);
42 fSteps = 100; // still hard-wired - set in SetDetParam and get it via
43 // fDCS together with the others eventually
45 //______________________________________________________________________
46 AliITSsimulationSSD& AliITSsimulationSSD::operator=(AliITSsimulationSSD
50 if(this==&source) return *this;
52 this->fDCS = new AliITSdcsSSD(*(source.fDCS));
53 this->fMapA2 = source.fMapA2;
54 this->fNstrips = source.fNstrips;
55 this->fPitch = source.fPitch;
56 this->fSteps = source.fSteps;
59 //_____________________________________________________________---------
60 AliITSsimulationSSD::AliITSsimulationSSD(AliITSsimulationSSD &source){
65 //______________________________________________________________________
66 AliITSsimulationSSD::~AliITSsimulationSSD() {
71 //_______________________________________________________________-------
72 void AliITSsimulationSSD::DigitiseModule(AliITSmodule *mod,Int_t module,
74 // Digitizes hits for one SSD module
76 Int_t lay, lad, detect;
77 AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
78 AliITSgeom *geom = aliITS->GetITSgeom();
79 geom->GetModuleId(module,lay, lad, detect);
80 if ( lay == 6 )((AliITSsegmentationSSD*)fSegmentation)->SetLayer(6);
81 if ( lay == 5 )((AliITSsegmentationSSD*)fSegmentation)->SetLayer(5);
83 TObjArray *hits = mod->GetHits();
84 Int_t nhits = hits->GetEntriesFast();
86 //cout<<"!! module, nhits ="<<module<<","<<nhits<<endl;
88 Double_t x0=0.0, y0=0.0, z0=0.0;
89 Double_t x1=0.0, y1=0.0, z1=0.0;
91 Int_t maxNdigits = 2*fNstrips;
92 Float_t **pList = new Float_t* [maxNdigits];
93 memset(pList,0,sizeof(Float_t*)*maxNdigits);
94 Int_t indexRange[4] = {0,0,0,0};
95 static Bool_t first=kTRUE;
99 for(Int_t i=0; i<nhits; i++) {
100 // LineSegmentL returns 0 if the hit is entering
101 // If hits is exiting returns positions of entering and exiting hits
102 // Returns also energy loss
104 if (mod->LineSegmentL(i, x0, x1, y0, y1, z0, z1, de, idtrack)) {
105 HitToDigit(module, x0, y0, z0, x1, y1, z1, de, indexRange, first);
107 if (lasttrack != idtrack || i==(nhits-1)) {
108 GetList(idtrack,pList,indexRange);
113 } // end loop over hits
118 ChargeToSignal(pList);
122 //----------------------------------------------------------------------
123 void AliITSsimulationSSD::HitToDigit(Int_t module, Double_t x0, Double_t y0,
124 Double_t z0, Double_t x1, Double_t y1,
125 Double_t z1, Double_t de,
126 Int_t *indexRange, Bool_t first) {
127 // Turns hits in SSD module into one or more digits.
129 Float_t tang[2] = {0.0,0.0};
130 fSegmentation->Angles(tang[0], tang[1]);// stereo<< -> tan(stereo)~=stereo
132 Double_t dex=0.0, dey=0.0, dez=0.0;
134 Double_t ionE = 3.62E-9; // ionization energy of Si (GeV)
136 Double_t sigma[2] = {0.,0.};// standard deviation of the diffusion gaussian
138 Double_t D[2] = {11.,30.}; // diffusion constant {h,e} (cm**2/sec)
139 Double_t tdrift[2] = {0.,0.}; // time of drift
140 Double_t vdrift[2] = {0.86E6,2.28E6}; // drift velocity (cm/sec)
142 Double_t inf[2], sup[2], par0[2];
143 // Steps in the module are determined "manually" (i.e. No Geant)
144 // NumOfSteps divide path between entering and exiting hits in steps
145 Int_t numOfSteps = NumOfSteps(x1, y1, z1, dex, dey, dez);
147 // Enery loss is equally distributed among steps
149 pairs = de/ionE; // e-h pairs generated
151 for(Int_t j=0; j<numOfSteps; j++) { // stepping
152 // cout<<"step number ="<<j<<endl;
153 x = x0 + (j+0.5)*dex;
154 y = y0 + (j+0.5)*dey;
155 //if ( y > (seg->Dy()/2 +10)*1.0E-4 ) {
156 if ( y > (fSegmentation->Dy()/2+10)*1.0E-4 ) {
157 // check if particle is within the detector
158 cout<<"AliITSsimulationSSD::HitToDigit: Warning: hit "
159 "out of detector y0,y,dey,j ="
160 <<y0<<","<<y<<","<<dey<<","<<j<<endl;
163 z = z0 + (j+0.5)*dez;
165 // calculate drift time
166 // y is the minimum path
167 tdrift[0] = (y+(fSegmentation->Dy()*1.0E-4)/2) / vdrift[0];
168 tdrift[1] = ((fSegmentation->Dy()*1.0E-4)/2-y) / vdrift[1];
170 for(Int_t k=0; k<2; k++) { // both sides remember: 0=Pside 1=Nside
172 tang[k]=TMath::Tan(tang[k]);
174 // w is the coord. perpendicular to the strips
176 //w=(x+(seg->Dx()*1.0E-4)/2)-(z+(seg->Dz()*1.0E-4)/2)*tang[k];
177 w = (x+(fSegmentation->Dx()*1.0E-4)/2) -
178 (z+(fSegmentation->Dz()*1.0E-4)/2)*tang[k];
180 //w =(x+(seg->Dx()*1.0E-4)/2)+(z-(seg->Dz()*1.0E-4)/2)*tang[k];
181 w = (x+(fSegmentation->Dx()*1.0E-4)/2) +
182 (z-(fSegmentation->Dz()*1.0E-4)/2)*tang[k];
183 //cout<<"k,x,z,w ="<<k<<","<<x<<","<<z<<","<<w<<endl;
185 w = w / (fPitch*1.0E-4); // w is converted in units of pitch
187 if((w<(-0.5)) || (w>(fNstrips-0.5))) {
188 // this check rejects hits in regions not covered by strips
189 // 0.5 takes into account boundaries
190 if(k==0) cout<<"AliITSsimulationSSD::HitToDigit: "
191 "Warning: no strip in this region of P side"
193 else cout<<"AliITSsimulationSSD::HitToDigit: "
194 "Warning: no strip in this region of N side"<<endl;
198 // sigma is the standard deviation of the diffusion gaussian
200 if(tdrift[k]<0) return;
202 sigma[k] = TMath::Sqrt(2*D[k]*tdrift[k]);
203 sigma[k] = sigma[k] /(fPitch*1.0E-4); //units of Pitch
205 cout<<"AliITSsimulationSSD::DigitiseModule: Error: sigma=0"
211 // we integrate the diffusion gaussian from -3sigma to 3sigma
212 inf[k] = w - 3*sigma[k]; // 3 sigma from the gaussian average
213 sup[k] = w + 3*sigma[k]; // 3 sigma from the gaussian average
214 // IntegrateGaussian does the actual
215 // integration of diffusion gaussian
216 IntegrateGaussian(k, par0[k], w, sigma[k], inf[k], sup[k],
218 } // end for loop over side (0=Pside, 1=Nside)
222 //____________________________________________________________________--
223 void AliITSsimulationSSD::ApplyNoise() {
227 Float_t noise[2] = {0.,0.};
228 fResponse->GetNoiseParam(noise[0],noise[1]); // retrieves noise parameters
230 for(Int_t k=0;k<2;k++){ // both sides (0=Pside, 1=Nside)
231 for(Int_t ix=0;ix<fNstrips;ix++){ // loop over strips
232 signal = (Float_t) fMapA2->GetSignal(k,ix);// retrieves signal
235 signal += gRandom->Gaus(0,noise[k]);// add noise to signal
236 if(signal<0.) signal=0.0; // in case noise is negative...
238 fMapA2->SetHit(k,ix,(Double_t)signal); // give back signal to map
240 } // loop over k (P or N side)
242 //______________________________________________________________________
243 void AliITSsimulationSSD::ApplyCoupling() {
244 // Apply the effect of electronic coupling between channels
245 Float_t signal, signalLeft=0, signalRight=0;
247 for(Int_t ix=0;ix<fNstrips;ix++){
248 if(ix>0.) signalLeft = (Float_t) fMapA2->GetSignal(0,ix-1)*
249 fDCS->GetCouplingPL();
250 else signalLeft = 0.0;
251 if(ix<(fNstrips-1)) signalRight = (Float_t) fMapA2->GetSignal(0,ix+1)*
252 fDCS->GetCouplingPR();
253 else signalRight = 0.0;
254 signal = (Float_t) fMapA2->GetSignal(0,ix);
255 signal += signalLeft + signalRight;
256 fMapA2->SetHit(0,ix,(Double_t)signal);
258 if(ix>0.) signalLeft = (Float_t) fMapA2->GetSignal(1,ix-1)*
259 fDCS->GetCouplingNL();
260 else signalLeft = 0.0;
261 if(ix<(fNstrips-1)) signalRight = (Float_t) fMapA2->GetSignal(1,ix+1)*
262 fDCS->GetCouplingNR();
263 else signalRight = 0.0;
264 signal = (Float_t) fMapA2->GetSignal(1,ix);
265 signal += signalLeft + signalRight;
266 fMapA2->SetHit(1,ix,(Double_t)signal);
267 } // loop over strips
269 //______________________________________________________________________
270 Float_t AliITSsimulationSSD::F(Float_t av, Float_t x, Float_t s) {
271 // Computes the integral of a gaussian using Error Function
272 Float_t sqrt2 = TMath::Sqrt(2.0);
273 Float_t sigm2 = sqrt2*s;
276 integral = 0.5 * TMath::Erf( (x - av) / sigm2);
279 //______________________________________________________________________
280 void AliITSsimulationSSD::IntegrateGaussian(Int_t k,Double_t par, Double_t w,
282 Double_t inf, Double_t sup,
283 Int_t *indexRange, Bool_t first) {
284 // integrate the diffusion gaussian
285 // remind: inf and sup are w-3sigma and w+3sigma
286 // we could define them here instead of passing them
287 // this way we are free to introduce asimmetry
289 Double_t a=0.0, b=0.0;
290 Double_t signal = 0.0, dXCharge1 = 0.0, dXCharge2 = 0.0;
291 // dXCharge1 and 2 are the charge to two neighbouring strips
292 // Watch that we only involve at least two strips
293 // Numbers greater than 2 of strips in a cluster depend on
294 // geometry of the track and delta rays, not charge diffusion!
296 Double_t strip = TMath::Floor(w); // clostest strip on the left
298 if ( TMath::Abs((strip - w)) < 0.5) {
299 // gaussian mean is closer to strip on the left
300 a = inf; // integration starting point
301 if((strip+0.5)<=sup) {
302 // this means that the tail of the gaussian goes beyond
303 // the middle point between strips ---> part of the signal
304 // is given to the strip on the right
305 b = strip + 0.5; // integration stopping point
306 dXCharge1 = F( w, b, sigma) - F(w, a, sigma);
307 dXCharge2 = F( w, sup, sigma) - F(w ,b, sigma);
309 // this means that all the charge is given to the strip on the left
311 dXCharge1 = 0.9973; // gaussian integral at 3 sigmas
315 dXCharge1 = par * dXCharge1;// normalize by mean of number of carriers
316 dXCharge2 = par * dXCharge2;
318 // for the time being, signal is the charge
319 // in ChargeToSignal signal is converted in ADC channel
320 signal = fMapA2->GetSignal(k,strip);
323 fMapA2->SetHit(k,strip,(Double_t)signal);
324 if(((Int_t) strip) < (fNstrips-1)) {
325 // strip doesn't have to be the last (remind: last=fNstrips-1)
326 // otherwise part of the charge is lost
327 signal = fMapA2->GetSignal(k,(strip+1));
329 fMapA2->SetHit(k,(strip+1),(Double_t)signal);
334 indexRange[k*2+0]=indexRange[k*2+1]=(Int_t) strip;
338 indexRange[k*2+0]=TMath::Min(indexRange[k*2+0],(Int_t) strip);
339 indexRange[k*2+1]=TMath::Max(indexRange[k*2+1],(Int_t) strip);
343 // gaussian mean is closer to strip on the right
344 strip++; // move to strip on the rigth
345 b = sup; // now you know where to stop integrating
346 if((strip-0.5)>=inf) {
347 // tail of diffusion gaussian on the left goes left of
348 // middle point between strips
349 a = strip - 0.5; // integration starting point
350 dXCharge1 = F(w, b, sigma) - F(w, a, sigma);
351 dXCharge2 = F(w, a, sigma) - F(w, inf, sigma);
354 dXCharge1 = 0.9973; // gaussian integral at 3 sigmas
358 dXCharge1 = par * dXCharge1; // normalize by means of carriers
359 dXCharge2 = par * dXCharge2;
361 // for the time being, signal is the charge
362 // in ChargeToSignal signal is converted in ADC channel
363 signal = fMapA2->GetSignal(k,strip);
365 fMapA2->SetHit(k,strip,(Double_t)signal);
366 if(((Int_t) strip) > 0) {
367 // strip doesn't have to be the first
368 // otherwise part of the charge is lost
369 signal = fMapA2->GetSignal(k,(strip-1));
371 fMapA2->SetHit(k,(strip-1),(Double_t)signal);
376 indexRange[k*2+0]=indexRange[k*2+1]=(Int_t) strip;
380 indexRange[k*2+0]=TMath::Min(indexRange[k*2+0],(Int_t) strip);
381 indexRange[k*2+1]=TMath::Max(indexRange[k*2+1],(Int_t) strip);
385 //______________________________________________________________________
386 Int_t AliITSsimulationSSD::NumOfSteps(Double_t x, Double_t y, Double_t z,
387 Double_t & dex,Double_t & dey,Double_t & dez){
389 // it also returns steps for each coord
390 //AliITSsegmentationSSD *seg = new AliITSsegmentationSSD();
392 Double_t step = 25E-4;
393 //step = (Double_t) seg->GetStepSize(); // step size (cm)
394 Int_t numOfSteps = (Int_t) (TMath::Sqrt(x*x+y*y+z*z)/step);
396 if (numOfSteps < 1) numOfSteps = 1; // one step, at least
398 // we could condition the stepping depending on the incident angle
406 //----------------------------------------------------------------------
407 void AliITSsimulationSSD::GetList(Int_t label,Float_t **pList,
409 // loop over nonzero digits
410 Int_t ix,globalIndex;
412 Float_t highest,middle,lowest;
413 // printf("SPD-GetList: indexRange[0] indexRange[1] indexRange[2] indexRange[3] %d %d %d %d\n",indexRange[0], indexRange[1], indexRange[2], indexRange[3]);
415 for(Int_t k=0; k<2; k++) {
416 for(ix=indexRange[k*2+0];ix<indexRange[k*2+1]+1;ix++){
417 if(indexRange[k*2+0]<indexRange[k*2+1])
418 signal=fMapA2->GetSignal(k,ix);
420 globalIndex = k*fNstrips+ix; // globalIndex starts from 0!
421 if(!pList[globalIndex]){
423 //Create new list (6 elements-3 signals and 3 tracks+total sig)
425 pList[globalIndex] = new Float_t [6];
427 *pList[globalIndex] = -2.;
428 *(pList[globalIndex]+1) = -2.;
429 *(pList[globalIndex]+2) = -2.;
430 *(pList[globalIndex]+3) = 0.;
431 *(pList[globalIndex]+4) = 0.;
432 *(pList[globalIndex]+5) = 0.;
433 *pList[globalIndex] = (float)label;
434 *(pList[globalIndex]+3) = signal;
436 // check the signal magnitude
437 highest = *(pList[globalIndex]+3);
438 middle = *(pList[globalIndex]+4);
439 lowest = *(pList[globalIndex]+5);
440 signal -= (highest+middle+lowest);
442 // compare the new signal with already existing list
444 if(signal<lowest) continue; // neglect this track
446 *(pList[globalIndex]+5) = middle;
447 *(pList[globalIndex]+4) = highest;
448 *(pList[globalIndex]+3) = signal;
449 *(pList[globalIndex]+2) = *(pList[globalIndex]+1);
450 *(pList[globalIndex]+1) = *pList[globalIndex];
451 *pList[globalIndex] = label;
452 }else if (signal>middle){
453 *(pList[globalIndex]+5) = middle;
454 *(pList[globalIndex]+4) = signal;
455 *(pList[globalIndex]+2) = *(pList[globalIndex]+1);
456 *(pList[globalIndex]+1) = label;
458 *(pList[globalIndex]+5) = signal;
459 *(pList[globalIndex]+2) = label;
462 } // end of loop pixels in x
463 } // end of loop over pixels in z
465 //----------------------------------------------------------------------
466 void AliITSsimulationSSD::ChargeToSignal(Float_t **pList) {
468 AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
469 Float_t threshold = 0.;
470 Int_t digits[3], tracks[3],hits[3],gi,j1;
473 Float_t noise[2] = {0.,0.};
475 fResponse->GetNoiseParam(noise[0],noise[1]);
477 for(Int_t k=0;k<2;k++){ // both sides (0=Pside, 1=Nside)
479 // Threshold for zero-suppression
480 // It can be defined in AliITSresponseSSD
481 // threshold = (Float_t)fResponse->MinVal(k);
482 // I prefer to think adjusting the threshold "manually", looking
483 // at the scope, and considering noise standard deviation
484 threshold = 4.0*noise[k]; // 4 times noise is a choice
485 for(Int_t ix=0;ix<fNstrips;ix++){ // loop over strips
487 signal = (Float_t) fMapA2->GetSignal(k,ix);
489 gi =k*fNstrips+ix; // global index
490 if (signal > threshold) {
494 // convert to ADC signal
495 // conversion factor are rather arbitrary (need tuning)
496 // minimum ionizing particle--> ~30000 pairs--> ADC channel 50
497 signal = signal*50.0/30000.0;
498 if(signal>1000.) signal = 1000.0;//if exceeding, accumulate
500 digits[2]=(Int_t) signal;
502 //gi =k*fNstrips+ix; // global index
505 tracks[j1] = (Int_t)(*(pList[gi]+j1));
507 tracks[j1]=-2; //noise
518 aliITS->AddSimDigit(2,phys,digits,tracks,hits,charges);
520 //if(pList[gi]) delete [] pList[gi];
521 } // end if signal > threshold
522 if(pList[gi]) delete [] pList[gi];