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>
79 static Int_t FindNodeDepth(const char* name, const char* volname);
82 //====================================================================
83 ClassImp(AliFMDGeometry)
85 ; // This is here to keep Emacs for indenting the next line
88 //____________________________________________________________________
89 AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
91 //____________________________________________________________________
93 AliFMDGeometry::Instance()
95 // Return (newly created) singleton instance
96 if (!fgInstance) fgInstance = new AliFMDGeometry;
100 //____________________________________________________________________
101 AliFMDGeometry::AliFMDGeometry()
102 : AliGeometry("FMD", "Forward multiplicity"),
103 fIsInitialized(kFALSE),
122 // Default constructor
127 fUseAssembly = kTRUE;
128 fInner = new AliFMDRing('I');
129 fOuter = new AliFMDRing('O');
130 fFMD1 = new AliFMD1(fInner);
131 fFMD2 = new AliFMD2(fInner, fOuter);
132 fFMD3 = new AliFMD3(fInner, fOuter);
133 fIsInitialized = kFALSE;
137 //____________________________________________________________________
138 AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other)
139 : AliGeometry(other),
140 fIsInitialized(other.fIsInitialized),
141 fInner(other.fInner),
142 fOuter(other.fOuter),
146 fUseFMD1(other.fUseFMD1),
147 fUseFMD2(other.fUseFMD2),
148 fUseFMD3(other.fUseFMD3),
149 fBuilder(other.fBuilder),
150 fDetectorOff(other.fDetectorOff),
151 fModuleOff(other.fModuleOff),
152 fRingOff(other.fRingOff),
153 fSectorOff(other.fSectorOff),
154 fActive(other.fActive),
155 fDetailed(other.fDetailed),
156 fUseAssembly(other.fUseAssembly)
164 //____________________________________________________________________
166 AliFMDGeometry::operator=(const AliFMDGeometry& other)
169 // Assignment operator
170 fUseFMD1 = other.fUseFMD1;
171 fUseFMD2 = other.fUseFMD2;
172 fUseFMD3 = other.fUseFMD3;
176 fInner = other.fInner;
177 fOuter = other.fOuter;
178 fIsInitialized = other.fIsInitialized;
182 //____________________________________________________________________
184 AliFMDGeometry::Init()
186 // Initialize the the singleton if not done so already
187 if (fIsInitialized) return;
195 //____________________________________________________________________
197 AliFMDGeometry::InitTransformations()
199 // Find all local <-> global transforms
201 AliError("No TGeoManager defined");
204 AliFMDDebug(0, ("Initialising transforms for FMD geometry"));
205 if (fFMD1) fFMD1->InitTransformations();
206 if (fFMD2) fFMD2->InitTransformations();
207 if (fFMD3) fFMD3->InitTransformations();
210 //____________________________________________________________________
212 AliFMDGeometry::Build()
214 // Build the geometry
215 if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
216 fBuilder->SetDetailed(fDetailed);
217 fBuilder->UseAssembly(fUseAssembly);
221 //____________________________________________________________________
223 AliFMDGeometry::SetActive(Int_t* active, Int_t n)
225 // Set active volumes
227 for (Int_t i = 0; i < n; i++) {
228 AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
229 fActive[i] = active[i];
233 //____________________________________________________________________
235 AliFMDGeometry::AddActive(Int_t active)
237 // Add an active volume
238 Int_t n = fActive.fN;
243 //____________________________________________________________________
245 AliFMDGeometry::IsActive(Int_t vol) const
247 // Check if a volume is active
248 for (Int_t i = 0; i < fActive.fN; i++)
249 if (fActive[i] == vol) return kTRUE;
253 //____________________________________________________________________
255 AliFMDGeometry::GetDetector(Int_t i) const
257 // Get the ith detector. i should be one of 1, 2, or 3. If an
258 // invalid value is passed, 0 (NULL) is returned.
260 case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
261 case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
262 case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
267 //____________________________________________________________________
269 AliFMDGeometry::GetRing(Char_t i) const
271 // Get the ith ring. i should be one of 'I' or 'O' (case
272 // insensitive). If an invalid parameter is passed, 0 (NULL) is
276 case 'i': return fInner;
278 case 'o': return fOuter;
283 //____________________________________________________________________
285 AliFMDGeometry::Enable(Int_t i)
287 // Enable the ith detector. i should be one of 1, 2, or 3
289 case 1: fUseFMD1 = kTRUE; break;
290 case 2: fUseFMD2 = kTRUE; break;
291 case 3: fUseFMD3 = kTRUE; break;
295 //____________________________________________________________________
297 AliFMDGeometry::Disable(Int_t i)
299 // Disable the ith detector. i should be one of 1, 2, or 3
301 case 1: fUseFMD1 = kFALSE; break;
302 case 2: fUseFMD2 = kFALSE; break;
303 case 3: fUseFMD3 = kFALSE; break;
307 //____________________________________________________________________
309 AliFMDGeometry::Detector2XYZ(UShort_t detector,
317 // Translate detector coordinates (detector, ring, sector, strip) to
318 // spatial coordinates (x, y, z) in the master reference frame of
320 AliFMDDetector* det = GetDetector(detector);
322 AliWarning(Form("Unknown detector %d", detector));
325 det->Detector2XYZ(ring, sector, strip, x, y, z);
328 //____________________________________________________________________
330 AliFMDGeometry::XYZ2Detector(Double_t x,
336 UShort_t& strip) const
338 // Translate spatial coordinates (x,y,z) in the master reference frame of
339 // ALICE to the detector coordinates (detector, ring, sector,
340 // strip). Note, that if this method is to be used in
341 // reconstruction or the like, then the input z-coordinate should be
342 // corrected for the events interactions points z-coordinate, like
343 // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
344 AliFMDDetector* det = 0;
346 for (int i = 1; i <= 3; i++) {
347 det = GetDetector(i);
349 if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
350 detector = det->GetId();
358 //____________________________________________________________________
360 AliFMDGeometry::GetGlobal(const AliRecPoint* p,
362 TMatrixF& /* mat */) const
364 // Get the global coordinates cooresponding to the reconstructed
365 // point p. The coordiates is returned in the 3-vector pos passed
366 // to this member function. The matrix mat is used for rotations.
370 //____________________________________________________________________
372 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const
374 // Get the global coordinates cooresponding to the reconstructed
375 // point p. The coordiates is returned in the 3-vector pos passed
376 // to this member function. Note, as AliRecPoint only has places for
377 // 3 indicies, it is assumed that the ring hit is an inner ring -
378 // which obviously needn't be the case. This makes the member
379 // function pretty darn useless.
380 // FIXME: Implement this function to work with outer rings too.
383 p->GetLocalPosition(local);
384 UShort_t detector = UShort_t(local.X());
385 UShort_t sector = UShort_t(local.Y());
386 UShort_t strip = UShort_t(local.Z());
387 Detector2XYZ(detector, 'I', sector, strip, x, y, z);
391 //____________________________________________________________________
393 AliFMDGeometry::Impact(const TParticle* /* particle */) const
395 // Return true, if the particle will hit the active detector
396 // elements, and false if not. Should be used for fast
397 // simulations. Note, that the function currently return false
399 // FIXME: Implement this function.
403 //____________________________________________________________________
405 AliFMDGeometry::SetAlignableVolumes() const
407 // Declare alignable volumes
408 for (Int_t d = 1; d <= 3; d++)
409 if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
413 //____________________________________________________________________
415 AliFMDGeometry::ExtractGeomInfo()
417 // Check the volume depth of some nodes, get the active volume
418 // numbers, and so forth.
420 // TODO: Here, we should actually also get the parameters of the
421 // shapes, like the verticies of the polygon shape that makes up the
422 // silicon sensor, the strip pitch, the ring radii, the z-positions,
423 // and so on - that is, all the geometric information we need for
424 // futher processing, such as simulation, digitization,
425 // reconstruction, etc.
426 Int_t detectorDepth = FindNodeDepth("FMD1_1", "ALIC");
427 Int_t ringDepth = FindNodeDepth(Form("FMDI_%d", Int_t('I')), "ALIC");
428 Int_t moduleDepth = FindNodeDepth("FIFV_0", "ALIC");
429 Int_t sectorDepth = FindNodeDepth("FISE_1", "ALIC");
431 AliFMDDebug(1, ("Geometry depths:\n"
436 sectorDepth, moduleDepth, ringDepth, detectorDepth));
437 if (sectorDepth < 0 && moduleDepth < 0) {
442 fDetectorOff = (ringDepth - detectorDepth);
443 TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
444 TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
445 if (actiVol) AddActive(actiVol->GetNumber());
446 if (actiVol) AddActive(actoVol->GetNumber());
448 else if (sectorDepth < 0) {
452 fRingOff = (moduleDepth - ringDepth) + 1;
453 fDetectorOff = (moduleDepth - detectorDepth) + 1;
454 TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
455 TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
456 if (modiVol) AddActive(modiVol->GetNumber());
457 if (modoVol) AddActive(modoVol->GetNumber());
460 Int_t stripDepth = FindNodeDepth("FIST_1", "ALIC");
462 fSectorOff = (stripDepth - sectorDepth);
463 fModuleOff = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
464 fRingOff = (stripDepth - ringDepth);
465 fDetectorOff = (stripDepth - detectorDepth );
466 TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
467 TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
468 if (striVol) AddActive(striVol->GetNumber());
469 if (stroVol) AddActive(stroVol->GetNumber());
471 AliFMDDebug(1, ("Geometry offsets:\n"
476 fSectorOff, fModuleOff, fRingOff, fDetectorOff));
480 //____________________________________________________________________
482 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
484 // If there's no node here.
485 if (!node) return -1;
486 // Check if it this one
488 if (sname == node->GetName()) return lvl;
490 // Check if the node is an immediate daugther
491 TObjArray* nodes = node->GetNodes();
492 if (!nodes) return -1;
493 // Increase the level, and search immediate sub nodes.
495 TGeoNode* found = static_cast<TGeoNode*>(nodes->FindObject(name));
496 if (found) return lvl;
498 // Check the sub node, if any of their sub-nodes match.
499 for (Int_t i = 0; i < nodes->GetEntries(); i++) {
500 TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
503 if (CheckNodes(sub, name, lvl) >= 0) return lvl;
505 // If not found, decrease the level
509 //____________________________________________________________________
511 FindNodeDepth(const char* name, const char* volname)
513 // Find the depth of a node
514 TGeoVolume* vol = gGeoManager->GetVolume(volname);
516 std::cerr << "No top volume defined" << std::endl;
519 TObjArray* nodes = vol->GetNodes();
521 std::cerr << "No nodes in top volume" << std::endl;
527 while ((node = static_cast<TGeoNode*>(next())))
528 if (CheckNodes(node, name, lvl) >= 0) return lvl;
532 //____________________________________________________________________