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