Added the class AliFMDGeometryBuilder (and derived
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 5 Dec 2005 22:52:09 +0000 (22:52 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 5 Dec 2005 22:52:09 +0000 (22:52 +0000)
AliFMDGeometryBuilderSimple) that defines the geometry.  AliFMDGeometry
uses that class.   AliFMDGeometry can also get crucial information from
a predefined class (but more needs to be extracted from the TGeoManager).
The code has been changed to reflect this.  In particular, the class
AliFMDSimulator is largely obsolete.   I've kept it for a while, as I'd
like to test what penalty  one endure from such a class.   I believe
it is negligible, but Federico thinks it's not.

The AliFMDG3Simulator and derived can essentially disappear.

Fixed some compilation warnings in AliFMDReconstructor.

24 files changed:
FMD/AliFMD.cxx
FMD/AliFMD.h
FMD/AliFMDAlla.cxx
FMD/AliFMDDetector.cxx
FMD/AliFMDDetector.h
FMD/AliFMDGeometry.cxx
FMD/AliFMDGeometry.h
FMD/AliFMDGeometryBuilder.cxx [new file with mode: 0644]
FMD/AliFMDGeometryBuilder.h [new file with mode: 0644]
FMD/AliFMDGeometryBuilderSimple.cxx [new file with mode: 0644]
FMD/AliFMDGeometryBuilderSimple.h [new file with mode: 0644]
FMD/AliFMDReconstructor.cxx
FMD/AliFMDReconstructor.h
FMD/AliFMDRing.cxx
FMD/AliFMDRing.h
FMD/AliFMDSimulator.cxx
FMD/AliFMDSimulator.h
FMD/AliFMDv1.cxx
FMD/AliFMDv1.h
FMD/Config.C
FMD/FMDsimLinkDef.h
FMD/libFMDbase.pkg
FMD/libFMDrec.pkg
FMD/libFMDsim.pkg

index f07b1f9..17fb122 100644 (file)
 #include <AliLoader.h>         // ALILOADER_H
 #include <AliRun.h>            // ALIRUN_H
 #include <AliMC.h>             // ALIMC_H
+#include "AliMagF.h"           // ALIMAGF_H
 #include <AliLog.h>            // ALILOG_H
 #include "AliFMD.h"            // ALIFMD_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIG_H
 #include "AliFMDDetector.h"    // ALIFMDDETECTOR_H
 #include "AliFMDRing.h"                // ALIFMDRING_H
 #include "AliFMDDigitizer.h"   // ALIFMDDIGITIZER_H
+#ifdef USE_PRE_MOVE
 #include "AliFMDSimulator.h"   // ALIFMDSIMULATOR_H
 #include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H
 #include "AliFMDGeoSimulator.h"        // ALIFMDGEOSIMULATOR_H
 #include "AliFMDG3OldSimulator.h"      // ALIFMDG3OLDSIMULATOR_H
 #include "AliFMDGeoOldSimulator.h"     // ALIFMDGEOOLDSIMULATOR_H
+#else
+#include "AliFMDGeometryBuilderSimple.h"
+#endif
 #include "AliFMDRawWriter.h"   // ALIFMDRAWWRITER_H
+#include <TVector2.h>
 
 //____________________________________________________________________
 ClassImp(AliFMD)
@@ -134,7 +140,10 @@ AliFMD::AliFMD()
     fSDigits(0), 
     fNsdigits(0),
     fDetailed(kTRUE),
-    fSimulator(0)
+#ifdef USE_PRE_MOVE
+    fSimulator(0), 
+#endif
+    fBad(0)
 {
   //
   // Default constructor for class AliFMD
@@ -144,9 +153,8 @@ AliFMD::AliFMD()
   fDigits      = 0;
   fIshunt      = 0;
   fUseOld      = kFALSE;
-  fUseDivided  = kFALSE;
-  fUseAssembly = kFALSE;
-  fUseGeo      = kTRUE;
+  fUseAssembly = kTRUE;
+  fBad         = new TClonesArray("AliFMDHit");
 }
 
 //____________________________________________________________________
@@ -155,13 +163,14 @@ AliFMD::AliFMD(const AliFMD& other)
     fSDigits(other.fSDigits), 
     fNsdigits(other.fNsdigits),
     fDetailed(other.fDetailed),
-    fSimulator(other.fSimulator)
+#ifdef USE_PRE_MOVE
+    fSimulator(other.fSimulator),
+#endif
+    fBad(other.fBad)
 {
   // Copy constructor 
   fUseOld      = other.fUseOld;
-  fUseDivided  = other.fUseDivided;
   fUseAssembly = other.fUseAssembly;
-  fUseGeo      = other.fUseGeo;
 }
 
 //____________________________________________________________________
@@ -170,16 +179,18 @@ AliFMD::AliFMD(const char *name, const char *title)
     fSDigits(0),
     fNsdigits(0),
     fDetailed(kTRUE),
-    fSimulator(0)
+#ifdef USE_PRE_MOVE
+    fSimulator(0), 
+#endif
+    fBad(0)
 {
   //
   // Standard constructor for Forward Multiplicity Detector
   //
   AliDebug(10, "\tStandard CTOR");
   fUseOld      = kFALSE;
-  fUseDivided  = kFALSE;
   fUseAssembly = kFALSE;
-  fUseGeo      = kTRUE;
+  fBad         = new TClonesArray("AliFMDHit");
   
   // Initialise Hit array
   HitsArray();
@@ -214,6 +225,11 @@ AliFMD::~AliFMD ()
     delete fSDigits;
     fSDigits = 0;
   }
+  if (fBad) {
+    fBad->Delete();
+    delete fBad;
+    fBad = 0;
+  }
 }
 
 //____________________________________________________________________
@@ -224,8 +240,10 @@ AliFMD::operator=(const AliFMD& other)
   fSDigits             = other.fSDigits; 
   fNsdigits            = other.fNsdigits;
   fDetailed            = other.fDetailed;
+#ifdef USE_PRE_MOVE
   fSimulator            = other.fSimulator;
-  
+#endif
+  fBad                  = other.fBad;
   return *this;
 }
 
@@ -262,30 +280,220 @@ AliFMD::CreateGeometry()
   //     AliFMDSubDetector::Geomtry();
   //   END FOR
   //
+#ifndef USE_PRE_MOVE
+  AliFMDGeometry*  fmd = AliFMDGeometry::Instance();
+  if (fUseOld) fmd->SetBuilder(new AliFMDGeometryBuilderSimple(fDetailed));
+  fmd->SetDetailed(fDetailed);
+  fmd->UseAssembly(fUseAssembly);
+  fmd->Build();
+#else
   if (!fSimulator) {
     AliFatal("Simulator object not made yet!");
     return;
   }
   fSimulator->DefineGeometry();
