]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - FMD/AliFMDRing.cxx
restore threshold getters after parameter dynamics update (fw v. >= A012)
[u/mrichter/AliRoot.git] / FMD / AliFMDRing.cxx
index 9f94ba71793a0c67b14dc3a4fa7f479fbb38c909..601e95fe26c00f1af26ef4fcb7dacd82cc6af441 100644 (file)
  * about the suitability of this software for any purpose. It is          *
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
-
 /* $Id$ */
-
+/** @file    AliFMDRing.cxx
+    @author  Christian Holm Christensen <cholm@nbi.dk>
+    @date    Mon Mar 27 12:47:43 2006
+    @brief   FMD ring geometry parameters 
+*/
 //__________________________________________________________________
 //
 // Utility class to help implement collection of FMD modules into
-// rings.  This is used by AliFMDSubDetector and AliFMD.  
-//
-// The AliFMD object owns the AliFMDRing objects, and the
-// AliFMDSubDetector objects reference these.  That is, the AliFMDRing
-// objects are share amoung the AliFMDSubDetector objects.
+// rings.  This is used by AliFMDDetector and AliFMDGeometry.
+// 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
 //
-#ifndef ALIFMDRING_H
-# include "AliFMDRing.h"
-#endif
-#ifndef ALILOG_H
-# include "AliLog.h"
-#endif
-#ifndef ROOT_TMath
-# include <TMath.h>
-#endif
-#ifndef ROOT_TH2
-# include <TH2.h>
-#endif
-#ifndef ROOT_TVirtualMC
-# include <TVirtualMC.h>
-#endif
-#ifndef ROOT_TVector2
-# include <TVector2.h>
-#endif
-#ifndef ROOT_TBrowser
-# include <TBrowser.h>
-#endif
-#ifndef ROOT_TString
-# include <TString.h>
-#endif
-#ifndef ROOT_TArc
-# include <TArc.h>
-#endif
-#ifndef ROOT_TObjArray
-# include <TObjArray.h>
-#endif
-#ifndef ROOT_TXTRU
-# include <TXTRU.h>
-#endif
-#ifndef ROOT_TNode
-# include <TNode.h>
-#endif
-#ifndef ROOT_TRotMatrix
-# include <TRotMatrix.h>
-#endif
-#ifndef ROOT_TList
-# include <TList.h>
-#endif
-#ifndef __IOSTREAM__
-# include <iostream>
-#endif
-#include <math.h>
 
-const Char_t* AliFMDRing::fgkRingFormat         = "FRG%c";
-const Char_t* AliFMDRing::fgkVirtualFormat      = "FV%c%c";
-const Char_t* AliFMDRing::fgkActiveFormat       = "FAC%c";
-const Char_t* AliFMDRing::fgkSectorFormat       = "FSE%c";
-const Char_t* AliFMDRing::fgkStripFormat        = "FST%c";
-const Char_t* AliFMDRing::fgkPrintboardFormat   = "FP%c%c";
+#include <TMath.h>             // ROOT_TMath
+#include <TVector2.h>          // ROOT_TVector2
 
+// #include <AliLog.h>         // ALILOG_H
+#include "AliFMDRing.h"                // ALIFMDRING_H
 
-//____________________________________________________________________
-ClassImp(AliFMDRing);
+//====================================================================
+ClassImp(AliFMDRing)
+#if 0
+  ; // This is here to keep Emacs for indenting the next line
+#endif
 
 //____________________________________________________________________
-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),
+AliFMDRing::AliFMDRing(Char_t id) 
+  : TNamed(Form("FMD%c", id), "Forward multiplicity ring"), 
+    fId(id), 
     fBondingWidth(0),
-    fWaferRadius(0), 
+    fWaferRadius(0),
     fSiThickness(0),
-    fLowR(0), 
-    fHighR(0), 
-    fTheta(0), 
-    fNStrips(0), 
+    fLowR(0),
+    fHighR(0),
+    fMinR(0),
+    fMaxR(0),
+    fTheta(0),
+    fNStrips(0),
     fRingDepth(0),
     fLegRadius(0),
     fLegLength(0),
     fLegOffset(0),
     fModuleSpacing(0),
     fPrintboardThickness(0),
