1 /**************************************************************************
2 * Copyright(c) 1998-1999, 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 **************************************************************************/
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
22 //____________________________________________________________________
24 // Forward Multiplicity Detector based on Silicon wafers.
26 // This class is a singleton that handles the geometry parameters of
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
36 // +----------------+<>--+ |
37 // | AliFMDGeometry | ^
38 // +----------------+<>--+ V 1..2
39 // 3 | +----------------+
40 // +-| AliFMDDetector |
44 // +-------------+-------------+
46 // +---------+ +---------+ +---------+
47 // | AliFMD1 | | AliFMD2 | | AliFMD3 |
48 // +---------+ +---------+ +---------+
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.
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.
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>
81 static Int_t FindNodeDepth(const char* name, const char* volname);
84 //====================================================================
85 ClassImp(AliFMDGeometry)
87 ; // This is here to keep Emacs for indenting the next line
90 //____________________________________________________________________
91 AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
93 //____________________________________________________________________
95 AliFMDGeometry::Instance()
103 if (!fgInstance) fgInstance = new AliFMDGeometry("FMD");
107 //____________________________________________________________________
108 AliFMDGeometry::AliFMDGeometry()
110 fIsInitialized(kFALSE),
119 fIsInitTrans(kFALSE),
135 //____________________________________________________________________
136 AliFMDGeometry::AliFMDGeometry(const char* )
137 : AliGeometry("FMD", "Forward multiplicity"),
138 fIsInitialized(kFALSE),
147 fIsInitTrans(kFALSE),
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;
173 //____________________________________________________________________
174 AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other)
175 : AliGeometry(other),
176 fIsInitialized(other.fIsInitialized),
177 fInner(other.fInner),
178 fOuter(other.fOuter),
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)
200 // other To copy from
206 //____________________________________________________________________
208 AliFMDGeometry::operator=(const AliFMDGeometry& other)
212 // Assignment operator
215 // other To assig from
217 // reference to this.
219 fUseFMD1 = other.fUseFMD1;
220 fUseFMD2 = other.fUseFMD2;
221 fUseFMD3 = other.fUseFMD3;
225 fInner = other.fInner;
226 fOuter = other.fOuter;
227 fIsInitialized = other.fIsInitialized;
231 //____________________________________________________________________
233 AliFMDGeometry::Init()
236 // Initialize the the singleton if not done so already
238 if (fIsInitialized) return;
246 //____________________________________________________________________
248 AliFMDGeometry::InitTransformations(Bool_t force)
251 // Find all local <-> global transforms
253 if (force) fIsInitTrans = kFALSE;
254 if (fIsInitTrans) return;
256 AliError("No TGeoManager defined");
259 AliFMDDebug(1, ("Initialising transforms for FMD geometry"));
260 if (fFMD1) fFMD1->InitTransformations();
261 if (fFMD2) fFMD2->InitTransformations();
262 if (fFMD3) fFMD3->InitTransformations();
263 fIsInitTrans = kTRUE;
266 //____________________________________________________________________
268 AliFMDGeometry::Build()
271 // Make the geometry. This delegates to AliFMDGeometryBuilder
273 if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
274 fBuilder->SetDetailed(fDetailed);
275 fBuilder->UseAssembly(fUseAssembly);
279 //____________________________________________________________________
281 AliFMDGeometry::SetActive(Int_t* active, Int_t n)
284 // Set active volumes
287 // active Active volume id array
288 // n elements of @a active
291 for (Int_t i = 0; i < n; i++) {
292 AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
293 fActive[i] = active[i];
297 //____________________________________________________________________
299 AliFMDGeometry::AddActive(Int_t active)
302 // Add an active volume
305 // id Register volume @a id to be active
308 Int_t n = fActive.fN;
313 //____________________________________________________________________
315 AliFMDGeometry::IsActive(Int_t vol) const
318 // Check if volume @a vol is marked as active
323 // @c true if @a vol is declared active
325 for (Int_t i = 0; i < fActive.fN; i++)
326 if (fActive[i] == vol) return kTRUE;
330 //____________________________________________________________________
332 AliFMDGeometry::GetDetector(Int_t i) const
335 // Get description of a sub-detector
340 // Description of sub-detector, or 0
343 case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
344 case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
345 case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
350 //____________________________________________________________________
352 AliFMDGeometry::GetRing(Char_t i) const
355 // Get description of a ring, i should be one of 'I' or 'O' (case
356 // insensitive). If an invalid parameter is passed, 0 (NULL) is
362 // Description of ring, or 0
366 case 'i': return fInner;
368 case 'o': return fOuter;
373 //____________________________________________________________________
375 AliFMDGeometry::Enable(Int_t i)
378 // Enable the ith detector
381 // i IF true, enable sub-detector @a i
384 case 1: fUseFMD1 = kTRUE; break;
385 case 2: fUseFMD2 = kTRUE; break;
386 case 3: fUseFMD3 = kTRUE; break;
390 //____________________________________________________________________
392 AliFMDGeometry::Disable(Int_t i)
395 // Disable the ith detector
398 // i IF true, disable sub-detector @a i
401 case 1: fUseFMD1 = kFALSE; break;
402 case 2: fUseFMD2 = kFALSE; break;
403 case 3: fUseFMD3 = kFALSE; break;
407 //____________________________________________________________________
409 AliFMDGeometry::Detector2XYZ(UShort_t detector,
418 // Translate detector coordinates (detector, ring, sector, strip)
419 // to spatial coordinates (x, y, z) in the master reference frame
420 // of ALICE. The member function uses the transformations
421 // previously obtained from the TGeoManager.
424 // detector Detector number
426 // sector Sector number
427 // strip Strip number
428 // x On return, X coordinate
429 // y On return, Y coordinate
430 // z On return, Z coordinate
432 AliFMDDetector* det = GetDetector(detector);
434 AliWarning(Form("Unknown detector %d", detector));
437 det->Detector2XYZ(ring, sector, strip, x, y, z);
440 //____________________________________________________________________
442 AliFMDGeometry::XYZ2Detector(Double_t x,
448 UShort_t& strip) const
451 // Translate spatial coordinates (x,y,z) in the master reference
452 // frame of ALICE to the detector coordinates (detector, ring,
453 // sector, strip). Note, that if this method is to be used in
454 // reconstruction or the like, then the input z-coordinate should
455 // be corrected for the events interactions points z-coordinate,
458 // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
465 // detector On return, Detector number
466 // ring On return, Ring id
467 // sector On return, Sector number
468 // strip On return, Strip number
470 // @c false of (@a x, @a y, @a z) is not within this
473 AliFMDDetector* det = 0;
475 for (int i = 1; i <= 3; i++) {
476 det = GetDetector(i);
478 if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
479 detector = det->GetId();
486 //____________________________________________________________________
488 AliFMDGeometry::XYZ2REtaPhiTheta(Double_t x, Double_t y,
490 Double_t& r, Double_t& eta,
491 Double_t& phi, Double_t& theta)
495 // Service function to convert Cartisean XYZ to r, eta, phi, and theta.
497 // Note, that the z input should be corrected for the vertex location
501 // x Cartisean X coordinate
502 // y Cartisean Y coordinate
503 // z Cartisean Z coordinate
504 // r On return, the radius
505 // eta On return, the pseudo-rapidity
506 // phi On return, the azimuthal angle
507 // theta On return, the polar angle;
510 // kTRUE on success, kFALSE in case of problems
512 if (x == 0 && y == 0 && z == 0) return kFALSE;
514 // Correct for vertex offset.
515 phi = TMath::ATan2(y, x);
516 r = TMath::Sqrt(y * y + x * x);
517 theta = TMath::ATan2(r, z);
518 eta = -TMath::Log(TMath::Tan(theta / 2));
524 //____________________________________________________________________
526 AliFMDGeometry::GetGlobal(const AliRecPoint* p,
528 TMatrixF& /* mat */) const
531 // Get global coordinates cooresponding to a rec point.
534 // p Reconstructed point.
535 // pos On return, the position
536 // mat On return, the material at @a post
541 //____________________________________________________________________
543 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const
546 // Get global coordinates cooresponding to a rec point.
549 // p Reconstructed point.
550 // pos On return, the position
552 // FIXME: Implement this function to work with outer rings too.
555 p->GetLocalPosition(local);
556 UShort_t detector = UShort_t(local.X());
557 UShort_t sector = UShort_t(local.Y());
558 UShort_t strip = UShort_t(local.Z());
559 Detector2XYZ(detector, 'I', sector, strip, x, y, z);
563 //____________________________________________________________________
565 AliFMDGeometry::Impact(const TParticle* /* particle */) const
568 // Check if particle will hit an active detector element.
570 // @todo implement this function
575 // @c true if @a particle will hit this detector
580 //____________________________________________________________________
582 AliFMDGeometry::SetAlignableVolumes() const
585 // Declare alignable volumes
587 for (Int_t d = 1; d <= 3; d++)
588 if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
592 //____________________________________________________________________
594 AliFMDGeometry::ExtractGeomInfo()
596 // Check the volume depth of some nodes, get the active volume
597 // numbers, and so forth.
599 // TODO: Here, we should actually also get the parameters of the
600 // shapes, like the verticies of the polygon shape that makes up the
601 // silicon sensor, the strip pitch, the ring radii, the z-positions,
602 // and so on - that is, all the geometric information we need for
603 // futher processing, such as simulation, digitization,
604 // reconstruction, etc.
605 Int_t detectorDepth = FindNodeDepth("F1MT_1", "ALIC");
606 Int_t ringDepth = FindNodeDepth(Form("FITV_%d", int('I')), "ALIC");
607 Int_t moduleDepth = FindNodeDepth("FIBH_0", "ALIC");
608 Int_t sectorDepth = FindNodeDepth("FISC_1", "ALIC");
611 AliFMDDebug(1, ("Geometry depths:\n"
616 sectorDepth, moduleDepth, ringDepth, detectorDepth));
617 if (sectorDepth < 0 && moduleDepth < 0) {
622 fDetectorOff = (ringDepth - detectorDepth);
623 TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
624 TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
625 if (actiVol) AddActive(actiVol->GetNumber());
626 if (actiVol) AddActive(actoVol->GetNumber());
628 else if (sectorDepth < 0) {
632 fRingOff = (moduleDepth - ringDepth) + 1;
633 fDetectorOff = (moduleDepth - detectorDepth) + 1;
634 TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
635 TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
636 if (modiVol) AddActive(modiVol->GetNumber());
637 if (modoVol) AddActive(modoVol->GetNumber());
640 Int_t stripDepth = FindNodeDepth("FIST_1", "ALIC");
642 fSectorOff = (stripDepth - sectorDepth);
643 fModuleOff = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
644 fRingOff = (stripDepth - ringDepth);
645 fDetectorOff = (stripDepth - detectorDepth );
646 TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
647 TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
648 if (striVol) AddActive(striVol->GetNumber());
649 if (stroVol) AddActive(stroVol->GetNumber());
651 AliFMDDebug(1, ("Geometry offsets:\n"
656 fSectorOff, fModuleOff, fRingOff, fDetectorOff));
660 //____________________________________________________________________
662 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
664 // If there's no node here.
665 if (!node) return -1;
666 // Check if it this one
668 if (sname == node->GetName()) return lvl;
670 // Check if the node is an immediate daugther
671 TObjArray* nodes = node->GetNodes();
672 if (!nodes) return -1;
673 // Increase the level, and search immediate sub nodes.
675 TGeoNode* found = static_cast<TGeoNode*>(nodes->FindObject(name));
676 if (found) return lvl;
678 // Check the sub node, if any of their sub-nodes match.
679 for (Int_t i = 0; i < nodes->GetEntries(); i++) {
680 TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
683 if (CheckNodes(sub, name, lvl) >= 0) return lvl;
685 // If not found, decrease the level
689 //____________________________________________________________________
691 FindNodeDepth(const char* name, const char* volname)
693 // Find the depth of a node
694 TGeoVolume* vol = gGeoManager->GetVolume(volname);
696 std::cerr << "No top volume defined" << std::endl;
700 TGeoIterator next(vol);
703 while ((node = next())) {
704 if (sName == node->GetName()) {
705 //std::cout << "Found node " << node->GetName() << " at level "
706 // << next.GetLevel() << std::endl;
707 return next.GetLevel();
712 TObjArray* nodes = vol->GetNodes();
714 std::cerr << "No nodes in top volume" << std::endl;
720 while ((node = static_cast<TGeoNode*>(next())))
721 if (CheckNodes(node, name, lvl) >= 0) return lvl;
726 //____________________________________________________________________