Bug fixed (Christian)
[u/mrichter/AliRoot.git] / FMD / AliFMDDetector.cxx
CommitLineData
1a1fdef7 1/**************************************************************************
2 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
1a1fdef7 15/* $Id$ */
c2fc1258 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
02a27b50 20 @ingroup FMD_base
c2fc1258 21*/
1a1fdef7 22
23//____________________________________________________________________
24//
6169f936 25// AliFMDDetector.
26//
27// Base class for concrete FMD detectors, like AliFMD1, AliFMD2,
28// AliFMD3.
1a1fdef7 29// Utility class to help implement the FMD geometry. This provides
30// the interface for the concrete geometry implementations of the FMD
31// sub-detectors.
32//
33// The AliFMDGeometry object owns the AliFMDDetector objects
34//
35// Latest changes by Christian Holm Christensen
36//
37#include "AliFMDDetector.h" // ALIFMDSUBDETECTOR_H
38#include "AliFMDRing.h" // ALIFMDRING_H
bf000c32 39#include "AliLog.h" // ALILOG_H
40#include <TGeoManager.h> // ROOT_TGeoManager
41#include <TGeoMatrix.h> // ROOT_TGeoMatrix
02a27b50 42// #include <TMath.h> // ROOT_TMath
1a1fdef7 43
44//====================================================================
45ClassImp(AliFMDDetector)
46#if 0
47 ; // This is here to keep Emacs for indenting the next line
48#endif
49
50//____________________________________________________________________
51AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer)
52 : TNamed(Form("FMD%d", id), "Forward multiplicity ring"),
53 fId(id),
b5ee4425 54 fInnerZ(0.),
55 fOuterZ(0.),
56 fHoneycombThickness(0.),
57 fAlThickness(0.),
58 fInnerHoneyLowR(0.),
59 fInnerHoneyHighR(0.),
60 fOuterHoneyLowR(0.),
61 fOuterHoneyHighR(0.),
1a1fdef7 62 fInner(inner),
bf000c32 63 fOuter(outer),
64 fInnerTransforms(0),
65 fOuterTransforms(0)
1a1fdef7 66{
088f8e79 67 // Constructor
68 //
69 // ID Id of detector (1,2, or 3)
70 // INNER Inner ring geometry
71 // OUTER Outer ring geometry (if any)
72 //
1a1fdef7 73 SetHoneycombThickness();
74 SetAlThickness();
75 SetInnerHoneyLowR(0);
76 SetInnerHoneyHighR(0);
77 SetInnerZ(0);
78 SetOuterZ(0);
79 SetOuterHoneyLowR(0);
80 SetOuterHoneyHighR(0);
81}
82
83//____________________________________________________________________
088f8e79 84AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
85 : TNamed(other),
86 fId(other.fId),
b5ee4425 87 fInnerZ(0.),
88 fOuterZ(0.),
89 fHoneycombThickness(0.),
90 fAlThickness(0.),
91 fInnerHoneyLowR(0.),
92 fInnerHoneyHighR(0.),
93 fOuterHoneyLowR(0.),
94 fOuterHoneyHighR(0.),
088f8e79 95 fInner(other.fInner),
bf000c32 96 fOuter(other.fOuter),
97 fInnerTransforms(other.fInnerTransforms),
98 fOuterTransforms(other.fOuterTransforms)
088f8e79 99{
100 // Copy constructor
101 SetHoneycombThickness(other.GetHoneycombThickness());
102 SetAlThickness(other.GetAlThickness());
103 SetInnerHoneyLowR(other.GetInnerHoneyLowR());
104 SetInnerHoneyHighR(other.GetInnerHoneyHighR());
105 SetInnerZ(other.GetInnerZ());
106 SetOuterZ(other.GetOuterZ());
107 SetOuterHoneyLowR(other.GetOuterHoneyLowR());
108 SetOuterHoneyHighR(other.GetOuterHoneyHighR());
109}
110
111//____________________________________________________________________
112AliFMDDetector&
113AliFMDDetector::operator=(const AliFMDDetector& other)
114{
115 // Assignment operator
116 SetName(other.GetName());
117 SetTitle(other.GetTitle());
bf000c32 118 fId = other.fId;
119 fInner = other.fInner;
120 fOuter = other.fOuter;
121 fInnerTransforms = other.fInnerTransforms;
122 fOuterTransforms = other.fOuterTransforms;
088f8e79 123 SetHoneycombThickness(other.GetHoneycombThickness());
124 SetAlThickness(other.GetAlThickness());
125 SetInnerHoneyLowR(other.GetInnerHoneyLowR());
126 SetInnerHoneyHighR(other.GetInnerHoneyHighR());
127 SetInnerZ(other.GetInnerZ());
128 SetOuterZ(other.GetOuterZ());
129 SetOuterHoneyLowR(other.GetOuterHoneyLowR());
130 SetOuterHoneyHighR(other.GetOuterHoneyHighR());
131 return *this;
132}
133
134//____________________________________________________________________
1a1fdef7 135void
136AliFMDDetector::Init()
137{
088f8e79 138 // Initialize.
1a1fdef7 139 if (fInner) {
140 SetInnerHoneyLowR(fInner->GetLowR() + 1.);
141 SetInnerHoneyHighR(fInner->GetHighR() + 1.);
142 }
143 if (fOuter) {
144 SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
145 SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
bf000c32 146 }
147}
148
149//____________________________________________________________________
150Bool_t
151AliFMDDetector::HasAllTransforms(Char_t ring) const
152{
02a27b50 153 // Check if we got all transformations for a given ring. Return
154 // true in that case.
bf000c32 155 AliFMDRing* r = GetRing(ring);
156 if (!r) return kTRUE;
157 TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
158 if (!matricies) return kTRUE;
159 if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
160 return kFALSE;
161}
162
163#define IS_NODE_THIS(name) \
164 (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
165 (name[3] == 'T' || name[3] == 'B'))
166#define IS_NODE_SENSOR(name) \
167 (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
168
169//____________________________________________________________________
170void
171AliFMDDetector::InitTransformations()
172{
02a27b50 173 // Find all local<->global transformations for this detector.
bf000c32 174 if ((!fInner || (fInner && fInnerTransforms)) &&
175 (!fOuter || (fOuter && fOuterTransforms))) {
176 AliDebug(5, Form("Transforms for FMD%d already registered", fId));
177 return;
178 }
179 AliDebug(5, Form("Initializing transforms for FMD%d", fId));
180 if (!gGeoManager) {
181 AliFatal("No TGeoManager defined");
182 return;
183 }
184 TGeoVolume* topVolume = gGeoManager->GetTopVolume();
185 if (!topVolume) {
186 AliFatal("No top-level volume defined");
187 return;
188 }
189 // Make container of transforms
190 if (fInner && !fInnerTransforms)
191 fInnerTransforms = new TObjArray(fInner->GetNModules());
192 if (fOuter && !fOuterTransforms)
193 fOuterTransforms = new TObjArray(fOuter->GetNModules());
194
195 // Make an iterator
196 TGeoIterator next(topVolume);
197 TGeoNode* node = 0;
198
199 // Find the node corresponding to this detector, and then find the
200 // sensor volumes
201 Bool_t thisNodeFound = kFALSE;
202 Bool_t allInners = HasAllTransforms('I');
203 Bool_t allOuters = HasAllTransforms('O');
204
205 while ((node = static_cast<TGeoNode*>(next()))
206 && !(allInners && allOuters)) {
207 // Get nodes names
208 const Char_t* name = node->GetName();
209 if (!name) continue;
210 AliDebug(50, Form("Got volume %s", name));
211 // Check if this node is this detector
212 // The base offset for numbers in the ASCII table is 48
213 if (IS_NODE_THIS(name)) {
214 AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
215 thisNodeFound = kTRUE;
216 }
217 // if the detector was found, then we're on that branch, and we
218 // check if this node represents a module in that branch.
219 if (thisNodeFound && IS_NODE_SENSOR(name)) {
220 AliDebug(20, Form("Found sensor node '%s' for FMD%d", name, fId));
221 // Get the ring Id.
222 Char_t ringid = name[1];
223
224 // Get the approprate ring
225 AliFMDRing* ring = GetRing(ringid);
226 if (!ring) continue;
227
228 // Check whether we have all the modules we need for this ring,
229 // and if so, go on to the next node.
230 Bool_t& done = (ring == fInner ? allInners : allOuters);
231 if ((done = HasAllTransforms(ringid))) {
232 AliDebug(20, Form("Already has all module transforms for ring %c",
233 ringid));
234 continue;
235 }
236
237 // Get the approprate container
238 TObjArray* matricies = (ringid == 'i' || ringid == 'I'
239 ? fInnerTransforms : fOuterTransforms);
240
241 // Get the copy (module) number, and check that it hasn't
242 // already been added to the container.
243 Int_t copy = node->GetNumber();
244 if (matricies->At(copy)) {
245 AliWarning(Form("Have a transformation for module %d in ring %c",
246 copy, ringid));
247 continue;
248 }
249
250 // Get the global transformation matrix, and store it.
251 TGeoMatrix* trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
252 matricies->AddAt(trans, copy);
253
254 }
1a1fdef7 255 }
1a1fdef7 256}
257
258//____________________________________________________________________
259AliFMDRing*
260AliFMDDetector::GetRing(Char_t id) const
261{
088f8e79 262 // Get the specified ring
263 //
264 // ID Id of ring ('I' or 'O')
265 //
1a1fdef7 266 switch (id) {
267 case 'i':
268 case 'I': return GetInner();
269 case 'o':
270 case 'O': return GetOuter();
271 }
272 return 0;
273}
274
275//____________________________________________________________________
276Double_t
277AliFMDDetector::GetRingZ(Char_t id) const
278{
088f8e79 279 // Get the z-coordinate specified ring
280 //
281 // ID Id of ring ('I' or 'O')
282 //
1a1fdef7 283 switch (id) {
284 case 'i':
285 case 'I': return GetInnerZ();
286 case 'o':
287 case 'O': return GetOuterZ();
288 }
289 return 0;
290}
bf000c32 291
292//____________________________________________________________________
293TGeoMatrix*
294AliFMDDetector::FindTransform(Char_t ring, UShort_t sector) const
295{
296 // Find the transformation that corresponds to sector sector in ring
297 // ring.
298 TObjArray* matricies = 0;
299 switch (ring) {
300 case 'i': case 'I': matricies = fInnerTransforms; break;
301 case 'o': case 'O': matricies = fOuterTransforms; break;
302 }
303 if (!matricies) {
304 AliWarning(Form("Unknown ring %c of FMD%d", ring, fId));
305 return 0;
306 }
307 UInt_t module = sector / 2;
308 TGeoMatrix* m = static_cast<TGeoMatrix*>(matricies->At(module));
309 if (!m) {
310 AliWarning(Form("No matrix found for sector %d in FMD%d%c",
311 sector, fId, ring));
312 return 0;
313 }
314 return m;
315}
316
317
1a1fdef7 318//____________________________________________________________________
319void
bf000c32 320AliFMDDetector::Detector2XYZ(Char_t ring,
1a1fdef7 321 UShort_t sector,
322 UShort_t strip,
323 Double_t& x,
324 Double_t& y,
325 Double_t& z) const
326{
088f8e79 327 // Translate detector coordinates (this,ring,sector,strip) into
328 // (x,y,z) coordinates (in global reference frame)
1a1fdef7 329 AliFMDRing* r = GetRing(ring);
330 if (!r) return;
bf000c32 331 TGeoMatrix* m = FindTransform(ring, sector);
332 if (!m) return;
333 Double_t rho = r->GetStripRadius(strip);
334 Double_t phi = ((sector % 2) - .5) * r->GetTheta();
335 Double_t siThick = r->GetSiThickness();
336 Double_t modThick = (siThick
337 + r->GetPrintboardThickness()
338 + r->GetCopperThickness()
339 + r->GetChipThickness()
340 + r->GetSpacing());
15b17c89 341 AliDebug(30,Form("Rho %7.3f, angle %7.3f", rho, phi));
bf000c32 342# define DEGRAD TMath::Pi() / 180.
343 Double_t local[] = { rho * TMath::Cos(phi * DEGRAD),
344 rho * TMath::Sin(phi * DEGRAD),
345 -modThick + siThick / 2 };
346 Double_t master[3];
15b17c89 347 AliDebug(30, Form("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
bf000c32 348 m->LocalToMaster(local, master);
15b17c89 349 AliDebug(30, Form("Master (%7.3f,%7.3f,%7.3f)",
bf000c32 350 master[0],master[1],master[2]));
351 x = master[0];
352 y = master[1];
353 z = master[2];
1a1fdef7 354}
355
356//____________________________________________________________________
54e415a8 357Bool_t
358AliFMDDetector::XYZ2Detector(Double_t x,
359 Double_t y,
360 Double_t z,
361 Char_t& ring,
362 UShort_t& sector,
363 UShort_t& strip) const
364{
088f8e79 365 // Translate (x,y,z) coordinates (in global reference frame) into
366 // detector coordinates (this,ring,sector,strip).
54e415a8 367 AliFMDRing* rng = 0;
368 ring = -1;
369 for (int j = 0; j < 2; j++) {
370 rng = GetRing(j == 0 ? 'I' : 'O');
371 if (!rng) continue;
372 Double_t ringZ = GetRingZ(j == 0 ? 'I' : 'O');
373 Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
374 if (TMath::Abs(z - ringZ) < 0.01 ||
375 TMath::Abs(z - ringZ + modSpace) < 0.01) break;
376 rng = 0;
377 }
378 if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
379 sector, strip)) {
380 ring = rng->GetId();
381 return kTRUE;
382 }
383 return kFALSE;
384}
385
386
387
388//____________________________________________________________________
1a1fdef7 389//
390// EOF
391//