* 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
//
-#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";
+// #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.
- //
- // id Id of the ring (either 'i' or 'o').
- // detailed Whether the strips are made or not.
- //
+ // CTOR
+ 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
+#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
- //
- 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;
+ // Get the i'th vertex of polygon shape
+ 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(30, Form("\tInitializing ring %c", fId));
- fPolygon.Clear();
- SetupCoordinates();
+ // Get the i'th vertex of polygon shape
+ return static_cast<TVector2*>(fSensorVerticies.At(i));
}
//____________________________________________________________________
-AliFMDRing::~AliFMDRing()
+TVector2*
+AliFMDRing::GetHybridVertex(Int_t i) const
{
- // Destructor - deletes shape and rotation matricies
- AliDebug(30, Form("\tDestructing ring %c", fId));
- if (fShape) delete fShape;
- if (fRotMatricies) delete fRotMatricies;
+ // Get the i'th vertex of polygon shape
+ return static_cast<TVector2*>(fHybridVerticies.At(i));
}
-
//____________________________________________________________________
-void
-AliFMDRing::Browse(TBrowser* /* b */)
+TVector2*
+AliFMDRing::GetFootPosition(Int_t i) const
{
- // DebugGuard guard("AliFMDRing::Browse");
- AliDebug(30, Form("\tBrowsing ring %c", fId));
+ // Get the i'th vertex of polygon shape
+ 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.
- //
- //
-
- // 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);
+ // Return the nominal strip radius
+ 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(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);
+ return (GetSiThickness()
+ + GetSpacing()
+ + GetPrintboardThickness()
+ + GetCopperThickness()
+ + GetChipThickness()
+ + GetLegLength());
- ret = fPolygon.Contains(xr,yr);
- }
- return ret;
}
-
-
+//____________________________________________________________________
+Double_t
+AliFMDRing::GetFullDepth() const
+{
+ return (GetModuleDepth()
+ + GetModuleSpacing()
+ + GetHoneycombThickness()
+ + GetFMDDPrintboardThickness()
+ + GetFMDDCopperThickness()
+ + GetFMDDChipThickness()
+ + 0.5);
+}
//____________________________________________________________________
void
-AliFMDRing::Draw(Option_t* option) const
+AliFMDRing::Detector2XYZ(UShort_t sector,
+ UShort_t strip,
+ Double_t& x,
+ Double_t& y,
+ Double_t& z) 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(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);
-
- 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());
+ // Translate detector coordinates (this,sector,strip) to global
+ // coordinates (x,y,z)
+ if (sector >= GetNSectors()) {
+ Error("Detector2XYZ", "Invalid sector number %d (>=%d) in ring %c",
+ sector, GetNSectors(), fId);
+ return;
}
-
- 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();
+ if (strip >= GetNStrips()) {
+ Error("Detector2XYZ", "Invalid strip number %d (>=%d)",
+ 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::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId,
- 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
{
- // 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;
+ // Translate global coordinates (x,y,z) to detector coordinates
+ // (this,sector,strip)
+ 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;
-
- // 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");
- }
+ strip = str;
+ sector = sec;
+ return kTRUE;
}
//____________________________________________________________________
-void
-AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z,
- Int_t /* pbRotId */, Int_t idRotId)
+Float_t
+AliFMDRing::GetStripLength(UShort_t strip) const
{
- // 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");
-}
-
-//____________________________________________________________________
-void
-AliFMDRing::SimpleGeometry(TList* nodes,
- TNode* mother,
- Int_t colour,
- Double_t z,
- Int_t n)
-{
- // Make a simple geometry of the ring for event display.
- //
- // The simple geometry is made from ROOT TNode and TShape objects.
- // Note, that we cache the TShape and TRotMatrix objects used for
- // this.
- //
- // Parameters
- //
- // nodes List of nodes to register all create nodes in
- // mother Mother node to put the ring in.
- // colour Colour of the nodes
- // z Z position of the node in the mother volume
- // n Detector number
- //
- // DebugGuard guard("AliFMDRing::SimpleGeometry");
- 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);
- }
+ if(strip >= GetNStrips())
+ Error("GetStripLength", "Invalid strip number %d (>=%d)",
+ 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()) {
+ arclength = radius*theta; //One sector since theta is by definition half-hybrid
+
}
+
}
-
- 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
- //
- // 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);
+Float_t
+AliFMDRing::GetBaseStripLength(UShort_t strip) const
+{
+ Float_t rad = GetMaxR()-GetMinR();
+ Float_t segment = rad / GetNStrips();
+ Float_t basearc = 2*TMath::Pi() / (0.5*GetNSectors()); // One hybrid: 36 degrees inner, 18 outer
+ Float_t radius = GetMinR() + strip*segment;
+ Float_t basearclength = 0.5*basearc * radius; // One sector
+
+ return basearclength;
}
-
//
// EOF
//