-    fShape(0),
-    fRotMatricies(0)
+    fCopperThickness(0),
+    fChipThickness(0),
+    fSpacing(0),
+    fHoneycombThickness(0.),
+    fAlThickness(0.),
+    fVerticies(0), 
+    fSensorVerticies(0),
+    fHybridVerticies(0),
+    fFeetPositions(0)
 {
-  // Construct a alifmdring. 
+  // Constructor 
   // 
-  //     id            Id of the ring (either 'i' or 'o').
-  //     detailed       Whether the strips are made or not.
+  // Parameters: 
+  //    id      Type of ring (either 'I' or 'O') 
   // 
+  SetBondingWidth();
+  SetWaferRadius();
+  SetSiThickness();
+  SetLegRadius();
+  SetLegLength();
+  SetLegOffset();
+  SetModuleSpacing();
+  SetPrintboardThickness();
+  SetCopperThickness();
+  SetChipThickness();
+  SetSpacing();
+  SetHoneycombThickness();
+  SetAlThickness();
+  
+  if (fId == 'I' || fId == 'i') {
+    SetLowR(4.3);
+    SetHighR(17.2);
+    SetTheta(36/2);
+    SetNStrips(512);
+    Double_t base = 0; // 4.1915;
+    fFeetPositions.Add(new TVector2( 0.0551687, 8.0534-base));
+    fFeetPositions.Add(new TVector2( 2.9993,   12.9457-base));
+    fFeetPositions.Add(new TVector2(-2.9062,   12.9508-base));
+    
+    fHybridVerticies.Add(new TVector2(0.0000,  4.1700));
+    fHybridVerticies.Add(new TVector2(1.0574,  4.1700));
+    fHybridVerticies.Add(new TVector2(4.6614, 15.2622));
+    fHybridVerticies.Add(new TVector2(0.9643, 17.4000));
+    fHybridVerticies.Add(new TVector2(0.0000, 17.4000));
+
+    fSensorVerticies.Add(new TVector2(0.0000,  4.1915));
+    fSensorVerticies.Add(new TVector2(1.5793,  4.1915));
+    fSensorVerticies.Add(new TVector2(5.2293, 15.4251));
+    fSensorVerticies.Add(new TVector2(1.9807, 17.3035));
+    fSensorVerticies.Add(new TVector2(0.0000, 17.3035));
+
+    fVerticies.Add(new TVector2(0.0000,  4.3000));
+    fVerticies.Add(new TVector2(1.3972,  4.3000));
+    fVerticies.Add(new TVector2(4.9895, 15.3560));
+    fVerticies.Add(new TVector2(1.8007, 17.2000));
+    fVerticies.Add(new TVector2(0.0000, 17.2000));
+  }
+  else if (fId == 'O' || fId == 'o') {
+    SetLowR(15.6);
+    SetHighR(28.0);
+    SetTheta(18/2);
+    SetNStrips(256);
+    Double_t base = 0; // 14.9104;
+    fFeetPositions.Add(new TVector2(-1.72540000, 20.6267-base));
+    fFeetPositions.Add(new TVector2( 1.72900000, 20.6267-base));
+    fFeetPositions.Add(new TVector2( 0.00177616, 26.6007-base));
+
+    fHybridVerticies.Add(new TVector2(0.0000, 14.9104));
+    fHybridVerticies.Add(new TVector2(2.0783, 14.9104));
+    fHybridVerticies.Add(new TVector2(3.9202, 26.5395));
+    fHybridVerticies.Add(new TVector2(0.6784, 28.2500));
+    fHybridVerticies.Add(new TVector2(0.0000, 28.2500));
+
+    fSensorVerticies.Add(new TVector2(0.0000, 15.0104));
+    fSensorVerticies.Add(new TVector2(2.5799, 15.0104));
+    fSensorVerticies.Add(new TVector2(4.4439, 26.7766));
+    fSensorVerticies.Add(new TVector2(1.8350, 28.1500));
+    fSensorVerticies.Add(new TVector2(0.0000, 28.1500));
+
+    fVerticies.Add(new TVector2(0.0000, 15.2104));
+    fVerticies.Add(new TVector2(2.4091, 15.2104));
+    fVerticies.Add(new TVector2(4.2231, 26.6638));
+    fVerticies.Add(new TVector2(1.8357, 27.9500));
+    fVerticies.Add(new TVector2(0.0000, 27.9500));
+  }
 }
 
 //____________________________________________________________________
