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