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.4.3 2002/10/14 13:14:08 hristov
19 Updating VirtualMC to v3-09-02
21 Revision 1.20 2002/09/11 10:32:41 hristov
22 Use new for arrays with variable size
24 Revision 1.19 2002/09/09 17:23:28 nilsen
25 Minor changes in support of changes to AliITSdigitS?D class'.
27 Revision 1.18 2002/08/21 22:11:13 nilsen
28 Debug output now settable via a DEBUG flag.
30 Revision 1.17 2002/07/16 17:00:17 barbera
31 Fixes added to make the slow simulation running with the current HEAD (from M. Masera)
33 Revision 1.16 2002/06/19 16:02:22 hristov
34 Division by zero corrected
36 Revision 1.15 2002/03/15 17:32:14 nilsen
37 Reintroduced SDigitization, and Digitization from SDigits, along with
38 functions InitSimulationModule, and FinishSDigitizModule.
40 Revision 1.14 2001/11/23 13:04:07 barbera
41 Some protection added in case of high multiplicity
43 Revision 1.13 2001/11/13 11:13:24 barbera
44 A protection against tracks with the same entrance and exit has been made more strict
46 Revision 1.12 2001/10/04 22:44:31 nilsen
47 Major changes in supppor of PreDigits (SDigits). Changes made with will make
48 it easier to suppor expected changes in AliITSHit class. Added use of new
49 class AliITSpList. Both SPD and SDD have added effects of Dead Channels. Both
50 of these will require addtional work as data bases of detectors and the like
59 #include <TParticle.h>
63 #include "AliITShit.h"
64 #include "AliITSdigit.h"
65 #include "AliITSmodule.h"
66 #include "AliITSMapA2.h"
67 #include "AliITSpList.h"
68 #include "AliITSsimulationSPD.h"
69 #include "AliITSsegmentation.h"
70 #include "AliITSresponse.h"
71 #include "AliITSsegmentationSPD.h"
72 #include "AliITSresponseSPD.h"
76 ClassImp(AliITSsimulationSPD)
77 ////////////////////////////////////////////////////////////////////////
79 // Written by Rocco Caliandro
80 // from a model developed with T. Virgili and R.A. Fini
83 // AliITSsimulationSPD is the simulation of SPDs
85 //______________________________________________________________________
86 AliITSsimulationSPD::AliITSsimulationSPD(){
87 // Default constructor
100 //______________________________________________________________________
101 AliITSsimulationSPD::AliITSsimulationSPD(AliITSsegmentation *seg,
102 AliITSresponse *resp) {
103 // Standard constructor
115 Init((AliITSsegmentationSPD*)seg,(AliITSresponseSPD*)resp);
117 //______________________________________________________________________
118 void AliITSsimulationSPD::Init(AliITSsegmentationSPD *seg,
119 AliITSresponseSPD *resp) {
120 // Initilizes the variables of AliITSsimulation SPD.
125 fMapA2 = new AliITSMapA2(fSegmentation);
126 fpList = new AliITSpList(GetNPixelsZ()+1,GetNPixelsX()+1);
128 fResponse->Thresholds(fThresh,fSigma);
129 fResponse->GetNoiseParam(fCouplCol,fCouplRow);
130 fNPixelsZ = fSegmentation->Npz();
131 fNPixelsX = fSegmentation->Npx();
134 //______________________________________________________________________
135 AliITSsimulationSPD::~AliITSsimulationSPD() {
146 //______________________________________________________________________
147 AliITSsimulationSPD::AliITSsimulationSPD(const AliITSsimulationSPD &source){
150 if(&source == this) return;
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 AliITSsimulationSPD& AliITSsimulationSPD::operator=(const AliITSsimulationSPD
167 // Assignment operator
169 if(&source == this) return *this;
171 this->fMapA2 = source.fMapA2;
172 this->fHis = source.fHis;
174 this->fThresh = source.fThresh;
175 this->fSigma = source.fSigma;
176 this->fCouplCol = source.fCouplCol;
177 this->fCouplRow = source.fCouplRow;
178 this->fNPixelsX = source.fNPixelsX;
179 this->fNPixelsZ = source.fNPixelsZ;
183 //______________________________________________________________________
184 void AliITSsimulationSPD::InitSimulationModule(Int_t module,Int_t event){
185 // Creates maps to build the list of tracks for each sumable digit
187 // Int_t module // Module number to be simulated
188 // Int_t event // Event number to be simulated
199 //______________________________________________________________________
200 void AliITSsimulationSPD::FinishSDigitiseModule(){
201 // Does the Sdigits to Digits work
209 SDigitsToDigits(fModule,fpList);
211 //______________________________________________________________________
212 void AliITSsimulationSPD::SDigitiseModule(AliITSmodule *mod, Int_t dummy0,
214 // Sum digitize module
215 if (!(mod->GetNhits())) return; // if module has no hits then no Sdigits.
216 Int_t number = 10000;
217 Int_t *frowpixel = new Int_t[number];
218 Int_t *fcolpixel = new Int_t[number];
219 Double_t *fenepixel = new Double_t[number];
221 fModule = mod->GetIndex();
223 // Array of pointers to store the track index of the digits
224 // leave +1, otherwise pList crashes when col=256, row=192
226 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
228 WriteSDigits(fpList);
237 //______________________________________________________________________
238 void AliITSsimulationSPD::DigitiseModule(AliITSmodule *mod, Int_t dummy0,
240 // digitize module. Also need to digitize modules with only noise.
242 Int_t number = 10000;
243 Int_t *frowpixel = new Int_t[number];
244 Int_t *fcolpixel = new Int_t[number];
245 Double_t *fenepixel = new Double_t[number];
247 // Array of pointers to store the track index of the digits
248 // leave +1, otherwise pList crashes when col=256, row=192
249 fModule = mod->GetIndex();
251 SetFluctuations(fpList,fModule);
253 HitsToAnalogDigits(mod,frowpixel,fcolpixel,fenepixel,fpList);
255 // apply mask to SPD module
258 CreateDigit(fModule,fpList);
267 //______________________________________________________________________
268 void AliITSsimulationSPD::SDigitsToDigits(Int_t module,AliITSpList *pList) {
269 // sum digits to Digits.
272 cout << "Entering AliITSsimulatinSPD::SDigitsToDigits for module=";
273 cout << module << endl;
278 SetFluctuations(pList,module);
280 fMapA2->ClearMap(); // since noise is in pList aready. Zero Map so that
281 // noise is not doubled when calling FillMapFrompList.
283 FillMapFrompList(pList);
285 // apply mask to SPD module
288 CreateDigit(module,pList);
293 //______________________________________________________________________
294 void AliITSsimulationSPD::UpdateMapSignal(Int_t row,Int_t col,Int_t trk,
295 Int_t hit,Int_t mod,Double_t ene,
296 AliITSpList *pList) {
297 // updates the Map of signal, adding the energy (ene) released by
300 fMapA2->AddSignal(row,col,ene);
301 pList->AddSignal(row,col,trk,hit,mod,ene);
303 //______________________________________________________________________
304 void AliITSsimulationSPD::UpdateMapNoise(Int_t row,Int_t col,Int_t mod,
305 Double_t ene,AliITSpList *pList) {
306 // updates the Map of noise, adding the energy (ene) give my noise
308 fMapA2->AddSignal(row,col,ene);
309 pList->AddNoise(row,col,mod,ene);
311 //______________________________________________________________________
312 void AliITSsimulationSPD::HitsToAnalogDigits(AliITSmodule *mod,
313 Int_t *frowpixel,Int_t *fcolpixel,
315 AliITSpList *pList) {
316 // Loops over all hits to produce Analog/floting point digits. This
317 // is also the first task in producing standard digits.
319 // loop over hits in the module
320 Int_t hitpos,nhits = mod->GetNhits();
321 for (hitpos=0;hitpos<nhits;hitpos++) {
322 HitToDigit(mod,hitpos,frowpixel,fcolpixel,fenepixel,pList);
323 }// end loop over digits
325 //______________________________________________________________________
326 void AliITSsimulationSPD::HitToDigit(AliITSmodule *mod,Int_t hitpos,
327 Int_t *frowpixel,Int_t *fcolpixel,
328 Double_t *fenepixel,AliITSpList *pList) {
329 // Steering function to determine the digits associated to a given
331 // The digits are created by charge sharing (ChargeSharing) and by
332 // capacitive coupling (SetCoupling). At all the created digits is
333 // associated the track number of the hit (ntrack)
334 Double_t x1l=0.0,y1l=0.0,z1l=0.0,x2l=0.0,y2l=0.0,z2l=0.0;
335 Int_t r1,r2,c1,c2,row,col,npixel = 0;
337 Double_t ene=0.0,etot=0.0;
338 const Float_t kconv = 10000.; // cm -> microns
339 const Float_t kconv1= 0.277e9; // GeV -> electrons equivalent
341 if(!(mod->LineSegmentL(hitpos,x1l,x2l,y1l,y2l,z1l,z2l,etot,ntrack)))return;
343 x2l += x1l; y2l += y1l; z2l += z1l; // Convert to ending coordinate.
344 // positions shifted and converted in microns
345 x1l = x1l*kconv + fSegmentation->Dx()/2.;
346 z1l = z1l*kconv + fSegmentation->Dz()/2.;
347 // positions shifted and converted in microns
348 x2l = x2l*kconv + fSegmentation->Dx()/2.;
349 z2l = z2l*kconv + fSegmentation->Dz()/2.;
350 etot *= kconv1; // convert from GeV to electrons equivalent.
351 Int_t module = mod->GetIndex();
353 // to account for the effective sensitive area
354 // introduced in geometry
355 if (z1l<0 || z1l>fSegmentation->Dz()) return;
356 if (z2l<0 || z2l>fSegmentation->Dz()) return;
357 if (x1l<0 || x1l>fSegmentation->Dx()) return;
358 if (x2l<0 || x2l>fSegmentation->Dx()) return;
360 //Get the col and row number starting from 1
361 // the x direction is not inverted for the second layer!!!
362 fSegmentation->GetPadIxz(x1l, z1l, c1, r1);
363 fSegmentation->GetPadIxz(x2l, z2l, c2, r2);
365 // to account for unexpected equal entrance and
367 if (x1l==x2l) x2l=x2l+x2l*0.1;
368 if (z1l==z2l) z2l=z2l+z2l*0.1;
370 if ((r1==r2) && (c1==c2)){
373 frowpixel[npixel-1] = r1;
374 fcolpixel[npixel-1] = c1;
375 fenepixel[npixel-1] = etot;
378 ChargeSharing(x1l,z1l,x2l,z2l,c1,r1,c2,r2,etot,
379 npixel,frowpixel,fcolpixel,fenepixel);
380 } // end if r1==r2 && c1==c2.
382 for (Int_t npix=0;npix<npixel;npix++){
383 row = frowpixel[npix];
384 col = fcolpixel[npix];
385 ene = fenepixel[npix];
386 UpdateMapSignal(row,col,ntrack,hitpos,module,ene,pList);
387 // Starting capacitive coupling effect
388 SetCoupling(row,col,ntrack,hitpos,module,pList);
391 //______________________________________________________________________
392 void AliITSsimulationSPD::ChargeSharing(Float_t x1l,Float_t z1l,Float_t x2l,
393 Float_t z2l,Int_t c1,Int_t r1,Int_t c2,
394 Int_t r2,Float_t etot,
395 Int_t &npixel,Int_t *frowpixel,
396 Int_t *fcolpixel,Double_t *fenepixel){
397 // Take into account the geometrical charge sharing when the track
398 // crosses more than one pixel.
402 <img src="picts/ITS/barimodel_2.gif">
405 <font size=+2 color=red>
406 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
412 Float_t xa,za,xb,zb,dx,dz,dtot,refr,refm,refc;
414 Float_t arefm, arefr, arefn, arefc, azb, az2l, axb, ax2l;
415 Int_t dirx,dirz,rb,cb;
416 Int_t flag,flagrow,flagcol;
426 dtot = TMath::Sqrt((dx*dx)+(dz*dz));
427 if (dtot==0.0) dtot = 0.01;
428 dirx = (Int_t) TMath::Sign((Float_t)1,dx);
429 dirz = (Int_t) TMath::Sign((Float_t)1,dz);
431 // calculate the x coordinate of the pixel in the next column
432 // and the z coordinate of the pixel in the next row
435 fSegmentation->GetPadCxz(c1, r1-1, xpos, zpos);
437 Float_t xsize = fSegmentation->Dpx(0);
438 Float_t zsize = fSegmentation->Dpz(r1-1);
440 if (dirx == 1) refr = xpos+xsize/2.;
441 else refr = xpos-xsize/2.;
443 if (dirz == 1) refn = zpos+zsize/2.;
444 else refn = zpos-zsize/2.;
450 // calculate the x coordinate of the intersection with the pixel
451 // in the next cell in row direction
453 refm = dx*((refn - z1l)/dz) + x1l;
455 refm = refr+dirx*xsize;
457 // calculate the z coordinate of the intersection with the pixel
458 // in the next cell in column direction
460 refc = dz*((refr - x1l)/dx) + z1l;
462 refc = refn+dirz*zsize;
469 if ((arefm < arefr) && (arefn < arefc)){
470 // the track goes in the pixel in the next cell in row direction
477 if (rb == r2) flagrow=1;
482 // shift to the pixel in the next cell in row direction
483 Float_t zsizeNext = fSegmentation->Dpz(rb-1);
484 //to account for cell at the borders of the detector
485 if(zsizeNext==0) zsizeNext = zsize;
486 refn += zsizeNext*dirz;
488 // the track goes in the pixel in the next cell in column direction
495 if (cb == c2) flagcol=1;
499 } // end ifaxb > ax2l
501 // shift to the pixel in the next cell in column direction
502 Float_t xsizeNext = fSegmentation->Dpx(cb-1);
503 //to account for cell at the borders of the detector
504 if(xsizeNext==0) xsizeNext = xsize;
505 refr += xsizeNext*dirx;
506 } // end if (arefm < arefr) && (arefn < arefc)
508 //calculate the energy lost in the crossed pixel
509 epar = TMath::Sqrt((xb-xa)*(xb-xa)+(zb-za)*(zb-za));
510 epar = etot*(epar/dtot);
512 //store row, column and energy lost in the crossed pixel
513 frowpixel[npixel] = r1;
514 fcolpixel[npixel] = c1;
515 fenepixel[npixel] = epar;
518 // the exit point of the track is reached
519 if (epar == 0) flag = 1;
520 if ((r1 == r2) && (c1 == c2)) flag = 1;
529 //______________________________________________________________________
530 void AliITSsimulationSPD::SetCoupling(Int_t row, Int_t col, Int_t ntrack,
531 Int_t idhit,Int_t module,
532 AliITSpList *pList) {
533 // Take into account the coupling between adiacent pixels.
534 // The parameters probcol and probrow are the fractions of the
535 // signal in one pixel shared in the two adjacent pixels along
536 // the column and row direction, respectively.
540 <img src="picts/ITS/barimodel_3.gif">
543 <font size=+2 color=red>
544 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
550 Double_t pulse1,pulse2;
551 Float_t couplR=0.0,couplC=0.0;
553 GetCouplings(couplR,couplC);
556 pulse1 = fMapA2->GetSignal(row,col);
558 for (Int_t isign=-1;isign<=1;isign+=2){// loop in row direction
562 if ((j1<0) || (j1>GetNPixelsZ()-1) || (pulse1<GetThreshold())){
563 pulse1 = fMapA2->GetSignal(row,col);
567 UpdateMapSignal(j1,col,ntrack,idhit,module,pulse1,pList);
571 // loop in column direction
575 if ((j2<0) || (j2>(GetNPixelsX()-1)) || (pulse2<GetThreshold())){
576 pulse2 = fMapA2->GetSignal(row,col);
580 UpdateMapSignal(row,j2,ntrack,idhit,module,pulse2,pList);
586 //______________________________________________________________________
587 void AliITSsimulationSPD::CreateDigit(Int_t module,AliITSpList *pList) {
588 // The pixels are fired if the energy deposited inside them is above
589 // the threshold parameter ethr. Fired pixed are interpreted as digits
590 // and stored in the file digitfilename. One also needs to write out
591 // cases when there is only noise (nhits==0).
593 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
595 Int_t size = AliITSdigitSPD::GetNTracks();
596 Int_t * digits = new Int_t[size];
597 Int_t * tracks = new Int_t[size];
598 Int_t * hits = new Int_t[size];
599 Float_t * charges = new Float_t[size];
602 for (Int_t r=1;r<=GetNPixelsZ();r++) {
603 for (Int_t c=1;c<=GetNPixelsX();c++) {
604 // check if the deposited energy in a pixel is above the
606 Float_t signal = (Float_t) fMapA2->GetSignal(r,c);
607 if ( signal > GetThreshold()) {
608 digits[0] = r-1; // digits starts from 0
609 digits[1] = c-1; // digits starts from 0
611 digits[2] = (Int_t) signal; // the signal is stored in
613 for(j1=0;j1<size;j1++){
614 if(j1<pList->GetNEnteries()){
615 tracks[j1] = pList->GetTrack(r,c,j1);
616 hits[j1] = pList->GetHit(r,c,j1);
624 aliITS->AddSimDigit(0,phys,digits,tracks,hits,charges);
626 cout << " CreateSPDDigit mod=" << fModule << " r,c=" << r;
627 cout <<","<<c<< " sig=" << fpList->GetSignalOnly(r,c);
628 cout << " noise=" << fpList->GetNoise(r,c);
629 cout << " Msig="<< signal << " Thres=" << GetThreshold()<<endl;
631 } // end if of threshold condition
640 //______________________________________________________________________
641 void AliITSsimulationSPD::SetFluctuations(AliITSpList *pList,Int_t module) {
642 // Set the electronic noise and threshold non-uniformities to all the
643 // pixels in a detector.
644 // The parameter fSigma is the squared sum of the sigma due to noise
645 // and the sigma of the threshold distribution among pixels.
649 <img src="picts/ITS/barimodel_1.gif">
652 <font size=+2 color=red>
653 <a href="mailto:Rocco.Caliandro@ba.infn.it"></a>.
658 Float_t thr=0.0,sigm=0.0;
659 Double_t signal,sigma;
662 GetThresholds(thr,sigm);
663 sigma = (Double_t) sigm;
664 for(iz=1;iz<=GetNPixelsZ();iz++){
665 for(ix=1;ix<=GetNPixelsX();ix++){
666 signal = sigma*gRandom->Gaus();
667 fMapA2->SetHit(iz,ix,signal);
668 // insert in the label-signal-hit list the pixels fired
670 pList->AddNoise(iz,ix,module,signal);
671 } // end of loop on pixels
672 } // end of loop on pixels
674 //______________________________________________________________________
675 void AliITSsimulationSPD::SetMask() {
676 // Apply a mask to the SPD module. 1% of the pixel channels are
677 // masked. When the database will be ready, the masked pixels
678 // should be read from it.
682 Float_t perc = ((AliITSresponseSPD*)fResponse)->GetFractionDead();
683 // in this way we get the same set of random numbers for all runs.
684 // This is a cluge for now.
685 static TRandom *rnd = new TRandom();
687 totMask= perc*GetNPixelsZ()*GetNPixelsX();
688 for(im=1;im<totMask;im++){
690 ix=(Int_t)(rnd->Rndm()*(GetNPixelsX()-1.) + 1.);
691 } while(ix<=0 || ix>GetNPixelsX());
693 iz=(Int_t)(rnd->Rndm()*(GetNPixelsZ()-1.) + 1.);
694 } while(iz<=0 || iz>GetNPixelsZ());
696 fMapA2->SetHit(iz,ix,signal);
697 } // end loop on masked pixels
699 //______________________________________________________________________
700 void AliITSsimulationSPD::CreateHistograms() {
704 fHis=new TObjArray(GetNPixelsZ());
705 for(i=0;i<GetNPixelsZ();i++) {
706 TString spdname("spd_");
708 sprintf(candnum,"%d",i+1);
709 spdname.Append(candnum);
710 (*fHis)[i] = new TH1F(spdname.Data(),"SPD maps",
711 GetNPixelsX(),0.,(Float_t) GetNPixelsX());
714 //______________________________________________________________________
715 void AliITSsimulationSPD::ResetHistograms() {
716 // Reset histograms for this detector
719 for(i=0;i<GetNPixelsZ();i++ ) {
720 if ((*fHis)[i]) ((TH1F*)(*fHis)[i])->Reset();
723 //______________________________________________________________________
724 void AliITSsimulationSPD::WriteSDigits(AliITSpList *pList){
725 // Fills the Summable digits Tree
727 static AliITS *aliITS = (AliITS*)gAlice->GetModule("ITS");
729 pList->GetMaxMapIndex(ni,nj);
730 for(i=0;i<ni;i++)for(j=0;j<nj;j++){
731 if(pList->GetSignalOnly(i,j)>0.0){
732 aliITS->AddSumDigit(*(pList->GetpListItem(i,j)));
734 cout << "pListSPD: " << *(pList->GetpListItem(i,j)) << endl;
735 cout << " CreateSPDSDigit mod=" << fModule << " r,c=";
736 cout << i <<","<< j << " sig=" << fpList->GetSignalOnly(i,j);
737 cout << " noise=" << fpList->GetNoise(i,j) <<endl;
743 //______________________________________________________________________
744 void AliITSsimulationSPD::FillMapFrompList(AliITSpList *pList){
745 // Fills fMap2A from the pList of Summable digits
748 for(iz=0;iz<GetNPixelsZ();iz++)for(ix=0;ix<GetNPixelsX();ix++)
749 fMapA2->AddSignal(iz,ix,pList->GetSignal(iz,ix));