-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)
+void
+AliFMDRing::Init()
 {
-  // Copy constructor of a AliFMDRing. 
+  // Initialize 
+  // 
+  // All derived quantities are calculated here. 
+  // 
+#if 0
+  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;
+  
+  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);  
+#endif
+
+  // A's length. Corresponds to distance from nominal beam line to the
+  // cornor of the active silicon element. 
+  fMinR = GetVertex(1)->Mod(); // GetVertex(5)->Mod();
+  // A's length. Corresponds to distance from nominal beam line to the
+  // cornor of the active silicon element. 
+  fMaxR = fHighR;
+
+  fRingDepth = (fSiThickness + fPrintboardThickness 
+               + fCopperThickness + fChipThickness 
+               + fLegLength + fModuleSpacing + fSpacing);
 }
 
 //____________________________________________________________________
-AliFMDRing&
-AliFMDRing::operator=(const AliFMDRing& other) 
+TVector2*
+AliFMDRing::GetVertex(Int_t i) const
 {
-  // Assignment operator 
+  // Get the i'th vertex of polygon shape
   // 
-  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;
+  // the polygon shape describes the shape of the rings' sensors
+  // 
+  // Parameters: 
+  //     i    The vertex number to get (from 0 to 5)
+  return static_cast<TVector2*>(fVerticies.At(i));
 }
 
-  
-
 //____________________________________________________________________
-void 
-AliFMDRing::Init() 
+TVector2*
+AliFMDRing::GetSensorVertex(Int_t i) const
 {
-  // Initialize the ring object.
-  // DebugGuard guard("AliFMDRing::Init");
-  AliDebug(10, "AliFMDRing::Init");
-  fPolygon.Clear();
-  SetupCoordinates();  
+  // Get the i'th vertex of polygon shape
+  // 
+  // the polygon shape describes the shape of the rings' sensors
+  // 
+  // Parameters: 
+  //     i    The vertex number to get (from 0 to 5)
+  return static_cast<TVector2*>(fSensorVerticies.At(i));
 }
 
 //____________________________________________________________________
-AliFMDRing::~AliFMDRing() 
+TVector2*
+AliFMDRing::GetHybridVertex(Int_t i) const
 {
-  // Destructor - deletes shape and rotation matricies 
-  if (fShape) delete fShape;
-  if (fRotMatricies) delete fRotMatricies;
+  // Get the i'th vertex of polygon shape
+  // 
+  // the polygon shape describes the shape of the rings' hybrid cards
+  // 
+  // Parameters: 
+  //     i    The vertex number to get (from 0 to 5)
+  return static_cast<TVector2*>(fHybridVerticies.At(i));
 }
 
-
 //____________________________________________________________________
-void 
-AliFMDRing::Browse(TBrowser* /* b */)
+TVector2*
+AliFMDRing::GetFootPosition(Int_t i) const
 {
-  // DebugGuard guard("AliFMDRing::Browse");
-  AliDebug(10, "AliFMDRing::Browse");
+  // Get the i'th vertex of polygon shape
+  // 
+  // The feet are attached to the hybrid cards
+  // 
+  // Parameters: 
+  //     i    The foot number to get (from 0 to 2)
+  return static_cast<TVector2*>(fFeetPositions.At(i));
 }
 
-  
 //____________________________________________________________________
