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 **************************************************************************/
16 /** @file AliFMDGeometry.cxx
17 @author Christian Holm Christensen <cholm@nbi.dk>
18 @date Mon Mar 27 12:40:37 2006
19 @brief Geometry mananger for the FMD
21 //____________________________________________________________________
23 // Forward Multiplicity Detector based on Silicon wafers.
25 // This class is a singleton that handles the geometry parameters of
28 // The actual code is done by various separate classes. Below is
29 // diagram showing the relationship between the various FMD classes
30 // that handles the geometry
35 // +----------------+<>--+ |
36 // | AliFMDGeometry | ^
37 // +----------------+<>--+ V 1..2
38 // 3 | +----------------+
39 // +-| AliFMDDetector |
43 // +-------------+-------------+
45 // +---------+ +---------+ +---------+
46 // | AliFMD1 | | AliFMD2 | | AliFMD3 |
47 // +---------+ +---------+ +---------+
51 // This class contains all stuff needed to do with a ring. It's
52 // used by the AliFMDDetector objects to instantise inner and
53 // outer rings. The AliFMDRing objects are shared by the
54 // AliFMDDetector objects, and owned by the AliFMDv1 object.
56 // * AliFMD1, AliFMD2, and AliFMD3
57 // These are specialisation of AliFMDDetector, that contains the
58 // particularities of each of the sub-detector system. It is
59 // envisioned that the classes should also define the support
60 // volumes and material for each of the detectors.
63 #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
64 #include "AliFMDRing.h" // ALIFMDRING_H
65 #include "AliFMD1.h" // ALIFMD1_H
66 #include "AliFMD2.h" // ALIFMD2_H
67 #include "AliFMD3.h" // ALIFMD2_H
68 #include "AliRecPoint.h" // ALIRECPOINT_H
69 #include "AliFMDDebug.h" // ALILOG_H
70 #include <TVector3.h> // ROOT_TVector3
71 // #include <TMatrix.h> // ROOT_TMatrix
72 // #include <TParticle.h> // ROOT_TParticle
73 #include <Riostream.h>
74 #include "AliFMDGeometryBuilder.h"
75 // #include <TArrayI.h>
76 #include <TGeoManager.h>
77 #include <TGeoVolume.h>
80 static Int_t FindNodeDepth(const char* name, const char* volname);
83 //====================================================================
84 ClassImp(AliFMDGeometry)
86 ; // This is here to keep Emacs for indenting the next line
89 //____________________________________________________________________
90 AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
92 //____________________________________________________________________
94 AliFMDGeometry::Instance()
96 // Return (newly created) singleton instance
97 if (!fgInstance) fgInstance = new AliFMDGeometry;
101 //____________________________________________________________________
102 AliFMDGeometry::AliFMDGeometry()
103 : AliGeometry("FMD", "Forward multiplicity"),
104 fIsInitialized(kFALSE),
113 fIsInitTrans(kFALSE),
124 // Default constructor
129 fUseAssembly = kTRUE;
130 fInner = new AliFMDRing('I');
131 fOuter = new AliFMDRing('O');
132 fFMD1 = new AliFMD1(fInner);
133 fFMD2 = new AliFMD2(fInner, fOuter);
134 fFMD3 = new AliFMD3(fInner, fOuter);
135 fIsInitialized = kFALSE;
139 //____________________________________________________________________
140 AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other)
141 : AliGeometry(other),
142 fIsInitialized(other.fIsInitialized),
143 fInner(other.fInner),
144 fOuter(other.fOuter),
148 fUseFMD1(other.fUseFMD1),
149 fUseFMD2(other.fUseFMD2),
150 fUseFMD3(other.fUseFMD3),
151 fIsInitTrans(other.fIsInitTrans),
152 fBuilder(other.fBuilder),
153 fDetectorOff(other.fDetectorOff),
154 fModuleOff(other.fModuleOff),
155 fRingOff(other.fRingOff),
156 fSectorOff(other.fSectorOff),
157 fActive(other.fActive),
158 fDetailed(other.fDetailed),
159 fUseAssembly(other.fUseAssembly)
167 //____________________________________________________________________
169 AliFMDGeometry::operator=(const AliFMDGeometry& other)
172 // Assignment operator
173 fUseFMD1 = other.fUseFMD1;
174 fUseFMD2 = other.fUseFMD2;
175 fUseFMD3 = other.fUseFMD3;
179 fInner = other.fInner;
180 fOuter = other.fOuter;
181 fIsInitialized = other.fIsInitialized;
185 //____________________________________________________________________
187 AliFMDGeometry::Init()
189 // Initialize the the singleton if not done so already
190 if (fIsInitialized) return;
198 //____________________________________________________________________
200 AliFMDGeometry::InitTransformations(Bool_t force)
202 // Find all local <-> global transforms
203 if (force) fIsInitTrans = kFALSE;
204 if (fIsInitTrans) return;
206 AliError("No TGeoManager defined");
209 AliFMDDebug(1, ("Initialising transforms for FMD geometry"));
210 if (fFMD1) fFMD1->InitTransformations();
211 if (fFMD2) fFMD2->InitTransformations();
212 if (fFMD3) fFMD3->InitTransformations();
213 fIsInitTrans = kTRUE;
216 //____________________________________________________________________
218 AliFMDGeometry::Build()
220 // Build the geometry
221 if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
222 fBuilder->SetDetailed(fDetailed);
223 fBuilder->UseAssembly(fUseAssembly);
227 //____________________________________________________________________
229 AliFMDGeometry::SetActive(Int_t* active, Int_t n)
231 // Set active volumes
233 for (Int_t i = 0; i < n; i++) {
234 AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
235 fActive[i] = active[i];
239 //____________________________________________________________________
241 AliFMDGeometry::AddActive(Int_t active)
243 // Add an active volume
244 Int_t n = fActive.fN;
249 //____________________________________________________________________
251 AliFMDGeometry::IsActive(Int_t vol) const
253 // Check if a volume is active
254 for (Int_t i = 0; i < fActive.fN; i++)
255 if (fActive[i] == vol) return kTRUE;
259 //____________________________________________________________________
261 AliFMDGeometry::GetDetector(Int_t i) const
263 // Get the ith detector. i should be one of 1, 2, or 3. If an
264 // invalid value is passed, 0 (NULL) is returned.
266 case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
267 case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
268 case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
273 //____________________________________________________________________
275 AliFMDGeometry::GetRing(Char_t i) const
277 // Get the ith ring. i should be one of 'I' or 'O' (case
278 // insensitive). If an invalid parameter is passed, 0 (NULL) is
282 case 'i': return fInner;
284 case 'o': return fOuter;
289 //____________________________________________________________________
291 AliFMDGeometry::Enable(Int_t i)
293 // Enable the ith detector. i should be one of 1, 2, or 3
295 case 1: fUseFMD1 = kTRUE; break;
296 case 2: fUseFMD2 = kTRUE; break;
297 case 3: fUseFMD3 = kTRUE; break;
301 //____________________________________________________________________
303 AliFMDGeometry::Disable(Int_t i)
305 // Disable the ith detector. i should be one of 1, 2, or 3
307 case 1: fUseFMD1 = kFALSE; break;
308 case 2: fUseFMD2 = kFALSE; break;
309 case 3: fUseFMD3 = kFALSE; break;
313 //____________________________________________________________________
315 AliFMDGeometry::Detector2XYZ(UShort_t detector,
323 // Translate detector coordinates (detector, ring, sector, strip) to
324 // spatial coordinates (x, y, z) in the master reference frame of
326 AliFMDDetector* det = GetDetector(detector);
328 AliWarning(Form("Unknown detector %d", detector));
331 det->Detector2XYZ(ring, sector, strip, x, y, z);
334 //____________________________________________________________________
336 AliFMDGeometry::XYZ2Detector(Double_t x,
342 UShort_t& strip) const
344 // Translate spatial coordinates (x,y,z) in the master reference frame of
345 // ALICE to the detector coordinates (detector, ring, sector,
346 // strip). Note, that if this method is to be used in
347 // reconstruction or the like, then the input z-coordinate should be
348 // corrected for the events interactions points z-coordinate, like
349 // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
350 AliFMDDetector* det = 0;
352 for (int i = 1; i <= 3; i++) {
353 det = GetDetector(i);
355 if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
356 detector = det->GetId();
363 //____________________________________________________________________
365 AliFMDGeometry::XYZ2REtaPhiTheta(Double_t x, Double_t y,
367 Double_t& r, Double_t& eta,
368 Double_t& phi, Double_t& theta)
371 // Service function to convert Cartisean XYZ to r, eta, phi, and theta.
373 // Note, that the z input should be corrected for the vertex location
376 // x Cartisean X coordinate
377 // y Cartisean Y coordinate
378 // z Cartisean Z coordinate
379 // r On return, the radius
380 // eta On return, the pseudo-rapidity
381 // phi On return, the azimuthal angle
382 // theta On return, the polar angle;
385 // kFALSE in case of problems.
387 if (x == 0 && y == 0 && z == 0) return kFALSE;
389 // Correct for vertex offset.
390 phi = TMath::ATan2(y, x);
391 r = TMath::Sqrt(y * y + x * x);
392 theta = TMath::ATan2(r, z);
393 eta = -TMath::Log(TMath::Tan(theta / 2));
399 //____________________________________________________________________
401 AliFMDGeometry::GetGlobal(const AliRecPoint* p,
403 TMatrixF& /* mat */) const
405 // Get the global coordinates cooresponding to the reconstructed
406 // point p. The coordiates is returned in the 3-vector pos passed
407 // to this member function. The matrix mat is used for rotations.
411 //____________________________________________________________________
413 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const
415 // Get the global coordinates cooresponding to the reconstructed
416 // point p. The coordiates is returned in the 3-vector pos passed
417 // to this member function. Note, as AliRecPoint only has places for
418 // 3 indicies, it is assumed that the ring hit is an inner ring -
419 // which obviously needn't be the case. This makes the member
420 // function pretty darn useless.
421 // FIXME: Implement this function to work with outer rings too.
424 p->GetLocalPosition(local);
425 UShort_t detector = UShort_t(local.X());
426 UShort_t sector = UShort_t(local.Y());
427 UShort_t strip = UShort_t(local.Z());
428 Detector2XYZ(detector, 'I', sector, strip, x, y, z);
432 //____________________________________________________________________
434 AliFMDGeometry::Impact(const TParticle* /* particle */) const
436 // Return true, if the particle will hit the active detector
437 // elements, and false if not. Should be used for fast
438 // simulations. Note, that the function currently return false
440 // FIXME: Implement this function.
444 //____________________________________________________________________
446 AliFMDGeometry::SetAlignableVolumes() const
448 // Declare alignable volumes
449 for (Int_t d = 1; d <= 3; d++)
450 if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
454 //____________________________________________________________________
456 AliFMDGeometry::ExtractGeomInfo()
458 // Check the volume depth of some nodes, get the active volume
459 // numbers, and so forth.
461 // TODO: Here, we should actually also get the parameters of the
462 // shapes, like the verticies of the polygon shape that makes up the
463 // silicon sensor, the strip pitch, the ring radii, the z-positions,
464 // and so on - that is, all the geometric information we need for
465 // futher processing, such as simulation, digitization,
466 // reconstruction, etc.
467 Int_t detectorDepth = FindNodeDepth("F1MT_1", "ALIC");
468 Int_t ringDepth = FindNodeDepth(Form("FITV_%d", int('I')), "ALIC");
469 Int_t moduleDepth = FindNodeDepth("FIBH_0", "ALIC");
470 Int_t sectorDepth = FindNodeDepth("FISC_1", "ALIC");
473 AliFMDDebug(1, ("Geometry depths:\n"
478 sectorDepth, moduleDepth, ringDepth, detectorDepth));
479 if (sectorDepth < 0 && moduleDepth < 0) {
484 fDetectorOff = (ringDepth - detectorDepth);
485 TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
486 TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
487 if (actiVol) AddActive(actiVol->GetNumber());
488 if (actiVol) AddActive(actoVol->GetNumber());
490 else if (sectorDepth < 0) {
494 fRingOff = (moduleDepth - ringDepth) + 1;
495 fDetectorOff = (moduleDepth - detectorDepth) + 1;
496 TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
497 TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
498 if (modiVol) AddActive(modiVol->GetNumber());
499 if (modoVol) AddActive(modoVol->GetNumber());
502 Int_t stripDepth = FindNodeDepth("FIST_1", "ALIC");
504 fSectorOff = (stripDepth - sectorDepth);
505 fModuleOff = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
506 fRingOff = (stripDepth - ringDepth);
507 fDetectorOff = (stripDepth - detectorDepth );
508 TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
509 TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
510 if (striVol) AddActive(striVol->GetNumber());
511 if (stroVol) AddActive(stroVol->GetNumber());
513 AliFMDDebug(1, ("Geometry offsets:\n"
518 fSectorOff, fModuleOff, fRingOff, fDetectorOff));
522 //____________________________________________________________________
524 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
526 // If there's no node here.
527 if (!node) return -1;
528 // Check if it this one
530 if (sname == node->GetName()) return lvl;
532 // Check if the node is an immediate daugther
533 TObjArray* nodes = node->GetNodes();
534 if (!nodes) return -1;
535 // Increase the level, and search immediate sub nodes.
537 TGeoNode* found = static_cast<TGeoNode*>(nodes->FindObject(name));
538 if (found) return lvl;
540 // Check the sub node, if any of their sub-nodes match.
541 for (Int_t i = 0; i < nodes->GetEntries(); i++) {
542 TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
545 if (CheckNodes(sub, name, lvl) >= 0) return lvl;
547 // If not found, decrease the level
551 //____________________________________________________________________
553 FindNodeDepth(const char* name, const char* volname)
555 // Find the depth of a node
556 TGeoVolume* vol = gGeoManager->GetVolume(volname);
558 std::cerr << "No top volume defined" << std::endl;
562 TGeoIterator next(vol);
565 while ((node = next())) {
566 if (sName == node->GetName()) {
567 //std::cout << "Found node " << node->GetName() << " at level "
568 // << next.GetLevel() << std::endl;
569 return next.GetLevel();
574 TObjArray* nodes = vol->GetNodes();
576 std::cerr << "No nodes in top volume" << std::endl;
582 while ((node = static_cast<TGeoNode*>(next())))
583 if (CheckNodes(node, name, lvl) >= 0) return lvl;
588 //____________________________________________________________________