]> git.uio.no Git - u/mrichter/AliRoot.git/commitdiff
Migrated to a geometry implemented via AliFMDGeometry (derives from
authorcholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 30 Dec 2004 10:43:47 +0000 (10:43 +0000)
committercholm <cholm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 30 Dec 2004 10:43:47 +0000 (10:43 +0000)
AliGeometry) and support classes AliFMDRing, AliFMDDetector.

The geometry classes holds parameters only, and does some calculations
based on these.

Simulation code is moved into a seperate abstract class AliFMDSimulator
with 2 concrete implementations.   AliFMDGeoSimulator and AliFMDg3Simulator.
The AliFMDSimulator classes sets up the geometry and handles hits in the
detector elements.   AliFMD simply forwards calls to the AliFMDSimulator
object.   AliFMDGeoSimulator implements the geometry via the ROOT TGeo
classes.  That means that we can implement the shape of the silicon
sensors via a divided TUBS volume put inside a ONLY XTRU volume.
AliFMDG3Simulator implements the geometry via messages to TVirtualMC.
Which concrete AliFMDSimulator is instantized is decided at run-time
by checking TVirtualMC::IsRootGeometrySupported.  If it returns true, then
the AliFMDGeoSimulator is used.  Otherwise, the AliFMDG3Simulator is used.

The new singleton class AliFMDParameters acts as a simple DB of some
parameters which is shared amoung the various piecies of the code, and
which does not belong to the geometry.

TODO:  Implement the AliGeometry member functions Impact and
ToGlobal.  The latter is seriously limited by the fact that AliRecoPoint
only has 3 indicies to identify a detector, while the FMD uses 4 (detector,
ring, sector, strip).   Implement the DrawDetector member function in
AliFMDSimulator (one way od the other).   In AliFMDG3Detector, we should
check if the hit is inside the real shape of the silicon sensor.

Things to consider:  TGeoManager says it finds the `illegal' extrussions:

  * extrusion ov058/FIMO_x_0: vol=FIMO node=FIAC_0 extr=1.16823
  * extrusion ov061/FOMO_x_0: vol=FOMO node=FOAC_0 extr=0.737969

and overlaps

  * overlap ov190/FMD3_o_7_8: vol=FMD3 <F3SL_6<->F3SL_7> ovlp=0.148996
  * overlap ov191/FMD3_o_5_6: vol=FMD3 <F3SL_4<->F3SL_5> ovlp=0.148996
  * overlap ov192/FMD3_o_6_7: vol=FMD3 <F3SL_5<->F3SL_6> ovlp=0.148996
  * overlap ov193/FMD3_o_1_2: vol=FMD3 <F3SL_0<->F3SL_1> ovlp=0.148996
  * overlap ov194/FMD3_o_1_8: vol=FMD3 <F3SL_0<->F3SL_7> ovlp=0.148996
  * overlap ov195/FMD3_o_2_3: vol=FMD3 <F3SL_1<->F3SL_2> ovlp=0.148996
  * overlap ov196/FMD3_o_3_4: vol=FMD3 <F3SL_2<->F3SL_3> ovlp=0.148996
  * overlap ov197/FMD3_o_4_5: vol=FMD3 <F3SL_3<->F3SL_4> ovlp=0.148996

The first comes from the MANY TUBS volume inside the ONLY XTRU volume,
and that should be OK. The latter comes from the some overlaps between the
8 support beams in the FMD3 cone.  I've made these MANY volumes (I think),
but TGeoManager still complains (I don't know why - it shouldn't).

Christian Holm <cholm@nbi.dk>
Thursday, 30th of December, 2004.

61 files changed:
FMD/AliFMD.cxx
FMD/AliFMD.h
FMD/AliFMD1.cxx
FMD/AliFMD1.h
FMD/AliFMD2.cxx
FMD/AliFMD2.h
FMD/AliFMD3.cxx
FMD/AliFMD3.h
FMD/AliFMD3Support.cxx [deleted file]
FMD/AliFMD3Support.h [deleted file]
FMD/AliFMDBoolMap.cxx
FMD/AliFMDDetector.cxx [new file with mode: 0644]
FMD/AliFMDDetector.h [new file with mode: 0644]
FMD/AliFMDDigit.cxx
FMD/AliFMDDigitizer.cxx
FMD/AliFMDEdepMap.cxx
FMD/AliFMDG3Simulator.cxx [new file with mode: 0644]
FMD/AliFMDG3Simulator.h [new file with mode: 0644]
FMD/AliFMDGeoSimulator.cxx [new file with mode: 0644]
FMD/AliFMDGeoSimulator.h [new file with mode: 0644]
FMD/AliFMDGeometry.cxx [new file with mode: 0644]
FMD/AliFMDGeometry.h [new file with mode: 0644]
FMD/AliFMDHit.cxx
FMD/AliFMDMap.cxx
FMD/AliFMDMult.cxx
FMD/AliFMDMultAlgorithm.cxx
FMD/AliFMDMultNaiive.cxx
FMD/AliFMDMultPoisson.cxx
FMD/AliFMDMultRegion.cxx
FMD/AliFMDMultStrip.cxx
FMD/AliFMDParameters.cxx [new file with mode: 0644]
FMD/AliFMDParameters.h [new file with mode: 0644]
FMD/AliFMDPolygon.cxx [deleted file]
FMD/AliFMDPolygon.h [deleted file]
FMD/AliFMDRawReader.cxx
FMD/AliFMDRawReader.h
FMD/AliFMDRawStream.cxx
FMD/AliFMDRawWriter.cxx
FMD/AliFMDRawWriter.h
FMD/AliFMDReconstructor.cxx
FMD/AliFMDReconstructor.h
FMD/AliFMDRing.cxx
FMD/AliFMDRing.h
FMD/AliFMDSimulator.cxx [new file with mode: 0644]
FMD/AliFMDSimulator.h [new file with mode: 0644]
FMD/AliFMDSubDetector.cxx [deleted file]
FMD/AliFMDSubDetector.h [deleted file]
FMD/AliFMDUShortMap.cxx
FMD/AliFMDv0.cxx
FMD/AliFMDv0.h
FMD/AliFMDv1.cxx
FMD/AliFMDv1.h
FMD/Config.C
FMD/FMDbaseLinkDef.h
FMD/FMDsimLinkDef.h
FMD/Simulate.C
FMD/ViewFMD.C
FMD/libFMDbase.pkg
FMD/libFMDsim.pkg
FMD/scripts/DrawFMD2.C [new file with mode: 0644]
FMD/scripts/DrawFMD3.C

index 7e18e889ef32bdfee6494093b47a718358417ec0..c1fbfcede525bf48ba5e26a8fdac4bebd56b3567 100644 (file)
 //                                                                          
 // Forward Multiplicity Detector based on Silicon wafers. This class
 // contains the base procedures for the Forward Multiplicity detector
-// Detector consists of 5 Si volumes covered pseudorapidity interval
-// from 1.7 to 5.1.
+// 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 geometry 
+// that handles the simulation
 //
 //
 //       +----------+   +----------+   
-//       | AliFMDv1 |  | AliFMDv1 |   
+//       | AliFMDv1 |  | AliFMDv0 |   
 //       +----------+   +----------+   
-//            |              |
-//       +----+--------------+
-//       |
-//       |           +------------+ 1  +---------------+
-//       |        +- | AliFMDRing |<>--| AliFMDPolygon | 
-//       V     2  |  +------------+    +---------------+   
-//  +--------+<>--+        |
-//  | AliFMD |             ^                       
-//  +--------+<>--+        V 1..2                     
-//            3  | +-------------------+ 
-//               +-| AliFMDSubDetector | 
-//                 +-------------------+
+//            |              |                    +-----------------+
+//       +----+--------------+                 +--| AliFMDDigitizer |
+//       |                                     |  +-----------------+
+//       |           +---------------------+   |
+//       |        +- | AliFMDBaseDigitizer |<--+
+//       V     1  |  +---------------------+   |
+//  +--------+<>--+                            |  +------------------+
+//  | AliFMD |                                 +--| AliFMDSDigitizer |    
+//  +--------+<>--+                               +------------------+       
+//            1  | +-----------------+ 
+//               +-| AliFMDSimulator |
+//                 +-----------------+
 //                           ^              
 //                           |
 //             +-------------+-------------+
-//             |             |             |         
-//        +---------+   +---------+   +---------+
-//        | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
-//        +---------+   +---------+   +---------+
+//             |                           |         
+//    +--------------------+   +-------------------+
+//    | AliFMDGeoSimulator |   | AliFMDG3Simulator | 
+//    +--------------------+   +---------+---------+
 //      
 //
 // *  AliFMD 
 //    This defines the interface for the various parts of AliROOT that
-//    uses the FMD, like AliFMDDigitizer, AliFMDReconstructor, and so
-//    on. 
+//    uses the FMD, like AliFMDSimulator, AliFMDDigitizer, 
+//    AliFMDReconstructor, and so on. 
+//
+// *  AliFMDv0
+//    This is a concrete implementation of the AliFMD interface. 
+//    It is the responsibility of this class to create the FMD
+//    geometry.
 //
 // *  AliFMDv1 
 //    This is a concrete implementation of the AliFMD interface. 
 //    geometry, process hits in the FMD, and serve hits and digits to
 //    the various clients. 
 //  
-//    It uses the objects of class AliFMDSubDetector to do the various
-//    stuff for FMD1, 2, and 3 
-//
-// *  AliFMDRing 
-//    This class contains all stuff needed to do with a ring.  It's
-//    used by the AliFMDSubDetector objects to instantise inner and
-//    outer rings.  The AliFMDRing objects are shared by the
-//    AliFMDSubDetector objects, and owned by the AliFMDv1 object. 
-//
-// *  AliFMDPolygon 
-//    The code I lifted from TGeoPolygon to help with the geometry of
-//    the modules, as well as to decide wether a hit is actually with
-//    in the real module shape.  The point is, that the shape of the
-//    various ring modules are really polygons (much like the lid of a
-//    coffin), but it's segmented at constant radius.  That is very
-//    hard to implement using GEANT 3.21 shapes, so instead the
-//    modules are implemented as TUBS (tube sections), and in the step
-//    procedure we do the test whether the track was inside the real
-//    shape of the module.  
-//
-// *  AliFMD1, AliFMD2, and AliFMD3 
-//    These are specialisation of AliFMDSubDetector, that contains the
-//    particularities of each of the sub-detector system.  It is
-//    envisioned that the classes should also define the support
-//    volumes and material for each of the detectors.                          
+// *  AliFMDSimulator
+//    This is the base class for the FMD simulation tasks.   The
+//    simulator tasks are responsible to implment the geoemtry, and
+//    process hits. 
 //                                                                          
-// The responsible person for this module is Alla Maevskaia
-// <Alla.Maevskaia@cern.ch>.
+// *  AliFMDGeoSimulator
+//    This is a concrete implementation of the AliFMDSimulator that
+//    uses the TGeo classes directly only. 
 //
-// Many modifications by Christian Holm Christensen <cholm@nbi.dk>
+// *  AliFMDG3Simulator
+//    This is a concrete implementation of the AliFMDSimulator that
+//    uses the TVirtualMC interface with GEANT 3.21-like messages.
 //
 
 // These files are not in the same directory, so there's no reason to
 // ask the preprocessor to search in the current directory for these
 // files by including them with `#include "..."' 
+#include <math.h>               // __CMATH__
 #include <TClonesArray.h>      // ROOT_TClonesArray
 #include <TGeometry.h>         // ROOT_TGeomtry
 #include <TNode.h>             // ROOT_TNode
+#include <TXTRU.h>             // ROOT_TXTRU
+#include <TRotMatrix.h>                // ROOT_TRotMatrix
 #include <TTUBE.h>             // ROOT_TTUBE
 #include <TTree.h>             // ROOT_TTree
-#include <TVirtualMC.h>                // ROOT_TVirtualMC
 #include <TBrowser.h>          // ROOT_TBrowser
 #include <TMath.h>             // ROOT_TMath
+#include <TVirtualMC.h>                // ROOT_TVirtualMC
 
 #include <AliRunDigitizer.h>   // ALIRUNDIGITIZER_H
 #include <AliLoader.h>         // ALILOADER_H
 #include <AliRun.h>            // ALIRUN_H
 #include <AliMC.h>             // ALIMC_H
 #include <AliLog.h>            // ALILOG_H
-#include <AliMagF.h>           // ALIMAGF_H
 #include "AliFMD.h"            // ALIFMD_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIG_H
 #include "AliFMDHit.h"         // ALIFMDHIT_H
+#include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h"    // ALIFMDDETECTOR_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
 #include "AliFMDDigitizer.h"   // ALIFMDDIGITIZER_H
-#include "AliFMD1.h"           // ALIFMD1_H
-#include "AliFMD2.h"           // ALIFMD2_H
-#include "AliFMD3.h"           // ALIFMD3_H
+#include "AliFMDSimulator.h"   // ALIFMDSIMULATOR_H
+#include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H
+#include "AliFMDGeoSimulator.h"        // ALIFMDGEOSIMULATOR_H
 #include "AliFMDRawWriter.h"   // ALIFMDRAWWRITER_H
 
 //____________________________________________________________________
 ClassImp(AliFMD)
-
-//____________________________________________________________________
-const Char_t* AliFMD::fgkShortLegName = "FSSL";
-const Char_t* AliFMD::fgkLongLegName  = "FSLL";
+#if 0
+  ; // This is to keep Emacs from indenting the next line 
+#endif 
 
 //____________________________________________________________________
 AliFMD::AliFMD()
-  : fInner(0), 
-    fOuter(0),
-    fFMD1(0),
-    fFMD2(0), 
-    fFMD3(0), 
-    fSDigits(0), 
+  : fSDigits(0), 
     fNsdigits(0),
-    fPrintboardRotationId(0),
-    fIdentityRotationId(0),
-    fShortLegId(0),
-    fLongLegId(0),
-    fLegLength(0),
-    fLegRadius(0),
-    fModuleSpacing(0), 
-    fSiDensity(0),
-    fSiThickness(0),
-    fSiDeDxMip(1.664),
-    fVA1MipRange(0),
-    fAltroChannelSize(0),
-    fSampleRate(0)
+    fDetailed(kTRUE),
+    fSimulator(0)
 {
   //
   // Default constructor for class AliFMD
   //
-  AliDebug(0, "\tDefault CTOR");
+  AliDebug(10, "\tDefault CTOR");
   fHits     = 0;
   fDigits   = 0;
   fIshunt   = 0;
@@ -165,58 +140,26 @@ AliFMD::AliFMD()
 //____________________________________________________________________
 AliFMD::AliFMD(const AliFMD& other)
   : AliDetector(other),
-    fInner(other.fInner), 
-    fOuter(other.fOuter),
-    fFMD1(other.fFMD1),
-    fFMD2(other.fFMD2), 
-    fFMD3(other.fFMD3), 
     fSDigits(other.fSDigits), 
     fNsdigits(other.fNsdigits),
-    fPrintboardRotationId(other.fPrintboardRotationId),
-    fIdentityRotationId(other.fIdentityRotationId),
-    fShortLegId(other.fShortLegId),
-    fLongLegId(other.fLongLegId),
-    fLegLength(other.fLegLength),
-    fLegRadius(other.fLegRadius),
-    fModuleSpacing(other.fModuleSpacing), 
-    fSiDensity(other.fSiDensity),
-    fSiThickness(other.fSiThickness),
-    fSiDeDxMip(other.fSiDeDxMip),
-    fVA1MipRange(other.fVA1MipRange),
-    fAltroChannelSize(other.fAltroChannelSize),
-    fSampleRate(other.fSampleRate)
+    fDetailed(other.fDetailed),
+    fSimulator(other.fSimulator)
 {
   // Copy constructor 
 }
 
 //____________________________________________________________________
-AliFMD::AliFMD(const char *name, const char *title, bool detailed)
+AliFMD::AliFMD(const char *name, const char *title)
   : AliDetector (name, title),
-    fInner(0), 
-    fOuter(0),
-    fFMD1(0),
-    fFMD2(0), 
-    fFMD3(0),
     fSDigits(0),
     fNsdigits(0),
-    fPrintboardRotationId(0),
-    fIdentityRotationId(0),
-    fShortLegId(0),
-    fLongLegId(0),
-    fLegLength(0),
-    fLegRadius(0),
-    fModuleSpacing(0), 
-    fSiDensity(0),
-    fSiThickness(0),
-    fSiDeDxMip(1.664),
-    fVA1MipRange(0),
-    fAltroChannelSize(0),
-    fSampleRate(0)
+    fDetailed(kTRUE),
+    fSimulator(0)
 {
   //
   // Standard constructor for Forward Multiplicity Detector
   //
-  AliDebug(0, "\tStandard CTOR");
+  AliDebug(10, "\tStandard CTOR");
 
   // Initialise Hit array
   HitsArray();
@@ -230,64 +173,6 @@ AliFMD::AliFMD(const char *name, const char *title, bool detailed)
   fIshunt = 0;
   SetMarkerColor(kRed);
   SetLineColor(kYellow);
-  SetSiDensity();
-
-  // Create sub-volume managers 
-  fInner = new AliFMDRing('I', detailed);
-  fOuter = new AliFMDRing('O', detailed);
-  fFMD1  = new AliFMD1();
-  fFMD2  = new AliFMD2();
-  fFMD3  = new AliFMD3();
-
-  // Specify parameters of sub-volume managers 
-  fFMD1->SetInner(fInner);
-  fFMD1->SetOuter(0);
-
-  fFMD2->SetInner(fInner);
-  fFMD2->SetOuter(fOuter);
-  
-  fFMD3->SetInner(fInner);
-  fFMD3->SetOuter(fOuter);
-
-  SetLegLength();
-  SetLegRadius();
-  SetLegOffset();
-  SetModuleSpacing();
-  SetSiThickness();
-  SetSiDensity();
-  SetVA1MipRange();
-  SetAltroChannelSize();
-  SetSampleRate();
-  
-  fInner->SetLowR(4.3);
-  fInner->SetHighR(17.2);
-  fInner->SetWaferRadius(13.4/2);
-  fInner->SetTheta(36/2);
-  fInner->SetNStrips(512);
-  fInner->SetSiThickness(fSiThickness);
-  fInner->SetPrintboardThickness(.11);
-  fInner->SetBondingWidth(.5);
-
-  fOuter->SetLowR(15.6);
-  fOuter->SetHighR(28.0);
-  fOuter->SetWaferRadius(13.4/2);
-  fOuter->SetTheta(18/2);
-  fOuter->SetNStrips(256);
-  fOuter->SetSiThickness(fSiThickness);
-  fOuter->SetPrintboardThickness(.1);
-  fOuter->SetBondingWidth(.5);
-  
-  
-  fFMD1->SetHoneycombThickness(1);
-  fFMD1->SetInnerZ(340.0);
-  
-  fFMD2->SetHoneycombThickness(1);
-  fFMD2->SetInnerZ(83.4);
-  fFMD2->SetOuterZ(75.2);
-
-  fFMD3->SetHoneycombThickness(1);
-  fFMD3->SetInnerZ(-62.8);
-  fFMD3->SetOuterZ(-75.2);
 }
 
 //____________________________________________________________________
@@ -316,27 +201,11 @@ AliFMD&
 AliFMD::operator=(const AliFMD& other)
 {
   AliDetector::operator=(other);
-  fInner               = other.fInner; 
-  fOuter               = other.fOuter;
-  fFMD1                        = other.fFMD1;
-  fFMD2                        = other.fFMD2; 
-  fFMD3                        = other.fFMD3; 
   fSDigits             = other.fSDigits; 
   fNsdigits            = other.fNsdigits;
-  fSiDensity           = other.fSiDensity;
-  fPrintboardRotationId        = other.fPrintboardRotationId;
-  fIdentityRotationId  = other.fIdentityRotationId;
-  fShortLegId          = other.fShortLegId;
-  fLongLegId           = other.fLongLegId;
-  fLegLength           = other.fLegLength;
-  fLegRadius           = other.fLegRadius;
-  fModuleSpacing       = other.fModuleSpacing; 
-  fSiDensity           = other.fSiDensity;
-  fSiThickness         = other.fSiThickness;
-  fVA1MipRange         = other.fVA1MipRange;
-  fAltroChannelSize    = other.fAltroChannelSize;
-  fSampleRate          = other.fSampleRate;
-
+  fDetailed            = other.fDetailed;
+  fSimulator            = other.fSimulator;
+  
   return *this;
 }
 
@@ -372,43 +241,12 @@ AliFMD::CreateGeometry()
   //   FOR subdetectors fFMD1, fFMD2, and fFMD3 DO 
   //     AliFMDSubDetector::Geomtry();
   //   END FOR
-  //   
-
-  // DebugGuard guard("AliFMD::CreateGeometry");
-  AliDebug(10, "\tCreating geometry");
-
-  fInner->Init();
-  fOuter->Init();
-
-  Double_t par[3];
-
-  Int_t airId = (*fIdtmed)[kAirId];
-  Int_t alId  = (*fIdtmed)[kAlId];
-  Int_t cId   = (*fIdtmed)[kCarbonId];
-  Int_t siId  = (*fIdtmed)[kSiId];
-  Int_t pcbId = (*fIdtmed)[kPcbId];
-  Int_t plaId = (*fIdtmed)[kPlasticId];
-  Int_t pbId  = fPrintboardRotationId;
-  Int_t idId  = fIdentityRotationId;
-  
-  par[0]      =  fLegRadius - .1;
-  par[1]      =  fLegRadius;
-  par[2]      =  fLegLength / 2;
-  fShortLegId =  gMC->Gsvolu(fgkShortLegName,"TUBE", plaId, par, 3);
-  
-  par[2]      += fModuleSpacing / 2;
-  fLongLegId  =  gMC->Gsvolu(fgkLongLegName,"TUBE", plaId, par, 3);
-
-  fInner->SetupGeometry(airId, siId, pcbId, pbId, idId);
-  fOuter->SetupGeometry(airId, siId, pcbId, pbId, idId);
-
-  fFMD1->SetupGeometry(airId, alId, cId);
-  fFMD2->SetupGeometry(airId, alId, cId);
-  fFMD3->SetupGeometry(airId, alId, cId);
-  
-  fFMD1->Geometry("ALIC", pbId, idId);
-  fFMD2->Geometry("ALIC", pbId, idId);
-  fFMD3->Geometry("ALIC", pbId, idId);    
+  //
+  if (!fSimulator) {
+    AliFatal("Simulator object not made yet!");
+    return;
+  }
+  fSimulator->DefineGeometry();
 }    
 
 //____________________________________________________________________
@@ -417,170 +255,22 @@ void AliFMD::CreateMaterials()
   // Register various materials and tracking mediums with the
   // backend.   
   // 
-  // Currently defined materials and mediums are 
-  // 
-  //    FMD Air                Normal air 
-  //    FMD Si          Active silicon of sensors 
-  //    FMD Carbon      Normal carbon used in support, etc. 
-  //    FMD Kapton      Carbon used in Honeycomb
-  //    FMD PCB         Printed circuit board material 
-  //    FMD Plastic     Material for support legs 
-  // 
-  // Also defined are two rotation matricies. 
-  //
-  // DebugGuard guard("AliFMD::CreateMaterials");
   AliDebug(10, "\tCreating materials");
-  Int_t    id;
-  Double_t a                = 0;
-  Double_t z                = 0;
-  Double_t density          = 0;
-  Double_t radiationLength  = 0;
-  Double_t absorbtionLength = 999;
-  Int_t    fieldType        = gAlice->Field()->Integ();     // Field type 
-  Double_t maxField         = gAlice->Field()->Max();     // Field max.
-  Double_t maxBending       = 0;     // Max Angle
-  Double_t maxStepSize      = 0.001; // Max step size 
-  Double_t maxEnergyLoss    = 1;     // Max Delta E
-  Double_t precision        = 0.001; // Precision
-  Double_t minStepSize      = 0.001; // Minimum step size 
-  // Silicon 
-  a                = 28.0855;
-  z                = 14.;
-  density          = fSiDensity;
-  radiationLength  = 9.36;
-  maxBending       = 1;
-  maxStepSize      = .001;
-  precision        = .001;
-  minStepSize      = .001;
-  id               = kSiId;
-  AliMaterial(id, "FMD Si$", a, z, density, radiationLength, absorbtionLength);
-  AliMedium(kSiId, "FMD Si$",id,1,fieldType,maxField,maxBending,
-           maxStepSize,maxEnergyLoss,precision,minStepSize);
-
-
-  // Carbon 
-  a                = 12.011;
-  z                = 6.;
-  density          = 2.265;
-  radiationLength  = 18.8;
-  maxBending       = 10;
-  maxStepSize      = .01;
-  precision        = .003;
-  minStepSize      = .003;
-  id               = kCarbonId;
-  AliMaterial(id, "FMD Carbon$", a, z, density, radiationLength, 
-             absorbtionLength);
-  AliMedium(kCarbonId, "FMD Carbon$",id,0,fieldType,maxField,maxBending,
-           maxStepSize,maxEnergyLoss,precision,minStepSize);
-
-  // Aluminum
-  a                = 26.981539;
-  z                = 13.;
-  density          = 2.7;
-  radiationLength  = 8.9;
-  id               = kAlId;
-  AliMaterial(id, "FMD Aluminum$", a, z, density, radiationLength, 
-             absorbtionLength);
-  AliMedium(kAlId, "FMD Aluminum$", id, 0, fieldType, maxField, maxBending,
-           maxStepSize, maxEnergyLoss, precision, minStepSize);
-  
-  
-  // Silicon chip 
-  {
-    Float_t as[] = { 12.0107,      14.0067,      15.9994,
-                    1.00794,      28.0855,     107.8682 };
-    Float_t zs[] = {  6.,           7.,           8.,
-                     1.,          14.,          47. };
-    Float_t ws[] = {  0.039730642,  0.001396798,  0.01169634,
-                     0.004367771,  0.844665,     0.09814344903 };
-    density = 2.36436;
-    maxBending       = 10;
-    maxStepSize      = .01;
-    precision        = .003;
-    minStepSize      = .003;
-    id = kSiChipId;
-    AliMixture(id, "FMD Si Chip$", as, zs, density, 6, ws);
-    AliMedium(kSiChipId, "FMD Si Chip$", id, 0, fieldType, maxField, 
-             maxBending, maxStepSize, maxEnergyLoss, precision, minStepSize);
-  }
-  
-#if 0
-  // 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               = KaptionId;
-    AliMixture(id, "FMD Kaption$", as, zs, density, 4, ws);
-    AliMedium(kAlId, "FMD Kaption$",id,0,fieldType,maxField,maxBending,
-             maxStepSize,maxEnergyLoss,precision,minStepSize);
-  }
-#endif
 
-  // Air
-  {
-    Float_t as[] = { 12.0107, 14.0067,   15.9994,  39.948 };
-    Float_t zs[] = {  6.,      7.,       8.,       18. };
-    Float_t ws[] = { 0.000124, 0.755267, 0.231781, 0.012827 }; 
-    density      = .00120479;
-    maxBending   = 1;
-    maxStepSize  = .001;
-    precision    = .001;
-    minStepSize  = .001;
-    id           = kAirId;
-    AliMixture(id, "FMD Air$", as, zs, density, 4, ws);
-    AliMedium(kAirId, "FMD Air$", id,0,fieldType,maxField,maxBending,
-             maxStepSize,maxEnergyLoss,precision,minStepSize);
-  }
-  
-  // PCB
-  {
-    Float_t zs[] = { 14.,         20.,         13.,         12.,
-                     5.,         22.,         11.,         19.,
-                    26.,          9.,          8.,          6.,
-                     7.,          1.};
-    Float_t as[] = { 28.0855,     40.078,      26.981538,   24.305, 
-                    10.811,      47.867,      22.98977,    39.0983,
-                    55.845,      18.9984,     15.9994,     12.0107,
-                    14.0067,      1.00794};
-    Float_t ws[] = {  0.15144894,  0.08147477,  0.04128158,  0.00904554, 
-                     0.01397570,  0.00287685,  0.00445114,  0.00498089,
-                     0.00209828,  0.00420000,  0.36043788,  0.27529426,
-                     0.01415852,  0.03427566};
-    density      = 1.8;
-    maxBending   = 1;
-    maxStepSize  = .001;
-    precision    = .001;
-    minStepSize  = .001;
-    id           = kPcbId;
-    AliMixture(id, "FMD PCB$", as, zs, density, 14, ws);
-    AliMedium(kPcbId, "FMD PCB$", id,0,fieldType,maxField,maxBending,
-             maxStepSize,maxEnergyLoss,precision,minStepSize);
+  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)
+    fSimulator = new AliFMDGeoSimulator(this, fDetailed);
+  else 
+    fSimulator = new AliFMDG3Simulator(this, fDetailed);
   
-  // Plastic 
-  {
-    Float_t as[] = { 1.01, 12.01 };
-    Float_t zs[] = { 1.,   6.    };
-    Float_t ws[] = { 1.,   1.    };
-    density      = 1.03;
-    maxBending   = 10;
-    maxStepSize  = .01;
-    precision    = .003;
-    minStepSize  = .003;
-    id           = kPlasticId;
-    AliMixture(id, "FMD Plastic$", as, zs, density, -2, ws);
-    AliMedium(kPlasticId, "FMD Plastic$", id,0,fieldType,maxField,maxBending,
-               maxStepSize,maxEnergyLoss,precision,minStepSize);
-  }
-  AliMatrix(fPrintboardRotationId, 90, 90, 0, 90, 90, 0);
-  AliMatrix(fIdentityRotationId, 90, 0, 90, 90, 0, 0);
+  fSimulator->DefineMaterials();
 }
 
 //____________________________________________________________________
@@ -623,11 +313,117 @@ AliFMD::BuildGeometry()
   // AliFMDSubDetector::SimpleGeometry. 
   AliDebug(10, "\tCreating a simplified geometry");
 
+  AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+  
+  static TXTRU*     innerShape = 0;
+  static TXTRU*     outerShape = 0;
+  static TObjArray* innerRot   = 0;
+  static TObjArray* outerRot   = 0;
+
+  if (!innerShape || !outerShape) {
+    // Make the shapes for the modules 
+    for (Int_t i = 0; i < 2; i++) {
+      AliFMDRing* r = 0;
+      switch (i) {
+      case 0: r = fmd->GetRing('I'); break;
+      case 1: r = fmd->GetRing('O'); break;
+      }
+      if (!r) {
+       AliError(Form("no ring found for i=%d", i));
+       return;
+      }
+      Double_t    siThick  = r->GetSiThickness();
+      const Int_t nv       = r->GetNVerticies();
+      Double_t    theta    = r->GetTheta();
+      Int_t       nmod     = r->GetNModules();
+      
+      TXTRU* shape = new TXTRU(r->GetName(), r->GetTitle(), "void", nv, 2);
+      for (Int_t j = 0; j < nv; j++) {
+       TVector2* vv = r->GetVertex(nv - 1 - j);
+       shape->DefineVertex(j, vv->X(), vv->Y());
+      }
+      shape->DefineSection(0, -siThick / 2, 1, 0, 0);
+      shape->DefineSection(1, +siThick / 2, 1, 0, 0);
+      shape->SetLineColor(GetLineColor());
+      
+      TObjArray* rots = new TObjArray(nmod);
+      for (Int_t j = 0; j < nmod; j++) {
+       Double_t th = (j + .5) * theta * 2;
+       TString name(Form("FMD_ring_%c_rot_%02d", r->GetId(), j));
+       TString title(Form("FMD Ring %c Rotation # %d", r->GetId(), j));
+       TRotMatrix* rot = new TRotMatrix(name.Data(), title.Data(),
+                                        90, th, 90, fmod(90+th,360), 0, 0);
+       rots->AddAt(rot, j);
+      }
+      
+      switch (r->GetId()) {
+      case 'i':
+      case 'I': innerShape = shape; innerRot = rots; break;
+      case 'o':
+      case 'O': outerShape = shape; outerRot = rots; break;
+      }
+    }
+  }
+  
   TNode* top = gAlice->GetGeometry()->GetNode("alice");
   
-  fFMD1->SimpleGeometry(fNodes, top, GetLineColor(), 0);
-  fFMD2->SimpleGeometry(fNodes, top, GetLineColor(), 0);
-  fFMD3->SimpleGeometry(fNodes, top, GetLineColor(), 0);
+  for (Int_t i = 1; i <= 3; i++) {
+    AliFMDDetector* det = fmd->GetDetector(i);
+    if (!det) {
+      Warning("BuildGeometry", "FMD%d seems to be disabled", i);
+      continue;
+    }
+    Double_t w  = 0;
+    Double_t rh = det->GetRing('I')->GetHighR();
+    Char_t   id = 'I';
+    if (det->GetRing('O')) {
+      w  = TMath::Abs(det->GetRingZ('O') - det->GetRingZ('I'));
+      id = (TMath::Abs(det->GetRingZ('O')) 
+           > TMath::Abs(det->GetRingZ('I')) ? 'O' : 'I');
+      rh = det->GetRing('O')->GetHighR();
+    }
+    w += (det->GetRing(id)->GetModuleSpacing() +
+         det->GetRing(id)->GetSiThickness());
+    TShape* shape = new TTUBE(det->GetName(), det->GetTitle(), "void",
+                             det->GetRing('I')->GetLowR(), rh, w / 2);
+    Double_t z = (det->GetRingZ('I') - w / 2);
+    if (z > 0) z += det->GetRing(id)->GetModuleSpacing();
+    top->cd();
+    TNode* node = new TNode(det->GetName(), det->GetTitle(), shape, 
+                           0, 0, z, 0);
+    fNodes->Add(node);
+    
+    for (Int_t j = 0; j < 2; j++) {
+      AliFMDRing* r      = 0;
+      TShape*     rshape = 0;
+      TObjArray*  rots   = 0;
+      switch (j) {
+      case 0: 
+       r = det->GetRing('I'); rshape = innerShape; rots = innerRot; break;
+      case 1: 
+       r = det->GetRing('O'); rshape = outerShape; rots = outerRot; break;
+      }
+      if (!r) continue;
+      
+      Double_t    siThick  = r->GetSiThickness();
+      Int_t       nmod     = r->GetNModules();
+      Double_t    modspace = r->GetModuleSpacing();
+      Double_t    rz       = - (z - det->GetRingZ(r->GetId()));
+      
+      for (Int_t k = 0; k < nmod; k++) {
+       node->cd();
+       Double_t    offz    = (k % 2 == 1 ? modspace : 0);
+       TRotMatrix* rot     = static_cast<TRotMatrix*>(rots->At(k));
+       TString name(Form("%s%c_module_%02d", det->GetName(), r->GetId(),k));
+       TString title(Form("%s%c Module %d", det->GetName(), r->GetId(),k));
+       TNode* mnod = new TNode(name.Data(), title.Data(), rshape, 
+                               0, 0, rz - siThick / 2 
+                               + TMath::Sign(offz,z), rot);
+       mnod->SetLineColor(GetLineColor());
+       fNodes->Add(mnod);
+      } // for (Int_t k = 0 ; ...)
+    } // for (Int_t j = 0 ; ...)
+  } // for (Int_t i = 1 ; ...)
 }
 
 //____________________________________________________________________