-void 
-AliFMDRing::SetupCoordinates() 
+Double_t
+AliFMDRing::GetStripRadius(UShort_t strip) const
 {
-  // Calculates the parameters of the polygon shape. 
+  // Return the nominal strip radius 
   // 
-  // DebugGuard guard("AliFMDRing::SetupCoordinates");
-  AliDebug(10, "AliFMDRing::SetupCoordinates");
-  // Get out immediately if we have already done all this 
-  if (fPolygon.GetNVerticies() > 1) return;
-
-  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        = 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);
+  // Parameter 
+  //   strip    Strip number (0-511 for inners, 0-255 for outers)
+  Double_t rmax     = GetMaxR();
+  Double_t stripoff = GetMinR();
+  Double_t dstrip   = (rmax - stripoff) / GetNStrips();
+  return (strip + .5) * dstrip + stripoff; // fLowR
 }
-
 //____________________________________________________________________
-bool
-AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const
+Double_t
+AliFMDRing::GetModuleDepth() const
 {
-  // Checks if a point (x,y) is inside the module with number moduleNo 
-  //
-  // DebugGuard guard("AliFMDRing::IsWithin");
-  AliDebug(10, "AliFMDRing::IsWithin");
-  bool   ret            = false;
-  double r2             = x * x + y * y;
-  if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) {
-    // double point_angle    = TMath::ATan2(y, x);
-    // int    n_modules      = 360 / Int_t(fTheta * 2);
-    double m_angle        = (.5 + moduleNo) * 2 * fTheta;
-    double m_radians      = TMath::Pi() * m_angle / 180.;
-    
-    // Rotate the point.
-    double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians);
-    double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians);
+  // Get the total depth of a module (sensor + hybrid card) 
+  // 
+  // The depth is the sum of 
+  // 
+  //   The silicon thickness 
+  //   The thickness of spacers between the silicon and hybrid
+  //   The thickness of the hybrid PCB
+  //   The thickness of the copper layer in the PCB
+  //   The thickness of the chip layer in the PCB
+  //   The height of the legs
+  return (GetSiThickness() 
+         + GetSpacing() 
+         + GetPrintboardThickness()
+         + GetCopperThickness()
+         + GetChipThickness()
+         + GetLegLength());
   
-    ret = fPolygon.Contains(xr,yr);
-  }
-  return ret;
 }
 
-
-
-
 //____________________________________________________________________
-void
-AliFMDRing::Draw(Option_t* option) const
+Double_t
+AliFMDRing::GetFullDepth() const
 {
-  // Draw a the shape of the ring into a 2D histogram.  Useful for
-  // superimposing the actual shape of the ring onto a scatter plot of
-  // hits in the detector. 
-  // 
-  // DebugGuard guard("AliFMDRing::Draw");
-  AliDebug(10, "AliFMDRing::Draw");
-  // The unrotated coordinates of the polygon verticies
-  if (fPolygon.GetNVerticies() < 1) return;
-  
-  TVector2 v[6];
-  for (size_t i = 0; i < fPolygon.GetNVerticies(); i++) 
-    v[i] = fPolygon.GetVertex(i);
-  
-  Int_t    nModules  = 360 / Int_t(fTheta * 2);
-  Double_t dTheta    = fTheta * 2;
-  
-  TString opt(option);
-  if (opt.Contains("B", TString::kIgnoreCase)) {
-    opt.Remove(opt.Index("B", 1, TString::kIgnoreCase),1);
-    TH1* null = new TH2F("null", "Null",
-                        100, -fHighR * 1.1, fHighR * 1.1, 
-                        100, -fHighR * 1.1, fHighR * 1.1);
-    null->SetStats(0);
-    null->Draw(opt.Data());
-  }
-   
-  for (int i = 0; i < nModules; i++) {
-    Double_t theta = (i + .5) * dTheta;
-    AliFMDPolygon p;
-    for (int j = 0; j < 6; j++) {
-      TVector2 vr(v[j].Rotate(TMath::Pi() * theta / 180.));
-      if (!p.AddVertex(vr.X(),vr.Y())) {
-       // std::cerr << "Draw of polygon " << i << " failed" << std::endl;
-       break;
-      }
-    }
-    p.Draw(opt.Data(), Form("MOD%c_%d", fId, i));
-  }
-  if (opt.Contains("0", TString::kIgnoreCase)) {
-    TArc* arcH = new TArc(0,0, fHighR);
-    arcH->SetLineStyle(2);
-    arcH->SetLineColor(4);
-    arcH->Draw();
-
-    TArc* arcL = new TArc(0,0, fLowR);
-    arcL->SetLineStyle(2);
-    arcL->SetLineColor(4);
-    arcL->Draw();
-  }
+  // Get the full depth of this ring, including the honeycomb, 
+  // digitizer and card. 
+  return (GetModuleDepth() 
+         + GetModuleSpacing()
+         + GetHoneycombThickness()
+         + GetFMDDPrintboardThickness()
+         + GetFMDDCopperThickness()
+         + GetFMDDChipThickness() 
+         + 0.5);
 }
 
 //____________________________________________________________________
