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