- Revised comments and adapted them for Doxygen
[u/mrichter/AliRoot.git] / MUON / AliMUONGeometryTransformer.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 AliMUONGeometryTransformer
20 // ----------------------------
21 // Top container class for geometry transformations
22 // Author: Ivana Hrivnacova, IPN Orsay
23
24 #include "AliMUONGeometryTransformer.h"
25 #include "AliMUONGeometryModuleTransformer.h"
26 #include "AliMUONGeometryDetElement.h"
27 #include "AliMUONGeometryStore.h"
28 #include "AliMUONGeometryBuilder.h"
29
30 #include "AliLog.h"
31 #include "AliAlignObjMatrix.h"
32 #include "AliAlignObj.h"
33
34 #include <Riostream.h>
35 #include <TSystem.h>
36 #include <TClonesArray.h>
37 #include <TGeoManager.h>
38 #include <TGeoPhysicalNode.h>
39 #include <TFile.h>
40
41 #include <sstream>
42
43 /// \cond CLASSIMP
44 ClassImp(AliMUONGeometryTransformer)
45 /// \endcond
46  
47 //______________________________________________________________________________
48 AliMUONGeometryTransformer::AliMUONGeometryTransformer(Bool_t isOwner)
49   : TObject(),
50     fModuleTransformers(0),
51     fMisAlignArray(0)
52 {
53 /// Standard constructor
54
55   // Create array for geometry modules
56   fModuleTransformers = new TObjArray();
57   fModuleTransformers->SetOwner(isOwner);
58 }
59
60 //______________________________________________________________________________
61 AliMUONGeometryTransformer::AliMUONGeometryTransformer() 
62   : TObject(),
63     fModuleTransformers(0),
64     fMisAlignArray(0)
65 {
66 /// Default constructor
67
68
69 //______________________________________________________________________________
70 AliMUONGeometryTransformer::~AliMUONGeometryTransformer()
71 {
72 /// Destructor
73
74   delete fModuleTransformers;
75   delete fMisAlignArray;
76 }
77
78 //
79 // private methods
80 //
81
82 //_____________________________________________________________________________
83 AliMUONGeometryModuleTransformer* 
84 AliMUONGeometryTransformer::GetModuleTransformerNonConst(
85                                           Int_t index, Bool_t warn) const
86 {
87 /// Return the geometry module specified by index
88
89   if (index < 0 || index >= fModuleTransformers->GetEntriesFast()) {
90     if (warn) {
91       AliWarningStream() 
92         << "Index: " << index << " outside limits" << std::endl;
93     }                    
94     return 0;  
95   }  
96
97   return (AliMUONGeometryModuleTransformer*) fModuleTransformers->At(index);
98 }    
99
100 //______________________________________________________________________________
101 TGeoHMatrix AliMUONGeometryTransformer::GetTransform(
102                   Double_t x, Double_t y, Double_t z,
103                   Double_t a1, Double_t a2, Double_t a3, 
104                   Double_t a4, Double_t a5, Double_t a6) const
105 {                 
106 /// Build the transformation from the given parameters
107
108   // Compose transform
109   return TGeoCombiTrans(TGeoTranslation(x, y, z), 
110                         TGeoRotation("rot", a1, a2, a3, a4, a5, a6));
111 }
112
113
114 //______________________________________________________________________________
115 void AliMUONGeometryTransformer::FillModuleVolPath(Int_t moduleId,
116                                            const TString& volPath) 
117 {
118 /// Create module with the given moduleId and volPath
119
120   // Get/Create geometry module transformer
121   AliMUONGeometryModuleTransformer* moduleTransformer
122     = GetModuleTransformerNonConst(moduleId, false);
123
124   if ( !moduleTransformer ) {
125     moduleTransformer = new AliMUONGeometryModuleTransformer(moduleId);
126     AddModuleTransformer(moduleTransformer);
127   }  
128   moduleTransformer->SetVolumePath(volPath);
129 }                  
130   
131 //______________________________________________________________________________
132 void AliMUONGeometryTransformer::FillDetElemVolPath(Int_t detElemId, 
133                                            const TString& volPath) 
134 {
135 /// Create detection element with the given detElemId and volPath
136
137   // Module Id
138   Int_t moduleId = AliMUONGeometryStore::GetModuleId(detElemId);
139
140   // Get detection element store
141   AliMUONGeometryStore* detElements = 
142     GetModuleTransformer(moduleId)->GetDetElementStore();     
143
144   // Add detection element
145   AliMUONGeometryDetElement* detElement
146     = new AliMUONGeometryDetElement(detElemId, volPath);
147   detElements->Add(detElemId, detElement);
148 }                  
149   
150
151 //______________________________________________________________________________
152 void AliMUONGeometryTransformer::FillModuleTransform(Int_t moduleId,
153                   Double_t x, Double_t y, Double_t z,
154                   Double_t a1, Double_t a2, Double_t a3,
155                   Double_t a4, Double_t a5, Double_t a6) 
156 {
157 /// Fill the transformation of the module.
158
159   // Get/Create geometry module transformer
160   moduleId--;
161       // Modules numbers in the file are starting from 1
162
163   AliMUONGeometryModuleTransformer* moduleTransformer
164     = GetModuleTransformerNonConst(moduleId, false);
165
166   if ( !moduleTransformer) {
167     AliErrorStream() 
168       << "Module " << moduleId << " has not volume path defined." << endl;
169   }  
170       
171   // Build the transformation from the parameters
172   TGeoHMatrix transform 
173     = GetTransform(x, y, z, a1, a2, a3, a4, a5, a6);
174       
175   moduleTransformer->SetTransformation(transform);
176 }                  
177   
178 //______________________________________________________________________________
179 void AliMUONGeometryTransformer::FillDetElemTransform(
180                   Int_t detElemId, 
181                   Double_t x, Double_t y, Double_t z,
182                   Double_t a1, Double_t a2, Double_t a3,
183                   Double_t a4, Double_t a5, Double_t a6) 
184 {
185 /// Fill the transformation of the detection element.
186
187   // Module Id
188   Int_t moduleId = AliMUONGeometryStore::GetModuleId(detElemId);
189
190   // Get module transformer
191   const AliMUONGeometryModuleTransformer* kModuleTransformer
192     = GetModuleTransformer(moduleId);
193
194   if ( ! kModuleTransformer ) {
195     AliFatal(Form("Module transformer not defined, detElemId: %d", detElemId));
196     return;  
197   }  
198
199   // Get detection element
200   AliMUONGeometryDetElement* detElement 
201     = kModuleTransformer->GetDetElement(detElemId);     
202
203   if ( ! detElement ) {
204     AliFatal(Form("Det element %d has not volume path defined", detElemId));
205     return;  
206   }  
207       
208   // Build the transformation from the parameters
209   TGeoHMatrix localTransform 
210     = GetTransform(x, y, z, a1, a2, a3, a4, a5, a6);
211   detElement->SetLocalTransformation(localTransform); 
212    
213   // Compute global transformation
214   TGeoHMatrix globalTransform 
215     = AliMUONGeometryBuilder::Multiply( 
216                                   *kModuleTransformer->GetTransformation(),
217                                   localTransform );
218   detElement->SetGlobalTransformation(globalTransform);
219 }                  
220
221 //______________________________________________________________________________
222 Bool_t  
223 AliMUONGeometryTransformer::ReadVolPaths(ifstream& in)
224 {
225 /// Read modules and detection element volume paths from stream
226
227   Int_t id;
228   TString key, volumePath;
229   in >> key;
230   
231   while ( !in.eof() ) {
232
233     in >> id >> volumePath;
234
235     // cout << "id="     << id << "  "
236     //   << "volPath= " << volumePath
237     //   << endl;   
238
239     if ( key == TString("CH") ) 
240       FillModuleVolPath(id, volumePath);
241   
242     else if ( key == TString("DE") )
243       FillDetElemVolPath(id, volumePath);
244   
245     else {
246       AliFatal(Form("%s key not recognized",  key.Data()));
247       return false;
248     }
249     in >> key;
250   }     
251
252   return true;
253 }
254
255 //______________________________________________________________________________
256 TString  AliMUONGeometryTransformer::ReadModuleTransforms(ifstream& in)
257 {
258 /// Read and fill modules transformations from the stream.
259 /// Return true, if reading finished correctly.
260
261   TString key("CH");
262   while ( key == TString("CH") ) {
263     Int_t id;
264     Double_t  x, y, z;
265     Double_t  a1, a2, a3, a4, a5, a6;
266     TString dummy;
267   
268     in >> id;
269     in >> dummy;
270     in >> x;
271     in >> y;
272     in >> z;
273     in >> dummy;
274     in >> a1; 
275     in >> a2; 
276     in >> a3; 
277     in >> a4; 
278     in >> a5; 
279     in >> a6; 
280
281     //cout << "moduleId="     << id << "  "
282     //   << "position= " << x << ", " << y << ", " << z << "  "
283     //   << "rotation= " << a1 << ", " << a2 << ", " << a3  << ", "
284     //                   << a4 << ", " << a5 << ", " << a6 
285     //   << endl;   
286          
287     // Fill data
288     FillModuleTransform(id, x, y, z, a1, a2, a3, a4, a5, a6);
289     
290     // Go to next line
291     in >> key;
292   }
293   
294   return key;            
295 }
296
297 //______________________________________________________________________________
298 TString  AliMUONGeometryTransformer::ReadDetElemTransforms(ifstream& in)
299 {
300 /// Read detection elements transformations from the stream.
301 /// Return true, if reading finished correctly.
302
303   TString key("DE");
304   while ( key == TString("DE") ) {
305
306     // Input data
307     Int_t detElemId;
308     Double_t  x, y, z;
309     Double_t  a1, a2, a3, a4, a5, a6;
310     TString dummy;
311   
312     in >> detElemId;
313     in >> dummy;
314     in >> x;
315     in >> y;
316     in >> z;
317     in >> dummy;
318     in >> a1; 
319     in >> a2; 
320     in >> a3; 
321     in >> a4; 
322     in >> a5; 
323     in >> a6; 
324
325     //cout << "detElemId=" << detElemId << "  "
326     //     << "position= " << x << ", " << y << ", " << z << "  "
327     //     << "rotation= " << a1 << ", " << a2 << ", " << a3  << ", "
328     //                     << a4 << ", " << a5 << ", " << a6 
329     //     << endl;   
330          
331     // Fill data
332     FillDetElemTransform(detElemId, x, y, z, a1, a2, a3, a4, a5, a6);    
333     
334     // Go to next line
335     in >> key;
336   } 
337   
338   return key;
339 }
340
341 //______________________________________________________________________________
342 Bool_t  
343 AliMUONGeometryTransformer::LoadTransforms(TGeoManager* tgeoManager)
344 {
345 /// Load transformations for defined modules and detection elements
346 /// from the root file
347
348   if ( !tgeoManager) {
349     AliFatal("No TGeoManager defined.");
350     return false;
351   }   
352
353   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
354     AliMUONGeometryModuleTransformer* moduleTransformer 
355       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
356
357     // Module path
358     TString path = moduleTransformer->GetVolumePath();
359     
360     // Make physical node
361     TGeoPhysicalNode* moduleNode = tgeoManager->MakePhysicalNode(path);
362     if ( ! moduleNode ) {
363       AliErrorStream() 
364         << "Module id: " << moduleTransformer->GetModuleId()
365         << " volume path: " << path << " not found in geometry." << endl;
366         return false;
367     }    
368     
369     // Set matrix from physical node
370     TGeoHMatrix matrix = *moduleNode->GetMatrix();
371     moduleTransformer->SetTransformation(matrix);
372     
373     // Loop over detection elements
374     AliMUONGeometryStore* detElements 
375       = moduleTransformer->GetDetElementStore();    
376    
377     for (Int_t j=0; j<detElements->GetNofEntries(); j++) {
378       AliMUONGeometryDetElement* detElement
379         = (AliMUONGeometryDetElement*)detElements->GetEntry(j);
380
381       // Det element path
382       TString dePath = detElement->GetVolumePath();
383
384       // Make physical node
385       TGeoPhysicalNode* deNode = tgeoManager->MakePhysicalNode(dePath);
386       if ( ! deNode ) {
387         AliErrorStream() 
388           << "Det element id: " << detElement->GetId()
389           << " volume path: " << path << " not found in geometry." << endl;
390           return false;
391       } 
392          
393       // Set global matrix from physical node
394       TGeoHMatrix globalMatrix = *deNode->GetMatrix();
395       detElement->SetGlobalTransformation(globalMatrix);
396
397       // Set local matrix
398       TGeoHMatrix localMatrix = 
399         AliMUONGeometryBuilder::Multiply(
400            matrix.Inverse(), globalMatrix );
401       detElement->SetLocalTransformation(localMatrix);
402     }  
403   } 
404   return true;    
405 }  
406
407 //______________________________________________________________________________
408 Bool_t  
409 AliMUONGeometryTransformer::ReadVolPaths(const TString& fileName)
410 {
411 /// Read detection element volume paths from a file.
412 /// Return true, if reading finished correctly.
413
414   // File path
415   TString filePath = gSystem->Getenv("ALICE_ROOT");
416   filePath += "/MUON/data/";
417   filePath += fileName;
418   
419   // Open input file
420   ifstream in(filePath, ios::in);
421   if (!in) {
422     cerr << filePath << endl;   
423     AliFatal("File not found.");
424     return false;
425   }
426
427   ReadVolPaths(in);
428   return true;
429 }
430
431 //______________________________________________________________________________
432 Bool_t  
433 AliMUONGeometryTransformer::ReadTransformations(const TString& fileName)
434 {
435 /// Read transformations from a file.
436 /// Return true, if reading finished correctly.
437
438   // File path
439   TString filePath = gSystem->Getenv("ALICE_ROOT");
440   filePath += "/MUON/data/";
441   filePath += fileName;
442   
443   // Open input file
444   ifstream in(filePath, ios::in);
445   if (!in) {
446     cerr << filePath << endl;   
447     AliFatal("File not found.");
448     return false;
449   }
450
451   TString key;
452   in >> key;
453   while ( !in.eof() ) {
454     if (key == TString("CH")) 
455       key = ReadModuleTransforms(in);
456     else if (key == TString("DE"))
457       key = ReadDetElemTransforms(in);
458     else {
459       AliFatal(Form("%s key not recognized",  key.Data()));
460       return false;
461     }
462   }     
463
464   return true;
465 }
466
467 //______________________________________________________________________________
468 Bool_t  
469 AliMUONGeometryTransformer::ReadTransformations2(const TString& fileName)
470 {
471 /// Read transformations from root geometry file.
472 /// Return true, if reading finished correctly.
473
474   // File path
475   TString filePath = gSystem->Getenv("ALICE_ROOT");
476   filePath += "/MUON/data/";
477   filePath += fileName;
478   
479   // Load root geometry
480   TGeoManager* tgeoManager = TGeoManager::Import(fileName);
481
482   // Retrieve matrices
483   LoadTransforms(tgeoManager);     
484
485   return true;
486 }
487
488 //______________________________________________________________________________
489 void AliMUONGeometryTransformer::WriteTransform(ofstream& out,
490                                    const TGeoMatrix* transform) const
491 {
492 /// Write given transformation 
493
494   out << "   pos: ";
495   const Double_t* xyz = transform->GetTranslation();
496   out << setw(10) << setprecision(4) << xyz[0] << "  " 
497       << setw(10) << setprecision(4) << xyz[1] << "  " 
498       << setw(10) << setprecision(4) << xyz[2];
499
500   out << "   rot: ";
501   const Double_t* rm = transform->GetRotationMatrix();
502   TGeoRotation rotation;
503   rotation.SetMatrix(const_cast<Double_t*>(rm));
504   Double_t a1, a2, a3, a4, a5, a6;
505   rotation.GetAngles(a1, a2, a3, a4, a5, a6);
506       
507   out << setw(8) << setprecision(4) << a1 << "  " 
508       << setw(8) << setprecision(4) << a2 << "  " 
509       << setw(8) << setprecision(4) << a3 << "  " 
510       << setw(8) << setprecision(4) << a4 << "  " 
511       << setw(8) << setprecision(4) << a5 << "  " 
512       << setw(8) << setprecision(4) << a6 << "  " << endl; 
513 }
514
515 //______________________________________________________________________________
516 void AliMUONGeometryTransformer::WriteModuleVolPaths(ofstream& out) const
517 {
518 /// Write module volume paths for all module transformers
519
520   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
521     AliMUONGeometryModuleTransformer* moduleTransformer 
522       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
523
524     // Write data on out
525     out << "CH " 
526         << setw(4) << moduleTransformer->GetModuleId() << "    " 
527         << moduleTransformer->GetVolumePath() << endl;
528   }     
529   out << endl;                  
530 }
531
532 //______________________________________________________________________________
533 void AliMUONGeometryTransformer::WriteDetElemVolPaths(ofstream& out) const
534 {
535 /// Write detection element volume paths for all detection elements in all 
536 /// module transformers
537
538   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
539     AliMUONGeometryModuleTransformer* moduleTransformer 
540       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
541     AliMUONGeometryStore* detElements 
542       = moduleTransformer->GetDetElementStore();    
543
544     for (Int_t j=0; j<detElements->GetNofEntries(); j++) {
545       AliMUONGeometryDetElement* detElement
546         = (AliMUONGeometryDetElement*)detElements->GetEntry(j);
547         
548       // Write data on out
549       out << "DE " 
550           << setw(4) << detElement->GetId() << "    " 
551           << detElement->GetVolumePath() << endl;
552     }
553     out << endl;                        
554   }     
555 }
556
557 //______________________________________________________________________________
558 void AliMUONGeometryTransformer::WriteModuleTransforms(ofstream& out) const
559 {
560 /// Write module transformations for all module transformers
561
562   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
563     AliMUONGeometryModuleTransformer* moduleTransformer 
564       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
565     const TGeoMatrix* transform 
566       = moduleTransformer->GetTransformation();    
567
568     // Write data on out
569     out << "CH " 
570         << setw(4) << moduleTransformer->GetModuleId() + 1;
571     
572     WriteTransform(out, transform);
573   }
574   out << endl;
575 }
576
577 //______________________________________________________________________________
578 void AliMUONGeometryTransformer::WriteDetElemTransforms(ofstream& out) const
579 {
580 /// Write detection element transformations for all detection elements in all 
581 /// module transformers
582
583   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
584     AliMUONGeometryModuleTransformer* moduleTransformer 
585       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
586     AliMUONGeometryStore* detElements 
587       = moduleTransformer->GetDetElementStore();    
588
589     for (Int_t j=0; j<detElements->GetNofEntries(); j++) {
590       AliMUONGeometryDetElement* detElement
591         = (AliMUONGeometryDetElement*)detElements->GetEntry(j);
592       const TGeoMatrix* transform 
593         = detElement->GetLocalTransformation(); 
594         
595       // Write data on out
596       out << "DE " << setw(4) << detElement->GetId();
597      
598       WriteTransform(out, transform);
599     }
600     out << endl;                        
601   }     
602 }
603
604 //
605 // public functions
606 //
607
608 //______________________________________________________________________________
609 Bool_t  
610 AliMUONGeometryTransformer::ReadGeometryData(
611                                 const TString& volPathFileName,
612                                 const TString& transformFileName)
613 {
614 /// Read geometry data from given files;
615 /// if transformFileName has ".root" extension, the transformations
616 /// are loaded from root geometry file, otherwise ASCII file
617 /// format is supposed
618
619   Bool_t result1 = ReadVolPaths(volPathFileName);
620
621   // Get file extension
622   std::string fileName = transformFileName.Data();
623   std::string rootExt = fileName.substr(fileName.size()-5, fileName.size());
624   Bool_t result2;
625   if ( rootExt != ".root" ) 
626     result2 = ReadTransformations(transformFileName);
627   else   
628     result2 = ReadTransformations2(transformFileName);
629   
630   return result1 && result2;
631 }  
632
633 //______________________________________________________________________________
634 Bool_t  
635 AliMUONGeometryTransformer::ReadGeometryData(
636                                 const TString& volPathFileName,
637                                 TGeoManager* tgeoManager)
638 {
639 /// Load geometry data from root geometry using defined
640 /// volume paths from file
641
642   Bool_t result1 = ReadVolPaths(volPathFileName);
643
644   Bool_t result2 = LoadTransforms(tgeoManager);
645   
646   return result1 && result2;
647 }  
648
649 //______________________________________________________________________________
650 Bool_t  
651 AliMUONGeometryTransformer::WriteGeometryData(
652                                  const TString& volPathFileName,
653                                  const TString& transformFileName,
654                                  const TString& misalignFileName) const
655 {
656 /// Write geometry data into given files
657
658   Bool_t result1 = WriteVolumePaths(volPathFileName);
659   Bool_t result2 = WriteTransformations(transformFileName);
660   
661   Bool_t result3 = true;
662   if ( misalignFileName != "" )
663     result3 = WriteMisAlignmentData(misalignFileName);
664   
665   return result1 && result2 && result3;
666 }
667                                  
668 //______________________________________________________________________________
669 Bool_t  
670 AliMUONGeometryTransformer::WriteVolumePaths(const TString& fileName) const
671 {
672 /// Write volume paths for modules and detection element volumes into a file.
673 /// Return true, if writing finished correctly.
674
675   // No writing
676   // if builder is not associated with any geometry module
677   if (fModuleTransformers->GetEntriesFast() == 0) return false;
678
679   // File path
680   TString filePath = gSystem->Getenv("ALICE_ROOT");
681   filePath += "/MUON/data/";
682   filePath += fileName;
683   
684   // Open output file
685   ofstream out(filePath, ios::out);
686   if (!out) {
687     cerr << filePath << endl;   
688     AliError("File not found.");
689     return false;
690   }
691 #if !defined (__DECCXX)
692   out.setf(std::ios::fixed);
693 #endif
694   WriteModuleVolPaths(out);
695   WriteDetElemVolPaths(out);
696   
697   return true;
698 }  
699
700 //______________________________________________________________________________
701 Bool_t  
702 AliMUONGeometryTransformer::WriteTransformations(const TString& fileName) const
703 {
704 /// Write transformations into a file.
705 /// Return true, if writing finished correctly.
706
707   // No writing
708   // if builder is not associated with any geometry module
709   if (fModuleTransformers->GetEntriesFast() == 0) return false;
710
711   // File path
712   TString filePath = gSystem->Getenv("ALICE_ROOT");
713   filePath += "/MUON/data/";
714   filePath += fileName;
715   
716   // Open output file
717   ofstream out(filePath, ios::out);
718   if (!out) {
719     cerr << filePath << endl;   
720     AliError("File not found.");
721     return false;
722   }
723 #if !defined (__DECCXX)
724   out.setf(std::ios::fixed);
725 #endif
726   WriteModuleTransforms(out);
727   WriteDetElemTransforms(out);
728   
729   return true;
730 }  
731
732 //______________________________________________________________________________
733 Bool_t  
734 AliMUONGeometryTransformer::WriteMisAlignmentData(const TString& fileName) const
735 {
736 /// Write misalignment data into a file
737 /// Return true, if writing finished correctly.
738
739   // No writing
740   // if builder is not associated with any geometry module
741   if ( fModuleTransformers->GetEntriesFast() == 0 ) {
742     AliWarningStream() << "No geometry modules defined." << endl;
743     return false;
744   }  
745   
746   // No writing
747   // if builder has no mis-alignment data
748   if ( ! fMisAlignArray ) {
749     AliWarningStream() << "No mis-alignment data defined." << endl;
750     return false;
751   }  
752
753   // File path
754   TString filePath = gSystem->Getenv("ALICE_ROOT");
755   filePath += "/MUON/data/";
756   filePath += fileName;
757   
758   // Write mis-alignment data in the root file
759   TFile file(fileName.Data(), "RECREATE");
760   fMisAlignArray->Write();
761   file.Close();
762   
763   return true;
764 }  
765
766 //_____________________________________________________________________________
767 void AliMUONGeometryTransformer::AddModuleTransformer(
768                           AliMUONGeometryModuleTransformer* moduleTransformer)
769 {
770 /// Add the module transformer to the array
771
772   fModuleTransformers->AddAt(moduleTransformer, 
773                              moduleTransformer->GetModuleId());
774 }
775
776 //_____________________________________________________________________________
777 void  AliMUONGeometryTransformer::AddMisAlignModule(Int_t moduleId, 
778                                               const TGeoHMatrix& matrix)
779 {
780 /// Build AliAlignObjMatrix with module ID, its volumePath
781 /// and the given delta transformation matrix                                         
782
783   if ( ! fMisAlignArray )
784     fMisAlignArray = new TClonesArray("AliAlignObjMatrix", 200);
785     
786   const AliMUONGeometryModuleTransformer* kTransformer 
787     = GetModuleTransformer(moduleId);
788   if ( ! kTransformer ) {
789     AliErrorStream() << "Module " << moduleId << " not found." << endl; 
790     return;
791   }   
792   
793   // Get path  
794   TString path = kTransformer->GetVolumePath(); 
795   
796   // Get unique align object ID
797   Int_t volId = AliAlignObj::LayerToVolUID(AliAlignObj::kMUON, moduleId); 
798
799   // Create mis align matrix
800   TClonesArray& refArray =*fMisAlignArray;
801   Int_t pos = fMisAlignArray->GetEntriesFast();
802   new (refArray[pos]) AliAlignObjMatrix(path.Data(), volId, 
803                               const_cast<TGeoHMatrix&>(matrix));
804 }
805
806 //_____________________________________________________________________________
807 void  AliMUONGeometryTransformer::AddMisAlignDetElement(Int_t detElemId, 
808                                               const TGeoHMatrix& matrix)
809 {
810 /// Build AliAlignObjMatrix with detection element ID, its volumePath
811 /// and the given delta transformation matrix                                         
812
813   if ( ! fMisAlignArray )
814     fMisAlignArray = new TClonesArray("AliAlignObjMatrix", 200);
815
816   const AliMUONGeometryDetElement* kDetElement 
817     = GetDetElement(detElemId);
818
819   if ( ! kDetElement ) {
820     AliErrorStream() << "Det element " << detElemId << " not found." << endl; 
821     return;
822   }   
823   
824   // Get path  
825   TString path = kDetElement->GetVolumePath(); 
826   
827   // Get unique align object ID
828   Int_t volId = AliAlignObj::LayerToVolUID(AliAlignObj::kMUON, detElemId); 
829
830   // Create mis align matrix
831   TClonesArray& refArray =*fMisAlignArray;
832   Int_t pos = fMisAlignArray->GetEntriesFast();
833   new(refArray[pos]) AliAlignObjMatrix(path.Data(), volId, 
834                               const_cast<TGeoHMatrix&>(matrix));
835 }
836
837 //_____________________________________________________________________________
838 TClonesArray* AliMUONGeometryTransformer::CreateZeroAlignmentData() const
839 {
840 /// Create array with zero alignment data
841                                
842   // Create array for zero-alignment objects
843   TClonesArray* array = new TClonesArray("AliAlignObjMatrix", 200);
844   TClonesArray& refArray =*array;
845   array->SetOwner(true);
846
847   // Identity matrix
848   TGeoHMatrix matrix;
849
850   // Modules 
851   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
852     AliMUONGeometryModuleTransformer* module 
853       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
854
855     TString path = module->GetVolumePath(); 
856     Int_t moduleId = module->GetModuleId();
857   
858     // Align object ID
859     Int_t volId = AliAlignObj::LayerToVolUID(AliAlignObj::kMUON, moduleId); 
860
861     // Create mis align matrix
862     Int_t pos = array->GetEntriesFast();
863     new (refArray[pos]) AliAlignObjMatrix(path.Data(), volId, matrix);
864   }     
865
866   // Detection elements
867   for (Int_t i=0; i<fModuleTransformers->GetEntriesFast(); i++) {
868     AliMUONGeometryModuleTransformer* moduleTransformer 
869       = (AliMUONGeometryModuleTransformer*)fModuleTransformers->At(i);
870     AliMUONGeometryStore* detElements 
871       = moduleTransformer->GetDetElementStore();    
872
873     for (Int_t j=0; j<detElements->GetNofEntries(); j++) {
874       AliMUONGeometryDetElement* detElement
875         = (AliMUONGeometryDetElement*)detElements->GetEntry(j);
876         
877       TString path = detElement->GetVolumePath(); 
878       Int_t detElemId = detElement->GetId();
879   
880       // Align object ID
881       Int_t volId = AliAlignObj::LayerToVolUID(AliAlignObj::kMUON, detElemId); 
882
883       // Create mis align matrix
884       Int_t pos = array->GetEntriesFast();
885       new (refArray[pos]) AliAlignObjMatrix(path.Data(), volId, matrix);
886     }
887   }
888   
889   return array;
890 }       
891
892 //_____________________________________________________________________________
893 void AliMUONGeometryTransformer::Global2Local(Int_t detElemId,
894                  Float_t xg, Float_t yg, Float_t zg, 
895                  Float_t& xl, Float_t& yl, Float_t& zl) const
896 {
897 /// Transform point from the global reference frame (ALIC)
898 /// to the local reference frame of the detection element specified
899 /// by detElemId.
900
901   const AliMUONGeometryModuleTransformer* kTransformer 
902     = GetModuleTransformerByDEId(detElemId);
903   
904   if (kTransformer) 
905     kTransformer->Global2Local(detElemId, xg, yg, zg, xl, yl, zl);
906 }   
907                  
908 //_____________________________________________________________________________
909 void AliMUONGeometryTransformer::Global2Local(Int_t detElemId,
910                  Double_t xg, Double_t yg, Double_t zg, 
911                  Double_t& xl, Double_t& yl, Double_t& zl) const
912 {
913 /// Transform point from the global reference frame (ALIC)
914 /// to the local reference frame of the detection element specified
915 /// by detElemId.
916
917   const AliMUONGeometryModuleTransformer* kTransformer 
918     = GetModuleTransformerByDEId(detElemId);
919   
920   if (kTransformer) 
921     kTransformer->Global2Local(detElemId, xg, yg, zg, xl, yl, zl);
922 }   
923
924 //_____________________________________________________________________________
925 void AliMUONGeometryTransformer::Local2Global(Int_t detElemId,
926                  Float_t xl, Float_t yl, Float_t zl, 
927                  Float_t& xg, Float_t& yg, Float_t& zg) const
928 {                
929 /// Transform point from the local reference frame of the detection element 
930 /// specified by detElemId to the global reference frame (ALIC).
931
932   const AliMUONGeometryModuleTransformer* kTransformer 
933     = GetModuleTransformerByDEId(detElemId);
934     
935   if (kTransformer) 
936     kTransformer->Local2Global(detElemId, xl, yl, zl, xg, yg, zg);
937 }   
938
939 //_____________________________________________________________________________
940 void AliMUONGeometryTransformer::Local2Global(Int_t detElemId,
941                  Double_t xl, Double_t yl, Double_t zl, 
942                  Double_t& xg, Double_t& yg, Double_t& zg) const
943 {                
944 /// Transform point from the local reference frame of the detection element 
945 /// specified by detElemId to the global reference frame (ALIC).
946
947   const AliMUONGeometryModuleTransformer* kTransformer 
948     = GetModuleTransformerByDEId(detElemId);
949     
950   if (kTransformer) 
951     kTransformer->Local2Global(detElemId, xl, yl, zl, xg, yg, zg);
952 }   
953
954 //_____________________________________________________________________________
955 const AliMUONGeometryModuleTransformer* 
956 AliMUONGeometryTransformer::GetModuleTransformer(Int_t index, Bool_t warn) const
957 {
958 /// Return the geometry module transformer specified by index
959
960   return GetModuleTransformerNonConst(index, warn);
961 }    
962
963 //_____________________________________________________________________________
964 const AliMUONGeometryModuleTransformer* 
965 AliMUONGeometryTransformer::GetModuleTransformerByDEId(Int_t detElemId, 
966                                                        Bool_t warn) const
967 {
968 /// Return the geometry module transformer specified by detection element ID
969
970   // Get module index
971   Int_t index = AliMUONGeometryStore::GetModuleId(detElemId);
972
973   return GetModuleTransformer(index, warn);
974 }    
975
976 //_____________________________________________________________________________
977 const AliMUONGeometryDetElement* 
978 AliMUONGeometryTransformer::GetDetElement(Int_t detElemId, Bool_t warn) const
979 {
980 /// Return detection element with given detElemId                              
981
982   const AliMUONGeometryModuleTransformer* kTransformer 
983     = GetModuleTransformerByDEId(detElemId, warn);
984     
985   if (!kTransformer) return 0;
986     
987   return kTransformer->GetDetElement(detElemId, warn); 
988 }
989
990 //_____________________________________________________________________________
991 Bool_t  AliMUONGeometryTransformer::HasDE(Int_t detElemId) const
992 {
993 /// Return true if detection element with given detElemId is defined
994
995   const AliMUONGeometryModuleTransformer* kTransformer 
996     = GetModuleTransformerByDEId(detElemId, false);
997     
998   if (!kTransformer) return false;
999     
1000   return ( kTransformer->GetDetElement(detElemId, false) != 0 );
1001 }  
1002     
1003