-void 
-AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, 
-                         Int_t pbRotId, Int_t idRotId)
+void
+AliFMDRing::Detector2XYZ(UShort_t sector,
+                        UShort_t strip, 
+                        Double_t& x, 
+                        Double_t& y, 
+                        Double_t& z) 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 
+  // Translate detector coordinates (this,sector,strip) to global
+  // coordinates (x,y,z)
   // 
-  //    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 
+  // Parameters 
+  //    sector        Sector number in this ring 
+  //    strip         Strip number in this ring 
+  //    x             On return, the global X coordinate
+  //    y             On return, the global Y coordinate 
+  //    z             On return, the z coordinate in the ring plane 
   //
-  // DebugGuard guard("AliFMDRing::SetupGeometry");
-  AliDebug(10, "AliFMDRing::SetupGeometry");
-
-  const TVector2& bCorner   = fPolygon.GetVertex(3); // Third  corner
-  const TVector2& aCorner   = fPolygon.GetVertex(5); // First  corner
-  const TVector2& cCorner   = fPolygon.GetVertex(4); // Second corner
-  TString name;
-  TString name2;
-  Double_t dStrip     = (bCorner.Mod() - aCorner.Mod()) / fNStrips;
-  Double_t stripOff   = aCorner.Mod();
-  Double_t rmin       = fLowR;
-  Double_t rmax       = bCorner.Mod();
-  Double_t pars[10];
-  fRingDepth          = (fSiThickness 
-                        + fPrintboardThickness 
-                        + fLegLength 
-                        + fModuleSpacing);
-
-  // Ring virtual volume 
-  pars[0]             = rmin;
-  pars[1]             = 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, 'F', fId);
-  fVirtualFrontId     = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5);
-
-  // Virtual volume for modules with long legs 
-  pars[2]             =  (fRingDepth - fModuleSpacing) / 2;
-  name                =  Form(fgkVirtualFormat, 'B', fId);
-  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, 'T', fId);
-  fPrintboardTopId    = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
-
-  // Bottom of the print board
-  pars[0]             = aCorner.Y() - pars[4];
-  pars[1]             = cCorner.Y() - pars[4];
-  pars[3]             = (cCorner.X() - aCorner.X()) / 2;
-  name                = Form(fgkPrintboardFormat, 'B', fId);
-  fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4);
-
-  // Define rotation matricies
-  Int_t    nModules  = 360 / Int_t(fTheta * 2);
-  Double_t dTheta    = fTheta * 2;
-  fRotations.Set(nModules);
-  for (int i = 0; i < nModules; i++) {
-    Double_t theta  = (i + .5) * dTheta;
-    Int_t    idrot  = 0;
-    // Rotation matrix for virtual module volumes
-    gMC->Matrix(idrot, 90, theta, 90, fmod(90 + theta, 360), 0, 0);
-    fRotations[i] = idrot;
+  // The ring plane is the plane half way between the two sensor
+  // layers. 
+  if (sector >= GetNSectors()) {
+    Error("Detector2XYZ", "Invalid sector number %d (>=%d) in ring %c", 
+         sector, GetNSectors(), fId);
+    return;
   }
-
-
-  // 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, (isFront ? 'F' : 'B'), fId);
-    dz   = (w - fRingDepth) / 2;
-    gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i]);
-
-    // We only need to place the children once, they are copied when
-    // we place the other virtual volumes. 
-    if (i > 1) continue;
-    name2 = name;
-
-    // Place active silicon wafer - this is put so that the front of
-    // the silicon is on the edge of the virtual volume. 
-    name  = Form(fgkActiveFormat, fId);
-    dz    = (w - fSiThickness) / 2;
-    gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId);
-
-    // Place print board.  This is put immediately behind the silicon
-    name = Form(fgkPrintboardFormat, 'T', fId);
-    dz   =  w / 2 - fSiThickness - fPrintboardThickness / 2;
-    gMC->Gspos(name.Data(), id, name2.Data(), 
-              fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY");
-    name = Form(fgkPrintboardFormat, 'B', fId);
-    gMC->Gspos(name.Data(), id, name2.Data(), 
-              fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY");
-
-    // Support legs 
-    // This is put immediately behind the pringboard. 
-    dz     = (w / 2 - fSiThickness - fPrintboardThickness 
-            - (fLegLength + (isFront ? fModuleSpacing : 0)) /2);
-    name  = (isFront ? "FLL" : "FSL");
-    gMC->Gspos(name.Data(), id*10 + 1, name2.Data(), 
-              aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, "");
-    Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius;
-    gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(), y,dz,idRotId,"");
-    gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(), -y,dz,idRotId,"");
+  if (strip >= GetNStrips()) {
+    Error("Detector2XYZ", "Invalid strip number %d (>=%d) for ring type '%c'", 
+         strip, GetNStrips(), fId);
+    return;
   }
