Making online tracklets usable in offline reconstruction
[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 //                                                                        //
22 //  Authors: C. Blume (blume@ikf.uni-frankfurt.de)                        //
23 //           C. Lippmann                                                  //
24 //           B. Vulpescu                                                  //
25 //                                                                        //
26 //  The following effects are included:                                   //
27 //      - Diffusion                                                       //
28 //      - ExB effects                                                     //
29 //      - Gas gain including fluctuations                                 //
30 //      - Pad-response (simple Gaussian approximation)                    //
31 //      - Time-response                                                   //
32 //      - Electronics noise                                               //
33 //      - Electronics gain                                                //
34 //      - Digitization                                                    //
35 //      - Zero suppression                                                //
36 //                                                                        //
37 ////////////////////////////////////////////////////////////////////////////
38
39 #include <TF1.h>
40 #include <TFile.h>
41 #include <TGeoGlobalMagField.h>
42 #include <TGeoManager.h>
43 #include <TList.h>
44 #include <TMath.h>
45 #include <TROOT.h>
46 #include <TRandom.h>
47 #include <TTask.h>
48 #include <TTree.h>
49 #include <TVector.h>
50
51 #include "AliRun.h"
52 #include "AliMC.h"
53 #include "AliRunLoader.h"
54 #include "AliLoader.h"
55 #include "AliConfig.h"
56 #include "AliMagF.h"
57 #include "AliRunDigitizer.h"
58 #include "AliRunLoader.h"
59 #include "AliLoader.h"
60 #include "AliLog.h"
61 #include "AliTRD.h"
62 #include "AliTRDhit.h"
63 #include "AliTRDdigitizer.h"
64
65 #include "AliTRDarrayDictionary.h"
66 #include "AliTRDarrayADC.h"
67 #include "AliTRDarraySignal.h"
68 #include "AliTRDdigitsManager.h"
69 #include "AliTRDgeometry.h"
70 #include "AliTRDpadPlane.h"
71 #include "AliTRDcalibDB.h"
72 #include "AliTRDSimParam.h"
73 #include "AliTRDCommonParam.h"
74 #include "AliTRDfeeParam.h"
75 #include "AliTRDmcmSim.h"
76 #include "Cal/AliTRDCalROC.h"
77 #include "Cal/AliTRDCalDet.h"
78
79 ClassImp(AliTRDdigitizer)
80
81 //_____________________________________________________________________________
82 AliTRDdigitizer::AliTRDdigitizer()
83   :AliDigitizer()
84   ,fRunLoader(0)
85   ,fDigitsManager(0)
86   ,fSDigitsManager(0)
87   ,fSDigitsManagerList(0)
88   ,fTRD(0)
89   ,fGeo(0)
90   ,fEvent(0)
91   ,fMasks(0)
92   ,fCompress(kTRUE)
93   ,fSDigits(kFALSE)
94   ,fMergeSignalOnly(kFALSE)
95 {
96   //
97   // AliTRDdigitizer default constructor
98   //
99   
100   Init();
101
102 }
103
104 //_____________________________________________________________________________
105 AliTRDdigitizer::AliTRDdigitizer(const Text_t *name, const Text_t *title)              
106   :AliDigitizer(name,title)
107   ,fRunLoader(0)
108   ,fDigitsManager(0)
109   ,fSDigitsManager(0)
110   ,fSDigitsManagerList(0)
111   ,fTRD(0)
112   ,fGeo(0)
113   ,fEvent(0)
114   ,fMasks(0)
115   ,fCompress(kTRUE)
116   ,fSDigits(kFALSE)
117   ,fMergeSignalOnly(kFALSE)
118 {
119   //
120   // AliTRDdigitizer constructor
121   //
122
123   Init();
124
125 }
126
127 //_____________________________________________________________________________
128 AliTRDdigitizer::AliTRDdigitizer(AliRunDigitizer *manager
129                                , const Text_t *name, const Text_t *title)
130   :AliDigitizer(manager,name,title)
131   ,fRunLoader(0)
132   ,fDigitsManager(0)
133   ,fSDigitsManager(0)
134   ,fSDigitsManagerList(0)
135   ,fTRD(0)
136   ,fGeo(0)
137   ,fEvent(0)
138   ,fMasks(0)
139   ,fCompress(kTRUE)
140   ,fSDigits(kFALSE)
141   ,fMergeSignalOnly(kFALSE)
142 {
143   //
144   // AliTRDdigitizer constructor
145   //
146
147   Init();
148
149 }
150
151 //_____________________________________________________________________________
152 AliTRDdigitizer::AliTRDdigitizer(AliRunDigitizer *manager)
153   :AliDigitizer(manager,"AliTRDdigitizer","TRD digitizer")
154   ,fRunLoader(0)
155   ,fDigitsManager(0)
156   ,fSDigitsManager(0)
157   ,fSDigitsManagerList(0)
158   ,fTRD(0)
159   ,fGeo(0)
160   ,fEvent(0)
161   ,fMasks(0)
162   ,fCompress(kTRUE)
163   ,fSDigits(kFALSE)
164   ,fMergeSignalOnly(kFALSE)
165 {
166   //
167   // AliTRDdigitizer constructor
168   //
169
170   Init();
171
172 }
173
174 //_____________________________________________________________________________
175 Bool_t AliTRDdigitizer::Init()
176 {
177   //
178   // Initialize the digitizer with default values
179   //
180
181   fRunLoader          = 0;
182   fDigitsManager      = 0;
183   fSDigitsManager     = 0;
184   fSDigitsManagerList = 0;
185   fTRD                = 0;
186   fGeo                = 0;
187
188   fEvent              = 0;
189   fMasks              = 0;
190   fCompress           = kTRUE;
191   fSDigits            = kFALSE;
192   fMergeSignalOnly    = kFALSE;
193   
194   return AliDigitizer::Init();
195
196 }
197
198 //_____________________________________________________________________________
199 AliTRDdigitizer::AliTRDdigitizer(const AliTRDdigitizer &d)
200   :AliDigitizer(d)
201   ,fRunLoader(0)
202   ,fDigitsManager(0)
203   ,fSDigitsManager(0)
204   ,fSDigitsManagerList(0)
205   ,fTRD(0)
206   ,fGeo(0)
207   ,fEvent(0)
208   ,fMasks(0)
209   ,fCompress(d.fCompress)
210   ,fSDigits(d.fSDigits)
211   ,fMergeSignalOnly(d.fMergeSignalOnly)
212 {
213   //
214   // AliTRDdigitizer copy constructor
215   //
216
217 }
218
219 //_____________________________________________________________________________
220 AliTRDdigitizer::~AliTRDdigitizer()
221 {
222   //
223   // AliTRDdigitizer destructor
224   //
225
226   if (fDigitsManager) {
227     delete fDigitsManager;
228     fDigitsManager      = 0;
229   }
230
231   if (fDigitsManager) {              //typo? fSDigitsManager?
232     delete fSDigitsManager;
233     fSDigitsManager     = 0;
234   }
235
236   if (fSDigitsManagerList) {
237     fSDigitsManagerList->Delete();
238     delete fSDigitsManagerList;
239     fSDigitsManagerList = 0;
240   }
241
242   if (fMasks) {
243     delete [] fMasks;
244     fMasks       = 0;
245   }
246
247   if (fGeo) {
248     delete fGeo;
249     fGeo = 0;
250   }
251
252 }
253
254 //_____________________________________________________________________________
255 AliTRDdigitizer &AliTRDdigitizer::operator=(const AliTRDdigitizer &d)
256 {
257   //
258   // Assignment operator
259   //
260
261   if (this != &d) {
262     ((AliTRDdigitizer &) d).Copy(*this);
263   }
264
265   return *this;
266
267 }
268
269 //_____________________________________________________________________________
270 void AliTRDdigitizer::Copy(TObject &d) const
271 {
272   //
273   // Copy function
274   //
275
276   ((AliTRDdigitizer &) d).fRunLoader          = 0;
277   ((AliTRDdigitizer &) d).fDigitsManager      = 0;
278   ((AliTRDdigitizer &) d).fSDigitsManager     = 0;
279   ((AliTRDdigitizer &) d).fSDigitsManagerList = 0;
280   ((AliTRDdigitizer &) d).fTRD                = 0;
281   ((AliTRDdigitizer &) d).fGeo                = 0;
282   ((AliTRDdigitizer &) d).fEvent              = 0;
283   ((AliTRDdigitizer &) d).fMasks              = 0;
284   ((AliTRDdigitizer &) d).fCompress           = fCompress;
285   ((AliTRDdigitizer &) d).fSDigits            = fSDigits;
286   ((AliTRDdigitizer &) d).fMergeSignalOnly    = fMergeSignalOnly;
287
288 }
289
290 //_____________________________________________________________________________
291 void AliTRDdigitizer::Exec(Option_t *option)
292 {
293   //
294   // Executes the merging
295   //
296
297   Int_t iInput;
298
299   AliTRDdigitsManager *sdigitsManager;
300
301   TString optionString = option;
302   if (optionString.Contains("deb")) {
303     AliLog::SetClassDebugLevel("AliTRDdigitizer",1);
304     AliInfo("Called with debug option");
305   }
306
307   // The AliRoot file is already connected by the manager
308   AliRunLoader *inrl = 0x0;
309   
310   if (gAlice) {
311     AliDebug(1,"AliRun object found on file.");
312   }
313   else {
314     inrl = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(0));
315     inrl->LoadgAlice();
316     gAlice = inrl->GetAliRun();
317     if (!gAlice) {
318       AliError("Could not find AliRun object.")
319       return;
320     }
321   }
322                                                                            
323   Int_t nInput = fManager->GetNinputs();
324   fMasks       = new Int_t[nInput];
325   for (iInput = 0; iInput < nInput; iInput++) {
326     fMasks[iInput] = fManager->GetMask(iInput);
327   }
328
329   //
330   // Initialization
331   //
332
333   AliRunLoader *orl = AliRunLoader::GetRunLoader(fManager->GetOutputFolderName());
334
335   if (InitDetector()) {
336
337     AliLoader *ogime = orl->GetLoader("TRDLoader");
338
339     TTree *tree = 0;
340     if (fSDigits) { 
341       // If we produce SDigits
342       tree = ogime->TreeS();
343       if (!tree) {
344         ogime->MakeTree("S");
345         tree = ogime->TreeS();
346       }
347     }
348     else {
349       // If we produce Digits
350       tree = ogime->TreeD();
351       if (!tree) {
352         ogime->MakeTree("D");
353         tree = ogime->TreeD();
354       }
355     }
356
357     MakeBranch(tree);
358
359   }
360  
361   for (iInput = 0; iInput < nInput; iInput++) {
362
363     AliDebug(1,Form("Add input stream %d",iInput));
364
365     // Check if the input tree exists
366     inrl = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(iInput));
367     AliLoader *gime = inrl->GetLoader("TRDLoader");
368
369     TTree *treees = gime->TreeS();
370     if (treees == 0x0) {
371       if (gime->LoadSDigits()) {
372         AliError(Form("Error Occured while loading S. Digits for input %d.",iInput));
373         return;
374       }
375       treees = gime->TreeS();
376     }
377     
378     if (treees == 0x0) {
379       AliError(Form("Input stream %d does not exist",iInput));
380       return;
381     } 
382
383     // Read the s-digits via digits manager
384     sdigitsManager = new AliTRDdigitsManager();
385     sdigitsManager->SetSDigits(kTRUE);
386     
387     AliRunLoader *rl = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(iInput));
388     AliLoader *gimme = rl->GetLoader("TRDLoader");
389     if (!gimme->TreeS()) 
390       {
391         gimme->LoadSDigits();
392       }
393
394     sdigitsManager->ReadDigits(gimme->TreeS());
395    
396     // Add the s-digits to the input list 
397     AddSDigitsManager(sdigitsManager);
398
399   }
400
401   // Convert the s-digits to normal digits
402   AliDebug(1,"Do the conversion");
403   SDigits2Digits();
404
405   // Store the digits
406   AliDebug(1,"Write the digits");
407   fDigitsManager->WriteDigits();
408
409   // Write parameters
410   orl->CdGAFile();
411
412   // Clean up
413   DeleteSDigitsManager();
414
415   AliDebug(1,"Done");
416
417 }
418
419 //_____________________________________________________________________________
420 Bool_t AliTRDdigitizer::Open(const Char_t *file, Int_t nEvent)
421 {
422   //
423   // Opens a ROOT-file with TRD-hits and reads in the hit-tree
424   //
425   // Connect the AliRoot file containing Geometry, Kine, and Hits
426   //  
427
428   TString evfoldname = AliConfig::GetDefaultEventFolderName();
429
430   fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
431   if (!fRunLoader) {
432     fRunLoader = AliRunLoader::Open(file,evfoldname,"UPDATE");
433   }  
434   if (!fRunLoader) {
435     AliError(Form("Can not open session for file %s.",file));
436     return kFALSE;
437   }
438    
439   if (!fRunLoader->GetAliRun()) {
440     fRunLoader->LoadgAlice();
441   }
442   gAlice = fRunLoader->GetAliRun();
443   
444   if (gAlice) {
445     AliDebug(1,"AliRun object found on file.");
446   }
447   else {
448     AliError("Could not find AliRun object.");
449     return kFALSE;
450   }
451
452   fEvent = nEvent;
453
454   AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
455   if (!loader) {
456     AliError("Can not get TRD loader from Run Loader");
457     return kFALSE;
458   }
459   
460   if (InitDetector()) {
461     TTree *tree = 0;
462     if (fSDigits) { 
463       // If we produce SDigits
464       tree = loader->TreeS();
465       if (!tree) {
466         loader->MakeTree("S");
467         tree = loader->TreeS();
468       }
469     }
470     else {
471       // If we produce Digits
472       tree = loader->TreeD();
473       if (!tree) {
474         loader->MakeTree("D");
475         tree = loader->TreeD();
476       }
477     }
478     return MakeBranch(tree);
479   }
480   else {
481     return kFALSE;
482   }
483
484 }
485
486 //_____________________________________________________________________________
487 Bool_t AliTRDdigitizer::Open(AliRunLoader *runLoader, Int_t nEvent)
488 {
489   //
490   // Opens a ROOT-file with TRD-hits and reads in the hit-tree
491   //
492   // Connect the AliRoot file containing Geometry, Kine, and Hits
493   //  
494
495   fRunLoader = runLoader;
496   if (!fRunLoader) {
497     AliError("RunLoader does not exist");
498     return kFALSE;
499   }
500    
501   if (!fRunLoader->GetAliRun()) {
502     fRunLoader->LoadgAlice();
503   }
504   gAlice = fRunLoader->GetAliRun();
505   
506   if (gAlice) {
507     AliDebug(1,"AliRun object found on file.");
508   }
509   else {
510     AliError("Could not find AliRun object.");
511     return kFALSE;
512   }
513
514   fEvent = nEvent;
515
516   AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
517   if (!loader) {
518     AliError("Can not get TRD loader from Run Loader");
519     return kFALSE;
520   }
521   
522   if (InitDetector()) {
523     TTree *tree = 0;
524     if (fSDigits) { 
525       // If we produce SDigits
526       tree = loader->TreeS();
527       if (!tree) {
528         loader->MakeTree("S");
529         tree = loader->TreeS();
530       }
531     }
532     else {
533       // If we produce Digits
534       tree = loader->TreeD();
535       if (!tree) {
536         loader->MakeTree("D");
537         tree = loader->TreeD();
538       }
539     }
540     return MakeBranch(tree);
541   }
542   else {
543     return kFALSE;
544   }
545
546 }
547
548 //_____________________________________________________________________________
549 Bool_t AliTRDdigitizer::InitDetector()
550 {
551   //
552   // Sets the pointer to the TRD detector and the geometry
553   //
554
555   // Get the pointer to the detector class and check for version 1
556   fTRD = (AliTRD *) gAlice->GetDetector("TRD");
557   if (!fTRD) {
558     AliFatal("No TRD module found");
559     exit(1);
560   }
561   if (fTRD->IsVersion() != 1) {
562     AliFatal("TRD must be version 1 (slow simulator)");
563     exit(1);
564   }
565
566   // Get the geometry
567   fGeo = new AliTRDgeometry();
568
569   // Create a digits manager
570   if (fDigitsManager) {
571     delete fDigitsManager;
572   }
573   fDigitsManager = new AliTRDdigitsManager();
574   fDigitsManager->SetSDigits(fSDigits);
575   fDigitsManager->CreateArrays();
576   fDigitsManager->SetEvent(fEvent);
577
578   // The list for the input s-digits manager to be merged
579   if (fSDigitsManagerList) {
580     fSDigitsManagerList->Delete();
581   } 
582   else {
583     fSDigitsManagerList = new TList();
584   }
585
586   return kTRUE;
587
588 }
589 //_____________________________________________________________________________
590 Bool_t AliTRDdigitizer::MakeBranch(TTree *tree) const
591 {
592   // 
593   // Create the branches for the digits array
594   //
595
596   return fDigitsManager->MakeBranch(tree);
597
598 }
599
600 //_____________________________________________________________________________
601 void AliTRDdigitizer::AddSDigitsManager(AliTRDdigitsManager *man)
602 {
603   //
604   // Add a digits manager for s-digits to the input list.
605   //
606
607   fSDigitsManagerList->Add(man);
608
609 }
610
611 //_____________________________________________________________________________
612 void AliTRDdigitizer::DeleteSDigitsManager()
613 {
614   //
615   // Removes digits manager from the input list.
616   //
617
618   fSDigitsManagerList->Delete();
619
620 }
621
622 //_____________________________________________________________________________
623 Bool_t AliTRDdigitizer::MakeDigits()
624 {
625   //
626   // Creates digits.
627   //
628
629   AliDebug(1,"Start creating digits");
630
631   if (!fGeo) {
632     AliError("No geometry defined");
633     return kFALSE;
634   }
635
636   AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
637   if (!calibration) {
638     AliFatal("Could not get calibration object");
639     return kFALSE;
640   }
641
642   const Int_t kNdet  = AliTRDgeometry::Ndet();
643
644   Float_t **hits = new Float_t*[kNdet];
645   Int_t    *nhit = new Int_t[kNdet];
646
647   AliTRDarraySignal *signals = 0x0;
648  
649   // Sort all hits according to detector number
650   if (!SortHits(hits,nhit)) {
651     AliError("Sorting hits failed");
652     return kFALSE;
653   }
654
655   // Loop through all detectors
656   for (Int_t det = 0; det < kNdet; det++) {
657
658     // Detectors that are switched off, not installed, etc.
659     if (( calibration->IsChamberInstalled(det)) &&
660         (!calibration->IsChamberMasked(det))    &&
661         ( fGeo->ChamberInGeometry(det))         &&
662         (nhit[det] > 0)) {
663
664       signals = new AliTRDarraySignal();
665           
666       // Convert the hits of the current detector to detector signals
667       if (!ConvertHits(det,hits[det],nhit[det],signals)) {
668         AliError(Form("Conversion of hits failed for detector=%d",det));
669         return kFALSE;
670       }
671       // Convert the detector signals to digits or s-digits
672       if (!ConvertSignals(det,signals)) {
673         AliError(Form("Conversion of signals failed for detector=%d",det));
674         return kFALSE;
675       }
676
677       // Delete the signals array
678       delete signals;
679       signals = 0x0;
680
681     } // if: detector status
682
683     delete [] hits[det];
684
685   } // for: detector
686
687   delete [] hits;
688   delete [] nhit;
689
690   return kTRUE;
691
692 }
693
694 //_____________________________________________________________________________
695 Bool_t AliTRDdigitizer::SortHits(Float_t **hits, Int_t *nhit)
696 {
697   //
698   // Read all the hits and sorts them according to detector number
699   // in the output array <hits>.
700   //
701
702   AliDebug(1,"Start sorting hits");
703
704   const Int_t kNdet = AliTRDgeometry::Ndet();
705   // Size of the hit vector
706   const Int_t kNhit = 6;
707
708   Float_t *xyz      = 0;
709   Int_t    nhitTrk  = 0;
710
711   Int_t   *lhit     = new Int_t[kNdet];
712
713   for (Int_t det = 0; det < kNdet; det++) {
714     lhit[det] = 0;
715     nhit[det] = 0;
716     hits[det] = 0;
717   }
718
719   AliLoader *gimme = fRunLoader->GetLoader("TRDLoader");
720   if (!gimme->TreeH()) {
721     gimme->LoadHits();
722   }
723   TTree *hitTree = gimme->TreeH();
724   if (hitTree == 0x0) {
725     AliError("Can not get TreeH");
726     return kFALSE;
727   }
728   fTRD->SetTreeAddress();
729
730   // Get the number of entries in the hit tree
731   // (Number of primary particles creating a hit somewhere)
732   Int_t nTrk = (Int_t) hitTree->GetEntries();
733   AliDebug(1,Form("Found %d tracks",nTrk));
734
735   // Loop through all the tracks in the tree
736   for (Int_t iTrk = 0; iTrk < nTrk; iTrk++) {
737
738     gAlice->GetMCApp()->ResetHits();
739     hitTree->GetEvent(iTrk);
740
741     if (!fTRD->Hits()) {
742       AliError(Form("No hits array for track = %d",iTrk));
743       continue;
744     }
745
746     // Number of hits for this track
747     nhitTrk = fTRD->Hits()->GetEntriesFast();
748
749     Int_t hitCnt = 0;
750     // Loop through the TRD hits
751     AliTRDhit *hit = (AliTRDhit *) fTRD->FirstHit(-1);
752     while (hit) {
753
754       hitCnt++;
755
756       // Don't analyze test hits
757       if (((Int_t) hit->GetCharge()) != 0) {
758
759         Int_t   trk  = hit->Track();
760         Int_t   det  = hit->GetDetector();
761         Int_t   q    = hit->GetCharge();
762         Float_t x    = hit->X();
763         Float_t y    = hit->Y();
764         Float_t z    = hit->Z();
765         Float_t time = hit->GetTime();
766
767         if (nhit[det] == lhit[det]) {
768           // Inititialization of new detector
769           xyz        = new Float_t[kNhit*(nhitTrk+lhit[det])];
770           if (hits[det]) {
771             memcpy(xyz,hits[det],sizeof(Float_t)*kNhit*lhit[det]);
772             delete [] hits[det];
773           }
774           lhit[det] += nhitTrk;
775           hits[det]  = xyz;
776         }
777         else {
778           xyz        = hits[det];
779         }
780         xyz[nhit[det]*kNhit+0] = x;
781         xyz[nhit[det]*kNhit+1] = y;
782         xyz[nhit[det]*kNhit+2] = z;
783         xyz[nhit[det]*kNhit+3] = q;
784         xyz[nhit[det]*kNhit+4] = trk;
785         xyz[nhit[det]*kNhit+5] = time;
786         nhit[det]++;
787
788       } // if: charge != 0
789
790       hit = (AliTRDhit *) fTRD->NextHit();   
791
792     } // for: hits of one track
793
794   } // for: tracks
795
796   delete [] lhit;
797
798   return kTRUE;
799
800 }
801
802 //_____________________________________________________________________________
803 Bool_t AliTRDdigitizer::ConvertHits(Int_t det, Float_t *hits, Int_t nhit
804                                   , AliTRDarraySignal *signals)
805 {
806   //
807   // Converts the detectorwise sorted hits to detector signals
808   //
809
810   AliDebug(1,Form("Start converting hits for detector=%d (nhits=%d)",det,nhit));
811
812   // Number of pads included in the pad response
813   const Int_t kNpad      = 3;
814   // Number of track dictionary arrays
815   const Int_t kNdict     = AliTRDdigitsManager::kNDict;
816   // Size of the hit vector
817   const Int_t kNhit      = 6;
818
819   // Width of the amplification region
820   const Float_t kAmWidth = AliTRDgeometry::AmThick();
821   // Width of the drift region
822   const Float_t kDrWidth = AliTRDgeometry::DrThick();
823   // Drift + amplification region 
824   const Float_t kDrMin   =          - 0.5 * kAmWidth;
825   const Float_t kDrMax   = kDrWidth + 0.5 * kAmWidth;
826   
827   Int_t    iPad          = 0;
828   Int_t    dict          = 0;
829   Int_t    timeBinTRFend = 1;
830
831   Double_t pos[3];
832   Double_t loc[3];
833   Double_t padSignal[kNpad];
834   Double_t signalOld[kNpad];
835
836   AliTRDarrayDictionary *dictionary[kNdict];
837
838   AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
839   AliTRDCommonParam *commonParam = AliTRDCommonParam::Instance();
840   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
841
842   if (!commonParam) {
843     AliFatal("Could not get common parameterss");
844     return kFALSE;
845   }
846   if (!simParam) {
847     AliFatal("Could not get simulation parameters");
848     return kFALSE;
849   }  
850   if (!calibration) {
851     AliFatal("Could not get calibration object");  
852     return kFALSE;
853   }
854
855   // Get the detector wise calibration objects
856   AliTRDCalROC       *calVdriftROC      = 0;
857   Float_t             calVdriftDetValue = 0.0;
858   const AliTRDCalDet *calVdriftDet      = calibration->GetVdriftDet();  
859   AliTRDCalROC       *calT0ROC          = 0;
860   Float_t             calT0DetValue     = 0.0;
861   const AliTRDCalDet *calT0Det          = calibration->GetT0Det();  
862
863   if (simParam->TRFOn()) {
864     timeBinTRFend = ((Int_t) (simParam->GetTRFhi() 
865                   * commonParam->GetSamplingFrequency())) - 1;
866   }
867
868   Int_t   nTimeTotal   = calibration->GetNumberOfTimeBins();
869   Float_t samplingRate = commonParam->GetSamplingFrequency();
870   Float_t elAttachProp = simParam->GetElAttachProp() / 100.0; 
871
872   AliTRDpadPlane *padPlane = fGeo->GetPadPlane(det);
873   Int_t   layer   = fGeo->GetLayer(det);         //update
874   Float_t row0    = padPlane->GetRow0ROC();
875   Int_t   nRowMax = padPlane->GetNrows();
876   Int_t   nColMax = padPlane->GetNcols();
877
878   // Create a new array for the signals
879   signals->Allocate(nRowMax,nColMax,nTimeTotal);
880
881   // Create a new array for the dictionary
882   for (dict = 0; dict < kNdict; dict++) {       
883     dictionary[dict] = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(det,dict);
884     dictionary[dict]->Allocate(nRowMax,nColMax,nTimeTotal);
885   }      
886
887   // Loop through the hits in this detector
888   for (Int_t hit = 0; hit < nhit; hit++) {
889
890     pos[0]          = hits[hit*kNhit+0];
891     pos[1]          = hits[hit*kNhit+1];
892     pos[2]          = hits[hit*kNhit+2];
893     Float_t q       = hits[hit*kNhit+3];
894     Float_t hittime = hits[hit*kNhit+5];
895     Int_t   track   = ((Int_t) hits[hit*kNhit+4]);
896
897     Int_t   inDrift = 1;
898
899     // Find the current volume with the geo manager
900     gGeoManager->SetCurrentPoint(pos);
901     gGeoManager->FindNode();      
902     if (strstr(gGeoManager->GetPath(),"/UK")) {
903       inDrift = 0;
904     }
905
906     // Get the calibration objects
907     calVdriftROC      = calibration->GetVdriftROC(det);
908     calVdriftDetValue = calVdriftDet->GetValue(det);
909     calT0ROC          = calibration->GetT0ROC(det);
910     calT0DetValue     = calT0Det->GetValue(det);
911
912     // Go to the local coordinate system:
913     // loc[0] - col  direction in amplification or driftvolume
914     // loc[1] - row  direction in amplification or driftvolume
915     // loc[2] - time direction in amplification or driftvolume
916     gGeoManager->MasterToLocal(pos,loc);
917     if (inDrift) {
918       // Relative to middle of amplification region
919       loc[2] = loc[2] - kDrWidth/2.0 - kAmWidth/2.0;
920     } 
921
922     // The driftlength [cm] (w/o diffusion yet !).
923     // It is negative if the hit is between pad plane and anode wires.
924     Double_t driftlength = -1.0 * loc[2];
925
926     // Stupid patch to take care of TR photons that are absorbed
927     // outside the chamber volume. A real fix would actually need
928     // a more clever implementation of the TR hit generation
929     if (q < 0.0) {
930       if ((loc[1] < padPlane->GetRowEndROC()) ||
931           (loc[1] > padPlane->GetRow0ROC())) {
932         continue;
933       }
934       if ((driftlength < kDrMin) ||
935           (driftlength > kDrMax)) {
936         continue;
937       }
938     }
939
940     // Get row and col of unsmeared electron to retrieve drift velocity
941     // The pad row (z-direction)
942     Int_t    rowE         = padPlane->GetPadRowNumberROC(loc[1]);
943     if (rowE < 0) {
944       continue;
945     }
946     Double_t rowOffset    = padPlane->GetPadRowOffsetROC(rowE,loc[1]);
947     // The pad column (rphi-direction)
948     Double_t offsetTilt   = padPlane->GetTiltOffset(rowOffset);
949     Int_t    colE         = padPlane->GetPadColNumber(loc[0]+offsetTilt);
950     if (colE < 0) {
951       continue;   
952     }
953     Double_t colOffset    = 0.0;
954
955     // Normalized drift length
956     Float_t  driftvelocity  = calVdriftDetValue * calVdriftROC->GetValue(colE,rowE);
957     Double_t absdriftlength = TMath::Abs(driftlength);
958     if (commonParam->ExBOn()) {
959       absdriftlength /= TMath::Sqrt(GetLorentzFactor(driftvelocity));
960     }
961
962     // Loop over all electrons of this hit
963     // TR photons produce hits with negative charge
964     Int_t nEl = ((Int_t) TMath::Abs(q));
965     for (Int_t iEl = 0; iEl < nEl; iEl++) {
966
967       // Now the real local coordinate system of the ROC
968       // column direction: locC
969       // row direction:    locR 
970       // time direction:   locT
971       // locR and locC are identical to the coordinates of the corresponding
972       // volumina of the drift or amplification region.
973       // locT is defined relative to the wire plane (i.e. middle of amplification
974       // region), meaning locT = 0, and is negative for hits coming from the
975       // drift region. 
976       Double_t locC = loc[0];
977       Double_t locR = loc[1];
978       Double_t locT = loc[2];
979
980       // Electron attachment
981       if (simParam->ElAttachOn()) {
982         if (gRandom->Rndm() < (absdriftlength * elAttachProp)) {
983           continue;
984         }
985       }
986           
987       // Apply the diffusion smearing
988       if (simParam->DiffusionOn()) {
989         if (!(Diffusion(driftvelocity,absdriftlength,locR,locC,locT))) {
990           continue;
991         }
992       }
993
994       // Apply E x B effects (depends on drift direction)
995       if (commonParam->ExBOn()) { 
996         if (!(ExB(driftvelocity,driftlength,locC))) {
997           continue;
998         }
999       }
1000
1001       // The electron position after diffusion and ExB in pad coordinates.
1002       // The pad row (z-direction)
1003       rowE       = padPlane->GetPadRowNumberROC(locR);
1004       if (rowE < 0) continue;
1005       rowOffset  = padPlane->GetPadRowOffsetROC(rowE,locR);
1006
1007       // The pad column (rphi-direction)
1008       offsetTilt = padPlane->GetTiltOffset(rowOffset);
1009       colE       = padPlane->GetPadColNumber(locC+offsetTilt);
1010       if (colE < 0) continue;         
1011       colOffset  = padPlane->GetPadColOffset(colE,locC+offsetTilt);
1012           
1013       // Also re-retrieve drift velocity because col and row may have changed
1014       driftvelocity = calVdriftDetValue * calVdriftROC->GetValue(colE,rowE);
1015       Float_t t0    = calT0DetValue     + calT0ROC->GetValue(colE,rowE);
1016
1017       // Convert the position to drift time [mus], using either constant drift velocity or
1018       // time structure of drift cells (non-isochronity, GARFIELD calculation).
1019       // Also add absolute time of hits to take pile-up events into account properly
1020       Double_t drifttime;
1021       if (simParam->TimeStructOn()) {
1022         // Get z-position with respect to anode wire
1023         Double_t zz  =  row0 - locR + padPlane->GetAnodeWireOffset();
1024         zz -= ((Int_t)(2 * zz)) / 2.0;
1025         if (zz > 0.25) {
1026           zz  = 0.5 - zz;
1027         }
1028         // Use drift time map (GARFIELD)
1029         drifttime = commonParam->TimeStruct(driftvelocity,0.5*kAmWidth-1.0*locT,zz)
1030                   + hittime;
1031       } 
1032       else {
1033         // Use constant drift velocity
1034         drifttime = TMath::Abs(locT) / driftvelocity
1035                   + hittime;
1036       }
1037
1038       // Apply the gas gain including fluctuations
1039       Double_t ggRndm = 0.0;
1040       do {
1041         ggRndm = gRandom->Rndm();
1042       } while (ggRndm <= 0);
1043       Double_t signal = -(simParam->GetGasGain()) * TMath::Log(ggRndm);
1044
1045       // Apply the pad response 
1046       if (simParam->PRFOn()) {
1047         // The distance of the electron to the center of the pad 
1048         // in units of pad width
1049         Double_t dist = (colOffset - 0.5*padPlane->GetColSize(colE))
1050                       / padPlane->GetColSize(colE);
1051         // This is a fixed parametrization, i.e. not dependent on
1052         // calibration values !
1053         if (!(calibration->PadResponse(signal,dist,layer,padSignal))) continue;
1054       }
1055       else {
1056         padSignal[0] = 0.0;
1057         padSignal[1] = signal;
1058         padSignal[2] = 0.0;
1059       }
1060
1061       // The time bin (always positive), with t0 distortion
1062       Double_t timeBinIdeal = drifttime * samplingRate + t0;
1063       // Protection 
1064       if (TMath::Abs(timeBinIdeal) > 2*nTimeTotal) {
1065         timeBinIdeal = 2 * nTimeTotal;
1066       }
1067       Int_t    timeBinTruncated = ((Int_t) timeBinIdeal);
1068       // The distance of the position to the middle of the timebin
1069       Double_t timeOffset       = ((Float_t) timeBinTruncated 
1070                                 + 0.5 - timeBinIdeal) / samplingRate;
1071           
1072       // Sample the time response inside the drift region
1073       // + additional time bins before and after.
1074       // The sampling is done always in the middle of the time bin
1075       for (Int_t iTimeBin = TMath::Max(timeBinTruncated,0)
1076           ;iTimeBin < TMath::Min(timeBinTruncated+timeBinTRFend,nTimeTotal)
1077           ;iTimeBin++) {
1078
1079         // Apply the time response
1080         Double_t timeResponse = 1.0;
1081         Double_t crossTalk    = 0.0;
1082         Double_t time         = (iTimeBin - timeBinTruncated) / samplingRate + timeOffset;
1083
1084         if (simParam->TRFOn()) {
1085           timeResponse = simParam->TimeResponse(time);
1086         }
1087         if (simParam->CTOn()) {
1088           crossTalk    = simParam->CrossTalk(time);
1089         }
1090
1091         signalOld[0] = 0.0;
1092         signalOld[1] = 0.0;
1093         signalOld[2] = 0.0;
1094
1095         for (iPad = 0; iPad < kNpad; iPad++) {
1096
1097           Int_t colPos = colE + iPad - 1;
1098           if (colPos <        0) continue;
1099           if (colPos >= nColMax) break;
1100
1101           // Add the signals
1102           signalOld[iPad] = signals->GetData(rowE,colPos,iTimeBin);
1103
1104           if (colPos != colE) {
1105             // Cross talk added to non-central pads
1106             signalOld[iPad] += padSignal[iPad] 
1107                              * (timeResponse + crossTalk);
1108           } 
1109           else {
1110             // W/o cross talk at central pad
1111             signalOld[iPad] += padSignal[iPad] 
1112                              * timeResponse;
1113           }
1114
1115           signals->SetData(rowE,colPos,iTimeBin,signalOld[iPad]);
1116
1117           // Store the track index in the dictionary
1118           // Note: We store index+1 in order to allow the array to be compressed
1119           // Note2: Taking out the +1 in track
1120           if (signalOld[iPad] > 0.0) { 
1121             for (dict = 0; dict < kNdict; dict++) {
1122               Int_t oldTrack = dictionary[dict]->GetData(rowE,colPos,iTimeBin); 
1123               if (oldTrack == track) break;
1124               if (oldTrack ==  -1 ) {
1125                 dictionary[dict]->SetData(rowE,colPos,iTimeBin,track);
1126                 break;
1127               }
1128             }
1129           }
1130
1131         } // Loop: pads
1132
1133       } // Loop: time bins
1134
1135     } // Loop: electrons of a single hit
1136
1137   } // Loop: hits
1138
1139   AliDebug(2,Form("Finished analyzing %d hits",nhit));
1140
1141   return kTRUE;
1142
1143 }
1144
1145 //_____________________________________________________________________________
1146 Bool_t AliTRDdigitizer::ConvertSignals(Int_t det, AliTRDarraySignal *signals)
1147 {
1148   //
1149   // Convert signals to digits
1150   //
1151
1152   AliDebug(1,Form("Start converting the signals for detector %d",det));
1153
1154   if (fSDigits) {
1155     // Convert the signal array to s-digits
1156     if (!Signal2SDigits(det,signals)) {
1157       return kFALSE;
1158     }
1159   }
1160   else {
1161     // Convert the signal array to digits
1162     if (!Signal2ADC(det,signals)) {
1163       return kFALSE;
1164     }
1165   }
1166
1167   // Compress the arrays
1168   CompressOutputArrays(det);   
1169
1170   return kTRUE;
1171
1172 }
1173
1174 //_____________________________________________________________________________
1175 Bool_t AliTRDdigitizer::Signal2ADC(Int_t det, AliTRDarraySignal *signals)
1176 {
1177   //
1178   // Converts the sampled electron signals to ADC values for a given chamber
1179   //
1180
1181   AliDebug(1,Form("Start converting signals to ADC values for detector=%d",det));
1182
1183   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1184   if (!calibration) {
1185     AliFatal("Could not get calibration object");
1186     return kFALSE;
1187   }
1188
1189   AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
1190   if (!simParam) {
1191     AliFatal("Could not get simulation parameters");
1192     return kFALSE;
1193   }  
1194
1195   // Converts number of electrons to fC
1196   const Double_t kEl2fC = 1.602e-19 * 1.0e15; 
1197
1198   // Coupling factor
1199   Double_t coupling     = simParam->GetPadCoupling() 
1200                         * simParam->GetTimeCoupling();
1201   // Electronics conversion factor
1202   Double_t convert      = kEl2fC 
1203                         * simParam->GetChipGain();
1204   // ADC conversion factor
1205   Double_t adcConvert   = simParam->GetADCoutRange()
1206                         / simParam->GetADCinRange();
1207   // The electronics baseline in mV
1208   Double_t baseline     = simParam->GetADCbaseline() 
1209                         / adcConvert;
1210   // The electronics baseline in electrons
1211   Double_t baselineEl   = baseline
1212                         / convert;
1213
1214   Int_t row  = 0;
1215   Int_t col  = 0;
1216   Int_t time = 0;
1217
1218   Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1219   Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1220   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1221
1222   // The gainfactor calibration objects
1223   const AliTRDCalDet *calGainFactorDet      = calibration->GetGainFactorDet();  
1224   AliTRDCalROC       *calGainFactorROC      = 0;
1225   Float_t             calGainFactorDetValue = 0.0;
1226
1227   AliTRDarrayADC     *digits = 0x0;
1228
1229   if (!signals) {
1230     AliError(Form("Signals array for detector %d does not exist\n",det));
1231     return kFALSE;
1232   }
1233   if (signals->HasData()) {
1234     // Expand the container if neccessary
1235     signals->Expand();   
1236   }
1237   else {
1238     // Create missing containers
1239     signals->Allocate(nRowMax,nColMax,nTimeTotal);      
1240   }
1241
1242   // Get the container for the digits of this detector
1243   if (fDigitsManager->HasSDigits()) {
1244     AliError("Digits manager has s-digits");
1245     return kFALSE;
1246   }
1247
1248   digits = (AliTRDarrayADC *) fDigitsManager->GetDigits(det);
1249   // Allocate memory space for the digits buffer
1250   if (!digits->HasData()) {
1251     digits->Allocate(nRowMax,nColMax,nTimeTotal);
1252   }
1253
1254   // Get the calibration objects
1255   calGainFactorROC      = calibration->GetGainFactorROC(det);
1256   calGainFactorDetValue = calGainFactorDet->GetValue(det);
1257
1258   // Create the digits for this chamber
1259   for (row  = 0; row  <  nRowMax; row++ ) {
1260     for (col  = 0; col  <  nColMax; col++ ) {
1261
1262       // Check whether pad is masked
1263       // Bridged pads are not considered yet!!!
1264       if (calibration->IsPadMasked(det,col,row)) {
1265         continue;
1266       }
1267
1268       // The gain factors
1269       Float_t padgain = calGainFactorDetValue 
1270                       * calGainFactorROC->GetValue(col,row);
1271       if (padgain <= 0) {
1272         AliError(Form("Not a valid gain %f, %d %d %d",padgain,det,col,row));
1273       }
1274
1275       for (time = 0; time < nTimeTotal; time++) {
1276
1277         // Get the signal amplitude
1278         Float_t signalAmp = signals->GetData(row,col,time);
1279         // Pad and time coupling
1280         signalAmp *= coupling;
1281         // Gain factors
1282         signalAmp *= padgain;
1283
1284         // Add the noise, starting from minus ADC baseline in electrons
1285         signalAmp  = TMath::Max((Double_t) gRandom->Gaus(signalAmp,simParam->GetNoise())
1286                                ,-baselineEl);
1287
1288         // Convert to mV
1289         signalAmp *= convert;
1290         // Add ADC baseline in mV
1291         signalAmp += baseline;
1292
1293         // Convert to ADC counts. Set the overflow-bit fADCoutRange if the
1294         // signal is larger than fADCinRange
1295         Short_t adc  = 0;
1296         if (signalAmp >= simParam->GetADCinRange()) {
1297           adc = ((Short_t) simParam->GetADCoutRange());
1298         }
1299         else {
1300           adc = TMath::Nint(signalAmp * adcConvert);
1301         }
1302
1303         // Saving all digits
1304         digits->SetData(row,col,time,adc);
1305
1306       } // for: time
1307
1308     } // for: col
1309   } // for: row
1310
1311   // Run the digital processing in the MCM
1312   RunDigitalProcessing(digits, det);
1313
1314   return kTRUE;
1315
1316 }
1317
1318 //_____________________________________________________________________________
1319 Bool_t AliTRDdigitizer::Signal2SDigits(Int_t det, AliTRDarraySignal *signals)
1320 {
1321   //
1322   // Converts the sampled electron signals to s-digits
1323   //
1324
1325   AliDebug(1,Form("Start converting signals to s-digits for detector=%d",det));
1326
1327   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1328   if (!calibration) {
1329     AliFatal("Could not get calibration object");
1330     return kFALSE;
1331   }
1332
1333   Int_t row  = 0;
1334   Int_t col  = 0;
1335   Int_t time = 0;
1336
1337   Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1338   Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1339   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1340
1341   // Get the container for the digits of this detector
1342
1343   if (!fDigitsManager->HasSDigits()) {
1344     AliError("Digits manager has no s-digits");
1345     return kFALSE;
1346   }
1347
1348   AliTRDarraySignal *digits = (AliTRDarraySignal *) fDigitsManager->GetSDigits(det);
1349   // Allocate memory space for the digits buffer
1350   if (!digits->HasData()) {
1351     digits->Allocate(nRowMax,nColMax,nTimeTotal);
1352   }
1353
1354   // Create the sdigits for this chamber
1355   for (row  = 0; row  <  nRowMax; row++ ) {
1356     for (col  = 0; col  <  nColMax; col++ ) {
1357       for (time = 0; time < nTimeTotal; time++) {         
1358         digits->SetData(row,col,time,signals->GetData(row,col,time));
1359       } // for: time
1360     } // for: col
1361   } // for: row
1362   
1363   return kTRUE;
1364
1365 }
1366
1367 //_____________________________________________________________________________
1368 Bool_t AliTRDdigitizer::SDigits2Digits()
1369 {
1370   //
1371   // Merges the input s-digits and converts them to normal digits
1372   //
1373
1374   if (!MergeSDigits()) {
1375     return kFALSE;
1376   }
1377
1378   return ConvertSDigits();
1379
1380 }
1381
1382 //_____________________________________________________________________________
1383 Bool_t AliTRDdigitizer::MergeSDigits()
1384 {
1385   //
1386   // Merges the input s-digits:
1387   //   - The amplitude of the different inputs are summed up.
1388   //   - Of the track IDs from the input dictionaries only one is
1389   //     kept for each input. This works for maximal 3 different merged inputs.
1390   //
1391
1392   // Number of track dictionary arrays
1393   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1394
1395   AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
1396   if (!simParam) {
1397     AliFatal("Could not get simulation parameters");
1398     return kFALSE;
1399   }
1400   
1401   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1402   if (!calibration) {
1403     AliFatal("Could not get calibration object");
1404     return kFALSE;
1405   }
1406   
1407   Int_t iDict = 0;
1408   Int_t jDict = 0;
1409
1410   AliTRDarraySignal     *digitsA;
1411   AliTRDarraySignal     *digitsB;
1412   AliTRDarrayDictionary *dictionaryA[kNDict];
1413   AliTRDarrayDictionary *dictionaryB[kNDict];
1414
1415   AliTRDdigitsManager   *mergeSDigitsManager = 0x0;
1416   // Get the first s-digits
1417   fSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->First();
1418   if (!fSDigitsManager) { 
1419     AliError("No SDigits manager");
1420     return kFALSE;
1421   }
1422
1423   // Loop through the other sets of s-digits
1424   mergeSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->After(fSDigitsManager);
1425
1426   if (mergeSDigitsManager) {
1427     AliDebug(1,Form("Merge %d input files.",fSDigitsManagerList->GetSize()));
1428   }
1429   else {
1430     AliDebug(1,"Only one input file.");
1431   }
1432   
1433   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();  
1434   Int_t iMerge = 0;
1435
1436   while (mergeSDigitsManager) {
1437
1438     iMerge++;
1439       
1440     // Loop through the detectors
1441     for (Int_t iDet = 0; iDet < AliTRDgeometry::Ndet(); iDet++) {
1442
1443       Int_t nRowMax = fGeo->GetPadPlane(iDet)->GetNrows();
1444       Int_t nColMax = fGeo->GetPadPlane(iDet)->GetNcols();
1445           
1446       // Loop through the pixels of one detector and add the signals
1447       digitsA = (AliTRDarraySignal *) fSDigitsManager->GetSDigits(iDet);    
1448       digitsB = (AliTRDarraySignal *) mergeSDigitsManager->GetSDigits(iDet); 
1449       digitsA->Expand();  
1450       if (!digitsA->HasData()) continue;
1451       digitsB->Expand();    
1452       if (!digitsB->HasData()) continue;
1453           
1454       for (iDict = 0; iDict < kNDict; iDict++) {
1455         dictionaryA[iDict] = (AliTRDarrayDictionary *) fSDigitsManager->GetDictionary(iDet,iDict);
1456         dictionaryB[iDict] = (AliTRDarrayDictionary *) mergeSDigitsManager->GetDictionary(iDet,iDict);
1457         dictionaryA[iDict]->Expand();  
1458         dictionaryB[iDict]->Expand();
1459       }
1460
1461       // Merge only detectors that contain a signal
1462       Bool_t doMerge = kTRUE;
1463       if (fMergeSignalOnly) {
1464         if (digitsA->GetOverThreshold(0) == 0) {                             
1465           doMerge = kFALSE;
1466         }
1467       }
1468           
1469       if (doMerge) {
1470               
1471         AliDebug(1,Form("Merge detector %d of input no.%d",iDet,iMerge+1));
1472               
1473         for (Int_t iRow  = 0; iRow  <  nRowMax;   iRow++ ) {
1474           for (Int_t iCol  = 0; iCol  <  nColMax;   iCol++ ) {
1475             for (Int_t iTime = 0; iTime < nTimeTotal; iTime++) {
1476                 
1477               // Add the amplitudes of the summable digits 
1478               Float_t ampA = digitsA->GetData(iRow,iCol,iTime);
1479               Float_t ampB = digitsB->GetData(iRow,iCol,iTime);
1480               ampA += ampB;
1481               digitsA->SetData(iRow,iCol,iTime,ampA);
1482
1483               // Add the mask to the track id if defined.
1484               for (iDict = 0; iDict < kNDict; iDict++) {
1485                 Int_t trackB = dictionaryB[iDict]->GetData(iRow,iCol,iTime);
1486                 if ((fMasks) && (trackB > 0))  {
1487                   for (jDict = 0; jDict < kNDict; jDict++) { 
1488                     Int_t trackA = dictionaryA[iDict]->GetData(iRow,iCol,iTime); 
1489                     if (trackA == 0) {
1490                       trackA = trackB + fMasks[iMerge];
1491                       dictionaryA[iDict]->SetData(iRow,iCol,iTime,trackA);  
1492                     } // if:  track A == 0
1493                   } // for: jDict
1494                 } // if:  fMasks and trackB > 0
1495               } // for: iDict
1496
1497             } // for: iTime
1498           } // for: iCol
1499         } // for: iRow
1500
1501       } // if:  doMerge
1502
1503       mergeSDigitsManager->RemoveDigits(iDet);
1504       mergeSDigitsManager->RemoveDictionaries(iDet);
1505   
1506       if (fCompress) {
1507         digitsA->Compress(0); 
1508         for (iDict = 0; iDict < kNDict; iDict++) {                                     
1509           dictionaryA[iDict]->Compress();
1510         }
1511       }
1512       
1513     } // for: detectors    
1514       
1515     // The next set of s-digits
1516     mergeSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->After(mergeSDigitsManager);
1517     
1518   } // while: mergeDigitsManagers
1519   
1520   return kTRUE;
1521
1522 }
1523
1524 //_____________________________________________________________________________
1525 Bool_t AliTRDdigitizer::ConvertSDigits()
1526 {
1527   //
1528   // Converts s-digits to normal digits
1529   //
1530
1531   AliTRDarraySignal *digitsIn = 0x0;
1532
1533   if (!fSDigitsManager->HasSDigits()) {
1534     AliError("No s-digits in digits manager");
1535     return kFALSE;
1536   }
1537
1538   // Loop through the detectors
1539   for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
1540
1541     // Get the merged s-digits (signals)
1542     digitsIn = (AliTRDarraySignal *) fSDigitsManager->GetSDigits(det);
1543     if (!digitsIn->HasData()) {
1544       AliDebug(2,Form("No digits for det=%d",det));
1545       continue;
1546     }
1547     
1548     // Convert the merged sdigits to digits
1549     if (!Signal2ADC(det,digitsIn)) {
1550       continue;
1551     }
1552
1553     // Copy the dictionary information to the output array
1554     if (!CopyDictionary(det)) {
1555       continue;
1556     }
1557
1558     // Delete 
1559     fSDigitsManager->RemoveDigits(det);
1560     fSDigitsManager->RemoveDictionaries(det);
1561
1562     // Compress the arrays
1563     CompressOutputArrays(det);
1564
1565   } // for: detector numbers
1566
1567
1568   return kTRUE;
1569
1570 }
1571
1572 //_____________________________________________________________________________
1573 Bool_t AliTRDdigitizer::CopyDictionary(Int_t det)
1574 {
1575   //
1576   // Copies the dictionary information from the s-digits arrays
1577   // to the output arrays
1578   //
1579
1580   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1581   if (!calibration) {
1582     AliFatal("Could not get calibration object");
1583     return kFALSE;
1584   }
1585
1586   AliDebug(1,Form("Start copying dictionaries for detector=%d",det));
1587
1588   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1589   AliTRDarrayDictionary *dictionaryIn[kNDict];
1590   AliTRDarrayDictionary *dictionaryOut[kNDict];
1591
1592   Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1593   Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1594   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1595
1596   Int_t row  = 0;
1597   Int_t col  = 0;
1598   Int_t time = 0;
1599   Int_t dict = 0;
1600
1601   for (dict = 0; dict < kNDict; dict++) {
1602
1603     dictionaryIn[dict]  = (AliTRDarrayDictionary *) fSDigitsManager->GetDictionary(det,dict);
1604     dictionaryIn[dict]->Expand();
1605     dictionaryOut[dict] = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(det,dict);
1606     dictionaryOut[dict]->Allocate(nRowMax,nColMax,nTimeTotal);
1607
1608     for (row = 0; row < nRowMax; row++) {
1609       for (col = 0; col < nColMax; col++) {
1610         for (time = 0; time < nTimeTotal; time++) {
1611           Int_t track = dictionaryIn[dict]->GetData(row,col,time);
1612           dictionaryOut[dict]->SetData(row,col,time,track);
1613         } // for: time
1614       } // for: col
1615     } // for: row
1616     
1617   } // for: dictionaries
1618   
1619   return kTRUE;
1620
1621 }
1622
1623 //_____________________________________________________________________________
1624 void AliTRDdigitizer::CompressOutputArrays(Int_t det)
1625 {
1626   //
1627   // Compress the output arrays
1628   //
1629
1630   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1631   AliTRDarrayDictionary *dictionary = 0x0;
1632
1633   if (fCompress) {
1634
1635     if (!fSDigits) {
1636       AliTRDarrayADC *digits = 0x0;  
1637       digits = (AliTRDarrayADC *) fDigitsManager->GetDigits(det);
1638       digits->Compress();
1639     }
1640
1641     if (fSDigits) {
1642       AliTRDarraySignal *digits = 0x0; 
1643       digits = (AliTRDarraySignal *) fDigitsManager->GetSDigits(det);
1644       digits->Compress(0);
1645     }
1646
1647     for (Int_t dict = 0; dict < kNDict; dict++) {
1648       dictionary = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(det,dict);
1649       dictionary->Compress();
1650     }
1651
1652   }
1653
1654 }
1655
1656 //_____________________________________________________________________________
1657 Bool_t AliTRDdigitizer::WriteDigits() const
1658 {
1659   //
1660   // Writes out the TRD-digits and the dictionaries
1661   //
1662
1663   // Write parameters
1664   fRunLoader->CdGAFile();
1665
1666   // Store the digits and the dictionary in the tree
1667   return fDigitsManager->WriteDigits();
1668
1669 }
1670
1671 //_____________________________________________________________________________
1672 void AliTRDdigitizer::InitOutput(Int_t iEvent)
1673 {
1674   //
1675   // Initializes the output branches
1676   //
1677
1678   fEvent = iEvent;
1679    
1680   if (!fRunLoader) {
1681     AliError("Run Loader is NULL");
1682     return;  
1683   }
1684
1685   AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
1686   if (!loader) {
1687     AliError("Can not get TRD loader from Run Loader");
1688     return;
1689   }
1690
1691   TTree *tree = 0;
1692   
1693   if (fSDigits) { 
1694     // If we produce SDigits
1695     tree = loader->TreeS();
1696     if (!tree) {
1697       loader->MakeTree("S");
1698       tree = loader->TreeS();
1699     }
1700   }
1701   else {
1702     // If we produce Digits
1703     tree = loader->TreeD();
1704     if (!tree) {
1705       loader->MakeTree("D");
1706       tree = loader->TreeD();
1707     }
1708   }
1709   fDigitsManager->SetEvent(iEvent);
1710   fDigitsManager->MakeBranch(tree);
1711
1712 }
1713   
1714 //_____________________________________________________________________________
1715 Int_t AliTRDdigitizer::Diffusion(Float_t vdrift, Double_t absdriftlength
1716                                , Double_t &lRow, Double_t &lCol, Double_t &lTime)
1717 {
1718   //
1719   // Applies the diffusion smearing to the position of a single electron.
1720   // Depends on absolute drift length.
1721   //
1722   
1723   Float_t diffL = 0.0;
1724   Float_t diffT = 0.0;
1725
1726   if (AliTRDCommonParam::Instance()->GetDiffCoeff(diffL,diffT,vdrift)) {
1727
1728     Float_t driftSqrt = TMath::Sqrt(absdriftlength);
1729     Float_t sigmaT    = driftSqrt * diffT;
1730     Float_t sigmaL    = driftSqrt * diffL;
1731     lRow  = gRandom->Gaus(lRow ,sigmaT);
1732     lCol  = gRandom->Gaus(lCol ,sigmaT * GetLorentzFactor(vdrift));
1733     lTime = gRandom->Gaus(lTime,sigmaL * GetLorentzFactor(vdrift));
1734
1735     return 1;
1736
1737   }
1738   else {
1739
1740     return 0;
1741
1742   }
1743
1744 }
1745
1746 //_____________________________________________________________________________
1747 Float_t AliTRDdigitizer::GetLorentzFactor(Float_t vd)
1748 {
1749   //
1750   // Returns the Lorentz factor
1751   //
1752
1753   Double_t omegaTau      = AliTRDCommonParam::Instance()->GetOmegaTau(vd);
1754   Double_t lorentzFactor = 1.0;
1755   if (AliTRDCommonParam::Instance()->ExBOn()) {
1756     lorentzFactor = 1.0 / (1.0 + omegaTau*omegaTau);
1757   }
1758
1759   return lorentzFactor;
1760
1761 }
1762   
1763 //_____________________________________________________________________________
1764 Int_t AliTRDdigitizer::ExB(Float_t vdrift, Double_t driftlength, Double_t &lCol)
1765 {
1766   //
1767   // Applies E x B effects to the position of a single electron.
1768   // Depends on signed drift length.
1769   //
1770
1771   lCol = lCol 
1772        + AliTRDCommonParam::Instance()->GetOmegaTau(vdrift) 
1773        * driftlength;
1774
1775   return 1;
1776
1777 }
1778
1779 //_____________________________________________________________________________
1780 void AliTRDdigitizer::RunDigitalProcessing(AliTRDarrayADC *digits, Int_t det)
1781 {
1782   //
1783   // Run the digital processing in the TRAP
1784   //
1785
1786   AliTRDfeeParam *feeParam = AliTRDfeeParam::Instance();
1787
1788   //Create and initialize the mcm object 
1789   AliTRDmcmSim* mcmfast = new AliTRDmcmSim(); 
1790
1791   //Call the methods in the mcm class using the temporary array as input  
1792   for(Int_t rob = 0; rob < digits->GetNrow() / 2; rob++)
1793   {
1794     for(Int_t mcm = 0; mcm < 16; mcm++)
1795     {
1796       mcmfast->Init(det, rob, mcm); 
1797       mcmfast->SetData(digits, fDigitsManager);
1798       mcmfast->Filter();
1799       if (feeParam->GetTracklet()) {
1800         mcmfast->Tracklet();
1801         mcmfast->StoreTracklets();
1802       }
1803       mcmfast->ZSMapping();
1804       mcmfast->WriteData(digits);
1805     }
1806   }
1807
1808   delete mcmfast;
1809 }