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.16 2002/06/19 16:02:22 hristov
19 Division by zero corrected
21 Revision 1.15 2002/03/15 17:32:14 nilsen
22 Reintroduced SDigitization, and Digitization from SDigits, along with
23 functions InitSimulationModule, and FinishSDigitizModule.
25 Revision 1.14 2001/11/23 13:04:07 barbera
26 Some protection added in case of high multiplicity
28 Revision 1.13 2001/11/13 11:13:24 barbera
29 A protection against tracks with the same entrance and exit has been made more strict
31 Revision 1.12 2001/10/04 22:44:31 nilsen
32 Major changes in supppor of PreDigits (SDigits). Changes made with will make
33 it easier to suppor expected changes in AliITSHit class. Added use of new
34 class AliITSpList. Both SPD and SDD have added effects of Dead Channels. Both
35 of these will require addtional work as data bases of detectors and the like
44 #include <TParticle.h>
48 #include "AliITShit.h"
49 #include "AliITSdigit.h"
50 #include "AliITSmodule.h"
51 #include "AliITSMapA2.h"
52 #include "AliITSpList.h"
53 #include "AliITSsimulationSPD.h"
54 #include "AliITSsegmentation.h"
55 #include "AliITSresponse.h"
56 #include "AliITSsegmentationSPD.h"
57 #include "AliITSresponseSPD.h"
60 ClassImp(AliITSsimulationSPD)
61 ////////////////////////////////////////////////////////////////////////
63 // Written by Rocco Caliandro
64 // from a model developed with T. Virgili and R.A. Fini
67 // AliITSsimulationSPD is the simulation of SPDs
69 //______________________________________________________________________
70 AliITSsimulationSPD::AliITSsimulationSPD(){
71 // Default constructor
84 //______________________________________________________________________
85 AliITSsimulationSPD::AliITSsimulationSPD(AliITSsegmentation *seg,
86 AliITSresponse *resp) {
87 // Standard constructor
99 Init((AliITSsegmentationSPD*)seg,(AliITSresponseSPD*)resp);
101 //______________________________________________________________________
102 void AliITSsimulationSPD::Init(AliITSsegmentationSPD *seg,
103 AliITSresponseSPD *resp) {
104 // Initilizes the variables of AliITSsimulation SPD.
109 fMapA2 = new AliITSMapA2(fSegmentation);
110 fpList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
112 fResponse->Thresholds(fThresh,fSigma);
113 fResponse->GetNoiseParam(fCouplCol,fCouplRow);
114 fNPixelsZ = fSegmentation->Npz();
115 fNPixelsX = fSegmentation->Npx();
118 //______________________________________________________________________
119 AliITSsimulationSPD::~AliITSsimulationSPD() {
130 //______________________________________________________________________
131 AliITSsimulationSPD::AliITSsimulationSPD(const AliITSsimulationSPD &source){
134 if(&source == this) return;
136 this->fMapA2 = source.fMapA2;
137 this->fHis = source.fHis;
139 this->fThresh = source.fThresh;
140 this->fSigma = source.fSigma;
141 this->fCouplCol = source.fCouplCol;
142 this->fCouplRow = source.fCouplRow;
143 this->fNPixelsX = source.fNPixelsX;
144 this->fNPixelsZ = source.fNPixelsZ;
148 //______________________________________________________________________
149 AliITSsimulationSPD& AliITSsimulationSPD::operator=(const AliITSsimulationSPD
151 // Assignment operator
153 if(&source == this) return *this;
155 this->fMapA2 = source.fMapA2;
156 this->fHis = source.fHis;
158 this->fThresh = source.fThresh;
159 this->fSigma = source.fSigma;
160 this->fCouplCol = source.fCouplCol;
161 this->fCouplRow = source.fCouplRow;
162 this->fNPixelsX = source.fNPixelsX;
163 this->fNPixelsZ = source.fNPixelsZ;
167 //______________________________________________________________________
168 void AliITSsimulationSPD::InitSimulationModule(Int_t module,Int_t event){
169 // Creates maps to build the list of tracks for each sumable digit
171 // Int_t module // Module number to be simulated
172 // Int_t event // Event number to be simulated
183 //______________________________________________________________________
184 void AliITSsimulationSPD::FinishSDigitiseModule(){
185 // Does the Sdigits to Digits work
193 SDigitsToDigits(fModule,fpList);
195 //______________________________________________________________________
196 void AliITSsimulationSPD::SDigitiseModule(AliITSmodule *mod, Int_t dummy0,
198 // Sum digitize module
199 if (!(mod->GetNhits())) return; // if module has no hits then no Sdigits.
200 Int_t number = 10000;
201 Int_t *frowpixel = new Int_t[number];
202 Int_t *fcolpixel = new Int_t[number];
203 Double_t *fenepixel = new Double_t[number];
205 fModule = mod->GetIndex();
207 // Array of pointers to store the track index of the digits
208 // leave +1, otherwise pList crashes when col=256, row=192
210 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
212 WriteSDigits(fpList);
221 //______________________________________________________________________
222 void AliITSsimulationSPD::DigitiseModule(AliITSmodule *mod, Int_t dummy0,
224 // digitize module. Also need to digitize modules with only noise.
226 Int_t number = 10000;
227 Int_t *frowpixel = new Int_t[number];
228 Int_t *fcolpixel = new Int_t[number];
229 Double_t *fenepixel = new Double_t[number];
231 // Array of pointers to store the track index of the digits
232 // leave +1, otherwise pList crashes when col=256, row=192
233 fModule = mod->GetIndex();
235 SetFluctuations(fpList,fModule);
237 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
239 // apply mask to SPD module
242 CreateDigit(fModule,fpList);
251 //______________________________________________________________________
252 void AliITSsimulationSPD::SDigitsToDigits(Int_t module,AliITSpList *pList) {
253 // sum digits to Digits.
254 // cout << "Entering AliITSsimulatinSPD::SDigitsToDigits for module=";
255 // cout << module << endl;
259 SetFluctuations(pList,module);
261 fMapA2->ClearMap(); // since noise is in pList aready. Zero Map so that
262 // noise is not doubled when calling FillMapFrompList.
264 FillMapFrompList(pList);
266 // apply mask to SPD module
269 CreateDigit(module,pList);
274 //______________________________________________________________________
275 void AliITSsimulationSPD::UpdateMapSignal(Int_t row,Int_t col,Int_t trk,
276 Int_t hit,Int_t mod,Double_t ene,
277 AliITSpList *pList) {
278 // updates the Map of signal, adding the energy (ene) released by
281 fMapA2->AddSignal(row,col,ene);
282 pList->AddSignal(row,col,trk,hit,mod,ene);
284 //______________________________________________________________________
285 void AliITSsimulationSPD::UpdateMapNoise(Int_t row,Int_t col,Int_t mod,
286 Double_t ene,AliITSpList *pList) {
287 // updates the Map of noise, adding the energy (ene) give my noise
289 fMapA2->AddSignal(row,col,ene);
290 pList->AddNoise(row,col,mod,ene);
292 //______________________________________________________________________
293 void AliITSsimulationSPD::HitsToAnalogDigits(AliITSmodule *mod,
294 Int_t *frowpixel,Int_t *fcolpixel,
296 AliITSpList *pList) {
297 // Loops over all hits to produce Analog/floting point digits. This
298 // is also the first task in producing standard digits.
300 // loop over hits in the module
301 Int_t hitpos,nhits = mod->GetNhits();
302 for (hitpos=0;hitpos<nhits;hitpos++) {
303 HitToDigit(mod,hitpos,frowpixel,fcolpixel,fenepixel,pList);
304 }// end loop over digits
306 //______________________________________________________________________
307 void AliITSsimulationSPD::HitToDigit(AliITSmodule *mod,Int_t hitpos,
308 Int_t *frowpixel,Int_t *fcolpixel,
309 Double_t *fenepixel,AliITSpList *pList) {
310 // Steering function to determine the digits associated to a given
312 // The digits are created by charge sharing (ChargeSharing) and by
313 // capacitive coupling (SetCoupling). At all the created digits is
314 // associated the track number of the hit (ntrack)
315 Double_t x1l=0.0,y1l=0.0,z1l=0.0,x2l=0.0,y2l=0.0,z2l=0.0;
316 Int_t r1,r2,c1,c2,row,col,npixel = 0;
318 Double_t ene=0.0,etot=0.0;
319 const Float_t kconv = 10000.; // cm -> microns
320 const Float_t kconv1= 0.277e9; // GeV -> electrons equivalent
322 if(!(mod->LineSegmentL(hitpos,x1l,x2l,y1l,y2l,z1l,z2l,etot,ntrack)))return;
324 x2l += x1l; y2l += y1l; z2l += z1l; // Convert to ending coordinate.
325 // positions shifted and converted in microns
326 x1l = x1l*kconv + fSegmentation->Dx()/2.;
327 z1l = z1l*kconv + fSegmentation->Dz()/2.;
328 // positions shifted and converted in microns
329 x2l = x2l*kconv + fSegmentation->Dx()/2.;
330 z2l = z2l*kconv + fSegmentation->Dz()/2.;
331 etot *= kconv1; // convert from GeV to electrons equivalent.
332 Int_t module = mod->GetIndex();
334 // to account for the effective sensitive area
335 // introduced in geometry
336 if (z1l<0 || z1l>fSegmentation->Dz()) return;
337 if (z2l<0 || z2l>fSegmentation->Dz()) return;
338 if (x1l<0 || x1l>fSegmentation->Dx()) return;
339 if (x2l<0 || x2l>fSegmentation->Dx()) return;
341 //Get the col and row number starting from 1
342 // the x direction is not inverted for the second layer!!!
343 fSegmentation->GetPadIxz(x1l, z1l, c1, r1);
344 fSegmentation->GetPadIxz(x2l, z2l, c2, r2);
346 // to account for unexpected equal entrance and
348 if (x1l==x2l) x2l=x2l+x2l*0.1;
349 if (z1l==z2l) z2l=z2l+z2l*0.1;
351 if ((r1==r2) && (c1==c2)){
354 frowpixel[npixel-1] = r1;
355 fcolpixel[npixel-1] = c1;
356 fenepixel[npixel-1] = etot;
359 ChargeSharing(x1l,z1l,x2l,z2l,c1,r1,c2,r2,etot,
360 npixel,frowpixel,fcolpixel,fenepixel);
361 } // end if r1==r2 && c1==c2.
363 for (Int_t npix=0;npix<npixel;npix++){
364 row = frowpixel[npix];
365 col = fcolpixel[npix];
366 ene = fenepixel[npix];
367 UpdateMapSignal(row,col,ntrack,hitpos,module,ene,pList);
368 // Starting capacitive coupling effect
369 SetCoupling(row,col,ntrack,hitpos,module,pList);
372 //______________________________________________________________________
373 void AliITSsimulationSPD::ChargeSharing(Float_t x1l,Float_t z1l,Float_t x2l,
374 Float_t z2l,Int_t c1,Int_t r1,Int_t c2,
375 Int_t r2,Float_t etot,
376 Int_t &npixel,Int_t *frowpixel,
377 Int_t *fcolpixel,Double_t *fenepixel){
378 // Take into account the geometrical charge sharing when the track
379 // crosses more than one pixel.
383 <img src="picts/ITS/barimodel_2.gif">
386 <font size=+2 color=red>
387 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
392 Float_t xa,za,xb,zb,dx,dz,dtot,dm,refr,refm,refc;
394 Float_t arefm, arefr, arefn, arefc, azb, az2l, axb, ax2l;
395 Int_t dirx,dirz,rb,cb;
396 Int_t flag,flagrow,flagcol;
406 dtot = TMath::Sqrt((dx*dx)+(dz*dz));
407 if (dtot==0.0) dtot = 0.01;
408 dirx = (Int_t) TMath::Sign((Float_t)1,dx);
409 dirz = (Int_t) TMath::Sign((Float_t)1,dz);
411 // calculate the x coordinate of the pixel in the next column
412 // and the z coordinate of the pixel in the next row
415 fSegmentation->GetPadCxz(c1, r1-1, xpos, zpos);
417 Float_t xsize = fSegmentation->Dpx(0);
418 Float_t zsize = fSegmentation->Dpz(r1-1);
420 if (dirx == 1) refr = xpos+xsize/2.;
421 else refr = xpos-xsize/2.;
423 if (dirz == 1) refn = zpos+zsize/2.;
424 else refn = zpos-zsize/2.;
430 // calculate the x coordinate of the intersection with the pixel
431 // in the next cell in row direction
433 refm = dx*((refn - z1l)/dz) + x1l;
435 refm = refr+dirx*xsize;
437 // calculate the z coordinate of the intersection with the pixel
438 // in the next cell in column direction
440 refc = dz*((refr - x1l)/dx) + z1l;
442 refc = refn+dirz*zsize;
449 if ((arefm < arefr) && (arefn < arefc)){
450 // the track goes in the pixel in the next cell in row direction
457 if (rb == r2) flagrow=1;
462 // shift to the pixel in the next cell in row direction
463 Float_t zsizeNext = fSegmentation->Dpz(rb-1);
464 //to account for cell at the borders of the detector
465 if(zsizeNext==0) zsizeNext = zsize;
466 refn += zsizeNext*dirz;
468 // the track goes in the pixel in the next cell in column direction
475 if (cb == c2) flagcol=1;
479 } // end ifaxb > ax2l
481 // shift to the pixel in the next cell in column direction
482 Float_t xsizeNext = fSegmentation->Dpx(cb-1);
483 //to account for cell at the borders of the detector
484 if(xsizeNext==0) xsizeNext = xsize;
485 refr += xsizeNext*dirx;
486 } // end if (arefm < arefr) && (arefn < arefc)
488 //calculate the energy lost in the crossed pixel
489 epar = TMath::Sqrt((xb-xa)*(xb-xa)+(zb-za)*(zb-za));
490 epar = etot*(epar/dtot);
492 //store row, column and energy lost in the crossed pixel
493 frowpixel[npixel] = r1;
494 fcolpixel[npixel] = c1;
495 fenepixel[npixel] = epar;
498 // the exit point of the track is reached
499 if (epar == 0) flag = 1;
500 if ((r1 == r2) && (c1 == c2)) flag = 1;
509 //______________________________________________________________________
510 void AliITSsimulationSPD::SetCoupling(Int_t row, Int_t col, Int_t ntrack,
511 Int_t idhit,Int_t module,
512 AliITSpList *pList) {
513 // Take into account the coupling between adiacent pixels.
514 // The parameters probcol and probrow are the fractions of the
515 // signal in one pixel shared in the two adjacent pixels along
516 // the column and row direction, respectively.
520 <img src="picts/ITS/barimodel_3.gif">
523 <font size=+2 color=red>
524 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
530 Double_t pulse1,pulse2;
531 Float_t couplR=0.0,couplC=0.0;
533 GetCouplings(couplR,couplC);
536 pulse1 = fMapA2->GetSignal(row,col);
538 for (Int_t isign=-1;isign<=1;isign+=2){// loop in row direction
542 if ((j1<0) || (j1>GetNPixelsZ()-1) || (pulse1<GetThreshold())){
543 pulse1 = fMapA2->GetSignal(row,col);
547 UpdateMapSignal(j1,col,ntrack,idhit,module,pulse1,pList);
551 // loop in column direction
555 if ((j2<0) || (j2>(GetNPixelsX()-1)) || (pulse2<GetThreshold())){
556 pulse2 = fMapA2->GetSignal(row,col);
560 UpdateMapSignal(row,j2,ntrack,idhit,module,pulse2,pList);
566 //______________________________________________________________________
567 void AliITSsimulationSPD::CreateDigit(Int_t module,AliITSpList *pList) {
568 // The pixels are fired if the energy deposited inside them is above
569 // the threshold parameter ethr. Fired pixed are interpreted as digits
570 // and stored in the file digitfilename. One also needs to write out
571 // cases when there is only noise (nhits==0).
573 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
581 for (Int_t r=1;r<=GetNPixelsZ();r++) {
582 for (Int_t c=1;c<=GetNPixelsX();c++) {
583 // check if the deposited energy in a pixel is above the
585 Float_t signal = (Float_t) fMapA2->GetSignal(r,c);
586 if ( signal > GetThreshold()) {
587 digits[0] = r-1; // digits starts from 0
588 digits[1] = c-1; // digits starts from 0
590 digits[2] = (Int_t) signal; // the signal is stored in
593 tracks[j1] = pList->GetTrack(r,c,j1);
594 hits[j1] = pList->GetHit(r,c,j1);
598 aliITS->AddSimDigit(0,phys,digits,tracks,hits,charges);
599 // cout << " CreateSPDDigit mod=" << fModule << " r,c=" << r;
600 // cout <<","<<c<< " sig=" << fpList->GetSignalOnly(r,c);
601 // cout << " noise=" << fpList->GetNoise(r,c);
602 // cout << " Msig="<< signal << " Thres=" << GetThreshold()<<endl;
603 } // end if of threshold condition
607 //______________________________________________________________________
608 void AliITSsimulationSPD::SetFluctuations(AliITSpList *pList,Int_t module) {
609 // Set the electronic noise and threshold non-uniformities to all the
610 // pixels in a detector.
611 // The parameter fSigma is the squared sum of the sigma due to noise
612 // and the sigma of the threshold distribution among pixels.
616 <img src="picts/ITS/barimodel_1.gif">
619 <font size=+2 color=red>
620 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
625 Float_t thr=0.0,sigm=0.0;
626 Double_t signal,sigma;
629 GetThresholds(thr,sigm);
630 sigma = (Double_t) sigm;
631 for(iz=1;iz<=GetNPixelsZ();iz++){
632 for(ix=1;ix<=GetNPixelsX();ix++){
633 signal = sigma*gRandom->Gaus();
634 fMapA2->SetHit(iz,ix,signal);
635 // insert in the label-signal-hit list the pixels fired
637 pList->AddNoise(iz,ix,module,signal);
638 } // end of loop on pixels
639 } // end of loop on pixels
641 //______________________________________________________________________
642 void AliITSsimulationSPD::SetMask() {
643 // Apply a mask to the SPD module. 1% of the pixel channels are
644 // masked. When the database will be ready, the masked pixels
645 // should be read from it.
649 Float_t perc = ((AliITSresponseSPD*)fResponse)->GetFractionDead();
650 // in this way we get the same set of random numbers for all runs.
651 // This is a cluge for now.
652 static TRandom *rnd = new TRandom();
654 totMask= perc*GetNPixelsZ()*GetNPixelsX();
655 for(im=1;im<totMask;im++){
657 ix=(Int_t)(rnd->Rndm()*(GetNPixelsX()-1.) + 1.);
658 } while(ix<=0 || ix>GetNPixelsX());
660 iz=(Int_t)(rnd->Rndm()*(GetNPixelsZ()-1.) + 1.);
661 } while(iz<=0 || iz>GetNPixelsZ());
663 fMapA2->SetHit(iz,ix,signal);
664 } // end loop on masked pixels
666 //______________________________________________________________________
667 void AliITSsimulationSPD::CreateHistograms() {
671 fHis=new TObjArray(GetNPixelsZ());
672 for(i=0;i<GetNPixelsZ();i++) {
673 TString spdname("spd_");
675 sprintf(candnum,"%d",i+1);
676 spdname.Append(candnum);
677 (*fHis)[i] = new TH1F(spdname.Data(),"SPD maps",
678 GetNPixelsX(),0.,(Float_t) GetNPixelsX());
681 //______________________________________________________________________
682 void AliITSsimulationSPD::ResetHistograms() {
683 // Reset histograms for this detector
686 for(i=0;i<GetNPixelsZ();i++ ) {
687 if ((*fHis)[i]) ((TH1F*)(*fHis)[i])->Reset();
690 //______________________________________________________________________
691 void AliITSsimulationSPD::WriteSDigits(AliITSpList *pList){
692 // Fills the Summable digits Tree
694 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
696 pList->GetMaxMapIndex(ni,nj);
697 for(i=0;i<ni;i++)for(j=0;j<nj;j++){
698 if(pList->GetSignalOnly(i,j)>0.0){
699 aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
700 // cout << "pListSPD: " << *(pList->GetpListItem(i,j)) << endl;
701 // cout << " CreateSPDSDigit mod=" << fModule << " r,c=";
702 // cout << i <<","<< j << " sig=" << fpList->GetSignalOnly(i,j);
703 // cout << " noise=" << fpList->GetNoise(i,j) <<endl;
708 //______________________________________________________________________
709 void AliITSsimulationSPD::FillMapFrompList(AliITSpList *pList){
710 // Fills fMap2A from the pList of Summable digits
713 for(iz=0;iz<GetNPixelsZ();iz++)for(ix=0;ix<GetNPixelsX();ix++)
714 fMapA2->AddSignal(iz,ix,pList->GetSignal(iz,ix));