+  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);
 }
+
 //____________________________________________________________________
-void 
-AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z, 
-                    Int_t /* pbRotId */, Int_t idRotId)
+Bool_t
+AliFMDRing::XYZ2Detector(Double_t  x, 
+                        Double_t  y, 
+                        Double_t  z,
+                        UShort_t& sector,
+                        UShort_t& strip) const
 {
-  // Positions a RNGx volume inside a mother. 
+  // Translate global coordinates (x,y,z) to detector coordinates
+  // (this,sector,strip)
   // 
-  // 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 
+  //  Parameters: 
+  //     x       Global x coordinate 
+  //     y       Global y coordinate
+  //     z       Global y coordinate
+  //     sector  On return, the sector number in this ring
+  //     strip   On return, the strip number in this ring
   // 
-  // DebugGuard guard("AliFMDRing::Geometry");
-  AliDebug(10, "AliFMDRing::Geometry");
-  TString  name;
-  Double_t offsetZ   = (fSiThickness 
-                       + fPrintboardThickness 
-                       + fLegLength + fModuleSpacing) / 2;
-  name = Form(fgkRingFormat, fId);
-  gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, "");
-}
+  sector = strip = 0;
+  Double_t r = TMath::Sqrt(x * x + y * y);
+  Int_t str = Int_t((r - fMinR) / GetPitch());
+  if (str < 0 || str >= GetNStrips()) return kFALSE;
+
+  Double_t phi = TMath::ATan2(y, x) * 180. / TMath::Pi();
+  if (phi < 0) phi = 360. + phi;
+  Int_t sec = Int_t(phi / fTheta);
+  if (sec < 0 || sec >= GetNSectors()) return kFALSE;
+  if ((sec / 2) % 2 == 1) {
+    if (TMath::Abs(z - TMath::Sign(fModuleSpacing, z)) >= 0.01)
+      return kFALSE;
+  }
+  else if (TMath::Abs(z) >= 0.01) return kFALSE;
 
+  strip  = str;
+  sector = sec;
+  return kTRUE;
+}
 //____________________________________________________________________
