Fixed some coding style violations.
[u/mrichter/AliRoot.git] / FMD / AliFMDDigitizer.cxx
1 /**************************************************************************
2  * Copyright(c) 2004, 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 //  This class contains the procedures simulation ADC  signal for the
21 //  Forward Multiplicity detector  : Hits->Digits and Hits->SDigits
22 // 
23 //  Digits consists of
24 //   - Detector #
25 //   - Ring ID                                             
26 //   - Sector #     
27 //   - Strip #
28 //   - ADC count in this channel                                  
29 //
30 //  Digits consists of
31 //   - Detector #
32 //   - Ring ID                                             
33 //   - Sector #     
34 //   - Strip #
35 //   - Total energy deposited in the strip
36 //   - ADC count in this channel                                  
37 //
38 // As the Digits and SDigits have so much in common, the classes
39 // AliFMDDigitizer and AliFMDSDigitizer are implemented via a base
40 // class AliFMDBaseDigitizer.
41 //
42 //                 +---------------------+
43 //                 | AliFMDBaseDigitizer |
44 //                 +---------------------+
45 //                           ^
46 //                           |
47 //                +----------+---------+
48 //                |                    |
49 //      +-----------------+     +------------------+
50 //      | AliFMDDigitizer |     | AliFMDSDigitizer |
51 //      +-----------------+     +------------------+
52 //
53 // These classes has several paramters: 
54 //
55 //     fPedestal
56 //     fPedestalWidth
57 //         (Only AliFMDDigitizer)
58 //         Mean and width of the pedestal.  The pedestal is simulated
59 //         by a Guassian, but derived classes my override MakePedestal
60 //         to simulate it differently (or pick it up from a database).
61 //
62 //     fVA1MipRange
63 //         The dymamic MIP range of the VA1_ALICE pre-amplifier chip 
64 //
65 //     fAltroChannelSize
66 //         The largest number plus one that can be stored in one
67 //         channel in one time step in the ALTRO ADC chip. 
68 //
69 //     fSampleRate
70 //         How many times the ALTRO ADC chip samples the VA1_ALICE
71 //         pre-amplifier signal.   The VA1_ALICE chip is read-out at
72 //         10MHz, while it's possible to drive the ALTRO chip at
73 //         25MHz.  That means, that the ALTRO chip can have time to
74 //         sample each VA1_ALICE signal up to 2 times.  Although it's
75 //         not certain this feature will be used in the production,
76 //         we'd like have the option, and so it should be reflected in
77 //         the code.
78 //
79 //
80 // The shaping function of the VA1_ALICE is generally given by 
81 //
82 //      f(x) = A(1 - exp(-Bx))
83 //
84 // where A is the total charge collected in the pre-amp., and B is a
85 // paramter that depends on the shaping time of the VA1_ALICE circut.
86 // 
87 // When simulating the shaping function of the VA1_ALICe
88 // pre-amp. chip, we have to take into account, that the shaping
89 // function depends on the previous value of read from the pre-amp. 
90 //
91 // That results in the following algorithm:
92 //
93 //    last = 0;
94 //    FOR charge IN pre-amp. charge train DO 
95 //      IF last < charge THEN 
96 //        f(t) = (charge - last) * (1 - exp(-B * t)) + last
97 //      ELSE
98 //        f(t) = (last - charge) * exp(-B * t) + charge)
99 //      ENDIF
100 //      FOR i IN # samples DO 
101 //        adc_i = f(i / (# samples))
102 //      DONE
103 //      last = charge
104 //   DONE
105 //
106 // Here, 
107 //
108 //   pre-amp. charge train 
109 //       is a series of 128 charges read from the VA1_ALICE chip
110 //
111 //   # samples
112 //       is the number of times the ALTRO ADC samples each of the 128
113 //       charges from the pre-amp. 
114 //
115 // Where Q is the total charge collected by the VA1_ALICE
116 // pre-amplifier.   Q is then given by 
117 //
118 //           E S 
119 //      Q =  - -
120 //           e R
121 //
122 // where E is the total energy deposited in a silicon strip, R is the
123 // dynamic range of the VA1_ALICE pre-amp (fVA1MipRange), e is the
124 // energy deposited by a single MIP, and S ALTRO channel size in each
125 // time step (fAltroChannelSize).  
126 //
127 // The energy deposited per MIP is given by 
128 //
129 //      e = M * rho * w 
130 //
131 // where M is the universal number 1.664, rho is the density of
132 // silicon, and w is the depth of the silicon sensor. 
133 //
134 // The final ADC count is given by 
135 //
136 //      C' = C + P
137 //
138 // where P is the (randomized) pedestal (see MakePedestal)
139 //
140 // This class uses the class template AliFMDMap<Type> to make an
141 // internal cache of the energy deposted of the hits.  The class
142 // template is instantasized as 
143 //
144 //  typedef AliFMDMap<std::pair<Float_t, UShort_t> > AliFMDEdepMap;
145 //
146 // The first member of the values is the summed energy deposition in a
147 // given strip, while the second member of the values is the number of
148 // hits in a given strip.  Using the second member, it's possible to
149 // do some checks on just how many times a strip got hit, and what
150 // kind of error we get in our reconstructed hits.  Note, that this
151 // information is currently not written to the digits tree.  I think a
152 // QA (Quality Assurance) digit tree is better suited for that task.
153 // However, the information is there to be used in the future. 
154 //
155 //
156 // Latest changes by Christian Holm Christensen
157 //
158 //////////////////////////////////////////////////////////////////////////////
159
160 //      /1
161 //      |           A(-1 + B + exp(-B))
162 //      | f(x) dx = ------------------- = 1
163 //      |                    B
164 //      / 0
165 //
166 // and B is the a parameter defined by the shaping time (fShapingTime).  
167 //
168 // Solving the above equation, for A gives
169 //
170 //                 B
171 //      A = ----------------
172 //          -1 + B + exp(-B)
173 //
174 // So, if we define the function g: [0,1] -> [0:1] by 
175 //
176 //               / v
177 //               |              Bu + exp(-Bu) - Bv - exp(-Bv) 
178 //      g(u,v) = | f(x) dx = -A -----------------------------
179 //               |                            B
180 //               / u
181 //
182 // we can evaluate the ALTRO sample of the VA1_ALICE pre-amp between
183 // any two times (u, v), by 
184 //       
185 //
186 //                                B         Bu + exp(-Bu) - Bv - exp(-Bv)
187 //      C = Q g(u,v) = - Q ---------------- -----------------------------
188 //                         -1 + B + exp(-B)              B                  
189 //
190 //               Bu + exp(-Bu) - Bv - exp(-Bv) 
191 //        = -  Q -----------------------------
192 //                    -1 + B + exp(-B)
193 //
194
195 #include <TTree.h>              // ROOT_TTree
196 #include <TRandom.h>            // ROOT_TRandom
197 #include <AliLog.h>             // ALILOG_H
198 #include "AliFMDDigitizer.h"    // ALIFMDDIGITIZER_H
199 #include "AliFMD.h"             // ALIFMD_H
200 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
201 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
202 #include "AliFMDRing.h"         // ALIFMDRING_H
203 #include "AliFMDHit.h"          // ALIFMDHIT_H
204 #include "AliFMDDigit.h"        // ALIFMDDIGIT_H
205 #include <AliRunDigitizer.h>    // ALIRUNDIGITIZER_H
206 #include <AliRun.h>             // ALIRUN_H
207 #include <AliLoader.h>          // ALILOADER_H
208 #include <AliRunLoader.h>       // ALIRUNLOADER_H
209     
210 //====================================================================
211 ClassImp(AliFMDBaseDigitizer)
212 #if 0
213   ; // This is here to keep Emacs for indenting the next line
214 #endif
215
216 //____________________________________________________________________
217 AliFMDBaseDigitizer::AliFMDBaseDigitizer()  
218   : fRunLoader(0)
219 {
220   // Default ctor - don't use it
221 }
222
223 //____________________________________________________________________
224 AliFMDBaseDigitizer::AliFMDBaseDigitizer(AliRunDigitizer* manager) 
225   : AliDigitizer(manager, "AliFMDBaseDigitizer", "FMD Digitizer base class"), 
226     fRunLoader(0),
227     fEdep(AliFMDMap::kMaxDetectors, 
228           AliFMDMap::kMaxRings, 
229           AliFMDMap::kMaxSectors, 
230           AliFMDMap::kMaxStrips)
231 {
232   // Normal CTOR
233   AliDebug(1," processed");
234   SetVA1MipRange();
235   SetAltroChannelSize();
236   SetSampleRate();
237   SetShapingTime();
238 }
239
240 //____________________________________________________________________
241 AliFMDBaseDigitizer::AliFMDBaseDigitizer(const Char_t* name, 
242                                          const Char_t* title) 
243   : AliDigitizer(name, title),
244     fRunLoader(0),
245     fEdep(AliFMDMap::kMaxDetectors, 
246           AliFMDMap::kMaxRings, 
247           AliFMDMap::kMaxSectors, 
248           AliFMDMap::kMaxStrips)
249 {
250   // Normal CTOR
251   AliDebug(1," processed");
252   SetVA1MipRange();
253   SetAltroChannelSize();
254   SetSampleRate();
255   SetShapingTime();
256 }
257
258 //____________________________________________________________________
259 AliFMDBaseDigitizer::~AliFMDBaseDigitizer()
260 {
261   // Destructor
262 }
263
264 //____________________________________________________________________
265 Bool_t 
266 AliFMDBaseDigitizer::Init()
267 {
268   // Initialization
269   return kTRUE;
270 }
271  
272
273 //____________________________________________________________________
274 void
275 AliFMDBaseDigitizer::SumContributions(AliFMD* fmd) 
276 {
277   // Sum energy deposited contributions from each hit in a cache
278   // (fEdep).  
279   if (!fRunLoader) 
280     Fatal("SumContributions", "no run loader");
281   
282   // Clear array of deposited energies 
283   fEdep.Reset();
284   
285   // Get the FMD loader 
286   AliLoader* inFMD = fRunLoader->GetLoader("FMDLoader");
287   // And load the hits 
288   inFMD->LoadHits("READ");
289   
290   // Get the tree of hits 
291   TTree* hitsTree = inFMD->TreeH();
292   if (!hitsTree)  {
293     // Try again 
294     inFMD->LoadHits("READ");
295     hitsTree = inFMD->TreeH();
296   }
297   
298   // Get the FMD branch 
299   TBranch* hitsBranch = hitsTree->GetBranch("FMD");
300   if (hitsBranch) fmd->SetHitsAddressBranch(hitsBranch);
301   else            AliFatal("Branch FMD hit not found");
302   
303   // Get a list of hits from the FMD manager 
304   TClonesArray *fmdHits = fmd->Hits();
305   
306   // Get number of entries in the tree 
307   Int_t ntracks  = Int_t(hitsTree->GetEntries());
308   
309   Int_t read = 0;
310   // Loop over the tracks in the 
311   for (Int_t track = 0; track < ntracks; track++)  {
312     // Read in entry number `track' 
313     read += hitsBranch->GetEntry(track);
314     
315     // Get the number of hits 
316     Int_t nhits = fmdHits->GetEntries ();
317     for (Int_t hit = 0; hit < nhits; hit++) {
318       // Get the hit number `hit'
319       AliFMDHit* fmdHit = 
320         static_cast<AliFMDHit*>(fmdHits->UncheckedAt(hit));
321       
322       // Extract parameters 
323       UShort_t detector = fmdHit->Detector();
324       Char_t   ring     = fmdHit->Ring();
325       UShort_t sector   = fmdHit->Sector();
326       UShort_t strip    = fmdHit->Strip();
327       Float_t  edep     = fmdHit->Edep();
328       if (fEdep(detector, ring, sector, strip).fEdep != 0)
329         AliDebug(5, Form("Double hit in %d%c(%d,%d)", 
330                          detector, ring, sector, strip));
331       
332       fEdep(detector, ring, sector, strip).fEdep  += edep;
333       fEdep(detector, ring, sector, strip).fN     += 1;
334       // Add this to the energy deposited for this strip
335     }  // hit loop
336   } // track loop
337   AliDebug(1, Form("Size of cache: %d bytes, read %d bytes", 
338                    sizeof(fEdep), read));
339 }
340
341 //____________________________________________________________________
342 void
343 AliFMDBaseDigitizer::DigitizeHits(AliFMD* fmd) const
344 {
345   // For the stored energy contributions in the cache (fEdep), convert
346   // the energy signal to ADC counts, and store the created digit in
347   // the digits array (AliFMD::fDigits)
348   //
349   AliFMDGeometry* geometry = AliFMDGeometry::Instance();
350   
351   TArrayI counts(3);
352   for (UShort_t detector=1; detector <= 3; detector++) {
353     // Get pointer to subdetector 
354     AliFMDDetector* det = geometry->GetDetector(detector);
355     if (!det) continue;
356     for (UShort_t ringi = 0; ringi <= 1; ringi++) {
357       // Get pointer to Ring
358       AliFMDRing* r = det->GetRing((ringi == 0 ? 'I' : 'O'));
359       if (!r) continue;
360       
361       // Get number of sectors 
362       UShort_t nSectors = UShort_t(360. / r->GetTheta());
363       // Loop over the number of sectors 
364       for (UShort_t sector = 0; sector < nSectors; sector++) {
365         // Get number of strips 
366         UShort_t nStrips = r->GetNStrips();
367         // Loop over the stips 
368         Float_t last = 0;
369         for (UShort_t strip = 0; strip < nStrips; strip++) {
370           // Reset the counter array to the invalid value -1 
371           counts.Reset(-1);
372           // Reset the last `ADC' value when we've get to the end of a
373           // VA1_ALICE channel. 
374           if (strip % 128 == 0) last = 0;
375           
376           Float_t edep = fEdep(detector, r->GetId(), sector, strip).fEdep;
377           ConvertToCount(edep, last, r->GetSiThickness(), 
378                          geometry->GetSiDensity(), counts);
379           last = edep;
380           AddDigit(fmd, detector, r->GetId(), sector, strip, 
381                    edep, UShort_t(counts[0]), 
382                    Short_t(counts[1]), Short_t(counts[2]));
383 #if 0
384           // This checks if the digit created will give the `right'
385           // number of particles when reconstructed, using a naiive
386           // approach.  It's here only as a quality check - nothing
387           // else. 
388           CheckDigit(fEdep(detector, r->GetId(), sector, strip).fEdep,
389                      fEdep(detector, r->GetId(), sector, strip).fN,
390                      counts);
391 #endif
392         } // Strip
393       } // Sector 
394     } // Ring 
395   } // Detector 
396 }
397
398 //____________________________________________________________________
399 void
400 AliFMDBaseDigitizer::ConvertToCount(Float_t   edep, 
401                                     Float_t   last,
402                                     Float_t   siThickness, 
403                                     Float_t   siDensity, 
404                                     TArrayI&  counts) const
405 {
406   // Convert the total energy deposited to a (set of) ADC count(s). 
407   // 
408   // This is done by 
409   // 
410   //               Energy_Deposited      ALTRO_Channel_Size
411   //    ADC = -------------------------- ------------------- + pedestal
412   //          Energy_Deposition_Of_1_MIP VA1_ALICE_MIP_Range
413   //
414   //               Energy_Deposited             fAltroChannelSize
415   //        = --------------------------------- ----------------- + pedestal 
416   //          1.664 * Si_Thickness * Si_Density   fVA1MipRange   
417   //          
418   // 
419   //        = Energy_Deposited * ConversionFactor + pedestal
420   // 
421   // However, this is modified by the response function of the
422   // VA1_ALICE pre-amp. chip in case we are doing oversampling of the
423   // VA1_ALICE output. 
424   // 
425   // In that case, we get N=fSampleRate values of the ADC, and the
426   // `EnergyDeposited' is a function of which sample where are
427   // calculating the ADC for 
428   // 
429   //     ADC_i = f(EnergyDeposited, i/N, Last) * ConversionFactor + pedestal 
430   // 
431   // where Last is the Energy deposited in the previous strip. 
432   // 
433   // Here, f is the shaping function of the VA1_ALICE.   This is given
434   // by 
435   //                       
436   //                    |   (E - l) * (1 - exp(-B * t) + l   if E > l
437   //       f(E, t, l) = <
438   //                    |   (l - E) * exp(-B * t) + E        otherwise
439   //                       
440   // 
441   //                  = E + (l - E) * ext(-B * t)
442   // 
443   Float_t  mipEnergy  = 1.664 * siThickness * siDensity;
444   Float_t  convF      = (1/mipEnergy*Float_t(fAltroChannelSize)/fVA1MipRange);
445   UShort_t ped       = MakePedestal();
446
447   // In case we don't oversample, just return the end value. 
448   if (fSampleRate == 1) {
449     counts[0] = UShort_t(TMath::Min(edep * convF + ped, 
450                                     Float_t(fAltroChannelSize)));
451     return;
452   }
453   
454   // Create a pedestal 
455   Int_t   n = fSampleRate;
456   Float_t b = fShapingTime;
457   for (Ssiz_t i = 0; i < n;  i++) {
458     Float_t t = Float_t(i) / n;
459     Float_t s = edep + (last - edep) * TMath::Exp(-b * t);
460     counts[i] = UShort_t(TMath::Min(s * convF + ped, 
461                                     Float_t(fAltroChannelSize))); 
462   }
463 }
464
465
466 //====================================================================
467 ClassImp(AliFMDDigitizer)
468
469 //____________________________________________________________________
470 AliFMDDigitizer::AliFMDDigitizer()  
471   : AliFMDBaseDigitizer()
472 {
473   // Default ctor - don't use it
474 }
475
476 //____________________________________________________________________
477 AliFMDDigitizer::AliFMDDigitizer(AliRunDigitizer* manager) 
478   : AliFMDBaseDigitizer(manager)
479 {
480   // Normal CTOR
481   AliDebug(1," processed");
482   SetPedestal();
483 }
484
485 //____________________________________________________________________
486 void
487 AliFMDDigitizer::Exec(Option_t*) 
488 {
489   // Get the output manager 
490   TString outFolder(fManager->GetOutputFolderName());
491   AliRunLoader* out = 
492     AliRunLoader::GetRunLoader(outFolder.Data());
493   // Get the FMD output manager 
494   AliLoader* outFMD = out->GetLoader("FMDLoader");
495
496   // Get the input loader 
497   TString inFolder(fManager->GetInputFolderName(0));
498   fRunLoader = 
499     AliRunLoader::GetRunLoader(inFolder.Data());
500   if (!fRunLoader) {
501     AliError("Can not find Run Loader for input stream 0");
502     return;
503   }
504   // Get the AliRun object 
505   if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
506
507   // Get the AliFMD object 
508   AliFMD* fmd = static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
509   if (!fmd) {
510     AliError("Can not get FMD from gAlice");
511     return;
512   }
513
514   Int_t nFiles= fManager->GetNinputs();
515   for (Int_t inputFile = 0; inputFile < nFiles; inputFile++) {
516     AliDebug(1,Form(" Digitizing event number %d",
517                     fManager->GetOutputEventNr()));
518     // Get the current loader 
519     fRunLoader = 
520       AliRunLoader::GetRunLoader(fManager->GetInputFolderName(inputFile));
521     if (!fRunLoader) Fatal("Exec", "no run loader");
522     // Cache contriutions 
523     SumContributions(fmd);
524   }
525   // Digitize the event 
526   DigitizeHits(fmd);
527
528   // Load digits from the tree 
529   outFMD->LoadDigits("update");
530   // Get the tree of digits 
531   TTree* digitTree = outFMD->TreeD();
532   if (!digitTree) {
533     outFMD->MakeTree("D");
534     digitTree = outFMD->TreeD();
535   }
536   digitTree->Reset();
537   // Make a branch in the tree 
538   TClonesArray* digits = fmd->Digits();
539   fmd->MakeBranchInTree(digitTree, fmd->GetName(), &(digits), 4000, 0);
540   // TBranch* digitBranch = digitTree->GetBranch(fmd->GetName());
541   // Fill the tree 
542   Int_t write = 0;
543   write = digitTree->Fill();
544   AliDebug(1, Form("Wrote %d bytes to digit tree", write));
545   
546   // Write the digits to disk 
547   outFMD->WriteDigits("OVERWRITE");
548   outFMD->UnloadHits();
549   outFMD->UnloadDigits();
550
551   // Reset the digits in the AliFMD object 
552   fmd->ResetDigits();
553 }
554
555
556 //____________________________________________________________________
557 UShort_t
558 AliFMDDigitizer::MakePedestal() const 
559 {
560   // Make a pedestal 
561   return UShort_t(TMath::Max(gRandom->Gaus(fPedestal, fPedestalWidth), 0.));
562 }
563
564 //____________________________________________________________________
565 void
566 AliFMDDigitizer::AddDigit(AliFMD*  fmd,
567                           UShort_t detector, 
568                           Char_t   ring,
569                           UShort_t sector, 
570                           UShort_t strip, 
571                           Float_t  /* edep */, 
572                           UShort_t count1, 
573                           Short_t  count2, 
574                           Short_t  count3) const
575 {
576   // Add a digit
577   fmd->AddDigitByFields(detector, ring, sector, strip, count1, count2, count3);
578 }
579
580 //____________________________________________________________________
581 void
582 AliFMDDigitizer::CheckDigit(Float_t         /* edep */, 
583                             UShort_t        nhits,
584                             const TArrayI&  counts) 
585 {
586   // Check that digit is consistent
587   Int_t integral = counts[0];
588   if (counts[1] >= 0) integral += counts[1];
589   if (counts[2] >= 0) integral += counts[2];
590   integral -= Int_t(fPedestal + 2 * fPedestalWidth);
591   if (integral < 0) integral = 0;
592   
593   Float_t convF = Float_t(fVA1MipRange) / fAltroChannelSize;
594   Float_t mips  = integral * convF;
595   if (mips > Float_t(nhits) + .5 || mips < Float_t(nhits) - .5) 
596     Warning("CheckDigit", "Digit -> %4.2f MIPS != %d +/- .5 hits", 
597             mips, nhits);
598 }
599
600 //====================================================================
601 ClassImp(AliFMDSDigitizer)
602
603 //____________________________________________________________________
604 AliFMDSDigitizer::AliFMDSDigitizer()  
605 {
606   // Default ctor - don't use it
607 }
608
609 //____________________________________________________________________
610 AliFMDSDigitizer::AliFMDSDigitizer(const Char_t* headerFile, 
611                                    const Char_t* /* sdigfile */)
612   : AliFMDBaseDigitizer("FMDSDigitizer", "FMD SDigitizer")
613 {
614   // Normal CTOR
615   AliDebug(1," processed");
616
617   fRunLoader = AliRunLoader::GetRunLoader(); // Open(headerFile);
618   if (!fRunLoader) 
619     Fatal("AliFMDSDigitizer", "cannot open session, header file '%s'",
620           headerFile);
621   AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
622   if (!loader) 
623     Fatal("AliFMDSDigitizer", "cannot find FMD loader in specified event");
624
625   // Add task to tasks folder 
626   loader->PostSDigitizer(this);
627
628 }
629
630 //____________________________________________________________________
631 AliFMDSDigitizer::~AliFMDSDigitizer() 
632 {
633   // Destructor
634   AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
635   loader->CleanSDigitizer();
636 }
637
638 //____________________________________________________________________
639 void
640 AliFMDSDigitizer::Exec(Option_t*) 
641 {
642   // Get the output manager 
643   if (!fRunLoader) {
644     Error("Exec", "Run loader is not set");
645     return;
646   }
647   if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
648   if (!fRunLoader->TreeE())     fRunLoader->LoadHeader();
649   
650   AliLoader* fmdLoader = fRunLoader->GetLoader("FMDLoader");
651   if (!fmdLoader) Fatal("Exec", "no FMD loader");
652   
653   // Get the AliFMD object 
654   AliFMD* fmd = 
655     static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
656   if (!fmd) {
657     AliError("Can not get FMD from gAlice");
658     return;
659   }
660
661   Int_t nEvents = Int_t(fRunLoader->TreeE()->GetEntries());
662   for (Int_t event = 0; event < nEvents; event++) {
663     AliDebug(1,Form(" Digitizing event number %d", event));
664     // Get the current loader 
665     fRunLoader->GetEvent(event);
666
667     if (!fmdLoader->TreeS()) fmdLoader->MakeTree("S");
668     // Make a branch
669     fmd->MakeBranch("S");
670     
671     // Cache contriutions 
672     SumContributions(fmd);
673
674     // Digitize the event 
675     DigitizeHits(fmd);
676
677     fmdLoader->TreeS()->Reset();
678     fmdLoader->TreeS()->Fill();
679     fmdLoader->WriteSDigits("OVERWRITE");
680   }
681 }
682
683 //____________________________________________________________________
684 void
685 AliFMDSDigitizer::AddDigit(AliFMD*  fmd,
686                            UShort_t detector, 
687                            Char_t   ring,
688                            UShort_t sector, 
689                            UShort_t strip, 
690                            Float_t  edep, 
691                            UShort_t count1, 
692                            Short_t  count2, 
693                            Short_t  count3) const
694 {
695   // Add a summable digit
696   fmd->AddSDigitByFields(detector, ring, sector, strip, edep, 
697                          count1, count2, count3); 
698 }
699
700
701
702 //____________________________________________________________________
703 //
704 // EOF
705 // 
706
707
708
709