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