Complete rewrite of the FMD code.
authoralla <alla@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 15 Oct 2004 12:04:03 +0000 (12:04 +0000)
committeralla <alla@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 15 Oct 2004 12:04:03 +0000 (12:04 +0000)
AliFMD now uses the service classes AliFMDSubDetector, AliFMDRing,
and AliFMDPolygon.

AliFMDHit, AliFMDDigit, AliFMDSDigit uses detector, ring, sector, strip
to identiy the strip.

AliFMDv0 and AliFMDv1 doesn't do a whole lot.  All geomtry code is
in the AliFMDSubDetector and AliFMDRing classes.

Digitisation was revisited.  SDigitization was reimplemented.

AliFMD::Digits2Raw is implemented, using AliAltroBuffer.

AliFMDReconstructor can now read both Digits and Raw data.  Raw
data is read via AliFMDRawStream (derived from AliAltroRawStream) using
an AliRawReader object.

Both the Reconstructor and the Digitizer uses the AliFMDMap class template
to make internal caches.

The scripts Config.C, Simulate.C, Reconstruct.C, ReadRaw.C where added
for testing and documentation purposes.

The script Document.C was added to make local documentation of the FMD
classes.

Preliminary tests with TFluka indicates that FMD works with FLUKA.

53 files changed:
FMD/.cvsignore [new file with mode: 0644]
FMD/AliFMD.cxx
FMD/AliFMD.h
FMD/AliFMD1.cxx [new file with mode: 0644]
FMD/AliFMD1.h [new file with mode: 0644]
FMD/AliFMD2.cxx [new file with mode: 0644]
FMD/AliFMD2.h [new file with mode: 0644]
FMD/AliFMD3.cxx [new file with mode: 0644]
FMD/AliFMD3.h [new file with mode: 0644]
FMD/AliFMDDigit.cxx [new file with mode: 0644]
FMD/AliFMDDigit.h [new file with mode: 0644]
FMD/AliFMDDigitizer.cxx
FMD/AliFMDDigitizer.h
FMD/AliFMDHit.cxx [new file with mode: 0644]
FMD/AliFMDHit.h [moved from FMD/AliFMDhit.h with 58% similarity]
FMD/AliFMDMap.h [new file with mode: 0644]
FMD/AliFMDParticles.cxx [new file with mode: 0644]
FMD/AliFMDParticles.h [new file with mode: 0644]
FMD/AliFMDPolygon.cxx [new file with mode: 0644]
FMD/AliFMDPolygon.h [new file with mode: 0644]
FMD/AliFMDRawStream.cxx [new file with mode: 0644]
FMD/AliFMDRawStream.h [new file with mode: 0644]
FMD/AliFMDReconstParticles.cxx [deleted file]
FMD/AliFMDReconstParticles.h [deleted file]
FMD/AliFMDReconstructor.cxx
FMD/AliFMDReconstructor.h
FMD/AliFMDRing.cxx [new file with mode: 0644]
FMD/AliFMDRing.h [new file with mode: 0644]
FMD/AliFMDSubDetector.cxx [new file with mode: 0644]
FMD/AliFMDSubDetector.h [new file with mode: 0644]
FMD/AliFMDdigit.cxx [deleted file]
FMD/AliFMDdigit.h [deleted file]
FMD/AliFMDv0.cxx [deleted file]
FMD/AliFMDv0.h [deleted file]
FMD/AliFMDv1.cxx [deleted file]
FMD/AliFMDv1.h [deleted file]
FMD/Config.C [new file with mode: 0644]
FMD/Digitize.C [copied from FMD/AliFMDhit.cxx with 70% similarity]
FMD/Document.C [new file with mode: 0644]
FMD/DrawFMD.C
FMD/FMDDigit.C [deleted file]
FMD/FMDMerger.C [deleted file]
FMD/FMDReconstructor.C [deleted file]
FMD/FMDbaseLinkDef.h
FMD/FMDrecLinkDef.h
FMD/FMDsimLinkDef.h
FMD/ReadRaw.C [new file with mode: 0644]
FMD/Reconstruct.C [copied from FMD/AliFMDhit.cxx with 73% similarity]
FMD/Simulate.C [moved from FMD/AliFMDhit.cxx with 72% similarity]
FMD/ViewFMD.C
FMD/libFMDbase.pkg
FMD/libFMDrec.pkg
FMD/libFMDsim.pkg

diff --git a/FMD/.cvsignore b/FMD/.cvsignore
new file mode 100644 (file)
index 0000000..6e308a7
--- /dev/null
@@ -0,0 +1,4 @@
+semantic.cache
+html
+tgt_*
+
index 5dc3984..ac2efba 100644 (file)
 
 /* $Id$ */
 
- //////////////////////////////////////////////////////////////////////////////
-//                                                                            //
-//  Forward Multiplicity Detector based on Silicon plates                    //
-//  This class contains the base procedures for the Forward Multiplicity     //
-//  detector                                                                 //
-//  Detector consists of 5 Si volumes covered pseudorapidity interval         //
-//  from 1.7 to 5.1.                                                         //
-//                                                                           //
+//////////////////////////////////////////////////////////////////////////////
+//                                                                          
+//  Forward Multiplicity Detector based on Silicon wafers This class
+//  contains the base procedures for the Forward Multiplicity detector
+//  Detector consists of 5 Si volumes covered pseudorapidity interval
+//  from 1.7 to 5.1.
+//                                                                           
+// The actual code is done by various separate classes.   Below is
+// diagram showing the relationship between the various FMD classes
+// that handles the geometry 
+//
+//
+//       +----------+   +----------+   
+//       | AliFMDv1 |  | AliFMDv1 |   
+//       +----------+   +----------+   
+//            |              |
+//       +----+--------------+
+//       |
+//       |           +------------+ 1  +---------------+
+//       |        +- | AliFMDRing |<>--| AliFMDPolygon | 
+//       V     2  |  +------------+    +---------------+   
+//  +--------+<>--+        |
+//  | AliFMD |             ^                       
+//  +--------+<>--+        V 1..2                     
+//            3  | +-------------------+ 
+//               +-| AliFMDSubDetector | 
+//                 +-------------------+
+//                           ^              
+//                           |
+//             +-------------+-------------+
+//             |             |             |         
+//        +---------+   +---------+   +---------+
+//        | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
+//        +---------+   +---------+   +---------+
+//      
+//
+// *  AliFMD 
+//    This defines the interface for the various parts of AliROOT that
+//    uses the FMD, like AliFMDDigitizer, AliFMDReconstructor, and so
+//    on. 
+//
+// *  AliFMDv1 
+//    This is a concrete implementation of the AliFMD interface. 
+//    It is the responsibility of this class to create the FMD
+//    geometry, process hits in the FMD, and serve hits and digits to
+//    the various clients. 
+//  
+//    It uses the objects of class AliFMDSubDetector to do the various
+//    stuff for FMD1, 2, and 3 
+//
+// *  AliFMDRing 
+//    This class contains all stuff needed to do with a ring.  It's
+//    used by the AliFMDSubDetector objects to instantise inner and
+//    outer rings.  The AliFMDRing objects are shared by the
+//    AliFMDSubDetector objects, and owned by the AliFMDv1 object. 
+//
+// *  AliFMDPolygon 
+//    The code I lifted from TGeoPolygon to help with the geometry of
+//    the modules, as well as to decide wether a hit is actually with
+//    in the real module shape.  The point is, that the shape of the
+//    various ring modules are really polygons (much like the lid of a
+//    coffin), but it's segmented at constant radius.  That is very
+//    hard to implement using GEANT 3.21 shapes, so instead the
+//    modules are implemented as TUBS (tube sections), and in the step
+//    procedure we do the test whether the track was inside the real
+//    shape of the module.  
+//
+// *  AliFMD1, AliFMD2, and AliFMD3 
+//    These are specialisation of AliFMDSubDetector, that contains the
+//    particularities of each of the sub-detector system.  It is
+//    envisioned that the classes should also define the support
+//    volumes and material for each of the detectors.                          
+//                                                                          
 //Begin_Html
 /*
-<img src="gif/AliFMDClass.gif">
-</pre>
-<br clear=left>
-<font size=+2 color=red>
-<p>The responsible person for this module is
-<a href="mailto:Alla.Maevskaia@cern.ch">Alla Maevskaia</a>.
-</font>
-<pre>
+   <img src="gif/AliFMDClass.gif">
+   </pre>
+   <br clear=left>
+   <p>
+     The responsible person for this module is
+     <a href="mailto:Alla.Maevskaia@cern.ch">Alla Maevskaia</a>.
+   </p>
+   <p>
+     Many modifications by <a href="mailto:cholm@nbi.dk">Christian
+       Holm Christensen</a>.
+   </p>
+   <pre>
 */
 //End_Html
-//                                                                           //
-//                                                                           //
-///////////////////////////////////////////////////////////////////////////////
 
-#define DEBUG
+#ifndef ROOT_TClonesArray
+#include <TClonesArray.h>
+#endif
+#ifndef ROOT_TGeomtry
+# include <TGeometry.h>
+#endif
+#ifndef ROOT_TNode
+# include <TNode.h>
+#endif
+#ifndef ROOT_TTUBE
+# include <TTUBE.h>
+#endif
+#ifndef ROOT_TTree
+# include <TTree.h>
+#endif
+#ifndef ROOT_TVirtualMC
+# include <TVirtualMC.h>
+#endif
+#ifndef ROOT_TBrowser
+# include <TBrowser.h>
+#endif
+#ifndef ROOT_TMath
+# include <TMath.h>
+#endif
 
-#include <Riostream.h>
-#include <stdlib.h>
+#ifndef ALIRUNDIGITIZER_H
+# include "AliRunDigitizer.h"
+#endif
+#ifndef ALILOADER_H
+# include "AliLoader.h"
+#endif
+#ifndef ALIRUN_H
+# include "AliRun.h"
+#endif
+#ifndef ALIMC_H
+# include "AliMC.h"
+#endif
+#ifndef ALILog_H
+# include "AliLog.h"
+#endif
+#ifndef ALIMAGF_H
+# include "AliMagF.h"
+#endif
+#ifndef ALIFMD_H
+# include "AliFMD.h"
+#endif
+#ifndef ALIFMDDIGIG_H
+# include "AliFMDDigit.h"
+#endif
+#ifndef ALIFMDHIT_H
+# include "AliFMDHit.h"
+#endif
+#ifndef ALIFMDDIGITIZER_H
+# include "AliFMDDigitizer.h"
+#endif
+#ifndef ALIFMD1_H
+# include "AliFMD1.h"
+#endif
+#ifndef ALIFMD2_H
+# include "AliFMD2.h"
+#endif
+#ifndef ALIFMD3_H
+# include "AliFMD3.h"
+#endif
+#ifndef ALIALTROBUFFER_H
+# include "AliAltroBuffer.h"
+#endif
 
-#include <TClonesArray.h>
-#include <TFile.h>
-#include <TGeometry.h>
-#include <TNode.h>
-#include <TTUBE.h>
-#include <TTree.h>
-#include <TVirtualMC.h>
-
-#include "AliDetector.h"
-#include "AliFMDdigit.h"
-#include "AliFMDhit.h"
-#include "AliFMDv1.h"
-#include "AliLoader.h"
-#include "AliRun.h"
-#include "AliMC.h"
-#include "AliFMDDigitizer.h"
-
-ClassImp (AliFMD)
-  //_____________________________________________________________________________
-AliFMD::AliFMD ():AliDetector ()
+//____________________________________________________________________
+ClassImp(AliFMD);
+
+//____________________________________________________________________
+AliFMD::AliFMD()
+  : fInner(0), 
+    fOuter(0),
+    fFMD1(0),
+    fFMD2(0), 
+    fFMD3(0)
 {
   //
   // Default constructor for class AliFMD
   //
-  fIshunt = 0;
+  AliDebug(0, "Default CTOR");
   fHits     = 0;
   fDigits   = 0;
+  fSDigits  = 0;
+  fNsdigits = 0;
+  fIshunt   = 0;
 }
 
-//_____________________________________________________________________________
-AliFMD::AliFMD (const char *name, const char *title):
-AliDetector (name, title)
+//____________________________________________________________________
+AliFMD::AliFMD(const char *name, const char *title, bool detailed)
+  : AliDetector (name, title),
+    fInner(0), 
+    fOuter(0),
+    fFMD1(0),
+    fFMD2(0), 
+    fFMD3(0)
 {
   //
   // Standard constructor for Forward Multiplicity Detector
   //
+  AliDebug(0, "Standard CTOR");
 
-  //
   // Initialise Hit array
-  fHits = new TClonesArray ("AliFMDhit", 1000);
-  // Digits for each Si disk
-  fDigits = new TClonesArray ("AliFMDdigit", 1000);
-  gAlice->GetMCApp()->AddHitList (fHits);
+  HitsArray();
+  gAlice->GetMCApp()->AddHitList(fHits);
 
+  // (S)Digits for the detectors disk
+  DigitsArray();
+  SDigitsArray();
+  
+  // CHC: What is this?
   fIshunt = 0;
-  //  fMerger = 0;
-  SetMarkerColor (kRed);
+  SetMarkerColor(kRed);
+  SetLineColor(kYellow);
+  SetSiDensity();
+
+  // Create sub-volume managers 
+  fInner = new AliFMDRing('I', detailed);
+  fOuter = new AliFMDRing('O', detailed);
+  fFMD1  = new AliFMD1();
+  fFMD2  = new AliFMD2();
+  fFMD3  = new AliFMD3();
+
+  // Specify parameters of sub-volume managers 
+  fFMD1->SetInner(fInner);
+  fFMD1->SetOuter(0);
+
+  fFMD2->SetInner(fInner);
+  fFMD2->SetOuter(fOuter);
+  
+  fFMD3->SetInner(fInner);
+  fFMD3->SetOuter(fOuter);
+
+  SetLegLength();
+  SetLegRadius();
+  SetLegOffset();
+  SetModuleSpacing();
+  
+  fInner->SetLowR(4.3);
+  fInner->SetHighR(17.2);
+  fInner->SetWaferRadius(13.4/2);
+  fInner->SetTheta(36/2);
+  fInner->SetNStrips(512);
+  fInner->SetSiThickness(.03);
+  fInner->SetPrintboardThickness(.11);
+  fInner->SetBondingWidth(.5);
+
+  fOuter->SetLowR(15.6);
+  fOuter->SetHighR(28.0);
+  fOuter->SetWaferRadius(13.4/2);
+  fOuter->SetTheta(18/2);
+  fOuter->SetNStrips( 256);
+  fOuter->SetSiThickness(.03);
+  fOuter->SetPrintboardThickness(.1);
+  fOuter->SetBondingWidth(.5);
+  
+  
+  fFMD1->SetHoneycombThickness(1);
+  fFMD1->SetInnerZ(340.0);
+  
+  fFMD2->SetHoneycombThickness(1);
+  fFMD2->SetInnerZ(83.4);
+  fFMD2->SetOuterZ(75.2);
+
+  fFMD3->SetHoneycombThickness(1);
+  fFMD3->SetInnerZ(-62.8);
+  fFMD3->SetOuterZ(-75.2);
 }
 
-//-----------------------------------------------------------------------------
+//____________________________________________________________________
 AliFMD::~AliFMD ()
 {
-  //destructor for base class AliFMD
-  if (fHits)
-    {
-      fHits->Delete ();
-      delete fHits;
-      fHits = 0;
-    }
-  if (fDigits)
-    {
-      fDigits->Delete ();
-      delete fDigits;
-      fDigits = 0;
-    }
+  // Destructor for base class AliFMD
+  if (fHits) {
+    fHits->Delete();
+    delete fHits;
+    fHits = 0;
+  }
+  if (fDigits) {
+    fDigits->Delete();
+    delete fDigits;
+    fDigits = 0;
+  }
+  if (fSDigits) {
+    fSDigits->Delete();
+    delete fSDigits;
+    fSDigits = 0;
+  }
+}
+
+//====================================================================
+//
+// GEometry ANd Traking
+//
+//____________________________________________________________________
+void 
+AliFMD::CreateGeometry()
+{
+ //
+  // Create the geometry of Forward Multiplicity Detector version 0
+  //
+  // DebugGuard guard("AliFMD::CreateGeometry");
+  AliDebug(10, "Creating geometry");
 
+  fInner->Init();
+  fOuter->Init();
+
+  TString name;
+  Double_t par[3];
+
+  par[0]      =  fLegRadius - .1;
+  par[1]      =  fLegRadius;
+  par[2]      =  fLegLength / 2;
+  name        =  "SLEG";
+  fShortLegId =  gMC->Gsvolu(name.Data(),"TUBE",(*fIdtmed)[kPlasticId],par,3);
+  
+  par[2]      += fModuleSpacing / 2;
+  name        = "LLEG";
+  fLongLegId  =  gMC->Gsvolu(name.Data(),"TUBE",(*fIdtmed)[kPlasticId],par,3);
+
+  fInner->SetupGeometry((*fIdtmed)[kAirId], 
+                       (*fIdtmed)[kSiId], 
+                       (*fIdtmed)[kPcbId], 
+                       fPrintboardRotationId, 
+                       fIdentityRotationId);
+  fOuter->SetupGeometry((*fIdtmed)[kAirId], 
+                       (*fIdtmed)[kSiId], 
+                       (*fIdtmed)[kPcbId], 
+                       fPrintboardRotationId, 
+                       fIdentityRotationId);
+
+  fFMD1->SetupGeometry((*fIdtmed)[kAirId], (*fIdtmed)[kKaptionId]);
+  fFMD2->SetupGeometry((*fIdtmed)[kAirId], (*fIdtmed)[kKaptionId]);
+  fFMD3->SetupGeometry((*fIdtmed)[kAirId], (*fIdtmed)[kKaptionId]);
+  
+  fFMD1->Geometry("ALIC", fPrintboardRotationId, fIdentityRotationId);
+  fFMD2->Geometry("ALIC", fPrintboardRotationId, fIdentityRotationId);
+  fFMD3->Geometry("ALIC", fPrintboardRotationId, fIdentityRotationId);    
+}    
+
+//____________________________________________________________________
+void AliFMD::CreateMaterials() 
+{
+  // Register various materials and tracking mediums with the
+  // backend.   
+  // 
+  // Currently defined materials and mediums are 
+  // 
+  //    FMD Air                Normal air 
+  //    FMD Si          Active silicon of sensors 
+  //    FMD Carbon      Normal carbon used in support, etc. 
+  //    FMD Kapton      Carbon used in Honeycomb
+  //    FMD PCB         Printed circuit board material 
+  //    FMD Plastic     Material for support legs 
+  // 
+  // Also defined are two rotation matricies. 
+  //
+  // DebugGuard guard("AliFMD::CreateMaterials");
+  AliDebug(10, "Creating materials");
+  Int_t    id;
+  Double_t a                = 0;
+  Double_t z                = 0;
+  Double_t density          = 0;
+  Double_t radiationLength  = 0;
+  Double_t absorbtionLength = 999;
+  Int_t    fieldType        = gAlice->Field()->Integ();     // Field type 
+  Double_t maxField         = gAlice->Field()->Max();     // Field max.
+  Double_t maxBending       = 0;     // Max Angle
+  Double_t maxStepSize      = 0.001; // Max step size 
+  Double_t maxEnergyLoss    = 1;     // Max Delta E
+  Double_t precision        = 0.001; // Precision
+  Double_t minStepSize      = 0.001; // Minimum step size 
+  // Silicon 
+  a                = 28.0855;
+  z                = 14.;
+  density          = fSiDensity;
+  radiationLength  = 9.36;
+  maxBending       = 1;
+  maxStepSize      = .001;
+  precision        = .001;
+  minStepSize      = .001;
+  id               = kSiId;
+  AliMaterial(id, "FMD Si$", a, z, density, radiationLength, absorbtionLength);
+  AliMedium(kSiId, "FMD Si$",id,1,fieldType,maxField,maxBending,
+           maxStepSize,maxEnergyLoss,precision,minStepSize);
+
+
+  // Carbon 
+  a                = 12.011;
+  z                = 6.;
+  density          = 2.265;
+  radiationLength  = 18.8;
+  maxBending       = 10;
+  maxStepSize      = .01;
+  precision        = .003;
+  minStepSize      = .003;
+  id               = kCarbonId;
+  AliMaterial(id, "FMD Carbon$", a, z, density, radiationLength, 
+             absorbtionLength);
+  AliMedium(kCarbonId, "FMD Carbon$",id,0,fieldType,maxField,maxBending,
+           maxStepSize,maxEnergyLoss,precision,minStepSize);
+
+  // Silicon chip 
+  {
+    Float_t as[] = { 12.0107,      14.0067,      15.9994,
+                    1.00794,      28.0855,     107.8682 };
+    Float_t zs[] = {  6.,           7.,           8.,
+                     1.,          14.,          47. };
+    Float_t ws[] = {  0.039730642,  0.001396798,  0.01169634,
+                     0.004367771,  0.844665,     0.09814344903 };
+    density = 2.36436;
+    maxBending       = 10;
+    maxStepSize      = .01;
+    precision        = .003;
+    minStepSize      = .003;
+    id = kSiChipId;
+    AliMixture(id, "FMD Si Chip$", as, zs, density, 6, ws);
+    AliMedium(kSiChipId, "FMD Si Chip$", id, 0, fieldType, maxField, 
+             maxBending, maxStepSize, maxEnergyLoss, precision, minStepSize);
+  }
+  
+
+  // Kaption 
+  {
+    Float_t as[] = { 1.00794,  12.0107,  14.010,   15.9994};
+    Float_t zs[] = { 1.,        6.,       7.,       8.};
+    Float_t ws[] = { 0.026362,  0.69113,  0.07327,  0.209235};
+    density          = 1.42;
+    maxBending       = 1;
+    maxStepSize      = .001;
+    precision        = .001;
+    minStepSize      = .001;
+    id               = kKaptionId;
+    AliMixture(id, "FMD Kaption$", as, zs, density, 4, ws);
+    AliMedium(kKaptionId, "FMD Kaption$",id,0,fieldType,maxField,maxBending,
+             maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+  
+  // Air
+  {
+    Float_t as[] = { 12.0107, 14.0067,   15.9994,  39.948 };
+    Float_t zs[] = {  6.,      7.,       8.,       18. };
+    Float_t ws[] = { 0.000124, 0.755267, 0.231781, 0.012827 }; 
+    density      = .00120479;
+    maxBending   = 1;
+    maxStepSize  = .001;
+    precision    = .001;
+    minStepSize  = .001;
+    id           = kAirId;
+    AliMixture(id, "FMD Air$", as, zs, density, 4, ws);
+    AliMedium(kAirId, "FMD Air$", id,0,fieldType,maxField,maxBending,
+             maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+  
+  // PCB
+  {
+    Float_t zs[] = { 14.,         20.,         13.,         12.,
+                     5.,         22.,         11.,         19.,
+                    26.,          9.,          8.,          6.,
+                     7.,          1.};
+    Float_t as[] = { 28.0855,     40.078,      26.981538,   24.305, 
+                    10.811,      47.867,      22.98977,    39.0983,
+                    55.845,      18.9984,     15.9994,     12.0107,
+                    14.0067,      1.00794};
+    Float_t ws[] = {  0.15144894,  0.08147477,  0.04128158,  0.00904554, 
+                     0.01397570,  0.00287685,  0.00445114,  0.00498089,
+                     0.00209828,  0.00420000,  0.36043788,  0.27529426,
+                     0.01415852,  0.03427566};
+    density      = 1.8;
+    maxBending   = 1;
+    maxStepSize  = .001;
+    precision    = .001;
+    minStepSize  = .001;
+    id           = kPcbId;
+    AliMixture(id, "FMD PCB$", as, zs, density, 14, ws);
+    AliMedium(kPcbId, "FMD PCB$", id,1,fieldType,maxField,maxBending,
+             maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+  
+  // Plastic 
+  {
+    Float_t as[] = { 1.01, 12.01 };
+    Float_t zs[] = { 1.,   6.    };
+    Float_t ws[] = { 1.,   1.    };
+    density      = 1.03;
+    maxBending   = 10;
+    maxStepSize  = .01;
+    precision    = .003;
+    minStepSize  = .003;
+    id           = kPlasticId;
+    AliMixture(id, "FMD Plastic$", as, zs, density, -2, ws);
+    AliMedium(kPlasticId, "FMD Plastic$", id,0,fieldType,maxField,maxBending,
+               maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+  AliMatrix(fPrintboardRotationId, 90, 90, 0, 90, 90, 0);
+  AliMatrix(fIdentityRotationId, 90, 0, 90, 90, 0, 0);
 }
 
-//_____________________________________________________________________________
-void AliFMD::AddHit (Int_t track, Int_t * vol, Float_t * hits)
+//____________________________________________________________________
+void  
+AliFMD::Init()
 {
   //
-  // Add a hit to the list
+  // Initialis the FMD after it has been built
+  Int_t i;
+  //
+  if (fDebug) {
+    std::cout << "\n" << ClassName() << ": " << std::flush;
+    for (i = 0; i < 35; i++) std::cout << "*";
+    std::cout << " FMD_INIT ";
+    for (i = 0; i < 35; i++) std::cout << "*";
+    std::cout << "\n" << ClassName() << ": " << std::flush;
+    //
+    // Here the FMD initialisation code (if any!)
+    for (i = 0; i < 80; i++) std::cout << "*";
+    std::cout << std::endl;
+  }
+  //
   //
-  TClonesArray & lhits = *fHits;
-  new (lhits[fNhits++]) AliFMDhit (fIshunt, track, vol, hits);
 }
 
-//_____________________________________________________________________________
-void AliFMD::AddDigit (Int_t * digits)
+//====================================================================
+//
+// Graphics and event display
+//
+//____________________________________________________________________
+void 
+AliFMD::BuildGeometry()
 {
-  // add a real digit - as coming from data
+  //
+  // Build simple ROOT TNode geometry for event display
+  //
+  // Build a simplified geometry of the FMD used for event display  
+  // 
+  AliDebug(10, "Creating a simplified geometry");
 
-  if (fDigits == 0x0) fDigits = new TClonesArray ("AliFMDdigit", 1000);  
-  TClonesArray & ldigits = *fDigits;
-  new (ldigits[fNdigits++]) AliFMDdigit (digits);
+  TNode* top = gAlice->GetGeometry()->GetNode("alice");
+  
+  fFMD1->SimpleGeometry(fNodes, top, GetLineColor(), 0);
+  fFMD2->SimpleGeometry(fNodes, top, GetLineColor(), 0);
+  fFMD3->SimpleGeometry(fNodes, top, GetLineColor(), 0);
 }
 
-//_____________________________________________________________________________
-void AliFMD::BuildGeometry ()
+//____________________________________________________________________
+void 
+AliFMD::DrawDetector()
 {
   //
-  // Build simple ROOT TNode geometry for event display
+  // Draw a shaded view of the Forward multiplicity detector version 0
   //
-  TNode *node, *top;
-  const int kColorFMD = 5;
-  //
-  top = gAlice->GetGeometry ()->GetNode ("alice");
-
-  // FMD define the different volumes
-  new TRotMatrix ("rot901", "rot901", 90, 0, 90, 90, 180, 0);
-
-  new TTUBE ("S_FMD0", "FMD  volume 0", "void", 4.2, 17.2, 1.5);
-  top->cd ();
-  node = new TNode ("FMD0", "FMD0", "S_FMD0", 0, 0, -62.8, "");
-  node->SetLineColor (kColorFMD);
-  fNodes->Add (node);
-
-  new TTUBE ("S_FMD1", "FMD  volume 1", "void", 15.4, 28.4, 1.5);
-  top->cd ();
-  node = new TNode ("FMD1", "FMD1", "S_FMD1", 0, 0, -75.2, "");
-  node->SetLineColor (kColorFMD);
-  fNodes->Add (node);
-
-  new TTUBE ("S_FMD2", "FMD  volume 2", "void", 4.2, 17.2, 1.5);
-  top->cd ();
-  node = new TNode ("FMD2", "FMD2", "S_FMD2", 0, 0, 83.2, "");
-  node->SetLineColor (kColorFMD);
-  fNodes->Add (node);
-
-  new TTUBE ("S_FMD3", "FMD  volume 3", "void", 15.4, 28.4, 1.5);
-  top->cd ();
-  node = new TNode ("FMD3", "FMD3", "S_FMD3", 0, 0, 75.2, "");
-  node->SetLineColor (kColorFMD);
-  fNodes->Add (node);
-
-  new TTUBE ("S_FMD4", "FMD  volume 4", "void", 4.2, 17.2, 1.5);
-  top->cd ();
-  node = new TNode ("FMD4", "FMD4", "S_FMD4", 0, 0, 340, "");
-  node->SetLineColor (kColorFMD);
-  fNodes->Add (node);
+  // DebugGuard guard("AliFMD::DrawDetector");
+  AliDebug(10, "Draw detector");
+  
+  //Set ALIC mother transparent
+  gMC->Gsatt("ALIC","SEEN",0);
+
+  //Set volumes visible
+  fFMD1->Gsatt();
+  fFMD2->Gsatt();
+  fFMD3->Gsatt();
+  fInner->Gsatt();
+  fOuter->Gsatt();
+
+  //
+  gMC->Gdopt("hide", "on");
+  gMC->Gdopt("shad", "on");
+  gMC->Gsatt("*", "fill", 7);
+  gMC->SetClipBox(".");
+  gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
+  gMC->DefaultRange();
+  gMC->Gdraw("alic", 40, 30, 0, 12, 12, .055, .055);
+  gMC->Gdhead(1111, "Forward Multiplicity Detector");
+  gMC->Gdman(16, 10, "MAN");
+  gMC->Gdopt("hide", "off");
 }
 
-//_____________________________________________________________________________
-const Int_t AliFMD::DistanceToPrimitive (Int_t /*px*/, Int_t /*py*/)
+//____________________________________________________________________
+const Int_t 
+AliFMD::DistanceToPrimitive(Int_t, Int_t)
 {
   //
   // Calculate the distance from the mouse to the FMD on the screen
@@ -187,112 +595,752 @@ const Int_t AliFMD::DistanceToPrimitive (Int_t /*px*/, Int_t /*py*/)
   return 9999;
 }
 
-//___________________________________________
-void AliFMD::ResetHits ()
+//====================================================================
+//
+// Hit and Digit managment 
+//
+//____________________________________________________________________
+void 
+AliFMD::MakeBranch(Option_t * option)
+{
+  // Create Tree branches for the FMD.
+  const Int_t kBufferSize = 16000;
+  TString branchname(GetName());
+  TString opt(option);
+  
+  if (opt.Contains("H", TString::kIgnoreCase)) {
+    HitsArray();
+    AliDetector::MakeBranch(option); 
+  }
+  if (opt.Contains("D", TString::kIgnoreCase)) { 
+    DigitsArray();
+    MakeBranchInTree(fLoader->TreeD(), branchname.Data(),
+                    &fDigits, kBufferSize, 0);
+  }
+  if (opt.Contains("S", TString::kIgnoreCase)) { 
+    SDigitsArray();
+    MakeBranchInTree(fLoader->TreeS(), branchname.Data(),
+                    &fSDigits, kBufferSize, 0);
+  }
+}
+
+//____________________________________________________________________
+void 
+AliFMD::SetTreeAddress()
+{
+  // Set branch address for the Hits and Digits Tree.
+
+  if (fLoader->TreeH()) HitsArray();
+  AliDetector::SetTreeAddress();
+
+  TTree *treeD = fLoader->TreeD();
+  if (treeD) {
+    DigitsArray();
+    TBranch* branch = treeD->GetBranch ("FMD");
+    if (branch) branch->SetAddress(&fDigits);
+  }
+
+  TTree *treeS = fLoader->TreeS();
+  if (treeS) {
+    SDigitsArray();
+    TBranch* branch = treeS->GetBranch ("FMD");
+    if (branch) branch->SetAddress(&fSDigits);
+  }
+}
+
+
+
+//____________________________________________________________________
+void 
+AliFMD::SetHitsAddressBranch(TBranch *b)
 {
-  // Reset number of clusters and the cluster array for this detector
-  AliDetector::ResetHits ();
+  b->SetAddress(&fHits);
 }
 
-//____________________________________________
-void AliFMD::ResetDigits ()
+//____________________________________________________________________
+void 
+AliFMD::AddHit(Int_t track, Int_t *vol, Float_t *hits) 
+{
+  // Add a hit to the hits tree 
+  // 
+  // The information of the two arrays are decoded as 
+  // 
+  // Parameters
+  //    track               Track #
+  //    ivol[0]  [UShort_t ] Detector # 
+  //    ivol[1]         [Char_t   ] Ring ID 
+  //    ivol[2]         [UShort_t ] Sector #
+  //    ivol[3]         [UShort_t ] Strip # 
+  //    hits[0]         [Float_t  ] Track's X-coordinate at hit 
+  //    hits[1]         [Float_t  ] Track's Y-coordinate at hit
+  //    hits[3]  [Float_t  ] Track's Z-coordinate at hit
+  //    hits[4]  [Float_t  ] X-component of track's momentum            
+  //    hits[5]         [Float_t  ] Y-component of track's momentum             
+  //    hits[6]         [Float_t  ] Z-component of track's momentum            
+  //    hits[7]         [Float_t  ] Energy deposited by track                  
+  //    hits[8]         [Int_t    ] Track's particle Id # 
+  //    hits[9]         [Float_t  ] Time when the track hit                    
+  AddHit(track, 
+        UShort_t(vol[0]),  // Detector # 
+        Char_t(vol[1]),    // Ring ID
+        UShort_t(vol[2]),  // Sector # 
+        UShort_t(vol[3]),  // Strip # 
+        hits[0],           // X
+        hits[1],           // Y
+        hits[2],           // Z
+        hits[3],           // Px
+        hits[4],           // Py
+        hits[5],           // Pz
+        hits[6],           // Energy loss 
+        Int_t(hits[7]),    // PDG 
+        hits[8]);          // Time
+}
+
+//____________________________________________________________________
+void 
+AliFMD::AddHit(Int_t    track, 
+              UShort_t detector, 
+              Char_t   ring, 
+              UShort_t sector, 
+              UShort_t strip, 
+              Float_t  x, 
+              Float_t  y, 
+              Float_t  z,
+              Float_t  px, 
+              Float_t  py, 
+              Float_t  pz,
+              Float_t  edep,
+              Int_t    pdg,
+              Float_t  t)
 {
   //
-  // Reset number of digits and the digits array for this detector
-  AliDetector::ResetDigits ();
+  // Add a hit to the list
   //
+  // Parameters:
+  // 
+  //    track    Track #
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+  //    x        Track's X-coordinate at hit
+  //    y        Track's Y-coordinate at hit
+  //    z        Track's Z-coordinate at hit
+  //    px       X-component of track's momentum 
+  //    py       Y-component of track's momentum
+  //    pz       Z-component of track's momentum
+  //    edep     Energy deposited by track
+  //    pdg      Track's particle Id #
+  //    t        Time when the track hit 
+  // 
+  TClonesArray& a = *(HitsArray());
+  // Search through the list of already registered hits, and see if we
+  // find a hit with the same parameters.  If we do, then don't create
+  // a new hit, but rather update the energy deposited in the hit.
+  // This is done, so that a FLUKA based simulation will get the
+  // number of hits right, not just the enerrgy deposition. 
+  for (Int_t i = 0; i < fNhits; i++) {
+    if (!a.At(i)) continue;
+    AliFMDHit* hit = static_cast<AliFMDHit*>(a.At(i));
+    if (hit->Detector() == detector 
+       && hit->Ring() == ring
+       && hit->Sector() == sector 
+       && hit->Strip() == strip
+       && hit->Track() == track) {
+      hit->SetEdep(hit->Edep() + edep);
+      return;
+    }
+  }
+  // If hit wasn't already registered, do so know. 
+  new (a[fNhits]) AliFMDHit(fIshunt, track, detector, ring, sector, strip, 
+                           x, y, z, px, py, pz, edep, pdg, t);
+  fNhits++;
 }
 
-//-------------------------------------------------------------------------
-void  AliFMD::Init ()
+//____________________________________________________________________
+void 
+AliFMD::AddDigit(Int_t* digits)
 {
+  // Add a digit to the Digit tree 
+  // 
+  // Paramters 
   //
-  // Initialis the FMD after it has been built
-  Int_t i;
+  //    digits[0]  [UShort_t] Detector #
+  //    digits[1]  [Char_t]   Ring ID
+  //    digits[2]  [UShort_t] Sector #
+  //    digits[3]  [UShort_t] Strip #
+  //    digits[4]  [UShort_t] ADC Count 
+  //    digits[5]  [Short_t]  ADC Count, -1 if not used
+  //    digits[6]  [Short_t]  ADC Count, -1 if not used 
+  // 
+  AddDigit(UShort_t(digits[0]),  // Detector #
+          Char_t(digits[1]),    // Ring ID
+          UShort_t(digits[2]),  // Sector #
+          UShort_t(digits[3]),  // Strip #
+          UShort_t(digits[4]),  // ADC Count1 
+          Short_t(digits[5]),   // ADC Count2 
+          Short_t(digits[6]));  // ADC Count3 
+}
+
+//____________________________________________________________________
+void 
+AliFMD::AddDigit(UShort_t detector, 
+                Char_t   ring, 
+                UShort_t sector, 
+                UShort_t strip, 
+                UShort_t count1, 
+                Short_t  count2,
+                Short_t  count3)
+{
+  // add a real digit - as coming from data
+  // 
+  // Parameters 
   //
-  if (fDebug)
-    {
-      printf ("\n%s: ", ClassName ());
-      for (i = 0; i < 35; i++)
-       printf ("*");
-      printf (" FMD_INIT ");
-      for (i = 0; i < 35; i++)
-       printf ("*");
-      printf ("\n%s: ", ClassName ());
-      //
-      // Here the FMD initialisation code (if any!)
-      for (i = 0; i < 80; i++)
-       printf ("*");
-      printf ("\n");
-    }
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+  //    count1    ADC count (a 10-bit word)
+  //    count2    ADC count (a 10-bit word), or -1 if not used
+  //    count3    ADC count (a 10-bit word), or -1 if not used
+  TClonesArray& a = *(DigitsArray());
+  
+  new (a[fNdigits++]) 
+    AliFMDDigit(detector, ring, sector, strip, count1, count2, count3);
+}
+
+//____________________________________________________________________
+void 
+AliFMD::AddSDigit(Int_t* digits)
+{
+  // Add a digit to the SDigit tree 
+  // 
+  // Paramters 
   //
+  //    digits[0]  [UShort_t] Detector #
+  //    digits[1]  [Char_t]   Ring ID
+  //    digits[2]  [UShort_t] Sector #
+  //    digits[3]  [UShort_t] Strip #
+  //    digits[4]  [Float_t]  Total energy deposited 
+  //    digits[5]  [UShort_t] ADC Count 
+  //    digits[6]  [Short_t]  ADC Count, -1 if not used
+  //    digits[7]  [Short_t]  ADC Count, -1 if not used 
+  // 
+  AddSDigit(UShort_t(digits[0]),  // Detector #
+           Char_t(digits[1]),    // Ring ID
+           UShort_t(digits[2]),  // Sector #
+           UShort_t(digits[3]),  // Strip #
+           Float_t(digits[4]),   // Edep
+           UShort_t(digits[5]),  // ADC Count1 
+           Short_t(digits[6]),   // ADC Count2 
+           Short_t(digits[7]));  // ADC Count3 
+}
+
+//____________________________________________________________________
+void 
+AliFMD::AddSDigit(UShort_t detector, 
+                 Char_t   ring, 
+                 UShort_t sector, 
+                 UShort_t strip, 
+                 Float_t  edep,
+                 UShort_t count1, 
+                 Short_t  count2,
+                 Short_t  count3)
+{
+  // add a summable digit
+  // 
+  // Parameters 
   //
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+  //    edep      Total energy deposited
+  //    count1    ADC count (a 10-bit word)
+  //    count2    ADC count (a 10-bit word), or -1 if not used
+  //    count3    ADC count (a 10-bit word), or -1 if not used
+  TClonesArray& a = *(SDigitsArray());
+  
+  new (a[fNsdigits++]) 
+    AliFMDSDigit(detector, ring, sector, strip, edep, count1, count2, count3);
 }
-//---------------------------------------------------------------------
-void AliFMD::MakeBranch (Option_t * option)
+
+//____________________________________________________________________
+void 
+AliFMD::ResetSDigits()
 {
-  // Create Tree branches for the FMD.
-  char branchname[10];
-  const Int_t kBufferSize = 16000;
-  sprintf (branchname, "%s", GetName ());
+  //
+  // Reset number of digits and the digits array for this detector
+  //
+  fNsdigits   = 0;
+  if (fSDigits) fSDigits->Clear();
+}
+
+
+//____________________________________________________________________
+TClonesArray*
+AliFMD::HitsArray() 
+{
+  // Initialize hit array if not already, and return pointer to it. 
+  if (!fHits) { 
+    fHits = new TClonesArray("AliFMDHit", 1000);
+    fNhits = 0;
+  }
+  return fHits;
+}
+
+//____________________________________________________________________
+TClonesArray*
+AliFMD::DigitsArray() 
+{
+  // Initialize digit array if not already, and return pointer to it. 
+  if (!fDigits) { 
+    fDigits = new TClonesArray("AliFMDDigit", 1000);
+    fNdigits = 0;
+  }
+  return fDigits;
+}
+
+//____________________________________________________________________
+TClonesArray*
+AliFMD::SDigitsArray() 
+{
+  // Initialize digit array if not already, and return pointer to it. 
+  if (!fSDigits) { 
+    fSDigits = new TClonesArray("AliFMDSDigit", 1000);
+    fNsdigits = 0;
+  }
+  return fSDigits;
+}
+
+//====================================================================
+//
+// Digitization 
+//
+//____________________________________________________________________
+void 
+AliFMD::Hits2Digits() 
+{
+  AliRunDigitizer* manager = new AliRunDigitizer(1, 1);
+  manager->SetInputStream(0, "galice.root");
+  manager->SetOutputFile("H2Dfile");
   
-  const char *cH = strstr(option,"H");
-  const char *cD = strstr(option,"D");
+  /* AliDigitizer* dig =*/ CreateDigitizer(manager);
+  manager->Exec("");
+}
+
+//____________________________________________________________________
+void 
+AliFMD::Hits2SDigits() 
+{
+  AliDigitizer* sdig = new AliFMDSDigitizer("galice.root");
+  sdig->Exec("");
+}
+
   
-  if (cH && (fHits == 0x0)) fHits = new TClonesArray ("AliFMDhit", 1000);
+//____________________________________________________________________
+AliDigitizer* 
+AliFMD::CreateDigitizer(AliRunDigitizer* manager) const
+{
+  // Create a digitizer object 
+  return new AliFMDDigitizer(manager);
+}
 
-  AliDetector::MakeBranch (option);
+//====================================================================
+//
+// Raw data simulation 
+//
+//__________________________________________________________________
+void 
+AliFMD::Digits2Raw() 
+{
+  AliFMD* fmd = static_cast<AliFMD*>(gAlice->GetDetector(GetName()));
+  fLoader->LoadDigits();
+  TTree* digitTree = fLoader->TreeD();
+  if (!digitTree) {
+    Error("Digits2Raw", "no digit tree");
+    return;
+  }
   
-  if (cD){
-    if (fDigits == 0x0) fDigits = new TClonesArray ("AliFMDdigit", 1000);  
-    MakeBranchInTree(fLoader->TreeD(), branchname,&fDigits, kBufferSize, 0);
+  TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
+  fmd->SetTreeAddress();
+  TBranch* digitBranch = digitTree->GetBranch(GetName());
+  if (!digitBranch) {
+    Error("Digits2Raw", "no branch for %s", GetName());
+    return;
   }
+  digitBranch->SetAddress(&digits);
+  
+  Int_t nEvents = digitTree->GetEntries();
+  for (Int_t event = 0; event < nEvents; event++) {
+    fmd->ResetDigits();
+    digitTree->GetEvent(event);
+    
+    Int_t nDigits = digits->GetEntries();
+    if (nDigits < 1) continue;
 
-}
 
-//_____________________________________________________________________________
-void AliFMD::SetTreeAddress ()
-{
-  // Set branch address for the Hits and Digits Tree.
+    UShort_t prevDetector = 0;
+    Char_t   prevRing     = '\0';
+    UShort_t prevSector   = 0;
+    // UShort_t prevStrip    = 0;
 
-  if (fLoader->TreeH() && (fHits == 0x0)) 
-    fHits = new TClonesArray ("AliFMDhit", 1000);  
+    // The first seen strip number for a channel 
+    UShort_t startStrip   = 0;
+    
+    // Which channel number in the ALTRO channel we're at 
+    UShort_t offset       = 0;
 
-  AliDetector::SetTreeAddress ();
+    // How many times the ALTRO Samples one VA1_ALICE channel 
+    Int_t sampleRate = 1;
 
-  TBranch *branch;
-  TTree *treeD = fLoader->TreeD();
+    // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
+    // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate' 
+    TArrayI channel(128 * sampleRate);
+    
+    // The Altro buffer 
+    AliAltroBuffer* altro = 0;
+    
+    // Loop over the digits in the event.  Note, that we assume the
+    // the digits are in order in the branch.   If they were not, we'd
+    // have to cache all channels before we could write the data to
+    // the ALTRO buffer, or we'd have to set up a map of the digits. 
+    for (Int_t i = 0; i < nDigits; i++) {
+      // Get the digit
+      AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
+
+      UShort_t det    = digit->Detector();
+      Char_t   ring   = digit->Ring();
+      UShort_t sector = digit->Sector();
+      UShort_t strip  = digit->Strip();
+      if (det != prevDetector) {
+       AliDebug(10, Form("FMD: New DDL, was %d, now %d",
+                         kBaseDDL + prevDetector - 1,
+                         kBaseDDL + det - 1));
+       // If an altro exists, delete the object, flushing the data to
+       // disk, and closing the file. 
+       if (altro) { 
+         // When the first argument is false, we write the real
+         // header. 
+         AliDebug(10, Form("New altro: Write channel at %d Strip: %d "
+                           "Sector: %d  Ring: %d", 
+                           i, startStrip, prevSector, prevRing));
+         // TPC to FMD translations 
+         // 
+         //    TPC                FMD
+         //    ----------+-----------
+         //    pad       |      strip
+         //    row       |     sector
+         //    sector    |       ring
+         // 
+         altro->WriteChannel(Int_t(startStrip), 
+                             Int_t(prevSector), 
+                             Int_t((prevRing == 'I' ? 0 : 1)), 
+                             channel.fN, channel.fArray, 0);
+         altro->Flush();
+         altro->WriteDataHeader(kFALSE, kFALSE);
+         delete altro;
+         altro = 0;
+       }
+
+       prevDetector = det;
+       // Need to open a new DDL! 
+       Int_t ddlId = kBaseDDL + det - 1;
+       TString filename(Form("%s_%d.ddl", GetName(),  ddlId));
+
+       AliDebug(10, Form("New altro buffer with DDL file %s", 
+                         filename.Data()));
+       AliDebug(10, Form("New altro at %d", i));
+       // Create a new altro buffer - a `1' as the second argument
+       // means `write mode' 
+       altro = new AliAltroBuffer(filename.Data(), 1);
+       
+       // Write a dummy (first argument is true) header to the DDL
+       // file - later on, when we close the file, we write the real
+       // header
+       altro->WriteDataHeader(kTRUE, kFALSE);
+
+       // Figure out the sample rate 
+       if (digit->Count2() > 0) sampleRate = 2;
+       if (digit->Count3() > 0) sampleRate = 3;
+
+       channel.Set(128 * sampleRate);
+       offset     = 0;
+       prevRing   = ring;
+       prevSector = sector;
+       startStrip = strip;
+      }
+      else if (offset == 128                        
+              || digit->Ring() != prevRing 
+              || digit->Sector() != prevSector) {
+       // Force a new Altro channel
+       AliDebug(10, Form("Flushing channel to disk because %s",
+                         (offset == 128 ? "channel is full" :
+                          (ring != prevRing ? "new ring up" :
+                           "new sector up"))));
+       AliDebug(10, Form("New Channel: Write channel at %d Strip: %d "
+                         "Sector: %d  Ring: %d", 
+                         i, startStrip, prevSector, prevRing));
+       altro->WriteChannel(Int_t(startStrip), 
+                           Int_t(prevSector), 
+                           Int_t((prevRing == 'I' ? 0 : 1)), 
+                           channel.fN, channel.fArray, 0);
+       // Reset and update channel variables 
+       channel.Reset(0);
+       offset     = 0; 
+       startStrip = strip;
+       prevRing   = ring;
+       prevSector = sector;
+      }
 
-  if (treeD)
-    {
-      if (fDigits == 0x0) fDigits = new TClonesArray ("AliFMDdigit", 1000);
-      branch = treeD->GetBranch ("FMD");
-      if (branch)
-       branch->SetAddress (&fDigits);
+      // Store the counts of the ADC in the channel buffer 
+      channel[offset * sampleRate] = digit->Count1();
+      if (sampleRate > 1) 
+       channel[offset * sampleRate + 1] = digit->Count2();
+      if (sampleRate > 2) 
+       channel[offset * sampleRate + 2] = digit->Count3();
+      offset++;
     }
+    // Finally, we need to close the final ALTRO buffer if it wasn't
+    // already 
+    if (altro) {
+      altro->Flush();
+      altro->WriteDataHeader(kFALSE, kFALSE);
+      delete altro;
+    }
+  }
+  fLoader->UnloadDigits();
 }
 
+//==================================================================
+//
+// Various setter functions for the common paramters 
+//
 
+//__________________________________________________________________
+void 
+AliFMD::SetLegLength(Double_t length) 
+{
+ // Set lenght of plastic legs that hold the hybrid (print board and
+  // silicon sensor) onto the honeycomp support
+  //
+  // DebugGuard guard("AliFMD::SetLegLength");
+   AliDebug(10, "AliFMD::SetLegLength");
+  fLegLength = length;
+  fInner->SetLegLength(fLegLength);
+  fOuter->SetLegLength(fLegLength);
+}
 
-//-----------------------------------------------------------------------
+//__________________________________________________________________
+void 
+AliFMD::SetLegOffset(Double_t offset) 
+{
+  // Set offset from edge of hybrid to plastic legs that hold the
+  // hybrid (print board and silicon sensor) onto the honeycomp
+  // support 
+  //
+  // DebugGuard guard("AliFMD::SetLegOffset");
+  AliDebug(10, "AliFMD::SetLegOffset");
+  fInner->SetLegOffset(offset);
+  fOuter->SetLegOffset(offset);
+}
 
-void AliFMD::MakeBranchInTreeD(TTree *treeD, const char *file)
+//__________________________________________________________________
+void 
+AliFMD::SetLegRadius(Double_t radius) 
 {
-    //
-    // Create TreeD branches for the FMD
-    //
-    const Int_t kBufferSize = 4000;
-    char branchname[20];
-    sprintf(branchname,"%s",GetName());        
-    if(treeD)
-     {
-       MakeBranchInTree(treeD,  branchname,&fDigits, kBufferSize, file);
-     }
+  // Set the diameter of the plastic legs that hold the hybrid (print
+  // board and silicon sensor) onto the honeycomp support
+  //
+  // DebugGuard guard("AliFMD::SetLegRadius");
+  AliDebug(10, "AliFMD::SetLegRadius");
+  fLegRadius = radius;
+  fInner->SetLegRadius(fLegRadius);
+  fOuter->SetLegRadius(fLegRadius);
 }
 
-//____________________________________________________________________________
-AliDigitizer* AliFMD::CreateDigitizer(AliRunDigitizer* manager) const
+//__________________________________________________________________
+void 
+AliFMD::SetModuleSpacing(Double_t spacing) 
 {
-  return new AliFMDDigitizer(manager);
+  // Set the distance between the front and back sensor modules
+  // (module staggering). 
+  //
+  // DebugGuard guard("AliFMD::SetModuleSpacing");
+  AliDebug(10, "AliFMD::SetModuleSpacing");  
+  fModuleSpacing = spacing;
+  fInner->SetModuleSpacing(fModuleSpacing);
+  fOuter->SetModuleSpacing(fModuleSpacing);
+}
+
+//====================================================================
+//
+// Utility 
+//
+//__________________________________________________________________
+void 
+AliFMD::Browse(TBrowser* b) 
+{
+  AliDebug(10, "AliFMD::Browse");
+  AliDetector::Browse(b);
+  if (fInner) b->Add(fInner, "Inner Ring");
+  if (fOuter) b->Add(fOuter, "Outer Ring");
+  if (fFMD1)  b->Add(fFMD1,  "FMD1 SubDetector");
+  if (fFMD2)  b->Add(fFMD2,  "FMD2 SubDetector");
+  if (fFMD3)  b->Add(fFMD3,  "FMD3 SubDetector");
+}
+
+
+//********************************************************************
+//
+// AliFMDv0
+//
+//__________________________________________________________________
+
+ClassImp(AliFMDv0);
+
+//********************************************************************
+//
+// AliFMDv1
+//
+//__________________________________________________________________
+
+ClassImp(AliFMDv1);
+
+
+//_//____________________________________________________________________
+void 
+AliFMDv1::StepManager()
+{
+  //
+  // Called for every step in the Forward Multiplicity Detector
+  //
+  // The procedure is as follows: 
+  // 
+  //   - IF NOT track is alive THEN RETURN ENDIF
+  //   - IF NOT particle is charged THEN RETURN ENDIF
+  //   - IF NOT volume name is "STRI" or "STRO" THEN RETURN ENDIF 
+  //   - Get strip number (volume copy # minus 1)
+  //   - Get phi division number (mother volume copy #)
+  //   - Get module number (grand-mother volume copy #)
+  //   - section # = 2 * module # + phi division # - 1
+  //   - Get ring Id from volume name 
+  //   - Get detector # from grand-grand-grand-mother volume name 
+  //   - Get pointer to sub-detector object. 
+  //   - Get track position 
+  //   - IF track is entering volume AND track is inside real shape THEN
+  //   -   Reset energy deposited 
+  //   -   Get track momentum 
+  //   -   Get particle ID # 
+  ///  - ENDIF
+  //   - IF track is inside volume AND inside real shape THEN 
+  ///  -   Update energy deposited 
+  //   - ENDIF 
+  //   - IF track is inside real shape AND (track is leaving volume,
+  //         or it died, or it is stopped  THEN
+  //   -   Create a hit 
+  //   - ENDIF
+  //     
+  //
+  // DebugGuard guard("AliFMDv1::StepManager");
+  AliDebug(10, "AliFMDv1::StepManager");
+  // return;
+
+  // If the track is gone, return
+  if (!gMC->IsTrackAlive()) return;
+  
+  // Only process charged particles 
+  if(TMath::Abs(gMC->TrackCharge()) <= 0) return; 
+
+  // Only do stuff is the track is in one of the strips. 
+  TString vol(gMC->CurrentVolName());
+  if (!vol.Contains("STR")) return;
+
+
+  // Get the strip number.  Note, that GEANT numbers divisions from 1,
+  // so we subtract one 
+  Int_t strip;             
+  gMC->CurrentVolID(strip);
+  strip--;                 
+
+  // Get the phi division of the module 
+  Int_t phiDiv;                         // * The phi division number (1 or 2)
+  gMC->CurrentVolOffID(1, phiDiv);      //   in the module  
+
+  // Active volume number - not used. 
+  // Int_t active;                         
+  // gMC->CurrentVolOffID(2, active);      
+
+  // Get the module number in the ring. 
+  Int_t module;                    
+  gMC->CurrentVolOffID(3, module); 
+  
+  // Ring copy number - the same as the detector number - not used
+  // Int_t ringCopy;                       // * Ring copy number
+  // gMC->CurrentVolOffID(4, ringCopy);    //   Same as detector number 
+  
+  // Get the detector number from the path name 
+  Int_t detector = Int_t((gMC->CurrentVolOffName(5)[3]) - 48);
+
+  // The sector number, calculated from module and phi division # 
+  Int_t  sector =  2 * module + phiDiv - 1;
+
+  // The ring ID is encoded in the volume name 
+  Char_t ring = vol[3];
+
+  // Get a pointer to the sub detector structure 
+  AliFMDSubDetector* det = 0;
+  switch (detector) {
+  case 1: det = fFMD1; break;
+  case 2: det = fFMD2; break;
+  case 3: det = fFMD3; break;
+  }
+  if (!det) return;
+
+  // Get the current track position 
+  TLorentzVector v;
+  gMC->TrackPosition(v);
+  // Check that the track is actually within the active area 
+  Bool_t isWithin = det->CheckHit(ring, module, v.X(), v.Y());
+  Bool_t entering = gMC->IsTrackEntering() && isWithin;
+  Bool_t inside   = gMC->IsTrackInside()   && isWithin;
+  Bool_t out      = (gMC->IsTrackExiting() 
+                    || gMC->IsTrackDisappeared() 
+                    || gMC->IsTrackStop() 
+                    || !isWithin);
+// Reset the energy deposition for this track, and update some of
+  // our parameters.
+  if (entering) {
+    fCurrentDeltaE = 0;
+
+    // Get production vertex and momentum of the track 
+    fCurrentV = v;
+    gMC->TrackMomentum(fCurrentP);
+    fCurrentPdg = gMC->IdFromPDG(gMC->TrackPid());
+
+    // if (fAnalyser) 
+    //   fAnalyser->Update(detector, ring, isWithin, v.X(), v.Y());
+  }
+  
+  // If the track is inside, then update the energy deposition
+  if (inside && fCurrentDeltaE >= 0) 
+    fCurrentDeltaE += 1000 * gMC->Edep();
+
+  // The track exits the volume, or it disappeared in the volume, or
+  // the track is stopped because it no longer fulfills the cuts
+  // defined, then we create a hit. 
+  if (out && fCurrentDeltaE >= 0) {
+    fCurrentDeltaE += 1000 * gMC->Edep();
+
+    AddHit(gAlice->GetMCApp()->GetCurrentTrackNumber(),
+          detector, ring,  sector, strip,
+          fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(),
+          fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(), 
+          fCurrentDeltaE, fCurrentPdg, fCurrentV.T());
+    fCurrentDeltaE = -1;
+  }
 }
+//___________________________________________________________________
+//
+// EOF
+//
index b1834ed..8bead67 100644 (file)
+// -*- mode: c++ -*- 
 #ifndef ALIFMD_H
 #define ALIFMD_H
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+ *
+ * See cxx source for full Copyright notice                               
+ */
 
 ////////////////////////////////////////////////
 //  Manager and hits classes for set:Si-FMD     //
 ////////////////////////////////////////////////
-#include <AliDetector.h>
-#include <TBranch.h>
-#include <AliLoader.h>
 
-class TClonesArray;
- class AliFMD : public AliDetector {
+#ifndef ALIDETECTOR_H 
+# include <AliDetector.h>
+#endif
+#ifndef ALIFMDSUBDETECTOR_H
+# include "AliFMDSubDetector.h"
+#endif
+#ifndef ALIFMDRING_H
+# include "AliFMDRing.h"
+#endif
+#ifndef ROOT_TBranch
+# include <TBranch.h>
+#endif
+#ifndef ROOT_TArrayI
+# include <TArrayI.h>
+#endif
+
+//____________________________________________________________________
+class AliFMD : public AliDetector 
+{
 public:
   AliFMD();
-  AliFMD(const char *name, const char *title);
-  AliFMD(const AliFMD& FMD):AliDetector(FMD) {;}  //copy ctor
-  virtual       ~AliFMD(); 
- AliFMD&  operator=(const AliFMD&)                 {return *this;}
-  virtual void   AddHit(Int_t track, Int_t * vol, Float_t * hits);
-  virtual void   AddDigit(Int_t* digits);
-   virtual void   BuildGeometry();
-  virtual void   CreateGeometry() {}
-  virtual void   CreateMaterials()=0; 
-  virtual const Int_t  DistanceToPrimitive(Int_t px, Int_t py);
-  virtual Int_t  IsVersion() const =0;
+  AliFMD(const char *name, const char *title, bool detailed);
+  AliFMD(const AliFMD& FMD) : AliDetector(FMD)  {}  //copy ctor
+  virtual ~AliFMD(); 
+  AliFMD&               operator=(const AliFMD&)  {return *this;}
+
+  // GEometry ANd Tracking (GEANT :-)
+  virtual void   CreateGeometry();
+  virtual void   CreateMaterials(); 
   virtual void   Init();
-  virtual void   MakeBranch(Option_t *opt=" ");
-  virtual void   MakeBranchInTreeD(TTree *treeD, const char *file=0);
-  virtual void   SetTreeAddress();
-  virtual void   ResetHits();
-  virtual void   ResetDigits();
-  virtual void   DrawDetector()=0;
-  virtual void   StepManager() {}
-   
-  void SetEventNumber(Int_t i)     {fEvNrSig = i;}
+  virtual void   StepManager() = 0;
+  AliFMDSubDetector*    GetFMD1() const       { return fFMD1; }
+  AliFMDSubDetector*    GetFMD2() const       { return fFMD2; }
+  AliFMDSubDetector*    GetFMD3() const       { return fFMD3; }
+  AliFMDRing*           GetInner() const      { return fInner; }
+  AliFMDRing*           GetOuter() const      { return fOuter; }
 
+  // Graphics and event display 
+  virtual        void   BuildGeometry();
+  virtual        void   DrawDetector();
+  virtual const  Int_t  DistanceToPrimitive(Int_t px, Int_t py);
 
-   // Digitisation
-  virtual const void SetHitsAddressBranch(TBranch *b){b->SetAddress(&fHits);}
+  // Hit and digit management 
+  virtual void          MakeBranch(Option_t *opt=" ");
+  virtual void          SetHitsAddressBranch(TBranch *b);
+  virtual void          SetTreeAddress();
+  virtual TClonesArray* SDigits() { return fSDigits; }        
+  virtual void          ResetSDigits();
+  virtual void          AddHit(Int_t track, Int_t *vol, Float_t *hits);
+  virtual void          AddHit(Int_t    track, 
+                              UShort_t detector, 
+                              Char_t   ring, 
+                              UShort_t sector, 
+                              UShort_t strip, 
+                              Float_t  x=0,
+                              Float_t  y=0, 
+                              Float_t  z=0,
+                              Float_t  px=0, 
+                              Float_t  py=0, 
+                              Float_t  pz=0,
+                              Float_t  edep=0,
+                              Int_t    pdg=0,
+                              Float_t  t=0);
+  virtual        void   AddDigit(Int_t *digits);
+  virtual        void   AddDigit(UShort_t detector=0, 
+                                Char_t   ring='\0', 
+                                UShort_t sector=0, 
+                                UShort_t strip=0, 
+                                UShort_t count1=0, 
+                                Short_t  count2=-1, 
+                                Short_t  count3=-1);
+  virtual        void   AddSDigit(Int_t *digits);
+  virtual        void   AddSDigit(UShort_t detector=0, 
+                                 Char_t   ring='\0', 
+                                 UShort_t sector=0, 
+                                 UShort_t strip=0, 
+                                 Float_t  edep=0,
+                                 UShort_t count1=0, 
+                                 Short_t  count2=-1, 
+                                 Short_t  count3=-1);
+
+  // Digitisation
   virtual AliDigitizer* CreateDigitizer(AliRunDigitizer* manager) const;
+  virtual        void   Hits2Digits();
+  virtual        void   Hits2SDigits();
+
+  // Raw data 
+  virtual        void   Digits2Raw();
+
+  // Set various parameters 
+  void     SetLegLength(Double_t     length=1);
+  void     SetLegRadius(Double_t     radius=.5);
+  void     SetLegOffset(Double_t     offset=.5);
+  void     SetModuleSpacing(Double_t spacing=1);
+
+  // Get various parameters
+  Int_t    GetSiId() const                 { return (*fIdtmed)[kSiId]; }
+  Int_t    GetAirId() const                { return (*fIdtmed)[kAirId]; }
+  Int_t    GetPlasticId() const            { return (*fIdtmed)[kPlasticId]; }
+  Int_t    GetPcbId() const                { return (*fIdtmed)[kPcbId]; }
+  Int_t    GetKaptionId() const            { return (*fIdtmed)[kKaptionId]; }
+  Int_t    GetCarbonId() const             { return (*fIdtmed)[kCarbonId]; }
+  Int_t    GetPrintboardRotationId() const { return fPrintboardRotationId; }
+  Int_t    GetShortLegId() const          { return fShortLegId; }
+  Int_t    GetLongLegId() const                   { return fLongLegId; }
+  Double_t GetLegLength() const                   { return fLegLength; }
+  Double_t GetLegRadius() const                   { return fLegRadius; }
+  Double_t GetModuleSpacing() const       { return fModuleSpacing; }  
 
- protected:
-//Granularity
-  Int_t fRingsSi1;       // Number of rings
-  Int_t fSectorsSi1;    // Number of sectors
-  Int_t fRingsSi2;       // Number of rings
-  Int_t fSectorsSi2;    // Number of sectors
+  // Utility
+  void   Browse(TBrowser* b);
+  Float_t GetSiDensity() const { return fSiDensity; }
+  enum { 
+    kBaseDDL = 0x1000 // DDL offset for the FMD
+  };
+protected:
+  enum {
+    kSiId,                 // ID of Si medium
+    kAirId,                // ID of Air medium
+    kPlasticId,            // ID of Plastic medium
+    kPcbId,                // ID of PCB medium
+    kSiChipId,             // ID of Si Chip medium
+    kKaptionId,            // ID of Kaption medium
+    kCarbonId              // ID of Carbon medium
+  };
 
-  Int_t   fNevents ;        // Number of events to digitize
-  Int_t fEvNrSig;                 // signal     event number
+  void    SetSiDensity(Float_t r=2.33) { fSiDensity = r; }
+  TClonesArray*      HitsArray();
+  TClonesArray*      DigitsArray();
+  TClonesArray*      SDigitsArray();
+  
+  AliFMDRing*        fInner;        // Inner ring structure
+  AliFMDRing*        fOuter;        // Outer ring structure  
+  AliFMDSubDetector* fFMD1;         // FMD1 structure
+  AliFMDSubDetector* fFMD2;         // FMD2 structure  
+  AliFMDSubDetector* fFMD3;         // FMD3 structure
 
- ClassDef(AliFMD,7)  //Class for the FMD detector
+  TClonesArray*      fSDigits;
+  Int_t              fNsdigits;
+  
+  Float_t    fSiDensity;            // Density of Silicon
+  Int_t      fPrintboardRotationId; // ID of Rotation of print bard
+  Int_t      fIdentityRotationId;   // ID of identity matrix 
+  Int_t      fShortLegId;           // ID short leg volume
+  Int_t      fLongLegId;            // ID long leg volume  
+  Double_t   fLegLength;            // Leg length
+  Double_t   fLegRadius;            // Leg radius
+  Double_t   fModuleSpacing;        // Staggering offset 
+  
+  ClassDef(AliFMD,8)     // Base class FMD entry point
 };
-#endif // AliFMD_H
 
+//____________________________________________________________________
+class AliFMDv0 : public AliFMD 
+{
+public:
+  AliFMDv0() {}
+  AliFMDv0(const char *name, const char *title="Coarse geometry") 
+    : AliFMD(name, title, false)
+  {}
+  virtual ~AliFMDv0() 
+  {}
+
+  // Required member functions 
+  virtual Int_t  IsVersion() const {return 0;}
+  virtual void   StepManager() {}
+
+  ClassDef(AliFMDv0,1) // Coarse FMD geometry 
+};
+
+//____________________________________________________________________
+#ifndef ROOT_TLorentzVector
+# include <TLorentzVector.h>
+#endif
+class AliFMDv1 : public AliFMD 
+{
+public:
+  AliFMDv1() {}
+  AliFMDv1(const char *name, const char *title="Detailed geometry") 
+    : AliFMD(name, title, true) 
+  {}
+  virtual ~AliFMDv1() {}
+
+  // Required member functions 
+  virtual Int_t  IsVersion() const {return 1;}
+  virtual void   StepManager();
+protected:
+  Double_t   fCurrentDeltaE;        // The current accumelated energy loss
+  TLorentzVector fCurrentV;         // Current production vertex 
+  TLorentzVector fCurrentP;         // Current momentum vector 
+  Int_t          fCurrentPdg;       // Current PDG code 
+  
+  ClassDef(AliFMDv1,3)  // Detailed FMD geometry
+};
 
+#endif
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMD1.cxx b/FMD/AliFMD1.cxx
new file mode 100644 (file)
index 0000000..9415034
--- /dev/null
@@ -0,0 +1,90 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//                                                                          
+// Concrete implementation of AliFMDSubDetector 
+//
+// This implements the geometry for FMD1 
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef ALIFMD1_H
+# include "AliFMD1.h"
+#endif 
+#ifndef ROOT_TVirtualMC
+# include <TVirtualMC.h>
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+
+
+//____________________________________________________________________
+ClassImp(AliFMD1);
+
+//____________________________________________________________________
+AliFMD1::AliFMD1() 
+  : AliFMDSubDetector(1) 
+{}
+
+//____________________________________________________________________
+AliFMD1::~AliFMD1() 
+{}
+
+//____________________________________________________________________
+void 
+AliFMD1::SetupGeometry(Int_t airId, Int_t kaptionId) 
+{
+  fInnerHoneyLowR  = fInner->GetLowR() + 1;
+  fInnerHoneyHighR = fInner->GetHighR() + 1;
+  fOuterHoneyLowR  = 0;
+  fOuterHoneyHighR = 0;
+
+  Double_t par[3];
+  par[0] = fInner->GetLowR();
+  par[1] = fInnerHoneyHighR;
+  par[2] = fDz = (fInner->GetLegLength() 
+                 + fInner->GetSiThickness() 
+                 + fInner->GetPrintboardThickness() 
+                 + fInner->GetModuleSpacing() 
+                 + fHoneycombThickness) / 2;
+  fVolumeId = gMC->Gsvolu("FMD1", "TUBE", airId, par, 3);
+
+  // Rotate the full sub-detector 
+  gMC->Matrix(fRotationId, 270, 180, 90, 90, 180, 0); 
+
+  AliFMDSubDetector::SetupGeometry(airId, kaptionId);
+}
+
+//____________________________________________________________________
+void 
+AliFMD1::Geometry(const char* mother, Int_t pbRotId, 
+                 Int_t idRotId, Double_t z) 
+{
+  // The Z passed in isn't used. 
+  z = fInnerZ + fDz;
+  gMC->Gspos("FMD1", 1, mother, 0, 0, z, fRotationId);
+
+  AliFMDSubDetector::Geometry("FMD1", pbRotId, idRotId, z);
+}
+
+  
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMD1.h b/FMD/AliFMD1.h
new file mode 100644 (file)
index 0000000..306771e
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- mode: C++ -*-
+//
+// $Id$
+//
+#ifndef ALIFMD1_H
+#define ALIFMD1_H
+
+#ifndef ALIFMDSUBDETECTOR_H
+# include "AliFMDSubDetector.h"
+#endif
+
+class AliFMD1 : public AliFMDSubDetector 
+{
+private:
+  Int_t    fVolumeId;
+  Double_t fDz;
+public:
+  AliFMD1();
+  virtual ~AliFMD1();
+  virtual void   SetupGeometry(Int_t airId, Int_t kaptionId);  
+  virtual void   Geometry(const char* mother, Int_t pbRotId, 
+                         Int_t idRotId, Double_t z=0);
+  ClassDef(AliFMD1,1); // Geometry of FMD1 
+};
+
+#endif
+//
+// EOF
+//
diff --git a/FMD/AliFMD2.cxx b/FMD/AliFMD2.cxx
new file mode 100644 (file)
index 0000000..85a4875
--- /dev/null
@@ -0,0 +1,88 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//                                                                          
+// Concrete implementation of AliFMDSubDetector 
+//
+// This implements the geometry for FMD2
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef ALIFMD2_H
+# include "AliFMD2.h"
+#endif 
+#ifndef ROOT_TVirtualMC
+# include <TVirtualMC.h>
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMD2);
+
+//____________________________________________________________________
+AliFMD2::AliFMD2() 
+  : AliFMDSubDetector(2) 
+{}
+
+//____________________________________________________________________
+AliFMD2::~AliFMD2() 
+{}
+
+//____________________________________________________________________
+void 
+AliFMD2::SetupGeometry(Int_t airId, Int_t kaptionId) 
+{
+  fInnerHoneyLowR  = fInner->GetLowR() + 1;
+  fInnerHoneyHighR = fInner->GetHighR() + 1;
+  fOuterHoneyLowR  = fOuter->GetLowR() + 1;
+  fOuterHoneyHighR = fOuter->GetHighR() + 1;
+
+  Double_t par[3];
+  par[0] = fInner->GetLowR();
+  par[1] = fOuterHoneyHighR;
+  par[2] = fDz = (TMath::Abs(fInnerZ - fOuterZ)
+                 + fInner->GetSiThickness() 
+                 + fInner->GetPrintboardThickness() 
+                 + fInner->GetLegLength() 
+                 + fInner->GetModuleSpacing() 
+                 + fHoneycombThickness) / 2;
+  fVolumeId = gMC->Gsvolu("FMD2", "TUBE", airId, par, 3);
+
+  // Rotate the full sub-detector 
+  gMC->Matrix(fRotationId, 270, 180, 90, 90, 180, 0); 
+
+  AliFMDSubDetector::SetupGeometry(airId, kaptionId);
+}
+
+//____________________________________________________________________
+void 
+AliFMD2::Geometry(const char* mother, Int_t pbRotId, 
+                 Int_t idRotId, Double_t z) 
+{
+  z = fDz + fOuterZ;
+  AliFMDSubDetector::Geometry("FMD2", pbRotId, idRotId, z);
+  gMC->Gspos("FMD2", 1, mother, 0, 0, z, fRotationId);  
+}
+
+  
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMD2.h b/FMD/AliFMD2.h
new file mode 100644 (file)
index 0000000..502977c
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- mode: C++ -*-
+//
+// $Id$
+//
+#ifndef ALIFMD2_H
+#define ALIFMD2_H
+
+#ifndef ALIFMDSUBDETECTOR_H
+# include "AliFMDSubDetector.h"
+#endif
+
+class AliFMD2 : public AliFMDSubDetector 
+{
+private:
+  Int_t    fVolumeId;
+  Double_t fDz;
+public:
+  AliFMD2();
+  virtual ~AliFMD2();
+  virtual void   SetupGeometry(Int_t airId, Int_t kaptionId);  
+  virtual void   Geometry(const char* mother, Int_t pbRotId, 
+                         Int_t idRotId, Double_t z=0);
+  ClassDef(AliFMD2,1); // Geometry of FMD2 
+};
+
+#endif
+//
+// EOF
+//
diff --git a/FMD/AliFMD3.cxx b/FMD/AliFMD3.cxx
new file mode 100644 (file)
index 0000000..372d3aa
--- /dev/null
@@ -0,0 +1,89 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//                                                                          
+// Concrete implementation of AliFMDSubDetector 
+//
+// This implements the geometry for FMD3
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef ALIFMD3_H
+# include "AliFMD3.h"
+#endif 
+#ifndef ROOT_TVirtualMC
+# include <TVirtualMC.h>
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMD3);
+
+//____________________________________________________________________
+AliFMD3::AliFMD3() 
+  : AliFMDSubDetector(3) 
+{}
+
+//____________________________________________________________________
+AliFMD3::~AliFMD3() 
+{}
+
+//____________________________________________________________________
+void 
+AliFMD3::SetupGeometry(Int_t airId, Int_t kaptionId) 
+{
+  fInnerHoneyLowR  = fInner->GetLowR() + 1;
+  fInnerHoneyHighR = fInner->GetHighR() + 1;
+  fOuterHoneyLowR  = fOuter->GetLowR() + 1;
+  fOuterHoneyHighR = fOuter->GetHighR() + 1;
+
+  Double_t par[3];
+  par[0] = fInner->GetLowR();
+  par[1] = fOuterHoneyHighR;
+  par[2] = fDz = (TMath::Abs(fInnerZ - fOuterZ) 
+                 + fInner->GetSiThickness() 
+                 + fInner->GetPrintboardThickness() 
+                 + fInner->GetLegLength() 
+                 + fInner->GetModuleSpacing() 
+                 + fHoneycombThickness) / 2;
+  fVolumeId = gMC->Gsvolu("FMD3", "TUBE", airId, par, 3);
+
+  gMC->Matrix(fRotationId, 90, 0, 90, 90, 0, 0); 
+  //0, 180, 90, 90, 180, 0);
+
+  AliFMDSubDetector::SetupGeometry(airId, kaptionId);
+}
+
+//____________________________________________________________________
+void 
+AliFMD3::Geometry(const char* mother, Int_t pbRotId, 
+                 Int_t idRotId, Double_t z) 
+{
+  z = fInnerZ - fDz;
+  gMC->Gspos("FMD3", 1, mother, 0, 0, z, fRotationId);
+  
+  AliFMDSubDetector::Geometry("FMD3", pbRotId, idRotId, z);
+}
+
+  
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMD3.h b/FMD/AliFMD3.h
new file mode 100644 (file)
index 0000000..bbea3e3
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- mode: C++ -*-
+//
+// $Id$
+//
+#ifndef ALIFMD3_H
+#define ALIFMD3_H
+
+#ifndef ALIFMDSUBDETECTOR_H
+# include "AliFMDSubDetector.h"
+#endif
+
+class AliFMD3 : public AliFMDSubDetector 
+{
+private:
+  Int_t    fVolumeId;
+  Double_t fDz;
+public:
+  AliFMD3();
+  virtual ~AliFMD3();
+  virtual void   SetupGeometry(Int_t airId, Int_t kaptionId);  
+  virtual void   Geometry(const char* mother, Int_t pbRotId, 
+                         Int_t idRotId, Double_t z=0);
+  ClassDef(AliFMD3,1); // Geometry of FMD3 
+};
+
+#endif
+//
+// EOF
+//
diff --git a/FMD/AliFMDDigit.cxx b/FMD/AliFMDDigit.cxx
new file mode 100644 (file)
index 0000000..f7c1e4d
--- /dev/null
@@ -0,0 +1,218 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////
+//
+//  Digits classes for the FMD                
+//
+//  Digits consists of
+//   - Detector #
+//   - Ring ID                                             
+//   - Sector #     
+//   - Strip #
+//   - ADC count in this channel                                  
+//
+//  Digits consists of
+//   - Detector #
+//   - Ring ID                                             
+//   - Sector #     
+//   - Strip #
+//   - Total energy deposited in the strip
+//   - ADC count in this channel                                  
+//
+// As the Digits and SDigits have so much in common, the classes
+// AliFMDDigit and AliFMDSDigit are implemented via a base
+// class AliFMDBaseDigit.
+///
+//              +-----------------+
+//              | AliFMDBaseDigit |
+//              +-----------------+
+//                      ^
+//                      |
+//                +------------+
+//                |            |
+//      +-------------+ +--------------+
+//      | AliFMDDigit |        | AliFMDSDigit |
+//      +-------------+        +--------------+
+//
+// (Note, that I'd really would have liked to implement AliFMDHit as a
+// derived class from some base class - say AliFMDStrip, and the Digit
+// classes would (eventually) have derived from that as well.
+// However, ROOT doesn't do well with multiple inheritance, so I chose
+// not to anyway).
+//
+// Latest changes by Christian Holm Christensen
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifndef ALIFMDDIGIT_H
+# include "AliFMDDigit.h"
+#endif
+#ifndef __IOSTREAM__
+# include <iostream>
+#endif
+#ifndef __IOMANIP__
+# include <iomanip>
+#endif
+
+//====================================================================
+ClassImp(AliFMDBaseDigit);
+
+//____________________________________________________________________
+AliFMDBaseDigit::AliFMDBaseDigit()
+  : fDetector(0), 
+    fRing('\0'), 
+    fSector(0), 
+    fStrip(0)
+{}
+
+//____________________________________________________________________
+AliFMDBaseDigit::AliFMDBaseDigit(UShort_t detector, 
+                        Char_t   ring, 
+                        UShort_t sector, 
+                        UShort_t strip)
+  : fDetector(detector), 
+    fRing(ring), 
+    fSector(sector), 
+    fStrip(strip)
+{
+  //
+  // Creates a base data digit object
+  //
+  // Parameters 
+  //
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+}
+
+//____________________________________________________________________
+void
+AliFMDBaseDigit::Print(Option_t* /* option*/) const 
+{
+  // Print digit to standard out 
+  std::cout << ClassName() << ": FMD" << fDetector << fRing << "[" 
+           << std::setw(3) << fSector << ","
+           << std::setw(3) << fStrip << "]" 
+           << std::endl;
+}
+
+//====================================================================
+ClassImp(AliFMDDigit);
+
+//____________________________________________________________________
+AliFMDDigit::AliFMDDigit()
+  : fCount1(0),
+    fCount2(-1),
+    fCount3(-1)
+{}
+
+//____________________________________________________________________
+AliFMDDigit::AliFMDDigit(UShort_t detector, 
+                        Char_t   ring, 
+                        UShort_t sector, 
+                        UShort_t strip, 
+                        UShort_t count1,
+                        Short_t  count2, 
+                        Short_t  count3)
+  : AliFMDBaseDigit(detector, ring, sector, strip), 
+    fCount1(count1),
+    fCount2(count2),
+    fCount3(count3)
+{
+  //
+  // Creates a real data digit object
+  //
+  // Parameters 
+  //
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+  //    count1    ADC count (a 10-bit word)
+  //    count2    ADC count (a 10-bit word) -1 if not used
+  //    count3    ADC count (a 10-bit word) -1 if not used
+}
+
+//____________________________________________________________________
+void
+AliFMDDigit::Print(Option_t* /* option*/) const 
+{
+  // Print digit to standard out 
+  AliFMDBaseDigit::Print();
+  std::cout << "\t" 
+           << fCount1 << " (+ " << fCount2 << " + " << fCount2 << ") = " 
+           << Counts() << std::endl;
+}
+
+//====================================================================
+ClassImp(AliFMDSDigit);
+
+//____________________________________________________________________
+AliFMDSDigit::AliFMDSDigit()
+  : fEdep(0), 
+    fCount1(0),
+    fCount2(-1),
+    fCount3(-1)
+{}
+
+//____________________________________________________________________
+AliFMDSDigit::AliFMDSDigit(UShort_t detector, 
+                          Char_t   ring, 
+                          UShort_t sector, 
+                          UShort_t strip, 
+                          Float_t  edep,
+                          UShort_t count1,
+                          Short_t  count2, 
+                          Short_t  count3)
+  : AliFMDBaseDigit(detector, ring, sector, strip), 
+    fEdep(edep),
+    fCount1(count1),
+    fCount2(count2),
+    fCount3(count3)
+{
+  //
+  // Creates a real data digit object
+  //
+  // Parameters 
+  //
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+  //    edep      Total energy deposited 
+  //    count1    ADC count (a 10-bit word)
+  //    count2    ADC count (a 10-bit word) -1 if not used
+  //    count3    ADC count (a 10-bit word) -1 if not used
+}
+
+//____________________________________________________________________
+void
+AliFMDSDigit::Print(Option_t* /* option*/) const 
+{
+  // Print digit to standard out 
+  AliFMDBaseDigit::Print();
+  std::cout << "\t" << fEdep << " -> "
+           << fCount1 << " (+ " << fCount2 << " + " << fCount2 << ") = " 
+           << Counts() << std::endl;
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDDigit.h b/FMD/AliFMDDigit.h
new file mode 100644 (file)
index 0000000..cc4a2d0
--- /dev/null
@@ -0,0 +1,111 @@
+// -*- mode: c++ -*- 
+#ifndef ALIFMDDIGIT_H
+#define ALIFMDDIGIT_H
+
+//////////////////////////////////////////////////////////////////////
+//
+//  Digits classes for the FMD                
+//
+//////////////////////////////////////////////////////////////////////
+#ifndef ROOT_TObject
+# include <TObject.h>
+#endif
+
+//____________________________________________________________________
+class AliFMDBaseDigit : public TObject 
+{
+protected:
+  UShort_t fDetector;  // (Sub) Detector # (1,2, or 3)
+  Char_t   fRing;      // Ring ID ('I' or 'O')
+  UShort_t fSector;    // Sector # (phi division)
+  UShort_t fStrip;     // Strip # (radial division)
+public: 
+  AliFMDBaseDigit();
+  AliFMDBaseDigit(UShort_t detector, 
+                 Char_t   ring='\0', 
+                 UShort_t sector=0, 
+                 UShort_t strip=0);
+  virtual ~AliFMDBaseDigit() {}
+  UShort_t     Detector()         const { return fDetector; }
+  Char_t       Ring()             const { return fRing;     }
+  UShort_t     Sector()                   const { return fSector;   }
+  UShort_t     Strip()            const { return fStrip;    }
+  virtual void Print(Option_t* opt="") const;
+  ClassDef(AliFMDBaseDigit, 1) // Base class for FMD digits 
+};
+
+//____________________________________________________________________
+class AliFMDDigit : public AliFMDBaseDigit
+{
+protected:
+  UShort_t fCount1;     // Digital signal 
+  Short_t  fCount2;     // Digital signal (-1 if not used)
+  Short_t  fCount3;     // Digital signal (-1 if not used)
+public:
+  AliFMDDigit();
+  AliFMDDigit(UShort_t detector, 
+             Char_t   ring='\0', 
+             UShort_t sector=0, 
+             UShort_t strip=0, 
+             UShort_t count=0, 
+             Short_t  count2=-1, 
+             Short_t  count3=-1);
+  virtual ~AliFMDDigit() {}
+  UShort_t Count1()                const { return fCount1;   }
+  Short_t  Count2()                const { return fCount2;   }
+  Short_t  Count3()                const { return fCount3;   }
+  UShort_t Counts()                const;
+  void     Print(Option_t* opt="") const;
+  ClassDef(AliFMDDigit,1)     // Normal FMD digit
+};
+
+inline UShort_t 
+AliFMDDigit::Counts() const 
+{
+  return fCount1 
+    + (fCount2 >= 0 ? fCount2 : 0)
+    + (fCount3 >= 0 ? fCount3 : 0);
+}
+
+//____________________________________________________________________
+class AliFMDSDigit : public AliFMDBaseDigit
+{
+protected:
+  Float_t  fEdep;       // Energy deposited 
+  UShort_t fCount1;     // Digital signal 
+  Short_t  fCount2;     // Digital signal (-1 if not used)
+  Short_t  fCount3;     // Digital signal (-1 if not used)
+public:
+  AliFMDSDigit();
+  AliFMDSDigit(UShort_t detector, 
+              Char_t   ring='\0', 
+              UShort_t sector=0, 
+              UShort_t strip=0, 
+              Float_t  edep=0,
+              UShort_t count=0, 
+              Short_t  count2=-1, 
+              Short_t  count3=-1);
+  virtual ~AliFMDSDigit() {}
+  UShort_t Count1()                const { return fCount1;   }
+  Short_t  Count2()                const { return fCount2;   }
+  Short_t  Count3()                const { return fCount3;   }
+  Float_t  Edep()                  const { return fEdep;     }
+  UShort_t Counts()                const;
+  void     Print(Option_t* opt="") const;
+  ClassDef(AliFMDSDigit,1)     // Summable FMD digit
+};
+  
+inline UShort_t 
+AliFMDSDigit::Counts() const 
+{
+  return fCount1 
+    + (fCount2 >= 0 ? fCount2 : 0)
+    + (fCount3 >= 0 ? fCount3 : 0);
+}
+
+
+#endif
+//____________________________________________________________________
+//
+// EOF
+//
index 5f35ef5..a273ad3 100644 (file)
@@ -1,5 +1,5 @@
- /**************************************************************************
- * Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
  *                                                                        *
  * Author: The ALICE Off-line Project.                                    *
  * Contributors are mentioned in the code where appropriate.              *
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 
- //////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  Forward Multiplicity Detector based on Silicon plates                    //
-//  This class contains the procedures simulation ADC  signal for            //
-//  the Forward Multiplicity detector  : hits -> digits                      //
-//  ADC signal consists                                                      //
-//   - number of detector;                                                   //
-//   - number of ring;                                                       //
-//   - number of sector;                                                     //
-//   - ADC signal in this channel                                            //
-//                                                                           //
- //////////////////////////////////////////////////////////////////////////////
-
-#include <TTree.h> 
-#include <TVector.h>
-#include <TObjArray.h>
-#include <TFile.h>
-#include <TDirectory.h>
-#include <TRandom.h>
-
-
-#include "AliLog.h"
-#include "AliFMDDigitizer.h"
-#include "AliFMD.h"
-#include "AliFMDhit.h"
-#include "AliFMDdigit.h"
-#include "AliRunDigitizer.h"
-
-#include "AliRun.h"
-#include "AliLoader.h"
-#include "AliRunLoader.h"
-
-#include <stdlib.h>
-#include <Riostream.h>
-#include <Riostream.h>
-
-ClassImp(AliFMDDigitizer)
-
-//___________________________________________
-  AliFMDDigitizer::AliFMDDigitizer()  :AliDigitizer()
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  This class contains the procedures simulation ADC  signal for the
+//  Forward Multiplicity detector  : Hits->Digits and Hits->SDigits
+// 
+//  Digits consists of
+//   - Detector #
+//   - Ring ID                                             
+//   - Sector #     
+//   - Strip #
+//   - ADC count in this channel                                  
+//
+//  Digits consists of
+//   - Detector #
+//   - Ring ID                                             
+//   - Sector #     
+//   - Strip #
+//   - Total energy deposited in the strip
+//   - ADC count in this channel                                  
+//
+// As the Digits and SDigits have so much in common, the classes
+// AliFMDDigitizer and AliFMDSDigitizer are implemented via a base
+// class AliFMDBaseDigitizer.
+//
+//                 +---------------------+
+//                 | AliFMDBaseDigitizer |
+//                 +---------------------+
+//                           ^
+//                           |
+//                +----------+---------+
+//                |                    |
+//      +-----------------+     +------------------+
+//      | AliFMDDigitizer |    | AliFMDSDigitizer |
+//      +-----------------+    +------------------+
+//
+// These classes has several paramters: 
+//
+//     fPedestal
+//     fPedestalWidth
+//         (Only AliFMDDigitizer)
+//         Mean and width of the pedestal.  The pedestal is simulated
+//         by a Guassian, but derived classes my override MakePedestal
+//         to simulate it differently (or pick it up from a database).
+//
+//     fVA1MipRange
+//         The dymamic MIP range of the VA1_ALICE pre-amplifier chip 
+//
+//     fAltroChannelSize
+//         The largest number plus one that can be stored in one
+//         channel in one time step in the ALTRO ADC chip. 
+//
+//     fSampleRate
+//         How many times the ALTRO ADC chip samples the VA1_ALICE
+//         pre-amplifier signal.   The VA1_ALICE chip is read-out at
+//         10MHz, while it's possible to drive the ALTRO chip at
+//         25MHz.  That means, that the ALTRO chip can have time to
+//         sample each VA1_ALICE signal up to 2 times.  Although it's
+//         not certain this feature will be used in the production,
+//         we'd like have the option, and so it should be reflected in
+//         the code.
+//
+// The shaping function of the VA1_ALICE is given by 
+//
+//      f(x) = A(1 - exp(-Bx))
+//
+// Where A is a normalization constant, tuned so that the integral 
+//
+//      /1
+//      |           A(-1 + B + exp(-B))
+//      | f(x) dx = ------------------- = 1
+//      |                    B
+//      / 0
+//
+// and B is the a parameter defined by the shaping time (fShapingTime).  
+//
+// Solving the above equation, for A gives
+//
+//                 B
+//      A = ----------------
+//          -1 + B + exp(-B)
+//
+// So, if we define the function g: [0,1] -> [0:1] by 
+//
+//               / v
+//               |              Bu + exp(-Bu) - Bv - exp(-Bv) 
+//      g(u,v) = | f(x) dx = -A -----------------------------
+//               |                            B
+//               / u
+//
+// we can evaluate the ALTRO sample of the VA1_ALICE pre-amp between
+// any two times (u, v), by 
+//       
+//
+//                                B        Bu + exp(-Bu) - Bv - exp(-Bv)
+//      C = Q g(u,v) = - Q ---------------- -----------------------------
+//                        -1 + B + exp(-B)              B                  
+//
+//               Bu + exp(-Bu) - Bv - exp(-Bv) 
+//        = -  Q -----------------------------
+//                    -1 + B + exp(-B)
+//
+// Where Q is the total charge collected by the VA1_ALICE
+// pre-amplifier.   Q is then given by 
+//
+//           E S 
+//      Q =  - -
+//           e R
+//
+// where E is the total energy deposited in a silicon strip, R is the
+// dynamic range of the VA1_ALICE pre-amp (fVA1MipRange), e is the
+// energy deposited by a single MIP, and S ALTRO channel size in each
+// time step (fAltroChannelSize).  
+//
+// The energy deposited per MIP is given by 
+//
+//      e = M * rho * w 
+//
+// where M is the universal number 1.664, rho is the density of
+// silicon, and w is the depth of the silicon sensor. 
+//
+// The final ADC count is given by 
+//
+//      C' = C + P
+//
+// where P is the (randomized) pedestal (see MakePedestal)
+//
+// This class uses the class template AliFMDMap<Type> to make an
+// internal cache of the energy deposted of the hits.  The class
+// template is instantasized as 
+//
+//  typedef AliFMDMap<std::pair<Float_t, UShort_t> > AliFMDEdepMap;
+//
+// The first member of the values is the summed energy deposition in a
+// given strip, while the second member of the values is the number of
+// hits in a given strip.  Using the second member, it's possible to
+// do some checks on just how many times a strip got hit, and what
+// kind of error we get in our reconstructed hits.  Note, that this
+// information is currently not written to the digits tree.  I think a
+// QA (Quality Assurance) digit tree is better suited for that task.
+// However, the information is there to be used in the future. 
+//
+//
+// Latest changes by Christian Holm Christensen
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ROOT_TTree
+# include <TTree.h>
+#endif
+#ifndef ROOT_TRandom
+# include <TRandom.h>
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+#ifndef ALIFMDDIGITIZER_H
+# include "AliFMDDigitizer.h"
+#endif
+#ifndef ALIFMD_H
+# include "AliFMD.h"
+#endif
+#ifndef ALIFMDHIT_H
+# include "AliFMDHit.h"
+#endif
+#ifndef ALIFMDDIGIT_H
+# include "AliFMDDigit.h"
+#endif
+#ifndef ALIFMDDIGIT_H
+# include "AliFMDSDigit.h"
+#endif
+#ifndef ALIRUNDIGITIZER_H
+# include "AliRunDigitizer.h"
+#endif
+#ifndef ALIRUN_H
+# include "AliRun.h"
+#endif
+#ifndef ALILOADER_H
+# include "AliLoader.h"
+#endif
+#ifndef ALIRUNLOADER_H
+# include "AliRunLoader.h"
+#endif
+    
+//____________________________________________________________________
+ClassImp(AliFMDEdepMap);
+
+//====================================================================
+ClassImp(AliFMDBaseDigitizer);
+
+//____________________________________________________________________
+AliFMDBaseDigitizer::AliFMDBaseDigitizer()  
+  : fRunLoader(0)
 {
-// Default ctor - don't use it
-  ;
+  // Default ctor - don't use it
 }
 
-//___________________________________________
-AliFMDDigitizer::AliFMDDigitizer(AliRunDigitizer* manager) 
-    :AliDigitizer(manager) 
+//____________________________________________________________________
+AliFMDBaseDigitizer::AliFMDBaseDigitizer(AliRunDigitizer* manager) 
+  : AliDigitizer(manager, "AliFMDBaseDigitizer", "FMD Digitizer base class"), 
+    fRunLoader(0),
+    fEdep(kMaxDetectors, kMaxRings, kMaxSectors, kMaxStrips)
 {
-  // ctor which should be used
-  //  fDebug =0;
+  // Normal CTOR
   AliDebug(1," processed");
+  SetVA1MipRange();
+  SetAltroChannelSize();
+  SetSampleRate();
+  SetShapingTime();
 }
 
-//------------------------------------------------------------------------
-AliFMDDigitizer::~AliFMDDigitizer()
+//____________________________________________________________________
+AliFMDBaseDigitizer::AliFMDBaseDigitizer(const Char_t* name, 
+                                        const Char_t* title) 
+  : AliDigitizer(name, title),
+    fRunLoader(0),
+    fEdep(kMaxDetectors, kMaxRings, kMaxSectors, kMaxStrips)
 {
-// Destructor
+  // Normal CTOR
+  AliDebug(1," processed");
+  SetVA1MipRange();
+  SetAltroChannelSize();
+  SetSampleRate();
+  SetShapingTime();
+}
 
+//____________________________________________________________________
+AliFMDBaseDigitizer::~AliFMDBaseDigitizer()
+{
+  // Destructor
 }
 
- //------------------------------------------------------------------------
-Bool_t AliFMDDigitizer::Init()
+//____________________________________________________________________
+Bool_t 
+AliFMDBaseDigitizer::Init()
 {
-// Initialization
-// cout<<"AliFMDDigitizer::Init"<<endl;
- return kTRUE;
+  // Initialization
+  return kTRUE;
 }
  
 
-//---------------------------------------------------------------------
+//____________________________________________________________________
+void
+AliFMDBaseDigitizer::SumContributions(AliFMD* fmd) 
+{
+  // Sum energy deposited contributions from each hit in a cache
+  // (fEdep).  
+  if (!fRunLoader) 
+    Fatal("SumContributions", "no run loader");
+  
+  // Clear array of deposited energies 
+  fEdep.Clear();
+  
+  // Get the FMD loader 
+  AliLoader* inFMD = fRunLoader->GetLoader("FMDLoader");
+  // And load the hits 
+  inFMD->LoadHits("READ");
+  
+  // Get the tree of hits 
+  TTree* hitsTree = inFMD->TreeH();
+  if (!hitsTree)  {
+    // Try again 
+    inFMD->LoadHits("READ");
+    hitsTree = inFMD->TreeH();
+  }
+  
+  // Get the FMD branch 
+  TBranch* hitsBranch = hitsTree->GetBranch("FMD");
+  if (hitsBranch) fmd->SetHitsAddressBranch(hitsBranch);
+  else            AliFatal("Branch FMD hit not found");
+  
+  // Get a list of hits from the FMD manager 
+  TClonesArray *fmdHits = fmd->Hits();
+  
+  // Get number of entries in the tree 
+  Int_t ntracks  = Int_t(hitsTree->GetEntries());
+  
+  // Loop over the tracks in the 
+  for (Int_t track = 0; track < ntracks; track++)  {
+    // Read in entry number `track' 
+    hitsBranch->GetEntry(track);
+    
+    // Get the number of hits 
+    Int_t nhits = fmdHits->GetEntries ();
+    for (Int_t hit = 0; hit < nhits; hit++) {
+      // Get the hit number `hit'
+      AliFMDHit* fmdHit = 
+       static_cast<AliFMDHit*>(fmdHits->UncheckedAt(hit));
+      
+      // Extract parameters 
+      UShort_t detector = fmdHit->Detector();
+      Char_t   ring     = fmdHit->Ring();
+      UShort_t sector   = fmdHit->Sector();
+      UShort_t strip    = fmdHit->Strip();
+      Float_t  edep     = fmdHit->Edep();
+      if (fEdep(detector, ring, sector, strip).first != 0)
+       AliDebug(1, Form("Double hit in %d%c(%d,%d)", 
+                        detector, ring, sector, strip));
+      
+      fEdep(detector, ring, sector, strip).first  += edep;
+      fEdep(detector, ring, sector, strip).second += 1;
+      // Add this to the energy deposited for this strip
+    }  // hit loop
+  } // track loop
+}
 
-void AliFMDDigitizer::Exec(Option_t * /*option*/)
+//____________________________________________________________________
+void
+AliFMDBaseDigitizer::DigitizeHits(AliFMD* fmd) const
 {
+  // For the stored energy contributions in the cache (fEdep), convert
+  // the energy signal to ADC counts, and store the created digit in
+  // the digits array (AliFMD::fDigits)
+  //
+  TArrayI counts(3);
+  for (UShort_t detector=1; detector <= 3; detector++) {
+    // Get pointer to subdetector 
+    AliFMDSubDetector* det = 0;
+    switch (detector) {
+    case 1: det = fmd->GetFMD1(); break;
+    case 2: det = fmd->GetFMD2(); break;
+    case 3: det = fmd->GetFMD3(); break;
+    }
+    if (!det) continue;
+    for (UShort_t ringi = 0; ringi <= 1; ringi++) {
+      // Get pointer to Ring
+      AliFMDRing* r = 0;
+      switch (ringi) {
+      case 0: if (det->GetInner()) r = det->GetInner(); break;
+      case 1: if (det->GetOuter()) r = det->GetOuter(); break;
+      }
+      if (!r) continue;
+      
+      // Get number of sectors 
+      UShort_t nSectors = UShort_t(360. / r->GetTheta());
+      // Loop over the number of sectors 
+      for (UShort_t sector = 0; sector < nSectors; sector++) {
+       // Get number of strips 
+       UShort_t nStrips = r->GetNStrips();
+       // Loop over the stips 
+       for (UShort_t strip = 0; strip < nStrips; strip++) {
+         counts.Reset(-1);
+         Float_t edep = fEdep(detector, r->GetId(), sector, strip).first;
+         ConvertToCount(edep, r->GetSiThickness(), fmd->GetSiDensity(), 
+                        counts);
+         AddDigit(fmd, detector, r->GetId(), sector, strip, 
+                  edep, UShort_t(counts[0]), 
+                  Short_t(counts[1]), Short_t(counts[2]));
+#if 0
+         // This checks if the digit created will give the `right'
+         // number of particles when reconstructed, using a naiive
+         // approach.  It's here only as a quality check - nothing
+         // else. 
+         CheckDigit(fEdep(detector, r->GetId(), sector, strip).first,
+                    fEdep(detector, r->GetId(), sector, strip).second,
+                    counts);
+#endif
+       } // Strip
+      } // Sector 
+    } // Ring 
+  } // Detector 
+}
 
-  /*
-   Conver hits to digits:
-   - number of detector;
-   - number of ring;
-   - number of sector;
-   - ADC signal in this channel
-  */
+//____________________________________________________________________
+Float_t
+AliFMDBaseDigitizer::ShapeIntegral(Float_t u, Float_t v) const
+{
+  // Calculates the integral 
+  // 
+  //      / v
+  //      |               Bu + exp(-Bu) - Bv - exp(-Bv) 
+  //      | f(x) dx = - A -----------------------------
+  //      |                             B
+  //      / u
+  // 
+  // of the shaping function of the VA1_ALICE between times u and v
+  //
+  //      f(x) = A(1 - exp(-Bx))
+  //
+  // where A is a normalization constant, tuned so that the integral 
+  //
+  //      /1
+  //      |                              B         
+  //      | f(x) dx = 1   =>  A = ----------------
+  //      |                      -1 + B + exp(-B)
+  //      / 0
+  //
+  // and B is the a parameter defined by the shaping time (fShapingTime).  
+  // 
+  // That is, the function return the value 
+  // 
+  //        Bu + exp(-Bu) - Bv - exp(-Bv) 
+  //      - -----------------------------
+  //               -1 + B + exp(-B)
+  // 
+  // u,v should lie in the interval [0,1], and u < v
+  if (u == 0 && v == 1) return 1;
+  Float_t B = fShapingTime;
+  
+  // Calculate the integral 
+  Float_t res = - ((B * u + TMath::Exp(-B * u) - B * v - TMath::Exp(-B * v)) /
+                (-1 + B + TMath::Exp(-B)));
+  return res;
+}
 
-  AliRunLoader *inRL, *outRL;//in and out Run Loaders
-  AliLoader *pInFMD, *pOutFMD;// in and out ITSLoaders
+//____________________________________________________________________
+void
+AliFMDBaseDigitizer::ConvertToCount(Float_t   edep, 
+                                   Float_t   siThickness, 
+                                   Float_t   siDensity, 
+                                   TArrayI&  counts) const
+{
+  // Put noise and make ADC signal
+  // This is calculated as the product 
+  // 
+  //   DeltaEmip * SiThickness * SiDensity / Number 
+  //
+  // Where 
+  //  
+  //   DeltaEmip     is the energy loss of a MIP 
+  //   SiThickness   is the thickness of the silicon 
+  //   SiDensity     is the Silicon density 
+  //   Number        is # of e^- per MIP
+  //
+  // Note: Need to check this is correct. 
+  // 
+  const Float_t mipI = 1.664 * siThickness * siDensity;
+  // const Float_t mipI = 1.664 * 0.04 * 2.33 / 22400; // = 6.923e-6;
+  
+  // Create a pedestal 
+  UShort_t ped = MakePedestal();
+  
+  Float_t convf = 1 / mipI * Float_t(fAltroChannelSize) / fVA1MipRange;
+  Int_t n = fSampleRate;
+  for (Ssiz_t i = 0; i < n;  i++) {
+    Float_t w = ShapeIntegral(Float_t(i)/n, Float_t(i+1)/n);
+    counts[i] = UShort_t(TMath::Min(w * edep * convf + ped, 
+                                   Float_t(fAltroChannelSize))); 
+  }
+}
 
-  outRL = AliRunLoader::GetRunLoader(fManager->GetOutputFolderName());
-  pOutFMD = outRL->GetLoader("FMDLoader");
 
+//====================================================================
+ClassImp(AliFMDDigitizer);
 
-  AliDebug(1," start...");
+//____________________________________________________________________
+AliFMDDigitizer::AliFMDDigitizer()  
+  : AliFMDBaseDigitizer()
+{
+  // Default ctor - don't use it
+}
 
+//____________________________________________________________________
+AliFMDDigitizer::AliFMDDigitizer(AliRunDigitizer* manager) 
+  : AliFMDBaseDigitizer(manager)
+{
+  // Normal CTOR
+  AliDebug(1," processed");
+  SetPedestal();
+}
 
-  Int_t volume, sector, ring, charge;
-  Float_t e;
-  Float_t de[10][50][520];
-  Int_t hit;
-  Int_t digit[5];
-  Int_t ivol, iSector, iRing;
-  for (Int_t i=0; i<10; i++)
-    for(Int_t j=0; j<50; j++)
-      for(Int_t ij=0; ij<520; ij++)
-     de[i][j][ij]=0;
-  Int_t numberOfRings[5]= {512,256,512,256,512};
-  Int_t numberOfSector[5] =  {20,40,20,40,20}; 
+//____________________________________________________________________
+void
+AliFMDDigitizer::Exec(Option_t*) 
+{
+  // Get the output manager 
+  TString outFolder(fManager->GetOutputFolderName());
+  AliRunLoader* out = 
+    AliRunLoader::GetRunLoader(outFolder.Data());
+  // Get the FMD output manager 
+  AliLoader* outFMD = out->GetLoader("FMDLoader");
+
+  // Get the input loader 
+  TString inFolder(fManager->GetInputFolderName(0));
+  fRunLoader = 
+    AliRunLoader::GetRunLoader(fManager->GetInputFolderName(0));
+  if (!fRunLoader) {
+    AliError("Can not find Run Loader for input stream 0");
+    return;
+  }
+  // Get the AliRun object 
+  if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
+
+  // Get the AliFMD object 
+  AliFMD* fmd = static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
+  if (!fmd) {
+    AliError("Can not get FMD from gAlice");
+    return;
+  }
+
+  Int_t nFiles= fManager->GetNinputs();
+  for (Int_t inputFile = 0; inputFile < nFiles; inputFile++) {
+    AliDebug(1,Form(" Digitizing event number %d",
+                   fManager->GetOutputEventNr()));
+    // Get the current loader 
+    fRunLoader = 
+      AliRunLoader::GetRunLoader(fManager->GetInputFolderName(inputFile));
+    if (!fRunLoader) Fatal("Exec", "no run loader");
+    // Cache contriutions 
+    SumContributions(fmd);
+  }
+  // Digitize the event 
+  DigitizeHits(fmd);
+
+  // Load digits from the tree 
+  outFMD->LoadDigits("update");
+  // Get the tree of digits 
+  TTree* digitTree = outFMD->TreeD();
+  if (!digitTree) {
+    outFMD->MakeTree("D");
+    digitTree = outFMD->TreeD();
+  }
+  digitTree->Reset();
+  // Make a branch in the tree 
+  TClonesArray* digits = fmd->Digits();
+  fmd->MakeBranchInTree(digitTree, fmd->GetName(), &(digits), 4000, 0);
+  // TBranch* digitBranch = digitTree->GetBranch(fmd->GetName());
+  // Fill the tree 
+  digitTree->Fill();
   
-  AliFMDhit *fmdHit=0;
-  TTree *tH=0;
-  TBranch *brHits=0;
-  TBranch *brD=0;
+  // Write the digits to disk 
+  outFMD->WriteDigits("OVERWRITE");
+  outFMD->UnloadHits();
+  outFMD->UnloadDigits();
 
-  inRL = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(0));
+  // Reset the digits in the AliFMD object 
+  fmd->ResetDigits();
+}
 
-  if (inRL == 0x0)
-    {
-      AliError("Can not find Run Loader for input stream 0");
-      return;
-    }
 
-  if (!inRL->GetAliRun()) inRL->LoadgAlice();
+//____________________________________________________________________
+UShort_t
+AliFMDDigitizer::MakePedestal() const 
+{
+  return UShort_t(TMath::Max(gRandom->Gaus(fPedestal, fPedestalWidth), 0.));
+}
 
-  AliFMD * fFMD = (AliFMD *) inRL->GetAliRun()->GetDetector("FMD");
+//____________________________________________________________________
+void
+AliFMDDigitizer::AddDigit(AliFMD*  fmd,
+                         UShort_t detector, 
+                         Char_t   ring,
+                         UShort_t sector, 
+                         UShort_t strip, 
+                         Float_t  /* edep */, 
+                         UShort_t count1, 
+                         Short_t  count2, 
+                         Short_t  count3) const
+{
+  fmd->AddDigit(detector, ring, sector, strip, count1, count2, count3);
+}
 
-  if (fFMD == 0x0)
-   {
-     AliError("Can not get FMD from gAlice");
-     return;
-   }
-// Loop over files to digitize
+//____________________________________________________________________
+void
+AliFMDDigitizer::CheckDigit(Float_t         /* edep */, 
+                           UShort_t        nhits,
+                           const TArrayI&  counts) 
+{
+  Int_t integral = counts[0];
+  if (counts[1] >= 0) integral += counts[1];
+  if (counts[2] >= 0) integral += counts[2];
+  integral -= Int_t(fPedestal + 2 * fPedestalWidth);
+  if (integral < 0) integral = 0;
+  
+  Float_t convf = Float_t(fVA1MipRange) / fAltroChannelSize;
+  Float_t mips  = integral * convf;
+  if (mips > Float_t(nhits) + .5 || mips < Float_t(nhits) - .5) 
+    Warning("CheckDigit", "Digit -> %4.2f MIPS != %d +/- .5 hits", 
+           mips, nhits);
+}
 
-  Int_t nFiles=GetManager()->GetNinputs();
-  for (Int_t inputFile=0; inputFile<nFiles;inputFile++) 
-   {
+//====================================================================
+ClassImp(AliFMDSDigitizer);
 
-  AliDebug(1,Form(" Digitizing event number %d",fManager->GetOutputEventNr()));
-    if (fFMD)
-     {
+//____________________________________________________________________
+AliFMDSDigitizer::AliFMDSDigitizer()  
+{
+  // Default ctor - don't use it
+}
 
-      inRL = AliRunLoader::GetRunLoader(fManager->GetInputFolderName(inputFile));
-      pInFMD = inRL->GetLoader("FMDLoader");
-      pInFMD->LoadHits("READ");
-      
-      
-      tH = pInFMD->TreeH();
-      if (tH == 0x0)
-       {
-         pInFMD->LoadHits("read");
-         tH = pInFMD->TreeH();
-       }
-      brHits = tH->GetBranch("FMD");
-      if (brHits) {
-          fFMD->SetHitsAddressBranch(brHits);
-      }else{
-        AliFatal("Branch FMD hit not found");
-      }
-      TClonesArray *fFMDhits = fFMD->Hits ();
-      
-      Int_t ntracks    = (Int_t) tH->GetEntries();
+//____________________________________________________________________
+AliFMDSDigitizer::AliFMDSDigitizer(const Char_t* headerFile, 
+                                  const Char_t* /* sdigfile */)
+  : AliFMDBaseDigitizer("FMDSDigitizer", "FMD SDigitizer")
+{
+  // Normal CTOR
+  AliDebug(1," processed");
 
-      for (Int_t track = 0; track < ntracks; track++)
-       {
-         brHits->GetEntry(track);
-         Int_t nhits = fFMDhits->GetEntries ();
+  fRunLoader = AliRunLoader::GetRunLoader(); // Open(headerFile);
+  if (!fRunLoader) 
+    Fatal("AliFMDSDigitizer", "cannot open session, header file '%s'",
+         headerFile);
+  AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
+  if (!loader) 
+    Fatal("AliFMDSDigitizer", "cannot find FMD loader in specified event");
 
-         for (hit = 0; hit < nhits; hit++)
-           {
-             fmdHit = (AliFMDhit *) fFMDhits->UncheckedAt(hit);
+  // Add task to tasks folder 
+  loader->PostSDigitizer(this);
+}
 
-             volume = fmdHit->Volume ();
-             sector = fmdHit->NumberOfSector ();
-             ring = fmdHit->NumberOfRing ();
-             e = fmdHit->Edep ();
-             de[volume][sector][ring] += e;
+//____________________________________________________________________
+AliFMDSDigitizer::~AliFMDSDigitizer() 
+{
+  AliLoader* loader = fRunLoader->GetLoader("FMDLoader");
+  loader->CleanSDigitizer();
+}
 
-           }          //hit loop
-       }               //track loop
-    }               
-//if FMD
-   }
+//____________________________________________________________________
+void
+AliFMDSDigitizer::Exec(Option_t*) 
+{
+  // Get the output manager 
+  if (!fRunLoader) {
+    Error("Exec", "Run loader is not set");
+    return;
+  }
+  if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
+  if (!fRunLoader->TreeE())     fRunLoader->LoadHeader();
+  
+  AliLoader* fmdLoader = fRunLoader->GetLoader("FMDLoader");
+  if (!fmdLoader) Fatal("Exec", "no FMD loader");
+  
+  // Get the AliFMD object 
+  AliFMD* fmd = 
+    static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
+  if (!fmd) {
+    AliError("Can not get FMD from gAlice");
+    return;
+  }
+
+  Int_t nEvents = Int_t(fRunLoader->TreeE()->GetEntries());
+  for (Int_t event = 0; event < nEvents; event++) {
+    AliDebug(1,Form(" Digitizing event number %d", event));
+    // Get the current loader 
+    fRunLoader->GetEvent(event);
+
+    if (!fmdLoader->TreeS()) fmdLoader->MakeTree("S");
+    // Make a branch
+    fmd->MakeBranch("S");
+    
+    // Cache contriutions 
+    SumContributions(fmd);
+
+    // Digitize the event 
+    DigitizeHits(fmd);
+
+    fmdLoader->TreeS()->Reset();
+    fmdLoader->TreeS()->Fill();
+    fmdLoader->WriteSDigits("OVERWRITE");
+  }
+}
 
-  // Put noise and make ADC signal
-   Float_t mipI = 1.664 * 0.04 * 2.33 / 22400;     // = 6.923e-6;
-   for ( ivol=1; ivol<=5; ivol++){
-     for ( iSector=1; iSector<=numberOfSector[ivol-1]; iSector++){
-       for ( iRing=1; iRing<=numberOfRings[ivol-1]; iRing++){
-         digit[0]=ivol;
-         digit[1]=iSector;
-         digit[2]=iRing;
-         charge = Int_t (de[ivol][iSector][iRing] / mipI);
-         Int_t pedestal=Int_t(gRandom->Gaus(500,250));
-  //       digit[3]=PutNoise(charge);
-         digit[3]=charge + pedestal;
-         if(digit[3]<= 500) digit[3]=500; 
-    //dynamic range from MIP(0.155MeV) to 30MIP(4.65MeV)
-    //1024 ADC channels 
-         Float_t channelWidth=(22400*50)/1024;
-         digit[4]=Int_t(digit[3]/channelWidth);
-         if (digit[4]>1024) digit[4]=1024; 
-         fFMD->AddDigit(digit);
-       } //ivol
-     } //iSector
-   } //iRing
-
-   pOutFMD->LoadDigits("update");
-   TTree* treeD = pOutFMD->TreeD();
-
-   if (treeD == 0x0) {
-     pOutFMD->MakeTree("D");
-     treeD = pOutFMD->TreeD();
-
-   }
-
-   treeD->Reset();
-   fFMD->MakeBranchInTreeD(treeD);
-   brD = treeD->GetBranch("FMD");
-
-
-   treeD->Fill();
-
-   pOutFMD->WriteDigits("OVERWRITE");
-   pOutFMD->UnloadHits();
-   pOutFMD->UnloadDigits();
-   fFMD->ResetDigits();
+//____________________________________________________________________
+void
+AliFMDSDigitizer::AddDigit(AliFMD*  fmd,
+                          UShort_t detector, 
+                          Char_t   ring,
+                          UShort_t sector, 
+                          UShort_t strip, 
+                          Float_t  edep, 
+                          UShort_t count1, 
+                          Short_t  count2, 
+                          Short_t  count3) const
+{
+  fmd->AddSDigit(detector, ring, sector, strip, edep, count1, count2, count3);
 }
+
+
+
+//____________________________________________________________________
+//
+// EOF
+// 
 
 
 
index 028d88c..bbcb1e9 100644 (file)
+// -*- mode: c++ -*-
 #ifndef ALIFMDDIGITIZER_H
 #define ALIFMDDIGITIZER_H
-/* Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
-
-#include <AliDigitizer.h>
-#include <AliRunDigitizer.h>
+/* Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * See cxx source for full Copyright notice                               
+ */
+#ifndef ALIDIGITIZER_H
+# include <AliDigitizer.h>
+#endif
+#ifndef ALIRUNDIGITIZER_H
+# include <AliRunDigitizer.h>
+#endif
+#ifndef ALIFMDMAP_H
+# include <AliFMDMap.h>
+#endif
+#ifndef __UTILITY__
+# include <utility>
+#endif
+// #ifndef ROOT_TArrayF
+// # include <TArrayF.h>
+// #endif
 
+//====================================================================
 class TClonesArray;
-class AliFMDDigitizer : public AliDigitizer {
- public:
-  
-  AliFMDDigitizer();
-  AliFMDDigitizer(AliRunDigitizer * manager);
-  virtual ~AliFMDDigitizer();
-  virtual Bool_t Init();
+class AliFMD;
+class AliLoader;
+class AliRunLoader;
+
+typedef AliFMDMap<std::pair<Float_t, UShort_t> > AliFMDEdepMap;
+
+//====================================================================
+class AliFMDBaseDigitizer : public AliDigitizer 
+{
+public:
+  AliFMDBaseDigitizer();
+  AliFMDBaseDigitizer(AliRunDigitizer * manager);
+  AliFMDBaseDigitizer(const Char_t* name, const Char_t* title);
+  virtual ~AliFMDBaseDigitizer();
    
-  
   // Do the main work
-  void Exec(Option_t* option=0) ;
-  Int_t PutNoise(Int_t charge) {return (Int_t)(gRandom->Gaus(charge,500));}
-  TClonesArray *Digits() const {return fDigits;}
-  TClonesArray *Hits() const {return fHits;}
+  virtual Bool_t Init();
+
+  // Extra member functions 
+  void     SetVA1MipRange(UShort_t r=20) { fVA1MipRange = r; }
+  void     SetAltroChannelSize(UShort_t s=1024) { fAltroChannelSize = s;}
+  void     SetSampleRate(UShort_t r=1) { fSampleRate = (r>2 ? 2 : r); }
+  void     SetShapingTime(Float_t t=10) { fShapingTime = t;  }
+  
+  UShort_t GetVA1MipRange()      const { return fVA1MipRange; }
+  UShort_t GetAltroChannelSize() const { return fAltroChannelSize; }
+  UShort_t GetSampleRate()       const { return fSampleRate; }
+  Float_t  GetShapingTime()      const { return fShapingTime; }
+protected:
+  virtual void     SumContributions(AliFMD* fmd);
+  virtual void     DigitizeHits(AliFMD* fmd) const;
+  virtual void     ConvertToCount(Float_t   edep, 
+                                 Float_t   siThickness, 
+                                 Float_t   siDensity, 
+                                 TArrayI&  counts) const;
+  virtual UShort_t MakePedestal() const { return 0; }
+  virtual Float_t  ShapeIntegral(Float_t u, Float_t v) const;
+  virtual void     AddNoise(TArrayI&) const {}
+  virtual void     AddDigit(AliFMD*  /* fmd      */,
+                           UShort_t /* detector */, 
+                           Char_t   /* ring     */,
+                           UShort_t /* sector   */, 
+                           UShort_t /* strip    */, 
+                           Float_t  /* edep     */, 
+                           UShort_t /* count1   */, 
+                           Short_t  /* count2   */, 
+                           Short_t  /* count3   */) const {}
 
+  AliRunLoader* fRunLoader;
+  AliFMDEdepMap fEdep;             // Cache of Energy from hits 
+  UShort_t      fVA1MipRange;      // How many MIPs the pre-amp can do    
+  UShort_t      fAltroChannelSize; // Largest # to store in 1 ADC chan.
+  UShort_t      fSampleRate;       // Times the ALTRO samples pre-amp.
+  Float_t       fShapingTime;      // Shaping profile parameter
+  
+  enum { 
+    kMaxDetectors = 3, 
+    kMaxRings     = 2, 
+    kMaxSectors   = 20, 
+    kMaxStrips    = 512
+  };
+  ClassDef(AliFMDBaseDigitizer,0) // Base class for FMD digitizers
+};
+
+//====================================================================
+class AliFMDDigitizer : public AliFMDBaseDigitizer 
+{
+public:
+  AliFMDDigitizer();
+  AliFMDDigitizer(AliRunDigitizer * manager);
+  virtual ~AliFMDDigitizer() {}
+  virtual void  Exec(Option_t* option=0);
   
-  enum {kBgTag = -1};
-      
    
- private:
-  TClonesArray *fDigits;               // ! array with digits
-  TClonesArray *fHits;                 // List of hits
-  AliRunDigitizer* GetManager(){return fManager;}
-         
-    ClassDef(AliFMDDigitizer,0)
-};    
-#endif
+  // Extra member functions 
+  void     SetPedestal(Float_t mean=10, Float_t width=.5);
+  void     GetPedestal(Float_t& mean,   Float_t& width) const;
+protected:
+  virtual void     AddDigit(AliFMD*  fmd,
+                           UShort_t detector, 
+                           Char_t   ring,
+                           UShort_t sector, 
+                           UShort_t strip, 
+                           Float_t  edep, 
+                           UShort_t count1, 
+                           Short_t  count2, 
+                           Short_t  count3) const;
+  virtual UShort_t MakePedestal() const;
+  virtual void     CheckDigit(Float_t         edep, 
+                             UShort_t        nhits,
+                             const TArrayI&  counts);
+  Float_t       fPedestal;         // Mean of pedestal 
+  Float_t       fPedestalWidth;    // Width of pedestal 
+  ClassDef(AliFMDDigitizer,0) // Make Digits from Hits
+};
+//____________________________________________________________________
+inline void 
+AliFMDDigitizer::SetPedestal(Float_t mean, Float_t width) 
+{
+  fPedestal      = mean;
+  fPedestalWidth = width;
+}
+
+//____________________________________________________________________
+inline void 
+AliFMDDigitizer::GetPedestal(Float_t& mean, Float_t& width)  const
+{
+  mean  = fPedestal;
+  width = fPedestalWidth;
+}
 
 
+//====================================================================
+class AliFMDSDigitizer : public AliFMDBaseDigitizer 
+{
+public:
+  AliFMDSDigitizer();
+  AliFMDSDigitizer(const Char_t* headerFile, const Char_t* sdigFile="");
+  virtual ~AliFMDSDigitizer();
+  virtual void  Exec(Option_t* option=0);
+protected:
+  virtual void     AddDigit(AliFMD*  fmd,
+                           UShort_t detector, 
+                           Char_t   ring,
+                           UShort_t sector, 
+                           UShort_t strip, 
+                           Float_t  edep, 
+                           UShort_t count1, 
+                           Short_t  count2, 
+                           Short_t  count3) const;
+  ClassDef(AliFMDSDigitizer,0) // Make Summable Digits from Hits
+};
 
 
+
+#endif
+//____________________________________________________________________
+//
+// EOF
+//
+
diff --git a/FMD/AliFMDHit.cxx b/FMD/AliFMDHit.cxx
new file mode 100644 (file)
index 0000000..4b7826a
--- /dev/null
@@ -0,0 +1,127 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//  Hits in the FMD 
+//
+// Latest changes by Christian Holm Christensen
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef ALIFMDHIT_H
+# include "AliFMDHit.h"
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+#ifndef __IOSTREAM__
+# include <iostream>
+#endif
+#ifndef __IOMANIP__
+# include <iomanip>
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMDHit);
+
+
+//____________________________________________________________________
+AliFMDHit::AliFMDHit()
+  : fDetector(0), 
+    fRing(0), 
+    fSector(0), 
+    fStrip('\0'), 
+    fPx(0),
+    fPy(0),
+    fPz(0),
+    fPdg(0),
+    fEdep(0), 
+    fTime(0)
+{
+  fX = fY = fZ = 0;
+}
+  
+
+//____________________________________________________________________
+AliFMDHit::AliFMDHit(Int_t    shunt, 
+                    Int_t    track, 
+                    UShort_t detector, 
+                    Char_t   ring, 
+                    UShort_t sector, 
+                    UShort_t strip, 
+                    Float_t  x, 
+                    Float_t  y, 
+                    Float_t  z,
+                    Float_t  px, 
+                    Float_t  py, 
+                    Float_t  pz,
+                    Float_t  edep,
+                    Int_t    pdg,
+                    Float_t  t)
+  : AliHit(shunt, track),
+    fDetector(detector), 
+    fRing(ring), 
+    fSector(sector), 
+    fStrip(strip), 
+    fPx(px),
+    fPy(py),
+    fPz(pz),
+    fPdg(pdg),
+    fEdep(edep), 
+    fTime(t)
+{
+  // Normal FMD hit ctor
+  // 
+  // Parameters:
+  // 
+  //    shunt     ???
+  //    track    Track #
+  //    detector  Detector # (1, 2, or 3)                      
+  //    ring     Ring ID ('I' or 'O')
+  //    sector   Sector # (For inner/outer rings: 0-19/0-39)
+  //    strip    Strip # (For inner/outer rings: 0-511/0-255)
+  //    x        Track's X-coordinate at hit
+  //    y        Track's Y-coordinate at hit
+  //    z        Track's Z-coordinate at hit
+  //    px       X-component of track's momentum 
+  //    py       Y-component of track's momentum
+  //    pz       Z-component of track's momentum
+  //    edep     Energy deposited by track
+  //    pdg      Track's particle Id #
+  //    t        Time when the track hit 
+  // 
+  fX = x;
+  fY = y;
+  fZ = z;
+}
+
+//____________________________________________________________________
+void
+AliFMDHit::Print(Option_t* /* option */) const 
+{
+  // Print Hit to standard out 
+  std::cout << "AliFMDHit: FMD" 
+           << fDetector << fRing << "[" 
+           << std::setw(3) << fSector << ","
+           << std::setw(3) << fStrip << "] = " 
+           << fEdep << std::endl;
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
similarity index 58%
rename from FMD/AliFMDhit.h
rename to FMD/AliFMDHit.h
index 9db5671..e5bb73e 100644 (file)
@@ -1,14 +1,21 @@
+// -*- mode: c++ -*-
 #ifndef AliFMDhit_H
 #define AliFMDhit_H
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * See cxx source for full Copyright notice                               
+ */
 ////////////////////////////////////////////////
-//  Manager and hits classes for set:FMD     //
+//
+//  Manager and hits classes for set:FMD     
+//
 ////////////////////////////////////////////////
-#include "AliHit.h"
+#ifndef ALIHIT_H
+# include "AliHit.h"
+#endif
  
-class AliFMDhit : public AliHit {
+
 ///////////////////////////////////////////////////////////////////////
 // AliFMDhit is the hit class for the FMD. Hits are the information
 // that comes from a Monte Carlo at each step as a particle mass through
@@ -69,33 +76,58 @@ class AliFMDhit : public AliHit {
 //     The time of flight associated with the particle ending in this
 // hit. The time is typically measured from the point of creation of the
 // original particle (if this particle is a daughter).  The units
-// are those determined by the Monte Carlo.
+// are those determined by the Monte Carlo. 
 
-  
+class AliFMDHit : public AliHit 
+{
 public:
-  AliFMDhit() {}
-  AliFMDhit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits);
-  virtual ~AliFMDhit() {}
-  Int_t Volume() const {return fVolume;}
-  Int_t NumberOfSector() const {return fNumberOfSector;}
-  Int_t NumberOfRing() const {return fNumberOfRing;}
-  Float_t Particle() const {return fParticle;} 
-  Float_t Edep() const {return fEdep;}
-  Float_t Px() const {return fPx;}
-  Float_t Py() const {return fPy;}
-  Float_t Pz() const {return fPz;} 
-  Float_t Time() const {return fTime;}
+  AliFMDHit();
+  AliFMDHit(Int_t    shunt, 
+           Int_t    track, 
+           UShort_t detector, 
+           Char_t   ring, 
+           UShort_t sector, 
+           UShort_t strip, 
+           Float_t  x=0, 
+           Float_t  y=0, 
+           Float_t  z=0,
+           Float_t  px=0, 
+           Float_t  py=0, 
+           Float_t  pz=0,
+           Float_t  edep=0,
+           Int_t    pdg=0,
+           Float_t  t=0);
+  virtual ~AliFMDHit() {}
+
+  UShort_t Detector()  const { return fDetector; }
+  Char_t   Ring()      const { return fRing;     }
+  UShort_t Sector()    const { return fSector;   }
+  UShort_t Strip()     const { return fStrip;    }
+  Float_t  Edep()       const { return fEdep;     }
+  Float_t  Px()         const { return fPx;       }
+  Float_t  Py()         const { return fPy;       }
+  Float_t  Pz()         const { return fPz;       } 
+  Int_t    Pdg()        const { return fPdg;      }
+  Float_t  Time()       const { return fTime;     }
+  void     Print(Option_t* opt="") const;
+
+  void     SetEdep(Float_t edep) { fEdep = edep; }
 private:
-  Int_t      fVolume;       //Volume copy identifier
-  Int_t    fNumberOfSector;  //number of sector of hitted pad 
-  Int_t    fNumberOfRing;    //number of ring of  hitted pad
-  Int_t      fParticle;     //Particle identificator
-  Float_t    fEdep;         //Energy deposition
-  Float_t    fPx;            // Particle's momentum X
-  Float_t    fPy;            // Particle's momentum Y
-  Float_t    fPz;            // Particle's momentum Z
-  Float_t    fTime;         // Particle's time of flight
+  UShort_t fDetector;  // (Sub) Detector # (1,2, or 3)
+  Char_t   fRing;      // Ring ID ('I' or 'O')
+  UShort_t fSector;    // Sector # (phi division)
+  UShort_t fStrip;     // Strip # (radial division)
+  Float_t  fPx;        // Particle's X momentum X
+  Float_t  fPy;        // Particle's Y momentum Y
+  Float_t  fPz;        // Particle's Z momentum Z
+  Int_t    fPdg;       // Particles PDG code 
+  Float_t  fEdep;      // Energy deposition
+  Float_t  fTime;      // Particle's time of flight
 
-  ClassDef(AliFMDhit,1)  //Hits for detector FMD
+  ClassDef(AliFMDHit,1)  //Hits for detector FMD
 };
 #endif
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDMap.h b/FMD/AliFMDMap.h
new file mode 100644 (file)
index 0000000..b8efd3b
--- /dev/null
@@ -0,0 +1,135 @@
+// -*- mode: c++ -*-
+#ifndef ALIFMDMAP_H
+#define ALIFMDMAP_H
+/* Copyright(c) 1998-2000, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * See cxx source for full Copyright notice                               
+ */
+#ifndef __VECTOR__
+# include <vector>
+#endif 
+
+template <typename Type> 
+class AliFMDMap : public TObject 
+{
+private:
+  typedef std::vector<Type> ValueVector; // Type of container
+  ValueVector fValues;                   // Contained values
+  size_t      fMaxDetectors;             // Maximum # of detectors
+  size_t      fMaxRings;                 // Maximum # of rings
+  size_t      fMaxSectors;               // Maximum # of sectors
+  size_t      fMaxStrips;                // Maximum # of strips
+  
+  size_t CalcIndex(size_t det, Char_t ring, size_t sec, size_t str) const;
+public:
+  AliFMDMap(size_t maxDet=3, size_t maxRing=2, size_t maxSec=40, 
+           size_t maxStr=512);
+  virtual ~AliFMDMap() {}
+  void Clear();
+  Type& operator()(size_t det, Char_t ring, size_t sec, size_t str);
+  const Type& operator()(size_t det, Char_t ring, size_t sec, size_t str)const;
+  ClassDef(AliFMDMap, 0); // Map of FMD index's to values 
+};
+
+
+//____________________________________________________________________
+template <typename Type>
+inline 
+AliFMDMap<Type>::AliFMDMap(size_t maxDet, 
+                          size_t maxRing, 
+                          size_t maxSec, 
+                          size_t maxStr)
+  : fValues(maxDet * maxRing * maxSec * maxStr), 
+    fMaxDetectors(maxDet), 
+    fMaxRings(maxRing), 
+    fMaxSectors(maxSec), 
+    fMaxStrips(maxStr)
+{
+  // Construct a map
+  //
+  // Parameters:
+  //     maxDet       Maximum # of detectors
+  //     maxRinf      Maximum # of rings
+  //     maxSec       Maximum # of sectors
+  //     maxStr       Maximum # of strips
+}
+
+
+//____________________________________________________________________
+template <typename Type>
+inline size_t 
+AliFMDMap<Type>::CalcIndex(size_t det, Char_t ring, size_t sec, size_t str) const
+{
+  // Calculate index into storage from arguments. 
+  // 
+  // Parameters: 
+  //     det       Detector #
+  //     ring      Ring ID
+  //     sec       Sector # 
+  //     str       Strip # 
+  //
+  // Returns appropriate index into storage 
+  //
+  size_t ringi = (ring == 'I' ||  ring == 'i' ? 0 : 1);
+  size_t idx = 
+    (det + fMaxDetectors * (ringi + fMaxRings * (sec + fMaxSectors * str)));
+  if (idx >= fMaxDetectors * fMaxRings * fMaxSectors * fMaxStrips) {
+    Fatal("CalcIndex", "Index (%d,'%c',%d,%d) out of bounds, "
+         "in particular the %s index", 
+         det, ring, sec, str, 
+         (det >= fMaxDetectors ? "Detector" : 
+          (ringi >= fMaxRings ? "Ring" : 
+           (sec >= fMaxSectors ? "Sector" : "Strip"))));
+    return 0;
+  }
+  return idx;
+}
+
+//____________________________________________________________________
+template <typename Type>
+inline void
+AliFMDMap<Type>::Clear() 
+{
+  // Resets stored values to the default value for that type 
+  for (size_t i = 0; i < fValues.size(); ++i) fValues[i] = Type();
+}
+
+//____________________________________________________________________
+template <typename Type>
+inline Type& 
+AliFMDMap<Type>::operator()(size_t det, Char_t ring, size_t sec, size_t str)
+{
+  // Parameters: 
+  //     det       Detector #
+  //     ring      Ring ID
+  //     sec       Sector # 
+  //     str       Strip # 
+  //
+  // Returns data[det][ring][sec][str]
+  return fValues[CalcIndex(det, ring, sec, str)];
+}
+
+//____________________________________________________________________
+template <typename Type>
+inline const Type& 
+AliFMDMap<Type>::operator()(size_t det, Char_t ring, size_t sec, size_t str)const
+{
+  // Parameters: 
+  //     det       Detector #
+  //     ring      Ring ID
+  //     sec       Sector # 
+  //     str       Strip # 
+  //
+  // Returns data[det][ring][sec][str]
+  return fValues[CalcIndex(det, ring, sec, str)];
+}
+
+
+
+#endif 
+//
+// EOF
+//
+
+
diff --git a/FMD/AliFMDParticles.cxx b/FMD/AliFMDParticles.cxx
new file mode 100644 (file)
index 0000000..d82df4e
--- /dev/null
@@ -0,0 +1,93 @@
+//////////////////////////////////////////////////////////////////////
+//
+//  Forward Multiplicity Detector have to be reconstructed number of
+//  particles in fixed pseudorapidity interval from fNumOfMinRing
+//  to fNumOfMaxRing and phi interval from fNumOfMinSector to
+//  fNumOfMaxSector
+//
+//////////////////////////////////////////////////////////////////////
+#ifndef ALIFMDPARTICLES_H
+# include "AliFMDParticles.h"
+#endif
+#ifndef __IOSTREAM__
+# include <iostream>
+#endif
+#ifndef __IOMANIP__
+# include <iomanip>
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMDParticles)
+
+//____________________________________________________________________
+AliFMDParticles::AliFMDParticles()
+  : fDetector(0),
+    fRing('\0'),
+    fMinSector(0),
+    fMaxSector(0),
+    fMinStrip(0),
+    fMaxStrip(0),
+    fMinEta(0),
+    fMaxEta(0),
+    fMinPhi(0),
+    fMaxPhi(0),
+    fParticles(0),
+    fMethod(kNaive)
+{}
+
+//____________________________________________________________________
+AliFMDParticles::AliFMDParticles(UShort_t detector,  Char_t ring, 
+                                UShort_t minSector, UShort_t maxSector, 
+                                UShort_t minStrip,  UShort_t maxStrip, 
+                                Float_t  minEta,    Float_t  maxEta, 
+                                Float_t  minPhi,    Float_t  maxPhi,
+                                Float_t  particles, UShort_t method)
+  : fDetector(detector),
+    fRing(ring),
+    fMinSector(minSector),
+    fMaxSector(maxSector),
+    fMinStrip(minStrip),
+    fMaxStrip(maxStrip),
+    fMinEta(minEta),
+    fMaxEta(maxEta),
+    fMinPhi(minPhi),
+    fMaxPhi(maxPhi),
+    fParticles(particles),
+    fMethod(method)
+{
+  switch (fMethod) {
+  case kPoission: 
+  case kIterative: 
+  case kNaive:    
+    break;    
+  default:        
+    Warning("AliFMDParticles", "unknown method: %d", method);
+    break;
+  }
+}
+
+
+//____________________________________________________________________
+void
+AliFMDParticles::Print(Option_t* /* opt*/) const
+{
+  std::cout << "FMD Reconstructed particles: " << fParticles << "\n" 
+           << "  Detector:      FMD" << fDetector << fRing << "\n"
+           << "  Sector range:  [" << fMinSector << "," << fMaxSector << "\n"
+           << "  Strip range:   [" << fMinStrip << "," << fMaxStrip << "\n"
+           << "  Eta range:     [" << fMinEta << "," << fMaxEta << "\n"
+           << "  Phi range:     [" << fMinPhi << "," << fMaxPhi << "\n"
+           << "  Method:        " << std::flush;
+  switch (fMethod) {
+  case kPoission:  std::cout << "Poission"  << std::endl; break;
+  case kIterative: std::cout << "Iterative" << std::endl; break;
+  case kNaive:     std::cout << "Naive"     << std::endl; break; 
+  default:         std::cout << "Unknown"   << std::endl; break;
+  }
+}
+
+    
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDParticles.h b/FMD/AliFMDParticles.h
new file mode 100644 (file)
index 0000000..54f7460
--- /dev/null
@@ -0,0 +1,61 @@
+// -*- mode: c++ -*- 
+#ifndef ALIFMDPARTICLES_H
+#define ALIFMDPARTICLES_H
+
+/* Reconstracted Particles Class: has number of reconstructed
+ * particles in sectors from NumOfMinSector to NumberOfMaxSector()
+ * rings from NumOfMinRing to NumOfMaxRing for each FMDvolume
+ */
+#ifndef ROOT_TObject
+# include <TObject.h>
+#endif
+
+class AliFMDParticles: public TObject
+{
+public:
+  enum EMethod {
+    kPoission, 
+    kIterative, 
+    kNaive
+  };
+  
+  AliFMDParticles();
+  AliFMDParticles (UShort_t detector,  Char_t ring, 
+                  UShort_t minSector, UShort_t maxSector, 
+                  UShort_t minStrip,  UShort_t maxStrip, 
+                  Float_t  minEta,    Float_t  maxEta, 
+                  Float_t  minPhi,    Float_t  maxPhi,
+                  Float_t  particles, UShort_t method);
+  virtual ~AliFMDParticles(){};
+
+  UShort_t Detector() const        { return fDetector; }
+  Char_t   Ring() const            { return fRing; }
+  UShort_t MinSector() const       { return fMinSector; }
+  UShort_t MaxSector() const       { return fMaxSector; }
+  UShort_t MinStrip() const        { return fMinStrip; }
+  UShort_t MaxStrip() const        { return fMaxStrip; }
+  Float_t  MinEta() const          { return fMinEta; }
+  Float_t  MaxEta() const          { return fMaxEta; }
+  Float_t  MinPhi() const          { return fMinPhi; }
+  Float_t  MaxPhi() const          { return fMaxPhi; }
+  Float_t  Particles() const       { return fParticles; }
+  UShort_t Method() const          { return fMethod; }
+  
+  virtual void Print(Option_t* opt="") const;
+protected:
+  UShort_t fDetector;        // Detector #
+  Char_t   fRing;            // Ring ID
+  UShort_t fMinSector;       // First sector of this region
+  UShort_t fMaxSector;       // Last sector of this region
+  UShort_t fMinStrip;        // First strip of this region
+  UShort_t fMaxStrip;        // Second strip of this region  
+  Float_t  fMinEta;          // Least eta covered
+  Float_t  fMaxEta;          // Largest eta covered
+  Float_t  fMinPhi;          // Least phi covered
+  Float_t  fMaxPhi;          // Largest phi covered
+  Float_t  fParticles;       // Number of particles 
+  UShort_t fMethod;          // Method use to get fParticles
+
+  ClassDef(AliFMDParticles,2) // Reconstructed # or particles in a eta,phi region
+};
+#endif
diff --git a/FMD/AliFMDPolygon.cxx b/FMD/AliFMDPolygon.cxx
new file mode 100644 (file)
index 0000000..a3f6649
--- /dev/null
@@ -0,0 +1,287 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Utility class to help implement shape of the FMD modules
+//
+// Latest changes by Christian Holm Christensen
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef ALIFMDPOLYGON_H
+# include "AliFMDPolygon.h"
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+#ifndef ROOT_TString
+# include <TString.h>
+#endif
+#ifndef ROOT_TVector2
+# include <TVector2.h>
+#endif
+#ifndef ROOT_TCanvas
+# include <TCanvas.h>
+#endif
+#ifndef ROOT_TText
+# include <TText.h>
+#endif
+#ifndef ROOT_TGraph
+# include <TGraph.h>
+#endif
+#ifndef ROOT_TError
+# include <TError.h>
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMDPolygon);
+
+//____________________________________________________________________
+AliFMDPolygon::AliFMDPolygon()
+  : fState(kUnknown)
+{}
+
+//____________________________________________________________________
+AliFMDPolygon::~AliFMDPolygon() 
+{
+  fVerticies.Delete();
+}
+
+//____________________________________________________________________
+bool
+AliFMDPolygon::AddVertex(double x, double y) 
+{
+  // Add points in order to the polygon. 
+  TVector2* c = new TVector2(x,y);
+  return AddVertex(c);
+}
+//____________________________________________________________________
+bool
+AliFMDPolygon::AddVertex(TVector2* c) 
+{
+  // Add points in order to the polygon.
+  //
+  // Checks if the addition of the vertex makes the alipolygon
+  // concave, and if it does, returns false.  Note, that the check
+  // isn't performed until at least 3 verticies have already been
+  // added to the alipolygon (a triangle is always convex).
+  if (!c) return false;
+  if (fVerticies.GetEntries() >= 3) {
+    if (!IsOnLeftHand(c, fVerticies.GetEntries()-2,
+                     fVerticies.GetEntries()-1)) {
+      Error("AliFMDPolygon::AddVertex", 
+           "Adding vertex (%f,%f) makes alipolygon concave", 
+           c->X(), c->Y());
+      return false;
+    }
+  }
+  fState = kUnknown;
+  fVerticies.AddAtAndExpand(c, fVerticies.GetEntries());
+  return true;
+}
+
+//____________________________________________________________________
+const TVector2&
+AliFMDPolygon::GetVertex(size_t i) const
+{
+  // Get one of the verticies
+  if (i > size_t(fVerticies.GetEntries()))
+    Fatal("AliFMDPolygon::GetVertex", "Index %d out of range [0,%d]", 
+         i, fVerticies.GetEntries());
+  return *(static_cast<TVector2*>(fVerticies.At(i)));
+}
+
+//____________________________________________________________________
+bool
+AliFMDPolygon::Contains(const TVector2* c) const
+{
+  /* This function checks if a point is inside the polygon.  It does
+   * that by looping over the segments of the polygon, and decides
+   * wether the point is on the left-hand-side (LHS) of the segment.
+   * 
+   * Suppose we had the polygon and point 
+   *
+   *     2 x----x 1
+   *      /      \\
+   *    3 x   P   x 0
+   *      \\      /
+   *     4 x----x 5
+   * 
+   * Then, P is on LHS of the segment 0->1, 1->2, ..., and 5->0, and
+   * so inside the polygon.
+   * 
+   * Suppose instead the point was like
+   * 
+   *     2 x----x 1
+   *      /      \\    P
+   *    3 x       x 0
+   *      \\      /
+   *     4 x----x 5
+   * 
+   * Then it would still be on the LHS of the segments 1->2, 2->3,
+   * 3->4, 4->5, but on the right-hand-side of 5->0, and 0->1 and
+   * hence outside the polygon.
+   */ 
+  if (!c) return kFALSE;
+  if (fState == kUnknown) fState = (ConvexCheck() ? kConvex : kConcave);
+  if (fState == kConcave) return false;
+  size_t n = fVerticies.GetEntries();
+  for (size_t i = 0; i < n; ++i) 
+    if (!IsOnLeftHand(c, i, (i + 1) % n))
+      // If point is on the left hand side of the segment, it's
+      // outside the polygon.
+      return false;
+  return true;
+}
+
+//____________________________________________________________________
+bool
+AliFMDPolygon::Contains(double x, double y) const
+{
+  TVector2 c(x,y);
+  return Contains(&c);
+}
+
+//____________________________________________________________________
+bool
+AliFMDPolygon::ConvexCheck() const
+{
+  /* 
+   * This member function loops through the verticies, and checks if
+   * the next-to-next vertex is in between the current vertex and the
+   * next vertex.
+   * 
+   * Suppose we have the polygon 
+   *           
+   *     2 x----x 1
+   *      /      \\
+   *    3 x       x 0
+   *      \\      /
+   *     4 x----x 5
+   * 
+   * Then the vertex 2 is on the left-hand-side (LHS) of the segment
+   * 0->1, 3 is on the LHS of 1->2, ..., and 0 is on the RHS of 4->5,
+   * and so the polygon is convex.
+   * 
+   * If we had a polygon like
+   *
+   *     2 x----x 1
+   *        \\    \\
+   *       3 x    x 0
+   *        /     /
+   *     4 x----x 5
+   * 
+   * Then, the vertex 4 is NOT on the LHS of the segment 2->3, and so
+   * the polygon is NOT convex.
+   */
+  size_t n = fVerticies.GetEntries();
+  // A triangle is always convex. 
+  if (n <= 3) return true;
+  for (size_t i = 0; i < n; i++) {
+    // Get the next, and next-to-next indicies, taking care to go
+    // around the polygon.
+    size_t j = (i + 1) % n;
+    size_t k = (i + 2) % n;
+    // Check The next-to-next vertex is on the LHS of the current
+    // vertex and the next vertex 
+    if (!IsOnLeftHand(static_cast<TVector2*>(fVerticies.At(k)), i, j)) {
+      Error("AliFMDPolygon::ConvexCheck", 
+           "AliFMDPolygon is concave at segment %d -> %d" , i, j);
+      return false;
+    }
+  }
+  return true;
+}
+    
+//____________________________________________________________________
+bool
+AliFMDPolygon::IsOnLeftHand(const TVector2* c, size_t i1, size_t i2) const
+{
+  /* Check if a point is on the left-hand-side (LHS) or
+   * right-hand-side (RHS) of the segment defined by the two indicies.
+   * 
+   * Suppose we have the segment and point 
+   * 
+   *     1 x
+   *        \\    P
+   *         x 0  
+   *
+   * Then, we define the vectors 
+   *
+   *   v: 0->P 
+   *   u: perpendicular to 1->0 
+   * 
+   * The dot product of u and v is >= 0, meaning that the
+   * angle between the two vectors is in [0,pi], and so P is on the
+   * RHS of the segment
+   *
+   * Suppose we had 
+   *
+   *       1 x
+   *    P     \\    
+   *           x 0  
+   *
+   * And defining the vectors u,v as above.  In this case the dot
+   * product is less than 0, meaning the angle between u,v is in
+   * (pi,2pi], and so P is on the LHS of the segment
+   */
+  if (!c) return false;
+  const TVector2& v1 = GetVertex(i1);
+  const TVector2& v2 = GetVertex(i2);
+  double dot = (  (c->X()  - v1.X())  * (v2.Y() - v1.Y()) 
+               - (c->Y() - v1.Y()) * (v2.X()  - v1.X()));
+  return (dot < 0 ? true : false);
+}
+
+//____________________________________________________________________
+void
+AliFMDPolygon::Clear(Option_t*) 
+{
+  fState = kUnknown;
+  fVerticies.Delete();
+  // fVerticies.Resize(0);
+}
+
+//____________________________________________________________________
+void
+AliFMDPolygon::Draw(const char* option, const char* name) const 
+{
+  size_t n = fVerticies.GetEntries();
+  TGraph* g = new TGraph(n+1);
+  if (name) g->SetName(name);
+  g->SetMarkerStyle(20);
+  for (size_t i = 0; i < n; i++) {
+    const TVector2& v = GetVertex(i);
+    g->SetPoint(i, v.X(), v.Y());
+  }
+  const TVector2& v = GetVertex(0);
+  g->SetPoint(n, v.X(), v.Y());
+  g->Draw(option);
+  TString opt(option);
+  if (!opt.Contains("p", TString::kIgnoreCase))
+    return;
+  for (size_t i = 0; i < n; i++) {
+    const TVector2& v = GetVertex(i);
+    TText* t = new TText(v.X(), v.Y(), Form("%d", i));
+    t->Draw();
+  }
+}
+
+//____________________________________________________________________
+//
+// EOf
+//
diff --git a/FMD/AliFMDPolygon.h b/FMD/AliFMDPolygon.h
new file mode 100644 (file)
index 0000000..5884e05
--- /dev/null
@@ -0,0 +1,68 @@
+// -*- mode: C++ -*-
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+ *
+ * See cxx source for full Copyright notice                               
+ */
+#ifndef ALIFMDPOLYGON_H
+#define ALIFMDPOLYGON_H
+#ifndef ROOT_TVector2
+# include <TVector2.h>
+#endif
+#ifndef ROOT_TObjArray
+# include <TObjArray.h>
+#endif
+
+class AliFMDPolygon : public TObject 
+{
+private:
+  enum {
+    kUnknown, 
+    kConvex, 
+    kConcave
+  };
+  mutable Int_t fState;
+  // List of coordinates 
+  TObjArray fVerticies;
+  // Force convexity check 
+  bool ConvexCheck() const;
+  // Check if a point is at the right-hand side of a segment 
+  bool IsOnLeftHand(const TVector2* c, size_t i1, size_t i2) const;
+public:
+  // Construct a alipolygon with N sides
+  AliFMDPolygon();
+  virtual ~AliFMDPolygon();
+
+  // Clear the polygon 
+  void Clear(Option_t* option="");
+  
+  // Add a vertex 
+  bool AddVertex(TVector2* c);
+  bool AddVertex(double x, double y);
+
+  // Get a vertex point 
+  const TVector2& GetVertex(size_t i) const;
+  
+  // Check if a point is inside the polygon 
+  bool Contains(const TVector2* c) const;
+  bool Contains(double x, double y) const;
+  
+  // Get the number of verticies 
+  size_t GetNVerticies() const { return fVerticies.GetEntries(); }  
+  // Get the coordinates 
+  const TObjArray& GetVerticies() const { return fVerticies; }
+  
+  void Draw(const char* option="PL", const char* name=0) const;
+
+  ClassDef(AliFMDPolygon,1) // Polygon parameters
+};
+
+#endif
+//
+// EOF
+//
+
+  
+      
diff --git a/FMD/AliFMDRawStream.cxx b/FMD/AliFMDRawStream.cxx
new file mode 100644 (file)
index 0000000..c2c4e6c
--- /dev/null
@@ -0,0 +1,187 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////
+//                                                                          
+// Buffer to read RAW ALTRO FMD format from a AliRawReader 
+// 
+// Currently, I had to overload the Next member function and introduce
+// my own members fMyData, fMyPosition, fMyCount, and fMyBunchLength.
+// The reason is, that we can use the fMyCount to determine the
+// sampling rate used in the ALTRO.   However,
+// AliAltroBuffer::fCount is private, so we can not access it. 
+//
+// If it wasn't I'd implement Next as 
+//
+//     Bool_t
+//     AliFMDRawStreamer::Next()
+//     {
+//        if (AliAltroRawStreamer::Next()) {
+//          if (fPrevPad != fPad) 
+//             fSampleRate = (fCount - 2) / 128;
+//          return kTRUE;
+//        }
+//        return kFALSE;
+//     } 
+//
+//////////////////////////////////////////////////////////////////////
+#ifndef ALIFMDRAWSTREAM_H
+# include "AliFMDRawStream.h"
+#endif
+#ifndef ALIRAWREADER_H
+# include "AliRawReader.h"
+#endif
+#ifndef __IOSTREAM__
+# include <iostream>
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMDRawStream);
+
+//____________________________________________________________________
+AliFMDRawStream::AliFMDRawStream(AliRawReader* reader) 
+  : AliAltroRawStream(reader), 
+    // fMyData(0), 
+    // fMyPosition(0), 
+    // fMyCount(0),
+    //    fMyBunchLength(0), 
+    fPrevTime(-1)
+{}
+
+
+
+//_____________________________________________________________________________
+Bool_t 
+AliFMDRawStream::Next()
+{
+  // read the next raw digit
+  // returns kFALSE if there is no digit left
+  fPrevTime = fTime;
+  if (AliAltroRawStream::Next()) {
+    if (fPrevPad != fPad) {
+      fSampleRate = fTimeBunch / 128;
+#if 1
+      std::cout << "Setting Sample rate to (" << fTimeBunch << "/" 
+               << 128 << "=" << fSampleRate << std::endl;
+#endif
+    }
+    return kTRUE;
+  }
+  return kFALSE;
+}
+
+#if 0
+//_____________________________________________________________________________
+Bool_t 
+AliFMDRawStream::Next()
+{
+  // read the next raw digit
+  // returns kFALSE if there is no digit left
+  fPrevSector = fSector;
+  fPrevRow    = fRow;
+  fPrevPad    = fPad;
+  fPrevTime   = fTime;
+  
+  while (fMyCount == 0) {  // next trailer
+    if (fMyPosition <= 0) {  // next payload
+      do {
+        if (!fRawReader->ReadNextData(fMyData)) return kFALSE;
+      } while (fRawReader->GetDataSize() == 0);
+
+      fMyPosition = (fRawReader->GetDataSize() * 8) / 10;
+      while (Get10BitWord(fMyData, fMyPosition-1) == 0x2AA) fMyPosition--;
+    }
+
+    if (fMyPosition > 0) {
+      // read the trailer
+      if (fMyPosition <= 4) {
+        Error("Next", "could not read trailer");
+        return kFALSE;
+      }
+      fSector   = Get10BitWord(fMyData, --fMyPosition);
+      fRow      = Get10BitWord(fMyData, --fMyPosition);
+      fPad      = Get10BitWord(fMyData, --fMyPosition);
+      fMyCount  = Get10BitWord(fMyData, --fMyPosition);
+
+      fMyPosition -= (4 - (fMyCount % 4)) % 4;  // skip fill words
+      fMyBunchLength = 0;
+
+      // Set the sample rate, based on the number of samples in the
+      // channel. 
+      fSampleRate = (fMyCount - 2) / 128;
+#if 0
+      std::cout << "Setting Sample rate to (" << fMyCount << " - 2)/" 
+               << 128 << "=" << fSampleRate << std::endl;
+#endif
+    }
+  }
+
+  if (fMyBunchLength == 0) {
+    if (fMyPosition <= 0) {
+      Error("Next", "could not read bunch length");
+      return kFALSE;
+    }
+    fMyBunchLength = Get10BitWord(fMyData, --fMyPosition) - 2;
+    fMyCount--;
+    
+
+    if (fMyPosition <= 0) {
+      Error("Next", "could not read time bin");
+      return kFALSE;
+    }
+    fTime = Get10BitWord(fMyData, --fMyPosition);
+    fMyCount--;
+  } else {
+    fTime--;
+  }
+
+  if (fMyPosition <= 0) {
+    Error("Next", "could not read sample amplitude");
+    return kFALSE;
+  }
+  fSignal = Get10BitWord(fMyData, --fMyPosition);
+  fMyCount--;
+  fMyBunchLength--;
+
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+UShort_t 
+AliFMDRawStream::Get10BitWord(UChar_t* buffer, Int_t position) const
+{
+// return a word in a 10 bit array as an UShort_t
+
+  Int_t iBit = position * 10;
+  Int_t iByte = iBit / 8;
+  Int_t shift = iBit % 8;
+//  return ((buffer[iByte+1] * 256 + buffer[iByte]) >> shift) & 0x03FF;
+
+  // recalculate the byte numbers and the shift because
+  // the raw data is written as integers where the high bits are filled first
+  // -> little endian is assumed here !
+  Int_t iByteHigh = 4 * (iByte / 4) + 3 - (iByte % 4);
+  iByte++;
+  Int_t iByteLow  = 4 * (iByte / 4) + 3 - (iByte % 4);
+  shift = 6 - shift;
+  return ((buffer[iByteHigh] * 256 + buffer[iByteLow]) >> shift) & 0x03FF;
+}
+#endif 
+//_____________________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDRawStream.h b/FMD/AliFMDRawStream.h
new file mode 100644 (file)
index 0000000..c2fa594
--- /dev/null
@@ -0,0 +1,53 @@
+// -*- mode: c++ -*- 
+//
+// 
+#ifndef ALIFMDRAWSTREAM_H
+#define ALIFMDRAWSTREAM_H
+
+#ifndef ALIALTRORAWSTREAM_H
+# include <AliAltroRawStream.h>
+#endif 
+
+
+// TPC to FMD translations 
+// 
+//    TPC                FMD
+//    ----------+-----------
+//    pad+time  |      strip
+//    row       |     sector
+//    sector    |       ring
+// 
+class AliFMDRawStream : public AliAltroRawStream 
+{
+private:
+  UShort_t fSampleRate; // # of ALTRO samples per VA1_ALICE clock
+  // UChar_t* fMyData;
+  // Int_t    fMyPosition;
+  // Int_t    fMyCount;
+  // Int_t    fMyBunchLength;
+  Int_t    fPrevTime;
+protected:
+  // UShort_t Get10BitWord(UChar_t* buffer, Int_t position) const;
+public:
+  AliFMDRawStream(AliRawReader* reader);
+
+  Short_t Sector()      const { return fRow; }
+  Char_t  Ring()        const { return (fSector == 0 ? 'I' : 'O'); }
+  Short_t Strip()       const { return fPad + fTime / fSampleRate; }
+  Short_t PrevSector()  const { return fPrevRow; }
+  Char_t  PrevRing()    const { return (fPrevSector == 0 ? 'I' : 'O'); }
+  Short_t PrevStrip()   const { return fPrevPad + fPrevTime/fSampleRate; }
+
+  Bool_t  IsNewRing()   const { return (fSector != fPrevSector); }
+  Bool_t  IsNewSector() const { return (fRow != fPrevRow) || IsNewRing(); }
+  Bool_t  IsNewStrip()  const { return(Strip() != PrevStrip())||IsNewSector();}
+    
+  Short_t Count()      const { return fSignal; }
+  Short_t SampleRate() const { return fSampleRate; }
+  
+  virtual Bool_t   Next();
+  
+  ClassDef(AliFMDRawStream, 0) // Read raw FMD Altro data 
+};
+
+#endif
diff --git a/FMD/AliFMDReconstParticles.cxx b/FMD/AliFMDReconstParticles.cxx
deleted file mode 100644 (file)
index 8b3c37f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-
- //////////////////////////////////////////////////////////////////////////////
-//                                                                           //
-//  Forward Multiplicity Detector have to be reconstructed                   //
-//  number of particles in fixed pseudorapidity interval from                //
-// fNumOfMinRing  to fNumOfMaxRing                                           //
-// and phi interval                                                          //
-//  from fNumOfMinSector to fNumOfMaxSector                                  //
- //////////////////////////////////////////////////////////////////////////////
-
-#include "AliFMDReconstParticles.h"
-
-ClassImp(AliFMDReconstParticles)
-
-AliFMDReconstParticles::AliFMDReconstParticles()
-{
-     fNumOfDet=0;
-     fNumOfMinSector=0;
-     fNumOfMaxSector=0;
-     fNumOfMinRing=0;
-     fNumOfMaxRing=0;
-     fNumOfReconstParticles=0;
-}
-AliFMDReconstParticles::AliFMDReconstParticles(Int_t *RecParticles)
-{
-     fNumOfDet=RecParticles[0];
-     fNumOfMinSector=RecParticles[1];
-     fNumOfMaxSector=RecParticles[2];
-     fNumOfMinRing=RecParticles[3];
-     fNumOfMaxRing=RecParticles[4];
-     fNumOfReconstParticles=RecParticles[5];
-}
diff --git a/FMD/AliFMDReconstParticles.h b/FMD/AliFMDReconstParticles.h
deleted file mode 100644 (file)
index a47dee6..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef AliFMDReconstParticles_h
-#define AliFMDReconstParticles_h
-
-#include <TObject.h>
-class TClonesArray; 
-
-class AliFMDReconstParticles: public TObject
-{
-  /*
- Reconstracted Particles Class:
- has number of reconstructed particles in 
- sectors from NumOfMinSector to NumberOfMaxSector()
- rings from NumOfMinRing to NumOfMaxRing for each FMDvolume
-  */
-
-
- public:
-  AliFMDReconstParticles();
-  AliFMDReconstParticles (Int_t *RecParticles);
-  virtual ~AliFMDReconstParticles(){};
-  Int_t GetVolume() const  {return fNumOfDet;}  //number of volume 
-  Int_t GetNumberOfMinSector() const  {return fNumOfMinSector;} //number of min sector
-  Int_t GetNumberOfMaxSector() const {return fNumOfMaxSector;}  // number of max sector
-  Int_t GetNumberOfMinRing() const {return fNumOfMinRing;} //number of min ring
-  Int_t GetNumberOfMaxRing() const {return fNumOfMaxRing;}  //number of max ring 
-  Int_t GetNumberOfReconstParticles()const {return fNumOfReconstParticles;} //number of reconstructed particles
- private:
-  Int_t fNumOfDet;                       //Number of FMD disk;
-  Int_t fNumOfMinSector;                    //Number of min sector 
-  Int_t fNumOfMaxSector;                    //Number of max sector
-  Int_t fNumOfMinRing;                   //Number of min ring
-  Int_t fNumOfMaxRing;                      //Number of max ring
-  Int_t fNumOfReconstParticles;          //Number of reconstructed particles
-
-  ClassDef(AliFMDReconstParticles,2)
-};
-#endif
index 69cb4dd..0587d52 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 
-//_________________________________________________________________________
-// This is a class that constructs ReconstParticles (reconstructed particles) 
-// out of Digits
+//____________________________________________________________________
+// This is a class that constructs ReconstParticles (reconstructed
+// particles) out of Digits
+//
+//
+// This class reads either digits from a TClonesArray or raw data from
+// a DDL file (or similar), and stores the read ADC counts in an
+// internal cache (fAdcs). 
+//
+// From the cached values it then calculates the number of particles
+// that hit a region of the FMDs, as specified by the user. 
+//
+// The reconstruction can be done in two ways: Either via counting the
+// number of empty strips (Poisson method), or by converting the ADC
+// signal to an energy deposition, and then dividing by the typical
+// energy loss of a particle.
+// 
+// Currently, this class only reads the digits from a TClonesArray,
+// and the Poission method for reconstruction. 
+//
 // 
 //-- Authors: Evgeny Karpechev(INR) and Alla Maevsksia
-//////////////////////////////////////////////////////////////////////////////
+//  Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+//
+//
+//____________________________________________________________________
 
-// --- ROOT system ---
-#include "TTask.h"
-#include "TTree.h"
-#include "TSystem.h"
-#include "TFile.h"
-#include "TROOT.h"
-#include "TFolder.h"
-#include "TH2F.h"
-#include "TRandom.h"
+#ifndef ALIFMD_H
+# include "AliFMD.h"
+#endif
+#ifndef ALIFMDDIGIT_H
+# include "AliFMDDigit.h"
+#endif
+#ifndef ALIFMDPARTICLES_H
+# include "AliFMDParticles.h"
+#endif
+#ifndef ALIFMDRECONSTRUCTOR_H
+# include "AliFMDReconstructor.h"
+#endif
+#ifndef ALIALTROBUFFER_H
+# include "AliAltroBuffer.h"
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+#ifndef ALIRUN_H
+# include "AliRun.h"
+#endif
+#ifndef ALIRUNLOADER_H
+# include "AliRunLoader.h"
+#endif
+#ifndef ALILOADER_H
+# include "AliLoader.h"
+#endif
+#ifndef ALIHEADER_H
+# include "AliHeader.h"
+#endif
+#ifndef ALIGENEVENTHEADER_H
+# include "AliGenEventHeader.h"
+#endif
+#ifndef ALIRAWREADERFILE_H
+# include "AliRawReaderFile.h"
+#endif
+#ifndef ALIFMDRAWSTREAM_H
+# include "AliFMDRawStream.h"
+#endif
+
+//____________________________________________________________________
+ClassImp(AliFMDReconstructor);
 
-// --- Standard library ---
-#include <stdlib.h>
-#include <Riostream.h>
+//____________________________________________________________________
+AliFMDReconstructor::AliFMDReconstructor() 
+  : AliReconstructor(),
+    fAdcs(kMaxDetectors, kMaxRings, kMaxSectors, kMaxStrips),
+    fDeltaEta(0), 
+    fDeltaPhi(0), 
+    fThreshold(0),
+    fPedestal(0), 
+    fPedestalWidth(0)
+{
+  SetDeltaEta();
+  SetDeltaPhi();
+  SetThreshold();
+  SetPedestal();
+
+  fParticles = new TClonesArray("AliFMDParticles", 1000);
+  fFMDLoader = 0;
+  fRunLoader = 0;
+  fFMD       = 0;
+}
+  
+//____________________________________________________________________
+void 
+AliFMDReconstructor::SetPedestal(Float_t mean, Float_t width) 
+{
+  // Set the pedestal, and pedestal width 
+  fPedestal      = mean;
+  fPedestalWidth = width;
+}
+
+//____________________________________________________________________
+void 
+AliFMDReconstructor::Reconstruct(AliRunLoader* runLoader, 
+                                AliRawReader* rawReader) const
+{ 
+  // Collects all digits in the same active volume into number of
+  // particles
+  //
+  // Reconstruct number of particles in given group of pads for given
+  // FMDvolume determined by numberOfVolume,
+  // numberOfMinSector, numberOfMaxSector, numberOfMinRing,
+  // numberOgMaxRing 
+  //
+  // The reconstruction method is choosen based on the number of empty
+  // strips. 
+  fParticles->Clear();
+  if (!runLoader) {
+    Error("Exec","Run Loader loader is NULL - Session not opened");
+    return;
+  }
+  fRunLoader = runLoader;
+  fFMDLoader = runLoader->GetLoader("FMDLoader");
+  if (!fFMDLoader) 
+    Fatal("AliFMDReconstructor","Can not find FMD (loader) "
+         "in specified event");
 
-// --- AliRoot header files ---
+  // Get the AliRun object
+  if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
+  
+  // Get the AliFMD object
+  fFMD = static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
+  if (!fFMD) {
+    AliError("Can not get FMD from gAlice");
+    return;
+  }
+  fFMDLoader->LoadRecPoints("RECREATE");
 
-#include "AliRunLoader.h"
-#include "AliLoader.h"
+  if (!fRunLoader->TreeE())     fRunLoader->LoadHeader();
 
-#include "AliFMDdigit.h"
-#include "AliFMDReconstParticles.h"
-#include "AliFMDReconstructor.h"
-#include "AliRun.h"
-#include "AliConfig.h"
-#include "AliHeader.h"
-#include "AliGenEventHeader.h"
+  TClonesArray* digits = fFMD->Digits();
+  if (rawReader) {
+    Int_t event = 0;
+    while (rawReader->NextEvent()) {
+      ProcessEvent(event, rawReader, digits);
+      event++;
+    }
+  }
+  else {
+    Int_t nEvents= Int_t(fRunLoader->TreeE()->GetEntries()); 
+    for(Int_t event = 0; event < nEvents; event++) 
+      ProcessEvent(event, 0, digits);
+  }
 
-ClassImp(AliFMDReconstructor)
 
-        
-//____________________________________________________________________________
+  fFMDLoader->UnloadRecPoints();
+  fFMDLoader = 0;
+  fRunLoader = 0;
+  fFMD       = 0;
+}
 
-void AliFMDReconstructor::Reconstruct(AliRunLoader* runLoader) const
+//____________________________________________________________________
+void 
+AliFMDReconstructor::Reconstruct(AliRunLoader* runLoader) const
 { 
- //Collects all digits in the same active volume into number of particles
-  /*
-    Reconstruct number of particles 
-    in given group of pads for given FMDvolume
-    determine by numberOfVolume , 
-    numberOfMinSector,numberOfMaxSector,
-    numberOfMinRing, numberOgMaxRing
-    Reconstructor method choose dependence on number of empty pads  
-  */
-
-
-#ifdef DEBUG
-  Info("Exec ","Start");
-#endif
+  // Collects all digits in the same active volume into number of
+  // particles
+  //
+  // Reconstruct number of particles in given group of pads for given
+  // FMDvolume determined by numberOfVolume,
+  // numberOfMinSector, numberOfMaxSector, numberOfMinRing,
+  // numberOgMaxRing 
+  //
+  // The reconstruction method is choosen based on the number of empty
+  // strips. 
+  Reconstruct(runLoader, 0);
+}
+
+
+//____________________________________________________________________
+void 
+AliFMDReconstructor::ProcessEvent(Int_t event, 
+                                 AliRawReader* reader, 
+                                 TClonesArray* digits) const
+{
+  fRunLoader->GetEvent(event) ;
+  //event z-vertex for correction eta-rad dependence      
+  AliHeader *header            = fRunLoader->GetHeader();
+  if (!header) 
+    Warning("ProcessEvent", "no AliHeader found!");
+  AliGenEventHeader* genHeader = (header ? header->GenEventHeader() : 0);
 
-  Int_t const knumVolumes=5;
-  Int_t padADC;
-  Float_t eta, etain,etaout,rad,theta;
-  Int_t ivol, iSector, iRing;
-  Float_t rin[5]={4.2,15.4,4.2,15.4,4.2};
-  Float_t rout[5]={17.4,28.4,17.4,28.4,17.4};
-  Float_t z[5]={-62.8, -75.2, 83.4, 75.2, 340.};
-  Int_t numberOfRings[5]={512,256,512,256,512};
-  Int_t numberOfSectors[5]=  {20,40,20,40,20};
-  Int_t numberOfEtaIntervals[5];
-  // number of ring for boundary 0.1 eta
+  // Get the Z--coordinate from the event header 
+  TArrayF o(3); 
+  if (genHeader) genHeader->PrimaryVertex(o);
+  Float_t zVertex = o.At(2);
 
+  // If the recontruction tree isn't loaded, load it
+  if(fFMDLoader->TreeR()==0) fFMDLoader->MakeTree("R");
   
-  if (runLoader == 0x0)
-   {
-    Error("Exec","Run Loader loader is NULL - Session not opened");
-    return;
-   }
-
-  AliLoader* plFMD = runLoader->GetLoader("FMDLoader");
-  if (plFMD == 0x0)
-   {
-     Fatal("AliFMDReconstructor","Can not find FMD (loader) in specified event");
-     return;//never reached
-   }
-   
-  if (!runLoader->GetAliRun()) runLoader->LoadgAlice();
-  if (!runLoader->TreeE()) runLoader->LoadHeader();
-
-  TDirectory* cwd = gDirectory;
-  gDirectory = 0x0;
-  Text_t buf1[20];
-  TH2F* hTotal[10];
-  for (Int_t j=1; j<=5; j++){
-    sprintf(buf1,"hTotal%d",j);
+  //Make branches to hold the reconstructed particles 
+  const Int_t kBufferSize = 16000;
+  fFMDLoader->TreeR()->Branch("FMD", &fParticles, kBufferSize);
+
+  // Load or recreate the digits 
+  if (fFMDLoader->LoadDigits((reader ? "UPDATE" : "READ"))) {
+    if (!reader) {
+      Error("Exec","Error occured while loading digits. Exiting.");
+      return;
+    }
     
-    hTotal[j] = new TH2F(buf1," Number of primary particles ",
-                        numberOfSectors[j-1],1,numberOfSectors[j-1],
-                        numberOfRings[j-1],1,numberOfRings[j-1]);
-  }   
-  gDirectory = cwd;
-  plFMD->LoadRecPoints("RECREATE");
-  TClonesArray* reconParticles = new TClonesArray("AliFMDReconstParticles"); 
-  TClonesArray* digits = new TClonesArray("AliFMDdigit");
-  Int_t retval=0;     
-  Int_t nevents=Int_t (runLoader->TreeE()->GetEntries()); 
-#ifdef DEBUG
-  cout<<" nevents "<<nevents<<endl;
-#endif
-   for(Int_t ievent=0;ievent<nevents;ievent++)
-    { 
-#ifdef DEBUG
-      cout<<" *** event "<<ievent<<endl; 
-#endif
-      runLoader->GetEvent(ievent) ;
-      //event z-vertex for correction eta-rad dependence      
-      AliHeader *header = runLoader->GetHeader();
-      AliGenEventHeader* genHeader = header->GenEventHeader();
-      TArrayF *o = new TArrayF(3); 
-      if (genHeader) genHeader->PrimaryVertex(*o);
-      Float_t zVertex=o->At(2);
-
-      for (Int_t i=0; i<5; i++)
-        hTotal[i+1]->Reset();
-      
-      retval = plFMD->LoadDigits("READ"); 
-      if (retval)
-       {
-         Error("Exec","Error occured while loading digits. Exiting.");
-         return;
+  }
+  // Get the digits tree 
+  TTree* digitTree = fFMDLoader->TreeD();
+  if (!digitTree) { 
+    if (!reader) {
+      Error("Exec","Can not get Tree with Digits. "
+           "Nothing to reconstruct - Exiting");
+      return;
+    }
+    fFMDLoader->MakeTree("D");
+    digitTree = fFMDLoader->TreeD();
+    
+  }
+  // Get the FMD branch holding the digits. 
+  TBranch *digitBranch = digitTree->GetBranch("FMD");
+  if (!digitBranch) {
+    if (!reader) {
+      Error("Exec", "No digit branch for the FMD found");
+      return;
+    }
+    fFMD->MakeBranchInTree(digitTree, fFMD->GetName(), &(digits), 4000, 0);
+  }
+  if (!reader) digitBranch->SetAddress(&digits);
+
+  fEmptyStrips = 0;
+  fTotalStrips = 0;
+  Bool_t ok = kFALSE;
+  if      (reader) ok = ReadAdcs(reader);
+  else if (digits) ok = ReadAdcs(digits);
+  if (!ok) return;
+  
+  ReconstructFromCache(zVertex);
+
+  if (reader) {
+    digitTree->Fill();
+    fFMDLoader->WriteDigits("OVERWRITE");
+  }
+  fFMDLoader->UnloadDigits();
+  fFMDLoader->TreeR()->Reset();
+  fFMDLoader->TreeR()->Fill(); 
+  fFMDLoader->WriteRecPoints("OVERWRITE");
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDReconstructor::ReadAdcs(TClonesArray* digits) const
+{
+  AliDebug(10, "Reading ADCs from Digits array");
+  // read Digits, and reconstruct the particles
+  if (!fFMDLoader->TreeD()->GetEvent(0)) return kFALSE;
+
+  // Reads the digits from the array, and fills up the cache (fAdcs) 
+  fAdcs.Clear();
+  Int_t nDigits = digits->GetEntries();
+  for (Int_t digit = 0; digit < nDigits; digit++) {
+    AliFMDDigit* fmdDigit = 
+      static_cast<AliFMDDigit*>(digits->UncheckedAt(digit));    
+    
+    ProcessDigit(fmdDigit);
+  } //digit loop
+  return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDReconstructor::ReadAdcs(AliRawReader* reader) const
+{
+  AliDebug(10, "Reading ADCs from RawReader");
+  // Reads the digits from a RAW data 
+  fAdcs.Clear();
+  // reader->Reset();
+
+  if (!reader->ReadHeader()) {
+    Error("ReadAdcs", "Couldn't read header");
+    return kFALSE;
+  }
+
+  // Use AliAltroRawStream to read the ALTRO format.  No need to
+  // reinvent the wheel :-) 
+  AliFMDRawStream input(reader);
+  // Select FMD DDL's 
+  reader->Select(AliFMD::kBaseDDL >> 8);
+  
+  Int_t    oldDDL      = -1;
+  Int_t    count       = 0;
+  UShort_t detector    = 1; // Must be one here
+  UShort_t oldDetector = 0;
+  // Loop over data in file 
+  Bool_t   next       = kTRUE;
+
+  // local Cache 
+  TArrayI counts(10);
+  counts.Reset(-1);
+  Int_t offset = 0;
+  
+  while (next) {
+    next = input.Next();
+
+
+    count++; 
+    Int_t ddl = reader->GetDDLID();
+    if (ddl != oldDDL 
+       || input.IsNewStrip()
+       || !next) {
+      // Make a new digit, if we have some data! 
+      if (counts[0] >= 0) {
+       // Got a new strip. 
+       AliDebug(10, Form("Add a new strip: FMD%d%c[%2d,%3d] "
+                         "(current: FMD%d%c[%2d,%3d])", 
+                         oldDetector, input.PrevRing(), 
+                         input.PrevSector() , input.PrevStrip(),
+                         detector , input.Ring(), input.Sector(), 
+                         input.Strip()));
+       fFMD->AddDigit(oldDetector, 
+                      input.PrevRing(), 
+                      input.PrevSector(), 
+                      input.PrevStrip(), 
+                      counts[0], counts[1], counts[2]);
+       AliFMDDigit* digit = 
+         static_cast<AliFMDDigit*>(fFMD->Digits()->
+                                   UncheckedAt(fFMD->GetNdigits()-1));
+       ProcessDigit(digit);
+      }
+       
+      if (!next) { 
+       AliDebug(10, Form("Read %d channels for FMD%d", 
+                         count + 1, detector));
+       break;
+      }
+    
+    
+      // If we got a new DDL, it means we have a new detector. 
+      if (ddl != oldDDL) {
+       if (detector != 0) 
+         AliDebug(10, Form("Read %d channels for FMD%d", 
+                           count + 1, detector));
+       // Reset counts, and update the DDL cache 
+       count       = 0;
+       oldDDL      = ddl;
+       // Check that we're processing a FMD detector 
+       Int_t detId = reader->GetDetectorID();
+       if (detId != (AliFMD::kBaseDDL >> 8)) {
+         Error("ReadAdcs", "Detector ID %d != %d",
+               detId, (AliFMD::kBaseDDL >> 8));
+         break;
        }
-      
-      TTree* treeD = plFMD->TreeD();
-      if (treeD == 0x0)
-       {
-         Error("Exec","Can not get Tree with Digits. Nothing to reconstruct - Exiting");
-         return;
+       // Figure out what detector we're deling with 
+       oldDetector = detector;
+       switch (ddl) {
+       case 0: detector = 1; break;
+       case 1: detector = 2; break;
+       case 2: detector = 3; break;
+       default:
+         Error("ReadAdcs", "Unknown DDL 0x%x for FMD", ddl);
+         return kFALSE;
        }
-      
-      TBranch *brDigits=0;
-           
-      brDigits=treeD->GetBranch("FMD");
-
-      if (brDigits) {
-       brDigits->SetAddress(&digits);
-      }else{
-       cerr<<"EXEC Branch FMD digits not found"<<endl;
-       return;
-      } 
-         
-      if(plFMD->TreeR()==0) plFMD->MakeTree("R");
+       AliDebug(10, Form("Reading ADCs for 0x%x  - That is FMD%d",
+                         reader->GetEquipmentId(), detector));
+      }
+      counts.Reset(-1);
+      offset = 0;
+    }
+    
+    counts[offset] = input.Count();
+    offset++;
+    
+    AliDebug(10, Form("ADC of FMD%d%c[%2d,%3d] += %d",
+                     detector, input.Ring(), input.Sector(), 
+                     input.Strip(), input.Count()));
+    oldDetector = detector;
+  }
+  return kTRUE;
+}
 
-      //Make branches
-      const Int_t kBufferSize = 16000;
-      plFMD->TreeR()->Branch("FMD", &reconParticles, kBufferSize);
+//____________________________________________________________________
+void
+AliFMDReconstructor::ProcessDigit(AliFMDDigit* digit) const
+{
+  // Process a digit.  Derived classes can overload this member
+  // function to do stuff to the digit.  However, it should write the
+  // ADC count to the internal cache 
+  //
+  //    fAdcs(detector - 1, ring, sector, strip) = counts;
+  //
+  // In this implementation, we count the number of strips below
+  // threshold.   This we do to later choose what kind of
+  // reconstruction algorithm we'd like to use. 
+  // 
+  UShort_t detector = digit->Detector();
+  Char_t   ring     = digit->Ring();
+  UShort_t sector   = digit->Sector();
+  UShort_t strip    = digit->Strip();    
+  
+  UShort_t counts  = SubtractPedestal(digit);
+  
+  fAdcs(detector - 1, ring, sector, strip) = counts;
+  if (counts < fThreshold) fEmptyStrips++;
+  fTotalStrips++;
+}
 
-      
-      Int_t zeroADC=6;
-      // read Digits 
-      AliFMDdigit  *fmdDigit;
-       if (plFMD->TreeD()->GetEvent(0))
-       {                 
-         Int_t nDigits=digits->GetEntries();
-         Int_t recParticles[6];
-         Int_t nRecPart=0 ;
-         Int_t zeroPads=0;
-         Int_t numberOfPads=0;
-         Int_t pedestal;
-         Float_t channelWidth=(22400*50)/1024;
-         for (Int_t digit=0;digit<nDigits;digit++) 
-           {
-             fmdDigit=(AliFMDdigit*)digits->UncheckedAt(digit);    
-             ivol=fmdDigit->Volume();
-             iSector=fmdDigit->NumberOfSector();
-             iRing=fmdDigit->NumberOfRing();
-             pedestal=Int_t(gRandom->Gaus(500,250));
-             padADC= fmdDigit->ADCsignal()
-               -Int_t(Float_t(pedestal)/channelWidth);
-             if (padADC<0) padADC=0;
-              hTotal[ivol]->Fill(iSector,iRing,padADC);
-           } //digit loop
-
-         //reconstruct multiplicity in 0.1 eta according Poisson distribution 
-
-         Int_t rmin=0; Int_t rmax=0; 
-         Int_t smin=0; Int_t smax=0; 
-         for (ivol=0; ivol<knumVolumes; ivol++)
-           {
-             Float_t ring2number=Float_t (numberOfRings[ivol])/
-               (rout[ivol]-rin[ivol]);
-             Float_t realZ=zVertex+z[ivol];
-             theta=TMath::ATan(rout[ivol]/TMath::Abs(realZ));
-             etain = - TMath::Log( TMath::Tan(theta/2.));
-             theta=TMath::ATan(rin[ivol]/TMath::Abs(realZ));
-             etaout=- TMath::Log( TMath::Tan(theta/2.));
-             numberOfEtaIntervals[ivol]=Int_t((etaout-etain)*10)-1;
-             eta=etain;
-             for (Int_t e1=0;e1<=numberOfEtaIntervals[ivol];e1++) 
-               {
-                 theta = 2.*TMath::ATan (TMath::Exp (-eta));
-                 Float_t radmin = TMath::Abs(realZ) * (TMath::Tan (theta));
-                 rmax= Int_t ( (radmin-rin[ivol])*ring2number+0.5);
-                 eta=eta+0.1;
-                 theta = 2.*TMath::ATan (TMath::Exp (-eta));
-                 rad = TMath::Abs(realZ) * (TMath::Tan (theta));
-                 rmin=Int_t( (rad-rin[ivol])*ring2number+0.5);
-                 
-                 zeroPads=0;
-                 smin=0;
-                 smax=numberOfSectors[ivol]; 
-                 numberOfPads=(rmax-rmin)*(smax-smin);
-                 for (Int_t iring=rmin; iring<rmax; iring++) 
-                   {
-                     for 
-                       (Int_t isector=0;
-                        isector<numberOfSectors[ivol]; 
-                        isector++) 
-                       {
-                         if(hTotal[ivol+1]->GetBinContent(isector+1,iring+1)
-                            <zeroADC) zeroPads++;}
-                     
-                   } //ring
-                 Float_t numberOfPads=Float_t(smax-smin)*Float_t(rmax-rmin);
-
-                 Double_t lambda=-TMath::Log(Double_t(zeroPads)/numberOfPads);
-                 Int_t fRecon=Int_t (lambda*numberOfPads+0.5);
-                 recParticles[0]=ivol+1;
-                 recParticles[1]=smin;
-                 recParticles[2]=smax;
-                 recParticles[3]=rmin;
-                 recParticles[4]=rmax;
-                 recParticles[5]= fRecon;
-                 new((*reconParticles)[nRecPart++])   AliFMDReconstParticles(recParticles);             
-                 
-
-                } // eta
-            } // volume
-          
-       }//if (plFMD->TreeD()->GetEvent(0))
-       plFMD->TreeR()->Reset();
-       plFMD->TreeR()->Fill(); 
-       plFMD->WriteRecPoints("OVERWRITE");
-       plFMD->UnloadDigits();
-    } //event loop
-  plFMD->UnloadRecPoints();
-#ifdef DEBUG
-  Info(" Exec"," finished");
-#endif
-  //  delete hTotal[10]; 
+//____________________________________________________________________
+UShort_t
+AliFMDReconstructor::SubtractPedestal(AliFMDDigit* digit) const
+{
+  // Member function to subtract the pedestal from a digit
+  // This implementation does nothing, but a derived class could over
+  // load this to subtract a pedestal that was given in a database or
+  // something like that. 
 
+  Int_t counts = 
+    TMath::Max(Int_t(digit->Count1() - fPedestal - 3 * fPedestalWidth), 0);
+  if (digit->Count2() >= 0) 
+    counts += 
+      TMath::Max(Int_t(digit->Count2() - fPedestal - 3 * fPedestalWidth), 0);
+  if (digit->Count3() >= 0) 
+    counts += 
+      TMath::Max(Int_t(digit->Count3() - fPedestal - 3 * fPedestalWidth), 0);
+      
+  if (counts < 0) counts = 0;
+  return  UShort_t(counts);
 }
 
+//____________________________________________________________________
+void
+AliFMDReconstructor::ReconstructFromCache(Float_t zVertex) const
+{
+  // Based on the information in the cache, do the reconstruction. 
+  Int_t nRecon = 0;
+  // Loop over the detectors 
+  for (Int_t i = 1; i <= 3; i++) {
+    AliFMDSubDetector* sub = 0;
+    switch (i) {
+    case 1: sub = fFMD->GetFMD1(); break;
+    case 2: sub = fFMD->GetFMD2(); break;
+    case 3: sub = fFMD->GetFMD3(); break;
+    }
+    if (!sub) continue;
+       
+    // Loop over the rings in the detector
+    for (Int_t j = 0; j < 2; j++) {
+      Float_t     rZ = 0;
+      AliFMDRing* r  = 0;
+      switch (j) {
+      case 0: r  = sub->GetInner(); rZ = sub->GetInnerZ(); break;
+      case 1: r  = sub->GetOuter(); rZ = sub->GetOuterZ(); break;
+      }
+      if (!r) continue;
+      
+      // Calculate low/high theta and eta 
+      // FIXME: Is this right? 
+      Float_t realZ    = zVertex + rZ;
+      Float_t thetaOut = TMath::ATan2(r->GetHighR(), realZ);
+      Float_t thetaIn  = TMath::ATan2(r->GetLowR(), realZ);
+      Float_t etaOut   = - TMath::Log(TMath::Tan(thetaOut / 2));
+      Float_t etaIn    = - TMath::Log(TMath::Tan(thetaIn / 2));
+      if (TMath::Abs(etaOut) > TMath::Abs(etaIn)) {
+       Float_t tmp = etaIn;
+       etaIn       = etaOut;
+       etaOut      = tmp;
+      }
+
+      //-------------------------------------------------------------
+      //
+      // Here starts poisson method 
+      //
+      // Calculate eta step per strip, number of eta steps, number of
+      // phi steps, and check the sign of the eta increment 
+      Float_t stripEta = (Float_t(r->GetNStrips()) / (etaIn - etaOut));
+      Int_t   nEta     = Int_t(TMath::Abs(etaIn - etaOut) / fDeltaEta); 
+      Int_t   nPhi     = Int_t(360. / fDeltaPhi);
+      Float_t sign     = TMath::Sign(Float_t(1.), etaIn);
 
-//_____________________________________________________________________________
-void AliFMDReconstructor::FillESD(AliRunLoader* /*runLoader*/, 
-                                 AliESD* /*esd*/) const
+      AliDebug(10, Form("FMD%d%c Eta range: %f, %f %d Phi steps",
+                       sub->GetId(), r->GetId(), etaOut, etaIn, nPhi));
+
+      // Loop over relevant phi values 
+      for (Int_t p = 0; p < nPhi; p++) {
+       Float_t  minPhi    = p * fDeltaPhi;
+       Float_t  maxPhi    = minPhi + fDeltaPhi;
+       UShort_t minSector = UShort_t(minPhi / 360) * r->GetNSectors();
+       UShort_t maxSector = UShort_t(maxPhi / 360) * r->GetNSectors();
+       
+       AliDebug(10, Form(" Now in phi range %f, %f (sectors %d,%d)",
+                         minPhi, maxPhi, minSector, maxSector));
+       // Loop over relevant eta values 
+       for (Int_t e = nEta; e >= 0; --e) {
+         Float_t  maxEta   = etaIn  - sign * e * fDeltaEta;
+         Float_t  minEta   = maxEta - sign * fDeltaEta;
+         if (sign > 0)  minEta = TMath::Max(minEta, etaOut);
+         else           minEta = TMath::Min(minEta, etaOut);
+         Float_t  theta1   = 2 * TMath::ATan(TMath::Exp(-minEta));
+         Float_t  theta2   = 2 * TMath::ATan(TMath::Exp(-maxEta));
+         Float_t  minR     = TMath::Abs(realZ * TMath::Tan(theta2));
+         Float_t  maxR     = TMath::Abs(realZ * TMath::Tan(theta1));
+         UShort_t minStrip = UShort_t((etaIn - maxEta) * stripEta + 0.5);
+         UShort_t maxStrip = UShort_t((etaIn - minEta) * stripEta + 0.5);
+
+         AliDebug(10, Form("  Now in eta range %f, %f (strips %d, %d)\n"
+                           "    [radii %f, %f, thetas %f, %f, sign %d]", 
+                           minEta, maxEta, minStrip, maxStrip, 
+                           minR, maxR, theta1, theta2, sign));
+
+         // Count number of empty strips
+         Int_t   emptyStrips = 0;
+         for (Int_t sector = minSector; sector < maxSector; sector++) 
+           for (Int_t strip = minStrip; strip < maxStrip; strip++) 
+             if (fAdcs(sub->GetId() - 1, r->GetId(), sector, strip) 
+                 < fThreshold) emptyStrips++;
+         
+         // The total number of strips 
+         Float_t nTotal = (maxSector - minSector) * (maxStrip - minStrip);
+         
+         // Log ratio of empty to total number of strips 
+         AliDebug(10, Form("Lambda= %d / %d = %f", 
+                           emptyStrips, nTotal, 
+                           Float_t(emptyStrips) / nTotal));
+         
+         Double_t lambda = (emptyStrips > 0 ? 
+                            - TMath::Log(Double_t(emptyStrips) / nTotal) :
+                            1);
+
+         // The reconstructed number of particles is then given by 
+         Int_t reconstructed = Int_t(lambda * nTotal + 0.5);
+           
+         // Add a AliFMDParticles to the reconstruction tree. 
+         new((*fParticles)[nRecon])   
+           AliFMDParticles(sub->GetId(), r->GetId(),
+                           minSector, maxSector, minStrip, maxStrip,
+                           minEta, maxEta, minPhi, maxPhi,
+                           reconstructed, AliFMDParticles::kPoission);
+         nRecon++;
+       } // phi 
+      } // eta
+    } // ring 
+  } // detector 
+}
+
+//____________________________________________________________________
+void 
+AliFMDReconstructor::FillESD(AliRunLoader* /*fRunLoader*/, 
+                            AliESD* /*esd*/) const
 {
 // nothing to be done
 
index 5d638c5..9d6a460 100644 (file)
@@ -1,45 +1,94 @@
-//   Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved.
+// -*- mode: c++ -*- 
+//
+//  Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+//  reserved. 
+//
 //  See cxx source for full Copyright notice                               
+//
 //  AliFMDReconstructor.h 
-//  Task Class for making TreeR in FMD                        
+//  Task Class for making TreeR for FMD                        
+//
 //-- Authors: Evgeny Karpechev (INR) and Alla Maevskaia (INR)
+//   Latest changes by Christian Holm Christensen <cholm@nbi.dk>
 /*
-    Reconstruct nember of particles 
-    in given group of pads for given FMDvolume
-    determine by numberOfVolume , 
-    numberOfMinSector,numberOfMaxSector,
-    numberOfMinRing, numberOfMaxRing
-    Reconstruction method choose dependence on number of empty pads  
+    Reconstruct nember of particles in given group of pads for given
+    FMDvolume determine by numberOfVolume ,
+    numberOfMinSector,numberOfMaxSector, numberOfMinRing,
+    numberOfMaxRing Reconstruction method choose dependence on number
+    of empty pads
   */
 /* $Id$ */
-
-
 #ifndef ALIFMDRECONSTRUCTOR_H
 #define ALIFMDRECONSTRUCTOR_H
+#ifndef ALIRECONSTRUCTOR_H
+# include <AliReconstructor.h>
+#endif
+#ifndef ALIFMDMAP_H
+# include <AliFMDMap.h>
+#endif
 
-#include "AliReconstructor.h"
+//____________________________________________________________________
+class TClonesArray;
+class AliFMD;
+class AliLoader;
+class AliRunLoader;
+class AliFMDDigit;
+class AliRawReader;
+typedef AliFMDMap<UShort_t> AliFMDAdcMap;
 
 
+//____________________________________________________________________
 class AliFMDReconstructor: public AliReconstructor 
 {
- public:
-  AliFMDReconstructor(): AliReconstructor() {}; 
-  virtual ~AliFMDReconstructor() {};
-
-  virtual void         Reconstruct(AliRunLoader* runLoader) const;
-  virtual void         FillESD(AliRunLoader* runLoader, AliESD* esd) const;
+protected:
+  mutable AliFMDAdcMap  fAdcs;
+  mutable AliRunLoader* fRunLoader;
+  mutable AliLoader*    fFMDLoader;
+  mutable TClonesArray* fParticles;
+  mutable AliFMD*       fFMD;
   
+  Float_t               fDeltaEta;
+  Float_t               fDeltaPhi;
+  UShort_t              fThreshold;
+  Float_t               fPedestal;
+  Float_t               fPedestalWidth;
+  mutable Int_t         fEmptyStrips;
+  mutable Int_t         fTotalStrips;
+  
+  enum { 
+    kMaxDetectors = 3, 
+    kMaxRings     = 2, 
+    kMaxSectors   = 20, 
+    kMaxStrips    = 512
+  };
+  
+public:
+  AliFMDReconstructor();
+  virtual ~AliFMDReconstructor() {}
+
+  void         SetDeltaEta(Float_t deta=.1)  { fDeltaEta = deta;  }
+  void         SetDeltaPhi(Float_t dphi=360) { fDeltaPhi = dphi;  } 
+  void         SetThreshold(UShort_t t=6)    { fThreshold = t; }
+  void         SetPedestal(Float_t mean=10, Float_t width=1);
+     
+  virtual void Reconstruct(AliRunLoader* runLoader) const;
+  virtual void Reconstruct(AliRunLoader* runLoader,  
+                          AliRawReader* rawReader) const;
+  virtual void FillESD(AliRunLoader* runLoader, AliESD* esd) const;
+  
+protected:
+  virtual void     ProcessEvent(Int_t event, 
+                               AliRawReader* rawReader, 
+                               TClonesArray* digits) const;
+  virtual Bool_t   ReadAdcs(TClonesArray* digits) const;
+  virtual Bool_t   ReadAdcs(AliRawReader* rawReader) const;
+  virtual void     ProcessDigit(AliFMDDigit* digit) const;
+  virtual UShort_t SubtractPedestal(AliFMDDigit* digit) const;
+  virtual void     ReconstructFromCache(Float_t zVertex) const;
   ClassDef(AliFMDReconstructor, 0)  // class for the FMD reconstruction
-
-
 }; 
 #endif
-
-
-
-
-
-
-
-
-
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDRing.cxx b/FMD/AliFMDRing.cxx
new file mode 100644 (file)
index 0000000..6feac47
--- /dev/null
@@ -0,0 +1,558 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Utility class to help implement collection of FMD modules into
+// rings.  This is used by AliFMDSubDetector and AliFMD.  
+//
+// The AliFMD object owns the AliFMDRing objects, and the
+// AliFMDSubDetector objects reference these.  That is, the AliFMDRing
+// objects are share amoung the AliFMDSubDetector objects.
+//
+// Latest changes by Christian Holm Christensen
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef ALIFMDRING_H
+# include "AliFMDRing.h"
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+#ifndef ROOT_TMath
+# include <TMath.h>
+#endif
+#ifndef ROOT_TH2
+# include <TH2.h>
+#endif
+#ifndef ROOT_TVirtualMC
+# include <TVirtualMC.h>
+#endif
+#ifndef ROOT_TVector2
+# include <TVector2.h>
+#endif
+#ifndef ROOT_TBrowser
+# include <TBrowser.h>
+#endif
+#ifndef ROOT_TString
+# include <TString.h>
+#endif
+#ifndef ROOT_TArc
+# include <TArc.h>
+#endif
+#ifndef ROOT_TObjArray
+# include <TObjArray.h>
+#endif
+#ifndef ROOT_TXTRU
+# include <TXTRU.h>
+#endif
+#ifndef ROOT_TNode
+# include <TNode.h>
+#endif
+#ifndef ROOT_TRotMatrix
+# include <TRotMatrix.h>
+#endif
+#ifndef ROOT_TList
+# include <TList.h>
+#endif
+#ifndef __IOSTREAM__
+# include <iostream>
+#endif
+
+ClassImp(AliFMDRing);
+
+//____________________________________________________________________
+// Construct a alifmdring. 
+// 
+//     id              Id of the ring (either 'i' or 'o').
+//     lowr            Lower radius of ring (in centimeters).
+//     highr           Upper radius of ring (in centimeters).
+//     r               Radius of the silicon wafers (in centimeters). 
+//     theta           Opening angle of the silicon wafers.
+//     strips          Number of strips. 
+AliFMDRing::AliFMDRing(Char_t id, Bool_t detailed) 
+  : fId(id), 
+    fDetailed(detailed),
+    fWaferRadius(0), 
+    fSiThickness(0),
+    fLowR(0), 
+    fHighR(0), 
+    fTheta(0), 
+    fNStrips(0), 
+    fShape(0),
+    fRotMatricies(0)
+{}
+
+//____________________________________________________________________
+void 
+AliFMDRing::Init() 
+{
+  // Initialize the ring object.
+  // DebugGuard guard("AliFMDRing::Init");
+  AliDebug(10, "AliFMDRing::Init");
+  fPolygon.Clear();
+  SetupCoordinates();  
+}
+
+//____________________________________________________________________
+AliFMDRing::~AliFMDRing() 
+{
+  if (fShape) delete fShape;
+  if (fRotMatricies) delete fRotMatricies;
+}
+
+
+//____________________________________________________________________
+void 
+AliFMDRing::Browse(TBrowser* /* b */)
+{
+  // DebugGuard guard("AliFMDRing::Browse");
+  AliDebug(10, "AliFMDRing::Browse");
+}
+
+  
+//____________________________________________________________________
+void 
+AliFMDRing::SetupCoordinates() 
+{
+  // Calculates the parameters of the polygon shape. 
+  // 
+  // DebugGuard guard("AliFMDRing::SetupCoordinates");
+  AliDebug(10, "AliFMDRing::SetupCoordinates");
+  // Get out immediately if we have already done all this 
+  if (fPolygon.GetNVerticies() > 1) return;
+
+  double tan_theta  = TMath::Tan(fTheta * TMath::Pi() / 180.);
+  double tan_theta2 = TMath::Power(tan_theta,2);
+  double r2         = TMath::Power(fWaferRadius,2);
+  double y_A        = tan_theta * fLowR;
+  double lr2        = TMath::Power(fLowR, 2);
+  double hr2        = TMath::Power(fHighR,2);
+  double x_D        = fLowR + TMath::Sqrt(r2 - tan_theta2 * lr2);
+  double x_D2       = TMath::Power(x_D,2);
+  //double x_D_2      = fLowR - TMath::Sqrt(r2 - tan_theta2 * lr2);
+  double y_B        = sqrt(r2 - hr2 + 2 * fHighR * x_D - x_D2);
+  double x_C        = ((x_D + TMath::Sqrt(-tan_theta2 * x_D2 + r2 
+                                         + r2 * tan_theta2)) 
+                      / (1 + tan_theta2));
+  double y_C        = tan_theta * x_C;
+
+  fPolygon.AddVertex(fLowR,  -y_A);
+  fPolygon.AddVertex(x_C,    -y_C);
+  fPolygon.AddVertex(fHighR, -y_B);
+  fPolygon.AddVertex(fHighR,  y_B);
+  fPolygon.AddVertex(x_C,     y_C);
+  fPolygon.AddVertex(fLowR,   y_A);
+}
+
+//____________________________________________________________________
+bool
+AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const
+{
+  // Checks if a point (x,y) is inside the module with number moduleNo 
+  //
+  // DebugGuard guard("AliFMDRing::IsWithin");
+  AliDebug(10, "AliFMDRing::IsWithin");
+  bool   ret            = false;
+  double r2             = x * x + y * y;
+  if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) {
+    // double point_angle    = TMath::ATan2(y, x);
+    // int    n_modules      = 360 / Int_t(fTheta * 2);
+    double m_angle        = (.5 + moduleNo) * 2 * fTheta;
+    double m_radians      = TMath::Pi() * m_angle / 180.;
+    
+    // Rotate the point.
+    double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians);
+    double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians);
+  
+    ret = fPolygon.Contains(xr,yr);
+  }
+  return ret;
+}
+
+
+
+
+//____________________________________________________________________
+void
+AliFMDRing::Draw(Option_t* option) const
+{
+  // Draw a the shape of the ring into a 2D histogram.  Useful for
+  // superimposing the actual shape of the ring onto a scatter plot of
+  // hits in the detector. 
+  // 
+  // DebugGuard guard("AliFMDRing::Draw");
+  AliDebug(10, "AliFMDRing::Draw");
+  // The unrotated coordinates of the polygon verticies
+  if (fPolygon.GetNVerticies() < 1) return;
+  
+  TVector2 v[6];
+  for (size_t i = 0; i < fPolygon.GetNVerticies(); i++) 
+    v[i] = fPolygon.GetVertex(i);
+  
+  Int_t    nModules  = 360 / Int_t(fTheta * 2);
+  Double_t dTheta    = fTheta * 2;
+  
+  TString opt(option);
+  if (opt.Contains("B", TString::kIgnoreCase)) {
+    opt.Remove(opt.Index("B", 1, TString::kIgnoreCase),1);
+    TH1* null = new TH2F("null", "Null",
+                        100, -fHighR * 1.1, fHighR * 1.1, 
+                        100, -fHighR * 1.1, fHighR * 1.1);
+    null->SetStats(0);
+    null->Draw(opt.Data());
+  }
+   
+  for (int i = 0; i < nModules; i++) {
+    Double_t theta = (i + .5) * dTheta;
+    AliFMDPolygon p;
+    for (int j = 0; j < 6; j++) {
+      TVector2 vr(v[j].Rotate(TMath::Pi() * theta / 180.));
+      if (!p.AddVertex(vr.X(),vr.Y())) {
+       // std::cerr << "Draw of polygon " << i << " failed" << std::endl;
+       break;
+      }
+    }
+    p.Draw(opt.Data(), Form("MOD%c_%d", fId, i));
+  }
+  if (opt.Contains("0", TString::kIgnoreCase)) {
+    TArc* arcH = new TArc(0,0, fHighR);
+    arcH->SetLineStyle(2);
+    arcH->SetLineColor(4);
+    arcH->Draw();
+
+    TArc* arcL = new TArc(0,0, fLowR);
+    arcL->SetLineStyle(2);
+    arcL->SetLineColor(4);
+    arcL->Draw();
+  }
+}
+
+//____________________________________________________________________
+void 
+AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, 
+                         Int_t pbRotId, Int_t idRotId)
+{
+  // Setup the geometry of the ring.  It defines the volumes 
+  // RNGI or RNGO which can later be positioned in a sub-detector
+  // volume. 
+  // 
+  // The hieracy of the RNGx volume is 
+  // 
+  //    RNGx                        // Ring volume
+  //      VFx                       // Container of hybrid + legs
+  //        ACTx                    // Active volume (si sensor approx)
+  //          SECx                  // Section division
+  //            STRx                // Strip division 
+  //        PBTx                    // Print board (bottom)
+  //        PTTx                    // Print board (top)  
+  //        LLEG                    // Support leg (long version)
+  //      VBx                       // Container of hybrid + legs
+  //        ACTx                    // Active volume (si sensor approx)
+  //          SECx                  // Section division
+  //            STRx                // Strip division 
+  //        PBTx                    // Print board (bottom)
+  //        PTTx                    // Print board (top)  
+  //        SLEG                    // Support leg (long version)
+  //        
+  // Parameters: 
+  //
+  //   vacuumId        Medium of inactive virtual volumes 
+  //   siId            Medium of Silicon sensor (active)
+  //   pcbId           Medium of print boards 
+  //   pbRotId         Print board rotation matrix 
+  //   idRotId         Identity rotation matrix 
+  //
+  // DebugGuard guard("AliFMDRing::SetupGeometry");
+  AliDebug(10, "AliFMDRing::SetupGeometry");
+
+  const TVector2& bCorner   = fPolygon.GetVertex(3); // Third  corner
+  const TVector2& aCorner   = fPolygon.GetVertex(5); // First  corner
+  const TVector2& cCorner   = fPolygon.GetVertex(4); // Second corner
+  TString name;
+  TString name2;
+  Double_t dStrip     = (bCorner.Mod() - aCorner.Mod()) / fNStrips;
+  Double_t stripOff   = aCorner.Mod();
+  Double_t rmin       = fLowR;
+  Double_t rmax       = bCorner.Mod();
+  Double_t pars[10];
+  fRingDepth          = (fSiThickness 
+                        + fPrintboardThickness 
+                        + fLegLength 
+                        + fModuleSpacing);
+
+  // Ring virtual volume 
+  pars[0]             = rmin;
+  pars[1]             = fHighR;
+  pars[2]             = fRingDepth / 2;
+  name                = Form("RNG%c", fId);
+  fRingId             = gMC->Gsvolu(name.Data(), "TUBE", vacuumId, pars, 3);
+  
+  // Virtual volume for modules with long legs 
+  pars[1]             = rmax;
+  pars[3]             = -fTheta;
+  pars[4]             =  fTheta;
+  name                = Form("VF%c", fId);
+  fVirtualFrontId     = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
+
+  // Virtual volume for modules with long legs 
+  pars[2]             =  (fRingDepth - fModuleSpacing) / 2;
+  name                =  Form("VB%c", fId);
+  fVirtualBackId      =  gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
+  
+  // Virtual mother volume for silicon
+  pars[2]             =  fSiThickness/2;
+  name2               =  name;
+  name                =  Form("ACT%c",fId);
+  fActiveId           =  gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5);
+
+  if (fDetailed) {
+    // Virtual sector volumes 
+    name2               = name;
+    name                = Form("SEC%c",fId);
+    gMC->Gsdvn2(name.Data(), name2.Data(), 2, 2, -fTheta, vacuumId);
+    fSectionId          = gMC->VolId(name.Data());
+    
+    // Active strip volumes 
+    name2               = name;
+    name                = Form("STR%c", fId);
+    gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1, 
+               stripOff, siId, fNStrips);
+    fStripId            = gMC->VolId(name.Data());
+  }
+  
+  // Print-board on back of module 
+  pars[4]             = TMath::Tan(TMath::Pi() * fTheta / 180) * fBondingWidth;
+  // Top of the print board
+  pars[0]             = cCorner.Y() - pars[4];
+  pars[1]             = bCorner.Y() - pars[4];
+  pars[2]             = fPrintboardThickness / 2; // PCB half thickness
+  pars[3]             = (bCorner.X() - cCorner.X()) / 2;
+  name                = Form("PBT%c", fId);
+  fPrintboardTopId    = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
+
+  // Bottom of the print board
+  pars[0]             = aCorner.Y() - pars[4];
+  pars[1]             = cCorner.Y() - pars[4];
+  pars[3]             = (cCorner.X() - aCorner.X()) / 2;
+  name                = Form("PBB%c", fId);
+  fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
+
+  // Define rotation matricies
+  Int_t    nModules  = 360 / Int_t(fTheta * 2);
+  Double_t dTheta    = fTheta * 2;
+  fRotations.Set(nModules);
+  for (int i = 0; i < nModules; i++) {
+    Double_t theta  = (i + .5) * dTheta;
+    Int_t    idrot  = 0;
+    // Rotation matrix for virtual module volumes
+    gMC->Matrix(idrot, 90, theta, 90, fmod(90 + theta, 360), 0, 0);
+    fRotations[i] = idrot;
+  }
+
+
+  // Int_t    nModules  = 360 / Int_t(fTheta * 2);
+  // Double_t dTheta    = fTheta * 2;
+  Double_t pbTopL    = (bCorner.X() - cCorner.X());
+  Double_t pbBotL    = (cCorner.X() - aCorner.X());
+  Double_t yoffset   = ((TMath::Tan(TMath::Pi() * fTheta / 180) 
+                        * fBondingWidth)); 
+  
+  for (int i = 0; i < nModules; i++) {
+    TString  name2    = Form("RNG%c", fId);
+
+    Int_t     id      = i;
+    // Double_t  theta   = (i + .5) * dTheta;
+    Bool_t    isFront = (i % 2 == 1);
+    Double_t  dz      = 0;
+    Double_t  w       = fRingDepth - (isFront ? 0 : fModuleSpacing);
+
+    // Place virtual module volume 
+    name = Form("V%c%c", (isFront ? 'F' : 'B'), fId);
+    dz   = (w - fRingDepth) / 2;
+    gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i]);
+
+    // We only need to place the children once, they are copied when
+    // we place the other virtual volumes. 
+    if (i > 1) continue;
+    name2 = name;
+
+    // Place active silicon wafer - this is put so that the front of
+    // the silicon is on the edge of the virtual volume. 
+    name  = Form("ACT%c", fId);
+    dz    = (w - fSiThickness) / 2;
+    gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId);
+
+    // Place print board.  This is put immediately behind the silicon
+    name = Form("PBT%c", fId);
+    dz   =  w / 2 - fSiThickness - fPrintboardThickness / 2;
+    gMC->Gspos(name.Data(), id, name2.Data(), 
+              fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY");
+    name = Form("PBB%c", fId);
+    gMC->Gspos(name.Data(), id, name2.Data(), 
+              fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY");
+
+    // Support legs 
+    // This is put immediately behind the pringboard. 
+    dz     = (w / 2 - fSiThickness - fPrintboardThickness 
+            - (fLegLength + (isFront ? fModuleSpacing : 0)) /2);
+    name  = (isFront ? "LLEG" : "SLEG");
+    gMC->Gspos(name.Data(), id*10 + 1, name2.Data(), 
+              aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, "");
+    Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius;
+    gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(), y,dz,idRotId,"");
+    gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(), -y,dz ,idRotId,"");
+  }
+}
+//____________________________________________________________________
+void 
+AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z, 
+                    Int_t /* pbRotId */, Int_t idRotId)
+{
+  // Positions a RNGx volume inside a mother. 
+  // 
+  // Parameters
+  //  
+  //    mother    Mother volume to position the RNGx volume in 
+  //    baseId    Base copy number 
+  //    z         Z coordinate where the front of the active silicon
+  //              should be in the mother volume, so we need to
+  //              subtract half the ring width.  
+  //    idRotId   Identity rotation matrix 
+  // 
+  // DebugGuard guard("AliFMDRing::Geometry");
+  AliDebug(10, "AliFMDRing::Geometry");
+  TString  name;
+  Double_t offsetZ   = (fSiThickness 
+                       + fPrintboardThickness 
+                       + fLegLength + fModuleSpacing) / 2;
+  name = Form("RNG%c", fId);
+  gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, "");
+}
+
+//____________________________________________________________________
+void 
+AliFMDRing::SimpleGeometry(TList* nodes, 
+                          TNode* mother, 
+                          Int_t colour, 
+                          Double_t z, 
+                          Int_t n) 
+{
+  // Make a simple geometry of the ring for event display. 
+  // 
+  // The simple geometry is made from ROOT TNode and TShape objects. 
+  // Note, that we cache the TShape and TRotMatrix objects used for
+  // this. 
+  // 
+  // Parameters
+  // 
+  //    nodes     List of nodes to register all create nodes in 
+  //    mother    Mother node to put the ring in. 
+  //    colour    Colour of the nodes 
+  //    z         Z position of the node in the mother volume 
+  //    n         Detector number
+  //
+  // DebugGuard guard("AliFMDRing::SimpleGeometry");
+  AliDebug(10, "AliFMDRing::SimpleGeometry");
+  SetupCoordinates();
+
+  // If the shape hasn't been defined yet, we define it here. 
+  if (!fShape) {
+    TString name(Form("ACT%c", fId));
+    TString title(Form("Shape of modules in %c Rings", fId));
+    Int_t n = fPolygon.GetNVerticies();
+    TXTRU* shape = new TXTRU(name.Data(), title.Data(), "void", n, 2);
+    for (Int_t i = 0; i < n; i++) {
+      const TVector2& v = fPolygon.GetVertex(i);
+      shape->DefineVertex(i, v.X(), v.Y());
+    }
+    shape->DefineSection(0, - fSiThickness / 2, 1, 0, 0);
+    shape->DefineSection(1, + fSiThickness / 2, 1, 0, 0);
+    fShape = shape;
+    fShape->SetLineColor(colour);
+  }
+  
+  Int_t    nModules  = 360 / Int_t(fTheta * 2);
+  Double_t dTheta    = fTheta * 2;
+
+  // If the roation matricies hasn't been defined yet, we do so here
+  if (!fRotMatricies) {
+    fRotMatricies = new TObjArray(nModules);
+    for (int i = 0; i < nModules; i++) {
+      Double_t theta  = (i + .5) * dTheta;
+      TString name(Form("FMD_ring_%c_rot", fId));
+      TString title(Form("FMD Ring %c Rotation", fId));
+      TRotMatrix* rot = 
+       new TRotMatrix(name.Data(), title.Data(), 
+                      90, theta, 90, fmod(90 + theta, 360), 0, 0);
+      fRotMatricies->AddAt(rot, i);
+    }
+  }
+
+  Double_t offsetZ   = (fSiThickness 
+                       + fPrintboardThickness
+                       + fLegLength + fModuleSpacing) / 2;
+
+  // Make all the nodes
+  for (int i = 0; i < nModules; i++) {
+    Bool_t    isFront = (i % 2 == 1);
+    mother->cd();
+    TRotMatrix* rot = static_cast<TRotMatrix*>(fRotMatricies->At(i));
+    TString name(Form("ACT%c_%d_%d", fId, n, i));
+    TString title(Form("Active FMD%d volume in %c Ring", n, fId));
+    TNode* node = new TNode(name.Data(), title.Data(), fShape, 
+                           0, 0, 
+                           z - offsetZ + (isFront ? fModuleSpacing : 0), 
+                           rot);
+    node->SetLineColor(colour);
+    nodes->Add(node);
+  }
+}
+
+  
+
+//____________________________________________________________________
+void 
+AliFMDRing::Gsatt() 
+{
+  // Set drawing attributes for the RING 
+  // 
+  // DebugGuard guard("AliFMDRing::Gsatt");
+  AliDebug(10, "AliFMDRing::Gsatt");
+  TString name;
+  name = Form("RNG%c",fId);
+  gMC->Gsatt(name.Data(), "SEEN", 0);
+
+  name = Form("VF%c",fId);
+  gMC->Gsatt(name.Data(), "SEEN", 0);
+
+  name = Form("VB%c",fId);
+  gMC->Gsatt(name.Data(), "SEEN", 0);
+
+  name = Form("ACT%c",fId);
+  gMC->Gsatt(name.Data(), "SEEN", 1);
+
+  name = Form("PBT%c",fId);
+  gMC->Gsatt(name.Data(), "SEEN", 1);
+
+  name = Form("PBB%c",fId);
+  gMC->Gsatt(name.Data(), "SEEN", 1);
+}
+
+//
+// EOF
+//
diff --git a/FMD/AliFMDRing.h b/FMD/AliFMDRing.h
new file mode 100644 (file)
index 0000000..e482b20
--- /dev/null
@@ -0,0 +1,123 @@
+// -*- mode: c++ -*-
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * Latest changes by Christian Holm Christensen <cholm@nbi.dk>
+ *
+ * See cxx source for full Copyright notice                               
+ */
+#ifndef ALIFMDRING_H
+#define ALIFMDRING_H
+#ifndef ALIFMDPOLYGON_H
+# include <AliFMDPolygon.h>
+#endif
+#ifndef ROOT_TArrayI
+# include <TArrayI.h>
+#endif
+
+class TBrowser;
+class TNode;
+class TObjArray;
+class TShape;
+class TList;
+
+
+//__________________________________________________________________
+struct AliFMDRing : public TObject
+{
+  Char_t   fId;                         // ID
+  Bool_t   fDetailed;
+  Int_t    fActiveId;           // Active volume 
+  Int_t    fPrintboardBottomId;  // Print board bottom volume
+  Int_t    fPrintboardTopId;     // Print board top volume
+  Int_t    fRingId;             // Ring volume
+  Int_t    fSectionId;          // Section volumes 
+  Int_t    fStripId;            // Strip volumes 
+  Int_t    fVirtualBackId;      // Virtual Back volume
+  Int_t    fVirtualFrontId;     // Virtual Front volume
+
+  Double_t fBondingWidth;       // With of bonding pad on sensor
+  Double_t fWaferRadius;        // Size of wafer the sensor was made from 
+  Double_t fSiThickness;        // Thickness of sensor
+  Double_t fLowR;               // Lower radius of ring
+  Double_t fHighR;              // Upper radius of ring
+  Double_t fTheta;              // Opening angle of the silicon wafers
+  Int_t    fNStrips;            // Number of strips 
+  Double_t fRingDepth;           // How far the ring extends beyond
+                                // the z value given. 
+  Double_t fLegRadius;          // Radius of support legs 
+  Double_t fLegLength;          // Radius of support legs 
+  Double_t fLegOffset;          // Radius of support legs 
+
+  Double_t fModuleSpacing;      // Staggering offset 
+  Double_t fPrintboardThickness; // Thickness of print board
+
+  TArrayI    fRotations;        // Array of rotations
+  TShape*    fShape;             // Shape used for event display
+  TObjArray* fRotMatricies;      // Matricies used for event display
+
+  AliFMDPolygon  fPolygon;              // Polygon shape 
+public:
+  //----------------------------------------------------------------
+  AliFMDRing(Char_t id='\0', Bool_t detailed=kTRUE);
+  virtual ~AliFMDRing();
+  void   Init();
+  bool   IsWithin(size_t moduleNo, double x, double y) const;
+  void   SetupCoordinates();  
+  void   SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, 
+                      Int_t pbRotId, Int_t idRotId);
+  void   Geometry(const char* mother, Int_t baseId, Double_t z, Int_t pbRotId,
+                 Int_t idRotId);
+  void   SimpleGeometry(TList* nodes, 
+                       TNode* mother, 
+                       Int_t colour, 
+                       Double_t z, 
+                       Int_t n);
+  void   Gsatt();
+  void   Draw(Option_t* opt="HOL") const; //*MENU*
+  void   Browse(TBrowser* b);
+  Bool_t IsFolder() const { return kTRUE; }
+  
+  Char_t   GetId()                  const { return fId; }
+  Int_t    GetActiveId()           const { return fActiveId; }
+  Int_t    GetPrintboardBottomId()  const { return fPrintboardBottomId; }
+  Int_t    GetPrintboardTopId()     const { return fPrintboardTopId; }
+  Int_t    GetRingId()             const { return fRingId; }
+  Int_t    GetSectionId()           const { return fSectionId; }
+  Int_t    GetStripId()                    const { return fStripId; }
+  Int_t    GetVirtualBackId()      const { return fVirtualBackId; }
+  Int_t    GetVirtualFrontId()     const { return fVirtualFrontId; }
+  Double_t GetBondingWidth()       const { return fBondingWidth; }
+  Double_t GetWaferRadius()        const { return fWaferRadius; }
+  Double_t GetSiThickness()        const { return fSiThickness; }
+  Double_t GetLowR()               const { return fLowR; }
+  Double_t GetHighR()              const { return fHighR; }
+  Double_t GetTheta()              const { return fTheta; }
+  Int_t    GetNStrips()                    const { return fNStrips; }
+  Int_t    GetNSectors()           const { return Int_t(360 / fTheta); }
+  Double_t GetLegRadius()          const { return fLegRadius; }
+  Double_t GetLegLength()          const { return fLegLength; }
+  Double_t GetModuleSpacing()      const { return fModuleSpacing; }
+  Double_t GetPrintboardThickness() const { return fPrintboardThickness; }
+  Double_t GetRingDepth()           const { return fRingDepth; }
+
+  void SetBondingWidth(Double_t width)           { fBondingWidth = width; }
+  void SetWaferRadius(Double_t radius)           { fWaferRadius = radius; } 
+  void SetSiThickness(Double_t thickness)        { fSiThickness = thickness; }
+  void SetLowR(Double_t lowR)                    { fLowR = lowR; }
+  void SetHighR(Double_t highR)                          { fHighR = highR; }
+  void SetTheta(Double_t theta)                          { fTheta = theta; }
+  void SetNStrips(Int_t nStrips)                 { fNStrips = nStrips; }
+  void SetLegRadius(Double_t radius)             { fLegRadius = radius; }
+  void SetLegLength(Double_t length)             { fLegLength = length; }
+  void SetLegOffset(Double_t offset)             { fLegOffset = offset; }
+
+  void SetModuleSpacing(Double_t       spacing)          { fModuleSpacing = spacing; }
+  void SetPrintboardThickness(Double_t thickness) { fPrintboardThickness = thickness; }
+
+  ClassDef(AliFMDRing, 1) // Ring volume parameters 
+};
+#endif 
+//
+// EOF
+//
diff --git a/FMD/AliFMDSubDetector.cxx b/FMD/AliFMDSubDetector.cxx
new file mode 100644 (file)
index 0000000..977f761
--- /dev/null
@@ -0,0 +1,289 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Utility class to help implement the FMD geometry.  This provides
+// the interface for the concrete geometry implementations of the FMD
+// sub-detectors. 
+//
+// The AliFMD object owns the AliFMDSubDetector objects
+//
+// Latest changes by Christian Holm Christensen
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef ALIFMDSUBDETECTOR_H
+# include "AliFMDSubDetector.h"
+#endif
+#ifndef ALILOG_H
+# include "AliLog.h"
+#endif
+#ifndef ROOT_TVirtualMC
+# include <TVirtualMC.h>
+#endif
+#ifndef ROOT_TList
+# include <TList.h>
+#endif
+#ifndef ROOT_TString
+# include <TString.h>
+#endif
+#ifndef __IOSTREAM__
+# include <iostream>
+#endif
+
+ClassImp(AliFMDSubDetector);
+
+//____________________________________________________________________
+AliFMDSubDetector::AliFMDSubDetector(Int_t n)
+  : fId(n), 
+    fInnerZ(0), 
+    fOuterZ(0), 
+    fInner(0), 
+    fOuter(0)
+{}
+
+//____________________________________________________________________
+void 
+AliFMDSubDetector::Draw(Option_t* /* opt */) const 
+{
+  // DebugGuard guard("AliFMDSubDetector::Draw");
+  AliDebug(10, "AliFMDSubDetector::Draw");
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDSubDetector::CheckHit(Char_t ring, Int_t module, Double_t x, Double_t y) 
+{
+  // Check if a hit (x,y) in module module of ring ring is within the
+  // actual shape. 
+  Bool_t ret = kFALSE;
+  switch (ring) {
+  case 'i':
+  case 'I': 
+    if (!fInner) break;
+    ret = fInner->IsWithin(module, x, y);
+    break;
+  case 'o':
+  case 'O': 
+    if (!fOuter) break;
+    ret = fOuter->IsWithin(module, x, y);
+    break;
+  }
+  return ret;
+}
+
+//____________________________________________________________________
+void 
+AliFMDSubDetector::SimpleGeometry(TList* nodes, 
+                                 TNode* mother, 
+                                 Int_t colour, 
+                                 Double_t zMother) 
+{
+  // Make a simplified geometry for event display 
+  // 
+  // Parameters
+  // 
+  //    nodes     List of nodes to register all create nodes in 
+  //    mother    Mother node to put the ring in. 
+  //    colour    Colour of the nodes 
+  //    zMother   Z position of the node in the mother volume 
+  // 
+  for (int i = 0; i < 2; i++) {
+    AliFMDRing* r = 0;
+    Double_t z = 0;
+    switch (i) {
+    case 0: 
+      r     = fInner;
+      z     = fInnerZ;
+      break;
+    case 1: 
+      r     =  fOuter;
+      z     =  fOuterZ;
+      break;
+    }
+    if (!r) continue;
+
+    // Make the coordinates relative to the mother volume.   If we're
+    // on the positive side, then we need to flip the z-coordinate, as
+    // we'll rotate the whole sub-detector afterwards. 
+    z -= zMother;
+    if (zMother > 0) z *= -1;
+    
+    r->SimpleGeometry(nodes, mother, colour, z, fId);
+  }
+}
+
+  
+//____________________________________________________________________
+void 
+AliFMDSubDetector::SetupGeometry(Int_t airId, Int_t kaptionId) 
+{
+  // Set up the geometry of this particular detector. 
+  // 
+  // In this class, it defines the support honey comp calls and
+  // nothing else. 
+  // 
+  // Parameters
+  //   airId           Medium of inactive virtual volumes 
+  //   kaptionId       Medium of honeycomb
+  // 
+  // DebugGuard guard("AliFMDSubDetector::SetupGeometry");
+  AliDebug(10, "AliFMDSubDetector::SetupGeometry");
+  TString name;
+  Double_t par[5];
+
+  for (int i = 0; i < 2; i++) {
+    AliFMDRing* r       = 0;
+    char  c = '\0';
+    switch (i) {
+    case 0: 
+      r      = fInner;
+      c      = 'I';
+      par[0] = fInnerHoneyLowR;
+      par[1] = fInnerHoneyHighR;
+      break;
+    case 1: 
+      r     = fOuter;
+      c     = 'O';
+      par[0] = fOuterHoneyLowR;
+      par[1] = fOuterHoneyHighR;
+      break;
+    }
+    if (!r) continue;
+    // Top of honeycomb, inner ring 
+    par[2] = fHoneycombThickness / 2;
+    par[3] = 0;
+    par[4] = 180;
+    name   = Form("HT%c%d", c, fId);
+    gMC->Gsvolu(name.Data(), "TUBS", kaptionId, par, 5);
+    
+    // Bottom of honeycomb, inner ring 
+    par[3] = 180;
+    par[4] = 360;
+    name   = Form("HB%c%d", c, fId);
+    gMC->Gsvolu(name.Data(), "TUBS", kaptionId, par, 5);
+    
+    // Air in top of honeycomb, inner ring 
+    par[0] += fKaptionThickness;
+    par[1] -= fKaptionThickness;
+    par[2] -= fKaptionThickness;
+    par[3] = 0;
+    par[4] = 180;
+    name   = Form("GT%c%d", c, fId);
+    gMC->Gsvolu(name.Data(), "TUBS", airId, par, 5);
+    
+    // Air in bottom of honeycomb, inner ring 
+    par[3] = 180;
+    par[4] = 360;
+    name   = Form("GB%c%d", c, fId);
+    gMC->Gsvolu(name.Data(), "TUBS", airId, par, 5);
+  }
+}
+
+//____________________________________________________________________
+void 
+AliFMDSubDetector::Geometry(const char* mother, Int_t pbRotId, Int_t idRotId, 
+                     Double_t zMother) 
+{
+  // Place the volume inside mother volume. 
+  // 
+  // Parameters
+  // 
+  //     mother     Volume to position this detector in 
+  //     pbRotId    Print board rotation matrix, 
+  //     idRotId    Identity rotation matrix 
+  //     zMother    The Z passed in, is the position of the middle
+  //                point of the mother volume. 
+  // 
+  // In this base class, it asks the contained rings to position
+  // themselves in the mother volume, and positions the honey comb
+  // support in the mother volume 
+  // 
+  // DebugGuard guard("AliFMDSubDetector::Geometry");
+  AliDebug(10, "AliFMDSubDetector::Geometry");
+
+  Double_t  ringW;
+  Double_t  z = 0;
+  // Double_t* b = 0;
+  TString name;
+  TString name2;
+  
+  for (int i = 0; i < 2; i++) {
+    AliFMDRing* r = 0;
+    char  c = '\0';
+    switch (i) {
+    case 0: 
+      r     = fInner;
+      c     = 'I';
+      z     = fInnerZ;
+      break;
+    case 1: 
+      r     =  fOuter;
+      c     =  'O';
+      z     =  fOuterZ;
+      break;
+    }
+    if (!r) continue;
+
+    // Make the coordinates relative to the mother volume.   If we're
+    // on the positive side, then we need to flip the z-coordinate, as
+    // we'll rotate the whole sub-detector afterwards. 
+    z -= zMother;
+    if (zMother > 0) z *= -1;
+    
+    r->Geometry(mother, fId, z, pbRotId, idRotId);
+    ringW =  r->GetRingDepth();
+    z     -= ringW + fHoneycombThickness / 2;
+
+    // Top of honeycomb
+    name = Form("HT%c%d", c, fId);
+    gMC->Gspos(name.Data(), 1, mother, 0, 0, z, idRotId);
+
+    // Air in top of honeycomb
+    name2 = name;
+    name  = Form("GT%c%d", c, fId);
+    gMC->Gspos(name.Data(), 1, name2.Data(),0,fKaptionThickness,0,idRotId);
+    
+    // Bottom of honeycomb
+    name = Form("HB%c%d", c, fId);
+    gMC->Gspos(name.Data(), 1, mother, 0, 0, z, idRotId);
+
+    // Air in bottom of honeycomb
+    name2 = name;
+    name  = Form("GB%c%d", c, fId);
+    gMC->Gspos(name.Data(),1,name2.Data(),0,-fKaptionThickness,0,idRotId);
+  }
+}
+
+//____________________________________________________________________
+void
+AliFMDSubDetector::Gsatt() 
+{
+  // Set drawing attributes for the detector 
+  // 
+  // DebugGuard guard("AliFMDSubDetector::Gsatt");
+  AliDebug(10, "AliFMDSubDetector::Gsatt");
+  TString name(Form("FMD%d", fId));
+  gMC->Gsatt(name.Data(), "SEEN", 0);
+}
+
+
+//____________________________________________________________________
+// 
+// EOF
+//
diff --git a/FMD/AliFMDSubDetector.h b/FMD/AliFMDSubDetector.h
new file mode 100644 (file)
index 0000000..4167782
--- /dev/null
@@ -0,0 +1,79 @@
+// -*- mode: c++ -*-
+#ifndef ALIFMDSUBDETECTOR_H
+#define ALIFMDSUBDETECTOR_H
+#ifndef ROOT_TObject
+# include <TObject.h>
+#endif
+#ifndef ALIFMDRING_H
+# include <AliFMDRing.h>
+#endif
+
+class TNode;
+class TList;
+
+
+//__________________________________________________________________
+struct AliFMDSubDetector : public TObject
+{
+protected:
+  Int_t       fId;                 // Detector number 
+  Double_t    fInnerZ;             // Position of outer ring along z
+  Double_t    fOuterZ;             // Position of outer ring along z 
+  Double_t    fHoneycombThickness; // Thickness of honeycomb plate 
+  Double_t    fKaptionThickness;   // Thickness of kaption of honeycomb
+  Double_t    fInnerHoneyLowR;     // Inner radius of inner honeycomb
+  Double_t    fInnerHoneyHighR;    // Outer radius of inner honeycomb
+  Int_t       fInnerHoneyTopId;    // Volume ID of top of inner honeycomb
+  Int_t       fInnerHoneyBottomId; // Volume ID of bottom of inner honeycomb
+  Double_t    fOuterHoneyLowR;     // Inner radius of outer honeycomb
+  Double_t    fOuterHoneyHighR;    // Outer radius of outer honeycomb
+  Int_t       fOuterHoneyTopId;    // Volume ID of top of outer honeycomb   
+  Int_t       fOuterHoneyBottomId; // Volume ID of bottom of outer honeycomb
+
+  Int_t       fRotationId;
+  
+  AliFMDRing* fInner;              // Reference to inner ring description
+  AliFMDRing* fOuter;              // Reference to outer ring description
+public:  
+  AliFMDSubDetector(Int_t n);
+  virtual ~AliFMDSubDetector() {}
+  virtual void   SetupGeometry(Int_t airId, Int_t kaptionId);  
+  virtual void   Geometry(const char* mother, Int_t pbRotId, 
+                         Int_t idRotId, Double_t z=0);
+  virtual void   SimpleGeometry(TList* nodes, 
+                               TNode* mother, 
+                               Int_t colour, 
+                               Double_t zMother);
+  
+  virtual void   Gsatt();
+  virtual void   Draw(Option_t* option="BIOL0") const; //*MENU*
+  virtual Bool_t CheckHit(Char_t ring, Int_t module, Double_t x, Double_t y);
+
+  void   SetInner(AliFMDRing* r)             { fInner = r; }
+  void   SetOuter(AliFMDRing* r)             { fOuter = r; }
+  void   SetInnerZ(Double_t z)               { fInnerZ = z; }
+  void   SetOuterZ(Double_t z)               { fOuterZ = z; }
+  void   SetHoneycombThickness(Double_t t=1) { fHoneycombThickness = t; }
+  void   SetInnerHoneyLowR(Double_t r) { fInnerHoneyLowR = r; }
+  void   SetInnerHoneyHighR(Double_t r) { fInnerHoneyHighR = r; }
+  void   SetOuterHoneyLowR(Double_t r) { fOuterHoneyLowR = r; }
+  void   SetOuterHoneyHighR(Double_t r) { fOuterHoneyHighR = r; }
+  void   SetKaptionThickness(Double_t t=.1)   { fKaptionThickness = t; }
+     
+  Double_t    GetInnerZ()             const { return fInnerZ; }
+  Double_t    GetOuterZ()             const { return fOuterZ; }
+  AliFMDRing* GetInner()              const { return fInner; }
+  AliFMDRing* GetOuter()              const { return fOuter; }
+  Double_t    GetHoneycombThickness() const { return fHoneycombThickness; }
+  Double_t    GetInnerHoneyLowR() const { return fInnerHoneyLowR; }
+  Double_t    GetInnerHoneyHighR() const { return fInnerHoneyHighR; }
+  Double_t    GetOuterHoneyLowR() const { return fOuterHoneyLowR; }
+  Double_t    GetOuterHoneyHighR() const { return fOuterHoneyHighR; }
+  Double_t    GetKaptionThickness()   const { return fKaptionThickness; }
+  Int_t       GetId()                 const { return fId; }     
+  Bool_t      IsFolder()              const { return kTRUE; }
+
+  ClassDef(AliFMDSubDetector, 1) // Sub detectors
+};
+
+#endif
diff --git a/FMD/AliFMDdigit.cxx b/FMD/AliFMDdigit.cxx
deleted file mode 100644 (file)
index 9f645f5..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-////////////////////////////////////////////////
-//  Digits classes for set:FMD                //
-////////////////////////////////////////////////
-
-
-#include "AliFMDdigit.h"
-
-ClassImp(AliFMDdigit)
-
-AliFMDdigit::AliFMDdigit(Int_t *digits) {
-  //
-  // Creates a real data digit object
-  //
-  fNumOfDet       = digits[0];
-  fNumOfSector    = digits[1];
-  fNumOfRing      = digits[2];
-  fNelectrons     = digits[3];
-  fADC            = digits[4];
-}
-
diff --git a/FMD/AliFMDdigit.h b/FMD/AliFMDdigit.h
deleted file mode 100644 (file)
index fc28cb7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef ALIFMDDIGIT_H
-#define ALIFMDDIGIT_H
-
-////////////////////////////////////////////////
-//  Digits classes for set:FMD                //
-////////////////////////////////////////////////
-#include <TClonesArray.h>
-#include <TObject.h>
-
-
-//___________________________________________
-class AliFMDdigit: public TObject  {
-  
-private:
-  Int_t fNumOfDet ;       //Number of FMD disk
-  Int_t fNumOfSector ;    //Number of sector
-  Int_t fNumOfRing;       //Number of ring
-  Int_t fNelectrons;      // real charge
-  Int_t fADC;             // ADC signal for this charge
-public:
-  AliFMDdigit() {
-    // constructor
-    fNumOfDet=fNumOfSector=fNumOfRing=fNelectrons=fADC=0;
-  }
-  AliFMDdigit(Int_t *digits);
-  virtual ~AliFMDdigit() {
-    // destructor
-  }
-  Int_t Volume();
-  Int_t NumberOfSector();
-  Int_t NumberOfRing();
-  Int_t Charge();
-  Int_t ADCsignal();
-  
-  ClassDef(AliFMDdigit,1)     // Real data digit object for set:ITS
-};
-inline Int_t AliFMDdigit::Volume(){return fNumOfDet;}
-inline Int_t AliFMDdigit::NumberOfSector() {return fNumOfSector;} 
-inline Int_t AliFMDdigit::NumberOfRing() {return fNumOfRing;}
-inline Int_t AliFMDdigit::Charge() {return fNelectrons;}
-inline Int_t AliFMDdigit::ADCsignal() {return fADC;}
-
-
-#endif
diff --git a/FMD/AliFMDv0.cxx b/FMD/AliFMDv0.cxx
deleted file mode 100644 (file)
index f8b2f7a..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/**************************************************************************
- * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- *                                                                        *
- * Author: The ALICE Off-line Project.                                    *
- * Contributors are mentioned in the code where appropriate.              *
- *                                                                        *
- * Permission to use, copy, modify and distribute this software and its   *
- * documentation strictly for non-commercial purposes is hereby granted   *
- * without fee, provided that the above copyright notice appears in all   *
- * copies and that both the copyright notice and this permission notice   *
- * appear in the supporting documentation. The authors make no claims     *
- * about the suitability of this software for any purpose. It is          *
- * provided "as is" without express or implied warranty.                  *
- **************************************************************************/
-
-/* $Id$ */
-
- /////////////////////////////////////////////////////////////////////
-//                                                                 //
-// Forward Multiplicity detector based on Silicon version 0        //
-//
-//Begin Html       
-/*
-<img src="gif/AliFMDv0Class.gif">
-*/
-//End Html
-//                                                                  //
-//                                                                  //
-//////////////////////////////////////////////////////////////////////
-
-#include <Riostream.h>
-#include <stdlib.h>
-
-#include <TGeometry.h>
-#include <TLorentzVector.h>
-#include <TMath.h>
-#include <TNode.h>
-#include <TTUBE.h>
-#include <TLorentzVector.h>
-#include <TVirtualMC.h>
-
-#include "AliFMDv0.h"
-#include "AliMagF.h"
-#include "AliRndm.h"
-#include "AliRun.h"
-#include "AliFMDhit.h"
-
-ClassImp(AliFMDv0)
-
-//--------------------------------------------------------------------
-AliFMDv0::AliFMDv0(const char *name, const char *title):
- AliFMD(name,title)
-{
-  //
-  // Standart constructor for Forward Multiplicity Detector version 0
-  //
-  fIdSens1=0;
-  fIdSens2=0;
-  fIdSens3=0;
-  fIdSens4=0;
-  fIdSens5=0;
-//  setBufferSize(128000);
-}
-//-------------------------------------------------------------------------
-
-void AliFMDv0::CreateGeometry()
-{
-//
-  // Create the geometry of Forward Multiplicity Detector version 0
-  //
-  //Detector consists of 6 volumes: 
-  // 1st covered pseudorapidity interval from 3.3 to 2.0
-  // and placed on 65cm in Z-direction;
-  // 2nd - from 2.0 to 1.6 and Z=85 cm;
-  // 3d  - the same pseudorapidity interval as the 1st 
-  // but on the other side from the interaction point z=-65cm;
-  // 4th - simmetricaly with the 2nd : 
-  // pseudorapidity from 2.0 to 1.6, Z=-85cm   
-  // 5th - from 3.6 to 4.7, Z=-270cm
-  // 6th - from 4.5 to 5.5 , Z=-630cm.
-  // Each part has 400mkm Si (sensetive area, detector itself),
-  // 0.75cm of plastic simulated electronics material,
-  // Al support ring 2cm thickness and 1cm width placed on 
-  // the outer radius of each Si disk;
-  //    
-  // begin Html
-  /*
-   <img src="gif/AliFMDv0.gif">
-   */
-  //
-
-
-
-  Int_t *idtmed = fIdtmed->GetArray();
-   
-  Int_t ifmd;
-  Int_t idrotm[999];
-  Float_t zFMD,par[3],ppcon[15];
-  Float_t z[5]={-62.8, -75.2, 83.4, 75.2, 340.};
-  Float_t NylonTube[3]={0.2,0.6,0.45};
-  Float_t zPCB=0.12; Float_t zHoneyComb=0.5; 
-  Float_t zSi=0.03;
-  char nameFMD[5], nameSi[5], nameSector[5], nameRing[5];
-  Char_t nameHoney[5], nameHoneyIn[5], nameHoneyOut[5];
-  Char_t namePCB[5], nameCopper[5], nameChips[5], nameG10[5];
-  Char_t nameLPCB[5], nameLCopper[5], nameLChips[5], nameGL10[5];;
-  Float_t rin[5]={4.2,15.4,4.2,15.4,4.2};
-  Float_t rout[5]={17.4,28.4,17.4,28.4,17.4};
-  Float_t RinHoneyComb[5] ={ 5.15,16.4,  5.15,16.4,  5.15};
-  Float_t RoutHoneyComb[5]={20.63,34.92,22.3, 32.02,20.63};
-  Float_t zInside;
-  Float_t zCooper=0.01; Float_t zChips=0.01;
-  Float_t yNylonTube[5]={10,20,10,20,10};
-
-
-  AliMatrix(idrotm[901], 90, 0, 90, 90, 180, 0);
-  
-  
-  // Nylon tubes
-   gMC->Gsvolu("GNYL","TUBE", idtmed[1], NylonTube, 3);  //support nylon tube
-   Float_t wideSupport=zSi+3*zPCB+2*NylonTube[2]+zHoneyComb;
-     cout<<" wideSupport "<<wideSupport<<endl;
-
- for (ifmd=0; ifmd<5; ifmd++)
-    {
-      sprintf(nameFMD,"FMD%d",ifmd+1);
-      ppcon[0]=0;
-      ppcon[1]=360;
-      ppcon[2]=4;
-      
-      ppcon[3]=-wideSupport;
-      ppcon[4]=rin[ifmd]+0.1;
-      ppcon[5]=rout[ifmd]+0.1;
-      
-      ppcon[6]=ppcon[3]+2*zSi+2*zPCB+2*NylonTube[2];
-      ppcon[7]=rin[ifmd]+0.1;
-      ppcon[8]=rout[ifmd]+0.1;
-      
-      ppcon[9]=ppcon[6];
-      ppcon[10]=RinHoneyComb[ifmd]+0.1;
-      ppcon[11]=RoutHoneyComb[ifmd]+0.1;
-
-      ppcon[12]=ppcon[9]+2*zHoneyComb+zPCB;
-      ppcon[13]=RinHoneyComb[ifmd]+0.1;
-      ppcon[14]=RoutHoneyComb[ifmd]+0.1;
-      gMC->Gsvolu(nameFMD,"PCON",idtmed[0],ppcon,15);
-      if (z[ifmd] >0){  
-        zFMD=z[ifmd]+wideSupport;
-        gMC->Gspos(nameFMD,1,"ALIC",0,0,zFMD,0, "ONLY");}
-      else {
-        zFMD=z[ifmd]-wideSupport;
-        gMC->Gspos(nameFMD,1,"ALIC",0,0,zFMD,idrotm[901], "ONLY");}
-     //silicon
-      sprintf(nameSi,"GSI%d",ifmd+1);
-      sprintf(nameSector,"GSC%d",ifmd+1);
-      sprintf(nameRing,"GRN%d",ifmd+1);
-      
-      //honeycomb support
-      sprintf(nameHoney,"GSU%d",ifmd+1);
-      gMC->Gsvolu(nameHoney,"TUBE", idtmed[0], par, 0);  //honeycomb 
-      sprintf(nameHoneyIn,"GHI%d",ifmd+1);
-      gMC->Gsvolu(nameHoneyIn,"TUBE", idtmed[7], par, 0);  //honey comb inside 
-      sprintf(nameHoneyOut,"GHO%d",ifmd+1);
-      gMC->Gsvolu(nameHoneyOut,"TUBE", idtmed[6], par, 0);  //honey comb skin
-      //PCB
-      sprintf(namePCB,"GPC%d",ifmd+1);
-      gMC->Gsvolu(namePCB,"TUBE", idtmed[0], par, 0); //PCB
-      sprintf(nameCopper,"GCO%d",ifmd+1);
-      gMC->Gsvolu(nameCopper,"TUBE", idtmed[3], par, 0);  // Cooper
-      sprintf(nameChips,"GCH%d",ifmd+1);
-      gMC->Gsvolu(nameChips,"TUBE", idtmed[5], par, 0); // Si chips
-      sprintf(nameG10,"G10%d",ifmd+1);
-      gMC->Gsvolu(nameG10,"TUBE", idtmed[2], par, 0);  //G10 plate
-      //last PCB
-      sprintf(nameLPCB,"GPL%d",ifmd+1);
-      gMC->Gsvolu(nameLPCB,"TUBE", idtmed[0], par, 0); //PCB
-      sprintf(nameLCopper,"GCL%d",ifmd+1);
-      gMC->Gsvolu(nameLCopper,"TUBE", idtmed[3], par, 0);  // Cooper
-      sprintf(nameLChips,"GHL%d",ifmd+1);
-      gMC->Gsvolu(nameLChips,"TUBE", idtmed[5], par, 0); // Si chips
-      sprintf(nameGL10,"G1L%d",ifmd+1);
-      gMC->Gsvolu(nameGL10,"TUBE", idtmed[2], par, 0); // Last G10
-      par[0]=rin[ifmd]; // pipe size
-      par[1]=rout[ifmd];
-      par[2]=zSi/2;
-      gMC->Gsvolu(nameSi,"TUBE", idtmed[4], par, 3);
-      zInside=ppcon[3]+par[2];
-       gMC->Gspos(nameSi,ifmd+1,nameFMD,0,0,zInside,0, "ONLY");
-      //PCB 1
-      zInside += par[2]+zPCB/2;
-      par[2]=zPCB/2;
-      gMC->Gsposp(namePCB,1,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      zInside += zPCB;
-      gMC->Gsposp(namePCB,2,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      Float_t NulonTubeBegin=zInside+2.5*zPCB;
-      par[2]=zPCB/2-0.02;
-      Float_t zInPCB = -zPCB/2+par[2];
-      gMC->Gsposp(nameG10,1,namePCB,0,0,zInPCB,0, "ONLY",par,3);
-      zInPCB+=par[2]+zCooper/2 ;
-      par[2]=zCooper/2;
-      gMC->Gsposp(nameCopper,1,namePCB,0,0,zInPCB,0, "ONLY",par,3);
-      zInPCB += zCooper/2 + zChips/2;
-      par[2]=zChips/2;
-      gMC->Gsposp(nameChips,1,namePCB,0,0,zInPCB,0, "ONLY",par,3);
-      //HoneyComb
-      zHoneyComb=0.8;   
-      par[0] = RinHoneyComb[ifmd];
-      par[1] = RoutHoneyComb[ifmd];
-      par[2] = zHoneyComb/2;
-      zInside += 2*NylonTube[2]+par[2];
-      gMC->Gsposp(nameHoney,1,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      par[2]=0.1/2;
-      Float_t zHoney=-zHoneyComb/2+par[2];
-      gMC->Gsposp(nameHoneyOut,1,nameHoney,0,0,zHoney,0,
-                  "ONLY",par,3); //shkurki
-      zHoney=zHoneyComb/2-par[2];
-      gMC->Gsposp(nameHoneyOut,2,nameHoney,0,0,zHoney,0, "ONLY",par,3);
-      par[2]=(zHoneyComb-2.*0.1)/2; //soty vnutri
-      gMC->Gsposp(nameHoneyIn,1,nameHoney,0,0,0,0, "ONLY",par,3);
-      
-      gMC->Gspos("GNYL",1,nameFMD,0,yNylonTube[ifmd],
-                 NulonTubeBegin+NylonTube[2]/2.,0, "ONLY");
-      gMC->Gspos("GNYL",2,nameFMD,0,-yNylonTube[ifmd],
-                 NulonTubeBegin+NylonTube[2]/2.,0, "ONLY");
-         
-      //last PCB
-      par[0]=RoutHoneyComb[ifmd]-9;
-      par[1]=RoutHoneyComb[ifmd];
-      par[2]=zPCB/2;
-      zInside += zHoneyComb/2+par[2];
-      gMC->Gsposp(nameLPCB,1,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      
-       par[2]=zPCB/2-0.02;
-       zInPCB = -zPCB/2+par[2];
-       gMC->Gsposp(nameGL10,1,nameLPCB,0,0,zInPCB,0, "ONLY",par,3);
-       zInPCB+=par[2]+zCooper/2 ;
-       par[2]=zCooper/2;
-       gMC->Gsposp(nameLCopper,1,nameLPCB,0,0,zInPCB,0, "ONLY",par,3);
-       zInPCB += zCooper/2 + zChips/2;
-       par[2]=zChips/2;
-       gMC->Gsposp(nameLChips,1,nameLPCB,0,0,zInPCB,0, "ONLY",par,3);
-      
-           
-     //Granularity
-       fSectorsSi1=20;
-       fRingsSi1=256*2;
-    // fRingsSi1=3; // for drawing only
-       fSectorsSi2=40;
-       fRingsSi2=128*2;
-     //  fRingsSi2=3; //for  drawing onl
-    if(ifmd==1||ifmd==3)
-      { 
-        gMC->Gsdvn(nameSector, nameSi , fSectorsSi2, 2);
-        gMC->Gsdvn(nameRing, nameSector, fRingsSi2, 1);
-      }
-    else
-      {
-        gMC->Gsdvn(nameSector, nameSi , fSectorsSi1, 2);
-        gMC->Gsdvn(nameRing, nameSector , fRingsSi1, 1);
-      }
-    
-    }
-}    
-
-
-//------------------------------------------------------------------------
-void AliFMDv0::CreateMaterials() 
-{
- Int_t isxfld   = gAlice->Field()->Integ();
- Float_t sxmgmx = gAlice->Field()->Max();
-
- // Plastic CH
- Float_t aPlastic[2]={1.01,12.01};
- Float_t zPlastic[2]={1,6};
- Float_t wPlastic[2]={1,1};
- Float_t denPlastic=1.03;
-   //
-  //     60% SiO2 , 40% G10FR4 
- // PC board
- Float_t apcb[3]  = { 28.0855,15.9994,17.749 };
- Float_t zpcb[3]  = { 14.,8.,8.875 };
- Float_t wpcb[3]  = { .28,.32,.4 };
- Float_t denspcb  = 1.8;
-   //
-// AIR
-                                                                                           Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
-Float_t zAir[4]={6.,7.,8.,18.};
-Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
-Float_t dAir = 1.20479E-3;
-                                                                                            //*** Definition Of avaible FMD materials ***
- AliMixture(0, "FMD Air$", aAir, zAir, dAir, 4,wAir);
- AliMixture(1, "Plastic$",aPlastic,zPlastic,denPlastic,-2,wPlastic);
- AliMixture(2, "SSD PCB$",   apcb, zpcb, denspcb, 3, wpcb);
- AliMaterial(3, "SSD Copper$", 63.546, 29., 8.96, 1.43, 999.);
- AliMaterial(4, "SSD Si$",      28.0855, 14., 2.33, 9.36, 999.);
- AliMaterial(5, "SSD Si chip$", 28.0855, 14., 2.33, 9.36, 999.);
- AliMaterial(6, "SSD C$",       12.011,   6., 2.265,18.8, 999.);
- AliMaterial(7, "SSD Kapton$", 12.011, 6., 0.01, 31.27, 999.);//honeycomb
-  AliMaterial(8, "SSD G10FR4$", 17.749, 8.875, 1.8, 21.822, 999.);
-   
-
-//**
- AliMedium(0, "FMD air$", 0, 0, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(1, "Plastic$", 1, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(2, "SSD PCB$", 2, 0, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(3, "SSD Copper$", 3, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(4, "SSD Si$", 4, 1, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(5, "SSD Si chip$", 5, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(6, "SSD C$", 6, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(7, "SSD Kapton$", 7, 0, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(8, "SSD G10FR4$", 8, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
-
-
-}
-//---------------------------------------------------------------------
-void AliFMDv0::DrawDetector()
-{
-//
-// Draw a shaded view of the Forward multiplicity detector version 0
-//
-
-
-//Set ALIC mother transparent
-gMC->Gsatt("ALIC","SEEN",0);
-//
-//Set volumes visible
-gMC->Gsatt("FMD0","SEEN",1);
-gMC->Gsatt("FMD1","SEEN",1);
-gMC->Gsatt("FMD2","SEEN",1);
-gMC->Gsatt("FMD3","SEEN",1);
-gMC->Gsatt("FMD4","SEEN",1);
-gMC->Gsatt("FMD5","SEEN",1);
-
-//
-gMC->Gdopt("hide","on");
-gMC->Gdopt("shad","on");
-gMC->SetClipBox(".");
-gMC->SetClipBox("*",0,1000,-1000,1000,-1000,1000);
-gMC->DefaultRange();
-gMC->Gdraw("alic",40,30,0,12,9.5,.2,0.2);
-gMC->Gdhead(1111,"Forward multiplicity detector");
-gMC->Gdopt("hide","off");
-}
-//-------------------------------------------------------------------
-void AliFMDv0::Init()
-{
-// Initialises version 0 of the Forward Multiplicity Detector
-//
-AliFMD::Init();
-fIdSens1=gMC->VolId("GRN1");
-fIdSens2=gMC->VolId("GRN2");
-fIdSens3=gMC->VolId("GRN3");
-fIdSens4=gMC->VolId("GRN4");
-fIdSens5=gMC->VolId("GRN5");
-if (fDebug) printf("*** FMD version 0 initialized ***\n");
-}
-
-//-------------------------------------------------------------------
-
-void AliFMDv0::StepManager()
-{
-  //
-  // Called for every step in the Forward Multiplicity Detector
-  //
-}
-
diff --git a/FMD/AliFMDv0.h b/FMD/AliFMDv0.h
deleted file mode 100644 (file)
index 398339a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef ALIFMDV0_H
-#define ALIFMDV0_H
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
-
-///////////////////////////////////////////////
-//  Manager and hits classes for set:FMD     //
-////////////////////////////////////////////////
-#include "AliFMD.h"
-class AliFMDv0 : public AliFMD {
-  
-public:
-  AliFMDv0() {};
-  AliFMDv0(const char *name, const char *title);
-  virtual       ~AliFMDv0() {}
-  virtual void   CreateGeometry();
-  virtual void   CreateMaterials();
-  virtual void   DrawDetector();
-  virtual void   Init();
-  virtual Int_t  IsVersion() const {return 0;}
-  virtual void   StepManager();
-  
-protected:
-  Int_t fIdSens1; // Sensetive volume  in FMD
-  Int_t fIdSens2; // Sensetive volume  in FMD
-  Int_t fIdSens3; // Sensetive volume  in FMD
-  Int_t fIdSens4; // Sensetive volume  in FMD
-  Int_t fIdSens5; // Sensetive volume  in FMD
-   
-
-   
-  ClassDef(AliFMDv0,2)  //Class for FMD version 0
-};
-
-#endif
-
-
diff --git a/FMD/AliFMDv1.cxx b/FMD/AliFMDv1.cxx
deleted file mode 100644 (file)
index a0e4b2a..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/**************************************************************************
- * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- *                                                                        *
- * Author: The ALICE Off-line Project.                                    *
- * Contributors are mentioned in the code where appropriate.              *
- *                                                                        *
- * Permission to use, copy, modify and distribute this software and its   *
- * documentation strictly for non-commercial purposes is hereby granted   *
- * without fee, provided that the above copyright notice appears in all   *
- * copies and that both the copyright notice and this permission notice   *
- * appear in the supporting documentation. The authors make no claims     *
- * about the suitability of this software for any purpose. It is          *
- * provided "as is" without express or implied warranty.                  *
- **************************************************************************/
-
-/* $Id$ */
-
- /////////////////////////////////////////////////////////////////////
-//                                                                 //
-// Forward Multiplicity detector based on Silicon version 0        //
-//
-//Begin Html       
-/*
-<img src="gif/AliFMDv0Class.gif">
-*/
-//End Html
-//                                                                  //
-//                                                                  //
-//////////////////////////////////////////////////////////////////////
-
-#include <Riostream.h>
-#include <stdlib.h>
-
-#include <TClonesArray.h>
-#include <TDirectory.h>
-#include <TFile.h>
-#include <TGeometry.h>
-#include <TLorentzVector.h>
-#include <TMath.h>
-#include <TNode.h>
-#include <TTUBE.h>
-#include <TTree.h>
-#include <TVirtualMC.h>
-
-#include "AliFMDdigit.h"
-#include "AliFMDhit.h"
-#include "AliFMDv0.h"
-#include "AliFMDv1.h"
-#include "AliMagF.h"
-#include "AliRun.h"
-#include "AliMC.h"
-
-ClassImp(AliFMDv1)
-
-//--------------------------------------------------------------------
-AliFMDv1::AliFMDv1(const char *name, const char *title):
- AliFMD(name,title)
-{
-  //
-  // Standart constructor for Forward Multiplicity Detector version 0
-  //
-  fIdSens1=0;
-  fIdSens2=0;
-  fIdSens3=0;
-  fIdSens4=0;
-  fIdSens5=0;
-//  setBufferSize(128000);
- }
-//-------------------------------------------------------------------------
-void AliFMDv1::CreateGeometry()
-{
- //
-  // Create the geometry of Forward Multiplicity Detector version 0
-  //
-  //Detector consists of 6 volumes: 
-  // 1st covered pseudorapidity interval from 3.3 to 2.0
-  // and placed on 65cm in Z-direction;
-  // 2nd - from 2.0 to 1.6 and Z=85 cm;
-  // 3d  - the same pseudorapidity interval as the 1st 
-  // but on the other side from the interaction point z=-65cm;
-  // 4th - simmetricaly with the 2nd : 
-  // pseudorapidity from 2.0 to 1.6, Z=-85cm   
-  // 5th - from 3.6 to 4.7, Z=-270cm
-  // 6th - from 4.5 to 5.5 , Z=-630cm.
-  // Each part has 400mkm Si (sensetive area, detector itself),
-  // 0.75cm of plastic simulated electronics material,
-  // Al support ring 2cm thickness and 1cm width placed on 
-  // the outer radius of each Si disk;
-  //    
-  // begin Html
-  /*
-   <img src="gif/AliFMDv0.gif">
-   */
-  //
-
-
-
-  Int_t *idtmed = fIdtmed->GetArray();
-   
-  Int_t ifmd;
-  Int_t idrotm[999];
-  /*<<<<<<< AliFMDv1.cxx
-  Float_t zFMD,par[3],ppcon[15];
-  Float_t z[5]={62.8, 75.2, -83.4, -75.2, -340.};
-  Float_t NylonTube[3]={0.2,0.6,0.45};
-  Float_t zPCB=0.12; Float_t zHoneyComb=0.5; 
-  Float_t zSi=0.03;
-  char nameFMD[5], nameSi[5], nameSector[5], nameRing[5];
-  Char_t nameHoney[5], nameHoneyIn[5], nameHoneyOut[5];
-  Char_t namePCB[5], nameCopper[5], nameChips[5], nameG10[5];
-  Char_t nameLPCB[5], nameLCopper[5], nameLChips[5], nameGL10[5];;
-  Float_t rin[5]={4.2,15.4,4.2,15.4,4.2};
-  Float_t rout[5]={17.4,28.4,17.4,28.4,17.4};
-  Float_t RinHoneyComb[5] ={ 5.15,16.4,  5.15,16.4,  5.15};
-  Float_t RoutHoneyComb[5]={20.63,34.92,22.3, 32.02,20.63};
-  Float_t zInside;
-  Float_t zCooper=0.01; Float_t zChips=0.01;
-  Float_t yNylonTube[5]={10,20,10,20,10};
-  =======*/
-  Float_t zFMD,par[3],ppcon[15];
-  Float_t z[5]={-62.8, -75.2, 83.4, 75.2, 340.};
-  Float_t NylonTube[3]={0.2,0.6,0.45};
-  Float_t zPCB=0.12; Float_t zHoneyComb=0.5; 
-  Float_t zSi=0.03;
-  char nameFMD[5], nameSi[5], nameSector[5], nameRing[5];
-  Char_t nameHoney[5], nameHoneyIn[5], nameHoneyOut[5];
-  Char_t namePCB[5], nameCopper[5], nameChips[5], nameG10[5];
-  Char_t nameLPCB[5], nameLCopper[5], nameLChips[5], nameGL10[5];;
-  Float_t rin[5]={4.2,15.4,4.2,15.4,4.2};
-  Float_t rout[5]={17.4,28.4,17.4,28.4,17.4};
-  Float_t RinHoneyComb[5] ={ 5.15,16.4,  5.15,16.4,  5.15};
-  Float_t RoutHoneyComb[5]={20.63,34.92,22.3, 32.02,20.63};
-  Float_t zInside;
-  Float_t zCooper=0.01; Float_t zChips=0.01;
-  Float_t yNylonTube[5]={10,20,10,20,10};
-  //>>>>>>> 1.25
-
-
-  AliMatrix(idrotm[901], 90, 0, 90, 90, 180, 0);
-  
-  
-  // Nylon tubes
-   gMC->Gsvolu("GNYL","TUBE", idtmed[1], NylonTube, 3);  //support nylon tube
-   Float_t wideSupport=zSi+3*zPCB+2*NylonTube[2]+zHoneyComb;
-     cout<<" wideSupport "<<wideSupport<<endl;
-
- for (ifmd=0; ifmd<5; ifmd++)
-    {
-      sprintf(nameFMD,"FMD%d",ifmd+1);
-      ppcon[0]=0;
-      ppcon[1]=360;
-      ppcon[2]=4;
-      
-      ppcon[3]=-wideSupport;
-      ppcon[4]=rin[ifmd]-0.1;
-      ppcon[5]=rout[ifmd]+0.1;
-      
-      ppcon[6]=ppcon[3]+2*zSi+2*zPCB+2*NylonTube[2];
-      ppcon[7]=rin[ifmd]-0.1;
-      ppcon[8]=rout[ifmd]+0.1;
-      
-      ppcon[9]=ppcon[6];
-      ppcon[10]=RinHoneyComb[ifmd]-0.1;
-      ppcon[11]=RoutHoneyComb[ifmd]+0.1;
-
-      ppcon[12]=ppcon[9]+2*zHoneyComb+zPCB;
-      ppcon[13]=RinHoneyComb[ifmd]-0.1;
-      ppcon[14]=RoutHoneyComb[ifmd]+0.1;
-      gMC->Gsvolu(nameFMD,"PCON",idtmed[0],ppcon,15);
-      if (z[ifmd] >0){  
-        zFMD=z[ifmd]+wideSupport;
-        gMC->Gspos(nameFMD,1,"ALIC",0,0,zFMD,0, "ONLY");}
-      else {
-        zFMD=z[ifmd]-wideSupport;
-        gMC->Gspos(nameFMD,1,"ALIC",0,0,zFMD,idrotm[901], "ONLY");}
-     //silicon
-      sprintf(nameSi,"GSI%d",ifmd+1);
-      sprintf(nameSector,"GSC%d",ifmd+1);
-      sprintf(nameRing,"GRN%d",ifmd+1);
-      
-      //honeycomb support
-      sprintf(nameHoney,"GSU%d",ifmd+1);
-      gMC->Gsvolu(nameHoney,"TUBE", idtmed[0], par, 0);  //honeycomb 
-      sprintf(nameHoneyIn,"GHI%d",ifmd+1);
-      gMC->Gsvolu(nameHoneyIn,"TUBE", idtmed[7], par, 0);  //honey comb inside 
-      sprintf(nameHoneyOut,"GHO%d",ifmd+1);
-      gMC->Gsvolu(nameHoneyOut,"TUBE", idtmed[6], par, 0);  //honey comb skin
-      //PCB
-      sprintf(namePCB,"GPC%d",ifmd+1);
-      gMC->Gsvolu(namePCB,"TUBE", idtmed[0], par, 0); //PCB
-      sprintf(nameCopper,"GCO%d",ifmd+1);
-      gMC->Gsvolu(nameCopper,"TUBE", idtmed[3], par, 0);  // Cooper
-      sprintf(nameChips,"GCH%d",ifmd+1);
-      gMC->Gsvolu(nameChips,"TUBE", idtmed[5], par, 0); // Si chips
-      sprintf(nameG10,"G10%d",ifmd+1);
-      gMC->Gsvolu(nameG10,"TUBE", idtmed[2], par, 0);  //G10 plate
-      //last PCB
-      sprintf(nameLPCB,"GPL%d",ifmd+1);
-      gMC->Gsvolu(nameLPCB,"TUBE", idtmed[0], par, 0); //PCB
-      sprintf(nameLCopper,"GCL%d",ifmd+1);
-      gMC->Gsvolu(nameLCopper,"TUBE", idtmed[3], par, 0);  // Cooper
-      sprintf(nameLChips,"GHL%d",ifmd+1);
-      gMC->Gsvolu(nameLChips,"TUBE", idtmed[5], par, 0); // Si chips
-      sprintf(nameGL10,"G1L%d",ifmd+1);
-      gMC->Gsvolu(nameGL10,"TUBE", idtmed[2], par, 0); // Last G10
-      par[0]=rin[ifmd]; // pipe size
-      par[1]=rout[ifmd];
-      par[2]=zSi/2;
-      gMC->Gsvolu(nameSi,"TUBE", idtmed[4], par, 3);
-      zInside=ppcon[3]+par[2];
-       gMC->Gspos(nameSi,ifmd+1,nameFMD,0,0,zInside,0, "ONLY");
-      //PCB 1
-      zInside += par[2]+zPCB/2;
-      par[2]=zPCB/2;
-      gMC->Gsposp(namePCB,1,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      zInside += zPCB;
-      gMC->Gsposp(namePCB,2,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      Float_t NulonTubeBegin=zInside+2.5*zPCB;
-      par[2]=zPCB/2-0.02;
-      Float_t zInPCB = -zPCB/2+par[2];
-      gMC->Gsposp(nameG10,1,namePCB,0,0,zInPCB,0, "ONLY",par,3);
-      zInPCB+=par[2]+zCooper/2 ;
-      par[2]=zCooper/2;
-      gMC->Gsposp(nameCopper,1,namePCB,0,0,zInPCB,0, "ONLY",par,3);
-      zInPCB += zCooper/2 + zChips/2;
-      par[2]=zChips/2;
-      gMC->Gsposp(nameChips,1,namePCB,0,0,zInPCB,0, "ONLY",par,3);
-      //HoneyComb
-      zHoneyComb=0.8;   
-      par[0] = RinHoneyComb[ifmd];
-      par[1] = RoutHoneyComb[ifmd];
-      par[2] = zHoneyComb/2;
-      zInside += 2*NylonTube[2]+par[2];
-      gMC->Gsposp(nameHoney,1,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      par[2]=0.1/2;
-      Float_t zHoney=-zHoneyComb/2+par[2];
-      gMC->Gsposp(nameHoneyOut,1,nameHoney,0,0,zHoney,0,
-                  "ONLY",par,3); //shkurki
-      zHoney=zHoneyComb/2-par[2];
-      gMC->Gsposp(nameHoneyOut,2,nameHoney,0,0,zHoney,0, "ONLY",par,3);
-      par[2]=(zHoneyComb-2.*0.1)/2; //soty vnutri
-      gMC->Gsposp(nameHoneyIn,1,nameHoney,0,0,0,0, "ONLY",par,3);
-      
-      gMC->Gspos("GNYL",1,nameFMD,0,yNylonTube[ifmd],
-                 NulonTubeBegin+NylonTube[2]/2.,0, "ONLY");
-      gMC->Gspos("GNYL",2,nameFMD,0,-yNylonTube[ifmd],
-                 NulonTubeBegin+NylonTube[2]/2.,0, "ONLY");
-         
-      //last PCB
-      par[0]=RoutHoneyComb[ifmd]-9;
-      par[1]=RoutHoneyComb[ifmd];
-      par[2]=zPCB/2;
-      zInside += zHoneyComb/2+par[2];
-      gMC->Gsposp(nameLPCB,1,nameFMD,0,0,zInside,0, "ONLY",par,3);
-      
-       par[2]=zPCB/2-0.02;
-       zInPCB = -zPCB/2+par[2];
-       gMC->Gsposp(nameGL10,1,nameLPCB,0,0,zInPCB,0, "ONLY",par,3);
-       zInPCB+=par[2]+zCooper/2 ;
-       par[2]=zCooper/2;
-       gMC->Gsposp(nameLCopper,1,nameLPCB,0,0,zInPCB,0, "ONLY",par,3);
-       zInPCB += zCooper/2 + zChips/2;
-       par[2]=zChips/2;
-       gMC->Gsposp(nameLChips,1,nameLPCB,0,0,zInPCB,0, "ONLY",par,3);
-      
-           
-     //Granularity
-    fSectorsSi1=20;
-        fRingsSi1=256*2;
-       //  fRingsSi1=3; // for drawing only
-    fSectorsSi2=40;
-       fRingsSi2=128*2;
-       //   fRingsSi2=3; //for  drawing onl
-    if(ifmd==1||ifmd==3)
-      { 
-        gMC->Gsdvn(nameSector, nameSi , fSectorsSi2, 2);
-        gMC->Gsdvn(nameRing, nameSector, fRingsSi2, 1);
-      }
-    else
-      {
-        gMC->Gsdvn(nameSector, nameSi , fSectorsSi1, 2);
-        gMC->Gsdvn(nameRing, nameSector , fRingsSi1, 1);
-      }
-    
-    }
-}    
-
-
-//------------------------------------------------------------------------
-void AliFMDv1::CreateMaterials() 
-{
- Int_t isxfld   = gAlice->Field()->Integ();
- Float_t sxmgmx = gAlice->Field()->Max();
-
- // Plastic CH
- Float_t aPlastic[2]={1.01,12.01};
- Float_t zPlastic[2]={1,6};
- Float_t wPlastic[2]={1,1};
- Float_t denPlastic=1.03;
-   //
-  //     60% SiO2 , 40% G10FR4 
- // PC board
- Float_t apcb[3]  = { 28.0855,15.9994,17.749 };
- Float_t zpcb[3]  = { 14.,8.,8.875 };
- Float_t wpcb[3]  = { .28,.32,.4 };
- Float_t denspcb  = 1.8;
-   //
-// AIR
-                                                                                           Float_t aAir[4]={12.0107,14.0067,15.9994,39.948};
-Float_t zAir[4]={6.,7.,8.,18.};
-Float_t wAir[4]={0.000124,0.755267,0.231781,0.012827};
-Float_t dAir = 1.20479E-3;
-                                                                                            //*** Definition Of avaible FMD materials ***
- AliMixture(0, "FMD Air$", aAir, zAir, dAir, 4,wAir);
- AliMixture(1, "Plastic$",aPlastic,zPlastic,denPlastic,-2,wPlastic);
- AliMixture(2, "SSD PCB$",   apcb, zpcb, denspcb, 3, wpcb);
- AliMaterial(3, "SSD Copper$", 63.546, 29., 8.96, 1.43, 999.);
- AliMaterial(4, "SSD Si$",      28.0855, 14., 2.33, 9.36, 999.);
- AliMaterial(5, "SSD Si chip$", 28.0855, 14., 2.33, 9.36, 999.);
- AliMaterial(6, "SSD C$",       12.011,   6., 2.265,18.8, 999.);
- AliMaterial(7, "SSD Kapton$", 12.011, 6., 0.01, 31.27, 999.);//honeycomb
-  AliMaterial(8, "SSD G10FR4$", 17.749, 8.875, 1.8, 21.822, 999.);
-   
-
-//**
- AliMedium(0, "FMD air$", 0, 0, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(1, "Plastic$", 1, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(2, "SSD PCB$", 2, 0, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(3, "SSD Copper$", 3, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(4, "SSD Si$", 4, 1, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(5, "SSD Si chip$", 5, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(6, "SSD C$", 6, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
- AliMedium(7, "SSD Kapton$", 7, 0, isxfld, sxmgmx, 1., .001, 1., .001, .001);
- AliMedium(8, "SSD G10FR4$", 8, 0,isxfld, sxmgmx,  10., .01, 1., .003, .003);
-
-
-}
-//---------------------------------------------------------------------
-void AliFMDv1::DrawDetector()
-{
-//
-// Draw a shaded view of the Forward multiplicity detector version 0
-//
-
-//Set ALIC mother transparent
-gMC->Gsatt("ALIC","SEEN",0);
-//
-//Set volumes visible
-gMC->Gsatt("FMD1","SEEN",1);
-gMC->Gsatt("FMD2","SEEN",1);
-gMC->Gsatt("FMD3","SEEN",1);
-gMC->Gsatt("FMD4","SEEN",1);
-gMC->Gsatt("FMD5","SEEN",1);
-
-//
-gMC->Gdopt("hide","on");
-gMC->Gdopt("shad","on");
-gMC->SetClipBox(".");
-gMC->SetClipBox("*",0,1000,-1000,1000,-1000,1000);
-gMC->DefaultRange();
-gMC->Gdraw("alic",40,30,0,12,9.5,.2,0.2);
-gMC->Gdhead(1111,"Forward multiplicity detector");
-gMC->Gdopt("hide","off");
-}
-//-------------------------------------------------------------------
-void AliFMDv1::Init()
-{
-// Initialises version 0 of the Forward Multiplicity Detector
-//
-AliFMD::Init();
-fIdSens1=gMC->VolId("GRN1");
-fIdSens2=gMC->VolId("GRN2");
-fIdSens3=gMC->VolId("GRN3");
-fIdSens4=gMC->VolId("GRN4");
-fIdSens5=gMC->VolId("GRN5");
-printf("*** FMD version 1 initialized ***\n");
-}
-
-//-------------------------------------------------------------------
-
-void AliFMDv1::StepManager()
-{
-  //
-  // Called for every step in the Forward Multiplicity Detector
-  //
-  Int_t id,copy,copy1,copy2;
-  static Float_t hits[9];
-  static Int_t vol[3];
-  static Float_t de;
-  TLorentzVector pos;
-  TLorentzVector mom;
-
-
-  TClonesArray &lhits = *fHits;
-  if(!gMC->IsTrackAlive()) return; // particle has disappeared
-
-  Float_t charge = gMC->TrackCharge();
-  if(TMath::Abs(charge)<=0.) return; //take only charged particles
-
-  //  printf(" in StepManeger \n");
-  id=gMC->CurrentVolID(copy);
-  //((TGeant3*)gMC)->Gpcxyz();
-  
-// Check the sensetive volume
-   if(id==fIdSens1||id==fIdSens2||id==fIdSens3||id==fIdSens4||id==fIdSens5)
-     {
-       if(gMC->IsTrackEntering())
-        {
-          vol[2]=copy;
-          gMC->CurrentVolOffID(1,copy1);
-          vol[1]=copy1;
-          gMC->CurrentVolOffID(2,copy2);
-          vol[0]=copy2;
-
-          gMC->TrackPosition(pos);
-          hits[0]=pos[0];
-          hits[1]=pos[1];
-          hits[2]=pos[2];
-
-          gMC->TrackMomentum(mom);
-          hits[3]=mom[0];
-          hits[4]=mom[1];
-          hits[5]=mom[2];
-
-          Int_t iPart= gMC->TrackPid();
-          Int_t partId=gMC->IdFromPDG(iPart);
-          hits[7]=partId;
-          hits[8]=1e9*gMC->TrackTime();
-          de=0.;
-        }
-       if(gMC->IsTrackInside()){
-          de=de+1000.*gMC->Edep();
-       }
-       
-       if(gMC->IsTrackExiting()
-         ||gMC->IsTrackDisappeared()||
-         gMC->IsTrackStop())
-        {
-            hits[6]=de+1000.*gMC->Edep();
-      new(lhits[fNhits++]) AliFMDhit(fIshunt,gAlice->GetMCApp()->GetCurrentTrackNumber(),vol,hits);
-        } // IsTrackExiting()
-     }
-  }
-//--------------------------------------------------------------------------
-
-void AliFMDv1::Response( Float_t Edep)
-{
-  Float_t I=1.664*0.04*2.33/22400; // = 0.69e-6;
-  Float_t chargeOnly=Edep/I;
-  //Add noise ~500electrons
-  Int_t charge=500;
-  if (Edep>0)
-     charge=Int_t(gRandom->Gaus(chargeOnly,500));      
- }   
-
-
-
-
-
-
diff --git a/FMD/AliFMDv1.h b/FMD/AliFMDv1.h
deleted file mode 100644 (file)
index 5fb6089..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef ALIFMDV1_H
-#define ALIFMDV1_H
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
-
-///////////////////////////////////////////////
-//  Manager and hits classes for set:FMD     //
-////////////////////////////////////////////////
-#include "AliFMD.h"
-class AliFMDv1 : public AliFMD {
-  
-public:
-  AliFMDv1() {};
-  AliFMDv1(const char *name, const char *title);
-  virtual       ~AliFMDv1() {}
-  virtual void   CreateGeometry();
-  virtual void   CreateMaterials();
-  virtual void   DrawDetector();
-  virtual void   Init();
-  virtual Int_t  IsVersion() const {return 1;}
-  virtual void   StepManager();
-  //  virtual void Hit2Digits(Int_t bgrEvent, Option_t *opt1=" ",
-  //   Option_t *opt2=" ",Text_t *name=" "); // hit to digit for v1 :test  
- virtual void  Response( Float_t Edep);
-//private:
- //Int_t fCharge; 
-
-
-protected:
-   Int_t fIdSens1; // Sensetive volume  in FMD
-   Int_t fIdSens2; // Sensetive volume  in FMD
-   Int_t fIdSens3; // Sensetive volume  in FMD
-   Int_t fIdSens4; // Sensetive volume  in FMD
-   Int_t fIdSens5; // Sensetive volume  in FMD
-
-   
-// Background event for event mixing
-  
-  ClassDef(AliFMDv1,2)  //Class for FMD version 0
-};
-
-#endif
-
-
diff --git a/FMD/Config.C b/FMD/Config.C
new file mode 100644 (file)
index 0000000..b371bc5
--- /dev/null
@@ -0,0 +1,415 @@
+// One can use the configuration macro in compiled mode by
+// root [0] gSystem->Load("libgeant321");
+// root [0] gSystem->SetIncludePath("-I$ROOTSYS/include -I$ALICE_ROOT/include\
+//                   -I$ALICE_ROOT -I$ALICE/geant3/TGeant3");
+// root [0] .x grun.C(1,"Config.C++")
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include <Riostream.h>
+#include <TRandom.h>
+#include <TSystem.h>
+#include <TVirtualMC.h>
+#include <TGeant3.h>
+#include "STEER/AliRunLoader.h"
+#include "STEER/AliRun.h"
+#include "STEER/AliConfig.h"
+#include "PYTHIA6/AliDecayerPythia.h"
+#include "EVGEN/AliGenCocktail.h"
+#include "EVGEN/AliGenHIJINGpara.h"
+#include "STEER/AliMagFMaps.h"
+#include "STRUCT/AliBODY.h"
+#include "STRUCT/AliMAG.h"
+#include "STRUCT/AliABSOv0.h"
+#include "STRUCT/AliDIPOv2.h"
+#include "STRUCT/AliHALL.h"
+#include "STRUCT/AliFRAMEv2.h"
+#include "STRUCT/AliSHILv2.h"
+#include "STRUCT/AliPIPEv0.h"
+#include "ITS/AliITSvPPRasymmFMD.h"
+#include "TPC/AliTPCv2.h"
+#include "TOF/AliTOFv4T0.h"
+#include "RICH/AliRICHv1.h"
+#include "ZDC/AliZDCv2.h"
+#include "TRD/AliTRDv1.h"
+#include "FMD/AliFMDv1.h"
+#include "MUON/AliMUONv1.h"
+#include "MUON/AliMUONSt1GeometryBuilder.h"
+#include "MUON/AliMUONSt2GeometryBuilder.h"
+#include "MUON/AliMUONSlatGeometryBuilder.h"
+#include "MUON/AliMUONTriggerGeometryBuilder.h"
+#include "PHOS/AliPHOSv1.h"
+#include "PMD/AliPMDv1.h"
+#include "START/AliSTARTv1.h"
+#include "EMCAL/AliEMCALv1.h"
+#include "CRT/AliCRTv0.h"
+#include "VZERO/AliVZEROv3.h"
+#endif
+
+Float_t EtaToTheta(Float_t arg);
+static Int_t    eventsPerRun = 100;
+enum PprGeo_t 
+{
+    kHoles, kNoHoles
+};
+static PprGeo_t geo = kHoles;
+
+void Config()
+{
+  // ThetaRange is (0., 180.). It was (0.28,179.72) 7/12/00 09:00
+  // Theta range given through pseudorapidity limits 22/6/2001
+  
+  // Set Random Number seed
+  gRandom->SetSeed(123456); // Set 0 to use the currecnt time
+  cout<<"Seed for random number generation= "<<gRandom->GetSeed()<<endl; 
+  
+  
+  // libraries required by geant321
+#if defined(__CINT__)
+  gSystem->Load("libgeant321");
+#endif
+  
+  new TGeant3("C++ Interface to Geant3");
+  
+  AliRunLoader* rl = 0;
+  cout<<"Config.C: Creating Run Loader ..."<<endl;
+  rl = AliRunLoader::Open("galice.root", 
+                         AliConfig::GetDefaultEventFolderName(),
+                         "recreate");
+  if (!rl) {
+    gAlice->Fatal("Config.C","Can not instatiate the Run Loader");
+    return;
+  }
+  rl->SetCompressionLevel(2);
+  rl->SetNumberOfEventsPerFile(3);
+  gAlice->SetRunLoader(rl);
+
+    //
+    // Set External decayer
+  TVirtualMCDecayer *decayer = new AliDecayerPythia();
+  decayer->SetForceDecay(kAll);
+  decayer->Init();
+  gMC->SetExternalDecayer(decayer);
+
+  //=======================================================================
+  // ************* STEERING parameters FOR ALICE SIMULATION **************
+  // --- Specify event type to be tracked through the ALICE setup
+  // --- All positions are in cm, angles in degrees, and P and E in GeV
+  gMC->SetProcess("DCAY",1);
+  gMC->SetProcess("PAIR",1);
+  gMC->SetProcess("COMP",1);
+  gMC->SetProcess("PHOT",1);
+  gMC->SetProcess("PFIS",0);
+  gMC->SetProcess("DRAY",0);
+  gMC->SetProcess("ANNI",1);
+  gMC->SetProcess("BREM",1);
+  gMC->SetProcess("MUNU",1);
+  gMC->SetProcess("CKOV",1);
+  gMC->SetProcess("HADR",1);
+  gMC->SetProcess("LOSS",2);
+  gMC->SetProcess("MULS",1);
+  gMC->SetProcess("RAYL",1);
+
+  Float_t cut = 1.e-3;        // 1MeV cut by default
+  Float_t tofmax = 1.e10;
+
+  gMC->SetCut("CUTGAM", cut);
+  gMC->SetCut("CUTELE", cut);
+  gMC->SetCut("CUTNEU", cut);
+  gMC->SetCut("CUTHAD", cut);
+  gMC->SetCut("CUTMUO", cut);
+  gMC->SetCut("BCUTE",  cut); 
+  gMC->SetCut("BCUTM",  cut); 
+  gMC->SetCut("DCUTE",  cut); 
+  gMC->SetCut("DCUTM",  cut); 
+  gMC->SetCut("PPCUTM", cut);
+  gMC->SetCut("TOFMAX", tofmax); 
+
+  int     nParticles = 100;
+  if (gSystem->Getenv("CONFIG_NPARTICLES"))
+    nParticles = atoi(gSystem->Getenv("CONFIG_NPARTICLES"));
+
+  AliGenCocktail *gener = new AliGenCocktail();
+  gener->SetPhiRange(0, 360);
+  // Set pseudorapidity range from -8 to 8.
+  Float_t thmin = EtaToTheta(8);   // theta min. <---> eta max
+  Float_t thmax = EtaToTheta(-8);  // theta max. <---> eta min 
+  gener->SetThetaRange(thmin,thmax);
+  gener->SetOrigin(0, 0, 0);  //vertex position
+  gener->SetSigma(0, 0, 0);   //Sigma in (X,Y,Z) (cm) on IP position
+  
+  AliGenHIJINGpara *hijingparam = new AliGenHIJINGpara(nParticles);
+  hijingparam->SetMomentumRange(0.2, 999);
+  gener->AddGenerator(hijingparam,"HIJING PARAM",1);
+  
+  //    AliGenBox *genbox = new AliGenBox(nParticles);
+  //    genbox->SetPart(22);
+  //    genbox->SetPtRange(0.3, 10.00);
+  //    gener->AddGenerator(genbox,"GENBOX GAMMA for PHOS",1);
+  gener->Init();
+  
+  // Activate this line if you want the vertex smearing to happen
+  // track by track
+  //
+  //gener->SetVertexSmear(perTrack); 
+  // Field (L3 0.4 T)
+  AliMagFMaps* field = new AliMagFMaps("Maps","Maps", 2, 1., 10., 1);
+  gAlice->SetField(field);    
+
+
+  Bool_t useABSO  = kFALSE;
+  Bool_t useDIPO  = kFALSE;
+  Bool_t useFMD   = kTRUE;
+  Bool_t useFRAME = kFALSE;
+  Bool_t useHALL  = kFALSE;
+  Bool_t useITS   = kFALSE;
+  Bool_t useMAG   = kFALSE;
+  Bool_t useMUON  = kFALSE;
+  Bool_t usePHOS  = kFALSE;
+  Bool_t usePIPE  = kFALSE;
+  Bool_t usePMD   = kFALSE;
+  Bool_t useRICH  = kFALSE;
+  Bool_t useSHIL  = kFALSE;
+  Bool_t useSTART = kFALSE;
+  Bool_t useTOF   = kFALSE;
+  Bool_t useTPC   = kFALSE;
+  Bool_t useTRD   = kFALSE;
+  Bool_t useZDC   = kFALSE;
+  Bool_t useEMCAL = kFALSE;
+  Bool_t useCRT   = kFALSE;
+  Bool_t useVZERO = kFALSE;
+  rl->CdGAFile();
+
+  //=================== Alice BODY parameters =============================
+  AliBODY *BODY = new AliBODY("BODY", "Alice envelop");
+  
+  if (useMAG) {
+    //=================== MAG parameters ============================
+    // Start with Magnet since detector layouts may be depending ---
+    // on the selected Magnet dimensions ---
+    AliMAG *MAG = new AliMAG("MAG", "Magnet");
+  }
+
+  if (useABSO) {
+    //=================== ABSO parameters ============================
+    AliABSO *ABSO = new AliABSOv0("ABSO", "Muon Absorber");
+  }
+
+  if (useDIPO) {
+    //=================== DIPO parameters ============================
+    AliDIPO *DIPO = new AliDIPOv2("DIPO", "Dipole version 2");
+  }
+
+  if (useHALL) {
+    //=================== HALL parameters ============================
+    AliHALL *HALL = new AliHALL("HALL", "Alice Hall");
+  }
+
+
+  if (useFRAME) {
+    //=================== FRAME parameters ============================
+    AliFRAMEv2 *FRAME = new AliFRAMEv2("FRAME", "Space Frame");
+    if (geo == kHoles) {
+      FRAME->SetHoles(1);
+    } else {
+      FRAME->SetHoles(0);
+    }
+  }
+
+  if (useSHIL) {
+    //=================== SHIL parameters ============================
+    AliSHIL *SHIL = new AliSHILv2("SHIL", "Shielding Version 2");
+  }
+
+
+  if (usePIPE) {
+    //=================== PIPE parameters ============================
+    AliPIPE *PIPE = new AliPIPEv0("PIPE", "Beam Pipe");
+  }
+  if(useITS) {
+    //=================== ITS parameters ============================
+    //
+    // As the innermost detector in ALICE, the Inner Tracking System
+    // "impacts" on almost all other detectors. This involves the fact
+    // that the ITS geometry still has several options to be followed
+    // in parallel in order to determine the best set-up which
+    // minimizes the induced background. All the geometries available
+    // to date are described in the following. Read carefully the
+    // comments and use the default version (the only one uncommented)
+    // unless you are making comparisons and you know what you are
+    // doing. In this case just uncomment the ITS geometry you want to
+    // use and run Aliroot.
+    //
+    // Detailed geometries:         
+    //
+    //
+    //
+    AliITSvPPRasymmFMD *ITS  
+      = new AliITSvPPRasymmFMD("ITS", "ITS PPR detailed version "
+                              "with asymmetric services");
+    // don't touch this parameter if you're not an ITS developer
+    ITS->SetMinorVersion(2);  
+    // don't touch this parameter if you're not an ITS developer
+    ITS->SetReadDet(kTRUE);      
+    // don't touch this parameter if you're not an ITS developer
+    //  ITS->SetWriteDet("$ALICE_ROOT/ITS/ITSgeometry_vPPRasymm2.det");  
+    // detector thickness on layer 1 must be in the range [100,300]
+    ITS->SetThicknessDet1(200.);   
+    // detector thickness on layer 2 must be in the range [100,300]
+    ITS->SetThicknessDet2(200.);   
+    // chip thickness on layer 1 must be in the range [150,300]
+    ITS->SetThicknessChip1(200.);  
+    // chip thickness on layer 2 must be in the range [150,300]
+    ITS->SetThicknessChip2(200.);  
+    // 1 --> rails in ; 0 --> rails out
+    ITS->SetRails(0);         
+    // 1 --> water ; 0 --> freon
+    ITS->SetCoolingFluid(1);       
+
+    //
+    // Coarse geometries (warning: no hits are produced with these
+    // coarse geometries and they unuseful for reconstruction !):
+    //                                                     
+    //
+    // AliITSvPPRcoarseasymm *ITS  =
+    //   new AliITSvPPRcoarseasymm("ITS","New ITS PPR coarse version "
+    //                                 "with asymmetric services");
+    // 1 --> rails in ; 0 --> rails out
+    // ITS->SetRails(0);               
+    // 0 --> Copper ; 1 --> Aluminum ; 2 --> Carbon
+    // ITS->SetSupportMaterial(0);      
+    //
+    // AliITS *ITS  = 
+    //   new AliITSvPPRcoarsesymm("ITS","New ITS PPR coarse version "
+    //                           "with symmetric services");
+    // 1 --> rails in ; 0 --> rails out
+    // ITS->SetRails(0);                
+    // 0 --> Copper ; 1 --> Aluminum ; 2 --> Carbon
+    // ITS->SetSupportMaterial(0);      
+    //                      
+    //
+    //
+    // Geant3 <-> EUCLID conversion
+    // ============================
+    //
+    // SetEUCLID is a flag to output (=1) or not to output (=0) both
+    // geometry and media to two ASCII files (called by default
+    // ITSgeometry.euc and ITSgeometry.tme) in a format understandable
+    // to the CAD system EUCLID.  The default (=0) means that you dont
+    // want to use this facility.
+    //
+    ITS->SetEUCLID(0);  
+  }
+
+  if (useTPC) {
+    //============================ TPC parameters ====================
+    //
+    // This allows the user to specify sectors for the SLOW (TPC
+    // geometry 2) Simulator. SecAL (SecAU) <0 means that ALL lower
+    // (upper) sectors are specified, any value other than that
+    // requires at least one sector (lower or upper)to be specified!
+    // 
+    // Reminder: sectors 1-24 are lower sectors (1-12 -> z>0, 13-24 -> z<0)
+    //           sectors 25-72 are the upper ones (25-48 -> z>0, 49-72 -> z<0)
+    //   SecLows - number of lower sectors specified (up to 6)
+    //   SecUps  - number of upper sectors specified (up to 12)
+    //   Sens    - sensitive strips for the Slow Simulator !!!
+    //
+    // This does NOT work if all S or L-sectors are specified, i.e.
+    // if SecAL or SecAU < 0
+    //
+    //
+    //----------------------------------------------------------------
+    //  gROOT->LoadMacro("SetTPCParam.C");
+    //  AliTPCParam *param = SetTPCParam();
+    AliTPC *TPC = new AliTPCv2("TPC", "Default");
+    
+    // All sectors included 
+    TPC->SetSecAU(-1);
+    TPC->SetSecAL(-1);
+  }
+  
+  if (useTOF) {
+    //=================== TOF parameters ============================
+    AliTOF *TOF = new AliTOFv4T0("TOF", "normal TOF");
+  }
+
+  if (useRICH) {
+    //=================== RICH parameters ===========================
+    AliRICH *RICH = new AliRICHv1("RICH", "normal RICH");
+    
+  }
+
+  if (useZDC) {
+    //=================== ZDC parameters ============================
+    AliZDC *ZDC = new AliZDCv2("ZDC", "normal ZDC");
+  }
+
+  if (useTRD) {
+    //=================== TRD parameters ============================
+    AliTRD *TRD = new AliTRDv1("TRD", "TRD slow simulator");
+    
+    // Select the gas mixture (0: 97% Xe + 3% isobutane, 1: 90% Xe +
+    // 10% CO2) 
+    TRD->SetGasMix(1);
+    if (geo == kHoles) {
+      // With hole in front of PHOS
+      TRD->SetPHOShole();
+      // With hole in front of RICH
+      TRD->SetRICHhole();
+    }
+    // Switch on TR
+    AliTRDsim *TRDsim = TRD->CreateTR();
+  }
+
+  if (useFMD) {
+    //=================== FMD parameters ============================
+    AliFMD *FMD = new AliFMDv1("FMD", "Detailed FMD");
+  }
+
+  if (useMUON) {
+    //=================== MUON parameters ===========================
+    AliMUON *MUON = new AliMUONv1("MUON", "default");
+    MUON->AddGeometryBuilder(new AliMUONSt1GeometryBuilder(MUON));
+    MUON->AddGeometryBuilder(new AliMUONSt2GeometryBuilder(MUON));
+    MUON->AddGeometryBuilder(new AliMUONSlatGeometryBuilder(MUON));
+    MUON->AddGeometryBuilder(new AliMUONTriggerGeometryBuilder(MUON));
+  }
+  
+  //=================== PHOS parameters ===========================
+  if (usePHOS) {
+    AliPHOS *PHOS = new AliPHOSv1("PHOS", "IHEP");
+  }
+
+  if (usePMD) {
+    //=================== PMD parameters ============================
+    AliPMD *PMD = new AliPMDv1("PMD", "normal PMD");
+  }
+
+  if (useSTART) {
+    //=================== START parameters ============================
+    AliSTART *START = new AliSTARTv1("START", "START Detector");
+  }
+
+  if (useEMCAL) {
+    //=================== EMCAL parameters ============================
+    AliEMCAL *EMCAL = new AliEMCALv1("EMCAL", "EMCAL_55_25");
+  }
+
+  if (useCRT) {
+    //=================== CRT parameters ============================
+    AliCRT *CRT = new AliCRTv0("CRT", "normal ACORDE");
+  }
+
+  if (useVZERO) {
+    //=================== CRT parameters ============================
+    AliVZERO *VZERO = new AliVZEROv3("VZERO", "normal VZERO");
+  }
+  
+  cout << "End of FMD/Config.C" << endl;
+}
+
+Float_t EtaToTheta(Float_t arg){
+  return (180./TMath::Pi())*2.*atan(exp(-arg));
+}
similarity index 70%
copy from FMD/AliFMDhit.cxx
copy to FMD/Digitize.C
index 4d75aa1..3992548 100644 (file)
  * about the suitability of this software for any purpose. It is          *
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
-#include "AliFMDhit.h"
 
-ClassImp(AliFMDhit)
+/* $Id$ */
 
-AliFMDhit::AliFMDhit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits):
-  AliHit(shunt, track)
+// Script to do test the FMD digitization class. 
+void 
+Digitize() 
 {
-//Normal FMD  hit ctor
-  fVolume = vol[0];
-  fNumberOfSector=vol[1];
-  fNumberOfRing=vol[2];
-  fX=hits[0];
-  fY=hits[1];
-  fZ=hits[2];
-  fPx=hits[3];
-  fPy=hits[4];
-  fPz=hits[5];
-  fEdep=hits[6];
-  fParticle=(Int_t)hits[7];
-  fTime=hits[8];
+  // Dynamically link some shared libs
+  if (gClassTable->GetID("AliRun") < 0) {
+    gROOT->LoadMacro("loadlibs.C");
+    loadlibs();
+  }
+  if (gAlice) {
+    delete gAlice;
+    gAlice = 0;
+  }
+
+  AliRunDigitizer * manager = new AliRunDigitizer(1,1);
+  manager->SetInputStream(0,"galice.root");
+  AliFMDDigitizer *FMD = new AliFMDDigitizer(manager);
+  manager->Exec("");
 }
+
+
 
 
 
diff --git a/FMD/Document.C b/FMD/Document.C
new file mode 100644 (file)
index 0000000..046471c
--- /dev/null
@@ -0,0 +1,60 @@
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+// Script to do test the FMD digitization class. 
+void
+Document()
+{
+  gEnv->SetValue("Root.Html.SourceDir", "$(ALICE)/FMD");
+  gEnv->SetValue("Root.Html.OutputDir", "$(ALICE)/FMD/html");
+
+  gSystem->MakeDirectory("$(ALICE)/FMD/html");
+  
+  THtml* html = new THtml;
+  html->MakeAll(kFALSE, "AliFMD*");
+  html->Convert("$(ALICE)/FMD/Digitize.C", "Digitize", 
+               "FMD/html/src");
+  html->Convert("$(ALICE)/FMD/Reconstruct.C", "Reconstruct", 
+               "FMD/html/src");
+  html->Convert("$(ALICE)/FMD/Simulate.C", "Simulate", 
+               "FMD/html/src");
+  html->Convert("$(ALICE)/FMD/DrawFMD.C", "DrawFMD", 
+               "FMD/html/src");
+  html->Convert("$(ALICE)/FMD/ViewFMD.C", "ViewFMD", 
+               "FMD/html/src");
+  html->MakeIndex("AliFMD*");
+
+  std::ofstream index("FMD/html/index.html");
+  html->WriteHtmlHeader(index, "ALICE FMD Code - Index page");
+  
+  index << "<h1>ALICE FMD Code</h1>\n"
+       << "<ul>\n"
+       << "<li><a href=\"USER_Index.html\">Classes</a></li>\n"
+        << "<li><a href=\"src/Digitize.C.html\">Digitize script</a></li>\n"
+        << "<li><a href=\"src/Reconstruct.C.html\">Reconstruct script</a></li>\n"
+        << "<li><a href=\"src/Simulate.C.html\">Simulate script</a></li>\n"
+        << "<li><a href=\"src/DrawFMD.C.html\">DrawFMD script</a></li>\n"
+        << "<li><a href=\"src/ViewFMD.C.html\">ViewFMD script</a></li>\n"
+       << "</ul>\n"
+       << std::endl;
+  html->WriteHtmlFooter(index, "", "", "", "");
+  index.close();
+}
+
+//
+// EOF
+//
index 72744cc..49808a7 100644 (file)
@@ -2,7 +2,7 @@ void DrawFMD()
 {
    gMC->Gsatt("*", "seen", -1);
    gMC->Gsatt("alic", "seen", 0);
-   gROOT->LoadMacro("ViewFMD.C");
+   gROOT->LoadMacro("FMD/ViewFMD.C");
    gInterpreter->ProcessLine("ViewFMD()");
    gMC->Gdopt("hide", "on");
    gMC->Gdopt("shad", "on");
@@ -10,7 +10,9 @@ void DrawFMD()
    gMC->SetClipBox(".");
    gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
    gMC->DefaultRange();
-   gMC->Gdraw("alic", 40, 30, 0, 6, 9, .08, .08);
+   gMC->Gdraw("alic", 40, 30, 0, 12, 12, .055, .055);
    gMC->Gdhead(1111, "Forward Multiplicity Detector");
-   gMC->Gdman(13, 9, "MAN");
+   gMC->Gdman(16, 10, "MAN");
+   gPad->Modified();
+   gPad->cd();
 }
diff --git a/FMD/FMDDigit.C b/FMD/FMDDigit.C
deleted file mode 100644 (file)
index 4c87c0a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-void FMDDigit () 
-{
-// Dynamically link some shared libs
-
-   if (gClassTable->GetID("AliRun") < 0) {
-      gROOT->LoadMacro("loadlibs.C");
-      loadlibs();
-   }
-  if (gAlice) 
-   {
-     delete gAlice;
-     gAlice = 0x0;
-   }
-   
-  AliRunDigitizer * manager = new AliRunDigitizer(1,1);
-  manager->SetInputStream(0,"galice.root");
-  AliFMDDigitizer *FMD = new AliFMDDigitizer(manager);
-  manager->Exec("");
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FMD/FMDMerger.C b/FMD/FMDMerger.C
deleted file mode 100644 (file)
index e4ec950..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-void FMDMerger (Int_t evNumber1=0, Int_t evNumber2=0, Int_t ibg=0, Int_t bgr=10) 
-{
-// Dynamically link some shared libs
-
-   if (gClassTable->GetID("AliRun") < 0) {
-      gROOT->LoadMacro("loadlibs.C");
-      loadlibs();
-   }
-
-// Connect the Root Galice file containing Geometry, Kine and Hits
-
-   TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject("pipe.root");
-   if (file) file->Close(); 
-   file = new TFile("galice.root","UPDATE");
-   cout<<" Just starting... file "<<file<<endl;
-
-// Get AliRun object from file or create it if not on file
-
-   if (!gAlice) {
-       gAlice = (AliRun*)file->Get("gAlice");
-       if (gAlice) printf("AliRun object found on file\n");
-       if (!gAlice) gAlice = new AliRun("gAlice","Alice test program");
-   }
-   AliFMD *FMD  = (AliFMD*) gAlice->GetModule("FMD");
-
-   if (FMD) {
-// creation
-       AliFMDMerger* merger = new AliFMDMerger();
-       cout<<" merger "<<merger<<endl;
-       /*
-       // granularity
-       merger->SetRingsSi1(128);
-        merger->SetRingsSi2(64);
-        merger->SetSectorsSi1(20);
-        merger->SetSectorsSi2(24);
-       */
-// configuration
-       if (ibg) {
-        merger->SetMode(ibg);
-        merger->SetBackgroundFileName("bg.root");
-        cout<<" background"<<endl;
-      }
-       // pass
-       FMD->SetMerger(merger);
-   }
-// Action !
-//
-//   Loop over events              
-//
-    for (int nev=evNumber1; nev<= evNumber2; nev++) {
-       Int_t nparticles = gAlice->GetEvent(nev);
-       cout << "nev         " << nev <<endl;
-       cout << "nparticles  " << nparticles <<endl;
-       if (nev < evNumber1) continue;
-       if (nparticles <= 0) return;
-       Int_t nbgr_ev = Int_t(nev*bgr/(evNumber2+1));
-       cout<<" nbgr_ev "<<nbgr_ev<<endl;
-       
-       if (ibg) {
-           merger->SetBackgroundEventNumber(nbgr_ev);
-       }
-
-       gAlice->SDigits2Digits("FMD");
-
-       char hname[30];
-       sprintf(hname,"TreeD%d",nev);
-       //      gAlice->TreeD()->Write(hname);
-       //      cout<<hname<<" was written in file"<<file<<endl;
-       //      gAlice->TreeD()->Print();
-       //reset tree
-       gAlice->TreeD()->Reset();
-
-    }   // event loop 
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/FMD/FMDReconstructor.C b/FMD/FMDReconstructor.C
deleted file mode 100644 (file)
index 3724e07..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-void FMDReconstructor (Int_t evNumber=1) 
-{
-  if (gClassTable->GetID("AliRun") < 0) 
-    {
-      gROOT->LoadMacro("$ALICE_ROOT/macros/loadlibs.C");
-      loadlibs();
-    }
-  if (gSystem->Getenv("CONFIG_SPLIT_FILE"))
-    cout << "SPLIT" << endl;
-  else
-    cout << "NO SPLIT" << endl ;
-    
-  
-  
-  //TFile * f = new TFile("galice.root","UPDATE");
-  //gAlice = (AliRun*) f->Get("gAlice") ;
-  
-  AliRunLoader* rl = AliRunLoader::Open("galice.root",AliConfig::GetDefaultEventFolderName(),"read");
-  if (rl == 0x0)
-   {
-     cerr<<"Can not open session for file galice.root\n";
-     return;
-   }
-
-  rl->LoadgAlice();
-  gAlice = rl->GetAliRun();
-
-  AliFMD* FMD  = (AliFMD *)gAlice->GetDetector("FMD");
-
-  gAlice->RunReco("FMD");
-}
-  
index af807ee..182ffbe 100644 (file)
@@ -1,3 +1,4 @@
+// -*- mode: c++ -*- 
 #ifdef __CINT__
 /* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
  * See cxx source for full Copyright notice                               */
@@ -8,6 +9,13 @@
 #pragma link off all classes;
 #pragma link off all functions;
  
-#pragma link C++ class  AliFMDdigit+;
+#pragma link C++ class  AliFMDBaseDigit+;
+#pragma link C++ class  AliFMDDigit+;
+#pragma link C++ class  AliFMDSDigit+;
 
+#else
+# error Not for compilation 
 #endif
+//
+// EOF
+//
index 82a1414..5efba2f 100644 (file)
@@ -1,14 +1,25 @@
-#ifdef __CINT__
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
-
+// -*- mode: c++ -*- 
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * See cxx source for full Copyright notice
+ */
 /* $Id$ */
+#ifdef __CINT__
 
 #pragma link off all globals;
 #pragma link off all classes;
 #pragma link off all functions;
  
+#pragma link C++ class  AliFMDMap<UShort_t>;
+#pragma link C++ typedef AliFMDAdcMap;
 #pragma link C++ class  AliFMDReconstructor+;
-#pragma link C++ class  AliFMDReconstParticles+;
+#pragma link C++ class  AliFMDParticles+;
+#pragma link C++ class  AliFMDRawStream+;
 
+#else
+# error Not for compilation 
 #endif
+//
+// EOF
+//
index 1fb0098..c76f8c9 100644 (file)
@@ -1,17 +1,37 @@
-#ifdef __CINT__
-/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * See cxx source for full Copyright notice                               */
+// -*- mode: c++ -*- 
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights
+ * reserved. 
+ *
+ * See cxx source for full Copyright notice                               
+ */
 
 /* $Id$ */
+#ifdef __CINT__
 
 #pragma link off all globals;
 #pragma link off all classes;
 #pragma link off all functions;
+
+#pragma link C++ class  std::pair<Float_t,UShort_t>;
+#pragma link C++ class  AliFMDMap<std::pair<Float_t,UShort_t> >;
+#pragma link C++ typedef  AliFMDEdepMap;
+#pragma link C++ class  AliFMDHit+;
 #pragma link C++ class  AliFMD+;
 #pragma link C++ class  AliFMDv0+;
 #pragma link C++ class  AliFMDv1+;
-#pragma link C++ class  AliFMDhit+;
+#pragma link C++ class  AliFMDSubDetector+;
+#pragma link C++ class  AliFMD1+;
+#pragma link C++ class  AliFMD2+;
+#pragma link C++ class  AliFMD3+;
+#pragma link C++ class  AliFMDRing+;
+#pragma link C++ class  AliFMDPolygon+;
+#pragma link C++ class  AliFMDBaseDigitizer+;
 #pragma link C++ class  AliFMDDigitizer+;
+#pragma link C++ class  AliFMDSDigitizer+;
 
+#else
+# error Not for compilation 
 #endif
+//
+// EOF
+//
diff --git a/FMD/ReadRaw.C b/FMD/ReadRaw.C
new file mode 100644 (file)
index 0000000..ad2838b
--- /dev/null
@@ -0,0 +1,60 @@
+#include <iomanip>
+
+void 
+ReadRaw(Int_t det=2,  bool verbose=false, Int_t event=0) 
+{
+  TString file(Form("raw%d/FMD_%d.ddl", event, AliFMD::kBaseDDL + det - 1));
+
+  std::cout << "Reading raw data file " << file << std::endl;
+  
+  TH1* h = new TH1F("rawData", "Raw Data", 90, 0, 90);
+  
+  
+  // This method creates a text file containing the same information
+  // stored in an Altro file. The information in the text file is
+  // organized pad by pad and and for each pad it consists in a
+  // sequence of bunches (Bunch length +2, Time bin of the last
+  // amplitude sample in the bunch, amplitude values) It is used
+  // mainly //for debugging
+
+  AliAltroBuffer buff(file.Data(),0);
+  Int_t numWords,padNum,rowNum,secNum=0;
+  Int_t value = 0;
+  Int_t zero  = 0;
+  // if (!buff.ReadDataHeader()) {
+  // std::cout<< file << " isn't a valid data file!" << std::endl;
+  // }
+  
+  while(buff.ReadTrailerBackward(numWords,padNum,rowNum,secNum)){
+    if (verbose) 
+      std::cout << "Ring: " << (secNum == 0 ? 'I' : 'O') 
+               << " Sector: " << std::setw(2) << rowNum 
+               << " Strip:  " << std::setw(3) << padNum 
+               << " Words:  " << std::setw(4) << numWords << std::endl;
+    if (numWords == 0) zero++;
+    if (numWords % 4){
+      if (verbose) 
+       std::cout << "Skipping trailer of " 
+                 << (4 - numWords % 4) << " words" << std::endl;
+      for(Int_t j = 0; j < (4 - numWords % 4); j++)
+       value=buff.GetNextBackWord(); 
+    }//end if
+    for(Int_t i = 0; i <numWords; i++) {
+      value=buff.GetNextBackWord();
+      if (verbose) {
+       std::cout << std::setw(5) <<  value << std::flush;
+       if (i % 16 == 15) std::cout << std::endl;
+      }
+      h->Fill(value);
+    }//end for
+    if (verbose)
+      std::cout << std::endl;
+    if (zero > 1) {
+      std::cout << "Error: Read zero channels - should not happen" 
+               << std::endl;
+      break;
+    }
+  }//end while
+  h->Draw();
+  return;
+}
similarity index 73%
copy from FMD/AliFMDhit.cxx
copy to FMD/Reconstruct.C
index 4d75aa1..c8aa8a9 100644 (file)
  * about the suitability of this software for any purpose. It is          *
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
-#include "AliFMDhit.h"
 
-ClassImp(AliFMDhit)
+/* $Id$ */
 
-AliFMDhit::AliFMDhit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits):
-  AliHit(shunt, track)
+// Script to do test the FMD digitization class. 
+
+void 
+Reconstruct()
 {
-//Normal FMD  hit ctor
-  fVolume = vol[0];
-  fNumberOfSector=vol[1];
-  fNumberOfRing=vol[2];
-  fX=hits[0];
-  fY=hits[1];
-  fZ=hits[2];
-  fPx=hits[3];
-  fPy=hits[4];
-  fPz=hits[5];
-  fEdep=hits[6];
-  fParticle=(Int_t)hits[7];
-  fTime=hits[8];
+   AliReconstruction rec;   
+   rec.SetRunLocalReconstruction("FMD");
+   rec.SetRunVertexFinder(kFALSE);
+   rec.SetRunTracking(kFALSE); 
+   rec.SetFillESD(""); 
+   rec.SetInput("./");
+   rec.Run(); 
 }
-
-
-
-
-
-
-
-
-
-
-
-
 
+//
+// EOF
+//
similarity index 72%
rename from FMD/AliFMDhit.cxx
rename to FMD/Simulate.C
index 4d75aa1..c017329 100644 (file)
  * about the suitability of this software for any purpose. It is          *
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
-#include "AliFMDhit.h"
 
-ClassImp(AliFMDhit)
+/* $Id$ */
 
-AliFMDhit::AliFMDhit(Int_t shunt, Int_t track, Int_t *vol, Float_t *hits):
-  AliHit(shunt, track)
+// Script to do test the FMD digitization class. 
+void
+Simulate()
 {
-//Normal FMD  hit ctor
-  fVolume = vol[0];
-  fNumberOfSector=vol[1];
-  fNumberOfRing=vol[2];
-  fX=hits[0];
-  fY=hits[1];
-  fZ=hits[2];
-  fPx=hits[3];
-  fPy=hits[4];
-  fPz=hits[5];
-  fEdep=hits[6];
-  fParticle=(Int_t)hits[7];
-  fTime=hits[8];
+ AliSimulation sim;
+ sim.SetConfigFile("FMD/Config.C");
+ // sim.SetMakeSDigits("FMD");
+ // sim.SetMakeDigits("FMD");
+ sim.SetWriteRawData("FMD");
+ // sim.SetMakeDigitsFromHits("FMD");
+ sim.Run(); 
 }
-
-
-
-
-
-
-
-
-
-
-
-
 
+//
+// EOF
+//
index 306545c..cd7e3f2 100644 (file)
@@ -1,7 +1,18 @@
 void ViewFMD()
 {
-   gMC->Gsatt("FMD0","seen",1);
-   gMC->Gsatt("FMD1","seen",1);
-   gMC->Gsatt("FMD2","seen",1);
-   gMC->Gsatt("FMD3","seen",1);
+   gMC->Gsatt("FMD1","seen",0);
+   gMC->Gsatt("FMD2","seen",0);
+   gMC->Gsatt("FMD3","seen",0);
+   gMC->Gsatt("RNGI","seen",0);
+   gMC->Gsatt("RNGO","seen",0);
+   gMC->Gsatt("VFI","seen",0);
+   gMC->Gsatt("VFO","seen",0);
+   gMC->Gsatt("VBI","seen",0);
+   gMC->Gsatt("VBO","seen",0);
+   gMC->Gsatt("ACTI","seen",1);
+   gMC->Gsatt("ACTO","seen",1);
+   gMC->Gsatt("PBTI","seen",1);
+   gMC->Gsatt("PBTO","seen",1);
+   gMC->Gsatt("PBBI","seen",1);
+   gMC->Gsatt("PBBO","seen",1);
 }
index 82abea9..34c624d 100644 (file)
@@ -1,10 +1,11 @@
 #-*- Mode: Makefile -*-
+#
 # $Id$
 
-SRCS= AliFMDdigit.cxx
-
-
-HDRS= $(SRCS:.cxx=.h)
-
-DHDR:=FMDbaseLinkDef.h
+SRCS   =  AliFMDDigit.cxx
+HDRS   =  $(SRCS:.cxx=.h)
+DHDR   := FMDbaseLinkDef.h
 
+#
+# EOF
+#
\ No newline at end of file
index ec877bb..ce2a293 100644 (file)
@@ -1,10 +1,14 @@
 #-*- Mode: Makefile -*-
+#
 # $Id$
 
-SRCS= AliFMDReconstructor.cxx AliFMDReconstParticles.cxx
-
-
-HDRS= $(SRCS:.cxx=.h)
-
-DHDR:=FMDrecLinkDef.h
+SRCS           =  AliFMDReconstructor.cxx \
+                  AliFMDRawStream.cxx  \
+                  AliFMDParticles.cxx
+HDRS           =  $(SRCS:.cxx=.h)
+DHDR           := FMDrecLinkDef.h
+EINCLUDE       := $(ALICE)/RAW
 
+#
+# EOF
+#
index 14aeead..dad3248 100644 (file)
@@ -1,10 +1,20 @@
 #-*- Mode: Makefile -*-
+#
 # $Id$
 
-SRCS= AliFMD.cxx AliFMDv0.cxx AliFMDv1.cxx AliFMDhit.cxx  AliFMDDigitizer.cxx
-
-
-HDRS= $(SRCS:.cxx=.h)
-
-DHDR:=FMDsimLinkDef.h
+SRCS           =  AliFMD.cxx                   \
+                  AliFMDSubDetector.cxx        \
+                  AliFMD1.cxx                  \
+                  AliFMD2.cxx                  \
+                  AliFMD3.cxx                  \
+                  AliFMDRing.cxx               \
+                  AliFMDPolygon.cxx            \
+                  AliFMDHit.cxx                \
+                  AliFMDDigitizer.cxx
+HDRS           =  $(SRCS:.cxx=.h) AliFMDMap.h
+DHDR           := FMDsimLinkDef.h
+EINCLUDE       := $(ALICE)/RAW
 
+#
+# EOF
+#
\ No newline at end of file