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