+#endif
 }    
 
 //____________________________________________________________________
 void AliFMD::CreateMaterials() 
 {
-  // Register various materials and tracking mediums with the
-  // backend.   
+  // Define the materials and tracking mediums needed by the FMD
+  // simulation.   These mediums are made by sending the messages
+  // AliMaterial, AliMixture, and AliMedium to the passed AliModule
+  // object module.   The defined mediums are 
   // 
+  //   FMD Si$         Silicon (active medium in sensors)
+  //   FMD C$          Carbon fibre (support cone for FMD3 and vacuum pipe)
+  //   FMD Al$         Aluminium (honeycomb support plates)
+  //   FMD PCB$        Printed Circuit Board (FEE board with VA1_3)
+  //   FMD Chip$       Electronics chips (currently not used)
+  //   FMD Air$        Air (Air in the FMD)
+  //   FMD Plastic$    Plastic (Support legs for the hybrid cards)
+  //
+  // Pointers to TGeoMedium objects are retrived from the TGeoManager
+  // singleton.  These pointers are later used when setting up the
+  // geometry 
+  AliDebug(10, "\tCreating materials");
+  // Get pointer to geometry singleton object. 
+  AliFMDGeometry* geometry = AliFMDGeometry::Instance();
+  geometry->Init();
+#if 0
+  if (gGeoManager && gGeoManager->GetMedium("FMD Si$")) {
+    // We need to figure out the some stuff about the geometry
+    fmd->ExtractGeomInfo();
+    return;
+  }
+#endif  
+#ifndef USE_PRE_MOVE     
+  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          = geometry->GetSiDensity();
+  radiationLength  = 9.36;
+  maxBending       = 1;
+  maxStepSize      = .001;
+  precision        = .001;
+  minStepSize      = .001;
+  id               = kSiId;
+  AliMaterial(id, "Si$", a, z, density, radiationLength, absorbtionLength);
+  AliMedium(kSiId, "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, "Carbon$", a, z, density, radiationLength, absorbtionLength);
+  AliMedium(kCarbonId, "Carbon$", id,0,fieldType,maxField,maxBending,
+                   maxStepSize,maxEnergyLoss,precision,minStepSize);
+
+  // Aluminum
+  a                = 26.981539;
+  z                = 13.;
+  density          = 2.7;
+  radiationLength  = 8.9;
+  id               = kAlId;
+  AliMaterial(id, "Aluminum$",a,z, density, radiationLength, absorbtionLength);
+  AliMedium(kAlId, "Aluminum$", id, 0, fieldType, maxField, maxBending,
+           maxStepSize, maxEnergyLoss, precision, minStepSize);
+  
+  
+  // Copper 
+  a                = 63.546;
+  z                = 29;
+  density          =  8.96;
+  radiationLength  =  1.43;
+  id               = kCopperId;
+  AliMaterial(id, "Copper$", 
+                     a, z, density, radiationLength, absorbtionLength);
+  AliMedium(kCopperId, "Copper$", 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, "Si Chip$", as, zs, density, 6, ws);
+    AliMedium(kSiChipId, "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               = kKaptonId;
+    AliMixture(id, "Kaption$", as, zs, density, 4, ws);
+    AliMedium(kKaptonId, "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, "Air$", as, zs, density, 4, ws);
+    AliMedium(kAirId, "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, "PCB$", as, zs, density, 14, ws);
+    AliMedium(kPcbId, "PCB$", id,0,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, "Plastic$", as, zs, density, -2, ws);
+    AliMedium(kPlasticId, "Plastic$", id,0,fieldType,maxField,maxBending,
+             maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+#else
   AliDebug(10, "\tCreating materials");
 
   if (fSimulator) {
     AliFatal("Simulator object already instantised!");
     return;
   }
-  AliFMDGeometry* geometry = AliFMDGeometry::Instance();
-  geometry->Init();
   TVirtualMC* mc = TVirtualMC::GetMC();
+
   Bool_t geo = mc->IsRootGeometrySupported();
-  if (geo && fUseGeo) {
+  if (geo) {
     if (fUseOld) 
       fSimulator = new AliFMDGeoOldSimulator(this, fDetailed);
     else 
@@ -299,39 +507,33 @@ void AliFMD::CreateMaterials()
   }
   AliDebug(1, Form("using a %s as simulation backend", 
                   fSimulator->IsA()->GetName()));
-  fSimulator->UseDivided(fUseDivided);
+  fSimulator->SetDetailed(fDetailed);
   fSimulator->UseAssembly(fUseAssembly);
   fSimulator->DefineMaterials();
+#endif
 }
 
 //____________________________________________________________________
 void  
 AliFMD::Init()
-{
-  //
-  // Initialis the FMD after it has been built
-  Int_t i;
-  //
-  if (AliLog::GetGlobalDebugLevel()) {
-    cout << "\n" << ClassName() << ": " << flush;
-    for (i = 0; i < 35; i++) cout << "*";
-    cout << " FMD_INIT ";
-    for (i = 0; i < 35; i++) cout << "*";
-    cout << "\n" << ClassName() << ": " << flush;
-    //
-    // Here the FMD initialisation code (if any!)
-    for (i = 0; i < 80; i++) cout << "*";
-    cout << endl;
-  }
-  //
-  //
-}
+{}
 
 //____________________________________________________________________
 void
 AliFMD::FinishEvent()
 {
+#ifndef USE_PRE_MOVE
+  if (fBad && fBad->GetEntries() > 0) {
+    AliWarning((Form("EndEvent", "got %d 'bad' hits", fBad->GetEntries())));
+    TIter next(fBad);
+    AliFMDHit* hit;
+    while ((hit = static_cast<AliFMDHit*>(next()))) 
+      hit->Print("D");
+    fBad->Clear();
+  }
+#else
   if (fSimulator) fSimulator->EndEvent();
+#endif
 }
 
 
@@ -910,7 +1112,9 @@ AliFMD::Browse(TBrowser* b)
   //
   AliDebug(30, "\tBrowsing the FMD");
   AliDetector::Browse(b);
+#ifdef USE_PRE_MOVE
   if (fSimulator) b->Add(fSimulator);
+#endif
   b->Add(AliFMDGeometry::Instance());
 }
 
index 99786a7..c58f0d7 100644 (file)
@@ -22,7 +22,9 @@ class TBranch;
 class TClonesArray;
 class TBrowser;
 class AliDigitizer;
+#ifdef USE_PRE_MOVE
 class AliFMDSimulator;
+#endif
 class AliFMDHit;
 
 //____________________________________________________________________
@@ -36,9 +38,7 @@ public:
   AliFMD& operator=(const AliFMD& other);
   // Use old implementation
   void UseOld(Bool_t use=kTRUE) { fUseOld = use;  }
-  void UseDivided(Bool_t use=kTRUE) { fUseDivided = use; }
   void UseAssembly(Bool_t use=kTRUE) { fUseAssembly = use; }
-  void UseGeo(Bool_t use=kTRUE) { fUseGeo = use; }
   void UseDetailed(Bool_t use=kTRUE) { fDetailed = use; }
   
   // GEometry ANd Tracking (GEANT :-)
@@ -111,11 +111,24 @@ protected:
   Int_t              fNsdigits;             // Number of digits  
   Bool_t             fDetailed;             // Use detailed geometry
   Bool_t             fUseOld;               // Use old approx geometry
-  Bool_t             fUseDivided;           // Use divided volumes
   Bool_t             fUseAssembly;          // Use divided volumes
-  Bool_t             fUseGeo;               // Allow use of TGeo impl.
   
+  enum {
+    kSiId,                 // ID index of Si medium
+    kAirId,                // ID index of Air medium
+    kPlasticId,            // ID index of Plastic medium
+    kPcbId,                // ID index of PCB medium
+    kSiChipId,             // ID index of Si Chip medium
+    kAlId,                 // ID index of Al medium
+    kCarbonId,             // ID index of Carbon medium
+    kCopperId,             // ID index of Copper Medium
+    kKaptonId              // ID index of Kapton Medium
+  };  
+
+#ifdef USE_PRE_MOVE
   AliFMDSimulator*   fSimulator;            // Simulator task
+#endif
+  TObjArray*         fBad;                  //! debugging - bad hits 
   
   ClassDef(AliFMD,10)     // Base class FMD entry point
 };
index b669332..1a508e7 100644 (file)
 #include "AliMC.h"
 
 ClassImp(AliFMDAlla)
+#if 0
+  ;
+#endif
 
-  //--------------------------------------------------------------------
-  AliFMDAlla::AliFMDAlla(const char *name, const char *title)
-    : AliFMD(name,title)
+//--------------------------------------------------------------------
+AliFMDAlla::AliFMDAlla(const char *name, const char *title)
+  : AliFMD(name,title)
 {
   //
   // Standart constructor for Forward Multiplicity Detector version 0
@@ -66,7 +69,8 @@ ClassImp(AliFMDAlla)
   //  setBufferSize(128000);
 }
 //-------------------------------------------------------------------------
-void AliFMDAlla::CreateGeometry()
+void 
+AliFMDAlla::CreateGeometry()
 {
   //
   // Create the geometry of Forward Multiplicity Detector version 0
@@ -137,7 +141,7 @@ void AliFMDAlla::CreateGeometry()
   // 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;
+  AliDebug(1, Form("Support width: %f", wideSupport));
 
   for (ifmd=0; ifmd<5; ifmd++)  {
     sprintf(nameFMD,"FMD%d",ifmd+1);
@@ -283,7 +287,8 @@ void AliFMDAlla::CreateGeometry()
 
 
 //------------------------------------------------------------------------
-void AliFMDAlla::CreateMaterials() 
+void 
+AliFMDAlla::CreateMaterials() 
 {
   Int_t isxfld   = gAlice->Field()->Integ();
   Float_t sxmgmx = gAlice->Field()->Max();
@@ -333,7 +338,8 @@ void AliFMDAlla::CreateMaterials()
 
 }
 //---------------------------------------------------------------------
-void AliFMDAlla::DrawDetector()
+void 
+AliFMDAlla::DrawDetector()
 {
   //
   // Draw a shaded view of the Forward multiplicity detector version 0
@@ -360,7 +366,8 @@ void AliFMDAlla::DrawDetector()
   gMC->Gdopt("hide","off");
 }
 //-------------------------------------------------------------------
-void AliFMDAlla::Init()
+void 
+AliFMDAlla::Init()
 {
   // Initialises version 0 of the Forward Multiplicity Detector
   //
@@ -374,8 +381,8 @@ void AliFMDAlla::Init()
 }
 
 //-------------------------------------------------------------------
-
-void AliFMDAlla::StepManager()
+void 
+AliFMDAlla::StepManager()
 {
   //
   // Called for every step in the Forward Multiplicity Detector
@@ -474,12 +481,13 @@ void AliFMDAlla::StepManager()
                  detector, ring, sector, strip, 
                  hits[0], hits[1], hits[2], hits[3], hits[4], hits[5], 
                  hits[6], iPart, hits[8]);
+      if (hits[6] > 1 && p/mass > 1) fBad->Add(h);
     } // IsTrackExiting()
   }
 }
 //--------------------------------------------------------------------------
-
-void AliFMDAlla::Response( Float_t Edep)
+void 
+AliFMDAlla::Response(Float_t Edep)
 {
   Float_t I=1.664*0.04*2.33/22400; // = 0.69e-6;
   Float_t chargeOnly=Edep/I;
@@ -488,7 +496,10 @@ void AliFMDAlla::Response( Float_t Edep)
   if (Edep>0)
     charge=Int_t(gRandom->Gaus(chargeOnly,500));       
 }   
-
+//--------------------------------------------------------------------------
+//
+// EOF
+//
 
 
 
index 3ecf951..e28f52c 100644 (file)
@@ -108,6 +108,36 @@ AliFMDDetector::Detector2XYZ(Char_t ring,
 }
 
 //____________________________________________________________________
+Bool_t
+AliFMDDetector::XYZ2Detector(Double_t  x,
+                            Double_t  y,
+                            Double_t  z,
+                            Char_t&   ring, 
+                            UShort_t& sector,
+                            UShort_t& strip) const
+{
+  AliFMDRing* rng = 0;
+  ring = -1;
+  for (int j = 0; j < 2; j++) {
+    rng = GetRing(j == 0 ? 'I'  : 'O');
+    if (!rng) continue;
+    Double_t ringZ    = GetRingZ(j == 0 ? 'I'  : 'O');
+    Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
+    if (TMath::Abs(z - ringZ) < 0.01 || 
+       TMath::Abs(z - ringZ + modSpace) < 0.01) break;
+    rng = 0;
+  }
+  if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
+                              sector, strip)) {
+    ring = rng->GetId();
+    return kTRUE;
+  }
+  return kFALSE;
+}
+
+  
+
+//____________________________________________________________________
 // 
 // EOF
 //
index 55d372e..d4442ce 100644 (file)
@@ -78,7 +78,8 @@ public:
   
   void Detector2XYZ(Char_t ring, UShort_t sector, UShort_t strip, 
                    Double_t& x, Double_t& y, Double_t& z) const;
-
+  Bool_t XYZ2Detector(Double_t x, Double_t y, Double_t z, 
+                     Char_t& ring, UShort_t& sector, UShort_t& strip) const;
 protected:
   Int_t                fId;                    // Detector number
   Double_t     fInnerZ;                // Position of outer ring along z
index 6851978..16b4c84 100644 (file)
 #include <TMatrix.h>            // ROOT_TMatrix
 #include <TParticle.h>          // ROOT_TParticle
 #include <Riostream.h>
+#ifndef USE_PRE_MOVE
+#include "AliFMDGeometryBuilder.h"
+#include <TArrayI.h>
+#include <TGeoManager.h>
+#include <TGeoVolume.h>
+#include <TGeoNode.h>
+static Int_t FindNodeDepth(const char* name, const char* volname);
+#endif
+
 
 //====================================================================
 ClassImp(AliFMDGeometry)
@@ -93,15 +102,23 @@ AliFMDGeometry::AliFMDGeometry()
 {
   // PROTECTED
   // Default constructor 
-  fUseFMD1 = kTRUE;
-  fUseFMD2 = kTRUE;
-  fUseFMD3 = kTRUE;  
+  fUseFMD1     = kTRUE;
+  fUseFMD2     = kTRUE;
+  fUseFMD3     = kTRUE;  
+#ifndef USE_PRE_MOVE
+  fDetailed    = kTRUE;
+  fUseAssembly = kTRUE;
+#endif
   fInner = new AliFMDRing('I');
   fOuter = new AliFMDRing('O');
   fFMD1  = new AliFMD1(fInner);
   fFMD2  = new AliFMD2(fInner, fOuter);
   fFMD3  = new AliFMD3(fInner, fOuter);
   fIsInitialized = kFALSE;
+  // fActive.Set(4);
+#ifndef USE_PRE_MOVE
+  fActive.Reset(-1);
+#endif
 }
 
 //____________________________________________________________________
@@ -116,6 +133,11 @@ AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other)
     fUseFMD1(other.fUseFMD1), 
     fUseFMD2(other.fUseFMD2), 
     fUseFMD3(other.fUseFMD3)
+#ifndef USE_PRE_MOVE
+    , fActive(other.fActive),
+    fDetailed(other.fDetailed),
+    fUseAssembly(other.fUseAssembly)
+#endif
 {
   // PROTECTED
   // Copy constructor
@@ -154,6 +176,45 @@ AliFMDGeometry::Init()
   fFMD3->Init();
 }
 
