Fixed Effective C++ warnings
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometry.cxx
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  **************************************************************************/
15 /* $Id$ */
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 */
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
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>
78 #include <TGeoNode.h>
79 static Int_t FindNodeDepth(const char* name, const char* volname);
80
81
82 //====================================================================
83 ClassImp(AliFMDGeometry)
84 #if 0
85   ; // This is here to keep Emacs for indenting the next line
86 #endif
87
88 //____________________________________________________________________
89 AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
90
91 //____________________________________________________________________
92 AliFMDGeometry* 
93 AliFMDGeometry::Instance() 
94 {
95   // Return (newly created) singleton instance 
96   if (!fgInstance) fgInstance = new AliFMDGeometry;
97   return fgInstance;
98 }
99
100 //____________________________________________________________________
101 AliFMDGeometry::AliFMDGeometry() 
102   : AliGeometry("FMD", "Forward multiplicity"), 
103     fIsInitialized(kFALSE), 
104     fInner(0),
105     fOuter(0),
106     fFMD1(0),
107     fFMD2(0),
108     fFMD3(0),
109     fUseFMD1(kFALSE),
110     fUseFMD2(kFALSE),
111     fUseFMD3(kFALSE),
112     fBuilder(0),
113     fDetectorOff(0),
114     fModuleOff(0),  
115     fRingOff(0),
116     fSectorOff(0),
117     fActive(2),
118     fDetailed(kFALSE),       
119     fUseAssembly(kFALSE)
120 {
121   // PROTECTED
122   // Default constructor 
123   fUseFMD1     = kTRUE;
124   fUseFMD2     = kTRUE;
125   fUseFMD3     = kTRUE;  
126   fDetailed    = kTRUE;
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;
134   fActive.Reset(-1);
135 }
136
137 //____________________________________________________________________
138 AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other) 
139   : AliGeometry(other),
140     fIsInitialized(other.fIsInitialized),
141     fInner(other.fInner), 
142     fOuter(other.fOuter), 
143     fFMD1(other.fFMD1), 
144     fFMD2(other.fFMD2), 
145     fFMD3(other.fFMD3), 
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)
157 {
158   // PROTECTED
159   // Copy constructor
160 }
161
162
163
164 //____________________________________________________________________
165 AliFMDGeometry&
166 AliFMDGeometry::operator=(const AliFMDGeometry& other) 
167 {
168   // PROTECTED
169   // Assignment operator 
170   fUseFMD1              = other.fUseFMD1; 
171   fUseFMD2              = other.fUseFMD2; 
172   fUseFMD3              = other.fUseFMD3; 
173   fFMD1                 = other.fFMD1; 
174   fFMD2                 = other.fFMD2; 
175   fFMD3                 = other.fFMD3; 
176   fInner                = other.fInner; 
177   fOuter                = other.fOuter; 
178   fIsInitialized        = other.fIsInitialized;
179   return *this;
180 }
181
182 //____________________________________________________________________
183 void
184 AliFMDGeometry::Init()
185 {
186   // Initialize the the singleton if not done so already 
187   if (fIsInitialized) return;
188   fInner->Init();
189   fOuter->Init();
190   fFMD1->Init();
191   fFMD2->Init();
192   fFMD3->Init();
193 }
194
195 //____________________________________________________________________
196 void
197 AliFMDGeometry::InitTransformations()
198 {
199   // Find all local <-> global transforms 
200   if (!gGeoManager) {
201     AliError("No TGeoManager defined");
202     return;
203   }
204   AliDebug(0, "Initialising transforms for FMD geometry");
205   if (fFMD1) fFMD1->InitTransformations();
206   if (fFMD2) fFMD2->InitTransformations();
207   if (fFMD3) fFMD3->InitTransformations();
208 }
209
210 //____________________________________________________________________
211 void
212 AliFMDGeometry::Build()
213 {
214   // Build the geometry 
215   if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
216   fBuilder->SetDetailed(fDetailed);
217   fBuilder->UseAssembly(fUseAssembly);
218   fBuilder->Exec();
219 }
220
221 //____________________________________________________________________
222 void
223 AliFMDGeometry::SetActive(Int_t* active, Int_t n) 
224 {
225   // Set active volumes 
226   fActive.Set(n);
227   for (Int_t i = 0; i < n; i++) { 
228     AliDebug(1, Form("Active vol id # %d: %d", i, active[i]));
229     fActive[i] = active[i];
230   }
231 }
232
233 //____________________________________________________________________
234 void
235 AliFMDGeometry::AddActive(Int_t active)
236 {
237   // Add an active volume 
238   Int_t n = fActive.fN;
239   fActive.Set(n+1);
240   fActive[n] = active;
241 }
242
243 //____________________________________________________________________
244 Bool_t
245 AliFMDGeometry::IsActive(Int_t vol) const
246 {
247   // Check if a volume is active 
248   for (Int_t i = 0; i < fActive.fN; i++) 
249     if (fActive[i] == vol) return kTRUE;
250   return kFALSE;
251 }
252   
253 //____________________________________________________________________
254 AliFMDDetector*
255 AliFMDGeometry::GetDetector(Int_t i) const
256 {
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. 
259   switch (i) {
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;
263   }
264   return 0;
265 }
266
267 //____________________________________________________________________
268 AliFMDRing*
269 AliFMDGeometry::GetRing(Char_t i) const
270 {
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
273   // returned. 
274   switch (i) {
275   case 'I':
276   case 'i': return fInner;
277   case 'O':
278   case 'o': return fOuter;
279   }
280   return 0;
281 }
282
283 //____________________________________________________________________
284 void
285 AliFMDGeometry::Enable(Int_t i)
286 {
287   // Enable the ith detector.  i should be one of 1, 2, or 3
288   switch (i) {
289   case 1: fUseFMD1 = kTRUE; break;
290   case 2: fUseFMD2 = kTRUE; break;
291   case 3: fUseFMD3 = kTRUE; break;
292   }
293 }
294
295 //____________________________________________________________________
296 void
297 AliFMDGeometry::Disable(Int_t i)
298 {
299   // Disable the ith detector.  i should be one of 1, 2, or 3
300   switch (i) {
301   case 1: fUseFMD1 = kFALSE; break;
302   case 2: fUseFMD2 = kFALSE; break;
303   case 3: fUseFMD3 = kFALSE; break;
304   }
305 }
306
307 //____________________________________________________________________
308 void
309 AliFMDGeometry::Detector2XYZ(UShort_t  detector, 
310                              Char_t    ring, 
311                              UShort_t  sector, 
312                              UShort_t  strip, 
313                              Double_t& x, 
314                              Double_t& y, 
315                              Double_t& z) const
316 {
317   // Translate detector coordinates (detector, ring, sector, strip) to
318   // spatial coordinates (x, y, z) in the master reference frame of
319   // ALICE. 
320   AliFMDDetector* det = GetDetector(detector);
321   if (!det) { 
322     AliWarning(Form("Unknown detector %d", detector));
323     return;
324   }
325   det->Detector2XYZ(ring, sector, strip, x, y, z);
326 }
327
328 //____________________________________________________________________
329 Bool_t
330 AliFMDGeometry::XYZ2Detector(Double_t  x, 
331                              Double_t  y, 
332                              Double_t  z,
333                              UShort_t& detector, 
334                              Char_t&   ring, 
335                              UShort_t& sector, 
336                              UShort_t& strip) const
337 {
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;
345   detector = 0;
346   for (int i = 1; i <= 3; i++) {
347     det = GetDetector(i);
348     if (!det) continue;
349     if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
350       detector = det->GetId();
351       return kTRUE;
352     }
353   }
354   return kFALSE;
355 }
356
357
358 //____________________________________________________________________
359 void
360 AliFMDGeometry::GetGlobal(const AliRecPoint* p, 
361                           TVector3& pos, 
362                           TMatrixF& /* mat */) const 
363 {
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. 
367   GetGlobal(p, pos);
368 }
369
370 //____________________________________________________________________
371 void
372 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const 
373 {
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. 
381   Double_t x, y, z;
382   TVector3 local;
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);
388   pos.SetXYZ(x, y, z);
389 }
390
391 //____________________________________________________________________
392 Bool_t
393 AliFMDGeometry::Impact(const TParticle* /* particle */) const 
394
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
398   // always.  
399   // FIXME: Implement this function. 
400   return kFALSE; 
401 }
402
403 //____________________________________________________________________  
404 void  
405 AliFMDGeometry::ExtractGeomInfo()
406 {
407   // Check the volume depth of some nodes, get the active volume
408   // numbers, and so forth. 
409   // 
410   // TODO: Here, we should actually also get the parameters of the
411   // shapes, like the verticies of the polygon shape that makes up the
412   // silicon sensor, the strip pitch, the ring radii, the z-positions,
413   // and so on - that is, all the geometric information we need for
414   // futher processing, such as simulation, digitization,
415   // reconstruction, etc. 
416   Int_t detectorDepth = FindNodeDepth("FMD1_1", "ALIC");
417   Int_t ringDepth     = FindNodeDepth(Form("FMDI_%d", Int_t('I')), "ALIC");
418   Int_t moduleDepth   = FindNodeDepth("FIFV_0", "ALIC");
419   Int_t sectorDepth   = FindNodeDepth("FISE_1", "ALIC");
420   fActive.Reset(-1);
421   AliDebug(1, Form("Geometry depths:\n"
422                    "   Sector:     %d\n"
423                    "   Module:     %d\n"
424                    "   Ring:       %d\n"
425                    "   Detector:   %d", 
426                    sectorDepth, moduleDepth, ringDepth, detectorDepth));
427   if (sectorDepth < 0 && moduleDepth < 0) {
428     fDetailed    = kFALSE;
429     fSectorOff   = -1;
430     fModuleOff   = -1;
431     fRingOff     = 0;
432     fDetectorOff = (ringDepth - detectorDepth);
433     TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
434     TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
435     if (actiVol) AddActive(actiVol->GetNumber());
436     if (actiVol) AddActive(actoVol->GetNumber());
437   }
438   else if (sectorDepth < 0) {
439     fDetailed    = kFALSE;
440     fSectorOff   = -1;
441     fModuleOff   = 1;
442     fRingOff     = (moduleDepth - ringDepth) + 1;
443     fDetectorOff = (moduleDepth - detectorDepth) + 1;
444     TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
445     TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
446     if (modiVol) AddActive(modiVol->GetNumber());
447     if (modoVol) AddActive(modoVol->GetNumber());
448   }
449   else {
450     Int_t stripDepth    = FindNodeDepth("FIST_1", "ALIC");
451     fDetailed    = kTRUE;
452     fSectorOff   = (stripDepth - sectorDepth);
453     fModuleOff   = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
454     fRingOff     = (stripDepth - ringDepth);
455     fDetectorOff = (stripDepth - detectorDepth );
456     TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
457     TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
458     if (striVol) AddActive(striVol->GetNumber());
459     if (stroVol) AddActive(stroVol->GetNumber());
460   }    
461   AliDebug(1, Form("Geometry offsets:\n"
462                    "   Sector:     %d\n"
463                    "   Module:     %d\n"
464                    "   Ring:       %d\n"
465                    "   Detector:   %d", 
466                    fSectorOff, fModuleOff, fRingOff, fDetectorOff));
467 }
468
469   
470 //____________________________________________________________________  
471 static Int_t 
472 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
473 {
474   // If there's no node here. 
475   if (!node) return -1;
476   // Check if it this one 
477   TString sname(name);
478   if (sname == node->GetName()) return lvl;
479
480   // Check if the node is an immediate daugther 
481   TObjArray* nodes = node->GetNodes();
482   if (!nodes) return -1;
483   // Increase the level, and search immediate sub nodes. 
484   lvl++;
485   TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
486   if (found) return lvl;
487
488   // Check the sub node, if any of their sub-nodes match.
489   for (Int_t i = 0; i < nodes->GetEntries(); i++) {
490     TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
491     if (!sub) continue;
492     // Recurive check 
493     if (CheckNodes(sub, name, lvl) >= 0) return lvl;
494   }
495   // If not found, decrease the level 
496   lvl--;
497   return -1;
498 }
499 //____________________________________________________________________  
500 Int_t 
501 FindNodeDepth(const char* name, const char* volname) 
502 {
503   // Find the depth of a node 
504   TGeoVolume* vol  = gGeoManager->GetVolume(volname);
505   if (!vol) {
506     std::cerr << "No top volume defined" << std::endl;
507     return -1;
508   }
509   TObjArray* nodes = vol->GetNodes();
510   if (!nodes) { 
511     std::cerr << "No nodes in top volume" << std::endl;
512     return -1;
513   }
514   TIter next(nodes);
515   TGeoNode* node = 0;
516   Int_t lvl = 0;
517   while ((node = static_cast<TGeoNode*>(next()))) 
518     if (CheckNodes(node, name, lvl) >= 0) return lvl;
519   return -1;
520 }
521
522 //____________________________________________________________________
523 //
524 // EOF
525 //