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