@@ -640,18 +436,9 @@ AliFMD::DrawDetector()
   // DebugGuard guard("AliFMD::DrawDetector");
   AliDebug(10, "\tDraw detector");
   
+#if 0
   //Set ALIC mother transparent
   gMC->Gsatt("ALIC","SEEN",0);
-  gMC->Gsatt(fgkShortLegName,"SEEN",1);
-  gMC->Gsatt(fgkLongLegName,"SEEN",1);
-
-  //Set volumes visible
-  fFMD1->Gsatt();
-  fFMD2->Gsatt();
-  fFMD3->Gsatt();
-  fInner->Gsatt();
-  fOuter->Gsatt();
-
   //
   gMC->Gdopt("hide", "on");
   gMC->Gdopt("shad", "on");
@@ -663,6 +450,7 @@ AliFMD::DrawDetector()
   gMC->Gdhead(1111, "Forward Multiplicity Detector");
   gMC->Gdman(16, 10, "MAN");
   gMC->Gdopt("hide", "off");
+#endif
 }
 
 //____________________________________________________________________
@@ -1035,9 +823,6 @@ AliFMD::Hits2SDigits()
   // an AliFMDSDigitizer object, and executing it. 
   // 
   AliFMDSDigitizer* digitizer = new AliFMDSDigitizer("galice.root");
-  digitizer->SetSampleRate(fSampleRate);
-  digitizer->SetVA1MipRange(fVA1MipRange);
-  digitizer->SetAltroChannelSize(fAltroChannelSize);
   digitizer->Exec("");
 }
 
@@ -1048,9 +833,6 @@ AliFMD::CreateDigitizer(AliRunDigitizer* manager) const
 {
   // Create a digitizer object 
   AliFMDDigitizer* digitizer = new AliFMDDigitizer(manager);
-  digitizer->SetSampleRate(fSampleRate);
-  digitizer->SetVA1MipRange(fVA1MipRange);
-  digitizer->SetAltroChannelSize(fAltroChannelSize);
   return digitizer;
 }
 
@@ -1067,66 +849,9 @@ AliFMD::Digits2Raw()
   // This uses the class AliFMDRawWriter to do the job.   Please refer
   // to that class for more information. 
   AliFMDRawWriter writer(this);
-  writer.SetSampleRate(fSampleRate);
   writer.Exec();
 }
 
-//==================================================================
-//
-// Various setter functions for the common paramters 
-//
-
-//__________________________________________________________________
-void 
-AliFMD::SetLegLength(Double_t length) 
-{
-  // Set lenght of plastic legs that hold the hybrid (print board and
-  // silicon sensor) onto the honeycomp support
-  //
-  AliDebug(10, Form("\tLeg length set to %lf cm", length));
-  fLegLength = length;
-  fInner->SetLegLength(fLegLength);
-  fOuter->SetLegLength(fLegLength);
-}
-
-//__________________________________________________________________
-void 
-AliFMD::SetLegOffset(Double_t offset) 
-{
-  // Set offset from edge of hybrid to plastic legs that hold the
-  // hybrid (print board and silicon sensor) onto the honeycomp
-  // support 
-  //
-  AliDebug(10, Form("\tLeg offset set to %lf cm", offset));
-  fInner->SetLegOffset(offset);
-  fOuter->SetLegOffset(offset);
-}
-
-//__________________________________________________________________
-void 
-AliFMD::SetLegRadius(Double_t radius) 
-{
-  // Set the diameter of the plastic legs that hold the hybrid (print
-  // board and silicon sensor) onto the honeycomp support
-  //
-  AliDebug(10, Form("\tLeg radius set to %lf cm", radius));
-  fLegRadius = radius;
-  fInner->SetLegRadius(fLegRadius);
-  fOuter->SetLegRadius(fLegRadius);
-}
-
-//__________________________________________________________________
-void 
-AliFMD::SetModuleSpacing(Double_t spacing) 
-{
-  // Set the distance between the front and back sensor modules
-  // (module staggering). 
-  //
-  AliDebug(10, Form("\tModule spacing set to %lf cm", spacing));  
-  fModuleSpacing = spacing;
-  fInner->SetModuleSpacing(fModuleSpacing);
-  fOuter->SetModuleSpacing(fModuleSpacing);
-}
 
 //====================================================================
 //
@@ -1140,14 +865,10 @@ AliFMD::Browse(TBrowser* b)
   //
   AliDebug(30, "\tBrowsing the FMD");
   AliDetector::Browse(b);
-  if (fInner) b->Add(fInner, "Inner Ring");
-  if (fOuter) b->Add(fOuter, "Outer Ring");
-  if (fFMD1)  b->Add(fFMD1,  "FMD1 SubDetector");
-  if (fFMD2)  b->Add(fFMD2,  "FMD2 SubDetector");
-  if (fFMD3)  b->Add(fFMD3,  "FMD3 SubDetector");
+  if (fSimulator) b->Add(fSimulator);
+  b->Add(AliFMDGeometry::Instance());
 }
 
-
 //___________________________________________________________________
 //
 // EOF
index 050180c88be6c503e83119e3d2da8b91f16dc50c..48d3f5b51f1a08a4e46be4b4dd571d1cc893dbd0 100644 (file)
 #ifndef ALIDETECTOR_H 
 # include <AliDetector.h>
 #endif
-#ifndef ALIFMDSUBDETECTOR_H
-# include "AliFMDSubDetector.h"
-#endif
-#ifndef ALIFMDRING_H
-# include "AliFMDRing.h"
-#endif
 #ifndef ROOT_TBranch
 # include <TBranch.h>
 #endif
-#ifndef ROOT_TArrayI
-# include <TArrayI.h>
-#endif
+class TBranch;
+class TClonesArray;
+class TBrowser;
+class AliDigitizer;
+class AliFMDSimulator;
 
 //____________________________________________________________________
 class AliFMD : public AliDetector 
 {
 public:
   AliFMD();
-  AliFMD(const char *name, const char *title, bool detailed);
+  AliFMD(const char *name, const char *title);
   AliFMD(const AliFMD& other);
   virtual ~AliFMD(); 
   AliFMD& operator=(const AliFMD& other);
@@ -43,11 +39,6 @@ public:
   virtual void   CreateMaterials(); 
   virtual void   Init();
   virtual void   StepManager() = 0;
-  AliFMDSubDetector*    GetFMD1() const       { return fFMD1; }
-  AliFMDSubDetector*    GetFMD2() const       { return fFMD2; }
-  AliFMDSubDetector*    GetFMD3() const       { return fFMD3; }
-  AliFMDRing*           GetInner() const      { return fInner; }
-  AliFMDRing*           GetOuter() const      { return fOuter; }
 
   // Graphics and event display 
   virtual        void   BuildGeometry();
@@ -101,84 +92,20 @@ public:
   // Raw data 
   virtual        void   Digits2Raw();
 
-  // Set various parameters 
-  void     SetLegLength(Double_t     length=1);
-  void     SetLegRadius(Double_t     radius=.5);
-  void     SetLegOffset(Double_t     offset=2);
-  void     SetModuleSpacing(Double_t spacing=1);
-  void     SetSiDensity(Float_t r=2.33)         { fSiDensity = r; }
-  void     SetSiThickness(Float_t r=0.03)       { fSiThickness = r; }
-  void     SetVA1MipRange(UShort_t r=20)        { fVA1MipRange = r; }
-  void     SetAltroChannelSize(UShort_t s=1024) { fAltroChannelSize = s;}
-  void     SetSampleRate(UShort_t r=1)          { fSampleRate = (r>2 ? 2 : r);}
-
-  // Get various parameters
-  Int_t    GetSiId()                 const { return (*fIdtmed)[kSiId]; }
-  Int_t    GetAirId()                const { return (*fIdtmed)[kAirId]; }
-  Int_t    GetPlasticId()            const { return (*fIdtmed)[kPlasticId]; }
-  Int_t    GetPcbId()                const { return (*fIdtmed)[kPcbId]; }
-  Int_t    GetAlId()                 const { return (*fIdtmed)[kAlId]; }
-  Int_t    GetCarbonId()             const { return (*fIdtmed)[kCarbonId]; }
-  Int_t    GetPrintboardRotationId() const { return fPrintboardRotationId; }
-  Int_t    GetShortLegId()           const { return fShortLegId; }
-  Int_t    GetLongLegId()            const { return fLongLegId; }
-  Double_t GetLegLength()            const { return fLegLength; }
-  Double_t GetLegRadius()            const { return fLegRadius; }
-  Double_t GetModuleSpacing()        const { return fModuleSpacing; }  
-  Float_t  GetSiDensity()            const { return fSiDensity; }
-  Float_t  GetSiThickness()          const { return fSiThickness; }
-  UShort_t GetVA1MipRange()          const { return fVA1MipRange; }
-  UShort_t GetAltroChannelSize()     const { return fAltroChannelSize; }
-  UShort_t GetSampleRate()           const { return fSampleRate; }
-  Float_t  GetEdepMip()              const { 
-    return fSiDeDxMip * fSiDensity * fSiThickness;
-  }
-  
   // Utility
   void   Browse(TBrowser* b);
-  enum { 
-    kBaseDDL = 0x1000 // DDL offset for the FMD
-  };
-  // 
-  static const Char_t* fgkShortLegName;  // Format for short support legs
-  static const Char_t* fgkLongLegName;   // Format for long support legs
 protected:
   TClonesArray*      HitsArray();
   TClonesArray*      DigitsArray();
   TClonesArray*      SDigitsArray();
 
-  enum {
-    kSiId,                 // ID of Si medium
-    kAirId,                // ID of Air medium
-    kPlasticId,            // ID of Plastic medium
-    kPcbId,                // ID of PCB medium
-    kSiChipId,             // ID of Si Chip medium
-    kAlId,                 // ID of Al medium
-    kCarbonId              // ID of Carbon medium
-  };
-  
-  AliFMDRing*        fInner;                // Inner ring structure
-  AliFMDRing*        fOuter;                // Outer ring structure  
-  AliFMDSubDetector* fFMD1;                 // FMD1 structure
-  AliFMDSubDetector* fFMD2;                 // FMD2 structure  
-  AliFMDSubDetector* fFMD3;                 // FMD3 structure
   TClonesArray*      fSDigits;              // Summable digits
   Int_t              fNsdigits;             // Number of digits  
-  Int_t              fPrintboardRotationId; // ID of Rotation of print bard
-  Int_t              fIdentityRotationId;   // ID of identity matrix 
-  Int_t              fShortLegId;           // ID short leg volume
-  Int_t              fLongLegId;            // ID long leg volume  
-  Double_t           fLegLength;            // Leg length
-  Double_t           fLegRadius;            // Leg radius
-  Double_t           fModuleSpacing;        // Staggering offset 
-  Float_t            fSiDensity;            // Density of Silicon
-  Float_t            fSiThickness;          // Thickness of silicon wafers
-  const Float_t      fSiDeDxMip;            // MIP dE/dx in Silicon
-  UShort_t           fVA1MipRange;          // # MIPs the pre-amp can do    
-  UShort_t           fAltroChannelSize;     // Largest # to store in 1 ADC ch.
-  UShort_t           fSampleRate;           // Times the ALTRO samples pre-amp.
-
-  ClassDef(AliFMD,9)     // Base class FMD entry point
+  Bool_t             fDetailed;             // Use detailed geometry
+  
+  AliFMDSimulator*   fSimulator;            // Simulator task
+  
+  ClassDef(AliFMD,10)     // Base class FMD entry point
 };
 
 #endif
index 155b51e38982d6bc5720e2da27ccc9627adc97f4..fa0ea59f4687570af89d48979ba2c5d81e9ef16d 100644 (file)
 
 //____________________________________________________________________
 //                                                                          
-// Concrete implementation of AliFMDSubDetector 
+// Concrete implementation of AliFMDDetector 
 //
 // This implements the geometry for FMD1 
 //
 #include "AliFMD1.h"           // ALIFMD1_H 
 #include "AliFMDRing.h"                // ALIFMDRING_H 
-#include "TVirtualMC.h"                // ROOT_TVirtualMC
-#include "AliLog.h"            // ALILOG_H
 
 
-//____________________________________________________________________
+//====================================================================
 ClassImp(AliFMD1)
+#if 0
+  ; // This is to keep Emacs from indenting the next line 
+#endif 
 
 //____________________________________________________________________
-AliFMD1::AliFMD1() 
-  : AliFMDSubDetector(1) 
-{
-  // Default constructor for the FMD1 sub-detector 
-}
-
-//____________________________________________________________________
-AliFMD1::~AliFMD1() 
-{
-  // Destructor - does nothing 
-}
-
-//____________________________________________________________________
-void 
-AliFMD1::SetupGeometry(Int_t airId, Int_t alId, Int_t /* cId */) 
+AliFMD1::AliFMD1(AliFMDRing* inner) 
+  : AliFMDDetector(1, inner, 0)
 {
-  // Setup the FMD1 sub-detector geometry 
-  // 
-  // Parameters:
-  // 
-  //     airId         Id # of the Air medium 
-  //     alId     Id # of the Aluminium medium 
-  // 
-  AliDebug(10, "\tDefining the geometry for FMD1");
-  fInnerHoneyLowR  = fInner->GetLowR() + 1;
-  fInnerHoneyHighR = fInner->GetHighR() + 1;
-  fOuterHoneyLowR  = 0;
-  fOuterHoneyHighR = 0;
-
-  Double_t par[3];
-  par[0] = fInner->GetLowR();
-  par[1] = fInnerHoneyHighR;
-  par[2] = fDz = (fInner->GetLegLength() 
-                 + fInner->GetSiThickness() 
-                 + fInner->GetPrintboardThickness() 
-                 + fInner->GetModuleSpacing() 
-                 + fHoneycombThickness) / 2;
-  fVolumeId = gMC->Gsvolu("FMD1", "TUBE", airId, par, 3);
-
-  // Rotate the full sub-detector 
-  gMC->Matrix(fRotationId, 270, 180, 90, 90, 180, 0); 
-
-  AliFMDSubDetector::SetupGeometry(airId, alId);
-}
-
-//____________________________________________________________________
-void 
-AliFMD1::Geometry(const char* mother, Int_t pbRotId, 
-                 Int_t idRotId, Double_t z) 
-{
-  // Position the FMD1 sub-detector volume 
-  // 
-  // Parameters 
-  //
-  //     mother     name of the mother volume 
-  //     pbRotId    Printboard roation matrix ID 
-  //     idRotId    Identity rotation matrix ID 
-  //     z          Z position (not really used here, but passed down)
-  //
-  // The Z passed in isn't used. 
-  z = fInnerZ + fDz;
-  AliDebug(10, Form("\tPutting FMD1 in %s at z=%lf cm", mother, z));
-  gMC->Gspos("FMD1", 1, mother, 0, 0, z, fRotationId, "ONLY");
-
-  AliFMDSubDetector::Geometry("FMD1", pbRotId, idRotId, z);
+  SetInnerZ(340);
 }
 
-  
 
 //____________________________________________________________________
 //
index 51712d1488a4ed9d79f4f3c88f51eb4c7b2cc371..29c295962cd8182cbf9b2045d22db346e96e0a86 100644 (file)
@@ -1,25 +1,26 @@
+#ifndef ALIFMD1_H
+#define ALIFMD1_H
 //
 // $Id$
 //
-#ifndef ALIFMD1_H
-#define ALIFMD1_H
-
-#ifndef ALIFMDSUBDETECTOR_H
-# include "AliFMDSubDetector.h"
+#ifndef ALIFMDDETECTOR_H
+# include "AliFMDDetector.h"
 #endif
+class AliFMDRing;
 
-class AliFMD1 : public AliFMDSubDetector 
+//__________________________________________________________________
+/** Geometry description and parameters of the FMD1
+    detector. 
+    
+    The FMD1 only has one ring.     
+*/
+class AliFMD1 : public AliFMDDetector 
 {
 public:
-  AliFMD1();
-  virtual ~AliFMD1();
-  virtual void   SetupGeometry(Int_t airId, Int_t alId, Int_t cId=0);  
-  virtual void   Geometry(const char* mother, Int_t pbRotId, 
-                         Int_t idRotId, Double_t z=0);
-protected:
-  Int_t    fVolumeId;   // Volume ID
-  Double_t fDz;         // Half-length in Z
-  ClassDef(AliFMD1,1);  // Geometry of FMD1 
+  AliFMD1(AliFMDRing* inner);
+  virtual ~AliFMD1() {}
+  virtual void Init() { AliFMDDetector::Init(); }
+  ClassDef(AliFMD1,1)
 };
 
 #endif
index 124fa3ad0bbf56a231f30ed6f03e8b290ea376b4..37ac44a271b2b7ff45fb5915bbcc295c9b65dec9 100644 (file)
 
 //____________________________________________________________________
 //                                                                          
-// Concrete implementation of AliFMDSubDetector 
+// Concrete implementation of AliFMDDetector 
 //
 // This implements the geometry for FMD2
 //
 #include "AliFMD2.h"           // ALIFMD2_H 
 #include "AliFMDRing.h"                // ALIFMDRING_H 
-#include <AliLog.h>            // ALILOG_H
-#include <TVirtualMC.h>                // ROOT_TVirtualMC
 
-//____________________________________________________________________
+//====================================================================
 ClassImp(AliFMD2)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
