13-oct-2005 NvE TTask derived class IceCleanHits introduced to perform hit cleaning.
[u/mrichter/AliRoot.git] / FMD / AliFMD.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 // Forward Multiplicity Detector based on Silicon wafers. This class
21 // contains the base procedures for the Forward Multiplicity detector
22 // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
23 // which has 1 or 2 rings of silicon sensors. 
24 //                                                       
25 // This is the base class for all FMD manager classes. 
26 //                    
27 // The actual code is done by various separate classes.   Below is
28 // diagram showing the relationship between the various FMD classes
29 // that handles the simulation
30 //
31 //
32 //       +----------+   +----------+   
33 //       | AliFMDv1 |   | AliFMDv0 |   
34 //       +----------+   +----------+   
35 //            |              |                    +-----------------+
36 //       +----+--------------+                 +--| AliFMDDigitizer |
37 //       |                                     |  +-----------------+
38 //       |           +---------------------+   |
39 //       |        +- | AliFMDBaseDigitizer |<--+
40 //       V     1  |  +---------------------+   |
41 //  +--------+<>--+                            |  +------------------+
42 //  | AliFMD |                                 +--| AliFMDSDigitizer |    
43 //  +--------+<>--+                               +------------------+       
44 //             1  | +-----------------+ 
45 //                +-| AliFMDSimulator |
46 //                  +-----------------+
47 //                           ^              
48 //                           |
49 //             +-------------+-------------+
50 //             |                           |          
51 //    +--------------------+   +-------------------+
52 //    | AliFMDGeoSimulator |   | AliFMDG3Simulator | 
53 //    +--------------------+   +---------+---------+
54 //      
55 //
56 // *  AliFMD 
57 //    This defines the interface for the various parts of AliROOT that
58 //    uses the FMD, like AliFMDSimulator, AliFMDDigitizer, 
59 //    AliFMDReconstructor, and so on. 
60 //
61 // *  AliFMDv0
62 //    This is a concrete implementation of the AliFMD interface. 
63 //    It is the responsibility of this class to create the FMD
64 //    geometry.
65 //
66 // *  AliFMDv1 
67 //    This is a concrete implementation of the AliFMD interface. 
68 //    It is the responsibility of this class to create the FMD
69 //    geometry, process hits in the FMD, and serve hits and digits to
70 //    the various clients. 
71 //  
72 // *  AliFMDSimulator
73 //    This is the base class for the FMD simulation tasks.   The
74 //    simulator tasks are responsible to implment the geoemtry, and
75 //    process hits. 
76 //                                                                          
77 // *  AliFMDGeoSimulator
78 //    This is a concrete implementation of the AliFMDSimulator that
79 //    uses the TGeo classes directly only. 
80 //
81 // *  AliFMDG3Simulator
82 //    This is a concrete implementation of the AliFMDSimulator that
83 //    uses the TVirtualMC interface with GEANT 3.21-like messages.
84 //
85
86 // These files are not in the same directory, so there's no reason to
87 // ask the preprocessor to search in the current directory for these
88 // files by including them with `#include "..."' 
89 #include <math.h>               // __CMATH__
90 #include <TClonesArray.h>       // ROOT_TClonesArray
91 #include <TGeometry.h>          // ROOT_TGeomtry
92 #include <TNode.h>              // ROOT_TNode
93 #include <TXTRU.h>              // ROOT_TXTRU
94 #include <TRotMatrix.h>         // ROOT_TRotMatrix
95 #include <TTUBE.h>              // ROOT_TTUBE
96 #include <TTree.h>              // ROOT_TTree
97 #include <TBrowser.h>           // ROOT_TBrowser
98 #include <TMath.h>              // ROOT_TMath
99 #include <TVirtualMC.h>         // ROOT_TVirtualMC
100
101 #include <AliRunDigitizer.h>    // ALIRUNDIGITIZER_H
102 #include <AliLoader.h>          // ALILOADER_H
103 #include <AliRun.h>             // ALIRUN_H
104 #include <AliMC.h>              // ALIMC_H
105 #include <AliLog.h>             // ALILOG_H
106 #include "AliFMD.h"             // ALIFMD_H
107 #include "AliFMDDigit.h"        // ALIFMDDIGIG_H
108 #include "AliFMDHit.h"          // ALIFMDHIT_H
109 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
110 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
111 #include "AliFMDRing.h"         // ALIFMDRING_H
112 #include "AliFMDDigitizer.h"    // ALIFMDDIGITIZER_H
113 #include "AliFMDSimulator.h"    // ALIFMDSIMULATOR_H
114 #include "AliFMDG3Simulator.h"  // ALIFMDG3SIMULATOR_H
115 #include "AliFMDGeoSimulator.h" // ALIFMDGEOSIMULATOR_H
116 #include "AliFMDRawWriter.h"    // ALIFMDRAWWRITER_H
117
118 //____________________________________________________________________
119 ClassImp(AliFMD)
120 #if 0
121   ; // This is to keep Emacs from indenting the next line 
122 #endif 
123
124 //____________________________________________________________________
125 AliFMD::AliFMD()
126   : AliDetector(),
127     fSDigits(0), 
128     fNsdigits(0),
129     fDetailed(kTRUE),
130     fSimulator(0)
131 {
132   //
133   // Default constructor for class AliFMD
134   //
135   AliDebug(10, "\tDefault CTOR");
136   fHits     = 0;
137   fDigits   = 0;
138   fIshunt   = 0;
139 }
140
141 //____________________________________________________________________
142 AliFMD::AliFMD(const AliFMD& other)
143   : AliDetector(other),
144     fSDigits(other.fSDigits), 
145     fNsdigits(other.fNsdigits),
146     fDetailed(other.fDetailed),
147     fSimulator(other.fSimulator)
148 {
149   // Copy constructor 
150 }
151
152 //____________________________________________________________________
153 AliFMD::AliFMD(const char *name, const char *title)
154   : AliDetector (name, title),
155     fSDigits(0),
156     fNsdigits(0),
157     fDetailed(kTRUE),
158     fSimulator(0)
159 {
160   //
161   // Standard constructor for Forward Multiplicity Detector
162   //
163   AliDebug(10, "\tStandard CTOR");
164
165   // Initialise Hit array
166   HitsArray();
167   gAlice->GetMCApp()->AddHitList(fHits);
168
169   // (S)Digits for the detectors disk
170   DigitsArray();
171   SDigitsArray();
172   
173   // CHC: What is this?
174   fIshunt = 0;
175   SetMarkerColor(kRed);
176   SetLineColor(kYellow);
177 }
178
179 //____________________________________________________________________
180 AliFMD::~AliFMD ()
181 {
182   // Destructor for base class AliFMD
183   if (fHits) {
184     fHits->Delete();
185     delete fHits;
186     fHits = 0;
187   }
188   if (fDigits) {
189     fDigits->Delete();
190     delete fDigits;
191     fDigits = 0;
192   }
193   if (fSDigits) {
194     fSDigits->Delete();
195     delete fSDigits;
196     fSDigits = 0;
197   }
198 }
199
200 //____________________________________________________________________
201 AliFMD&
202 AliFMD::operator=(const AliFMD& other)
203 {
204   AliDetector::operator=(other);
205   fSDigits              = other.fSDigits; 
206   fNsdigits             = other.fNsdigits;
207   fDetailed             = other.fDetailed;
208   fSimulator            = other.fSimulator;
209   
210   return *this;
211 }
212
213 //====================================================================
214 //
215 // GEometry ANd Traking
216 //
217 //____________________________________________________________________
218 void 
219 AliFMD::CreateGeometry()
220 {
221   //
222   // Create the geometry of Forward Multiplicity Detector.  The actual
223   // construction of the geometry is delegated to the class AliFMDRing
224   // and AliFMDSubDetector and the relevant derived classes. 
225   //
226   // The flow of this member function is:
227   //
228   //   FOR rings fInner and fOuter DO  
229   //     AliFMDRing::Init();
230   //   END FOR
231   // 
232   //   Set up hybrud card support (leg) volume shapes  
233   // 
234   //   FOR rings fInner and fOuter DO  
235   //     AliFMDRing::SetupGeometry();
236   //   END FOR
237   // 
238   //   FOR subdetectors fFMD1, fFMD2, and fFMD3 DO 
239   //     AliFMDSubDetector::SetupGeomtry();
240   //   END FOR
241   // 
242   //   FOR subdetectors fFMD1, fFMD2, and fFMD3 DO 
243   //     AliFMDSubDetector::Geomtry();
244   //   END FOR
245   //
246   if (!fSimulator) {
247     AliFatal("Simulator object not made yet!");
248     return;
249   }
250   fSimulator->DefineGeometry();
251 }    
252
253 //____________________________________________________________________
254 void AliFMD::CreateMaterials() 
255 {
256   // Register various materials and tracking mediums with the
257   // backend.   
258   // 
259   AliDebug(10, "\tCreating materials");
260
261   if (fSimulator) {
262     AliFatal("Simulator object already instantised!");
263     return;
264   }
265   AliFMDGeometry* geometry = AliFMDGeometry::Instance();
266   geometry->Init();
267 //   TVirtualMC* mc = TVirtualMC::GetMC();
268 //   Bool_t geo = mc->IsRootGeometrySupported();
269 //   if (geo)
270 //     fSimulator = new AliFMDGeoSimulator(this, fDetailed);
271 //   else 
272     fSimulator = new AliFMDG3Simulator(this, fDetailed);
273   
274   fSimulator->DefineMaterials();
275 }
276
277 //____________________________________________________________________
278 void  
279 AliFMD::Init()
280 {
281   //
282   // Initialis the FMD after it has been built
283   Int_t i;
284   //
285   if (AliLog::GetGlobalDebugLevel()) {
286     cout << "\n" << ClassName() << ": " << flush;
287     for (i = 0; i < 35; i++) cout << "*";
288     cout << " FMD_INIT ";
289     for (i = 0; i < 35; i++) cout << "*";
290     cout << "\n" << ClassName() << ": " << flush;
291     //
292     // Here the FMD initialisation code (if any!)
293     for (i = 0; i < 80; i++) cout << "*";
294     cout << endl;
295   }
296   //
297   //
298 }
299
300 //====================================================================
301 //
302 // Graphics and event display
303 //
304 //____________________________________________________________________
305 void 
306 AliFMD::BuildGeometry()
307 {
308   //
309   // Build simple ROOT TNode geometry for event display
310   //
311   // Build a simplified geometry of the FMD used for event display  
312   // 
313   // The actual building of the TNodes is done by
314   // AliFMDSubDetector::SimpleGeometry. 
315   AliDebug(10, "\tCreating a simplified geometry");
316
317   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
318   
319   static TXTRU*     innerShape = 0;
320   static TXTRU*     outerShape = 0;
321   static TObjArray* innerRot   = 0;
322   static TObjArray* outerRot   = 0;
323
324   if (!innerShape || !outerShape) {
325     // Make the shapes for the modules 
326     for (Int_t i = 0; i < 2; i++) {
327       AliFMDRing* r = 0;
328       switch (i) {
329       case 0: r = fmd->GetRing('I'); break;
330       case 1: r = fmd->GetRing('O'); break;
331       }
332       if (!r) {
333         AliError(Form("no ring found for i=%d", i));
334         return;
335       }
336       Double_t    siThick  = r->GetSiThickness();
337       const Int_t nv       = r->GetNVerticies();
338       Double_t    theta    = r->GetTheta();
339       Int_t       nmod     = r->GetNModules();
340       
341       TXTRU* shape = new TXTRU(r->GetName(), r->GetTitle(), "void", nv, 2);
342       for (Int_t j = 0; j < nv; j++) {
343         TVector2* vv = r->GetVertex(nv - 1 - j);
344         shape->DefineVertex(j, vv->X(), vv->Y());
345       }
346       shape->DefineSection(0, -siThick / 2, 1, 0, 0);
347       shape->DefineSection(1, +siThick / 2, 1, 0, 0);
348       shape->SetLineColor(GetLineColor());
349       
350       TObjArray* rots = new TObjArray(nmod);
351       for (Int_t j = 0; j < nmod; j++) {
352         Double_t th = (j + .5) * theta * 2;
353         TString name(Form("FMD_ring_%c_rot_%02d", r->GetId(), j));
354         TString title(Form("FMD Ring %c Rotation # %d", r->GetId(), j));
355         TRotMatrix* rot = new TRotMatrix(name.Data(), title.Data(),
356                                          90, th, 90, fmod(90+th,360), 0, 0);
357         rots->AddAt(rot, j);
358       }
359       
360       switch (r->GetId()) {
361       case 'i':
362       case 'I': innerShape = shape; innerRot = rots; break;
363       case 'o':
364       case 'O': outerShape = shape; outerRot = rots; break;
365       }
366     }
367   }
368   
369   TNode* top = gAlice->GetGeometry()->GetNode("alice");
370   
371   for (Int_t i = 1; i <= 3; i++) {
372     AliFMDDetector* det = fmd->GetDetector(i);
373     if (!det) {
374       Warning("BuildGeometry", "FMD%d seems to be disabled", i);
375       continue;
376     }
377     Double_t w  = 0;
378     Double_t rh = det->GetRing('I')->GetHighR();
379     Char_t   id = 'I';
380     if (det->GetRing('O')) {
381       w  = TMath::Abs(det->GetRingZ('O') - det->GetRingZ('I'));
382       id = (TMath::Abs(det->GetRingZ('O')) 
383             > TMath::Abs(det->GetRingZ('I')) ? 'O' : 'I');
384       rh = det->GetRing('O')->GetHighR();
385     }
386     w += (det->GetRing(id)->GetModuleSpacing() +
387           det->GetRing(id)->GetSiThickness());
388     TShape* shape = new TTUBE(det->GetName(), det->GetTitle(), "void",
389                               det->GetRing('I')->GetLowR(), rh, w / 2);
390     Double_t z = (det->GetRingZ('I') - w / 2);
391     if (z > 0) z += det->GetRing(id)->GetModuleSpacing();
392     top->cd();
393     TNode* node = new TNode(det->GetName(), det->GetTitle(), shape, 
394                             0, 0, z, 0);
395     fNodes->Add(node);
396     
397     for (Int_t j = 0; j < 2; j++) {
398       AliFMDRing* r      = 0;
399       TShape*     rshape = 0;
400       TObjArray*  rots   = 0;
401       switch (j) {
402       case 0: 
403         r = det->GetRing('I'); rshape = innerShape; rots = innerRot; break;
404       case 1: 
405         r = det->GetRing('O'); rshape = outerShape; rots = outerRot; break;
406       }
407       if (!r) continue;
408       
409       Double_t    siThick  = r->GetSiThickness();
410       Int_t       nmod     = r->GetNModules();
411       Double_t    modspace = r->GetModuleSpacing();
412       Double_t    rz       = - (z - det->GetRingZ(r->GetId()));
413       
414       for (Int_t k = 0; k < nmod; k++) {
415         node->cd();
416         Double_t    offz    = (k % 2 == 1 ? modspace : 0);
417         TRotMatrix* rot     = static_cast<TRotMatrix*>(rots->At(k));
418         TString name(Form("%s%c_module_%02d", det->GetName(), r->GetId(),k));
419         TString title(Form("%s%c Module %d", det->GetName(), r->GetId(),k));
420         TNode* mnod = new TNode(name.Data(), title.Data(), rshape, 
421                                 0, 0, rz - siThick / 2 
422                                 + TMath::Sign(offz,z), rot);
423         mnod->SetLineColor(GetLineColor());
424         fNodes->Add(mnod);
425       } // for (Int_t k = 0 ; ...)
426     } // for (Int_t j = 0 ; ...)
427   } // for (Int_t i = 1 ; ...)
428 }
429
430 //____________________________________________________________________
431 void 
432 AliFMD::DrawDetector()
433 {
434   //
435   // Draw a shaded view of the Forward multiplicity detector
436   //
437   // DebugGuard guard("AliFMD::DrawDetector");
438   AliDebug(10, "\tDraw detector");
439   
440 #if 0
441   //Set ALIC mother transparent
442   gMC->Gsatt("ALIC","SEEN",0);
443   //
444   gMC->Gdopt("hide", "on");
445   gMC->Gdopt("shad", "on");
446   gMC->Gsatt("*", "fill", 7);
447   gMC->SetClipBox(".");
448   gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
449   gMC->DefaultRange();
450   gMC->Gdraw("alic", 40, 30, 0, 12, 12, .055, .055);
451   gMC->Gdhead(1111, "Forward Multiplicity Detector");
452   gMC->Gdman(16, 10, "MAN");
453   gMC->Gdopt("hide", "off");
454 #endif
455 }
456
457 //____________________________________________________________________
458 Int_t 
459 AliFMD::DistanceToPrimitive(Int_t, Int_t)
460 {
461   //
462   // Calculate the distance from the mouse to the FMD on the screen
463   // Dummy routine
464   //
465   return 9999;
466 }
467
468 //====================================================================
469 //
470 // Hit and Digit managment 
471 //
472 //____________________________________________________________________
473 void 
474 AliFMD::MakeBranch(Option_t * option)
475 {
476   // Create Tree branches for the FMD.
477   //
478   // Options:
479   //
480   //    H          Make a branch of TClonesArray of AliFMDHit's
481   //    D          Make a branch of TClonesArray of AliFMDDigit's
482   //    S          Make a branch of TClonesArray of AliFMDSDigit's
483   // 
484   const Int_t kBufferSize = 16000;
485   TString branchname(GetName());
486   TString opt(option);
487   
488   if (opt.Contains("H", TString::kIgnoreCase)) {
489     HitsArray();
490     AliDetector::MakeBranch(option); 
491   }
492   if (opt.Contains("D", TString::kIgnoreCase)) { 
493     DigitsArray();
494     MakeBranchInTree(fLoader->TreeD(), branchname.Data(),
495                      &fDigits, kBufferSize, 0);
496   }
497   if (opt.Contains("S", TString::kIgnoreCase)) { 
498     SDigitsArray();
499     MakeBranchInTree(fLoader->TreeS(), branchname.Data(),
500                      &fSDigits, kBufferSize, 0);
501   }
502 }
503
504 //____________________________________________________________________
505 void 
506 AliFMD::SetTreeAddress()
507 {
508   // Set branch address for the Hits, Digits, and SDigits Tree.
509   if (fLoader->TreeH()) HitsArray();
510   AliDetector::SetTreeAddress();
511
512   TTree *treeD = fLoader->TreeD();
513   if (treeD) {
514     DigitsArray();
515     TBranch* branch = treeD->GetBranch ("FMD");
516     if (branch) branch->SetAddress(&fDigits);
517   }
518
519   TTree *treeS = fLoader->TreeS();
520   if (treeS) {
521     SDigitsArray();
522     TBranch* branch = treeS->GetBranch ("FMD");
523     if (branch) branch->SetAddress(&fSDigits);
524   }
525 }
526
527
528
529 //____________________________________________________________________
530 void 
531 AliFMD::SetHitsAddressBranch(TBranch *b)
532 {
533   // Set the TClonesArray to read hits into. 
534   b->SetAddress(&fHits);
535 }
536
537 //____________________________________________________________________
538 void 
539 AliFMD::AddHit(Int_t track, Int_t *vol, Float_t *hits) 
540 {
541   // Add a hit to the hits tree 
542   // 
543   // The information of the two arrays are decoded as 
544   // 
545   // Parameters
546   //    track                Track #
547   //    ivol[0]  [UShort_t ] Detector # 
548   //    ivol[1]  [Char_t   ] Ring ID 
549   //    ivol[2]  [UShort_t ] Sector #
550   //    ivol[3]  [UShort_t ] Strip # 
551   //    hits[0]  [Float_t  ] Track's X-coordinate at hit 
552   //    hits[1]  [Float_t  ] Track's Y-coordinate at hit
553   //    hits[3]  [Float_t  ] Track's Z-coordinate at hit
554   //    hits[4]  [Float_t  ] X-component of track's momentum             
555   //    hits[5]  [Float_t  ] Y-component of track's momentum             
556   //    hits[6]  [Float_t  ] Z-component of track's momentum            
557   //    hits[7]  [Float_t  ] Energy deposited by track                  
558   //    hits[8]  [Int_t    ] Track's particle Id # 
559   //    hits[9]  [Float_t  ] Time when the track hit
560   // 
561   // 
562   AddHitByFields(track, 
563                  UShort_t(vol[0]),  // Detector # 
564                  Char_t(vol[1]),    // Ring ID
565                  UShort_t(vol[2]),  // Sector # 
566                  UShort_t(vol[3]),  // Strip # 
567                  hits[0],           // X
568                  hits[1],           // Y
569                  hits[2],           // Z
570                  hits[3],           // Px
571                  hits[4],           // Py
572                  hits[5],           // Pz
573                  hits[6],           // Energy loss 
574                  Int_t(hits[7]),    // PDG 
575                  hits[8]);          // Time
576 }
577
578 //____________________________________________________________________
579 void 
580 AliFMD::AddHitByFields(Int_t    track, 
581                        UShort_t detector, 
582                        Char_t   ring, 
583                        UShort_t sector, 
584                        UShort_t strip, 
585                        Float_t  x, 
586                        Float_t  y, 
587                        Float_t  z,
588                        Float_t  px, 
589                        Float_t  py, 
590                        Float_t  pz,
591                        Float_t  edep,
592                        Int_t    pdg,
593                        Float_t  t)
594 {
595   //
596   // Add a hit to the list
597   //
598   // Parameters:
599   // 
600   //    track     Track #
601   //    detector  Detector # (1, 2, or 3)                      
602   //    ring      Ring ID ('I' or 'O')
603   //    sector    Sector # (For inner/outer rings: 0-19/0-39)
604   //    strip     Strip # (For inner/outer rings: 0-511/0-255)
605   //    x         Track's X-coordinate at hit
606   //    y         Track's Y-coordinate at hit
607   //    z         Track's Z-coordinate at hit
608   //    px        X-component of track's momentum 
609   //    py        Y-component of track's momentum
610   //    pz        Z-component of track's momentum
611   //    edep      Energy deposited by track
612   //    pdg       Track's particle Id #
613   //    t         Time when the track hit 
614   // 
615   TClonesArray& a = *(HitsArray());
616   // Search through the list of already registered hits, and see if we
617   // find a hit with the same parameters.  If we do, then don't create
618   // a new hit, but rather update the energy deposited in the hit.
619   // This is done, so that a FLUKA based simulation will get the
620   // number of hits right, not just the enerrgy deposition. 
621   for (Int_t i = 0; i < fNhits; i++) {
622     if (!a.At(i)) continue;
623     AliFMDHit* hit = static_cast<AliFMDHit*>(a.At(i));
624     if (hit->Detector() == detector 
625         && hit->Ring() == ring
626         && hit->Sector() == sector 
627         && hit->Strip() == strip
628         && hit->Track() == track) {
629       Warning("AddHit", "already had a hit in FMD%d%c[%2d,%3d] for track # %d,"
630               " adding energy (%f) to that hit (%f) -> %f", 
631               detector, ring, sector, strip, track, edep, hit->Edep(),
632               hit->Edep() + edep);
633       hit->SetEdep(hit->Edep() + edep);
634       return;
635     }
636   }
637   // If hit wasn't already registered, do so know. 
638   new (a[fNhits]) AliFMDHit(fIshunt, track, detector, ring, sector, strip, 
639                             x, y, z, px, py, pz, edep, pdg, t);
640   fNhits++;
641 }
642
643 //____________________________________________________________________
644 void 
645 AliFMD::AddDigit(Int_t* digits, Int_t*)
646 {
647   // Add a digit to the Digit tree 
648   // 
649   // Paramters 
650   //
651   //    digits[0]  [UShort_t] Detector #
652   //    digits[1]  [Char_t]   Ring ID
653   //    digits[2]  [UShort_t] Sector #
654   //    digits[3]  [UShort_t] Strip #
655   //    digits[4]  [UShort_t] ADC Count 
656   //    digits[5]  [Short_t]  ADC Count, -1 if not used
657   //    digits[6]  [Short_t]  ADC Count, -1 if not used 
658   // 
659   AddDigitByFields(UShort_t(digits[0]),  // Detector #
660                    Char_t(digits[1]),    // Ring ID
661                    UShort_t(digits[2]),  // Sector #
662                    UShort_t(digits[3]),  // Strip #
663                    UShort_t(digits[4]),  // ADC Count1 
664                    Short_t(digits[5]),   // ADC Count2 
665                    Short_t(digits[6]));  // ADC Count3 
666 }
667
668 //____________________________________________________________________
669 void 
670 AliFMD::AddDigitByFields(UShort_t detector, 
671                          Char_t   ring, 
672                          UShort_t sector, 
673                          UShort_t strip, 
674                          UShort_t count1, 
675                          Short_t  count2,
676                          Short_t  count3)
677 {
678   // add a real digit - as coming from data
679   // 
680   // Parameters 
681   //
682   //    detector  Detector # (1, 2, or 3)                      
683   //    ring      Ring ID ('I' or 'O')
684   //    sector    Sector # (For inner/outer rings: 0-19/0-39)
685   //    strip     Strip # (For inner/outer rings: 0-511/0-255)
686   //    count1    ADC count (a 10-bit word)
687   //    count2    ADC count (a 10-bit word), or -1 if not used
688   //    count3    ADC count (a 10-bit word), or -1 if not used
689   TClonesArray& a = *(DigitsArray());
690   
691   new (a[fNdigits++]) 
692     AliFMDDigit(detector, ring, sector, strip, count1, count2, count3);
693 }
694
695 //____________________________________________________________________
696 void 
697 AliFMD::AddSDigit(Int_t* digits)
698 {
699   // Add a digit to the SDigit tree 
700   // 
701   // Paramters 
702   //
703   //    digits[0]  [UShort_t] Detector #
704   //    digits[1]  [Char_t]   Ring ID
705   //    digits[2]  [UShort_t] Sector #
706   //    digits[3]  [UShort_t] Strip #
707   //    digits[4]  [Float_t]  Total energy deposited 
708   //    digits[5]  [UShort_t] ADC Count 
709   //    digits[6]  [Short_t]  ADC Count, -1 if not used
710   //    digits[7]  [Short_t]  ADC Count, -1 if not used 
711   // 
712   AddSDigitByFields(UShort_t(digits[0]),  // Detector #
713                     Char_t(digits[1]),    // Ring ID
714                     UShort_t(digits[2]),  // Sector #
715                     UShort_t(digits[3]),  // Strip #
716                     Float_t(digits[4]),   // Edep
717                     UShort_t(digits[5]),  // ADC Count1 
718                     Short_t(digits[6]),   // ADC Count2 
719                     Short_t(digits[7]));  // ADC Count3 
720 }
721
722 //____________________________________________________________________
723 void 
724 AliFMD::AddSDigitByFields(UShort_t detector, 
725                           Char_t   ring, 
726                           UShort_t sector, 
727                           UShort_t strip, 
728                           Float_t  edep,
729                           UShort_t count1, 
730                           Short_t  count2,
731                           Short_t  count3)
732 {
733   // add a summable digit
734   // 
735   // Parameters 
736   //
737   //    detector  Detector # (1, 2, or 3)                      
738   //    ring      Ring ID ('I' or 'O')
739   //    sector    Sector # (For inner/outer rings: 0-19/0-39)
740   //    strip     Strip # (For inner/outer rings: 0-511/0-255)
741   //    edep      Total energy deposited
742   //    count1    ADC count (a 10-bit word)
743   //    count2    ADC count (a 10-bit word), or -1 if not used
744   //    count3    ADC count (a 10-bit word), or -1 if not used
745   //
746   TClonesArray& a = *(SDigitsArray());
747   
748   new (a[fNsdigits++]) 
749     AliFMDSDigit(detector, ring, sector, strip, edep, count1, count2, count3);
750 }
751
752 //____________________________________________________________________
753 void 
754 AliFMD::ResetSDigits()
755 {
756   //
757   // Reset number of digits and the digits array for this detector
758   //
759   fNsdigits   = 0;
760   if (fSDigits) fSDigits->Clear();
761 }
762
763
764 //____________________________________________________________________
765 TClonesArray*
766 AliFMD::HitsArray() 
767 {
768   // Initialize hit array if not already, and return pointer to it. 
769   if (!fHits) { 
770     fHits = new TClonesArray("AliFMDHit", 1000);
771     fNhits = 0;
772   }
773   return fHits;
774 }
775
776 //____________________________________________________________________
777 TClonesArray*
778 AliFMD::DigitsArray() 
779 {
780   // Initialize digit array if not already, and return pointer to it. 
781   if (!fDigits) { 
782     fDigits = new TClonesArray("AliFMDDigit", 1000);
783     fNdigits = 0;
784   }
785   return fDigits;
786 }
787
788 //____________________________________________________________________
789 TClonesArray*
790 AliFMD::SDigitsArray() 
791 {
792   // Initialize digit array if not already, and return pointer to it. 
793   if (!fSDigits) { 
794     fSDigits = new TClonesArray("AliFMDSDigit", 1000);
795     fNsdigits = 0;
796   }
797   return fSDigits;
798 }
799
800 //====================================================================
801 //
802 // Digitization 
803 //
804 //____________________________________________________________________
805 void 
806 AliFMD::Hits2Digits() 
807 {
808   // Create AliFMDDigit's from AliFMDHit's.  This is done by making a
809   // AliFMDDigitizer, and executing that code.
810   // 
811   AliRunDigitizer* manager = new AliRunDigitizer(1, 1);
812   manager->SetInputStream(0, "galice.root");
813   manager->SetOutputFile("H2Dfile");
814   
815   /* AliDigitizer* dig =*/ CreateDigitizer(manager);
816   manager->Exec("");
817   delete manager;
818 }
819
820 //____________________________________________________________________
821 void 
822 AliFMD::Hits2SDigits() 
823 {
824   // Create AliFMDSDigit's from AliFMDHit's.  This is done by creating
825   // an AliFMDSDigitizer object, and executing it. 
826   // 
827   AliFMDSDigitizer* digitizer = new AliFMDSDigitizer("galice.root");
828   digitizer->Exec("");
829   delete digitizer;
830 }
831
832   
833 //____________________________________________________________________
834 AliDigitizer* 
835 AliFMD::CreateDigitizer(AliRunDigitizer* manager) const
836 {
837   // Create a digitizer object 
838   AliFMDDigitizer* digitizer = new AliFMDDigitizer(manager);
839   return digitizer;
840 }
841
842 //====================================================================
843 //
844 // Raw data simulation 
845 //
846 //__________________________________________________________________
847 void 
848 AliFMD::Digits2Raw() 
849 {
850   // Turn digits into raw data. 
851   // 
852   // This uses the class AliFMDRawWriter to do the job.   Please refer
853   // to that class for more information. 
854   AliFMDRawWriter writer(this);
855   writer.Exec();
856 }
857
858
859 //====================================================================
860 //
861 // Utility 
862 //
863 //__________________________________________________________________
864 void 
865 AliFMD::Browse(TBrowser* b) 
866 {
867   // Browse this object. 
868   //
869   AliDebug(30, "\tBrowsing the FMD");
870   AliDetector::Browse(b);
871   if (fSimulator) b->Add(fSimulator);
872   b->Add(AliFMDGeometry::Instance());
873 }
874
875 //___________________________________________________________________
876 //
877 // EOF
878 //