1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 Revision 1.13 2001/11/13 11:13:24 barbera
19 A protection against tracks with the same entrance and exit has been made more strict
21 Revision 1.12 2001/10/04 22:44:31 nilsen
22 Major changes in supppor of PreDigits (SDigits). Changes made with will make
23 it easier to suppor expected changes in AliITSHit class. Added use of new
24 class AliITSpList. Both SPD and SDD have added effects of Dead Channels. Both
25 of these will require addtional work as data bases of detectors and the like
34 #include <TParticle.h>
38 #include "AliITShit.h"
39 #include "AliITSdigit.h"
40 #include "AliITSmodule.h"
41 #include "AliITSMapA2.h"
42 #include "AliITSpList.h"
43 #include "AliITSsimulationSPD.h"
44 #include "AliITSsegmentation.h"
45 #include "AliITSresponse.h"
46 #include "AliITSsegmentationSPD.h"
47 #include "AliITSresponseSPD.h"
50 ClassImp(AliITSsimulationSPD)
51 ////////////////////////////////////////////////////////////////////////
53 // Written by Rocco Caliandro
54 // from a model developed with T. Virgili and R.A. Fini
57 // AliITSsimulationSPD is the simulation of SPDs
59 //______________________________________________________________________
60 AliITSsimulationSPD::AliITSsimulationSPD(){
61 // Default constructor
73 //______________________________________________________________________
74 AliITSsimulationSPD::AliITSsimulationSPD(AliITSsegmentation *seg,
75 AliITSresponse *resp) {
76 // Standard constructor
87 Init((AliITSsegmentationSPD*)seg,(AliITSresponseSPD*)resp);
89 //______________________________________________________________________
90 void AliITSsimulationSPD::Init(AliITSsegmentationSPD *seg,
91 AliITSresponseSPD *resp) {
92 // Initilizes the variables of AliITSsimulation SPD.
97 fMapA2 = new AliITSMapA2(fSegmentation);
99 fResponse->Thresholds(fThresh,fSigma);
100 fResponse->GetNoiseParam(fCouplCol,fCouplRow);
101 fNPixelsZ = fSegmentation->Npz();
102 fNPixelsX = fSegmentation->Npx();
105 //______________________________________________________________________
106 AliITSsimulationSPD::~AliITSsimulationSPD() {
116 //______________________________________________________________________
117 AliITSsimulationSPD::AliITSsimulationSPD(const AliITSsimulationSPD &source){
120 if(&source == this) return;
122 this->fMapA2 = source.fMapA2;
123 this->fHis = source.fHis;
125 this->fThresh = source.fThresh;
126 this->fSigma = source.fSigma;
127 this->fCouplCol = source.fCouplCol;
128 this->fCouplRow = source.fCouplRow;
129 this->fNPixelsX = source.fNPixelsX;
130 this->fNPixelsZ = source.fNPixelsZ;
134 //______________________________________________________________________
135 AliITSsimulationSPD& AliITSsimulationSPD::operator=(const AliITSsimulationSPD
137 // Assignment operator
139 if(&source == this) return *this;
141 this->fMapA2 = source.fMapA2;
142 this->fHis = source.fHis;
144 this->fThresh = source.fThresh;
145 this->fSigma = source.fSigma;
146 this->fCouplCol = source.fCouplCol;
147 this->fCouplRow = source.fCouplRow;
148 this->fNPixelsX = source.fNPixelsX;
149 this->fNPixelsZ = source.fNPixelsZ;
153 //______________________________________________________________________
154 void AliITSsimulationSPD::SDigitiseModule(AliITSmodule *mod, Int_t dummy0,
156 // Sum digitize module
157 if (!(mod->GetNhits())) return; // if module has no hits then no Sdigits.
158 Int_t number = 10000;
159 Int_t *frowpixel = new Int_t[number];
160 Int_t *fcolpixel = new Int_t[number];
161 Double_t *fenepixel = new Double_t[number];
163 // Array of pointers to store the track index of the digits
164 // leave +1, otherwise pList crashes when col=256, row=192
165 AliITSpList *pList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
167 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,pList);
178 //______________________________________________________________________
179 void AliITSsimulationSPD::DigitiseModule(AliITSmodule *mod, Int_t dummy0,
181 // digitize module. Also need to digitize modules with only noise.
183 Int_t number = 10000;
184 Int_t *frowpixel = new Int_t[number];
185 Int_t *fcolpixel = new Int_t[number];
186 Double_t *fenepixel = new Double_t[number];
187 Int_t module = mod->GetIndex();
189 // Array of pointers to store the track index of the digits
190 // leave +1, otherwise pList crashes when col=256, row=192
191 AliITSpList *pList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
194 SetFluctuations(pList,module);
196 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,pList);
198 // apply mask to SPD module
201 CreateDigit(module,pList);
210 //______________________________________________________________________
211 void AliITSsimulationSPD::SDigitsToDigits(Int_t module,AliITSpList *pList) {
212 // sum digits to Digits.
214 FillMapFrompList(pList);
217 SetFluctuations(pList,module);
219 // apply mask to SPD module
222 CreateDigit(module,pList);
224 //______________________________________________________________________
225 void AliITSsimulationSPD::UpdateMapSignal(Int_t row,Int_t col,Int_t trk,
226 Int_t hit,Int_t mod,Double_t ene,
227 AliITSpList *pList) {
228 // updates the Map of signal, adding the energy (ene) released by
231 fMapA2->AddSignal(row,col,ene);
232 pList->AddSignal(row,col,trk,hit,mod,ene);
234 //______________________________________________________________________
235 void AliITSsimulationSPD::UpdateMapNoise(Int_t row,Int_t col,Int_t mod,
236 Double_t ene,AliITSpList *pList) {
237 // updates the Map of noise, adding the energy (ene) give my noise
239 fMapA2->AddSignal(row,col,ene);
240 pList->AddNoise(row,col,mod,ene);
242 //______________________________________________________________________
243 void AliITSsimulationSPD::HitsToAnalogDigits(AliITSmodule *mod,
244 Int_t *frowpixel,Int_t *fcolpixel,
246 AliITSpList *pList) {
247 // Loops over all hits to produce Analog/floting point digits. This
248 // is also the first task in producing standard digits.
250 // loop over hits in the module
251 Int_t hitpos,nhits = mod->GetNhits();
252 for (hitpos=0;hitpos<nhits;hitpos++) {
253 HitToDigit(mod,hitpos,frowpixel,fcolpixel,fenepixel,pList);
254 }// end loop over digits
256 //______________________________________________________________________
257 void AliITSsimulationSPD::HitToDigit(AliITSmodule *mod,Int_t hitpos,
258 Int_t *frowpixel,Int_t *fcolpixel,
259 Double_t *fenepixel,AliITSpList *pList) {
260 // Steering function to determine the digits associated to a given
262 // The digits are created by charge sharing (ChargeSharing) and by
263 // capacitive coupling (SetCoupling). At all the created digits is
264 // associated the track number of the hit (ntrack)
265 Double_t x1l=0.0,y1l=0.0,z1l=0.0,x2l=0.0,y2l=0.0,z2l=0.0;
266 Int_t r1,r2,c1,c2,row,col,npixel = 0;
268 Double_t ene=0.0,etot=0.0;
269 const Float_t kconv = 10000.; // cm -> microns
270 const Float_t kconv1= 0.277e9; // GeV -> electrons equivalent
272 if(!(mod->LineSegmentL(hitpos,x1l,x2l,y1l,y2l,z1l,z2l,etot,ntrack)))return;
274 x2l += x1l; y2l += y1l; z2l += z1l; // Convert to ending coordinate.
275 // positions shifted and converted in microns
276 x1l = x1l*kconv + fSegmentation->Dx()/2.;
277 z1l = z1l*kconv + fSegmentation->Dz()/2.;
278 // positions shifted and converted in microns
279 x2l = x2l*kconv + fSegmentation->Dx()/2.;
280 z2l = z2l*kconv + fSegmentation->Dz()/2.;
281 etot *= kconv1; // convert from GeV to electrons equivalent.
282 Int_t module = mod->GetIndex();
284 // to account for the effective sensitive area
285 // introduced in geometry
286 if (z1l<0 || z1l>fSegmentation->Dz()) return;
287 if (z2l<0 || z2l>fSegmentation->Dz()) return;
288 if (x1l<0 || x1l>fSegmentation->Dx()) return;
289 if (x2l<0 || x2l>fSegmentation->Dx()) return;
291 //Get the col and row number starting from 1
292 // the x direction is not inverted for the second layer!!!
293 fSegmentation->GetPadIxz(x1l, z1l, c1, r1);
294 fSegmentation->GetPadIxz(x2l, z2l, c2, r2);
296 // to account for unexpected equal entrance and
298 if (x1l==x2l) x2l=x2l+x2l*0.1;
299 if (z1l==z2l) z2l=z2l+z2l*0.1;
301 if ((r1==r2) && (c1==c2)){
304 frowpixel[npixel-1] = r1;
305 fcolpixel[npixel-1] = c1;
306 fenepixel[npixel-1] = etot;
309 ChargeSharing(x1l,z1l,x2l,z2l,c1,r1,c2,r2,etot,
310 npixel,frowpixel,fcolpixel,fenepixel);
311 } // end if r1==r2 && c1==c2.
313 for (Int_t npix=0;npix<npixel;npix++){
314 row = frowpixel[npix];
315 col = fcolpixel[npix];
316 ene = fenepixel[npix];
317 UpdateMapSignal(row,col,ntrack,hitpos,module,ene,pList);
318 // Starting capacitive coupling effect
319 SetCoupling(row,col,ntrack,hitpos,module,pList);
322 //______________________________________________________________________
323 void AliITSsimulationSPD::ChargeSharing(Float_t x1l,Float_t z1l,Float_t x2l,
324 Float_t z2l,Int_t c1,Int_t r1,Int_t c2,
325 Int_t r2,Float_t etot,
326 Int_t &npixel,Int_t *frowpixel,
327 Int_t *fcolpixel,Double_t *fenepixel){
328 // Take into account the geometrical charge sharing when the track
329 // crosses more than one pixel.
333 <img src="picts/ITS/barimodel_2.gif">
336 <font size=+2 color=red>
337 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
342 Float_t xa,za,xb,zb,dx,dz,dtot,dm,refr,refm,refc;
344 Float_t arefm, arefr, arefn, arefc, azb, az2l, axb, ax2l;
345 Int_t dirx,dirz,rb,cb;
346 Int_t flag,flagrow,flagcol;
352 dx = TMath::Abs(x1l-x2l);
353 if (dx == 0.) dx = 0.01;
354 dz = TMath::Abs(z1l-z2l);
355 if (dz == 0.) dz = 0.01;
356 dtot = TMath::Sqrt((dx*dx)+(dz*dz));
357 dm = (x2l - x1l) / (z2l - z1l);
358 if (dm == 0.) dm = 0.01;
359 dirx = (Int_t) ((x2l - x1l) / dx);
360 dirz = (Int_t) ((z2l - z1l) / dz);
362 // calculate the x coordinate of the pixel in the next column
363 // and the z coordinate of the pixel in the next row
366 fSegmentation->GetPadCxz(c1, r1-1, xpos, zpos);
368 Float_t xsize = fSegmentation->Dpx(0);
369 Float_t zsize = fSegmentation->Dpz(r1-1);
371 if (dirx == 1) refr = xpos+xsize/2.;
372 else refr = xpos-xsize/2.;
374 if (dirz == 1) refn = zpos+zsize/2.;
375 else refn = zpos-zsize/2.;
381 // calculate the x coordinate of the intersection with the pixel
382 // in the next cell in row direction
383 refm = (refn - z1l)*dm + x1l;
385 // calculate the z coordinate of the intersection with the pixel
386 // in the next cell in column direction
387 refc = (refr - x1l)/dm + z1l;
394 if ((arefm < arefr) && (arefn < arefc)){
395 // the track goes in the pixel in the next cell in row direction
402 if (rb == r2) flagrow=1;
407 // shift to the pixel in the next cell in row direction
408 Float_t zsizeNext = fSegmentation->Dpz(rb-1);
409 //to account for cell at the borders of the detector
410 if(zsizeNext==0) zsizeNext = zsize;
411 refn += zsizeNext*dirz;
413 // the track goes in the pixel in the next cell in column direction
420 if (cb == c2) flagcol=1;
424 } // end ifaxb > ax2l
426 // shift to the pixel in the next cell in column direction
427 Float_t xsizeNext = fSegmentation->Dpx(cb-1);
428 //to account for cell at the borders of the detector
429 if(xsizeNext==0) xsizeNext = xsize;
430 refr += xsizeNext*dirx;
431 } // end if (arefm < arefr) && (arefn < arefc)
433 //calculate the energy lost in the crossed pixel
434 epar = TMath::Sqrt((xb-xa)*(xb-xa)+(zb-za)*(zb-za));
435 epar = etot*(epar/dtot);
437 //store row, column and energy lost in the crossed pixel
438 frowpixel[npixel] = r1;
439 fcolpixel[npixel] = c1;
440 fenepixel[npixel] = epar;
443 // the exit point of the track is reached
444 if (epar == 0) flag = 1;
445 if ((r1 == r2) && (c1 == c2)) flag = 1;
454 //______________________________________________________________________
455 void AliITSsimulationSPD::SetCoupling(Int_t row, Int_t col, Int_t ntrack,
456 Int_t idhit,Int_t module,
457 AliITSpList *pList) {
458 // Take into account the coupling between adiacent pixels.
459 // The parameters probcol and probrow are the fractions of the
460 // signal in one pixel shared in the two adjacent pixels along
461 // the column and row direction, respectively.
465 <img src="picts/ITS/barimodel_3.gif">
468 <font size=+2 color=red>
469 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
475 Double_t pulse1,pulse2;
476 Float_t couplR=0.0,couplC=0.0;
478 GetCouplings(couplR,couplC);
481 pulse1 = fMapA2->GetSignal(row,col);
483 for (Int_t isign=-1;isign<=1;isign+=2){// loop in row direction
487 if ((j1<0) || (j1>GetNPixelsZ()-1) || (pulse1<GetThreshold())){
488 pulse1 = fMapA2->GetSignal(row,col);
492 UpdateMapSignal(j1,col,ntrack,idhit,module,pulse1,pList);
496 // loop in column direction
500 if ((j2<0) || (j2>(GetNPixelsX()-1)) || (pulse2<GetThreshold())){
501 pulse2 = fMapA2->GetSignal(row,col);
505 UpdateMapSignal(row,j2,ntrack,idhit,module,pulse2,pList);
511 //______________________________________________________________________
512 void AliITSsimulationSPD::CreateDigit(Int_t module,AliITSpList *pList) {
513 // The pixels are fired if the energy deposited inside them is above
514 // the threshold parameter ethr. Fired pixed are interpreted as digits
515 // and stored in the file digitfilename. One also needs to write out
516 // cases when there is only noise (nhits==0).
518 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
526 for (Int_t r=1;r<=GetNPixelsZ();r++) {
527 for (Int_t c=1;c<=GetNPixelsX();c++) {
528 // check if the deposited energy in a pixel is above the
530 Float_t signal = (Float_t) fMapA2->GetSignal(r,c);
531 if ( signal > GetThreshold()) {
532 digits[0] = r-1; // digits starts from 0
533 digits[1] = c-1; // digits starts from 0
535 digits[2] = (Int_t) signal; // the signal is stored in
538 tracks[j1] = pList->GetTrack(r,c,j1);
539 hits[j1] = pList->GetHit(r,c,j1);
543 aliITS->AddSimDigit(0,phys,digits,tracks,hits,charges);
544 } // end if of threshold condition
548 //______________________________________________________________________
549 void AliITSsimulationSPD::SetFluctuations(AliITSpList *pList,Int_t module) {
550 // Set the electronic noise and threshold non-uniformities to all the
551 // pixels in a detector.
552 // The parameter fSigma is the squared sum of the sigma due to noise
553 // and the sigma of the threshold distribution among pixels.
557 <img src="picts/ITS/barimodel_1.gif">
560 <font size=+2 color=red>
561 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
566 Float_t thr=0.0,sigm=0.0;
567 Double_t signal,sigma;
570 GetThresholds(thr,sigm);
571 sigma = (Double_t) sigm;
572 for(iz=1;iz<=GetNPixelsZ();iz++){
573 for(ix=1;ix<=GetNPixelsX();ix++){
574 signal = sigma*gRandom->Gaus();
575 fMapA2->SetHit(iz,ix,signal);
576 // insert in the label-signal-hit list the pixels fired
578 pList->AddNoise(iz,ix,module,signal);
579 } // end of loop on pixels
580 } // end of loop on pixels
582 //______________________________________________________________________
583 void AliITSsimulationSPD::SetMask() {
584 // Apply a mask to the SPD module. 1% of the pixel channels are
585 // masked. When the database will be ready, the masked pixels
586 // should be read from it.
590 Float_t perc = ((AliITSresponseSPD*)fResponse)->GetFractionDead();
591 // in this way we get the same set of random numbers for all runs.
592 // This is a cluge for now.
593 static TRandom *rnd = new TRandom();
595 totMask= perc*GetNPixelsZ()*GetNPixelsX();
596 for(im=1;im<totMask;im++){
598 ix=(Int_t)(rnd->Rndm()*(GetNPixelsX()-1.) + 1.);
599 } while(ix<=0 || ix>GetNPixelsX());
601 iz=(Int_t)(rnd->Rndm()*(GetNPixelsZ()-1.) + 1.);
602 } while(iz<=0 || iz>GetNPixelsZ());
604 fMapA2->SetHit(iz,ix,signal);
605 } // end loop on masked pixels
607 //______________________________________________________________________
608 void AliITSsimulationSPD::CreateHistograms() {
612 fHis=new TObjArray(GetNPixelsZ());
613 for(i=0;i<GetNPixelsZ();i++) {
614 TString spdname("spd_");
616 sprintf(candnum,"%d",i+1);
617 spdname.Append(candnum);
618 (*fHis)[i] = new TH1F(spdname.Data(),"SPD maps",
619 GetNPixelsX(),0.,(Float_t) GetNPixelsX());
622 //______________________________________________________________________
623 void AliITSsimulationSPD::ResetHistograms() {
624 // Reset histograms for this detector
627 for(i=0;i<GetNPixelsZ();i++ ) {
628 if ((*fHis)[i]) ((TH1F*)(*fHis)[i])->Reset();
631 //______________________________________________________________________
632 void AliITSsimulationSPD::WriteSDigits(AliITSpList *pList){
633 // Fills the Summable digits Tree
635 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
637 pList->GetMaxMapIndex(ni,nj);
638 for(i=0;i<ni;i++)for(j=0;j<nj;j++){
639 if(pList->GetSignalOnly(i,j)>0.0){
640 aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
641 // cout << "pListSPD: " << *(pList->GetpListItem(i,j)) << endl;
646 //______________________________________________________________________
647 void AliITSsimulationSPD::FillMapFrompList(AliITSpList *pList){
648 // Fills fMap2A from the pList of Summable digits
651 for(k=0;k<GetNPixelsZ();k++)for(ix=0;ix<GetNPixelsX();ix++)
652 fMapA2->AddSignal(k,ix,pList->GetSignal(k,ix));