]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - ITS/AliITSsimulationSDD.cxx
ConstructModules() corrected (both single and dependent modules are configured first...
[u/mrichter/AliRoot.git] / ITS / AliITSsimulationSDD.cxx
index 0533aba2f30619040a4463f6e0821c5e7c9cd348..58876f78fd216a584a0a9093f31b1b166ba223a2 100644 (file)
@@ -19,6 +19,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <TSystem.h>
+#include <TROOT.h>
 #include <TStopwatch.h>
 #include <TCanvas.h>
 #include <TF1.h>
@@ -221,7 +223,7 @@ AliITSsimulationSDD::AliITSsimulationSDD(AliITSsegmentation *seg,AliITSresponse
          return;
       }
 
-      fElectronics = new AliITSetfSDD(timeStep/fScaleSize);
+      fElectronics = new AliITSetfSDD(timeStep/fScaleSize,fResponse->Electronics());
 
       char opt1[20], opt2[20];
       fResponse->ParamOptions(opt1,opt2);
@@ -309,7 +311,7 @@ AliITSsimulationSDD::~AliITSsimulationSDD() {
 void AliITSsimulationSDD::DigitiseModule(AliITSmodule *mod,Int_t md,Int_t ev){
   // create maps to build the lists of tracks
   // for each digit
-
+    cout << "Module: " << md << endl;
     fModule=md;
     fEvent=ev;
 
@@ -331,107 +333,161 @@ void AliITSsimulationSDD::DigitiseModule(AliITSmodule *mod,Int_t md,Int_t ev){
     Int_t arg[6] = {0,0,0,0,0,0}; 
     fHitMap1->SetArray(list);
 
+    //    cout << "set Parameters" << endl;
 
     Int_t nofAnodes=fNofMaps/2;
 
     Float_t sddLength = fSegmentation->Dx();
     Float_t sddWidth = fSegmentation->Dz();
-
+    
     Int_t dummy=0;
     Float_t anodePitch = fSegmentation->Dpz(dummy);
     Float_t timeStep = fSegmentation->Dpx(dummy);
 
     Float_t driftSpeed=fResponse->DriftSpeed();    
 
+    Float_t maxadc = fResponse->MaxAdc();    
+    Float_t topValue = fResponse->DynamicRange();
+    Float_t CHloss = fResponse->ChargeLoss();
+    Float_t norm = maxadc/topValue;
+
     // Piergiorgio's part (apart for few variables which I made float
     // when i thought that can be done
 
     // Fill detector maps with GEANT hits
     // loop over hits in the module
 
+    //    TStopwatch timer;
+    //    timer.Start();
+
     const Float_t kconv=1.0e+6;  // GeV->KeV
     Int_t ii;
     Int_t idhit=-1;
+    Float_t xL[3];
+    Float_t xL1[3];
     for(ii=0; ii<nhits; ii++) {
-       AliITShit *hit = (AliITShit*) fHits->At(ii);
-       Float_t xL[3];
-       hit = (AliITShit*) fHits->At(ii);
+      //      cout << "hit: " << ii+1 << " of " << nhits << endl;
+      AliITShit *hit = (AliITShit*) fHits->At(ii);
+      AliITShit *hit1 = 0;
+      
+      // Take into account all hits when several GEANT steps are carried out
+      // inside the silicon
+      // Get and use the status of hit(track):
+      // 66  - for entering hit,
+      // 65  - for inside hit,
+      // 68  - for exiting hit,
+      // 33  - for stopping hit.
+
+      //Int_t status = hit->GetTrackStatus(); 
+      Int_t status1 = 0;
+      Int_t hitDetector = hit->GetDetector();
+      Float_t depEnergy = 0.;
+      if(hit->StatusEntering()) { // to be coupled to following hit
+       idhit=ii;
        hit->GetPositionL(xL[0],xL[1],xL[2]);
-       Int_t hitDetector = hit->GetDetector();
-
-        if(hit->StatusEntering()) idhit=ii;
-
-       // Deposited energy in keV
-       Float_t avpath = 0.;
-       Float_t avanod = 0.;
-       Float_t depEnergy = kconv*hit->GetIonization();
-       AliITShit *hit1 = 0;
-       if(depEnergy != 0.) continue;
-
-       ii++;
-       Float_t xL1[3];
+       if(ii<nhits-1) ii++;
        hit1 = (AliITShit*) fHits->At(ii);
        hit1->GetPositionL(xL1[0],xL1[1],xL1[2]);
-       avpath = xL1[0];
-       avanod = xL1[2];
-       depEnergy = kconv*hit1->GetIonization();
-       
-       // added 11.09.2000 - continue if the particle did not lose energy
-       // passing through detector
-       if (!depEnergy) {
+       status1 = hit1->GetTrackStatus();
+       depEnergy = kconv*hit1->GetIonization();          
+      } else {
+       depEnergy = kconv*hit->GetIonization();  // Deposited energy in keV
+       hit->GetPositionL(xL1[0],xL1[1],xL1[2]);
+      }
+      //      cout << "status: " << status << ", status1: " << status1 << ", dE: " << depEnergy << endl;
+      if(fFlag && status1 == 33) continue;
+      
+      Int_t nOfSplits = 1;
+
+      //      hit->Print();
+
+//     Int_t status1 = -1;
+//      Int_t ctr = 0;
+      //Take now the entering and inside hits only
+//     if(status == 66) {
+//     do  {
+//       if(ii<nhits-1) ii++;
+//       hit1 = (AliITShit*) fHits->At(ii);
+//       hit1->GetPositionL(xL1[0],xL1[1],xL1[2]);
+//       status1 = hit1->GetTrackStatus();
+//       depEnergy += kconv*hit1->GetIonization();       
+//       if(fFlag && status1 == 65) ctr++;
+//     } while(status1 != 68 && status1 != 33);
+//      }
+
+
+      // scale path to simulate a perpendicular track
+      // continue if the particle did not lose energy
+      // passing through detector
+      if (!depEnergy) {
          printf("This particle has passed without losing energy!\n");
          continue;
-       }
-       // end add
-
-       // scale path to simulate a perpendicular track
-       if (fFlag) {
-         Float_t lC[3];
-         hit->GetPositionL(lC[0],lC[1],lC[2]);
-         Float_t lC1[3];
-         hit1->GetPositionL(lC1[0],lC1[1],lC1[2]);
-         Float_t pathInSDD = TMath::Sqrt((lC[0]-lC1[0])*(lC[0]-lC1[0])+(lC[1]-lC1[1])*(lC[1]-lC1[1])+(lC[2]-lC1[2])*(lC[2]-lC1[2]));
-         if(pathInSDD) depEnergy *= (0.03/pathInSDD);
-       }
-
-       Float_t avDrft = xL[0]+avpath;
-       Float_t avAnode = xL[2]+avanod;
-
-       if(avpath != 0.) avDrft /= 2.;
-       if(avanod != 0.) avAnode /= 2.;
-
+      }
+      Float_t pathInSDD = TMath::Sqrt((xL[0]-xL1[0])*(xL[0]-xL1[0])+(xL[1]-xL1[1])*(xL[1]-xL1[1])+(xL[2]-xL1[2])*(xL[2]-xL1[2]));
+
+      if (fFlag && pathInSDD) { depEnergy *= (0.03/pathInSDD); }
+      Float_t Drft = (xL1[0]+xL[0])*0.5;
+      Float_t drPath = 10000.*Drft;
+      if(drPath < 0) drPath = -drPath;
+      drPath = sddLength-drPath;
+      if(drPath < 0) {
+       cout << "Warning: negative drift path " << drPath << endl;
+       continue;
+      }
+      
+      //   Drift Time
+      Float_t drTime = drPath/driftSpeed;
+      //  Signal 2d Shape
+      Float_t dfCoeff, s1;
+      fResponse->DiffCoeff(dfCoeff,s1);
+    
+      // Squared Sigma along the anodes
+      Double_t sig2A = 2.*dfCoeff*drTime+s1*s1;
+      Double_t sigA  = TMath::Sqrt(sig2A);
+      if(pathInSDD) { 
+       nOfSplits = (Int_t) (1 + 10000.*pathInSDD/sigA);
+       //cout << "nOfSplits: " << nOfSplits << ", sigA: " << sigA << ", path: " << pathInSDD << endl;
+      }        
+      if(fFlag) nOfSplits = 1;
+      depEnergy /= nOfSplits;
+
+      for(Int_t kk=0;kk<nOfSplits;kk++) {
+       Float_t avDrft =  
+                xL[0]+(xL1[0]-xL[0])*((kk+0.5)/((Float_t) nOfSplits));
+       Float_t avAnode = 
+                xL[2]+(xL1[2]-xL[2])*((kk+0.5)/((Float_t) nOfSplits));
        Float_t driftPath = 10000.*avDrft;
+
        Int_t iWing = 2;
        if(driftPath < 0) {
-         iWing = 1;
-         driftPath = -driftPath;
+          iWing = 1;
+          driftPath = -driftPath;
        }
        driftPath = sddLength-driftPath;
        Int_t detector = 2*(hitDetector-1) + iWing;
        if(driftPath < 0) {
-         cout << "Warning: negative drift path " << driftPath << endl;
-         continue;
+          cout << "Warning: negative drift path " << driftPath << endl;
+          continue;
        }
         
        //   Drift Time
        Float_t driftTime = driftPath/driftSpeed;
        Int_t timeSample = (Int_t) (fScaleSize*driftTime/timeStep + 1);
        if(timeSample > fScaleSize*fMaxNofSamples) {
-         cout << "Warning: Wrong Time Sample: " << timeSample << endl;
-         continue;
+          cout << "Warning: Wrong Time Sample: " << timeSample << endl;
+          continue;
        }
 
        //   Anode
        Float_t xAnode = 10000.*(avAnode)/anodePitch + nofAnodes/2;  // +1?
-       if((xAnode+1)*anodePitch > sddWidth || xAnode*anodePitch < 0.) 
-             { cout << "Warning: Z = " << xAnode*anodePitch << endl; }
+       if(xAnode*anodePitch > sddWidth || xAnode*anodePitch < 0.) 
+         { cout << "Warning: Z = " << xAnode*anodePitch << endl; }
        Int_t iAnode = (Int_t) (1.+xAnode); // xAnode?
-       if(iAnode < 0 || iAnode > nofAnodes) {
+       if(iAnode < 1 || iAnode > nofAnodes) {
          cout << "Warning: Wrong iAnode: " << iAnode << endl;
          continue;
        } 
 
-
        // work with the idtrack=entry number in the TreeH for the moment
        //Int_t idhit,idtrack;
        //mod->GetHitTrackAndHitIndex(ii,idtrack,idhit);    
@@ -439,7 +495,7 @@ void AliITSsimulationSDD::DigitiseModule(AliITSmodule *mod,Int_t md,Int_t ev){
         // or store straight away the particle position in the array
        // of particles and take idhit=ii only when part is entering (this
        // requires FillModules() in the macro for analysis) : 
-        Int_t itrack = hit->GetTrack();
+       Int_t itrack = hit->GetTrack();
 
        //  Signal 2d Shape
        Float_t diffCoeff, s0;
@@ -449,16 +505,25 @@ void AliITSsimulationSDD::DigitiseModule(AliITSmodule *mod,Int_t md,Int_t ev){
        Double_t sigma2A = 2.*diffCoeff*driftTime+s0*s0;
        Double_t sigmaA  = TMath::Sqrt(sigma2A);
        Double_t sigmaT  = sigmaA/driftSpeed;
-    
        // Peak amplitude in nanoAmpere
        Double_t eVpairs = 3.6;
        Double_t amplitude = fScaleSize*160.*depEnergy/(timeStep*eVpairs*2.*acos(-1.)*sigmaT*sigmaA);
-    
+       amplitude *= timeStep/25.; // WARNING!!!!! Amplitude scaling to account for clock variations (reference value: 40 MHz)
+       Double_t chargeloss = 1.-CHloss*driftPath/1000;
+       amplitude *= chargeloss;
        Float_t nsigma=fResponse->NSigmaIntegration();
+       Int_t nlookups = fResponse->GausNLookUp();
+       Float_t width = 2.*nsigma/(nlookups-1);
        // Spread the charge 
        // Pixel index
        Int_t ja = iAnode;
        Int_t jt = timeSample;
+       Int_t ndiv = 2;
+       Float_t nmul = 3.; 
+       if(driftTime > 1200.) { 
+         ndiv = 4;
+         nmul = 1.5;
+       }
        // Sub-pixel index
        Int_t nsplit = 4; // hard-wired
        nsplit = (nsplit+1)/2*2;
@@ -468,64 +533,78 @@ void AliITSsimulationSDD::DigitiseModule(AliITSmodule *mod,Int_t md,Int_t ev){
        // Define SDD window corresponding to the hit
        Int_t anodeWindow = (Int_t) (fScaleSize*nsigma*sigmaA/anodePitch + 1);
        Int_t timeWindow = (Int_t) (fScaleSize*nsigma*sigmaT/timeStep + 1);
-       Int_t jamin = (ja - anodeWindow/2 - 1)*fScaleSize*nsplit + 1;
-       Int_t jamax = (ja + anodeWindow/2)*fScaleSize*nsplit;
+       Int_t jamin = (ja - anodeWindow/ndiv - 1)*fScaleSize*nsplit + 1;
+       Int_t jamax = (ja + anodeWindow/ndiv)*fScaleSize*nsplit;
        if(jamin <= 0) jamin = 1;
        if(jamax > fScaleSize*nofAnodes*nsplit) jamax = fScaleSize*nofAnodes*nsplit;
-       Int_t jtmin = (jt - timeWindow*3 - 1)*nsplit + 1; //hard-wired
-       Int_t jtmax = (jt + timeWindow*3)*nsplit; //hard-wired
+       Int_t jtmin = (Int_t) (jt - timeWindow*nmul - 1)*nsplit + 1; //hard-wired
+       Int_t jtmax = (Int_t) (jt + timeWindow*nmul)*nsplit; //hard-wired
        if(jtmin <= 0) jtmin = 1;
        if(jtmax > fScaleSize*fMaxNofSamples*nsplit) jtmax = fScaleSize*fMaxNofSamples*nsplit;
 
-       Double_t rlAnode = log(aStep*amplitude);
-
        // Spread the charge in the anode-time window
         Int_t ka;
+       //cout << "jamin: " << jamin << ", jamax: " << jamax << endl;
+       //cout << "jtmin: " << jtmin << ", jtmax: " << jtmax << endl;
        for(ka=jamin; ka <=jamax; ka++) {
          Int_t ia = (ka-1)/(fScaleSize*nsplit) + 1;
          if(ia <= 0) { cout << "Warning: ia < 1: " << endl; continue; }
          if(ia > nofAnodes) ia = nofAnodes;
          Double_t aExpo = (aStep*(ka-0.5)-xAnode*anodePitch)/sigmaA;
-         Double_t anodeAmplitude = rlAnode - 0.5*aExpo*aExpo;
-         // Protect against overflows
-         if(anodeAmplitude > -87.3)
-           anodeAmplitude = exp(anodeAmplitude);
-         else
-           anodeAmplitude = 0;
+         Double_t anodeAmplitude = 0;
+         if(TMath::Abs(aExpo) > nsigma) {
+           anodeAmplitude = 0.;
+           //cout << "aExpo: " << aExpo << endl;
+         } else {
+           Int_t i = (Int_t) ((aExpo+nsigma)/width);
+           //cout << "eval ampl: " << i << ", " << amplitude << endl;
+           anodeAmplitude = amplitude*fResponse->GausLookUp(i);
+           //cout << "ampl: " << anodeAmplitude << endl;
+         }
          Int_t index = ((detector+1)%2)*nofAnodes+ia-1; // index starts from 0
          if(anodeAmplitude) {
-           Double_t rlTime = log(tStep*anodeAmplitude);
+           //Double_t rlTime = log(tStep*anodeAmplitude);
             Int_t kt;
            for(kt=jtmin; kt<=jtmax; kt++) {
              Int_t it = (kt-1)/nsplit+1;  // it starts from 1
              if(it<=0) { cout << "Warning: it < 1: " << endl; continue; } 
              if(it>fScaleSize*fMaxNofSamples) it = fScaleSize*fMaxNofSamples;
              Double_t tExpo = (tStep*(kt-0.5)-driftTime)/sigmaT;
-             Double_t timeAmplitude = rlTime - 0.5*tExpo*tExpo;
-             // Protect against overflows
-             if(timeAmplitude > -87.3){
-               timeAmplitude = exp(timeAmplitude);
-             } else
-               timeAmplitude = 0;
+             Double_t timeAmplitude = 0.;
+             if(TMath::Abs(tExpo) > nsigma) {
+               timeAmplitude = 0.;
+               //cout << "tExpo: " << tExpo << endl;
+             } else {
+               Int_t i = (Int_t) ((tExpo+nsigma)/width);
+               //cout << "eval ampl: " << i << ", " << anodeAmplitude << endl;
+               timeAmplitude = anodeAmplitude*fResponse->GausLookUp(i);
+             }
 
              // build the list of digits for this module       
              arg[0]=index;
              arg[1]=it;
              arg[2]=itrack;
              arg[3]=idhit;
+             timeAmplitude *= norm;
+             timeAmplitude *= 10;
              ListOfFiredCells(arg,timeAmplitude,list,padr);
-       } // loop over time in window 
-      } // end if anodeAmplitude
-    } // loop over anodes in window
-  } // end loop over hits
-
+             //cout << "ampl: " << timeAmplitude << endl;
+           } // loop over time in window 
+         } // end if anodeAmplitude
+       } // loop over anodes in window
+      } // end loop over "sub-hits"
+      for(Int_t ki=0; ki<3; ki++) xL[ki] = xL1[ki];
+    } // end loop over hits
+    
+    //    timer.Stop(); timer.Print(); 
+    
   // introduce the electronics effects and do zero-suppression if required
   Int_t nentries=list->GetEntriesFast();
   if (nentries) {
 
-    //TStopwatch timer;
+    //    TStopwatch timer1;
     ChargeToSignal(); 
-    //timer.Stop(); timer.Print();
+    //    timer1.Stop(); cout << "ele: ";  timer1.Print();
 
     const char *kopt=fResponse->ZeroSuppOption();
     ZeroSuppression(kopt);
@@ -796,11 +875,6 @@ void AliITSsimulationSDD::SortTracks(Int_t *tracks,Float_t *charges,Int_t *hits,
 void AliITSsimulationSDD::ChargeToSignal() {
   // add baseline, noise, electronics and ADC saturation effects
 
-
-  Float_t maxadc = fResponse->MaxAdc();    
-  Float_t topValue = fResponse->MagicValue();
-  Float_t norm = maxadc/topValue;
-
   char opt1[20], opt2[20];
   fResponse->ParamOptions(opt1,opt2);
   char *read = strstr(opt1,"file");
@@ -819,27 +893,30 @@ void AliITSsimulationSDD::ChargeToSignal() {
   TRandom random; 
   Int_t i,k,kk; 
 
+  Float_t maxadc = fResponse->MaxAdc();    
   if(!fDoFFT) {
     for (i=0;i<fNofMaps;i++) {
         if  (read && i<fNofMaps) GetAnodeBaseline(i,baseline,noise);
        for(k=0; k<fScaleSize*fMaxNofSamples; k++) {
           fInZR[k] = fHitMap2->GetSignal(i,k);
-          contrib = baseline + noise*random.Gaus();
+          contrib = (baseline + noise*random.Gaus());
           fInZR[k] += contrib;
        }
        for(k=0; k<fMaxNofSamples; k++) {
-          Float_t newcont = 0.;
-          Float_t maxcont = 0.;
+          Double_t newcont = 0.;
+          Double_t maxcont = 0.;
           for(kk=0;kk<fScaleSize;kk++) {
+            
             newcont = fInZR[fScaleSize*k+kk];
             if(newcont > maxcont) maxcont = newcont;
+            
+            //newcont += (fInZR[fScaleSize*k+kk]/fScaleSize);
           }
           newcont = maxcont;
-          Double_t signal = newcont*norm;
-          if (signal >= maxadc) signal = maxadc -1;
+          if (newcont >= maxadc) newcont = maxadc -1;
+          if(newcont >= baseline) cout << "newcont: " << newcont << endl;
           // back to analog: ?
-          signal /=norm;
-          fHitMap2->SetHit(i,k,signal);
+          fHitMap2->SetHit(i,k,newcont);
        }  
     } // loop over anodes
     return;
@@ -849,7 +926,7 @@ void AliITSsimulationSDD::ChargeToSignal() {
       if  (read && i<fNofMaps) GetAnodeBaseline(i,baseline,noise);
       for(k=0; k<fScaleSize*fMaxNofSamples; k++) {
        fInZR[k] = fHitMap2->GetSignal(i,k);
-       contrib = baseline + noise*random.Gaus();
+       contrib = (baseline + noise*random.Gaus());
        fInZR[k] += contrib;
        fInZI[k] = 0.;
       }
@@ -862,22 +939,19 @@ void AliITSsimulationSDD::ChargeToSignal() {
       }
       FastFourierTransform(fElectronics,&fOutZR[0],&fOutZI[0],-1);
       for(k=0; k<fMaxNofSamples; k++) {
-       Float_t newcont = 0.;
-       //Float_t totcont = 0.;
-       Float_t maxcont = 0.;
+       Double_t newcont1 = 0.;
+       Double_t maxcont1 = 0.;
        for(kk=0;kk<fScaleSize;kk++) {
-         newcont = fOutZR[fScaleSize*k+kk];
-         if(newcont > maxcont) maxcont = newcont;
-         //      totcont += (0.25*Out_ZR[4*k+kk]);
+         
+         newcont1 = fOutZR[fScaleSize*k+kk];
+         if(newcont1 > maxcont1) maxcont1 = newcont1;
+         
+         //newcont1 += (fInZR[fScaleSize*k+kk]/fScaleSize);
        }
-       newcont = maxcont;
-       Double_t signal = newcont*norm;
-       if (signal >= maxadc) signal = maxadc -1;
-       // back to analog: ?
-       // comment the line below because you want to keep the signal in ADCs
-       // convert back to nA in cluster finder
-       signal /=norm;
-       fHitMap2->SetHit(i,k,signal);
+       newcont1 = maxcont1;
+       //cout << "newcont1: " << newcont1 << endl;
+       if (newcont1 >= maxadc) newcont1 = maxadc -1;
+       fHitMap2->SetHit(i,k,newcont1);
       }      
   } // loop over anodes
   return;
@@ -1137,7 +1211,7 @@ void AliITSsimulationSDD::Compress2D(){
                nh++;
                Bool_t cond=kTRUE;
                FindCluster(i,j,signal,minval,cond);
-               if (cond && ((TMath::Abs(fHitMap2->GetSignal(i,j-1))-th)>=minval)) {
+               if (cond && j && ((TMath::Abs(fHitMap2->GetSignal(i,j-1))-th)>=minval)) {
                  if(do10to8) signal = Convert10to8(signal);
                  AddDigit(i,j,signal);
                }
@@ -1392,8 +1466,8 @@ void AliITSsimulationSDD::CreateHistograms(Int_t scale){
       Int_t i;
 
       fHis=new TObjArray(fNofMaps);
-      TString sddName("sdd_");
       for (i=0;i<fNofMaps;i++) {
+          TString sddName("sdd_");
           Char_t candNum[4];
           sprintf(candNum,"%d",i+1);
           sddName.Append(candNum);
@@ -1519,3 +1593,21 @@ Float_t AliITSsimulationSDD::GetNoise() {
   delete noisehist;
   return rnoise;
 }
+
+//____________________________________________
+
+void AliITSsimulationSDD::Print() {
+
+  // Print SDD simulation Parameters
+
+   cout << "**************************************************" << endl;
+   cout << "   Silicon Drift Detector Simulation Parameters   " << endl;
+   cout << "**************************************************" << endl;
+   cout << "Flag for Perpendicular tracks: " << (Int_t) fFlag << endl;
+   cout << "Flag for noise checking: " << (Int_t) fCheckNoise << endl;
+   cout << "Flag to switch off electronics: " << (Int_t) fDoFFT << endl;
+   cout << "Number pf Anodes used: " << fNofMaps << endl;
+   cout << "Number of Time Samples: " << fMaxNofSamples << endl;
+   cout << "Scale size factor: " << fScaleSize << endl;
+   cout << "**************************************************" << endl;
+}