]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONVPainter.cxx
Propagate the modification of the unit of the calibrated charge (fC) to the QA histograms
[u/mrichter/AliRoot.git] / MUON / AliMUONVPainter.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 "AliMUONVPainter.h"
19
20 #include "AliLog.h"
21 #include "AliMUON2DMap.h"
22 #include "AliMUONCalibParamND.h"
23 #include "AliMUONContour.h"
24 #include "AliMUONContourPainter.h"
25 #include "AliMUONObjectPair.h"
26 #include "AliMUONPainterGroup.h"
27 #include "AliMUONPainterHelper.h"
28 #include "AliMUONPainterDataRegistry.h"
29 #include "AliMUONTrackerDataHistogrammer.h"
30 #include "AliMUONVTrackerData.h"
31 #include "AliMpManuUID.h"
32 #include <Riostream.h>
33 #include <TCanvas.h>
34 #include <TClass.h>
35 #include <TClassMenuItem.h>
36 #include <TH1.h>
37 #include <TList.h>
38 #include <TMap.h>
39 #include <TMath.h>
40 #include <TMethodCall.h>
41 #include <TObjArray.h>
42 #include <TObjString.h>
43 #include <TROOT.h>
44 #include <TVirtualPad.h>
45 #include <cassert>
46 #include <float.h>
47
48 /// \class AliMUONVPainter
49 ///
50 /// Base class for a graphical object representing some part of the
51 /// MUON tracking system.
52 /// 
53 /// A painter is a graphical representation of some part (e.g. detection element,
54 /// full chamber, one manu, etc...) of the MUON tracking system.
55 ///
56 /// A painter is a double fold hierarchical structure. 
57 ///
58 /// First, a painter is part of a tree (mother->childrens), that describe
59 /// the natural organization of the spectrometer. For instance, a chamber
60 /// painter has children that are the detection element, the detection elements
61 /// themselves contain manus, which in turn contain channels.
62 ///
63 /// Second, a painter contains a number of "painter groups" (see AliMUONPainterGroup). 
64 /// A group gather all the painters of the same type, 
65 /// where the type is a string identifying which part of system we're dealing
66 /// with (chamber, DE, manu, etc...)
67 ///
68 /// The groups are there to ease the manipulation of similar painters, e.g. if
69 /// we want to hide all detection elements, we hide the "detection element group"
70 /// Some special groups are the responder and the plotter groups. The responder
71 /// group is the group which is currently responding to mouse events. 
72 /// The plotter group is the group which is supposed to represent some data.
73 /// 
74 /// There are two ways to represent the painter on screen. In any case, we can
75 /// outline the painter (i.e. draw its borders) (see AliMUONVPainter::PaintOutline).
76 /// In the cases where the painter is attached to some data source (i.e. it is
77 /// used to represent some data about its type, e.g. the mean charge on some manu),
78 /// we can draw the full area of the contour, using some color (see
79 /// AliMUONVPainter::PaintArea).
80 ///
81 /// Note that you can outline several types of painters (aka groups) at the same
82 /// time, but you cannot plot several groups at the same time.
83 ///
84 /// Painters are TQObject so they can emit signals.
85 ///
86 /// Currently emitted signal are : 
87 ///
88 /// void Clicked(AliMUONVPainter* painter, Double_t*);
89 /// DoubleClicked(AliMUONVPainter* painter, Double_t*);
90 ///
91 /// to know which and where a painter was (double-) clicked.
92 ///
93 /// \author Laurent Aphecetche, Subatech
94
95 ///\cond CLASSIMP
96 ClassImp(AliMUONVPainter)
97 ///\endcond
98
99 //_____________________________________________________________________________
100 AliMUONVPainter::AliMUONVPainter(TRootIOCtor*) : TObject(), 
101 TQObject(),
102 fHistogram(0x0),
103 fName(""),
104 fPathName(""),
105 fType(""),
106 fMother(0x0),
107 fGroup(0x0),
108 fContour(0x0),
109 fPainterGroups(0x0),
110 fChildren(0x0),
111 fResponderGroup(0x0),
112 fPlotterGroup(0x0),
113 fBorderFactor(1.1),
114 fPad(0x0),
115 fAttributes(),
116 fLineColor(1),
117 fLineWidth(1),
118 fIsValid(kTRUE)
119 {
120   /// streamer ctor
121 }
122
123 //_____________________________________________________________________________
124 AliMUONVPainter::AliMUONVPainter(const char* type)
125 : TObject(), 
126   TQObject(),
127   fHistogram(0x0),
128   fName(""),
129   fPathName(""),
130   fType(type),
131   fMother(0x0),
132   fGroup(0x0),
133   fContour(0x0),
134   fPainterGroups(0x0),
135   fChildren(0x0),
136   fResponderGroup(0x0),
137   fPlotterGroup(0x0),
138   fBorderFactor(1.1),
139   fPad(0x0),
140   fAttributes(),
141   fLineColor(1),
142   fLineWidth(1),
143   fIsValid(kTRUE)
144 {
145     /// ctor
146     SetID(-1,-1);
147 }
148
149 //_____________________________________________________________________________
150 AliMUONVPainter::AliMUONVPainter(const AliMUONVPainter& rhs)
151 : TObject(rhs),
152 TQObject(),
153 fHistogram(0x0),
154 fName(""),
155 fPathName(""),
156 fType(""),
157 fMother(0x0),
158 fGroup(0x0),
159 fContour(0x0),
160 fPainterGroups(0x0),
161 fChildren(0x0),
162 fResponderGroup(0x0),
163 fPlotterGroup(0x0),
164 fBorderFactor(1.0),
165 fPad(0x0),
166 fAttributes(),
167 fLineColor(-1),
168 fLineWidth(-1),
169 fIsValid(kTRUE)
170 {
171   /// copy ctor
172   rhs.Copy(*this);
173 }
174
175 //_____________________________________________________________________________
176 AliMUONVPainter& 
177 AliMUONVPainter::operator=(const AliMUONVPainter& rhs)
178 {
179   /// assignment operator
180   if ( this != &rhs ) 
181   {
182     rhs.Copy(*this);
183   }
184   return *this;
185 }
186
187 //_____________________________________________________________________________
188 AliMUONVPainter::~AliMUONVPainter()
189 {
190   /// dtor
191   delete fChildren;
192   delete fHistogram;
193 }
194
195 //_____________________________________________________________________________
196 AliMpArea
197 AliMUONVPainter::Area() const
198 {
199   /// Return the area covered by this painter
200   if ( fContour ) 
201   {
202     return fContour->Area();
203   }
204   else
205   {
206     AliWarning("Returning an invalid area, as contour is not defined");
207     return AliMpArea();
208   }
209 }
210
211 //_____________________________________________________________________________
212 void
213 AliMUONVPainter::Add(AliMUONVPainter* painter)
214 {
215   /// Add a child painter
216   if (!fChildren) fChildren = new TObjArray;
217   assert(painter->Mother()==0x0);
218   fChildren->Add(painter);
219   painter->SetMother(this);
220 }
221
222 //_____________________________________________________________________________
223 TCollection*
224 AliMUONVPainter::Children() const
225 {
226   /// Return the list of childrens
227   return fChildren;
228 }
229
230 //_____________________________________________________________________________
231 void
232 AliMUONVPainter::Clicked(AliMUONVPainter* painter, Double_t* values)
233 {
234   /// Let our mother emit the signal as clients are probably connected to
235   /// our (grand)mother, not to us
236
237   if ( Mother() ) 
238   {
239     Mother()->Clicked(painter,values);
240   }
241   else
242   {
243     Long_t param[] = { (Long_t)painter,(Long_t)values };
244   
245     Emit("Clicked(AliMUONVPainter*,Double_t*)",param);
246   }
247 }
248
249 //_____________________________________________________________________________
250 void
251 AliMUONVPainter::ShiftClicked(AliMUONVPainter* painter, Double_t* values)
252 {
253   /// Let our mother emit the signal as clients are probably connected to
254   /// our (grand)mother, not to us
255   
256   if ( Mother() ) 
257   {
258     Mother()->ShiftClicked(painter,values);
259   }
260   else
261   {
262     Long_t param[] = { (Long_t)painter,(Long_t)values };
263     
264     Emit("ShiftClicked(AliMUONVPainter*,Double_t*)",param);
265   }
266 }
267
268 //_____________________________________________________________________________
269 void
270 AliMUONVPainter::ComputeDataRange(const AliMUONVTrackerData&, Int_t,
271                                   Double_t&, Double_t&) const
272 {
273   /// Should compute the min and max of a given data source
274   AliError("Not implemented. Please fixe me");
275 }
276
277 //_____________________________________________________________________________
278 TString
279 AliMUONVPainter::ContourName() const
280 {
281   /// Default implementation of the contour name.
282   
283   TString name(PathName());
284
285   name += "-";
286   name += fAttributes.Name();
287   
288   return name;
289 }
290
291 //_____________________________________________________________________________
292 void
293 AliMUONVPainter::Copy(TObject& object) const
294 {
295   /// Copy this to object.
296   
297   TObject::Copy(object);
298
299   AliMUONVPainter& painter = static_cast<AliMUONVPainter&>(object);
300
301   painter.fType = fType;
302   painter.fName = fName;
303   painter.fPathName = fPathName;
304   
305   painter.fMother = 0x0;
306   painter.fContour = fContour;
307   
308   painter.fGroup = 0x0;
309   painter.fResponderGroup = 0x0;
310   painter.fPlotterGroup = 0x0;
311   
312   painter.fBorderFactor = fBorderFactor;
313
314   painter.fAttributes = fAttributes;
315   
316   painter.fAttributes.SetCathodeAndPlaneDisabled(kFALSE);
317   
318   painter.fPad = fPad;
319   
320   painter.fLineColor = fLineColor;
321   painter.fLineWidth = fLineWidth;
322   
323   painter.fIsValid = fIsValid;
324   
325   delete painter.fChildren;
326   painter.fChildren = 0x0;
327   
328   painter.fID[0] = fID[0];
329   painter.fID[1] = fID[1];
330   
331   delete painter.fHistogram;
332   painter.fHistogram = 0x0;
333   
334   TIter next(fChildren);
335   AliMUONVPainter* p;
336   
337   while ( ( p = static_cast<AliMUONVPainter*>(next()) ) )
338   {
339     painter.Add(static_cast<AliMUONVPainter*>(p->Clone()));
340   }
341     
342   painter.UpdateGroupsFrom(*this);
343   
344   object.ResetBit(kCanDelete);
345 }
346
347 //_____________________________________________________________________________
348 AliMUONPainterGroup*
349 AliMUONVPainter::CreateGroup(const char* type, Int_t depth)
350 {
351   /// Create a painter group at a given depth
352   
353   if (!fPainterGroups) fPainterGroups = new TMap;
354   TObject* o = fPainterGroups->GetValue(type);
355   if (o)
356   {
357     AliError(Form("Group %s is already there ! Check this",type));
358     return 0x0;
359   }
360   AliMUONPainterGroup* group = new AliMUONPainterGroup(type,depth);
361   fPainterGroups->Add(new TObjString(type),group);
362   return group;
363 }
364
365 //_____________________________________________________________________________
366 void
367 AliMUONVPainter::CreateGroups()
368 {
369   /// Groups our children into groups
370   
371   if ( Mother() ) 
372   {
373     AliFatal("Not supposed to create groups for a children");
374   }
375   
376   TList list;
377   FlatList(list);
378   
379   TIter next(&list);
380   AliMUONVPainter* painter;
381   
382   while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
383   {
384     AliMUONPainterGroup* group = Group(painter->Type());
385     if (!group) 
386     {
387       group = CreateGroup(painter->Type(),painter->Depth());
388     }
389     group->Add(painter);
390   }
391 }
392
393 //_____________________________________________________________________________
394 AliMUONVPainter*
395 AliMUONVPainter::Detach() const
396 {
397   /// Make this a new top painter (i.e. a master)
398   
399   AliDebug(1,Form("Detaching %s",GetName()));
400            
401   AliMUONVPainter* p = static_cast<AliMUONVPainter*>(Clone());
402   
403   AliMUONVPainter* master = Master();
404   
405   if ( master )
406   {
407     AliDebug(1,Form("UpdatingGroups of the detached painter %s from its master %s",
408                     p->GetName(),master->GetName()));
409     p->UpdateGroupsFrom(*master);
410   }
411   
412   return p;
413 }
414
415 //_____________________________________________________________________________
416 Int_t
417 AliMUONVPainter::Depth() const
418 {
419   /// Return our depth in the hierarchy
420   
421   if ( Mother() ) 
422   {
423     return Mother()->Depth() + 1;
424   }
425   else
426   {
427     return 0;
428   }
429 }
430
431 //_____________________________________________________________________________
432 Int_t   
433 AliMUONVPainter::DistancetoPrimitive(Int_t px, Int_t py)
434 {
435   /// See TObject::DistancetoPrimitive
436   
437   static const Int_t kBigValue = 999999;
438
439   if (!gPad) return kBigValue;
440   
441   Double_t x,y;
442   
443   AliMUONVPainter* painter = GetPainter(px,py,x,y);
444   
445   x=y=0.0; // to avoid compiler warning
446   
447   if ( painter == this) return 0;
448   
449   return kBigValue;
450 }
451
452 //_____________________________________________________________________________
453 void
454 AliMUONVPainter::DoubleClicked(AliMUONVPainter*, Double_t*)
455 {
456   /// Should emit the DoubleClicked signal (if I knew how to detect those events...)
457   
458   AliWarning("Please implement me !");
459
460   //  if ( fMother )
461 //  {
462 //    // let our top mother emit the signal as clients are probably connected to
463 //    // our mother, not to us
464 //    Top()->DoubleClicked(painter,values);
465 //  }
466 //  else
467 //  {
468 //    Long_t param[] = { (Long_t)painter,(Long_t)values };
469 //    
470 //    Emit("DoubleClicked(AliMUONVPainter*,Double_t*)",param);
471 //  }
472 }
473
474 //_____________________________________________________________________________
475 void
476 AliMUONVPainter::Draw(Option_t* opt)
477 {
478   /// Append ourselves to the current pad
479   
480   if (!gPad) 
481   {
482     gROOT->MakeDefCanvas();
483   }
484   
485   Bool_t kMustSetRange(kFALSE);
486  
487   TString sopt(opt);
488   sopt.ToUpper();
489  
490   if (sopt.Contains("R") ) kMustSetRange=kTRUE;
491   
492   if (kMustSetRange)
493   {
494     Double_t x1,y1,x2,y2;
495     GetBoundingBox(x1,y1,x2,y2);
496     if ( gPad) gPad->Range(x1,y1,x2,y2);
497   }
498  
499   if ( !fMother && !fPainterGroups ) 
500   {
501     CreateGroups();
502   }
503   
504   TIter next(fChildren);
505   AliMUONVPainter* painter;
506   while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
507   {
508     painter->Draw();
509   }  
510   
511   AppendPad(opt);
512   
513   fPad = gPad;
514 }
515
516 //_____________________________________________________________________________
517 void 
518 AliMUONVPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
519 {
520   /// Handle graphics events
521   
522   Double_t x,y;
523     
524   AliMUONVPainter* painter = GetPainter(px,py,x,y);
525
526   if ( painter == this ) 
527   {
528     Double_t values[] = { x,y };
529   
530     switch (event)
531     {
532       case kButton2Up:
533         ShiftClicked(this,values);
534         break;
535       case kButton1Up:
536         Clicked(this,values);      
537         break;
538       case kButton1Double:
539         //the following statement is required against other loop executions before returning (depending on the time between the clicks) 
540         gPad->GetCanvas()->HandleInput((EEventType)-1,0,0); 
541         DoubleClicked(this,values);
542         break;
543     }
544   }
545 }
546
547 //_____________________________________________________________________________
548 void
549 AliMUONVPainter::FlatList(TList& list)
550 {
551   /// Make a flat list of our children (and ourselves)
552   
553   TIter next(fChildren);
554   AliMUONVPainter* painter;
555   while ( ( painter = static_cast<AliMUONVPainter*>(next())))
556   {
557     painter->FlatList(list);
558   }
559   
560   list.Add(this);
561 }
562
563 //_____________________________________________________________________________
564 void 
565 AliMUONVPainter::GetBoundingBox(Double_t& x1, Double_t& y1, 
566                                 Double_t& x2, Double_t& y2) const
567 {
568   /// Get the bounding box = our area
569   AliMpArea area(Area().GetPositionX(),
570                  Area().GetPositionY(),
571                  Area().GetDimensionX()*fBorderFactor,
572                  Area().GetDimensionY()*fBorderFactor);
573
574   x1 = area.LeftBorder();
575   y1 = area.DownBorder();
576   x2 = area.RightBorder();
577   y2 = area.UpBorder();
578 }
579
580 //_____________________________________________________________________________
581 char*   
582 AliMUONVPainter::GetObjectInfo(Int_t, Int_t) const
583 {
584   /// See TObject::GetObjectInfo
585   return const_cast<char*>(GetName());
586 }
587
588 //_____________________________________________________________________________
589 AliMUONVPainter* 
590 AliMUONVPainter::GetPainter(Int_t px, Int_t py, Double_t& x, Double_t& y) const
591 {
592   /// Get the responder painter at integer position (px,py), and get back its
593   /// absolute position (x,y)
594   
595   PixelToPad(px,py,x,y);
596   
597   if ( !IsInside(x,y) ) return 0x0;
598   
599   if ( fGroup->IsResponder() ) return const_cast<AliMUONVPainter*>(this);
600   
601   if (fChildren)
602   {
603     TIter next(fChildren);
604     AliMUONVPainter* painter;
605     
606     while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
607     {
608       AliMUONVPainter* p = painter->GetPainter(px,py,x,y);
609       if (p) return p;
610     }
611   }  
612   
613   return 0x0;
614 }
615
616 //_____________________________________________________________________________
617 void
618 AliMUONVPainter::GetTypes(TObjArray& types) const
619 {
620   /// Get the list of types (as a TObjArray of TObjString) 
621   /// of our hierarchy, sorted alphabetically
622   
623   types.SetOwner(kTRUE);
624   types.Clear();
625
626   TObjArray tmp;
627   tmp.SetOwner(kFALSE);
628   
629   TIter next(fPainterGroups);
630   
631   TObjString* str;
632   while ( ( str = static_cast<TObjString*>(next()) ) )
633   {
634     AliMUONPainterGroup* group = Group(str->String().Data());
635     tmp.AddLast(group);
636   }
637   
638   tmp.Sort();
639   
640   Int_t n = tmp.GetLast()+1;
641   
642   Int_t* index = new Int_t[n];
643   
644   Int_t* a = new Int_t[n];
645   
646   for ( Int_t i = 0; i < n; ++i )
647   {
648     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(tmp.At(i));
649     a[i] = group->Depth();
650   }
651   
652   TMath::Sort(n,a,index,kFALSE);
653   
654   for ( Int_t i = 0; i < n; ++i ) 
655   {
656     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(tmp.At(index[i]));
657     types.AddLast(new TObjString(group->Type()));
658   }
659   
660   delete[] index;
661   delete[] a;
662 }
663
664 //_____________________________________________________________________________
665 AliMUONPainterGroup*
666 AliMUONVPainter::Group(const char* type) const
667 {
668   /// Returns a group of a given type
669   if (!fPainterGroups) return 0x0;
670   return static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(type));
671 }
672
673 //_____________________________________________________________________________
674 AliMUONPainterGroup*
675 AliMUONVPainter::Group(Int_t depth) const
676 {
677   /// Returns a group of a given depth
678   if (!fPainterGroups) return 0x0;
679   TIter next(fPainterGroups);
680   TObjString* groupName;
681   while ( ( groupName = static_cast<TObjString*>(next()) ) )
682   {
683     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>
684     (fPainterGroups->GetValue(groupName->String().Data()));
685     if ( group->Depth() == depth ) 
686     {
687       return group;
688     }
689   }
690   return 0x0;
691 }
692
693 //_____________________________________________________________________________
694 Bool_t 
695 AliMUONVPainter::IsInside(Double_t x, Double_t y) const
696 {
697   /// Whether point (x,y) is inside our contour
698   if (!fContour) return kFALSE;
699   return fContour->IsInside(x,y);
700 }
701
702 //_____________________________________________________________________________
703 Bool_t 
704 AliMUONVPainter::IsResponder() const
705 {
706   /// Whether we're responding to mouse events
707   return MotherGroup()->IsResponder();
708 }
709
710 //_____________________________________________________________________________
711 AliMUONVPainter*
712 AliMUONVPainter::Master() const
713 {
714   /// Return the top of the hierarchy
715   
716   /// if we get no mother, we are the master
717   
718   if ( Mother() == 0x0 ) return const_cast<AliMUONVPainter*>(this);
719   
720   AliMUONVPainter* p = Mother();
721   
722   while ( p->Mother() )
723   {
724     p = p->Mother();
725   }
726   
727   return p;
728 }
729
730 //_____________________________________________________________________________
731 void
732 AliMUONVPainter::Paint(Option_t*)
733 {
734   /// Paint ourselves of screen
735   /// If we have some data (i.e. we're belonging to the plotter group)
736   /// we use PaintArea.
737   /// And if must be outlined, then we do that too.
738   
739   if ( !MotherGroup()->IsVisible() ) return;
740
741   if ( MotherGroup()->IsPlotter() ) 
742   {
743     PaintArea(*(MotherGroup()->Data()),
744               MotherGroup()->DataIndex(),
745               MotherGroup()->DataMin(),
746               MotherGroup()->DataMax());
747   }
748   
749   if ( MotherGroup()->IsOutlined() )
750   {
751     PaintOutline();
752   }
753   
754   if ( IsExcluded() )
755   {
756     AliMUONContourPainter::Paint(*fContour,1,1,2); // red fill with black thin outline
757   }
758 }
759
760 //_____________________________________________________________________________
761 TString
762 AliMUONVPainter::Describe(const AliMUONVTrackerData&, Int_t, Double_t, Double_t)
763 {
764   /// Default implementation (must be overriden)
765   AliError(Form("%s : implement me",GetName()));
766   return "";
767 }
768
769 //_____________________________________________________________________________
770 void
771 AliMUONVPainter::PaintArea(const AliMUONVTrackerData&, Int_t, Double_t, Double_t)
772 {
773   /// Default implementation (must be overriden)
774   AliError(Form("%s : implement me",GetName()));
775   return;
776 }
777
778 //_____________________________________________________________________________
779 void
780 AliMUONVPainter::PaintOutline(Int_t color, Int_t width, Double_t /*x*/, Double_t /*y*/)
781 {
782   /// Default implementation is simply a drawing of the contour lines,
783   /// not using the optional (x,y)
784   Int_t c = color >= 0 ? color : GetLineColor();
785   Int_t w = width >= 0 ? width : GetLineWidth();
786   
787   AliMUONContourPainter::Paint(*fContour,c,w);
788 }
789
790 //_____________________________________________________________________________
791 void 
792 AliMUONVPainter::PixelToPad(Int_t px, Int_t py, Double_t& x, Double_t& y)
793 {
794   /// convert (px,py) into pad position (x,y)
795   
796   x = gPad->PadtoX(gPad->AbsPixeltoX(px));
797   y = gPad->PadtoY(gPad->AbsPixeltoY(py));
798 }
799
800 //_____________________________________________________________________________
801 void
802 AliMUONVPainter::Print(Option_t* opt) const
803 {
804   /// Printout
805   for ( Int_t i = 0; i < Depth()*4; ++i ) 
806   {
807     cout << " ";
808   }
809   
810   if ( !IsValid() ) cout << "!!!INVALID!!!" << endl;
811   
812   cout << Form("%p Name %s Depth %d ContourName %s ID=(%d,%d)",
813                this,GetName(),Depth(),ContourName().Data(),ID0(),ID1());
814   
815   if ( fResponderGroup )
816   {
817     cout << Form(" Responder group %p %s",fResponderGroup,fResponderGroup->Type());
818   }
819   if ( fPlotterGroup )
820   {
821     cout << Form(" Plotter group %p %s",fPlotterGroup,fPlotterGroup->Type());
822   }
823   if ( Mother() )
824   {
825     cout << Form(" Mother %p %s",Mother(),Mother()->GetName());
826   }
827   if ( MotherGroup() )
828   {
829     cout << Form(" Group %p %s ",MotherGroup(),MotherGroup()->Type());
830   }
831   
832   if ( fChildren ) 
833   {
834     cout << Form(" %d children",fChildren->GetLast()+1);
835   }
836   
837   cout << endl;
838   
839   TString sopt(opt);
840   sopt.ToUpper();
841   
842   if ( fChildren && ( sopt == "FULL" || sopt == "CHILD" ) ) 
843   {
844     TIter next(fChildren);
845     AliMUONVPainter* painter;
846     while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
847     {
848       painter->Print(opt);
849     }
850   }
851   
852   if ( fPainterGroups && ( sopt == "FULL" || sopt == "GROUP" ) )
853   {
854     TIter next(fPainterGroups);
855     TObjString* groupName;
856     while ( ( groupName = static_cast<TObjString*>(next()) ) )
857     {
858       AliMUONPainterGroup* group = Group(groupName->String().Data());
859       group->Print(opt);
860     }
861   }
862 }
863
864 //_____________________________________________________________________________
865 void 
866 AliMUONVPainter::SetAttributes(const AliMUONAttPainter& attributes)
867 {
868   /// Set our attributes  
869   fAttributes = attributes;
870 }
871
872 //_____________________________________________________________________________
873 void 
874 AliMUONVPainter::SetContour(AliMUONContour* contour)
875 {
876   /// Set out contour
877   if (!contour)
878   {
879     AliError(Form("Setting a null contour for painter %s : bad idea !",PathName().Data()));
880   }
881   fContour = contour;
882 }
883
884 //_____________________________________________________________________________
885 void
886 AliMUONVPainter::SetData(const char* pattern, AliMUONVTrackerData* data,
887                          Int_t dataIndex)
888 {
889   /// Tell all painters which type matches pattern that they should
890   /// monitor a given data source
891   
892   if ( !fPainterGroups ) 
893   {
894     CreateGroups();
895   }
896   
897   if ( data ) 
898   {
899     data->Connect("Destroyed()",ClassName(),this,Form("SetData(=\"%s\",0x0,-1)",pattern));
900   }
901   
902   TIter next(fPainterGroups);
903   TObjString* str;
904   
905   fPlotterGroup = 0x0;
906   
907   while ( ( str = static_cast<TObjString*>(next()) ) )
908   {
909     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
910         
911     if ( group->Matches(pattern) )
912     {
913       group->SetData(data,dataIndex);
914       if ( data ) 
915       {        
916         fPlotterGroup = group;
917       }
918     }
919     else
920     {
921       group->SetData(0x0,-1);
922     }
923   }
924   
925   // Update context menus
926   TList list;
927   FlatList(list);
928   
929   TIter pnext(&list);
930   AliMUONVPainter* p;
931   
932   AliMUONPainterGroup* group = Master()->PlotterGroup();
933   
934   while ( ( p = static_cast<AliMUONVPainter*>(pnext()) ) )
935   {
936     TList* l = p->IsA()->GetMenuList();
937   
938     l->Delete();
939   
940     TClassMenuItem* n(0x0);
941     
942     l->Add(new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
943                               "Include","Include",p,"",-1,kTRUE));
944     l->Add(new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
945                               "Exclude","Exclude",p,"",-1,kTRUE));    
946     
947     if ( group )  
948     {
949       if ( data && data->IsHistogrammed(0) ) 
950       {
951         // Add histo drawing to the popup menu
952         TString name("Draw histogram of ");
953         
954         name += data->ExternalDimensionName(0);
955         
956         n = new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
957                                name.Data(),"DrawHistogram0",p,"",-1,kTRUE);
958         l->Add(n);
959         
960         name += " clone";
961         
962         n = new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
963                                name.Data(),"DrawHistogramClone0",p,"",-1,kTRUE);
964         l->Add(n);
965       }
966       
967       Int_t nd = data->IsSingleEvent() ? data->ExternalDimension() : data->ExternalDimension()*2;
968       
969       for ( Int_t i = 0; i < nd; ++i ) 
970       {
971         n = new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
972                                Form("Draw %s clone",data->DimensionName(i).Data()),
973                                Form("DrawInternalHistogramClone%d",i),p,"",-1,kTRUE);
974         l->Add(n);
975       } 
976     }
977   }
978 }
979
980 //_____________________________________________________________________________
981 void
982 AliMUONVPainter::DrawInternalHistogram(Int_t dim) const
983 {
984   /// Draw histogram (and delete the previous one)
985   
986   delete fHistogram;
987   fHistogram = 0x0;
988   
989   DrawInternalHistogramClone(dim);
990 }
991
992 //_____________________________________________________________________________
993 void
994 AliMUONVPainter::DrawInternalHistogramClone(Int_t dim) const
995 {
996   /// Draw histogram 
997   
998   fHistogram = AliMUONTrackerDataHistogrammer::CreateHisto(*this,-1,dim);
999   
1000   if (fHistogram) 
1001   {
1002     new TCanvas();
1003     fHistogram->Draw();
1004   }
1005 }
1006
1007 //_____________________________________________________________________________
1008 void
1009 AliMUONVPainter::DrawHistogram(Double_t* values) const
1010 {
1011   /// Draw histogram (and delete the previous one)
1012
1013   delete fHistogram;
1014   fHistogram = 0x0;
1015   
1016   DrawHistogramClone(values);
1017 }
1018
1019 //_____________________________________________________________________________
1020 void
1021 AliMUONVPainter::DrawHistogramClone(Double_t*) const
1022 {
1023   /// Draw histogram 
1024   
1025   fHistogram = AliMUONTrackerDataHistogrammer::CreateHisto(*this,0,-1);
1026   
1027   if (fHistogram) 
1028   {
1029     new TCanvas();
1030     fHistogram->Draw();
1031   }
1032 }
1033
1034 //_____________________________________________________________________________
1035 void
1036 AliMUONVPainter::FillManuList(TObjArray& manuList) const
1037 {
1038   /// Append to manulist
1039   /// This is the default implementation, which just calls the FillManuList
1040   /// of all our children.
1041   /// Some derived class might need to override this in order to exclude
1042   /// some children from the fill.
1043   
1044   TIter next(Children());
1045   
1046   AliMUONVPainter* p;
1047   
1048   while ( ( p = static_cast<AliMUONVPainter*>(next()) ) )
1049   {
1050     p->FillManuList(manuList);
1051   }
1052 }
1053
1054 //_____________________________________________________________________________
1055 void
1056 AliMUONVPainter::SetLine(Int_t depth, Int_t lineColor, Int_t lineWidth)
1057 {
1058   /// Set the line attributes of painters at a given depth
1059   AliMUONPainterGroup* group = Group(depth);
1060   if ( group )
1061   {
1062     group->SetLine(lineColor,lineWidth);
1063   }
1064 }
1065
1066 //_____________________________________________________________________________
1067 void
1068 AliMUONVPainter::SetMother(AliMUONVPainter* painter)
1069 {
1070   /// Set our mother
1071   fMother = painter;
1072 }
1073
1074 //_____________________________________________________________________________
1075 void
1076 AliMUONVPainter::SetOutlined(const char* pattern, Bool_t flag)
1077 {
1078   /// Decide whether or not painters which type matches pattern 
1079   /// should be outlined
1080   
1081   AliDebug(1,Form("pattern=%s flag=%d",pattern,flag));
1082   
1083   if (!fPainterGroups)
1084   {
1085     CreateGroups();
1086   }
1087   
1088   TIter next(fPainterGroups);
1089   TObjString* str;
1090   
1091   while ( ( str = static_cast<TObjString*>(next()) ) )
1092   {
1093     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1094     if ( group->Matches(pattern) )
1095     {
1096       group->SetOutlined(flag);
1097     }
1098   }
1099 }
1100
1101 //_____________________________________________________________________________
1102 void
1103 AliMUONVPainter::SetResponder(const char* pattern)
1104 {
1105   /// Set the painters matching pattern to be the responder
1106   
1107   AliDebug(1,Form("pattern=%s",pattern));
1108   
1109   if (!fPainterGroups)
1110   {
1111     CreateGroups();
1112   }
1113   
1114   TIter next(fPainterGroups);
1115   TObjString* str;
1116   
1117   fResponderGroup = 0x0;
1118   
1119   while ( ( str = static_cast<TObjString*>(next()) ) )
1120   {
1121     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1122     if ( group->Matches(pattern) )
1123     {
1124       AliDebug(1,Form("group %s is matching pattern %s : setting to responder",
1125                       group->Type(),pattern));
1126       group->SetResponder(kTRUE);
1127       fResponderGroup = group;
1128     }
1129     else
1130     {
1131       group->SetResponder(kFALSE);
1132     }
1133   }
1134 }
1135
1136 //_____________________________________________________________________________
1137 void
1138 AliMUONVPainter::SetResponder(Int_t depth)
1139 {
1140   /// Select as responder the *first* group that has a given depth
1141   
1142   AliDebug(1,Form("depth=%d",depth));
1143   
1144   if (!fPainterGroups)
1145   {
1146     CreateGroups();
1147   }
1148   
1149   TIter next(fPainterGroups);
1150   TObjString* str;
1151   
1152   fResponderGroup = 0x0;
1153   
1154   while ( ( str = static_cast<TObjString*>(next()) ) )
1155   {
1156     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1157     if ( group->Depth() == depth ) 
1158     {
1159       AliDebug(1,Form("group %s has correct depth = %d, using as responder",
1160                       group->Type(),depth));
1161       group->SetResponder(kTRUE);
1162       fResponderGroup = group;
1163       break;
1164     }
1165     else
1166     {
1167       group->SetResponder(kFALSE);
1168     }
1169   }
1170 }
1171
1172 //_____________________________________________________________________________
1173 void
1174 AliMUONVPainter::SetVisible(const char* pattern, Bool_t flag)
1175 {
1176   /// Decide whether the painters matching pattern should be visible or not
1177   AliDebug(1,Form("pattern=%s flag=%d",pattern,flag));
1178   
1179   if (!fPainterGroups)
1180   {
1181     CreateGroups();
1182   }
1183   
1184   TIter next(fPainterGroups);
1185   TObjString* str;
1186   
1187   while ( ( str = static_cast<TObjString*>(next()) ) )
1188   {
1189     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1190     if ( group->Matches(pattern) )
1191     {
1192       group->SetVisible(flag);
1193     }
1194   }
1195 }
1196
1197 //_____________________________________________________________________________
1198 void
1199 AliMUONVPainter::UpdateGroupsFrom(const AliMUONVPainter& painter)
1200 {
1201   /// (re)Create groups
1202   delete fPainterGroups;
1203   fPainterGroups = 0x0;
1204   
1205   CreateGroups();
1206   
1207   // and copy the status of responder, plotter and visible
1208   if ( painter.ResponderGroup() ) 
1209   {
1210     SetResponder(painter.ResponderGroup()->Type());
1211   }
1212   
1213   if ( painter.PlotterGroup() ) 
1214   {
1215     SetData(painter.PlotterGroup()->Type(),
1216             painter.PlotterGroup()->Data(),
1217             painter.PlotterGroup()->DataIndex());
1218     PlotterGroup()->SetDataRange(painter.PlotterGroup()->DataMin(),
1219                                  painter.PlotterGroup()->DataMax());
1220   }
1221   
1222   TObjArray types;
1223   painter.GetTypes(types);
1224   TIter next(&types);
1225   TObjString* groupName;
1226   
1227   while ( ( groupName = static_cast<TObjString*>(next()) ) )
1228   {
1229     AliMUONPainterGroup* group = painter.Group(groupName->String().Data());      
1230     if ( group->IsVisible() ) 
1231     {
1232       SetVisible(group->Type(),kTRUE);
1233     }
1234     else
1235     {
1236       SetVisible(group->Type(),kFALSE);
1237     }
1238
1239     if ( group->IsOutlined() ) 
1240     {
1241       SetOutlined(group->Type(),kTRUE);
1242     }
1243     else
1244     {
1245       SetOutlined(group->Type(),kFALSE);
1246     }
1247     
1248     SetLine(group->Depth(),group->GetLineColor(),group->GetLineWidth());
1249   }
1250   
1251 }
1252
1253 //_____________________________________________________________________________
1254 void
1255 AliMUONVPainter::Include()
1256 {
1257   /// Include this painter
1258   AliInfo(GetName());
1259   
1260   /// Update the global interactive read out configuration  
1261   WriteIROC(1);
1262 }
1263
1264 //_____________________________________________________________________________
1265 void
1266 AliMUONVPainter::GetIROCManuList(TObjArray& manuList)
1267 {
1268   /// Get the list of manus spanned by this painter AND by its dual
1269
1270   FillManuList(manuList);
1271   
1272   // get our dual
1273   AliMUONAttPainter att(Attributes());
1274   
1275   att.Invert();
1276   
1277   att.SetCathodeAndPlaneDisabled(kTRUE);
1278   
1279   AliMUONVPainter* p = AliMUONVPainter::CreatePainter(ClassName(),att,ID0(),ID1());
1280   
1281   if (p)
1282   {
1283     p->FillManuList(manuList);
1284   }
1285   
1286   delete p;
1287 }
1288
1289 //_____________________________________________________________________________
1290 void
1291 AliMUONVPainter::WriteIROC(Double_t value)
1292 {
1293   /// Update the interactive readout configuration
1294   
1295   TObjArray manuList;
1296   GetIROCManuList(manuList);
1297   
1298   AliMpManuUID* muid;
1299   TIter nextm(&manuList);
1300   AliMUON2DMap store(true);
1301   
1302   while ((muid=static_cast<AliMpManuUID*>(nextm())))
1303   {
1304     AliMUONVCalibParam* param = new AliMUONCalibParamND(1,64,
1305                                                         muid->DetElemId(),
1306                                                         muid->ManuId(),value);
1307     store.Add(param);
1308   }
1309   
1310   InteractiveReadOutConfig()->Replace(store);
1311 }
1312
1313 //_____________________________________________________________________________
1314 void
1315 AliMUONVPainter::Exclude()
1316 {
1317   /// Exclude this painter
1318   AliInfo(GetName());
1319   
1320   /// Update the global interactive read out configuration
1321   WriteIROC(0.0);
1322 }
1323
1324 //_____________________________________________________________________________
1325 AliMUONVTrackerData*
1326 AliMUONVPainter::InteractiveReadOutConfig() const
1327 {
1328   /// get the interactive readout config object
1329   return AliMUONPainterDataRegistry::Instance()->InteractiveReadOutConfig();
1330 }
1331
1332 //_____________________________________________________________________________
1333 AliMUONVPainter* 
1334 AliMUONVPainter::CreatePainter(const char* className, 
1335                                const AliMUONAttPainter& att, 
1336                                Int_t id1, Int_t id2)
1337 {
1338   /// Create a painter (factory method)
1339   
1340   TClass* c = TClass::GetClass(className);
1341   
1342   if (!c)
1343   {
1344     AliErrorClass(Form("Cannot get class %s",className));
1345     return 0x0;
1346   }
1347   
1348   Int_t n(0);
1349   
1350   TMethodCall call;
1351   
1352   call.InitWithPrototype(c,className,"AliMUONAttPainter&,Int_t");
1353   
1354   if (call.IsValid()) n = 1;
1355   else
1356   {
1357     call.InitWithPrototype(c,className,"AliMUONAttPainter&,Int_t,Int_t");
1358     
1359     if ( call.IsValid() ) n = 2;
1360   }
1361   
1362   Long_t returnLong(0x0);
1363   
1364   if ( n ==1 ) 
1365   {
1366     Long_t params[] = { (Long_t)(&att), (Long_t)(id1) };
1367     call.SetParamPtrs((void*)(params));
1368     call.Execute((void*)(0x0),returnLong);
1369   }
1370   else if ( n == 2 ) 
1371   {
1372     Long_t params[] = { (Long_t)(&att), (Long_t)(id1), (Long_t)(id2) };
1373     call.SetParamPtrs((void*)(params));
1374     call.Execute((void*)(0x0),returnLong);
1375   }
1376   
1377   if (!returnLong)
1378   {
1379     AliErrorClass(Form("Cannot create a painter of class %s",className));
1380   }
1381   
1382   AliMUONVPainter* rv = reinterpret_cast<AliMUONVPainter*> (returnLong);
1383   
1384   if (!rv->IsValid()) 
1385   {
1386     AliErrorClass(Form("Painter of class %s is not valid",className));
1387     delete rv;
1388     rv = 0x0;
1389   }
1390   return rv;
1391 }
1392
1393 //_____________________________________________________________________________
1394 void
1395 AliMUONVPainter::PaintArea(Int_t fillColor)
1396 {
1397   AliMUONContourPainter::Paint(*(Contour()),-1,-1,fillColor);
1398 }