]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDdigitizer.cxx
- Error estimation for the tilted Riemann Fit (this is necessary since their
[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     // Run digital processing for digits
1166     RunDigitalProcessing(det);
1167   }
1168
1169   // Compress the arrays
1170   CompressOutputArrays(det);   
1171
1172   return kTRUE;
1173
1174 }
1175
1176 //_____________________________________________________________________________
1177 Bool_t AliTRDdigitizer::Signal2ADC(Int_t det, AliTRDarraySignal *signals)
1178 {
1179   //
1180   // Converts the sampled electron signals to ADC values for a given chamber
1181   //
1182
1183   AliDebug(1,Form("Start converting signals to ADC values for detector=%d",det));
1184
1185   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1186   if (!calibration) {
1187     AliFatal("Could not get calibration object");
1188     return kFALSE;
1189   }
1190
1191   AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
1192   if (!simParam) {
1193     AliFatal("Could not get simulation parameters");
1194     return kFALSE;
1195   }  
1196
1197   // Converts number of electrons to fC
1198   const Double_t kEl2fC = 1.602e-19 * 1.0e15; 
1199
1200   // Coupling factor
1201   Double_t coupling     = simParam->GetPadCoupling() 
1202                         * simParam->GetTimeCoupling();
1203   // Electronics conversion factor
1204   Double_t convert      = kEl2fC 
1205                         * simParam->GetChipGain();
1206   // ADC conversion factor
1207   Double_t adcConvert   = simParam->GetADCoutRange()
1208                         / simParam->GetADCinRange();
1209   // The electronics baseline in mV
1210   Double_t baseline     = simParam->GetADCbaseline() 
1211                         / adcConvert;
1212   // The electronics baseline in electrons
1213   Double_t baselineEl   = baseline
1214                         / convert;
1215
1216   Int_t row  = 0;
1217   Int_t col  = 0;
1218   Int_t time = 0;
1219
1220   Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1221   Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1222   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1223
1224   // The gainfactor calibration objects
1225   const AliTRDCalDet *calGainFactorDet      = calibration->GetGainFactorDet();  
1226   AliTRDCalROC       *calGainFactorROC      = 0;
1227   Float_t             calGainFactorDetValue = 0.0;
1228
1229   AliTRDarrayADC     *digits = 0x0;
1230
1231   if (!signals) {
1232     AliError(Form("Signals array for detector %d does not exist\n",det));
1233     return kFALSE;
1234   }
1235   if (signals->HasData()) {
1236     // Expand the container if neccessary
1237     signals->Expand();   
1238   }
1239   else {
1240     // Create missing containers
1241     signals->Allocate(nRowMax,nColMax,nTimeTotal);      
1242   }
1243
1244   // Get the container for the digits of this detector
1245   if (fDigitsManager->HasSDigits()) {
1246     AliError("Digits manager has s-digits");
1247     return kFALSE;
1248   }
1249
1250   digits = (AliTRDarrayADC *) fDigitsManager->GetDigits(det);
1251   // Allocate memory space for the digits buffer
1252   if (!digits->HasData()) {
1253     digits->Allocate(nRowMax,nColMax,nTimeTotal);
1254   }
1255
1256   // Get the calibration objects
1257   calGainFactorROC      = calibration->GetGainFactorROC(det);
1258   calGainFactorDetValue = calGainFactorDet->GetValue(det);
1259
1260   // Create the digits for this chamber
1261   for (row  = 0; row  <  nRowMax; row++ ) {
1262     for (col  = 0; col  <  nColMax; col++ ) {
1263
1264       // Check whether pad is masked
1265       // Bridged pads are not considered yet!!!
1266       if (calibration->IsPadMasked(det,col,row)) {
1267         continue;
1268       }
1269
1270       // The gain factors
1271       Float_t padgain = calGainFactorDetValue 
1272                       * calGainFactorROC->GetValue(col,row);
1273       if (padgain <= 0) {
1274         AliError(Form("Not a valid gain %f, %d %d %d",padgain,det,col,row));
1275       }
1276
1277       for (time = 0; time < nTimeTotal; time++) {
1278
1279         // Get the signal amplitude
1280         Float_t signalAmp = signals->GetData(row,col,time);
1281         // Pad and time coupling
1282         signalAmp *= coupling;
1283         // Gain factors
1284         signalAmp *= padgain;
1285
1286         // Add the noise, starting from minus ADC baseline in electrons
1287         signalAmp  = TMath::Max((Double_t) gRandom->Gaus(signalAmp,simParam->GetNoise())
1288                                ,-baselineEl);
1289
1290         // Convert to mV
1291         signalAmp *= convert;
1292         // Add ADC baseline in mV
1293         signalAmp += baseline;
1294
1295         // Convert to ADC counts. Set the overflow-bit fADCoutRange if the
1296         // signal is larger than fADCinRange
1297         Short_t adc  = 0;
1298         if (signalAmp >= simParam->GetADCinRange()) {
1299           adc = ((Short_t) simParam->GetADCoutRange());
1300         }
1301         else {
1302           adc = TMath::Nint(signalAmp * adcConvert);
1303         }
1304
1305         // Saving all digits
1306         digits->SetData(row,col,time,adc);
1307
1308       } // for: time
1309
1310     } // for: col
1311   } // for: row
1312
1313   return kTRUE;
1314
1315 }
1316
1317 //_____________________________________________________________________________
1318 Bool_t AliTRDdigitizer::Signal2SDigits(Int_t det, AliTRDarraySignal *signals)
1319 {
1320   //
1321   // Converts the sampled electron signals to s-digits
1322   //
1323
1324   AliDebug(1,Form("Start converting signals to s-digits for detector=%d",det));
1325
1326   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1327   if (!calibration) {
1328     AliFatal("Could not get calibration object");
1329     return kFALSE;
1330   }
1331
1332   Int_t row  = 0;
1333   Int_t col  = 0;
1334   Int_t time = 0;
1335
1336   Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1337   Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1338   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1339
1340   // Get the container for the digits of this detector
1341
1342   if (!fDigitsManager->HasSDigits()) {
1343     AliError("Digits manager has no s-digits");
1344     return kFALSE;
1345   }
1346
1347   AliTRDarraySignal *digits = (AliTRDarraySignal *) fDigitsManager->GetSDigits(det);
1348   // Allocate memory space for the digits buffer
1349   if (!digits->HasData()) {
1350     digits->Allocate(nRowMax,nColMax,nTimeTotal);
1351   }
1352
1353   // Create the sdigits for this chamber
1354   for (row  = 0; row  <  nRowMax; row++ ) {
1355     for (col  = 0; col  <  nColMax; col++ ) {
1356       for (time = 0; time < nTimeTotal; time++) {         
1357         digits->SetData(row,col,time,signals->GetData(row,col,time));
1358       } // for: time
1359     } // for: col
1360   } // for: row
1361   
1362   return kTRUE;
1363
1364 }
1365
1366 //_____________________________________________________________________________
1367 Bool_t AliTRDdigitizer::Digits2SDigits(AliTRDdigitsManager *manDig
1368                                      , AliTRDdigitsManager *manSDig)
1369 {
1370   //
1371   // Converts digits into s-digits. Needed for embedding into real data.
1372   //
1373
1374   AliDebug(1,"Start converting digits to s-digits");
1375
1376   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1377   if (!calibration) {
1378     AliFatal("Could not get calibration object");
1379     return kFALSE;
1380   }
1381
1382   AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
1383   if (!simParam) {
1384     AliFatal("Could not get simulation parameters");
1385     return kFALSE;
1386   }  
1387
1388   // Converts number of electrons to fC
1389   const Double_t kEl2fC = 1.602e-19 * 1.0e15; 
1390
1391   // Coupling factor
1392   Double_t coupling     = simParam->GetPadCoupling() 
1393                         * simParam->GetTimeCoupling();
1394   // Electronics conversion factor
1395   Double_t convert      = kEl2fC 
1396                         * simParam->GetChipGain();
1397   // ADC conversion factor
1398   Double_t adcConvert   = simParam->GetADCoutRange()
1399                         / simParam->GetADCinRange();
1400   // The electronics baseline in mV
1401   Double_t baseline     = simParam->GetADCbaseline() 
1402                         / adcConvert;
1403   // The electronics baseline in electrons
1404   Double_t baselineEl   = baseline
1405                         / convert;
1406
1407   // The gainfactor calibration objects
1408   //const AliTRDCalDet *calGainFactorDet      = calibration->GetGainFactorDet();  
1409   //AliTRDCalROC       *calGainFactorROC      = 0;
1410   //Float_t             calGainFactorDetValue = 0.0;
1411
1412   Int_t row  = 0;
1413   Int_t col  = 0;
1414   Int_t time = 0;
1415
1416   for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
1417
1418     Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1419     Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1420     Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1421
1422     // Get the calibration objects
1423     //calGainFactorROC      = calibration->GetGainFactorROC(det);
1424     //calGainFactorDetValue = calGainFactorDet->GetValue(det);
1425
1426     // Get the digits
1427     AliTRDarrayADC *digits = (AliTRDarrayADC *) manDig->GetDigits(det);
1428
1429     if (!manSDig->HasSDigits()) {
1430       AliError("SDigits manager has no s-digits");
1431       return kFALSE;
1432     }
1433     // Get the s-digits
1434     AliTRDarraySignal     *sdigits = (AliTRDarraySignal *)     manSDig->GetSDigits(det);
1435     AliTRDarrayDictionary *tracks0 = (AliTRDarrayDictionary *) manSDig->GetDictionary(det,0);
1436     AliTRDarrayDictionary *tracks1 = (AliTRDarrayDictionary *) manSDig->GetDictionary(det,1);
1437     AliTRDarrayDictionary *tracks2 = (AliTRDarrayDictionary *) manSDig->GetDictionary(det,2);
1438     // Allocate memory space for the digits buffer
1439     sdigits->Allocate(nRowMax,nColMax,nTimeTotal);
1440     tracks0->Allocate(nRowMax,nColMax,nTimeTotal);
1441     tracks1->Allocate(nRowMax,nColMax,nTimeTotal);
1442     tracks2->Allocate(nRowMax,nColMax,nTimeTotal);
1443
1444     // Create the sdigits for this chamber
1445     for (row  = 0; row  <  nRowMax; row++ ) {
1446       for (col  = 0; col  <  nColMax; col++ ) {
1447
1448         // The gain factors
1449         //Float_t padgain = calGainFactorDetValue 
1450         //                * calGainFactorROC->GetValue(col,row);
1451
1452         for (time = 0; time < nTimeTotal; time++) {
1453
1454           Double_t signal = (Double_t) digits->GetData(row,col,time);
1455
1456           // ADC -> signal in mV
1457           signal /= adcConvert;
1458
1459           // Subtract baseline in mV
1460           signal -= baseline;
1461
1462           // Signal in mV -> signal in #electrons
1463           signal /= convert;
1464
1465           // Gain factor
1466           //signal /= padgain; // Not needed for real data
1467
1468           // Pad and time coupling
1469           signal /= coupling;
1470
1471           sdigits->SetData(row,col,time,signal);
1472           tracks0->SetData(row,col,time,0);
1473           tracks1->SetData(row,col,time,0);
1474           tracks2->SetData(row,col,time,0);
1475
1476         } // for: time
1477
1478       } // for: col
1479     } // for: row
1480   
1481     sdigits->Compress(0);
1482     tracks0->Compress();
1483     tracks1->Compress();
1484     tracks2->Compress();
1485
1486   } // for: det
1487
1488   return kTRUE;
1489
1490 }
1491
1492 //_____________________________________________________________________________
1493 Bool_t AliTRDdigitizer::SDigits2Digits()
1494 {
1495   //
1496   // Merges the input s-digits and converts them to normal digits
1497   //
1498
1499   if (!MergeSDigits()) {
1500     return kFALSE;
1501   }
1502
1503   return ConvertSDigits();
1504
1505 }
1506
1507 //_____________________________________________________________________________
1508 Bool_t AliTRDdigitizer::MergeSDigits()
1509 {
1510   //
1511   // Merges the input s-digits:
1512   //   - The amplitude of the different inputs are summed up.
1513   //   - Of the track IDs from the input dictionaries only one is
1514   //     kept for each input. This works for maximal 3 different merged inputs.
1515   //
1516
1517   // Number of track dictionary arrays
1518   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1519
1520   AliTRDSimParam    *simParam    = AliTRDSimParam::Instance();
1521   if (!simParam) {
1522     AliFatal("Could not get simulation parameters");
1523     return kFALSE;
1524   }
1525   
1526   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1527   if (!calibration) {
1528     AliFatal("Could not get calibration object");
1529     return kFALSE;
1530   }
1531   
1532   Int_t iDict = 0;
1533   Int_t jDict = 0;
1534
1535   AliTRDarraySignal     *digitsA;
1536   AliTRDarraySignal     *digitsB;
1537   AliTRDarrayDictionary *dictionaryA[kNDict];
1538   AliTRDarrayDictionary *dictionaryB[kNDict];
1539
1540   AliTRDdigitsManager   *mergeSDigitsManager = 0x0;
1541   // Get the first s-digits
1542   fSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->First();
1543   if (!fSDigitsManager) { 
1544     AliError("No SDigits manager");
1545     return kFALSE;
1546   }
1547
1548   // Loop through the other sets of s-digits
1549   mergeSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->After(fSDigitsManager);
1550
1551   if (mergeSDigitsManager) {
1552     AliDebug(1,Form("Merge %d input files.",fSDigitsManagerList->GetSize()));
1553   }
1554   else {
1555     AliDebug(1,"Only one input file.");
1556   }
1557   
1558   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();  
1559   Int_t iMerge = 0;
1560
1561   while (mergeSDigitsManager) {
1562
1563     iMerge++;
1564       
1565     // Loop through the detectors
1566     for (Int_t iDet = 0; iDet < AliTRDgeometry::Ndet(); iDet++) {
1567
1568       Int_t nRowMax = fGeo->GetPadPlane(iDet)->GetNrows();
1569       Int_t nColMax = fGeo->GetPadPlane(iDet)->GetNcols();
1570           
1571       // Loop through the pixels of one detector and add the signals
1572       digitsA = (AliTRDarraySignal *) fSDigitsManager->GetSDigits(iDet);    
1573       digitsB = (AliTRDarraySignal *) mergeSDigitsManager->GetSDigits(iDet); 
1574       digitsA->Expand();  
1575       if (!digitsA->HasData()) continue;
1576       digitsB->Expand();    
1577       if (!digitsB->HasData()) continue;
1578           
1579       for (iDict = 0; iDict < kNDict; iDict++) {
1580         dictionaryA[iDict] = (AliTRDarrayDictionary *) fSDigitsManager->GetDictionary(iDet,iDict);
1581         dictionaryB[iDict] = (AliTRDarrayDictionary *) mergeSDigitsManager->GetDictionary(iDet,iDict);
1582         dictionaryA[iDict]->Expand();  
1583         dictionaryB[iDict]->Expand();
1584       }
1585
1586       // Merge only detectors that contain a signal
1587       Bool_t doMerge = kTRUE;
1588       if (fMergeSignalOnly) {
1589         if (digitsA->GetOverThreshold(0) == 0) {                             
1590           doMerge = kFALSE;
1591         }
1592       }
1593           
1594       if (doMerge) {
1595               
1596         AliDebug(1,Form("Merge detector %d of input no.%d",iDet,iMerge+1));
1597               
1598         for (Int_t iRow  = 0; iRow  <  nRowMax;   iRow++ ) {
1599           for (Int_t iCol  = 0; iCol  <  nColMax;   iCol++ ) {
1600             for (Int_t iTime = 0; iTime < nTimeTotal; iTime++) {
1601                 
1602               // Add the amplitudes of the summable digits 
1603               Float_t ampA = digitsA->GetData(iRow,iCol,iTime);
1604               Float_t ampB = digitsB->GetData(iRow,iCol,iTime);
1605               ampA += ampB;
1606               digitsA->SetData(iRow,iCol,iTime,ampA);
1607
1608               // Add the mask to the track id if defined.
1609               for (iDict = 0; iDict < kNDict; iDict++) {
1610                 Int_t trackB = dictionaryB[iDict]->GetData(iRow,iCol,iTime);
1611                 if ((fMasks) && (trackB > 0))  {
1612                   for (jDict = 0; jDict < kNDict; jDict++) { 
1613                     Int_t trackA = dictionaryA[iDict]->GetData(iRow,iCol,iTime); 
1614                     if (trackA == 0) {
1615                       trackA = trackB + fMasks[iMerge];
1616                       dictionaryA[iDict]->SetData(iRow,iCol,iTime,trackA);  
1617                     } // if:  track A == 0
1618                   } // for: jDict
1619                 } // if:  fMasks and trackB > 0
1620               } // for: iDict
1621
1622             } // for: iTime
1623           } // for: iCol
1624         } // for: iRow
1625
1626       } // if:  doMerge
1627
1628       mergeSDigitsManager->RemoveDigits(iDet);
1629       mergeSDigitsManager->RemoveDictionaries(iDet);
1630   
1631       if (fCompress) {
1632         digitsA->Compress(0); 
1633         for (iDict = 0; iDict < kNDict; iDict++) {                                     
1634           dictionaryA[iDict]->Compress();
1635         }
1636       }
1637       
1638     } // for: detectors    
1639       
1640     // The next set of s-digits
1641     mergeSDigitsManager = (AliTRDdigitsManager *) fSDigitsManagerList->After(mergeSDigitsManager);
1642     
1643   } // while: mergeDigitsManagers
1644   
1645   return kTRUE;
1646
1647 }
1648
1649 //_____________________________________________________________________________
1650 Bool_t AliTRDdigitizer::ConvertSDigits()
1651 {
1652   //
1653   // Converts s-digits to normal digits
1654   //
1655
1656   AliTRDarraySignal *digitsIn = 0x0;
1657
1658   if (!fSDigitsManager->HasSDigits()) {
1659     AliError("No s-digits in digits manager");
1660     return kFALSE;
1661   }
1662
1663   // Loop through the detectors
1664   for (Int_t det = 0; det < AliTRDgeometry::Ndet(); det++) {
1665
1666     // Get the merged s-digits (signals)
1667     digitsIn = (AliTRDarraySignal *) fSDigitsManager->GetSDigits(det);
1668     if (!digitsIn->HasData()) {
1669       AliDebug(2,Form("No digits for det=%d",det));
1670       continue;
1671     }
1672     
1673     // Convert the merged sdigits to digits
1674     if (!Signal2ADC(det,digitsIn)) {
1675       continue;
1676     }
1677
1678     // Copy the dictionary information to the output array
1679     if (!CopyDictionary(det)) {
1680       continue;
1681     }
1682
1683     // Delete 
1684     fSDigitsManager->RemoveDigits(det);
1685     fSDigitsManager->RemoveDictionaries(det);
1686
1687     // Run digital processing
1688     RunDigitalProcessing(det);
1689
1690     // Compress the arrays
1691     CompressOutputArrays(det);
1692
1693   } // for: detector numbers
1694
1695
1696   return kTRUE;
1697
1698 }
1699
1700 //_____________________________________________________________________________
1701 Bool_t AliTRDdigitizer::CopyDictionary(Int_t det)
1702 {
1703   //
1704   // Copies the dictionary information from the s-digits arrays
1705   // to the output arrays
1706   //
1707
1708   AliTRDcalibDB     *calibration = AliTRDcalibDB::Instance();
1709   if (!calibration) {
1710     AliFatal("Could not get calibration object");
1711     return kFALSE;
1712   }
1713
1714   AliDebug(1,Form("Start copying dictionaries for detector=%d",det));
1715
1716   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1717   AliTRDarrayDictionary *dictionaryIn[kNDict];
1718   AliTRDarrayDictionary *dictionaryOut[kNDict];
1719
1720   Int_t nRowMax    = fGeo->GetPadPlane(det)->GetNrows();
1721   Int_t nColMax    = fGeo->GetPadPlane(det)->GetNcols();
1722   Int_t nTimeTotal = calibration->GetNumberOfTimeBins();
1723
1724   Int_t row  = 0;
1725   Int_t col  = 0;
1726   Int_t time = 0;
1727   Int_t dict = 0;
1728
1729   for (dict = 0; dict < kNDict; dict++) {
1730
1731     dictionaryIn[dict]  = (AliTRDarrayDictionary *) fSDigitsManager->GetDictionary(det,dict);
1732     dictionaryIn[dict]->Expand();
1733     dictionaryOut[dict] = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(det,dict);
1734     dictionaryOut[dict]->Allocate(nRowMax,nColMax,nTimeTotal);
1735
1736     for (row = 0; row < nRowMax; row++) {
1737       for (col = 0; col < nColMax; col++) {
1738         for (time = 0; time < nTimeTotal; time++) {
1739           Int_t track = dictionaryIn[dict]->GetData(row,col,time);
1740           dictionaryOut[dict]->SetData(row,col,time,track);
1741         } // for: time
1742       } // for: col
1743     } // for: row
1744     
1745   } // for: dictionaries
1746   
1747   return kTRUE;
1748
1749 }
1750
1751 //_____________________________________________________________________________
1752 void AliTRDdigitizer::CompressOutputArrays(Int_t det)
1753 {
1754   //
1755   // Compress the output arrays
1756   //
1757
1758   const Int_t kNDict = AliTRDdigitsManager::kNDict;
1759   AliTRDarrayDictionary *dictionary = 0x0;
1760
1761   if (fCompress) {
1762
1763     if (!fSDigits) {
1764       AliTRDarrayADC *digits = 0x0;  
1765       digits = (AliTRDarrayADC *) fDigitsManager->GetDigits(det);
1766       digits->Compress();
1767     }
1768
1769     if (fSDigits) {
1770       AliTRDarraySignal *digits = 0x0; 
1771       digits = (AliTRDarraySignal *) fDigitsManager->GetSDigits(det);
1772       digits->Compress(0);
1773     }
1774
1775     for (Int_t dict = 0; dict < kNDict; dict++) {
1776       dictionary = (AliTRDarrayDictionary *) fDigitsManager->GetDictionary(det,dict);
1777       dictionary->Compress();
1778     }
1779
1780   }
1781
1782 }
1783
1784 //_____________________________________________________________________________
1785 Bool_t AliTRDdigitizer::WriteDigits() const
1786 {
1787   //
1788   // Writes out the TRD-digits and the dictionaries
1789   //
1790
1791   // Write parameters
1792   fRunLoader->CdGAFile();
1793
1794   // Store the digits and the dictionary in the tree
1795   return fDigitsManager->WriteDigits();
1796
1797 }
1798
1799 //_____________________________________________________________________________
1800 void AliTRDdigitizer::InitOutput(Int_t iEvent)
1801 {
1802   //
1803   // Initializes the output branches
1804   //
1805
1806   fEvent = iEvent;
1807    
1808   if (!fRunLoader) {
1809     AliError("Run Loader is NULL");
1810     return;  
1811   }
1812
1813   AliLoader *loader = fRunLoader->GetLoader("TRDLoader");
1814   if (!loader) {
1815     AliError("Can not get TRD loader from Run Loader");
1816     return;
1817   }
1818
1819   TTree *tree = 0;
1820   
1821   if (fSDigits) { 
1822     // If we produce SDigits
1823     tree = loader->TreeS();
1824     if (!tree) {
1825       loader->MakeTree("S");
1826       tree = loader->TreeS();
1827     }
1828   }
1829   else {
1830     // If we produce Digits
1831     tree = loader->TreeD();
1832     if (!tree) {
1833       loader->MakeTree("D");
1834       tree = loader->TreeD();
1835     }
1836   }
1837   fDigitsManager->SetEvent(iEvent);
1838   fDigitsManager->MakeBranch(tree);
1839
1840 }
1841   
1842 //_____________________________________________________________________________
1843 Int_t AliTRDdigitizer::Diffusion(Float_t vdrift, Double_t absdriftlength
1844                                , Double_t &lRow, Double_t &lCol, Double_t &lTime)
1845 {
1846   //
1847   // Applies the diffusion smearing to the position of a single electron.
1848   // Depends on absolute drift length.
1849   //
1850   
1851   Float_t diffL = 0.0;
1852   Float_t diffT = 0.0;
1853
1854   if (AliTRDCommonParam::Instance()->GetDiffCoeff(diffL,diffT,vdrift)) {
1855
1856     Float_t driftSqrt = TMath::Sqrt(absdriftlength);
1857     Float_t sigmaT    = driftSqrt * diffT;
1858     Float_t sigmaL    = driftSqrt * diffL;
1859     lRow  = gRandom->Gaus(lRow ,sigmaT);
1860     lCol  = gRandom->Gaus(lCol ,sigmaT * GetLorentzFactor(vdrift));
1861     lTime = gRandom->Gaus(lTime,sigmaL * GetLorentzFactor(vdrift));
1862
1863     return 1;
1864
1865   }
1866   else {
1867
1868     return 0;
1869
1870   }
1871
1872 }
1873
1874 //_____________________________________________________________________________
1875 Float_t AliTRDdigitizer::GetLorentzFactor(Float_t vd)
1876 {
1877   //
1878   // Returns the Lorentz factor
1879   //
1880
1881   Double_t omegaTau      = AliTRDCommonParam::Instance()->GetOmegaTau(vd);
1882   Double_t lorentzFactor = 1.0;
1883   if (AliTRDCommonParam::Instance()->ExBOn()) {
1884     lorentzFactor = 1.0 / (1.0 + omegaTau*omegaTau);
1885   }
1886
1887   return lorentzFactor;
1888
1889 }
1890   
1891 //_____________________________________________________________________________
1892 Int_t AliTRDdigitizer::ExB(Float_t vdrift, Double_t driftlength, Double_t &lCol)
1893 {
1894   //
1895   // Applies E x B effects to the position of a single electron.
1896   // Depends on signed drift length.
1897   //
1898
1899   lCol = lCol 
1900        + AliTRDCommonParam::Instance()->GetOmegaTau(vdrift) 
1901        * driftlength;
1902
1903   return 1;
1904
1905 }
1906
1907 //_____________________________________________________________________________
1908 void AliTRDdigitizer::RunDigitalProcessing(Int_t det)
1909 {
1910   //
1911   // Run the digital processing in the TRAP
1912   //
1913
1914   AliTRDfeeParam *feeParam = AliTRDfeeParam::Instance();
1915
1916   //Create and initialize the mcm object 
1917   AliTRDmcmSim* mcmfast = new AliTRDmcmSim(); 
1918
1919   AliTRDarrayADC *digits = fDigitsManager->GetDigits(det);
1920   if (!digits)
1921     return;
1922
1923   //Call the methods in the mcm class using the temporary array as input  
1924   for(Int_t rob = 0; rob < digits->GetNrow() / 2; rob++)
1925   {
1926     for(Int_t mcm = 0; mcm < 16; mcm++)
1927     {
1928       mcmfast->Init(det, rob, mcm); 
1929       mcmfast->SetData(digits, fDigitsManager);
1930       mcmfast->Filter();
1931       if (feeParam->GetTracklet()) {
1932         mcmfast->Tracklet();
1933         mcmfast->StoreTracklets();
1934       }
1935       mcmfast->ZSMapping();
1936       mcmfast->WriteData(digits);
1937     }
1938   }
1939
1940   delete mcmfast;
1941
1942 }