-AliFMD2::AliFMD2() 
-  : AliFMDSubDetector(2) 
+AliFMD2::AliFMD2(AliFMDRing* inner, AliFMDRing* outer
+  : AliFMDDetector(2, inner, outer)
 {
-  // Default constructor for the FMD2 sub-detector 
-}
-
-//____________________________________________________________________
-AliFMD2::~AliFMD2() 
-{
-  // Destructor - does nothing 
+  SetInnerZ(83.4);
+  SetOuterZ(75.2);
 }
 
 
 //____________________________________________________________________
-void 
-AliFMD2::SetupGeometry(Int_t airId, Int_t alId, Int_t cId
+void
+AliFMD2::Init(
 {
-  // Setup the FMD2 sub-detector geometry 
-  // 
-  // Parameters:
-  // 
-  //     airId         Id # of the Air medium 
-  //     alId     Id # of the Aluminium medium 
-  // 
-  AliDebug(10, "\tDefining the geometry for FMD1");
-  fInnerHoneyLowR  = fInner->GetLowR() + 1;
-  fInnerHoneyHighR = fOuter->GetHighR() + 1;
-  fOuterHoneyLowR  = fOuter->GetLowR() + 1;
-  fOuterHoneyHighR = fOuter->GetHighR() + 1;
-
-  Double_t par[3];
-  par[0] = fInner->GetLowR();
-  par[1] = fOuterHoneyHighR;
-  par[2] = fDz = (TMath::Abs(fInnerZ - fOuterZ)
-                 + fInner->GetSiThickness() 
-                 + fInner->GetPrintboardThickness() 
-                 + fInner->GetLegLength() 
-                 + fInner->GetModuleSpacing() 
-                 + fHoneycombThickness) / 2;
-  fVolumeId = gMC->Gsvolu("FMD2", "TUBE", airId, par, 3);
-
-  // Rotate the full sub-detector 
-  gMC->Matrix(fRotationId, 270, 180, 90, 90, 180, 0); 
-
-  AliFMDSubDetector::SetupGeometry(airId, alId, cId);
-}
-
-//____________________________________________________________________
-void 
-AliFMD2::Geometry(const char* mother, Int_t pbRotId, 
-                 Int_t idRotId, Double_t z) 
-{
-  // Position the FMD2 sub-detector volume 
-  // 
-  // Parameters 
-  //
-  //     mother     name of the mother volume 
-  //     pbRotId    Printboard roation matrix ID 
-  //     idRotId    Identity rotation matrix ID 
-  //     z          Z position (not really used here, but passed down)
-  //
-  z = fDz + fOuterZ;
-  AliDebug(10, Form("\tPutting FMD2 in %s at z=%lf cm", mother, z));
-  AliFMDSubDetector::Geometry("FMD2", pbRotId, idRotId, z);
-  gMC->Gspos("FMD2", 1, mother, 0, 0, z, fRotationId);  
+  AliFMDDetector::Init();
+  SetInnerHoneyHighR(GetOuterHoneyHighR());
 }
 
-  
-
 //____________________________________________________________________
 //
 // EOF
index 54dcc937f36a5c4d1ffb72865f699faf13edfda6..b0a0711a302ee8bb07aac77020248d97a77b981f 100644 (file)
@@ -4,22 +4,21 @@
 #ifndef ALIFMD2_H
 #define ALIFMD2_H
 
-#ifndef ALIFMDSUBDETECTOR_H
-# include "AliFMDSubDetector.h"
+#ifndef ALIFMDDETECTOR_H
+# include "AliFMDDetector.h"
 #endif
 
-class AliFMD2 : public AliFMDSubDetector 
+/** Geometry description and parameters of the FMD2
+    detector. 
+*/
+class AliFMD2 : public AliFMDDetector 
 {
-public:
-  AliFMD2();
-  virtual ~AliFMD2();
-  virtual void   SetupGeometry(Int_t airId, Int_t alId, Int_t cId=0);  
-  virtual void   Geometry(const char* mother, Int_t pbRotId, 
-                         Int_t idRotId, Double_t z=0);
-protected:
-  Int_t    fVolumeId;  // Volume ID       
-  Double_t fDz;               // Half-length in Z
-  ClassDef(AliFMD2,1); // Geometry of FMD2
+protected: 
+public: 
+  AliFMD2(AliFMDRing* inner, AliFMDRing* outer);
+  /** Initialize the geometry */
+  virtual void Init();
+  ClassDef(AliFMD2, 1);
 };
 
 #endif
index 899a7b7b7caa77a01f15c1f15d720532937a8bc4..82fdf251fd9354bb40ad06818a23c86c53636cd9 100644 (file)
 
 //____________________________________________________________________
 //                                                                          
-// Concrete implementation of AliFMDSubDetector 
+// Concrete implementation of AliFMDDetector 
 //
 // This implements the geometry for FMD3
 //
-#include "TVirtualMC.h"                // ROOT_TVirtualMC
-#include "TCONS.h"             // ROOT_TCONS
-#include "TNode.h"             // ROOT_TNode
-#include "TList.h"             // ROOT_TList
 #include "AliFMD3.h"           // ALIFMD3_H 
 #include "AliLog.h"            // ALILOG_H
 #include "AliFMDRing.h"                // ALIFMDRING_H 
-#include <Riostream.h>         // ROOT_Riostream
+#include <TMath.h>             // ROOT_TMath
 
-//____________________________________________________________________
+//====================================================================
 ClassImp(AliFMD3)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
-AliFMD3::AliFMD3() 
-  : AliFMDSubDetector(3), 
-    fVolumeId(0)
-{
-  // Default constructor for the FMD3 sub-detector 
-  AliDebug(10, "\t\tDefault CTOR");
-}
-
-
-//____________________________________________________________________
-AliFMD3::~AliFMD3() 
-{
-  // Destructor - does nothing 
-  AliDebug(10, "\t\tDTOR");
-}
-
-
-//____________________________________________________________________
-void 
-AliFMD3::SetupGeometry(Int_t airId, Int_t alId, Int_t carbonId) 
+AliFMD3::AliFMD3(AliFMDRing* inner, AliFMDRing* outer) 
+  : AliFMDDetector(3, inner, outer)
 {
-  // Setup the FMD3 sub-detector geometry 
-  // 
-  // Parameters:
-  // 
-  //     airId         Id # of the Air medium 
-  //     kaptionId     Id # of the Aluminium medium 
-  // 
-  AliDebug(10, "\tSetting up the geometry for FMD3");
-  Double_t innerZl = fInnerZ;
-  Double_t innerZh = (fInnerZ 
-                     - fInner->GetModuleSpacing() 
-                     - fInner->GetLegLength() 
-                     - fInner->GetSiThickness() 
-                     - fInner->GetPrintboardThickness()
-                     - fHoneycombThickness);
-  Double_t innerRl = fInner->GetLowR();
-  Double_t outerZl = fOuterZ;
-  Double_t outerZh = (fOuterZ 
-                     - fOuter->GetModuleSpacing() 
-                     - fOuter->GetLegLength() 
-                     - fOuter->GetSiThickness() 
-                     - fOuter->GetPrintboardThickness()                      
-                     - fHoneycombThickness);
-  Double_t outerRl = fOuter->GetLowR();
-  
-  fSupport.SetupGeometry(airId, carbonId, 
-                        innerZl, innerZh, innerRl,
-                        outerZl, outerZh, outerRl);
-
-  fInnerHoneyLowR  = fInner->GetLowR() + 1;
-  fInnerHoneyHighR = fSupport.ConeR(innerZh + fHoneycombThickness, "I");
-  fOuterHoneyLowR  = fOuter->GetLowR() + 1;
-  fOuterHoneyHighR = fSupport.GetBackLowR();
-
-  // Identity matrix
-  gMC->Matrix(fRotationId, 90, 0, 90, 90, 0, 0); 
-  //0, 180, 90, 90, 180, 0);
-
-
-  AliFMDSubDetector::SetupGeometry(airId, alId, carbonId);
+  SetInnerZ(-62.8);
+  SetOuterZ(-75.2);
+  SetNoseZ();
+  SetNoseLowR();
+  SetNoseHighR();
+  SetNoseLength();
+  SetBackLowR();
+  SetBackHighR();
+  SetBackLength();
+  SetBeamThickness();
+  SetBeamWidth();
+  SetConeLength();
+  SetFlangeR();
+  SetNBeam();
+  SetNFlange();
 }
 
 //____________________________________________________________________
-void 
-AliFMD3::Geometry(const char* mother, Int_t pbRotId, 
-                 Int_t idRotId, Double_t z) 
+void
+AliFMD3::Init() 
 {
-  // Position the FMD3 sub-detector volume 
-  // 
-  // Parameters 
-  //
-  //     mother     name of the mother volume 
-  //     pbRotId    Printboard roation matrix ID 
-  //     idRotId    Identity rotation matrix ID 
-  //     z          Z position (not really used here, but passed down)
-  //
-  z = fSupport.GetZ();
-  fSupport.Geometry(mother, fRotationId, z);
-  AliDebug(10, Form("\t\tPassing z=%lf to ring volumes", z));
-  AliFMDSubDetector::Geometry("FMD3", pbRotId, idRotId, z);
+  AliFMDDetector::Init();
+  SetInnerHoneyHighR(GetOuterHoneyHighR());
+  Double_t zdist   = fConeLength - fBackLength - fNoseLength;
+  Double_t tdist   = fBackHighR - fNoseHighR;
+  Double_t innerZh = fInnerZ - fInner->GetRingDepth() - fHoneycombThickness;
+  Double_t outerZh = fOuterZ - fOuter->GetRingDepth() - fHoneycombThickness;
+  Double_t minZ    = TMath::Min(fNoseZ - fConeLength, outerZh);
+  fAlpha           = tdist / zdist;
+  fZ               = fNoseZ + (minZ - fNoseZ) / 2;
+  fInnerHoneyHighR = ConeR(innerZh + fHoneycombThickness,"O") - 1;
+  fOuterHoneyHighR = GetBackLowR();
 }
 
-  
 //____________________________________________________________________
-void 
-AliFMD3::SimpleGeometry(TList* nodes, 
-                       TNode* mother, 
-                       Int_t colour, 
-                       Double_t zMother) 
+Double_t
+AliFMD3::ConeR(Double_t z, Option_t* opt) const
 {
-  // We need to get the equation for the line that connects the 
-  // outer circumfrences of the two rings, as  well as for the line
-  // that connects the inner curcumfrences, so that we can project to
-  // where the honey-comb actually ends. 
-  // 
-  // we have 
-  //   
-  //   y = a * x + b 
-  //   b = y - a * x;
-  // 
-  // For the outer line, we have the two equations 
-  // 
-  //    fOuterHoneyHighR = a * x1 + b;
-  //    fInnerHoneyHighR = a * x2 + b; 
-  // 
-  // where 
-  // 
-  //    x1 = (fOuterZ + fOuter->fSiThickness + fOuter->fPrintboardThickness 
-  //          + fOuter->fLegLength + fModuleSpacing) 
-  //       = fInner - fDz + fHoneycombThickness
-  //    x2 = (fInnerZ + fInner->fSiThickness + fInner->fPrintboardThickness 
-  //          + fInner->fLegLength + fModuleSpacing)
-  // 
-  // and 
-  //
-  //    a  = (fOuterHoneyHighR - fInnerHoneyHighR) / (x1 - x2)
-  //    
-  // 
-  AliDebug(10, "\tCreating simplified geometry for FMD3");
-  Double_t dz = (TMath::Abs(fInnerZ - fOuterZ) 
-                + fOuter->GetSiThickness() 
-                + fOuter->GetPrintboardThickness() 
-                + fOuter->GetLegLength() 
-                + fOuter->GetModuleSpacing() 
-                + fHoneycombThickness) / 2;
-#if 1
-  Double_t x1  = (fOuterZ - (fOuter->GetSiThickness() 
-                            + fOuter->GetPrintboardThickness() 
-                            + fOuter->GetLegLength() 
-                            + fOuter->GetModuleSpacing()));
-  Double_t x2  = (fInnerZ - (fInner->GetSiThickness() 
-                            + fInner->GetPrintboardThickness() 
-                            + fInner->GetLegLength() 
-                            + fInner->GetModuleSpacing()));
-  Double_t ao   = 0;
-  Double_t ao1  = (fOuterHoneyHighR - fInnerHoneyHighR) / (x1 - x2);
-  Double_t ao2  = ((fOuter->GetHighR() - fInner->GetHighR()) 
-                  / (fOuterZ - fInnerZ));
-  Double_t bo   = 0;
-  if (ao2 > ao1) {
-    // std::cout << "Wafer determinds the size" << std::endl;
-    ao  = ao2;
-    bo  = fInner->GetHighR() - ao * fInnerZ;
+  // Calculate the cone radius at Z
+  if (fAlpha < 0) {
+    Warning("ConeR", "alpha not set: %lf", fAlpha);
+    return -1;
   }
-  else {
-    ao = ao1;
-    bo = fOuterHoneyHighR - ao * x1;
+  if (z > fNoseZ) {
+    Warning("ConeR", "z=%lf is before start of cone %lf", z, fNoseZ);
+    return -1;
   }
-  
-  Double_t y1o = ao * (fInnerZ - 2 * dz) + bo;
-  Double_t y2o = ao * fInnerZ + bo;
-#endif
-  // We probably need to make a PCON here. 
-  TShape* shape = new TCONS("FMD3", "FMD3", "", dz, 
-                           fOuter->GetLowR(),  y1o, /* fOuterHoneyHighR, */
-                           fInner->GetLowR(),  y2o, /* fInnerHoneyHighR, */
-                           0, 360);
-  mother->cd();
-  zMother = fInnerZ - dz;  
-  TNode* node = new TNode("FMD3", "FMD3", shape, 0, 0, zMother, 0);
-  node->SetVisibility(0);
-  nodes->Add(node);
-  AliFMDSubDetector::SimpleGeometry(nodes, node, colour, zMother);
+  if (z < fOuterZ - fOuter->GetRingDepth() - fHoneycombThickness) {
+    Warning("ConeR", "z=%lf is after end of cone %lf", z, 
+           fOuterZ - fOuter->GetRingDepth() - fHoneycombThickness);
+    return -1;
+  }
+  Double_t e = fBeamThickness / TMath::Cos(TMath::ATan(fAlpha));
+  if (opt[0] == 'I' || opt[1] == 'i') e *= -1;
+  if (z > fNoseZ - fNoseLength) return fNoseHighR + e;
+  if (z < fNoseZ - fConeLength + fBackLength) return fBackHighR + e;
+  Double_t r = fNoseHighR + fAlpha * TMath::Abs(z - fNoseZ + fNoseLength) + e;
+  return r;
 }
 
-//____________________________________________________________________
-void 
-AliFMD3::Gsatt() const
-{
-  // Set draw attributes for the FMD3
-  AliDebug(10, "Setting drawing attributes for FMD3");
-  AliFMDSubDetector::Gsatt();
-  fSupport.Gsatt();
-}
 
 //____________________________________________________________________
 //
index c3f9cd22118604253a8b5f308244affd1baf674a..9a24496b0f69f6f1daf4d7de777fe98b08dbeede 100644 (file)
 #ifndef ALIFMD3_H
 #define ALIFMD3_H
 
-#ifndef ALIFMDSUBDETECTOR_H
-# include "AliFMDSubDetector.h"
-#endif
-#ifndef ALIFMD3SUPPORT_H
-# include "AliFMD3Support.h"
+#ifndef ALIFMDDETECTOR_H
+# include "AliFMDDetector.h"
 #endif
 
-class AliFMD3 : public AliFMDSubDetector 
+/** Geometry description and parameters of the FMD3 detector.
+    
+    FMD3 has a fairly complicated support structure 
+*/
+class AliFMD3 : public AliFMDDetector 
 {
-public:
-  AliFMD3();
-  virtual ~AliFMD3();
-  virtual void   SetupGeometry(Int_t airId, Int_t alId, Int_t cId=0);  
-  virtual void   Geometry(const char* mother, Int_t pbRotId, 
-                         Int_t idRotId, Double_t z=0);
-  virtual void   SimpleGeometry(TList* nodes, TNode* mother, 
-                               Int_t colour, Double_t zMother);
-  virtual void   Gsatt() const;
-protected:
-  Int_t          fVolumeId;  // Volume ID
-  AliFMD3Support fSupport;   // Support for FMD3 
-  ClassDef(AliFMD3,2);       // Geometry of FMD3 
+public: 
+  AliFMD3(AliFMDRing* inner, AliFMDRing* outer);
+  virtual ~AliFMD3(){}
+
+  /** Initialize the geometry */
+  virtual void Init();
+
+  /** @param z Z position of front of nose */
+  void SetNoseZ(Double_t z=-46) { fNoseZ = z; }
+  /** @param r Nose inner radius */
+  void SetNoseLowR(Double_t r=5.5) { fNoseLowR = r; }
+  /** @param r Nose outer radius */
+  void SetNoseHighR(Double_t r=6.7) { fNoseHighR = r; }
+  /** @param l Length of nose in Z */
+  void SetNoseLength(Double_t l=2.8) { fNoseLength = l; }
+  /** @param r Inner radius of base of cone */
+  void SetBackLowR(Double_t r=61./2) { fBackLowR = r; }
+  /** @param r Outer radius of base of cone */
+  void SetBackHighR(Double_t r=66.8/2) { fBackHighR = r; }
+  /** @param l Length of base of cone in Z */
+  void SetBackLength(Double_t l=1.4) { fBackLength = l; }
+  /** @param t Thickness of support beams */
+  void SetBeamThickness(Double_t t=.5) { fBeamThickness = t; }
+  /** @param w Width of support beams */
+  void SetBeamWidth(Double_t w=6) { fBeamWidth = w; }
+  /** @param l Length of the cone in Z */
+  void SetConeLength(Double_t l=30.9) { fConeLength = l; }
+  /** @param r Outer radius of flanges */
+  void SetFlangeR(Double_t r=49.25) { fFlangeR = r; }
+  /** @param n Number of support beams */
+  void SetNBeam(Int_t n=8) { fNBeam = n; }
+  /** @param n Number of support flanges */
+  void SetNFlange(Int_t n=4) { fNFlange = n; }
+
+  /** @return Z position of front of nose */
+  Double_t GetNoseZ() const { return fNoseZ; }
+  /** @return Nose inner radius */
+  Double_t GetNoseLowR() const { return fNoseLowR; }
+  /** @return Nose outer radius */
+  Double_t GetNoseHighR() const { return fNoseHighR; }
+  /** @return Length of nose in Z */
+  Double_t GetNoseLength() const { return fNoseLength; }
+  /** @return Inner radius of base of cone */
+  Double_t GetBackLowR() const { return fBackLowR; }
+  /** @return Outer radius of base of cone */
+  Double_t GetBackHighR() const { return fBackHighR; }
+  /** @return Length of base of cone in Z */
+  Double_t GetBackLength() const { return fBackLength; }
+  /** @return Thickness of support beams */
+  Double_t GetBeamThickness() const { return fBeamThickness; }
+  /** @return Width of support beams */
+  Double_t GetBeamWidth() const { return fBeamWidth; }
+  /** @return Length of the cone in Z */
+  Double_t GetConeLength() const { return fConeLength; }
+  /** @return Outer radius of flanges */
+  Double_t GetFlangeR() const { return fFlangeR; }
+  /** @return Midpoint of mother volume */
+  Double_t GetZ() const { return fZ; }
+  /** @return Slope of cone */
+  Double_t GetAlpha() const { return fAlpha; }
+  /** @return Number of support beams */
+  Int_t GetNBeam() const { return fNBeam; }
+  /** @return Number of support flanges */
+  Int_t GetNFlange() const { return fNFlange; }
+
+  /** Get the cone radii at @a z. 
+      @param z Point to evaulate at 
+      @param opt If @c "O" get the outer radii, if @c "I" get the
+      inner radii. 
+      @return the radius of the cone */
+  Double_t ConeR(Double_t z, Option_t* opt="O") const;
+
+protected: 
+  Double_t     fNoseZ;                 // Z position of front of nose
+  Double_t     fNoseLowR;              // Nose inner radius
+  Double_t     fNoseHighR;             // Nose outer radius
+  Double_t     fNoseLength;            // Length of nose in Z
+  Double_t     fBackLowR;              // Inner radius of base of cone
+  Double_t     fBackHighR;             // Outer radius of base of cone
+  Double_t     fBackLength;            // Length of base of cone in Z
+  Double_t     fBeamThickness;         // Thickness of support beams
+  Double_t     fBeamWidth;             // Width of support beams
+  Double_t     fConeLength;            // Length of the cone in Z
+  Double_t     fFlangeR;               // Outer radius of flanges
+  Double_t     fZ;                     // Midpoint of mother volume
+  Double_t     fAlpha;                 // Slope of cone
+  Int_t                fNBeam;                 // Number of support beams
+  Int_t                fNFlange;               // Number of support flangesy
+  ClassDef(AliFMD3, 1);
 };
 
 #endif
diff --git a/FMD/AliFMD3Support.cxx b/FMD/AliFMD3Support.cxx
deleted file mode 100644 (file)
index d0ab9c5..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/**************************************************************************
- * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
- *                                                                        *
- * Author: The ALICE Off-line Project.                                    *
- * Contributors are mentioned in the code where appropriate.              *
- *                                                                        *
- * Permission to use, copy, modify and distribute this software and its   *
- * documentation strictly for non-commercial purposes is hereby granted   *
- * without fee, provided that the above copyright notice appears in all   *
- * copies and that both the copyright notice and this permission notice   *
- * appear in the supporting documentation. The authors make no claims     *
- * about the suitability of this software for any purpose. It is          *
- * provided "as is" without express or implied warranty.                  *
- **************************************************************************/
-
-/* $Id$ */
-
-//____________________________________________________________________
-//                                                                          
-// Concrete implementation of AliFMDSubDetector 
-//
-// This implements the geometry for FMD3
-//
-#include "TVirtualMC.h"                // ROOT_TVirtualMC
-#include "AliFMD3Support.h"    // ALIFMD3SUPPORT_H 
-#include "AliLog.h"            // ALILOG_H
-#include <Riostream.h>         // ROOT_Riostream
-
-//____________________________________________________________________
-ClassImp(AliFMD3Support)
-
-//____________________________________________________________________
-const Char_t* AliFMD3Support::fgkNoseName   = "F3SN";
-const Char_t* AliFMD3Support::fgkBackName   = "F3SB";
-const Char_t* AliFMD3Support::fgkBeamName   = "F3SL";
-const Char_t* AliFMD3Support::fgkFlangeName = "F3SF";
-
-//____________________________________________________________________
-AliFMD3Support::AliFMD3Support() 
-  : fZ(0),
-    fAlpha(-1),
-    fNoseId(-1),
-    fBeamId(-1),
-    fBackId(-1), 
-    fFlangeId(-1)
-{
-  // Default constructor for the support of FMD3 sub-detector 
-  SetNoseZ();
-  SetNoseLowR();
-  SetNoseHighR();
-  SetNoseLength();
-  SetBackLowR();
-  SetBackHighR();
-  SetBackLength();
-  SetBeamThickness();
-  SetBeamWidth();
-  SetConeLength();
-  SetFlangeR();
-  SetNBeam();
-  SetNFlange();
-}
-
-
-//____________________________________________________________________
-AliFMD3Support::~AliFMD3Support() 
-{
-  // Destructor - does nothing 
-}
-
-
-//____________________________________________________________________
-void 
-AliFMD3Support::SetupGeometry(Int_t    airId, 
-                             Int_t    cId, 
-                             Double_t innerZl, 
-                             Double_t innerZh, 
-                             Double_t innerRl, 
-                             Double_t /* outerZl */, 
-                             Double_t outerZh, 
-                             Double_t outerRl)
-{
-  // Setup the FMD3 sub-detector geometry 
-  // 
-  // Parameters:
-  // 
-  //     airId         Id # of the Air medium 
-  //     cId           Id # of the Carbon fibre medium 
-  // 
-
-  // Global stuff we need 
-  Double_t zdist = fConeLength - fBackLength - fNoseLength;
-  Double_t tdist = fBackHighR - fNoseHighR;
-  Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist);
-  Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
-  Double_t minZ  = TMath::Min(fNoseZ - fConeLength, outerZh);
-  fAlpha         = tdist / zdist;
-  fZ             = fNoseZ + (minZ - fNoseZ) / 2;
-  AliDebug(30, Form("\tTheta = %lf", theta));
-  
-  const Char_t* mother = "FMD3";
-  Double_t p[3 + 9 * 3];
-  Double_t eps = 0;
-  // ------------- Mother volume -------------------------------------
-  // The planes should be defined with increasing Z, as it will become
-  // invalid if not 
-  // Global parameters 
-  p[0]  = 0;
-  p[1]  = 360;
-  p[2]  = 8;
-  // First plane (at back of back or outer ring)
-  p[3]  = minZ - fZ - eps;
-  p[4]  = outerRl - eps;                                  
-  p[5]  = fFlangeR + eps;
-  // Second plane (at front of back, at end of flanges)
-  p[6]  = fNoseZ - zdist - fNoseLength  - fZ  + eps;
-  p[7]  = p[4];
-  p[8]  = p[5];             
-  // Third plane (at front of back)
-  p[9]  = p[6] - eps/2; 
-  p[10] = p[7];
-  p[11] = ConeR(p[9] + fZ)  + eps;                
-  // Fourth plane (at back of inner ring) 
-  p[12] = innerZh - fZ - eps;    
-  p[13] = outerRl - eps;         
-  p[14] = ConeR(p[12] + fZ) + eps;
-  // Fifth plane (at back of inner ring) 
-  p[15] = p[12] - eps/2;         
-  p[16] = innerRl - eps;        
-  p[17] = ConeR(p[15] + fZ) + eps;
-  // Sixth plane  (at front of inner ring)
-  p[18] = innerZl - fZ + eps;   
-  p[19] = p[16];                 
-  p[20] = ConeR(p[18] + fZ) + eps;
-  // Seventh plane (at end of nose)
-  p[21] = fNoseZ - fNoseLength  - fZ - eps;    
-  p[22] = fNoseLowR - eps;                     
-  p[23] = ConeR(p[21] + fZ) + eps; // fNoseHighR;
-  // Eight (and final) plane (at start of nose)
-  p[24] = fNoseZ  - fZ + eps;
-  p[25] = p[22];
-  p[26] = fNoseHighR + eps;  
-
-  // The volume 
-  gMC->Gsvolu(mother, "PCON", airId, p, 27);
-  
-  // ------------- Support Structures --------------------------------
-  fRotations.Set(fNBeam + fNFlange);
-  Double_t par[3];
-  
-  // The nose 
-  par[0]  = fNoseLowR;
-  par[1]  = fNoseHighR;
-  par[2]  = fNoseLength / 2;
-  fNoseId = gMC->Gsvolu(fgkNoseName, "TUBE", cId, par, 3);
-
-  // The Back 
-  par[0]  = fBackLowR;
-  par[1]  = fBackHighR;
-  par[2]  = fBackLength / 2;
-  fBackId = gMC->Gsvolu(fgkBackName, "TUBE", cId, par, 3);
-
-  // The Beams 
-  par[0]  = fBeamThickness  / 2;
-  par[1]  = fBeamWidth / 2;
-  par[2]  = beaml / 2;
-  fBeamId = gMC->Gsvolu(fgkBeamName, "BOX", cId, par, 3);
-  for (Int_t i = 0; i < fNBeam; i++) {
-    // cout << "Making beam # " << i << endl;
-    Double_t phi = 360. / fNBeam * i;
-    Int_t    id;
-    gMC->Matrix(id, 180 - theta, phi, 90, 90 + phi, theta, phi);
-    fRotations[i] = id;
-  }
-
-  // The Flanges 
-  par[0]    = (fFlangeR - fBackHighR) / 2;
-  par[1]    = fBeamWidth / 2;
-  par[2]    = fBackLength  / 2;
-  fFlangeId = gMC->Gsvolu(fgkFlangeName, "BOX", cId, par, 3);
-  for (Int_t i = 0; i < fNFlange; i++) {
-    Double_t phi = 360. / fNFlange * i + 180. / fNFlange;
-    Int_t id;
-    gMC->Matrix(id, 90, phi, 90, 90+phi, 0, 0);
-    fRotations[fNBeam + i] = id;
-  }
-}
-
-//____________________________________________________________________
-void 
-AliFMD3Support::Geometry(const char* mother, Int_t idRotId, Double_t zTop) 
-{
-  // Position the FMD3 sub-detector volume 
-  // 
-  // Parameters 
-  //
-  //     mother     name of the mother volume 
-  //     idRotId    Identity rotation matrix ID 
-  //     z          Z position
-  //
-
-  // Common parameters 
-  Double_t zdist = fConeLength - fBackLength - fNoseLength;
-  Double_t tdist = fBackHighR - fNoseHighR;
-  const Char_t* name = "FMD3";
-  Double_t z = zTop;
-  
-  // Placing mother volume 
-  AliDebug(10, Form("\tPutting %s in %s at z=%lf", name, mother, zTop));
-  gMC->Gspos(name, 1, mother, 0, 0, zTop, idRotId, "ONLY");
-
-  // Placing the nose 
-  z       = fNoseZ - fNoseLength / 2 - fZ;
-  AliDebug(10, Form("\tPutting %s in %s at z=%lf-%lf/2-%lf=%lf", 
-                   fgkNoseName, name, fNoseZ, fNoseLength, fZ, z));
-  gMC->Gspos(fgkNoseName, 1, name, 0., 0., z, idRotId, "");
-
-  // Placing  the back 
-  z       = fNoseZ - fNoseLength - zdist - fBackLength / 2 - fZ;
-  AliDebug(10, Form("\tPutting %s in %s at z=%lf-%lf-%lf-%lf/2-%lf=%lf", 
-                   fgkBackName, name, fNoseZ, fNoseLength, zdist, 
-                   fBackLength, fZ, z));
-  gMC->Gspos(fgkBackName, 1, name, 0., 0., z, idRotId, "");
-
-  // Placing the beams 
-  z          = fNoseZ - fNoseLength - zdist / 2 - fZ;
-  Double_t r = fNoseHighR + tdist / 2;
-  AliDebug(10, Form("\tPutting %s's in %s at z=%lf-%lf-%lf/2-%lf=%lf", 
-                   fgkBeamName, name, fNoseZ, fNoseLength, zdist, fZ, z));
-  for (Int_t i = 0; i < fNBeam; i++) {
-    // cout << "Making beam # " << i << endl;
-    Double_t phi = 360. / fNBeam * i;
-    gMC->Gspos(fgkBeamName, i, name, 
-              r * TMath::Cos(TMath::Pi() / 180 * phi), 
-              r * TMath::Sin(TMath::Pi() / 180 * phi), 
-              z, fRotations[i], "");
-  }
-
-  // Placing the flanges 
-  r         = fBackHighR + (fFlangeR - fBackHighR) / 2;
-  z         = fNoseZ - fNoseLength - zdist - fBackLength / 2 - fZ;
-  AliDebug(10, Form("\tPutting %s in %s at z=%lf-%lf-%lf-%lf/2-%lf=%lf", 
-                   fgkFlangeName, name, fNoseZ, fNoseLength, zdist, 
-                   fBackLength, fZ, z));
-  for (Int_t i = 0; i < fNFlange; i++) {
-    Double_t phi = 360. / fNFlange * i + 180. / fNFlange;
-    gMC->Gspos(fgkFlangeName, i, name, 
-              r * TMath::Cos(TMath::Pi() / 180 * phi), 
-              r * TMath::Sin(TMath::Pi() / 180 * phi), 
-              z, fRotations[fNBeam + i], "");
-  }
-
-}
-
-//____________________________________________________________________
-Double_t
-AliFMD3Support::ConeR(Double_t z, Option_t* opt) const
-{
-  // Calculate the cone radius at Z 
-  if (fAlpha < 0) {
-    Warning("ConeR", "alpha not set: %lf", fAlpha);
-    return -1;
-  }
-  if (z > fNoseZ) { 
-    Warning("ConeR", "z=%lf is before start of cone %lf", z, fNoseZ);
-    return -1;
-  }
-  Double_t e = fBeamThickness / TMath::Cos(TMath::ATan(fAlpha));
-  if (opt[0] == 'I' || opt[1] == 'i') e *= -1;
-  if (z > fNoseZ - fNoseLength) return fNoseHighR + e; 
-  if (z < fNoseZ - fConeLength + fBackLength) return fBackHighR + e; 
-  Double_t r = fNoseHighR + fAlpha * TMath::Abs(z - fNoseZ + fNoseLength) + e;
-  return r;
-}
-
-//____________________________________________________________________
-void 
-AliFMD3Support::Gsatt() const
-{
-  // Set drawing attributes for the FMD3 Support 
-  gMC->Gsatt(fgkNoseName, "SEEN", 1);
-  gMC->Gsatt(fgkBeamName, "SEEN", 1);
-  gMC->Gsatt(fgkBackName, "SEEN", 1);
-  gMC->Gsatt(fgkFlangeName, "SEEN", 1);
-}
-
-
-//____________________________________________________________________
-//
-// EOF
-//
diff --git a/FMD/AliFMD3Support.h b/FMD/AliFMD3Support.h
deleted file mode 100644 (file)
index b714616..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// $Id$
-//
-#ifndef ALIFMD3SUPPORT_H
-#define ALIFMD3SUPPORT_H
-
-#ifndef ROOT_TObject
-# include <TObject.h>
-#endif
-#ifndef ROOT_TArrayI
-# include <TArrayI.h>
-#endif
-
-class AliFMD3Support : public TObject
-{
-public:
-  AliFMD3Support();
-  virtual ~AliFMD3Support();
-  virtual void   SetupGeometry(Int_t airId, Int_t cId,
-                              Double_t innerZl, Double_t innerZh, 
-                              Double_t innerRl, Double_t outerZl, 
-                              Double_t outerZh, Double_t outerRl);
-  virtual void   Geometry(const char* mother, Int_t idRotId, Double_t z=0);
-  virtual void   Gsatt() const;
-  
-  void SetNoseZ(Double_t         x=-46)                { fNoseZ = x; }
-  void SetNoseLowR(Double_t      x=5.5)                { fNoseLowR = x; }
-  void SetNoseHighR(Double_t     x=6.7)                { fNoseHighR = x; }
-  void SetNoseLength(Double_t    x=2.8)                { fNoseLength = x; }
-  void SetBackLowR(Double_t      x=61./2)      { fBackLowR = x; }
-  void SetBackHighR(Double_t     x=66.8/2)     { fBackHighR = x; }
-  void SetBackLength(Double_t    x=1.4)                { fBackLength = x; }
-  void SetBeamThickness(Double_t x=.5)         { fBeamThickness = x; }
-  void SetBeamWidth(Double_t     x=6)          { fBeamWidth = x; }
-  void SetConeLength(Double_t    x=30.9)       { fConeLength = x; }
-  void SetFlangeR(Double_t       x=49.25)      { fFlangeR = x; }
-  void SetNBeam(Int_t            n=8)           { fNBeam = n; }
-  void SetNFlange(Int_t          n=4)           { fNFlange = n; }
-  
-  Double_t GetNoseZ() const            { return fNoseZ; }
-  Double_t GetNoseLowR() const         { return fNoseLowR; }
-  Double_t GetNoseHighR() const                { return fNoseHighR; }
-  Double_t GetNoseLength() const       { return fNoseLength; }
-  Double_t GetBackLowR() const         { return fBackLowR; }
-  Double_t GetBackHighR() const                { return fBackHighR; }
-  Double_t GetBackLength() const       { return fBackLength; }
-  Double_t GetBeamThickness() const    { return fBeamThickness; }
-  Double_t GetBeamWidth() const                { return fBeamWidth; }
-  Double_t GetConeLength() const       { return fConeLength; }
-  Double_t GetFlangeR() const          { return fFlangeR; }
-  Int_t    GetNBeam() const             { return fNBeam; }
-  Int_t    GetNFlange() const           { return fNFlange; }
-  Double_t GetZ() const                 { return fZ; }
-  Double_t ConeR(Double_t z, Option_t* opt="O") const;
-protected:
-  Double_t fNoseZ;             // Z position of front of nose
-  Double_t fNoseLowR;          // Nose inner radius
-  Double_t fNoseHighR;         // Nose outer radius
-  Double_t fNoseLength;                // Length of nose in Z
-  Double_t fBackLowR;          // Inner radius of base of cone
-  Double_t fBackHighR;         // Outer radius of base of cone
-  Double_t fBackLength;                // Length of base of cone in Z
-  Double_t fBeamThickness;     // Thickness of support beams
-  Double_t fBeamWidth;         // Width of support beams
-  Double_t fConeLength;                // Length of the cone in Z
-  Double_t fFlangeR;            // Outer radius of flanges
-  Double_t fZ;                  // Midpoint of mother volume 
-  Double_t fAlpha;              // Slope of cone 
-  
-  Int_t    fNBeam;              // Number of support beams 
-  Int_t    fNFlange;            // Number of support flanges
-  Int_t    fNoseId;             // Id of nose volume
-  Int_t    fBeamId;             // Id of beam volumes 
-  Int_t    fBackId;             // Id of base volume
-  Int_t    fFlangeId;           // Id of flange volume
-  TArrayI  fRotations;
-  
-  static const Char_t* fgkNoseName; // Name of nose volume 
-  static const Char_t* fgkBeamName; // Name of beam volumes
-  static const Char_t* fgkBackName; // Name of base volume 
-  static const Char_t* fgkFlangeName; // Name of flange volume 
-  
-  ClassDef(AliFMD3Support,1); // Geometry of Support for the FMD3 
-};
-
-#endif
-//____________________________________________________________________
-//
-// Local Variables:
-//   mode: C++
-// End:
-//
-//
-// EOF
-//
index 5360a46af8cbd417bbce3144f4e198d39b58c498..cc7fa074c2890682ee1057cf953b6af44e46b6d0 100644 (file)
@@ -24,6 +24,9 @@
 #include "AliFMDBoolMap.h"     //ALIFMDBOOLMAP_H
 //__________________________________________________________
 ClassImp(AliFMDBoolMap)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 //__________________________________________________________
 AliFMDBoolMap::AliFMDBoolMap(const AliFMDBoolMap& other)
   : AliFMDMap(other.fMaxDetectors,
diff --git a/FMD/AliFMDDetector.cxx b/FMD/AliFMDDetector.cxx
new file mode 100644 (file)
index 0000000..3ecf951
--- /dev/null
@@ -0,0 +1,113 @@
+/**************************************************************************
+ * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved.      *
+ *                                                                        *
+ * Author: The ALICE Off-line Project.                                    *
+ * Contributors are mentioned in the code where appropriate.              *
+ *                                                                        *
+ * Permission to use, copy, modify and distribute this software and its   *
+ * documentation strictly for non-commercial purposes is hereby granted   *
+ * without fee, provided that the above copyright notice appears in all   *
+ * copies and that both the copyright notice and this permission notice   *
+ * appear in the supporting documentation. The authors make no claims     *
+ * about the suitability of this software for any purpose. It is          *
+ * provided "as is" without express or implied warranty.                  *
+ **************************************************************************/
+
+/* $Id$ */
+
+//____________________________________________________________________
+//
+// Utility class to help implement the FMD geometry.  This provides
+// the interface for the concrete geometry implementations of the FMD
+// sub-detectors. 
+//
+// The AliFMDGeometry object owns the AliFMDDetector objects
+//
+// Latest changes by Christian Holm Christensen
+//
+#include "AliFMDDetector.h"    // ALIFMDSUBDETECTOR_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
+#include <AliLog.h>            // ALILOG_H
+
+//====================================================================
+ClassImp(AliFMDDetector)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer) 
+  : TNamed(Form("FMD%d", id), "Forward multiplicity ring"), 
+    fId(id), 
+    fInner(inner),
+    fOuter(outer)
+{
+  SetHoneycombThickness();
+  SetAlThickness();
+  SetInnerHoneyLowR(0);
+  SetInnerHoneyHighR(0);
+  SetInnerZ(0);
+  SetOuterZ(0);
+  SetOuterHoneyLowR(0);
+  SetOuterHoneyHighR(0);
+}
+
+//____________________________________________________________________
+void
+AliFMDDetector::Init()
+{
+  if (fInner) {
+    SetInnerHoneyLowR(fInner->GetLowR() + 1.);
+    SetInnerHoneyHighR(fInner->GetHighR() + 1.);
+  }
+  if (fOuter) {
+    SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
+    SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
+  }
+    
+}
+
+//____________________________________________________________________
+AliFMDRing*
+AliFMDDetector::GetRing(Char_t id) const
+{
+  switch (id) {
+  case 'i':
+  case 'I': return GetInner();
+  case 'o':
+  case 'O': return GetOuter();
+  }
+  return 0;
+}
+
+//____________________________________________________________________
+Double_t
+AliFMDDetector::GetRingZ(Char_t id) const
+{
+  switch (id) {
+  case 'i':
+  case 'I': return GetInnerZ();
+  case 'o':
+  case 'O': return GetOuterZ();
+  }
+  return 0;
+}
+//____________________________________________________________________
+void
+AliFMDDetector::Detector2XYZ(Char_t ring, 
+                            UShort_t sector,
+                            UShort_t strip, 
+                            Double_t& x, 
+                            Double_t& y, 
+                            Double_t& z) const
+{
+  AliFMDRing* r = GetRing(ring);
+  if (!r) return;
+  z = GetRingZ(ring);
+  r->Detector2XYZ(sector, strip, x, y, z);
+}
+
+//____________________________________________________________________
+// 
+// EOF
+//
diff --git a/FMD/AliFMDDetector.h b/FMD/AliFMDDetector.h
new file mode 100644 (file)
index 0000000..55d372e
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef ALIFMDDETECTOR_H
+#define ALIFMDDETECTOR_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_TNamed
+# include <TNamed.h>
+#endif
+class AliFMDRing;
+
+
+//__________________________________________________________________
+/** Base class for the geometry description and parameters of the FMD
+    sub detectors FMD1, FMD2, and FMD3.
+
+    This class hold common parameters of the specific FMD detectors.
+*/
+class AliFMDDetector : public TNamed 
+{
+public:
+  AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer);
+  virtual ~AliFMDDetector() {}
+  /** Initialize the geometry */
+  virtual void Init();
+    
+  /** @param x Detector number */
+  void SetId(Int_t x) { fId = x; }
+  /** @param x Position of outer ring along z */
+  void SetInnerZ(Double_t x) { fInnerZ = x; }
+  /** @param x Position of outer ring along z */
+  void SetOuterZ(Double_t x) { fOuterZ = x; }
+  /** @param x Thickness of honeycomb plate */
+  void SetHoneycombThickness(Double_t x=1) { fHoneycombThickness = x; }
+  /** @param x Thickness of aluminium of honeycomb */
+  void SetAlThickness(Double_t x=.1) { fAlThickness = x; }
+  /** @param x Inner radius of inner honeycomb */
+  void SetInnerHoneyLowR(Double_t x) { fInnerHoneyLowR = x; }
+  /** @param x Outer radius of inner honeycomb */
+  void SetInnerHoneyHighR(Double_t x) { fInnerHoneyHighR = x; }
+  /** @param x Inner radius of outer honeycomb */
+  void SetOuterHoneyLowR(Double_t x) { fOuterHoneyLowR = x; }
+  /** @param x Outer radius of outer honeycomb */
+  void SetOuterHoneyHighR(Double_t x) { fOuterHoneyHighR = x; }
+    
+  /** @return Detector number */
+  Int_t GetId() const { return fId; }
+  /** @return Position of outer ring along z */
+  Double_t GetInnerZ() const { return fInnerZ; }
+  /** @return Position of outer ring along z */
+  Double_t GetOuterZ() const { return fOuterZ; }
+  /** @return Thickness of honeycomb plate */
+  Double_t GetHoneycombThickness() const { return fHoneycombThickness; }
+  /** @return Thickness of aluminium of honeycomb */
+  Double_t GetAlThickness() const { return fAlThickness; }
+  /** @return Inner radius of inner honeycomb */
+  Double_t GetInnerHoneyLowR() const { return fInnerHoneyLowR; }
+  /** @return Outer radius of inner honeycomb */
+  Double_t GetInnerHoneyHighR() const { return fInnerHoneyHighR; }
+  /** @return Inner radius of outer honeycomb */
+  Double_t GetOuterHoneyLowR() const { return fOuterHoneyLowR; }
+  /** @return Outer radius of outer honeycomb */
+  Double_t GetOuterHoneyHighR() const { return fOuterHoneyHighR; }
+    
+  /** @return Inner ring information */
+  AliFMDRing* GetInner() const { return fInner; }
+  /** @return Outer ring information */
+  AliFMDRing* GetOuter() const { return fOuter; }
+  /** @param id Id of ring to get 
+      @return Pointer to ring, 0 on failure */
+  AliFMDRing* GetRing(Char_t id) const;
+  /** @param id Id of ring to get 
+      @return Z position of ring or 0 on failure */
+  Double_t GetRingZ(Char_t id) const;
+  
+  void Detector2XYZ(Char_t ring, UShort_t sector, UShort_t strip, 
+                   Double_t& x, Double_t& y, Double_t& z) const;
+
+protected:
+  Int_t                fId;                    // Detector number
+  Double_t     fInnerZ;                // Position of outer ring along z
+  Double_t     fOuterZ;                // Position of outer ring along z
+  Double_t     fHoneycombThickness;    // Thickness of honeycomb plate
+  Double_t     fAlThickness;           // Thickness of aluminium of honeycomb
+  Double_t     fInnerHoneyLowR;        // Inner radius of inner honeycomb
+  Double_t     fInnerHoneyHighR;       // Outer radius of inner honeycomb
+  Double_t     fOuterHoneyLowR;        // Inner radius of outer honeycomb
+  Double_t     fOuterHoneyHighR;       // Outer radius of outer honeycomb
+  AliFMDRing*  fInner;                 // Pointer to inner ring information
+  AliFMDRing*  fOuter;                 // Pointer to outer ring information
+  
+  ClassDef(AliFMDDetector, 1); // 
+};
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
index ebb44134885a6ee8ade73c30b3a85d5818c915f9..e40bfded195038f1f24627e44f4669135ba29483 100644 (file)
@@ -64,6 +64,9 @@
 
 //====================================================================
 ClassImp(AliFMDBaseDigit)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDBaseDigit::AliFMDBaseDigit()
index 2de93bd2b73801989a9138a97d43cfc340a7c996..9ea4329011cdf3d1007b8e6d15da6c707a283a0e 100644 (file)
 #include <AliLog.h>            // ALILOG_H
 #include "AliFMDDigitizer.h"   // ALIFMDDIGITIZER_H
 #include "AliFMD.h"            // ALIFMD_H
+#include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h"    // ALIFMDDETECTOR_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
 #include "AliFMDHit.h"         // ALIFMDHIT_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIT_H
 #include <AliRunDigitizer.h>   // ALIRUNDIGITIZER_H
 #include <AliLoader.h>         // ALILOADER_H
 #include <AliRunLoader.h>      // ALIRUNLOADER_H
     
-//____________________________________________________________________
-ClassImp(AliFMDEdepMap)
-
 //====================================================================
 ClassImp(AliFMDBaseDigitizer)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDBaseDigitizer::AliFMDBaseDigitizer()  
@@ -340,23 +343,16 @@ AliFMDBaseDigitizer::DigitizeHits(AliFMD* fmd) const
   // the energy signal to ADC counts, and store the created digit in
   // the digits array (AliFMD::fDigits)
   //
+  AliFMDGeometry* geometry = AliFMDGeometry::Instance();
+  
   TArrayI counts(3);
   for (UShort_t detector=1; detector <= 3; detector++) {
     // Get pointer to subdetector 
-    AliFMDSubDetector* det = 0;
-    switch (detector) {
-    case 1: det = fmd->GetFMD1(); break;
-    case 2: det = fmd->GetFMD2(); break;
-    case 3: det = fmd->GetFMD3(); break;
-    }
+    AliFMDDetector* det = geometry->GetDetector(detector);
     if (!det) continue;
     for (UShort_t ringi = 0; ringi <= 1; ringi++) {
       // Get pointer to Ring
-      AliFMDRing* r = 0;
-      switch (ringi) {
-      case 0: if (det->GetInner()) r = det->GetInner(); break;
-      case 1: if (det->GetOuter()) r = det->GetOuter(); break;
-      }
+      AliFMDRing* r = det->GetRing((ringi == 0 ? 'I' : 'O'));
       if (!r) continue;
       
       // Get number of sectors 
@@ -376,7 +372,7 @@ AliFMDBaseDigitizer::DigitizeHits(AliFMD* fmd) const
          
          Float_t edep = fEdep(detector, r->GetId(), sector, strip).fEdep;
          ConvertToCount(edep, last, r->GetSiThickness(), 
-                        fmd->GetSiDensity(), counts);
+                        geometry->GetSiDensity(), counts);
          last = edep;
          AddDigit(fmd, detector, r->GetId(), sector, strip, 
                   edep, UShort_t(counts[0]), 
index 37792248212144c802c10b9d972d91b38197ac4a..87cdbbc8cb11812857e9fe90e868c8b1680b44bb 100644 (file)
@@ -23,6 +23,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDEdepMap)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDEdepMap::AliFMDEdepMap(const AliFMDEdepMap& other)
diff --git a/FMD/AliFMDG3Simulator.cxx b/FMD/AliFMDG3Simulator.cxx
new file mode 100644 (file)
index 0000000..f92bea6
--- /dev/null
@@ -0,0 +1,653 @@
+/**************************************************************************
+ * 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 |<>-----| AliFMDSimulator |
+//      +--------+      +-----------------+
+//                               ^              
+//                               |
+//                 +-------------+-------------+
+//                 |                           |             
+//        +--------------------+   +-------------------+
+//        | AliFMDGeoSimulator |   | AliFMDG3Simulator | 
+//        +--------------------+   +---------+---------+
+//      
+//
+// *  AliFMD 
+//    This defines the interface for the various parts of AliROOT that
+//    uses the FMD, like AliFMDSimulator, AliFMDDigitizer, 
+//    AliFMDReconstructor, and so on. 
+//
+// *  AliFMDSimulator
+//    This is the base class for the FMD simulation tasks.   The
+//    simulator tasks are responsible to implment the geoemtry, and
+//    process hits. 
+//                                                                          
+// *  AliFMDGeoSimulator
+//    This is a concrete implementation of the AliFMDSimulator 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 AliFMDSimulator 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). 
+//
+#include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_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
+
+//====================================================================
+ClassImp(AliFMDG3Simulator)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDG3Simulator::AliFMDG3Simulator() 
+{
+  // Default constructor
+  fSectorOff   = 1;
+  fModuleOff   = 3;
+  fRingOff     = 4;
+  fDetectorOff = 5;
+}
+
+//____________________________________________________________________
+AliFMDG3Simulator::AliFMDG3Simulator(AliFMD* fmd, Bool_t detailed) 
+  : AliFMDSimulator(fmd, detailed)
+{
+  // Normal constructor
+  // 
+  // Parameters: 
+  // 
+  //      fmd          Pointer to AliFMD object 
+  //      detailed      Whether to make a detailed simulation or not 
+  // 
+  fSectorOff   = 1;
+  fModuleOff   = 3;
+  fRingOff     = 4;
+  fDetectorOff = 5;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDG3Simulator::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 kFALSE;
+  }
+  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    par[10];
+  TString     name;
+  TString     name2;
+  TVirtualMC* mc       = TVirtualMC::GetMC();
+  
+  Int_t siId = fFMD->GetIdtmed()->At(kSiId);
+  Int_t airId = fFMD->GetIdtmed()->At(kAirId);
+  Int_t pcbId = fFMD->GetIdtmed()->At(kPcbId);
+  Int_t plaId = fFMD->GetIdtmed()->At(kPlasticId);
+
+  // Virtual volume shape to divide - This volume is only defined if
+  // the geometry is set to be detailed. 
+  // Ring mother volume 
+  par[0]     =  rmin;
+  par[1]     =  rmax;
+  par[2]     =  (siThick + pcbThick + legl + modSpace) / 2;
+  name       =  Form(fgkRingName, id);
+  mc->Gsvolu(name.Data(), "TUBE", airId, par, 3);
+
+  par[0] = rmin;
+  par[1] = rmax;
+  par[2] = siThick / 2;
+  par[3] = -theta;
+  par[4] = theta;
+  name   = Form(fgkActiveName, id);
+  mc->Gsvolu(name.Data(), "TUBS", (fDetailed ? airId : siId), par, 5);
+
+  Int_t sid = -1;
+  if (fDetailed) {
+    name2 = name;
+    name  = Form(fgkSectorName, id);
+    mc->Gsdvn2(name.Data(), name2.Data(), 2, 2, -theta, airId);
+    
+    name2 = name;
+    name  = Form(fgkStripName, id);
+    mc->Gsdvt2(name.Data(), name2.Data(), dstrip, 1, stripoff, siId, ns);
+    sid = mc->VolId(name.Data());
+    AliDebug(10, Form("Got volume id %d for volume %s", sid, name.Data()));
+  }
+  
+  switch (id) {
+  case 'i':
+  case 'I':
+    fInnerId = sid;
+    // fInnerV  = moduleVolume->GetNumber();
+    break;
+  case 'o':
+  case 'O':
+    fOuterId = sid;
+    // fOuterV  = moduleVolume->GetNumber();
+    break;
+  }
+
+  // Shape of Printed circuit Board 
+  // Top
+  par[0] = c->Y() - off;
+  par[1] = b->Y() - off;
+  par[2] = pcbThick / 2;
+  par[3] = (b->X() - c->X()) / 2;
+  par[4] = off;
+  name   = Form(fgkPCBName, id, 'T');
+  mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4);
+  // Bottom
+  par[0] = a->Y() - off;
+  par[1] = c->Y() - off;
+  par[3] = (c->X() - a->X()) / 2;
+  name   = Form(fgkPCBName, id, 'B');
+  mc->Gsvolu(name.Data(), "TRD1", pcbId, par, 4);
+
+  // Short leg volume 
+  par[0] = legr - .1;
+  par[1] = legr;
+  par[2] = legl / 2;
+  name   = Form(fgkShortLegName, id);
+  mc->Gsvolu(name.Data(),  "TUBE",  plaId, par, 3);
+  
+  // Long leg volume 
+  par[2] += modSpace / 2;
+  name   = Form(fgkLongLegName, id);
+  mc->Gsvolu(name.Data(),  "TUBE",  plaId, par, 3);
+  
+  // Back container volume 
+  par[0] = rmin;
+  par[1] = rmax;
+  par[2] = (siThick + pcbThick + legl) / 2;
+  par[3] = -theta;
+  par[4] = +theta;
+  name   = Form(fgkBackVName, id);
+  mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
+  
+  Double_t x = 0;
+  Double_t y = 0;
+  Double_t z = - par[2] + siThick / 2;
+  name2      = name;
+  name       = Form(fgkActiveName, id);
+  mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY");
+  
+  Double_t pbTopL = (b->X() - c->X());
+  Double_t pbBotL = (c->X() - a->X());
+  Int_t    pbRot;
+  mc->Matrix(pbRot, 90, 90, 0, 90, 90, 0);  
+
+  x          =  rmin + pbBotL + pbTopL / 2;
+  z          += siThick / 2 + pcbThick / 2;
+  name       =  Form(fgkPCBName, id, 'T');
+  mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, pbRot, "ONLY");
+  
+  x          =  rmin + pbBotL / 2;
+  name       =  Form(fgkPCBName, id, 'B');
+  mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, pbRot, "ONLY");
+
+  x          =  a->X() + legoff + legr;
+  y          =  0;
+  z          += pcbThick / 2 + legl / 2;
+  name       =  Form(fgkShortLegName, id);
+  mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY");
+
+  x          =  c->X();
+  y          =  c->Y() - legoff - legr - off;
+  mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY");
+
+  y          =  -y;
+  mc->Gspos(name.Data(), 2, name2.Data(), x, y, z, 0, "ONLY");
+
+
+  // Front container volume 
+  par[2]     += modSpace / 2;
+  name       =  Form(fgkFrontVName, id);
+  mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
+  
+  x          =  0;
+  y          =  0;
+  z          =  - par[2] + siThick / 2;
+  name2      =  name;
+  name       =  Form(fgkActiveName, id);
+  mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY");
+  
+  pbTopL     =  (b->X() - c->X());
+  pbBotL     =  (c->X() - a->X());
+  x          =  rmin + pbBotL + pbTopL / 2;
+  z          += siThick / 2 + pcbThick / 2;
+  name       =  Form(fgkPCBName, id, 'T');
+  mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, pbRot, "ONLY");
+  
+  x          =  rmin + pbBotL / 2;
+  name       =  Form(fgkPCBName, id, 'B');
+  mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, pbRot, "ONLY");
+
+  x          =  a->X() + legoff + legr;
+  y          =  0;
+  z          += pcbThick / 2 + legl / 2 + modSpace / 2;
+  name       =  Form(fgkLongLegName, id);
+  mc->Gspos(name.Data(), 0, name2.Data(), x, y, z, 0, "ONLY");
+
+  x          =  c->X();
+  y          =  c->Y() - legoff - legr - off;
+  mc->Gspos(name.Data(), 1, name2.Data(), x, y, z, 0, "ONLY");
+
+  y          =  -y;
+  mc->Gspos(name.Data(), 2, name2.Data(), x, y, z, 0, "ONLY");
+
+
+
+  Int_t nmod = r->GetNModules();
+  name2      =  Form(fgkRingName, id);
+  AliDebug(10, Form("making %d modules in ring %c", nmod, id));
+  for (Int_t i = 0; i < nmod; i++) {
+    Double_t th      = (i + .5) * 2 * theta;
+    Bool_t   isFront = (i % 2 == 0);
+    name             = (isFront ? Form(fgkFrontVName,id) : 
+                       Form(fgkBackVName,id));
+    Double_t z       = (isFront ? 0 : modSpace) / 2;
+    Int_t    rot;
+    mc->Matrix(rot, 90, th, 90, fmod(90 + th, 360), 0, 0);
+    mc->Gspos(name.Data(), i, name2.Data(), 0, 0, z, rot, "ONLY");
+  }
+
+  return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDG3Simulator::DetectorGeometry(AliFMDDetector* d, Double_t zmother) 
+{
+  // 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 
+  //    zmother          The midpoint in global coordinates of detector vol.
+  //
+  // Returns:
+  //    true on success
+  // 
+  if (!d) return kFALSE;
+
+  TString     name;
+  TString     name2;
+  TVirtualMC* mc       = TVirtualMC::GetMC();
+
+  // 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;
+    switch (i) {
+    case 0: 
+      r      = d->GetInner();
+      lowr   = d->GetInnerHoneyLowR();
+      highr  = d->GetInnerHoneyHighR();
+      rz     = d->GetInnerZ();
+      break;
+    case 1: 
+      r      = d->GetOuter();
+      lowr   = d->GetOuterHoneyLowR();
+      highr  = d->GetOuterHoneyHighR();
+      rz     = d->GetOuterZ();
+      break;
+    }
+    if (!r) continue;
+    Char_t   c       = r->GetId();
+    Int_t    id      = d->GetId();
+    Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
+    Int_t    alId    = (fFMD->GetIdtmed()->At(kAlId));
+    Double_t hcThick = d->GetHoneycombThickness();
+    Double_t alThick = d->GetAlThickness();
+    Double_t par[10];
+    Double_t z;
+    // Place ring in mother volume
+    if (zmother > 0) z = rz - zmother + r->GetRingDepth() / 2;
+    else             z = zmother - rz + r->GetRingDepth() / 2;
+    name  = Form(fgkRingName, c);
+    name2 = d->GetName();
+    mc->Gspos(name.Data(), Int_t(c), name2.Data(), 0, 0, z, 0, "ONLY");
+    
+    // Place Top Honeycomb in mother volume 
+    z += + r->GetRingDepth() / 2 + hcThick / 2;
+    // Top of Honeycomb
+    par[0] = lowr;
+    par[1] = highr;
+    par[2] = hcThick / 2;
+    par[3] = 0;
+    par[4] = 180;
+    name   = Form(fgkTopHCName, id, c);
+    mc->Gsvolu(name.Data(), "TUBS", alId, par, 5);
+    mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, z, 0, "ONLY");
+
+    par[0] += alThick;
+    par[1] -= alThick;
+    par[2] -= alThick / 2;
+    name2  =  name;
+    name   =  Form(fgkTopIHCName, id, c);
+    mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
+    mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, 0, 0, "ONLY");
+    
+    // Bot of Honeycomb
+    par[0] = lowr;
+    par[1] = highr;
+    par[2] = hcThick / 2;
+    par[3] = 180;
+    par[4] = 360;
+    name2  = d->GetName();
+    name   = Form(fgkBotHCName, id, c);
+    mc->Gsvolu(name.Data(), "TUBS", alId, par, 5);
+    mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, z, 0, "ONLY");
+
+    par[0] += alThick;
+    par[1] -= alThick;
+    par[2] -= alThick / 2;
+    name2  =  name;
+    name   =  Form(fgkBotIHCName, id, c);
+    mc->Gsvolu(name.Data(), "TUBS", airId, par, 5);
+    mc->Gspos(name.Data(), 0, name2.Data(), 0, 0, 0, 0, "ONLY");
+  }
+  return kTRUE;
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDG3Simulator::FMD1Geometry(AliFMD1* fmd1) 
+{
+  // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
+  // special support as it is at the momement. 
+  // 
+  // See also AliFMDG3Simulator::DetectorGeometry 
+  // 
+  if (!fmd1) return kFALSE;
+  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;
+  TVirtualMC* mc   = TVirtualMC::GetMC();
+  Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
+
+  Double_t par[3];
+  par[0] = rmin;
+  par[1] = rmax;
+  par[2] = w / 2;
+  mc->Gsvolu(fmd1->GetName(), "TUBE", airId, par, 3);
+  mc->Gspos(fmd1->GetName(), fmd1->GetId(), "ALIC", 0, 0, z, 0, "ONLY");
+
+  return DetectorGeometry(fmd1, z);
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDG3Simulator::FMD2Geometry(AliFMD2* fmd2) 
+{
+  // Setup the FMD2 geometry.  The FMD2 has no
+  // special support as it is at the momement. 
+  // 
+  // See also AliFMDG3Simulator::DetectorGeometry 
+  // 
+  if (!fmd2) return kFALSE;
+  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;
+  
+  TVirtualMC* mc   = TVirtualMC::GetMC();
+  Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
+
+  Double_t par[3];
+  par[0] = rmin;
+  par[1] = rmax;
+  par[2] = w / 2;
+  mc->Gsvolu(fmd2->GetName(), "TUBE", airId, par, 3);
+  mc->Gspos(fmd2->GetName(), fmd2->GetId(), "ALIC", 0, 0, z, 0, "ONLY");
+
+  return DetectorGeometry(fmd2, z);
+}
+  
+//____________________________________________________________________
+Bool_t
+AliFMDG3Simulator::FMD3Geometry(AliFMD3* fmd3) 
+{
+  // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
+  // structure, as the support will also support the vacuum
+  // beam-pipe. 
+  // 
+  // See also AliFMDG3Simulator::DetectorGeometry 
+  // 
+  if (!fmd3) return kFALSE;
+  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;
+  TVirtualMC* mc   = TVirtualMC::GetMC();
+  Int_t    airId   = (fFMD->GetIdtmed()->At(kAirId));
+  Int_t    cId     = (fFMD->GetIdtmed()->At(kCarbonId));
+  Double_t par[27];
+  
+  // FMD3 volume 
+  par[0]  = 0;
+  par[1]  = 360;
+  par[2]  = 8;
+  // First
+  par[3]  = z - nz;
+  par[4]  = noser1;
+  par[5]  = noser2;
+  // Second
+  par[6]  = z - (nz - nlen);
+  par[7]  = noser1;
+  par[8]  = fmd3->ConeR(z - par[6])+.15;
+  // Third
+  par[9]  = z - innerZ;
+  par[10] = innerr1;
+  par[11] = fmd3->ConeR(z - par[9])+.15;
+  // Fourth
+  par[12] = z - innerZh;
+  par[13] = innerr1;
+  par[14] = fmd3->ConeR(z - par[12])+.15;
+  // Fifth
+  par[15] = par[12];
+  par[16] = outerr1;
+  par[17] = fmd3->ConeR(z - par[15])+.15;
+  // Sixth
+  par[18] = z - nz + zdist + nlen;
+  par[19] = outerr1;
+  par[20] = fmd3->ConeR(z - par[18])+.15;
+  // Seventh
+  par[21] = z - nz + nlen + zdist;
+  par[22] = outerr1;
+  par[23] = flanger+1.5;
+  // Eight
+  par[24] = z - minZ;
+  par[25] = outerr1;
+  par[26] = flanger+1.5;
+  mc->Gsvolu(fmd3->GetName(), "PCON", airId, par, 27);
+  
+  Int_t id;
+  mc->Matrix(id, 270, 180, 90, 90, 180, 0);
+  mc->Gspos(fmd3->GetName(), fmd3->GetId(), "ALIC", 0, 0, z, id, "ONLY");
+  
+  // Nose volume 
+  par[0] = noser1;
+  par[1] = noser2;
+  par[2] = nlen / 2;
+  zi = z - nz + nlen / 2;
+  mc->Gsvolu(fgkNoseName, "TUBE", cId, par, 3);
+  mc->Gspos(fgkNoseName, 0, fmd3->GetName(), 0, 0, zi, 0, "MANY");
+  
+  // Back
+  par[0] = backr1;
+  par[1] = backr2;
+  par[2] = backl / 2;
+  zi = z - nz + conel - backl / 2;
+  mc->Gsvolu(fgkBackName, "TUBE", cId, par, 3);
+  mc->Gspos(fgkBackName, 0, fmd3->GetName(), 0, 0, zi, 0, "ONLY");
+  
+  Int_t n;
+  Double_t r;
+  // The flanges 
+  par[0] = (flanger - backr2) / 2;
+  par[1] = fmd3->GetBeamWidth() / 2;
+  par[2] = backl / 2;
+  mc->Gsvolu(fgkFlangeName, "BOX", cId, par, 3);
+  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);
+    Int_t    id;
+    mc->Matrix(id, 90, phi, 90, 90 + phi, 0, 0);
+    mc->Gspos(fgkFlangeName, i, fmd3->GetName(), x, y, zi, id, "ONLY");
+  }
+
+  // The Beams 
+  par[0] = fmd3->GetBeamThickness() / 2;
+  par[1] = fmd3->GetBeamWidth() / 2;   
+  par[2] = beaml / 2;             
+  mc->Gsvolu(fgkBeamName, "BOX", cId, par, 3);
+  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);
+    Int_t    id;
+    (void)theta;
+    mc->Matrix(id, 90-theta, phi, 90, 90 + phi, 360 - theta, phi);
+    mc->Gspos(fgkBeamName, i, fmd3->GetName(), x, y, zi, id, "MANY");
+  }
+  
+  return DetectorGeometry(fmd3, z);
+}
+
+//____________________________________________________________________
+void
+AliFMDG3Simulator::DefineGeometry() 
+{
+  // Setup up the FMD geometry. 
+  AliDebug(10, "Setting up volume");
+
+  AliFMDGeometry* fmd   = AliFMDGeometry::Instance();
+  if (!RingGeometry(fmd->GetInner())) {
+    AliError("Failed to create inner ring volume");
+    return;
+  }
+  if (!RingGeometry(fmd->GetOuter())) {
+    AliError("Failed to create outer ring volume");
+    return;
+  }
+  FMD1Geometry(fmd->GetFMD1());
+  FMD2Geometry(fmd->GetFMD2());
+  FMD3Geometry(fmd->GetFMD3());
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDG3Simulator.h b/FMD/AliFMDG3Simulator.h
new file mode 100644 (file)
index 0000000..0df9b8e
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef ALIFMDG3SIMULATOR_H
+#define ALIFMDG3SIMULATOR_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 ALIFMDSIMULATOR
+# include <AliFMDSimulator.h>
+#endif
+class AliFMD;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+//____________________________________________________________________
+class AliFMDG3Simulator : public AliFMDSimulator
+{
+public:
+  AliFMDG3Simulator();
+  /** CTOR */
+  AliFMDG3Simulator(AliFMD* fmd, Bool_t detailed=kTRUE);
+  virtual ~AliFMDG3Simulator() {}
+  /** Register */
+  virtual void DefineGeometry();
+protected:
+  /** Make a ring volume 
+      @param r Ring geometry 
+      @return  Ring volume */
+  Bool_t 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 */
+  Bool_t DetectorGeometry(AliFMDDetector* d, Double_t zmother);
+  /** Make FMD1 volume 
+      @param d Detector geometry 
+      @param inner Inner ring volume 
+      @return FMD1 volume  */
+  Bool_t FMD1Geometry(AliFMD1* d);
+  /** Make FMD2 volume 
+      @param d Detector geometry 
+      @param inner Inner ring volume 
+      @param outer Outer ring volume 
+      @return FMD2 volume  */
+  Bool_t FMD2Geometry(AliFMD2* d);
+  /** Make FMD3 volume 
+      @param d Detector geometry 
+      @param inner Inner ring volume 
+      @param outer Outer ring volume 
+      @return FMD3 volume  */
+  Bool_t FMD3Geometry(AliFMD3* d);
+
+  ClassDef(AliFMDG3Simulator,1);
+};
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
+
diff --git a/FMD/AliFMDGeoSimulator.cxx b/FMD/AliFMDGeoSimulator.cxx
new file mode 100644 (file)
index 0000000..6ace35b
--- /dev/null
@@ -0,0 +1,679 @@
+/**************************************************************************
+ * 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 |<>-----| AliFMDSimulator |
+//      +--------+      +-----------------+
+//                               ^              
+//                               |
+//                 +-------------+-------------+
+//                 |                           |             
+//        +--------------------+   +-------------------+
+//        | AliFMDGeoSimulator |   | AliFMDG3Simulator | 
+//        +--------------------+   +---------+---------+
+//      
+//
+// *  AliFMD 
+//    This defines the interface for the various parts of AliROOT that
+//    uses the FMD, like AliFMDSimulator, AliFMDDigitizer, 
+//    AliFMDReconstructor, and so on. 
+//
+// *  AliFMDSimulator
+//    This is the base class for the FMD simulation tasks.   The
+//    simulator tasks are responsible to implment the geoemtry, and
+//    process hits. 
+//                                                                          
+// *  AliFMDGeoSimulator
+//    This is a concrete implementation of the AliFMDSimulator 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 AliFMDSimulator 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). 
+//
+#include "AliFMDGeoSimulator.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(AliFMDGeoSimulator)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDGeoSimulator::AliFMDGeoSimulator() 
+  : fSi(0),
+    fC(0),
+    fAl(0),
+    fPCB(0),
+    fChip(0),
+    fPlastic(0)
+{
+  // Default constructor
+  fSectorOff   = 1;
+  fModuleOff   = 4;
+  fRingOff     = 5;
+  fDetectorOff = 6;
+}
+
+//____________________________________________________________________
+AliFMDGeoSimulator::AliFMDGeoSimulator(AliFMD* fmd, Bool_t detailed) 
+  : AliFMDSimulator(fmd, detailed),
+    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 
+  // 
+  fSectorOff   = 1;
+  fModuleOff   = 4;
+  fRingOff     = 5;
+  fDetectorOff = 6;
+}
+
+//____________________________________________________________________
+void
+AliFMDGeoSimulator::DefineMaterials() 
+{
+  // 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_ALICE)
+  //   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");
+
+  if (!gGeoManager) {
+    AliFatal("No TGeoManager defined");
+    return;
+  }
+  AliFMDSimulator::DefineMaterials();
+  fSi      = gGeoManager->GetMedium("FMD Si$");
+  fC       = gGeoManager->GetMedium("FMD Carbon$");
+  fAl      = gGeoManager->GetMedium("FMD Aluminum$");
+  fChip    = gGeoManager->GetMedium("FMD Chip$");
+  fAir     = gGeoManager->GetMedium("FMD Air$");
+  fPCB     = gGeoManager->GetMedium("FMD PCB$");
+  fPlastic = gGeoManager->GetMedium("FMD Plastic$");
+}
+
+//____________________________________________________________________
+TGeoVolume*
+AliFMDGeoSimulator::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;
+  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();
+  }
+  
+  // Virtual volume shape to divide - This volume is only defined if
+  // the geometry is set to be detailed. 
+  Int_t sid = -1;
+  TGeoVolume* activeVolume = 0;
+  if (fDetailed) {
+    TGeoTubeSeg* activeShape = 
+      new TGeoTubeSeg(rmin, rmax, siThick/2, - theta, theta);
+    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();
+  }
+  
+  // 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);
+  // Add divived MANY volume to the true shape of the module, but only
+  // if a detailed simulation is reguested. 
+  if (activeVolume) moduleVolume->AddNodeOverlap(activeVolume, 0);
+  
+  switch (id) {
+  case 'i':
+  case 'I':
+    fInnerId = sid;
+    // fInnerV  = moduleVolume->GetNumber();
+    break;
+  case 'o':
+  case 'O':
+    fOuterId = sid;
+    // fOuterV  = moduleVolume->GetNumber();
+    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;
+  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 + 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 + 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*
+AliFMDGeoSimulator::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*
+AliFMDGeoSimulator::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 AliFMDGeoSimulator::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;
+  
+  TGeoTube* fmd1Shape = new TGeoTube(rmin, rmax, w / 2);
+  TGeoVolume* fmd1Volume = new TGeoVolume(fmd1->GetName(), fmd1Shape, fAir);
+  
+  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*
+AliFMDGeoSimulator::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 AliFMDGeoSimulator::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;
+  
+  TGeoTube* fmd2Shape = new TGeoTube(rmin, rmax, w / 2);
+  TGeoVolume* fmd2Volume = new TGeoVolume(fmd2->GetName(), fmd2Shape, fAir);
+  
+  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*
+AliFMDGeoSimulator::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 AliFMDGeoSimulator::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 
+  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);
+  TGeoVolume* fmd3Volume = new TGeoVolume(fmd3->GetName(), fmd3Shape, fAir);
+  
+  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);
+  
+  // 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);
+    
+  }
+
+  // The Beams 
+  TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, 
+                                    fmd3->GetBeamWidth() / 2,
+                                    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));
+    rot->RotateZ(phi);
+    rot->RotateY(-theta);
+    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
+AliFMDGeoSimulator::DefineGeometry() 
+{
+  // Setup up the FMD geometry. 
+  AliDebug(10, "Setting up volume");
+
+  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);
+}
+
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDGeoSimulator.h b/FMD/AliFMDGeoSimulator.h
new file mode 100644 (file)
index 0000000..c3395e5
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef ALIFMDGEOSIMULATOR_H
+#define ALIFMDGEOSIMULATOR_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 ALIFMDSIMULATOR
+# include <AliFMDSimulator.h>
+#endif
+class TGeoVolume;
+class TGeoMedium;
+class AliFMD;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+//____________________________________________________________________
+class AliFMDGeoSimulator : public AliFMDSimulator
+{
+public:
+  AliFMDGeoSimulator();
+  /** CTOR */
+  AliFMDGeoSimulator(AliFMD* fmd, Bool_t detailed=kTRUE);
+  virtual ~AliFMDGeoSimulator() {}
+  /** Initialize */
+  virtual void DefineMaterials();
+  /** Register */
+  virtual void DefineGeometry();
+protected:
+  /** Make a ring volume 
+      @param r Ring geometry 
+      @return  Ring volume */
+  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 */
+  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  */
+  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  */
+  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  */
+  TGeoVolume* FMD3Geometry(AliFMD3* d, TGeoVolume* inner, 
+                          TGeoVolume* outer);
+  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
+
+  ClassDef(AliFMDGeoSimulator,1)
+};
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
+
diff --git a/FMD/AliFMDGeometry.cxx b/FMD/AliFMDGeometry.cxx
new file mode 100644 (file)
index 0000000..6aacd3d
--- /dev/null
@@ -0,0 +1,212 @@
+/**************************************************************************
+ * 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 is a singleton that handles the geometry parameters of
+// the FMD detectors.  
+//                                                       
+// The actual code is done by various separate classes.   Below is
+// diagram showing the relationship between the various FMD classes
+// that handles the geometry 
+//
+//                               +------------+ 
+//                            +- | AliFMDRing |
+//                        2  |  +------------+
+//      +----------------+<>--+        |                               
+//      | AliFMDGeometry |             ^                               
+//      +----------------+<>--+        V 1..2                          
+//                        3  | +----------------+              
+//                           +-| AliFMDDetector |              
+//                                     +----------------+              
+//                                     ^
+//                                     |
+//                       +-------------+-------------+
+//                       |             |             |       
+//                  +---------+   +---------+   +---------+
+//                  | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
+//                  +---------+   +---------+   +---------+
+//      
+//
+// *  AliFMDRing 
+//    This class contains all stuff needed to do with a ring.  It's
+//    used by the AliFMDDetector objects to instantise inner and
+//    outer rings.  The AliFMDRing objects are shared by the
+//    AliFMDDetector objects, and owned by the AliFMDv1 object. 
+//
+// *  AliFMD1, AliFMD2, and AliFMD3 
+//    These are specialisation of AliFMDDetector, that contains the
+//    particularities of each of the sub-detector system.  It is
+//    envisioned that the classes should also define the support
+//    volumes and material for each of the detectors.                          
+//                                                                          
+//
+#include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
+#include "AliFMD1.h"           // ALIFMD1_H
+#include "AliFMD2.h"           // ALIFMD2_H
+#include "AliFMD3.h"           // ALIFMD2_H
+#include "AliRecPoint.h"       // ALIRECPOINT_H
+#include "AliLog.h"            // ALIRECPOINT_H
+#include <TVector3.h>           // ROOT_TVector3
+#include <TMatrix.h>            // ROOT_TMatrix
+#include <TParticle.h>          // ROOT_TParticle
+#include <Riostream.h>
+
+//====================================================================
+ClassImp(AliFMDGeometry)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
+
+//____________________________________________________________________
+AliFMDGeometry* 
+AliFMDGeometry::Instance() 
+{
+  if (!fgInstance) fgInstance = new AliFMDGeometry;
+  return fgInstance;
+}
+
+//____________________________________________________________________
+AliFMDGeometry::AliFMDGeometry() 
+  : AliGeometry("FMD", "Forward multiplicity")
+{
+  fUseFMD1 = kTRUE;
+  fUseFMD2 = kTRUE;
+  fUseFMD3 = kTRUE;  
+  fInner = new AliFMDRing('I');
+  fOuter = new AliFMDRing('O');
+  fFMD1  = new AliFMD1(fInner);
+  fFMD2  = new AliFMD2(fInner, fOuter);
+  fFMD3  = new AliFMD3(fInner, fOuter);
+  fIsInitialized = kFALSE;
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::Init()
+{
+  if (fIsInitialized) return;
+  fInner->Init();
+  fOuter->Init();
+  fFMD1->Init();
+  fFMD2->Init();
+  fFMD3->Init();
+}
+
+//____________________________________________________________________
+AliFMDDetector*
+AliFMDGeometry::GetDetector(Int_t i) const
+{
+  switch (i) {
+  case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
+  case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
+  case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
+  }
+  return 0;
+}
+
+//____________________________________________________________________
+AliFMDRing*
+AliFMDGeometry::GetRing(Char_t i) const
+{
+  switch (i) {
+  case 'I':
+  case 'i': return fInner;
+  case 'O':
+  case 'o': return fOuter;
+  }
+  return 0;
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::Enable(Int_t i)
+{
+  switch (i) {
+  case 1: fUseFMD1 = kTRUE; break;
+  case 2: fUseFMD2 = kTRUE; break;
+  case 3: fUseFMD3 = kTRUE; break;
+  }
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::Disable(Int_t i)
+{
+  switch (i) {
+  case 1: fUseFMD1 = kFALSE; break;
+  case 2: fUseFMD2 = kFALSE; break;
+  case 3: fUseFMD3 = kFALSE; break;
+  }
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::Detector2XYZ(UShort_t  detector, 
+                    Char_t    ring, 
+                    UShort_t  sector, 
+                    UShort_t  strip, 
+                    Double_t& x, 
+                    Double_t& y, 
+                    Double_t& z) const
+{
+  AliFMDDetector* det = GetDetector(detector);
+  if (!det) return;
+  det->Detector2XYZ(ring, sector, strip, x, y, z);
+}
+
+
+//____________________________________________________________________
+void
+AliFMDGeometry::GetGlobal(const AliRecPoint* p, 
+                         TVector3& pos, 
+                         TMatrix& /* mat */) const 
+{
+  GetGlobal(p, pos);
+}
+
+//____________________________________________________________________
+void
+AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const 
+{
+  Double_t x, y, z;
+  TVector3 local;
+  p->GetLocalPosition(local);
+  UShort_t detector = UShort_t(local.X());
+  UShort_t sector   = UShort_t(local.Y());
+  UShort_t strip    = UShort_t(local.Z());
+  Detector2XYZ(detector, 'I', sector, strip, x, y, z);
+  pos.SetXYZ(x, y, z);
+}
+
+//____________________________________________________________________
+Bool_t
+AliFMDGeometry::Impact(const TParticle* /* particle */) const 
+{ 
+  return kFALSE; 
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDGeometry.h b/FMD/AliFMDGeometry.h
new file mode 100644 (file)
index 0000000..698ece0
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef ALIFMDGEOMETRY_H
+#define ALIFMDGEOMETRY_H
+//____________________________________________________________________ 
+//  
+// $Id$ 
+//
+#ifndef ALIGEOMETRY_H
+# include <AliGeometry.h>
+#endif
+#ifndef ROOT_TObjArray
+# include <TObjArray.h>
+#endif
+class TVector3;
+class TMatrix;
+class TParticle;
+class AliRecPoint;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+
+//__________________________________________________________________
+/** Singleton object of FMD geometry descriptions and parameters.
+ */
+class AliFMDGeometry : public AliGeometry
+{
+public:
+  static AliFMDGeometry* Instance();
+  virtual void Init();
+  AliFMDRing*     GetInner() const { return fInner; }
+  AliFMDRing*     GetOuter() const { return fOuter; }
+  AliFMD1*        GetFMD1()  const { return (fUseFMD1 ? fFMD1 : 0); }
+  AliFMD2*        GetFMD2()  const { return (fUseFMD2 ? fFMD2 : 0); }
+  AliFMD3*        GetFMD3()  const { return (fUseFMD3 ? fFMD3 : 0); }
+  AliFMDDetector* GetDetector(Int_t i) const;
+  AliFMDRing*     GetRing(Char_t i) const;
+  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;
+
+  // AliGeometry member functions 
+  virtual void GetGlobal(const AliRecPoint* p, TVector3& pos, 
+                        TMatrix& mat) const;
+  virtual void GetGlobal(const AliRecPoint* p, TVector3& pos) const;
+  virtual Bool_t Impact(const TParticle* particle) const;
+protected:
+  Bool_t        fIsInitialized;
+  AliFMDRing*  fInner;         // Inner ring geometry information
+  AliFMDRing*  fOuter;         // Outer ring geometry information
+  AliFMD1*     fFMD1;          // FMD1 geometry information
+  AliFMD2*     fFMD2;          // FMD2 geometry information
+  AliFMD3*     fFMD3;          // FMD3 geometry information
+  Bool_t       fUseFMD1;       // Wheter to Use FMD1 or not
+  Bool_t       fUseFMD2;       // Wheter to Use FMD2 or not
+  Bool_t       fUseFMD3;       // Wheter to Use FMD3 or not
+  static AliFMDGeometry* fgInstance;
+  AliFMDGeometry();
+  virtual ~AliFMDGeometry() {}
+
+  ClassDef(AliFMDGeometry,1); //
+};
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
index 3bc01a1e5b7978e1eb817187a67e5e49c231cd71..09ab2b139c4982a2263aeed6f898d7c9b00ef3c2 100644 (file)
@@ -27,6 +27,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDHit)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 
 //____________________________________________________________________
index 395b77059fadc2238a7be4e4158d23b2bd498aab..39737c316776540df42889b03a5577a0a099bea8 100644 (file)
@@ -23,6 +23,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMap)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDMap::AliFMDMap(size_t maxDet, 
index 32c22a43e95413e34cdb1aac3a9ef430fbd51be2..54f5e0edaf3610435854932a9105c756bd356e63 100644 (file)
@@ -28,6 +28,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMult)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDMult::AliFMDMult(Float_t  particles, UShort_t method)
index 0438ef23b4be34a0ad1650c2c024e9ce6a2b9cde..5fc4bb91924c39f25750abb90095758d114069e5 100644 (file)
@@ -76,6 +76,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMultAlgorithm)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDMultAlgorithm::AliFMDMultAlgorithm(const char* name, const char* title)
index c33eca39e8776f3cba6d961986d687f86a348925..0d6496d7a4b133f6a7237675aa9748c7ae73eddf 100644 (file)
@@ -26,6 +26,7 @@
 // 
 #include "AliFMD.h"                    // ALIFMD_H
 #include "AliFMDMultNaiive.h"          // ALIFMDMULTNAIIVE_H
