Fixed coding convention issues as given by the automatic
[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 /** 
17  * @file    AliFMDGeometry.cxx
18  * @author  Christian Holm Christensen <cholm@nbi.dk>
19  * @date    Mon Mar 27 12:40:37 2006
20  * @brief   Geometry mananger for the FMD
21  */
22 //____________________________________________________________________
23 //                                                                          
24 // Forward Multiplicity Detector based on Silicon wafers. 
25 //
26 // This class is a singleton that handles the geometry parameters of
27 // the FMD detectors.  
28 //                                                       
29 // The actual code is done by various separate classes.   Below is
30 // diagram showing the relationship between the various FMD classes
31 // that handles the geometry 
32 //
33 //                               +------------+ 
34 //                            +- | AliFMDRing |
35 //                         2  |  +------------+
36 //      +----------------+<>--+        |                                
37 //      | AliFMDGeometry |             ^                        
38 //      +----------------+<>--+        V 1..2                           
39 //                         3  | +----------------+              
40 //                            +-| AliFMDDetector |              
41 //                              +----------------+              
42 //                                     ^
43 //                                     |
44 //                       +-------------+-------------+
45 //                       |             |             |        
46 //                  +---------+   +---------+   +---------+
47 //                  | AliFMD1 |   | AliFMD2 |   | AliFMD3 |
48 //                  +---------+   +---------+   +---------+
49 //      
50 //
51 // *  AliFMDRing 
52 //    This class contains all stuff needed to do with a ring.  It's
53 //    used by the AliFMDDetector objects to instantise inner and
54 //    outer rings.  The AliFMDRing objects are shared by the
55 //    AliFMDDetector objects, and owned by the AliFMDv1 object. 
56 //
57 // *  AliFMD1, AliFMD2, and AliFMD3 
58 //    These are specialisation of AliFMDDetector, that contains the
59 //    particularities of each of the sub-detector system.  It is
60 //    envisioned that the classes should also define the support
61 //    volumes and material for each of the detectors.                          
62 //                                                                          
63 //
64 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
65 #include "AliFMDRing.h"         // ALIFMDRING_H
66 #include "AliFMD1.h"            // ALIFMD1_H
67 #include "AliFMD2.h"            // ALIFMD2_H
68 #include "AliFMD3.h"            // ALIFMD2_H
69 #include "AliRecPoint.h"        // ALIRECPOINT_H
70 #include "AliFMDDebug.h"                   // ALILOG_H
71 #include <TVector3.h>           // ROOT_TVector3
72 // #include <TMatrix.h>            // ROOT_TMatrix
73 // #include <TParticle.h>          // ROOT_TParticle
74 #include <Riostream.h>
75 #include "AliFMDGeometryBuilder.h"
76 // #include <TArrayI.h>
77 #include <TGeoManager.h>
78 #include <TGeoVolume.h>
79 #include <TGeoNode.h>
80 #include <TMath.h>
81 static Int_t FindNodeDepth(const char* name, const char* volname);
82
83
84 //====================================================================
85 ClassImp(AliFMDGeometry)
86 #if 0
87   ; // This is here to keep Emacs for indenting the next line
88 #endif
89
90 //____________________________________________________________________
91 AliFMDGeometry* AliFMDGeometry::fgInstance = 0;
92
93 //____________________________________________________________________
94 AliFMDGeometry* 
95 AliFMDGeometry::Instance() 
96 {
97   // 
98   // singleton access 
99   //
100   // Return:
101   //    Singleton 
102   //
103   if (!fgInstance) fgInstance = new AliFMDGeometry("FMD");
104   return fgInstance;
105 }
106
107 //____________________________________________________________________
108 AliFMDGeometry::AliFMDGeometry() 
109   : AliGeometry(),
110     fIsInitialized(kFALSE), 
111     fInner(0),
112     fOuter(0),
113     fFMD1(0),
114     fFMD2(0),
115     fFMD3(0),
116     fUseFMD1(kTRUE),
117     fUseFMD2(kTRUE),
118     fUseFMD3(kTRUE),
119     fIsInitTrans(kFALSE),
120     fBuilder(0),
121     fDetectorOff(0),
122     fModuleOff(0),  
123     fRingOff(0),
124     fSectorOff(0),
125     fActive(2),
126     fDetailed(kTRUE),       
127     fUseAssembly(kTRUE)
128 {
129   // PROTECTED
130   // 
131   // CTOR 
132   //
133 }
134
135 //____________________________________________________________________
136 AliFMDGeometry::AliFMDGeometry(const char* ) 
137   : AliGeometry("FMD", "Forward multiplicity"), 
138     fIsInitialized(kFALSE), 
139     fInner(0),
140     fOuter(0),
141     fFMD1(0),
142     fFMD2(0),
143     fFMD3(0),
144     fUseFMD1(kTRUE),
145     fUseFMD2(kTRUE),
146     fUseFMD3(kTRUE),
147     fIsInitTrans(kFALSE),
148     fBuilder(0),
149     fDetectorOff(0),
150     fModuleOff(0),  
151     fRingOff(0),
152     fSectorOff(0),
153     fActive(2),
154     fDetailed(kTRUE),       
155     fUseAssembly(kTRUE)
156 {
157   // PROTECTED
158   // 
159   // CTOR 
160   // 
161   // Parameters:
162   //    name Not used
163   //
164 }
165
166 //____________________________________________________________________
167 AliFMDGeometry::AliFMDGeometry(const AliFMDGeometry& other) 
168   : AliGeometry(other),
169     fIsInitialized(other.fIsInitialized),
170     fInner(other.fInner), 
171     fOuter(other.fOuter), 
172     fFMD1(other.fFMD1), 
173     fFMD2(other.fFMD2), 
174     fFMD3(other.fFMD3), 
175     fUseFMD1(other.fUseFMD1), 
176     fUseFMD2(other.fUseFMD2), 
177     fUseFMD3(other.fUseFMD3), 
178     fIsInitTrans(other.fIsInitTrans),
179     fBuilder(other.fBuilder),
180     fDetectorOff(other.fDetectorOff),
181     fModuleOff(other.fModuleOff),  
182     fRingOff(other.fRingOff),
183     fSectorOff(other.fSectorOff),
184     fActive(other.fActive),
185     fDetailed(other.fDetailed),
186     fUseAssembly(other.fUseAssembly)
187 {
188   // PROTECTED
189   // 
190   // Copy CTOR
191   // 
192   // Parameters:
193   //    other To copy from  
194   //
195 }
196
197
198
199 //____________________________________________________________________
200 AliFMDGeometry&
201 AliFMDGeometry::operator=(const AliFMDGeometry& other) 
202 {
203   // PROTECTED
204   // 
205   // Assignment operator 
206   // 
207   // Parameters:
208   //    other To assig from
209   // Return:
210   //    reference to this.  
211   //
212   fUseFMD1              = other.fUseFMD1; 
213   fUseFMD2              = other.fUseFMD2; 
214   fUseFMD3              = other.fUseFMD3; 
215   fFMD1                 = other.fFMD1; 
216   fFMD2                 = other.fFMD2; 
217   fFMD3                 = other.fFMD3; 
218   fInner                = other.fInner; 
219   fOuter                = other.fOuter; 
220   fIsInitialized        = other.fIsInitialized;
221   return *this;
222 }
223
224 //____________________________________________________________________
225 void
226 AliFMDGeometry::Init()
227 {
228   // 
229   // Initialize the the singleton if not done so already 
230   //
231   if (fIsInitialized) return;
232   fInner->Init();
233   fOuter->Init();
234   fFMD1->Init();
235   fFMD2->Init();
236   fFMD3->Init();
237 }
238
239 //____________________________________________________________________
240 void
241 AliFMDGeometry::InitTransformations(Bool_t force)
242 {
243   // 
244   // Find all local <-> global transforms 
245   //
246   if (force) fIsInitTrans = kFALSE;
247   if (fIsInitTrans) return; 
248   if (!gGeoManager) {
249     AliError("No TGeoManager defined");
250     return;
251   }
252   AliFMDDebug(1, ("Initialising transforms for FMD geometry"));
253   if (fFMD1) fFMD1->InitTransformations();
254   if (fFMD2) fFMD2->InitTransformations();
255   if (fFMD3) fFMD3->InitTransformations();
256   fIsInitTrans = kTRUE;
257 }
258
259 //____________________________________________________________________
260 void
261 AliFMDGeometry::Build()
262 {
263   // 
264   // Make the geometry.  This delegates to AliFMDGeometryBuilder 
265   //
266   if (!fBuilder) fBuilder = new AliFMDGeometryBuilder(fDetailed);
267   fBuilder->SetDetailed(fDetailed);
268   fBuilder->UseAssembly(fUseAssembly);
269   fBuilder->Exec();
270 }
271
272 //____________________________________________________________________
273 void
274 AliFMDGeometry::SetActive(Int_t* active, Int_t n) 
275 {
276   // 
277   // Set active volumes 
278   // 
279   // Parameters:
280   //    active Active volume id array 
281   //    n elements of @a active 
282   //
283   fActive.Set(n);
284   for (Int_t i = 0; i < n; i++) { 
285     AliFMDDebug(1, ("Active vol id # %d: %d", i, active[i]));
286     fActive[i] = active[i];
287   }
288 }
289
290 //____________________________________________________________________
291 void
292 AliFMDGeometry::AddActive(Int_t active)
293 {
294   //
295   // Add an active volume 
296   // 
297   // Parameters:
298   //    id Register volume @a id to be active 
299   //
300   // 
301   Int_t n = fActive.fN;
302   fActive.Set(n+1);
303   fActive[n] = active;
304 }
305
306 //____________________________________________________________________
307 Bool_t
308 AliFMDGeometry::IsActive(Int_t vol) const
309 {
310   // 
311   // Check if volume @a vol is marked as active 
312   // 
313   // Parameters:
314   //    vol Volume ID
315   // Return:
316   //     @c true if @a vol is declared active 
317   //
318   for (Int_t i = 0; i < fActive.fN; i++) 
319     if (fActive[i] == vol) return kTRUE;
320   return kFALSE;
321 }
322   
323 //____________________________________________________________________
324 AliFMDDetector*
325 AliFMDGeometry::GetDetector(Int_t i) const
326 {
327   // 
328   // Get description of a sub-detector
329   // 
330   // Parameters:
331   //    i Sub-detector #
332   // Return:
333   //    Description of sub-detector, or 0 
334   //
335   switch (i) {
336   case 1: return fUseFMD1 ? static_cast<AliFMDDetector*>(fFMD1) : 0;
337   case 2: return fUseFMD2 ? static_cast<AliFMDDetector*>(fFMD2) : 0;
338   case 3: return fUseFMD3 ? static_cast<AliFMDDetector*>(fFMD3) : 0;
339   }
340   return 0;
341 }
342
343 //____________________________________________________________________
344 AliFMDRing*
345 AliFMDGeometry::GetRing(Char_t i) const
346 {
347   // 
348   // Get description of a ring, i should be one of 'I' or 'O' (case
349   // insensitive).  If an invalid parameter is passed, 0 (NULL) is
350   // returned.
351   // 
352   // Parameters:
353   //    i Ring id
354   // Return:
355   //    Description of ring, or 0 
356   //
357   switch (i) {
358   case 'I':
359   case 'i': return fInner;
360   case 'O':
361   case 'o': return fOuter;
362   }
363   return 0;
364 }
365
366 //____________________________________________________________________
367 void
368 AliFMDGeometry::Enable(Int_t i)
369 {
370   // 
371   // Enable the ith detector
372   // 
373   // Parameters:
374   //    i IF true, enable sub-detector @a i 
375   //
376   switch (i) {
377   case 1: fUseFMD1 = kTRUE; break;
378   case 2: fUseFMD2 = kTRUE; break;
379   case 3: fUseFMD3 = kTRUE; break;
380   }
381 }
382
383 //____________________________________________________________________
384 void
385 AliFMDGeometry::Disable(Int_t i)
386 {
387   // 
388   // Disable the ith detector
389   // 
390   // Parameters:
391   //    i IF true, disable sub-detector @a i 
392   //
393   switch (i) {
394   case 1: fUseFMD1 = kFALSE; break;
395   case 2: fUseFMD2 = kFALSE; break;
396   case 3: fUseFMD3 = kFALSE; break;
397   }
398 }
399
400 //____________________________________________________________________
401 void
402 AliFMDGeometry::Detector2XYZ(UShort_t  detector, 
403                              Char_t    ring, 
404                              UShort_t  sector, 
405                              UShort_t  strip, 
406                              Double_t& x, 
407                              Double_t& y, 
408                              Double_t& z) const
409 {
410   // 
411   // Translate detector coordinates (detector, ring, sector, strip)
412   // to spatial coordinates (x, y, z) in the master reference frame
413   // of ALICE.  The member function uses the transformations
414   // previously obtained from the TGeoManager.
415   // 
416   // Parameters:
417   //    detector Detector number
418   //    ring     Ring id
419   //    sector   Sector number
420   //    strip    Strip number
421   //    x        On return, X coordinate 
422   //    y        On return, Y coordinate 
423   //    z        On return, Z coordinate  
424   //
425   AliFMDDetector* det = GetDetector(detector);
426   if (!det) { 
427     AliWarning(Form("Unknown detector %d", detector));
428     return;
429   }
430   det->Detector2XYZ(ring, sector, strip, x, y, z);
431 }
432
433 //____________________________________________________________________
434 Bool_t
435 AliFMDGeometry::XYZ2Detector(Double_t  x, 
436                              Double_t  y, 
437                              Double_t  z,
438                              UShort_t& detector, 
439                              Char_t&   ring, 
440                              UShort_t& sector, 
441                              UShort_t& strip) const
442 {
443   // 
444   // Translate spatial coordinates (x,y,z) in the master reference
445   // frame of ALICE to the detector coordinates (detector, ring,
446   // sector, strip).  Note, that if this method is to be used in
447   // reconstruction or the like, then the input z-coordinate should
448   //  be corrected for the events interactions points z-coordinate,
449   // like  
450   // @code 
451   // geom->XYZ2Detector(x,y,z-ipz,d,r,s,t);
452   // @endcode
453   // 
454   // Parameters:
455   //    x        X coordinate
456   //    y             Y coordinate
457   //    z             Z coordinate
458   //    detector On return, Detector number
459   //    ring     On return, Ring id                
460   //    sector   On return, Sector number          
461   //    strip    On return, Strip number           
462   // Return:
463   //    @c  false of (@a x, @a y, @a z) is not within this
464   // detector.  
465   //
466   AliFMDDetector* det = 0;
467   detector = 0;
468   for (int i = 1; i <= 3; i++) {
469     det = GetDetector(i);
470     if (!det) continue;
471     if (det->XYZ2Detector(x, y, z, ring, sector, strip)) {
472       detector = det->GetId();
473       return kTRUE;
474     }
475   }
476   return kFALSE;
477 }
478
479 //____________________________________________________________________
480 Bool_t
481 AliFMDGeometry::XYZ2REtaPhiTheta(Double_t  x,   Double_t y, 
482                                  Double_t  z, 
483                                  Double_t& r,   Double_t& eta, 
484                                  Double_t& phi, Double_t& theta)
485 {
486   
487   // 
488   // Service function to convert Cartisean XYZ to r, eta, phi, and theta.   
489   //
490   // Note, that the z input should be corrected for the vertex location 
491   // if needed.
492   // 
493   // Parameters:
494   //    x      Cartisean X coordinate
495   //    y      Cartisean Y coordinate 
496   //    z      Cartisean Z coordinate 
497   //    r      On return, the radius
498   //    eta    On return, the pseudo-rapidity
499   //    phi    On return, the azimuthal angle
500   //    theta  On return, the polar angle;
501   //
502   // Return:
503   //    kTRUE on success, kFALSE in case of problems
504   //     
505   if (x == 0 && y == 0 && z == 0) return kFALSE;
506   
507   // Correct for vertex offset. 
508   phi   =  TMath::ATan2(y, x);
509   r     =  TMath::Sqrt(y * y + x * x);
510   theta =  TMath::ATan2(r, z);
511   eta   = -TMath::Log(TMath::Tan(theta / 2));
512
513   return kTRUE;
514 }
515
516
517 //____________________________________________________________________
518 void
519 AliFMDGeometry::GetGlobal(const AliRecPoint* p, 
520                           TVector3& pos, 
521                           TMatrixF& /* mat */) const 
522 {
523   // 
524   // Get global coordinates cooresponding to a rec point. 
525   // 
526   // Parameters:
527   //    p   Reconstructed point.
528   //    pos On return, the position
529   //    mat On return, the material at @a post 
530   //
531   GetGlobal(p, pos);
532 }
533
534 //____________________________________________________________________
535 void
536 AliFMDGeometry::GetGlobal(const AliRecPoint* p, TVector3& pos) const 
537 {
538   // 
539   // Get global coordinates cooresponding to a rec point. 
540   // 
541   // Parameters:
542   //    p   Reconstructed point.
543   //    pos On return, the position 
544   //
545   // FIXME: Implement this function to work with outer rings too. 
546   Double_t x, y, z;
547   TVector3 local;
548   p->GetLocalPosition(local);
549   UShort_t detector = UShort_t(local.X());
550   UShort_t sector   = UShort_t(local.Y());
551   UShort_t strip    = UShort_t(local.Z());
552   Detector2XYZ(detector, 'I', sector, strip, x, y, z);
553   pos.SetXYZ(x, y, z);
554 }
555
556 //____________________________________________________________________
557 Bool_t
558 AliFMDGeometry::Impact(const TParticle* /* particle */) const 
559
560   // 
561   // Check if particle will hit an active detector element.  
562   // 
563   // @todo implement this function 
564   // 
565   // Parameters:
566   //    particle Track 
567   // Return:
568   //    @c true if @a particle will hit this detector 
569   //
570   return kFALSE; 
571 }
572
573 //____________________________________________________________________  
574 void  
575 AliFMDGeometry::SetAlignableVolumes() const
576 {
577   // 
578   // Declare alignable volumes 
579   //
580   for (Int_t d = 1; d <= 3; d++) 
581     if (GetDetector(d)) GetDetector(d)->SetAlignableVolumes();
582 }
583
584
585 //____________________________________________________________________  
586 void  
587 AliFMDGeometry::ExtractGeomInfo()
588 {
589   // Check the volume depth of some nodes, get the active volume
590   // numbers, and so forth. 
591   // 
592   // TODO: Here, we should actually also get the parameters of the
593   // shapes, like the verticies of the polygon shape that makes up the
594   // silicon sensor, the strip pitch, the ring radii, the z-positions,
595   // and so on - that is, all the geometric information we need for
596   // futher processing, such as simulation, digitization,
597   // reconstruction, etc. 
598   Int_t detectorDepth = FindNodeDepth("F1MT_1", "ALIC");
599   Int_t ringDepth     = FindNodeDepth(Form("FITV_%d", int('I')), "ALIC");
600   Int_t moduleDepth   = FindNodeDepth("FIBH_0", "ALIC");
601   Int_t sectorDepth   = FindNodeDepth("FISC_1", "ALIC");
602   fActive.Set(0);
603   fActive.Reset(-1);
604   AliFMDDebug(1, ("Geometry depths:\n"
605                    "   Sector:     %d\n"
606                    "   Module:     %d\n"
607                    "   Ring:       %d\n"
608                    "   Detector:   %d", 
609                    sectorDepth, moduleDepth, ringDepth, detectorDepth));
610   if (sectorDepth < 0 && moduleDepth < 0) {
611     fDetailed    = kFALSE;
612     fSectorOff   = -1;
613     fModuleOff   = -1;
614     fRingOff     = 0;
615     fDetectorOff = (ringDepth - detectorDepth);
616     TGeoVolume* actiVol = gGeoManager->GetVolume("FIAC");
617     TGeoVolume* actoVol = gGeoManager->GetVolume("FOAC");
618     if (actiVol) AddActive(actiVol->GetNumber());
619     if (actiVol) AddActive(actoVol->GetNumber());
620   }
621   else if (sectorDepth < 0) {
622     fDetailed    = kFALSE;
623     fSectorOff   = -1;
624     fModuleOff   = 1;
625     fRingOff     = (moduleDepth - ringDepth) + 1;
626     fDetectorOff = (moduleDepth - detectorDepth) + 1;
627     TGeoVolume* modiVol = gGeoManager->GetVolume("FIMO");
628     TGeoVolume* modoVol = gGeoManager->GetVolume("FOMO");
629     if (modiVol) AddActive(modiVol->GetNumber());
630     if (modoVol) AddActive(modoVol->GetNumber());
631   }
632   else {
633     Int_t stripDepth    = FindNodeDepth("FIST_1", "ALIC");
634     fDetailed    = kTRUE;
635     fSectorOff   = (stripDepth - sectorDepth);
636     fModuleOff   = (moduleDepth >= 0 ? (stripDepth - moduleDepth) : -1);
637     fRingOff     = (stripDepth - ringDepth);
638     fDetectorOff = (stripDepth - detectorDepth );
639     TGeoVolume* striVol = gGeoManager->GetVolume("FIST");
640     TGeoVolume* stroVol = gGeoManager->GetVolume("FOST");
641     if (striVol) AddActive(striVol->GetNumber());
642     if (stroVol) AddActive(stroVol->GetNumber());
643   }    
644   AliFMDDebug(1, ("Geometry offsets:\n"
645                    "   Sector:     %d\n"
646                    "   Module:     %d\n"
647                    "   Ring:       %d\n"
648                    "   Detector:   %d", 
649                    fSectorOff, fModuleOff, fRingOff, fDetectorOff));
650 }
651
652   
653 //____________________________________________________________________  
654 static Int_t 
655 CheckNodes(TGeoNode* node, const char* name, Int_t& lvl)
656 {
657   // If there's no node here. 
658   if (!node) return -1;
659   // Check if it this one 
660   TString sname(name);
661   if (sname == node->GetName()) return lvl;
662
663   // Check if the node is an immediate daugther 
664   TObjArray* nodes = node->GetNodes();
665   if (!nodes) return -1;
666   // Increase the level, and search immediate sub nodes. 
667   lvl++;
668   TGeoNode*  found = static_cast<TGeoNode*>(nodes->FindObject(name));
669   if (found) return lvl;
670
671   // Check the sub node, if any of their sub-nodes match.
672   for (Int_t i = 0; i < nodes->GetEntries(); i++) {
673     TGeoNode* sub = static_cast<TGeoNode*>(nodes->At(i));
674     if (!sub) continue;
675     // Recurive check 
676     if (CheckNodes(sub, name, lvl) >= 0) return lvl;
677   }
678   // If not found, decrease the level 
679   lvl--;
680   return -1;
681 }
682 //____________________________________________________________________  
683 Int_t 
684 FindNodeDepth(const char* name, const char* volname) 
685 {
686   // Find the depth of a node 
687   TGeoVolume* vol  = gGeoManager->GetVolume(volname);
688   if (!vol) {
689     std::cerr << "No top volume defined" << std::endl;
690     return -1;
691   }
692
693   TGeoIterator next(vol);
694   TGeoNode*    node = 0;
695   TString      sName(name);
696   while ((node = next())) { 
697     if (sName == node->GetName()) { 
698       //std::cout << "Found node " << node->GetName() << " at level " 
699       //                << next.GetLevel() << std::endl;
700       return next.GetLevel();
701     }
702   }
703   return -1;
704 #if 0
705   TObjArray* nodes = vol->GetNodes();
706   if (!nodes) { 
707     std::cerr << "No nodes in top volume" << std::endl;
708     return -1;
709   }
710   TIter next(nodes);
711   TGeoNode* node = 0;
712   Int_t lvl = 0;
713   while ((node = static_cast<TGeoNode*>(next()))) 
714     if (CheckNodes(node, name, lvl) >= 0) return lvl;
715   return -1;
716 #endif
717 }
718
719 //____________________________________________________________________
720 //
721 // EOF
722 //