Updates (N. Bastid)
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometry.cxx
CommitLineData
1a1fdef7 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 **************************************************************************/
1a1fdef7 15/* $Id$ */
c2fc1258 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
20*/
1a1fdef7 21//____________________________________________________________________
22//
23// Forward Multiplicity Detector based on Silicon wafers.
24//
25// This class is a singleton that handles the geometry parameters of
26// the FMD detectors.
27//
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
31//
32// +------------+
33// +- | AliFMDRing |
34// 2 | +------------+
35// +----------------+<>--+ |
36// | AliFMDGeometry | ^
37// +----------------+<>--+ V 1..2
38// 3 | +----------------+
39// +-| AliFMDDetector |
40// +----------------+
41// ^
42// |
43// +-------------+-------------+
44// | | |
45// +---------+ +---------+ +---------+
46// | AliFMD1 | | AliFMD2 | | AliFMD3 |
47// +---------+ +---------+ +---------+
48//
49//
50// * AliFMDRing
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.
55//
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.
61//
62//
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 "AliLog.h" // ALIRECPOINT_H
70#include <TVector3.h> // ROOT_TVector3
02a27b50 71// #include <TMatrix.h> // ROOT_TMatrix
72// #include <TParticle.h> // ROOT_TParticle
1a1fdef7 73#include <Riostream.h>
54e415a8 74#include "AliFMDGeometryBuilder.h"
02a27b50 75// #include <TArrayI.h>
54e415a8 76#include <TGeoManager.h>
77#include <TGeoVolume.h>
78#include <TGeoNode.h>
79static Int_t FindNodeDepth(const char* name, const char* volname);
54e415a8 80
1a1fdef7 81
82//====================================================================
83ClassImp(AliFMDGeometry)
84#if 0
85 ; // This is here to keep Emacs for indenting the next line
86#endif
87
88//____________________________________________________________________
89AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
90
91//____________________________________________________________________
92AliFMDGeometry*
93AliFMDGeometry::Instance()
94{
69b696b9 95 // Return (newly created) singleton instance
1a1fdef7 96 if (!fgInstance) fgInstance = new AliFMDGeometry;
97 return fgInstance;
98}
99
100//____________________________________________________________________
101AliFMDGeometry::AliFMDGeometry()
a1f80595 102 : AliGeometry("FMD", "Forward multiplicity"),
103 fBuilder(0)
1a1fdef7 104{
69b696b9 105 // PROTECTED
106 // Default constructor
54e415a8 107 fUseFMD1 = kTRUE;
108 fUseFMD2 = kTRUE;
109 fUseFMD3 = kTRUE;
54e415a8 110 fDetailed = kTRUE;
111 fUseAssembly = kTRUE;
1a1fdef7 112 fInner = new AliFMDRing('I');
113 fOuter = new AliFMDRing('O');
114 fFMD1 = new AliFMD1(fInner);
115 fFMD2 = new AliFMD2(fInner, fOuter);
116 fFMD3 = new AliFMD3(fInner, fOuter);
117 fIsInitialized = kFALSE;
54e415a8 118 fActive.Reset(-1);
1a1fdef7 119}
120
121//____________________________________________________________________
69b696b9 122AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other)
123 : AliGeometry(other),
124 fIsInitialized(other.fIsInitialized),
125 fInner(other.fInner),
126 fOuter(other.fOuter),
127 fFMD1(other.fFMD1),
128 fFMD2(other.fFMD2),
129 fFMD3(other.fFMD3),
130 fUseFMD1(other.fUseFMD1),
131 fUseFMD2(other.fUseFMD2),
bf000c32 132 fUseFMD3(other.fUseFMD3),
133 fActive(other.fActive),
54e415a8 134 fDetailed(other.fDetailed),
135 fUseAssembly(other.fUseAssembly)
69b696b9 136{
137 // PROTECTED
138 // Copy constructor
139}
140
141
142
143//____________________________________________________________________
144AliFMDGeometry&
145AliFMDGeometry::operator=(const AliFMDGeometry& other)
146{
147 // PROTECTED
148 // Assignment operator
149 fUseFMD1 = other.fUseFMD1;
150 fUseFMD2 = other.fUseFMD2;
151 fUseFMD3 = other.fUseFMD3;
152 fFMD1 = other.fFMD1;
153 fFMD2 = other.fFMD2;
154 fFMD3 = other.fFMD3;
155 fInner = other.fInner;
156 fOuter = other.fOuter;
157 fIsInitialized = other.fIsInitialized;
158 return *this;
159}
160
161//____________________________________________________________________
1a1fdef7 162void
163AliFMDGeometry::Init()
164{
69b696b9 165 // Initialize the the singleton if not done so already
1a1fdef7 166 if (fIsInitialized) return;
167 fInner->Init();
168 fOuter->Init();
169 fFMD1->Init();
170 fFMD2->Init();
171 fFMD3->Init();
172}
173
bf000c32 174//____________________________________________________________________
175void
176AliFMDGeometry::InitTransformations()
177{
02a27b50 178 // Find all local <-> global transforms
bf000c32 179 if (!gGeoManager) {
180 AliError("No TGeoManager defined");
181 return;
182 }
183 AliDebug(0, "Initialising transforms for FMD geometry");
184 if (fFMD1) fFMD1->InitTransformations();
185 if (fFMD2) fFMD2->InitTransformations();
186 if (fFMD3) fFMD3->InitTransformations();
187}
188
54e415a8 189//____________________________________________________________________
190void
191AliFMDGeometry::Build()
192{
02a27b50 193 // Build the geometry
54e415a8 194 if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
195 fBuilder->SetDetailed(fDetailed);
196 fBuilder->UseAssembly(fUseAssembly);
197 fBuilder->Exec();
198}
199
200//____________________________________________________________________
201void
202AliFMDGeometry::SetActive(Int_t* active, Int_t n)
203{
02a27b50 204 // Set active volumes
54e415a8 205 fActive.Set(n);
088f8e79 206 for (Int_t i = 0; i < n; i++) {
207 AliDebug(1, Form("Active vol id # %d: %d", i, active[i]));
208 fActive[i] = active[i];
209 }
54e415a8 210}
211
212//____________________________________________________________________
213void
214AliFMDGeometry::AddActive(Int_t active)
215{
02a27b50 216 // Add an active volume
54e415a8 217 Int_t n = fActive.fN;
218 fActive.Set(n+1);
219 fActive[n] = active;
220}
221
222//____________________________________________________________________
223Bool_t
224AliFMDGeometry::IsActive(Int_t vol) const
225{
02a27b50 226 // Check if a volume is active
54e415a8 227 for (Int_t i = 0; i < fActive.fN; i++)
228 if (fActive[i] == vol) return kTRUE;
229 return kFALSE;
230}
54e415a8 231
1a1fdef7 232//____________________________________________________________________
233AliFMDDetector*
234AliFMDGeometry::GetDetector(Int_t i) const
235{
69b696b9 236 // Get the ith detector. i should be one of 1, 2, or 3. If an
237 // invalid value is passed, 0 (NULL) is returned.
1a1fdef7 238 switch (i) {
239 case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
240 case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
241 case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
242 }
243 return 0;
244}
245
246//____________________________________________________________________
247AliFMDRing*
248AliFMDGeometry::GetRing(Char_t i) const
249{
69b696b9 250 // Get the ith ring. i should be one of 'I' or 'O' (case
251 // insensitive). If an invalid parameter is passed, 0 (NULL) is
252 // returned.
1a1fdef7 253 switch (i) {
254 case 'I':
255 case 'i': return fInner;
256 case 'O':
257 case 'o': return fOuter;
258 }
259 return 0;
260}
261
262//____________________________________________________________________
263void
264AliFMDGeometry::Enable(Int_t i)
265{
69b696b9 266 // Enable the ith detector. i should be one of 1, 2, or 3
1a1fdef7 267 switch (i) {
268 case 1: fUseFMD1 = kTRUE; break;
269 case 2: fUseFMD2 = kTRUE; break;
270 case 3: fUseFMD3 = kTRUE; break;
271 }
272}
273
274//____________________________________________________________________
275void
276AliFMDGeometry::Disable(Int_t i)
277{
69b696b9 278 // Disable the ith detector. i should be one of 1, 2, or 3
1a1fdef7 279 switch (i) {
280 case 1: fUseFMD1 = kFALSE; break;
281 case 2: fUseFMD2 = kFALSE; break;
282 case 3: fUseFMD3 = kFALSE; break;
283 }
284}
285
286//____________________________________________________________________
287void
288AliFMDGeometry::Detector2XYZ(UShort_t detector,
69b696b9 289 Char_t ring,
290 UShort_t sector,
291 UShort_t strip,
292 Double_t& x,
293 Double_t& y,
294 Double_t& z) const
1a1fdef7 295{
69b696b9 296 // Translate detector coordinates (detector, ring, sector, strip) to
297 // spatial coordinates (x, y, z) in the master reference frame of
298 // ALICE.
1a1fdef7 299 AliFMDDetector* det = GetDetector(detector);
bf000c32 300 if (!det) {
301 AliWarning(Form("Unknown detector %d", detector));
302 return;
303 }
1a1fdef7 304 det->Detector2XYZ(ring, sector, strip, x, y, z);
305}
306
54e415a8 307//____________________________________________________________________
308Bool_t
309AliFMDGeometry::XYZ2Detector(Double_t x,
310 Double_t y,
311 Double_t z,
312 UShort_t& detector,
313 Char_t& ring,
314 UShort_t& sector,
315 UShort_t& strip) const
316{
317 // Translate spatial coordinates (x,y,z) in the master reference frame of
318 // ALICE to the detector coordinates (detector, ring, sector,
319 // strip). Note, that if this method is to be used in
320 // reconstruction or the like, then the input z-coordinate should be
321 // corrected for the events interactions points z-coordinate, like
322 // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
323 AliFMDDetector* det = 0;
324 detector = 0;
325 for (int i = 1; i <= 3; i++) {
326 det = GetDetector(i);
327 if (!det) continue;
328 if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
329 detector = det->GetId();
330 return kTRUE;
331 }
332 }
333 return kFALSE;
334}
335
1a1fdef7 336
337//____________________________________________________________________
338void
339AliFMDGeometry::GetGlobal(const AliRecPoint* p,
340 TVector3& pos,
e8d02863 341 TMatrixF& /* mat */) const
1a1fdef7 342{
69b696b9 343 // Get the global coordinates cooresponding to the reconstructed
344 // point p. The coordiates is returned in the 3-vector pos passed
345 // to this member function. The matrix mat is used for rotations.
1a1fdef7 346 GetGlobal(p, pos);
347}
348
349//____________________________________________________________________
350void
351AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const
352{
69b696b9 353 // Get the global coordinates cooresponding to the reconstructed
354 // point p. The coordiates is returned in the 3-vector pos passed
355 // to this member function. Note, as AliRecPoint only has places for
356 // 3 indicies, it is assumed that the ring hit is an inner ring -
357 // which obviously needn't be the case. This makes the member
358 // function pretty darn useless.
359 // FIXME: Implement this function to work with outer rings too.
1a1fdef7 360 Double_t x, y, z;
361 TVector3 local;
362 p->GetLocalPosition(local);
363 UShort_t detector = UShort_t(local.X());
364 UShort_t sector = UShort_t(local.Y());
365 UShort_t strip = UShort_t(local.Z());
366 Detector2XYZ(detector, 'I', sector, strip, x, y, z);
367 pos.SetXYZ(x, y, z);
368}
369
370//____________________________________________________________________
371Bool_t
372AliFMDGeometry::Impact(const TParticle* /* particle */) const
373{
69b696b9 374 // Return true, if the particle will hit the active detector
375 // elements, and false if not. Should be used for fast
376 // simulations. Note, that the function currently return false
377 // always.
378 // FIXME: Implement this function.
1a1fdef7 379 return kFALSE;
380}
381
54e415a8 382//____________________________________________________________________
383void
384AliFMDGeometry::ExtractGeomInfo()
385{
386 // Check the volume depth of some nodes, get the active volume
387 // numbers, and so forth.
388 //
389 // TODO: Here, we should actually also get the parameters of the
390 // shapes, like the verticies of the polygon shape that makes up the
391 // silicon sensor, the strip pitch, the ring radii, the z-positions,
392 // and so on - that is, all the geometric information we need for
393 // futher processing, such as simulation, digitization,
394 // reconstruction, etc.
395 Int_t detectorDepth = FindNodeDepth("FMD1_1", "ALIC");
396 Int_t ringDepth = FindNodeDepth(Form("FMDI_%d", Int_t('I')), "ALIC");
397 Int_t moduleDepth = FindNodeDepth("FIFV_0", "ALIC");
398 Int_t sectorDepth = FindNodeDepth("FISE_1", "ALIC");
399 fActive.Reset(-1);
400 AliDebug(1, Form("Geometry depths:\n"
401 " Sector: %d\n"
402 " Module: %d\n"
403 " Ring: %d\n"
404 " Detector: %d",
405 sectorDepth, moduleDepth, ringDepth, detectorDepth));
406 if (sectorDepth < 0 && moduleDepth < 0) {
407 fDetailed = kFALSE;
408 fSectorOff = -1;
409 fModuleOff = -1;
410 fRingOff = 0;
411 fDetectorOff = (ringDepth - detectorDepth);
412 TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
413 TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
414 if (actiVol) AddActive(actiVol->GetNumber());
415 if (actiVol) AddActive(actoVol->GetNumber());
416 }
417 else if (sectorDepth < 0) {
418 fDetailed = kFALSE;
419 fSectorOff = -1;
420 fModuleOff = 1;
421 fRingOff = (moduleDepth - ringDepth) + 1;
422 fDetectorOff = (moduleDepth - detectorDepth) + 1;
423 TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
424 TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
425 if (modiVol) AddActive(modiVol->GetNumber());
426 if (modoVol) AddActive(modoVol->GetNumber());
427 }
428 else {
429 Int_t stripDepth = FindNodeDepth("FIST_1", "ALIC");
430 fDetailed = kTRUE;
431 fSectorOff = (stripDepth - sectorDepth);
432 fModuleOff = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
433 fRingOff = (stripDepth - ringDepth);
434 fDetectorOff = (stripDepth - detectorDepth );
435 TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
436 TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
437 if (striVol) AddActive(striVol->GetNumber());
438 if (stroVol) AddActive(stroVol->GetNumber());
439 }
440 AliDebug(1, Form("Geometry offsets:\n"
441 " Sector: %d\n"
442 " Module: %d\n"
443 " Ring: %d\n"
444 " Detector: %d",
445 fSectorOff, fModuleOff, fRingOff, fDetectorOff));
446}
447
448
449//____________________________________________________________________
450static Int_t
451CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
452{
453 // If there's no node here.
454 if (!node) return -1;
455 // Check if it this one
456 TString sname(name);
457 if (sname == node->GetName()) return lvl;
458
459 // Check if the node is an immediate daugther
460 TObjArray* nodes = node->GetNodes();
461 if (!nodes) return -1;
462 // Increase the level, and search immediate sub nodes.
463 lvl++;
464 TGeoNode* found = static_cast<TGeoNode*>(nodes->FindObject(name));
465 if (found) return lvl;
466
467 // Check the sub node, if any of their sub-nodes match.
468 for (Int_t i = 0; i < nodes->GetEntries(); i++) {
469 TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
470 if (!sub) continue;
471 // Recurive check
472 if (CheckNodes(sub, name, lvl) >= 0) return lvl;
473 }
474 // If not found, decrease the level
475 lvl--;
476 return -1;
477}
478//____________________________________________________________________
479Int_t
480FindNodeDepth(const char* name, const char* volname)
481{
02a27b50 482 // Find the depth of a node
54e415a8 483 TGeoVolume* vol = gGeoManager->GetVolume(volname);
484 if (!vol) {
485 std::cerr << "No top volume defined" << std::endl;
486 return -1;
487 }
488 TObjArray* nodes = vol->GetNodes();
489 if (!nodes) {
490 std::cerr << "No nodes in top volume" << std::endl;
491 return -1;
492 }
493 TIter next(nodes);
494 TGeoNode* node = 0;
495 Int_t lvl = 0;
496 while ((node = static_cast<TGeoNode*>(next())))
497 if (CheckNodes(node, name, lvl) >= 0) return lvl;
498 return -1;
499}
54e415a8 500
1a1fdef7 501//____________________________________________________________________
502//
503// EOF
504//