+#include "AliFMDParameters.h"           // ALIFMDPARAMETERS_H
 #include "AliFMDMultStrip.h"           // ALIFMDMULTNAIIVE_H
 #include "AliFMDDigit.h"               // ALIFMDDIGIT_H
 #include <TClonesArray.h>               // ROOT_TClonesArray
@@ -33,6 +34,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMultNaiive)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDMultNaiive::AliFMDMultNaiive()
@@ -48,8 +52,9 @@ AliFMDMultNaiive::PreRun(AliFMD* fmd)
 {
   // Initialise before a run 
   AliFMDMultAlgorithm::PreRun(fmd);
-  fEdepMip = fmd->GetEdepMip();
-  fGain = (Float_t(fmd->GetVA1MipRange()) / fmd->GetAltroChannelSize() 
+  AliFMDParameters* pars = AliFMDParameters::Instance();
+  fEdepMip = pars->GetEdepMip();
+  fGain = (Float_t(pars->GetVA1MipRange()) / pars->GetAltroChannelSize() 
           * fEdepMip);
 }
 
index f3ae7cacf3b7ea926b7f593eeb9e317b1ece1bb3..af89b6f52a5659532ffc454ae083f97c8e08f370 100644 (file)
@@ -25,6 +25,9 @@
 // ratio of empty to full strips. 
 //
 #include "AliFMD.h"                    // ALIFMD_H
+#include "AliFMDGeometry.h"            // ALIFMDGEOMETRY_H
+#include "AliFMDDetector.h"            // ALIFMDDETECTOR_H
+#include "AliFMDRing.h"                        // ALIFMDRING_H
 #include "AliFMDMultPoisson.h"         // ALIFMDMULTPOISSON_H
 #include "AliFMDMultRegion.h"          // ALIFMDMULTREGION_H
 #include "AliFMDDigit.h"               // ALIFMDDIGIT_H
@@ -34,6 +37,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMultPoisson)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDMultPoisson::AliFMDMultPoisson()
@@ -94,22 +100,14 @@ AliFMDMultPoisson::PostEvent()
 
   // Loop over the detectors 
   for (Int_t i = 1; i <= 3; i++) {
-    AliFMDSubDetector* sub = 0;
-    switch (i) {
-    case 1: sub = fFMD->GetFMD1(); break;
-    case 2: sub = fFMD->GetFMD2(); break;
-    case 3: sub = fFMD->GetFMD3(); break;
-    }
+    AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+    AliFMDDetector* sub = fmd->GetDetector(i);
     if (!sub) continue;
        
     // Loop over the rings in the detector
     for (Int_t j = 0; j < 2; j++) {
-      Float_t     rZ = 0;
-      AliFMDRing* r  = 0;
-      switch (j) {
-      case 0: r  = sub->GetInner(); rZ = sub->GetInnerZ(); break;
-      case 1: r  = sub->GetOuter(); rZ = sub->GetOuterZ(); break;
-      }
+      AliFMDRing* r  = sub->GetRing((j == 0 ? 'I' : 'O'));
+      Float_t     rZ = sub->GetRingZ((j == 0 ? 'I' : 'O'));
       if (!r) continue;
       
       // Calculate low/high theta and eta 
index 7119795339af39260f2c44053c97a43a60f59830..460c6301888b88297f11a3ca72aa99f0d23ff200 100644 (file)
@@ -35,6 +35,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMultRegion)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 
 //____________________________________________________________________
index 0f08768df75f5dd77220676ea22aec7eb3c3b1ea..f42654a5ec211c40b777543b09d939c277e2c28e 100644 (file)
@@ -32,6 +32,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDMultStrip)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 
 //____________________________________________________________________