+#ifndef USE_PRE_MOVE
+//____________________________________________________________________
+void
+AliFMDGeometry::Build()
+{
+  if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
+  fBuilder->SetDetailed(fDetailed);
+  fBuilder->UseAssembly(fUseAssembly);
+  fBuilder->Exec();
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::SetActive(Int_t* active, Int_t n) 
+{
+  fActive.Set(n);
+  for (Int_t i = 0; i < n; i++) fActive[i] = active[i];
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::AddActive(Int_t active)
+{
+  Int_t n = fActive.fN;
+  fActive.Set(n+1);
+  fActive[n] = active;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDGeometry::IsActive(Int_t vol) const
+{
+  for (Int_t i = 0; i < fActive.fN; i++) 
+    if (fActive[i] == vol) return kTRUE;
+  return kFALSE;
+}
+
+#endif
+  
 //____________________________________________________________________
 AliFMDDetector*
 AliFMDGeometry::GetDetector(Int_t i) const
@@ -226,6 +287,35 @@ AliFMDGeometry::Detector2XYZ(UShort_t  detector,
   det->Detector2XYZ(ring, sector, strip, x, y, z);
 }
 
+//____________________________________________________________________
+Bool_t
+AliFMDGeometry::XYZ2Detector(Double_t  x, 
+                            Double_t  y, 
+                            Double_t  z,
+                            UShort_t& detector, 
+                            Char_t&   ring, 
+                            UShort_t& sector, 
+                            UShort_t& strip) const
+{
+  // Translate spatial coordinates (x,y,z) in the master reference frame of
+  // ALICE to the detector coordinates (detector, ring, sector,
+  // strip).  Note, that if this method is to be used in
+  // reconstruction or the like, then the input z-coordinate should be
+  // corrected for the events interactions points z-coordinate, like 
+  // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
+  AliFMDDetector* det = 0;
+  detector = 0;
+  for (int i = 1; i <= 3; i++) {
+    det = GetDetector(i);
+    if (!det) continue;
+    if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
+      detector = det->GetId();
+      return kTRUE;
+    }
+  }
+  return kFALSE;
+}
+
 
 //____________________________________________________________________
 void
@@ -272,6 +362,126 @@ AliFMDGeometry::Impact(const TParticle* /* particle */) const
   return kFALSE; 
 }
 
+#ifndef USE_PRE_MOVE
+//____________________________________________________________________ 
+void  
+AliFMDGeometry::ExtractGeomInfo()
+{
+  // Check the volume depth of some nodes, get the active volume
+  // numbers, and so forth. 
+  // 
+  // TODO: Here, we should actually also get the parameters of the
+  // shapes, like the verticies of the polygon shape that makes up the
+  // silicon sensor, the strip pitch, the ring radii, the z-positions,
+  // and so on - that is, all the geometric information we need for
+  // futher processing, such as simulation, digitization,
+  // reconstruction, etc. 
+  Int_t detectorDepth = FindNodeDepth("FMD1_1", "ALIC");
+  Int_t ringDepth     = FindNodeDepth(Form("FMDI_%d", Int_t('I')), "ALIC");
+  Int_t moduleDepth   = FindNodeDepth("FIFV_0", "ALIC");
+  Int_t sectorDepth   = FindNodeDepth("FISE_1", "ALIC");
+  fActive.Reset(-1);
+  AliDebug(1, Form("Geometry depths:\n"
+                  "   Sector:     %d\n"
+                  "   Module:     %d\n"
+                  "   Ring:       %d\n"
+                  "   Detector:   %d", 
+                  sectorDepth, moduleDepth, ringDepth, detectorDepth));
+  if (sectorDepth < 0 && moduleDepth < 0) {
+    fDetailed    = kFALSE;
+    fSectorOff   = -1;
+    fModuleOff   = -1;
+    fRingOff     = 0;
+    fDetectorOff = (ringDepth - detectorDepth);
+    TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
+    TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
+    if (actiVol) AddActive(actiVol->GetNumber());
+    if (actiVol) AddActive(actoVol->GetNumber());
+  }
+  else if (sectorDepth < 0) {
+    fDetailed    = kFALSE;
+    fSectorOff   = -1;
+    fModuleOff   = 1;
+    fRingOff     = (moduleDepth - ringDepth) + 1;
+    fDetectorOff = (moduleDepth - detectorDepth) + 1;
+    TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
+    TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
+    if (modiVol) AddActive(modiVol->GetNumber());
+    if (modoVol) AddActive(modoVol->GetNumber());
+  }
+  else {
+    Int_t stripDepth    = FindNodeDepth("FIST_1", "ALIC");
+    fDetailed    = kTRUE;
+    fSectorOff   = (stripDepth - sectorDepth);
+    fModuleOff   = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
+    fRingOff     = (stripDepth - ringDepth);
+    fDetectorOff = (stripDepth - detectorDepth );
+    TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
+    TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
+    if (striVol) AddActive(striVol->GetNumber());
+    if (stroVol) AddActive(stroVol->GetNumber());
+  }    
+  AliDebug(1, Form("Geometry offsets:\n"
+                  "   Sector:     %d\n"
+                  "   Module:     %d\n"
+                  "   Ring:       %d\n"
+                  "   Detector:   %d", 
+                  fSectorOff, fModuleOff, fRingOff, fDetectorOff));
+}
+
+  
+//____________________________________________________________________ 
+static Int_t 
+CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
+{
+  // If there's no node here. 
+  if (!node) return -1;
+  // Check if it this one 
+  TString sname(name);
+  if (sname == node->GetName()) return lvl;
+
+  // Check if the node is an immediate daugther 
+  TObjArray* nodes = node->GetNodes();
+  if (!nodes) return -1;
+  // Increase the level, and search immediate sub nodes. 
+  lvl++;
+  TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
+  if (found) return lvl;
+
+  // Check the sub node, if any of their sub-nodes match.
+  for (Int_t i = 0; i < nodes->GetEntries(); i++) {
+    TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
+    if (!sub) continue;
+    // Recurive check 
+    if (CheckNodes(sub, name, lvl) >= 0) return lvl;
+  }
+  // If not found, decrease the level 
+  lvl--;
+  return -1;
+}
+//____________________________________________________________________ 
+Int_t 
+FindNodeDepth(const char* name, const char* volname) 
+{
+  TGeoVolume* vol  = gGeoManager->GetVolume(volname);
+  if (!vol) {
+    std::cerr << "No top volume defined" << std::endl;
+    return -1;
+  }
+  TObjArray* nodes = vol->GetNodes();
+  if (!nodes) { 
+    std::cerr << "No nodes in top volume" << std::endl;
+    return -1;
+  }
+  TIter next(nodes);
+  TGeoNode* node = 0;
+  Int_t lvl = 0;
+  while ((node = static_cast<TGeoNode*>(next()))) 
+    if (CheckNodes(node, name, lvl) >= 0) return lvl;
+  return -1;
+}
+#endif
+
 //____________________________________________________________________
 //
 // EOF
index 1cd6f9e..bee945a 100644 (file)
@@ -21,6 +21,13 @@ class AliFMDDetector;
 class AliFMD1;
 class AliFMD2;
 class AliFMD3;
+#ifndef USE_PRE_MOVE
+#ifndef ROOT_TArrayI
+# include <TArrayI.h>
+#endif
+class AliFMDGeometryBuilder;
+class TArrayI;
+#endif
 
 
 //__________________________________________________________________
@@ -41,9 +48,31 @@ public:
   void            Disable(Int_t i);
   void            Enable(Int_t i);
   Double_t        GetSiDensity() const { return 2.33; }
-  void Detector2XYZ(UShort_t detector, 
-                   Char_t ring, UShort_t sector, UShort_t strip, 
-                   Double_t& x, Double_t& y, Double_t& z) const;
+  void            Detector2XYZ(UShort_t detector, Char_t ring, 
+                              UShort_t sector, UShort_t strip, 
+                              Double_t& x, Double_t& y, Double_t& z) const;
+  Bool_t          XYZ2Detector(Double_t x, Double_t y, Double_t z, 
+                              UShort_t& detector, Char_t& ring, 
+                              UShort_t& sector, UShort_t& strip) const;
+#ifndef USE_PRE_MOVE
+  void   Build();
+  Int_t  GetDetectorOff() const    { return fDetectorOff; }
+  Int_t  GetModuleOff() const      { return fModuleOff;   }
+  Int_t  GetRingOff() const        { return fRingOff;     }
+  Int_t  GetSectorOff() const      { return fSectorOff;   }
+  void   SetDetectorOff(Int_t off) { fDetectorOff = off; }
+  void   SetModuleOff(Int_t off)   { fModuleOff   = off; }
+  void   SetRingOff(Int_t off)     { fRingOff     = off; }
+  void   SetSectorOff(Int_t off)   { fSectorOff   = off; }
+  Bool_t IsActive(Int_t vol) const;
+  void   SetActive(Int_t* active, Int_t n);
+  void   AddActive(Int_t id);
+  void   SetBuilder(AliFMDGeometryBuilder* b) { fBuilder = b; }
+  void   ExtractGeomInfo();
+  void   SetDetailed(Bool_t det) { fDetailed = det; }
+  Bool_t IsDetailed() const { return fDetailed; }
+  void   UseAssembly(Bool_t ass)  { fUseAssembly = ass; }
+#endif  
 
   // AliGeometry member functions 
   virtual void GetGlobal(const AliRecPoint* p, TVector3& pos, 
@@ -66,6 +95,17 @@ protected:
   AliFMDGeometry& operator=(const AliFMDGeometry& other);
   virtual ~AliFMDGeometry() {}
   
+#ifndef USE_PRE_MOVE
+  AliFMDGeometryBuilder* fBuilder;
+  Int_t fDetectorOff;
+  Int_t fModuleOff;  
+  Int_t fRingOff;    
+  Int_t fSectorOff;  
+  TArrayI fActive;
+  Bool_t fDetailed;
+  Bool_t fUseAssembly;
+#endif
+
   ClassDef(AliFMDGeometry,1); //
 };
 
diff --git a/FMD/AliFMDGeometryBuilder.cxx b/FMD/AliFMDGeometryBuilder.cxx
new file mode 100644 (file)
index 0000000..4d3b2cd
--- /dev/null
@@ -0,0 +1,715 @@
+/**************************************************************************
+ * 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 wafers. This class
+// contains the base procedures for the Forward Multiplicity detector
+// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
+// which has 1 or 2 rings of silicon sensors. 
+//                                                       
+// This is the base class for all FMD manager classes. 
+//                    
+// The actual code is done by various separate classes.   Below is
+// diagram showing the relationship between the various FMD classes
+// that handles the simulation
+//
+//      +--------+ 1     +-----------------+ 
+//      | AliFMD |<>-----| AliFMDGeometryBuilder |
+//      +--------+      +-----------------+
+//                               ^              
+//                               |
+//                 +-------------+-------------+
+//                 |                           |             
+//        +--------------------+   +-------------------+
+//        | AliFMDGeometryBuilder |   | AliFMDG3Simulator | 
+//        +--------------------+   +---------+---------+
+//                                           ^
+//                                           |
+//                                +--------------------+
+//                               | AliFMDOldSimulator |
+//                               +--------------------+
+//      
+// *  AliFMD 
+//    This defines the interface for the various parts of AliROOT that
+//    uses the FMD, like AliFMDGeometryBuilder, AliFMDDigitizer, 
+//    AliFMDReconstructor, and so on. 
+//
+// *  AliFMDGeometryBuilder
+//    This is the base class for the FMD simulation tasks.   The
+//    simulator tasks are responsible to implment the geoemtry, and
+//    process hits. 
+//                                                                          
+// *  AliFMDGeometryBuilder
+//    This is a concrete implementation of the AliFMDGeometryBuilder that
+//    uses the TGeo classes directly only.  This defines the active
+//    volume as an ONLY XTRU shape with a divided MANY TUBS shape
+//    inside to implement the particular shape of the silicon
+//    sensors. 
+//
+// *  AliFMDG3Simulator
+//    This is a concrete implementation of the AliFMDGeometryBuilder that
+//    uses the TVirtualMC interface with GEANT 3.21-like messages.
+//    This implements the active volume as a divided TUBS shape.  Hits
+//    in the corners should be cut away at run time (but currently
+//    isn't). 
+//
+// *  AliFMDOldSimulator
+//    This is a concrete implementation of AliFMDGeometryBuilder.   It
+//    approximates the of the rings as segmented disks. 
+// 
+#include "AliFMDGeometryBuilder.h"     // ALIFMDGEOSIMULATOR_H
+#include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h"    // ALIFMDDETECTOR_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
+#include "AliFMD1.h"           // ALIFMD1_H
+#include "AliFMD2.h"           // ALIFMD2_H
+#include "AliFMD3.h"           // ALIFMD3_H
+#include "AliFMD.h"            // ALIFMD_H
+#include "AliLog.h"            // ALILOG_H
+#include <TGeoVolume.h>                // ROOT_TGeoVolume
+#include <TGeoTube.h>          // ROOT_TGeoTube
+#include <TGeoPcon.h>          // ROOT_TGeoPcon
+#include <TGeoMaterial.h>      // ROOT_TGeoMaterial
+#include <TGeoMedium.h>                // ROOT_TGeoMedium
+#include <TGeoXtru.h>          // ROOT_TGeoXtru
+#include <TGeoPolygon.h>       // ROOT_TGeoPolygon
+#include <TGeoTube.h>          // ROOT_TGeoTube
+#include <TGeoManager.h>       // ROOT_TGeoManager
+#include <TVector2.h>          // ROOT_TVector2
+#include <TArrayD.h>           // ROOT_TArrayD
+
+//====================================================================
+ClassImp(AliFMDGeometryBuilder)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+const Char_t* AliFMDGeometryBuilder::fgkActiveName     = "F%cAC";
+const Char_t* AliFMDGeometryBuilder::fgkSectorName     = "F%cSE";
+const Char_t* AliFMDGeometryBuilder::fgkStripName      = "F%cST";
+const Char_t* AliFMDGeometryBuilder::fgkModuleName     = "F%cMO";
+const Char_t* AliFMDGeometryBuilder::fgkPCBName                = "F%cP%c";
+const Char_t* AliFMDGeometryBuilder::fgkLongLegName    = "F%cLL";
+const Char_t* AliFMDGeometryBuilder::fgkShortLegName   = "F%cSL";
+const Char_t* AliFMDGeometryBuilder::fgkFrontVName     = "F%cFV";
+const Char_t* AliFMDGeometryBuilder::fgkBackVName      = "F%cBV";
+const Char_t* AliFMDGeometryBuilder::fgkRingName       = "FMD%c";
+const Char_t* AliFMDGeometryBuilder::fgkTopHCName      = "F%d%cI";
+const Char_t* AliFMDGeometryBuilder::fgkBotHCName      = "F%d%cJ";
+const Char_t* AliFMDGeometryBuilder::fgkTopIHCName     = "F%d%cK";
+const Char_t* AliFMDGeometryBuilder::fgkBotIHCName     = "F%d%cL";
+const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
+const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F3SB";
+const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F3SL";
+const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F3SF";
+
+//____________________________________________________________________
+AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
+  : fDetailed(kTRUE),
+    fUseAssembly(kTRUE),
+    fSi(0),
+    fC(0),
+    fAl(0),
+    fPCB(0),
+    fChip(0),
+    fPlastic(0)
+{
+  // Default constructor
+  fActiveId.Set(4);
+}
+
+//____________________________________________________________________
+AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
+  : TTask("FMD", "Geometry builder"),
+    fDetailed(detailed),
+    fUseAssembly(kTRUE),
+    fSi(0),
+    fC(0),
+    fAl(0),
+    fPCB(0),
+    fChip(0),
+    fPlastic(0)
+{
+  // Normal constructor
+  // 
+  // Parameters: 
+  // 
+  //      fmd          Pointer to AliFMD object 
+  //      detailed      Whether to make a detailed simulation or not 
+  // 
+  fActiveId.Set(4);
+}
+
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) 
+{
+  // Setup the geometry of a ring.    The defined TGeoVolume is
+  // returned, and should be used when setting up the rest of the
+  // volumes. 
+  // 
+  // 
+  // Parameters:
+  //
+  //     r             Pointer to ring geometry object 
+  // 
+  // Returns:
+  //    pointer to ring volume 
+  //
+  if (!r) { 
+    AliError("Didn't get a ring object");
+    return 0;
+  }
+  Char_t      id       = r->GetId();
+  Double_t    siThick  = r->GetSiThickness();
+  const Int_t nv       = r->GetNVerticies();
+  TVector2*   a        = r->GetVertex(5);
+  TVector2*   b        = r->GetVertex(3);
+  TVector2*   c        = r->GetVertex(4);
+  Double_t    theta    = r->GetTheta();
+  Double_t    off      = (TMath::Tan(TMath::Pi() * theta / 180) 
+                         * r->GetBondingWidth());
+  Double_t    rmax     = b->Mod();
+  Double_t    rmin     = r->GetLowR();
+  Double_t    pcbThick = r->GetPrintboardThickness();
+  Double_t    modSpace = r->GetModuleSpacing();
+  Double_t    legr     = r->GetLegRadius();
+  Double_t    legl     = r->GetLegLength();
+  Double_t    legoff   = r->GetLegOffset();
+  Int_t       ns       = r->GetNStrips();
+  Double_t    stripoff = a->Mod();
+  Double_t    dstrip   = (rmax - stripoff) / ns;
+  Double_t    space    = r->GetSpacing();
+  TArrayD xs(nv);
+  TArrayD ys(nv);
+  for (Int_t i = 0; i < nv; i++) {
+    // Reverse the order 
+    TVector2* vv = r->GetVertex(nv - 1 - i);
+    if (!vv) {
+      AliError(Form("Failed to get vertex # %d", nv - 1 - i));
+      continue;
+    }
+    xs[i] = vv->X();
+    ys[i] = vv->Y();
+  }
+  
+  // Shape of actual sensor 
+  TGeoXtru* moduleShape = new TGeoXtru(2);
+  moduleShape->DefinePolygon(nv, xs.fArray, ys.fArray);
+  moduleShape->DefineSection(0, - siThick/2);
+  moduleShape->DefineSection(1, siThick/2);
+  TGeoVolume* moduleVolume = new TGeoVolume(Form(fgkModuleName, id), 
+                                           moduleShape, fSi);
+  Int_t sid = moduleVolume->GetNumber();
+  fSectorOff   = -1;
+  fModuleOff   = 1;
+  fRingOff     = 2;
+  fDetectorOff = 3;
+  if (fDetailed) {
+    fSectorOff   = 1;
+    fModuleOff   = 4;
+    fRingOff     = 5;
+    fDetectorOff = 6;
+    // Virtual volume shape to divide - This volume is only defined if
+    // the geometry is set to be detailed. 
+    TGeoTubeSeg* activeShape = 
+      new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta);
+    TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
+                                             activeShape,fSi);
+    TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), 
+                                                     2, 2, -theta,0,0,"N");
+    TGeoVolume* stripVolume  = sectorVolume->Divide(Form(fgkStripName, id), 
+                                                   1, ns, stripoff, dstrip, 
+                                                   0, "SX");
+    sid = stripVolume->GetNumber();
+    moduleVolume->AddNodeOverlap(activeVolume, 0);
+  }
+  
+  switch (id) {
+  case 'i':
+  case 'I': fActiveId[0] = sid; break;
+  case 'o':
+  case 'O': fActiveId[2] = sid; break;
+  }
+
+  // Shape of Printed circuit Board 
+  TGeoXtru* pcbShape = new TGeoXtru(2);
+  for (Int_t i = 0;      i < nv / 2; i++) ys[i] -= off;
+  for (Int_t i = nv / 2; i < nv;     i++) ys[i] += off;
+  pcbShape->DefinePolygon(nv, xs.fArray, ys.fArray);
+  pcbShape->DefineSection(0, - pcbThick/2);
+  pcbShape->DefineSection(1, pcbThick/2);
+  TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id, 'B'), 
+                                        pcbShape, fPCB);
+
+  // Short leg shape 
+  TGeoTube*   shortLegShape  = new TGeoTube(0, legr, legl / 2);
+  TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), 
+                                             shortLegShape, fPlastic);
+
+  // Long leg shape
+  TGeoTube*   longLegShape   = new TGeoTube(0, legr, (legl + modSpace) / 2);
+  TGeoVolume* longLegVolume  = new TGeoVolume(Form(fgkLongLegName, id), 
+                                             longLegShape, fPlastic);
+  
+  TGeoMatrix* matrix = 0;
+  // Back container volume 
+  Double_t contThick     = siThick + pcbThick + legl + space;
+  TGeoTubeSeg* backShape = new TGeoTubeSeg(rmin, rmax, contThick/2, 
+                                          - theta, theta);
+  TGeoVolume* backVolume = new TGeoVolume(Form(fgkBackVName, id), 
+                                         backShape, fAir);
+  Double_t x = 0;
+  Double_t y = 0;
+  Double_t z = -contThick / 2 + siThick / 2;
+  matrix     = new TGeoTranslation(Form("FMD Ring  %c mod 1 transform", id), 
+                                  x, y, z);
+  backVolume->AddNode(moduleVolume, 0, matrix);
+  z          += siThick / 2 + space + pcbThick / 2;
+  matrix     =  new TGeoTranslation(Form("FMD Ring %c pcb 1 transfrom", id), 
+                                   x, y, z);
+  backVolume->AddNode(pcbVolume, 0, matrix);
+  x          =  a->X() + legoff + legr;
+  y          =  0;
+  z          += pcbThick / 2 + legl / 2;
+  matrix     = new TGeoTranslation(Form("FMD Ring %c leg 1 transfrom", id), 
+                                  x, y, z);
+  backVolume->AddNode(shortLegVolume, 0, matrix);
+  x          =  c->X();
+  y          =  c->Y() - legoff - legr - off;
+  matrix     =  new TGeoTranslation(Form("FMD Ring %c leg 2 transfrom", id), 
+                                   x, y, z);
+  backVolume->AddNode(shortLegVolume, 1, matrix);
+  y          =  -y;
+  matrix     =  new TGeoTranslation(Form("FMD Ring %c leg 3 transfrom", id), 
+                                   x, y, z);
+  backVolume->AddNode(shortLegVolume, 2, matrix);
+  // backVolume->SetVisibility(kFALSE);
+  // backVolume->VisibleDaughters(kTRUE);
+
+  // Front container volume 
+  contThick += modSpace;
+  TGeoTubeSeg* frontShape = new TGeoTubeSeg(rmin, rmax, contThick/2, 
+                                           -theta, theta);
+  TGeoVolume* frontVolume = new TGeoVolume(Form(fgkFrontVName, id),
+                                          frontShape, fAir);
+  x         =  0;
+  y         =  0;
+  z         =  -contThick / 2 + siThick / 2 ;
+  matrix    = new TGeoTranslation(Form("FMD Ring %c mod 2 transfrom", id), 
+                                 0, 0, z);
+  frontVolume->AddNode(moduleVolume, 1, matrix);
+  z         += siThick / 2 + space + pcbThick / 2;
+  matrix    =  new TGeoTranslation(Form("FMD Ring %c pcb 2 transfrom", id), 
+                                  x, y, z);
+  frontVolume->AddNode(pcbVolume, 1, matrix);
+  x         =  a->X() + legoff + legr;
+  y         =  0;
+  z         += pcbThick / 2 + (legl + modSpace)/ 2;
+  matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
+                                  x, y, z);
+  frontVolume->AddNode(longLegVolume, 0, matrix);
+  x         =  c->X();
+  y         =  c->Y() - legoff - legr - off;
+  matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
+                                  x, y, z);
+  frontVolume->AddNode(longLegVolume, 1, matrix);
+  y         =  -y;
+  matrix    =  new TGeoTranslation(Form("FMD Ring %c leg 4 transfrom", id), 
+                                  x, y, z);
+  frontVolume->AddNode(longLegVolume, 2, matrix);
+  // frontVolume->SetVisibility(kFALSE);
+  // frontVolume->VisibleDaughters(kTRUE);
+  
+  // Ring mother volume 
+  TGeoTube*   ringShape  = new TGeoTube(rmin, rmax, contThick / 2);
+  TGeoVolume* ringVolume = new TGeoVolume(Form(fgkRingName,id),
+                                         ringShape,fAir);
+
+  Int_t nmod = r->GetNModules();
+  AliDebug(10, Form("making %d modules in ring %c", nmod, id));
+  for (Int_t i = 0; i < nmod; i++) {
+    Bool_t isFront    = (i % 2 == 0);
+    TGeoVolume* vol   = (isFront ? frontVolume : backVolume);
+    TGeoRotation* rot =new TGeoRotation(Form("FMD Ring %c rotation %d",id,i));
+    rot->RotateZ((i + .5) * 2 * theta);
+    Double_t z = (isFront ? 0 : modSpace) / 2;
+    matrix     = new TGeoCombiTrans(Form("FMD Ring %c transform %d", id, i), 
+                                   0, 0, z, rot);
+    ringVolume->AddNode(vol, i, matrix);
+  }
+
+  ringVolume->SetVisibility(kFALSE);
+  ringVolume->VisibleDaughters(kTRUE);
+  return ringVolume;
+}
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, 
+                                       TGeoVolume* mother, 
+                                       Double_t    zmother, 
+                                       TGeoVolume* inner, 
+                                       TGeoVolume* outer) 
+{
+  // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
+  // This includes putting the Honeycomb support plates and the rings
+  // into the mother volumes.   
+  // 
+  // Parameeters:
+  //   d         The detector geometry to use 
+  //   mother    The mother volume of the detector 
+  //    zmother          The midpoint in global coordinates of detector vol.
+  //   inner     Pointer to inner ring volume 
+  //    outer    Pointer to outer ring volume
+  //
+  // Returns:
+  //    Pointer to mother (detector volume) 
+  // 
+  if (!d) return 0;
+  // Loop over the defined rings 
+  for (int i = 0; i < 2; i++) {
+    AliFMDRing* r     = 0;
+    Double_t    lowr  = 0;
+    Double_t    highr = 0;
+    Double_t    rz    = 0;
+    TGeoVolume* rvol  = 0;
+    switch (i) {
+    case 0: 
+      r      = d->GetInner();
+      lowr   = d->GetInnerHoneyLowR();
+      highr  = d->GetInnerHoneyHighR();
+      rz     = d->GetInnerZ();
+      rvol   = inner;
+      break;
+    case 1: 
+      r      = d->GetOuter();
+      lowr   = d->GetOuterHoneyLowR();
+      highr  = d->GetOuterHoneyHighR();
+      rz     = d->GetOuterZ();
+      rvol   = outer;
+      break;
+    }
+    if (!r) continue;
+    Char_t   c       = r->GetId();
+    Int_t    id      = d->GetId();
+    Double_t hcThick = d->GetHoneycombThickness();
+    Double_t alThick = d->GetAlThickness();
+    Double_t z;
+    if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2;
+    else             z = zmother - rz + r->GetRingDepth() / 2;
+    // Place ring in mother volume
+    mother->AddNode(rvol, Int_t(c), 
+                   new TGeoTranslation(Form("FMD%d%c transform", id, c), 
+                                       0, 0, z));
+
+    z += r->GetRingDepth() / 2 + hcThick / 2;
+    // Top of Honeycomb
+    TGeoTubeSeg* topHCShape  = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180);
+    TGeoVolume*  topHCVolume = new TGeoVolume(Form(fgkTopHCName, id, c), 
+                                             topHCShape, fAl);
+    TGeoMatrix*  topHCMatrix = 
+      new TGeoTranslation(Form("FMD%d%c top HC transform", id, c), 0, 0, z);
+    mother->AddNode(topHCVolume, 0, topHCMatrix);
+
+    // Air in top of honeycomb
+    TGeoTubeSeg* topIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
+                                              (hcThick-alThick)/2, 0, 180);
+    TGeoVolume*  topIHCVolume = new TGeoVolume(Form(fgkTopIHCName, id, c), 
+                                              topIHCShape, fAir);
+    topHCVolume->AddNode(topIHCVolume, 0);
+    topHCVolume->VisibleDaughters(kFALSE);    
+    topHCVolume->SetVisibility(kTRUE);
+
+
+    // Bottom of Honeycomb
+    TGeoTubeSeg* botHCShape = new TGeoTubeSeg(lowr, highr, hcThick/2, 
+                                             180, 360);
+    TGeoVolume*  botHCVolume = new TGeoVolume(Form(fgkBotHCName, id, c), 
+                                             botHCShape, fAl);
+    TGeoMatrix*  botHCMatrix = 
+      new TGeoTranslation(Form("FMD%d%c bottom HC transform", id, c), 0, 0, z);
+    mother->AddNode(botHCVolume, 0, botHCMatrix);
+
+    // Air in bot of honeycomb
+    TGeoTubeSeg* botIHCShape = new TGeoTubeSeg(lowr+alThick, highr - alThick, 
+                                              (hcThick-alThick)/2, 180, 360);
+    TGeoVolume*  botIHCVolume = new TGeoVolume(Form(fgkBotIHCName, id, c), 
+                                              botIHCShape, fAir);
+    botHCVolume->AddNode(botIHCVolume, 0);
+    botHCVolume->VisibleDaughters(kFALSE);    
+    botHCVolume->SetVisibility(kTRUE);    
+  }
+  mother->SetVisibility(kFALSE);
+  mother->VisibleDaughters(kTRUE);
+  return mother;
+}
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, TGeoVolume* inner) 
+{
+  // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
+  // special support as it is at the momement. 
+  // 
+  // See also AliFMDGeometryBuilder::DetectorGeometry 
+  // 
+  if (!fmd1 || !inner) return 0;
+  Double_t rmin    = fmd1->GetInner()->GetLowR();
+  Double_t rmax    = fmd1->GetInnerHoneyHighR();
+  Double_t hcThick = fmd1->GetHoneycombThickness();
+  Double_t w       = fmd1->GetInner()->GetRingDepth() + hcThick;
+  Double_t z       = fmd1->GetInnerZ() + w / 2;
+
+  TGeoVolume* fmd1Volume = 0;
+  if (!fUseAssembly) {
+    TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2);
+    fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir);
+  }
+  else
+    fmd1Volume = new TGeoVolumeAssembly(fmd1->GetName());
+  
+  TGeoVolume* top = gGeoManager->GetVolume("ALIC");
+  TGeoMatrix* matrix = new TGeoTranslation("FMD1 transform", 0, 0, z);
+  top->AddNode(fmd1Volume, fmd1->GetId(), matrix);
+
+  return DetectorGeometry(fmd1, fmd1Volume, z, inner, 0);
+}
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
+                                TGeoVolume* inner, 
+                                TGeoVolume* outer) 
+{
+  // Setup the FMD2 geometry.  The FMD2 has no
+  // special support as it is at the momement. 
+  // 
+  // See also AliFMDGeometryBuilder::DetectorGeometry 
+  // 
+  if (!fmd2 || !inner || !outer) return 0;
+  Double_t rmin     = fmd2->GetInner()->GetLowR();
+  Double_t rmax     = fmd2->GetOuterHoneyHighR();
+  Double_t hcThick  = fmd2->GetHoneycombThickness();
+  Double_t ow       = fmd2->GetInner()->GetRingDepth();
+  Double_t iz       = fmd2->GetInnerZ();
+  Double_t oz       = fmd2->GetOuterZ();
+  Double_t w        = TMath::Abs(oz - iz) + ow + hcThick;
+  Double_t z        = oz + w / 2;
+  
+  TGeoVolume* fmd2Volume = 0;
+  if (!fUseAssembly) {
+    TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2);
+    fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir);
+  }
+  else 
+    fmd2Volume = new TGeoVolumeAssembly(fmd2->GetName());
+  
+  TGeoVolume* top = gGeoManager->GetVolume("ALIC");
+  TGeoMatrix* matrix = new TGeoTranslation("FMD2 transform", 0, 0, z);
+  top->AddNode(fmd2Volume, fmd2->GetId(), matrix);
+
+  return DetectorGeometry(fmd2, fmd2Volume, z, inner, outer);
+}
+  
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
+                                TGeoVolume* inner, 
+                                TGeoVolume* outer) 
+{
+  // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
+  // structure, as the support will also support the vacuum
+  // beam-pipe. 
+  // 
+  // See also AliFMDGeometryBuilder::DetectorGeometry 
+  // 
+  if (!fmd3 || !inner || !outer) return 0;
+  Double_t nlen    = fmd3->GetNoseLength();
+  Double_t nz      = fmd3->GetNoseZ();
+  Double_t noser1  = fmd3->GetNoseLowR();
+  Double_t noser2  = fmd3->GetNoseHighR();
+  Double_t conel   = fmd3->GetConeLength();
+  Double_t backl   = fmd3->GetBackLength();
+  Double_t backr1  = fmd3->GetBackLowR();
+  Double_t backr2  = fmd3->GetBackHighR();
+  Double_t zdist   = conel -  backl - nlen;
+  Double_t tdist   = backr2 - noser2;
+  Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
+  Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
+  Double_t innerZ  = fmd3->GetInnerZ();
+  Double_t innerZh = (innerZ - fmd3->GetInner()->GetRingDepth() 
+                     - fmd3->GetHoneycombThickness());
+  Double_t outerZ  = fmd3->GetOuterZ();
+  Double_t outerZh = (outerZ - fmd3->GetOuter()->GetRingDepth() 
+                     - fmd3->GetHoneycombThickness());
+  Double_t innerr1 = fmd3->GetInner()->GetLowR();
+  // Double_t innerr2 = fmd3->GetInner()->GetHighR();
+  Double_t outerr1 = fmd3->GetOuter()->GetLowR();
+  // Double_t outerr2 = fmd3->GetOuter()->GetHighR();
+  Double_t flanger = fmd3->GetFlangeR();
+  Double_t minZ    = TMath::Min(nz - conel, outerZh);
+  Double_t z       = fmd3->GetZ();
+  Double_t zi;
+
+  // FMD3 volume 
+  TGeoVolume* fmd3Volume = 0;
+  if (!fUseAssembly) {
+    TGeoPcon* fmd3Shape = new TGeoPcon(0, 360, 8);
+    zi = z - nz;
+    fmd3Shape->DefineSection(0, zi,  noser1,   noser2);
+    zi = z - (nz - nlen);
+    fmd3Shape->DefineSection(1, zi,  noser1,   fmd3->ConeR(z - zi)+.15);
+    zi = z - innerZ;
+    fmd3Shape->DefineSection(2, zi,  innerr1,  fmd3->ConeR(z - zi)+.15);
+    zi = z - innerZh;
+    fmd3Shape->DefineSection(3, zi,  innerr1,  fmd3->ConeR(z - zi)+.15);
+    fmd3Shape->DefineSection(4, zi,  outerr1,  fmd3->ConeR(z - zi)+.15);
+    zi = z - nz + zdist + nlen;
+    fmd3Shape->DefineSection(5, zi,  outerr1,  fmd3->ConeR(z - zi)+.15);
+    zi = z - nz + nlen + zdist;
+    fmd3Shape->DefineSection(6, zi,  outerr1,  flanger+1.5);
+    zi = z - minZ;
+    fmd3Shape->DefineSection(7, zi,  outerr1,  flanger+1.5);
+    fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir);
+  }
+  else 
+    fmd3Volume = new TGeoVolumeAssembly(fmd3->GetName());
+  
+  TGeoRotation* rot = new TGeoRotation("FMD3 rotatation");
+  rot->RotateY(180);
+  TGeoVolume* top = gGeoManager->GetVolume("ALIC");
+  TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 transform", 0, 0, z, rot);
+  top->AddNode(fmd3Volume, fmd3->GetId(), mmatrix);
+  
+  // Nose volume 
+  TGeoTube* noseShape = new TGeoTube(noser1, noser2, nlen / 2);
+  TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
+  zi = z - nz + nlen / 2;
+  TGeoMatrix* nmatrix = new TGeoTranslation("FMD3 Nose translation", 0, 0, zi);
+  // fmd3Volume->AddNodeOverlap(noseVolume, 0, nmatrix);
+  fmd3Volume->AddNode(noseVolume, 0, nmatrix);
+  
+  // Back
+  TGeoTube* backShape = new TGeoTube(backr1, backr2, backl / 2);
+  TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC);
+  zi = z - nz + conel - backl / 2;
+  TGeoMatrix* bmatrix = new TGeoTranslation("FMD3 Back translation", 0, 0, zi);
+  fmd3Volume->AddNode(backVolume, 0, bmatrix);
+  
+  Int_t n;
+  Double_t r;
+  // The flanges 
+  TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, 
+                                      fmd3->GetBeamWidth() / 2,
+                                      backl / 2);
+  TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC);
+  n = fmd3->GetNFlange();
+  r = backr2 + (flanger - backr2) / 2;
+  for (Int_t i = 0; i  < n; i++) {
+    Double_t phi = 360. / n * i + 180. / n;
+    Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
+    Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
+    TGeoRotation* rot = new TGeoRotation(Form("FMD3 Flange rotation %d", i));
+    rot->RotateZ(phi);
+    TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 flange transform %d", 
+                                                i), x, y, zi, rot);
+    // fmd3Volume->AddNodeOverlap(flangeVolume, i, matrix);
+    fmd3Volume->AddNode(flangeVolume, i, matrix);
+    
+  }
+
+  // The Beams 
+  TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, 
+                                    fmd3->GetBeamWidth() / 2 - .1,
+                                    beaml / 2);
+  TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC);
+  n = fmd3->GetNBeam();
+  r = noser2 + tdist / 2;
+  zi = z - nz + nlen + zdist / 2;
+  for (Int_t i = 0; i  < n; i++) {
+    Double_t phi = 360. / n * i;
+    Double_t x   = r * TMath::Cos(TMath::Pi() / 180 * phi);
+    Double_t y   = r * TMath::Sin(TMath::Pi() / 180 * phi);
+    TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i));
+    // Order is important
+    rot->RotateY(-theta);
+    rot->RotateZ(phi);
+    TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam transform %d", i),
+                                           x, y, zi, rot);
+    fmd3Volume->AddNode(beamVolume, i, matrix);    
+  }
+  
+  
+  return DetectorGeometry(fmd3, fmd3Volume, z, inner, outer);
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometryBuilder::Exec(Option_t*) 
+{
+  // Setup up the FMD geometry. 
+  AliDebug(1,  Form("\tGeometry options: %s, %s",
+                   (fDetailed  ? "divided into strips" : "one volume"), 
+                   (fUseAssembly ? "within assemblies" : "in real volumes")));
+  if (!gGeoManager) {
+    AliFatal("No TGeoManager defined");
+    return;
+  }
+
+  fSi      = gGeoManager->GetMedium("FMD_Si$");
+  fC       = gGeoManager->GetMedium("FMD_Carbon$");
+  fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
+  fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
+  fAir     = gGeoManager->GetMedium("FMD_Air$");
+  fPCB     = gGeoManager->GetMedium("FMD_PCB$");
+  fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
+  fCopper  = gGeoManager->GetMedium("FMD_Copper$");
+
+  if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper) {
+    AliError("Failed to get some or all tracking mediums");
+    return;
+  }    
+  AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+  TGeoVolume* inner = RingGeometry(fmd->GetInner());
+  TGeoVolume* outer = RingGeometry(fmd->GetOuter());
+  if (!inner || !outer) {
+    AliError("Failed to create one of the ring volumes");
+    return;
+  }
+  FMD1Geometry(fmd->GetFMD1(), inner);
+  FMD2Geometry(fmd->GetFMD2(), inner, outer);
+  FMD3Geometry(fmd->GetFMD3(), inner, outer);
+#ifndef USE_PRE_MOVE
+  fmd->SetSectorOff(fSectorOff);
+  fmd->SetModuleOff(fModuleOff);
+  fmd->SetRingOff(fRingOff);
+  fmd->SetDetectorOff(fDetectorOff);
+  fmd->SetActive(fActiveId.fArray, fActiveId.fN);
+#endif
+  // fmd->ExtractGeomInfo();
+  
+}
+
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDGeometryBuilder.h b/FMD/AliFMDGeometryBuilder.h
new file mode 100644 (file)
index 0000000..957144c
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef ALIFMDGEOMETRYBUILDER_H
+#define ALIFMDGEOMETRYBUILDER_H
+/* 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 ROOT_TTask
+# include <TTask.h>
+#endif
+#ifndef ROOT_TArrayI
+# include <TArrayI.h>
+#endif
+class TGeoVolume;
+class TGeoMedium;
+class AliFMD;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+//____________________________________________________________________
+class AliFMDGeometryBuilder : public TTask
+{
+public:
+  AliFMDGeometryBuilder();
+  /** CTOR */
+  AliFMDGeometryBuilder(Bool_t detailed);
+  virtual ~AliFMDGeometryBuilder() {}
+  /** Register */
+  virtual void Exec(Option_t* option="");
+  /** @param use Wheher to assemblies in the geometry definition */
+  virtual void UseAssembly(Bool_t use=kTRUE) { fUseAssembly = use; }
+  /** Whether to make a detailed geometry or not. 
+      @param use If true, make a detailed geometry */
+  virtual void SetDetailed(Bool_t use) { fDetailed = use; }
+  /** @return Sector offset in volume tree  */
+  Int_t GetSectorOff() const { return fSectorOff; }
+    /** @return Module offset in volume tree */
+  Int_t GetModuleOff() const { return fModuleOff; }
+    /** @return Ring offset in the volume tree  */
+  Int_t GetRingOff() const { return fRingOff; }
+    /** @return Detector offfset in the volume tree  */
+  Int_t GetDetectorOff() const { return fDetectorOff; }
+protected:
+  /** Make a ring volume 
+      @param r Ring geometry 
+      @return  Ring volume */
+  virtual TGeoVolume* RingGeometry(AliFMDRing* r);
+  /** Make a detector volume 
+      @param d Detector geometry 
+      @param mother Mother volume (detector volume)
+      @param zmother Z position of mother 
+      @param inner Inner ring volume 
+      @param outer Outer ring volume 
+      @return  Detector volume */
+  virtual TGeoVolume* DetectorGeometry(AliFMDDetector* d, 
+                                      TGeoVolume* mother, 
+                                      Double_t zmother, 
+                                      TGeoVolume* inner, 
+                                      TGeoVolume* outer=0);
+  /** Make FMD1 volume 
+      @param d Detector geometry 
+      @param inner Inner ring volume 
+      @return FMD1 volume  */
+  virtual TGeoVolume* FMD1Geometry(AliFMD1* d, TGeoVolume* inner);
+  /** Make FMD2 volume 
+      @param d Detector geometry 
+      @param inner Inner ring volume 
+      @param outer Outer ring volume 
+      @return FMD2 volume  */
+  virtual TGeoVolume* FMD2Geometry(AliFMD2* d, TGeoVolume* inner, 
+                                  TGeoVolume* outer);
+  /** Make FMD3 volume 
+      @param d Detector geometry 
+      @param inner Inner ring volume 
+      @param outer Outer ring volume 
+      @return FMD3 volume  */
+  virtual TGeoVolume* FMD3Geometry(AliFMD3* d, TGeoVolume* inner, 
+                                  TGeoVolume* outer);
+
+
+  TArrayI     fActiveId;      //! Active volume ID's
+  Bool_t      fDetailed;      // Whether to make a detailed simulation 
+  Bool_t      fUseAssembly;   // Assembly volumes
+  Int_t       fSectorOff;     // Sector offset in volume tree 
+  Int_t       fModuleOff;     // Module offset in volume tree
+  Int_t       fRingOff;       // Ring offset in the volume tree 
+  Int_t       fDetectorOff;   // Detector offfset in the volume tree 
+
+  TGeoMedium* fSi;      //! Si Medium
+  TGeoMedium* fC;       //! C Medium
+  TGeoMedium* fAl;      //! Al Medium
+  TGeoMedium* fPCB;     //! PCB Medium
+  TGeoMedium* fChip;    //! Chip Medium
+  TGeoMedium* fAir;     //! Air Medium
+  TGeoMedium* fPlastic;         //! Plastic Medium
+  TGeoMedium* fCopper;  //! Copper Medium
+
+  static const Char_t* fgkActiveName;  // Name of Active volumes
+  static const Char_t* fgkSectorName;  // Name of Sector volumes
+  static const Char_t* fgkStripName;   // Name of Strip volumes
+  static const Char_t* fgkModuleName;  // Name of Module volumes
+  static const Char_t* fgkPCBName;     // Name of PCB volumes
+  static const Char_t* fgkLongLegName; // Name of LongLeg volumes
+  static const Char_t* fgkShortLegName;        // Name of ShortLeg volumes
+  static const Char_t* fgkFrontVName;  // Name of Front volumes
+  static const Char_t* fgkBackVName;   // Name of Back volumes
+  static const Char_t* fgkRingName;    // Name of Ring volumes
+  static const Char_t* fgkTopHCName;   // Name of TopHC volumes
+  static const Char_t* fgkBotHCName;   // Name of BotHC volumes
+  static const Char_t* fgkTopIHCName;  // Name of TopIHC volumes
+  static const Char_t* fgkBotIHCName;  // Name of BotIHC volumes
+  static const Char_t* fgkNoseName;    // Name of Nose volumes
+  static const Char_t* fgkBackName;    // Name of Back volumes
+  static const Char_t* fgkBeamName;    // Name of Beam volumes
+  static const Char_t* fgkFlangeName;  // Name of Flange volumes
+
+  ClassDef(AliFMDGeometryBuilder,1)
+};
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
+
diff --git a/FMD/AliFMDGeometryBuilderSimple.cxx b/FMD/AliFMDGeometryBuilderSimple.cxx
new file mode 100644 (file)
index 0000000..2dff552
--- /dev/null
@@ -0,0 +1,219 @@
+/**************************************************************************
+ * 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 wafers. This class
+// contains the base procedures for the Forward Multiplicity detector
+// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
+// which has 1 or 2 rings of silicon sensors. 
+//                                                       
+// This is the base class for all FMD manager classes. 
+//                    
+// The actual code is done by various separate classes.   Below is
+// diagram showing the relationship between the various FMD classes
+// that handles the simulation
+//
+//      +--------+ 1     +-----------------------+ 
+//      | AliFMD |<>-----| AliFMDGeometryBuilder |
+//      +--------+      +-----------------------+
+//                               ^              
+//                               |
+//                    +-----------------------------+
+//                   | AliFMDGeometryBuilderSimple |
+//                   +-----------------------------+
+//                     
+//
+// *  AliFMD 
+//    This defines the interface for the various parts of AliROOT that
+//    uses the FMD, AliFMDDigitizer, AliFMDReconstructor, and so on. 
+//
+// *  AliFMDGeometryBuilder
+//    This is the base class for the FMD geometry builder tasks. The
+//    builder tasks are responsible to implment the geoemtry. This
+//    defines the active volume as an ONLY XTRU shape with a divided
+//    MANY TUBS shape inside to implement the particular shape of the
+//    silicon sensors. 
+//                                                                          
+// *  AliFMDGeometryBuilderSimple
+//    This is a concrete implementation of the AliFMDGeometryBuilder,
+//    that defines the active elements as sections of a TUBE. 
+//
+#include "AliFMDGeometryBuilderSimple.h" // ALIFMDG3OLDSIMULATOR_H
+#include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h"    // ALIFMDDETECTOR_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
+#include "AliFMD1.h"           // ALIFMD1_H
+#include "AliFMD2.h"           // ALIFMD2_H
+#include "AliFMD3.h"           // ALIFMD3_H
+#include "AliFMD.h"            // ALIFMD_H
+#include <AliLog.h>            // ALILOG_H
+#include <TVector2.h>          // ROOT_TVector2
+#include <TVirtualMC.h>                // ROOT_TVirtualMC
+#include <TArrayI.h>           // ROOT_TArrayI
+#include <TGeoVolume.h>                // ROOT_TGeoVolume
+#include <TGeoTube.h>          // ROOT_TGeoTube
+#include <TGeoMatrix.h>         // ROOT_TGeoMatrix
+#include <cmath>                // __CMATH__  
+//====================================================================
+ClassImp(AliFMDGeometryBuilderSimple)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDGeometryBuilderSimple::AliFMDGeometryBuilderSimple() 
+{
+  // Default constructor
+}
+
+//____________________________________________________________________
+AliFMDGeometryBuilderSimple::AliFMDGeometryBuilderSimple(Bool_t detailed) 
+  : AliFMDGeometryBuilder(detailed)
+{
+  // Normal constructor
+  // 
+  // Parameters: 
+  // 
+  //      fmd          Pointer to AliFMD object 
+  //      detailed      Whether to make a detailed simulation or not 
+  // 
+}
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeometryBuilderSimple::RingGeometry(AliFMDRing* r) 
+{
+  // Setup the geometry of a ring.    The defined TGeoVolume is
+  // returned, and should be used when setting up the rest of the
+  // volumes. 
+  // 
+  // Parameters:
+  //
+  //     r             Pointer to ring geometry object 
+  // 
+  // Returns:
+  //    true on success 
+  //
+  if (!r) { 
+    AliError("Didn't get a ring object");
+    return 0;
+  }
+  Char_t      id          = r->GetId();
+  Double_t    siThick     = r->GetSiThickness();
+  // const Int_t nv       = r->GetNVerticies();
+  //TVector2*   a           = r->GetVertex(5);
+  TVector2*   b           = r->GetVertex(3);
+  //TVector2*   c           = r->GetVertex(4);
+  Double_t    theta       = r->GetTheta();
+  //Double_t    off         = (TMath::Tan(TMath::Pi() * theta / 180) 
+  //                        * r->GetBondingWidth());
+  Double_t    rmax        = b->Mod();
+  Double_t    rmin        = r->GetLowR();
+  Double_t    pcbThick    = r->GetPrintboardThickness();
+  Double_t    copperThick = r->GetCopperThickness(); // .01;
+  Double_t    chipThick   = r->GetChipThickness(); // .01;
+  //Double_t    modSpace    = r->GetModuleSpacing();
+  //Double_t    legr        = r->GetLegRadius();
+  //Double_t    legl        = r->GetLegLength();
+  //Double_t    legoff      = r->GetLegOffset();
+  Int_t       ns          = r->GetNStrips();
+  Int_t       nsec        = Int_t(360 / theta);
+  Double_t    space       = r->GetSpacing();
+  //Double_t    stripoff    = a->Mod();
+  //Double_t    dstrip      = (rmax - stripoff) / ns;
+  TString     name;
+  TString     name2;
+  
+  Double_t ringWidth = (siThick + 2 * (pcbThick + copperThick + chipThick));
+  // Virtual volume shape to divide - This volume is only defined if
+  // the geometry is set to be detailed. 
+  // Ring mother volume 
+  TGeoShape* ringShape   = new TGeoTube(rmin, rmax, ringWidth / 2);
+  name                   =  Form(fgkRingName, id);
+  TGeoVolume* ringVolume = new TGeoVolume(name.Data(), ringShape, fAir);
+
+  TGeoShape* activeShape   = new TGeoTube(rmin, rmax, siThick / 2);
+  name                     = Form(fgkActiveName, id);
+  Double_t z               = - ringWidth / 2 + siThick / 2;
+  TGeoVolume* activeVolume = new TGeoVolume(name.Data(), activeShape, fSi);
+  ringVolume->AddNode(activeVolume, 1, new TGeoTranslation(0, 0, z));
+  
+  fSectorOff   = -1;
+  fModuleOff   = -1;
+  fRingOff     = 1;
+  fDetectorOff = 2;
+  Int_t sid = activeVolume->GetNumber();
+  if (fDetailed) {
+    fSectorOff   = 1;
+    fRingOff     = 3;
+    fDetectorOff = 4;
+    name                     = Form(fgkSectorName, id);
+    TGeoVolume* sectorVolume = activeVolume->Divide(name.Data(), 2, nsec,
+                                                   0, 0, 0, "N");
+    
+    name                     = Form(fgkStripName, id);
+    TGeoVolume* stripVolume  = sectorVolume->Divide(name.Data(), 1, ns,
+                                                   0, 0, 0, "N");
+    sid                      = stripVolume->GetNumber();
+    AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
+  }
+  switch (id) {
+  case 'i':
+  case 'I': fActiveId[0] = sid; break;
+  case 'o':
+  case 'O': fActiveId[2] = sid; break;
+  }
+
+  // Shape of Printed circuit Board 
+  Double_t boardThick = (pcbThick + copperThick + chipThick);
+  TGeoShape*  boardShape  =  new TGeoTube(rmin+.1, rmax-.1, boardThick/ 2);
+  name                    =  Form(fgkPCBName, id, 'B');
+  TGeoVolume* boardVolume =  new TGeoVolume(name.Data(), boardShape, fAir);
+  z                       += siThick / 2 + space + boardThick / 2;
+  ringVolume->AddNode(boardVolume,  0, new TGeoTranslation(0, 0, z));
+  ringVolume->AddNode(boardVolume,  1, new TGeoTranslation(0,0,z+boardThick));
+
+  // PCB
+  TGeoShape*  pcbShape    = new TGeoTube(rmin+.1,rmax-.1, pcbThick / 2);
+  name                    =  Form("F%cPC", id);
+  z                       =  -boardThick / 2 + pcbThick / 2;
+  TGeoVolume* pcbVolume   = new TGeoVolume(name.Data(), pcbShape, fPCB);
+  boardVolume->AddNode(pcbVolume, 0, new TGeoTranslation(0, 0, z));
+
+  // Copper
+  TGeoShape*  cuShape     =  new TGeoTube(rmin+.1, rmax-.1, copperThick / 2);
+  name                    =  Form("F%cCO", id);
+  z                       += pcbThick / 2 + copperThick / 2;
+  TGeoVolume* cuVolume    =  new TGeoVolume(name.Data(), cuShape, fCopper);
+  boardVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
+
+  // Chip
+  TGeoShape*  chipShape   = new TGeoTube(rmin+.1, rmax-.1, chipThick / 2);
+  name                    =  Form("F%cCH", id);
+  z                       += copperThick / 2 + chipThick / 2;
+  TGeoVolume* chipVolume  = new TGeoVolume(name.Data(), chipShape, fChip);
+  boardVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
+
+  return ringVolume;
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDGeometryBuilderSimple.h b/FMD/AliFMDGeometryBuilderSimple.h
new file mode 100644 (file)
index 0000000..6b12675
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef ALIFMDGEOMETRYBUILDERSIMPLE_H
+#define ALIFMDGEOMETRYBUILDERSIMPLE_H
+/* 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 ALIFMDGEOMETRYBUILDER
+# include <AliFMDGeometryBuilder.h>
+#endif
+class AliFMDRing;
+
+//____________________________________________________________________
+class AliFMDGeometryBuilderSimple : public AliFMDGeometryBuilder
+{
+public:
+  AliFMDGeometryBuilderSimple();
+  /** CTOR */
+  AliFMDGeometryBuilderSimple(Bool_t detailed);
+  virtual ~AliFMDGeometryBuilderSimple() {}
+protected:
+  /** Make a ring volume 
+      @param r Ring geometry 
+      @return  Ring volume */
+  TGeoVolume* RingGeometry(AliFMDRing* r);
+  ClassDef(AliFMDGeometryBuilderSimple,1);
+};
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
+
index 6801f5b..b5e23f5 100644 (file)
@@ -239,15 +239,15 @@ AliFMDReconstructor::Reconstruct(TTree* digitsTree,
   // FIXME: The vertex may not be known yet, so we may have to move
   // some of this to FillESD. 
   AliDebug(1, "Reconstructing from digits in a tree");
-
+#if 0
   if (fESD) {
-    const AliESDVertex* vertex = fESD->GetVertex();
+    // const AliESDVertex* vertex = fESD->GetVertex();
     // if (vertex) {
     //   AliDebug(1, Form("Got vertex from ESD: %f", vertex->GetZv()));
     //   fCurrentVertex = vertex->GetZv();
     // }
   }
-  
+#endif  
   TBranch *digitBranch = digitsTree->GetBranch("FMD");
   if (!digitBranch) {
     Error("Exec", "No digit branch for the FMD found");
@@ -374,6 +374,56 @@ AliFMDReconstructor::FillESD(TTree*  /* digitsTree */,
 #endif   
 }
 
+
+//____________________________________________________________________
+void 
+AliFMDReconstructor::Reconstruct(AliRawReader*,TTree*) const 
+{
+  // Cannot be used.  See member function with same name but with 2
+  // TTree arguments.   Make sure you do local reconstrucion 
+  AliError("MayNotUse");
+}
+//____________________________________________________________________
+void 
+AliFMDReconstructor::Reconstruct(AliRunLoader*) const 
+{
+  // Cannot be used.  See member function with same name but with 2
+  // TTree arguments.   Make sure you do local reconstrucion 
+  AliError("MayNotUse");
+}
+//____________________________________________________________________
+void 
+AliFMDReconstructor::Reconstruct(AliRunLoader*, AliRawReader*) const 
+{
+  // Cannot be used.  See member function with same name but with 2
+  // TTree arguments.   Make sure you do local reconstrucion 
+  AliError("MayNotUse");
+}
+//____________________________________________________________________
+void 
+AliFMDReconstructor::FillESD(AliRawReader*,TTree*,AliESD*) const 
+{
+  // Cannot be used.  See member function with same name but with 2
+  // TTree arguments.   Make sure you do local reconstrucion 
+  AliError("MayNotUse");
+}
+//____________________________________________________________________
+void 
+AliFMDReconstructor::FillESD(AliRunLoader*,AliESD*) const
+{
+  // Cannot be used.  See member function with same name but with 2
+  // TTree arguments.   Make sure you do local reconstrucion 
+  AliError("MayNotUse");
+}
+//____________________________________________________________________
+void 
+AliFMDReconstructor::FillESD(AliRunLoader*,AliRawReader*,AliESD*) const 
+{
+  // Cannot be used.  See member function with same name but with 2
+  // TTree arguments.   Make sure you do local reconstrucion 
+  AliError("MayNotUse");
+}
+
 //____________________________________________________________________
 //
 // EOF
index 348e5ff..85793bd 100644 (file)
@@ -62,6 +62,14 @@ public:
                         AliESD* esd) const;
   virtual void   SetESD(AliESD* esd) { fESD = esd; }
      
+private:
+  void Reconstruct(AliRawReader*, TTree*) const;
+  void Reconstruct(AliRunLoader*) const;
+  void Reconstruct(AliRunLoader*, AliRawReader*) const;
+  void FillESD(AliRawReader*, TTree*, AliESD*) const;
+  void FillESD(AliRunLoader*, AliESD*) const;
+  void FillESD(AliRunLoader*, AliRawReader*, AliESD*) const;
+  
 protected:
   virtual void     ProcessDigits(TClonesArray* digits) const;
   virtual UShort_t SubtractPedestal(AliFMDDigit* digit) const;
index 445eec9..93a9323 100644 (file)
@@ -95,6 +95,13 @@ AliFMDRing::Init()
   fVerticies.AddAt(new TVector2(xC,      yC), 4);
   fVerticies.AddAt(new TVector2(fLowR,   yA), 5);  
 
+  // A's length. Corresponds to distance from nominal beam line to the
+  // cornor of the active silicon element. 
+  fMinR = GetVertex(5)->Mod();
+  // A's length. Corresponds to distance from nominal beam line to the
+  // cornor of the active silicon element. 
+  fMaxR = fHighR;
+
   fRingDepth = (fSiThickness + fPrintboardThickness 
                + fCopperThickness + fChipThickness 
                + fLegLength + fModuleSpacing + fSpacing);
@@ -133,6 +140,35 @@ AliFMDRing::Detector2XYZ(UShort_t sector,
     z += TMath::Sign(fModuleSpacing, z);
 }
 
+//____________________________________________________________________
+Bool_t
+AliFMDRing::XYZ2Detector(Double_t  x, 
+                        Double_t  y, 
+                        Double_t  z,
+                        UShort_t& sector,
+                        UShort_t& strip) const
+{
+  sector = strip = 0;
+  Double_t r = TMath::Sqrt(x * x + y * y);
+  Int_t str = Int_t((r - fMinR) / GetPitch());
+  if (str < 0 || str >= GetNStrips()) return kFALSE;
+
+  Double_t phi = TMath::ATan2(y, x) * 180. / TMath::Pi();
+  if (phi < 0) phi = 360. + phi;
+  Int_t sec = Int_t(phi / fTheta);
+  if (sec < 0 || sec >= GetNSectors()) return kFALSE;
+  if ((sec / 2) % 2 == 1) {
+    if (TMath::Abs(z - TMath::Sign(fModuleSpacing, z)) >= 0.01)
+      return kFALSE;
+  }
+  else if (TMath::Abs(z) >= 0.01) return kFALSE;
+
+  strip  = str;
+  sector = sec;
+  return kTRUE;
+}
+
+
 //
 // EOF
 //
index 755a250..99ab1f3 100644 (file)
@@ -83,6 +83,10 @@ public:
   Double_t GetWaferRadius() const { return fWaferRadius; }
   /** @return Thickness of sensor */
   Double_t GetSiThickness() const { return fSiThickness; }
+  /** @return Minimum r for an active strip */
+  Double_t GetMinR() const { return fMinR; }
+  /** @return Maximum r for an active strip */
+  Double_t GetMaxR() const { return fMaxR; }
   /** @return Lower radius of ring */
   Double_t GetLowR() const { return fLowR; }
   /** @return Upper radius of ring */
@@ -113,7 +117,9 @@ public:
   Double_t GetChipThickness() const { return fChipThickness; }
   /** @return Value of spacing between si and PCB */
   Double_t GetSpacing() const { return fSpacing; }
-
+  /** @return The strip pitch */ 
+  Double_t GetPitch() const { return (fMaxR - fMinR) / fNStrips; }
+     
   /** @return List of verticies */
   const TObjArray& GetVerticies() const { return fVerticies; }
   /** @return Number of verticies */
@@ -124,7 +130,8 @@ public:
      
   void Detector2XYZ(UShort_t sector, UShort_t strip, 
                    Double_t& x, Double_t& y, Double_t& z) const;
-  
+  Bool_t XYZ2Detector(Double_t x, Double_t y, Double_t z, 
+                     UShort_t& sector, UShort_t& strip) const;
 private: 
   Char_t       fId;                    // The Id of this ring type
   Double_t     fBondingWidth;          // With of bonding pad on sensor
@@ -132,6 +139,8 @@ private:
   Double_t     fSiThickness;           // Thickness of sensor
   Double_t     fLowR;                  // Lower radius of ring
   Double_t     fHighR;                 // Upper radius of ring
+  Double_t     fMinR;                  // Lower radius of active strips
+  Double_t     fMaxR;                  // Upper radius of active strips
   Double_t     fTheta;                 // Opening angle of the silicon wafers
   Int_t                fNStrips;               // Number of strips
   Double_t     fRingDepth;             // How far the ring extends beyond z
index 2cacd68..68d5411 100644 (file)
@@ -132,8 +132,8 @@ const Char_t* AliFMDSimulator::fgkFlangeName    = "F3SF";
 //____________________________________________________________________
 AliFMDSimulator::AliFMDSimulator() 
   : fFMD(0), 
-    fDetailed(kFALSE),
     fActiveId(4), 
+    fDetailed(kFALSE),
     fUseDivided(kFALSE),
     fUseAssembly(kTRUE), 
     fBad(0)
@@ -145,8 +145,8 @@ AliFMDSimulator::AliFMDSimulator()
 AliFMDSimulator::AliFMDSimulator(AliFMD* fmd, Bool_t detailed) 
   : TTask("FMDSimulator", "Forward Multiplicity Detector Simulator"), 
     fFMD(fmd), 
-    fDetailed(detailed),
     fActiveId(4),
+    fDetailed(detailed),
     fUseDivided(kFALSE),
     fUseAssembly(kTRUE),
     fBad(0)
index 3864ee1..7b65d29 100644 (file)
@@ -41,18 +41,20 @@ public:
   /** Deal with a hit in the FMD */
   virtual void Exec(Option_t* option="");
   virtual void EndEvent();
+  /** @param use Wheher to use a divided geometry */
   virtual void UseDivided(Bool_t use=kTRUE)  { fUseDivided = use; }
+  /** @param use Wheher to assemblies in the geometry definition */
   virtual void UseAssembly(Bool_t use=kTRUE) { fUseAssembly = use; }
+  /** Whether to make a detailed geometry or not. 
+      @param use If true, make a detailed geometry */
+  virtual void SetDetailed(Bool_t use) { fDetailed = use; }
 protected:  
   AliFMD*        fFMD;           //! Pointer to module 
-  Bool_t         fDetailed;      // Whether to make a detailed simulation 
   TLorentzVector fCurrentV;      //! Current hit postition 
   TLorentzVector fCurrentP;      //! Current hit momentum
   TArrayI        fActiveId;      //! Active volume ID's
   Int_t          fCurrentPdg;    //! Current hit particle code 
   Double_t       fCurrentDeltaE; //! Current hit energy loss
-  Bool_t         fUseDivided;    // Divided volumes
-  Bool_t         fUseAssembly;   // Assembly volumes
   
   Bool_t         IsActive(Int_t volId) const;
   Bool_t         VMC2FMD(Int_t copy, TLorentzVector& v,
@@ -92,6 +94,9 @@ protected:
     kKaptonId              // ID index of Kapton Medium
   };  
 
+  Bool_t      fDetailed;      // Whether to make a detailed simulation 
+  Bool_t      fUseDivided;    // Divided volumes
+  Bool_t      fUseAssembly;   // Assembly volumes
   Int_t fSectorOff;        // Sector offset in volume tree 
   Int_t fModuleOff;        // Module offset in volume tree
   Int_t fRingOff;          // Ring offset in the volume tree 
index 34a320a..e028469 100644 (file)
 #include <AliMC.h>             // ALIMC_H
 #include <AliLog.h>            // ALILOG_H
 #include "AliFMDv1.h"          // ALIFMDV1_H
+#ifndef USE_PRE_MOVE
+#include "AliFMDGeometryBuilder.h"
+#include "AliFMDGeometry.h"
+#include "AliFMDDetector.h"
+#include "AliFMDRing.h"
+#include <TParticlePDG.h>
+#include <TDatabasePDG.h>
+#include "AliFMDHit.h"
+#else
 #include "AliFMDSimulator.h"   // ALIFMDSIMULATOR_H
 #include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H
 #include "AliFMDGeoSimulator.h"        // ALIFMDGEOSIMULATOR_H
+#include "AliFMDG3OldSimulator.h"      // ALIFMDG3OLDSIMULATOR_H
+#include "AliFMDGeoOldSimulator.h"     // ALIFMDGEOOLDSIMULATOR_H
+#endif
 
 //____________________________________________________________________
 ClassImp(AliFMDv1)
@@ -44,10 +56,249 @@ ClassImp(AliFMDv1)
 #endif
 
 
+#ifndef USE_PRE_MOVE
+//____________________________________________________________________
+Bool_t
+AliFMDv1::VMC2FMD(TLorentzVector& v, UShort_t& detector,
+                 Char_t& ring, UShort_t& sector, UShort_t& strip) const
+{
+  TVirtualMC* mc = TVirtualMC::GetMC();
+  AliFMDGeometry*  fmd = AliFMDGeometry::Instance();
+
+  // Get track position
+  mc->TrackPosition(v);
+  Int_t moduleno; mc->CurrentVolOffID(fmd->GetModuleOff(), moduleno);
+  Int_t iring;    mc->CurrentVolOffID(fmd->GetRingOff(), iring);   
+  ring = Char_t(iring);
+  Int_t det;      mc->CurrentVolOffID(fmd->GetDetectorOff(), det); 
+  detector = det;
+  
+
+  // Get the ring geometry
+  //Int_t     nsec = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors();
+  Int_t     nstr  = fmd->GetDetector(detector)->GetRing(ring)->GetNStrips();
+  Double_t  lowr  = fmd->GetDetector(detector)->GetRing(ring)->GetMinR();
+  Double_t  theta = fmd->GetDetector(detector)->GetRing(ring)->GetTheta();
+  Double_t  pitch = fmd->GetDetector(detector)->GetRing(ring)->GetPitch();
+
+  // Figure out the strip number
+  Double_t r     = TMath::Sqrt(v.X() * v.X() + v.Y() * v.Y());
+  Int_t    str   = Int_t((r - lowr) / pitch);
+  if (str < 0 || str >= nstr) return kFALSE;
+  strip          = str;
+
+  // Figure out the sector number
+  Double_t phi    = TMath::ATan2(v.Y(), v.X()) * 180. / TMath::Pi();
+  if (phi < 0) phi = 360. + phi;
+  Double_t t      = phi - 2 * moduleno * theta;
+  sector          = 2 * moduleno;
+  if (t < 0 || t > 2 * theta) return kFALSE;
+  else if (t > theta)         sector += 1;
+
+  AliDebug(40, Form("<1> Inside an active FMD volume FMD%d%c[%2d,%3d] %s",
+                   detector, ring, sector, strip, mc->CurrentVolPath()));
+  return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDv1::VMC2FMD(Int_t copy, TLorentzVector& v,
+                 UShort_t& detector, Char_t& ring,
+                 UShort_t& sector, UShort_t& strip) const
+{
+  TVirtualMC* mc = TVirtualMC::GetMC();
+  AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+
+  strip = copy - 1;
+  Int_t sectordiv; mc->CurrentVolOffID(fmd->GetSectorOff(), sectordiv);
+  if (fmd->GetModuleOff() >= 0) {
+    Int_t module;    mc->CurrentVolOffID(fmd->GetModuleOff(), module);
+    sector = 2 * module + sectordiv;
+  }
+  else 
+    sector = sectordiv;
+  Int_t iring;     mc->CurrentVolOffID(fmd->GetRingOff(), iring); 
+  ring = Char_t(iring);
+  Int_t det;       mc->CurrentVolOffID(fmd->GetDetectorOff(), det); 
+  detector = det;
+
+  //Double_t  rz  = fmd->GetDetector(detector)->GetRingZ(ring);
+  Int_t     n   = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors();
+#if 0
+  if (rz < 0) {
+    Int_t s = ((n - sector + n / 2) % n) + 1;
+    AliDebug(1, Form("Recalculating sector to %d (=%d-%d+%d/2%%%d+1 z=%f)",
+                    s, n, sector, n, n, rz));
+    sector = s;
+  }
+#endif
+  if (sector < 1 || sector > n) {
+    Warning("Step", "sector # %d out of range (0-%d)", sector-1, n-1);
+    return kFALSE;
+  }
+  sector--;
+  // Get track position
+  mc->TrackPosition(v);
+  AliDebug(15, Form("<2> Inside an active FMD volume FMD%d%c[%2d,%3d] %s",
+                   detector, ring, sector, strip, mc->CurrentVolPath()));
+
+  return kTRUE;
+}
+#endif
+
 //____________________________________________________________________
 void 
 AliFMDv1::StepManager()
 {
+  // Member function that is executed each time a hit is made in the
+  // FMD.  None-charged particles are ignored.   Dead tracks  are
+  // ignored. 
+  //
+  // 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
+  //     
+#ifndef USE_PRE_MOVE
+  TVirtualMC* mc = TVirtualMC::GetMC();
+  if (!mc->IsTrackAlive()) return;
+  Double_t absQ = TMath::Abs(mc->TrackCharge());
+  if (absQ <= 0) return;
+  
+  Int_t copy;
+  Int_t vol = mc->CurrentVolID(copy);
+  AliFMDGeometry*  fmd = AliFMDGeometry::Instance();
+  if (!fmd->IsActive(vol)) {
+    AliDebug(50, Form("Not an FMD volume %d '%s'",vol,mc->CurrentVolName()));
+    return;
+  }
+  TLorentzVector v;
+  UShort_t       detector;
+  Char_t         ring;
+  UShort_t       sector;
+  UShort_t       strip;
+  
+  if (fmd->IsDetailed()) {
+    if (!VMC2FMD(copy, v, detector, ring, sector, strip)) return;
+  } else {
+    if (!VMC2FMD(v, detector, ring, sector, strip)) return;
+  }
+  TLorentzVector p;
+  mc->TrackMomentum(p);
+  Int_t    trackno = gAlice->GetMCApp()->GetCurrentTrackNumber();
+  Int_t    pdg     = mc->TrackPid();
+  Double_t mass    = mc->TrackMass();
+  Double_t edep    = mc->Edep() * 1000; // keV
+  Double_t poverm  = (mass == 0 ? 0 : p.P() / mass);
+  Bool_t   isBad   = kFALSE;
+  
+  // This `if' is to debug abnormal energy depositions.  We trigger on
+  // p/m approx larger than or equal to a MIP, and a large edep - more 
+  // than 1 keV - a MIP is 100 eV. 
+  if (edep > absQ * absQ && poverm > 1) {
+    isBad = kTRUE;
+    TArrayI procs;
+    mc->StepProcesses(procs);
+    TString processes;
+    for (Int_t ip = 0; ip < procs.fN; ip++) {
+      if (ip != 0) processes.Append(",");
+      processes.Append(TMCProcessName[procs.fArray[ip]]);
+    }
+    TDatabasePDG* pdgDB        = TDatabasePDG::Instance();
+    TParticlePDG* particleType = pdgDB->GetParticle(pdg);
+    TString pname(particleType ? particleType->GetName() : "???");
+    TString what;
+    if (mc->IsTrackEntering())    what.Append("entering ");
+    if (mc->IsTrackExiting())     what.Append("exiting ");
+    if (mc->IsTrackInside())      what.Append("inside ");
+    if (mc->IsTrackDisappeared()) what.Append("disappeared ");
+    if (mc->IsTrackStop())        what.Append("stopped ");
+    if (mc->IsNewTrack())         what.Append("new ");
+    if (mc->IsTrackAlive())       what.Append("alive ");
+    if (mc->IsTrackOut())         what.Append("out ");
+    
+    Int_t mother = gAlice->GetMCApp()->GetPrimary(trackno);
+    Warning("Step", "Track # %5d deposits a lot of energy\n" 
+           "  Volume:    %s\n" 
+           "  Momentum:  (%7.4f,%7.4f,%7.4f)\n"
+           "  PDG:       %d (%s)\n" 
+           "  Edep:      %-14.7f keV (mother %d)\n"
+           "  p/m:       %-7.4f/%-7.4f = %-14.7f\n"
+           "  Processes: %s\n"
+           "  What:      %s\n",
+           trackno, mc->CurrentVolPath(), p.X(), p.Y(), p.Z(),
+           pdg, pname.Data(), edep, mother, p.P(), mass, 
+           poverm, processes.Data(), what.Data());
+  }
+  
+  // Check that the track is actually within the active area 
+  Bool_t entering = mc->IsTrackEntering();
+  Bool_t inside   = mc->IsTrackInside();
+  Bool_t out      = (mc->IsTrackExiting()|| mc->IsTrackDisappeared()||
+                    mc->IsTrackStop());
+  // Reset the energy deposition for this track, and update some of
+  // our parameters.
+  if (entering) {
+    AliDebug(15, Form("Track # %8d entering active FMD volume %s: "
+                     "Edep=%f (%f,%f,%f)", trackno, mc->CurrentVolPath(),
+                     edep, v.X(), v.Y(), v.Z()));
+    fCurrentP      = p;
+    fCurrentV      = v;    
+    fCurrentDeltaE = edep;
+    fCurrentPdg    = pdg; // mc->IdFromPDG(pdg);
+  }
+  // If the track is inside, then update the energy deposition
+  if (inside && fCurrentDeltaE >= 0) {
+    fCurrentDeltaE += edep;
+    AliDebug(15, Form("Track # %8d inside active FMD volume %s: Edep=%f, "
+                     "Accumulated Edep=%f  (%f,%f,%f)", trackno, 
+                     mc->CurrentVolPath(), edep, fCurrentDeltaE, 
+                     v.X(), v.Y(), v.Z()));
+  }
+  // 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) {
+    if (fCurrentDeltaE >= 0) {
+      fCurrentDeltaE += edep;
+      AliDebug(15, Form("Track # %8d exiting active FMD volume %s: Edep=%g, "
+                       "Accumulated Edep=%g (%f,%f,%f)", trackno, 
+                       mc->CurrentVolPath(), edep, fCurrentDeltaE, 
+                       v.X(), v.Y(), v.Z()));
+      AliFMDHit* h = 
+       AddHitByFields(trackno, detector, ring, sector, strip,
+                      fCurrentV.X(),  fCurrentV.Y(), fCurrentV.Z(),
+                      fCurrentP.X(),  fCurrentP.Y(), fCurrentP.Z(), 
+                      fCurrentDeltaE, fCurrentPdg,   fCurrentV.T());
+      // Add a copy 
+      if (isBad && fBad) { 
+       new ((*fBad)[fBad->GetEntries()]) AliFMDHit(*h);
+      }
+    }
+    fCurrentDeltaE = -1;
+  }
+#else
   // Called for every step in the Forward Multiplicity Detector
   //
   // The message is deligated to AliFMDSimulator::Exec 
@@ -57,6 +308,7 @@ AliFMDv1::StepManager()
     return;
   }
   fSimulator->Exec("");
+#endif
 }
 //___________________________________________________________________
 //
