1 /**************************************************************************
2 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /** @file AliFMDDetector.cxx
17 @author Christian Holm Christensen <cholm@nbi.dk>
18 @date Mon Mar 27 12:36:27 2006
19 @brief Sub-detector base class implementation
23 //____________________________________________________________________
25 // Utility class to help implement the FMD geometry. This provides
26 // the interface for the concrete geometry implementations of the FMD
29 // The AliFMDGeometry object owns the AliFMDDetector objects
31 // Latest changes by Christian Holm Christensen
33 #include "AliFMDDetector.h" // ALIFMDSUBDETECTOR_H
34 #include "AliFMDRing.h" // ALIFMDRING_H
35 #include "AliLog.h" // ALILOG_H
36 #include <TGeoManager.h> // ROOT_TGeoManager
37 #include <TGeoMatrix.h> // ROOT_TGeoMatrix
38 // #include <TMath.h> // ROOT_TMath
40 //====================================================================
41 ClassImp(AliFMDDetector)
43 ; // This is here to keep Emacs for indenting the next line
46 //____________________________________________________________________
47 AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer)
48 : TNamed(Form("FMD%d", id), "Forward multiplicity ring"),
57 // ID Id of detector (1,2, or 3)
58 // INNER Inner ring geometry
59 // OUTER Outer ring geometry (if any)
61 SetHoneycombThickness();
64 SetInnerHoneyHighR(0);
68 SetOuterHoneyHighR(0);
71 //____________________________________________________________________
72 AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
77 fInnerTransforms(other.fInnerTransforms),
78 fOuterTransforms(other.fOuterTransforms)
81 SetHoneycombThickness(other.GetHoneycombThickness());
82 SetAlThickness(other.GetAlThickness());
83 SetInnerHoneyLowR(other.GetInnerHoneyLowR());
84 SetInnerHoneyHighR(other.GetInnerHoneyHighR());
85 SetInnerZ(other.GetInnerZ());
86 SetOuterZ(other.GetOuterZ());
87 SetOuterHoneyLowR(other.GetOuterHoneyLowR());
88 SetOuterHoneyHighR(other.GetOuterHoneyHighR());
91 //____________________________________________________________________
93 AliFMDDetector::operator=(const AliFMDDetector& other)
95 // Assignment operator
96 SetName(other.GetName());
97 SetTitle(other.GetTitle());
99 fInner = other.fInner;
100 fOuter = other.fOuter;
101 fInnerTransforms = other.fInnerTransforms;
102 fOuterTransforms = other.fOuterTransforms;
103 SetHoneycombThickness(other.GetHoneycombThickness());
104 SetAlThickness(other.GetAlThickness());
105 SetInnerHoneyLowR(other.GetInnerHoneyLowR());
106 SetInnerHoneyHighR(other.GetInnerHoneyHighR());
107 SetInnerZ(other.GetInnerZ());
108 SetOuterZ(other.GetOuterZ());
109 SetOuterHoneyLowR(other.GetOuterHoneyLowR());
110 SetOuterHoneyHighR(other.GetOuterHoneyHighR());
114 //____________________________________________________________________
116 AliFMDDetector::Init()
120 SetInnerHoneyLowR(fInner->GetLowR() + 1.);
121 SetInnerHoneyHighR(fInner->GetHighR() + 1.);
124 SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
125 SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
129 //____________________________________________________________________
131 AliFMDDetector::HasAllTransforms(Char_t ring) const
133 // Check if we got all transformations for a given ring. Return
134 // true in that case.
135 AliFMDRing* r = GetRing(ring);
136 if (!r) return kTRUE;
137 TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
138 if (!matricies) return kTRUE;
139 if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
143 #define IS_NODE_THIS(name) \
144 (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
145 (name[3] == 'T' || name[3] == 'B'))
146 #define IS_NODE_SENSOR(name) \
147 (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
149 //____________________________________________________________________
151 AliFMDDetector::InitTransformations()
153 // Find all local<->global transformations for this detector.
154 if ((!fInner || (fInner && fInnerTransforms)) &&
155 (!fOuter || (fOuter && fOuterTransforms))) {
156 AliDebug(5, Form("Transforms for FMD%d already registered", fId));
159 AliDebug(5, Form("Initializing transforms for FMD%d", fId));
161 AliFatal("No TGeoManager defined");
164 TGeoVolume* topVolume = gGeoManager->GetTopVolume();
166 AliFatal("No top-level volume defined");
169 // Make container of transforms
170 if (fInner && !fInnerTransforms)
171 fInnerTransforms = new TObjArray(fInner->GetNModules());
172 if (fOuter && !fOuterTransforms)
173 fOuterTransforms = new TObjArray(fOuter->GetNModules());
176 TGeoIterator next(topVolume);
179 // Find the node corresponding to this detector, and then find the
181 Bool_t thisNodeFound = kFALSE;
182 Bool_t allInners = HasAllTransforms('I');
183 Bool_t allOuters = HasAllTransforms('O');
185 while ((node = static_cast<TGeoNode*>(next()))
186 && !(allInners && allOuters)) {
188 const Char_t* name = node->GetName();
190 AliDebug(50, Form("Got volume %s", name));
191 // Check if this node is this detector
192 // The base offset for numbers in the ASCII table is 48
193 if (IS_NODE_THIS(name)) {
194 AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
195 thisNodeFound = kTRUE;
197 // if the detector was found, then we're on that branch, and we
198 // check if this node represents a module in that branch.
199 if (thisNodeFound && IS_NODE_SENSOR(name)) {
200 AliDebug(20, Form("Found sensor node '%s' for FMD%d", name, fId));
202 Char_t ringid = name[1];
204 // Get the approprate ring
205 AliFMDRing* ring = GetRing(ringid);
208 // Check whether we have all the modules we need for this ring,
209 // and if so, go on to the next node.
210 Bool_t& done = (ring == fInner ? allInners : allOuters);
211 if ((done = HasAllTransforms(ringid))) {
212 AliDebug(20, Form("Already has all module transforms for ring %c",
217 // Get the approprate container
218 TObjArray* matricies = (ringid == 'i' || ringid == 'I'
219 ? fInnerTransforms : fOuterTransforms);
221 // Get the copy (module) number, and check that it hasn't
222 // already been added to the container.
223 Int_t copy = node->GetNumber();
224 if (matricies->At(copy)) {
225 AliWarning(Form("Have a transformation for module %d in ring %c",
230 // Get the global transformation matrix, and store it.
231 TGeoMatrix* trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
232 matricies->AddAt(trans, copy);
238 //____________________________________________________________________
240 AliFMDDetector::GetRing(Char_t id) const
242 // Get the specified ring
244 // ID Id of ring ('I' or 'O')
248 case 'I': return GetInner();
250 case 'O': return GetOuter();
255 //____________________________________________________________________
257 AliFMDDetector::GetRingZ(Char_t id) const
259 // Get the z-coordinate specified ring
261 // ID Id of ring ('I' or 'O')
265 case 'I': return GetInnerZ();
267 case 'O': return GetOuterZ();
272 //____________________________________________________________________
274 AliFMDDetector::FindTransform(Char_t ring, UShort_t sector) const
276 // Find the transformation that corresponds to sector sector in ring
278 TObjArray* matricies = 0;
280 case 'i': case 'I': matricies = fInnerTransforms; break;
281 case 'o': case 'O': matricies = fOuterTransforms; break;
284 AliWarning(Form("Unknown ring %c of FMD%d", ring, fId));
287 UInt_t module = sector / 2;
288 TGeoMatrix* m = static_cast<TGeoMatrix*>(matricies->At(module));
290 AliWarning(Form("No matrix found for sector %d in FMD%d%c",
298 //____________________________________________________________________
300 AliFMDDetector::Detector2XYZ(Char_t ring,
307 // Translate detector coordinates (this,ring,sector,strip) into
308 // (x,y,z) coordinates (in global reference frame)
309 AliFMDRing* r = GetRing(ring);
312 TGeoMatrix* m = FindTransform(ring, sector);
314 Double_t rho = r->GetStripRadius(strip);
315 Double_t phi = ((sector % 2) - .5) * r->GetTheta();
316 Double_t siThick = r->GetSiThickness();
317 Double_t modThick = (siThick
318 + r->GetPrintboardThickness()
319 + r->GetCopperThickness()
320 + r->GetChipThickness()
322 AliDebug(10,Form("Rho %7.3f, angle %7.3f", rho, phi));
323 # define DEGRAD TMath::Pi() / 180.
324 Double_t local[] = { rho * TMath::Cos(phi * DEGRAD),
325 rho * TMath::Sin(phi * DEGRAD),
326 -modThick + siThick / 2 };
328 AliDebug(10, Form("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
329 m->LocalToMaster(local, master);
330 AliDebug(10, Form("Master (%7.3f,%7.3f,%7.3f)",
331 master[0],master[1],master[2]));
337 r->Detector2XYZ(sector, strip, x, y, z);
341 //____________________________________________________________________
343 AliFMDDetector::XYZ2Detector(Double_t x,
348 UShort_t& strip) const
350 // Translate (x,y,z) coordinates (in global reference frame) into
351 // detector coordinates (this,ring,sector,strip).
354 for (int j = 0; j < 2; j++) {
355 rng = GetRing(j == 0 ? 'I' : 'O');
357 Double_t ringZ = GetRingZ(j == 0 ? 'I' : 'O');
358 Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
359 if (TMath::Abs(z - ringZ) < 0.01 ||
360 TMath::Abs(z - ringZ + modSpace) < 0.01) break;
363 if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
373 //____________________________________________________________________