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 if (&other == this) return *this;
220 fUseFMD1 = other.fUseFMD1;
221 fUseFMD2 = other.fUseFMD2;
222 fUseFMD3 = other.fUseFMD3;
226 fInner = other.fInner;
227 fOuter = other.fOuter;
228 fIsInitialized = other.fIsInitialized;
232 //____________________________________________________________________
234 AliFMDGeometry::Init()
237 // Initialize the the singleton if not done so already
239 if (fIsInitialized) return;
247 //____________________________________________________________________
249 AliFMDGeometry::InitTransformations(Bool_t force)
252 // Find all local <-> global transforms
254 if (force) fIsInitTrans = kFALSE;
255 if (fIsInitTrans) return;
257 AliError("No TGeoManager defined");
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;
267 //____________________________________________________________________
269 AliFMDGeometry::Build()
272 // Make the geometry. This delegates to AliFMDGeometryBuilder
274 if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
275 fBuilder->SetDetailed(fDetailed);
276 fBuilder->UseAssembly(fUseAssembly);
280 //____________________________________________________________________
282 AliFMDGeometry::SetActive(Int_t* active, Int_t n)
285 // Set active volumes
288 // active Active volume id array
289 // n elements of @a active
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];
298 //____________________________________________________________________
300 AliFMDGeometry::AddActive(Int_t active)
303 // Add an active volume
306 // id Register volume @a id to be active
309 Int_t n = fActive.fN;
314 //____________________________________________________________________
316 AliFMDGeometry::IsActive(Int_t vol) const
319 // Check if volume @a vol is marked as active
324 // @c true if @a vol is declared active
326 for (Int_t i = 0; i < fActive.fN; i++)
327 if (fActive[i] == vol) return kTRUE;
331 //____________________________________________________________________
333 AliFMDGeometry::GetDetector(Int_t i) const
336 // Get description of a sub-detector
341 // Description of sub-detector, or 0
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;
351 //____________________________________________________________________
353 AliFMDGeometry::GetRing(Char_t i) const
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
363 // Description of ring, or 0
367 case 'i': return fInner;
369 case 'o': return fOuter;
374 //____________________________________________________________________
376 AliFMDGeometry::Enable(Int_t i)
379 // Enable the ith detector
382 // i IF true, enable sub-detector @a i
385 case 1: fUseFMD1 = kTRUE; break;
386 case 2: fUseFMD2 = kTRUE; break;
387 case 3: fUseFMD3 = kTRUE; break;
391 //____________________________________________________________________
393 AliFMDGeometry::Disable(Int_t i)
396 // Disable the ith detector
399 // i IF true, disable sub-detector @a i
402 case 1: fUseFMD1 = kFALSE; break;
403 case 2: fUseFMD2 = kFALSE; break;
404 case 3: fUseFMD3 = kFALSE; break;
408 //____________________________________________________________________
410 AliFMDGeometry::Detector2XYZ(UShort_t detector,
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.
425 // detector Detector number
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
433 AliFMDDetector* det = GetDetector(detector);
435 AliWarning(Form("Unknown detector %d", detector));
438 det->Detector2XYZ(ring, sector, strip, x, y, z);
441 //____________________________________________________________________
443 AliFMDGeometry::XYZ2Detector(Double_t x,
449 UShort_t& strip) const
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,
459 // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
466 // detector On return, Detector number
467 // ring On return, Ring id
468 // sector On return, Sector number
469 // strip On return, Strip number
471 // @c false of (@a x, @a y, @a z) is not within this
474 AliFMDDetector* det = 0;
476 for (int i = 1; i <= 3; i++) {
477 det = GetDetector(i);
479 if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
480 detector = det->GetId();
487 //____________________________________________________________________
489 AliFMDGeometry::XYZ2REtaPhiTheta(Double_t x, Double_t y,
491 Double_t& r, Double_t& eta,
492 Double_t& phi, Double_t& theta)
496 // Service function to convert Cartisean XYZ to r, eta, phi, and theta.
498 // Note, that the z input should be corrected for the vertex location
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;
511 // kTRUE on success, kFALSE in case of problems
513 if (x == 0 && y == 0 && z == 0) return kFALSE;
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));
525 //____________________________________________________________________
527 AliFMDGeometry::GetGlobal(const AliRecPoint* p,
529 TMatrixF& /* mat */) const
532 // Get global coordinates cooresponding to a rec point.
535 // p Reconstructed point.
536 // pos On return, the position
537 // mat On return, the material at @a post
542 //____________________________________________________________________
544 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const
547 // Get global coordinates cooresponding to a rec point.
550 // p Reconstructed point.
551 // pos On return, the position
553 // FIXME: Implement this function to work with outer rings too.
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);
564 //____________________________________________________________________
566 AliFMDGeometry::Impact(const TParticle* /* particle */) const
569 // Check if particle will hit an active detector element.
571 // @todo implement this function
576 // @c true if @a particle will hit this detector
581 //____________________________________________________________________
583 AliFMDGeometry::SetAlignableVolumes() const
586 // Declare alignable volumes
588 for (Int_t d = 1; d <= 3; d++)
589 if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
593 //____________________________________________________________________
595 AliFMDGeometry::ExtractGeomInfo()
597 // Check the volume depth of some nodes, get the active volume
598 // numbers, and so forth.
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");
612 AliFMDDebug(1, ("Geometry depths:\n"
617 sectorDepth, moduleDepth, ringDepth, detectorDepth));
618 if (sectorDepth < 0 && moduleDepth < 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());
629 else if (sectorDepth < 0) {
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());
641 Int_t stripDepth = FindNodeDepth("FIST_1", "ALIC");
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());
652 AliFMDDebug(1, ("Geometry offsets:\n"
657 fSectorOff, fModuleOff, fRingOff, fDetectorOff));
661 //____________________________________________________________________
663 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
665 // If there's no node here.
666 if (!node) return -1;
667 // Check if it this one
669 if (sname == node->GetName()) return lvl;
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.
676 TGeoNode* found = static_cast<TGeoNode*>(nodes->FindObject(name));
677 if (found) return lvl;
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));
684 if (CheckNodes(sub, name, lvl) >= 0) return lvl;
686 // If not found, decrease the level
692 //____________________________________________________________________
694 FindNodeDepth(const char* name, const char* volname)
696 // Find the depth of a node
697 TGeoVolume* vol = gGeoManager->GetVolume(volname);
699 std::cerr << "No top volume defined" << std::endl;
703 TGeoIterator next(vol);
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();
715 TObjArray* nodes = vol->GetNodes();
717 std::cerr << "No nodes in top volume" << std::endl;
723 while ((node = static_cast<TGeoNode*>(next())))
724 if (CheckNodes(node, name, lvl) >= 0) return lvl;
729 //____________________________________________________________________