diff --git a/FMD/AliFMDParameters.cxx b/FMD/AliFMDParameters.cxx
new file mode 100644 (file)
index 0000000..8ec4a78
--- /dev/null
@@ -0,0 +1,80 @@
+/**************************************************************************
+ * 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 is a singleton that handles various parameters of
+// the FMD detectors.  
+//                                                       
+#include "AliFMDParameters.h"  // ALIFMDPARAMETERS_H
+#include "AliFMDGeometry.h"    // ALIFMDGEOMETRY_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
+#include "AliLog.h"            // ALILOG_H
+#include <Riostream.h>
+
+//====================================================================
+ClassImp(AliFMDParameters)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+AliFMDParameters* AliFMDParameters::fgInstance = 0;
+
+//____________________________________________________________________
+AliFMDParameters* 
+AliFMDParameters::Instance() 
+{
+  // Get static instance 
+  if (!fgInstance) fgInstance = new AliFMDParameters;
+  return fgInstance;
+}
+
+//____________________________________________________________________
+AliFMDParameters::AliFMDParameters() 
+  : fSiDeDxMip(1.664)
+{
+  // Default constructor 
+  SetVA1MipRange();
+  SetAltroChannelSize();
+  SetChannelsPerAltro();
+  SetZeroSuppression();
+  SetSampleRate();
+  SetPedestal();
+  SetPedestalWidth();
+  SetPedestalFactor();
+}
+
+
+
+//__________________________________________________________________
+Float_t
+AliFMDParameters::GetEdepMip() const 
+{ 
+  // Get energy deposited by a MIP in the silicon sensors
+  AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+  return (fSiDeDxMip 
+         * fmd->GetRing('I')->GetSiThickness() 
+         * fmd->GetSiDensity());
+}
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDParameters.h b/FMD/AliFMDParameters.h
new file mode 100644 (file)
index 0000000..062440c
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef ALIFMDPARAMETERS_H
+#define ALIFMDPARAMETERS_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                               
+ */
+
+//____________________________________________________________________
+//
+//  Singleton class to handle various parameters (not geometry) of the
+//  FMD
+//
+#ifndef ROOT_TNamed
+# include <TNamed.h>
+#endif
+
+class AliFMDParameters : public TNamed
+{
+public:
+  static AliFMDParameters* Instance();
+  
+  // Set various parameters 
+  void     SetVA1MipRange(UShort_t r=20)          { fVA1MipRange = r; }
+  void     SetAltroChannelSize(UShort_t s=1024)   { fAltroChannelSize = s;}
+  void     SetChannelsPerAltro(UShort_t size=128) { fChannelsPerAltro = size; }
+  void     SetZeroSuppression(UShort_t s=0)       { fZeroSuppression = s; }
+  void     SetSampleRate(UShort_t r=1)            { fSampleRate = (r>2?2:r);}
+  void     SetPedestal(Float_t p=10)              { fPedestal = p; }
+  void     SetPedestalWidth(Float_t w=1)          { fPedestalWidth = w; }
+  void     SetPedestalFactor(Float_t f=3)         { fPedestalFactor = f; }
+
+  // Get various parameters
+  UShort_t GetVA1MipRange()          const { return fVA1MipRange; }
+  UShort_t GetAltroChannelSize()     const { return fAltroChannelSize; }
+  UShort_t GetChannelsPerAltro()     const { return fChannelsPerAltro; }
+  UShort_t GetZeroSuppression()      const { return fZeroSuppression; }
+  UShort_t GetSampleRate()           const { return fSampleRate; }
+  Float_t  GetEdepMip()              const;
+  Float_t  GetPedestal()            const { return fPedestal; }
+  Float_t  GetPedestalWidth()       const { return fPedestalWidth; }
+  Float_t  GetPedestalFactor()      const { return fPedestalFactor; }
+
+  enum { 
+    kBaseDDL = 0x1000 // DDL offset for the FMD
+  };
+protected:
+  AliFMDParameters();
+  virtual ~AliFMDParameters() {}
+  static AliFMDParameters* fgInstance;
+  
+  const Float_t fSiDeDxMip;        // MIP dE/dx in Silicon
+  UShort_t      fVA1MipRange;      // # MIPs the pre-amp can do    
+  UShort_t      fAltroChannelSize; // Largest # to store in 1 ADC ch.
+  UShort_t      fChannelsPerAltro; // Number of pre-amp. channels/adc chan.
+  UShort_t      fZeroSuppression;  // Threshold for zero-suppression
+  UShort_t      fSampleRate;       // Times the ALTRO samples pre-amp.
+  Float_t       fPedestal;         // Pedestal to subtract
+  Float_t       fPedestalWidth;    // Width of pedestal
+  Float_t       fPedestalFactor;   // Number of pedestal widths
+
+  
+  ClassDef(AliFMDParameters,1)
+};
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
+
diff --git a/FMD/AliFMDPolygon.cxx b/FMD/AliFMDPolygon.cxx
deleted file mode 100644 (file)
index 92192ce..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/**************************************************************************
- * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
- *                                                                        *
- * Author: The ALICE Off-line Project.                                    *
- * Contributors are mentioned in the code where appropriate.              *
- *                                                                        *
- * Permission to use, copy, modify and distribute this software and its   *
- * documentation strictly for non-commercial purposes is hereby granted   *
- * without fee, provided that the above copyright notice appears in all   *
- * copies and that both the copyright notice and this permission notice   *
- * appear in the supporting documentation. The authors make no claims     *
- * about the suitability of this software for any purpose. It is          *
- * provided "as is" without express or implied warranty.                  *
- **************************************************************************/
-
-/* $Id$ */
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Utility class to help implement shape of the FMD modules
-//
-// Latest changes by Christian Holm Christensen
-//
-//////////////////////////////////////////////////////////////////////////////
-#include "AliFMDPolygon.h"     // ALIFMDPOLYGON_H
-#include "AliLog.h"            // ALILOG_H
-#include "TString.h"           // ROOT_TString
-#include "TVector2.h"          // ROOT_TVector2
-#include "TCanvas.h"           // ROOT_TCanvas
-#include "TText.h"             // ROOT_TText
-#include "TGraph.h"            // ROOT_TGraph
-#include "TError.h"            // ROOT_TError
-
-//____________________________________________________________________
-ClassImp(AliFMDPolygon)
-
-//____________________________________________________________________
-AliFMDPolygon::AliFMDPolygon()
-  : fState(kUnknown)
-{}
-
-//____________________________________________________________________
-AliFMDPolygon::~AliFMDPolygon() 
-{
-  fVerticies.Delete();
-}
-
-//____________________________________________________________________
-bool
-AliFMDPolygon::AddVertex(double x, double y) 
-{
-  // Add points in order to the polygon. 
-  TVector2* c = new TVector2(x,y);
-  return AddVertex(c);
-}
-//____________________________________________________________________
-bool
-AliFMDPolygon::AddVertex(TVector2* c) 
-{
-  // Add points in order to the polygon.
-  //
-  // Checks if the addition of the vertex makes the alipolygon
-  // concave, and if it does, returns false.  Note, that the check
-  // isn't performed until at least 3 verticies have already been
-  // added to the alipolygon (a triangle is always convex).
-  if (!c) return false;
-  if (fVerticies.GetEntries() >= 3) {
-    if (!IsOnLeftHand(c, fVerticies.GetEntries()-2,
-                     fVerticies.GetEntries()-1)) {
-      Error("AliFMDPolygon::AddVertex", 
-           "Adding vertex (%f,%f) makes alipolygon concave", 
-           c->X(), c->Y());
-      return false;
-    }
-  }
-  fState = kUnknown;
-  fVerticies.AddAtAndExpand(c, fVerticies.GetEntries());
-  return true;
-}
-
-//____________________________________________________________________
-const TVector2&
-AliFMDPolygon::GetVertex(size_t i) const
-{
-  // Get one of the verticies
-  if (i > size_t(fVerticies.GetEntries()))
-    Fatal("AliFMDPolygon::GetVertex", "Index %d out of range [0,%d]", 
-         i, fVerticies.GetEntries());
-  return *(static_cast<TVector2*>(fVerticies.At(i)));
-}
-
-//____________________________________________________________________
-bool
-AliFMDPolygon::Contains(const TVector2* c) const
-{
-  /* This function checks if a point is inside the polygon.  It does
-   * that by looping over the segments of the polygon, and decides
-   * wether the point is on the left-hand-side (LHS) of the segment.
-   * 
-   * Suppose we had the polygon and point 
-   *
-   *     2 x----x 1
-   *      /      \\
-   *    3 x   P   x 0
-   *      \\      /
-   *     4 x----x 5
-   * 
-   * Then, P is on LHS of the segment 0->1, 1->2, ..., and 5->0, and
-   * so inside the polygon.
-   * 
-   * Suppose instead the point was like
-   * 
-   *     2 x----x 1
-   *      /      \\    P
-   *    3 x       x 0
-   *      \\      /
-   *     4 x----x 5
-   * 
-   * Then it would still be on the LHS of the segments 1->2, 2->3,
-   * 3->4, 4->5, but on the right-hand-side of 5->0, and 0->1 and
-   * hence outside the polygon.
-   */ 
-  if (!c) return kFALSE;
-  if (fState == kUnknown) fState = (ConvexCheck() ? kConvex : kConcave);
-  if (fState == kConcave) return false;
-  size_t n = fVerticies.GetEntries();
-  for (size_t i = 0; i < n; ++i) 
-    if (!IsOnLeftHand(c, i, (i + 1) % n))
-      // If point is on the left hand side of the segment, it's
-      // outside the polygon.
-      return false;
-  return true;
-}
-
-//____________________________________________________________________
-bool
-AliFMDPolygon::Contains(double x, double y) const
-{
-  TVector2 c(x,y);
-  return Contains(&c);
-}
-
-//____________________________________________________________________
-bool
-AliFMDPolygon::ConvexCheck() const
-{
-  /* 
-   * This member function loops through the verticies, and checks if
-   * the next-to-next vertex is in between the current vertex and the
-   * next vertex.
-   * 
-   * Suppose we have the polygon 
-   *           
-   *     2 x----x 1
-   *      /      \\
-   *    3 x       x 0
-   *      \\      /
-   *     4 x----x 5
-   * 
-   * Then the vertex 2 is on the left-hand-side (LHS) of the segment
-   * 0->1, 3 is on the LHS of 1->2, ..., and 0 is on the RHS of 4->5,
-   * and so the polygon is convex.
-   * 
-   * If we had a polygon like
-   *
-   *     2 x----x 1
-   *        \\    \\
-   *       3 x    x 0
-   *        /     /
-   *     4 x----x 5
-   * 
-   * Then, the vertex 4 is NOT on the LHS of the segment 2->3, and so
-   * the polygon is NOT convex.
-   */
-  size_t n = fVerticies.GetEntries();
-  // A triangle is always convex. 
-  if (n <= 3) return true;
-  for (size_t i = 0; i < n; i++) {
-    // Get the next, and next-to-next indicies, taking care to go
-    // around the polygon.
-    size_t j = (i + 1) % n;
-    size_t k = (i + 2) % n;
-    // Check The next-to-next vertex is on the LHS of the current
-    // vertex and the next vertex 
-    if (!IsOnLeftHand(static_cast<TVector2*>(fVerticies.At(k)), i, j)) {
-      Error("AliFMDPolygon::ConvexCheck", 
-           "AliFMDPolygon is concave at segment %d -> %d" , i, j);
-      return false;
-    }
-  }
-  return true;
-}
-    
-//____________________________________________________________________
-bool
-AliFMDPolygon::IsOnLeftHand(const TVector2* c, size_t i1, size_t i2) const
-{
-  /* Check if a point is on the left-hand-side (LHS) or
-   * right-hand-side (RHS) of the segment defined by the two indicies.
-   * 
-   * Suppose we have the segment and point 
-   * 
-   *     1 x
-   *        \\    P
-   *         x 0  
-   *
-   * Then, we define the vectors 
-   *
-   *   v: 0->P 
-   *   u: perpendicular to 1->0 
-   * 
-   * The dot product of u and v is >= 0, meaning that the
-   * angle between the two vectors is in [0,pi], and so P is on the
-   * RHS of the segment
-   *
-   * Suppose we had 
-   *
-   *       1 x
-   *    P     \\    
-   *           x 0  
-   *
-   * And defining the vectors u,v as above.  In this case the dot
-   * product is less than 0, meaning the angle between u,v is in
-   * (pi,2pi], and so P is on the LHS of the segment
-   */
-  if (!c) return false;
-  const TVector2& v1 = GetVertex(i1);
-  const TVector2& v2 = GetVertex(i2);
-  double dot = (  (c->X()  - v1.X())  * (v2.Y() - v1.Y()) 
-               - (c->Y() - v1.Y()) * (v2.X()  - v1.X()));
-  return (dot < 0 ? true : false);
-}
-
-//____________________________________________________________________
-void
-AliFMDPolygon::Clear(Option_t*) 
-{
-  fState = kUnknown;
-  fVerticies.Delete();
-  // fVerticies.Resize(0);
-}
-
-//____________________________________________________________________
-void
-AliFMDPolygon::Draw(const char* option, const char* name) const 
-{
-  size_t n = fVerticies.GetEntries();
-  TGraph* g = new TGraph(n+1);
-  if (name) g->SetName(name);
-  g->SetMarkerStyle(20);
-  for (size_t i = 0; i < n; i++) {
-    const TVector2& v = GetVertex(i);
-    g->SetPoint(i, v.X(), v.Y());
-  }
-  const TVector2& v = GetVertex(0);
-  g->SetPoint(n, v.X(), v.Y());
-  g->Draw(option);
-  TString opt(option);
-  if (!opt.Contains("p", TString::kIgnoreCase))
-    return;
-  for (size_t i = 0; i < n; i++) {
-    const TVector2& v = GetVertex(i);
-    TText* t = new TText(v.X(), v.Y(), Form("%d", i));
-    t->Draw();
-  }
-}
-
-//____________________________________________________________________
-//
-// EOf
-//
diff --git a/FMD/AliFMDPolygon.h b/FMD/AliFMDPolygon.h
deleted file mode 100644 (file)
index ecd3eaf..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef ALIFMDPOLYGON_H
-#define ALIFMDPOLYGON_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_TVector2
-# include <TVector2.h>
-#endif
-#ifndef ROOT_TObjArray
-# include <TObjArray.h>
-#endif
-
-class AliFMDPolygon : public TObject 
-{
-public:
-  // Construct a alipolygon with N sides
-  AliFMDPolygon();
-  virtual ~AliFMDPolygon();
-
-  // Clear the polygon 
-  void Clear(Option_t* option="");
-  
-  // Add a vertex 
-  bool AddVertex(TVector2* c);
-  bool AddVertex(double x, double y);
-
-  // Get a vertex point 
-  const TVector2& GetVertex(size_t i) const;
-  
-  // Check if a point is inside the polygon 
-  bool Contains(const TVector2* c) const;
-  bool Contains(double x, double y) const;
-  
-  // Get the number of verticies 
-  size_t GetNVerticies() const { return fVerticies.GetEntries(); }  
-  // Get the coordinates 
-  const TObjArray& GetVerticies() const { return fVerticies; }
-  
-  void Draw(const char* option="PL", const char* name=0) const;
-
-private:
-  enum {
-    kUnknown, 
-    kConvex, 
-    kConcave
-  };
-  mutable Int_t fState;
-  // List of coordinates 
-  TObjArray fVerticies;
-  // Force convexity check 
-  bool ConvexCheck() const;
-  // Check if a point is at the right-hand side of a segment 
-  bool IsOnLeftHand(const TVector2* c, size_t i1, size_t i2) const;
-
-  ClassDef(AliFMDPolygon,1) // Polygon parameters
-};
-
-#endif
-//____________________________________________________________________
-//
-// Local Variables:
-//   mode: C++
-// End:
-//
-// EOF
-//
-
-  
-      
index fddd3536d95f386c24a40892283e9c2d597c6eab..6f516a10467b24665f902b0ac55376beef6631e5 100644 (file)
 //      +----------------+
 //
 #include <AliLog.h>            // ALILOG_H
-#include "AliFMD.h"            // ALIFMD_H
+#include "AliFMDParameters.h"  // ALIFMDPARAMETERS_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIT_H
 #include "AliFMDRawStream.h"   // ALIFMDRAWSTREAM_H 
 #include "AliRawReader.h"      // ALIRAWREADER_H 
 #include "AliFMDRawReader.h"   // ALIFMDRAWREADER_H 
 #include <TArrayI.h>           // ROOT_TArrayI
-// #include <TClonesArray.h>   // ROOT_TClonesArray
+#include <TTree.h>             // ROOT_TTree
+#include <TClonesArray.h>      // ROOT_TClonesArray
 
 //____________________________________________________________________
 ClassImp(AliFMDRawReader)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
-AliFMDRawReader::AliFMDRawReader(AliFMD* fmd, AliRawReader* reader
+AliFMDRawReader::AliFMDRawReader(AliRawReader* reader, TTree* tree
   : TTask("FMDRawReader", "Reader of Raw ADC values from the FMD"),
-    fFMD(fmd),
-    fReader(reader)
+    fTree(tree),
+    fReader(reader), 
+    fSampleRate(1)
 {
   // Default CTOR
-  SetSampleRate(fmd->GetSampleRate());
+  AliFMDParameters* pars = AliFMDParameters::Instance();
+  fSampleRate = pars->GetSampleRate();
 }
 
 
@@ -75,11 +81,15 @@ AliFMDRawReader::Exec(Option_t*)
     return;
   }
 
+  Int_t n = 0;
+  TClonesArray* array = new TClonesArray("AliFMDDigit");
+  fTree->Branch("FMD", &array);
+
   // Use AliAltroRawStream to read the ALTRO format.  No need to
   // reinvent the wheel :-) 
   AliFMDRawStream input(fReader, fSampleRate);
   // Select FMD DDL's 
-  fReader->Select(AliFMD::kBaseDDL >> 8);
+  fReader->Select(AliFMDParameters::kBaseDDL >> 8);
   
   Int_t    oldDDL      = -1;
   Int_t    count       = 0;
@@ -109,11 +119,12 @@ AliFMDRawReader::Exec(Option_t*)
                          input.PrevSector() , input.PrevStrip(),
                          detector , input.Ring(), input.Sector(), 
                          input.Strip()));
-       fFMD->AddDigit(oldDetector, 
-                      input.PrevRing(), 
-                      input.PrevSector(), 
-                      input.PrevStrip(), 
-                      counts[0], counts[1], counts[2]);
+       new ((*array)[n]) AliFMDDigit(oldDetector, 
+                                     input.PrevRing(), 
+                                     input.PrevSector(), 
+                                     input.PrevStrip(), 
+                                     counts[0], counts[1], counts[2]);
+       n++;
 #if 0
        AliFMDDigit* digit = 
          static_cast<AliFMDDigit*>(fFMD->Digits()->
@@ -138,9 +149,9 @@ AliFMDRawReader::Exec(Option_t*)
        oldDDL      = ddl;
        // Check that we're processing a FMD detector 
        Int_t detId = fReader->GetDetectorID();
-       if (detId != (AliFMD::kBaseDDL >> 8)) {
+       if (detId != (AliFMDParameters::kBaseDDL >> 8)) {
          Error("ReadAdcs", "Detector ID %d != %d",
-               detId, (AliFMD::kBaseDDL >> 8));
+               detId, (AliFMDParameters::kBaseDDL >> 8));
          break;
        }
        // Figure out what detector we're deling with 
@@ -166,6 +177,7 @@ AliFMDRawReader::Exec(Option_t*)
                      input.Strip(), input.Count()));
     oldDetector = detector;
   }
+  fTree->Fill();
   return;
 
 }
index 60ad7d88e2e6cbb38da21d2f7bd5936fb68e7d5f..13ac06824974ce5145188b2f5cd89fd8b1956e00 100644 (file)
 
 //____________________________________________________________________
 class AliRawReader;
-class AliFMD;
+class TTree;
 
 
 //____________________________________________________________________
 class AliFMDRawReader : public TTask 
 {
 public:
-  AliFMDRawReader(AliFMD* fmd, AliRawReader* reader);
+  AliFMDRawReader(AliRawReader* reader, TTree* array);
 
   virtual void Exec(Option_t* option="");
-  void SetSampleRate(UShort_t sampleRate=1) { fSampleRate = sampleRate; }
 protected:
-  AliFMD*       fFMD;        //! Pointer to detector description 
+  TTree*        fTree;       //! Pointer to tree to read into 
   AliRawReader* fReader;     //! Pointer to raw reader 
   UShort_t      fSampleRate; // The sample rate (if 0, inferred from data)
   ClassDef(AliFMDRawReader, 0) // Read FMD raw data into a cache 
index 1bf8c5c0a5abad0efd7ccf13fc715f910b6a046f..8cfcbfd225a5d0a98c974a4f0b59fd43be0607eb 100644 (file)
@@ -30,6 +30,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDRawStream)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDRawStream::AliFMDRawStream(AliRawReader* reader, UShort_t sampleRate) 
index 89c20e782f0f4887a709958e9de34e9b234d739f..f03e8df5101a6f60ad5d1cdca960578f44cc656d 100644 (file)
@@ -37,6 +37,7 @@
 #include <AliLoader.h>         // ALILOADER_H
 #include <AliAltroBuffer.h>     // ALIALTROBUFFER_H
 #include "AliFMD.h"            // ALIFMD_H
+#include "AliFMDParameters.h"  // ALIFMDPARAMETERS_H
 #include "AliFMDDigit.h"       // ALIFMDDIGIT_H
 #include "AliFMDRawWriter.h"   // ALIFMDRAWREADER_H 
 #include <TArrayI.h>           // ROOT_TArrayI
 
 //____________________________________________________________________
 ClassImp(AliFMDRawWriter)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDRawWriter::AliFMDRawWriter(AliFMD* fmd) 
   : TTask("FMDRawWriter", "Writer of Raw ADC values from the FMD"),
     fFMD(fmd)
 {
-  SetSampleRate();
-  SetThreshold();
-  SetChannelsPerAltro();
+  AliFMDParameters* pars = AliFMDParameters::Instance();
+  fSampleRate            = pars->GetSampleRate();
+  fThreshold             = pars->GetZeroSuppression();
+  fChannelsPerAltro      = pars->GetChannelsPerAltro();
 }
 
 
