Class description on 5 lines
[u/mrichter/AliRoot.git] / MUON / AliMUONGeometryBuilder.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *      SigmaEffect_thetadegrees                                                                  *
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 purpeateose. It is      *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 // $Id$
17 //
18 // ----------------------------
19 // Class AliMUONGeometryBuilder
20 // ----------------------------
21 // Manager class for geometry construction via geometry builders.
22 // Author: Ivana Hrivnacova, IPN Orsay
23
24 #include "AliMUONGeometryBuilder.h"
25 #include "AliMUONVGeometryBuilder.h"    
26 #include "AliMUONGeometry.h"
27 #include "AliMUONGeometryTransformer.h"
28 #include "AliMUONGeometryModule.h"      
29 #include "AliMUONGeometryModuleTransformer.h"   
30 #include "AliMUONGeometryEnvelope.h"    
31 #include "AliMUONGeometryEnvelopeStore.h"
32 #include "AliMUONGeometryDetElement.h"
33 #include "AliMUONGeometryStore.h"
34 #include "AliMUONGeometryConstituent.h"
35
36 #include "AliModule.h"
37 #include "AliLog.h"
38 #include "AliRun.h"
39
40 #include <TObjArray.h>
41 #include <TVirtualMC.h>
42 #include <TGeoManager.h>
43
44 // static data members
45  
46 const TString  AliMUONGeometryBuilder::fgkDefaultVolPathsFileName = "volpath.dat";   
47 const TString  AliMUONGeometryBuilder::fgkDefaultTransformFileName = "transform.dat";   
48 const TString  AliMUONGeometryBuilder::fgkDefaultSVMapFileName = "svmap.dat";    
49 const TString  AliMUONGeometryBuilder::fgkOutFileNameExtension = ".out";    
50
51 ClassImp(AliMUONGeometryBuilder)
52
53 // static functions
54
55 //______________________________________________________________________________
56 TGeoHMatrix AliMUONGeometryBuilder::Multiply(const TGeoMatrix& m1, 
57                                              const TGeoMatrix& m2)
58 {
59 /// Temporary fix for problem with matrix multiplication in Root 5.02/00
60
61   if (m1.IsIdentity() && m2.IsIdentity()) return TGeoHMatrix();
62   
63   if (m1.IsIdentity()) return m2;
64   
65   if (m2.IsIdentity()) return m1;
66   
67   return m1 * m2;
68 }
69
70 //______________________________________________________________________________
71 TGeoHMatrix AliMUONGeometryBuilder::Multiply(const TGeoMatrix& m1, 
72                                              const TGeoMatrix& m2,
73                                              const TGeoMatrix& m3)
74 {                                            
75 /// Temporary fix for problem with matrix multiplication in Root 5.02/00
76
77   if (m1.IsIdentity() && m2.IsIdentity() & m3.IsIdentity())  
78     return TGeoHMatrix();
79   
80   if (m1.IsIdentity()) return Multiply(m2, m3);
81   
82   if (m2.IsIdentity()) return Multiply(m1, m3);
83   
84   if (m3.IsIdentity()) return Multiply(m1, m2);
85   
86   return m1 * m2 * m3;
87 }
88
89 //______________________________________________________________________________
90 TGeoHMatrix AliMUONGeometryBuilder::Multiply(const TGeoMatrix& m1, 
91                                              const TGeoMatrix& m2,
92                                              const TGeoMatrix& m3,
93                                              const TGeoMatrix& m4)
94 {                                            
95 /// Temporary fix for problem with matrix multiplication in Root 5.02/00
96
97   if (m1.IsIdentity() && m2.IsIdentity() & m3.IsIdentity() & m4.IsIdentity())  
98     return TGeoHMatrix();
99   
100   if (m1.IsIdentity()) return Multiply(m2, m3, m4);
101   
102   if (m2.IsIdentity()) return Multiply(m1, m3, m4);
103   
104   if (m3.IsIdentity()) return Multiply(m1, m2, m4);
105   
106   if (m4.IsIdentity()) return Multiply(m1, m2, m3);
107   
108   return m1 * m2 * m3 * m4;
109 }
110
111 //______________________________________________________________________________
112 AliMUONGeometryBuilder::AliMUONGeometryBuilder(AliModule* module)
113   : TObject(),
114     fModule(module),
115     fAlign(false),
116     fTransformFileName(fgkDefaultTransformFileName),
117     fSVMapFileName(fgkDefaultSVMapFileName),
118     fGlobalTransformation(), 
119     fGeometryBuilders(0),
120     fGeometry(0)
121 {
122 /// Standard constructor
123
124   fGeometryBuilders = new TObjArray();
125   fGeometryBuilders->SetOwner(true);
126   
127   fGeometry = new AliMUONGeometry(true);
128
129   // Define the global transformation:
130   // Transformation from the old ALICE coordinate system to a new one:
131   // x->-x, z->-z 
132   TGeoRotation* rotGlobal 
133     = new TGeoRotation("rotGlobal", 90., 180., 90., 90., 180., 0.);
134   fGlobalTransformation = TGeoCombiTrans(0., 0., 0., rotGlobal);
135 }
136
137 //______________________________________________________________________________
138 AliMUONGeometryBuilder::AliMUONGeometryBuilder() 
139   : TObject(),
140     fModule(0),
141     fAlign(false),
142     fTransformFileName(),
143     fSVMapFileName(),
144     fGlobalTransformation(),
145     fGeometryBuilders(0),
146     fGeometry(0)
147 {
148 /// Default constructor
149
150
151 //______________________________________________________________________________
152 AliMUONGeometryBuilder::AliMUONGeometryBuilder(const AliMUONGeometryBuilder& right) 
153   : TObject(right) 
154 {  
155 /// Copy constructor (not implemented)
156
157   AliFatal("Copy constructor not provided.");
158 }
159
160 //______________________________________________________________________________
161 AliMUONGeometryBuilder::~AliMUONGeometryBuilder()
162 {
163 /// Destructor
164   
165   delete fGeometryBuilders;
166   delete fGeometry;
167 }
168
169 //______________________________________________________________________________
170 AliMUONGeometryBuilder& 
171 AliMUONGeometryBuilder::operator=(const AliMUONGeometryBuilder& right)
172 {
173 /// Assignement operator (not implemented)
174
175   // check assignement to self
176   if (this == &right) return *this;
177
178   AliFatal("Assignement operator not provided.");
179     
180   return *this;  
181 }    
182
183 //
184 // private functions
185 //
186
187 //______________________________________________________________________________
188 void AliMUONGeometryBuilder::PlaceVolume(const TString& name, const TString& mName, 
189                             Int_t copyNo, const TGeoHMatrix& matrix, 
190                             Int_t npar, Double_t* param, const char* only,
191                             Bool_t makeAssembly) const
192 {
193 /// Place the volume specified by name with the given transformation matrix
194
195   if (makeAssembly)
196     gGeoManager->MakeVolumeAssembly(name.Data());
197
198   TGeoHMatrix transform(matrix);
199   // Do not apply global transformation 
200   // if mother volume was already placed in 
201   // the new system of coordinates (that is MUON in negative Z)
202   // (as it is applied on the mother volume)
203   if (mName == TString("DDIP"))
204     transform = fGlobalTransformation.Inverse() * transform;
205      
206   // Decompose transformation
207   const Double_t* xyz = transform.GetTranslation();
208   const Double_t* rm = transform.GetRotationMatrix();
209         
210   //cout << "Got translation: "
211   //     << xyz[0] << " " << xyz[1] << " " << xyz[2] << endl;
212         
213   //cout << "Got rotation: "
214   //     << rm[0] << " " << rm[1] << " " << rm[2] << endl
215   //     << rm[3] << " " << rm[4] << " " << rm[5] << endl
216   //     << rm[6] << " " << rm[7] << " " << rm[8] << endl;
217
218   // Check for presence of rotation
219   // (will be nice to be available in TGeo)
220   const Double_t kTolerance = 1e-04;
221   Bool_t isRotation = true; 
222   if (TMath::Abs(rm[0] - 1.) < kTolerance &&
223       TMath::Abs(rm[1] - 0.) < kTolerance &&
224       TMath::Abs(rm[2] - 0.) < kTolerance &&
225       TMath::Abs(rm[3] - 0.) < kTolerance &&
226       TMath::Abs(rm[4] - 1.) < kTolerance &&
227       TMath::Abs(rm[5] - 0.) < kTolerance &&
228       TMath::Abs(rm[6] - 0.) < kTolerance &&
229       TMath::Abs(rm[7] - 0.) < kTolerance &&
230       TMath::Abs(rm[8] - 1.) < kTolerance) isRotation = false; 
231
232   Int_t krot = 0;
233   if (isRotation) {
234     TGeoRotation rot;
235     rot.SetMatrix(const_cast<Double_t*>(transform.GetRotationMatrix()));
236     Double_t theta1, phi1, theta2, phi2, theta3, phi3;
237     rot.GetAngles(theta1, phi1, theta2, phi2, theta3, phi3);
238         
239     //cout << "angles: " 
240     //     << theta1 << " " << phi1 << " "
241     //     << theta2 << " " << phi2 << " "
242     //     << theta3 << " " << phi3 << endl;
243         
244     fModule->AliMatrix(krot, theta1, phi1, theta2, phi2, theta3, phi3);
245   }     
246         
247   // Place the volume in ALIC
248   if (npar == 0)
249     gMC->Gspos(name, copyNo, mName, xyz[0], xyz[1], xyz[2] , krot, only);
250   else 
251     gMC->Gsposp(name, copyNo, mName, xyz[0], xyz[1], xyz[2] , krot, only,
252                 param, npar);
253
254
255 //______________________________________________________________________________
256 void AliMUONGeometryBuilder::CreateGeometryWithTGeo()
257 {
258 /// Construct geometry using geometry builders.
259 /// Virtual modules/envelopes are placed as TGeoVolume assembly
260
261   if (fAlign) {
262     // Read transformations from ASCII data file  
263     fGeometry->GetTransformer()
264       ->ReadGeometryData(fgkDefaultVolPathsFileName, fTransformFileName);
265   }    
266  
267   for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
268
269     // Get the builder
270     AliMUONVGeometryBuilder* builder
271       = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
272
273     // Create geometry + envelopes
274     //
275     builder->CreateGeometry();
276     if (!fAlign) builder->SetTransformations();
277     
278     // Place module volumes and envelopes
279     //
280     for (Int_t j=0; j<builder->NofGeometries(); j++) {
281
282       AliMUONGeometryModule* geometry = builder->Geometry(j);
283       AliMUONGeometryModuleTransformer* transformer= geometry->GetTransformer();
284       const TGeoHMatrix* kModuleTransform = transformer->GetTransformation();
285       TString volName       = transformer->GetVolumeName(); 
286       TString motherVolName = transformer->GetMotherVolumeName(); 
287       
288       // Place the module volume
289       PlaceVolume(volName, motherVolName, 
290                   1, *kModuleTransform, 0, 0, "ONLY", geometry->IsVirtual());
291   
292       TGeoCombiTrans appliedGlobalTransform;
293       if (builder->ApplyGlobalTransformation())
294         appliedGlobalTransform = fGlobalTransformation;
295
296       // Loop over envelopes
297       const TObjArray* kEnvelopes 
298         = geometry->GetEnvelopeStore()->GetEnvelopes();
299       for (Int_t k=0; k<kEnvelopes->GetEntriesFast(); k++) {
300
301         // Get envelope
302         AliMUONGeometryEnvelope* env 
303           = (AliMUONGeometryEnvelope*)kEnvelopes->At(k);
304           
305         const TGeoCombiTrans* kEnvTrans = env->GetTransformation();
306         const char* only = "ONLY";
307         if (env->IsMANY()) only = "MANY";
308
309         if (env->IsVirtual() && env->GetConstituents()->GetEntriesFast() == 0 ) {
310           // virtual envelope + nof constituents = 0 
311           //         => not allowed;
312           //            empty virtual envelope has no sense 
313           AliFatal("Virtual envelope must have constituents.");
314           return;
315         }
316
317         if (!env->IsVirtual() && env->GetConstituents()->GetEntriesFast() > 0 ) {
318           // non virtual envelope + nof constituents > 0 
319           //        => not allowed;
320           //           use VMC to place constituents
321           AliFatal("Non virtual envelope cannot have constituents.");
322           return;
323         }
324
325         // Place envelope in geometry module by composed transformation:
326         // [Tglobal] * Tenv
327         TGeoHMatrix total 
328           = Multiply( appliedGlobalTransform, 
329                      (*kEnvTrans) );
330         PlaceVolume(env->GetName(), volName,
331                     env->GetCopyNo(), total, 0, 0, only, env->IsVirtual());
332         
333         if ( env->IsVirtual() )  {
334           //  Place constituents in the envelope
335           for  (Int_t l=0; l<env->GetConstituents()->GetEntriesFast(); l++) {
336             AliMUONGeometryConstituent* constituent
337               = (AliMUONGeometryConstituent*)env->GetConstituents()->At(l);
338  
339             PlaceVolume(constituent->GetName(), env->GetName(),
340                         constituent->GetCopyNo(),
341                         *constituent->GetTransformation() ,
342                         constituent->GetNpar(), constituent->GetParam(), only);
343           }
344         }
345       } // end of loop over envelopes
346     } // end of loop over builder geometries
347   } // end of loop over builders
348 }
349
350 //______________________________________________________________________________
351 void AliMUONGeometryBuilder::CreateGeometryWithoutTGeo()
352 {
353 /// Construct geometry using geometry builders.
354 /// Virtual modules/enevlopes are not placed
355
356   if (fAlign) {
357     // Read transformations from ASCII data file  
358     fGeometry->GetTransformer()
359       ->ReadGeometryData(fgkDefaultVolPathsFileName, fTransformFileName);
360   }     
361
362   for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
363
364     // Get the builder
365     AliMUONVGeometryBuilder* builder
366       = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
367
368     // Create geometry + envelopes
369     //
370     builder->CreateGeometry();
371     if (!fAlign) builder->SetTransformations();
372     
373     // Place module volumes and envelopes
374     //
375     for (Int_t j=0; j<builder->NofGeometries(); j++) {
376
377       AliMUONGeometryModule* geometry = builder->Geometry(j);
378       AliMUONGeometryModuleTransformer* transformer= geometry->GetTransformer();
379       const TGeoHMatrix* kModuleTransform = transformer->GetTransformation();
380       TString volName       = transformer->GetVolumeName(); 
381       TString motherVolName = transformer->GetMotherVolumeName(); 
382       
383       // Place the module volume
384       if ( !geometry->IsVirtual() ) {
385           PlaceVolume(volName, motherVolName, 
386                       1, *kModuleTransform, 0, 0, "ONLY");
387       }               
388   
389       TGeoCombiTrans appliedGlobalTransform;
390       if (builder->ApplyGlobalTransformation())
391         appliedGlobalTransform = fGlobalTransformation;
392
393       // Loop over envelopes
394       const TObjArray* kEnvelopes 
395         = geometry->GetEnvelopeStore()->GetEnvelopes();
396       for (Int_t k=0; k<kEnvelopes->GetEntriesFast(); k++) {
397
398         // Get envelope
399         AliMUONGeometryEnvelope* env 
400           = (AliMUONGeometryEnvelope*)kEnvelopes->At(k);
401           
402         const TGeoCombiTrans* kEnvTrans = env->GetTransformation();
403         const char* only = "ONLY";
404         if (env->IsMANY()) only = "MANY";
405
406         if (env->IsVirtual() && env->GetConstituents()->GetEntriesFast() == 0 ) {
407           // virtual envelope + nof constituents = 0 
408           //         => not allowed;
409           //            empty virtual envelope has no sense 
410           AliFatal("Virtual envelope must have constituents.");
411           return;
412         }
413
414         if (!env->IsVirtual() && env->GetConstituents()->GetEntriesFast() > 0 ) {
415           // non virtual envelope + nof constituents > 0 
416           //        => not allowed;
417           //           use VMC to place constituents
418           AliFatal("Non virtual envelope cannot have constituents.");
419           return;
420         }
421
422         if (!env->IsVirtual() && env->GetConstituents()->GetEntriesFast() == 0 ) {
423           // non virtual envelope + nof constituents = 0 
424           //        => place envelope in ALICE by composed transformation:
425           //           Tch * [Tglobal] * Tenv
426
427           // Compound chamber transformation with the envelope one
428           if (geometry->IsVirtual()) {
429              TGeoHMatrix total 
430                = Multiply( (*kModuleTransform), 
431                             appliedGlobalTransform, 
432                            (*kEnvTrans) );
433              PlaceVolume(env->GetName(), motherVolName,
434                          env->GetCopyNo(), total, 0, 0, only);
435           }
436           else {
437              TGeoHMatrix total 
438                = Multiply( appliedGlobalTransform, 
439                            (*kEnvTrans) );
440              PlaceVolume(env->GetName(), volName,
441                          env->GetCopyNo(), total, 0, 0, only);
442           }                      
443         }
444
445         if (env->IsVirtual() && env->GetConstituents()->GetEntriesFast() > 0 ) {
446           // virtual envelope + nof constituents > 0 
447           //         => do not place envelope and place constituents
448           //            in ALICE by composed transformation:
449           //            Tch * [Tglobal] * Tenv * Tconst   
450
451           for  (Int_t l=0; l<env->GetConstituents()->GetEntriesFast(); l++) {
452             AliMUONGeometryConstituent* constituent
453               = (AliMUONGeometryConstituent*)env->GetConstituents()->At(l);
454  
455             // Compound chamber transformation with the envelope one + the constituent one
456             if (geometry->IsVirtual()) {
457               TGeoHMatrix total 
458                 = Multiply ( (*kModuleTransform),
459                              appliedGlobalTransform, 
460                              (*kEnvTrans), 
461                              (*constituent->GetTransformation()) );
462
463               PlaceVolume(constituent->GetName(), motherVolName,
464                           constituent->GetCopyNo(), total,
465                           constituent->GetNpar(), constituent->GetParam(), only);
466             }
467             else {                        
468               TGeoHMatrix total 
469                 = Multiply ( appliedGlobalTransform, 
470                              (*kEnvTrans),
471                              (*constituent->GetTransformation()) );
472
473               PlaceVolume(constituent->GetName(), volName,
474                           constituent->GetCopyNo(), total,
475                           constituent->GetNpar(), constituent->GetParam(), only);
476             }                     
477           }
478         }
479       } // end of loop over envelopes
480     } // end of loop over builder geometries
481   } // end of loop over builders
482 }
483
484 //_____________________________________________________________________________
485 void AliMUONGeometryBuilder::SetAlign(AliMUONVGeometryBuilder* builder)
486 {
487 /// Set align option to all geometry modules associated with the builder
488
489   for (Int_t j=0; j<builder->NofGeometries(); j++) {
490
491     AliMUONGeometryModule* geometry = builder->Geometry(j);
492   
493     geometry->SetAlign(fAlign);
494   }       
495 }            
496
497 //
498 // public functions
499 //
500
501 //_____________________________________________________________________________
502 void AliMUONGeometryBuilder::AddBuilder(AliMUONVGeometryBuilder* geomBuilder)
503 {
504 /// Add the geometry builder to the list
505
506   fGeometryBuilders->Add(geomBuilder);
507   
508   // Pass geometry modules created in the to the geometry parametrisation
509   for (Int_t i=0; i<geomBuilder->NofGeometries(); i++) {
510     fGeometry->AddModule(geomBuilder->Geometry(i));
511   }  
512   
513   if (geomBuilder->ApplyGlobalTransformation())
514     geomBuilder->SetReferenceFrame(fGlobalTransformation);
515   
516   SetAlign(geomBuilder);
517 }
518
519 //______________________________________________________________________________
520 void AliMUONGeometryBuilder::CreateGeometry()
521 {
522 /// Construct geometry using geometry builders.
523
524   if ( gMC->IsRootGeometrySupported() && 
525        TString(gMC->ClassName()) != "TGeant4" ) {
526        
527    CreateGeometryWithTGeo();
528   } 
529   else
530    CreateGeometryWithoutTGeo();
531 }
532
533 //_____________________________________________________________________________
534 void AliMUONGeometryBuilder::CreateMaterials()
535 {
536 /// Construct materials specific to modules via builders
537   
538   for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
539
540     // Get the builder
541     AliMUONVGeometryBuilder* builder
542       = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
543
544     // Create materials with each builder
545     if (builder) builder->CreateMaterials();
546   }
547 }
548
549 //______________________________________________________________________________
550 void AliMUONGeometryBuilder::InitGeometry(const TString& svmapFileName)
551 {
552 /// Initialize geometry
553
554   // Load alignement data from geometry if geometry is read from Root file
555   if ( gAlice->IsRootGeometry() ) {
556     fAlign = true;
557
558     fGeometry->GetTransformer()
559       ->ReadGeometryData(fgkDefaultVolPathsFileName, gGeoManager);
560   }    
561
562   // Read sensitive volume map from a file
563   fGeometry->ReadSVMap(svmapFileName);
564       
565   // Set the chamber (sensitive region) GEANT identifier
566   //
567   for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
568
569     // Get the builder
570     AliMUONVGeometryBuilder* builder
571       = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
572
573     // Set sensitive volumes with each builder
574     builder->SetSensitiveVolumes();
575
576     if (!fAlign)  {
577       // Create detection elements from built geometry
578       builder->CreateDetElements();
579     }  
580   }  
581 }
582
583 //______________________________________________________________________________
584 void AliMUONGeometryBuilder::WriteSVMaps(const TString& fileName, 
585                                          Bool_t rebuild)
586 {
587 /// Write sensitive volume maps into files per builder
588
589   // Rebuild sv maps
590   //
591   if (rebuild) 
592     for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
593
594       AliMUONVGeometryBuilder* builder
595         = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
596
597       Bool_t writeEnvelopes = false;
598       if ( gMC->IsRootGeometrySupported() &&
599            TString(gMC->ClassName()) != "TGeant4") writeEnvelopes = true;
600
601       builder->RebuildSVMaps(writeEnvelopes);
602     }  
603     
604   // Write maps in file
605   fGeometry->WriteSVMap(fileName);
606 }
607
608 //_____________________________________________________________________________
609 void AliMUONGeometryBuilder::SetAlign(Bool_t align)
610
611 /// Set the option for alignement
612
613   fAlign = align; 
614
615   for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
616
617     AliMUONVGeometryBuilder* builder
618       = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
619     
620     SetAlign(builder); 
621   }   
622 }
623
624 //_____________________________________________________________________________
625 void AliMUONGeometryBuilder::SetAlign(const TString& fileName, Bool_t align)
626
627 /// Set the option for alignement
628
629   fTransformFileName = fileName;
630   fAlign = align; 
631
632   for (Int_t i=0; i<fGeometryBuilders->GetEntriesFast(); i++) {
633
634     AliMUONVGeometryBuilder* builder
635       = (AliMUONVGeometryBuilder*)fGeometryBuilders->At(i);
636     
637     SetAlign(builder); 
638   }   
639 }