index fa3f1b8..829d49d 100644 (file)
@@ -41,12 +41,20 @@ public:
   virtual Int_t  IsVersion() const {return 1;}
   virtual void   StepManager();
 protected:
-  Double_t   fCurrentDeltaE;        // The current accumelated energy loss
+#ifndef USE_PRE_MOVE
+  Bool_t VMC2FMD(TLorentzVector& v, UShort_t& detector,
+                Char_t& ring, UShort_t& sector, UShort_t& strip) const;
+  Bool_t VMC2FMD(Int_t copy, TLorentzVector& v,
+                UShort_t& detector, Char_t& ring,
+                UShort_t& sector, UShort_t& strip) const;
+#endif  
+
+  Double_t       fCurrentDeltaE;    // The current accumulated energy loss
   TLorentzVector fCurrentV;         // Current production vertex 
   TLorentzVector fCurrentP;         // Current momentum vector 
   Int_t          fCurrentPdg;       // Current PDG code 
   
-  ClassDef(AliFMDv1,4)  // Detailed FMD geometry
+  ClassDef(AliFMDv1,5)  // Detailed FMD geometry
 };
 
 #endif
index abf201f..7e1c07e 100644 (file)
@@ -222,7 +222,7 @@ Config()
   Rad_t rad  = kGluonRadiation;
   Mag_t mag  = k5kG;
   Int_t seed = 12345; //Set 0 to use the current time