@@ -175,15 +180,15 @@ AliFMDRawWriter::Exec(Option_t*)
       UShort_t sector = digit->Sector();
       UShort_t strip  = digit->Strip();
       if (det != prevDetector) {
-       AliDebug(10, Form("FMD: New DDL, was %d, now %d",
-                         AliFMD::kBaseDDL + prevDetector - 1,
-                         AliFMD::kBaseDDL + det - 1));
+       AliDebug(15, Form("FMD: New DDL, was %d, now %d",
+                         AliFMDParameters::kBaseDDL + prevDetector - 1,
+                         AliFMDParameters::kBaseDDL + det - 1));
        // If an altro exists, delete the object, flushing the data to
        // disk, and closing the file. 
        if (altro) { 
          // When the first argument is false, we write the real
          // header. 
-         AliDebug(10, Form("New altro: Write channel at %d Strip: %d "
+         AliDebug(15, Form("New altro: Write channel at %d Strip: %d "
                            "Sector: %d  Ring: %d", 
                            i, startStrip, prevSector, prevRing));
          // TPC to FMD translations 
@@ -203,12 +208,12 @@ AliFMDRawWriter::Exec(Option_t*)
 
        prevDetector = det;
        // Need to open a new DDL! 
-       Int_t ddlId = AliFMD::kBaseDDL + det - 1;
+       Int_t ddlId = AliFMDParameters::kBaseDDL + det - 1;
        TString filename(Form("%s_%d.ddl", fFMD->GetName(),  ddlId));
 
-       AliDebug(10, Form("New altro buffer with DDL file %s", 
+       AliDebug(15, Form("New altro buffer with DDL file %s", 
                          filename.Data()));
-       AliDebug(10, Form("New altro at %d", i));
+       AliDebug(15, Form("New altro at %d", i));
        // Create a new altro buffer - a `1' as the second argument
        // means `write mode' 
        altro = new AliAltroBuffer(filename.Data(), 1);
@@ -235,11 +240,11 @@ AliFMDRawWriter::Exec(Option_t*)
               || digit->Ring() != prevRing 
               || digit->Sector() != prevSector) {
        // Force a new Altro channel
-       AliDebug(10, Form("Flushing channel to disk because %s",
+       AliDebug(15, Form("Flushing channel to disk because %s",
                          (offset == fChannelsPerAltro ? "channel is full" :
                           (ring != prevRing ? "new ring up" :
                            "new sector up"))));
-       AliDebug(10, Form("New Channel: Write channel at %d Strip: %d "
+       AliDebug(15, Form("New Channel: Write channel at %d Strip: %d "
                          "Sector: %d  Ring: %d", 
                          i, startStrip, prevSector, prevRing));
        WriteChannel(altro, startStrip, prevSector, prevRing, channel);
index 7a841a08617ba4aa20533b1ef0c5e0830fde5c1d..94a2a0e83ed707aa2aa22375a7f6babc6233f3f1 100644 (file)
@@ -29,9 +29,6 @@ public:
   AliFMDRawWriter(AliFMD* fmd);
 
   virtual void Exec(Option_t* option="");
-  void SetSampleRate(UShort_t sampleRate=1) { fSampleRate = sampleRate; }
-  void SetChannelsPerAltro(UShort_t size=128) { fChannelsPerAltro = size; }
-  void SetThreshold(UShort_t t=0) { fThreshold = t; }
 protected:
   virtual void WriteChannel(AliAltroBuffer* altro, 
                            UShort_t strip, UShort_t sector, Char_t ring, 
index 5302ce9492288b44a12f5bf22bb857c96d2ff69e..c9dec1691fed377913ca2b02c97b952e31d4cc51 100644 (file)
 #include <AliHeader.h>                     // ALIHEADER_H
 #include <AliRawReader.h>                  // ALIRAWREADER_H
 #include <AliGenEventHeader.h>             // ALIGENEVENTHEADER_H
-#include "AliFMD.h"                        // ALIFMD_H
+#include "AliFMD.h"                       // ALIFMD_H
+#include "AliFMDGeometry.h"                // ALIFMDGEOMETRY_H
+#include "AliFMDParameters.h"              // ALIFMDPARAMETERS_H
+#include "AliFMDDetector.h"                // ALIFMDDETECTOR_H
+#include "AliFMDRing.h"                    // ALIFMDRING_H
 #include "AliFMDDigit.h"                   // ALIFMDDIGIT_H
 #include "AliFMDReconstructor.h"           // ALIFMDRECONSTRUCTOR_H
 #include "AliFMDRawStream.h"               // ALIFMDRAWSTREAM_H
 
 //____________________________________________________________________
 ClassImp(AliFMDReconstructor)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDReconstructor::AliFMDReconstructor() 
@@ -114,11 +121,11 @@ AliFMDReconstructor::AliFMDReconstructor()
     fPedestalFactor(0)
 {
   // Make a new FMD reconstructor object - default CTOR.
-  SetPedestal();
-
-  fFMDLoader = 0;
-  fRunLoader = 0;
-  fFMD       = 0;
+  AliFMDParameters* pars = AliFMDParameters::Instance();
+  fPedestal       = pars->GetPedestal();
+  fPedestalWidth  = pars->GetPedestalWidth();
+  fPedestalFactor = pars->GetPedestalFactor();
+  
   fAlgorithms.Add(new AliFMDMultNaiive);
   fAlgorithms.Add(new AliFMDMultPoisson);
 }
@@ -132,11 +139,10 @@ AliFMDReconstructor::AliFMDReconstructor(const AliFMDReconstructor& other)
     fPedestalFactor(0)
 {
   // Copy constructor 
-  SetPedestal(other.fPedestal, other.fPedestalWidth, other.fPedestalFactor);
+  fPedestal       = other.fPedestal;
+  fPedestalWidth  = other.fPedestalWidth;
+  fPedestalFactor = other.fPedestalFactor;
 
-  fFMDLoader = other.fFMDLoader;
-  fRunLoader = other.fRunLoader;
-  fFMD       = other.fFMD;
   
   fAlgorithms.Delete();
   TIter next(&(other.fAlgorithms));
@@ -152,11 +158,9 @@ AliFMDReconstructor&
 AliFMDReconstructor::operator=(const AliFMDReconstructor& other) 
 {
   // Assignment operator
-  SetPedestal(other.fPedestal, other.fPedestalWidth, other.fPedestalFactor);
-
-  fFMDLoader = other.fFMDLoader;
-  fRunLoader = other.fRunLoader;
-  fFMD       = other.fFMD;
+  fPedestal       = other.fPedestal;
+  fPedestalWidth  = other.fPedestalWidth;
+  fPedestalFactor = other.fPedestalFactor;
 
   fAlgorithms.Delete();
   TIter next(&(other.fAlgorithms));
@@ -174,241 +178,95 @@ AliFMDReconstructor::~AliFMDReconstructor()
   // Destructor 
   fAlgorithms.Delete();
 }
-  
-//____________________________________________________________________
-void 
-AliFMDReconstructor::SetPedestal(Float_t mean, Float_t width, Float_t factor) 
-{
-  // Set the pedestal, and pedestal width 
-  fPedestal       = mean;
-  fPedestalWidth  = width;
-  fPedestalFactor = factor;
-}
 
 //____________________________________________________________________
 void 
-AliFMDReconstructor::Reconstruct(AliRunLoader* runLoader, 
-                                AliRawReader* rawReader) const
-{ 
-  // Collects all digits in the same active volume into number of
-  // particles
-  //
-  // Reconstruct number of particles in given group of pads for given
-  // FMDvolume determined by numberOfVolume,
-  // numberOfMinSector, numberOfMaxSector, numberOfMinRing,
-  // numberOgMaxRing 
-  //
-  // The reconstruction method is choosen based on the number of empty
-  // strips. 
-  if (!runLoader) {
-    Error("Exec","Run Loader loader is NULL - Session not opened");
+AliFMDReconstructor::Init(AliRunLoader* runLoader) 
+{
+  // Initialize the reconstructor 
+  AliDebug(1, Form("Init called with runloader 0x%x", runLoader));
+  fCurrentVertex = 0;
+  if (!runLoader) { 
+    Warning("Init", "No run loader");
     return;
   }
-  fRunLoader = runLoader;
-  fFMDLoader = runLoader->GetLoader("FMDLoader");
-  if (!fFMDLoader) 
-    Fatal("AliFMDReconstructor","Can not find FMD (loader) "
-         "in specified event");
-
-  // Get the AliRun object
-  if (!fRunLoader->GetAliRun()) fRunLoader->LoadgAlice();
-  
-  // Get the AliFMD object
-  fFMD = static_cast<AliFMD*>(fRunLoader->GetAliRun()->GetDetector("FMD"));
-  if (!fFMD) {
-    AliError("Can not get FMD from gAlice");
+  AliHeader* header = runLoader->GetHeader();
+  if (!header) {
+    Warning("Init", "No header");
     return;
   }
-  fFMDLoader->LoadRecPoints("RECREATE");
-
-  if (!fRunLoader->TreeE())     fRunLoader->LoadHeader();
-
-  TIter next(&fAlgorithms);
-  AliFMDMultAlgorithm* algorithm = 0;
-  while ((algorithm = static_cast<AliFMDMultAlgorithm*>(next()))) 
-    algorithm->PreRun(fFMD);
-
-  if (rawReader) {
-    Int_t event = 0;
-    while (rawReader->NextEvent()) {
-      ProcessEvent(event, rawReader);
-      event++;
-    }
-  }
-  else {
-    Int_t nEvents= Int_t(fRunLoader->TreeE()->GetEntries()); 
-    for(Int_t event = 0; event < nEvents; event++) 
-      ProcessEvent(event, 0);
+  AliGenEventHeader* eventHeader = header->GenEventHeader();
+  if (!eventHeader) {
+    Warning("Init", "no event header");
+    return;
   }
-
-  next.Reset();
-  algorithm = 0;
-  while ((algorithm = static_cast<AliFMDMultAlgorithm*>(next()))) 
-    algorithm->PostRun();
-
-  fFMDLoader->UnloadRecPoints();
-  fFMDLoader = 0;
-  fRunLoader = 0;
-  fFMD       = 0;
+  TArrayF vtx;
+  eventHeader->PrimaryVertex(vtx);
+  fCurrentVertex = vtx[2];
+  AliDebug(1, Form("Primary vertex Z coordinate for event # %d/%d is %f", 
+                  header->GetRun(), header->GetEvent(), fCurrentVertex));
 }
 
 //____________________________________________________________________
 void 
-AliFMDReconstructor::Reconstruct(AliRunLoader* runLoader) const
-{ 
-  // Collects all digits in the same active volume into number of
-  // particles
-  //
-  // Reconstruct number of particles in given group of pads for given
-  // FMDvolume determined by numberOfVolume,
-  // numberOfMinSector, numberOfMaxSector, numberOfMinRing,
-  // numberOgMaxRing 
-  //
-  // The reconstruction method is choosen based on the number of empty
-  // strips. 
-  Reconstruct(runLoader, 0);
+AliFMDReconstructor::ConvertDigits(AliRawReader* reader, 
+                                  TTree* digitsTree) const
+{
+  // Convert Raw digits to AliFMDDigit's in a tree 
+  AliFMDRawReader rawRead(reader, digitsTree);
+  // rawRead.SetSampleRate(fFMD->GetSampleRate());
+  rawRead.Exec();
 }
 
-
 //____________________________________________________________________
 void 
-AliFMDReconstructor::ProcessEvent(Int_t event
-                                 AliRawReader* reader) const
+AliFMDReconstructor::Reconstruct(TTree* digitsTree
+                                TTree* clusterTree) const 
 {
-  // Process one event read from either a clones array or from a a raw
-  // data reader. 
-  fRunLoader->GetEvent(event) ;
-  //event z-vertex for correction eta-rad dependence      
-  AliHeader *header            = fRunLoader->GetHeader();
-  if (!header) Warning("ProcessEvent", "no AliHeader found!");
-  AliGenEventHeader* genHeader = (header ? header->GenEventHeader() : 0);
-
-  // Get the Z--coordinate from the event header 
-  TArrayF o(3); 
-  if (genHeader) genHeader->PrimaryVertex(o);
-  else           Warning("ProcessEvent", "No GenEventHeader Found");
-  fCurrentVertex = o.At(2);
-
-  // If the recontruction tree isn't loaded, load it
-  if(fFMDLoader->TreeR()==0) fFMDLoader->MakeTree("R");
-  
-  // Load or recreate the digits 
-  if (fFMDLoader->LoadDigits((reader ? "UPDATE" : "READ"))) {
-    if (!reader) {
-      Error("Exec","Error occured while loading digits. Exiting.");
-      return;
-    }
-  }
-  // Get the digits tree 
-  TTree* digitTree = fFMDLoader->TreeD();
-  if (!digitTree) { 
-    if (!reader) {
-      Error("Exec","Can not get Tree with Digits. "
-           "Nothing to reconstruct - Exiting");
-      return;
-    }
-    fFMDLoader->MakeTree("D");
-    digitTree = fFMDLoader->TreeD();
-    
-  }
+  // Reconstruct event from digits in tree 
   // Get the FMD branch holding the digits. 
-  TBranch *digitBranch = digitTree->GetBranch("FMD");
-  TClonesArray* digits = fFMD->Digits();
+  AliDebug(1, "Reconstructing from digits in a tree");
+  
+  TBranch *digitBranch = digitsTree->GetBranch("FMD");
+  TClonesArray* digits = new TClonesArray("AliFMDDigit");
   if (!digitBranch) {
-    if (!reader) {
-      Error("Exec", "No digit branch for the FMD found");
-      return;
-    }
-    fFMD->MakeBranchInTree(digitTree, fFMD->GetName(), &(digits), 4000, 0);
+    Error("Exec", "No digit branch for the FMD found");
+    return;
   }
-  if (!reader) digitBranch->SetAddress(&digits);
+  digitBranch->SetAddress(&digits);
 
-  if  (reader) {
-    AliFMDRawReader rawRead(fFMD, reader);
-    AliDebug(10, Form("Making raw reader with sample rate: %d",
-                     fFMD->GetSampleRate()));
-    rawRead.SetSampleRate(fFMD->GetSampleRate());
-    rawRead.Exec();
-  }
-  else {
-    // Read the ADC values from a clones array. 
-    AliDebug(10, "Reading ADCs from Digits array");
-    // read Digits, and reconstruct the particles
-    if (!fFMDLoader->TreeD()->GetEvent(0)) return;
-  }
-  
   TIter next(&fAlgorithms);
   AliFMDMultAlgorithm* algorithm = 0;
   while ((algorithm = static_cast<AliFMDMultAlgorithm*>(next()))) 
-    algorithm->PreEvent(fFMDLoader->TreeR(), fCurrentVertex);
-
+    algorithm->PreEvent(clusterTree, fCurrentVertex);
+  digitBranch->GetEntry(0);
+  
   ProcessDigits(digits);
 
   next.Reset();
   algorithm = 0;
   while ((algorithm = static_cast<AliFMDMultAlgorithm*>(next()))) 
     algorithm->PostEvent();
-  
-  if (reader) {
-    digitTree->Fill();
-    fFMDLoader->WriteDigits("OVERWRITE");
-  }
-  fFMDLoader->UnloadDigits();
-  fFMDLoader->TreeR()->Reset();
-  fFMDLoader->TreeR()->Fill(); 
-  fFMDLoader->WriteRecPoints("OVERWRITE");
-}
-
-//____________________________________________________________________
-UShort_t
-AliFMDReconstructor::SubtractPedestal(AliFMDDigit* digit) const
-{
-  // Member function to subtract the pedestal from a digit
-  // This implementation does nothing, but a derived class could over
-  // load this to subtract a pedestal that was given in a database or
-  // something like that. 
-
-  Int_t counts = 0;
-  Float_t ped = fPedestal + fPedestalFactor * fPedestalWidth;
-  if (digit->Count3() > 0)      counts = digit->Count3();
-  else if (digit->Count2() > 0) counts = digit->Count2();
-  else                          counts = digit->Count1();
-  counts = TMath::Max(Int_t(counts - ped), 0);
-  return  UShort_t(counts);
+  clusterTree->Fill();
 }
-
 //____________________________________________________________________
 void
 AliFMDReconstructor::ProcessDigits(TClonesArray* digits) const
 {
   Int_t nDigits = digits->GetEntries();
+  AliDebug(1, Form("Got %d digits", nDigits));
   for (Int_t i = 0; i < nDigits; i++) {
     AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
-    AliFMDSubDetector* subDetector = 0;
-    switch (digit->Detector()) {
-    case 1: subDetector = fFMD->GetFMD1(); break;
-    case 2: subDetector = fFMD->GetFMD2(); break;
-    case 3: subDetector = fFMD->GetFMD3(); break;
-    }
+    AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+    AliFMDDetector* subDetector = fmd->GetDetector(digit->Detector());
     if (!subDetector) { 
       Warning("ProcessDigits", "Unknown detector: FMD%d" , digit->Detector());
       continue;
     }
     
-    AliFMDRing* ring  = 0;
-    Float_t     ringZ = 0;
-    switch(digit->Ring()) {
-    case 'i':
-    case 'I':  
-      ring  = subDetector->GetInner(); 
-      ringZ = subDetector->GetInnerZ();
-      break;
-    case 'o':
-    case 'O':  
-      ring  = subDetector->GetOuter(); 
-      ringZ = subDetector->GetOuterZ();
-      break;
-    }
+    AliFMDRing* ring  = subDetector->GetRing(digit->Ring());
+    Float_t     ringZ = subDetector->GetRingZ(digit->Ring());
     if (!ring) {
       Warning("ProcessDigits", "Unknown ring: FMD%d%c", digit->Detector(), 
              digit->Ring());
@@ -432,11 +290,29 @@ AliFMDReconstructor::ProcessDigits(TClonesArray* digits) const
   }
 }
       
+//____________________________________________________________________
+UShort_t
+AliFMDReconstructor::SubtractPedestal(AliFMDDigit* digit) const
+{
+  // Member function to subtract the pedestal from a digit
+  // This implementation does nothing, but a derived class could over
+  // load this to subtract a pedestal that was given in a database or
+  // something like that. 
+
+  Int_t counts = 0;
+  Float_t ped = fPedestal + fPedestalFactor * fPedestalWidth;
+  if (digit->Count3() > 0)      counts = digit->Count3();
+  else if (digit->Count2() > 0) counts = digit->Count2();
+  else                          counts = digit->Count1();
+  counts = TMath::Max(Int_t(counts - ped), 0);
+  return  UShort_t(counts);
+}
+
 //____________________________________________________________________
 void 
-AliFMDReconstructor::FillESD(AliRunLoader* /*fRunLoader*/, 
-                            AliESD* /*esd*/) const
+AliFMDReconstructor::FillESD(TTree*  /* digitsTree */, 
+                            TTree*  /* clusterTree */,
+                            AliESD* /* esd*/) const
 {
   // nothing to be done
 
index 0555df2e2b791d95b0daf386fd401d005aa24794..ddb88b5437418ab20ae3b947df070aa246a1d02e 100644 (file)
 #endif
 
 //____________________________________________________________________
+class TTree;
 class TClonesArray;
-class AliFMD;
-class AliLoader;
-class AliRunLoader;
 class AliFMDDigit;
 class AliRawReader;
+class AliRunLoader;
 
 //____________________________________________________________________
 class AliFMDReconstructor: public AliReconstructor 
@@ -53,22 +52,17 @@ public:
   virtual ~AliFMDReconstructor();
   AliFMDReconstructor& operator=(const AliFMDReconstructor& other);
 
-  void         SetPedestal(Float_t mean=10, Float_t width=1, Float_t f=3);
+  virtual void   Init(AliRunLoader* runLoader);
+  virtual Bool_t HasDigitConversion() const { return kTRUE; }
+  virtual void   ConvertDigits(AliRawReader* reader, TTree* digitsTree) const;
+  virtual Bool_t HasLocalReconstruction() const { return kTRUE; }
+  virtual void   Reconstruct(TTree* digitsTree, TTree* clusterTree) const;
+  virtual void   FillESD(TTree* digitsTree, TTree* clusterTree, 
+                        AliESD* esd) const;
      
-  virtual void Reconstruct(AliRunLoader* runLoader) const;
-  virtual void Reconstruct(AliRunLoader* runLoader,  
-                          AliRawReader* rawReader) const;
-  virtual void FillESD(AliRunLoader* runLoader, AliESD* esd) const;
-  
 protected:
-  virtual void     ProcessEvent(Int_t event, 
-                               AliRawReader* rawReader) const;
   virtual void     ProcessDigits(TClonesArray* digits) const;
   virtual UShort_t SubtractPedestal(AliFMDDigit* digit) const;
-
-  mutable AliRunLoader* fRunLoader;  //! Run loader 
-  mutable AliLoader*    fFMDLoader;  //! FMD specific loader 
-  mutable AliFMD*       fFMD;        //! Pointer to FMD manager 
   
   TObjArray            fAlgorithms;    // Array of algorithms
   Float_t               fPedestal;      // Pedestal to subtract
index 3069216e3d78ea07851cae2a3da8ee649887a6c9..023ac683f686e5f385954d2b439e02d774863ad0 100644 (file)
 //__________________________________________________________________
 //
 // Utility class to help implement collection of FMD modules into
-// rings.  This is used by AliFMDSubDetector and AliFMD.  
+// rings.  This is used by AliFMDDetector and AliFMDGeometry.  
 //
-// The AliFMD object owns the AliFMDRing objects, and the
-// AliFMDSubDetector objects reference these.  That is, the AliFMDRing
-// objects are share amoung the AliFMDSubDetector objects.
+// The AliFMDGeometry object owns the AliFMDRing objects, and the
+// AliFMDDetector objects reference these.  That is, the AliFMDRing
+// objects are share amoung the AliFMDDetector objects.
 //
 // Latest changes by Christian Holm Christensen
 //
 
-#include <math.h>               // fmod
 #include <AliLog.h>            // ALILOG_H
 #include "AliFMDRing.h"                // ALIFMDRING_H
-#include "AliFMD.h"            // ALIFMD_H
 #include <TMath.h>             // ROOT_TMath
-#include <TH2.h>               // ROOT_TH2
-#include <TVirtualMC.h>                // ROOT_TVirtualMC
 #include <TVector2.h>          // ROOT_TVector2
-#include <TBrowser.h>          // ROOT_TBrowser
-#include <TString.h>           // ROOT_TString
-#include <TArc.h>              // ROOT_TArc
-#include <TObjArray.h>         // ROOT_TObjArray
-#include <TXTRU.h>             // ROOT_TXTRU
-#include <TNode.h>             // ROOT_TNode
-#include <TRotMatrix.h>                // ROOT_TRotMatrix
-#include <TList.h>             // ROOT_TList
 
-const Char_t* AliFMDRing::fgkRingFormat         = "F%cRG";
-const Char_t* AliFMDRing::fgkVirtualFormat      = "F%cV%c";
-const Char_t* AliFMDRing::fgkActiveFormat       = "F%cAC";
-const Char_t* AliFMDRing::fgkSectorFormat       = "F%cAP";
-const Char_t* AliFMDRing::fgkStripFormat        = "F%cAR";
-const Char_t* AliFMDRing::fgkPrintboardFormat   = "F%cP%c";
-
-
-//____________________________________________________________________
-ClassImp(AliFMDRing)
-
-//____________________________________________________________________
-AliFMDRing::AliFMDRing(Char_t id, Bool_t detailed) 
-  : fId(id), 
-    fDetailed(detailed),
-    fActiveId(0),
-    fPrintboardBottomId(0),
-    fPrintboardTopId(0),
-    fRingId(0),
-    fSectionId(0),
-    fStripId(0),
-    fVirtualBackId(0),
-    fVirtualFrontId(0),
-    fBondingWidth(0),
-    fWaferRadius(0), 
-    fSiThickness(0),
-    fLowR(0), 
-    fHighR(0), 
-    fTheta(0), 
-    fNStrips(0), 
-    fRingDepth(0),
-    fLegRadius(0),
-    fLegLength(0),
-    fLegOffset(0),
-    fModuleSpacing(0),
-    fPrintboardThickness(0),
-    fShape(0),
-    fRotMatricies(0)
-{
-  // Construct a alifmdring. 
-  // 
-  //     id            Id of the ring (either 'i' or 'o').
-  //     detailed       Whether the strips are made or not.
-  // 
-}
-
-//____________________________________________________________________
-AliFMDRing::AliFMDRing(const AliFMDRing& other) 
-  : TObject(other),
-    fId(other.fId), 
-    fDetailed(other.fDetailed),
-    fActiveId(other.fActiveId),
-    fPrintboardBottomId(other.fPrintboardBottomId),
-    fPrintboardTopId(other.fPrintboardTopId),
-    fRingId(other.fRingId),
-    fSectionId(other.fSectionId),
-    fStripId(other.fStripId),
-    fVirtualBackId(other.fVirtualBackId),
-    fVirtualFrontId(other.fVirtualFrontId),
-    fBondingWidth(other.fBondingWidth),
-    fWaferRadius(other.fWaferRadius), 
-    fSiThickness(other.fSiThickness),
-    fLowR(other.fLowR), 
-    fHighR(other.fHighR), 
-    fTheta(other.fTheta), 
-    fNStrips(other.fNStrips), 
-    fRingDepth(other.fRingDepth),
-    fLegRadius(other.fLegRadius),
-    fLegLength(other.fLegLength),
-    fLegOffset(other.fLegOffset),
-    fModuleSpacing(other.fModuleSpacing),
-    fPrintboardThickness(other.fPrintboardThickness),
-    fRotations(other.fRotations),
-    fShape(other.fShape), 
-    fRotMatricies(other.fRotMatricies)
-{
-  // Copy constructor of a AliFMDRing. 
-}
-
-//____________________________________________________________________
-AliFMDRing&
-AliFMDRing::operator=(const AliFMDRing& other) 
-{
-  // Assignment operator 
-  // 
-  fId                  = other.fId; 
-  fDetailed            = other.fDetailed;
-  fActiveId            = other.fActiveId;
-  fPrintboardBottomId  = other.fPrintboardBottomId;
-  fPrintboardTopId     = other.fPrintboardTopId;
-  fRingId              = other.fRingId;
-  fSectionId           = other.fSectionId;
-  fStripId             = other.fStripId;
-  fVirtualBackId       = other.fVirtualBackId;
-  fVirtualFrontId      = other.fVirtualFrontId;
-  fBondingWidth                = other.fBondingWidth;
-  fWaferRadius         = other.fWaferRadius; 
-  fSiThickness         = other.fSiThickness;
-  fLowR                        = other.fLowR; 
-  fHighR               = other.fHighR; 
-  fTheta               = other.fTheta; 
-  fNStrips             = other.fNStrips; 
-  fRingDepth           = other.fRingDepth;
-  fLegRadius           = other.fLegRadius;
-  fLegLength           = other.fLegLength;
-  fLegOffset           = other.fLegOffset;
-  fModuleSpacing       = other.fModuleSpacing;
-  fPrintboardThickness = other.fPrintboardThickness;
-  fRotations            = other.fRotations;
-  if (other.fShape)  {
-    if (other.fShape->IsA() == TXTRU::Class()) 
-      ((TXTRU*)other.fShape)->Copy(*fShape);
-    else 
-      fShape = 0;
-  }
-  if (other.fRotMatricies) {
-    Int_t n = other.fRotMatricies->GetEntries();
-    if (!fRotMatricies) fRotMatricies = new TObjArray(n);
-    else                fRotMatricies->Expand(n);
-    TIter next(other.fRotMatricies);
-    TObject* o = 0;
-    while ((o = next())) fRotMatricies->Add(o);
-  }
-  return *this;
-}
-
-  
-
-//____________________________________________________________________
-void 
-AliFMDRing::Init() 
-{
-  // Initialize the ring object.
-  // DebugGuard guard("AliFMDRing::Init");
-  AliDebug(30, Form("\tInitializing ring %c", fId));
-  fPolygon.Clear();
-  SetupCoordinates();  
-}
-
-//____________________________________________________________________
-AliFMDRing::~AliFMDRing() 
-{
-  // Destructor - deletes shape and rotation matricies 
-  AliDebug(30, Form("\tDestructing ring %c", fId));
-  if (fShape) delete fShape;
-  if (fRotMatricies) delete fRotMatricies;
-}
-
-
-//____________________________________________________________________
-void 
-AliFMDRing::Browse(TBrowser* /* b */)
-{
-  // DebugGuard guard("AliFMDRing::Browse");
-  AliDebug(30, Form("\tBrowsing ring %c", fId));
-}
-
-  
-//____________________________________________________________________
-void 
-AliFMDRing::SetupCoordinates() 
-{
-  // Calculates the parameters of the polygon shape. 
-  // 
-  //
-
-  // Get out immediately if we have already done all this 
-  if (fPolygon.GetNVerticies() > 1) return;
-  AliDebug(10, Form("\tSetting up the coordinates for ring %c", fId));
-
-  double tanTheta  = TMath::Tan(fTheta * TMath::Pi() / 180.);
-  double tanTheta2 = TMath::Power(tanTheta,2);
-  double r2         = TMath::Power(fWaferRadius,2);
-  double yA        = tanTheta * fLowR;
-  double lr2        = TMath::Power(fLowR, 2);
-  double hr2        = TMath::Power(fHighR,2);
-  double xD        = fLowR + TMath::Sqrt(r2 - tanTheta2 * lr2);
-  double xD2       = TMath::Power(xD,2);
-  //double xD_2      = fLowR - TMath::Sqrt(r2 - tanTheta2 * lr2);
-  double yB        = TMath::Sqrt(r2 - hr2 + 2 * fHighR * xD - xD2);
-  double xC        = ((xD + TMath::Sqrt(-tanTheta2 * xD2 + r2 
-                                       + r2 * tanTheta2)) 
-                      / (1 + tanTheta2));
-  double yC        = tanTheta * xC;
-
-  fPolygon.AddVertex(fLowR,  -yA);
-  fPolygon.AddVertex(xC,     -yC);
-  fPolygon.AddVertex(fHighR, -yB);
-  fPolygon.AddVertex(fHighR,  yB);
-  fPolygon.AddVertex(xC,      yC);
-  fPolygon.AddVertex(fLowR,   yA);
-}
+//====================================================================
+ClassImp(AliFMDRing);
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
-bool
-AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const
+AliFMDRing::AliFMDRing(Char_t id) 
+  : TNamed(Form("FMD%c", id), "Forward multiplicity ring"), 
+    fId(id), 
+    fVerticies(0)
 {
-  // Checks if a point (x,y) is inside the module with number moduleNo 
-  //
-  // DebugGuard guard("AliFMDRing::IsWithin");
-  AliDebug(20, Form("\tChecking wether the hit at (%lf,%lf) in module %d "
-                   "is within this ring (%c)", x, y, moduleNo, fId));
-  bool   ret            = false;
-  double r2             = x * x + y * y;
-  if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) {
-    // double point_angle    = TMath::ATan2(y, x);
-    // int    n_modules      = 360 / Int_t(fTheta * 2);
-    double m_angle        = (.5 + moduleNo) * 2 * fTheta;
-    double m_radians      = TMath::Pi() * m_angle / 180.;
-    
-    // Rotate the point.
-    double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians);
-    double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians);
+  SetBondingWidth();
+  SetWaferRadius();
+  SetSiThickness();
+  SetLegRadius();
+  SetLegLength();
+  SetLegOffset();
+  SetModuleSpacing();
+  SetPrintboardThickness();
   
-    ret = fPolygon.Contains(xr,yr);
+  if (fId == 'I' || fId == 'i') {
+    SetLowR(4.3);
+    SetHighR(17.2);
+    SetTheta(36/2);
+    SetNStrips(512);
+  }
+  else if (fId == 'O' || fId == 'o') {
+    SetLowR(15.6);
+    SetHighR(28.0);
+    SetTheta(18/2);
+    SetNStrips(256);
   }
-  return ret;
 }
 
-
-
-
 //____________________________________________________________________
 void
-AliFMDRing::Draw(Option_t* option) const
+AliFMDRing::Init()
 {
-  // Draw a the shape of the ring into a 2D histogram.  Useful for
-  // superimposing the actual shape of the ring onto a scatter plot of
-  // hits in the detector. 
-  // 
-  // DebugGuard guard("AliFMDRing::Draw");
-  AliDebug(20, Form("\tDrawing ring %c", fId));
-  // The unrotated coordinates of the polygon verticies
-  if (fPolygon.GetNVerticies() < 1) return;
-  
-  TVector2 v[6];
-  for (size_t i = 0; i < fPolygon.GetNVerticies(); i++) 
-    v[i] = fPolygon.GetVertex(i);
+  Double_t tanTheta  = TMath::Tan(fTheta * TMath::Pi() / 180.);
+  Double_t tanTheta2 = TMath::Power(tanTheta,2);
+  Double_t r2        = TMath::Power(fWaferRadius,2);
+  Double_t yA        = tanTheta * fLowR;
+  Double_t lr2       = TMath::Power(fLowR, 2);
+  Double_t hr2       = TMath::Power(fHighR,2);
+  Double_t xD        = fLowR + TMath::Sqrt(r2 - tanTheta2 * lr2);
+  Double_t xD2       = TMath::Power(xD,2);
+  Double_t yB        = TMath::Sqrt(r2 - hr2 + 2 * fHighR * xD - xD2);
+  Double_t xC        = ((xD + TMath::Sqrt(-tanTheta2 * xD2 + r2
+                                         + r2 * tanTheta2)) 
+                       / (1 + tanTheta2));
+  Double_t yC        = tanTheta * xC;
   
-  Int_t    nModules  = 360 / Int_t(fTheta * 2);
-  Double_t dTheta    = fTheta * 2;
-  
-  TString opt(option);
-  if (opt.Contains("B", TString::kIgnoreCase)) {
-    opt.Remove(opt.Index("B", 1, TString::kIgnoreCase),1);
-    TH1* null = new TH2F("null", "Null",
-                        100, -fHighR * 1.1, fHighR * 1.1, 
-                        100, -fHighR * 1.1, fHighR * 1.1);
-    null->SetStats(0);
-    null->Draw(opt.Data());
-  }
-   
-  for (int i = 0; i < nModules; i++) {
-    Double_t theta = (i + .5) * dTheta;
-    AliFMDPolygon p;
-    for (int j = 0; j < 6; j++) {
-      TVector2 vr(v[j].Rotate(TMath::Pi() * theta / 180.));
-      if (!p.AddVertex(vr.X(),vr.Y())) {
-       // std::cerr << "Draw of polygon " << i << " failed" << std::endl;
-       break;
-      }
-    }
-    p.Draw(opt.Data(), Form("MOD%c_%d", fId, i));
-  }
-  if (opt.Contains("0", TString::kIgnoreCase)) {
-    TArc* arcH = new TArc(0,0, fHighR);
-    arcH->SetLineStyle(2);
-    arcH->SetLineColor(4);
-    arcH->Draw();
-
-    TArc* arcL = new TArc(0,0, fLowR);
-    arcL->SetLineStyle(2);
-    arcL->SetLineColor(4);
-    arcL->Draw();
-  }
+  fVerticies.Expand(6);
+  fVerticies.AddAt(new TVector2(fLowR,  -yA), 0);
+  fVerticies.AddAt(new TVector2(xC,     -yC), 1);
+  fVerticies.AddAt(new TVector2(fHighR, -yB), 2);
+  fVerticies.AddAt(new TVector2(fHighR,  yB), 3);
+  fVerticies.AddAt(new TVector2(xC,      yC), 4);
+  fVerticies.AddAt(new TVector2(fLowR,   yA), 5);  
+
+  fRingDepth = (fSiThickness + fPrintboardThickness 
+               + fLegLength + fModuleSpacing);
 }
 
 //____________________________________________________________________
-void 
-AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, 
-                         Int_t pbRotId, Int_t idRotId)
+TVector2*
+AliFMDRing::GetVertex(Int_t i) const
 {
-  // Setup the geometry of the ring.  It defines the volumes 
-  // RNGI or RNGO which can later be positioned in a sub-detector
-  // volume. 
-  // 
-  // The hieracy of the RNGx volume is 
-  // 
-  //    FRGx                        // Ring volume
-  //      FVFx                      // Container of hybrid + legs
-  //        FACx                    // Active volume (si sensor approx)
-  //          FSEx                  // Section division
-  //            FSTx                // Strip division 
-  //        FPTx                    // Print board (bottom)
-  //        FPBx                    // Print board (top)  
-  //        FLL                     // Support leg (long version)
-  //      FVBx                      // Container of hybrid + legs
-  //        FACx                    // Active volume (si sensor approx)
-  //          FSEx                  // Section division
-  //            FSTx                // Strip division 
-  //        FPTx                    // Print board (bottom)
-  //        FPBx                    // Print board (top)  
-  //        FSL                     // Support leg (long version)
-  //        
-  // Parameters: 
-  //
-  //   vacuumId        Medium of inactive virtual volumes 
-  //   siId            Medium of Silicon sensor (active)
-  //   pcbId           Medium of print boards 
-  //   pbRotId         Print board rotation matrix 
-  //   idRotId         Identity rotation matrix 
-  //
-  // DebugGuard guard("AliFMDRing::SetupGeometry");
-  AliDebug(10, Form("\tSetting up the geometry for ring %c", fId));
-
-  const TVector2& bCorner   = fPolygon.GetVertex(3); // Third  corner
-  const TVector2& aCorner   = fPolygon.GetVertex(5); // First  corner
-  const TVector2& cCorner   = fPolygon.GetVertex(4); // Second corner
-  TString name;
-  TString name2;
-  Double_t dStrip     = (bCorner.Mod() - aCorner.Mod()) / fNStrips;
-  Double_t stripOff   = aCorner.Mod();
-  Double_t rmin       = fLowR;
-  Double_t rmax       = bCorner.Mod();
-  Double_t pars[10];
-  fRingDepth          = (fSiThickness 
-                        + fPrintboardThickness 
-                        + fLegLength 
-                        + fModuleSpacing);
-
-  // Ring virtual volume 
-  pars[0]             = rmin;
-  pars[1]             = rmax;
-  pars[2]             = fRingDepth / 2;
-  name                = Form(fgkRingFormat, fId);
-  fRingId             = gMC->Gsvolu(name.Data(), "TUBE", vacuumId, pars, 3);
-  
-  // Virtual volume for modules with long legs 
-  pars[1]             = rmax;
-  pars[3]             = -fTheta;
-  pars[4]             =  fTheta;
-  name                = Form(fgkVirtualFormat, fId, 'F');
-  fVirtualFrontId     = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
-
-  // Virtual volume for modules with long legs 
-  pars[2]             =  (fRingDepth - fModuleSpacing) / 2;
-  name                =  Form(fgkVirtualFormat, fId, 'B');
-  fVirtualBackId      =  gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
-  
-  // Virtual mother volume for silicon
-  pars[2]             =  fSiThickness/2;
-  name2               =  name;
-  name                =  Form(fgkActiveFormat, fId);
-  fActiveId           =  gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5);
-
-  if (fDetailed) {
-    // Virtual sector volumes 
-    name2               = name;
-    name                = Form(fgkSectorFormat, fId);
-    gMC->Gsdvn2(name.Data(), name2.Data(), 2, 2, -fTheta, vacuumId);
-    fSectionId          = gMC->VolId(name.Data());
-    
-    // Active strip volumes 
-    name2               = name;
-    name                = Form(fgkStripFormat, fId);
-    gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1,stripOff, siId, fNStrips);
-    fStripId            = gMC->VolId(name.Data());
-  }
-  
-  // Print-board on back of module 
-  pars[4]             = TMath::Tan(TMath::Pi() * fTheta / 180) * fBondingWidth;
-  // Top of the print board
-  pars[0]             = cCorner.Y() - pars[4];
-  pars[1]             = bCorner.Y() - pars[4];
-  pars[2]             = fPrintboardThickness / 2; // PCB half thickness
-  pars[3]             = (bCorner.X() - cCorner.X()) / 2;
-  name                = Form(fgkPrintboardFormat, fId, 'T');
-  fPrintboardTopId    = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
-
-  // Bottom of the print board
-  pars[0]             = aCorner.Y() - pars[4];
-  pars[1]             = cCorner.Y() - pars[4];
-  pars[3]             = (cCorner.X() - aCorner.X()) / 2;
-  name                = Form(fgkPrintboardFormat, fId, 'B');
-  fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
-
-  // Define rotation matricies
-  Int_t    nModules  = 360 / Int_t(fTheta * 2);
-  Double_t dTheta    = fTheta * 2;
-  fRotations.Set(nModules);
-  for (int i = 0; i < nModules; i++) {
-    Double_t theta  = (i + .5) * dTheta;
-    Int_t    idrot  = 0;
-    // Rotation matrix for virtual module volumes
-    gMC->Matrix(idrot, 90, theta, 90, fmod(90 + theta, 360), 0, 0);
-    fRotations[i] = idrot;
-  }
-
-
-  // Int_t    nModules  = 360 / Int_t(fTheta * 2);
-  // Double_t dTheta    = fTheta * 2;
-  Double_t pbTopL    = (bCorner.X() - cCorner.X());
-  Double_t pbBotL    = (cCorner.X() - aCorner.X());
-  Double_t yoffset   = ((TMath::Tan(TMath::Pi() * fTheta / 180) 
-                        * fBondingWidth)); 
-  
-  for (int i = 0; i < nModules; i++) {
-    TString  name2    = Form(fgkRingFormat, fId);
-
-    Int_t     id      = i;
-    // Double_t  theta   = (i + .5) * dTheta;
-    Bool_t    isFront = (i % 2 == 1);
-    Double_t  dz      = 0;
-    Double_t  w       = fRingDepth - (isFront ? 0 : fModuleSpacing);
-
-    // Place virtual module volume 
-    name = Form(fgkVirtualFormat, fId, (isFront ? 'F' : 'B'));
-    dz   = (w - fRingDepth) / 2;
-    gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i], 
-              "ONLY");
-
-    // We only need to place the children once, they are copied when
-    // we place the other virtual volumes. 
-    if (i > 1) continue;
-    name2 = name;
-
-    // Place active silicon wafer - this is put so that the front of
-    // the silicon is on the edge of the virtual volume. 
-    name  = Form(fgkActiveFormat, fId);
-    dz    = (w - fSiThickness) / 2;
-    gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId, "ONLY");
-
-    // Place print board.  This is put immediately behind the silicon
-    name = Form(fgkPrintboardFormat, fId, 'T');
-    dz   =  w / 2 - fSiThickness - fPrintboardThickness / 2;
-    gMC->Gspos(name.Data(), id, name2.Data(), 
-              fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY");
-    name = Form(fgkPrintboardFormat, fId, 'B');
-    gMC->Gspos(name.Data(), id, name2.Data(), 
-              fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY");
-
-    // Support legs 
-    // This is put immediately behind the pringboard. 
-    dz     = (w / 2 - fSiThickness - fPrintboardThickness 
-            - (fLegLength + (isFront ? fModuleSpacing : 0)) /2);
-    name  = (isFront ? AliFMD::fgkLongLegName : AliFMD::fgkShortLegName);
-    gMC->Gspos(name.Data(), id*10 + 1, name2.Data(), 
-              aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, "ONLY");
-    Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius;
-    gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(),y,dz,
-              idRotId,"ONLY");
-    gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(),-y,dz,
-              idRotId,"ONLY");
-  }
-}
-//____________________________________________________________________
-void 
-AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z, 
-                    Int_t /* pbRotId */, Int_t idRotId)
-{
-  // Positions a RNGx volume inside a mother. 
-  // 
-  // Parameters
-  //  
-  //    mother    Mother volume to position the RNGx volume in 
-  //    baseId    Base copy number 
-  //    z         Z coordinate where the front of the active silicon
-  //              should be in the mother volume, so we need to
-  //              subtract half the ring width.  
-  //    idRotId   Identity rotation matrix 
-  // 
-  // DebugGuard guard("AliFMDRing::Geometry");
-  TString  name;
-  Double_t offsetZ   = (fSiThickness 
-                       + fPrintboardThickness 
-                       + fLegLength + fModuleSpacing) / 2;
-  name = Form(fgkRingFormat, fId);
-  AliDebug(10, Form("\tPlacing ring %s in %s at z=%lf-%lf=%lf (base ID: %d)", 
-                   name.Data(), mother, z, offsetZ, z-offsetZ, baseId));
-  gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, 
-            "ONLY");
+  return static_cast<TVector2*>(fVerticies.At(i));
 }
 
 //____________________________________________________________________
-void 
-AliFMDRing::SimpleGeometry(TList* nodes, 
-                          TNode* mother
-                          Int_t colour
-                          Double_t z
-                          Int_t n) 
+void
+AliFMDRing::Detector2XYZ(UShort_t sector,
+                        UShort_t strip
+                        Double_t& x
+                        Double_t& y
+                        Double_t& z) const
 {
-  // Make a simple geometry of the ring for event display. 
-  // 
-  // The simple geometry is made from ROOT TNode and TShape objects. 
-  // Note, that we cache the TShape and TRotMatrix objects used for
-  // this. 
-  // 
-  // Parameters
-  // 
-  //    nodes     List of nodes to register all create nodes in 
-  //    mother    Mother node to put the ring in. 
-  //    colour    Colour of the nodes 
-  //    z         Z position of the node in the mother volume 
-  //    n         Detector number
-  //
-  // DebugGuard guard("AliFMDRing::SimpleGeometry");
-  SetupCoordinates();
-
-  AliDebug(10, Form("\tCreating simple geometry for "
-                   "ring %c at z=%lf cm in %s", 
-                   fId, z, mother->GetName()));
-  // If the shape hasn't been defined yet, we define it here. 
-  if (!fShape) {
-
-    TString name(Form(fgkActiveFormat, fId));
-    TString title(Form("Shape of modules in %c Rings", fId));
-    Int_t n = fPolygon.GetNVerticies();
-    TXTRU* shape = new TXTRU(name.Data(), title.Data(), "void", n, 2);
-    for (Int_t i = 0; i < n; i++) {
-      const TVector2& v = fPolygon.GetVertex(i);
-      shape->DefineVertex(i, v.X(), v.Y());
-    }
-    shape->DefineSection(0, - fSiThickness / 2, 1, 0, 0);
-    shape->DefineSection(1, + fSiThickness / 2, 1, 0, 0);
-    fShape = shape;
-    fShape->SetLineColor(colour);
-  }
-  
-  Int_t    nModules  = 360 / Int_t(fTheta * 2);
-  Double_t dTheta    = fTheta * 2;
-
-  // If the roation matricies hasn't been defined yet, we do so here
-  if (!fRotMatricies) {
-    fRotMatricies = new TObjArray(nModules);
-    for (int i = 0; i < nModules; i++) {
-      Double_t theta  = (i + .5) * dTheta;
-      TString name(Form("FMD_ring_%c_rot", fId));
-      TString title(Form("FMD Ring %c Rotation", fId));
-      TRotMatrix* rot = 
-       new TRotMatrix(name.Data(), title.Data(), 
-                      90, theta, 90, fmod(90 + theta, 360), 0, 0);
-      fRotMatricies->AddAt(rot, i);
-    }
+  if (sector >= GetNSectors()) {
+    Error("Detector2XYZ", "Invalid sector number %d (>=%d) in ring %c", 
+         sector, GetNSectors(), fId);
+    return;
   }
-
-  Double_t offsetZ   = (fSiThickness 
-                       + fPrintboardThickness
-                       + fLegLength + fModuleSpacing) / 2;
-
-  // Make all the nodes
-  for (int i = 0; i < nModules; i++) {
-    Bool_t    isFront = (i % 2 == 1);
-    mother->cd();
-    TRotMatrix* rot = static_cast<TRotMatrix*>(fRotMatricies->At(i));
-    TString name(Form("FAC%c_%d_%d", fId, n, i));
-    TString title(Form("Active FMD%d volume in %c Ring", n, fId));
-    TNode* node = new TNode(name.Data(), title.Data(), fShape, 
-                           0, 0, 
-                           z - offsetZ + (isFront ? fModuleSpacing : 0), 
-                           rot);
-    node->SetLineColor(colour);
-    nodes->Add(node);
+  if (strip >= GetNStrips()) {
+    Error("Detector2XYZ", "Invalid strip number %d (>=%d)", 
+         strip, GetNStrips(), fId);
+    return;
   }
-}
-
-  
-
-//____________________________________________________________________
-void 
-AliFMDRing::Gsatt() 
-{
-  // Set drawing attributes for the RING 
-  // 
-  // DebugGuard guard("AliFMDRing::Gsatt");
-  AliDebug(10, Form("\tSetting drawing attributes for Ring %c", fId));
-  TString name;
-  name = Form(fgkRingFormat,fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkVirtualFormat, fId, 'F');
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkVirtualFormat, fId, 'B');
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkActiveFormat,fId);
-  gMC->Gsatt(name.Data(), "SEEN", 1);
-
-  name = Form(fgkSectorFormat,fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkStripFormat,fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkPrintboardFormat, fId, 'T');
-  gMC->Gsatt(name.Data(), "SEEN", 1);
-
-  name = Form(fgkPrintboardFormat, fId, 'B');
-  gMC->Gsatt(name.Data(), "SEEN", 1);
+  Double_t phi = Float_t(sector + .5) / GetNSectors() * 2 * TMath::Pi();
+  Double_t r   = Float_t(strip + .5) / GetNStrips() * (fHighR - fLowR) + fLowR;
+  x = r * TMath::Cos(phi);
+  y = r * TMath::Sin(phi);
+  if (((sector / 2) % 2) == 1) 
+    z += TMath::Sign(fModuleSpacing, z);
 }
 
 //
index 10f2ade8e5cb4b5d0dc266a3507f4136d7796efd..de08e70a410e19a5e8472d0345db63987b194160 100644 (file)
 // This class is responsible to make the (common) rings of the three
 // sub-detectors. 
 //
-#ifndef ALIFMDPOLYGON_H
-# include "AliFMDPolygon.h"
+#ifndef ROOT_TNamed
+# include <TNamed.h>
 #endif
-#ifndef ROOT_TArrayI
-# include <TArrayI.h>
+#ifndef ROOT_TObjArray
+# include <TObjArray.h>
 #endif
 
 class TBrowser;
-class TNode;
-class TObjArray;
-class TShape;
-class TList;
+class TVector2;
 
-
-//__________________________________________________________________
-class AliFMDRing : public TObject
+/** Geometry description and parameters of a ring in the FMD
+    detector. 
+    
+    As there are only 2 kinds of rings @e Inner (@c 'I') and @e
+    Outer (@c 'O') the two objects of this class is owned by the
+    Geometry::FMD singleton object.  The 3 Geometry::FMDDetector
+    objects shares these two instances as needed. 
+*/
+class AliFMDRing : public TNamed
 {
 public:
-  AliFMDRing(Char_t id='\0', Bool_t detailed=kTRUE);
-  AliFMDRing(const AliFMDRing& other);
-  AliFMDRing& operator=(const AliFMDRing& other);
-  virtual ~AliFMDRing();
-
-  void   Init();
-  bool   IsWithin(size_t moduleNo, double x, double y) const;
-  void   SetupCoordinates();  
-  void   SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, 
-                      Int_t pbRotId, Int_t idRotId);
-  void   Geometry(const char* mother, Int_t baseId, Double_t z, Int_t pbRotId,
-                 Int_t idRotId);
-  void   SimpleGeometry(TList* nodes, 
-                       TNode* mother, 
-                       Int_t colour, 
-                       Double_t z, 
-                       Int_t n);
-  void   Gsatt();
-  void   Draw(Option_t* opt="HOL") const; //*MENU*
-  void   Browse(TBrowser* b);
-  Bool_t IsFolder() const { return kTRUE; }
+  AliFMDRing(Char_t fId);
+  virtual ~AliFMDRing() {}
+  /** Initialize the ring geometry */
+  virtual void Init();
+  
+  /** @param x Value of The Id of this ring type */
+  void SetId(Char_t x) { fId = x; }
+  /** @param x Value of With of bonding pad on sensor */
+  void SetBondingWidth(Double_t x=.5) { fBondingWidth = x; }
+  /** @param x Value of Size of wafer the sensor was made from */
+  void SetWaferRadius(Double_t x=13.4/2) { fWaferRadius = x; }
+  /** @param x Value of Thickness of sensor */
+  void SetSiThickness(Double_t x=.03) { fSiThickness = x; }
+  /** @param x Value of Lower radius of ring */
+  void SetLowR(Double_t x) { fLowR = x; }
+  /** @param x Value of Upper radius of ring */
+  void SetHighR(Double_t x) { fHighR = x; }
+  /** @param x Value of Opening angle of the silicon wafers */
+  void SetTheta(Double_t x) { fTheta = x; }
+  /** @param x Value of Number of strips */
+  void SetNStrips(Int_t x) { fNStrips = x; }
+  /** @param x Value of How far the ring extends beyond the z value given. */
+  void SetRingDepth(Double_t x) { fRingDepth = x; }
+  /** @param x Value of Radius of support legs */
+  void SetLegRadius(Double_t x=.5) { fLegRadius = x; }
+  /** @param x Value of Radius of support legs */
+  void SetLegLength(Double_t x=1) { fLegLength = x; }
+  /** @param x Value of Radius of support legs */
+  void SetLegOffset(Double_t x=2) { fLegOffset = x; }
+  /** @param x Value of Staggering offset */
+  void SetModuleSpacing(Double_t x=1) { fModuleSpacing = x; }
+  /** @param x Value of Thickness of print board */
+  void SetPrintboardThickness(Double_t x=.1) { fPrintboardThickness = x; }
   
-  Char_t   GetId()                  const { return fId; }
-  Int_t    GetActiveId()           const { return fActiveId; }
-  Int_t    GetPrintboardBottomId()  const { return fPrintboardBottomId; }
-  Int_t    GetPrintboardTopId()     const { return fPrintboardTopId; }
-  Int_t    GetRingId()             const { return fRingId; }
-  Int_t    GetSectionId()           const { return fSectionId; }
-  Int_t    GetStripId()                    const { return fStripId; }
-  Int_t    GetVirtualBackId()      const { return fVirtualBackId; }
-  Int_t    GetVirtualFrontId()     const { return fVirtualFrontId; }
-  Double_t GetBondingWidth()       const { return fBondingWidth; }
-  Double_t GetWaferRadius()        const { return fWaferRadius; }
-  Double_t GetSiThickness()        const { return fSiThickness; }
-  Double_t GetLowR()               const { return fLowR; }
-  Double_t GetHighR()              const { return fHighR; }
-  Double_t GetTheta()              const { return fTheta; }
-  Int_t    GetNStrips()                    const { return fNStrips; }
-  Int_t    GetNSectors()           const { return Int_t(360 / fTheta); }
-  Double_t GetLegRadius()          const { return fLegRadius; }
-  Double_t GetLegLength()          const { return fLegLength; }
-  Double_t GetModuleSpacing()      const { return fModuleSpacing; }
+  /** @return The Id of this ring type */
+  Char_t GetId() const { return fId; }
+  /** @return With of bonding pad on sensor */
+  Double_t GetBondingWidth() const { return fBondingWidth; }
+  /** @return Size of wafer the sensor was made from */
+  Double_t GetWaferRadius() const { return fWaferRadius; }
+  /** @return Thickness of sensor */
+  Double_t GetSiThickness() const { return fSiThickness; }
+  /** @return Lower radius of ring */
+  Double_t GetLowR() const { return fLowR; }
+  /** @return Upper radius of ring */
+  Double_t GetHighR() const { return fHighR; }
+  /** @return Opening angle of the sector (half that of silicon wafers) */
+  Double_t GetTheta() const { return fTheta; }
+  /** @return Number of strips */
+  Int_t GetNStrips() const { return fNStrips; }
+  /** @return Number of sectors */
+  Int_t GetNSectors() const { return Int_t(360. / fTheta); }
+  /** @return Number of modules (2 sectors per module) */
+  Int_t GetNModules() const { return GetNSectors() / 2; }
+  /** @return How far the ring extends beyond the z value given. */
+  Double_t GetRingDepth() const { return fRingDepth; }
+  /** @return Radius of support legs */
+  Double_t GetLegRadius() const { return fLegRadius; }
+  /** @return Radius of support legs */
+  Double_t GetLegLength() const { return fLegLength; }
+  /** @return Radius of support legs */
+  Double_t GetLegOffset() const { return fLegOffset; }
+  /** @return Staggering offset */
+  Double_t GetModuleSpacing() const { return fModuleSpacing; }
+  /** @return Thickness of print board */
   Double_t GetPrintboardThickness() const { return fPrintboardThickness; }
-  Double_t GetRingDepth()           const { return fRingDepth; }
-
-  void SetBondingWidth(Double_t width)           { fBondingWidth = width; }
-  void SetWaferRadius(Double_t radius)           { fWaferRadius = radius; } 
-  void SetSiThickness(Double_t thickness)        { fSiThickness = thickness; }
-  void SetLowR(Double_t lowR)                    { fLowR = lowR; }
-  void SetHighR(Double_t highR)                          { fHighR = highR; }
-  void SetTheta(Double_t theta)                          { fTheta = theta; }
-  void SetNStrips(Int_t nStrips)                 { fNStrips = nStrips; }
-  void SetLegRadius(Double_t radius)             { fLegRadius = radius; }
-  void SetLegLength(Double_t length)             { fLegLength = length; }
-  void SetLegOffset(Double_t offset)             { fLegOffset = offset; }
-
-  void SetModuleSpacing(Double_t       spacing)          { fModuleSpacing = spacing; }
-  void SetPrintboardThickness(Double_t thickness) { fPrintboardThickness = thickness; }
-
-protected:
-  Char_t   fId;                         // ID
-  Bool_t   fDetailed;            // True if a detailed geometry is made
-  Int_t    fActiveId;           // Active volume 
-  Int_t    fPrintboardBottomId;  // Print board bottom volume
-  Int_t    fPrintboardTopId;     // Print board top volume
-  Int_t    fRingId;             // Ring volume
-  Int_t    fSectionId;          // Section volumes 
-  Int_t    fStripId;            // Strip volumes 
-  Int_t    fVirtualBackId;      // Virtual Back volume
-  Int_t    fVirtualFrontId;     // Virtual Front volume
-
-  Double_t fBondingWidth;       // With of bonding pad on sensor
-  Double_t fWaferRadius;        // Size of wafer the sensor was made from 
-  Double_t fSiThickness;        // Thickness of sensor
-  Double_t fLowR;               // Lower radius of ring
-  Double_t fHighR;              // Upper radius of ring
-  Double_t fTheta;              // Opening angle of the silicon wafers
-  Int_t    fNStrips;            // Number of strips 
-  Double_t fRingDepth;           // How far the ring extends beyond
-                                // the z value given. 
-  Double_t fLegRadius;          // Radius of support legs 
-  Double_t fLegLength;          // Radius of support legs 
-  Double_t fLegOffset;          // Radius of support legs 
-
-  Double_t fModuleSpacing;      // Staggering offset 
-  Double_t fPrintboardThickness; // Thickness of print board
-
-  TArrayI    fRotations;        // Array of rotations
-  TShape*    fShape;             // Shape used for event display
-  TObjArray* fRotMatricies;      // Matricies used for event display
-
-  AliFMDPolygon  fPolygon;              // Polygon shape 
-
-  static const Char_t* fgkRingFormat;       // Format for Ring names 
-  static const Char_t* fgkVirtualFormat;    // Format for Virtual names
-  static const Char_t* fgkActiveFormat;     // Format for Active names 
-  static const Char_t* fgkSectorFormat;     // Format for Sector names 
-  static const Char_t* fgkStripFormat;      // Format for Strip names 
-  static const Char_t* fgkPrintboardFormat; // Format for Printboard names 
+  /** @return List of verticies */
+  const TObjArray& GetVerticies() const { return fVerticies; }
+  /** @return Number of verticies */
+  Int_t GetNVerticies() const { return fVerticies.GetEntries(); }
+  /** @param i Vertex number 
+      @return the ith vertex */
+  TVector2* GetVertex(Int_t i) const;
+     
+  void Detector2XYZ(UShort_t sector, UShort_t strip, 
+                   Double_t& x, Double_t& y, Double_t& z) const;
+  
+private: 
+  Char_t       fId;                    // The Id of this ring type
+  Double_t     fBondingWidth;          // With of bonding pad on sensor
+  Double_t     fWaferRadius;           // Size of wafer sensor was made from
+  Double_t     fSiThickness;           // Thickness of sensor
+  Double_t     fLowR;                  // Lower radius of ring
+  Double_t     fHighR;                 // Upper radius of ring
+  Double_t     fTheta;                 // Opening angle of the silicon wafers
+  Int_t                fNStrips;               // Number of strips
+  Double_t     fRingDepth;             // How far the ring extends beyond z
+  Double_t     fLegRadius;             // Radius of support legs
+  Double_t     fLegLength;             // Radius of support legs
+  Double_t     fLegOffset;             // Radius of support legs
+  Double_t     fModuleSpacing;         // Staggering offset
+  Double_t     fPrintboardThickness;   // Thickness of print board
+  TObjArray    fVerticies;             // List of verticies
 
-  ClassDef(AliFMDRing, 1) // FMD Ring volume parameters 
+  ClassDef(AliFMDRing, 0);
 };
 #endif 
 //____________________________________________________________________
diff --git a/FMD/AliFMDSimulator.cxx b/FMD/AliFMDSimulator.cxx
new file mode 100644 (file)
index 0000000..1937858
--- /dev/null
@@ -0,0 +1,457 @@
+/**************************************************************************
+ * 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 |<>-----| AliFMDSimulator |
+//      +--------+      +-----------------+
+//                               ^              
+//                               |
+//                 +-------------+-------------+
+//                 |                           |             
+//        +--------------------+   +-------------------+
+//        | AliFMDGeoSimulator |   | AliFMDG3Simulator | 
+//        +--------------------+   +---------+---------+
+//      
+//
+// *  AliFMD 
+//    This defines the interface for the various parts of AliROOT that
+//    uses the FMD, like AliFMDSimulator, AliFMDDigitizer, 
+//    AliFMDReconstructor, and so on. 
+//
+// *  AliFMDSimulator
+//    This is the base class for the FMD simulation tasks.   The
+//    simulator tasks are responsible to implment the geoemtry, and
+//    process hits. 
+//                                                                          
+// *  AliFMDGeoSimulator
+//    This is a concrete implementation of the AliFMDSimulator 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 AliFMDSimulator 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). 
+//
+#include "AliFMDSimulator.h"   // ALIFMDSIMULATOR_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 <AliRun.h>            // ALIRUN_H
+#include <AliMC.h>             // ALIMC_H
+#include <AliMagF.h>           // ALIMAGF_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 <TTree.h>             // ROOT_TTree
+#include <TParticle.h>         // ROOT_TParticle
+#include <TLorentzVector.h>    // ROOT_TLorentzVector
+#include <TVector2.h>          // ROOT_TVector2
+#include <TVector3.h>          // ROOT_TVector3
+#include <TVirtualMC.h>                // ROOT_TVirtualMC
+#include <TArrayD.h>           // ROOT_TArrayD
+
+//====================================================================
+ClassImp(AliFMDSimulator)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
+
+//____________________________________________________________________
+const Char_t* AliFMDSimulator::fgkActiveName   = "F%cAC";
+const Char_t* AliFMDSimulator::fgkSectorName   = "F%cSE";
+const Char_t* AliFMDSimulator::fgkStripName    = "F%cST";
+const Char_t* AliFMDSimulator::fgkModuleName   = "F%cMO";
+const Char_t* AliFMDSimulator::fgkPCBName      = "F%cP%c";
+const Char_t* AliFMDSimulator::fgkLongLegName  = "F%cLL";
+const Char_t* AliFMDSimulator::fgkShortLegName = "F%cSL";
+const Char_t* AliFMDSimulator::fgkFrontVName   = "F%cFV";
+const Char_t* AliFMDSimulator::fgkBackVName    = "F%cBV";
+const Char_t* AliFMDSimulator::fgkRingName     = "FMD%c";
+const Char_t* AliFMDSimulator::fgkTopHCName    = "F%d%cI";
+const Char_t* AliFMDSimulator::fgkBotHCName    = "F%d%cJ";
+const Char_t* AliFMDSimulator::fgkTopIHCName   = "F%d%cK";
+const Char_t* AliFMDSimulator::fgkBotIHCName   = "F%d%cL";
+const Char_t* AliFMDSimulator::fgkNoseName      = "F3SN";
+const Char_t* AliFMDSimulator::fgkBackName      = "F3SB";
+const Char_t* AliFMDSimulator::fgkBeamName      = "F3SL";
+const Char_t* AliFMDSimulator::fgkFlangeName    = "F3SF";
+
+//____________________________________________________________________
+AliFMDSimulator::AliFMDSimulator() 
+  : fFMD(0), 
+    fDetailed(kFALSE),
+    fInnerId(-1),
+    fOuterId(-1)
+{
+  // Default constructor
+}
+
+//____________________________________________________________________
+AliFMDSimulator::AliFMDSimulator(AliFMD* fmd, Bool_t detailed) 
+  : TTask("FMDsimulator", "Forward Multiplicity Detector Simulator"), 
+    fFMD(fmd), 
+    fDetailed(detailed),
+    fInnerId(-1),
+    fOuterId(-1)
+{
+  // Normal constructor
+  // 
+  // Parameters: 
+  // 
+  //      fmd          Pointer to AliFMD object 
+  //      detailed      Whether to make a detailed simulation or not 
+  // 
+}
+
+
+//____________________________________________________________________
+void
+AliFMDSimulator::DefineMaterials() 
+{
+  // 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_ALICE)
+  //   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();
+  
+  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;
+  fFMD->AliMaterial(id, "FMD Si$", 
+                     a, z, density, radiationLength, absorbtionLength);
+  fFMD->AliMedium(kSiId, "FMD Si$",
+                   id,1,fieldType,maxField,maxBending,
+                   maxStepSize,maxEnergyLoss,precision,minStepSize);
+  
+
+  // Carbon 
+  a                = 12.011;
+  z                = 6.;
+  density          = 2.265;
+  radiationLength  = 18.8;
+  maxBending       = 10;
+  maxStepSize      = .01;
+  precision        = .003;
+  minStepSize      = .003;
+  id               = kCarbonId;
+  fFMD->AliMaterial(id, "FMD Carbon$", 
+                     a, z, density, radiationLength, absorbtionLength);
+  fFMD->AliMedium(kCarbonId, "FMD Carbon$",
+                   id,0,fieldType,maxField,maxBending,
+                   maxStepSize,maxEnergyLoss,precision,minStepSize);
+
+  // Aluminum
+  a                = 26.981539;
+  z                = 13.;
+  density          = 2.7;
+  radiationLength  = 8.9;
+  id               = kAlId;
+  fFMD->AliMaterial(id, "FMD Aluminum$", 
+                     a, z, density, radiationLength, absorbtionLength);
+  fFMD->AliMedium(kAlId, "FMD Aluminum$", 
+                   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;
+    fFMD->AliMixture(id, "FMD Si Chip$", as, zs, density, 6, ws);
+    fFMD->AliMedium(kSiChipId, "FMD Si Chip$", 
+                     id, 0, fieldType, maxField, maxBending, 
+                     maxStepSize, maxEnergyLoss, precision, minStepSize);
+  }
+  
+#if 0
+  // 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               = KaptionId;
+    fFMD->AliMixture(id, "FMD Kaption$", as, zs, density, 4, ws);
+    fFMD->AliMedium(kAlId, "FMD Kaption$",
+                     id,0,fieldType,maxField,maxBending,
+                     maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+#endif
+
+  // 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;
+    fFMD->AliMixture(id, "FMD Air$", as, zs, density, 4, ws);
+    fFMD->AliMedium(kAirId, "FMD Air$", 
+                     id,0,fieldType,maxField,maxBending,
+                     maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+  
+  // PCB
+  {
+    Float_t zs[] = { 14.,         20.,         13.,         12.,
+                     5.,         22.,         11.,         19.,
+                    26.,          9.,          8.,          6.,
+                     7.,          1.};
+    Float_t as[] = { 28.0855,     40.078,      26.981538,   24.305, 
+                    10.811,      47.867,      22.98977,    39.0983,
+                    55.845,      18.9984,     15.9994,     12.0107,
+                    14.0067,      1.00794};
+    Float_t ws[] = {  0.15144894,  0.08147477,  0.04128158,  0.00904554, 
+                     0.01397570,  0.00287685,  0.00445114,  0.00498089,
+                     0.00209828,  0.00420000,  0.36043788,  0.27529426,
+                     0.01415852,  0.03427566};
+    density      = 1.8;
+    maxBending   = 1;
+    maxStepSize  = .001;
+    precision    = .001;
+    minStepSize  = .001;
+    id           = kPcbId;
+    fFMD->AliMixture(id, "FMD PCB$", as, zs, density, 14, ws);
+    fFMD->AliMedium(kPcbId, "FMD 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;
+    fFMD->AliMixture(id, "FMD Plastic$", as, zs, density, -2, ws);
+    fFMD->AliMedium(kPlasticId, "FMD Plastic$", 
+                     id,0,fieldType,maxField,maxBending,
+                     maxStepSize,maxEnergyLoss,precision,minStepSize);
+  }
+}
+
+//____________________________________________________________________
+void
+AliFMDSimulator::Exec(Option_t* /* option */) 
+{
+  // 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
+  //     
+  TVirtualMC* mc = TVirtualMC::GetMC();
+  
+  if (!mc->IsTrackAlive()) return;
+  if (TMath::Abs(mc->TrackCharge()) <= 0) return;
+  
+  Int_t copy;
+  Int_t vol = mc->CurrentVolID(copy);
+  if (vol != fInnerId && vol != fOuterId) {
+    AliDebug(15, Form("Not an FMD volume %d '%s' (%d or %d)", 
+                     vol, mc->CurrentVolName(), fInnerId, fOuterId));
+    return;
+  }
+
+  // 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, "Entering active FMD volume");
+    fCurrentDeltaE = 0;
+
+    // Get production vertex and momentum of the track 
+    mc->TrackMomentum(fCurrentP);
+    mc->TrackPosition(fCurrentV);
+    fCurrentPdg = mc->IdFromPDG(mc->TrackPid());
+  }
+  
+  // If the track is inside, then update the energy deposition
+  if (inside && fCurrentDeltaE >= 0) 
+    AliDebug(15, "Inside active FMD volume");
+    fCurrentDeltaE += 1000 * mc->Edep();
+
+  // The track exits the volume, or it disappeared in the volume, or
+  // the track is stopped because it no longer fulfills the cuts
+  // defined, then we create a hit. 
+  if (out && fCurrentDeltaE >= 0) {
+    AliDebug(15, Form("Leaving active FMD volume %s", mc->CurrentVolPath()));
+
+    Int_t strip = copy - 1;
+    Int_t sectordiv;
+    mc->CurrentVolOffID(fSectorOff, sectordiv);
+    Int_t module;
+    mc->CurrentVolOffID(fModuleOff, module);
+    Int_t sector = 2 * module + sectordiv;
+    Int_t iring;
+    mc->CurrentVolOffID(fRingOff, iring);
+    Char_t ring = Char_t(iring);
+    Int_t detector;
+    mc->CurrentVolOffID(fDetectorOff, detector);
+
+
+    AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+    Double_t rz = fmd->GetDetector(detector)->GetRingZ(ring);
+    Int_t    n  = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors();
+    if (rz < 0) {
+      Int_t s = ((n - sector + n / 2) % n) + 1;
+      AliDebug(40, Form("Recalculating sector to %d (=%d-%d+%d/2%%%d+1 z=%f)", 
+                       s, n, sector, n, n, rz));
+      sector = s;
+    }
+    if (sector < 1 || sector > n) {
+      Warning("Step", "sector # %d out of range (0-%d)", sector-1, n-1);
+      return;
+    }
+    sector--;
+    fCurrentDeltaE += 1000 * mc->Edep();
+
+    AliDebug(20, Form("Processing hit in FMD%d%c[%2d,%3d]: %f", 
+                     detector, ring, sector, strip, fCurrentDeltaE));
+    
+    fFMD->AddHit(gAlice->GetMCApp()->GetCurrentTrackNumber(),
+                UShort_t(detector), ring, UShort_t(sector), UShort_t(strip),
+                fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(),
+                fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(), 
+                fCurrentDeltaE, fCurrentPdg, fCurrentV.T());
+    fCurrentDeltaE = -1;
+  }
+}
+
+
+
+//____________________________________________________________________
+//
+// EOF
+//
diff --git a/FMD/AliFMDSimulator.h b/FMD/AliFMDSimulator.h
new file mode 100644 (file)
index 0000000..dd494d9
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef ALIFMDSIMULATOR_H
+#define ALIFMDSIMULATOR_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 TTask
+# include <TTask.h>
+#endif
+#ifndef TLorentzVector
+# include <TLorentzVector.h>
+#endif
+class TVector3;
+class AliFMD;
+class AliFMDRing;
+class AliFMDDetector;
+class AliFMD1;
+class AliFMD2;
+class AliFMD3;
+
+/** Simulation of the FMD. 
+    This class builds the geometry, and processes hits in the FMD */ 
+class AliFMDSimulator : public TTask  
+{
+public:
+  AliFMDSimulator();
+  /** CTOR */
+  AliFMDSimulator(AliFMD* fmd, Bool_t detailed=kTRUE);
+  virtual ~AliFMDSimulator() {}
+  /** Initialize */
+  virtual void DefineMaterials();
+  /** Register */
+  virtual void DefineGeometry() = 0;
+  /** Deal with a hit in the FMD */
+  virtual void Exec(Option_t* option="");
+
+protected:  
+  AliFMD*        fFMD;           //! Pointer to module 
+  Bool_t         fDetailed;      // Whether to make a detailed simulation 
+  Int_t         fInnerId;       //! ID of inner ring strips
+  Int_t         fOuterId;       //! ID of outer ring strips
+  TLorentzVector fCurrentV;      //! Current hit postition 
+  TLorentzVector fCurrentP;      //! Current hit momentum
+  Int_t          fCurrentPdg;    //! Current hit particle code 
+  Double_t       fCurrentDeltaE; //! Current hit energy loss
+
+  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
+  
+  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
+  };  
+
+  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 
+  
+  ClassDef(AliFMDSimulator,0) // Simulation class for the FMD
+};
+
+
+
+#endif
+//____________________________________________________________________
+//
+// Local Variables:
+//   mode: C++
+// End:
+//
+// EOF
+//
diff --git a/FMD/AliFMDSubDetector.cxx b/FMD/AliFMDSubDetector.cxx
deleted file mode 100644 (file)
index e189ac1..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/**************************************************************************
- * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved.      *
- *                                                                        *
- * Author: The ALICE Off-line Project.                                    *
- * Contributors are mentioned in the code where appropriate.              *
- *                                                                        *
- * Permission to use, copy, modify and distribute this software and its   *
- * documentation strictly for non-commercial purposes is hereby granted   *
- * without fee, provided that the above copyright notice appears in all   *
- * copies and that both the copyright notice and this permission notice   *
- * appear in the supporting documentation. The authors make no claims     *
- * about the suitability of this software for any purpose. It is          *
- * provided "as is" without express or implied warranty.                  *
- **************************************************************************/
-
-/* $Id$ */
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Utility class to help implement the FMD geometry.  This provides
-// the interface for the concrete geometry implementations of the FMD
-// sub-detectors. 
-//
-// The AliFMD object owns the AliFMDSubDetector objects
-//
-// Latest changes by Christian Holm Christensen
-//
-//////////////////////////////////////////////////////////////////////////////
-
-#include "AliFMDSubDetector.h" // ALIFMDSUBDETECTOR_H
-#include "AliFMDRing.h"                // ALIFMDRING_H
-#include <AliLog.h>            // ALILOG_H
-#include <TVirtualMC.h>                // ROOT_TVirtualMC
-#include <TList.h>             // ROOT_TList
-#include <TString.h>           // ROOT_TString
-
-//____________________________________________________________________
-ClassImp(AliFMDSubDetector)
-
-//____________________________________________________________________
-const Char_t* AliFMDSubDetector::fgkHoneyTopFormat         = "F%d%cH";
-const Char_t* AliFMDSubDetector::fgkHoneyBottomFormat      = "F%d%cI";
-const Char_t* AliFMDSubDetector::fgkHoneyTopInnerFormat    = "F%d%cJ";
-const Char_t* AliFMDSubDetector::fgkHoneyBottomInnerFormat = "F%d%cK";
-
-//____________________________________________________________________
-AliFMDSubDetector::AliFMDSubDetector(Int_t n)
-  : fId(n), 
-    fInnerZ(0), 
-    fOuterZ(0), 
-    fInner(0), 
-    fOuter(0)
-{
-  // Normal CTOR
-  SetAlThickness();
-  SetHoneycombThickness();
-}
-
-
-//____________________________________________________________________
-void 
-AliFMDSubDetector::Draw(Option_t* /* opt */) const 
-{
-  // DebugGuard guard("AliFMDSubDetector::Draw");
-  AliDebug(30, Form("\tDrawing FMD%d", fId));
-  Gsatt();
-  gMC->Gdraw(Form("FMD%d", fId));
-}
-
-//____________________________________________________________________
-void 
-AliFMDSubDetector::DrawSpecs() const 
-{
-  // DebugGuard guard("AliFMDSubDetector::Draw");
-  AliDebug(30, Form("\tDrawing specs foro FMD%d", fId));
-  gMC->DrawOneSpec(Form("FMD%d", fId));
-}
-
-//____________________________________________________________________
-Bool_t
-AliFMDSubDetector::CheckHit(Char_t ring, Int_t module, Double_t x, Double_t y) 
-{
-  // Check if a hit (x,y) in module module of ring ring is within the
-  // actual shape. 
-  AliDebug(30, Form("\tChecking wether the hit at (%lf,%lf) "
-                   "is in ring %c module %d", x, y, ring, module));
-  Bool_t ret = kFALSE;
-  switch (ring) {
-  case 'i':
-  case 'I': 
-    if (!fInner) break;
-    ret = fInner->IsWithin(module, x, y);
-    break;
-  case 'o':
-  case 'O': 
-    if (!fOuter) break;
-    ret = fOuter->IsWithin(module, x, y);
-    break;
-  }
-  return ret;
-}
-
-//____________________________________________________________________
-void 
-AliFMDSubDetector::SimpleGeometry(TList* nodes, 
-                                 TNode* mother, 
-                                 Int_t colour, 
-                                 Double_t zMother) 
-{
-  // Make a simplified geometry for event display 
-  // 
-  // Parameters
-  // 
-  //    nodes     List of nodes to register all create nodes in 
-  //    mother    Mother node to put the ring in. 
-  //    colour    Colour of the nodes 
-  //    zMother   Z position of the node in the mother volume 
-  // 
-  AliDebug(20, Form("\tCreating simple geometry for FMD%d", fId));
-  for (int i = 0; i < 2; i++) { 
-    AliFMDRing* r = 0;
-    Double_t z = 0;
-    switch (i) {
-    case 0: 
-      r     = fInner;
-      z     = fInnerZ;
-      break;
-    case 1: 
-      r     =  fOuter;
-      z     =  fOuterZ;
-      break;
-    }
-    if (!r) continue;
-
-    // Make the coordinates relative to the mother volume.   If we're
-    // on the positive side, then we need to flip the z-coordinate, as
-    // we'll rotate the whole sub-detector afterwards. 
-    z -= zMother;
-    if (zMother > 0) z *= -1;
-    
-    r->SimpleGeometry(nodes, mother, colour, z, fId);
-  }
-}
-
-  
-//____________________________________________________________________
-void 
-AliFMDSubDetector::SetupGeometry(Int_t airId, Int_t alId, Int_t /* cId
-                                                                */) 
-{
-  // Set up the geometry of this particular detector. 
-  // 
-  // In this class, it defines the support honey comp calls and
-  // nothing else. 
-  // 
-  // Parameters
-  //   airId           Medium of inactive virtual volumes 
-  //   alId       Medium of honeycomb
-  // 
-  // DebugGuard guard("AliFMDSubDetector::SetupGeometry");
-  AliDebug(20, Form("\tSetting up the geometry for FMD%d", fId));
-  TString name;
-  Double_t par[5];
-
-  for (int i = 0; i < 2; i++) {
-    AliFMDRing* r       = 0;
-    char  c = '\0';
-    switch (i) {
-    case 0: 
-      r      = fInner;
-      par[0] = fInnerHoneyLowR;
-      par[1] = fInnerHoneyHighR;
-      break;
-    case 1: 
-      r     = fOuter;
-      par[0] = fOuterHoneyLowR;
-      par[1] = fOuterHoneyHighR;
-      break;
-    }
-    if (!r) continue;
-    c = r->GetId();
-    
-    // Top of honeycomb, inner ring 
-    par[2] = fHoneycombThickness / 2;
-    par[3] = 0;
-    par[4] = 180;
-    name   = Form(fgkHoneyTopFormat, fId, c);
-    gMC->Gsvolu(name.Data(), "TUBS", alId, par, 5);
-    
-    // Bottom of honeycomb, inner ring 
-    par[3] = 180;
-    par[4] = 360;
-    name   = Form(fgkHoneyBottomFormat, fId, c);
-    gMC->Gsvolu(name.Data(), "TUBS", alId, par, 5);
-    
-    // Air in top of honeycomb, inner ring 
-    par[0] += fAlThickness;
-    par[1] -= fAlThickness;
-    par[2] -= fAlThickness;
-    par[3] = 0;
-    par[4] = 180;
-    name   = Form(fgkHoneyTopInnerFormat, fId, c);
-    gMC->Gsvolu(name.Data(), "TUBS", airId, par, 5);
-    
-    // Air in bottom of honeycomb, inner ring 
-    par[3] = 180;
-    par[4] = 360;
-    name   = Form(fgkHoneyBottomInnerFormat, fId, c);
-    gMC->Gsvolu(name.Data(), "TUBS", airId, par, 5);
-  }
-}
-
-//____________________________________________________________________
-void 
-AliFMDSubDetector::Geometry(const char* mother, Int_t pbRotId, Int_t idRotId, 
-                     Double_t zMother) 
-{
-  // Place the volume inside mother volume. 
-  // 
-  // Parameters
-  // 
-  //     mother     Volume to position this detector in 
-  //     pbRotId    Print board rotation matrix, 
-  //     idRotId    Identity rotation matrix 
-  //     zMother    The Z passed in, is the position of the middle
-  //                point of the mother volume. 
-  // 
-  // In this base class, it asks the contained rings to position
-  // themselves in the mother volume, and positions the honey comb
-  // support in the mother volume 
-  // 
-  // DebugGuard guard("AliFMDSubDetector::Geometry");
-  AliDebug(20, Form("\tDefining the rings in  %s (z=%lf cm)", 
-                   mother, zMother));
-
-  Double_t  ringW;
-  Double_t  z = 0;
-  // Double_t* b = 0;
-  TString name;
-  TString name2;
-  
-  for (int i = 0; i < 2; i++) {
-    AliFMDRing* r = 0;
-    char  c = '\0';
-    switch (i) {
-    case 0: 
-      r     = fInner;
-      z     = fInnerZ;
-      break;
-    case 1: 
-      r     =  fOuter;
-      z     =  fOuterZ;
-      break;
-    }
-    if (!r) continue;
-    c = r->GetId();
-
-    // Make the coordinates relative to the mother volume.   If we're
-    // on the positive side, then we need to flip the z-coordinate, as
-    // we'll rotate the whole sub-detector afterwards. 
-    Double_t z2 = z;
-    z2 -= zMother;
-    if (zMother > 0) z2 *= -1;
-    AliDebug(10, Form("\tPutting ring %c in %s at z=%lf-%lf=%lf", 
-                     c, mother, z, zMother, z2));
-    r->Geometry(mother, fId, z2, pbRotId, idRotId);
-    ringW =  r->GetRingDepth();
-    z2    -= ringW + fHoneycombThickness / 2;
-
-    // Top of honeycomb
-    name   = Form(fgkHoneyTopFormat, fId, c);
-    gMC->Gspos(name.Data(), 1, mother, 0, 0, z2, idRotId, "ONLY");
-
-    // Air in top of honeycomb
-    name2 = name;
-    name   = Form(fgkHoneyTopInnerFormat, fId, c);
-    gMC->Gspos(name.Data(), 1, name2.Data(),0,fAlThickness,0,idRotId,"ONLY");
-    
-    // Bottom of honeycomb
-    name   = Form(fgkHoneyBottomFormat, fId, c);
-    gMC->Gspos(name.Data(), 1, mother, 0, 0, z2, idRotId, "ONLY");
-
-    // Air in bottom of honeycomb
-    name2 = name;
-    name   = Form(fgkHoneyBottomInnerFormat, fId, c);
-    gMC->Gspos(name.Data(),1,name2.Data(),0,-fAlThickness,0,idRotId, "ONLY");
-  }
-}
-
-//____________________________________________________________________
-void
-AliFMDSubDetector::Gsatt() const
-{
-  // Set drawing attributes for the detector 
-  // 
-  // DebugGuard guard("AliFMDSubDetector::Gsatt");
-  AliDebug(30, Form("\tSetting draw attributs for FMD%d", fId));
-  TString name;
-
-  name = Form("FMD%d", fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  for (int i = 0; i < 2; i++) {
-    AliFMDRing* r = 0;
-    char  c = '\0';
-    switch (i) {
-    case 0: r = fInner; break;
-    case 1: r = fOuter; break;
-    }
-    if (!r) continue;
-    c = r->GetId();
-
-    name = Form(fgkHoneyTopFormat, fId, c);
-    gMC->Gsatt(name.Data(), "SEEN", 1);
-
-    name = Form(fgkHoneyBottomFormat, fId, c);
-    gMC->Gsatt(name.Data(), "SEEN", 1);
-
-    name = Form(fgkHoneyTopInnerFormat, fId, c);
-    gMC->Gsatt(name.Data(), "SEEN", 0);
-
-    name = Form(fgkHoneyBottomInnerFormat, fId, c);
-    gMC->Gsatt(name.Data(), "SEEN", 0);
-  }
-}
-
-
-//____________________________________________________________________
-// 
-// EOF
-//
diff --git a/FMD/AliFMDSubDetector.h b/FMD/AliFMDSubDetector.h
deleted file mode 100644 (file)
index 9f158ba..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef ALIFMDSUBDETECTOR_H
-#define ALIFMDSUBDETECTOR_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                               
- */
-//____________________________________________________________________
-// 
-// Parameters of a sub-detector, and builder of sub detector geometry 
-//
-#ifndef ROOT_TObject
-# include <TObject.h>
-#endif
-class TNode;
-class TList;
-class AliFMDRing;
-
-
-//__________________________________________________________________
-class AliFMDSubDetector : public TObject
-{
-public:  
-  AliFMDSubDetector(Int_t n);
-  virtual ~AliFMDSubDetector() {}
-  virtual void   SetupGeometry(Int_t airId, Int_t alId, Int_t cId=0);  
-  virtual void   Geometry(const char* mother, Int_t pbRotId, 
-                         Int_t idRotId, Double_t z=0);
-  virtual void   SimpleGeometry(TList* nodes, 
-                               TNode* mother, 
-                               Int_t colour, 
-                               Double_t zMother);
-  
-  virtual void   Gsatt() const;
-  virtual void   Draw(Option_t* option="BIOL0") const; //*MENU*
-  virtual void   DrawSpecs() const; // *MENU*
-  virtual Bool_t CheckHit(Char_t ring, Int_t module, Double_t x, Double_t y);
-
-  void   SetInner(AliFMDRing* r)             { fInner = r; }
-  void   SetOuter(AliFMDRing* r)             { fOuter = r; }
-  void   SetInnerZ(Double_t z)               { fInnerZ = z; }
-  void   SetOuterZ(Double_t z)               { fOuterZ = z; }
-  void   SetHoneycombThickness(Double_t t=1) { fHoneycombThickness = t; }
-  void   SetInnerHoneyLowR(Double_t r)       { fInnerHoneyLowR = r; }
-  void   SetInnerHoneyHighR(Double_t r)      { fInnerHoneyHighR = r; }
-  void   SetOuterHoneyLowR(Double_t r)       { fOuterHoneyLowR = r; }
-  void   SetOuterHoneyHighR(Double_t r)      { fOuterHoneyHighR = r; }
-  void   SetAlThickness(Double_t t=.05)      { fAlThickness = t; }
-     
-  Double_t    GetInnerZ()             const { return fInnerZ; }
-  Double_t    GetOuterZ()             const { return fOuterZ; }
-  AliFMDRing* GetInner()              const { return fInner; }
-  AliFMDRing* GetOuter()              const { return fOuter; }
-  Double_t    GetHoneycombThickness() const { return fHoneycombThickness; }
-  Double_t    GetInnerHoneyLowR()     const { return fInnerHoneyLowR; }
-  Double_t    GetInnerHoneyHighR()    const { return fInnerHoneyHighR; }
-  Double_t    GetOuterHoneyLowR()     const { return fOuterHoneyLowR; }
-  Double_t    GetOuterHoneyHighR()    const { return fOuterHoneyHighR; }
-  Double_t    GetAlThickness()        const { return fAlThickness; }
-  Int_t       GetId()                 const { return fId; }     
-  Bool_t      IsFolder()              const { return kTRUE; }
-
-protected:
-  Int_t       fId;                 // Detector number 
-  Double_t    fInnerZ;             // Position of outer ring along z
-  Double_t    fOuterZ;             // Position of outer ring along z 
-  Double_t    fHoneycombThickness; // Thickness of honeycomb plate 
-  Double_t    fAlThickness;        // Thickness of aluminium of honeycomb
-  Double_t    fInnerHoneyLowR;     // Inner radius of inner honeycomb
-  Double_t    fInnerHoneyHighR;    // Outer radius of inner honeycomb
-  Int_t       fInnerHoneyTopId;    // Volume ID of top of inner honeycomb
-  Int_t       fInnerHoneyBottomId; // Volume ID of bottom of inner honeycomb
-  Double_t    fOuterHoneyLowR;     // Inner radius of outer honeycomb
-  Double_t    fOuterHoneyHighR;    // Outer radius of outer honeycomb
-  Int_t       fOuterHoneyTopId;    // Volume ID of top of outer honeycomb   
-  Int_t       fOuterHoneyBottomId; // Volume ID of bottom of outer honeycomb
-
-  Int_t       fRotationId;         // The ID of the sub-detector rotation
-  
-  AliFMDRing* fInner;              // Reference to inner ring description
-  AliFMDRing* fOuter;              // Reference to outer ring description
-
-  static const Char_t* fgkHoneyTopFormat;         // Format of honeycomb name
-  static const Char_t* fgkHoneyBottomFormat;      // Format of honeycomb name
-  static const Char_t* fgkHoneyTopInnerFormat;    // Format of honeycomb name
-  static const Char_t* fgkHoneyBottomInnerFormat; // Format of honeycomb name
-
-  ClassDef(AliFMDSubDetector, 1) // FMD Sub detector base class
-};
-
-#endif
-//____________________________________________________________________
-//
-// Local Variables:
-//   mode: C++
-// End:
-//
-// EOF
-//
index 4b94ee12fad8032d3d9ebf8ef61f6feb27722ccc..a33c98c3a4c54074cb78141244c935d48d03c69b 100644 (file)
@@ -24,6 +24,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDUShortMap)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
 AliFMDUShortMap::AliFMDUShortMap(const AliFMDUShortMap& other)
index 73a8e196bdee03b8b1b6ec82919c4c5511df6ce4..6298dda20c5de4ab398d4fcf45421ee5f09b9e44 100644 (file)
 
 //____________________________________________________________________
 //                                                                          
-// Forward Multiplicity Detector based on Silicon wafers This class
+// Forward Multiplicity Detector based on Silicon wafers. This class
 // contains the base procedures for the Forward Multiplicity detector
-// Detector consists of 5 Si volumes covered pseudorapidity interval
-// from 1.7 to 5.1.
-// 
+// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
+// which has 1 or 2 rings of silicon sensors. 
+//                                                       
 // This contains the coarse version of the FMD - that is, the
 // simulation produces no hits in the FMD volumes. 
-//                                                                          
-// The actual code is done by various separate classes.   Below is
-// diagram showing the relationship between the various FMD classes
-// that handles the geometry 
-//
-//
-//       +----------+   +----------+   
-//       | AliFMDv1 |  | AliFMDv1 |   
-//       +----------+   +----------+   
-//            |              |
-//       +----+--------------+
-//       |
-//       |           +------------+ 1  +---------------+
-//       |        +- | AliFMDRing |<>--| AliFMDPolygon | 
-//       V     2  |  +------------+    +---------------+   
-//  +--------+<>--+        |
-//  | AliFMD |             ^                       
-//  +--------+<>--+        V 1..2                     
-//            3  | +-------------------+ 
-//               +-| AliFMDSubDetector | 
-//                 +-------------------+
-//                           ^              
-//                           |
-//             +-------------+-------------+
-//             |             |             |         
-//        +---------+   +---------+   +---------+
-//        | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
-//        +---------+   +---------+   +---------+
-//      
 //
 // See also the AliFMD class for a more detailed description of the
 // various components. 
@@ -62,6 +33,9 @@
 
 //____________________________________________________________________
 ClassImp(AliFMDv0)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //___________________________________________________________________
 //
index c492bac0d7f60bb0601594854105e86acd924337..f29ad5565eb38eb95416b2f1f33290eebe2cd6ef 100644 (file)
@@ -22,7 +22,7 @@ class AliFMDv0 : public AliFMD
 public:
   AliFMDv0() {}
   AliFMDv0(const char *name, const char *title="Coarse geometry") 
-    : AliFMD(name, title, false)
+    : AliFMD(name, title)
   {}
   virtual ~AliFMDv0() 
   {}
index 89d3dd71ebbddcd4e9b5540def488d108a8e4e14..34a320aca7bd7cc4d8de47e42c715172b71a7efd 100644 (file)
 //                                                                          
 // Forward Multiplicity Detector based on Silicon wafers. This class
 // contains the base procedures for the Forward Multiplicity detector
-// Detector consists of 5 Si volumes covered pseudorapidity interval
-// from 1.7 to 5.1.
-//
+// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
+// which has 1 or 2 rings of silicon sensors. 
+//                                                       
 // This class contains the detailed version of the FMD - that is, hits
 // are produced during simulation. 
 //                                                                           
-// The actual code is done by various separate classes.   Below is
-// diagram showing the relationship between the various FMD classes
-// that handles the geometry 
-//
-//
-//       +----------+   +----------+   
-//       | AliFMDv1 |  | AliFMDv1 |   
-//       +----------+   +----------+   
-//            |              |
-//       +----+--------------+
-//       |
-//       |           +------------+ 1  +---------------+
-//       |        +- | AliFMDRing |<>--| AliFMDPolygon | 
-//       V     2  |  +------------+    +---------------+   
-//  +--------+<>--+        |
-//  | AliFMD |             ^                       
-//  +--------+<>--+        V 1..2                     
-//            3  | +-------------------+ 
-//               +-| AliFMDSubDetector | 
-//                 +-------------------+
-//                           ^              
-//                           |
-//             +-------------+-------------+
-//             |             |             |         
-//        +---------+   +---------+   +---------+
-//        | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
-//        +---------+   +---------+   +---------+
-//      
-//
 // See also the class AliFMD for a more detailed explanation of the
 // various componets. 
+//
 #include <TVirtualMC.h>                // ROOT_TVirtualMC
 #include <AliRun.h>            // ALIRUN_H
 #include <AliMC.h>             // ALIMC_H
 #include <AliLog.h>            // ALILOG_H
 #include "AliFMDv1.h"          // ALIFMDV1_H
+#include "AliFMDSimulator.h"   // ALIFMDSIMULATOR_H
+#include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H
+#include "AliFMDGeoSimulator.h"        // ALIFMDGEOSIMULATOR_H
 
 //____________________________________________________________________
 ClassImp(AliFMDv1)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 
 //____________________________________________________________________
 void 
 AliFMDv1::StepManager()
 {
-  //
   // Called for every step in the Forward Multiplicity Detector
   //
-  // The procedure is as follows: 
+  // The message is deligated to AliFMDSimulator::Exec 
   // 
-  //   - 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
-  //     
-  //
-  AliDebug(10, Form("Is inside %s", gMC->CurrentVolName()));
-
-  // If the track is gone, return
-  if (!gMC->IsTrackAlive()) return;
-  
-  // Only process charged particles 
-  if(TMath::Abs(gMC->TrackCharge()) <= 0) return; 
-
-  // Only do stuff is the track is in one of the strips. 
-  // TString vol(gMC->CurrentVolName());
-  // if (!vol.Contains("STR")) return;
-  Int_t copy;
-  Int_t volumeId = gMC->CurrentVolID(copy);
-  // The ring ID is encoded in the volume name 
-  Char_t ring = '\0';
-  if (volumeId == fInner->GetStripId())      ring = 'I';
-  else if (volumeId == fOuter->GetStripId()) ring = 'O'; 
-  else                                       return;
-
-  // Get the strip number.  Note, that GEANT numbers divisions from 1,
-  // so we subtract one 
-  Int_t strip = copy - 1;
-
-  // Get the phi division of the module 
-  Int_t phiDiv;                         // * The phi division number (1 or 2)
-  gMC->CurrentVolOffID(1, phiDiv);      //   in the module  
-
-  // Active volume number - not used. 
-  // Int_t active;                         
-  // gMC->CurrentVolOffID(2, active);      
-
-  // Get the module number in the ring. 
-  Int_t module;                    
-  gMC->CurrentVolOffID(3, module); 
-  
-  // Ring copy number - the same as the detector number - not used
-  // Int_t ringCopy;                       // * Ring copy number
-  // gMC->CurrentVolOffID(4, ringCopy);    //   Same as detector number 
-  
-  // Get the detector number from the path name 
-  Int_t detector = Int_t((gMC->CurrentVolOffName(5)[3]) - 48);
-
-  // The sector number, calculated from module and phi division # 
-  Int_t  sector =  2 * module + phiDiv - 1;
-
-  
-  // Get a pointer to the sub detector structure 
-  AliFMDSubDetector* det = 0;
-  switch (detector) {
-  case 1: det = fFMD1; break;
-  case 2: det = fFMD2; break;
-  case 3: det = fFMD3; break;
-  }
-  if (!det) return;
-
-  // Get the current track position 
-  TLorentzVector v;
-  gMC->TrackPosition(v);
-  // Check that the track is actually within the active area 
-  Bool_t isWithin = det->CheckHit(ring, module, v.X(), v.Y());
-  Bool_t entering = gMC->IsTrackEntering() && isWithin;
-  Bool_t inside   = gMC->IsTrackInside()   && isWithin;
-  Bool_t out      = (gMC->IsTrackExiting() 
-                    || gMC->IsTrackDisappeared() 
-                    || gMC->IsTrackStop() 
-                    || !isWithin);
-
-  AliDebug(2, Form("Is inside FMD%d%c[%02d,%03d]: particle is %s", 
-                  detector, ring, sector, strip, 
-                  (entering ? "entering" : 
-                   (inside ? "inside" : 
-                    "exiting"))));
-
-  // Reset the energy deposition for this track, and update some of
-  // our parameters.
-  if (entering) {
-    fCurrentDeltaE = 0;
-
-    // Get production vertex and momentum of the track 
-    fCurrentV = v;
-    gMC->TrackMomentum(fCurrentP);
-    fCurrentPdg = gMC->IdFromPDG(gMC->TrackPid());
-
-    // if (fAnalyser) 
-    //   fAnalyser->Update(detector, ring, isWithin, v.X(), v.Y());
-  }
-  
-  // If the track is inside, then update the energy deposition
-  if (inside && fCurrentDeltaE >= 0) 
-    fCurrentDeltaE += 1000 * gMC->Edep();
-
-  // The track exits the volume, or it disappeared in the volume, or
-  // the track is stopped because it no longer fulfills the cuts
-  // defined, then we create a hit. 
-  if (out && fCurrentDeltaE >= 0) {
-    fCurrentDeltaE += 1000 * gMC->Edep();
-
-    AddHit(gAlice->GetMCApp()->GetCurrentTrackNumber(),
-          detector, ring,  sector, strip,
-          fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(),
-          fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(), 
-          fCurrentDeltaE, fCurrentPdg, fCurrentV.T());
-    fCurrentDeltaE = -1;
+  if (!fSimulator) {
+    AliFatal("No simulator object made");
+    return;
   }
+  fSimulator->Exec("");
 }
 //___________________________________________________________________
 //
index ddb8d13a8651437066b02bdac8ea0b226a2129f1..951e3b50da0a6e8056d0b34a1300a0ac8bd34fb0 100644 (file)
 class AliFMDv1 : public AliFMD 
 {
 public:
-  AliFMDv1() {}
+  AliFMDv1() { fDetailed = kTRUE; }
   AliFMDv1(const char *name, const char *title="Detailed geometry") 
-    : AliFMD(name, title, true
-  {}
+    : AliFMD(name, title) 
+  { fDetailed = kTRUE; }
   virtual ~AliFMDv1() {}
 
   // Required member functions 
@@ -38,7 +38,7 @@ protected:
   TLorentzVector fCurrentP;         // Current momentum vector 
   Int_t          fCurrentPdg;       // Current PDG code 
   
-  ClassDef(AliFMDv1,3)  // Detailed FMD geometry
+  ClassDef(AliFMDv1,4)  // Detailed FMD geometry
 };
 
 #endif
index 937e442686a5d578b6b02a692e164bf26367e4bc..468e25878e8c49924796d7efcd53e2b2cd5d7c45 100644 (file)
@@ -197,7 +197,8 @@ enum Mag_t {
 enum MC_t {
   kFLUKA, 
   kGEANT3, 
-  kGEANT4
+  kGEANT4, 
+  kGEANT3TGEO,
 };
 
 //____________________________________________________________________
@@ -220,7 +221,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 
@@ -263,6 +264,18 @@ Config()
     // 
     new TGeant3("C++ Interface to Geant3");
     break;
+  case kGEANT3TGEO:
+    //
+    // Libraries needed by GEANT 3.21 
+    //
+    gSystem->Load("libgeant321");
+    
+    // 
+    // GEANT 3.21 MC 
+    // 
+    new TGeant3TGeo("C++ Interface to Geant3");
+    Printf("Making a TGeant3TGeo objet");
+    break;
   default:
     gAlice->Fatal("Config.C", "No MC type chosen");
     return;
@@ -350,7 +363,6 @@ Config()
 
   //__________________________________________________________________
   // Generator Configuration
-  gAlice->SetDebug(0);
   AliGenerator* gener = GeneratorFactory(eg, rad, comment);
   gener->SetOrigin(0, 0, 0);    // vertex position
   gener->SetSigma(0, 0, 5.3);   // Sigma in (X,Y,Z) (cm) on IP position
@@ -394,27 +406,27 @@ Config()
   // 
   // Used detectors 
   // 
-  Bool_t useABSO  = kFALSE; 
-  Bool_t useCRT   = kFALSE; 
-  Bool_t useDIPO  = kFALSE; 
+  Bool_t useABSO  = kTRUE; 
+  Bool_t useCRT   = kTRUE; 
+  Bool_t useDIPO  = kTRUE; 
   Bool_t useFMD   = kTRUE; 
-  Bool_t useFRAME = kFALSE; 
-  Bool_t useHALL  = kFALSE; 
-  Bool_t useITS   = kFALSE; 
-  Bool_t useMAG   = kFALSE; 
-  Bool_t useMUON  = kFALSE; 
-  Bool_t usePHOS  = kFALSE; 
-  Bool_t usePIPE  = kFALSE; 
-  Bool_t usePMD   = kFALSE; 
-  Bool_t useRICH  = kFALSE; 
-  Bool_t useSHIL  = kFALSE; 
-  Bool_t useSTART = kFALSE; 
-  Bool_t useTOF   = kFALSE; 
-  Bool_t useTPC   = kFALSE;
-  Bool_t useTRD   = kFALSE; 
-  Bool_t useZDC   = kFALSE; 
-  Bool_t useEMCAL = kFALSE; 
-  Bool_t useVZERO = kFALSE;
+  Bool_t useFRAME = kTRUE; 
+  Bool_t useHALL  = kTRUE; 
+  Bool_t useITS   = kTRUE; 
+  Bool_t useMAG   = kTRUE; 
+  Bool_t useMUON  = kTRUE; 
+  Bool_t usePHOS  = kTRUE; 
+  Bool_t usePIPE  = kTRUE; 
+  Bool_t usePMD   = kTRUE; 
+  Bool_t useRICH  = kTRUE; 
+  Bool_t useSHIL  = kTRUE; 
+  Bool_t useSTART = kTRUE; 
+  Bool_t useTOF   = kTRUE; 
+  Bool_t useTPC   = kTRUE;
+  Bool_t useTRD   = kTRUE; 
+  Bool_t useZDC   = kTRUE; 
+  Bool_t useEMCAL = kTRUE; 
+  Bool_t useVZERO = kTRUE;
 
   cout << "\t* Creating the detectors ..." << endl;
   //=================== Alice BODY parameters =============================
@@ -607,6 +619,7 @@ Config()
   if (useFMD) {
     //=================== FMD parameters ============================
     AliFMD *FMD = new AliFMDv1("FMD", "normal FMD");
+    AliLog::SetModuleDebugLevel("FMD", 10);
   }
 
   if (useMUON) {
@@ -731,12 +744,12 @@ GeneratorFactory(EG_t eg, Rad_t rad, TString& comment)
   case kParam_fmd:
     {
       comment = comment.Append("HIJINGparam N=100");
-      AliGenHIJINGpara *gener = new AliGenHIJINGpara(100);
+      AliGenHIJINGpara *gener = new AliGenHIJINGpara(500);
       gener->SetMomentumRange(0, 999999.);
       gener->SetPhiRange(0., 360.);
       // Set pseudorapidity range from -8 to 8.
-      Float_t thmin = EtaToTheta(8);   // theta min. <---> eta max
-      Float_t thmax = EtaToTheta(-8);  // theta max. <---> eta min 
+      Float_t thmin = EtaToTheta(6);   // theta min. <---> eta max
+      Float_t thmax = EtaToTheta(2);  // theta max. <---> eta min 
       gener->SetThetaRange(thmin,thmax);
       gGener=gener;
     }
index 6b5a58216782ffd8107f0bd51775361f2bbdf063..39c8cffa3a2e2bf89798b3c2927de6a9163a1175 100644 (file)
 #pragma link C++ class  AliFMDDigit+;
 #pragma link C++ class  AliFMDSDigit+;
 #pragma link C++ class  AliFMDMap+;
+#pragma link C++ class  AliFMD1+;
+#pragma link C++ class  AliFMD2+;
+#pragma link C++ class  AliFMD3+;
+#pragma link C++ class  AliFMDRing+;
+#pragma link C++ class  AliFMDDetector+;
+#pragma link C++ class  AliFMDGeometry+;
+#pragma link C++ class  AliFMDParameters+;
 
 #else
 # error Not for compilation 
index a350fd9d9926b2ab0b78bef6d22f50a398634956..190c3fe55746d3c5bb1b74914184c27ffbcbfb9a 100644 (file)
 #pragma link C++ class  AliFMD+;
 #pragma link C++ class  AliFMDv0+;
 #pragma link C++ class  AliFMDv1+;
-#pragma link C++ class  AliFMDSubDetector+;
-#pragma link C++ class  AliFMD1+;
-#pragma link C++ class  AliFMD2+;
-#pragma link C++ class  AliFMD3+;
-#pragma link C++ class  AliFMD3Support+;
-#pragma link C++ class  AliFMDRing+;
-#pragma link C++ class  AliFMDPolygon+;
+#pragma link C++ class  AliFMDSimulator+;
+#pragma link C++ class  AliFMDGeoSimulator+;
+#pragma link C++ class  AliFMDG3Simulator+;
 #pragma link C++ class  AliFMDBaseDigitizer+;
 #pragma link C++ class  AliFMDDigitizer+;
 #pragma link C++ class  AliFMDSDigitizer+;
index ae1fe73fda3e47bbc0eb1533cf80afd7ab66ad50..0cfd70614f447f405f8e2b8fdb7204ad6f163ab9 100644 (file)
@@ -25,7 +25,7 @@ Simulate()
  // sim.SetMakeDigits("FMD");
  sim.SetWriteRawData("FMD");
  // sim.SetMakeDigitsFromHits("FMD");
- sim.Run(); 
+ sim.Run(2); 
 }
 
 //
index 2f66bf0e710b9e5ad69f93cae9d649ef430d6712..6bcdc8f08340ef23a3277061b5781af4ba1f8a48 100644 (file)
@@ -3,8 +3,6 @@ void ViewFMD()
   gMC->Gsatt("FMD1","seen",0);
   gMC->Gsatt("FMD2","seen",0);
   gMC->Gsatt("FMD3","seen",0);
-  gMC->Gsatt("FSSL","seen",1);
-  gMC->Gsatt("FSLL","seen",1);
 
   TString name;
   // Rings
@@ -15,18 +13,24 @@ void ViewFMD()
     case 1: c = 'O'; break;
     }
      
-    name = Form("F%cRG", c);
+    name = Form("FMD%c", c);
     gMC->Gsatt(name.Data(),"seen",0); // Ring volume        
 
-    name = Form("F%cVF", c);
+    name = Form("F%cFV", c);
     gMC->Gsatt(name.Data(),"seen",0); // Virtual volume front
 
-    name = Form("F%cVB", c);
+    name = Form("F%cBV", c);
     gMC->Gsatt(name.Data(),"seen",0); // Virtual volume back
 
     name = Form("F%cAC", c);
     gMC->Gsatt(name.Data(),"seen",-2); // Active volume
 
+    name =  Form("F%cSL", c);
+    gMC->Gsatt(name.Data() ,"seen",1);
+
+    name =  Form("F%cLL", c);
+    gMC->Gsatt(name.Data() ,"seen",1);
+
     // name = Form("F%cAP", c);
     // gMC->Gsatt(name.Data(),"seen",-1); // Phi segmentation of active
 
@@ -49,16 +53,16 @@ void ViewFMD()
       case 1: c = 'O'; break;
       }
        
-      name = Form("F%d%cH", i, c);
+      name = Form("F%d%cI", i, c);
       gMC->Gsatt(name.Data(),"seen",-2); // Honeycomp top 
 
-      name = Form("F%d%cI", i, c);
+      name = Form("F%d%cJ", i, c);
       gMC->Gsatt(name.Data(),"seen",-2); // Honeycomp bottom
 
-      name = Form("F%d%cJ", i, c);
+      name = Form("F%d%cK", i, c);
       gMC->Gsatt(name.Data(),"seen",0); // Honeycomp inner top 
 
-      name = Form("F%d%cK", i, c);
+      name = Form("F%d%cL", i, c);
       gMC->Gsatt(name.Data(),"seen",0); // Honeycomp inner bottom 
     }
   }
index b795afff32d8492bdda80b17035cf0f1044e5808..5f565af3568e0d5866f56dbcb896d0216b69e410 100644 (file)
@@ -3,7 +3,14 @@
 # $Id$
 
 SRCS   =  AliFMDDigit.cxx              \
-          AliFMDMap.cxx                
+          AliFMDMap.cxx                \
+          AliFMDParameters.cxx         \
+          AliFMDGeometry.cxx           \
+          AliFMDRing.cxx               \
+          AliFMDDetector.cxx           \
+          AliFMD1.cxx                  \
+          AliFMD2.cxx                  \
+          AliFMD3.cxx
 HDRS   =  $(SRCS:.cxx=.h)
 DHDR   := FMDbaseLinkDef.h
 
index 33b9ca0f32072009e6a5380e212d1921ec1e8882..a4290232633e83dbb18e7bb557b6ca29c615928d 100644 (file)
@@ -5,13 +5,9 @@
 SRCS           =  AliFMD.cxx                   \
                   AliFMDv0.cxx                 \
                   AliFMDv1.cxx                 \
-                  AliFMDSubDetector.cxx        \
-                  AliFMD1.cxx                  \
-                  AliFMD2.cxx                  \
-                  AliFMD3.cxx                  \
-                  AliFMD3Support.cxx           \
-                  AliFMDRing.cxx               \
-                  AliFMDPolygon.cxx            \
+                  AliFMDSimulator.cxx          \
+                  AliFMDGeoSimulator.cxx       \
+                  AliFMDG3Simulator.cxx        \
                   AliFMDHit.cxx                \
                   AliFMDDigitizer.cxx          \
                   AliFMDEdepMap.cxx            \
diff --git a/FMD/scripts/DrawFMD2.C b/FMD/scripts/DrawFMD2.C
new file mode 100644 (file)
index 0000000..81c1374
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Script to draw detail of the FMD
+//
+void DrawFMD2()
+{
+  // gAlice->Init("FMD/scripts/ConfigInner.C");
+  gAlice->Init("$(ALICE)/FMD/Config.C");
+  gMC->Gsatt("*", "seen", -1);
+  gMC->Gsatt("alic", "seen", 0);
+  gROOT->LoadMacro("$(ALICE)/FMD/ViewFMD.C");
+  gInterpreter->ProcessLine("ViewFMD()");
+  gMC->Gsatt("FMD3", "seen", -1);
+  gMC->Gsatt("FMD1", "seen", -1);
+  gMC->Gdopt("hide", "on");
+  gMC->Gdopt("shad", "on");
+  gMC->Gsatt("*", "fill", 7);
+  gMC->SetClipBox(".");
+  gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
+  gMC->DefaultRange();
+  // gMC->Gdraw("alic", 90, 0, 0, 28, 10, .25, .25);
+  // gMC->Gdraw("alic", 90, 0, 0, 28, 10, .25, .25);
+  gMC->Gdraw("alic", 179, 0, 0, 10, 10, .25, .25);
+
+#if 0
+  TArrow* a1 = new TArrow(13.5, 16, 15, 18., .03, "<|");
+  a1->SetAngle(30);
+  a1->SetFillColor(1);
+  a1->Draw();
+  
+  TLatex* l1 = new TLatex(15, 18, "Honeycomb");
+  l1->SetTextAlign(12);
+  l1->SetTextFont(132);
+  l1->SetTextSize(.04);
+  l1->Draw();
+  
+  a1->DrawArrow(13.4, 14., 15, 15, .03, "<|");
+  l1->DrawLatex(15, 15, "Support Leg");
+  
+  a1->DrawArrow(10.7, 14.2, 15, 13, .03, "<|");
+  l1->DrawLatex(15, 13, "Print board");
+
+  a1->DrawArrow(9.7, 12.5, 15, 11, .03, "<|");
+  l1->DrawLatex(15, 11, "Silicon sensor");
+
+  a1->DrawArrow(8.3, 12.7, 7, 15, .03, "<|");
+  TLatex* l2 = new TLatex(7, 15, "Support Cone");
+  l2->SetTextSize(.04);
+  l2->SetTextFont(132);
+  l2->SetTextAlign(32);
+  l2->Draw();
+
+  TLatex* l3 = new TLatex(3, 3, "FMD2");
+  l3->SetTextSize(.06);
+  l3->SetTextFont(132);
+  l3->Draw();  
+#endif
+
+  gPad->Modified();
+  gPad->cd();
+  gPad->Print("FMD2.png");
+}
index 8d9f69f1806909ddd96fd64809ff847b3638c164..7414f4dd7303db94a1e30c553e127fffefe852ab 100644 (file)
@@ -15,7 +15,7 @@ void DrawFMD3()
   gMC->SetClipBox(".");
   gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
   gMC->DefaultRange();
-  gMC->Gdraw("alic", 60, 0, 0, -3, 10, .25, .25);
+  gMC->Gdraw("alic", 90, 0, 0, -3, 10, .25, .25);
 
   TArrow* a1 = new TArrow(13.5, 16, 15, 18., .03, "<|");
   a1->SetAngle(30);