-void 
-AliFMDRing::SimpleGeometry(TList* nodes, 
-                          TNode* mother, 
-                          Int_t colour, 
-                          Double_t z, 
-                          Int_t n) 
+Float_t 
+AliFMDRing::GetStripLength(UShort_t strip) const 
 {
-  // Make a simple geometry of the ring for event display. 
+  // Get the length of a strip 
   // 
-  // The simple geometry is made from ROOT TNode and TShape objects. 
-  // Note, that we cache the TShape and TRotMatrix objects used for
-  // this. 
+  // Parameters:
+  //   strip     Strip number (0-511 for inners, 0-255 for outers)
   // 
-  // Parameters
-  // 
-  //    nodes     List of nodes to register all create nodes in 
-  //    mother    Mother node to put the ring in. 
-  //    colour    Colour of the nodes 
-  //    z         Z position of the node in the mother volume 
-  //    n         Detector number
-  //
-  // DebugGuard guard("AliFMDRing::SimpleGeometry");
-  AliDebug(10, "AliFMDRing::SimpleGeometry");
-  SetupCoordinates();
-
-  // If the shape hasn't been defined yet, we define it here. 
-  if (!fShape) {
-    TString name(Form(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);
-  }
+  if(strip >= GetNStrips())
+    Error("GetStripLength", "Invalid strip number %d (>=%d) for ring type %c", 
+         strip, GetNStrips(), fId);
   
-  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);
+  Float_t rad        = GetMaxR()-GetMinR();
+  
+  Float_t segment    = rad / GetNStrips();
+  
+  TVector2* corner1  = GetVertex(2);  
+  TVector2* corner2  = GetVertex(3);
+  
+  Float_t slope      = ((corner1->Y() - corner2->Y()) / 
+                       (corner1->X() - corner2->X()));
+  Float_t constant   = ((corner2->Y() * corner1->X() - 
+                        (corner2->X()*corner1->Y())) / 
+                       (corner1->X() - corner2->X()));
+  Float_t radius     = GetMinR() + strip*segment;
+  
+  Float_t d          = (TMath::Power(TMath::Abs(radius*slope),2) + 
+                       TMath::Power(radius,2) - TMath::Power(constant,2));
+  
+  Float_t arclength  = GetBaseStripLength(strip);
+  if(d>0) {
+    Float_t x        = ((-1 * TMath::Sqrt(d) -slope*constant) / 
+                       (1 + TMath::Power(slope,2)));
+    Float_t y        = slope*x + constant;
+    Float_t theta    = TMath::ATan2(x,y);
+    
+    if(x < corner1->X() && y > corner1->Y()) {
+      //One sector since theta is by definition half-hybrid
+      arclength = radius*theta;
     }
   }
-
-  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);
-  }
-}
-
   
-
+  return arclength;
+  
+  
+}
 //____________________________________________________________________
-void 
-AliFMDRing::Gsatt() 
-{
-  // Set drawing attributes for the RING 
+Float_t 
+AliFMDRing::GetBaseStripLength(UShort_t strip) const 
+{  
+  // Get the basic strip length 
   // 
-  // DebugGuard guard("AliFMDRing::Gsatt");
-  AliDebug(10, "AliFMDRing::Gsatt");
-  TString name;
-  name = Form(fgkRingFormat,fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkVirtualFormat, 'T', fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkVirtualFormat, 'B', fId);
-  gMC->Gsatt(name.Data(), "SEEN", 0);
-
-  name = Form(fgkActiveFormat,fId);
-  gMC->Gsatt(name.Data(), "SEEN", 1);
-
-  name = Form(fgkPrintboardFormat, 'T', fId);
-  gMC->Gsatt(name.Data(), "SEEN", 1);
-
-  name = Form(fgkPrintboardFormat, 'B',fId);
-  gMC->Gsatt(name.Data(), "SEEN", 1);
+  // Parameters:
+  //   strip    Strip number
+  Float_t rad             = GetMaxR()-GetMinR();
+  Float_t segment         = rad / GetNStrips();
+  Float_t basearc         = 2*TMath::Pi() / (0.5*GetNSectors()); 
+  Float_t radius          = GetMinR() + strip*segment;
+  Float_t basearclength   = 0.5*basearc * radius;                
+  
+  return basearclength;
 }
-
 //
 // EOF
 //