]> git.uio.no Git - u/mrichter/AliRoot.git/blame_incremental - FMD/AliFMDGeometry.cxx
minor coverity defects: self-assignment protection
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometry.cxx
... / ...
CommitLineData
1/**************************************************************************
2 * Copyright(c) 1998-1999, 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/**
17 * @file AliFMDGeometry.cxx
18 * @author Christian Holm Christensen <cholm@nbi.dk>
19 * @date Mon Mar 27 12:40:37 2006
20 * @brief Geometry mananger for the FMD
21 */
22//____________________________________________________________________
23//
24// Forward Multiplicity Detector based on Silicon wafers.
25//
26// This class is a singleton that handles the geometry parameters of
27// the FMD detectors.
28//
29// The actual code is done by various separate classes. Below is
30// diagram showing the relationship between the various FMD classes
31// that handles the geometry
32//
33// +------------+
34// +- | AliFMDRing |
35// 2 | +------------+
36// +----------------+<>--+ |
37// | AliFMDGeometry | ^
38// +----------------+<>--+ V 1..2
39// 3 | +----------------+
40// +-| AliFMDDetector |
41// +----------------+
42// ^
43// |
44// +-------------+-------------+
45// | | |
46// +---------+ +---------+ +---------+
47// | AliFMD1 | | AliFMD2 | | AliFMD3 |
48// +---------+ +---------+ +---------+
49//
50//
51// * AliFMDRing
52// This class contains all stuff needed to do with a ring. It's
53// used by the AliFMDDetector objects to instantise inner and
54// outer rings. The AliFMDRing objects are shared by the
55// AliFMDDetector objects, and owned by the AliFMDv1 object.
56//
57// * AliFMD1, AliFMD2, and AliFMD3
58// These are specialisation of AliFMDDetector, that contains the
59// particularities of each of the sub-detector system. It is
60// envisioned that the classes should also define the support
61// volumes and material for each of the detectors.
62//
63//
64#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
65#include "AliFMDRing.h" // ALIFMDRING_H
66#include "AliFMD1.h" // ALIFMD1_H
67#include "AliFMD2.h" // ALIFMD2_H
68#include "AliFMD3.h" // ALIFMD2_H
69#include "AliRecPoint.h" // ALIRECPOINT_H
70#include "AliFMDDebug.h" // ALILOG_H
71#include <TVector3.h> // ROOT_TVector3
72// #include <TMatrix.h> // ROOT_TMatrix
73// #include <TParticle.h> // ROOT_TParticle
74#include <Riostream.h>
75#include "AliFMDGeometryBuilder.h"
76// #include <TArrayI.h>
77#include <TGeoManager.h>
78#include <TGeoVolume.h>
79#include <TGeoNode.h>
80#include <TMath.h>
81static Int_t FindNodeDepth(const char* name, const char* volname);
82
83
84//====================================================================
85ClassImp(AliFMDGeometry)
86#if 0
87 ; // This is here to keep Emacs for indenting the next line
88#endif
89
90//____________________________________________________________________
91AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
92
93//____________________________________________________________________
94AliFMDGeometry*
95AliFMDGeometry::Instance()
96{
97 //
98 // singleton access
99 //
100 // Return:
101 // Singleton
102 //
103 if (!fgInstance) fgInstance = new AliFMDGeometry("FMD");
104 return fgInstance;
105}
106
107//____________________________________________________________________
108AliFMDGeometry::AliFMDGeometry()
109 : AliGeometry(),
110 fIsInitialized(kFALSE),
111 fInner(0),
112 fOuter(0),
113 fFMD1(0),
114 fFMD2(0),
115 fFMD3(0),
116 fUseFMD1(kTRUE),
117 fUseFMD2(kTRUE),
118 fUseFMD3(kTRUE),
119 fIsInitTrans(kFALSE),
120 fBuilder(0),
121 fDetectorOff(0),
122 fModuleOff(0),
123 fRingOff(0),
124 fSectorOff(0),
125 fActive(2),
126 fDetailed(kTRUE),
127 fUseAssembly(kTRUE)
128{
129 // PROTECTED
130 //
131 // CTOR
132 //
133}
134
135//____________________________________________________________________
136AliFMDGeometry::AliFMDGeometry(const char* )
137 : AliGeometry("FMD", "Forward multiplicity"),
138 fIsInitialized(kFALSE),
139 fInner(0),
140 fOuter(0),
141 fFMD1(0),
142 fFMD2(0),
143 fFMD3(0),
144 fUseFMD1(kTRUE),
145 fUseFMD2(kTRUE),
146 fUseFMD3(kTRUE),
147 fIsInitTrans(kFALSE),
148 fBuilder(0),
149 fDetectorOff(0),
150 fModuleOff(0),
151 fRingOff(0),
152 fSectorOff(0),
153 fActive(2),
154 fDetailed(kTRUE),
155 fUseAssembly(kTRUE)
156{
157 // PROTECTED
158 //
159 // CTOR
160 //
161 // Parameters:
162 // name Not used
163 //
164 fInner = new AliFMDRing('I');
165 fOuter = new AliFMDRing('O');
166 fFMD1 = new AliFMD1(fInner);
167 fFMD2 = new AliFMD2(fInner, fOuter);
168 fFMD3 = new AliFMD3(fInner, fOuter);
169 fIsInitialized = kFALSE;
170 fActive.Reset(-1);
171}
172
173//____________________________________________________________________
174AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other)
175 : AliGeometry(other),
176 fIsInitialized(other.fIsInitialized),
177 fInner(other.fInner),
178 fOuter(other.fOuter),
179 fFMD1(other.fFMD1),
180 fFMD2(other.fFMD2),
181 fFMD3(other.fFMD3),
182 fUseFMD1(other.fUseFMD1),
183 fUseFMD2(other.fUseFMD2),
184 fUseFMD3(other.fUseFMD3),
185 fIsInitTrans(other.fIsInitTrans),
186 fBuilder(other.fBuilder),
187 fDetectorOff(other.fDetectorOff),
188 fModuleOff(other.fModuleOff),
189 fRingOff(other.fRingOff),
190 fSectorOff(other.fSectorOff),
191 fActive(other.fActive),
192 fDetailed(other.fDetailed),
193 fUseAssembly(other.fUseAssembly)
194{
195 // PROTECTED
196 //
197 // Copy CTOR
198 //
199 // Parameters:
200 // other To copy from
201 //
202}
203
204
205
206//____________________________________________________________________
207AliFMDGeometry&
208AliFMDGeometry::operator=(const AliFMDGeometry& other)
209{
210 // PROTECTED
211 //
212 // Assignment operator
213 //
214 // Parameters:
215 // other To assig from
216 // Return:
217 // reference to this.
218 //
219 if (&other == this) return *this;
220 fUseFMD1 = other.fUseFMD1;
221 fUseFMD2 = other.fUseFMD2;
222 fUseFMD3 = other.fUseFMD3;
223 fFMD1 = other.fFMD1;
224 fFMD2 = other.fFMD2;
225 fFMD3 = other.fFMD3;
226 fInner = other.fInner;
227 fOuter = other.fOuter;
228 fIsInitialized = other.fIsInitialized;
229 return *this;
230}
231
232//____________________________________________________________________
233void
234AliFMDGeometry::Init()
235{
236 //
237 // Initialize the the singleton if not done so already
238 //
239 if (fIsInitialized) return;
240 fInner->Init();
241 fOuter->Init();
242 fFMD1->Init();
243 fFMD2->Init();
244 fFMD3->Init();
245}
246
247//____________________________________________________________________
248void
249AliFMDGeometry::InitTransformations(Bool_t force)
250{
251 //
252 // Find all local <-> global transforms
253 //
254 if (force) fIsInitTrans = kFALSE;
255 if (fIsInitTrans) return;
256 if (!gGeoManager) {
257 AliError("No TGeoManager defined");
258 return;
259 }
260 AliFMDDebug(1, ("Initialising transforms for FMD geometry"));
261 if (fFMD1) fFMD1->InitTransformations();
262 if (fFMD2) fFMD2->InitTransformations();
263 if (fFMD3) fFMD3->InitTransformations();
264 fIsInitTrans = kTRUE;
265}
266
267//____________________________________________________________________
268void
269AliFMDGeometry::Build()
270{
271 //
272 // Make the geometry. This delegates to AliFMDGeometryBuilder
273 //
274 if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
275 fBuilder->SetDetailed(fDetailed);
276 fBuilder->UseAssembly(fUseAssembly);
277 fBuilder->Exec();
278}
279
280//____________________________________________________________________
281void
282AliFMDGeometry::SetActive(Int_t* active, Int_t n)
283{
284 //
285 // Set active volumes
286 //
287 // Parameters:
288 // active Active volume id array
289 // n elements of @a active
290 //
291 fActive.Set(n);
292 for (Int_t i = 0; i < n; i++) {
293 AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
294 fActive[i] = active[i];
295 }
296}
297
298//____________________________________________________________________
299void
300AliFMDGeometry::AddActive(Int_t active)
301{
302 //
303 // Add an active volume
304 //
305 // Parameters:
306 // id Register volume @a id to be active
307 //
308 //
309 Int_t n = fActive.fN;
310 fActive.Set(n+1);
311 fActive[n] = active;
312}
313
314//____________________________________________________________________
315Bool_t
316AliFMDGeometry::IsActive(Int_t vol) const
317{
318 //
319 // Check if volume @a vol is marked as active
320 //
321 // Parameters:
322 // vol Volume ID
323 // Return:
324 // @c true if @a vol is declared active
325 //
326 for (Int_t i = 0; i < fActive.fN; i++)
327 if (fActive[i] == vol) return kTRUE;
328 return kFALSE;
329}
330
331//____________________________________________________________________
332AliFMDDetector*
333AliFMDGeometry::GetDetector(Int_t i) const
334{
335 //
336 // Get description of a sub-detector
337 //
338 // Parameters:
339 // i Sub-detector #
340 // Return:
341 // Description of sub-detector, or 0
342 //
343 switch (i) {
344 case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
345 case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
346 case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
347 }
348 return 0;
349}
350
351//____________________________________________________________________
352AliFMDRing*
353AliFMDGeometry::GetRing(Char_t i) const
354{
355 //
356 // Get description of a ring, i should be one of 'I' or 'O' (case
357 // insensitive). If an invalid parameter is passed, 0 (NULL) is
358 // returned.
359 //
360 // Parameters:
361 // i Ring id
362 // Return:
363 // Description of ring, or 0
364 //
365 switch (i) {
366 case 'I':
367 case 'i': return fInner;
368 case 'O':
369 case 'o': return fOuter;
370 }
371 return 0;
372}
373
374//____________________________________________________________________
375void
376AliFMDGeometry::Enable(Int_t i)
377{
378 //
379 // Enable the ith detector
380 //
381 // Parameters:
382 // i IF true, enable sub-detector @a i
383 //
384 switch (i) {
385 case 1: fUseFMD1 = kTRUE; break;
386 case 2: fUseFMD2 = kTRUE; break;
387 case 3: fUseFMD3 = kTRUE; break;
388 }
389}
390
391//____________________________________________________________________
392void
393AliFMDGeometry::Disable(Int_t i)
394{
395 //
396 // Disable the ith detector
397 //
398 // Parameters:
399 // i IF true, disable sub-detector @a i
400 //
401 switch (i) {
402 case 1: fUseFMD1 = kFALSE; break;
403 case 2: fUseFMD2 = kFALSE; break;
404 case 3: fUseFMD3 = kFALSE; break;
405 }
406}
407
408//____________________________________________________________________
409void
410AliFMDGeometry::Detector2XYZ(UShort_t detector,
411 Char_t ring,
412 UShort_t sector,
413 UShort_t strip,
414 Double_t& x,
415 Double_t& y,
416 Double_t& z) const
417{
418 //
419 // Translate detector coordinates (detector, ring, sector, strip)
420 // to spatial coordinates (x, y, z) in the master reference frame
421 // of ALICE. The member function uses the transformations
422 // previously obtained from the TGeoManager.
423 //
424 // Parameters:
425 // detector Detector number
426 // ring Ring id
427 // sector Sector number
428 // strip Strip number
429 // x On return, X coordinate
430 // y On return, Y coordinate
431 // z On return, Z coordinate
432 //
433 AliFMDDetector* det = GetDetector(detector);
434 if (!det) {
435 AliWarning(Form("Unknown detector %d", detector));
436 return;
437 }
438 det->Detector2XYZ(ring, sector, strip, x, y, z);
439}
440
441//____________________________________________________________________
442Bool_t
443AliFMDGeometry::XYZ2Detector(Double_t x,
444 Double_t y,
445 Double_t z,
446 UShort_t& detector,
447 Char_t& ring,
448 UShort_t& sector,
449 UShort_t& strip) const
450{
451 //
452 // Translate spatial coordinates (x,y,z) in the master reference
453 // frame of ALICE to the detector coordinates (detector, ring,
454 // sector, strip). Note, that if this method is to be used in
455 // reconstruction or the like, then the input z-coordinate should
456 // be corrected for the events interactions points z-coordinate,
457 // like
458 // @code
459 // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
460 // @endcode
461 //
462 // Parameters:
463 // x X coordinate
464 // y Y coordinate
465 // z Z coordinate
466 // detector On return, Detector number
467 // ring On return, Ring id
468 // sector On return, Sector number
469 // strip On return, Strip number
470 // Return:
471 // @c false of (@a x, @a y, @a z) is not within this
472 // detector.
473 //
474 AliFMDDetector* det = 0;
475 detector = 0;
476 for (int i = 1; i <= 3; i++) {
477 det = GetDetector(i);
478 if (!det) continue;
479 if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
480 detector = det->GetId();
481 return kTRUE;
482 }
483 }
484 return kFALSE;
485}
486
487//____________________________________________________________________
488Bool_t
489AliFMDGeometry::XYZ2REtaPhiTheta(Double_t x, Double_t y,
490 Double_t z,
491 Double_t& r, Double_t& eta,
492 Double_t& phi, Double_t& theta)
493{
494
495 //
496 // Service function to convert Cartisean XYZ to r, eta, phi, and theta.
497 //
498 // Note, that the z input should be corrected for the vertex location
499 // if needed.
500 //
501 // Parameters:
502 // x Cartisean X coordinate
503 // y Cartisean Y coordinate
504 // z Cartisean Z coordinate
505 // r On return, the radius
506 // eta On return, the pseudo-rapidity
507 // phi On return, the azimuthal angle
508 // theta On return, the polar angle;
509 //
510 // Return:
511 // kTRUE on success, kFALSE in case of problems
512 //
513 if (x == 0 && y == 0 && z == 0) return kFALSE;
514
515 // Correct for vertex offset.
516 phi = TMath::ATan2(y, x);
517 r = TMath::Sqrt(y * y + x * x);
518 theta = TMath::ATan2(r, z);
519 eta = -TMath::Log(TMath::Tan(theta / 2));
520
521 return kTRUE;
522}
523
524
525//____________________________________________________________________
526void
527AliFMDGeometry::GetGlobal(const AliRecPoint* p,
528 TVector3& pos,
529 TMatrixF& /* mat */) const
530{
531 //
532 // Get global coordinates cooresponding to a rec point.
533 //
534 // Parameters:
535 // p Reconstructed point.
536 // pos On return, the position
537 // mat On return, the material at @a post
538 //
539 GetGlobal(p, pos);
540}
541
542//____________________________________________________________________
543void
544AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const
545{
546 //
547 // Get global coordinates cooresponding to a rec point.
548 //
549 // Parameters:
550 // p Reconstructed point.
551 // pos On return, the position
552 //
553 // FIXME: Implement this function to work with outer rings too.
554 Double_t x, y, z;
555 TVector3 local;
556 p->GetLocalPosition(local);
557 UShort_t detector = UShort_t(local.X());
558 UShort_t sector = UShort_t(local.Y());
559 UShort_t strip = UShort_t(local.Z());
560 Detector2XYZ(detector, 'I', sector, strip, x, y, z);
561 pos.SetXYZ(x, y, z);
562}
563
564//____________________________________________________________________
565Bool_t
566AliFMDGeometry::Impact(const TParticle* /* particle */) const
567{
568 //
569 // Check if particle will hit an active detector element.
570 //
571 // @todo implement this function
572 //
573 // Parameters:
574 // particle Track
575 // Return:
576 // @c true if @a particle will hit this detector
577 //
578 return kFALSE;
579}
580
581//____________________________________________________________________
582void
583AliFMDGeometry::SetAlignableVolumes() const
584{
585 //
586 // Declare alignable volumes
587 //
588 for (Int_t d = 1; d <= 3; d++)
589 if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
590}
591
592
593//____________________________________________________________________
594void
595AliFMDGeometry::ExtractGeomInfo()
596{
597 // Check the volume depth of some nodes, get the active volume
598 // numbers, and so forth.
599 //
600 // TODO: Here, we should actually also get the parameters of the
601 // shapes, like the verticies of the polygon shape that makes up the
602 // silicon sensor, the strip pitch, the ring radii, the z-positions,
603 // and so on - that is, all the geometric information we need for
604 // futher processing, such as simulation, digitization,
605 // reconstruction, etc.
606 Int_t detectorDepth = FindNodeDepth("F1MT_1", "ALIC");
607 Int_t ringDepth = FindNodeDepth(Form("FITV_%d", int('I')), "ALIC");
608 Int_t moduleDepth = FindNodeDepth("FIBH_0", "ALIC");
609 Int_t sectorDepth = FindNodeDepth("FISC_1", "ALIC");
610 fActive.Set(0);
611 fActive.Reset(-1);
612 AliFMDDebug(1, ("Geometry depths:\n"
613 " Sector: %d\n"
614 " Module: %d\n"
615 " Ring: %d\n"
616 " Detector: %d",
617 sectorDepth, moduleDepth, ringDepth, detectorDepth));
618 if (sectorDepth < 0 && moduleDepth < 0) {
619 fDetailed = kFALSE;
620 fSectorOff = -1;
621 fModuleOff = -1;
622 fRingOff = 0;
623 fDetectorOff = (ringDepth - detectorDepth);
624 TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
625 TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
626 if (actiVol) AddActive(actiVol->GetNumber());
627 if (actiVol) AddActive(actoVol->GetNumber());
628 }
629 else if (sectorDepth < 0) {
630 fDetailed = kFALSE;
631 fSectorOff = -1;
632 fModuleOff = 1;
633 fRingOff = (moduleDepth - ringDepth) + 1;
634 fDetectorOff = (moduleDepth - detectorDepth) + 1;
635 TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
636 TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
637 if (modiVol) AddActive(modiVol->GetNumber());
638 if (modoVol) AddActive(modoVol->GetNumber());
639 }
640 else {
641 Int_t stripDepth = FindNodeDepth("FIST_1", "ALIC");
642 fDetailed = kTRUE;
643 fSectorOff = (stripDepth - sectorDepth);
644 fModuleOff = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
645 fRingOff = (stripDepth - ringDepth);
646 fDetectorOff = (stripDepth - detectorDepth );
647 TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
648 TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
649 if (striVol) AddActive(striVol->GetNumber());
650 if (stroVol) AddActive(stroVol->GetNumber());
651 }
652 AliFMDDebug(1, ("Geometry offsets:\n"
653 " Sector: %d\n"
654 " Module: %d\n"
655 " Ring: %d\n"
656 " Detector: %d",
657 fSectorOff, fModuleOff, fRingOff, fDetectorOff));
658}
659
660#if 0
661//____________________________________________________________________
662static Int_t
663CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
664{
665 // If there's no node here.
666 if (!node) return -1;
667 // Check if it this one
668 TString sname(name);
669 if (sname == node->GetName()) return lvl;
670
671 // Check if the node is an immediate daugther
672 TObjArray* nodes = node->GetNodes();
673 if (!nodes) return -1;
674 // Increase the level, and search immediate sub nodes.
675 lvl++;
676 TGeoNode* found = static_cast<TGeoNode*>(nodes->FindObject(name));
677 if (found) return lvl;
678
679 // Check the sub node, if any of their sub-nodes match.
680 for (Int_t i = 0; i < nodes->GetEntries(); i++) {
681 TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
682 if (!sub) continue;
683 // Recurive check
684 if (CheckNodes(sub, name, lvl) >= 0) return lvl;
685 }
686 // If not found, decrease the level
687 lvl--;
688 return -1;
689}
690#endif
691
692//____________________________________________________________________
693Int_t
694FindNodeDepth(const char* name, const char* volname)
695{
696 // Find the depth of a node
697 TGeoVolume* vol = gGeoManager->GetVolume(volname);
698 if (!vol) {
699 std::cerr << "No top volume defined" << std::endl;
700 return -1;
701 }
702
703 TGeoIterator next(vol);
704 TGeoNode* node = 0;
705 TString sName(name);
706 while ((node = next())) {
707 if (sName == node->GetName()) {
708 //std::cout << "Found node " << node->GetName() << " at level "
709 // << next.GetLevel() << std::endl;
710 return next.GetLevel();
711 }
712 }
713 return -1;
714#if 0
715 TObjArray* nodes = vol->GetNodes();
716 if (!nodes) {
717 std::cerr << "No nodes in top volume" << std::endl;
718 return -1;
719 }
720 TIter next(nodes);
721 TGeoNode* node = 0;
722 Int_t lvl = 0;
723 while ((node = static_cast<TGeoNode*>(next())))
724 if (CheckNodes(node, name, lvl) >= 0) return lvl;
725 return -1;
726#endif
727}
728
729//____________________________________________________________________
730//
731// EOF
732//