]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDdigitizer.cxx
bc0f6c222bafa7b851cd952d256656388a6bdb3b
[u/mrichter/AliRoot.git] / TRD / AliTRDdigitizer.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  Creates and handles digits from TRD hits                                 //
21 //  Author: C. Blume (C.Blume@gsi.de)                                        //
22 //                                                                           //
23 //  The following effects are included:                                      //
24 //      - Diffusion                                                          //
25 //      - ExB effects                                                        //
26 //      - Gas gain including fluctuations                                    //
27 //      - Pad-response (simple Gaussian approximation)                       //
28 //      - Time-response                                                      //
29 //      - Electronics noise                                                  //
30 //      - Electronics gain                                                   //
31 //      - Digitization                                                       //
32 //      - ADC threshold                                                      //
33 //  The corresponding parameter can be adjusted via the various              //
34 //  Set-functions. If these parameters are not explicitly set, default       //
35 //  values are used (see Init-function).                                     //
36 //  As an example on how to use this class to produce digits from hits       //
37 //  have a look at the macro hits2digits.C                                   //
38 //  The production of summable digits is demonstrated in hits2sdigits.C      //
39 //  and the subsequent conversion of the s-digits into normal digits is      //
40 //  explained in sdigits2digits.C.                                           //
41 //                                                                           //
42 ///////////////////////////////////////////////////////////////////////////////
43
44 #include <stdlib.h>
45
46 #include <TMath.h>
47 #include <TVector.h>
48 #include <TRandom.h>
49 #include <TROOT.h>
50 #include <TTree.h>
51 #include <TFile.h>
52 #include <TF1.h>
53 #include <TList.h>
54 #include <TTask.h>
55
56 #include "AliRun.h"
57 #include "AliRunLoader.h"
58 #include "AliLoader.h"
59 #include "AliConfig.h"
60 #include "AliMagF.h"
61 #include "AliRunDigitizer.h"
62 #include "AliRunLoader.h"
63 #include "AliLoader.h"
64
65 #include "AliTRD.h"
66 #include "AliTRDhit.h"
67 #include "AliTRDdigitizer.h"
68 #include "AliTRDdataArrayI.h"
69 #include "AliTRDdataArrayF.h"
70 #include "AliTRDsegmentArray.h"
71 #include "AliTRDdigitsManager.h"
72 #include "AliTRDgeometry.h"
73 #include "AliTRDparameter.h"
74
75 ClassImp(AliTRDdigitizer)
76
77 //_____________________________________________________________________________
78 AliTRDdigitizer::AliTRDdigitizer()
79 {
80   //
81   // AliTRDdigitizer default constructor
82   //
83
84   fRunLoader          = 0;
85   fDigitsManager      = 0;
86   fSDigitsManager     = 0;
87   fSDigitsManagerList = 0;
88   fTRD                = 0;
89   fGeo                = 0;
90   fPar                = 0;
91   fEvent              = 0;
92   fMasks              = 0;
93   fCompress           = kTRUE;
94   fDebug              = 0;
95   fSDigits            = kFALSE;
96   fSDigitsScale       = 0.0;
97   fMergeSignalOnly    = kFALSE;
98   fSimpleSim          = kFALSE;
99   fSimpleDet          = 0;
100  
101 }
102
103 //_____________________________________________________________________________
104 AliTRDdigitizer::AliTRDdigitizer(const Text_t *name, const Text_t *title)
105                 :AliDigitizer(name,title)
106 {
107   //
108   // AliTRDdigitizer constructor
109   //
110
111   fRunLoader          = 0;
112
113   //NewIO: These data members probably are not needed anymore
114   fDigitsManager      = 0;
115   fSDigitsManager     = 0;
116   fSDigitsManagerList = 0;
117   fTRD                = 0;
118   fGeo                = 0;
119   fPar                = 0;
120   //End NewIO comment
121   fEvent              = 0;
122   fMasks              = 0;
123   fCompress           = kTRUE;
124   fDebug              = 0;
125   fSDigits            = kFALSE;
126   fSDigitsScale       = 100.; // For the summable digits
127   fMergeSignalOnly    = kFALSE;
128   fSimpleSim          = kFALSE;
129   fSimpleDet          = 0;
130  
131
132 }
133
134 //_____________________________________________________________________________
135 AliTRDdigitizer::AliTRDdigitizer(AliRunDigitizer *manager
136                                 , const Text_t *name, const Text_t *title)
137                 :AliDigitizer(manager,name,title)
138 {
139   //
140   // AliTRDdigitizer constructor
141   //
142
143   fRunLoader          = 0;
144   fDigitsManager      = 0;
145   fSDigitsManager     = 0;
146   fSDigitsManagerList = 0;
147   fTRD                = 0;
148   fGeo                = 0;
149   fPar                = 0;
150   fEvent              = 0;
151   fMasks              = 0;
152   fCompress           = kTRUE;
153   fDebug              = 0;
154   fSDigits            = kFALSE;
155   fSDigitsScale       = 100.; // For the summable digits
156   fMergeSignalOnly    = kFALSE;
157   fSimpleSim          = kFALSE;
158   fSimpleDet          = 0;
159  
160
161 }
162
163 //_____________________________________________________________________________
164 AliTRDdigitizer::AliTRDdigitizer(AliRunDigitizer *manager)
165                 :AliDigitizer(manager,"AliTRDdigitizer","TRD digitizer")
166 {
167   //
168   // AliTRDdigitizer constructor
169   //
170
171
172   fRunLoader          = 0;
173   fDigitsManager      = 0;
174   fSDigitsManager     = 0;
175   fSDigitsManagerList = 0;
176   fTRD                = 0;
177   fGeo                = 0;
178   fPar                = 0;
179   fEvent              = 0;
180   fMasks              = 0;
181   fCompress           = kTRUE;
182   fDebug              = 0;
183   fSDigits            = kFALSE;
184   fSDigitsScale       = 100.;  // For the summable digits
185   fMergeSignalOnly    = kFALSE;
186   fSimpleSim          = kFALSE;
187   fSimpleDet          = 0;
188
189
190 }
191
192 //_____________________________________________________________________________
193 AliTRDdigitizer::AliTRDdigitizer(const AliTRDdigitizer &d):AliDigitizer(d)
194 {
195   //
196   // AliTRDdigitizer copy constructor
197   //
198
199   ((AliTRDdigitizer &) d).Copy(*this);
200
201 }
202
203 //_____________________________________________________________________________
204 AliTRDdigitizer::~AliTRDdigitizer()
205 {
206   //
207   // AliTRDdigitizer destructor
208   //
209
210
211   if (fDigitsManager) {
212     delete fDigitsManager;
213     fDigitsManager = 0;
214   }
215
216   if (fSDigitsManager) {
217     delete fSDigitsManager;
218     fSDigitsManager = 0;
219   }
220
221   if (fSDigitsManagerList) {
222     delete fSDigitsManagerList;
223     fSDigitsManagerList = 0;
224   }
225
226   if (fMasks) {
227     delete [] fMasks;
228     fMasks = 0;
229   }
230
231 }
232
233 //_____________________________________________________________________________
234 AliTRDdigitizer &AliTRDdigitizer::operator=(const AliTRDdigitizer &d)
235 {
236   //
237   // Assignment operator
238   //
239
240   if (this != &d) ((AliTRDdigitizer &) d).Copy(*this);
241   return *this;
242
243 }
244
245 //_____________________________________________________________________________
246 void AliTRDdigitizer::Copy(TObject &d)
247 {
248   //
249   // Copy function
250   //
251
252   ((AliTRDdigitizer &) d).fRunLoader          = 0;
253   ((AliTRDdigitizer &) d).fDigitsManager      = 0;
254   ((AliTRDdigitizer &) d).fSDigitsManager     = 0;
255   ((AliTRDdigitizer &) d).fSDigitsManagerList = 0;
256   ((AliTRDdigitizer &) d).fTRD                = 0;
257   ((AliTRDdigitizer &) d).fGeo                = 0;
258   ((AliTRDdigitizer &) d).fPar                = 0;
259   ((AliTRDdigitizer &) d).fEvent              = 0;
260   ((AliTRDdigitizer &) d).fMasks              = 0;
261   ((AliTRDdigitizer &) d).fCompress           = fCompress;
262   ((AliTRDdigitizer &) d).fDebug              = fDebug  ;
263   ((AliTRDdigitizer &) d).fSDigits            = fSDigits;
264   ((AliTRDdigitizer &) d).fSDigitsScale       = fSDigitsScale;
265   ((AliTRDdigitizer &) d).fMergeSignalOnly    = fMergeSignalOnly;
266   ((AliTRDdigitizer &) d).fSimpleSim          = fSimpleSim;
267   ((AliTRDdigitizer &) d).fSimpleDet          = fSimpleDet;
268                                        
269 }
270
271 //_____________________________________________________________________________
272 void AliTRDdigitizer::Exec(Option_t* option)
273 {
274   //
275   // Executes the merging
276   //
277
278   Int_t iInput;
279
280   AliTRDdigitsManager *sdigitsManager;
281
282   TString optionString = option;
283   if (optionString.Contains("deb")) {
284     fDebug = 1;
285     if (optionString.Contains("2")) {
286       fDebug = 2;
287     }
288     printf("<AliTRDdigitizer::Exec> ");
289     printf("Called with debug option %d\n",fDebug);
290   }
291
292   // The AliRoot file is already connected by the manager
293   AliRunLoader* inrl;
294   
295   if (gAlice) 
296    {
297     if (fDebug > 0) {
298       printf("<AliTRDdigitizer::Exec> ");
299       printf("AliRun object found on file.\n");
300     }
301    }
302   else {
303     inrl = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(0));
304     inrl->LoadgAlice();
305     gAlice = inrl->GetAliRun();
306     if (!gAlice)
307      {
308        printf("<AliTRDdigitizer::Exec> ");
309        printf("Could not find AliRun object.\n");
310        return;
311      }
312   }
313                                                                            
314   Int_t nInput = fManager->GetNinputs();
315   fMasks = new Int_t[nInput];
316   for (iInput = 0; iInput < nInput; iInput++) {
317     fMasks[iInput] = fManager->GetMask(iInput);
318   }
319
320   // Initialization
321
322   AliRunLoader* orl = AliRunLoader::GetRunLoader(fManager->GetOutputFolderName());
323   if (InitDetector()) {
324     AliLoader* ogime = orl->GetLoader("TRDLoader");
325
326     TTree* tree = 0;
327     if (fSDigits)
328       { 
329         //if we produce SDigits
330         tree = ogime->TreeS();
331         if (!tree)
332           {
333             ogime->MakeTree("S");
334             tree = ogime->TreeS();
335           }
336       }
337     else
338       {//if we produce Digits
339         tree = ogime->TreeD();
340         if (!tree)
341           {
342             ogime->MakeTree("D");
343             tree = ogime->TreeD();
344           }
345       }
346     MakeBranch(tree);
347   }
348  
349   for (iInput = 0; iInput < nInput; iInput++) {
350
351     if (fDebug > 0) {
352       printf("<AliTRDdigitizer::Exec> ");
353       printf("Add input stream %d\n",iInput);
354     }
355
356     // check if the input tree exists
357     inrl = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(iInput));
358     AliLoader* gime = inrl->GetLoader("TRDLoader");
359
360     TTree * treees =  gime->TreeS();
361     if (treees == 0x0) 
362      {
363       if (gime->LoadSDigits())
364        {
365          Error("Exec","Error Occured while loading S. Digits for input %d.",iInput);
366          return;
367        }
368       treees =  gime->TreeS();
369      }
370     
371     if (treees == 0x0) {
372       printf("<AliTRDdigitizer::Exec> ");
373       printf("Input stream %d does not exist\n",iInput);
374       return;
375     } 
376
377     // Read the s-digits via digits manager
378     sdigitsManager = new AliTRDdigitsManager();
379     sdigitsManager->SetDebug(fDebug);
380     sdigitsManager->SetSDigits(kTRUE);
381     
382     AliRunLoader* rl = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(iInput));
383     AliLoader* gimme = rl->GetLoader("TRDLoader");
384     if (!gimme->TreeS()) gimme->LoadSDigits();
385     sdigitsManager->ReadDigits(gimme->TreeS());
386
387     // Add the s-digits to the input list 
388     AddSDigitsManager(sdigitsManager);
389
390   }
391
392   // Convert the s-digits to normal digits
393   if (fDebug > 0) {
394     printf("<AliTRDdigitizer::Exec> ");
395     printf("Do the conversion\n");
396   }
397   SDigits2Digits();
398
399   // Store the digits
400   if (fDebug > 0) {
401     printf("<AliTRDdigitizer::Exec> ");
402     printf("Write the digits\n");
403   }
404   
405   fDigitsManager->WriteDigits();
406
407   //Write parameters
408   orl->CdGAFile();
409   GetParameter()->Write();
410
411   if (fDebug > 0) {
412     printf("<AliTRDdigitizer::Exec> ");
413     printf("Done\n");
414   }
415
416   DeleteSDigitsManager();
417
418 }
419
420 //_____________________________________________________________________________
421 Bool_t AliTRDdigitizer::Open(const Char_t *file, Int_t nEvent)
422 {
423   //
424   // Opens a ROOT-file with TRD-hits and reads in the hit-tree
425   //
426
427   // Connect the AliRoot file containing Geometry, Kine, and Hits
428   
429   fRunLoader = AliRunLoader::Open(file,AliConfig::fgkDefaultEventFolderName,
430                                   "UPDATE");
431   
432   if (!fRunLoader)
433    {
434      Error("Open","Can not open session for file %s.",file);
435      return kFALSE;
436    }
437    
438   fRunLoader->LoadgAlice();
439   gAlice = fRunLoader->GetAliRun();
440   
441   if (gAlice) {
442     if (fDebug > 0) {
443       printf("<AliTRDdigitizer::Open> ");
444       printf("AliRun object found on file.\n");
445     }
446   }
447   else {
448     printf("<AliTRDdigitizer::Open> ");
449     printf("Could not find AliRun object.\n");
450     return kFALSE;
451   }
452
453   fEvent = nEvent;
454
455   // Import the Trees for the event nEvent in the file
456   fRunLoader->GetEvent(fEvent);
457   
458   AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
459   if (!loader)
460    {
461      Error("Open","Can not get TRD loader from Run Loader");
462      return kFALSE;
463    }
464   
465   if (InitDetector()) {
466     TTree* tree = 0;
467     if (fSDigits)
468      { 
469      //if we produce SDigits
470        tree = loader->TreeS();
471        if (!tree)
472         {
473          loader->MakeTree("S");
474          tree = loader->TreeS();
475         }
476      }
477     else
478      {//if we produce Digits
479        tree = loader->TreeD();
480        if (!tree)
481         {
482          loader->MakeTree("D");
483          tree = loader->TreeD();
484         }
485      }
486     return MakeBranch(tree);
487   }
488   else {
489     return kFALSE;
490   }
491
492 }
493
494 //_____________________________________________________________________________
495 Bool_t AliTRDdigitizer::InitDetector()
496 {
497   //
498   // Sets the pointer to the TRD detector and the geometry
499   //
500
501   // Get the pointer to the detector class and check for version 1
502   fTRD = (AliTRD *) gAlice->GetDetector("TRD");
503   if (!fTRD) {
504     printf("<AliTRDdigitizer::InitDetector> ");
505     printf("No TRD module found\n");
506     exit(1);
507   }
508   if (fTRD->IsVersion() != 1) {
509     printf("<AliTRDdigitizer::InitDetector> ");
510     printf("TRD must be version 1 (slow simulator).\n");
511     exit(1);
512   }
513
514   // Get the geometry
515   fGeo = fTRD->GetGeometry();
516   if (fDebug > 0) {
517     printf("<AliTRDdigitizer::InitDetector> ");
518     printf("Geometry version %d\n",fGeo->IsVersion());
519   }
520
521   // Create a digits manager
522   fDigitsManager = new AliTRDdigitsManager();
523   fDigitsManager->SetSDigits(fSDigits);
524   fDigitsManager->CreateArrays();
525   fDigitsManager->SetEvent(fEvent);
526   fDigitsManager->SetDebug(fDebug);
527
528   // The list for the input s-digits manager to be merged
529   fSDigitsManagerList = new TList();
530
531   return kTRUE;
532
533 }
534
535 //_____________________________________________________________________________
536 Bool_t AliTRDdigitizer::MakeBranch(TTree* tree) const
537 {
538   // 
539   // Create the branches for the digits array
540   //
541
542   return fDigitsManager->MakeBranch(tree);
543
544 }
545
546 //_____________________________________________________________________________
547 Bool_t AliTRDdigitizer::MakeDigits()
548 {
549   //
550   // Creates digits.
551   //
552
553   ///////////////////////////////////////////////////////////////
554   // Parameter 
555   ///////////////////////////////////////////////////////////////
556
557   // Converts number of electrons to fC
558   const Double_t kEl2fC  = 1.602E-19 * 1.0E15; 
559
560   ///////////////////////////////////////////////////////////////
561
562   // Number of pads included in the pad response
563   const Int_t kNpad  = 3;
564
565   // Number of track dictionary arrays
566   const Int_t kNDict = AliTRDdigitsManager::kNDict;
567
568   // Half the width of the amplification region
569   const Float_t kAmWidth = AliTRDgeometry::AmThick() / 2.;
570
571   Int_t   iRow, iCol, iTime, iPad;
572   Int_t   iDict  = 0;
573   Int_t   nBytes = 0;
574
575   Int_t   totalSizeDigits = 0;
576   Int_t   totalSizeDict0  = 0;
577   Int_t   totalSizeDict1  = 0;
578   Int_t   totalSizeDict2  = 0;
579
580   Int_t   timeTRDbeg = 0;
581   Int_t   timeTRDend = 1;
582
583   Float_t pos[3];
584   Float_t rot[3];
585   Float_t xyz[3];
586   Float_t padSignal[kNpad];
587   Float_t signalOld[kNpad];
588
589   AliTRDdataArrayF *signals = 0;
590   AliTRDdataArrayI *digits  = 0;
591   AliTRDdataArrayI *dictionary[kNDict];
592
593   // Create a default parameter class if none is defined
594   if (!fPar) {
595     fPar = new AliTRDparameter("TRDparameter","Standard TRD parameter");
596     if (fDebug > 0) {
597       printf("<AliTRDdigitizer::MakeDigits> ");
598       printf("Create the default parameter object\n");
599     }
600   }
601
602   // Create a container for the amplitudes
603   AliTRDsegmentArray *signalsArray 
604                      = new AliTRDsegmentArray("AliTRDdataArrayF"
605                                              ,AliTRDgeometry::Ndet());
606
607   if (fPar->TRFOn()) {
608     timeTRDbeg = ((Int_t) (-fPar->GetTRFlo() / fPar->GetTimeBinSize())) - 1;
609     timeTRDend = ((Int_t) ( fPar->GetTRFhi() / fPar->GetTimeBinSize())) - 1;
610     if (fDebug > 0) {
611       printf("<AliTRDdigitizer::MakeDigits> ");
612       printf("Sample the TRF between -%d and %d\n",timeTRDbeg,timeTRDend);
613     }
614   }
615
616   Float_t elAttachProp = fPar->GetElAttachProp() / 100.; 
617
618   if (!fGeo) {
619     printf("<AliTRDdigitizer::MakeDigits> ");
620     printf("No geometry defined\n");
621     return kFALSE;
622   }
623
624   if (fDebug > 0) {
625     printf("<AliTRDdigitizer::MakeDigits> ");
626     printf("Start creating digits.\n");
627   }
628
629   AliLoader* gimme = fRunLoader->GetLoader("TRDLoader");
630   if (!gimme->TreeH()) gimme->LoadHits();
631   TTree* hitTree = gimme->TreeH();
632   if (hitTree == 0x0)
633     {
634       Error("MakeDigits","Can not get TreeH");
635       return kFALSE;
636     }
637   fTRD->SetTreeAddress();
638   
639   // Get the number of entries in the hit tree
640   // (Number of primary particles creating a hit somewhere)
641   Int_t nTrack = 1;
642   if (!fSimpleSim) {
643     nTrack = (Int_t) hitTree->GetEntries();
644     if (fDebug > 0) {
645       printf("<AliTRDdigitizer::MakeDigits> ");
646       printf("Found %d primary particles\n",nTrack);
647     } 
648   }
649
650   Int_t detectorOld = -1;
651   Int_t countHits   =  0; 
652
653   // Loop through all entries in the tree
654   for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
655
656     if (!fSimpleSim) {   
657       gAlice->ResetHits();
658       nBytes += hitTree->GetEvent(iTrack);
659     }
660
661     // Loop through the TRD hits
662     Int_t iHit = 0;
663     AliTRDhit *hit = (AliTRDhit *) fTRD->FirstHit(-1);
664     while (hit) {
665  
666       countHits++;
667       iHit++;
668
669               pos[0]      = hit->X();
670               pos[1]      = hit->Y();
671               pos[2]      = hit->Z();
672       Float_t q           = hit->GetCharge();
673       Int_t   track       = hit->Track();
674       Int_t   detector    = hit->GetDetector();
675       Int_t   plane       = fGeo->GetPlane(detector);
676       Int_t   sector      = fGeo->GetSector(detector);
677       Int_t   chamber     = fGeo->GetChamber(detector);
678       Int_t   nRowMax     = fPar->GetRowMax(plane,chamber,sector);
679       Int_t   nColMax     = fPar->GetColMax(plane);
680       Int_t   nTimeMax    = fPar->GetTimeMax();
681       Int_t   nTimeBefore = fPar->GetTimeBefore();
682       Int_t   nTimeAfter  = fPar->GetTimeAfter();
683       Int_t   nTimeTotal  = fPar->GetTimeTotal();
684       Float_t row0        = fPar->GetRow0(plane,chamber,sector);
685       Float_t col0        = fPar->GetCol0(plane);
686       Float_t time0       = fPar->GetTime0(plane);
687       Float_t rowPadSize  = fPar->GetRowPadSize(plane,chamber,sector);
688       Float_t colPadSize  = fPar->GetColPadSize(plane);
689       Float_t timeBinSize = fPar->GetTimeBinSize();
690       Float_t divideRow   = 1.0 / rowPadSize;
691       Float_t divideCol   = 1.0 / colPadSize;
692       Float_t divideTime  = 1.0 / timeBinSize;
693
694       if (fDebug > 1) {
695         printf("Analyze hit no. %d ",iHit);
696         printf("-----------------------------------------------------------\n");
697         hit->Dump();
698         printf("plane = %d, sector = %d, chamber = %d\n"
699               ,plane,sector,chamber);
700         printf("nRowMax = %d, nColMax = %d, nTimeMax = %d\n" 
701               ,nRowMax,nColMax,nTimeMax);
702         printf("nTimeBefore = %d, nTimeAfter = %d, nTimeTotal = %d\n"
703               ,nTimeBefore,nTimeAfter,nTimeTotal);
704         printf("row0 = %f, col0 = %f, time0 = %f\n"
705               ,row0,col0,time0);
706         printf("rowPadSize = %f, colPadSize = %f, timeBinSize = %f\n"
707                ,rowPadSize,colPadSize,timeBinSize); 
708       }
709        
710       // Don't analyze test hits and switched off detectors
711       if ((CheckDetector(plane,chamber,sector)) &&
712           (((Int_t) q) != 0)) {
713
714         if (detector != detectorOld) {
715
716           if (fDebug > 1) {
717             printf("<AliTRDdigitizer::MakeDigits> ");
718             printf("Get new container. New det = %d, Old det = %d\n"
719                   ,detector,detectorOld);
720           }
721           // Compress the old one if enabled
722           if ((fCompress) && (detectorOld > -1)) {
723             if (fDebug > 1) {
724               printf("<AliTRDdigitizer::MakeDigits> ");
725               printf("Compress the old container ...");
726             }
727             signals->Compress(1,0);
728             for (iDict = 0; iDict < kNDict; iDict++) {
729               dictionary[iDict]->Compress(1,0);
730             }
731             if (fDebug > 1) printf("done\n");
732           }
733           // Get the new container
734           signals = (AliTRDdataArrayF *) signalsArray->At(detector);
735           if (signals->GetNtime() == 0) {
736             // Allocate a new one if not yet existing
737             if (fDebug > 1) {
738               printf("<AliTRDdigitizer::MakeDigits> ");
739               printf("Allocate a new container ... ");
740             }
741             signals->Allocate(nRowMax,nColMax,nTimeTotal);
742           }
743           else if (fSimpleSim) {
744             // Clear an old one for the simple simulation
745             if (fDebug > 1) {
746               printf("<AliTRDdigitizer::MakeDigits> ");
747               printf("Clear a old container ... ");
748             }
749             signals->Clear();
750           }
751           else {
752             // Expand an existing one
753             if (fCompress) {
754               if (fDebug > 1) {
755                 printf("<AliTRDdigitizer::MakeDigits> ");
756                 printf("Expand an existing container ... ");
757               }
758               signals->Expand();
759             }
760           }
761           // The same for the dictionary
762           if (!fSimpleSim) {       
763             for (iDict = 0; iDict < kNDict; iDict++) {       
764               dictionary[iDict] = fDigitsManager->GetDictionary(detector,iDict);
765               if (dictionary[iDict]->GetNtime() == 0) {
766                 dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeTotal);
767               }
768               else {
769                 if (fCompress) dictionary[iDict]->Expand();
770               }
771             }
772           }      
773           if (fDebug > 1) printf("done\n");
774           detectorOld = detector;
775         }
776
777         // Rotate the sectors on top of each other
778         if (fSimpleSim) {
779           rot[0] = pos[0];
780           rot[1] = pos[1];
781           rot[2] = pos[2];
782         }
783         else {
784           fGeo->Rotate(detector,pos,rot);
785         }
786
787         // The driftlength. It is negative if the hit is in the 
788         // amplification region.
789         Float_t driftlength = time0 - rot[0];
790
791         // Take also the drift in the amplification region into account
792         // The drift length is at the moment still the same, regardless of
793         // the position relativ to the wire. This non-isochronity needs still
794         // to be implemented.
795         Float_t driftlengthL = TMath::Abs(driftlength + kAmWidth);
796         if (fPar->ExBOn()) driftlengthL /= TMath::Sqrt(fPar->GetLorentzFactor());
797
798         // Loop over all electrons of this hit
799         // TR photons produce hits with negative charge
800         Int_t nEl = ((Int_t) TMath::Abs(q));
801         for (Int_t iEl = 0; iEl < nEl; iEl++) {
802
803           xyz[0] = rot[0];
804           xyz[1] = rot[1];
805           xyz[2] = rot[2];
806
807           // Electron attachment
808           if (fPar->ElAttachOn()) {
809             if (gRandom->Rndm() < (driftlengthL * elAttachProp)) 
810               continue;
811           }
812
813           // Apply the diffusion smearing
814           if (fPar->DiffusionOn()) {
815             if (!(fPar->Diffusion(driftlengthL,xyz))) continue;
816           }
817
818           // Apply E x B effects (depends on drift direction)
819           if (fPar->ExBOn()) { 
820             if (!(fPar->ExB(driftlength+kAmWidth,xyz))) continue;   
821           }
822
823           // The electron position after diffusion and ExB in pad coordinates 
824           // The pad row (z-direction)
825           Float_t rowDist   = xyz[2] - row0;
826           Int_t   rowE      = ((Int_t) (rowDist * divideRow));
827           if ((rowE < 0) || (rowE >= nRowMax)) continue;   
828           Float_t rowOffset = ((((Float_t) rowE) + 0.5) * rowPadSize) - rowDist;
829
830           // The pad column (rphi-direction)
831           Float_t col0tilt  = fPar->Col0Tilted(col0,rowOffset,plane);
832           Float_t colDist   = xyz[1] - col0tilt;
833           Int_t   colE      = ((Int_t) (colDist * divideCol));
834           if ((colE < 0) || (colE >= nColMax)) continue;   
835           Float_t colOffset = ((((Float_t) colE) + 0.5) * colPadSize) - colDist;    
836
837           // The time bin (negative for hits in the amplification region)
838           // In the amplification region the electrons drift from both sides
839           // to the middle (anode wire plane)
840           Float_t timeDist   = time0 - xyz[0];
841           Float_t timeOffset = 0;
842           Int_t   timeE      = 0;
843           if (timeDist > 0) {
844             // The time bin
845             timeE      = ((Int_t) (timeDist * divideTime));
846             // The distance of the position to the middle of the timebin
847             timeOffset = ((((Float_t) timeE) + 0.5) * timeBinSize) - timeDist;
848           }
849           else {
850             // Difference between half of the amplification gap width and
851             // the distance to the anode wire
852             Float_t anodeDist = kAmWidth - TMath::Abs(timeDist + kAmWidth);
853             // The time bin
854             timeE      = -1 * (((Int_t ) (anodeDist * divideTime)) + 1);
855             // The distance of the position to the middle of the timebin
856             timeOffset = ((((Float_t) timeE) + 0.5) * timeBinSize) + anodeDist;
857           }
858  
859           // Apply the gas gain including fluctuations
860           Float_t ggRndm = 0.0;
861           do {
862             ggRndm = gRandom->Rndm();
863           } while (ggRndm <= 0);
864           Int_t signal = (Int_t) (-fPar->GetGasGain() * TMath::Log(ggRndm));
865
866           // Apply the pad response 
867           if (fPar->PRFOn()) {
868             // The distance of the electron to the center of the pad 
869             // in units of pad width
870             Float_t dist = - colOffset * divideCol;
871             if (!(fPar->PadResponse(signal,dist,plane,padSignal))) continue;
872           }
873           else {
874             padSignal[0] = 0.0;
875             padSignal[1] = signal;
876             padSignal[2] = 0.0;
877           }
878
879           // Sample the time response inside the drift region
880           // + additional time bins before and after.
881           // The sampling is done always in the middle of the time bin
882           for (Int_t iTimeBin = TMath::Max(timeE-timeTRDbeg,        -nTimeBefore) 
883                     ;iTimeBin < TMath::Min(timeE+timeTRDend,nTimeMax+nTimeAfter ) 
884                     ;iTimeBin++) {
885
886             // Apply the time response
887             Float_t timeResponse = 1.0;
888             Float_t crossTalk    = 0.0;
889             Float_t time         = (iTimeBin - timeE) * timeBinSize + timeOffset;
890             if (fPar->TRFOn()) {
891               timeResponse = fPar->TimeResponse(time);
892             }
893             if (fPar->CTOn()) {
894               crossTalk    = fPar->CrossTalk(time);
895             }
896
897             signalOld[0] = 0.0;
898             signalOld[1] = 0.0;
899             signalOld[2] = 0.0;
900
901             for (iPad = 0; iPad < kNpad; iPad++) {
902
903               Int_t colPos = colE + iPad - 1;
904               if (colPos <        0) continue;
905               if (colPos >= nColMax) break;
906
907               // Add the signals
908               // Note: The time bin number is shifted by nTimeBefore to avoid negative
909               // time bins. This has to be subtracted later.
910               Int_t iCurrentTimeBin = iTimeBin + nTimeBefore;
911               signalOld[iPad]  = signals->GetDataUnchecked(rowE,colPos,iCurrentTimeBin);
912               if( colPos != colE ) {
913                 signalOld[iPad] += padSignal[iPad] * (timeResponse + crossTalk);
914               } 
915               else {
916                 signalOld[iPad] += padSignal[iPad] * timeResponse;
917               }
918               signals->SetDataUnchecked(rowE,colPos,iCurrentTimeBin,signalOld[iPad]);
919
920               // Store the track index in the dictionary
921               // Note: We store index+1 in order to allow the array to be compressed
922               if ((signalOld[iPad] > 0) && (!fSimpleSim)) { 
923                 for (iDict = 0; iDict < kNDict; iDict++) {
924                   Int_t oldTrack = dictionary[iDict]->GetDataUnchecked(rowE
925                                                                       ,colPos
926                                                                       ,iCurrentTimeBin);
927                   if (oldTrack == track+1) break;
928                   if (oldTrack ==       0) {
929                     dictionary[iDict]->SetDataUnchecked(rowE,colPos,iCurrentTimeBin,track+1);
930                     break;
931                   }
932                 }
933               }
934
935             } // Loop: pads
936
937           } // Loop: time bins
938
939         } // Loop: electrons of a single hit
940
941       } // If: detector and test hit
942
943       hit = (AliTRDhit *) fTRD->NextHit();   
944
945     } // Loop: hits of one primary track
946
947   } // Loop: primary tracks
948
949   if (fDebug > 0) {
950     printf("<AliTRDdigitizer::MakeDigits> ");
951     printf("Finished analyzing %d hits\n",countHits);
952   }
953
954   // The coupling factor
955   Float_t coupling = fPar->GetPadCoupling() 
956                    * fPar->GetTimeCoupling();
957
958   // The conversion factor
959   Float_t convert  = kEl2fC
960                    * fPar->GetChipGain();
961
962   // Loop through all chambers to finalize the digits
963   Int_t iDetBeg = 0;
964   Int_t iDetEnd = AliTRDgeometry::Ndet();
965   if (fSimpleSim) {
966     iDetBeg = fSimpleDet;
967     iDetEnd = iDetBeg + 1;
968   }
969   for (Int_t iDet = iDetBeg; iDet < iDetEnd; iDet++) {
970
971     Int_t plane       = fGeo->GetPlane(iDet);
972     Int_t sector      = fGeo->GetSector(iDet);
973     Int_t chamber     = fGeo->GetChamber(iDet);
974     Int_t nRowMax     = fPar->GetRowMax(plane,chamber,sector);
975     Int_t nColMax     = fPar->GetColMax(plane);
976     Int_t nTimeMax    = fPar->GetTimeMax();
977     Int_t nTimeTotal  = fPar->GetTimeTotal();
978
979     Double_t *inADC  = new Double_t[nTimeTotal];
980     Double_t *outADC = new Double_t[nTimeTotal];
981
982     if (fDebug > 0) {
983       printf("<AliTRDdigitizer::MakeDigits> ");
984       printf("Digitization for chamber %d\n",iDet);
985     }
986
987     // Add a container for the digits of this detector
988     digits = fDigitsManager->GetDigits(iDet);        
989     // Allocate memory space for the digits buffer
990     if (digits->GetNtime() == 0) {
991       digits->Allocate(nRowMax,nColMax,nTimeTotal);
992     }
993     else if (fSimpleSim) {
994       digits->Clear();
995     }
996  
997     // Get the signal container
998     signals = (AliTRDdataArrayF *) signalsArray->At(iDet);
999     if (signals->GetNtime() == 0) {
1000       // Create missing containers
1001       signals->Allocate(nRowMax,nColMax,nTimeTotal);      
1002     }
1003     else {
1004       // Expand the container if neccessary
1005       if (fCompress) signals->Expand();
1006     }
1007     // Create the missing dictionary containers
1008     if (!fSimpleSim) {    
1009       for (iDict = 0; iDict < kNDict; iDict++) {       
1010         dictionary[iDict] = fDigitsManager->GetDictionary(iDet,iDict);
1011         if (dictionary[iDict]->GetNtime() == 0) {
1012           dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeTotal);
1013         }
1014       } 
1015     }
1016
1017     Int_t nDigits = 0;
1018
1019     // Don't create noise in detectors that are switched off
1020     if (CheckDetector(plane,chamber,sector)) {
1021
1022       // Create the digits for this chamber
1023       for (iRow  = 0; iRow  <  nRowMax;   iRow++ ) {
1024         for (iCol  = 0; iCol  <  nColMax;   iCol++ ) {
1025
1026           // Create summable digits
1027           if (fSDigits) {
1028
1029             for (iTime = 0; iTime < nTimeTotal; iTime++) {         
1030               Float_t signalAmp = signals->GetDataUnchecked(iRow,iCol,iTime);
1031               signalAmp *= fSDigitsScale;
1032               signalAmp  = TMath::Min(signalAmp,(Float_t) 1.0e9);
1033               Int_t adc  = (Int_t) signalAmp;
1034               if (adc > 0) nDigits++;
1035               digits->SetDataUnchecked(iRow,iCol,iTime,adc);
1036             }
1037
1038           }
1039           // Create normal digits
1040           else {
1041
1042             for (iTime = 0; iTime < nTimeTotal; iTime++) {         
1043               Float_t signalAmp = signals->GetDataUnchecked(iRow,iCol,iTime);
1044               // Pad and time coupling
1045               signalAmp *= coupling;
1046               // Add the noise, starting from minus ADC baseline in electrons
1047               Double_t baselineEl = fPar->GetADCbaseline() * (fPar->GetADCinRange()
1048                                                            / fPar->GetADCoutRange()) 
1049                                                            / convert;
1050               signalAmp  = TMath::Max((Double_t) gRandom->Gaus(signalAmp,fPar->GetNoise())
1051                                      ,-baselineEl);
1052               // Convert to mV
1053               signalAmp *= convert;
1054               // Add ADC baseline in mV
1055               signalAmp += fPar->GetADCbaseline() * (fPar->GetADCinRange()
1056                                                    / fPar->GetADCoutRange());
1057               // Convert to ADC counts. Set the overflow-bit fADCoutRange if the 
1058               // signal is larger than fADCinRange
1059               Int_t adc  = 0;
1060               if (signalAmp >= fPar->GetADCinRange()) {
1061                 adc = ((Int_t) fPar->GetADCoutRange());
1062               }
1063               else {
1064                 adc = ((Int_t) (signalAmp * (fPar->GetADCoutRange() 
1065                                            / fPar->GetADCinRange())));
1066               }
1067               inADC[iTime]  = adc;
1068               outADC[iTime] = adc;
1069             }
1070
1071             // Apply the tail cancelation via the digital filter
1072             if (fPar->TCOn()) {
1073               DeConvExp(inADC,outADC,nTimeTotal,fPar->GetTCnexp());
1074             }
1075
1076             for (iTime = 0; iTime < nTimeTotal; iTime++) {   
1077               // Store the amplitude of the digit if above threshold
1078               if (outADC[iTime] > fPar->GetADCthreshold()) {
1079                 if (fDebug > 2) {
1080                   printf("  iRow = %d, iCol = %d, iTime = %d, adc = %f\n"
1081                         ,iRow,iCol,iTime,outADC[iTime]);
1082                 }
1083                 nDigits++;
1084                 digits->SetDataUnchecked(iRow,iCol,iTime,((Int_t) outADC[iTime]));
1085               }
1086             }
1087
1088           }
1089
1090         }
1091       }
1092
1093     }
1094
1095     // Compress the arrays
1096     if (!fSimpleSim) {  
1097       digits->Compress(1,0);
1098       for (iDict = 0; iDict < kNDict; iDict++) {
1099         dictionary[iDict]->Compress(1,0);
1100       }
1101
1102       totalSizeDigits += digits->GetSize();
1103       totalSizeDict0  += dictionary[0]->GetSize();
1104       totalSizeDict1  += dictionary[1]->GetSize();
1105       totalSizeDict2  += dictionary[2]->GetSize();
1106
1107       Float_t nPixel = nRowMax * nColMax * nTimeMax;
1108       if (fDebug > 0) {
1109         printf("<AliTRDdigitizer::MakeDigits> ");
1110         printf("Found %d digits in detector %d (%3.0f).\n"
1111               ,nDigits,iDet
1112               ,100.0 * ((Float_t) nDigits) / nPixel);
1113       } 
1114
1115       if (fCompress) signals->Compress(1,0);
1116
1117     }
1118
1119     delete [] inADC;
1120     delete [] outADC;
1121
1122   }
1123
1124   if (signalsArray) {
1125     delete signalsArray;
1126     signalsArray = 0;
1127   }
1128
1129   if (fDebug > 0) {
1130     printf("<AliTRDdigitizer::MakeDigits> ");
1131     printf("Total number of analyzed hits = %d\n",countHits);
1132     if (!fSimpleSim) {    
1133       printf("<AliTRDdigitizer::MakeDigits> ");
1134       printf("Total digits data size = %d, %d, %d, %d\n",totalSizeDigits
1135                                                         ,totalSizeDict0
1136                                                         ,totalSizeDict1
1137                                                         ,totalSizeDict2);        
1138     }
1139   }
1140
1141   return kTRUE;
1142
1143 }
1144
1145 //_____________________________________________________________________________
1146 void AliTRDdigitizer::AddSDigitsManager(AliTRDdigitsManager *man)
1147 {
1148   //
1149   // Add a digits manager for s-digits to the input list.
1150   //
1151
1152   fSDigitsManagerList->Add(man);
1153
1154 }
1155
1156 //_____________________________________________________________________________
1157 void AliTRDdigitizer::DeleteSDigitsManager()
1158 {
1159   //
1160   // Removes digits manager from the input list.
1161   //
1162
1163   fSDigitsManagerList->Delete();
1164
1165 }
1166
1167 //_____________________________________________________________________________
1168 Bool_t AliTRDdigitizer::ConvertSDigits()
1169 {
1170   //
1171   // Converts s-digits to normal digits
1172   //
1173
1174   // Number of track dictionary arrays
1175   const Int_t    kNDict = AliTRDdigitsManager::kNDict;
1176
1177   // Converts number of electrons to fC
1178   const Double_t kEl2fC = 1.602E-19 * 1.0E15; 
1179
1180   Int_t iDict = 0;
1181   Int_t iRow;
1182   Int_t iCol;
1183   Int_t iTime;
1184
1185   if (!fPar) {    
1186     fPar = new AliTRDparameter("TRDparameter","Standard parameter");
1187     if (fDebug > 0) {
1188       printf("<AliTRDdigitizer::ConvertSDigits> ");
1189       printf("Create the default parameter object\n");
1190     }
1191   }
1192
1193   Double_t sDigitsScale = 1.0 / GetSDigitsScale();
1194   Double_t noise        = fPar->GetNoise();
1195   Double_t padCoupling  = fPar->GetPadCoupling();
1196   Double_t timeCoupling = fPar->GetTimeCoupling();
1197   Double_t chipGain     = fPar->GetChipGain();
1198   Double_t coupling     = padCoupling * timeCoupling;
1199   Double_t convert      = kEl2fC * chipGain;
1200   Double_t adcInRange   = fPar->GetADCinRange();
1201   Double_t adcOutRange  = fPar->GetADCoutRange();
1202   Int_t    adcThreshold = fPar->GetADCthreshold();
1203   Int_t    adcBaseline  = fPar->GetADCbaseline();   
1204
1205   AliTRDdataArrayI *digitsIn;
1206   AliTRDdataArrayI *digitsOut;
1207   AliTRDdataArrayI *dictionaryIn[kNDict];
1208   AliTRDdataArrayI *dictionaryOut[kNDict];
1209
1210   // Loop through the detectors
1211   for (Int_t iDet = 0; iDet < AliTRDgeometry::Ndet(); iDet++) {
1212
1213     if (fDebug > 0) {
1214       printf("<AliTRDdigitizer::ConvertSDigits> ");
1215       printf("Convert detector %d to digits.\n",iDet);
1216     }
1217
1218     Int_t plane      = fGeo->GetPlane(iDet);
1219     Int_t sector     = fGeo->GetSector(iDet);
1220     Int_t chamber    = fGeo->GetChamber(iDet);
1221     Int_t nRowMax    = fPar->GetRowMax(plane,chamber,sector);
1222     Int_t nColMax    = fPar->GetColMax(plane);
1223     Int_t nTimeTotal = fPar->GetTimeTotal();
1224
1225     Double_t *inADC  = new Double_t[nTimeTotal];
1226     Double_t *outADC = new Double_t[nTimeTotal];
1227
1228     digitsIn  = fSDigitsManager->GetDigits(iDet);
1229     digitsIn->Expand();
1230     digitsOut = fDigitsManager->GetDigits(iDet);
1231     digitsOut->Allocate(nRowMax,nColMax,nTimeTotal);
1232     for (iDict = 0; iDict < kNDict; iDict++) {
1233       dictionaryIn[iDict]  = fSDigitsManager->GetDictionary(iDet,iDict);
1234       dictionaryIn[iDict]->Expand();
1235       dictionaryOut[iDict] = fDigitsManager->GetDictionary(iDet,iDict);
1236       dictionaryOut[iDict]->Allocate(nRowMax,nColMax,nTimeTotal);
1237     }
1238
1239     for (iRow  = 0; iRow  <  nRowMax;   iRow++ ) {
1240       for (iCol  = 0; iCol  <  nColMax;   iCol++ ) {
1241
1242         for (iTime = 0; iTime < nTimeTotal; iTime++) {         
1243           Double_t signal = (Double_t) digitsIn->GetDataUnchecked(iRow,iCol,iTime);
1244           signal *= sDigitsScale;
1245           // Pad and time coupling
1246           signal *= coupling;
1247           // Add the noise, starting from minus ADC baseline in electrons
1248           Double_t baselineEl = adcBaseline * (adcInRange / adcOutRange) / convert;
1249           signal  = TMath::Max((Double_t) gRandom->Gaus(signal,noise),-baselineEl);
1250           // Convert to mV
1251           signal *= convert;
1252           // add ADC baseline in mV
1253           signal += adcBaseline * (adcInRange / adcOutRange);
1254           // Convert to ADC counts. Set the overflow-bit adcOutRange if the 
1255           // signal is larger than adcInRange
1256           Int_t adc  = 0;
1257           if (signal >= adcInRange) {
1258             adc = ((Int_t) adcOutRange);
1259           }
1260           else {
1261             adc = ((Int_t) (signal * (adcOutRange / adcInRange)));
1262           }
1263           inADC[iTime]  = adc;
1264           outADC[iTime] = adc;
1265         }
1266
1267         // Apply the tail cancelation via the digital filter
1268         if (fPar->TCOn()) {
1269           DeConvExp(inADC,outADC,nTimeTotal,fPar->GetTCnexp());
1270         }
1271
1272         for (iTime = 0; iTime < nTimeTotal; iTime++) {   
1273           // Store the amplitude of the digit if above threshold
1274           if (outADC[iTime] > adcThreshold) {
1275             digitsOut->SetDataUnchecked(iRow,iCol,iTime,((Int_t) outADC[iTime]));
1276             // Copy the dictionary
1277             for (iDict = 0; iDict < kNDict; iDict++) { 
1278               Int_t track = dictionaryIn[iDict]->GetDataUnchecked(iRow,iCol,iTime);
1279               dictionaryOut[iDict]->SetDataUnchecked(iRow,iCol,iTime,track);
1280             }
1281           }
1282         }
1283
1284       }
1285     }
1286
1287     if (fCompress) {
1288       digitsIn->Compress(1,0);
1289       digitsOut->Compress(1,0);
1290       for (iDict = 0; iDict < kNDict; iDict++) {
1291         dictionaryIn[iDict]->Compress(1,0);
1292         dictionaryOut[iDict]->Compress(1,0);
1293       }
1294     }
1295
1296     delete [] inADC;
1297     delete [] outADC;
1298
1299   }    
1300
1301   return kTRUE;
1302
1303 }
1304
1305 //_____________________________________________________________________________
1306 Bool_t AliTRDdigitizer::MergeSDigits()
1307 {
1308   //
1309   // Merges the input s-digits:
1310   //   - The amplitude of the different inputs are summed up.
1311   //   - Of the track IDs from the input dictionaries only one is
1312   //     kept for each input. This works for maximal 3 different merged inputs.
1313   //
1314
1315   // Number of track dictionary arrays
1316   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1317
1318   if (!fPar) {
1319     fPar = new AliTRDparameter("TRDparameter","Standard parameter");
1320     if (fDebug > 0) {
1321       printf("<AliTRDdigitizer::MergeSDigits> ");
1322       printf("Create the default parameter object\n");
1323     }
1324   }
1325
1326   Int_t iDict = 0;
1327   Int_t jDict = 0;
1328
1329   AliTRDdataArrayI *digitsA;
1330   AliTRDdataArrayI *digitsB;
1331   AliTRDdataArrayI *dictionaryA[kNDict];
1332   AliTRDdataArrayI *dictionaryB[kNDict];
1333
1334   // Get the first s-digits
1335   fSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->First();
1336   if (!fSDigitsManager) return kFALSE;
1337
1338   // Loop through the other sets of s-digits
1339   AliTRDdigitsManager *mergeSDigitsManager;
1340   mergeSDigitsManager = (AliTRDdigitsManager *) 
1341                         fSDigitsManagerList->After(fSDigitsManager);
1342
1343   if (fDebug > 0) {
1344     if (mergeSDigitsManager) {
1345       printf("<AliTRDdigitizer::MergeSDigits> ");
1346       printf("Merge %d input files.\n",fSDigitsManagerList->GetSize());
1347     }
1348     else {
1349       printf("<AliTRDdigitizer::MergeSDigits> ");
1350       printf("Only one input file.\n");
1351     }
1352   }
1353
1354   Int_t iMerge = 0;
1355   while (mergeSDigitsManager) {
1356
1357     iMerge++;
1358
1359     // Loop through the detectors
1360     for (Int_t iDet = 0; iDet < AliTRDgeometry::Ndet(); iDet++) {
1361
1362       Int_t plane      = fGeo->GetPlane(iDet);
1363       Int_t sector     = fGeo->GetSector(iDet);
1364       Int_t chamber    = fGeo->GetChamber(iDet);
1365       Int_t nRowMax    = fPar->GetRowMax(plane,chamber,sector);
1366       Int_t nColMax    = fPar->GetColMax(plane);
1367       Int_t nTimeTotal = fPar->GetTimeTotal();
1368
1369       // Loop through the pixels of one detector and add the signals
1370       digitsA = fSDigitsManager->GetDigits(iDet);
1371       digitsB = mergeSDigitsManager->GetDigits(iDet);
1372       digitsA->Expand();
1373       digitsB->Expand();
1374       for (iDict = 0; iDict < kNDict; iDict++) {
1375         dictionaryA[iDict] = fSDigitsManager->GetDictionary(iDet,iDict);
1376         dictionaryB[iDict] = mergeSDigitsManager->GetDictionary(iDet,iDict);
1377         dictionaryA[iDict]->Expand();
1378         dictionaryB[iDict]->Expand();
1379       }
1380
1381       // Merge only detectors that contain a signal
1382       Bool_t doMerge = kTRUE;
1383       if (fMergeSignalOnly) {
1384         if (digitsA->GetOverThreshold(0) == 0) {
1385           doMerge = kFALSE;
1386         }
1387       }
1388
1389       if (doMerge) {
1390
1391         if (fDebug > 0) {
1392           printf("<AliTRDdigitizer::MergeSDigits> ");
1393           printf("Merge detector %d of input no.%d\n",iDet,iMerge+1);
1394         }
1395
1396         for (Int_t iRow  = 0; iRow  <  nRowMax;   iRow++ ) {
1397           for (Int_t iCol  = 0; iCol  <  nColMax;   iCol++ ) {
1398             for (Int_t iTime = 0; iTime < nTimeTotal; iTime++) {         
1399
1400               // Add the amplitudes of the summable digits 
1401               Int_t ampA = digitsA->GetDataUnchecked(iRow,iCol,iTime);
1402               Int_t ampB = digitsB->GetDataUnchecked(iRow,iCol,iTime);
1403               ampA += ampB;
1404               digitsA->SetDataUnchecked(iRow,iCol,iTime,ampA);
1405
1406              // Add the mask to the track id if defined.
1407               for (iDict = 0; iDict < kNDict; iDict++) {
1408                 Int_t trackB = dictionaryB[iDict]->GetDataUnchecked(iRow,iCol,iTime);
1409                 if ((fMasks) && (trackB > 0)) {
1410                   for (jDict = 0; jDict < kNDict; jDict++) { 
1411                     Int_t trackA = dictionaryA[iDict]->GetDataUnchecked(iRow,iCol,iTime);
1412                     if (trackA == 0) {
1413                       trackA = trackB + fMasks[iMerge];
1414                       dictionaryA[iDict]->SetDataUnchecked(iRow,iCol,iTime,trackA);
1415                     }
1416                   }
1417                 }
1418               }
1419
1420             }
1421           }
1422         }
1423
1424       }
1425
1426       if (fCompress) {
1427         digitsA->Compress(1,0);
1428         digitsB->Compress(1,0);
1429         for (iDict = 0; iDict < kNDict; iDict++) {
1430           dictionaryA[iDict]->Compress(1,0);
1431           dictionaryB[iDict]->Compress(1,0);
1432         }
1433       }
1434
1435     }    
1436
1437     // The next set of s-digits
1438     mergeSDigitsManager = (AliTRDdigitsManager *) 
1439                           fSDigitsManagerList->After(mergeSDigitsManager);
1440
1441   }
1442
1443   return kTRUE;
1444
1445 }
1446
1447 //_____________________________________________________________________________
1448 Bool_t AliTRDdigitizer::SDigits2Digits()
1449 {
1450   //
1451   // Merges the input s-digits and converts them to normal digits
1452   //
1453
1454   if (!MergeSDigits()) return kFALSE;
1455
1456   return ConvertSDigits();
1457
1458 }
1459
1460 //_____________________________________________________________________________
1461 Bool_t AliTRDdigitizer::CheckDetector(Int_t plane, Int_t chamber, Int_t sector)
1462 {
1463   //
1464   // Checks whether a detector is enabled
1465   //
1466
1467   if (fSimpleSim) return kTRUE; 
1468
1469   if ((fTRD->GetSensChamber() >=       0) &&
1470       (fTRD->GetSensChamber() != chamber)) return kFALSE;
1471   if ((fTRD->GetSensPlane()   >=       0) &&
1472       (fTRD->GetSensPlane()   !=   plane)) return kFALSE;
1473   if ( fTRD->GetSensSector()  >=       0) {
1474     Int_t sens1 = fTRD->GetSensSector();
1475     Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
1476     sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect())) 
1477            * AliTRDgeometry::Nsect();
1478     if (sens1 < sens2) {
1479       if ((sector < sens1) || (sector >= sens2)) return kFALSE;
1480     }
1481     else {
1482       if ((sector < sens1) && (sector >= sens2)) return kFALSE;
1483     }
1484   }
1485
1486   return kTRUE;
1487
1488 }
1489
1490 //_____________________________________________________________________________
1491 Bool_t AliTRDdigitizer::WriteDigits() const
1492 {
1493   //
1494   // Writes out the TRD-digits and the dictionaries
1495   //
1496
1497   // Store the digits and the dictionary in the tree
1498   return fDigitsManager->WriteDigits();
1499
1500 }
1501
1502 //_____________________________________________________________________________
1503 void AliTRDdigitizer::DeConvExp(Double_t *source, Double_t *target
1504                               , Int_t n, Int_t nexp) 
1505 {
1506   //
1507   // Does the deconvolution by the digital filter.
1508   //
1509   // Author:        Marcus Gutfleisch, KIP Heidelberg
1510   // Optimized for: New TRF from Venelin Angelov, simulated with CADENCE
1511   //                Pad-ground capacitance = 25 pF
1512   //                Pad-pad cross talk capacitance = 6 pF
1513   //                For 10 MHz digitization, corresponding to 20 time bins
1514   //                in the drift region
1515   //
1516
1517   Double_t rates[2];
1518   Double_t coefficients[2];
1519
1520   /* initialize (coefficient = alpha, rates = lambda) */
1521   
1522   if( nexp == 1 ) {
1523     rates[0] = 0.466998;
1524     /* no rescaling */
1525     coefficients[0] = 1.0;
1526   }
1527   if( nexp == 2 ) {
1528     rates[0] = 0.8988162;
1529     coefficients[0] = 0.11392069;
1530     rates[1] = 0.3745688;
1531     coefficients[1] = 0.8860793;
1532     /* no rescaling */
1533     Float_t sumc = coefficients[0]+coefficients[1];
1534     coefficients[0] /= sumc;
1535     coefficients[1] /= sumc;
1536   }
1537       
1538   Int_t i, k;
1539   Double_t reminder[2];
1540   Double_t correction, result;
1541
1542   /* attention: computation order is important */
1543   correction=0.0;
1544   for ( k = 0; k < nexp; k++ ) reminder[k]=0.0;
1545     
1546   for ( i = 0; i < n; i++ ) {
1547     result = ( source[i] - correction );    /* no rescaling */
1548     target[i] = result;
1549     
1550     for ( k = 0; k < nexp; k++ ) reminder[k] = rates[k] 
1551                              * ( reminder[k] + coefficients[k] * result);
1552       
1553     correction=0.0;
1554     for ( k = 0; k < nexp; k++ ) correction += reminder[k];
1555   }
1556   
1557 }
1558
1559 //_____________________________________________________________________________
1560 void AliTRDdigitizer::InitOutput(Int_t iEvent)
1561 {
1562   //
1563   // Initializes the output branches
1564   //
1565
1566   fEvent = iEvent;
1567    
1568   if (!fRunLoader)
1569    {
1570      Error("InitOutput","Run Loader is NULL");
1571      return;  
1572    }
1573   AliLoader* loader = fRunLoader->GetLoader("TRDLoader");
1574   if (!loader)
1575    {
1576      Error("Open","Can not get TRD loader from Run Loader");
1577      return;
1578    }
1579
1580   TTree* tree = 0;
1581   
1582   if (fSDigits)
1583    { 
1584    //if we produce SDigits
1585     tree = loader->TreeS();
1586     if (!tree)
1587      {
1588       loader->MakeTree("S");
1589       tree = loader->TreeS();
1590      }
1591    }
1592   else
1593    {//if we produce Digits
1594      tree = loader->TreeD();
1595      if (!tree)
1596       {
1597        loader->MakeTree("D");
1598        tree = loader->TreeD();
1599       }
1600    }
1601   fDigitsManager->SetEvent(iEvent);
1602   fDigitsManager->MakeBranch(tree);
1603
1604 }