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.15 2002/03/15 17:32:14 nilsen
19 Reintroduced SDigitization, and Digitization from SDigits, along with
20 functions InitSimulationModule, and FinishSDigitizModule.
22 Revision 1.14 2001/11/23 13:04:07 barbera
23 Some protection added in case of high multiplicity
25 Revision 1.13 2001/11/13 11:13:24 barbera
26 A protection against tracks with the same entrance and exit has been made more strict
28 Revision 1.12 2001/10/04 22:44:31 nilsen
29 Major changes in supppor of PreDigits (SDigits). Changes made with will make
30 it easier to suppor expected changes in AliITSHit class. Added use of new
31 class AliITSpList. Both SPD and SDD have added effects of Dead Channels. Both
32 of these will require addtional work as data bases of detectors and the like
41 #include <TParticle.h>
45 #include "AliITShit.h"
46 #include "AliITSdigit.h"
47 #include "AliITSmodule.h"
48 #include "AliITSMapA2.h"
49 #include "AliITSpList.h"
50 #include "AliITSsimulationSPD.h"
51 #include "AliITSsegmentation.h"
52 #include "AliITSresponse.h"
53 #include "AliITSsegmentationSPD.h"
54 #include "AliITSresponseSPD.h"
57 ClassImp(AliITSsimulationSPD)
58 ////////////////////////////////////////////////////////////////////////
60 // Written by Rocco Caliandro
61 // from a model developed with T. Virgili and R.A. Fini
64 // AliITSsimulationSPD is the simulation of SPDs
66 //______________________________________________________________________
67 AliITSsimulationSPD::AliITSsimulationSPD(){
68 // Default constructor
81 //______________________________________________________________________
82 AliITSsimulationSPD::AliITSsimulationSPD(AliITSsegmentation *seg,
83 AliITSresponse *resp) {
84 // Standard constructor
96 Init((AliITSsegmentationSPD*)seg,(AliITSresponseSPD*)resp);
98 //______________________________________________________________________
99 void AliITSsimulationSPD::Init(AliITSsegmentationSPD *seg,
100 AliITSresponseSPD *resp) {
101 // Initilizes the variables of AliITSsimulation SPD.
106 fMapA2 = new AliITSMapA2(fSegmentation);
107 fpList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
109 fResponse->Thresholds(fThresh,fSigma);
110 fResponse->GetNoiseParam(fCouplCol,fCouplRow);
111 fNPixelsZ = fSegmentation->Npz();
112 fNPixelsX = fSegmentation->Npx();
115 //______________________________________________________________________
116 AliITSsimulationSPD::~AliITSsimulationSPD() {
127 //______________________________________________________________________
128 AliITSsimulationSPD::AliITSsimulationSPD(const AliITSsimulationSPD &source){
131 if(&source == this) return;
133 this->fMapA2 = source.fMapA2;
134 this->fHis = source.fHis;
136 this->fThresh = source.fThresh;
137 this->fSigma = source.fSigma;
138 this->fCouplCol = source.fCouplCol;
139 this->fCouplRow = source.fCouplRow;
140 this->fNPixelsX = source.fNPixelsX;
141 this->fNPixelsZ = source.fNPixelsZ;
145 //______________________________________________________________________
146 AliITSsimulationSPD& AliITSsimulationSPD::operator=(const AliITSsimulationSPD
148 // Assignment operator
150 if(&source == this) return *this;
152 this->fMapA2 = source.fMapA2;
153 this->fHis = source.fHis;
155 this->fThresh = source.fThresh;
156 this->fSigma = source.fSigma;
157 this->fCouplCol = source.fCouplCol;
158 this->fCouplRow = source.fCouplRow;
159 this->fNPixelsX = source.fNPixelsX;
160 this->fNPixelsZ = source.fNPixelsZ;
164 //______________________________________________________________________
165 void AliITSsimulationSPD::InitSimulationModule(Int_t module,Int_t event){
166 // Creates maps to build the list of tracks for each sumable digit
168 // Int_t module // Module number to be simulated
169 // Int_t event // Event number to be simulated
180 //______________________________________________________________________
181 void AliITSsimulationSPD::FinishSDigitiseModule(){
182 // Does the Sdigits to Digits work
190 SDigitsToDigits(fModule,fpList);
192 //______________________________________________________________________
193 void AliITSsimulationSPD::SDigitiseModule(AliITSmodule *mod, Int_t dummy0,
195 // Sum digitize module
196 if (!(mod->GetNhits())) return; // if module has no hits then no Sdigits.
197 Int_t number = 10000;
198 Int_t *frowpixel = new Int_t[number];
199 Int_t *fcolpixel = new Int_t[number];
200 Double_t *fenepixel = new Double_t[number];
202 fModule = mod->GetIndex();
204 // Array of pointers to store the track index of the digits
205 // leave +1, otherwise pList crashes when col=256, row=192
207 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
209 WriteSDigits(fpList);
218 //______________________________________________________________________
219 void AliITSsimulationSPD::DigitiseModule(AliITSmodule *mod, Int_t dummy0,
221 // digitize module. Also need to digitize modules with only noise.
223 Int_t number = 10000;
224 Int_t *frowpixel = new Int_t[number];
225 Int_t *fcolpixel = new Int_t[number];
226 Double_t *fenepixel = new Double_t[number];
228 // Array of pointers to store the track index of the digits
229 // leave +1, otherwise pList crashes when col=256, row=192
230 fModule = mod->GetIndex();
232 SetFluctuations(fpList,fModule);
234 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
236 // apply mask to SPD module
239 CreateDigit(fModule,fpList);
248 //______________________________________________________________________
249 void AliITSsimulationSPD::SDigitsToDigits(Int_t module,AliITSpList *pList) {
250 // sum digits to Digits.
251 // cout << "Entering AliITSsimulatinSPD::SDigitsToDigits for module=";
252 // cout << module << endl;
256 SetFluctuations(pList,module);
258 fMapA2->ClearMap(); // since noise is in pList aready. Zero Map so that
259 // noise is not doubled when calling FillMapFrompList.
261 FillMapFrompList(pList);
263 // apply mask to SPD module
266 CreateDigit(module,pList);
271 //______________________________________________________________________
272 void AliITSsimulationSPD::UpdateMapSignal(Int_t row,Int_t col,Int_t trk,
273 Int_t hit,Int_t mod,Double_t ene,
274 AliITSpList *pList) {
275 // updates the Map of signal, adding the energy (ene) released by
278 fMapA2->AddSignal(row,col,ene);
279 pList->AddSignal(row,col,trk,hit,mod,ene);
281 //______________________________________________________________________
282 void AliITSsimulationSPD::UpdateMapNoise(Int_t row,Int_t col,Int_t mod,
283 Double_t ene,AliITSpList *pList) {
284 // updates the Map of noise, adding the energy (ene) give my noise
286 fMapA2->AddSignal(row,col,ene);
287 pList->AddNoise(row,col,mod,ene);
289 //______________________________________________________________________
290 void AliITSsimulationSPD::HitsToAnalogDigits(AliITSmodule *mod,
291 Int_t *frowpixel,Int_t *fcolpixel,
293 AliITSpList *pList) {
294 // Loops over all hits to produce Analog/floting point digits. This
295 // is also the first task in producing standard digits.
297 // loop over hits in the module
298 Int_t hitpos,nhits = mod->GetNhits();
299 for (hitpos=0;hitpos<nhits;hitpos++) {
300 HitToDigit(mod,hitpos,frowpixel,fcolpixel,fenepixel,pList);
301 }// end loop over digits
303 //______________________________________________________________________
304 void AliITSsimulationSPD::HitToDigit(AliITSmodule *mod,Int_t hitpos,
305 Int_t *frowpixel,Int_t *fcolpixel,
306 Double_t *fenepixel,AliITSpList *pList) {
307 // Steering function to determine the digits associated to a given
309 // The digits are created by charge sharing (ChargeSharing) and by
310 // capacitive coupling (SetCoupling). At all the created digits is
311 // associated the track number of the hit (ntrack)
312 Double_t x1l=0.0,y1l=0.0,z1l=0.0,x2l=0.0,y2l=0.0,z2l=0.0;
313 Int_t r1,r2,c1,c2,row,col,npixel = 0;
315 Double_t ene=0.0,etot=0.0;
316 const Float_t kconv = 10000.; // cm -> microns
317 const Float_t kconv1= 0.277e9; // GeV -> electrons equivalent
319 if(!(mod->LineSegmentL(hitpos,x1l,x2l,y1l,y2l,z1l,z2l,etot,ntrack)))return;
321 x2l += x1l; y2l += y1l; z2l += z1l; // Convert to ending coordinate.
322 // positions shifted and converted in microns
323 x1l = x1l*kconv + fSegmentation->Dx()/2.;
324 z1l = z1l*kconv + fSegmentation->Dz()/2.;
325 // positions shifted and converted in microns
326 x2l = x2l*kconv + fSegmentation->Dx()/2.;
327 z2l = z2l*kconv + fSegmentation->Dz()/2.;
328 etot *= kconv1; // convert from GeV to electrons equivalent.
329 Int_t module = mod->GetIndex();
331 // to account for the effective sensitive area
332 // introduced in geometry
333 if (z1l<0 || z1l>fSegmentation->Dz()) return;
334 if (z2l<0 || z2l>fSegmentation->Dz()) return;
335 if (x1l<0 || x1l>fSegmentation->Dx()) return;
336 if (x2l<0 || x2l>fSegmentation->Dx()) return;
338 //Get the col and row number starting from 1
339 // the x direction is not inverted for the second layer!!!
340 fSegmentation->GetPadIxz(x1l, z1l, c1, r1);
341 fSegmentation->GetPadIxz(x2l, z2l, c2, r2);
343 // to account for unexpected equal entrance and
345 if (x1l==x2l) x2l=x2l+x2l*0.1;
346 if (z1l==z2l) z2l=z2l+z2l*0.1;
348 if ((r1==r2) && (c1==c2)){
351 frowpixel[npixel-1] = r1;
352 fcolpixel[npixel-1] = c1;
353 fenepixel[npixel-1] = etot;
356 ChargeSharing(x1l,z1l,x2l,z2l,c1,r1,c2,r2,etot,
357 npixel,frowpixel,fcolpixel,fenepixel);
358 } // end if r1==r2 && c1==c2.
360 for (Int_t npix=0;npix<npixel;npix++){
361 row = frowpixel[npix];
362 col = fcolpixel[npix];
363 ene = fenepixel[npix];
364 UpdateMapSignal(row,col,ntrack,hitpos,module,ene,pList);
365 // Starting capacitive coupling effect
366 SetCoupling(row,col,ntrack,hitpos,module,pList);
369 //______________________________________________________________________
370 void AliITSsimulationSPD::ChargeSharing(Float_t x1l,Float_t z1l,Float_t x2l,
371 Float_t z2l,Int_t c1,Int_t r1,Int_t c2,
372 Int_t r2,Float_t etot,
373 Int_t &npixel,Int_t *frowpixel,
374 Int_t *fcolpixel,Double_t *fenepixel){
375 // Take into account the geometrical charge sharing when the track
376 // crosses more than one pixel.
380 <img src="picts/ITS/barimodel_2.gif">
383 <font size=+2 color=red>
384 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
389 Float_t xa,za,xb,zb,dx,dz,dtot,dm,refr,refm,refc;
391 Float_t arefm, arefr, arefn, arefc, azb, az2l, axb, ax2l;
392 Int_t dirx,dirz,rb,cb;
393 Int_t flag,flagrow,flagcol;
401 dtot = TMath::Sqrt((dx*dx)+(dz*dz));
402 if (dtot==0.0) dtot = 0.01;
403 dirx = (Int_t) TMath::Sign((Float_t)1,dx);
404 dirz = (Int_t) TMath::Sign((Float_t)1,dz);
406 // calculate the x coordinate of the pixel in the next column
407 // and the z coordinate of the pixel in the next row
410 fSegmentation->GetPadCxz(c1, r1-1, xpos, zpos);
412 Float_t xsize = fSegmentation->Dpx(0);
413 Float_t zsize = fSegmentation->Dpz(r1-1);
415 if (dirx == 1) refr = xpos+xsize/2.;
416 else refr = xpos-xsize/2.;
418 if (dirz == 1) refn = zpos+zsize/2.;
419 else refn = zpos-zsize/2.;
425 // calculate the x coordinate of the intersection with the pixel
426 // in the next cell in row direction
428 refm = dx*((refn - z1l)/dz) + x1l;
430 refm = refr+dirx*xsize;
432 // calculate the z coordinate of the intersection with the pixel
433 // in the next cell in column direction
435 refc = dz*((refr - x1l)/dx) + z1l;
437 refc = refn+dirz*zsize;
444 if ((arefm < arefr) && (arefn < arefc)){
445 // the track goes in the pixel in the next cell in row direction
452 if (rb == r2) flagrow=1;
457 // shift to the pixel in the next cell in row direction
458 Float_t zsizeNext = fSegmentation->Dpz(rb-1);
459 //to account for cell at the borders of the detector
460 if(zsizeNext==0) zsizeNext = zsize;
461 refn += zsizeNext*dirz;
463 // the track goes in the pixel in the next cell in column direction
470 if (cb == c2) flagcol=1;
474 } // end ifaxb > ax2l
476 // shift to the pixel in the next cell in column direction
477 Float_t xsizeNext = fSegmentation->Dpx(cb-1);
478 //to account for cell at the borders of the detector
479 if(xsizeNext==0) xsizeNext = xsize;
480 refr += xsizeNext*dirx;
481 } // end if (arefm < arefr) && (arefn < arefc)
483 //calculate the energy lost in the crossed pixel
484 epar = TMath::Sqrt((xb-xa)*(xb-xa)+(zb-za)*(zb-za));
485 epar = etot*(epar/dtot);
487 //store row, column and energy lost in the crossed pixel
488 frowpixel[npixel] = r1;
489 fcolpixel[npixel] = c1;
490 fenepixel[npixel] = epar;
493 // the exit point of the track is reached
494 if (epar == 0) flag = 1;
495 if ((r1 == r2) && (c1 == c2)) flag = 1;
504 //______________________________________________________________________
505 void AliITSsimulationSPD::SetCoupling(Int_t row, Int_t col, Int_t ntrack,
506 Int_t idhit,Int_t module,
507 AliITSpList *pList) {
508 // Take into account the coupling between adiacent pixels.
509 // The parameters probcol and probrow are the fractions of the
510 // signal in one pixel shared in the two adjacent pixels along
511 // the column and row direction, respectively.
515 <img src="picts/ITS/barimodel_3.gif">
518 <font size=+2 color=red>
519 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
525 Double_t pulse1,pulse2;
526 Float_t couplR=0.0,couplC=0.0;
528 GetCouplings(couplR,couplC);
531 pulse1 = fMapA2->GetSignal(row,col);
533 for (Int_t isign=-1;isign<=1;isign+=2){// loop in row direction
537 if ((j1<0) || (j1>GetNPixelsZ()-1) || (pulse1<GetThreshold())){
538 pulse1 = fMapA2->GetSignal(row,col);
542 UpdateMapSignal(j1,col,ntrack,idhit,module,pulse1,pList);
546 // loop in column direction
550 if ((j2<0) || (j2>(GetNPixelsX()-1)) || (pulse2<GetThreshold())){
551 pulse2 = fMapA2->GetSignal(row,col);
555 UpdateMapSignal(row,j2,ntrack,idhit,module,pulse2,pList);
561 //______________________________________________________________________
562 void AliITSsimulationSPD::CreateDigit(Int_t module,AliITSpList *pList) {
563 // The pixels are fired if the energy deposited inside them is above
564 // the threshold parameter ethr. Fired pixed are interpreted as digits
565 // and stored in the file digitfilename. One also needs to write out
566 // cases when there is only noise (nhits==0).
568 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
576 for (Int_t r=1;r<=GetNPixelsZ();r++) {
577 for (Int_t c=1;c<=GetNPixelsX();c++) {
578 // check if the deposited energy in a pixel is above the
580 Float_t signal = (Float_t) fMapA2->GetSignal(r,c);
581 if ( signal > GetThreshold()) {
582 digits[0] = r-1; // digits starts from 0
583 digits[1] = c-1; // digits starts from 0
585 digits[2] = (Int_t) signal; // the signal is stored in
588 tracks[j1] = pList->GetTrack(r,c,j1);
589 hits[j1] = pList->GetHit(r,c,j1);
593 aliITS->AddSimDigit(0,phys,digits,tracks,hits,charges);
594 // cout << " CreateSPDDigit mod=" << fModule << " r,c=" << r;
595 // cout <<","<<c<< " sig=" << fpList->GetSignalOnly(r,c);
596 // cout << " noise=" << fpList->GetNoise(r,c);
597 // cout << " Msig="<< signal << " Thres=" << GetThreshold()<<endl;
598 } // end if of threshold condition
602 //______________________________________________________________________
603 void AliITSsimulationSPD::SetFluctuations(AliITSpList *pList,Int_t module) {
604 // Set the electronic noise and threshold non-uniformities to all the
605 // pixels in a detector.
606 // The parameter fSigma is the squared sum of the sigma due to noise
607 // and the sigma of the threshold distribution among pixels.
611 <img src="picts/ITS/barimodel_1.gif">
614 <font size=+2 color=red>
615 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
620 Float_t thr=0.0,sigm=0.0;
621 Double_t signal,sigma;
624 GetThresholds(thr,sigm);
625 sigma = (Double_t) sigm;
626 for(iz=1;iz<=GetNPixelsZ();iz++){
627 for(ix=1;ix<=GetNPixelsX();ix++){
628 signal = sigma*gRandom->Gaus();
629 fMapA2->SetHit(iz,ix,signal);
630 // insert in the label-signal-hit list the pixels fired
632 pList->AddNoise(iz,ix,module,signal);
633 } // end of loop on pixels
634 } // end of loop on pixels
636 //______________________________________________________________________
637 void AliITSsimulationSPD::SetMask() {
638 // Apply a mask to the SPD module. 1% of the pixel channels are
639 // masked. When the database will be ready, the masked pixels
640 // should be read from it.
644 Float_t perc = ((AliITSresponseSPD*)fResponse)->GetFractionDead();
645 // in this way we get the same set of random numbers for all runs.
646 // This is a cluge for now.
647 static TRandom *rnd = new TRandom();
649 totMask= perc*GetNPixelsZ()*GetNPixelsX();
650 for(im=1;im<totMask;im++){
652 ix=(Int_t)(rnd->Rndm()*(GetNPixelsX()-1.) + 1.);
653 } while(ix<=0 || ix>GetNPixelsX());
655 iz=(Int_t)(rnd->Rndm()*(GetNPixelsZ()-1.) + 1.);
656 } while(iz<=0 || iz>GetNPixelsZ());
658 fMapA2->SetHit(iz,ix,signal);
659 } // end loop on masked pixels
661 //______________________________________________________________________
662 void AliITSsimulationSPD::CreateHistograms() {
666 fHis=new TObjArray(GetNPixelsZ());
667 for(i=0;i<GetNPixelsZ();i++) {
668 TString spdname("spd_");
670 sprintf(candnum,"%d",i+1);
671 spdname.Append(candnum);
672 (*fHis)[i] = new TH1F(spdname.Data(),"SPD maps",
673 GetNPixelsX(),0.,(Float_t) GetNPixelsX());
676 //______________________________________________________________________
677 void AliITSsimulationSPD::ResetHistograms() {
678 // Reset histograms for this detector
681 for(i=0;i<GetNPixelsZ();i++ ) {
682 if ((*fHis)[i]) ((TH1F*)(*fHis)[i])->Reset();
685 //______________________________________________________________________
686 void AliITSsimulationSPD::WriteSDigits(AliITSpList *pList){
687 // Fills the Summable digits Tree
689 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
691 pList->GetMaxMapIndex(ni,nj);
692 for(i=0;i<ni;i++)for(j=0;j<nj;j++){
693 if(pList->GetSignalOnly(i,j)>0.0){
694 aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
695 // cout << "pListSPD: " << *(pList->GetpListItem(i,j)) << endl;
696 // cout << " CreateSPDSDigit mod=" << fModule << " r,c=";
697 // cout << i <<","<< j << " sig=" << fpList->GetSignalOnly(i,j);
698 // cout << " noise=" << fpList->GetNoise(i,j) <<endl;
703 //______________________________________________________________________
704 void AliITSsimulationSPD::FillMapFrompList(AliITSpList *pList){
705 // Fills fMap2A from the pList of Summable digits
708 for(iz=0;iz<GetNPixelsZ();iz++)for(ix=0;ix<GetNPixelsX();ix++)
709 fMapA2->AddSignal(iz,ix,pList->GetSignal(iz,ix));