Create the magnetic field map in the reconstruction macros (Yuri)
[u/mrichter/AliRoot.git] / MUON / AliMUONPainterHelper.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
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 purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17
18 #include <cstdlib>
19 #include "AliMUONPainterHelper.h"
20
21 #include "AliMUONGeometryDetElement.h"
22 #include "AliMUONGeometryTransformer.h"
23 #include "AliMUONPainterContour.h"
24 #include "AliMUONPainterContourMaker.h"
25 #include "AliMUONPainterEnv.h"
26 #include "AliMUONPainterMatrix.h"
27 #include "AliMUONPainterPadStore.h"
28 #include "AliMUONPainterRegistry.h"
29 #include "AliMUONVCalibParam.h"
30 #include "AliMUONVDigit.h"
31 #include "AliMUONVTrackerData.h"
32 #include "AliMpCDB.h"
33 #include "AliMpConstants.h"
34 #include "AliMpDDLStore.h"
35 #include "AliMpDEIterator.h"
36 #include "AliMpDEManager.h"
37 #include "AliMpExMap.h"
38 #include "AliMpMotifMap.h"
39 #include "AliMpMotifPosition.h"
40 #include "AliMpPCB.h"
41 #include "AliMpPad.h"
42 #include "AliMpSector.h"
43 #include "AliMpSectorSegmentation.h"
44 #include "AliMpSegmentation.h"
45 #include "AliMpSlat.h"
46 #include "AliMpSlatSegmentation.h"
47 #include "AliMpStationType.h"
48 #include "AliMpVPadIterator.h"
49 #include "AliCodeTimer.h"
50 #include "AliLog.h"
51 #include <Riostream.h>
52 #include <TArrayI.h>
53 #include <TCanvas.h>
54 #include <TClass.h>
55 #include <TCollection.h>
56 #include <TFile.h>
57 #include <TGLabel.h>
58 #include <TGeoMatrix.h>
59 #include <TGMsgBox.h>
60 #include <TLine.h>
61 #include <TList.h>
62 #include <TMap.h>
63 #include <TObjArray.h>
64 #include <TObjString.h>
65 #include <TStyle.h>
66 #include <TSystem.h>
67 #include <TVector2.h>
68 #include <TVector3.h>
69 #include <TVirtualPad.h>
70 #include <TVirtualX.h>
71
72 ///\class AliMUONPainterHelper
73 ///
74 /// Helper class for painters
75 ///
76 ///\author Laurent Aphecetche, Subatech
77
78 ///\cond CLASSIMP
79 ClassImp(AliMUONPainterHelper)
80 ///\endcond
81
82 AliMUONPainterHelper* AliMUONPainterHelper::fgInstance(0x0);
83
84 //_____________________________________________________________________________
85 AliMUONPainterHelper::AliMUONPainterHelper() : 
86   TObject(),
87   fPadStore(0x0),
88   fExplodedGlobalTransformations(0x0),
89   fRealGlobalTransformations(0x0),
90   fIsModified(kFALSE),
91   fContourMaker(0x0),
92   fPainterMatrices(0x0),
93   fEnv(0x0)
94 {
95     /// ctor
96     fExplodeFactor[0] = 1.00;
97     fExplodeFactor[1] = 1.50;
98
99     if ( ! AliMpCDB::LoadMpSegmentation() ) 
100     {
101       AliFatal("Could not access mapping from OCDB !");
102     }
103     
104     // Load DDL store
105     if ( ! AliMpCDB::LoadDDLStore() ) 
106     {
107       AliFatal("Could not access DDL Store from OCDB !");
108     }        
109 }
110
111 //_____________________________________________________________________________
112 AliMUONPainterHelper::~AliMUONPainterHelper()
113 {
114   /// dtor
115   if ( fIsModified ) Save();
116   delete fExplodedGlobalTransformations;
117   delete fRealGlobalTransformations;
118   delete fPadStore;
119   delete fContourMaker;
120   delete fPainterMatrices;
121   fgInstance = 0;
122 }
123
124 //_____________________________________________________________________________
125 AliMUONPainterContour*
126 AliMUONPainterHelper::GetContour(const char* contourName) const
127 {
128   /// Get a contour by name
129   
130   AliCodeTimerAuto("")
131   
132   if ( fContourMaker ) 
133   {
134     return fContourMaker->GetContour(contourName);
135   }
136   return 0x0;
137 }
138
139 //_____________________________________________________________________________
140 Int_t 
141 AliMUONPainterHelper::FindPadID(const TArrayI& pads, Double_t x, Double_t y) const
142 {
143   /// Find a pad by position
144   
145   return fPadStore->FindPadID(pads,x,y);
146 }
147
148 //_____________________________________________________________________________
149 void
150 AliMUONPainterHelper::GenerateDefaultMatrices()
151 {
152   /// Kind of bootstrap method to trigger the generation of all contours
153   
154   fPainterMatrices = new TObjArray;
155   fPainterMatrices->SetOwner(kFALSE);
156   
157   TObjArray attributes;
158   
159   AliMUONAttPainter att;
160   
161   att.SetViewPoint(kTRUE,kFALSE);
162   att.SetPlane(kFALSE,kFALSE);
163   att.SetCathode(kTRUE,kFALSE);
164   
165   AliWarningClass("Should generate back views as well here");
166   
167   attributes.Add(new AliMUONAttPainter(att));  
168   att.SetCathode(kFALSE,kTRUE);
169   attributes.Add(new AliMUONAttPainter(att));
170   att.SetCathode(kFALSE,kFALSE);
171   att.SetPlane(kTRUE,kFALSE);
172   attributes.Add(new AliMUONAttPainter(att));
173   att.SetPlane(kFALSE,kTRUE);
174   attributes.Add(new AliMUONAttPainter(att));
175   
176   TIter next(&attributes);
177   AliMUONAttPainter* a;
178   
179   while ( ( a = static_cast<AliMUONAttPainter*>(next()) ) )
180   {
181     AliMUONPainterMatrix* matrix = new AliMUONPainterMatrix("Tracker",5,2);
182     
183     for ( Int_t i = 0; i < 10; ++i )
184     {
185       AliMUONVPainter* painter = AliMUONVPainter::CreatePainter("AliMUONChamberPainter",*a,i,-1);
186       
187       painter->SetResponder("Chamber");
188       
189       painter->SetOutlined("*",kFALSE);
190       
191       painter->SetOutlined("MANU",kTRUE);
192       
193       for ( Int_t j = 0; j < 3; ++j ) 
194       {
195         painter->SetLine(j,1,4-j);
196       }
197       
198       matrix->Adopt(painter);    
199     }
200     AliMUONPainterRegistry::Instance()->Register(matrix);
201     fPainterMatrices->Add(matrix);
202   }
203 }
204
205 //_____________________________________________________________________________
206 void
207 AliMUONPainterHelper::GenerateGeometry()
208 {  
209   /// Generate the geometry (FIXME: using transform.dat for the moment)
210   /// The geometry is not the "normal" one as we "explode" it to avoid
211   /// having overlapping detection elements as in the reality, which 
212   /// would be inconvenient for a display ;-)
213   
214   AliDebug(1,Form(" with explodeFactor=%e,%e",fExplodeFactor[0],fExplodeFactor[1]));
215   
216   AliMUONGeometryTransformer transformer;
217   transformer.LoadGeometryData("transform.dat");
218 //  transformer.LoadGeometryData("geometry.root"); //FIXME: add a protection if geometry.root file does not exist
219   fExplodedGlobalTransformations = new AliMpExMap(true);
220   fRealGlobalTransformations = new AliMpExMap(true);
221   AliMpDEIterator deIt;
222   deIt.First();
223   while ( !deIt.IsDone() )
224   {
225     Int_t detElemId = deIt.CurrentDEId();
226     const AliMUONGeometryDetElement* de = transformer.GetDetElement(detElemId);
227     
228     fRealGlobalTransformations->Add(detElemId,de->GetGlobalTransformation()->Clone());
229                                     
230     TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(de->GetGlobalTransformation()->Clone());
231     Double_t* translation = matrix->GetTranslation();
232     
233     AliDebug(1,Form("Initial translation for DE %04d is %7.3f, %7.3f",
234                     detElemId,translation[0],translation[1]));
235     
236     if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 ) 
237     {
238       translation[0] *= fExplodeFactor[0];
239       translation[1] *= fExplodeFactor[1];
240     }
241     else
242     {
243       Double_t shift = 5; // cm
244       Double_t xshift[] = { shift, -shift, -shift, shift };
245       Double_t yshift[] = { shift, shift, -shift, -shift };
246       Int_t ishift = detElemId % 100;
247       
248       translation[0] += xshift[ishift];
249       translation[1] += yshift[ishift];
250     }
251     matrix->SetTranslation(translation);
252     fExplodedGlobalTransformations->Add(detElemId,matrix);
253     deIt.Next();
254   }
255 }
256
257 //_____________________________________________________________________________
258 AliMUONPainterContour* 
259 AliMUONPainterHelper::GenerateManuContour(Int_t detElemId,
260                                           Int_t manuId,
261                                           AliMUONAttPainter viewType,
262                                           const char* contourName)
263 {
264   /// Generate the contour of the list of pads
265   
266   if (!fContourMaker) fContourMaker = new AliMUONPainterContourMaker(fExplodedGlobalTransformations);
267   
268   AliMUONPainterContour* contour = 
269     fContourMaker->GenerateManuContour(contourName,detElemId,manuId,viewType);
270   
271   if (contour) 
272   {
273     RegisterContour(contour);
274   }
275   
276   return contour;
277 }
278
279 //_____________________________________________________________________________
280 void
281 AliMUONPainterHelper::GeneratePadStore()
282 {
283   /// Generate the pad store
284   
285   AliCodeTimerAuto("")
286   AliDebugClass(1,"Generating pad store");
287   fPadStore = new AliMUONPainterPadStore();
288   
289   AliMpDEIterator deIt;
290   
291   deIt.First();
292   while ( !deIt.IsDone() )
293   {
294     Int_t detElemId = deIt.CurrentDEId();
295     if ( AliMpDEManager::GetStationType(detElemId) != AliMp::kStationTrigger )
296     {
297       GeneratePadStore(detElemId);
298     }
299     deIt.Next();
300   }
301 }
302
303 //_____________________________________________________________________________
304 void
305 AliMUONPainterHelper::GeneratePadStore(Int_t detElemId)
306 {
307   /// Generate part of the padstore for one detection element
308   
309   AliMp::CathodType cathode[] = { AliMp::kCath0, AliMp::kCath1 };
310   
311   for ( Int_t i = 0; i < 2; ++i ) 
312   {
313     const AliMpVSegmentation* seg = 
314     AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,cathode[i]);
315     AliMpVPadIterator* it = seg->CreateIterator();
316     it->First();
317     
318     while ( !it->IsDone() )
319     {
320       AliMpPad pad = it->CurrentItem();
321       
322       TVector2 localPosition(pad.Position());
323       Double_t x,y,z;
324       Local2Global(detElemId,localPosition.X(),localPosition.Y(),0,
325                    x,y,z);
326       Int_t manuId = pad.GetLocation().GetFirst();
327       Int_t manuChannel = pad.GetLocation().GetSecond();
328       AliMUONVCalibParam* param = fPadStore->Get(detElemId,manuId);
329       param->SetValueAsDouble(manuChannel,0,x);
330       param->SetValueAsDouble(manuChannel,1,y);
331       param->SetValueAsDouble(manuChannel,2,pad.Dimensions().X());
332       param->SetValueAsDouble(manuChannel,3,pad.Dimensions().Y());
333       it->Next();
334     }          
335     delete it;
336   }
337 }
338
339 //_____________________________________________________________________________
340 void 
341 AliMUONPainterHelper::GetBoundaries(const TArrayI& pads, Double_t& xmin, Double_t& ymin,
342                                     Double_t& xmax, Double_t& ymax) const
343 {
344   /// Get the area covered by an array of pads
345   
346   return fPadStore->GetBoundaries(pads,xmin,ymin,xmax,ymax);
347 }
348
349 //_____________________________________________________________________________
350 AliMp::CathodType
351 AliMUONPainterHelper::GetCathodeType(Int_t detElemId, Int_t manuId) const
352 {
353   /// Get the cathode type of a given manu
354   
355   AliMp::PlaneType planeType(AliMp::kBendingPlane);
356   if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
357   {
358     planeType = AliMp::kNonBendingPlane;
359   }
360   return AliMpDEManager::GetCathod(detElemId,planeType);
361 }
362
363 //_____________________________________________________________________________
364 AliMUONPainterContour* 
365 AliMUONPainterHelper::GetLocalManuContour(Int_t detElemId, Int_t manuId) const
366 {
367   /// Retrieve a manu contour (in local coordinates)
368   return fContourMaker->FindLocalManuContour(detElemId,manuId);
369 }
370
371 //_____________________________________________________________________________
372 AliMpMotifPosition* 
373 AliMUONPainterHelper::GetMotifPosition(Int_t detElemId, Int_t manuId) const
374 {
375   /// Get a given motif position
376   AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
377   if ( stationType == AliMp::kStation345 ) 
378   {
379     AliMp::PlaneType planeType(AliMp::kBendingPlane);
380     if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
381     {
382       planeType = AliMp::kNonBendingPlane;
383     }
384     const AliMpSlat* slat = GetSlat(detElemId,planeType);
385     return slat->FindMotifPosition(manuId);
386   }
387   else if ( stationType != AliMp::kStationTrigger ) 
388   {
389     AliMp::PlaneType planeType(AliMp::kBendingPlane);
390     if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
391     {
392       planeType = AliMp::kNonBendingPlane;
393     }
394     const AliMpSector* sector = GetSector(detElemId,planeType);
395     return sector->GetMotifMap()->FindMotifPosition(manuId);
396   }
397   AliFatalClass("Not supposed to work with trigger");
398   return 0x0;
399 }
400
401
402 //_____________________________________________________________________________
403 AliMpPCB*
404 AliMUONPainterHelper::GetPCB(Int_t detElemId, AliMp::CathodType cathodeType, 
405                              Int_t pcbNumber) const
406 {
407   /// Get a given PCB
408   const AliMpSlat* slat = GetSlat(detElemId,cathodeType);
409   if ( slat ) return slat->GetPCB(pcbNumber);
410   return 0x0;
411 }
412
413 //_____________________________________________________________________________
414 AliMpPCB*
415 AliMUONPainterHelper::GetPCB(Int_t detElemId, AliMp::PlaneType planeType, 
416                              Int_t pcbNumber) const
417 {
418   /// Get a given PCB
419   AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,
420                                                             planeType);
421   return GetPCB(detElemId,cathodeType,pcbNumber);
422 }
423
424 //_____________________________________________________________________________
425 AliMp::PlaneType
426 AliMUONPainterHelper::GetPlaneType(Int_t manuId) const
427 {
428   /// Get the planeType of a given manu
429   
430   if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
431   {
432     return AliMp::kNonBendingPlane;
433   }
434   return AliMp::kBendingPlane;
435 }
436
437 //_____________________________________________________________________________
438 const AliMpSlat*
439 AliMUONPainterHelper::GetSlat(Int_t detElemId, AliMp::PlaneType planeType) const
440 {
441   /// Get a given slat
442   
443   AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,
444                                                           planeType);
445
446   return GetSlat(detElemId,cathodeType);
447 }
448
449 //_____________________________________________________________________________
450 const AliMpSector*
451 AliMUONPainterHelper::GetSector(Int_t detElemId, AliMp::PlaneType planeType) const
452 {
453   /// Get a given sector
454   AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
455   if ( stationType != AliMp::kStation1 && stationType != AliMp::kStation2 ) return 0x0;
456   
457   AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,planeType);
458   
459   const AliMpVSegmentation* seg =
460   AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,cathodeType);
461   
462   const AliMpSectorSegmentation* sectorSeg = static_cast<const AliMpSectorSegmentation*>(seg);
463   return sectorSeg->GetSector();
464   
465 }
466
467 //_____________________________________________________________________________
468 const AliMpSlat*
469 AliMUONPainterHelper::GetSlat(Int_t detElemId, AliMp::CathodType cathodeType) const
470 {
471   /// Get a given slat
472   AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
473   if ( stationType != AliMp::kStation345 ) return 0x0;
474
475   const AliMpVSegmentation* seg =
476     AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,cathodeType);
477   
478   const AliMpSlatSegmentation* slatSeg = static_cast<const AliMpSlatSegmentation*>(seg);
479   return slatSeg->Slat();
480 }
481
482 //_____________________________________________________________________________
483 const AliMpSlat*
484 AliMUONPainterHelper::GetSlat(Int_t detElemId, Int_t manuId) const
485 {
486   /// Get a given slat
487   const AliMpVSegmentation* seg =
488     AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
489   
490   const AliMpSlatSegmentation* slatSeg = static_cast<const AliMpSlatSegmentation*>(seg);
491   return slatSeg->Slat();
492 }
493
494 //_____________________________________________________________________________
495 AliMUONPainterHelper*
496 AliMUONPainterHelper::Instance()
497 {
498   /// Return the global and unique instance of this class
499   
500   if (fgInstance) return fgInstance;
501   
502   AliMUONPainterEnv env;
503   
504   TString fileName(gSystem->ExpandPathName(env.String("PadStoreFileName","$HOME/padstore.root")));
505
506   if ( gSystem->AccessPathName(fileName.Data(),kFileExists) ) // mind the strange return value of that method...   
507   {
508     // file does NOT exist yet. Create it
509     AliDebugClass(1,"Generating instance");
510     
511     Int_t ret;
512     
513     new TGMsgBox(gClient->GetRoot(),gClient->GetRoot(),"",
514                  Form("File %s not found.\nI will generate it, and this will take a while.\n"
515                       "Click OK (and grab a cup of coffee ;-) ) to proceed,\n or Cancel to quit.",fileName.Data()),
516                  kMBIconQuestion,
517                  kMBOk | kMBCancel,
518                  &ret);
519     if ( ret == kMBCancel ) exit(1);
520     
521     fgInstance = new AliMUONPainterHelper;
522     fgInstance->GenerateGeometry();
523     fgInstance->GeneratePadStore();
524     fgInstance->GenerateDefaultMatrices();
525     fgInstance->Modified(kTRUE);
526     fgInstance->fEnv = new AliMUONPainterEnv;
527     fgInstance->fEnv->Set("PadStoreFileName",fileName.Data());
528     fgInstance->Save();
529     
530   }
531   else
532   {
533     AliDebugClass(1,"Reading instance");
534     TFile f(fileName.Data());
535     fgInstance = static_cast<AliMUONPainterHelper*>(f.Get("AliMUONPainterHelper"));
536     
537     TIter next(fgInstance->fPainterMatrices);
538     AliMUONPainterMatrix* matrix;
539     while ( ( matrix = static_cast<AliMUONPainterMatrix*>(next()) ) )
540     {
541       AliMUONPainterRegistry::Instance()->Register(matrix);
542     }
543     fgInstance->fPainterMatrices->SetOwner(kFALSE);
544     fgInstance->fEnv = new AliMUONPainterEnv;
545   }
546   return fgInstance;
547 }
548
549 //_____________________________________________________________________________
550 void 
551 AliMUONPainterHelper::Global2Local(Int_t detElemId, 
552                                     Double_t xg, Double_t yg, Double_t zg,
553                                     Double_t& xl, Double_t& yl, Double_t& zl) const
554 {
555   /// Local to global transformation of coordinates
556   
557   TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fExplodedGlobalTransformations->GetValue(detElemId));
558   Double_t pg[3] = { xg, yg, zg };
559   Double_t pl[3] = { 0., 0., 0. };
560   matrix->MasterToLocal(pg, pl);
561   xl = pl[0];
562   yl = pl[1];
563   zl = pl[2];
564 }
565
566 //_____________________________________________________________________________
567 void 
568 AliMUONPainterHelper::Global2LocalReal(Int_t detElemId, 
569                                        Double_t xg, Double_t yg, Double_t zg,
570                                        Double_t& xl, Double_t& yl, Double_t& zl) const
571 {
572   /// Local to global transformation of coordinates
573   
574   TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fRealGlobalTransformations->GetValue(detElemId));
575   Double_t pg[3] = { xg, yg, zg };
576   Double_t pl[3] = { 0., 0., 0. };
577   matrix->MasterToLocal(pg, pl);
578   xl = pl[0];
579   yl = pl[1];
580   zl = pl[2];
581 }
582
583 //_____________________________________________________________________________
584 void 
585 AliMUONPainterHelper::Local2Global(Int_t detElemId, 
586                                    Double_t xl, Double_t yl, Double_t zl,
587                                    Double_t& xg, Double_t& yg, Double_t& zg) const
588 {
589   /// Local to (exploded) global transformation of coordinates
590   
591   TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fExplodedGlobalTransformations->GetValue(detElemId));
592   Double_t pl[3] = { xl, yl, zl };
593   Double_t pg[3] = { 0., 0., 0. };
594   matrix->LocalToMaster(pl, pg);
595   xg = pg[0];
596   yg = pg[1];
597   zg = pg[2];
598 }
599
600 //_____________________________________________________________________________
601 void 
602 AliMUONPainterHelper::Local2GlobalReal(Int_t detElemId, 
603                                        Double_t xl, Double_t yl, Double_t zl,
604                                        Double_t& xg, Double_t& yg, Double_t& zg) const
605 {
606   /// Local to (real) global transformation of coordinates
607   
608   TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fRealGlobalTransformations->GetValue(detElemId));
609   Double_t pl[3] = { xl, yl, zl };
610   Double_t pg[3] = { 0., 0., 0. };
611   matrix->LocalToMaster(pl, pg);
612   xg = pg[0];
613   yg = pg[1];
614   zg = pg[2];
615 }
616
617 //_____________________________________________________________________________
618 Int_t
619 AliMUONPainterHelper::ColorFromValue(Double_t value, Double_t min, Double_t max) const
620
621   /// Convert a value into a color, fitting within a given range
622   
623   Int_t rv;
624   
625   if (value > max) rv = 1;
626   else if (value <= min) rv = 0;
627   else
628   {
629     if  ( max == min ) return gStyle->GetColorPalette(1);
630     Double_t range = max - min;
631     Double_t offset = value - min;
632     rv = gStyle->GetColorPalette( 1 + int( offset*(gStyle->GetNumberOfColors()-2)/range - 0.5 ) );
633   }
634   return rv;
635 }
636
637 //_____________________________________________________________________________
638 AliMUONPainterContour* 
639 AliMUONPainterHelper::MergeContours(const TObjArray& contours, 
640                                     const char* contourName)
641 {
642   /// Merge a set of contours (delegating to the contour maker)
643   if (!fContourMaker) 
644   {
645     fContourMaker = new AliMUONPainterContourMaker(fExplodedGlobalTransformations);
646   }
647   
648   AliMUONPainterContour* contour = fContourMaker->MergeContours(contours,
649                                                                 contourName);
650   
651   if (contour) 
652   {
653     RegisterContour(contour);
654   }
655   return contour;
656 }
657
658
659 //_____________________________________________________________________________
660 void
661 AliMUONPainterHelper::Print(Option_t* opt) const
662 {
663   /// Printout
664   TString sopt(opt);
665   sopt.ToUpper();
666   
667   if ( sopt.Length() == 0 )
668   {
669     cout << Form("ExplodeFactor=%e,%e",fExplodeFactor[0],fExplodeFactor[1]) << endl;
670     cout << Form("PadStore=%x",fPadStore);
671     if ( fPadStore ) cout << Form(" with %d pads",fPadStore->GetSize());
672     cout << endl;
673     cout << Form("GlobalTransformations=%x",fExplodedGlobalTransformations);
674     if ( fExplodedGlobalTransformations ) cout << Form(" with %d transformations",fExplodedGlobalTransformations->GetSize());
675     cout << endl;
676     if ( fContourMaker ) 
677     {
678       cout << Form(" with %d contours",fContourMaker->Size());
679     }
680     else
681     {
682       cout << "No contour";
683     }
684     cout << endl;
685     cout << "Modified=";
686     if ( IsModified() ) 
687     {
688     cout << "YES";
689   }
690   else
691   {
692     cout << "NO";
693   }
694   cout << endl;
695   }
696   
697   if ( sopt.Contains("CONTOUR") || sopt.Contains("FULL") )
698   {
699     fContourMaker->Print(opt);
700   }
701   
702   if ( sopt.Contains("MATRI") || sopt.Contains("FULL") )
703   {
704     fPainterMatrices->Print(opt);
705   }
706 }
707
708 //_____________________________________________________________________________
709 void
710 AliMUONPainterHelper::RegisterContour(AliMUONPainterContour* contour)
711 {
712   /// contour is adopted by contourMaker
713   AliCodeTimerAuto("")
714   AliDebug(1,contour->GetName());
715   if ( fContourMaker->HasContour(contour->GetName()) ) 
716   {
717     AliError(Form("Contour with name %s is already there",contour->GetName()));
718 //    Print("CONTOUR");
719     return;
720   }
721   fContourMaker->Add(contour);
722   Modified(kTRUE);
723 }
724
725 //_____________________________________________________________________________
726 void
727 AliMUONPainterHelper::Save()
728 {
729   /// Save to disk
730   
731   if (!IsModified()) return;
732
733   Modified(kFALSE);
734
735   AliInfo("");
736
737   fgInstance->Print();
738   
739   fgInstance->Env()->Save();
740   
741   TString fileName(gSystem->ExpandPathName(fgInstance->Env()->String("PadStoreFileName")));
742
743   AliInfo(Form("Saving to %s",fileName.Data()));
744           
745   TFile f(fileName,"RECREATE");
746
747   fgInstance->Write("");
748   
749   f.Close();
750 }
751
752 //_____________________________________________________________________________
753 AliMpPad 
754 AliMUONPainterHelper::PadByExplodedPosition(Int_t detElemId, Int_t manuId, 
755                                             Double_t x, Double_t y) const
756 {
757   /// Find a pad by exploded position. FIXME: not really used nor tested !
758   
759   Double_t xr, yr, zr;
760   
761 //  Local2Global(detElemId,0.0,0.0,0.0,dummy,dummy,z); // to find z 
762
763   AliDebug(1,Form("DE %04d ManuID %04d x %7.3f y %7.3f",detElemId,manuId,x,y));
764   
765   Exploded2Real(detElemId,x,y,0,xr,yr,zr);
766
767   AliDebug(1,Form("xr %7.3f yr %7.3f zr %7.3f",xr,yr,zr));
768
769   Double_t xl,yl,zl;
770
771   Global2LocalReal(detElemId,xr,yr,zr,xl,yl,zl);
772
773   AliDebug(1,Form("xl %7.3f yl %7.3f zl %7.3f",xl,yl,zl));
774
775   const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
776   
777   AliDebug(1,Form("dx,dy=%7.3f,%7.3f",seg->Dimensions().X(),seg->Dimensions().Y()));
778   
779   return seg->PadByPosition(TVector2(xl,yl));
780 }
781
782 //_____________________________________________________________________________
783 void 
784 AliMUONPainterHelper::Exploded2Real(Int_t detElemId, 
785                                     Double_t xe, Double_t ye, Double_t ze, 
786                                     Double_t& xr, Double_t& yr, Double_t& zr) const
787 {
788   /// Convert exploded coordinates into real ones. FIXME: not really used nor tested !
789   
790   // first go back to local
791   
792   Double_t xl,yl,zl;
793   
794   Global2Local(detElemId,xe,ye,ze,xl,yl,zl);
795   
796   // and then back to global but not exploded
797   
798   Local2GlobalReal(detElemId,xl,yl,zl,xr,yr,zr);
799 }
800
801 //_____________________________________________________________________________
802 TString 
803 AliMUONPainterHelper::ChamberName(Int_t chamberId) const
804 {
805   /// Build a name for one chamber
806   return Form("Chamber%1d",chamberId);
807 }
808
809 //_____________________________________________________________________________
810 TString 
811 AliMUONPainterHelper::StationName(Int_t stationId) const
812 {
813   /// Build a name for one station
814   return Form("Station%1d",stationId+1);
815 }
816
817 //_____________________________________________________________________________
818 TString 
819 AliMUONPainterHelper::DEName(Int_t detElemId) const
820 {
821   /// Build a name for one detection element
822   return Form("DE%04d",detElemId);
823 }
824
825 //_____________________________________________________________________________
826 TString 
827 AliMUONPainterHelper::ManuName(Int_t manuId) const
828 {
829   /// Build a name for one manu
830   return Form("MANU%04d",manuId);
831 }
832
833 //_____________________________________________________________________________
834 TString 
835 AliMUONPainterHelper::BusPatchName(Int_t busPatchId) const
836 {
837   /// Build a name for one buspatch
838   return Form("BUSPATCH%04d",busPatchId);
839 }
840
841 //_____________________________________________________________________________
842 TString 
843 AliMUONPainterHelper::PCBName(Int_t pcbNumber) const
844 {
845   /// Build a name for one pcb
846   return Form("PCB%1d",pcbNumber);
847 }
848
849 //_____________________________________________________________________________
850 TString 
851 AliMUONPainterHelper::ChamberPathName(Int_t chamberId) const
852 {
853   /// Build a name for one chamber
854   return Form("%s/%s",StationName(chamberId/2).Data(),ChamberName(chamberId).Data());
855 }
856
857 //_____________________________________________________________________________
858 TString 
859 AliMUONPainterHelper::StationPathName(Int_t stationId) const
860 {
861   /// Build a name for one station
862   return StationName(stationId);
863 }
864
865 //_____________________________________________________________________________
866 TString 
867 AliMUONPainterHelper::DEPathName(Int_t detElemId) const
868 {
869   /// Build a name for one detection element
870   
871   Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
872   
873   return Form("%s/%s/%s",
874               StationName(chamberId/2).Data(),
875               ChamberName(chamberId).Data(),
876               DEName(detElemId).Data());
877 }
878
879 //_____________________________________________________________________________
880 TString 
881 AliMUONPainterHelper::ManuPathName(Int_t detElemId, Int_t manuId) const
882 {
883   /// Build a name for one manu
884   return Form("%s/%s",DEPathName(detElemId).Data(),ManuName(manuId).Data());
885 }
886
887 //_____________________________________________________________________________
888 TString 
889 AliMUONPainterHelper::BusPatchPathName(Int_t busPatchId) const
890 {
891   /// Build a name for one buspatch
892   Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(busPatchId);
893   
894   return Form("%s/%s",DEPathName(detElemId).Data(),BusPatchName(busPatchId).Data());
895 }
896
897 //_____________________________________________________________________________
898 TString 
899 AliMUONPainterHelper::PCBPathName(Int_t detElemId, Int_t pcbNumber) const
900 {
901   /// Build a name for one pcb
902   return Form("%s/%s",DEPathName(detElemId).Data(),PCBName(pcbNumber).Data());
903 }
904
905 //_____________________________________________________________________________
906 TString
907 AliMUONPainterHelper::FormatValue(const char* name, Double_t value) const
908 {
909   /// Format a double value to be displayed
910   /// FIXME: should insure we have the right number of significant digits here...
911   
912   return Form("%s = %e",name,value);
913 }