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.21 2002/10/14 14:57:08 hristov
19 Merging the VirtualMC branch to the main development branch (HEAD)
21 Revision 1.15.4.3 2002/10/14 13:14:08 hristov
22 Updating VirtualMC to v3-09-02
24 Revision 1.20 2002/09/11 10:32:41 hristov
25 Use new for arrays with variable size
27 Revision 1.19 2002/09/09 17:23:28 nilsen
28 Minor changes in support of changes to AliITSdigitS?D class'.
30 Revision 1.18 2002/08/21 22:11:13 nilsen
31 Debug output now settable via a DEBUG flag.
33 Revision 1.17 2002/07/16 17:00:17 barbera
34 Fixes added to make the slow simulation running with the current HEAD (from M. Masera)
36 Revision 1.16 2002/06/19 16:02:22 hristov
37 Division by zero corrected
39 Revision 1.15 2002/03/15 17:32:14 nilsen
40 Reintroduced SDigitization, and Digitization from SDigits, along with
41 functions InitSimulationModule, and FinishSDigitizModule.
43 Revision 1.14 2001/11/23 13:04:07 barbera
44 Some protection added in case of high multiplicity
46 Revision 1.13 2001/11/13 11:13:24 barbera
47 A protection against tracks with the same entrance and exit has been made more strict
49 Revision 1.12 2001/10/04 22:44:31 nilsen
50 Major changes in supppor of PreDigits (SDigits). Changes made with will make
51 it easier to suppor expected changes in AliITSHit class. Added use of new
52 class AliITSpList. Both SPD and SDD have added effects of Dead Channels. Both
53 of these will require addtional work as data bases of detectors and the like
57 #include <Riostream.h>
62 #include <TParticle.h>
66 #include "AliITShit.h"
67 #include "AliITSdigit.h"
68 #include "AliITSmodule.h"
69 #include "AliITSMapA2.h"
70 #include "AliITSpList.h"
71 #include "AliITSsimulationSPD.h"
72 #include "AliITSsegmentation.h"
73 #include "AliITSresponse.h"
74 #include "AliITSsegmentationSPD.h"
75 #include "AliITSresponseSPD.h"
79 ClassImp(AliITSsimulationSPD)
80 ////////////////////////////////////////////////////////////////////////
82 // Written by Rocco Caliandro
83 // from a model developed with T. Virgili and R.A. Fini
86 // AliITSsimulationSPD is the simulation of SPDs
88 //______________________________________________________________________
89 AliITSsimulationSPD::AliITSsimulationSPD(){
90 // Default constructor
103 //______________________________________________________________________
104 AliITSsimulationSPD::AliITSsimulationSPD(AliITSsegmentation *seg,
105 AliITSresponse *resp) {
106 // Standard constructor
118 Init((AliITSsegmentationSPD*)seg,(AliITSresponseSPD*)resp);
120 //______________________________________________________________________
121 void AliITSsimulationSPD::Init(AliITSsegmentationSPD *seg,
122 AliITSresponseSPD *resp) {
123 // Initilizes the variables of AliITSsimulation SPD.
128 fMapA2 = new AliITSMapA2(fSegmentation);
129 fpList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
131 fResponse->Thresholds(fThresh,fSigma);
132 fResponse->GetNoiseParam(fCouplCol,fCouplRow);
133 fNPixelsZ = fSegmentation->Npz();
134 fNPixelsX = fSegmentation->Npx();
137 //______________________________________________________________________
138 AliITSsimulationSPD::~AliITSsimulationSPD() {
149 //______________________________________________________________________
150 AliITSsimulationSPD::AliITSsimulationSPD(const AliITSsimulationSPD &source){
153 if(&source == this) return;
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 AliITSsimulationSPD& AliITSsimulationSPD::operator=(const AliITSsimulationSPD
170 // Assignment operator
172 if(&source == this) return *this;
174 this->fMapA2 = source.fMapA2;
175 this->fHis = source.fHis;
177 this->fThresh = source.fThresh;
178 this->fSigma = source.fSigma;
179 this->fCouplCol = source.fCouplCol;
180 this->fCouplRow = source.fCouplRow;
181 this->fNPixelsX = source.fNPixelsX;
182 this->fNPixelsZ = source.fNPixelsZ;
186 //______________________________________________________________________
187 void AliITSsimulationSPD::InitSimulationModule(Int_t module,Int_t event){
188 // Creates maps to build the list of tracks for each sumable digit
190 // Int_t module // Module number to be simulated
191 // Int_t event // Event number to be simulated
202 //______________________________________________________________________
203 void AliITSsimulationSPD::FinishSDigitiseModule(){
204 // Does the Sdigits to Digits work
212 SDigitsToDigits(fModule,fpList);
214 //______________________________________________________________________
215 void AliITSsimulationSPD::SDigitiseModule(AliITSmodule *mod, Int_t dummy0,
217 // Sum digitize module
218 if (!(mod->GetNhits())) return; // if module has no hits then no Sdigits.
219 Int_t number = 10000;
220 Int_t *frowpixel = new Int_t[number];
221 Int_t *fcolpixel = new Int_t[number];
222 Double_t *fenepixel = new Double_t[number];
224 fModule = mod->GetIndex();
226 // Array of pointers to store the track index of the digits
227 // leave +1, otherwise pList crashes when col=256, row=192
229 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
231 WriteSDigits(fpList);
240 //______________________________________________________________________
241 void AliITSsimulationSPD::DigitiseModule(AliITSmodule *mod, Int_t dummy0,
243 // digitize module. Also need to digitize modules with only noise.
245 Int_t number = 10000;
246 Int_t *frowpixel = new Int_t[number];
247 Int_t *fcolpixel = new Int_t[number];
248 Double_t *fenepixel = new Double_t[number];
250 // Array of pointers to store the track index of the digits
251 // leave +1, otherwise pList crashes when col=256, row=192
252 fModule = mod->GetIndex();
254 SetFluctuations(fpList,fModule);
256 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
258 // apply mask to SPD module
261 CreateDigit(fModule,fpList);
270 //______________________________________________________________________
271 void AliITSsimulationSPD::SDigitsToDigits(Int_t module,AliITSpList *pList) {
272 // sum digits to Digits.
275 cout << "Entering AliITSsimulatinSPD::SDigitsToDigits for module=";
276 cout << module << endl;
281 SetFluctuations(pList,module);
283 fMapA2->ClearMap(); // since noise is in pList aready. Zero Map so that
284 // noise is not doubled when calling FillMapFrompList.
286 FillMapFrompList(pList);
288 // apply mask to SPD module
291 CreateDigit(module,pList);
296 //______________________________________________________________________
297 void AliITSsimulationSPD::UpdateMapSignal(Int_t row,Int_t col,Int_t trk,
298 Int_t hit,Int_t mod,Double_t ene,
299 AliITSpList *pList) {
300 // updates the Map of signal, adding the energy (ene) released by
303 fMapA2->AddSignal(row,col,ene);
304 pList->AddSignal(row,col,trk,hit,mod,ene);
306 //______________________________________________________________________
307 void AliITSsimulationSPD::UpdateMapNoise(Int_t row,Int_t col,Int_t mod,
308 Double_t ene,AliITSpList *pList) {
309 // updates the Map of noise, adding the energy (ene) give my noise
311 fMapA2->AddSignal(row,col,ene);
312 pList->AddNoise(row,col,mod,ene);
314 //______________________________________________________________________
315 void AliITSsimulationSPD::HitsToAnalogDigits(AliITSmodule *mod,
316 Int_t *frowpixel,Int_t *fcolpixel,
318 AliITSpList *pList) {
319 // Loops over all hits to produce Analog/floting point digits. This
320 // is also the first task in producing standard digits.
322 // loop over hits in the module
323 Int_t hitpos,nhits = mod->GetNhits();
324 for (hitpos=0;hitpos<nhits;hitpos++) {
325 HitToDigit(mod,hitpos,frowpixel,fcolpixel,fenepixel,pList);
326 }// end loop over digits
328 //______________________________________________________________________
329 void AliITSsimulationSPD::HitToDigit(AliITSmodule *mod,Int_t hitpos,
330 Int_t *frowpixel,Int_t *fcolpixel,
331 Double_t *fenepixel,AliITSpList *pList) {
332 // Steering function to determine the digits associated to a given
334 // The digits are created by charge sharing (ChargeSharing) and by
335 // capacitive coupling (SetCoupling). At all the created digits is
336 // associated the track number of the hit (ntrack)
337 Double_t x1l=0.0,y1l=0.0,z1l=0.0,x2l=0.0,y2l=0.0,z2l=0.0;
338 Int_t r1,r2,c1,c2,row,col,npixel = 0;
340 Double_t ene=0.0,etot=0.0;
341 const Float_t kconv = 10000.; // cm -> microns
342 const Float_t kconv1= 0.277e9; // GeV -> electrons equivalent
344 if(!(mod->LineSegmentL(hitpos,x1l,x2l,y1l,y2l,z1l,z2l,etot,ntrack)))return;
346 x2l += x1l; y2l += y1l; z2l += z1l; // Convert to ending coordinate.
347 // positions shifted and converted in microns
348 x1l = x1l*kconv + fSegmentation->Dx()/2.;
349 z1l = z1l*kconv + fSegmentation->Dz()/2.;
350 // positions shifted and converted in microns
351 x2l = x2l*kconv + fSegmentation->Dx()/2.;
352 z2l = z2l*kconv + fSegmentation->Dz()/2.;
353 etot *= kconv1; // convert from GeV to electrons equivalent.
354 Int_t module = mod->GetIndex();
356 // to account for the effective sensitive area
357 // introduced in geometry
358 if (z1l<0 || z1l>fSegmentation->Dz()) return;
359 if (z2l<0 || z2l>fSegmentation->Dz()) return;
360 if (x1l<0 || x1l>fSegmentation->Dx()) return;
361 if (x2l<0 || x2l>fSegmentation->Dx()) return;
363 //Get the col and row number starting from 1
364 // the x direction is not inverted for the second layer!!!
365 fSegmentation->GetPadIxz(x1l, z1l, c1, r1);
366 fSegmentation->GetPadIxz(x2l, z2l, c2, r2);
368 // to account for unexpected equal entrance and
370 if (x1l==x2l) x2l=x2l+x2l*0.1;
371 if (z1l==z2l) z2l=z2l+z2l*0.1;
373 if ((r1==r2) && (c1==c2)){
376 frowpixel[npixel-1] = r1;
377 fcolpixel[npixel-1] = c1;
378 fenepixel[npixel-1] = etot;
381 ChargeSharing(x1l,z1l,x2l,z2l,c1,r1,c2,r2,etot,
382 npixel,frowpixel,fcolpixel,fenepixel);
383 } // end if r1==r2 && c1==c2.
385 for (Int_t npix=0;npix<npixel;npix++){
386 row = frowpixel[npix];
387 col = fcolpixel[npix];
388 ene = fenepixel[npix];
389 UpdateMapSignal(row,col,ntrack,hitpos,module,ene,pList);
390 // Starting capacitive coupling effect
391 SetCoupling(row,col,ntrack,hitpos,module,pList);
394 //______________________________________________________________________
395 void AliITSsimulationSPD::ChargeSharing(Float_t x1l,Float_t z1l,Float_t x2l,
396 Float_t z2l,Int_t c1,Int_t r1,Int_t c2,
397 Int_t r2,Float_t etot,
398 Int_t &npixel,Int_t *frowpixel,
399 Int_t *fcolpixel,Double_t *fenepixel){
400 // Take into account the geometrical charge sharing when the track
401 // crosses more than one pixel.
405 <img src="picts/ITS/barimodel_2.gif">
408 <font size=+2 color=red>
409 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
415 Float_t xa,za,xb,zb,dx,dz,dtot,refr,refm,refc;
417 Float_t arefm, arefr, arefn, arefc, azb, az2l, axb, ax2l;
418 Int_t dirx,dirz,rb,cb;
419 Int_t flag,flagrow,flagcol;
429 dtot = TMath::Sqrt((dx*dx)+(dz*dz));
430 if (dtot==0.0) dtot = 0.01;
431 dirx = (Int_t) TMath::Sign((Float_t)1,dx);
432 dirz = (Int_t) TMath::Sign((Float_t)1,dz);
434 // calculate the x coordinate of the pixel in the next column
435 // and the z coordinate of the pixel in the next row
438 fSegmentation->GetPadCxz(c1, r1-1, xpos, zpos);
440 Float_t xsize = fSegmentation->Dpx(0);
441 Float_t zsize = fSegmentation->Dpz(r1-1);
443 if (dirx == 1) refr = xpos+xsize/2.;
444 else refr = xpos-xsize/2.;
446 if (dirz == 1) refn = zpos+zsize/2.;
447 else refn = zpos-zsize/2.;
453 // calculate the x coordinate of the intersection with the pixel
454 // in the next cell in row direction
456 refm = dx*((refn - z1l)/dz) + x1l;
458 refm = refr+dirx*xsize;
460 // calculate the z coordinate of the intersection with the pixel
461 // in the next cell in column direction
463 refc = dz*((refr - x1l)/dx) + z1l;
465 refc = refn+dirz*zsize;
472 if ((arefm < arefr) && (arefn < arefc)){
473 // the track goes in the pixel in the next cell in row direction
480 if (rb == r2) flagrow=1;
485 // shift to the pixel in the next cell in row direction
486 Float_t zsizeNext = fSegmentation->Dpz(rb-1);
487 //to account for cell at the borders of the detector
488 if(zsizeNext==0) zsizeNext = zsize;
489 refn += zsizeNext*dirz;
491 // the track goes in the pixel in the next cell in column direction
498 if (cb == c2) flagcol=1;
502 } // end ifaxb > ax2l
504 // shift to the pixel in the next cell in column direction
505 Float_t xsizeNext = fSegmentation->Dpx(cb-1);
506 //to account for cell at the borders of the detector
507 if(xsizeNext==0) xsizeNext = xsize;
508 refr += xsizeNext*dirx;
509 } // end if (arefm < arefr) && (arefn < arefc)
511 //calculate the energy lost in the crossed pixel
512 epar = TMath::Sqrt((xb-xa)*(xb-xa)+(zb-za)*(zb-za));
513 epar = etot*(epar/dtot);
515 //store row, column and energy lost in the crossed pixel
516 frowpixel[npixel] = r1;
517 fcolpixel[npixel] = c1;
518 fenepixel[npixel] = epar;
521 // the exit point of the track is reached
522 if (epar == 0) flag = 1;
523 if ((r1 == r2) && (c1 == c2)) flag = 1;
532 //______________________________________________________________________
533 void AliITSsimulationSPD::SetCoupling(Int_t row, Int_t col, Int_t ntrack,
534 Int_t idhit,Int_t module,
535 AliITSpList *pList) {
536 // Take into account the coupling between adiacent pixels.
537 // The parameters probcol and probrow are the fractions of the
538 // signal in one pixel shared in the two adjacent pixels along
539 // the column and row direction, respectively.
543 <img src="picts/ITS/barimodel_3.gif">
546 <font size=+2 color=red>
547 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
553 Double_t pulse1,pulse2;
554 Float_t couplR=0.0,couplC=0.0;
556 GetCouplings(couplR,couplC);
559 pulse1 = fMapA2->GetSignal(row,col);
561 for (Int_t isign=-1;isign<=1;isign+=2){// loop in row direction
565 if ((j1<0) || (j1>GetNPixelsZ()-1) || (pulse1<GetThreshold())){
566 pulse1 = fMapA2->GetSignal(row,col);
570 UpdateMapSignal(j1,col,ntrack,idhit,module,pulse1,pList);
574 // loop in column direction
578 if ((j2<0) || (j2>(GetNPixelsX()-1)) || (pulse2<GetThreshold())){
579 pulse2 = fMapA2->GetSignal(row,col);
583 UpdateMapSignal(row,j2,ntrack,idhit,module,pulse2,pList);
589 //______________________________________________________________________
590 void AliITSsimulationSPD::CreateDigit(Int_t module,AliITSpList *pList) {
591 // The pixels are fired if the energy deposited inside them is above
592 // the threshold parameter ethr. Fired pixed are interpreted as digits
593 // and stored in the file digitfilename. One also needs to write out
594 // cases when there is only noise (nhits==0).
596 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
598 Int_t size = AliITSdigitSPD::GetNTracks();
599 Int_t * digits = new Int_t[size];
600 Int_t * tracks = new Int_t[size];
601 Int_t * hits = new Int_t[size];
602 Float_t * charges = new Float_t[size];
605 for (Int_t r=1;r<=GetNPixelsZ();r++) {
606 for (Int_t c=1;c<=GetNPixelsX();c++) {
607 // check if the deposited energy in a pixel is above the
609 Float_t signal = (Float_t) fMapA2->GetSignal(r,c);
610 if ( signal > GetThreshold()) {
611 digits[0] = r-1; // digits starts from 0
612 digits[1] = c-1; // digits starts from 0
614 digits[2] = (Int_t) signal; // the signal is stored in
616 for(j1=0;j1<size;j1++){
617 if(j1<pList->GetNEnteries()){
618 tracks[j1] = pList->GetTrack(r,c,j1);
619 hits[j1] = pList->GetHit(r,c,j1);
627 aliITS->AddSimDigit(0,phys,digits,tracks,hits,charges);
629 cout << " CreateSPDDigit mod=" << fModule << " r,c=" << r;
630 cout <<","<<c<< " sig=" << fpList->GetSignalOnly(r,c);
631 cout << " noise=" << fpList->GetNoise(r,c);
632 cout << " Msig="<< signal << " Thres=" << GetThreshold()<<endl;
634 } // end if of threshold condition
643 //______________________________________________________________________
644 void AliITSsimulationSPD::SetFluctuations(AliITSpList *pList,Int_t module) {
645 // Set the electronic noise and threshold non-uniformities to all the
646 // pixels in a detector.
647 // The parameter fSigma is the squared sum of the sigma due to noise
648 // and the sigma of the threshold distribution among pixels.
652 <img src="picts/ITS/barimodel_1.gif">
655 <font size=+2 color=red>
656 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
661 Float_t thr=0.0,sigm=0.0;
662 Double_t signal,sigma;
665 GetThresholds(thr,sigm);
666 sigma = (Double_t) sigm;
667 for(iz=1;iz<=GetNPixelsZ();iz++){
668 for(ix=1;ix<=GetNPixelsX();ix++){
669 signal = sigma*gRandom->Gaus();
670 fMapA2->SetHit(iz,ix,signal);
671 // insert in the label-signal-hit list the pixels fired
673 pList->AddNoise(iz,ix,module,signal);
674 } // end of loop on pixels
675 } // end of loop on pixels
677 //______________________________________________________________________
678 void AliITSsimulationSPD::SetMask() {
679 // Apply a mask to the SPD module. 1% of the pixel channels are
680 // masked. When the database will be ready, the masked pixels
681 // should be read from it.
685 Float_t perc = ((AliITSresponseSPD*)fResponse)->GetFractionDead();
686 // in this way we get the same set of random numbers for all runs.
687 // This is a cluge for now.
688 static TRandom *rnd = new TRandom();
690 totMask= perc*GetNPixelsZ()*GetNPixelsX();
691 for(im=1;im<totMask;im++){
693 ix=(Int_t)(rnd->Rndm()*(GetNPixelsX()-1.) + 1.);
694 } while(ix<=0 || ix>GetNPixelsX());
696 iz=(Int_t)(rnd->Rndm()*(GetNPixelsZ()-1.) + 1.);
697 } while(iz<=0 || iz>GetNPixelsZ());
699 fMapA2->SetHit(iz,ix,signal);
700 } // end loop on masked pixels
702 //______________________________________________________________________
703 void AliITSsimulationSPD::CreateHistograms() {
707 fHis=new TObjArray(GetNPixelsZ());
708 for(i=0;i<GetNPixelsZ();i++) {
709 TString spdname("spd_");
711 sprintf(candnum,"%d",i+1);
712 spdname.Append(candnum);
713 (*fHis)[i] = new TH1F(spdname.Data(),"SPD maps",
714 GetNPixelsX(),0.,(Float_t) GetNPixelsX());
717 //______________________________________________________________________
718 void AliITSsimulationSPD::ResetHistograms() {
719 // Reset histograms for this detector
722 for(i=0;i<GetNPixelsZ();i++ ) {
723 if ((*fHis)[i]) ((TH1F*)(*fHis)[i])->Reset();
726 //______________________________________________________________________
727 void AliITSsimulationSPD::WriteSDigits(AliITSpList *pList){
728 // Fills the Summable digits Tree
730 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
732 pList->GetMaxMapIndex(ni,nj);
733 for(i=0;i<ni;i++)for(j=0;j<nj;j++){
734 if(pList->GetSignalOnly(i,j)>0.0){
735 aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
737 cout << "pListSPD: " << *(pList->GetpListItem(i,j)) << endl;
738 cout << " CreateSPDSDigit mod=" << fModule << " r,c=";
739 cout << i <<","<< j << " sig=" << fpList->GetSignalOnly(i,j);
740 cout << " noise=" << fpList->GetNoise(i,j) <<endl;
746 //______________________________________________________________________
747 void AliITSsimulationSPD::FillMapFrompList(AliITSpList *pList){
748 // Fills fMap2A from the pList of Summable digits
751 for(iz=0;iz<GetNPixelsZ();iz++)for(ix=0;ix<GetNPixelsX();ix++)
752 fMapA2->AddSignal(iz,ix,pList->GetSignal(iz,ix));