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.18 2002/08/21 22:11:13 nilsen
19 Debug output now settable via a DEBUG flag.
21 Revision 1.17 2002/07/16 17:00:17 barbera
22 Fixes added to make the slow simulation running with the current HEAD (from M. Masera)
24 Revision 1.16 2002/06/19 16:02:22 hristov
25 Division by zero corrected
27 Revision 1.15 2002/03/15 17:32:14 nilsen
28 Reintroduced SDigitization, and Digitization from SDigits, along with
29 functions InitSimulationModule, and FinishSDigitizModule.
31 Revision 1.14 2001/11/23 13:04:07 barbera
32 Some protection added in case of high multiplicity
34 Revision 1.13 2001/11/13 11:13:24 barbera
35 A protection against tracks with the same entrance and exit has been made more strict
37 Revision 1.12 2001/10/04 22:44:31 nilsen
38 Major changes in supppor of PreDigits (SDigits). Changes made with will make
39 it easier to suppor expected changes in AliITSHit class. Added use of new
40 class AliITSpList. Both SPD and SDD have added effects of Dead Channels. Both
41 of these will require addtional work as data bases of detectors and the like
50 #include <TParticle.h>
54 #include "AliITShit.h"
55 #include "AliITSdigit.h"
56 #include "AliITSmodule.h"
57 #include "AliITSMapA2.h"
58 #include "AliITSpList.h"
59 #include "AliITSsimulationSPD.h"
60 #include "AliITSsegmentation.h"
61 #include "AliITSresponse.h"
62 #include "AliITSsegmentationSPD.h"
63 #include "AliITSresponseSPD.h"
67 ClassImp(AliITSsimulationSPD)
68 ////////////////////////////////////////////////////////////////////////
70 // Written by Rocco Caliandro
71 // from a model developed with T. Virgili and R.A. Fini
74 // AliITSsimulationSPD is the simulation of SPDs
76 //______________________________________________________________________
77 AliITSsimulationSPD::AliITSsimulationSPD(){
78 // Default constructor
91 //______________________________________________________________________
92 AliITSsimulationSPD::AliITSsimulationSPD(AliITSsegmentation *seg,
93 AliITSresponse *resp) {
94 // Standard constructor
106 Init((AliITSsegmentationSPD*)seg,(AliITSresponseSPD*)resp);
108 //______________________________________________________________________
109 void AliITSsimulationSPD::Init(AliITSsegmentationSPD *seg,
110 AliITSresponseSPD *resp) {
111 // Initilizes the variables of AliITSsimulation SPD.
116 fMapA2 = new AliITSMapA2(fSegmentation);
117 fpList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
119 fResponse->Thresholds(fThresh,fSigma);
120 fResponse->GetNoiseParam(fCouplCol,fCouplRow);
121 fNPixelsZ = fSegmentation->Npz();
122 fNPixelsX = fSegmentation->Npx();
125 //______________________________________________________________________
126 AliITSsimulationSPD::~AliITSsimulationSPD() {
137 //______________________________________________________________________
138 AliITSsimulationSPD::AliITSsimulationSPD(const AliITSsimulationSPD &source){
141 if(&source == this) return;
143 this->fMapA2 = source.fMapA2;
144 this->fHis = source.fHis;
146 this->fThresh = source.fThresh;
147 this->fSigma = source.fSigma;
148 this->fCouplCol = source.fCouplCol;
149 this->fCouplRow = source.fCouplRow;
150 this->fNPixelsX = source.fNPixelsX;
151 this->fNPixelsZ = source.fNPixelsZ;
155 //______________________________________________________________________
156 AliITSsimulationSPD& AliITSsimulationSPD::operator=(const AliITSsimulationSPD
158 // Assignment operator
160 if(&source == this) return *this;
162 this->fMapA2 = source.fMapA2;
163 this->fHis = source.fHis;
165 this->fThresh = source.fThresh;
166 this->fSigma = source.fSigma;
167 this->fCouplCol = source.fCouplCol;
168 this->fCouplRow = source.fCouplRow;
169 this->fNPixelsX = source.fNPixelsX;
170 this->fNPixelsZ = source.fNPixelsZ;
174 //______________________________________________________________________
175 void AliITSsimulationSPD::InitSimulationModule(Int_t module,Int_t event){
176 // Creates maps to build the list of tracks for each sumable digit
178 // Int_t module // Module number to be simulated
179 // Int_t event // Event number to be simulated
190 //______________________________________________________________________
191 void AliITSsimulationSPD::FinishSDigitiseModule(){
192 // Does the Sdigits to Digits work
200 SDigitsToDigits(fModule,fpList);
202 //______________________________________________________________________
203 void AliITSsimulationSPD::SDigitiseModule(AliITSmodule *mod, Int_t dummy0,
205 // Sum digitize module
206 if (!(mod->GetNhits())) return; // if module has no hits then no Sdigits.
207 Int_t number = 10000;
208 Int_t *frowpixel = new Int_t[number];
209 Int_t *fcolpixel = new Int_t[number];
210 Double_t *fenepixel = new Double_t[number];
212 fModule = mod->GetIndex();
214 // Array of pointers to store the track index of the digits
215 // leave +1, otherwise pList crashes when col=256, row=192
217 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
219 WriteSDigits(fpList);
228 //______________________________________________________________________
229 void AliITSsimulationSPD::DigitiseModule(AliITSmodule *mod, Int_t dummy0,
231 // digitize module. Also need to digitize modules with only noise.
233 Int_t number = 10000;
234 Int_t *frowpixel = new Int_t[number];
235 Int_t *fcolpixel = new Int_t[number];
236 Double_t *fenepixel = new Double_t[number];
238 // Array of pointers to store the track index of the digits
239 // leave +1, otherwise pList crashes when col=256, row=192
240 fModule = mod->GetIndex();
242 SetFluctuations(fpList,fModule);
244 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
246 // apply mask to SPD module
249 CreateDigit(fModule,fpList);
258 //______________________________________________________________________
259 void AliITSsimulationSPD::SDigitsToDigits(Int_t module,AliITSpList *pList) {
260 // sum digits to Digits.
263 cout << "Entering AliITSsimulatinSPD::SDigitsToDigits for module=";
264 cout << module << endl;
269 SetFluctuations(pList,module);
271 fMapA2->ClearMap(); // since noise is in pList aready. Zero Map so that
272 // noise is not doubled when calling FillMapFrompList.
274 FillMapFrompList(pList);
276 // apply mask to SPD module
279 CreateDigit(module,pList);
284 //______________________________________________________________________
285 void AliITSsimulationSPD::UpdateMapSignal(Int_t row,Int_t col,Int_t trk,
286 Int_t hit,Int_t mod,Double_t ene,
287 AliITSpList *pList) {
288 // updates the Map of signal, adding the energy (ene) released by
291 fMapA2->AddSignal(row,col,ene);
292 pList->AddSignal(row,col,trk,hit,mod,ene);
294 //______________________________________________________________________
295 void AliITSsimulationSPD::UpdateMapNoise(Int_t row,Int_t col,Int_t mod,
296 Double_t ene,AliITSpList *pList) {
297 // updates the Map of noise, adding the energy (ene) give my noise
299 fMapA2->AddSignal(row,col,ene);
300 pList->AddNoise(row,col,mod,ene);
302 //______________________________________________________________________
303 void AliITSsimulationSPD::HitsToAnalogDigits(AliITSmodule *mod,
304 Int_t *frowpixel,Int_t *fcolpixel,
306 AliITSpList *pList) {
307 // Loops over all hits to produce Analog/floting point digits. This
308 // is also the first task in producing standard digits.
310 // loop over hits in the module
311 Int_t hitpos,nhits = mod->GetNhits();
312 for (hitpos=0;hitpos<nhits;hitpos++) {
313 HitToDigit(mod,hitpos,frowpixel,fcolpixel,fenepixel,pList);
314 }// end loop over digits
316 //______________________________________________________________________
317 void AliITSsimulationSPD::HitToDigit(AliITSmodule *mod,Int_t hitpos,
318 Int_t *frowpixel,Int_t *fcolpixel,
319 Double_t *fenepixel,AliITSpList *pList) {
320 // Steering function to determine the digits associated to a given
322 // The digits are created by charge sharing (ChargeSharing) and by
323 // capacitive coupling (SetCoupling). At all the created digits is
324 // associated the track number of the hit (ntrack)
325 Double_t x1l=0.0,y1l=0.0,z1l=0.0,x2l=0.0,y2l=0.0,z2l=0.0;
326 Int_t r1,r2,c1,c2,row,col,npixel = 0;
328 Double_t ene=0.0,etot=0.0;
329 const Float_t kconv = 10000.; // cm -> microns
330 const Float_t kconv1= 0.277e9; // GeV -> electrons equivalent
332 if(!(mod->LineSegmentL(hitpos,x1l,x2l,y1l,y2l,z1l,z2l,etot,ntrack)))return;
334 x2l += x1l; y2l += y1l; z2l += z1l; // Convert to ending coordinate.
335 // positions shifted and converted in microns
336 x1l = x1l*kconv + fSegmentation->Dx()/2.;
337 z1l = z1l*kconv + fSegmentation->Dz()/2.;
338 // positions shifted and converted in microns
339 x2l = x2l*kconv + fSegmentation->Dx()/2.;
340 z2l = z2l*kconv + fSegmentation->Dz()/2.;
341 etot *= kconv1; // convert from GeV to electrons equivalent.
342 Int_t module = mod->GetIndex();
344 // to account for the effective sensitive area
345 // introduced in geometry
346 if (z1l<0 || z1l>fSegmentation->Dz()) return;
347 if (z2l<0 || z2l>fSegmentation->Dz()) return;
348 if (x1l<0 || x1l>fSegmentation->Dx()) return;
349 if (x2l<0 || x2l>fSegmentation->Dx()) return;
351 //Get the col and row number starting from 1
352 // the x direction is not inverted for the second layer!!!
353 fSegmentation->GetPadIxz(x1l, z1l, c1, r1);
354 fSegmentation->GetPadIxz(x2l, z2l, c2, r2);
356 // to account for unexpected equal entrance and
358 if (x1l==x2l) x2l=x2l+x2l*0.1;
359 if (z1l==z2l) z2l=z2l+z2l*0.1;
361 if ((r1==r2) && (c1==c2)){
364 frowpixel[npixel-1] = r1;
365 fcolpixel[npixel-1] = c1;
366 fenepixel[npixel-1] = etot;
369 ChargeSharing(x1l,z1l,x2l,z2l,c1,r1,c2,r2,etot,
370 npixel,frowpixel,fcolpixel,fenepixel);
371 } // end if r1==r2 && c1==c2.
373 for (Int_t npix=0;npix<npixel;npix++){
374 row = frowpixel[npix];
375 col = fcolpixel[npix];
376 ene = fenepixel[npix];
377 UpdateMapSignal(row,col,ntrack,hitpos,module,ene,pList);
378 // Starting capacitive coupling effect
379 SetCoupling(row,col,ntrack,hitpos,module,pList);
382 //______________________________________________________________________
383 void AliITSsimulationSPD::ChargeSharing(Float_t x1l,Float_t z1l,Float_t x2l,
384 Float_t z2l,Int_t c1,Int_t r1,Int_t c2,
385 Int_t r2,Float_t etot,
386 Int_t &npixel,Int_t *frowpixel,
387 Int_t *fcolpixel,Double_t *fenepixel){
388 // Take into account the geometrical charge sharing when the track
389 // crosses more than one pixel.
393 <img src="picts/ITS/barimodel_2.gif">
396 <font size=+2 color=red>
397 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
403 Float_t xa,za,xb,zb,dx,dz,dtot,refr,refm,refc;
405 Float_t arefm, arefr, arefn, arefc, azb, az2l, axb, ax2l;
406 Int_t dirx,dirz,rb,cb;
407 Int_t flag,flagrow,flagcol;
417 dtot = TMath::Sqrt((dx*dx)+(dz*dz));
418 if (dtot==0.0) dtot = 0.01;
419 dirx = (Int_t) TMath::Sign((Float_t)1,dx);
420 dirz = (Int_t) TMath::Sign((Float_t)1,dz);
422 // calculate the x coordinate of the pixel in the next column
423 // and the z coordinate of the pixel in the next row
426 fSegmentation->GetPadCxz(c1, r1-1, xpos, zpos);
428 Float_t xsize = fSegmentation->Dpx(0);
429 Float_t zsize = fSegmentation->Dpz(r1-1);
431 if (dirx == 1) refr = xpos+xsize/2.;
432 else refr = xpos-xsize/2.;
434 if (dirz == 1) refn = zpos+zsize/2.;
435 else refn = zpos-zsize/2.;
441 // calculate the x coordinate of the intersection with the pixel
442 // in the next cell in row direction
444 refm = dx*((refn - z1l)/dz) + x1l;
446 refm = refr+dirx*xsize;
448 // calculate the z coordinate of the intersection with the pixel
449 // in the next cell in column direction
451 refc = dz*((refr - x1l)/dx) + z1l;
453 refc = refn+dirz*zsize;
460 if ((arefm < arefr) && (arefn < arefc)){
461 // the track goes in the pixel in the next cell in row direction
468 if (rb == r2) flagrow=1;
473 // shift to the pixel in the next cell in row direction
474 Float_t zsizeNext = fSegmentation->Dpz(rb-1);
475 //to account for cell at the borders of the detector
476 if(zsizeNext==0) zsizeNext = zsize;
477 refn += zsizeNext*dirz;
479 // the track goes in the pixel in the next cell in column direction
486 if (cb == c2) flagcol=1;
490 } // end ifaxb > ax2l
492 // shift to the pixel in the next cell in column direction
493 Float_t xsizeNext = fSegmentation->Dpx(cb-1);
494 //to account for cell at the borders of the detector
495 if(xsizeNext==0) xsizeNext = xsize;
496 refr += xsizeNext*dirx;
497 } // end if (arefm < arefr) && (arefn < arefc)
499 //calculate the energy lost in the crossed pixel
500 epar = TMath::Sqrt((xb-xa)*(xb-xa)+(zb-za)*(zb-za));
501 epar = etot*(epar/dtot);
503 //store row, column and energy lost in the crossed pixel
504 frowpixel[npixel] = r1;
505 fcolpixel[npixel] = c1;
506 fenepixel[npixel] = epar;
509 // the exit point of the track is reached
510 if (epar == 0) flag = 1;
511 if ((r1 == r2) && (c1 == c2)) flag = 1;
520 //______________________________________________________________________
521 void AliITSsimulationSPD::SetCoupling(Int_t row, Int_t col, Int_t ntrack,
522 Int_t idhit,Int_t module,
523 AliITSpList *pList) {
524 // Take into account the coupling between adiacent pixels.
525 // The parameters probcol and probrow are the fractions of the
526 // signal in one pixel shared in the two adjacent pixels along
527 // the column and row direction, respectively.
531 <img src="picts/ITS/barimodel_3.gif">
534 <font size=+2 color=red>
535 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
541 Double_t pulse1,pulse2;
542 Float_t couplR=0.0,couplC=0.0;
544 GetCouplings(couplR,couplC);
547 pulse1 = fMapA2->GetSignal(row,col);
549 for (Int_t isign=-1;isign<=1;isign+=2){// loop in row direction
553 if ((j1<0) || (j1>GetNPixelsZ()-1) || (pulse1<GetThreshold())){
554 pulse1 = fMapA2->GetSignal(row,col);
558 UpdateMapSignal(j1,col,ntrack,idhit,module,pulse1,pList);
562 // loop in column direction
566 if ((j2<0) || (j2>(GetNPixelsX()-1)) || (pulse2<GetThreshold())){
567 pulse2 = fMapA2->GetSignal(row,col);
571 UpdateMapSignal(row,j2,ntrack,idhit,module,pulse2,pList);
577 //______________________________________________________________________
578 void AliITSsimulationSPD::CreateDigit(Int_t module,AliITSpList *pList) {
579 // The pixels are fired if the energy deposited inside them is above
580 // the threshold parameter ethr. Fired pixed are interpreted as digits
581 // and stored in the file digitfilename. One also needs to write out
582 // cases when there is only noise (nhits==0).
584 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
586 Int_t size = AliITSdigitSPD::GetNTracks();
590 Float_t charges[size];
593 for (Int_t r=1;r<=GetNPixelsZ();r++) {
594 for (Int_t c=1;c<=GetNPixelsX();c++) {
595 // check if the deposited energy in a pixel is above the
597 Float_t signal = (Float_t) fMapA2->GetSignal(r,c);
598 if ( signal > GetThreshold()) {
599 digits[0] = r-1; // digits starts from 0
600 digits[1] = c-1; // digits starts from 0
602 digits[2] = (Int_t) signal; // the signal is stored in
604 for(j1=0;j1<size;j1++){
605 if(j1<pList->GetNEnteries()){
606 tracks[j1] = pList->GetTrack(r,c,j1);
607 hits[j1] = pList->GetHit(r,c,j1);
615 aliITS->AddSimDigit(0,phys,digits,tracks,hits,charges);
617 cout << " CreateSPDDigit mod=" << fModule << " r,c=" << r;
618 cout <<","<<c<< " sig=" << fpList->GetSignalOnly(r,c);
619 cout << " noise=" << fpList->GetNoise(r,c);
620 cout << " Msig="<< signal << " Thres=" << GetThreshold()<<endl;
622 } // end if of threshold condition
626 //______________________________________________________________________
627 void AliITSsimulationSPD::SetFluctuations(AliITSpList *pList,Int_t module) {
628 // Set the electronic noise and threshold non-uniformities to all the
629 // pixels in a detector.
630 // The parameter fSigma is the squared sum of the sigma due to noise
631 // and the sigma of the threshold distribution among pixels.
635 <img src="picts/ITS/barimodel_1.gif">
638 <font size=+2 color=red>
639 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
644 Float_t thr=0.0,sigm=0.0;
645 Double_t signal,sigma;
648 GetThresholds(thr,sigm);
649 sigma = (Double_t) sigm;
650 for(iz=1;iz<=GetNPixelsZ();iz++){
651 for(ix=1;ix<=GetNPixelsX();ix++){
652 signal = sigma*gRandom->Gaus();
653 fMapA2->SetHit(iz,ix,signal);
654 // insert in the label-signal-hit list the pixels fired
656 pList->AddNoise(iz,ix,module,signal);
657 } // end of loop on pixels
658 } // end of loop on pixels
660 //______________________________________________________________________
661 void AliITSsimulationSPD::SetMask() {
662 // Apply a mask to the SPD module. 1% of the pixel channels are
663 // masked. When the database will be ready, the masked pixels
664 // should be read from it.
668 Float_t perc = ((AliITSresponseSPD*)fResponse)->GetFractionDead();
669 // in this way we get the same set of random numbers for all runs.
670 // This is a cluge for now.
671 static TRandom *rnd = new TRandom();
673 totMask= perc*GetNPixelsZ()*GetNPixelsX();
674 for(im=1;im<totMask;im++){
676 ix=(Int_t)(rnd->Rndm()*(GetNPixelsX()-1.) + 1.);
677 } while(ix<=0 || ix>GetNPixelsX());
679 iz=(Int_t)(rnd->Rndm()*(GetNPixelsZ()-1.) + 1.);
680 } while(iz<=0 || iz>GetNPixelsZ());
682 fMapA2->SetHit(iz,ix,signal);
683 } // end loop on masked pixels
685 //______________________________________________________________________
686 void AliITSsimulationSPD::CreateHistograms() {
690 fHis=new TObjArray(GetNPixelsZ());
691 for(i=0;i<GetNPixelsZ();i++) {
692 TString spdname("spd_");
694 sprintf(candnum,"%d",i+1);
695 spdname.Append(candnum);
696 (*fHis)[i] = new TH1F(spdname.Data(),"SPD maps",
697 GetNPixelsX(),0.,(Float_t) GetNPixelsX());
700 //______________________________________________________________________
701 void AliITSsimulationSPD::ResetHistograms() {
702 // Reset histograms for this detector
705 for(i=0;i<GetNPixelsZ();i++ ) {
706 if ((*fHis)[i]) ((TH1F*)(*fHis)[i])->Reset();
709 //______________________________________________________________________
710 void AliITSsimulationSPD::WriteSDigits(AliITSpList *pList){
711 // Fills the Summable digits Tree
713 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
715 pList->GetMaxMapIndex(ni,nj);
716 for(i=0;i<ni;i++)for(j=0;j<nj;j++){
717 if(pList->GetSignalOnly(i,j)>0.0){
718 aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
720 cout << "pListSPD: " << *(pList->GetpListItem(i,j)) << endl;
721 cout << " CreateSPDSDigit mod=" << fModule << " r,c=";
722 cout << i <<","<< j << " sig=" << fpList->GetSignalOnly(i,j);
723 cout << " noise=" << fpList->GetNoise(i,j) <<endl;
729 //______________________________________________________________________
730 void AliITSsimulationSPD::FillMapFrompList(AliITSpList *pList){
731 // Fills fMap2A from the pList of Summable digits
734 for(iz=0;iz<GetNPixelsZ();iz++)for(ix=0;ix<GetNPixelsX();ix++)
735 fMapA2->AddSignal(iz,ix,pList->GetSignal(iz,ix));