]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometry.cxx
New detector numbering scheme (common for DAQ/HLT/Offline). All the subdetectors...
[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   // Find all local <-> global transforms 
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
189 //____________________________________________________________________
190 void
191 AliFMDGeometry::Build()
192 {
193   // Build the geometry 
194   if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
195   fBuilder->SetDetailed(fDetailed);
196   fBuilder->UseAssembly(fUseAssembly);
197   fBuilder->Exec();
198 }
199
200 //____________________________________________________________________
201 void
202 AliFMDGeometry::SetActive(Int_t* active, Int_t n) 
203 {
204   // Set active volumes 
205   fActive.Set(n);
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   }
210 }
211
212 //____________________________________________________________________
213 void
214 AliFMDGeometry::AddActive(Int_t active)
215 {
216   // Add an active volume 
217   Int_t n = fActive.fN;
218   fActive.Set(n+1);
219   fActive[n] = active;
220 }
221
222 //____________________________________________________________________
223 Bool_t
224 AliFMDGeometry::IsActive(Int_t vol) const
225 {
226   // Check if a volume is active 
227   for (Int_t i = 0; i < fActive.fN; i++) 
228     if (fActive[i] == vol) return kTRUE;
229   return kFALSE;
230 }
231   
232 //____________________________________________________________________
233 AliFMDDetector*
234 AliFMDGeometry::GetDetector(Int_t i) const
235 {
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. 
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 //____________________________________________________________________
247 AliFMDRing*
248 AliFMDGeometry::GetRing(Char_t i) const
249 {
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. 
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 //____________________________________________________________________
263 void
264 AliFMDGeometry::Enable(Int_t i)
265 {
266   // Enable the ith detector.  i should be one of 1, 2, or 3
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 //____________________________________________________________________
275 void
276 AliFMDGeometry::Disable(Int_t i)
277 {
278   // Disable the ith detector.  i should be one of 1, 2, or 3
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 //____________________________________________________________________
287 void
288 AliFMDGeometry::Detector2XYZ(UShort_t  detector, 
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
295 {
296   // Translate detector coordinates (detector, ring, sector, strip) to
297   // spatial coordinates (x, y, z) in the master reference frame of
298   // ALICE. 
299   AliFMDDetector* det = GetDetector(detector);
300   if (!det) { 
301     AliWarning(Form("Unknown detector %d", detector));
302     return;
303   }
304   det->Detector2XYZ(ring, sector, strip, x, y, z);
305 }
306
307 //____________________________________________________________________
308 Bool_t
309 AliFMDGeometry::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
336
337 //____________________________________________________________________
338 void
339 AliFMDGeometry::GetGlobal(const AliRecPoint* p, 
340                           TVector3& pos, 
341                           TMatrixF& /* mat */) const 
342 {
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. 
346   GetGlobal(p, pos);
347 }
348
349 //____________________________________________________________________
350 void
351 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const 
352 {
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. 
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 //____________________________________________________________________
371 Bool_t
372 AliFMDGeometry::Impact(const TParticle* /* particle */) const 
373
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. 
379   return kFALSE; 
380 }
381
382 //____________________________________________________________________  
383 void  
384 AliFMDGeometry::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 //____________________________________________________________________  
450 static Int_t 
451 CheckNodes(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 //____________________________________________________________________  
479 Int_t 
480 FindNodeDepth(const char* name, const char* volname) 
481 {
482   // Find the depth of a node 
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 }
500
501 //____________________________________________________________________
502 //
503 // EOF
504 //