X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=FMD%2FAliFMDRing.cxx;h=6eebbcd0b5f903ba4f1c98e9ff11cd58dc861aa9;hb=45cffd060c32f4e2f25f4e81ba563e52cc1de90d;hp=9f94ba71793a0c67b14dc3a4fa7f479fbb38c909;hpb=7c09877a6350a57099a23e14612403064376469b;p=u%2Fmrichter%2FAliRoot.git diff --git a/FMD/AliFMDRing.cxx b/FMD/AliFMDRing.cxx index 9f94ba71793..6eebbcd0b5f 100644 --- a/FMD/AliFMDRing.cxx +++ b/FMD/AliFMDRing.cxx @@ -12,651 +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 -#include -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 // ROOT_TMath +#include // ROOT_TVector2 +// #include // 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(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(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(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(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)", + 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)", + 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("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 //