X-Git-Url: http://git.uio.no/git/?p=u%2Fmrichter%2FAliRoot.git;a=blobdiff_plain;f=FMD%2FAliFMDRing.cxx;h=601e95fe26c00f1af26ef4fcb7dacd82cc6af441;hp=6feac4741c1ae09523e67cdd7e9d0357a5df6027;hb=0b1289d5ad2f180c1b55e43a2d66830b28462040;hpb=4347b38ff0813917a92cc4e1e0ee3f9bfef3f1bc diff --git a/FMD/AliFMDRing.cxx b/FMD/AliFMDRing.cxx index 6feac4741c1..601e95fe26c 100644 --- a/FMD/AliFMDRing.cxx +++ b/FMD/AliFMDRing.cxx @@ -1,5 +1,5 @@ /************************************************************************** - * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. * + * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * @@ -12,547 +12,427 @@ * 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 + @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 -#endif -#ifndef ROOT_TH2 -# include -#endif -#ifndef ROOT_TVirtualMC -# include -#endif -#ifndef ROOT_TVector2 -# include -#endif -#ifndef ROOT_TBrowser -# include -#endif -#ifndef ROOT_TString -# include -#endif -#ifndef ROOT_TArc -# include -#endif -#ifndef ROOT_TObjArray -# include -#endif -#ifndef ROOT_TXTRU -# include -#endif -#ifndef ROOT_TNode -# include -#endif -#ifndef ROOT_TRotMatrix -# include -#endif -#ifndef ROOT_TList -# include -#endif -#ifndef __IOSTREAM__ -# include -#endif -ClassImp(AliFMDRing); +#include // ROOT_TMath +#include // ROOT_TVector2 + +// #include // ALILOG_H +#include "AliFMDRing.h" // ALIFMDRING_H + +//==================================================================== +ClassImp(AliFMDRing) +#if 0 + ; // This is here to keep Emacs for indenting the next line +#endif //____________________________________________________________________ -// Construct a alifmdring. -// -// id Id of the ring (either 'i' or 'o'). -// lowr Lower radius of ring (in centimeters). -// highr Upper radius of ring (in centimeters). -// r Radius of the silicon wafers (in centimeters). -// theta Opening angle of the silicon wafers. -// strips Number of strips. -AliFMDRing::AliFMDRing(Char_t id, Bool_t detailed) - : fId(id), - fDetailed(detailed), - fWaferRadius(0), +AliFMDRing::AliFMDRing(Char_t id) + : TNamed(Form("FMD%c", id), "Forward multiplicity ring"), + fId(id), + fBondingWidth(0), + fWaferRadius(0), fSiThickness(0), - fLowR(0), - fHighR(0), - fTheta(0), - fNStrips(0), - fShape(0), - fRotMatricies(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), + fCopperThickness(0), + fChipThickness(0), + fSpacing(0), + fHoneycombThickness(0.), + fAlThickness(0.), + fVerticies(0), + fSensorVerticies(0), + fHybridVerticies(0), + fFeetPositions(0) +{ + // Constructor + // + // 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)); + } +} //____________________________________________________________________ -void -AliFMDRing::Init() +void +AliFMDRing::Init() { - // Initialize the ring object. - // DebugGuard guard("AliFMDRing::Init"); - AliDebug(10, "AliFMDRing::Init"); - fPolygon.Clear(); - SetupCoordinates(); + // 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() +TVector2* +AliFMDRing::GetVertex(Int_t i) const { - 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' sensors + // + // Parameters: + // i The vertex number to get (from 0 to 5) + return static_cast(fVerticies.At(i)); } - //____________________________________________________________________ -void -AliFMDRing::Browse(TBrowser* /* b */) +TVector2* +AliFMDRing::GetSensorVertex(Int_t i) const { - // DebugGuard guard("AliFMDRing::Browse"); - AliDebug(10, "AliFMDRing::Browse"); + // 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(fSensorVerticies.At(i)); } - //____________________________________________________________________ -void -AliFMDRing::SetupCoordinates() +TVector2* +AliFMDRing::GetHybridVertex(Int_t i) const { - // Calculates the parameters of the polygon shape. + // Get the i'th vertex of polygon shape // - // DebugGuard guard("AliFMDRing::SetupCoordinates"); - AliDebug(10, "AliFMDRing::SetupCoordinates"); - // Get out immediately if we have already done all this - if (fPolygon.GetNVerticies() > 1) return; - - double tan_theta = TMath::Tan(fTheta * TMath::Pi() / 180.); - double tan_theta2 = TMath::Power(tan_theta,2); - double r2 = TMath::Power(fWaferRadius,2); - double y_A = tan_theta * fLowR; - double lr2 = TMath::Power(fLowR, 2); - double hr2 = TMath::Power(fHighR,2); - double x_D = fLowR + TMath::Sqrt(r2 - tan_theta2 * lr2); - double x_D2 = TMath::Power(x_D,2); - //double x_D_2 = fLowR - TMath::Sqrt(r2 - tan_theta2 * lr2); - double y_B = sqrt(r2 - hr2 + 2 * fHighR * x_D - x_D2); - double x_C = ((x_D + TMath::Sqrt(-tan_theta2 * x_D2 + r2 - + r2 * tan_theta2)) - / (1 + tan_theta2)); - double y_C = tan_theta * x_C; - - fPolygon.AddVertex(fLowR, -y_A); - fPolygon.AddVertex(x_C, -y_C); - fPolygon.AddVertex(fHighR, -y_B); - fPolygon.AddVertex(fHighR, y_B); - fPolygon.AddVertex(x_C, y_C); - fPolygon.AddVertex(fLowR, y_A); + // 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(fHybridVerticies.At(i)); } //____________________________________________________________________ -bool -AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const +TVector2* +AliFMDRing::GetFootPosition(Int_t i) const { - // Checks if a point (x,y) is inside the module with number moduleNo - // - // DebugGuard guard("AliFMDRing::IsWithin"); - AliDebug(10, "AliFMDRing::IsWithin"); - bool ret = false; - double r2 = x * x + y * y; - if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) { - // double point_angle = TMath::ATan2(y, x); - // int n_modules = 360 / Int_t(fTheta * 2); - double m_angle = (.5 + moduleNo) * 2 * fTheta; - double m_radians = TMath::Pi() * m_angle / 180.; - - // Rotate the point. - double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians); - double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians); - - ret = fPolygon.Contains(xr,yr); - } - return ret; + // 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(fFeetPositions.At(i)); } - - - //____________________________________________________________________ -void -AliFMDRing::Draw(Option_t* option) const +Double_t +AliFMDRing::GetStripRadius(UShort_t strip) 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. + // Return the nominal strip radius // - // 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(); - } + // 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 } - + //____________________________________________________________________ -void -AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, - Int_t pbRotId, Int_t idRotId) +Double_t +AliFMDRing::GetModuleDepth() const { - // Setup the geometry of the ring. It defines the volumes - // RNGI or RNGO which can later be positioned in a sub-detector - // volume. + // Get the total depth of a module (sensor + hybrid card) // - // The hieracy of the RNGx volume is + // The depth is the sum of // - // RNGx // Ring volume - // VFx // Container of hybrid + legs - // ACTx // Active volume (si sensor approx) - // SECx // Section division - // STRx // Strip division - // PBTx // Print board (bottom) - // PTTx // Print board (top) - // LLEG // Support leg (long version) - // VBx // Container of hybrid + legs - // ACTx // Active volume (si sensor approx) - // SECx // Section division - // STRx // Strip division - // PBTx // Print board (bottom) - // PTTx // Print board (top) - // SLEG // Support leg (long version) - // - // Parameters: - // - // vacuumId Medium of inactive virtual volumes - // siId Medium of Silicon sensor (active) - // pcbId Medium of print boards - // pbRotId Print board rotation matrix - // idRotId Identity rotation matrix - // - // DebugGuard guard("AliFMDRing::SetupGeometry"); - AliDebug(10, "AliFMDRing::SetupGeometry"); - - const TVector2& bCorner = fPolygon.GetVertex(3); // Third corner - const TVector2& aCorner = fPolygon.GetVertex(5); // First corner - const TVector2& cCorner = fPolygon.GetVertex(4); // Second corner - TString name; - TString name2; - Double_t dStrip = (bCorner.Mod() - aCorner.Mod()) / fNStrips; - Double_t stripOff = aCorner.Mod(); - Double_t rmin = fLowR; - Double_t rmax = bCorner.Mod(); - Double_t pars[10]; - fRingDepth = (fSiThickness - + fPrintboardThickness - + fLegLength - + fModuleSpacing); - - // Ring virtual volume - pars[0] = rmin; - pars[1] = fHighR; - pars[2] = fRingDepth / 2; - name = Form("RNG%c", fId); - fRingId = gMC->Gsvolu(name.Data(), "TUBE", vacuumId, pars, 3); + // 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()); - // Virtual volume for modules with long legs - pars[1] = rmax; - pars[3] = -fTheta; - pars[4] = fTheta; - name = Form("VF%c", fId); - fVirtualFrontId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5); - - // Virtual volume for modules with long legs - pars[2] = (fRingDepth - fModuleSpacing) / 2; - name = Form("VB%c", fId); - fVirtualBackId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5); - - // Virtual mother volume for silicon - pars[2] = fSiThickness/2; - name2 = name; - name = Form("ACT%c",fId); - fActiveId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5); - - if (fDetailed) { - // Virtual sector volumes - name2 = name; - name = Form("SEC%c",fId); - gMC->Gsdvn2(name.Data(), name2.Data(), 2, 2, -fTheta, vacuumId); - fSectionId = gMC->VolId(name.Data()); - - // Active strip volumes - name2 = name; - name = Form("STR%c", fId); - gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1, - stripOff, siId, fNStrips); - fStripId = gMC->VolId(name.Data()); - } - - // Print-board on back of module - pars[4] = TMath::Tan(TMath::Pi() * fTheta / 180) * fBondingWidth; - // Top of the print board - pars[0] = cCorner.Y() - pars[4]; - pars[1] = bCorner.Y() - pars[4]; - pars[2] = fPrintboardThickness / 2; // PCB half thickness - pars[3] = (bCorner.X() - cCorner.X()) / 2; - name = Form("PBT%c", fId); - fPrintboardTopId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4); +} - // Bottom of the print board - pars[0] = aCorner.Y() - pars[4]; - pars[1] = cCorner.Y() - pars[4]; - pars[3] = (cCorner.X() - aCorner.X()) / 2; - name = Form("PBB%c", fId); - fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4); +//____________________________________________________________________ +Double_t +AliFMDRing::GetFullDepth() const +{ + // Get the full depth of this ring, including the honeycomb, + // digitizer and card. + return (GetModuleDepth() + + GetModuleSpacing() + + GetHoneycombThickness() + + GetFMDDPrintboardThickness() + + GetFMDDCopperThickness() + + GetFMDDChipThickness() + + 0.5); +} - // 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; +//____________________________________________________________________ +void +AliFMDRing::Detector2XYZ(UShort_t sector, + UShort_t strip, + Double_t& x, + Double_t& y, + Double_t& z) const +{ + // Translate detector coordinates (this,sector,strip) to global + // coordinates (x,y,z) + // + // 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 + // + // 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("RNG%c", fId); - - Int_t id = i; - // Double_t theta = (i + .5) * dTheta; - Bool_t isFront = (i % 2 == 1); - Double_t dz = 0; - Double_t w = fRingDepth - (isFront ? 0 : fModuleSpacing); - - // Place virtual module volume - name = Form("V%c%c", (isFront ? 'F' : 'B'), fId); - dz = (w - fRingDepth) / 2; - gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i]); - - // We only need to place the children once, they are copied when - // we place the other virtual volumes. - if (i > 1) continue; - name2 = name; - - // Place active silicon wafer - this is put so that the front of - // the silicon is on the edge of the virtual volume. - name = Form("ACT%c", fId); - dz = (w - fSiThickness) / 2; - gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId); - - // Place print board. This is put immediately behind the silicon - name = Form("PBT%c", fId); - dz = w / 2 - fSiThickness - fPrintboardThickness / 2; - gMC->Gspos(name.Data(), id, name2.Data(), - fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY"); - name = Form("PBB%c", fId); - gMC->Gspos(name.Data(), id, name2.Data(), - fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY"); - - // Support legs - // This is put immediately behind the pringboard. - dz = (w / 2 - fSiThickness - fPrintboardThickness - - (fLegLength + (isFront ? fModuleSpacing : 0)) /2); - name = (isFront ? "LLEG" : "SLEG"); - gMC->Gspos(name.Data(), id*10 + 1, name2.Data(), - aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, ""); - Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius; - gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(), y,dz,idRotId,""); - gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(), -y,dz ,idRotId,""); + 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("RNG%c", 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. - // - // The simple geometry is made from ROOT TNode and TShape objects. - // Note, that we cache the TShape and TRotMatrix objects used for - // this. + // Get the length of a strip // - // Parameters + // Parameters: + // strip Strip number (0-511 for inners, 0-255 for outers) // - // nodes List of nodes to register all create nodes in - // mother Mother node to put the ring in. - // colour Colour of the nodes - // z Z position of the node in the mother volume - // n Detector number - // - // DebugGuard guard("AliFMDRing::SimpleGeometry"); - AliDebug(10, "AliFMDRing::SimpleGeometry"); - SetupCoordinates(); - - // If the shape hasn't been defined yet, we define it here. - if (!fShape) { - TString name(Form("ACT%c", fId)); - TString title(Form("Shape of modules in %c Rings", fId)); - Int_t n = fPolygon.GetNVerticies(); - TXTRU* shape = new TXTRU(name.Data(), title.Data(), "void", n, 2); - for (Int_t i = 0; i < n; i++) { - const TVector2& v = fPolygon.GetVertex(i); - shape->DefineVertex(i, v.X(), v.Y()); - } - shape->DefineSection(0, - fSiThickness / 2, 1, 0, 0); - shape->DefineSection(1, + fSiThickness / 2, 1, 0, 0); - fShape = shape; - fShape->SetLineColor(colour); - } + 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(fRotMatricies->At(i)); - TString name(Form("ACT%c_%d_%d", fId, n, i)); - TString title(Form("Active FMD%d volume in %c Ring", n, fId)); - TNode* node = new TNode(name.Data(), title.Data(), fShape, - 0, 0, - z - offsetZ + (isFront ? fModuleSpacing : 0), - rot); - node->SetLineColor(colour); - nodes->Add(node); - } -} - - + 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("RNG%c",fId); - gMC->Gsatt(name.Data(), "SEEN", 0); - - name = Form("VF%c",fId); - gMC->Gsatt(name.Data(), "SEEN", 0); - - name = Form("VB%c",fId); - gMC->Gsatt(name.Data(), "SEEN", 0); - - name = Form("ACT%c",fId); - gMC->Gsatt(name.Data(), "SEEN", 1); - - name = Form("PBT%c",fId); - gMC->Gsatt(name.Data(), "SEEN", 1); - - name = Form("PBB%c",fId); - gMC->Gsatt(name.Data(), "SEEN", 1); + // 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 //