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