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