]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - FMD/AliFMDDetector.cxx
Typo corrected.
[u/mrichter/AliRoot.git] / FMD / AliFMDDetector.cxx
... / ...
CommitLineData
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 **************************************************************************/
15/* $Id$ */
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
20 @ingroup FMD_base
21*/
22
23//____________________________________________________________________
24//
25// AliFMDDetector.
26//
27// Base class for concrete FMD detectors, like AliFMD1, AliFMD2,
28// AliFMD3.
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
38#include <TGeoManager.h> // ROOT_TGeoManager
39#include <TGeoMatrix.h> // ROOT_TGeoMatrix
40#include <TMath.h> // ROOT_TMath
41
42#include "AliFMDDetector.h" // ALIFMDSUBDETECTOR_H
43#include "AliFMDRing.h" // ALIFMDRING_H
44#include "AliLog.h" // ALILOG_H
45
46//====================================================================
47ClassImp(AliFMDDetector)
48#if 0
49 ; // This is here to keep Emacs for indenting the next line
50#endif
51
52//____________________________________________________________________
53AliFMDDetector::AliFMDDetector(Int_t id, AliFMDRing* inner, AliFMDRing* outer)
54 : TNamed(Form("FMD%d", id), "Forward multiplicity ring"),
55 fId(id),
56 fInnerZ(0.),
57 fOuterZ(0.),
58 fHoneycombThickness(0.),
59 fAlThickness(0.),
60 fInnerHoneyLowR(0.),
61 fInnerHoneyHighR(0.),
62 fOuterHoneyLowR(0.),
63 fOuterHoneyHighR(0.),
64 fInner(inner),
65 fOuter(outer),
66 fInnerTransforms(0),
67 fOuterTransforms(0)
68{
69 // Constructor
70 //
71 // ID Id of detector (1,2, or 3)
72 // INNER Inner ring geometry
73 // OUTER Outer ring geometry (if any)
74 //
75 SetHoneycombThickness();
76 SetAlThickness();
77 SetInnerHoneyLowR(0);
78 SetInnerHoneyHighR(0);
79 SetInnerZ(0);
80 SetOuterZ(0);
81 SetOuterHoneyLowR(0);
82 SetOuterHoneyHighR(0);
83}
84
85//____________________________________________________________________
86AliFMDDetector::AliFMDDetector(const AliFMDDetector& other)
87 : TNamed(other),
88 fId(other.fId),
89 fInnerZ(0.),
90 fOuterZ(0.),
91 fHoneycombThickness(0.),
92 fAlThickness(0.),
93 fInnerHoneyLowR(0.),
94 fInnerHoneyHighR(0.),
95 fOuterHoneyLowR(0.),
96 fOuterHoneyHighR(0.),
97 fInner(other.fInner),
98 fOuter(other.fOuter),
99 fInnerTransforms(other.fInnerTransforms),
100 fOuterTransforms(other.fOuterTransforms)
101{
102 // Copy constructor
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());
111}
112
113//____________________________________________________________________
114AliFMDDetector&
115AliFMDDetector::operator=(const AliFMDDetector& other)
116{
117 // Assignment operator
118 SetName(other.GetName());
119 SetTitle(other.GetTitle());
120 fId = other.fId;
121 fInner = other.fInner;
122 fOuter = other.fOuter;
123 fInnerTransforms = other.fInnerTransforms;
124 fOuterTransforms = other.fOuterTransforms;
125 SetHoneycombThickness(other.GetHoneycombThickness());
126 SetAlThickness(other.GetAlThickness());
127 SetInnerHoneyLowR(other.GetInnerHoneyLowR());
128 SetInnerHoneyHighR(other.GetInnerHoneyHighR());
129 SetInnerZ(other.GetInnerZ());
130 SetOuterZ(other.GetOuterZ());
131 SetOuterHoneyLowR(other.GetOuterHoneyLowR());
132 SetOuterHoneyHighR(other.GetOuterHoneyHighR());
133 return *this;
134}
135
136//____________________________________________________________________
137void
138AliFMDDetector::Init()
139{
140 // Initialize.
141 if (fInner) {
142 SetInnerHoneyLowR(fInner->GetLowR() + 1.);
143 SetInnerHoneyHighR(fInner->GetHighR() + 1.);
144 }
145 if (fOuter) {
146 SetOuterHoneyLowR(fOuter->GetLowR() + 1.);
147 SetOuterHoneyHighR(fOuter->GetHighR() + 1.);
148 }
149}
150
151//____________________________________________________________________
152Bool_t
153AliFMDDetector::HasAllTransforms(Char_t ring) const
154{
155 // Check if we got all transformations for a given ring. Return
156 // true in that case.
157 AliFMDRing* r = GetRing(ring);
158 if (!r) return kTRUE;
159 TObjArray* matricies = (r == fInner ? fInnerTransforms : fOuterTransforms);
160 if (!matricies) return kTRUE;
161 if (matricies->GetEntries() == r->GetNModules()) return kTRUE;
162 return kFALSE;
163}
164
165#define IS_NODE_THIS(name) \
166 (name[0] == 'F' && name[2] == 'M' && name[1] == Char_t(48+fId) && \
167 (name[3] == 'T' || name[3] == 'B'))
168#define IS_NODE_SENSOR(name) \
169 (name[0] == 'F' && name[2] == 'S' && name[3] == 'E')
170#define IS_NODE_HALF(name) \
171 (name[0] == 'F' && name[2] == 'M' && (name[3] == 'B' || name[3] == 'T'))
172
173//____________________________________________________________________
174void
175AliFMDDetector::InitTransformations()
176{
177 // Find all local<->global transformations for this detector.
178 if ((!fInner || (fInner && fInnerTransforms)) &&
179 (!fOuter || (fOuter && fOuterTransforms))) {
180 AliDebug(5, Form("Transforms for FMD%d already registered", fId));
181 return;
182 }
183 AliDebug(5, Form("Initializing transforms for FMD%d", fId));
184 if (!gGeoManager) {
185 AliFatal("No TGeoManager defined");
186 return;
187 }
188 TGeoVolume* topVolume = gGeoManager->GetTopVolume();
189 if (!topVolume) {
190 AliFatal("No top-level volume defined");
191 return;
192 }
193 // Make container of transforms
194 if (fInner && !fInnerTransforms)
195 fInnerTransforms = new TObjArray(fInner->GetNModules());
196 if (fOuter && !fOuterTransforms)
197 fOuterTransforms = new TObjArray(fOuter->GetNModules());
198
199 // Make an iterator
200 TGeoIterator next(topVolume);
201 TGeoNode* node = 0;
202
203 // Find the node corresponding to this detector, and then find the
204 // sensor volumes
205 Bool_t thisNodeFound = kFALSE;
206 Bool_t allInners = HasAllTransforms('I');
207 Bool_t allOuters = HasAllTransforms('O');
208
209 while ((node = static_cast<TGeoNode*>(next()))
210 && !(allInners && allOuters)) {
211 // Get nodes names
212 const Char_t* name = node->GetName();
213 if (!name) continue;
214 AliDebug(50, Form("Got volume %s", name));
215 // Check if this node is this detector
216 // The base offset for numbers in the ASCII table is 48
217 if (IS_NODE_THIS(name)) {
218 AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
219 thisNodeFound = kTRUE;
220 }
221 // if the detector was found, then we're on that branch, and we
222 // check if this node represents a module in that branch.
223 if (thisNodeFound && IS_NODE_SENSOR(name)) {
224 AliDebug(20, Form("Found sensor node '%s' for FMD%d", name, fId));
225 // Get the ring Id.
226 Char_t ringid = name[1];
227
228 // Get the approprate ring
229 AliFMDRing* ring = GetRing(ringid);
230 if (!ring) continue;
231
232 // Check whether we have all the modules we need for this ring,
233 // and if so, go on to the next node.
234 Bool_t& done = (ring == fInner ? allInners : allOuters);
235 if ((done = HasAllTransforms(ringid))) {
236 AliDebug(20, Form("Already has all module transforms for ring %c",
237 ringid));
238 continue;
239 }
240
241 // Get the approprate container
242 TObjArray* matricies = (ringid == 'i' || ringid == 'I'
243 ? fInnerTransforms : fOuterTransforms);
244
245 // Get the copy (module) number, and check that it hasn't
246 // already been added to the container.
247 Int_t copy = node->GetNumber();
248 if (matricies->At(copy)) {
249 AliWarning(Form("Have a transformation for module %d in ring %c",
250 copy, ringid));
251 continue;
252 }
253
254 // Get the global transformation matrix, and store it.
255 TGeoMatrix* trans = new TGeoHMatrix(*(next.GetCurrentMatrix()));
256 matricies->AddAt(trans, copy);
257
258 }
259 }
260}
261
262//____________________________________________________________________
263void
264AliFMDDetector::SetAlignableVolumes() const
265{
266 AliDebug(10, Form("Making alignable volumes for FMD%d", fId));
267 if (!gGeoManager) {
268 AliFatal("No TGeoManager defined");
269 return;
270 }
271 TGeoVolume* topVolume = gGeoManager->GetTopVolume();
272 if (!topVolume) {
273 AliFatal("No top-level volume defined");
274 return;
275 }
276
277 // Make an iterator
278 TGeoIterator next(topVolume);
279 next.Reset(topVolume);
280 next.SetTopName(Form("/%s_1", topVolume->GetName()));
281 TGeoNode* node = 0;
282
283 Int_t nInnerSensor = (fInner ? fInner->GetNModules() : 0);
284 Int_t nOuterSensor = (fOuter ? fOuter->GetNModules() : 0);
285 // Find the node corresponding to this detector, and then find the
286 // sensor volumes
287 Bool_t thisNodeFound = kFALSE;
288 Char_t thisHalf = '\0';
289 Int_t iInnerSensor = 0;
290 Int_t iOuterSensor = 0;
291 Bool_t hasTop = false;
292 Bool_t hasBottom = false;
293
294 TString path, align;
295 while ((node = static_cast<TGeoNode*>(next()))
296 && (iInnerSensor < nInnerSensor || iOuterSensor < nOuterSensor
297 || !hasBottom || !hasTop)) {
298 // Get nodes names
299 const Char_t* name = node->GetName();
300 if (!name) continue;
301 AliDebug((name[0] == 'F' ? 40 : 50), Form("Got volume %s", name));
302 // Check if this node is this detector
303 // The base offset for numbers in the ASCII table is 48
304 if (IS_NODE_THIS(name)) {
305 AliDebug(20, Form("Found detector node '%s' for FMD%d", name, fId));
306 thisNodeFound = kTRUE;
307 }
308
309 // if a half ring is found, then we're on that branch, and we
310 // check if this node represents a half ring on that branch
311 if (thisNodeFound && IS_NODE_HALF(name)) {
312 AliDebug(30, Form("Found half node '%s' for FMD%d", name, fId));
313 // Get the half Id.
314 thisHalf = name[3];
315
316 // Check if we're done
317 Bool_t done = (thisHalf == 'T' ? hasTop : hasBottom);
318 if (done) {
319 AliDebug(20,Form("Already has all halves for detector %c",name[1]));
320 continue;
321 }
322
323 switch (thisHalf) {
324 case 'T': hasTop = true; break;
325 case 'B': hasBottom = true; break;
326 default:
327 AliWarning(Form("Unknown part '%c' of FMD%d", fId));
328 continue; // because the node is unknown.
329 }
330
331 // Get the node path
332 next.GetPath(path);
333 align = Form("FMD/FMD%d_%c", fId, thisHalf);
334 }
335
336 // if the detector was found, then we're on that branch, and we
337 // check if this node represents a module in that branch.
338 if (thisNodeFound && thisHalf && IS_NODE_SENSOR(name)) {
339 AliDebug(30, Form("Found sensor node '%s' for FMD%d", name, fId));
340 // Get the ring Id.
341 Char_t ringid = name[1];
342
343 // check that the ring is valid
344 if (!GetRing(ringid)) {
345 AliWarning(Form("Invalid ring %c for FMD%d", ringid, fId));
346 continue;
347 }
348
349 // Check if we're done
350 Bool_t done = false;
351 switch (ringid) {
352 case 'I': done = iInnerSensor >= nInnerSensor; break;
353 case 'O': done = iOuterSensor >= nOuterSensor; break;
354 default: continue;
355 }
356 if (done) {
357 AliDebug(20,Form("Already has all sensor volumes for ring %c",ringid));
358 continue;
359 }
360 // Get the copy (module) number, and check that it hasn't
361 // already been added to the container.
362 Int_t copy = node->GetNumber();
363 next.GetPath(path);
364 // path.Replace("ALIC", "/ALIC_1");
365 align = Form("FMD/FMD%d_%c/FMD%c_%02d", fId, thisHalf, ringid, copy);
366
367 switch (ringid) {
368 case 'I': iInnerSensor++; break;
369 case 'O': iOuterSensor++; break;
370 }
371 }
372 if (!align.IsNull() && !path.IsNull()) {
373 AliDebug(20, Form("Got %s -> %s", path.Data(), align.Data()));
374 TGeoPNEntry* entry =
375 gGeoManager->SetAlignableEntry(align.Data(),path.Data());
376 if(!entry)
377 AliFatal(Form("Alignable entry %s not created. "
378 "Volume path %s not valid",
379 align.Data(),path.Data()));
380#ifdef MAKE_ALIGNABLE_PHYSICAL
381 TGeoPhysicalNode* phys = gGeoManager->MakeAlignablePN(entry);
382 if (!phys)
383 AliWarning(Form("Physical node entry %s not created. "
384 "Volume path %s not valid",
385 align.Data(),path.Data()));
386#endif
387 align = "";
388 }
389 AliDebug(20, Form("FMD%d: top: %d bottom: %d Inner: %d/%d Outer %d/%d",
390 fId, hasTop, hasBottom, iInnerSensor, nInnerSensor,
391 iOuterSensor, nOuterSensor));
392 }
393}
394
395
396
397//____________________________________________________________________
398AliFMDRing*
399AliFMDDetector::GetRing(Char_t id) const
400{
401 // Get the specified ring
402 //
403 // ID Id of ring ('I' or 'O')
404 //
405 switch (id) {
406 case 'i':
407 case 'I': return GetInner();
408 case 'o':
409 case 'O': return GetOuter();
410 }
411 return 0;
412}
413
414//____________________________________________________________________
415Double_t
416AliFMDDetector::GetRingZ(Char_t id) const
417{
418 // Get the z-coordinate specified ring
419 //
420 // ID Id of ring ('I' or 'O')
421 //
422 switch (id) {
423 case 'i':
424 case 'I': return GetInnerZ();
425 case 'o':
426 case 'O': return GetOuterZ();
427 }
428 return 0;
429}
430
431//____________________________________________________________________
432TGeoMatrix*
433AliFMDDetector::FindTransform(Char_t ring, UShort_t sector) const
434{
435 // Find the transformation that corresponds to sector sector in ring
436 // ring.
437 TObjArray* matricies = 0;
438 switch (ring) {
439 case 'i': case 'I': matricies = fInnerTransforms; break;
440 case 'o': case 'O': matricies = fOuterTransforms; break;
441 }
442 if (!matricies) {
443 AliWarning(Form("Unknown ring %c of FMD%d", ring, fId));
444 return 0;
445 }
446 UInt_t module = sector / 2;
447 TGeoMatrix* m = static_cast<TGeoMatrix*>(matricies->At(module));
448 if (!m) {
449 AliWarning(Form("No matrix found for sector %d in FMD%d%c",
450 sector, fId, ring));
451 return 0;
452 }
453 return m;
454}
455
456
457//____________________________________________________________________
458void
459AliFMDDetector::Detector2XYZ(Char_t ring,
460 UShort_t sector,
461 UShort_t strip,
462 Double_t& x,
463 Double_t& y,
464 Double_t& z) const
465{
466 // Translate detector coordinates (this,ring,sector,strip) into
467 // (x,y,z) coordinates (in global reference frame)
468 AliFMDRing* r = GetRing(ring);
469 if (!r) return;
470 TGeoMatrix* m = FindTransform(ring, sector);
471 if (!m) return;
472 Double_t rho = r->GetStripRadius(strip);
473 Double_t phi = ((sector % 2) - .5) * r->GetTheta();
474 Double_t siThick = r->GetSiThickness();
475 Double_t modThick = (siThick
476 + r->GetPrintboardThickness()
477 + r->GetCopperThickness()
478 + r->GetChipThickness()
479 + r->GetSpacing());
480 AliDebug(30,Form("Rho %7.3f, angle %7.3f", rho, phi));
481# define DEGRAD TMath::Pi() / 180.
482 Double_t local[] = { rho * TMath::Cos(phi * DEGRAD),
483 rho * TMath::Sin(phi * DEGRAD),
484 -modThick + siThick / 2 };
485 Double_t master[3];
486 AliDebug(30, Form("Local (%7.3f,%7.3f,%7.3f)",local[0], local[1], local[2]));
487 m->LocalToMaster(local, master);
488 AliDebug(30, Form("Master (%7.3f,%7.3f,%7.3f)",
489 master[0],master[1],master[2]));
490 x = master[0];
491 y = master[1];
492 z = master[2];
493}
494
495//____________________________________________________________________
496Bool_t
497AliFMDDetector::XYZ2Detector(Double_t x,
498 Double_t y,
499 Double_t z,
500 Char_t& ring,
501 UShort_t& sector,
502 UShort_t& strip) const
503{
504 // Translate (x,y,z) coordinates (in global reference frame) into
505 // detector coordinates (this,ring,sector,strip).
506 AliFMDRing* rng = 0;
507 ring = -1;
508 for (int j = 0; j < 2; j++) {
509 rng = GetRing(j == 0 ? 'I' : 'O');
510 if (!rng) continue;
511 Double_t ringZ = GetRingZ(j == 0 ? 'I' : 'O');
512 Double_t modSpace = TMath::Sign(rng->GetModuleSpacing(), ringZ);
513 if (TMath::Abs(z - ringZ) < 0.01 ||
514 TMath::Abs(z - ringZ + modSpace) < 0.01) break;
515 rng = 0;
516 }
517 if (rng && rng->XYZ2Detector(x, y, z - GetRingZ(rng->GetId()),
518 sector, strip)) {
519 ring = rng->GetId();
520 return kTRUE;
521 }
522 return kFALSE;
523}
524
525
526
527//____________________________________________________________________
528//
529// EOF
530//