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