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