-  MC_t  mc   = kGEANT3;
+  MC_t  mc   = kGEANT3TGEO;
   
   //____________________________________________________________________
   // Comment line 
@@ -629,9 +629,9 @@ Config()
     //=================== FMD parameters ============================
     AliFMD *FMD = new AliFMDv1("FMD", "normal FMD");
     AliLog::SetModuleDebugLevel("FMD", 1);
-    // FMD->UseDivided();
-    FMD->UseOld();
-    // FMD->UseGeo(kFALSE);
+    // FMD->UseDetailed(kFALSE);
+    // FMD->UseAssembly();
+    // FMD->UseOld();
   }
 
   if (useMUON) {
index 4ece71a..1922a5f 100644 (file)
@@ -20,6 +20,8 @@
 #pragma link C++ class  AliFMD+;
 #pragma link C++ class  AliFMDv0+;
 #pragma link C++ class  AliFMDv1+;
+#pragma link C++ class  AliFMDGeometryBuilder+;
+#pragma link C++ class  AliFMDGeometryBuilderSimple+;
 #pragma link C++ class  AliFMDSimulator+;
 #pragma link C++ class  AliFMDGeoSimulator+;
 #pragma link C++ class  AliFMDGeoOldSimulator+;
index a484c00..099580e 100644 (file)
@@ -2,22 +2,24 @@
 #
 # $Id$
 
-SRCS   =  AliFMDDigit.cxx              \
-          AliFMDMap.cxx                \
-          AliFMDFloatMap.cxx           \
-          AliFMDBoolMap.cxx            \
-          AliFMDUShortMap.cxx          \
-          AliFMDCalibPedestal.cxx      \
-          AliFMDCalibGain.cxx          \
-          AliFMDParameters.cxx         \
-          AliFMDGeometry.cxx           \
-          AliFMDRing.cxx               \
-          AliFMDDetector.cxx           \
-          AliFMD1.cxx                  \
-          AliFMD2.cxx                  \
-          AliFMD3.cxx
-HDRS   =  $(SRCS:.cxx=.h)
-DHDR   := FMDbaseLinkDef.h
+SRCS           =  AliFMDDigit.cxx              \
+                  AliFMDMap.cxx                \
+                  AliFMDFloatMap.cxx           \
+                  AliFMDBoolMap.cxx            \
+                  AliFMDUShortMap.cxx          \
+                  AliFMDCalibPedestal.cxx      \
+                  AliFMDCalibGain.cxx          \
+                  AliFMDParameters.cxx         \
+                  AliFMDGeometry.cxx           \
+                  AliFMDRing.cxx               \
+                  AliFMDDetector.cxx           \
+                  AliFMD1.cxx                  \
+                  AliFMD2.cxx                  \
+                  AliFMD3.cxx
+HDRS           =  $(SRCS:.cxx=.h)
+DHDR           := FMDbaseLinkDef.h
+# Un comment to use old code with seperate simulator task
+# PACKCXXFLAGS := $(CXXFLAGS) -DUSE_PRE_MOVE
 
 #
 # EOF
index cacfcef..1d55f19 100644 (file)
@@ -14,6 +14,8 @@ SRCS          =  AliFMDReconstructor.cxx      \
 HDRS           =  $(SRCS:.cxx=.h)
 DHDR           := FMDrecLinkDef.h
 EINCLUDE       := $(ALICE)/RAW
+# Un comment to use old code with seperate simulator task
+# PACKCXXFLAGS := $(CXXFLAGS) -DUSE_PRE_MOVE
 
 #
 # EOF
index 07b39d1..bc8cc08 100644 (file)
@@ -2,22 +2,26 @@
 #
 # $Id$
 
-SRCS           =  AliFMD.cxx                   \
-                  AliFMDv0.cxx                 \
-                  AliFMDv1.cxx                 \
-                  AliFMDSimulator.cxx          \
-                  AliFMDGeoSimulator.cxx       \
-                  AliFMDGeoOldSimulator.cxx    \
-                  AliFMDG3Simulator.cxx        \
-                  AliFMDG3OldSimulator.cxx     \
-                  AliFMDHit.cxx                \
-                  AliFMDDigitizer.cxx          \
-                  AliFMDEdepMap.cxx            \
-                  AliFMDRawWriter.cxx          \
+SRCS           =  AliFMD.cxx                           \
+                  AliFMDv0.cxx                         \
+                  AliFMDv1.cxx                         \
+                  AliFMDGeometryBuilder.cxx            \
+                  AliFMDGeometryBuilderSimple.cxx      \
+                  AliFMDSimulator.cxx                  \
+                  AliFMDGeoSimulator.cxx               \
+                  AliFMDGeoOldSimulator.cxx            \
+                  AliFMDG3Simulator.cxx                \
+                  AliFMDG3OldSimulator.cxx             \
+                  AliFMDHit.cxx                        \
+                  AliFMDDigitizer.cxx                  \
+                  AliFMDEdepMap.cxx                    \
+                  AliFMDRawWriter.cxx                  \
                   AliFMDAlla.cxx               
 HDRS           =  $(SRCS:.cxx=.h) 
 DHDR           := FMDsimLinkDef.h
 EINCLUDE       := $(ALICE)/RAW
+# Un comment to use old code with seperate simulator task
+# PACKCXXFLAGS := $(CXXFLAGS) -DUSE_PRE_MOVE
 
 #
 # EOF