First big commit of the mchview program and its accompanying library,
authorivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 17 Jan 2008 15:50:03 +0000 (15:50 +0000)
committerivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Thu, 17 Jan 2008 15:50:03 +0000 (15:50 +0000)
libMUONgraphics.pkg:
- For information about the program, please see READMEmchview.txt
- For information about the new classes, see the classes themselves.
- Adding new program: binmchview.pkg, mchview.cxx;
- Adding new classes (26) in libMUONgraphics
- Adding new READMEmchview.txt file
- In AliMUONDigitMaker: Introducing usage of AliMUONLogger for error messages
- In AliMUONCalibrationData.h: Make CreateObject public
- AliMUONCDB.cxx: In init load ddlstore instead of just segmentation
(Laurent)

87 files changed:
MUON/AliMUONAttPainter.cxx [new file with mode: 0644]
MUON/AliMUONAttPainter.h [new file with mode: 0644]
MUON/AliMUONAttPainterSelectorFrame.cxx [new file with mode: 0644]
MUON/AliMUONAttPainterSelectorFrame.h [new file with mode: 0644]
MUON/AliMUONBusPatchPainter.cxx [new file with mode: 0644]
MUON/AliMUONBusPatchPainter.h [new file with mode: 0644]
MUON/AliMUONCDB.cxx
MUON/AliMUONCalibrationData.h
MUON/AliMUONChamberPainter.cxx [new file with mode: 0644]
MUON/AliMUONChamberPainter.h [new file with mode: 0644]
MUON/AliMUONDEPainter.cxx [new file with mode: 0644]
MUON/AliMUONDEPainter.h [new file with mode: 0644]
MUON/AliMUONDigitMaker.cxx
MUON/AliMUONDigitMaker.h
MUON/AliMUONManuPadPainter.cxx [new file with mode: 0644]
MUON/AliMUONManuPadPainter.h [new file with mode: 0644]
MUON/AliMUONManuPainter.cxx [new file with mode: 0644]
MUON/AliMUONManuPainter.h [new file with mode: 0644]
MUON/AliMUONPCBPainter.cxx [new file with mode: 0644]
MUON/AliMUONPCBPainter.h [new file with mode: 0644]
MUON/AliMUONPainterColorSlider.cxx [new file with mode: 0644]
MUON/AliMUONPainterColorSlider.h [new file with mode: 0644]
MUON/AliMUONPainterContour.cxx [new file with mode: 0644]
MUON/AliMUONPainterContour.h [new file with mode: 0644]
MUON/AliMUONPainterContourMaker.cxx [new file with mode: 0644]
MUON/AliMUONPainterContourMaker.h [new file with mode: 0644]
MUON/AliMUONPainterDataSourceFrame.cxx [new file with mode: 0644]
MUON/AliMUONPainterDataSourceFrame.h [new file with mode: 0644]
MUON/AliMUONPainterDataSourceItem.cxx [new file with mode: 0644]
MUON/AliMUONPainterDataSourceItem.h [new file with mode: 0644]
MUON/AliMUONPainterEnv.cxx [new file with mode: 0644]
MUON/AliMUONPainterEnv.h [new file with mode: 0644]
MUON/AliMUONPainterGroup.cxx [new file with mode: 0644]
MUON/AliMUONPainterGroup.h [new file with mode: 0644]
MUON/AliMUONPainterHelper.cxx [new file with mode: 0644]
MUON/AliMUONPainterHelper.h [new file with mode: 0644]
MUON/AliMUONPainterHighlighter.cxx [new file with mode: 0644]
MUON/AliMUONPainterHighlighter.h [new file with mode: 0644]
MUON/AliMUONPainterInterfaceHelper.cxx [new file with mode: 0644]
MUON/AliMUONPainterInterfaceHelper.h [new file with mode: 0644]
MUON/AliMUONPainterMasterFrame.cxx [new file with mode: 0644]
MUON/AliMUONPainterMasterFrame.h [new file with mode: 0644]
MUON/AliMUONPainterMatrix.cxx [new file with mode: 0644]
MUON/AliMUONPainterMatrix.h [new file with mode: 0644]
MUON/AliMUONPainterMatrixFrame.cxx [new file with mode: 0644]
MUON/AliMUONPainterMatrixFrame.h [new file with mode: 0644]
MUON/AliMUONPainterPadStore.cxx [new file with mode: 0644]
MUON/AliMUONPainterPadStore.h [new file with mode: 0644]
MUON/AliMUONPainterPlotSelector.cxx [new file with mode: 0644]
MUON/AliMUONPainterPlotSelector.h [new file with mode: 0644]
MUON/AliMUONPainterRegistry.cxx [new file with mode: 0644]
MUON/AliMUONPainterRegistry.h [new file with mode: 0644]
MUON/AliMUONTrackerData.cxx [new file with mode: 0644]
MUON/AliMUONTrackerData.h [new file with mode: 0644]
MUON/AliMUONTrackerOCDBDataMaker.cxx [new file with mode: 0644]
MUON/AliMUONTrackerOCDBDataMaker.h [new file with mode: 0644]
MUON/AliMUONTrackerRawDataMaker.cxx [new file with mode: 0644]
MUON/AliMUONTrackerRawDataMaker.h [new file with mode: 0644]
MUON/AliMUONVPainter.cxx [new file with mode: 0644]
MUON/AliMUONVPainter.h [new file with mode: 0644]
MUON/AliMUONVTrackerData.cxx [new file with mode: 0644]
MUON/AliMUONVTrackerData.h [new file with mode: 0644]
MUON/AliMUONVTrackerDataMaker.cxx [new file with mode: 0644]
MUON/AliMUONVTrackerDataMaker.h [new file with mode: 0644]
MUON/Doxymain.h
MUON/Doxymodules.h
MUON/MUONcoreLinkDef.h
MUON/MUONgraphicsLinkDef.h [new file with mode: 0644]
MUON/READMEmchview.txt [new file with mode: 0644]
MUON/binmchview.pkg [new file with mode: 0644]
MUON/libMUONcore.pkg
MUON/libMUONgraphics.pkg [new file with mode: 0644]
MUON/loadlibs.C
MUON/mapping/AliMpDEVisu.h
MUON/mapping/AliMpGraphContext.h
MUON/mapping/AliMpIteratorPainter.h
MUON/mapping/AliMpMotifPainter.h
MUON/mapping/AliMpPCBPainter.h
MUON/mapping/AliMpRowPainter.h
MUON/mapping/AliMpRowSegmentPainter.h
MUON/mapping/AliMpSectorPainter.h
MUON/mapping/AliMpSlatPainter.h
MUON/mapping/AliMpSubZonePainter.h
MUON/mapping/AliMpVPainter.h
MUON/mapping/AliMpZonePainter.h
MUON/mchview.cxx [new file with mode: 0644]
MUON/rootlogon.C

diff --git a/MUON/AliMUONAttPainter.cxx b/MUON/AliMUONAttPainter.cxx
new file mode 100644 (file)
index 0000000..807cff8
--- /dev/null
@@ -0,0 +1,142 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONAttPainter.h"
+
+#include <Riostream.h>
+
+/// \class AliMUONAttPainter
+///
+/// Basic attributes shared by all AliMUONVPainter objects
+///
+/// One basic attribute is "what side" of the detector part we are representing.
+/// Take the example of one full chamber. We can represent it as seen from the
+/// interaction point, i.e. showing all the "cathode0" of all detection elements.
+///
+/// Or we might want to see only the bending (or non bending) planes of all the
+/// detection elements.
+///
+/// This is governed by the SetCathode() and SetPlane() methods (and retrieved
+/// using IsCathodeDefined() and IsPlaneDefined() methods. In the first case
+/// above IsCathodeDefined() would be true and IsPlaneDefined() would be false.
+/// The second case would be the contrary.
+///
+/// \author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONAttPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONAttPainter::AliMUONAttPainter()
+: TObject()
+{
+  /// ctor
+  SetSingle(kTRUE);
+  SetValid(kTRUE);
+  SetCathodeAndPlaneMutuallyExclusive(kFALSE);
+  SetCathodeAndPlaneDisabled(kFALSE);
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainter::~AliMUONAttPainter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONAttPainter::Name() const
+{
+  /// Build our name
+  
+  TString name;
+  
+  if ( !IsValid() ) return "Invalid";
+  
+  if ( CathodeName().Length() > 0 ) name = CathodeName();
+  if ( PlaneName().Length() > 0 ) 
+  {
+    if ( name.Length() > 0 ) name += "-";
+    name += PlaneName();
+  }
+  if ( ViewPointName().Length() > 0 ) 
+  {
+    if ( name.Length() > 0 ) name += "-";
+    name += ViewPointName();
+  }
+  
+  return name;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONAttPainter::CathodeName() const
+{
+  /// Return cathode name in short form
+
+  if ( IsCathode0() && IsCathode1() ) return "Both";
+  else if ( !IsCathode0() && !IsCathode1() ) return "";
+  else if ( IsCathode0() ) return "0";
+  else if ( IsCathode1() ) return "1";
+  return "";
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONAttPainter::PlaneName() const
+{
+  /// Return plane name in short form
+  if ( IsBendingPlane() && IsNonBendingPlane() ) return "Both";
+  else if ( !IsBendingPlane() && !IsNonBendingPlane() ) return "";
+  else if ( IsBendingPlane() ) return "B";
+  else if ( IsNonBendingPlane() ) return "NB";
+  return "";
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONAttPainter::ViewPointName() const
+{
+  /// Return name of view point
+  if ( IsFrontView() ) return "Front";
+  if ( IsBackView() ) return "Back";
+  return "";
+}
+
+//_____________________________________________________________________________
+void
+AliMUONAttPainter::Print(Option_t*) const
+{
+  /// Printout
+  
+  if ( !IsValid() ) cout << "INVALID : ";
+  
+  if ( IsCathodeDefined() ) 
+  {
+    cout << "Cathode-defined " << CathodeName() << ". ";
+  }
+  if ( IsPlaneDefined() ) 
+  {
+    cout << "Plane-defined " << PlaneName() << ". ";
+  }
+  if ( IsCathodeAndPlaneMutuallyExclusive() )
+  {
+    cout << "Cathode and Plane mutually exclusive. ";
+  }
+  cout << ViewPointName() << endl;
+}
diff --git a/MUON/AliMUONAttPainter.h b/MUON/AliMUONAttPainter.h
new file mode 100644 (file)
index 0000000..5dcdb7f
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef ALIMUONATTPAINTER_H
+#define ALIMUONATTPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONAttPainter
+/// \brief Basic attributes shared by all painters
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+#ifndef ROOT_TString
+#  include "TString.h"
+#endif
+
+class AliMUONAttPainter : public TObject
+{
+public:
+  
+  enum EBits {
+    kIsCathode0         = BIT(14),
+    kIsCathode1         = BIT(15),
+    kIsBendingPlane     = BIT(16),
+    kIsNonBendingPlane  = BIT(17),
+    kIsFrontView        = BIT(18),
+    kIsBackView         = BIT(19),
+    kIsCathodeAndPlaneMutuallyExclusive = BIT(20),
+    kIsValid            = BIT(21),
+    kIsSinglePainter    = BIT(22),
+    kIsCathodeAndPlaneDisabled = BIT(23)
+  };
+  
+  AliMUONAttPainter();
+  virtual ~AliMUONAttPainter();
+  
+  /// Return our name
+  virtual const char* GetName() const { return Name(); }
+  
+  TString Name() const;
+  
+  TString CathodeName() const;
+  
+  TString ViewPointName() const;
+
+  TString PlaneName() const;
+  
+  /// Whether cathode & plane are disabled
+  Bool_t IsCathodeAndPlaneDisabled() const { return TestBit(kIsCathodeAndPlaneDisabled); }
+  
+  /// Whether we are representing bending plane
+  Bool_t IsBendingPlane() const { return TestBit(kIsBendingPlane); }
+  
+  /// Whether we are representing cathode 0
+  Bool_t IsCathode0() const { return TestBit(kIsCathode0); }
+  
+  /// Whether we are representing cathode 1
+  Bool_t IsCathode1() const { return TestBit(kIsCathode1); }
+  
+  /// Whether we can select both cathode and plane
+  Bool_t IsCathodeAndPlaneMutuallyExclusive() const { return TestBit(kIsCathodeAndPlaneMutuallyExclusive); }
+  
+  /// Whether we are defined by cathode
+  Bool_t IsCathodeDefined() const { return IsCathode0() || IsCathode1(); }
+  
+  /// Whether we are representing non bending plane
+  Bool_t IsNonBendingPlane() const { return TestBit(kIsNonBendingPlane); }
+  
+  /// Whether we are defined by plane
+  Bool_t IsPlaneDefined() const { return IsBendingPlane() || IsNonBendingPlane(); }
+  
+  /// Whether we are valid
+  Bool_t IsValid() const { return TestBit(kIsValid); }
+  
+  /// Set our cathode states
+  void SetCathode(Bool_t cath0, Bool_t cath1) { SetBit(kIsCathode0,cath0); SetBit(kIsCathode1,cath1); }
+  
+  /// Set our plane states
+  void SetPlane(Bool_t bending, Bool_t nonBending) { SetBit(kIsBendingPlane,bending); SetBit(kIsNonBendingPlane,nonBending); }
+  
+  /// Set single status
+  void SetSingle(Bool_t value) { SetBit(kIsSinglePainter,value); }
+  
+  /// Whether the painter is to be represented from front (as seen from IP)
+  Bool_t IsFrontView() const { return TestBit(kIsFrontView); }
+  
+  /// Whether the painter is to be represented from back (as seen from IP)
+  Bool_t IsBackView() const { return TestBit(kIsBackView); }
+  
+  /// Set view point
+  void SetViewPoint(Bool_t front, Bool_t back) { SetBit(kIsFrontView,front); SetBit(kIsBackView,back); }
+  
+  /// Set mutually exclusive flag
+  void SetCathodeAndPlaneMutuallyExclusive(Bool_t value) { SetBit(kIsCathodeAndPlaneMutuallyExclusive,value); }
+  
+  /// Set valid flag
+  void SetValid(Bool_t value) { SetBit(kIsValid,value); }
+  
+  /// Whether we represent attributes of a single painter (if false, means it's a painter group)
+  Bool_t IsSinglePainter() const { return TestBit(kIsSinglePainter); }
+  
+  /// Set cathode & plane disable flag
+  void SetCathodeAndPlaneDisabled(Bool_t value) { SetBit(kIsCathodeAndPlaneDisabled,value); }
+
+  void Print(Option_t* opt="") const;
+  
+  ClassDef(AliMUONAttPainter,1) // Basic attributes of painters
+};
+
+#endif
diff --git a/MUON/AliMUONAttPainterSelectorFrame.cxx b/MUON/AliMUONAttPainterSelectorFrame.cxx
new file mode 100644 (file)
index 0000000..ef00732
--- /dev/null
@@ -0,0 +1,206 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+///\class AliMUONAttPainterSelectorFrame
+///
+/// Widget to select painter view type
+///
+///\author Laurent Aphecetche, Subatech
+
+#include "AliMUONAttPainterSelectorFrame.h"
+
+#include "AliMUONAttPainter.h"
+#include "AliMUONPainterInterfaceHelper.h"
+#include "AliLog.h"
+#include <TGButton.h>
+#include <TGButtonGroup.h>
+
+///\cond CLASSIMP
+ClassImp(AliMUONAttPainterSelectorFrame)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONAttPainterSelectorFrame::AliMUONAttPainterSelectorFrame(TGWindow* p, UInt_t w, UInt_t h)
+: TGHorizontalFrame(p,w,h),
+fCathode(0x0),
+fPlane(0x0),
+fViewPoint(0x0),
+fAttributes()
+{
+  /// ctor
+  
+  fCathode = new TGButtonGroup(this,"Cathode",kHorizontalFrame);
+
+  fAttributes.SetCathode(kTRUE,kFALSE);
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fCathode,fAttributes.CathodeName(),(void*)(10));
+  fAttributes.SetCathode(kFALSE,kTRUE);
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fCathode,fAttributes.CathodeName(),(void*)(1));
+                                                
+  fPlane = new TGButtonGroup(this,"Plane",kHorizontalFrame);
+  
+  fAttributes.SetPlane(kTRUE,kFALSE);
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fPlane,fAttributes.PlaneName(),(void*)(10));
+  fAttributes.SetPlane(kFALSE,kTRUE);
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fPlane,fAttributes.PlaneName(),(void*)(1));
+
+  fViewPoint = new TGButtonGroup(this,"ViewPoint",kHorizontalFrame);
+
+  fAttributes.SetViewPoint(kTRUE,kFALSE);
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fViewPoint,fAttributes.ViewPointName(),(void*)(10));
+  fAttributes.SetViewPoint(kFALSE,kTRUE);
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fViewPoint,fAttributes.ViewPointName(),(void*)(1));
+
+  fViewPoint->SetState(kFALSE); //FIXME: until we're sure back views are handled correctly
+  
+  AddFrame(fCathode);
+  AddFrame(fPlane);
+  AddFrame(fViewPoint);
+  
+  fCathode->Connect("Clicked(Int_t)","AliMUONAttPainterSelectorFrame",this,"CathodeClicked(Int_t)");
+  fPlane->Connect("Clicked(Int_t)","AliMUONAttPainterSelectorFrame",this,"PlaneClicked(Int_t)");
+  fViewPoint->Connect("Clicked(Int_t)","AliMUONAttPainterSelectorFrame",this,"ViewClicked(Int_t)");
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainterSelectorFrame::~AliMUONAttPainterSelectorFrame()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONAttPainterSelectorFrame::CathodeClicked(Int_t buttonId)
+{
+  /// Cathode button clicked
+  
+  fAttributes.SetPlane(kFALSE,kFALSE);
+
+  TGButton* button = fCathode->GetButton(buttonId);
+  
+  Int_t i = (Int_t)(button->GetUserData());
+  
+  if ( i == 10 ) 
+  {
+    fAttributes.SetCathode(kTRUE,kFALSE);
+  }
+  else if ( i == 1 ) 
+  {
+    fAttributes.SetCathode(kFALSE,kTRUE);
+  }
+  else
+  {
+    AliFatal("");
+  }
+  
+  Clicked(&fAttributes);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONAttPainterSelectorFrame::PlaneClicked(Int_t buttonId)
+{
+  /// Plane button clicked
+  
+  fAttributes.SetCathode(kFALSE,kFALSE);
+  
+  TGButton* button = fPlane->GetButton(buttonId);
+  
+  Int_t i = (Int_t)(button->GetUserData());
+  
+  if ( i == 10 ) 
+  {
+    fAttributes.SetPlane(kTRUE,kFALSE);
+  }
+  else if ( i == 1 ) 
+  {
+    fAttributes.SetPlane(kFALSE,kTRUE);
+  }
+  else
+  {
+    AliFatal("");
+  }
+  
+  Clicked(&fAttributes);
+  
+}
+
+//_____________________________________________________________________________
+void
+AliMUONAttPainterSelectorFrame::ViewClicked(Int_t buttonId)
+{
+  /// View button clicked
+
+  TGButton* button = fViewPoint->GetButton(buttonId);
+  
+  Int_t i = (Int_t)(button->GetUserData());
+  
+  if ( i == 10 ) 
+  {
+    fAttributes.SetViewPoint(kTRUE,kFALSE);
+  }
+  else if ( i == 1 ) 
+  {
+    fAttributes.SetViewPoint(kFALSE,kTRUE);
+  }
+  else
+  {
+    AliFatal("");
+  }
+  
+  Clicked(&fAttributes);
+  
+}
+
+//_____________________________________________________________________________
+void
+AliMUONAttPainterSelectorFrame::Clicked(AliMUONAttPainter* newValues)
+{
+  /// Emit a signal
+  
+  Long_t params[] = { (Long_t)newValues };
+  
+  Emit("Clicked(AliMUONAttPainter*)",params);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONAttPainterSelectorFrame::Update(const AliMUONAttPainter& att)
+{
+  /// Update button state from the painter attributes
+
+  AliMUONPainterInterfaceHelper::Unselect(*fCathode,"*");
+  AliMUONPainterInterfaceHelper::Unselect(*fPlane,"*");
+  AliMUONPainterInterfaceHelper::Unselect(*fViewPoint,"*");
+
+  fAttributes = att;
+  
+  fCathode->SetState(!fAttributes.IsCathodeAndPlaneDisabled());
+  fPlane->SetState(!fAttributes.IsCathodeAndPlaneDisabled());
+
+  if ( fAttributes.IsCathodeDefined() ) 
+  {
+    AliMUONPainterInterfaceHelper::Select(*fCathode,fAttributes.CathodeName());
+  }
+  
+  if ( fAttributes.IsPlaneDefined() ) 
+  {
+    AliMUONPainterInterfaceHelper::Select(*fPlane,fAttributes.PlaneName());
+  }
+  
+  AliMUONPainterInterfaceHelper::Select(*fViewPoint,fAttributes.ViewPointName());
+  
+}
diff --git a/MUON/AliMUONAttPainterSelectorFrame.h b/MUON/AliMUONAttPainterSelectorFrame.h
new file mode 100644 (file)
index 0000000..124e48a
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef ALIMUONATTPAINTERSELECTORFRAME_H
+#define ALIMUONATTPAINTERSELECTORFRAME_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONAttPainterSelectorFrame
+/// \brief Widget to select the painter(s) view type
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TGFrame
+#  include "TGFrame.h"
+#endif
+#ifndef ROOT_RQ_OBJECT
+#   include <RQ_OBJECT.h>
+#endif
+#ifndef ALIMUONATTPAINTER_H
+#  include "AliMUONAttPainter.h"
+#endif
+
+class TGButtonGroup;
+
+class AliMUONAttPainterSelectorFrame : public TGHorizontalFrame
+{
+  RQ_OBJECT("AliMUONAttPainterSelectorFrame")
+  
+public:
+  AliMUONAttPainterSelectorFrame(TGWindow* p=0x0, UInt_t w=1, UInt_t h=1);
+  virtual ~AliMUONAttPainterSelectorFrame();
+  
+  void Update(const AliMUONAttPainter& att);
+  
+  void Clicked(AliMUONAttPainter* newValues); // *SIGNAL*
+  
+  void CathodeClicked(Int_t buttonId);
+  
+  void PlaneClicked(Int_t buttonId);
+  
+  void ViewClicked(Int_t buttonId);
+  
+private:
+  /// Not implemented
+  AliMUONAttPainterSelectorFrame(const AliMUONAttPainterSelectorFrame& rhs);
+  /// Not implemented
+  AliMUONAttPainterSelectorFrame& operator=(const AliMUONAttPainterSelectorFrame& rhs);
+  
+private:
+  
+  TGButtonGroup* fCathode; ///< cathode selection buttons
+  TGButtonGroup* fPlane;   ///< plane selection buttons
+  TGButtonGroup* fViewPoint; ///< viewpoint selection buttons
+  
+  AliMUONAttPainter fAttributes; ///< attributes
+  
+  ClassDef(AliMUONAttPainterSelectorFrame,1) // Widget to select painter view type
+};
+
+#endif
diff --git a/MUON/AliMUONBusPatchPainter.cxx b/MUON/AliMUONBusPatchPainter.cxx
new file mode 100644 (file)
index 0000000..5c85ba2
--- /dev/null
@@ -0,0 +1,289 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONBusPatchPainter.h"
+
+#include "AliMUONManuPainter.h"
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMpBusPatch.h"
+#include "AliMpConstants.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEManager.h"
+#include "AliMpPlaneType.h"
+#include "AliLog.h"
+#include <TObjArray.h>
+#include <TString.h>
+#include <float.h>
+
+/// \class AliMUONBusPatchPainter
+///
+/// Painter for one bus patch. Actually possibly for only part of one
+/// buspatch (the part that is on the plane/cathode requested when
+/// creating the painter)
+///
+/// \author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONBusPatchPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONBusPatchPainter::AliMUONBusPatchPainter()
+: AliMUONVPainter(),
+fBusPatchId(-1)
+{
+  /// default ctor
+}
+
+//_____________________________________________________________________________
+AliMUONBusPatchPainter::AliMUONBusPatchPainter(const AliMUONAttPainter& att, 
+                                               Int_t busPatchId)
+: AliMUONVPainter("BUSPATCH"),
+fBusPatchId(busPatchId)
+{
+  /// normal ctor
+  /// WARNING : the construction of this object can fail.
+  /// You MUST check the IsValid() method afterwards (real world would
+  /// be to use exception, but well, whether we should use exceptions
+  /// in aliroot is still unclear to me.
+  
+  SetAttributes(Validate(att));
+  
+  AliMp::PlaneType planeType = ( Attributes().IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+
+  Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(busPatchId);
+
+  AliMUONPainterHelper* h = AliMUONPainterHelper::Instance();
+  
+  SetID(busPatchId,-1);
+  SetName(h->BusPatchName(busPatchId));
+  SetPathName(h->BusPatchPathName(busPatchId));
+  
+  AliMpBusPatch* busPatch = AliMpDDLStore::Instance()->GetBusPatch(fBusPatchId);
+  
+  Int_t mask = AliMpConstants::ManuMask(AliMp::kNonBendingPlane);
+  
+  AliMUONPainterContour* bpContour = h->GetContour(ContourName());
+  
+  AliDebug(1,Form("BusPatchId %04d bending %d DE %4d bpContour(%s)=%p nofManus=%d",
+                  fBusPatchId,att.IsBendingPlane(),detElemId,ContourName().Data(),bpContour,busPatch->GetNofManus()));
+  
+  Double_t xmin(FLT_MAX), ymin(FLT_MAX), xmax(-FLT_MAX), ymax(-FLT_MAX);
+  
+  TObjArray contours;
+  
+  Int_t nmanus(0);
+  
+  for ( Int_t i = 0; i < busPatch->GetNofManus(); ++i ) 
+  {
+    Int_t manuId = busPatch->GetManuId(i);
+    
+    Bool_t correctPlane(kTRUE);
+    
+    if ( planeType == AliMp::kNonBendingPlane ) 
+    {
+      if ( ( manuId & mask ) == 0 ) correctPlane = kFALSE;
+    }
+    else
+    {
+      if ( ( manuId & mask ) == mask ) correctPlane = kFALSE;
+    }
+
+    AliDebug(1,Form("Adding Manu %04d to BusPatch %04d (DE %04d) "
+                    "manu & mask = %d correctPlane %d planeType %s",
+                    manuId,fBusPatchId,busPatch->GetDEId(),
+                    (manuId & mask),correctPlane,AliMp::PlaneTypeName(planeType).Data()));
+        
+    if (!correctPlane) continue;
+    
+    ++nmanus;
+    
+    AliMUONVPainter* painter = new AliMUONManuPainter(Attributes(),
+                                                      busPatch->GetDEId(),
+                                                      manuId);
+    
+    Add(painter);
+    
+    const AliMpArea& area = painter->Area();
+    
+    xmin = TMath::Min(xmin,\varea.LeftBorder());
+    ymin = TMath::Min(ymin,area.DownBorder());
+    xmax = TMath::Max(xmax,area.RightBorder());
+    ymax = TMath::Max(ymax,area.UpBorder());
+    
+    if (!bpContour)
+    {
+      contours.Add(painter->Contour());
+    }
+  }
+  
+  if ( !nmanus )
+  {
+    Invalidate();
+    return;
+  }
+    
+  if (!bpContour)
+  {
+    AliDebug(1,Form("Creating contour %s",ContourName().Data()));
+    bpContour = h->MergeContours(contours,ContourName());
+    if (!bpContour)
+    {
+      AliError("Could not merge those contours");
+      StdoutToAliError(contours.Print(););
+    }
+  }
+  
+  SetContour(bpContour);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONBusPatchPainter::ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                         Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Compute the data range spanned by this bus patch (on this cathode or plane)
+  dataMin = dataMax = data.BusPatch(fBusPatchId, dataIndex);
+}
+
+//_____________________________________________________________________________
+AliMUONBusPatchPainter::AliMUONBusPatchPainter(const AliMUONBusPatchPainter& rhs)
+: AliMUONVPainter(rhs), fBusPatchId(-1)
+{
+  /// Copy ctor
+  rhs.Copy(*this);
+}
+
+//_____________________________________________________________________________
+AliMUONBusPatchPainter&
+AliMUONBusPatchPainter::operator=(const AliMUONBusPatchPainter& rhs)
+{
+  /// Assignment operator
+  if ( this != &rhs ) 
+  {
+    rhs.Copy(*this);
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONBusPatchPainter::~AliMUONBusPatchPainter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONBusPatchPainter::Copy(TObject& object) const
+{
+  /// Copy this to object
+  AliMUONVPainter::Copy((AliMUONVPainter&)(object));
+  ((AliMUONBusPatchPainter&)(object)).fBusPatchId = fBusPatchId;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONBusPatchPainter::Describe(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                 Double_t, Double_t)
+{
+  /// Text about data
+  
+  if (!data.HasBusPatch(fBusPatchId)) return "";
+  
+  Double_t value = data.BusPatch(fBusPatchId,dataIndex);
+  
+  return AliMUONPainterHelper::Instance()->FormatValue(data.DimensionName(dataIndex).Data(),value);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONBusPatchPainter::PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                                  Double_t min, Double_t max)
+{
+  /// Paint area of this buspatch according to the data
+  
+  if (!data.HasBusPatch(fBusPatchId)) return;
+  
+  Double_t value = data.BusPatch(fBusPatchId,dataIndex);
+  
+  if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return;
+  
+  Int_t color = AliMUONPainterHelper::Instance()->ColorFromValue(value,min,max);
+  
+  Contour()->PaintArea(color);
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainter 
+AliMUONBusPatchPainter::Validate(const AliMUONAttPainter& attributes) const
+{
+  /// Normalize attributes
+  
+  // we invalidate the attributes, if we have no manu in the requested plane
+  // and we cross-check that both cathode and plane are up-to-date
+  
+  AliMUONAttPainter norm(attributes);
+  
+  Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(fBusPatchId);
+
+  if (!norm.IsValid()) return norm;
+  
+  if ( !norm.IsCathodeDefined() )
+  {
+    AliMp::PlaneType planeType = ( norm.IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+  
+    AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,planeType);
+    
+    Bool_t cath0 = ( cathodeType == AliMp::kCath0 );
+    
+    norm.SetCathode(cath0,!cath0);
+  }
+  else if ( !norm.IsPlaneDefined() )
+  {
+    AliMp::CathodType cathodeType = ( norm.IsCathode0() ? AliMp::kCath0 : AliMp::kCath1 );
+    
+    AliMp::PlaneType planeType = AliMpDEManager::GetPlaneType(detElemId,cathodeType);
+    
+    Bool_t bending = ( planeType == AliMp::kBendingPlane );
+
+    norm.SetPlane(bending,!bending);    
+  }
+  
+  AliMpBusPatch* busPatch = AliMpDDLStore::Instance()->GetBusPatch(fBusPatchId);
+  
+  Int_t mask = AliMpConstants::ManuMask(AliMp::kNonBendingPlane);
+  
+  Int_t nb(0);
+  Int_t b(0);
+  
+  for ( Int_t i = 0; i < busPatch->GetNofManus(); ++i ) 
+  {
+    Int_t manuId = busPatch->GetManuId(i);
+    
+    if ( manuId & mask  ) ++nb;
+    else ++b;
+  }
+  
+  if ( norm.IsBendingPlane() && !b ) norm.SetValid(kFALSE);
+  if ( norm.IsNonBendingPlane() && !nb ) norm.SetValid(kFALSE);
+  
+  return norm;
+}
+
diff --git a/MUON/AliMUONBusPatchPainter.h b/MUON/AliMUONBusPatchPainter.h
new file mode 100644 (file)
index 0000000..2c9b888
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef ALIMUONBUSPATCHPAINTER_H
+#define ALIMUONBUSPATCHPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONBusPatchPainter
+/// \brief A painter for one buspatch
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef AliMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+#ifndef ALI_MP_PLANE_TYPE_H
+#  include "AliMpPlaneType.h"
+#endif
+
+class AliMUONBusPatchPainter : public AliMUONVPainter
+{
+public:
+  
+  AliMUONBusPatchPainter();
+  AliMUONBusPatchPainter(const AliMUONAttPainter& att, Int_t busPatchId);
+  AliMUONBusPatchPainter(const AliMUONBusPatchPainter& rhs);
+  AliMUONBusPatchPainter& operator=(const AliMUONBusPatchPainter& rhs);
+  virtual ~AliMUONBusPatchPainter();
+  
+  /// Clone ourselves
+  virtual TObject* Clone(const char* = "") const { return new AliMUONBusPatchPainter(*this); }
+  
+  void ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                        Double_t& dataMin, Double_t& dataMax) const;
+    
+  virtual void Copy(TObject& object) const;
+  
+  void PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                 Double_t min, Double_t max);
+    
+  TString Describe(const AliMUONVTrackerData& data, Int_t, 
+                   Double_t x = FLT_MAX, Double_t y = FLT_MAX);
+
+  virtual AliMUONAttPainter Validate(const AliMUONAttPainter& attributes) const;
+
+private:
+  Int_t fBusPatchId; ///< our identifier
+  
+  ClassDef(AliMUONBusPatchPainter,1) // Painter for one buspatch
+};
+
+#endif
index d14074f..96b75b7 100644 (file)
@@ -165,7 +165,7 @@ AliMUONCDB::AliMUONCDB(const char* cdbpath)
 {
   /// ctor
     // Load mapping
-    if ( ! AliMpCDB::LoadMpSegmentation() ) {
+    if ( ! AliMpCDB::LoadDDLStore() ) {
       AliFatal("Could not access mapping from OCDB !");
     }
 }
@@ -675,7 +675,7 @@ AliMUONCDB::MakeLocalTriggerMaskStore(AliMUONVStore& localBoardMasks) const
   Int_t ngenerated(0);
   // Generate fake mask values for 234 localboards and put that into
   // one single container (localBoardMasks)
-  for ( Int_t i = 1; i <= 234; ++i )
+  for ( Int_t i = 1; i <= AliMpConstants::TotalNofLocalBoards(); ++i )
   {
     AliMUONVCalibParam* localBoard = new AliMUONCalibParamNI(1,8,i,0,0);
     for ( Int_t x = 0; x < 2; ++x )
index 03a2c85..6dc4681 100644 (file)
@@ -110,6 +110,8 @@ public:
   AliMUONTriggerEfficiencyCells* TriggerEfficiency() const;
   
   void Reset();
+
+  static TObject* CreateObject(Int_t runNumber, const char* path);
   
 protected:
   /// Not implemented
@@ -117,10 +119,6 @@ protected:
   /// Not implemented
   AliMUONCalibrationData& operator=(const AliMUONCalibrationData& other);
   
-private:  
-    
-  static TObject* CreateObject(Int_t runNumber, const char* path);
-  
 private:
   mutable Bool_t fIsValid; ///<  Whether we were able to correctly initialize
   Int_t fRunNumber; ///<  The run number for which we hold calibrations
diff --git a/MUON/AliMUONChamberPainter.cxx b/MUON/AliMUONChamberPainter.cxx
new file mode 100644 (file)
index 0000000..652c8cc
--- /dev/null
@@ -0,0 +1,238 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONChamberPainter.h"
+
+#include "AliMUONDEPainter.h"
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMpConstants.h"
+#include "AliMpDEIterator.h"
+#include "AliMpDEManager.h"
+#include "AliMpPlaneType.h"
+#include "AliMpSegmentation.h"
+#include "AliMpStationType.h"
+#include "AliMpVSegmentation.h"
+#include "AliMUONObjectPair.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TObjString.h>
+#include <TArrayI.h>
+#include <cassert>
+#include <float.h>
+
+/// \class AliMUONChamberPainter
+///
+/// Painter for one plane/cathode of one chamber
+///
+/// \author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONChamberPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONChamberPainter::AliMUONChamberPainter()
+: AliMUONVPainter(),
+fChamberId(-1)
+{
+  /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONChamberPainter::AliMUONChamberPainter(const AliMUONAttPainter& att, 
+                                             Int_t chamberId)
+: AliMUONVPainter("Chamber"),
+fChamberId(chamberId)
+{
+  /// ctor
+
+  AliMUONPainterHelper* h = AliMUONPainterHelper::Instance(); // to be sure mapping is loaded...
+
+  AliMUONAttPainter chAtt(att);
+  
+  chAtt.SetCathodeAndPlaneMutuallyExclusive(kTRUE);
+  
+  SetAttributes(chAtt);
+  
+  SetID(chamberId,-1);
+  SetName(h->ChamberName(fChamberId).Data());
+  SetPathName(h->ChamberPathName(fChamberId).Data());
+              
+  AliMpDEIterator deIt;
+  
+  deIt.First(fChamberId);
+  
+  AliMUONPainterContour* contour = h->GetContour(ContourName());
+  TObjArray contourArray;
+  
+  while (!deIt.IsDone())
+  {
+    Int_t detElemId = deIt.CurrentDEId();
+
+    AliMUONAttPainter deAtt(att);
+    
+    if ( att.IsCathodeDefined() ) 
+    {
+      deAtt.SetCathode(kFALSE,kFALSE);
+      AliMp::PlaneType planeType;
+      
+      if ( att.IsCathode0() ) planeType = AliMpDEManager::GetPlaneType(detElemId,AliMp::kCath0);
+      else planeType = AliMpDEManager::GetPlaneType(detElemId,AliMp::kCath1);
+      
+      Bool_t bending = ( planeType == AliMp::kBendingPlane );
+      
+      deAtt.SetPlane(bending,!bending);
+    }
+    
+    assert(deAtt.IsPlaneDefined());
+    
+    AliMUONVPainter* painter = new AliMUONDEPainter(deAtt,detElemId);
+
+    Add(painter);
+    
+    if (!contour)
+    {
+      contourArray.Add(painter->Contour());
+    }
+    
+    deIt.Next();
+  }
+  
+  Double_t xmin(1E9), xmax(-1E9), ymin(1E9), ymax(-1E9);
+  TIter next(Children());
+  AliMUONVPainter* painter;
+  
+  while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
+  {
+    const AliMpArea& area = painter->Area();
+    xmin = TMath::Min(xmin,area.LeftBorder());
+    xmax = TMath::Max(xmax,area.RightBorder());
+    ymin = TMath::Min(ymin,area.DownBorder());
+    ymax = TMath::Max(ymax,area.UpBorder());
+  }
+  
+  if ( contourArray.GetLast() >= 0 ) 
+  {
+    contour = h->MergeContours(contourArray,ContourName());
+  }
+  
+  SetContour(contour);    
+}
+
+//_____________________________________________________________________________
+AliMUONChamberPainter::AliMUONChamberPainter(const AliMUONChamberPainter& rhs)
+: AliMUONVPainter(rhs),
+fChamberId(rhs.fChamberId)
+{
+  /// copy ctor
+  rhs.Copy(*this);
+}
+
+//_____________________________________________________________________________
+AliMUONChamberPainter&
+AliMUONChamberPainter::operator=(const AliMUONChamberPainter& rhs)
+{
+  /// assignment operator
+  if ( this != &rhs )
+  {
+    rhs.Copy(*this);
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONChamberPainter::~AliMUONChamberPainter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONChamberPainter::ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                        Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Compute data range spanned by this (plane of that) chamber
+  dataMin = dataMax = data.Chamber(fChamberId, dataIndex);
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONChamberPainter::Copy(TObject& object) const
+{
+  /// Copy this to object
+  AliMUONVPainter::Copy((AliMUONVPainter&)(object));
+  ((AliMUONChamberPainter&)(object)).fChamberId = fChamberId;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONChamberPainter::Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                           Double_t, Double_t)
+{
+  /// Describe data at this chamber
+  
+  if (!data.HasChamber(fChamberId)) return "";
+  
+  Double_t value = data.Chamber(fChamberId,dataIndex);
+  
+  return AliMUONPainterHelper::Instance()->FormatValue(data.DimensionName(dataIndex).Data(),value);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONChamberPainter::PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                                 Double_t min, Double_t max)
+{
+  /// Paint area of this chamber according to data
+  
+  if (!data.HasChamber(fChamberId)) return;
+  
+  Double_t value = data.Chamber(fChamberId,dataIndex);
+  
+  if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return;
+  
+  Int_t color = AliMUONPainterHelper::Instance()->ColorFromValue(value,min,max);
+  
+  Contour()->PaintArea(color);
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainter 
+AliMUONChamberPainter::Validate(const AliMUONAttPainter& attributes) const
+{
+  /// Normalize attributes
+  
+  AliMUONAttPainter norm(attributes);
+  
+  // A chamber painter must be either cathode defined or plane defined
+  
+  if ( norm.IsCathodeDefined() && norm.IsPlaneDefined() ) 
+  {
+    norm.SetValid(kFALSE);
+  }
+
+  if ( !norm.IsCathodeDefined() && !norm.IsPlaneDefined() ) 
+  {
+    norm.SetValid(kFALSE);
+  }
+  
+  return norm;
+}
diff --git a/MUON/AliMUONChamberPainter.h b/MUON/AliMUONChamberPainter.h
new file mode 100644 (file)
index 0000000..e65df20
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef ALIMUONCHAMBERPAINTER_H
+#define ALIMUONCHAMBERPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONChamberPainter
+/// \brief Painter for one (plane of one) chamber
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+#ifndef ALI_MP_CATHOD_TYPE_H
+#  include "AliMpCathodType.h"
+#endif
+#ifndef ALI_MP_PLANE_TYPE_H
+#  include "AliMpPlaneType.h"
+#endif
+
+class AliMUONChamberPainter : public AliMUONVPainter
+{
+public:
+  AliMUONChamberPainter();
+  AliMUONChamberPainter(const AliMUONAttPainter& att, Int_t chamberId);
+  AliMUONChamberPainter(const AliMUONChamberPainter& rhs);
+  AliMUONChamberPainter& operator=(const AliMUONChamberPainter& rhs);
+  
+  virtual ~AliMUONChamberPainter();
+
+  void ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                        Double_t& dataMin, Double_t& dataMax) const;
+    
+  /// Clone ourselves
+  virtual TObject* Clone(const char* = "") const { return new AliMUONChamberPainter(*this); }
+
+  virtual void Copy(TObject& object) const;
+  
+  void PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                 Double_t min, Double_t max);
+    
+  TString Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                   Double_t, Double_t);
+    
+  AliMUONAttPainter Validate(const AliMUONAttPainter& attributes) const;
+
+private:
+  Int_t fChamberId; ///< our identifier (0..n)
+  
+  ClassDef(AliMUONChamberPainter,1) // Painter for one chamber
+};
+
+#endif
diff --git a/MUON/AliMUONDEPainter.cxx b/MUON/AliMUONDEPainter.cxx
new file mode 100644 (file)
index 0000000..6c9f68d
--- /dev/null
@@ -0,0 +1,303 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONDEPainter.h"
+
+#include "AliMUONBusPatchPainter.h"
+#include "AliMUONGeometryTransformer.h"
+#include "AliMUONPCBPainter.h"
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMUONObjectPair.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEManager.h"
+#include "AliMpDetElement.h"
+#include "AliMpPCB.h"
+#include "AliMpSector.h"
+#include "AliMpSlat.h"
+#include "AliLog.h"
+#include <TObjString.h>
+
+/// \class AliMUONDEPainter
+///
+/// Painter for one detection element
+///
+/// It draws a given plane (bending or non bending) of a given detection element
+///
+/// \author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONDEPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONDEPainter::AliMUONDEPainter()
+: AliMUONVPainter(),
+fDetElemId(-1)
+{
+  /// default ctor
+}
+
+//_____________________________________________________________________________
+AliMUONDEPainter::AliMUONDEPainter(const AliMUONAttPainter& att, Int_t detElemId)
+: AliMUONVPainter("DE"),
+fDetElemId(detElemId)
+{
+  /// normal ctor
+
+  AliMUONAttPainter deAtt(att);
+  
+  if ( att.IsCathodeDefined() )
+  {
+    AliMp::CathodType cathodType = ( att.IsCathode0() ? AliMp::kCath0 : AliMp::kCath1 ) ;
+    
+    Bool_t cath0 = ( cathodType == AliMp::kCath0 ) ;
+    
+    AliMp::PlaneType planeType = AliMpDEManager::GetPlaneType(detElemId,cathodType);
+    
+    Bool_t bending = (  planeType == AliMp::kBendingPlane );
+    
+    deAtt.SetCathode(cath0,!cath0);
+    deAtt.SetPlane(bending,!bending);
+
+  }
+  
+  if ( att.IsPlaneDefined() ) 
+  {  
+    AliMp::PlaneType planeType = ( att.IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+  
+    Bool_t bending = ( planeType == AliMp::kBendingPlane );
+  
+    Bool_t cath0 = ( AliMpDEManager::GetCathod(detElemId,planeType) == AliMp::kCath0 );
+    
+    deAtt.SetCathode(cath0,!cath0);
+    deAtt.SetPlane(bending,!bending);
+
+  }
+  
+  deAtt.SetCathodeAndPlaneMutuallyExclusive(kFALSE);
+                                            
+  SetAttributes(deAtt);
+  
+  AliMUONPainterHelper* h = AliMUONPainterHelper::Instance();
+  
+  SetID(detElemId,-1);
+  SetName(h->DEName(fDetElemId).Data());
+  SetPathName(h->DEPathName(fDetElemId).Data());
+              
+  AliMp::PlaneType planeType = ( Attributes().IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+  
+  Double_t x,y,z;
+  
+  if ( AliMpDEManager::GetStationType(DetElemId()) == AliMp::kStation345 ) 
+  {
+    const AliMpSlat* slat = h->GetSlat(DetElemId(),planeType);
+  
+    for ( Int_t i = 0; i < slat->GetSize(); ++i ) 
+    {
+      Add(new AliMUONPCBPainter(Attributes(),DetElemId(),i));
+    }
+    
+    AliMUONPainterHelper::Instance()->Local2Global(fDetElemId,0.0,0.0,0.0,x,y,z);    
+  }
+  else if ( AliMpDEManager::GetStationType(DetElemId()) != AliMp::kStationTrigger )
+  {
+    const AliMpSector* sector = h->GetSector(DetElemId(),planeType);
+
+    Double_t xl(sector->Dimensions().X());
+    Double_t yl(sector->Dimensions().Y());
+    
+    h->Local2Global(fDetElemId,xl,yl,0.0,x,y,z);
+  }
+  else
+  {
+    AliFatal("Not implemented for trigger !!!");
+  }
+  
+  AliMUONPainterContour* contour = h->GetContour(ContourName());
+  
+  TObjArray contourArray;
+    
+  AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(fDetElemId);
+  
+  AliDebug(1,Form("de %p n %d",de,de->GetNofBusPatches()));
+  
+  for ( Int_t i = 0; i < de->GetNofBusPatches(); ++i ) 
+  {
+    AliMUONBusPatchPainter* painter = new AliMUONBusPatchPainter(Attributes(),de->GetBusPatchId(i));
+                                                                 
+    if ( !painter->IsValid() ) 
+    {
+      AliDebug(1,Form("Skipping BP %d which seem to have no manu in plane %s",
+                   de->GetBusPatchId(i),
+                   Attributes().IsBendingPlane() ? "bending" : "non bending"));
+      delete painter;
+      continue;
+    }
+    else
+    {
+      Add(painter);
+    }
+    
+    if ( !contour ) 
+    {
+      contourArray.Add(painter->Contour());
+    }
+  }
+  
+  if (!contour)
+  {
+    contour = h->MergeContours(contourArray,ContourName());
+    if (!contour)
+    {
+      AliError(Form("%s : could not merge those contours",Name().Data()));
+      StdoutToAliError(contourArray.Print(););
+    }
+  }
+  
+  SetContour(contour);  
+}
+
+//_____________________________________________________________________________
+AliMUONDEPainter::AliMUONDEPainter(const AliMUONDEPainter& rhs):
+AliMUONVPainter(rhs), fDetElemId(-1)
+{
+  /// copy ctor
+  rhs.Copy(*this);
+}
+
+//_____________________________________________________________________________
+AliMUONDEPainter& 
+AliMUONDEPainter::operator=(const AliMUONDEPainter& rhs)
+{
+  /// assignment operator
+  if ( this != &rhs ) 
+  {
+    rhs.Copy(*this);
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONDEPainter::~AliMUONDEPainter()
+{
+  /// dtor = nop
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONDEPainter::ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                         Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Compute the data range spanned by this detection element
+  dataMin = dataMax = data.DetectionElement(fDetElemId, dataIndex);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONDEPainter::Copy(TObject& object) const
+{
+  /// Copy this to object
+  AliMUONVPainter::Copy((AliMUONVPainter&)(object));
+  ((AliMUONDEPainter&)(object)).fDetElemId = fDetElemId;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONDEPainter::Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                             Double_t, Double_t)
+{
+  /// Describe data at this detection element
+  
+  if (!data.HasDetectionElement(fDetElemId)) return "";
+  
+  Double_t value = data.DetectionElement(fDetElemId,dataIndex);
+  
+  return AliMUONPainterHelper::Instance()->FormatValue(data.DimensionName(dataIndex).Data(),value);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONDEPainter::PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                                  Double_t min, Double_t max)
+{
+  /// Paint the area of this detection element
+  
+  if (!data.HasDetectionElement(fDetElemId)) return;
+  
+  Double_t value = data.DetectionElement(fDetElemId,dataIndex);
+  
+  if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return;
+  
+  Int_t color = AliMUONPainterHelper::Instance()->ColorFromValue(value,min,max);
+  
+  Contour()->PaintArea(color);
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainter 
+AliMUONDEPainter::Validate(const AliMUONAttPainter& attributes) const
+{
+  /// Normalize attributes
+  
+  AliMUONAttPainter norm(attributes);
+  
+  norm.SetCathodeAndPlaneMutuallyExclusive(kFALSE);
+  
+  if ( norm.IsCathodeDefined() && !norm.IsPlaneDefined() )
+  {
+    // only cathode known : derive the plane
+    
+    AliMp::CathodType cathodType = ( norm.IsCathode0() ? AliMp::kCath0 : AliMp::kCath1 );
+    
+    AliMp::PlaneType planeType = AliMpDEManager::GetPlaneType(fDetElemId,cathodType);
+
+    Bool_t bending = ( planeType == AliMp::kBendingPlane ) ;
+    
+    norm.SetPlane(bending,!bending);
+  }
+  
+  else if ( !norm.IsCathodeDefined() && norm.IsPlaneDefined() )
+  {
+    // only plane is known : derive the cathode
+    
+    AliMp::PlaneType planeType = ( norm.IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+        
+    Bool_t cath0 = ( AliMpDEManager::GetCathod(fDetElemId,planeType) == AliMp::kCath0 );
+    
+    norm.SetCathode(cath0,!cath0);
+  }  
+  else    
+  {
+    // check that both information are compatible
+    
+    AliMp::PlaneType planeType = ( norm.IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+
+    AliMp::CathodType cathode = AliMpDEManager::GetCathod(fDetElemId,planeType);
+    
+    if ( cathode == AliMp::kCath0 && norm.IsCathode1() ||
+         cathode == AliMp::kCath1 && norm.IsCathode0() ) 
+    {
+      norm.SetValid(kFALSE);
+    }
+  }
+  
+  return norm;
+}
+
diff --git a/MUON/AliMUONDEPainter.h b/MUON/AliMUONDEPainter.h
new file mode 100644 (file)
index 0000000..9e8aad4
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef ALIMUONDEPAINTER_H
+#define ALIMUONDEPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONDEPainter
+/// \brief A painter for one detection element
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+
+class AliMUONDEPainter : public AliMUONVPainter
+{
+public:
+  AliMUONDEPainter();
+  AliMUONDEPainter(const AliMUONAttPainter& att, Int_t detElemId);
+  AliMUONDEPainter(const AliMUONDEPainter& rhs);
+  AliMUONDEPainter& operator=(const AliMUONDEPainter& rhs);
+  virtual ~AliMUONDEPainter();
+  
+  /// Clone this object
+  virtual TObject* Clone(const char* = "") const { return new AliMUONDEPainter(*this); }
+
+  void ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                        Double_t& dataMin, Double_t& dataMax) const;
+    
+  void Copy(TObject& object) const;
+  
+  /// Return the ID of this detection element
+  Int_t DetElemId() const { return fDetElemId; }
+  
+  void PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                 Double_t min, Double_t max);
+    
+  TString Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                   Double_t, Double_t);
+    
+  virtual AliMUONAttPainter Validate(const AliMUONAttPainter& attributes) const;
+
+private:
+  Int_t fDetElemId; ///< our id
+
+  ClassDef(AliMUONDEPainter,1) // Detection element painter
+};
+
+#endif
index 11fc98c..a218fd3 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "AliMUONDigitMaker.h"
 
+#include "AliCodeTimer.h"
 #include "AliLog.h"
 #include "AliMUONDDLTrigger.h"
 #include "AliMUONDarcHeader.h"
@@ -52,6 +53,7 @@
 #include "AliMUONGlobalTrigger.h"
 #include "AliMUONLocalStruct.h"
 #include "AliMUONLocalTrigger.h"
+#include "AliMUONLogger.h"
 #include "AliMUONRawStreamTracker.h"
 #include "AliMUONRawStreamTrackerHP.h"
 #include "AliMUONRawStreamTrigger.h"
@@ -80,11 +82,9 @@ AliMUONDigitMaker::AliMUONDigitMaker(Bool_t enableErrorLogger, Bool_t useFastDec
     fMakeTriggerDigits(kFALSE),
     fRawStreamTracker(NULL),
     fRawStreamTrigger(new AliMUONRawStreamTrigger()),    
-    fTrackerTimer(),
-    fTriggerTimer(),
-    fMappingTimer(),
     fDigitStore(0x0),
-    fTriggerStore(0x0)
+    fTriggerStore(0x0),
+  fLogger(new AliMUONLogger(10000))
 {
   /// ctor 
 
@@ -98,10 +98,6 @@ AliMUONDigitMaker::AliMUONDigitMaker(Bool_t enableErrorLogger, Bool_t useFastDec
     fRawStreamTrigger->EnabbleErrorLogger();
   }
 
-  fTrackerTimer.Start(kTRUE); fTrackerTimer.Stop();
-  fTriggerTimer.Start(kTRUE); fTriggerTimer.Stop();
-  fMappingTimer.Start(kTRUE); fMappingTimer.Stop();
-  
   SetMakeTriggerDigits();
 
 }
@@ -115,14 +111,7 @@ AliMUONDigitMaker::~AliMUONDigitMaker()
   delete fRawStreamTracker;
   delete fRawStreamTrigger;
 
-  AliDebug(1, Form("Execution time for MUON tracker : R:%.2fs C:%.2fs",
-               fTrackerTimer.RealTime(),fTrackerTimer.CpuTime()));
-  AliDebug(1, Form("   Execution time for MUON tracker (mapping calls part) "
-               ": R:%.2fs C:%.2fs",
-               fMappingTimer.RealTime(),fMappingTimer.CpuTime()));
-  AliDebug(1, Form("Execution time for MUON trigger : R:%.2fs C:%.2fs",
-               fTriggerTimer.RealTime(),fTriggerTimer.CpuTime()));
-
+  delete fLogger;
 }
 
 //__________________________________________________________________________
@@ -156,7 +145,7 @@ Int_t AliMUONDigitMaker::Raw2Digits(AliRawReader* rawReader,
   
   if (!fDigitStore && !fTriggerStore)
   {
-    AliError("No digit or trigger store given. Nothing to do...");
+    fLogger->Log("No digit or trigger store given. Nothing to do...");
     return kFALSE;
   }
   
@@ -171,7 +160,7 @@ Int_t AliMUONDigitMaker::Raw2Digits(AliRawReader* rawReader,
     if ( fTriggerStore ) fTriggerStore->Clear();
     if ( fMakeTriggerDigits && !fDigitStore ) 
     {
-      AliError("Asking for trigger digits but digitStore is null");
+      fLogger->Log("Asking for trigger digits but digitStore is null");
     }
     else
     {
@@ -190,7 +179,7 @@ Int_t AliMUONDigitMaker::ReadTrackerDDL(AliRawReader* rawReader)
 
   AliDebug(1,"");
   
-  fTrackerTimer.Start(kFALSE);
+  AliCodeTimerAuto("");
 
   // elex info
   Int_t    buspatchId;
@@ -210,6 +199,12 @@ Int_t AliMUONDigitMaker::ReadTrackerDDL(AliRawReader* rawReader)
       = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId, 
                                                                       manuId);  
 
+    if (!seg)
+    {
+      fLogger->Log(Form("(DE,MANUID)=(%04d,%04d) is not valid",detElemId,manuId));
+      continue;
+    }
+    
     AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId, 
                                                               seg->PlaneType());
 
@@ -217,7 +212,7 @@ Int_t AliMUONDigitMaker::ReadTrackerDDL(AliRawReader* rawReader)
     
     if (!pad.IsValid())
     {
-      AliError(Form("No pad for detElemId: %d, manuId: %d, channelId: %d",
+      fLogger->Log(Form("No pad for detElemId: %d, manuId: %d, channelId: %d",
                     detElemId, manuId, channelId));
       continue;
     } 
@@ -226,7 +221,7 @@ Int_t AliMUONDigitMaker::ReadTrackerDDL(AliRawReader* rawReader)
                                             AliMUONVDigitStore::kDeny);
     if (!digit)
     {
-      AliError(Form("Digit DE %04d Manu %04d Channel %02d could not be added",
+      fLogger->Log(Form("Digit DE %04d Manu %04d Channel %02d could not be added",
                     detElemId, manuId, channelId));
       continue;
     }
@@ -238,8 +233,6 @@ Int_t AliMUONDigitMaker::ReadTrackerDDL(AliRawReader* rawReader)
 
   }
   
-  fTrackerTimer.Stop();
-
   return kTRUE;
 }
 
@@ -258,7 +251,7 @@ Int_t AliMUONDigitMaker::ReadTriggerDDL(AliRawReader* rawReader)
 
   Int_t loCircuit;
 
-  fTriggerTimer.Start(kFALSE);
+  AliCodeTimerAuto("");
 
   fRawStreamTrigger->SetReader(rawReader);
 
@@ -289,7 +282,7 @@ Int_t AliMUONDigitMaker::ReadTriggerDDL(AliRawReader* rawReader)
                                 GetTriggerCrate(fRawStreamTrigger->GetDDL(), iReg);
       
       if (!crate) 
-        AliWarning(Form("Missing crate number %d in DDL %d\n", iReg, fRawStreamTrigger->GetDDL()));
+        fLogger->Log(Form("Missing crate number %d in DDL %d\n", iReg, fRawStreamTrigger->GetDDL()));
      
       
       regHeader =  darcHeader->GetRegHeaderEntry(iReg);
@@ -336,8 +329,6 @@ Int_t AliMUONDigitMaker::ReadTriggerDDL(AliRawReader* rawReader)
     } // iReg
   } // NextDDL
   
-  fTriggerTimer.Stop();
-
   return kTRUE;
 
 }
@@ -349,6 +340,8 @@ Int_t AliMUONDigitMaker::TriggerDigits(Int_t nBoard,
 {
   /// make digits for trigger from pattern, and add them to digitStore
 
+  AliCodeTimerAuto("");
+  
   Int_t detElemId;
 
   AliMpLocalBoard* localBoard = AliMpDDLStore::Instance()->GetLocalBoard(nBoard);
@@ -383,7 +376,7 @@ Int_t AliMUONDigitMaker::TriggerDigits(Int_t nBoard,
                         
             if (!pad.IsValid()) 
             {
-              AliWarning(Form("No pad for detElemId: %d, nboard %d, ibitxy: %d\n",
+              fLogger->Log(Form("No pad for detElemId: %d, nboard %d, ibitxy: %d\n",
                               detElemId, nBoard, ibitxy));
               continue;
             }
index 6daeefd..eb2272c 100644 (file)
@@ -12,7 +12,6 @@
 //  Author: Ch, Finck
 
 #include <TObject.h>
-#include "TStopwatch.h"
 
 class TArrayS;
 
@@ -25,6 +24,8 @@ class AliMUONRawStreamTrigger;
 class AliMUONVDigitStore;
 class AliMUONVTriggerStore;
 
+class AliMUONLogger;
+
 class AliMUONDigitMaker : public TObject 
 {
  public:
@@ -66,14 +67,12 @@ private:
   AliMUONVRawStreamTracker* fRawStreamTracker; //!< pointer of raw stream for tracker
   AliMUONRawStreamTrigger* fRawStreamTrigger;  //!< pointer of raw stream for trigger
 
-  TStopwatch fTrackerTimer;                    //!< time watcher for tracker part
-  TStopwatch fTriggerTimer;                    //!< time watcher for trigger part
-  TStopwatch fMappingTimer;                    //!< time watcher for mapping-tracker part
-
   AliMUONVDigitStore* fDigitStore; //!< not owner
   AliMUONVTriggerStore* fTriggerStore; //!< not owner
 
-  ClassDef(AliMUONDigitMaker,5) // MUON digit maker from rawdata
+  AliMUONLogger* fLogger; //!< to log messages
+  
+  ClassDef(AliMUONDigitMaker,6) // MUON digit maker from rawdata
 };
        
 #endif
diff --git a/MUON/AliMUONManuPadPainter.cxx b/MUON/AliMUONManuPadPainter.cxx
new file mode 100644 (file)
index 0000000..aaaff20
--- /dev/null
@@ -0,0 +1,324 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONManuPadPainter.h"
+
+#include "AliMUONPainterHelper.h"
+#include "AliMUONPainterPadStore.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVDigit.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMpConnection.h"
+#include "AliMpConstants.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDetElement.h"
+#include "AliMpPad.h"
+#include "AliMpSegmentation.h"
+#include "AliMpVSegmentation.h"
+#include "AliLog.h"
+#include <float.h>
+#include <TVirtualPad.h>
+#include <TVirtualX.h>
+
+///\class AliMUONManuPadPainter
+///
+/// Painter for the pads of one manu
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONManuPadPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONManuPadPainter::AliMUONManuPadPainter()
+: AliMUONVPainter(), 
+fDetElemId(-1), 
+fManuId(-1),
+fLineColorBck(-1),
+fLineWidthBck(-1),
+fFillColorBck(-1),
+fFillStyleBck(-1)
+{
+  /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONManuPadPainter::AliMUONManuPadPainter(const AliMUONVPainter& mother,
+                                             Int_t detElemId,
+                                             Int_t manuId)
+: AliMUONVPainter("PAD"),
+fDetElemId(detElemId),
+fManuId(manuId),
+fLineColorBck(-1),
+fLineWidthBck(-1),
+fFillColorBck(-1),
+fFillStyleBck(-1)
+{
+  /// ctor
+  SetID(detElemId,manuId);
+  SetName(Form("%s/PAD",mother.GetName()));
+  SetPathName(Form("%s/PAD",mother.PathName().Data()));
+  SetContour(mother.Contour());
+}
+
+//_____________________________________________________________________________
+AliMUONManuPadPainter::~AliMUONManuPadPainter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONManuPadPainter::BackupStyle()
+{
+  /// Remember line and fill style values
+  
+  fFillStyleBck = gVirtualX->GetFillStyle();
+  fFillColorBck = gVirtualX->GetFillColor();
+  fLineColorBck = gVirtualX->GetLineColor();
+  fLineWidthBck = gVirtualX->GetLineWidth();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONManuPadPainter::ComputeDataRange(const AliMUONVTrackerData& data,
+                                        Int_t dataIndex,
+                                        Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Compute data range spanned by this manu pads
+  AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(fDetElemId);
+  
+  dataMin = FLT_MAX;
+  dataMax = -FLT_MAX;
+  
+  for ( Int_t manuChannel = 0; manuChannel < AliMpConstants::ManuNofChannels(); 
+        ++manuChannel )
+  {
+    if ( de->IsConnectedChannel(fManuId,manuChannel) )
+    {
+      Double_t value = data.Channel(fDetElemId, fManuId, manuChannel, dataIndex);
+      dataMin = TMath::Min(value,dataMin);
+      dataMax = TMath::Max(value,dataMax);
+    }
+  }
+}
+
+//_____________________________________________________________________________
+char* 
+AliMUONManuPadPainter::GetObjectInfo(Int_t px, Int_t py) const
+{
+  /// Get object info
+  return const_cast<char*>(Form("%s:%d:%d",GetName(),px,py));
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONManuPadPainter::NameAtPosition(Double_t x, Double_t y) const
+{
+  /// Specific name, dependent on the position within this painter
+  
+  TString name("invalid");
+
+  AliMpPad pad = PadByPosition(x,y);
+  
+  if ( pad.IsValid() )
+  {  
+    name = Form("%s%d",PathName().Data(),pad.GetLocation().GetSecond());
+  }
+  
+  return name;
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONManuPadPainter::Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                                Double_t x, Double_t y)
+{
+  /// Describe data at given location
+  
+  if ( ! data.HasManu(fDetElemId,fManuId) ) return "";
+
+  AliMpPad pad = PadByPosition(x,y);
+  
+  if ( pad.IsValid() ) 
+  {
+    Double_t value = data.Channel(fDetElemId,fManuId,pad.GetLocation().GetSecond(),dataIndex);
+  
+    return AliMUONPainterHelper::Instance()->FormatValue(data.DimensionName(dataIndex).Data(),value);
+  }
+  else
+  {
+    return "invalid";
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONManuPadPainter::PaintArea(const AliMUONVTrackerData& data,
+                                 Int_t dataIndex,
+                                 Double_t min,
+                                 Double_t max)
+{
+    /// Paint area of this manu pads according to the data
+  
+  if ( !gPad ) return;
+  
+  if ( ! data.HasManu(fDetElemId,fManuId) ) return;
+  
+  AliMUONPainterHelper* h = AliMUONPainterHelper::Instance();
+  
+  BackupStyle();
+  
+  Int_t cathode = h->GetCathodeType(fDetElemId,fManuId);
+  
+  gVirtualX->SetLineColor(-1);
+  gVirtualX->SetFillStyle(1);
+  
+  for ( Int_t i = 0; i < AliMpConstants::ManuNofChannels(); ++i ) 
+  {    
+    Int_t id = AliMUONVDigit::BuildUniqueID(fDetElemId,fManuId,i,cathode);
+    
+    TVector2 position;
+    TVector2 dimensions;
+    
+    h->PadStore().GetPadGeometry(id,position,dimensions);
+    
+    if ( dimensions.X() > 0 ) 
+    {
+      Double_t value = data.Channel(fDetElemId,fManuId,i,dataIndex);
+      
+      if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) continue;
+      
+      Int_t color = h->ColorFromValue(value,min,max);
+      
+      if ( value > 0 )
+      {
+        AliDebug(1,Form("DE %d manuId %d channel %d value %e min %e max %e color %d",
+                        fDetElemId,fManuId,i,value,min,max,
+                        color));
+      }
+      
+      gVirtualX->SetFillColor(color);
+      
+      TVector2 bl(position-dimensions);
+      TVector2 ur(position+dimensions);
+      
+      gPad->PaintBox(bl.X(),bl.Y(),ur.X(),ur.Y());
+    }
+  }
+  
+  RestoreStyle();
+}
+                      
+//_____________________________________________________________________________
+void
+AliMUONManuPadPainter::PaintPad(Int_t padId) const
+{
+  /// Paint a single pad
+  
+  TVector2 position;
+  TVector2 dimensions;
+
+  AliMUONPainterHelper::Instance()->PadStore().GetPadGeometry(padId,position,dimensions);
+
+  if ( dimensions.X() > 0 ) 
+  {
+    TVector2 bl(position-dimensions);
+    TVector2 ur(position+dimensions);    
+  
+    gPad->PaintBox(bl.X(),bl.Y(),ur.X(),ur.Y());
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONManuPadPainter::PaintOutline(Int_t color, Int_t, Double_t x, Double_t y)
+{
+  /// Paint the outline of our pads
+
+  if ( !gPad ) return;
+  
+  Int_t lineColor = color >= 0 ? color : GetLineColor();
+  
+  AliMUONPainterHelper* h = AliMUONPainterHelper::Instance();
+
+  AliDebug(1,Form("color=%d lineColor=%d x=%7.3f y=%7.3f",color,lineColor,x,y));
+  
+  if ( lineColor > 0 )
+  {
+    BackupStyle();
+    
+    Int_t cathode = h->GetCathodeType(fDetElemId,fManuId);
+    
+    gVirtualX->SetLineColor(lineColor);
+    gVirtualX->SetFillStyle(0);
+    
+    if ( x < FLT_MAX && y < FLT_MAX ) 
+    {
+      // find pad to be drawn
+      AliMpPad pad = PadByPosition(x,y);
+      
+      Int_t id = AliMUONVDigit::BuildUniqueID(fDetElemId,fManuId,pad.GetLocation().GetSecond(),cathode);
+
+      PaintPad(id);        
+    }
+    else
+    {
+      for ( Int_t i = 0; i < AliMpConstants::ManuNofChannels(); ++i ) 
+      {    
+        Int_t id = AliMUONVDigit::BuildUniqueID(fDetElemId,fManuId,i,cathode);
+      
+        PaintPad(id);        
+      }
+    }
+    RestoreStyle();
+  }  
+  
+}
+
+//_____________________________________________________________________________
+AliMpPad
+AliMUONManuPadPainter::PadByPosition(Double_t x, Double_t y) const
+{
+  /// Find the pad at given exploded-position (x,y)
+  
+  const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(fDetElemId,fManuId);
+  
+  Double_t xg,yg,zg;
+  Double_t xl,yl,zl;
+  
+  AliMUONPainterHelper::Instance()->Local2Global(fDetElemId,0.0,0.0,0.0,xg,yg,zg); // to get zg
+  
+  AliMUONPainterHelper::Instance()->Global2Local(fDetElemId,x,y,zg,xl,yl,zl);
+  
+  return seg->PadByPosition(TVector2(xl,yl));
+}
+
+//_____________________________________________________________________________
+void
+AliMUONManuPadPainter::RestoreStyle()
+{
+  /// Restore line and fill style values
+  
+  gVirtualX->SetFillStyle(fFillStyleBck);
+  gVirtualX->SetFillColor(fFillColorBck);
+  gVirtualX->SetLineColor(fLineColorBck);
+  gVirtualX->SetLineWidth(fLineWidthBck);
+}
+
+
diff --git a/MUON/AliMUONManuPadPainter.h b/MUON/AliMUONManuPadPainter.h
new file mode 100644 (file)
index 0000000..e2f5e14
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef ALIMUONMANUPADPAINTER_H
+#define ALIMUONMANUPADPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONManuPadPainter
+/// \brief Painter for the pads of one manu
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+#ifndef ALI_MP_PAD_H
+#  include "AliMpPad.h"
+#endif
+
+class AliMUONManuPadPainter : public AliMUONVPainter
+{
+public:
+  AliMUONManuPadPainter();
+  AliMUONManuPadPainter(const AliMUONVPainter& mother,
+                        Int_t detElemId,
+                        Int_t manuId);
+  virtual ~AliMUONManuPadPainter();
+
+  /// Clone ourselves
+  virtual TObject* Clone(const char* = "") const { return new AliMUONManuPadPainter(*this); }
+  
+  virtual void ComputeDataRange(const AliMUONVTrackerData& data,
+                                Int_t dataIndex,
+                                Double_t& dataMin, Double_t& dataMax) const;
+    
+  virtual char* GetObjectInfo(Int_t px, Int_t py) const;
+  
+  /// We advertise that we do handle mouse movement
+  virtual Bool_t HandleMouseMotion() const { return kTRUE; }
+  
+  TString NameAtPosition(Double_t x, Double_t y) const;
+
+    virtual TString Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                             Double_t x=FLT_MAX, Double_t y=FLT_MAX);
+
+    void PaintArea(const AliMUONVTrackerData& data,
+                   Int_t dataIndex,
+                   Double_t min,
+                   Double_t max);
+  
+  void PaintOutline(Int_t color=-1, Int_t width=-1, Double_t x=FLT_MAX, Double_t y=FLT_MAX);
+  
+private:
+    
+  void BackupStyle();
+  void RestoreStyle();
+  void PaintPad(Int_t padId) const;
+  AliMpPad PadByPosition(Double_t x, Double_t y) const;
+  
+private:
+  Int_t fDetElemId; ///< our detection element id
+  Int_t fManuId; ///< our manu id
+  Int_t fLineColorBck; ///< line color for backup
+  Int_t fLineWidthBck; ///< line width for backup
+  Int_t fFillColorBck; ///< fill color for backup
+  Int_t fFillStyleBck; ///< fill style for backup
+  
+  ClassDef(AliMUONManuPadPainter,1) // Painter for the pads of one manu
+};
+
+#endif
diff --git a/MUON/AliMUONManuPainter.cxx b/MUON/AliMUONManuPainter.cxx
new file mode 100644 (file)
index 0000000..29a417e
--- /dev/null
@@ -0,0 +1,270 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONManuPainter.h"
+
+#include "AliMUONManuPadPainter.h"
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVDigit.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMpDEManager.h"
+#include "AliMpMotifPosition.h"
+#include "AliMpMotifType.h"
+#include "AliMpSlat.h"
+#include "AliMpStationType.h"
+#include "AliMpVMotif.h"
+#include "AliMpVPadIterator.h"
+#include "AliLog.h"
+#include <TArrayI.h>
+#include <float.h>
+
+///\class AliMUONManuPainter
+///
+/// Implementation of AliMUONVPainter for one manu (not the pads, only the manu
+/// itself).
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONManuPainter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONManuPainter::AliMUONManuPainter()
+: AliMUONVPainter(),
+fDetElemId(-1),
+fManuId(-1)
+{
+  /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONManuPainter::AliMUONManuPainter(const AliMUONAttPainter& att,
+                                       Int_t detElemId,
+                                       Int_t manuId)
+: AliMUONVPainter("MANU"),
+  fDetElemId(detElemId),
+  fManuId(manuId)
+{
+    /// ctor
+    
+    SetAttributes(att);
+    
+    AliMUONPainterHelper* h = AliMUONPainterHelper::Instance();
+    
+    SetID(detElemId,manuId);
+    SetName(h->ManuName(manuId));
+    SetPathName(h->ManuPathName(detElemId,manuId));
+    
+    AliMpMotifPosition* mp = h->GetMotifPosition(detElemId,manuId);
+    
+    if (!mp)
+    {
+      AliFatal(Form("Could not get manuId %04d from DE %04d",manuId,detElemId));
+    }
+    
+    Double_t x,y,z;
+    
+    AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
+
+    if ( stationType == AliMp::kStation345 ) 
+    {
+      const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(detElemId,manuId);
+
+      h->Local2Global(fDetElemId,
+                                                   mp->Position().X() -slat->Position().X(),
+                                                   mp->Position().Y() -slat->Position().Y(),
+                                                   0,
+                                                   x,y,z);
+    }
+    else if ( stationType != AliMp::kStationTrigger ) 
+    {
+      h->Local2Global(fDetElemId,
+                                                     mp->Position().X(),
+                                                     mp->Position().Y(),
+                                                     0,
+                                                     x,y,z);      
+    }
+    else
+    {
+      AliError("Hu ho. Not supposed to be used for trigger !");
+      Invalidate();
+      return;
+    }
+    
+    AliMUONPainterContour* contour = h->GetContour(ContourName());
+
+    if (!contour)
+    {
+      contour = h->GenerateManuContour(fDetElemId,
+                                                                      fManuId,
+                                                                      Attributes(),
+                                                                      ContourName());
+    }
+    SetContour(contour);
+    
+    Add(new AliMUONManuPadPainter(*this,fDetElemId,fManuId));
+}
+
+//_____________________________________________________________________________
+AliMUONManuPainter::AliMUONManuPainter(const AliMUONManuPainter& rhs)
+: AliMUONVPainter(rhs), fDetElemId(-1), fManuId(-1)
+{
+  /// copy ctor
+  rhs.Copy(*this);
+}
+
+//_____________________________________________________________________________
+AliMUONManuPainter&
+AliMUONManuPainter::operator=(const AliMUONManuPainter& rhs)
+{
+  /// assignment operator
+  if ( this != &rhs ) 
+  {
+    rhs.Copy(*this);
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONManuPainter::~AliMUONManuPainter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONManuPainter::ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                     Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Compute data range spanned by this manu
+  dataMin = dataMax = data.Manu(fDetElemId, fManuId, dataIndex);
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONManuPainter::Copy(TObject& object) const
+{
+  /// copyy this to object
+  AliMUONVPainter::Copy((AliMUONVPainter&)(object));
+  ((AliMUONManuPainter&)(object)).fDetElemId = fDetElemId;
+  ((AliMUONManuPainter&)(object)).fManuId = fManuId;
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONManuPainter::Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                             Double_t, Double_t)
+{
+  /// Describe data at this manu
+  
+  if (!data.HasManu(fDetElemId,fManuId)) return "";
+  
+  Double_t value = data.Manu(fDetElemId,fManuId,dataIndex);
+  
+  return AliMUONPainterHelper::Instance()->FormatValue(data.DimensionName(dataIndex).Data(),value);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONManuPainter::PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                              Double_t min, Double_t max)
+{
+  /// Paint area of this manu according to data
+  
+  if (!data.HasManu(fDetElemId,fManuId)) return;
+
+  Double_t value = data.Manu(fDetElemId,fManuId,dataIndex);
+  
+  if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return;
+  
+  Int_t color = AliMUONPainterHelper::Instance()->ColorFromValue(value,min,max);
+  
+  Contour()->PaintArea(color);
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainter
+AliMUONManuPainter::Validate(const AliMUONAttPainter& attributes) const
+{
+  /// Normalize the attributes
+  
+  /// check that cathode and plane are up-to-date, and that they are legal
+  
+  AliMUONAttPainter norm(attributes);
+
+  norm.SetValid(kFALSE);
+  
+  if ( norm.IsCathodeDefined() ) 
+  {
+    if ( norm.IsCathode0() != Attributes().IsCathode0() ) return norm;
+  }
+  
+  if ( norm.IsPlaneDefined() ) 
+  {
+    if ( norm.IsBendingPlane() != Attributes().IsBendingPlane() ) return norm;
+  }
+  
+  norm.SetValid(kTRUE);
+  
+  if ( norm.IsCathodeDefined() && !norm.IsPlaneDefined() ) 
+  {
+    // derive plane from cathode
+    
+    AliMp::CathodType cathode = ( norm.IsCathode0() ? AliMp::kCath0 : AliMp::kCath1 ) ;
+
+    AliMp::PlaneType planeType = AliMpDEManager::GetPlaneType(fDetElemId,cathode);
+    
+    Bool_t bending = ( planeType == AliMp::kBendingPlane );
+    
+    norm.SetPlane(bending,!bending);    
+  }
+  else if ( norm.IsPlaneDefined() && !norm.IsCathodeDefined() )
+  {
+    // derive cathode from plane
+
+    AliMp::PlaneType planeType = ( norm.IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+
+    AliMp::CathodType cathode = AliMpDEManager::GetCathod(fDetElemId,planeType);
+          
+    Bool_t cath0 = ( cathode == AliMp::kCath0 );
+    
+    norm.SetCathode(cath0,!cath0);    
+  }
+  else if ( norm.IsPlaneDefined() && norm.IsCathodeDefined() ) 
+  {
+    // check that cathode and plane matches
+    
+    AliMp::CathodType cathode = ( norm.IsCathode0() ? AliMp::kCath0 : AliMp::kCath1 ) ;
+
+    AliMp::PlaneType planeType = AliMpDEManager::GetPlaneType(fDetElemId,cathode);
+    
+    Bool_t bending = ( planeType == AliMp::kBendingPlane );
+    
+    if ( bending != norm.IsBendingPlane() ) 
+    {
+      norm.SetValid(kFALSE);
+    }
+  }
+  
+  return norm;
+}
+
+
diff --git a/MUON/AliMUONManuPainter.h b/MUON/AliMUONManuPainter.h
new file mode 100644 (file)
index 0000000..4463347
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef ALIMUONMANUPAINTER_H
+#define ALIMUONMANUPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONManuPainter
+/// \brief Painter for one manu (not the pads, only the manu)
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+
+class AliMUONManuPainter : public AliMUONVPainter
+{
+public:
+
+  AliMUONManuPainter();
+  AliMUONManuPainter(const AliMUONAttPainter& att, 
+                     Int_t detElemId, 
+                     Int_t manuId);
+  AliMUONManuPainter(const AliMUONManuPainter& rhs);
+  AliMUONManuPainter& operator=(const AliMUONManuPainter& rhs);
+  
+  virtual ~AliMUONManuPainter();
+  
+  virtual void ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                Double_t& dataMin, Double_t& dataMax) const;
+    
+  /// Clone ourselves
+  virtual TObject* Clone(const char* = "") const { return new AliMUONManuPainter(*this); }
+
+  virtual void Copy(TObject& object) const;
+  
+    virtual TString Describe(const AliMUONVTrackerData& data, Int_t dataIndex,
+                             Double_t x=FLT_MAX, Double_t y=FLT_MAX);
+
+    void PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                   Double_t min, Double_t max);
+  
+    virtual AliMUONAttPainter Validate(const AliMUONAttPainter& attributes) const;
+
+private:
+  Int_t fDetElemId; ///< our detection element id
+  Int_t fManuId; ///< our manu id
+  
+  ClassDef(AliMUONManuPainter,1) // Painter for one manu (not the pads, only the manu)
+};
+
+#endif
diff --git a/MUON/AliMUONPCBPainter.cxx b/MUON/AliMUONPCBPainter.cxx
new file mode 100644 (file)
index 0000000..88fb503
--- /dev/null
@@ -0,0 +1,170 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONPCBPainter
+///
+/// Implementation of AliMUONVPainter for slat's PCBs
+/// 
+/// \author Laurent Aphecetche, Subatech
+
+#include "AliMUONPCBPainter.h"
+
+#include "AliMUONManuPainter.h"
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMpDEManager.h"
+#include "AliMpMotifPosition.h"
+#include "AliMpPCB.h"
+#include "AliMpPlaneType.h"
+#include "AliMpSlat.h"
+#include "AliLog.h"
+
+/// \cond(CLASSIMP)
+ClassImp(AliMUONPCBPainter)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONPCBPainter::AliMUONPCBPainter()
+: AliMUONVPainter(),
+fDetElemId(-1),
+fPCBIndex(-1)
+{
+  /// empty ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPCBPainter::AliMUONPCBPainter(const AliMUONAttPainter& att,
+                                     Int_t detElemId,
+                                     Int_t pcbNumber)
+: AliMUONVPainter("PCB"),
+  fDetElemId(detElemId),
+  fPCBIndex(pcbNumber)
+{
+    /// Ctor
+
+    SetAttributes(att);
+    
+    AliMUONPainterHelper* h = AliMUONPainterHelper::Instance();
+    
+    AliMp::PlaneType planeType = ( att.IsBendingPlane() ? AliMp::kBendingPlane : AliMp::kNonBendingPlane );
+    
+    const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(fDetElemId,planeType);
+    
+    SetID(detElemId,pcbNumber);
+    SetName(h->PCBName(pcbNumber));
+    SetPathName(h->PCBPathName(detElemId,pcbNumber));
+    
+    AliMpPCB* pcb = slat->GetPCB(fPCBIndex);
+    
+    AliMUONPainterContour* contour = h->GetContour(ContourName());
+    TObjArray contourArray;
+    
+    for ( Int_t imp = 0 ; imp < pcb->GetSize(); ++imp ) 
+    {
+      AliMpMotifPosition* mp = pcb->GetMotifPosition(imp);
+      AliDebug(1,Form("Adding manu %d to PCB %d of DE %d",
+                      mp->GetID(),fPCBIndex,fDetElemId));
+      AliMUONVPainter* painter = new AliMUONManuPainter(Attributes(),fDetElemId,mp->GetID());
+      Add(painter);
+      if (!contour)
+      {
+        contourArray.Add(painter->Contour());
+      }
+    }
+    
+    Double_t x,y,z;
+    
+    h->Local2Global(fDetElemId,
+                                                   pcb->X()-slat->Position().X(),
+                                                   pcb->Y()-slat->Position().Y(),
+                                                   0.0,
+                                                   x,y,z);
+    
+    if (!contour)
+    {
+      contour = h->MergeContours(contourArray,ContourName());
+    }
+    
+    SetContour(contour);
+}
+
+//_____________________________________________________________________________
+AliMUONPCBPainter::~AliMUONPCBPainter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+AliMUONPCBPainter::AliMUONPCBPainter(const AliMUONPCBPainter& rhs)
+: AliMUONVPainter(rhs),
+  fDetElemId(-1),
+  fPCBIndex(-1)
+{
+    /// copy ctor
+    rhs.Copy(*this);
+}
+
+//_____________________________________________________________________________
+AliMUONPCBPainter&
+AliMUONPCBPainter::operator=(const AliMUONPCBPainter& rhs)
+{
+  /// assignment operator
+  if ( this != &rhs )
+  {
+    rhs.Copy(*this);
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPCBPainter::ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                                   Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Compute the min and max of this PCB data 
+  dataMin = dataMax = data.PCB(fDetElemId, fPCBIndex,dataIndex);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPCBPainter::Copy(TObject& object) const
+{
+  /// Copy this to object
+  AliMUONVPainter::Copy((AliMUONVPainter&)(object));
+  ((AliMUONPCBPainter&)(object)).fDetElemId = fDetElemId;
+  ((AliMUONPCBPainter&)(object)).fPCBIndex = fPCBIndex;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPCBPainter::PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                            Double_t min, Double_t max)
+{
+  /// Fill the contour of this PCB with a color depending of the value of the data
+  if (!data.HasPCB(fDetElemId,fPCBIndex)) return;
+  
+  Double_t value = data.PCB(fDetElemId,fPCBIndex,dataIndex);
+  
+  if ( value >= AliMUONVCalibParam::InvalidFloatValue() ) return;
+  
+  Int_t color = AliMUONPainterHelper::Instance()->ColorFromValue(value,min,max);
+  
+  Contour()->PaintArea(color);
+}
+
diff --git a/MUON/AliMUONPCBPainter.h b/MUON/AliMUONPCBPainter.h
new file mode 100644 (file)
index 0000000..603494f
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef ALIMUONPCBPAINTER_H
+#define ALIMUONPCBPAINTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPCBPainter
+/// \brief Implementation of AliMUONVPainter for slat's PCBs
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+
+class AliMUONPCBPainter : public AliMUONVPainter
+{
+public:
+  AliMUONPCBPainter();
+  AliMUONPCBPainter(const AliMUONAttPainter& att, 
+                    Int_t detElemId, 
+                    Int_t pcbNumber);
+  AliMUONPCBPainter(const AliMUONPCBPainter& rhs);
+  AliMUONPCBPainter& operator=(const AliMUONPCBPainter& rhs);
+
+  virtual ~AliMUONPCBPainter();
+
+  /// Clone this object
+  virtual TObject* Clone(const char* = "" ) const { return new AliMUONPCBPainter(*this); }
+  
+  virtual void Copy(TObject& object) const;
+
+  void ComputeDataRange(const AliMUONVTrackerData& data, Int_t dataIndex, 
+                        Double_t& dataMin, Double_t& dataMax) const;
+  
+  void PaintArea(const AliMUONVTrackerData& data, Int_t dataIndex,
+                 Double_t min, Double_t max);
+  
+private:
+  Int_t fDetElemId; ///< Detection element this pcb is in
+  Int_t fPCBIndex;  ///< Index of this PCB within the detection element
+  
+  ClassDef(AliMUONPCBPainter,1) // Implementation of AliMUONVPainter for St345 PCBs
+};
+
+#endif
diff --git a/MUON/AliMUONPainterColorSlider.cxx b/MUON/AliMUONPainterColorSlider.cxx
new file mode 100644 (file)
index 0000000..1b1c036
--- /dev/null
@@ -0,0 +1,139 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterColorSlider.h"
+#include "AliMUONPainterHelper.h"
+#include "AliLog.h"
+#include <TGNumberEntry.h>
+#include <TGButton.h>
+#include <TMath.h>
+
+///\class AliMUONPainterColorSlider
+///
+/// A painter color palette
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterColorSlider)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterColorSlider::AliMUONPainterColorSlider(const TGWindow* p, 
+                                                     UInt_t w, UInt_t h)
+: TGCompositeFrame(p,w,h,kVerticalFrame),
+  fEntryMin(0x0),
+  fEntryMax(0x0),
+  fMin(FLT_MAX),
+  fMax(-FLT_MAX)
+{
+    /// ctor
+    Int_t ndivisions(20);
+  
+  Int_t hsize = 20;
+  Int_t topBorder(5);
+  
+  Double_t min(0.0);
+  Double_t max(1.0);
+  
+  Double_t step = (max-min)/ndivisions;
+  
+  for ( Int_t i = -1; i <= ndivisions+1; ++i ) 
+  {
+    Double_t value = max - (min + step*i);
+    
+    Int_t color = AliMUONPainterHelper::Instance()->ColorFromValue(value,
+                                                                   min,max);
+    Pixel_t pixel = gVirtualX->GetPixel(color);
+    TGVerticalFrame* frame = new TGVerticalFrame(this,w,hsize,kFixedSize,pixel);
+    
+    AddFrame(frame,new TGLayoutHints(kLHintsExpandX,0,0,topBorder,0));
+    
+    topBorder = 0;
+  }
+  
+  fEntryMax = new TGNumberEntry(this);
+  
+  AddFrame(fEntryMax,new TGLayoutHints(kLHintsExpandX,0,0,topBorder,0));
+    
+  fEntryMin = new TGNumberEntry(this);
+  
+  AddFrame(fEntryMin,new TGLayoutHints(kLHintsExpandX,0,0,topBorder,0));
+  
+//  fEntryMin->SetFormat(TGNumberFormat::kNESRealOne);
+//  fEntryMax->SetFormat(TGNumberFormat::kNESRealOne);
+  
+  TGTextButton* button = new TGTextButton(this,"Auto");
+  
+  AddFrame(button,new TGLayoutHints(kLHintsExpandX,0,0,topBorder,0));
+  
+  button->Connect("Clicked()","AliMUONPainterColorSlider",this,"DataRangeAutoRequested()");
+  
+  fEntryMax->Connect("ValueSet(Long_t)","AliMUONPainterColorSlider",this,"DataRangeWasChanged(Double_t*)");
+  fEntryMin->Connect("ValueSet(Long_t)","AliMUONPainterColorSlider",this,"DataRangeWasChanged(Double_t*)");
+}
+
+//_____________________________________________________________________________
+AliMUONPainterColorSlider::~AliMUONPainterColorSlider()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterColorSlider::DataRangeAutoRequested()
+{
+  /// Signal that the "Auto" button was clicked
+  AliDebug(1,"");
+  Emit("DataRangeAutoRequested()");
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterColorSlider::DataRangeWasChanged(Double_t*)
+{
+  /// Data range was changed
+  
+  Double_t values[] = { fEntryMin->GetNumber(), fEntryMax->GetNumber() };
+  
+  Long_t param[] = { (Long_t)values };
+  
+  AliDebug(1,Form("double min %e max %e",values[0],values[1]));
+  
+  Emit("DataRangeWasChanged(Double_t*)",param);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterColorSlider::SetRange(Double_t min, Double_t max, Bool_t emit)
+{
+  /// Set the data range
+  
+  AliDebug(1,Form("min %e max %e emit %d",min,max,emit));
+  
+  fMin = min;
+  fMax = max;
+  
+  fEntryMin->SetNumber(fMin);
+  fEntryMax->SetNumber(fMax);
+  
+  if ( emit ) 
+  {
+    DataRangeWasChanged(0x0);
+  }
+}
+
diff --git a/MUON/AliMUONPainterColorSlider.h b/MUON/AliMUONPainterColorSlider.h
new file mode 100644 (file)
index 0000000..4f6670f
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef ALIMUONPAINTERCOLORSLIDER_H
+#define ALIMUONPAINTERCOLORSLIDER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterColorSlider
+/// \brief A vertical color palette
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TGFrame
+#  include "TGFrame.h"
+#endif
+
+class TGNumberEntry;
+
+class AliMUONPainterColorSlider : public TGCompositeFrame
+{
+public:
+  AliMUONPainterColorSlider(const TGWindow* p, UInt_t w, UInt_t h);
+  virtual ~AliMUONPainterColorSlider();
+
+  void DataRangeAutoRequested(); // *SIGNAL*
+
+  void DataRangeWasChanged(Double_t* range); // *SIGNAL*
+  
+  void SetRange(Double_t min, Double_t max, Bool_t emit=kTRUE);
+  
+private:
+  /// Not implemented
+  AliMUONPainterColorSlider(const AliMUONPainterColorSlider& rhs);
+  /// Not implemented
+  AliMUONPainterColorSlider& operator=(const AliMUONPainterColorSlider& rhs);
+  
+private:
+  TGNumberEntry* fEntryMin; ///< textbox for min value to be represented
+  TGNumberEntry* fEntryMax; ///< textbox for max value to be represented
+  Double_t fMin; ///< min value to be represented
+  Double_t fMax; ///< max value to be represented
+  
+  ClassDef(AliMUONPainterColorSlider,1) // A painter color palette
+};
+
+#endif
diff --git a/MUON/AliMUONPainterContour.cxx b/MUON/AliMUONPainterContour.cxx
new file mode 100644 (file)
index 0000000..9e4c8e2
--- /dev/null
@@ -0,0 +1,319 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterContour.h"
+
+#include "AliMpArea.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TGeoMatrix.h>
+#include <TMath.h>
+#include <TObjArray.h>
+#include <TPolyLine.h>
+#include <TString.h>
+#include <TVector2.h>
+#include <TVirtualX.h>
+#include <float.h>
+
+///\class AliMUONPainterContour
+///
+/// Contour for one painter. A contour is a set of TPolyLine (one polyline
+/// per closed shape).
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterContour)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterContour::AliMUONPainterContour(const char* name) : TNamed(name,""), 
+fPolyLines(new TObjArray),
+fXmin(FLT_MAX),
+fXmax(-FLT_MAX),
+fYmin(FLT_MAX),
+fYmax(-FLT_MAX)
+{
+  /// ctor
+  fPolyLines->SetOwner(kTRUE);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour::AliMUONPainterContour(const char* name, const AliMpArea& area) 
+: TNamed(name,""), 
+fPolyLines(new TObjArray),
+fXmin(area.LeftBorder()),
+fXmax(area.RightBorder()),
+fYmin(area.DownBorder()),
+fYmax(area.UpBorder())
+{
+  /// ctor
+  fPolyLines->SetOwner(kTRUE);
+  TPolyLine* line = new TPolyLine(5);
+  Double_t x = area.Position().X();
+  Double_t y = area.Position().Y();
+  Double_t dx = area.Dimensions().X();
+  Double_t dy = area.Dimensions().Y();
+  line->SetPoint(0,x-dx,y-dy);
+  line->SetPoint(1,x-dx,y+dy);
+  line->SetPoint(2,x+dx,y+dy);
+  line->SetPoint(3,x+dx,y-dy);
+  line->SetPoint(4,x-dx,y-dy);
+  
+  fPolyLines->AddLast(line);
+}
+
+//______________________________________________________________________________
+AliMUONPainterContour::AliMUONPainterContour(const AliMUONPainterContour& rhs) 
+: TNamed(rhs), 
+fPolyLines(0x0),
+fXmin(FLT_MAX),
+fXmax(-FLT_MAX),
+fYmin(FLT_MAX),
+fYmax(-FLT_MAX)
+{
+  /// Copy constructor.
+  
+  ((AliMUONPainterContour&)rhs).Copy(*this);
+}
+
+//______________________________________________________________________________
+AliMUONPainterContour&
+AliMUONPainterContour::operator=(const AliMUONPainterContour& rhs)
+{
+  /// Assignment operator
+  if ( this != &rhs ) 
+  {
+    delete fPolyLines;
+    fPolyLines = 0;
+    rhs.Copy(*this);
+  }
+  return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour::~AliMUONPainterContour()
+{
+  /// dtor
+  delete fPolyLines;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContour::AdoptPolyLine(TPolyLine* line)
+{
+  /// Adopt one polyline into our array of polylines
+  fPolyLines->AddLast(line);
+  for ( Int_t i = 0; i <= line->GetLastPoint(); ++i ) 
+  {
+    Double_t x = line->GetX()[i];
+    Double_t y = line->GetY()[i];
+    fXmin = TMath::Min(fXmin,x);
+    fXmax = TMath::Max(fXmax,x);
+    fYmin = TMath::Min(fYmin,y);
+    fYmax = TMath::Max(fYmax,y);
+  }
+}
+
+//_____________________________________________________________________________
+AliMpArea
+AliMUONPainterContour::Area() const
+{
+  /// Return the area covered by this contour (i.e. the area that
+  /// contains all the poylines)
+  
+  return AliMpArea( TVector2( (fXmax+fXmin)/2.0, (fYmax+fYmin)/2.0 ),
+                    TVector2( TMath::Abs(fXmax-fXmin)/2.0, TMath::Abs(fYmax-fYmin)/2.0 ) );
+}
+
+//______________________________________________________________________________
+void AliMUONPainterContour::Copy(TObject& obj) const
+{
+  /// Copy this to obj
+  
+  AliMUONPainterContour& rhs = static_cast<AliMUONPainterContour&>(obj);
+  TNamed::Copy(rhs);
+  rhs.fPolyLines = new TObjArray;
+  rhs.fPolyLines->SetOwner(kTRUE);
+  TIter next(fPolyLines);
+  TPolyLine* line;
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    rhs.fPolyLines->AddLast(line->Clone());
+  }
+  rhs.fXmin = fXmin;
+  rhs.fXmax = fXmax;
+  rhs.fYmin = fYmin;
+  rhs.fYmax = fYmax;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContour::IsInside(Double_t x, Double_t y) const
+{
+  /// Whether the point (x,y) is inside one of ours polylines
+//  if ( x >= fXmin && x <= fXmax && y >= fYmin && y <= fYmax ) 
+  {
+    TIter next(fPolyLines);
+    TPolyLine* line;
+    while ( ( line = static_cast<TPolyLine*>(next()) ) )
+    {
+      if ( TMath::IsInside(x,y,line->Size(),line->GetX(),line->GetY() ) )
+      {
+        return kTRUE;
+      }
+    }
+  }
+  return kFALSE;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContour::Offset(const TVector2& offset)
+{
+  /// Offset all lines by a given offset
+  
+  TIter next(fPolyLines);
+  TPolyLine* line;
+  
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    for ( Int_t i = 0; i <= line->GetLastPoint(); ++i ) 
+    {
+      Double_t x = line->GetX()[i];
+      Double_t y = line->GetY()[i];
+      x += offset.X();
+      y += offset.Y();
+      line->SetPoint(i,x,y);
+    }
+  }
+
+  fXmin += offset.X();
+  fXmax += offset.X();
+  fYmin += offset.Y();
+  fYmax += offset.Y();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContour::PaintArea(Int_t fillColor, Int_t fillStyle)
+{
+  /// Paint a filled contour
+  
+  Int_t fc = gVirtualX->GetFillColor();
+  Int_t fs = gVirtualX->GetFillStyle();
+  
+  TIter next(fPolyLines);
+  TPolyLine* line;
+  
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    line->SetFillColor(fillColor);
+    line->SetFillStyle(fillStyle);
+    line->Paint("F");
+  }
+  
+  gVirtualX->SetFillColor(fc);
+  gVirtualX->SetFillStyle(fs);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContour::PaintOutline(Int_t lineColor, Int_t lineWidth)
+{
+  /// Paint the outline of this contour
+  
+  Int_t lc = gVirtualX->GetLineColor();
+  Int_t lw = gVirtualX->GetLineWidth();
+  
+  TIter next(fPolyLines);
+  TPolyLine* line;
+  
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    line->SetLineColor(lineColor);
+    line->SetLineWidth(lineWidth);
+    line->Paint();
+  }
+  
+  gVirtualX->SetLineColor(lc);
+  gVirtualX->SetLineWidth(lw);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContour::Print(Option_t* opt) const
+{
+  /// Printout
+  
+  cout << GetName() << " Ngroups=" << fPolyLines->GetLast()+1;
+  TString sopt(opt);
+  sopt.ToUpper();
+
+  TIter next(fPolyLines);
+  TPolyLine* line;
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    cout << " (" << line->Size() << ")";
+    if ( sopt.Contains("FULL") )
+    {
+      cout << endl;
+      for ( Int_t i = 0; i < line->Size(); ++i ) 
+      {
+        Double_t x = line->GetX()[i];
+        Double_t y = line->GetY()[i];
+        cout << Form("Point %3d = %7.3f %7.3f",i,x,y) << endl;
+      }
+    }
+  }
+  cout << endl;
+}  
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContour::Transform(const TGeoHMatrix& matrix)
+{
+  /// Transform the polylines using the given transformation
+  
+  TIter next(fPolyLines);
+  TPolyLine* line;
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    for ( Int_t i = 0; i < line->Size(); ++i ) 
+    {
+      Double_t pl[3] = { line->GetX()[i], line->GetY()[i], 0 };
+      Double_t pg[3] = { 0., 0., 0. };
+      matrix.LocalToMaster(pl, pg);
+      line->SetPoint(i,pg[0],pg[1]);
+    }
+  }
+  
+
+  Double_t pl[3] = { fXmin,fYmin, 0 };
+  Double_t pg[3] = { 0., 0., 0. };
+  matrix.LocalToMaster(pl, pg);
+  
+  fXmin = pg[0];
+  fYmin = pg[1];
+  
+  pl[0] = fXmax;
+  pl[1] = fYmax;
+
+  matrix.LocalToMaster(pl, pg);
+  fXmax = pg[0];
+  fYmax= pg[1];
+}
diff --git a/MUON/AliMUONPainterContour.h b/MUON/AliMUONPainterContour.h
new file mode 100644 (file)
index 0000000..f9b46c1
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef AliMUONPainterContour_H
+#define AliMUONPainterContour_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterContour
+/// \brief Contour(s) of a painter
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TNamed
+#  include "TNamed.h"
+#endif
+
+class AliMpArea;
+class TObjArray;
+class TPolyLine;
+class TGeoHMatrix;
+class TVector2;
+
+class AliMUONPainterContour : public TNamed
+{
+public:
+  AliMUONPainterContour(const char* name="");
+  AliMUONPainterContour(const char* name, const AliMpArea& area);
+  AliMUONPainterContour(const AliMUONPainterContour& rhs);
+  AliMUONPainterContour& operator=(const AliMUONPainterContour& rhs);
+  virtual ~AliMUONPainterContour();
+  
+  AliMpArea Area() const;
+  
+  /// Add an offset to all points
+  void Offset(const TVector2& offset);
+  
+  /// Apply a global transformation to all points
+  void Transform(const TGeoHMatrix& matrix);
+  
+  void AdoptPolyLine(TPolyLine* line);
+
+  virtual void Copy(TObject& obj) const;
+    
+  Bool_t IsInside(Double_t x, Double_t y) const;
+
+  /// Paint the outline
+  void Paint(Option_t* ="") { PaintOutline(1,1); }
+  
+  void PaintOutline(Int_t lineColor, Int_t lineWidth);
+  
+  void PaintArea(Int_t fillColor, Int_t fillStyle=1001);
+
+  virtual void Print(Option_t* opt="") const;
+  
+  /// Return as an array of polylines
+  const TObjArray* AsPolyLines() const { return fPolyLines; }
+  
+private:
+  TObjArray* fPolyLines; ///< the polylines used to represent to contour
+  Double_t fXmin; ///< min x-value
+  Double_t fXmax; ///< max x-value
+  Double_t fYmin; ///< min y-value
+  Double_t fYmax; ///< max y-value
+  
+  ClassDef(AliMUONPainterContour,1) // Contour for one painter
+};
+
+#endif
diff --git a/MUON/AliMUONPainterContourMaker.cxx b/MUON/AliMUONPainterContourMaker.cxx
new file mode 100644 (file)
index 0000000..d6e7a7f
--- /dev/null
@@ -0,0 +1,1572 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterContourMaker.h"
+
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVDigit.h"
+#include "AliMpConnection.h"
+#include "AliMpConstants.h"
+#include "AliMpDEManager.h"
+#include "AliMpExMap.h"
+#include "AliMpMotifMap.h"
+#include "AliMpMotifPosition.h"
+#include "AliMpMotifType.h"
+#include "AliMpSector.h"
+#include "AliMpSectorSegmentation.h"
+#include "AliMpSegmentation.h"
+#include "AliMpSlat.h"
+#include "AliMpSlatSegmentation.h"
+#include "AliMpStationType.h"
+#include "AliMpVMotif.h"
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TArrayI.h>
+#include <TGeoMatrix.h>
+#include <TLine.h>
+#include <TMap.h>
+#include <TMath.h>
+#include <TMathBase.h>
+#include <TObjArray.h>
+#include <TPolyLine.h>
+#include <cassert>
+#include <float.h>
+
+///\class AliMUONPainterContourMaker
+///
+/// A class to build painter contours. 
+///
+/// The basics are to build one manu contour, and then to merge contours
+/// to build higher order objects, like PCBS, DEs, etc...
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterContourMaker)
+ClassImp(AliMUONPainterContourMaker::AliMUONNeighbour)
+///\endcond
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::AliMUONNeighbour::Compare(const TObject* obj) const
+{
+  /// Compare two neighbours objects
+  
+  const AliMUONNeighbour* n = static_cast<const AliMUONNeighbour*>(obj);
+  
+  if ( Position().X() < n->Position().X() )
+  {
+    return -1;
+  }
+  else if ( Position().X() > n->Position().X() )
+  {
+    return 1;
+  }
+  else
+  {
+    // same X
+    if ( Position().Y() < n->Position().Y() )
+    {
+      return -1;
+    }
+    else if ( Position().Y() > n->Position().Y() )
+    {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterContourMaker::AliMUONNeighbour::Print(Option_t*) const
+{
+  /// Printout
+  cout << Form("ID %10d DE %4d Manu %4d Channel %2d "
+               "(X,Y)=(%7.3f,%7.3f) L,R,T,B=%1d,%1d,%1d,%1d",
+               ID(),
+               AliMUONVDigit::DetElemId(ID()),
+               AliMUONVDigit::ManuId(ID()),
+               AliMUONVDigit::ManuChannel(ID()),
+               Position().X(),Position().Y(),
+               HasLeftNeighbour(),HasRightNeighbour(),
+               HasTopNeighbour(),HasBottomNeighbour())
+  << endl;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContourMaker::AliMUONPainterContourMaker(AliMpExMap* globalTransformations)
+: TObject(), 
+  fGlobalTransformations(globalTransformations),
+  fLocalManuContours(new TMap),
+  fContours(new TMap)
+{
+    /// ctor
+    fContours->SetOwner(kTRUE);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContourMaker::~AliMUONPainterContourMaker()
+{
+  /// dtor
+  fLocalManuContours->DeleteAll();
+  delete fLocalManuContours;
+  fContours->DeleteAll();
+  delete fContours;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterContourMaker::Add(AliMUONPainterContour* contour)
+{
+  /// Add a contour to our store of contours
+  fContours->Add(new TObjString(contour->GetName()),contour);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContourMaker::AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
+                                       Double_t x2, Double_t y2, Int_t id) const
+{
+  /// Add one segment defined by (x1,y1,x2,y2) to the array of segments
+  AliCodeTimerAuto("")
+  AliDebug(1,Form("AddSegment %7.3f,%7.3f -> %7.3f,%7.3f",x1,y1,x2,y2));
+  TLine* line = new TLine(x1,y1,x2,y2);
+  line->SetUniqueID(id);
+  segments.Add(line);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterContourMaker::HasLine(const TObjArray& segments,
+                                    const TLine& line) const
+{
+  /// Check whether line is already part of segments array
+  
+  TIter next(&segments);
+  TLine* l;
+  
+  while ( ( l = static_cast<TLine*>(next()) ) )
+  {
+    if ( IsEqual(line,*l) ) return kTRUE;
+  }
+  
+  return kFALSE;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContourMaker::AddSegments(TObjArray& segments, 
+                                        const AliMUONPainterContour& contour) const
+
+{
+  /// Add all the segments (that are not already there) 
+  /// of contour to the segments array
+  
+  AliCodeTimerAuto("")
+  
+  const TObjArray* pl = contour.AsPolyLines();
+
+  TIter next(pl);
+
+  Int_t n(0);
+  
+  TPolyLine* line;
+  
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )
+  {
+    n += line->GetLastPoint();
+  }  
+  
+  AliDebug(1,Form("Adding %d groups (%d lines) from contour %s ",pl->GetLast()+1,n,contour.GetName()));
+
+  next.Reset();
+  
+  while ( ( line = static_cast<TPolyLine*>(next()) ) )    
+  {
+    AliDebug(1,"line=");
+//    StdoutToAliDebug(1,line->Print(););
+    for ( Int_t i = 0; i < line->GetLastPoint(); ++i ) 
+    {
+      Double_t x1 = line->GetX()[i];
+      Double_t y1 = line->GetY()[i];
+      Double_t x2 = line->GetX()[i+1];
+      Double_t y2 = line->GetY()[i+1];
+      
+      TLine* line = new TLine(x1,y1,x2,y2);
+      
+      if ( !HasLine(segments,*line) )
+      {
+        segments.Add(line);      
+        AliDebug(1,Form("Adding line %s",LineAsString(*line).Data()));
+      }
+      else
+      {
+        AliDebug(1,Form("Line %s is already there",LineAsString(*line).Data()));
+      }      
+    }
+  }
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour*
+AliMUONPainterContourMaker::ConvertEdgePadsToContour(TObjArray& ePads, 
+                                                     const char* name) const
+{
+  /// Convert an array of edge pads into a contour of a given name
+  
+  AliCodeTimerAuto("")
+  
+  ePads.Sort();
+  
+  AliDebug(1,Form("%d pads to convert:",ePads.GetEntries()));
+//  StdoutToAliDebug(1,ePads.Print();)
+    
+  TObjArray segments;
+  segments.SetOwner(kTRUE);
+  
+  TIter nextPad(&ePads);
+  AliMUONNeighbour* ne;
+  
+  while ( ( ne = static_cast<AliMUONNeighbour*>(nextPad()) ) )
+  {
+    Int_t id = ne->ID();
+    
+    if ( ! ne->HasLeftNeighbour() )
+    {
+      AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
+                 ne->LowerLeft().X(),ne->UpperRight().Y(),id);
+    }
+    if ( ! ne->HasRightNeighbour() )
+    {
+      AddSegment(segments,ne->UpperRight().X(),ne->LowerLeft().Y(),
+                 ne->UpperRight().X(),ne->UpperRight().Y(),id);
+    }
+    if ( ! ne->HasTopNeighbour() )
+    {
+      AddSegment(segments,ne->LowerLeft().X(),ne->UpperRight().Y(),
+                 ne->UpperRight().X(),ne->UpperRight().Y(),id);
+    }
+    if ( ! ne->HasBottomNeighbour() )
+    {
+      AddSegment(segments,ne->LowerLeft().X(),ne->LowerLeft().Y(),
+                 ne->UpperRight().X(),ne->LowerLeft().Y(),id);
+    }    
+  }
+  
+  return ConvertSegmentsToContour(segments,name);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContourMaker::PrintLine(const TLine& line, const char* msg) const
+{
+  /// Printout of a line
+  cout << Form("%10s %s",
+               msg,LineAsString(line).Data()) << endl;   
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterContourMaker::LineAsString(const TLine& line, Bool_t slope) const
+{
+  /// Return a string representation of the line
+  
+  TString rv(Form("%7.3f,%7.3f -> %7.3f,%7.3f",
+                  line.GetX1(),line.GetY1(),
+                  line.GetX2(),line.GetY2()));
+             
+  if ( slope ) 
+  {
+    if ( IsHorizontal(line) ) rv += " H";
+    else if ( IsVertical(line) ) rv += " V";
+    else rv += Form(" (slope %e)",Slope(line));
+  }
+  
+  return rv;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContourMaker::PrintSegments(const TObjArray& segments) const
+{
+  /// Printout of segment arrays (debug)
+  
+  for ( Int_t i = 0; i <= segments.GetLast(); ++i )
+  {
+    TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
+    
+    cout << Form("***--- i %4d",i);
+    if ( l ) 
+    {
+      PrintLine(*l);
+    }
+    else
+    {
+      cout << " line is null ?" << endl;
+    }
+  }
+}
+
+//_____________________________________________________________________________
+TLine* 
+AliMUONPainterContourMaker::AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const
+{
+  /// Add one segment (taken from position i in array) into polyline
+  
+  AliDebug(1,Form("i=%d",i));
+  TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
+  if (l)
+  {
+    line.SetNextPoint(l->GetX1(),l->GetY1());
+    line.SetNextPoint(l->GetX2(),l->GetY2());
+  }
+  else
+  {
+    AliError(Form("Did not find the line at i=%d",i));
+    PrintSegments(segments);
+  }
+  return l;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterContourMaker::FindPoint(Double_t x, Double_t y, 
+                                      TObjArray& segments) const
+{
+  /// Find if point (x,y) is in segments array, and return
+  /// its index (=position within array)
+  
+  TIter next(&segments);
+  TLine* l;
+  
+  while ( ( l = static_cast<TLine*>(next()) ) )
+  {
+    if ( IsEqual(l->GetX1(),x) && IsEqual(l->GetY1(),y) )
+    {
+      return segments.IndexOf(l);
+    }
+  }
+  AliError(Form("Did not find point %7.3f %7.3f in those segments:",x,y));
+//  StdoutToAliDebug(1,PrintSegments(segments););
+  return -1;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour*
+AliMUONPainterContourMaker::ConvertSegmentsToContour(TObjArray& segments, 
+                                                     const char* name) const
+{
+  /// Convert an array of segments into a contour
+  
+  AliDebug(1,"");
+  AliCodeTimerAuto("");
+  
+  AliMUONPainterContour* contour = new AliMUONPainterContour(name);
+
+  Int_t n(0); // this is a protection against infinite loop (used for debug only)
+  
+  while ( segments.GetLast() >= 0 && n < 100 ) 
+  {
+    TPolyLine lines;
+    TIter next(&segments);
+    TLine* l;
+    
+    while ( ( l = static_cast<TLine*>(next() ) ) )
+    {
+      TLine* inserted = InsertSegment(lines,*l);
+      if ( inserted ) 
+      {
+        segments.Remove(inserted);
+        next.Reset();
+      }
+      
+      // check for closure
+      if ( IsLineClosed(lines) ) 
+      {
+        AliDebug(1,"Line closed. Starting a new one");
+        break;
+      }
+    }
+    
+    TPolyLine* sl = Simplify(lines);
+    
+    contour->AdoptPolyLine(sl);
+    ++n;
+  }
+  
+  if ( segments.GetLast() >= 0 ) 
+  {
+    AliError("segment should be empty by now");
+//    StdoutToAliError(PrintSegments(segments););
+  }
+  
+  return contour;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterContourMaker::FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const
+{
+  /// Return position of (x,y) within the polyline
+  
+  AliCodeTimerAuto("")
+  
+  for ( Int_t i = 0; i < lines.Size(); ++i ) 
+  {
+    if ( IsEqual(lines.GetX()[i],x) && IsEqual(lines.GetY()[i],y) ) 
+    {
+      return i;
+    }
+  }
+  return -1;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterContourMaker::CleanSegments(TObjArray& segments,
+                                          const TArrayI& toBeRemoved) const
+{
+  /// Remove segments at indices stored in toBeRemoved array
+  for ( Int_t i = 0; i < toBeRemoved.GetSize(); ++i ) 
+  {
+    if ( toBeRemoved[i] )
+    {
+      segments.RemoveAt(i);
+    }
+  }
+  segments.Compress();
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::SplitSegments(TObjArray& segments) const
+{
+  /// Split segments that have partial overlap 
+  
+  AliCodeTimerAuto("")
+  
+  TArrayI toBeRemoved(segments.GetLast()+1);
+  toBeRemoved.Reset(0);
+  Bool_t added(kFALSE);
+  
+  for ( Int_t i = 0; i <= segments.GetLast() && !added; ++i ) 
+  {
+    if ( toBeRemoved[i] ) continue;
+    
+    TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
+    
+    for ( Int_t j = i+1; j <= segments.GetLast() && !added; ++j ) 
+    {
+      if ( toBeRemoved[j] ) continue;
+      
+      TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
+      
+      Int_t o = Overlap(*li,*lj);
+
+      if ( o ) 
+      {
+        toBeRemoved[i] = toBeRemoved[j] = 1;
+        
+        Double_t x[] = { li->GetX1(), lj->GetX1(), li->GetX2(), lj->GetX2() };
+        Double_t y[] = { li->GetY1(), lj->GetY1(), li->GetY2(), lj->GetY2() };
+        
+        Double_t xmin(FLT_MAX), ymin(FLT_MAX);
+        Double_t xmax(-FLT_MAX), ymax(-FLT_MAX);
+
+        for ( Int_t i = 0; i < 4; ++i )
+        {
+          xmin = TMath::Min(x[i],xmin);
+          ymin = TMath::Min(y[i],ymin);
+          xmax = TMath::Max(x[i],xmax);
+          ymax = TMath::Max(y[i],ymax);
+        }
+        
+        TLine fullLine(xmin,ymin,xmax,ymax);
+        
+        for ( Int_t i = 0; i < 4; ++i )
+        {
+          for ( Int_t j = i+1; j < 4; ++j )
+          {
+            if ( TMath::Abs(i-j) != 2 ) 
+            {
+              TLine test(x[i],y[i],x[j],y[j]);
+
+              Bool_t isFullLine = IsEqual(test,fullLine);
+              
+              if ( !IsPoint(test) && !isFullLine ) 
+              {
+                segments.Add(new TLine(test));
+                added = kTRUE;
+              }              
+            }
+          }
+        }
+      }
+    }
+  }
+  
+  CleanSegments(segments,toBeRemoved);
+  
+  return added;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterContourMaker::ShouldBeRemoved(const TObjArray& contours,
+                                            Double_t x, Double_t y) const
+{
+  /// Tells whether or not a point can be removed, because it lies
+  /// inside the global contour
+  
+  const Double_t kPrecision(AliMpConstants::LengthTolerance());
+  const Double_t kShiftX[] = { kPrecision,kPrecision,-kPrecision,-kPrecision };
+  const Double_t kShiftY[] = { kPrecision,-kPrecision,kPrecision,-kPrecision };
+  
+  TIter next(&contours);
+  AliMUONPainterContour* contour;
+
+  Int_t n(0);
+
+  while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
+  {
+    for ( Int_t i = 0; i < 4; ++i )
+    {
+      if ( contour->IsInside( x + kShiftX[i], y + kShiftY[i]) )
+      {
+        ++n;
+      }
+    }
+  }
+  
+  return (n>=4);
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::RemoveInsideSegments(const TObjArray& contours,
+                                                 TObjArray& segments) const
+{
+  /// Remove segments that have 2 triple points
+
+  AliCodeTimerAuto("")
+  
+  TArrayI toBeRemoved(segments.GetLast()+1);
+  toBeRemoved.Reset(0);
+  
+  for ( Int_t i = 0; i <= segments.GetLast(); ++i ) 
+  {
+    TLine* line = static_cast<TLine*>(segments.UncheckedAt(i)); 
+    
+    Double_t x = (line->GetX1() + line->GetX2())/2.0;
+    Double_t y = (line->GetY1() + line->GetY2())/2.0;
+    
+    if ( ShouldBeRemoved(contours,x,y) )
+    {
+      toBeRemoved[i] = 1;
+    }
+  }
+    
+  Int_t before = segments.GetLast()+1;
+  
+  CleanSegments(segments,toBeRemoved);
+  
+  Int_t after = segments.GetLast()+1;
+  
+  AliDebug(1,Form("# of segments before = %d after = %d",before,after));  
+  
+  return after-before;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour* 
+AliMUONPainterContourMaker::MergeContours(const TObjArray& contours,
+                                          const char* contourName) const
+{
+  /// Merge an array of contours into a single contour, with a given name
+  
+  AliCodeTimerAuto("");
+  
+  AliDebug(1,Form("Merging %d contours into %s",contours.GetLast()+1,contourName));
+  
+  if ( contours.GetSize() == 0 ) return 0x0;
+  
+  TIter next(&contours);
+  AliMUONPainterContour* contour;
+  
+  TObjArray segments;
+  segments.SetOwner(kTRUE);
+  
+  while ( ( contour = static_cast<AliMUONPainterContour*>(next()) ) )
+  {
+    AddSegments(segments,*contour);
+  }
+  
+//  AliDebug(1,"After AddSegments");
+//  StdoutToAliDebug(1,PrintSegments(segments));
+  
+  while (SplitSegments(segments));
+
+//  AliDebug(1,"After SplitSegments");
+//  StdoutToAliDebug(1,PrintSegments(segments));
+
+//  if (!SanityCheck(contours,segments))
+//  {
+//    return 0x0;
+//  }
+
+  RemoveInsideSegments(contours,segments);
+  
+//  if (!SanityCheck(contours,segments))
+//  {
+//    return 0x0;
+//  }
+    
+//  AliDebug(1,"After RemoveInsideSegments");
+//  StdoutToAliDebug(1,PrintSegments(segments););
+    
+//  if (!SanityCheck(contours,segments))
+//  {
+//    return 0x0;
+//  }
+  
+  return ConvertSegmentsToContour(segments,contourName);
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONPainterContourMaker::NameIt(const AliMpMotifPosition& motifPosition) const
+{
+  /// Get the name of an AliMpMotifPosition
+  
+  AliMpVMotif* motif = motifPosition.GetMotif();
+  TString name(Form("%s",motif->GetID().Data()));
+  
+  for ( Int_t i = 0; i < motif->GetNofPadDimensions(); ++i )
+  {
+    TVector2 padDim = motif->GetPadDimensions(i);
+    name += Form("/%7.3f-%7.3f:",padDim.X(),padDim.Y());
+  }
+  return name;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour*
+AliMUONPainterContourMaker::FindLocalManuContour(Int_t detElemId, Int_t manuId) const
+{
+  /// Get a pre-computed manu contour (in local coordinates)
+  AliCodeTimerAuto("")
+  
+  AliMpMotifPosition* motifPos = FindMotifPosition(detElemId,manuId);
+  
+  TObject* o = fLocalManuContours->GetValue(NameIt(*motifPos));
+  
+  if (o) return static_cast<AliMUONPainterContour*>(o);
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+AliMpMotifPosition*
+AliMUONPainterContourMaker::FindMotifPosition(Int_t detElemId, Int_t manuId) const
+{
+  /// Find a given motifPosition object
+  
+  AliCodeTimerAuto("")
+  
+  const AliMpVSegmentation* vseg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
+  if (!vseg)
+  {
+    AliFatal(Form("Could not find motif for DE %d manu %d",detElemId,manuId));
+  }
+  
+  AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
+  
+  if ( stationType == AliMp::kStation345 ) 
+  {
+    const AliMpSlatSegmentation* seg = static_cast<const AliMpSlatSegmentation*>(vseg);
+    const AliMpSlat* slat = seg->Slat();
+    return slat->FindMotifPosition(manuId);
+  }
+  else
+  {
+    const AliMpSectorSegmentation* seg = static_cast<const AliMpSectorSegmentation*>(vseg);
+    const AliMpSector* sector = seg->GetSector();
+    return sector->GetMotifMap()->FindMotifPosition(manuId);
+  }
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour* 
+AliMUONPainterContourMaker::GenerateManuContour(const char* name, 
+                                                Int_t detElemId, Int_t manuId,
+                                                AliMUONAttPainter viewType) const
+{  
+  /// Generate the contour for a given manu
+  
+  AliDebug(3,Form("DE %04d ManuID %04d Name %s",detElemId,manuId,name));
+  
+  AliCodeTimerAuto("")
+  
+  AliMpMotifPosition* motifPosition = FindMotifPosition(detElemId,manuId);
+  AliMpVMotif* motif = motifPosition->GetMotif();
+  
+  AliMUONPainterContour* contour = FindLocalManuContour(detElemId,manuId); 
+  // do we already have the local contour for that manu ?
+  
+  // no : build it
+  if  (!contour)
+  {
+    AliCodeTimerAuto("Generation of local contour");
+    TObjArray ePads;
+    ePads.SetOwner(kTRUE);
+    AliMpMotifType* motifType = motif->GetMotifType();
+    AliDebug(3,Form("motifType %s",motifType->GetID().Data()));
+    
+//    for ( Int_t i = 0; i <= motifType->GetNofPads(); ++i ) 
+    for ( Int_t i = 0; i <= AliMpConstants::ManuNofChannels(); ++i ) 
+    {
+//      AliMpConnection* connection = motifType->FindConnectionByPadNum(i);
+      AliMpConnection* connection = motifType->FindConnectionByGassiNum(i);
+
+      AliDebug(3,Form("connection i =%d",i));
+      
+      if ( connection ) 
+      {
+        AliMpIntPair indices = connection->LocalIndices();
+        Bool_t left(kTRUE);
+        Bool_t right(kTRUE);
+        Bool_t top(kTRUE);
+        Bool_t bottom(kTRUE);
+        
+        if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(1,0)) )
+        {
+          right = kFALSE;
+        }
+        if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(-1,0)) )
+        {
+          left = kFALSE;
+        }
+        if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,1)) )
+        {
+          top = kFALSE;
+        }
+        if ( !motifType->FindConnectionByLocalIndices(indices+AliMpIntPair(0,-1)) )
+        {
+          bottom = kFALSE;
+        }
+        
+        AliDebug(3,Form("indices=(%3d,%3d) L %d R %d T %d B %d",
+                        indices.GetFirst(),indices.GetSecond(),
+                        left,right,top,bottom));
+        
+        TVector2 position = motif->PadPositionLocal(indices);
+        TVector2 dimensions = motif->GetPadDimensions(indices);
+
+        if ( !left  || !right || !top  || !bottom )
+        {
+          // the pad is on the edge
+          Int_t id = AliMUONVDigit::BuildUniqueID(detElemId,manuId,
+                                                  connection->GetGassiNum(),0);
+          ePads.AddLast(new AliMUONNeighbour(id,position,dimensions,left,right,top,bottom));
+        }
+      }
+    }
+    
+    contour = ConvertEdgePadsToContour(ePads,NameIt(*motifPosition));
+    
+    AliDebug(1,Form("localContour:"));
+//    StdoutToAliDebug(1,contour->Print("full"));
+    // register the local contour
+    fLocalManuContours->Add(new TObjString(contour->GetName()),contour);
+  }
+  
+  AliMUONPainterContour* globalContour = static_cast<AliMUONPainterContour*>(contour->Clone(name));
+  
+  // once we have the local contour, convert it to global
+  
+  TVector2 pos(motifPosition->Position());
+
+  if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 ) 
+  {
+    const AliMpSlat* slat = AliMUONPainterHelper::Instance()->GetSlat(detElemId,manuId);
+    pos -= slat->Position();
+  }
+  globalContour->Offset(pos);
+  TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
+  globalContour->Transform(*matrix);
+
+  if ( viewType.IsBackView() )
+  {
+    AliWarning("Got a back view : will rotate ! This has not been really tested. Please do so now !");
+    TGeoRotation rot;
+    rot.RotateZ(180);
+    globalContour->Transform(rot);
+  }
+  
+  return globalContour;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour*
+AliMUONPainterContourMaker::GetContour(const char* name) const
+{
+  /// Get contour by name
+  
+  TObject* o = fContours->GetValue(name);
+  return static_cast<AliMUONPainterContour*>(o);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterContourMaker::HasContour(const char* name) const
+{
+  /// Whether contour named "name" exists
+  TObject* o = fContours->GetValue(name);
+  if (o) return kTRUE;
+  return kFALSE;
+}
+
+//_____________________________________________________________________________
+TLine* 
+AliMUONPainterContourMaker::InsertSegment(TPolyLine& lines, TLine& l) const
+{
+  /// Insert line into polyline, at the correct position
+  
+  AliCodeTimerAuto("")
+//  AliDebug(2,Form("Trying to insert %7.3f,%7.3f -> %7.3f,%7.3f from "
+//                  "(DE,manu,ch)=(%d,%d,%d) into",
+//                  l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2(),
+//                  AliMUONVDigit::DetElemId(l.GetUniqueID()),
+//                  AliMUONVDigit::ManuId(l.GetUniqueID()),
+//                  AliMUONVDigit::ManuChannel(l.GetUniqueID())));
+  
+  if ( lines.Size()==0 ) 
+  {
+//    AliDebug(2,"Starting line");
+//    
+    lines.SetNextPoint(l.GetX1(),l.GetY1());
+    lines.SetNextPoint(l.GetX2(),l.GetY2());
+    return &l;
+  }
+  
+  Int_t i1 = FindPoint(lines,l.GetX1(),l.GetY1());
+  Int_t i2 = FindPoint(lines,l.GetX2(),l.GetY2());
+  
+  if ( i1 < 0 && i2 < 0 ) 
+  {
+//    AliDebug(2,"Not yet");
+    return 0x0;
+  }
+  
+  if ( i1 >= 0 && i2 >= 0 )
+  {
+    if ( i1==0 )
+    {
+      lines.SetNextPoint(l.GetX1(),l.GetY1());
+    }
+    else if ( i2==0 )
+    {
+      lines.SetNextPoint(l.GetX2(),l.GetY2());
+    }
+    else
+    {
+      AliError("Segment already there but does not correspond to ending the polyline !");
+      AliError(Form("Segment is %7.3f,%7.3f -> %7.3f,%7.3f and existing points are : ",
+                    l.GetX1(),l.GetY1(),l.GetX2(),l.GetY2()));
+                      
+      for ( Int_t i = 0; i < lines.Size(); ++i ) 
+      {
+        AliError(Form("Point %2d X %7.3f Y %7.3f",i,lines.GetX()[i],lines.GetY()[i]));
+      }
+//      TObject* o(0x0);
+//      o->Print(); // to crash and throw gdb...
+    }
+    return &l;
+  }
+  
+  Double_t x = (i1>=0) ? l.GetX2() : l.GetX1();
+  Double_t y = (i1>=0) ? l.GetY2() : l.GetY1();
+  
+  Int_t iref = ( i1 >= 0 ? i1 : i2 ) ;
+  
+  Bool_t firstPoint = ( iref == 0 );
+  
+  if ( firstPoint ) 
+  {
+    // must insert segment before
+    lines.SetPolyLine(lines.Size()+1);
+//    AliDebug(2,Form("Inserting %7.3f,%7.3f",x,y));
+    for ( Int_t i = lines.Size()-1; i > 0; --i ) 
+    {
+      lines.SetPoint(i,lines.GetX()[i-1],lines.GetY()[i-1]);
+    }
+    lines.SetPoint(0,x,y);
+  }
+  else
+  {
+//    AliDebug(2,Form("Appending %7.3f,%7.3f",x,y));
+    lines.SetNextPoint(x,y);
+  }
+  
+  return &l;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsEqual(Double_t x, Double_t y) const
+{
+  /// Whether x==y
+  
+  if ( TMath::Abs(x-y) < AliMpConstants::LengthTolerance() ) return kTRUE;
+  else return kFALSE;      
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsEqual(const TLine& line1,
+                                    const TLine& line2) const
+{
+  /// Whether line1 == line2
+  
+  Bool_t check1 =  
+    IsEqual(line1.GetX1(),line2.GetX1()) && 
+    IsEqual(line1.GetY1(),line2.GetY1()) &&
+    IsEqual(line1.GetX2(),line2.GetX2()) &&
+    IsEqual(line1.GetY2(),line2.GetY2());
+  
+  Bool_t check2 =  
+    IsEqual(line1.GetX1(),line2.GetX2()) && 
+    IsEqual(line1.GetY1(),line2.GetY2()) &&
+    IsEqual(line1.GetX2(),line2.GetX1()) &&
+    IsEqual(line1.GetY2(),line2.GetY1());
+  
+  return (check1 || check2);
+}
+
+//_____________________________________________________________________________
+Double_t 
+AliMUONPainterContourMaker::Slope(const TLine& line) const
+{
+  /// Get the slope of line
+  
+  Double_t x = TMath::Abs(line.GetX2() - line.GetX1());
+  
+  if ( x  < AliMpConstants::LengthTolerance() ) return FLT_MAX;
+  
+  return TMath::Abs(line.GetY2() - line.GetY1())/x;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsPoint(const TLine& line) const
+{
+  /// Whether the line is a point (sic ;-) )
+  return 
+  IsEqual(line.GetX1(),line.GetX2()) && 
+  IsEqual(line.GetY1(),line.GetY2());
+}
+
+//_____________________________________________________________________________
+TLine
+AliMUONPainterContourMaker::Shift(const TLine& line, Double_t x, Double_t y) const
+{
+  /// Shift the line by a given offset
+  
+  return TLine(line.GetX1()-x,line.GetY1()-y,line.GetX2()-x,line.GetY2()-y);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterContourMaker::SameDirection(const TLine& line1, const TLine& line2) const
+{
+  /// Whether both lines have the same direction.
+  
+  TLine l1 = Shift(line1,line1.GetX1(),line1.GetY1());
+  TLine l2 = Shift(line2,line2.GetX1(),line2.GetY1());
+  
+  Double_t v = l1.GetX2()*l2.GetX2() + l1.GetY2()*l2.GetY2();
+  
+  return v > 0 ;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContourMaker::Swap(TLine& line) const
+{
+  /// Swap both points of the line
+  
+  Double_t x = line.GetX1();
+  Double_t y = line.GetY1();
+  
+  line.SetX1(line.GetX2());
+  line.SetY1(line.GetY2());
+  line.SetX2(x);
+  line.SetY2(y);
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::IsInRange(Double_t x, Double_t a, Double_t b,
+                                      Bool_t strict) const
+{
+  /// Whether w is in [a,b] (if strict=kFALSE) or in ]a,b[ (if strict=kTRUE)
+  
+  if ( a > b ) 
+  {
+    Double_t tmp(b);
+    b = a;
+    a = tmp;
+  }
+  
+  Bool_t rv(kFALSE);
+  
+  if ( strict )  
+  {
+    rv = ( x > a && x < b );
+  }
+  else
+  {
+    rv = ( x >= a && x <= b);
+  }
+
+  AliDebug(4,Form("x = %7.3f a = %7.3f b = %7.3f strict = %d IsInRange = %d",x,a,b,strict,rv));
+  
+  return rv;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterContourMaker::IsInLine(const TLine& line,
+                                     Double_t x,
+                                     Double_t y,
+                                     Bool_t strict) const
+{
+  /// Check whether point (x,y) is belonging to the line segment
+  /// by computing the distance point to line
+  /// line1 must not be a single point.
+  /// Returns the number of *coordinates* that matches, for a point
+  /// that lies on line (if point is not on the line, returns 0 always).
+  /// For instance, if (x,y) is on the line (and strict=kFALSE), 
+  /// it will return 1 if x *or* y corresponds to line.GetX1() or X2 or Y1 or Y2,
+  /// and 2 if the pair (x,y) corresponds to one of the line points.
+  
+  Double_t x1 = line.GetX1();
+  Double_t x2 = line.GetX2();
+  Double_t y1 = line.GetY1();
+  Double_t y2 = line.GetY2();
+  
+  Double_t distance = TMath::Abs( (x2-x1)*(y1-y) - (x1-x)*(y2-y1) );
+  
+  distance /= TMath::Sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
+  
+  Bool_t online = ( distance < AliMpConstants::LengthTolerance() ) ;
+  
+  Int_t rv(0);
+  
+  if (online)
+  {
+    // point is on the line, 
+    // check in addition that it's within the segment
+    
+    rv = IsInRange(x,x1,x2,strict) + IsInRange(y,y1,y2,strict);
+  }
+  else
+  {
+    rv = 0;
+  }
+  
+  AliDebug(4,Form("Point (%7.3f,%7.3f) isinline=%d in line %s",
+                  x,y,rv,LineAsString(line).Data()));
+  
+  return rv;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterContourMaker::IsInside(const TLine& line1,
+                                     const TLine& line2,
+                                     Bool_t useEndPoints) const
+{
+  /// Check whether one or both points of line2 are within line1.
+  /// Both line1 and line2 must have the same slope 
+  /// and the same direction
+
+  if (!IsEqual(Slope(line1),Slope(line2))) return 0;
+  
+  TLine l2(line2);
+  
+  if (!SameDirection(line1,line2)) 
+  {
+    Swap(l2);
+  }
+      
+  Int_t rv = 
+    IsInLine(line1,l2.GetX1(),l2.GetY1(),!useEndPoints) +
+    IsInLine(line1,l2.GetX2(),l2.GetY2(),!useEndPoints);
+  
+  assert(rv<=4);
+  
+  return rv;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsInside(const TObjArray& segments, 
+                                     const TLine& line) const
+{
+  /// Whether the segment (line) is contained inside the contour defined
+  /// by all the segments (i.e. is it on the boundary or not)
+  /// Basic (and dirty) implementation only working with horizontal and vertical lines.
+  /// I know there must be a better way to do it, but it took me way too long
+  /// to get this stuff working, so I'm giving up on the optimisation/cleaning,
+  /// at least for now...
+  /// If you'd like to clean this (while keeping it working in all cases), be
+  /// my guest and do it ;-) )
+  
+  Int_t p1 = CountPoint(segments,line.GetX1(),line.GetY1());
+  Int_t p2 = CountPoint(segments,line.GetX2(),line.GetY2());
+  
+  Bool_t triplet = ( p1 >= 3 || p2 >= 3 );
+  
+  AliDebug(4,Form("IsInside(segments,%s) triplet=%d",
+                  LineAsString(line).Data(),triplet));
+  
+  if (!triplet) return kFALSE;
+    
+  Bool_t top(kFALSE), bottom(kFALSE), left(kFALSE), right(kFALSE);
+  
+  Bool_t vertical(IsVertical(line));
+  Bool_t horizontal(IsHorizontal(line));
+  
+  if (!vertical && !horizontal ) 
+  {
+    AliFatal("Only working with horizontal and vertical lines");
+  }
+  
+  for ( Int_t i = 0; i <= segments.GetLast(); ++i ) 
+  {
+    TLine* l = static_cast<TLine*>(segments.UncheckedAt(i));
+    
+    if ( IsEqual(*l,line) ) continue;
+    
+    if ( vertical && IsVertical(*l) )
+    {
+      TLine tmpLine(l->GetX1(),line.GetY1(),
+                    l->GetX1(),line.GetY2());
+      
+      AliDebug(4,Form("i=%2d VV\nIsInside(l=%s,%s)=%d\nIsInside(%s,l=%s)=%d",
+                      i,
+                      LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
+                      IsInside(*l,tmpLine,kTRUE),
+                      LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
+                      IsInside(tmpLine,*l,kTRUE)));
+                      
+      if ( IsInside(*l,tmpLine,kTRUE) == 4 || IsInside(tmpLine,*l,kTRUE) == 4 ) 
+      {
+        if ( l->GetX1() > line.GetX1() ) 
+        {
+          right = kTRUE;
+        }
+        else
+        {
+          left = kTRUE;
+        }
+      }
+    }
+    
+    if ( vertical && IsHorizontal(*l) )
+    {
+      if ( !IsEqual(l->GetY1(),line.GetX1()) && 
+           !IsEqual(l->GetY1(),line.GetY2()) &&
+           IsInLine(*l,line.GetX1(),l->GetY1(),kFALSE)==2 )
+        {
+        if ( line.GetY2() < l->GetY1() ) 
+        {
+          top = kTRUE;
+        }
+        else if ( line.GetY2() > l->GetY1() )
+        {
+          bottom = kTRUE;
+        }
+      }
+    }
+    
+    if ( horizontal && IsHorizontal(*l) )
+    {
+      TLine tmpLine(line.GetX1(),l->GetY1(),
+                    line.GetX2(),l->GetY1());
+      
+      AliDebug(4,Form("i=%2d HH\nIsInside(%s,%s)=%d\nIsInside(%s,%s)=%d",
+                      i,
+                      LineAsString(*l).Data(),LineAsString(tmpLine).Data(),
+                      IsInside(*l,tmpLine),
+                      LineAsString(tmpLine).Data(),LineAsString(*l).Data(),
+                      IsInside(tmpLine,*l)));
+      
+      if ( IsInside(*l,tmpLine) == 4 || IsInside(tmpLine,*l) == 4 ) 
+      {
+        if ( l->GetY1() > line.GetY1() ) 
+        {
+          top = kTRUE;
+        }
+        else
+        {
+          bottom = kTRUE;
+        }
+      }
+    }
+    
+    if ( horizontal && IsVertical(*l) )
+    {
+      if ( !IsEqual(l->GetX1(),line.GetX1()) && 
+           !IsEqual(l->GetX1(),line.GetX2()) &&
+           IsInLine(*l,l->GetX1(),line.GetY1(),kFALSE)==2 )
+        {
+        if ( line.GetX2() < l->GetX1() ) 
+        {
+          right = kTRUE;
+        }
+        else if ( line.GetX2() > l->GetX1() )
+        {
+          left = kTRUE;
+        }
+      }
+    }
+    
+  }
+  
+  Bool_t rv(kFALSE);
+
+  AliDebug(3,Form("%s %s R %d L %d T %d B% d IsInside %d",
+                  IsVertical(line) ? 
+                  "Vertical  " : 
+                  "Horizontal",
+                  LineAsString(line,kFALSE).Data(),right,left,top,bottom,rv));
+
+  if ( vertical ) 
+  {
+    rv = (right && left) && ( top || bottom );
+  }
+  
+  if ( horizontal ) 
+  {
+    rv = (top && bottom) && ( right || left );
+  }
+  
+  return rv;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsHorizontal(const TLine& line) const
+{
+  /// whether line is horizontal
+  
+  static Double_t l2 = AliMpConstants::LengthTolerance()*AliMpConstants::LengthTolerance();
+  
+  return ( Slope(line) < l2 );
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsVertical(const TLine& line) const
+{
+  /// whether line is vertical
+  
+  return ( TMath::Abs(Slope(line)) == FLT_MAX );
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::Overlap(const TLine& line1,
+                                    const TLine& line2) const
+{
+  /// Whether line1 and line2 overlap
+  
+  Int_t rv(0);
+  
+  if ( IsEqual(line1,line2) ) 
+  {
+    // First things first. If both lines are the same one, 
+    // they for sure overlap ;-)
+    rv = 4;
+  }
+  else
+  {
+    rv = IsInside(line1,line2) + IsInside(line2,line1);
+  }
+  
+  AliDebug(3,Form("%s and %s : overlap=%d",
+                  LineAsString(line1).Data(),
+                  LineAsString(line2).Data(),
+                  rv));
+  
+  return rv;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterContourMaker::IsLineClosed(const TPolyLine& line) const
+{
+  /// check if polyline is already closed (i.e. last point = first point)
+  
+  Double_t* x = line.GetX();
+  Double_t* y = line.GetY();
+  
+  if ( IsEqual(x[line.GetLastPoint()],x[0]) &&
+       IsEqual(y[line.GetLastPoint()],y[0]) )
+  {
+    return kTRUE;
+  }
+  else
+  {
+    return kFALSE;
+  }
+}  
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterContourMaker::Local2Global(Int_t detElemId, 
+                                         Double_t xl, Double_t yl, Double_t zl,
+                                         Double_t& xg, Double_t& yg, Double_t& zg) const
+{
+  /// Convert local coordinates to global ones
+  TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fGlobalTransformations->GetValue(detElemId));
+  Double_t pl[3] = { xl, yl, zl };
+  Double_t pg[3] = { 0., 0., 0. };
+  matrix->LocalToMaster(pl, pg);
+  xg = pg[0];
+  yg = pg[1];
+  zg = pg[2];
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterContourMaker::Print(Option_t* opt) const
+{
+  /// Printout
+  
+  cout << "Local Contours" << endl;
+  
+  TIter next(fLocalManuContours);
+  TObjString* key;
+  
+  while ( ( key = static_cast<TObjString*>(next()) ) )
+  {
+    cout << key->String().Data() << endl;
+    AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fLocalManuContours->GetValue(key));
+    contour->Print(opt);
+  }
+
+  cout << "Global Contours" << endl;
+  
+  TIter nextC(fContours);
+  
+  while ( ( key = static_cast<TObjString*>(nextC()) ) )
+  {
+    AliMUONPainterContour* contour = static_cast<AliMUONPainterContour*>(fContours->GetValue(key));
+    contour->Print(opt);
+  }
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::CountPoint(const TObjArray& segments, 
+                                       Double_t x, Double_t y) const
+{
+  /// Count the number of times the point (x,y) appears in the segment array
+  
+  Int_t n(0);
+  
+  for ( Int_t i = 0; i <= segments.GetLast(); ++i ) 
+  {
+    TLine* line = static_cast<TLine*>(segments.UncheckedAt(i));
+      
+    if ( IsEqual(x,line->GetX1()) &&
+         IsEqual(y,line->GetY1()) )
+    {
+      ++n;
+    }
+  
+    if ( IsEqual(x,line->GetX2()) &&
+         IsEqual(y,line->GetY2()) )
+    {
+      ++n;
+    }
+  }
+  
+  return n;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterContourMaker::SanityCheck(const TObjArray& contours,
+                                        const TObjArray& segments, Bool_t check) const
+{
+  /// (debug) check 
+  
+  Bool_t ok(kTRUE);
+
+  // cross-check that we have no more complete duplicates
+  // and that we have no orphan point
+
+  Double_t xmin(FLT_MAX), xmax(-FLT_MAX);
+  Double_t ymin(FLT_MAX), ymax(-FLT_MAX);
+  
+  for ( Int_t i = 0; i <= segments.GetLast(); ++i ) 
+  {
+    TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
+  
+    if (!IsHorizontal(*li) && !IsVertical(*li))
+    {
+      AliError("Got an oblique line !");
+      return kFALSE;
+    }
+    
+    xmin = TMath::Min(xmin,li->GetX1());
+    xmin = TMath::Min(xmin,li->GetX2());
+
+    xmax = TMath::Max(xmax,li->GetX1());
+    xmax = TMath::Max(xmax,li->GetX2());
+
+    ymin = TMath::Min(ymin,li->GetY1());
+    ymin = TMath::Min(ymin,li->GetY2());
+    
+    ymax = TMath::Max(ymax,li->GetY1());
+    ymax = TMath::Max(ymax,li->GetY2());
+    
+  }
+  
+  AliDebug(1,Form("xmin=%7.3f ymin=%7.3f xmax=%7.3f ymax=%7.3f",
+                  xmin,ymin,xmax,ymax));
+  
+  for ( Int_t i = 0; i <= segments.GetLast(); ++i ) 
+  {
+    TLine* li = static_cast<TLine*>(segments.UncheckedAt(i));
+
+    if (!check) 
+    {
+      for ( Int_t j = 0; j <= segments.GetLast(); ++j ) 
+      {
+        TLine* lj = static_cast<TLine*>(segments.UncheckedAt(j));
+
+        if ( i != j && IsEqual(*li,*lj) )
+        {
+          ok = kFALSE;
+          PrintLine(*li);
+          PrintLine(*lj);
+          AliFatal("");
+        }      
+      }
+    }
+    
+
+    Int_t rv(0);
+    
+    Double_t x = (li->GetX1()+li->GetX2())/2.0;
+    Double_t y = (li->GetY1()+li->GetY2())/2.0;
+    
+    if ( ShouldBeRemoved(contours,x,y) ) rv = 1;
+    
+    AliDebug(1,Form("Line %4d %7.3f,%7.3f -> %7.3f,%7.3f [ %d ]",
+                    i,
+                    li->GetX1(),li->GetY1(),
+                    li->GetX2(),li->GetY2(),
+                    rv));
+  }
+  
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+TPolyLine*
+AliMUONPainterContourMaker::Simplify(const TPolyLine& lines) const
+{
+  /// try to simplify the polyline, by minimizing the number of points
+
+  if ( lines.Size() < 3 ) 
+  {
+    AliError("Cannot simplify lines with less that 3 points !");
+    return 0x0;
+  }
+  
+  AliCodeTimerAuto("")
+  
+//  cout << "Before simplify" << endl;
+//  
+//  for ( Int_t i = 0; i < lines.Size(); ++i ) 
+//  {
+//    cout << Form("Point %3d %7.3f %7.3f",i,lines.GetX()[i],lines.GetY()[i]) << endl;
+//  }
+  
+  TPolyLine* l = new TPolyLine;
+
+  Double_t* x = lines.GetX();
+  Double_t* y = lines.GetY();
+
+  l->SetNextPoint(x[0],y[0]);
+
+  Bool_t verticalCurrent = IsEqual(x[1],x[0]);
+  Bool_t horizontalCurrent = IsEqual(y[1],y[0]);
+
+  Int_t i(2);
+
+  while ( i < lines.Size() )
+  {
+    Bool_t vertical = IsEqual(x[i],x[i-1]);
+    Bool_t horizontal = IsEqual(y[i],y[i-1]);
+    
+//    cout << Form("i %3d %7.3f %7.3f vert %d horiz %d (current vert %d horiz %d)",
+//                 i,x[i],y[i],vertical,horizontal,verticalCurrent,horizontalCurrent)
+//      << endl;
+    
+    if ( ( vertical != verticalCurrent ) || 
+         ( horizontal != horizontalCurrent ) )
+    {
+//      cout << Form("Changing direction : adding point %7.3f %7.3f",x[i-1],y[i-1]) << endl;
+      l->SetNextPoint(x[i-1],y[i-1]);
+      verticalCurrent = vertical;
+      horizontalCurrent = horizontal;
+    }
+    ++i;
+  }
+  
+  l->SetNextPoint(l->GetX()[0],l->GetY()[0]);
+  
+//  cout << "After simplify" << endl;
+//  
+//  for ( Int_t i = 0; i < l->Size(); ++i ) 
+//  {
+//    cout << Form("Point %3d %7.3f %7.3f",i,l->GetX()[i],l->GetY()[i]) << endl;
+//  }
+  
+  return l;
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterContourMaker::Size() const
+{
+  /// Number of contours we have already
+  
+  return fContours->GetSize();
+}
+                                         
diff --git a/MUON/AliMUONPainterContourMaker.h b/MUON/AliMUONPainterContourMaker.h
new file mode 100644 (file)
index 0000000..2206897
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef ALIMUONPAINTERCONTOURMAKER_H
+#define ALIMUONPAINTERCONTOURMAKER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterContourMaker
+/// \brief Utility class to build painter contours
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TVector2
+#  include "TVector2.h"
+#endif
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+
+class AliMpExMap;
+class AliMpMotifPosition;
+class AliMUONAttPainter;
+class AliMUONPainterContour;
+class AliMUONPainterPadStore;
+class TArrayI;
+class TMap;
+#include <TLine.h>
+class TPolyLine;
+class TObjArray;
+
+class AliMUONPainterContourMaker : public TObject
+{
+public:
+  AliMUONPainterContourMaker(AliMpExMap* globalTransformations=0x0);
+  virtual ~AliMUONPainterContourMaker();
+  
+  void Add(AliMUONPainterContour* contour);
+  
+  AliMUONPainterContour* FindLocalManuContour(Int_t detElemId, Int_t manuId) const;
+  
+  AliMUONPainterContour* GetContour(const char* name) const;
+
+  AliMUONPainterContour* GenerateManuContour(const char* name,
+                                             Int_t detElemId,
+                                             Int_t manuId,
+                                             AliMUONAttPainter viewType) const;
+
+  Bool_t HasContour(const char* name) const;
+
+  AliMUONPainterContour* MergeContours(const TObjArray& contours,
+                                       const char* contourName) const;
+  
+  Int_t Size() const;
+  
+  void Print(Option_t* opt="") const;
+  
+public:
+    
+  class AliMUONNeighbour : public TObject
+  {
+public:
+    AliMUONNeighbour()
+    : fID(-1), fPosition(), fDimensions(), 
+    fLeft(kFALSE), fRight(kFALSE), 
+    fTop(kFALSE), fBottom(kFALSE) {}
+    
+    AliMUONNeighbour(Int_t absID, 
+              const TVector2& position, 
+              const TVector2& dimensions,
+              Bool_t hasLeftNeighbour, Bool_t hasRightNeighbour,
+              Bool_t hasTopNeighbour, Bool_t hasBottomNeighbour)
+    : fID(absID), fPosition(position), fDimensions(dimensions), 
+    fLeft(hasLeftNeighbour), fRight(hasRightNeighbour), 
+      fTop(hasTopNeighbour), fBottom(hasBottomNeighbour) {}
+
+    virtual ~AliMUONNeighbour() {}
+    
+    virtual Bool_t IsSortable() const { return kTRUE; }
+    
+    virtual Int_t Compare(const TObject* object) const;
+    
+    Int_t ID() const { return fID; }
+    Bool_t HasLeftNeighbour() const { return fLeft; }
+    Bool_t HasRightNeighbour() const { return fRight; }
+    Bool_t HasTopNeighbour() const { return fTop; }
+    Bool_t HasBottomNeighbour() const { return fBottom; }
+    
+    TVector2 Position() const { return fPosition; }
+    TVector2 Dimensions() const { return fDimensions; }
+    
+    TVector2 LowerLeft() const { return fPosition - fDimensions; }
+    TVector2 UpperRight() const { return fPosition + fDimensions; }
+    
+    void Print(Option_t* opt="") const;
+    
+    void SetPosition(Double_t x, Double_t y) { fPosition.Set(x,y); }
+    
+private:
+    Int_t fID; ///< id of the pad
+    TVector2 fPosition; ///< position
+    TVector2 fDimensions; ///< (half)dimension
+    Bool_t fLeft; ///< do we have a neighbour on our left ?
+    Bool_t fRight; ///< do we have a neighbour on our right ?
+    Bool_t fTop; ///< do we have a neighbour on top of us ?
+    Bool_t fBottom; ///< do we have a neighbour below us ?
+    
+    ClassDef(AliMUONNeighbour,1) // Neighbour internal class
+  };
+    
+private:
+    /// not implemented
+    AliMUONPainterContourMaker(const AliMUONPainterContourMaker& rhs);
+  /// not implemented
+  AliMUONPainterContourMaker& operator=(const AliMUONPainterContourMaker& rhs);
+
+public:
+    
+
+  void AddSegments(TObjArray& segments, const AliMUONPainterContour& contour) const;
+
+  void AddSegment(TObjArray& segments, Double_t x1, Double_t y1,
+                    Double_t x2, Double_t y2, Int_t padID) const;
+  
+  TLine* AddToLine(TPolyLine& line, TObjArray& segments, Int_t i) const;
+
+  AliMpMotifPosition* FindMotifPosition(Int_t detElemId, Int_t manuId) const;
+  
+  Int_t FindPoint(const TPolyLine& lines, Double_t x, Double_t y) const;
+  
+  Int_t FindPoint(Double_t x, Double_t y, TObjArray& segments) const;
+
+  TLine* InsertSegment(TPolyLine& lines, TLine& l) const;
+
+  using TObject::IsEqual;
+  
+  Bool_t IsEqual(Double_t x, Double_t y) const;
+
+  Int_t Overlap(const TLine& line1, const TLine& line2) const;
+
+  Bool_t IsLineClosed(const TPolyLine& line) const;
+  
+  AliMUONPainterContour* ConvertEdgePadsToContour(TObjArray& edgePads, const char* name) const;
+  
+  AliMUONPainterContour* ConvertSegmentsToContour(TObjArray& segments, const char* name) const;
+  
+  void Local2Global(Int_t detElemId, Double_t xl, Double_t yl, Double_t zl,
+                    Double_t& xg, Double_t& yg, Double_t& zg) const;
+    
+  TString NameIt(const AliMpMotifPosition& motifPosition) const;
+
+  TPolyLine* Simplify(const TPolyLine& lines) const;
+
+  Double_t Slope(const TLine& line) const;
+
+  Bool_t IsPoint(const TLine& line) const;
+
+  void PrintLine(const TLine& line, const char* msg="") const;
+
+  void PrintSegments(const TObjArray& segments) const;
+    
+  Bool_t SameDirection(const TLine& line1, const TLine& line2) const;
+
+  void Swap(TLine& line) const;
+  
+  TLine Shift(const TLine& line, Double_t x, Double_t y) const;
+
+  Int_t IsInside(const TLine& line1, const TLine& line2,
+                 Bool_t useEndPoints=kFALSE) const;
+    
+  Bool_t IsInside(const TObjArray& segments, const TLine& line) const;
+    
+  Int_t IsInLine(const TLine& line, Double_t x, Double_t y, 
+                 Bool_t strict=kTRUE) const;
+  
+  Bool_t IsEqual(const TLine& line1, const TLine& line2) const;
+    
+  Bool_t SanityCheck(const TObjArray& contours, const TObjArray& segments, Bool_t check=kTRUE) const;
+  
+  TString LineAsString(const TLine& line, Bool_t slope=kTRUE) const;
+  
+  Int_t IsInRange(Double_t x, Double_t a, Double_t b, 
+                  Bool_t strict=kTRUE) const;
+  
+  Bool_t HasLine(const TObjArray& segments, const TLine& line) const;
+    
+  void CleanSegments(TObjArray& segments, const TArrayI& toBeRemoved) const;
+    
+  Int_t SplitSegments(TObjArray& segments) const;
+
+  Int_t RemoveInsideSegments(const TObjArray& contours, TObjArray& segments) const;
+      
+  Bool_t IsHorizontal(const TLine& line) const;
+
+  Bool_t IsVertical(const TLine& line) const;
+    
+  Int_t CountPoint(const TObjArray& segments, Double_t x, Double_t y) const;
+    
+  Bool_t ShouldBeRemoved(const TObjArray& contours, Double_t x, Double_t y) const;
+    
+private:
+  AliMpExMap* fGlobalTransformations; ///< store of global transformations for DEs
+  TMap* fLocalManuContours; ///< store for local contours of all manus
+  TMap* fContours; ///< store for all our contours
+  
+  ClassDef(AliMUONPainterContourMaker,1) // Painter contour builder
+};
+
+#endif
+
diff --git a/MUON/AliMUONPainterDataSourceFrame.cxx b/MUON/AliMUONPainterDataSourceFrame.cxx
new file mode 100644 (file)
index 0000000..cb7cd7a
--- /dev/null
@@ -0,0 +1,416 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterDataSourceFrame.h"
+
+#include "AliMUONPainterDataSourceItem.h"
+#include "AliMUONPainterEnv.h"
+#include "AliMUONPainterHelper.h"
+#include "AliMUONPainterRegistry.h"
+#include "AliMUONTrackerOCDBDataMaker.h"
+#include "AliMUONTrackerRawDataMaker.h"
+#include "AliMUONVTrackerDataMaker.h"
+#include "AliLog.h"
+#include "AliRawReaderDate.h"
+#include "AliRawReaderRoot.h"
+#include <TGButton.h>
+#include <TGComboBox.h>
+#include <TGFileDialog.h>
+#include <TGNumberEntry.h>
+#include <TGTextEntry.h>
+#include <TGrid.h>
+#include <TObjArray.h>
+#include <TObjString.h>
+#include <TRegexp.h>
+#include <TString.h>
+#include <TSystem.h>
+
+///\class AliMUONPainterDataSourceFrame
+///
+/// A complete frame to select and display various data sources to 
+/// be displayed : either raw data or OCDB data. 
+/// Later on we might add digits and clusters for instance.
+///
+///\author Laurent Aphecetche, Subatech
+
+const char* AliMUONPainterDataSourceFrame::fgkNumberOfDataSourcesKey = "NumberOfDataSources";
+const char* AliMUONPainterDataSourceFrame::fgkDataSourceURIKey = "DataSourceURI.%d";
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterDataSourceFrame)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterDataSourceFrame::AliMUONPainterDataSourceFrame(const TGWindow* p, UInt_t w, UInt_t h)
+: TGCompositeFrame(p,w,h,kVerticalFrame),
+  fRecentSourceSelector(new TGGroupFrame(p,"Recent sources",kHorizontalFrame)),
+  fRawSelector(new TGGroupFrame(p,"Raw file URI",kHorizontalFrame)),
+  fOCDBSelector(new TGGroupFrame(p,"OCDB Path",kHorizontalFrame)),
+  fDataReaders(new TGGroupFrame(p,"Data sources")),
+  fFilePath(new TGTextEntry(fRawSelector,"")),
+  fRawOCDBPath(new TGTextEntry(fRawSelector,"")),
+  fOCDBPath(new TGTextEntry(fOCDBSelector,"")),
+  fRunSelector(new TGNumberEntry(fOCDBSelector,0)),
+  fOCDBTypes(new TGComboBox(fOCDBSelector)),
+  fRecentSources(new TGComboBox(fRecentSourceSelector)),
+  fItems(new TObjArray)
+{
+  /// Ctor
+  
+    AliMUONPainterRegistry* reg = AliMUONPainterRegistry::Instance();
+    
+    reg->Connect("DataReaderWasRegistered(AliMUONVTrackerDataMaker*)",
+                 "AliMUONPainterDataSourceFrame",
+                 this,
+                 "DataReaderWasRegistered(AliMUONVTrackerDataMaker*)");
+    
+    reg->Connect("DataReaderWasUnregistered(AliMUONVTrackerDataMaker*)",
+                 "AliMUONPainterDataSourceFrame",
+                 this,
+                 "DataReaderWasUnregistered(AliMUONVTrackerDataMaker*)");
+    
+    fItems->SetOwner(kFALSE);
+    
+    /// Recent source selection
+    
+    AliMUONPainterEnv* env = AliMUONPainterHelper::Instance()->Env();
+    
+    Int_t nsources = env->Integer(fgkNumberOfDataSourcesKey);
+    
+    for ( Int_t i = 0; i < nsources; ++i )
+    {
+      AddRecentSource(env->String(Form(fgkDataSourceURIKey,i)));
+    }
+
+    fRecentSources->Resize(100,20);
+    
+    TGButton* createRecentButton = new TGTextButton(fRecentSourceSelector,"Create data source");
+    createRecentButton->Connect("Clicked()",
+                                "AliMUONPainterDataSourceFrame",
+                                this,
+                                "OpenRecentSource()");
+    
+    fRecentSourceSelector->AddFrame(fRecentSources,new TGLayoutHints(kLHintsExpandX | kLHintsTop,5,5,5,5));
+    fRecentSourceSelector->AddFrame(createRecentButton,new TGLayoutHints(kLHintsTop,5,5,5,5));
+                                    
+    /// Raw file selection
+    
+    TGButton* openButton = new TGPictureButton(fRawSelector,
+                                           gClient->GetPicture("fileopen.xpm"));
+    openButton->SetToolTipText("Click to open file dialog");
+                                        
+    TGButton* createRawButton = new TGTextButton(fRawSelector,"Create data source");
+    
+    fRawSelector->AddFrame(fFilePath, new TGLayoutHints(kLHintsExpandX | kLHintsTop,5,5,5,5));
+    fRawSelector->AddFrame(fRawOCDBPath, new TGLayoutHints(kLHintsTop,5,5,5,5));
+    fRawSelector->AddFrame(openButton,new TGLayoutHints(kLHintsTop,5,5,5,5));
+    fRawSelector->AddFrame(createRawButton,new TGLayoutHints(kLHintsTop,5,5,5,5));
+    
+    openButton->Connect("Clicked()",
+                        "AliMUONPainterDataSourceFrame",
+                        this,
+                        "OpenFileDialog()");
+
+    createRawButton->Connect("Clicked()",
+                        "AliMUONPainterDataSourceFrame",
+                        this,
+                        "CreateRawDataSource()");
+    
+    /// OCDB selection
+    
+    fOCDBTypes->AddEntry("Pedestals",0);
+    fOCDBTypes->AddEntry("Gains",1);
+    fOCDBTypes->AddEntry("Capacitances",2);
+    fOCDBTypes->Select(0);
+    fOCDBTypes->Resize(100,20);
+    
+    TGButton* createOCDBButton = new TGTextButton(fOCDBSelector,"Create data source");
+    createOCDBButton->Connect("Clicked()",
+                             "AliMUONPainterDataSourceFrame",
+                             this,
+                             "CreateOCDBDataSource()");
+    
+    
+    fOCDBSelector->AddFrame(fOCDBPath,new TGLayoutHints(kLHintsExpandX | kLHintsTop,5,5,5,5));    
+    fOCDBSelector->AddFrame(fRunSelector,new TGLayoutHints(kLHintsTop,5,5,5,5));
+    fOCDBSelector->AddFrame(fOCDBTypes,new TGLayoutHints(kLHintsExpandX | kLHintsTop,5,5,5,5));
+    fOCDBSelector->AddFrame(createOCDBButton,new TGLayoutHints(kLHintsTop,5,5,5,5));
+
+    AddFrame(fRecentSourceSelector,new TGLayoutHints(kLHintsExpandX,10,10,10,10));
+
+    AddFrame(fRawSelector,new TGLayoutHints(kLHintsExpandX,10,10,10,10));
+
+    AddFrame(fOCDBSelector,new TGLayoutHints(kLHintsExpandX,10,10,10,10));
+
+    AddFrame(fDataReaders, new TGLayoutHints(kLHintsExpandX,10,10,10,10));
+    
+}
+
+//_____________________________________________________________________________
+AliMUONPainterDataSourceFrame::~AliMUONPainterDataSourceFrame()
+{
+  /// dtor
+  
+  delete fItems;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceFrame::AddRecentSource(const char* name)
+{  
+  /// Add a source to the list of recently used sources
+  
+  TGListBox* lb = fRecentSources->GetListBox();
+  
+  for ( Int_t i = 0; i < lb->GetNumberOfEntries(); ++i ) 
+  {
+    TGTextLBEntry* t = (TGTextLBEntry*)lb->GetEntry(i);
+    TString s(t->GetText()->GetString());
+    if ( s == name ) 
+    {
+      return;
+    }
+  }
+  
+  fRecentSources->AddEntry(name,lb->GetNumberOfEntries());
+  fRecentSources->MapSubwindows();
+  fRecentSources->Layout();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceFrame::CreateOCDBDataSource()
+{
+  /// Create an OCDB data source (using information from the widgets)
+  
+  TString cdbPath = fOCDBPath->GetText();
+  Int_t runNumber = fRunSelector->GetIntNumber();
+  TGTextLBEntry* t = static_cast<TGTextLBEntry*>(fOCDBTypes->GetSelectedEntry());
+  TString type = t->GetText()->GetString();
+  
+  CreateOCDBDataSource(cdbPath,runNumber,type);
+  
+  fOCDBPath->SetText("");
+  fRunSelector->SetNumber(0);  
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceFrame::CreateOCDBDataSource(const TString& uri)
+{
+  /// Create an OCDB data source, given it's URI
+  
+  TObjArray* a = uri.Tokenize(";");
+  TString cdbPath = static_cast<TObjString*>(a->At(1))->String();
+  TString srun = static_cast<TObjString*>(a->At(2))->String();
+  TString type = static_cast<TObjString*>(a->At(3))->String();
+  
+  CreateOCDBDataSource(cdbPath,atoi(srun.Data()),type);
+  
+  delete a;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceFrame::CreateOCDBDataSource(const TString& cdbPath,
+                                                    Int_t runNumber,
+                                                    const TString& type)
+{
+  /// Create an OCDB data source for a given (path,runnumber,type) triplet
+  
+  AliMUONVTrackerDataMaker* reader = new AliMUONTrackerOCDBDataMaker(cdbPath.Data(),
+                                                                       runNumber,
+                                                                       type.Data());
+  
+  if ( reader->IsValid() ) 
+  {
+    AliMUONPainterRegistry::Instance()->Register(reader);
+    
+    AliMUONPainterEnv* env = AliMUONPainterHelper::Instance()->Env();
+    
+    Int_t n = env->Integer(fgkNumberOfDataSourcesKey);
+    
+    env->Set(fgkNumberOfDataSourcesKey,n+1);
+    
+    TString ds(Form("OCDB;%s;%d;%s",cdbPath.Data(),runNumber,type.Data()));
+    
+    env->Set(Form(fgkDataSourceURIKey,n),ds.Data());
+    
+    env->Save();
+    
+    AddRecentSource(ds.Data());
+  }
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterDataSourceFrame::CreateRawDataSource()
+{
+  /// Create a new raw data source (using info from the widgets)
+  
+  TString uri(gSystem->ExpandPathName(fFilePath->GetText()));
+  
+  if ( gSystem->AccessPathName(uri.Data()) )
+  {
+    AliError(Form("File %s does not exist",uri.Data()));
+    fFilePath->SetText("");
+    return;
+  }
+
+  uri = Form("RAW;%s;%s",uri.Data(),fRawOCDBPath->GetText());
+  
+  if ( CreateRawDataSource(uri) )
+  {
+    fFilePath->SetText("");
+    fRawOCDBPath->SetText("");
+  }
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONPainterDataSourceFrame::CreateRawDataSource(const TString& uri)
+{
+  /// Create a new raw data source, given its URI
+  
+  TString filename;
+  TString ocdbPath;
+  
+  TObjArray* a = uri.Tokenize(";");
+  
+  filename = static_cast<TObjString*>(a->At(1))->String();
+  
+  if ( a->GetLast() > 1 ) 
+  {
+    ocdbPath = static_cast<TObjString*>(a->At(2))->String();
+  }
+  
+  AliRawReader* rawReader = 0x0;
+
+  if ( filename.Contains(TRegexp(".root$")) ) 
+  {
+    AliDebug(1,"Using RawReaderRoot");
+    if ( filename.Contains(TRegexp("^alien")) )
+    {
+      // insure we've initialized the grid...
+      if (!gGrid)
+      {
+        TGrid::Connect("alien://");
+      }
+    }
+         
+    rawReader = new AliRawReaderRoot(filename.Data());
+  }
+  else if ( uri.Contains(TRegexp(".raw$")) )
+  {
+    AliDebug(1,"Using RawReaderDate");
+    rawReader = new AliRawReaderDate(filename.Data());
+  }
+  else
+  {
+    AliError(Form("Don't know how to open that file : %s\nURI=%s",filename.Data(),uri.Data()));
+    return kFALSE;
+  }
+  
+  AliMUONTrackerRawDataMaker* reader = new AliMUONTrackerRawDataMaker(rawReader,ocdbPath.Data());
+  
+  reader->SetSource(filename.Data());
+  
+  AliMUONPainterRegistry::Instance()->Register(reader);
+  
+  AliMUONPainterEnv* env = AliMUONPainterHelper::Instance()->Env();
+  
+  Int_t n = env->Integer(fgkNumberOfDataSourcesKey);
+  
+  env->Set(fgkNumberOfDataSourcesKey,n+1);
+  
+  TString ds(Form("RAW;%s;%s",filename.Data(),ocdbPath.Data()));
+  
+  env->Set(Form(fgkDataSourceURIKey,n),ds.Data());
+  
+  AddRecentSource(ds.Data());
+  
+  env->Save();
+
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterDataSourceFrame::DataReaderWasRegistered(AliMUONVTrackerDataMaker* reader)
+{
+  /// Update ourselves as a new data reader was created
+  
+  AliInfo(Form("%s",reader->GetName()));
+  
+  AliMUONPainterDataSourceItem* item = new AliMUONPainterDataSourceItem(fDataReaders,100,20,reader);
+      
+  fDataReaders->AddFrame(item);
+  
+  fItems->Add(item);
+
+  fDataReaders->MapSubwindows();
+  fDataReaders->Resize();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterDataSourceFrame::DataReaderWasUnregistered(AliMUONVTrackerDataMaker* reader)
+{
+  /// Update ourselves as a new data reader was deleted
+  
+  AliInfo(Form("%s",reader->GetName()));
+          
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceFrame::OpenFileDialog()
+{
+  /// Open a file dialog to select a file to be read
+  
+  TGFileInfo fileInfo;
+  
+  new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),
+                   kFDOpen,&fileInfo);
+  
+  
+  fFilePath->SetText(gSystem->ExpandPathName(Form("%s",fileInfo.fFilename)));
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceFrame::OpenRecentSource()
+{
+  /// Open one source from the recently used ones
+  
+  TGTextLBEntry* t = (TGTextLBEntry*)fRecentSources->GetSelectedEntry();
+
+  TString uri(t->GetText()->GetString());
+  
+  if ( uri.Contains(TRegexp("^RAW")) )
+  {
+    CreateRawDataSource(uri);
+  }
+  else if ( uri.Contains(TRegexp("^OCDB")) )
+  {
+    CreateOCDBDataSource(uri);
+  }
+  
+  fRecentSources->Select(-1);
+}
+
diff --git a/MUON/AliMUONPainterDataSourceFrame.h b/MUON/AliMUONPainterDataSourceFrame.h
new file mode 100644 (file)
index 0000000..565f742
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef ALIMUONPAINTERDATASOURCEFRAME_H
+#define ALIMUONPAINTERDATASOURCEFRAME_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterDataSourceFrame
+/// \brief Frame to select input data source(s) to be displayed
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TGFrame
+#  include <TGFrame.h>
+#endif
+
+class TObjArray;
+class TGGroupFrame;
+class AliMUONVTrackerDataMaker;
+class TGTextEntry;
+class TGNumberEntry;
+class TGComboBox;
+
+class AliMUONPainterDataSourceFrame : public TGCompositeFrame
+{
+public:
+  AliMUONPainterDataSourceFrame(const TGWindow* p, UInt_t w, UInt_t h);
+  virtual ~AliMUONPainterDataSourceFrame();
+  
+  void CreateOCDBDataSource();
+
+  void CreateRawDataSource();
+  
+  void DataReaderWasRegistered(AliMUONVTrackerDataMaker* reader);
+  
+  void DataReaderWasUnregistered(AliMUONVTrackerDataMaker* reader);
+
+  void OpenFileDialog();
+  
+  void OpenRecentSource();
+  
+private:
+  /// Not implemented
+  AliMUONPainterDataSourceFrame(const AliMUONPainterDataSourceFrame& rhs);
+  /// Not implemented
+  AliMUONPainterDataSourceFrame& operator=(const AliMUONPainterDataSourceFrame& rhs);
+
+  void AddRecentSource(const char* name);
+
+  Bool_t CreateRawDataSource(const TString& uri);
+  
+  void CreateOCDBDataSource(const TString& uri);
+
+  void CreateOCDBDataSource(const TString& cdbPath, Int_t runNumber, const TString& type);
+
+private:
+    
+  TGGroupFrame* fRecentSourceSelector; ///< to select recently used sources   
+  TGGroupFrame* fRawSelector; ///< to select a new raw data source
+  TGGroupFrame* fOCDBSelector; ///< to select a new OCDB data source
+  TGGroupFrame* fDataReaders; ///< to display currently active data sources  
+  TGTextEntry* fFilePath; ///< raw data file path text entry widget
+  TGTextEntry* fRawOCDBPath; ///< OCDB path for raw data calibration
+  TGTextEntry* fOCDBPath; ///< OCDB path text entry widget
+  TGNumberEntry* fRunSelector; ///< OCDB run number entry widget
+  TGComboBox* fOCDBTypes; ///< OCDB type combo box entry widget  
+  TGComboBox* fRecentSources; ///< recent sources combo box  
+  TObjArray* fItems; ///< list of data readers we handle
+  
+  static const char* fgkNumberOfDataSourcesKey; ///< key used to store the # of data sources in the resource file
+  static const char* fgkDataSourceURIKey; ///< key usde to store the data source URIs in the resource file
+
+  ClassDef(AliMUONPainterDataSourceFrame,1) // Data source selection frame
+};
+
+#endif
diff --git a/MUON/AliMUONPainterDataSourceItem.cxx b/MUON/AliMUONPainterDataSourceItem.cxx
new file mode 100644 (file)
index 0000000..bfeb2c1
--- /dev/null
@@ -0,0 +1,216 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterDataSourceItem.h"
+
+#include "AliMUONVTrackerDataMaker.h"
+#include "AliMUONVTrackerData.h"
+#include "AliLog.h"
+#include <TGLabel.h>
+#include <TGButton.h>
+#include <TThread.h>
+#include <Riostream.h>
+
+///\class AliMUONPainterDataSourceItem
+///
+/// Widget to show one data source, and allow to run/stop/rewind/remove it
+///
+/// WARNING : the thread business is not really working yet (AliRawReaders are
+/// not really thread-safe for the moment). So please use a single raw data
+/// source at a time, otherwise you'll get a crash !
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterDataSourceItem)
+///\endcond
+
+namespace
+{
+  void* RunFunction(void* args)
+  {
+    Long_t* params = (Long_t*)(args);
+    
+    AliMUONPainterDataSourceItem* calling = reinterpret_cast<AliMUONPainterDataSourceItem*>(params[0]);
+    AliMUONVTrackerDataMaker* reader = reinterpret_cast<AliMUONVTrackerDataMaker*> (params[1]);
+    
+    Bool_t ok(kTRUE);
+    
+    while ( ok ) 
+    {
+      ok = reader->NextEvent();
+    }
+    
+    calling->Rewind();
+    
+    return 0x0;
+  }
+}
+
+//_____________________________________________________________________________
+AliMUONPainterDataSourceItem::AliMUONPainterDataSourceItem(const TGWindow* p,
+                                                           UInt_t w, UInt_t h,
+                                                           AliMUONVTrackerDataMaker* reader)
+: TGCompositeFrame(p,w,h,kHorizontalFrame),
+  fDataReader(reader),
+  fSourceName(new TGLabel(this,reader->Data()->Name())),
+  fSource(new TGLabel(this,reader->Source().Data())),
+  fNumberOfEvents(new TGLabel(this,"0")),
+  fRun(new TGTextButton(this,"Run")),
+  fStop(new TGTextButton(this,"Stop")),
+  fRewind(new TGTextButton(this,"Rewind")),
+  fRemove(new TGTextButton(this,"Remove")),
+  fThread(0x0),
+  fShouldReset(kFALSE)
+{
+    /// ctor
+    
+    Update();
+    
+    fRun->SetEnabled(reader->Data()->IsRunnable());
+    fRun->Connect("Clicked()",
+                  "AliMUONPainterDataSourceItem",
+                  this,
+                  "Run()");
+    
+    fStop->SetEnabled(kFALSE);
+    fStop->Connect("Clicked()",
+                   "AliMUONPainterDataSourceItem",
+                   this,
+                   "Stop()");
+    
+    fRewind->SetEnabled(kFALSE);
+    fRewind->Connect("Clicked()",
+                     "AliMUONPainterDataSourceItem",
+                     this,
+                     "Rewind()");
+    
+    fRemove->Connect("Clicked()",
+                     "AliMUONPainterDataSourceItem",
+                     this,
+                     "Remove()");
+    
+    AddFrame(fSourceName, new TGLayoutHints(kLHintsNormal | kLHintsCenterY,5,5,5,5));
+    AddFrame(fSource,new TGLayoutHints(kLHintsExpandX | kLHintsCenterY,5,5,5,5));
+    AddFrame(fNumberOfEvents,new TGLayoutHints(kLHintsNormal | kLHintsCenterY,5,5,5,5));
+    AddFrame(fRun,new TGLayoutHints(kLHintsCenterY | kLHintsCenterY,5,5,5,5));
+    AddFrame(fStop,new TGLayoutHints(kLHintsCenterY | kLHintsCenterY,5,5,5,5));
+    AddFrame(fRewind,new TGLayoutHints(kLHintsCenterY | kLHintsCenterY,5,5,5,5));    
+    AddFrame(fRemove,new TGLayoutHints(kLHintsCenterY | kLHintsCenterY,5,5,5,5));    
+    
+    reader->Data()->Connect("NumberOfEventsChanged()",
+                            "AliMUONPainterDataSourceItem",
+                            this,
+                            "Update()");
+    Resize();
+}
+
+//_____________________________________________________________________________
+AliMUONPainterDataSourceItem::~AliMUONPainterDataSourceItem()
+{
+  /// dtor
+  TThread::Delete(fThread);
+  delete fThread;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceItem::Remove()
+{
+  /// Remove button was clicked
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceItem::Reset()
+{
+  /// Reset the data
+  fDataReader->Data()->Clear();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceItem::Rewind()
+{
+  /// Rewind button was clicked
+  
+  fRewind->SetEnabled(kTRUE);
+  
+  Stop();
+  
+  TThread::Delete(fThread);
+  delete fThread;
+  fThread = 0x0;
+  
+  fRun->SetEnabled(kTRUE);
+  fStop->SetEnabled(kFALSE);
+  fRewind->SetEnabled(kFALSE);
+  
+  fDataReader->Rewind();
+  
+  fShouldReset = kTRUE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceItem::Run()
+{
+  /// Run button was clicked
+  
+  if ( fShouldReset ) 
+  {
+    Reset();
+    fShouldReset = kFALSE;
+  }
+  
+  fRemove->SetEnabled(kFALSE);
+  
+  if (!fThread)
+  {
+    fParams[0] = (Long_t)(this);
+    fParams[1] = (Long_t)(fDataReader);
+    fThread = new TThread(RunFunction,(void*)(&fParams[0]));
+    fThread->Run();
+  }
+  
+  fDataReader->SetRunning(kTRUE);
+  
+  fRun->SetEnabled(kFALSE);
+  fStop->SetEnabled(kTRUE);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceItem::Stop()
+{
+  /// Stop button was clicked
+  
+  fDataReader->SetRunning(kFALSE);
+  
+  fStop->SetEnabled(kFALSE);
+  fRun->SetEnabled(kTRUE);
+  fRemove->SetEnabled(kTRUE);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterDataSourceItem::Update()
+{
+  /// Update ourselves
+  
+  fNumberOfEvents->SetText(Form("%10d",fDataReader->Data()->NumberOfEvents()));
+}
diff --git a/MUON/AliMUONPainterDataSourceItem.h b/MUON/AliMUONPainterDataSourceItem.h
new file mode 100644 (file)
index 0000000..dd19348
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef ALIMUONPAINTERDATASOURCEITEM_H
+#define ALIMUONPAINTERDATASOURCEITEM_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterDataSourceItem
+/// \brief A widget describing a single data source
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TGFrame
+#  include "TGFrame.h"
+#endif
+
+class AliMUONVTrackerDataMaker;
+class TGLabel;
+class TGTextButton;
+class AliMUONPainterDataReader;
+class TThread;
+
+class AliMUONPainterDataSourceItem : public TGCompositeFrame
+{
+public:
+  AliMUONPainterDataSourceItem(const TGWindow* p, UInt_t w, UInt_t h, 
+                               AliMUONVTrackerDataMaker* reader);
+  virtual ~AliMUONPainterDataSourceItem();
+  
+  void Run();
+  
+  void Stop(); 
+  
+  void Rewind();
+  
+  void Remove();
+  
+  void Update();
+  
+  void Reset();
+  
+private:
+  /// Not implemented
+  AliMUONPainterDataSourceItem(const AliMUONPainterDataSourceItem& rhs);
+  /// Not implemented
+  AliMUONPainterDataSourceItem& operator=(const AliMUONPainterDataSourceItem& rhs);
+  
+  AliMUONVTrackerDataMaker* fDataReader; ///< data source reader (not owner)  
+  TGLabel* fSourceName; ///< the (short) name of the data source
+  TGLabel* fSource; ///< the full uri of the data source
+  TGLabel* fNumberOfEvents; ///< number of evts this source has seen so far
+  TGTextButton* fRun; ///< button to start running over the source
+  TGTextButton* fStop; ///< button to stop running over the source
+  TGTextButton* fRewind; ///< button to rewind events for the source
+  TGTextButton* fRemove; ///< button to remove the source
+
+  TThread* fThread; ///< thread used to actually loop over the data
+  Long_t fParams[2]; ///< used in conjunction with fThread
+  
+  Bool_t fShouldReset; ///< whether we should reset or not...
+  
+  ClassDef(AliMUONPainterDataSourceItem,1) // Data source widget
+};
+
+#endif
diff --git a/MUON/AliMUONPainterEnv.cxx b/MUON/AliMUONPainterEnv.cxx
new file mode 100644 (file)
index 0000000..bd8d57b
--- /dev/null
@@ -0,0 +1,109 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterEnv.h"
+
+#include <TEnv.h>
+#include <TSystem.h>
+
+///\class AliMUONPainterEnv
+///
+/// A resource file handling class.
+///
+/// Used to get some things persistent between two sessions of the mchview
+/// program.
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterEnv)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterEnv::AliMUONPainterEnv(const char* resourceFile)
+: fEnv(new TEnv(resourceFile))
+{
+  /// Ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPainterEnv::~AliMUONPainterEnv()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+const char* 
+AliMUONPainterEnv::String(const char* resourceName, const char* defaultValue)
+{
+  /// Retrieve the value associated with a given source, as a string
+  
+  return fEnv->GetValue(resourceName,defaultValue);
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterEnv::Integer(const char* resourceName, Int_t defaultValue)
+{
+  /// Retrieve the value associated with a given source, as an integer
+
+  return fEnv->GetValue(resourceName,defaultValue);
+}
+
+//_____________________________________________________________________________
+Double_t 
+AliMUONPainterEnv::Double(const char* resourceName, Double_t defaultValue)
+{
+  /// Retrieve the value associated with a given source, as a double
+
+  return fEnv->GetValue(resourceName,defaultValue);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterEnv::Save()
+{
+  /// Save the resource file
+  fEnv->WriteFile(gSystem->ExpandPathName(Form("$HOME/%s",fEnv->GetRcName())));
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterEnv::Set(const char* resourceName, Int_t value)
+{
+  /// Set an integer resource
+
+  fEnv->SetValue(resourceName,Form("%d",value));
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterEnv::Set(const char* resourceName, const char* value)
+{
+  /// Set a string resource
+
+  fEnv->SetValue(resourceName,value);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterEnv::Set(const char* resourceName, Double_t value)
+{
+  /// Set a double resource
+
+  fEnv->SetValue(resourceName,Form("%g",value));
+}
diff --git a/MUON/AliMUONPainterEnv.h b/MUON/AliMUONPainterEnv.h
new file mode 100644 (file)
index 0000000..b08d098
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef ALIMUONPAINTERENV_H
+#define ALIMUONPAINTERENV_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterEnv
+/// \brief Resource file handling
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+
+class TEnv;
+
+class AliMUONPainterEnv : public TObject
+{
+public:
+  AliMUONPainterEnv(const char* resourceFile=".mchviewrc");
+  virtual ~AliMUONPainterEnv();
+  
+  const char* String(const char* resourceName, const char* defaultValue="");
+  
+  Int_t Integer(const char* resourceName, Int_t defaultValue=0);
+  
+  Double_t Double(const char* resourceName, Double_t defaultValue=0.0);
+  
+  void Save();
+  
+  void Set(const char* resourceName, Int_t value);
+
+  void Set(const char* resourceName, const char* value);
+
+  void Set(const char* resourceName, Double_t value);
+
+private:
+  /// Not implemented
+  AliMUONPainterEnv(const AliMUONPainterEnv& rhs);
+  /// Not implemented
+  AliMUONPainterEnv& operator=(const AliMUONPainterEnv& rhs);
+  
+  TEnv* fEnv; ///< the worker class
+  
+  ClassDef(AliMUONPainterEnv,1) // Painter display resource file
+};
+
+#endif
diff --git a/MUON/AliMUONPainterGroup.cxx b/MUON/AliMUONPainterGroup.cxx
new file mode 100644 (file)
index 0000000..3e3437c
--- /dev/null
@@ -0,0 +1,276 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterGroup.h"
+
+#include "AliMUONVPainter.h"
+#include "AliMUONVTrackerData.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TObjArray.h>
+#include <float.h>
+
+///\class AliMUONPainterGroup
+///
+/// A group of AliMUONVPainter
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterGroup)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterGroup::AliMUONPainterGroup()
+: TObject(),
+fType(""),
+fIsResponder(kFALSE),
+fIsVisible(kTRUE),
+fData(0x0),
+fDataIndex(-1),
+fDataMin(FLT_MAX),
+fDataMax(-FLT_MAX),
+fPainters(0x0),
+fDepth(-1),
+fIsOutlined(kTRUE)
+{
+  /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPainterGroup::AliMUONPainterGroup(const char* type, Int_t depth)
+: TObject(),
+ fType(type),
+ fIsResponder(kFALSE),
+ fIsVisible(kTRUE),
+ fData(0x0),
+ fDataIndex(-1),
+ fDataMin(FLT_MAX),
+ fDataMax(-FLT_MAX),
+ fPainters(0x0),
+ fDepth(depth),
+ fIsOutlined(kTRUE)
+{
+   /// ctor
+   if ( fType == "" || fDepth < 0 ) 
+   {
+     AliError("Sorry guy.");
+     TObject* o(0x0);
+     o->ls(); // to provoque a crash to be able to reach gdb...
+   }
+}
+
+//_____________________________________________________________________________
+AliMUONPainterGroup::~AliMUONPainterGroup()
+{
+  /// dtor
+  delete fPainters;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterGroup::Add(AliMUONVPainter* painter)
+{
+  /// Add a painter to this group (must be of the correct type)
+  
+   if ( fType != painter->Type() ) 
+   {
+     AliError(Form("Cannot add painter of type %s to this = %s",
+                   painter->Type(), fType.Data()));
+     return kFALSE;
+   }
+  
+  if ( fDepth != painter->Depth() )
+  {
+    AliError(Form("Cannot add painter of depth %d to this = %d",
+                  painter->Depth(), fDepth));
+    return kFALSE;
+  }
+  
+  if (!fPainters)
+  {
+    fPainters = new TObjArray;
+  }
+  
+  painter->SetMotherGroup(this);
+  
+  fPainters->Add(painter);
+
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterGroup::Compare(const TObject* obj) const
+{
+  /// Compare with another group (based on type)
+  
+  const AliMUONPainterGroup* group = static_cast<const AliMUONPainterGroup*>(obj);
+  return fType.CompareTo(group->Type());
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterGroup::ComputeDataRange(Double_t& dataMin, Double_t& dataMax)
+{
+  /// Compute the data range spanned by this group
+  dataMin = FLT_MAX;
+  dataMax = -FLT_MAX;
+  
+  if ( !fData || fDataIndex < 0 ) return;
+
+  TIter next(fPainters);
+  AliMUONVPainter* p;
+  
+  while ( ( p = static_cast<AliMUONVPainter*>(next()) ) )
+  {
+    Double_t min, max;
+    p->ComputeDataRange(*fData,fDataIndex,min,max);
+    dataMin = TMath::Min(min,dataMin);
+    dataMax = TMath::Max(max,dataMax);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterGroup::Draw(Option_t* opt)
+{
+  /// Draw our painters
+  TIter next(fPainters);
+  TObject* o;
+  while ( ( o = next() ) )
+  {
+    o->Draw(opt);
+  }
+}  
+
+//_____________________________________________________________________________
+AliMUONVPainter* 
+AliMUONPainterGroup::First() const
+{
+  /// Get the first painter in group
+  if ( fPainters ) 
+  {
+    return static_cast<AliMUONVPainter*>(fPainters->First());
+  }
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterGroup::GetLineColor() const
+{
+  /// Get line color of this group's painters
+  if ( fPainters ) 
+  {
+    return static_cast<AliMUONVPainter*>(fPainters->First())->GetLineColor();
+  }
+  return 1;
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterGroup::GetLineWidth() const
+{
+  /// Get line width of this group's painters
+  if ( fPainters ) 
+  {
+    return static_cast<AliMUONVPainter*>(fPainters->First())->GetLineWidth();
+  }
+  return 1;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPainterGroup::Matches(const char* pattern) const
+{
+  /// Whether our type matches "pattern"
+  TString spattern(pattern);
+  
+  if ( spattern == "*" || fType.Contains(pattern) )
+  {
+    return kTRUE;
+  }
+  return kFALSE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterGroup::Print(Option_t* opt) const
+{
+  /// Printout
+  cout << "Type " << fType.Data() << " Depth " << fDepth;
+  if ( IsResponder() ) cout << " is responder ";
+  if ( IsVisible() ) cout << " is visible ";
+  if ( IsPlotter() ) 
+  {
+    cout << Form(" is plotter for data %p %s dimension %d %s plot range = %e, %e",
+                 fData,(fData ? fData->Name() : ""),
+                 fDataIndex,( (fData && fDataIndex>=0 ) ? 
+                              fData->DimensionName(fDataIndex).Data() : ""),
+                 DataMin(),DataMax());
+  }
+  if ( IsOutlined() ) 
+  {
+    cout << " is outlined";
+  }
+  if ( fPainters ) 
+  {
+    cout << " contains " << fPainters->GetLast()+1 << " painters";
+  }
+  
+  cout << endl;
+  
+  TString sopt(opt);
+  sopt.ToUpper();
+  if ( sopt == "FULL" ) 
+  {
+    TIter next(fPainters);
+    AliMUONVPainter* painter;
+    while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
+    {
+      cout << "    ";
+      painter->Print();
+    }
+  }
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterGroup::SetData(AliMUONVTrackerData* data, Int_t dataIndex)
+{ 
+  /// Set the data to be plotted
+  fData = data; 
+  fDataIndex = dataIndex; 
+  fDataMax = -FLT_MAX;
+  fDataMin = FLT_MAX;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterGroup::SetLine(Int_t lineColor, Int_t lineWidth)
+{
+  /// Set our outline attributes
+  TIter next(fPainters);
+  AliMUONVPainter* painter;
+  while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
+  {
+    painter->SetLineColor(lineColor);
+    painter->SetLineWidth(lineWidth);
+  }
+}  
+
diff --git a/MUON/AliMUONPainterGroup.h b/MUON/AliMUONPainterGroup.h
new file mode 100644 (file)
index 0000000..c2f9cd2
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef ALIMUONPAINTERGROUP_H
+#define ALIMUONPAINTERGROUP_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterGroup
+/// \brief A group of AliMUONVPainter
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+#ifndef ROOT_TString
+#  include "TString.h"
+#endif
+
+class AliMUONVPainter;
+class AliMUONVTrackerData;
+
+class AliMUONPainterGroup : public TObject
+{
+public:
+  AliMUONPainterGroup();
+  AliMUONPainterGroup(const char* type, Int_t depth);
+  virtual ~AliMUONPainterGroup();
+  
+  Bool_t Add(AliMUONVPainter* painter);
+  
+  void ComputeDataRange(Double_t& dataMin, Double_t& dataMax);
+  
+  /// Return the data we are plotting
+  AliMUONVTrackerData* Data() const { return fData; }
+  
+  /// Return the index within the data
+  Int_t DataIndex() const { return fDataIndex; }
+  
+  /// Max data we are plotting
+  Double_t DataMax() const { return fDataMax; }
+  
+  /// Min data we are plotting
+  Double_t DataMin() const { return fDataMin; }
+  
+  /// Depth
+  Int_t Depth() const { return fDepth; }
+  
+  void Draw(Option_t* opt="");
+  
+  AliMUONVPainter* First() const;
+  
+  /// We are sortable (by type)
+  Bool_t IsSortable() const { return kTRUE; }
+  
+  Int_t Compare(const TObject* obj) const;
+  
+  /// Whether we should outline ourselves
+  Bool_t IsOutlined() const { return fIsOutlined; }
+  
+  /// Whether we are the plotting group
+  Bool_t IsPlotter() const { return fData != 0 && fDataIndex >= 0; }
+
+  /// Whether we are the responder group
+  Bool_t IsResponder() const { return fIsResponder; }
+  
+  /// Whether we are visible
+  Bool_t IsVisible() const { return fIsVisible; }
+  
+  Bool_t Matches(const char* pattern) const;
+  
+  void Print(Option_t* opt="") const;
+  
+  void SetData(AliMUONVTrackerData* data, Int_t dataIndex);
+  
+  /// Set the data range
+  void SetDataRange(Double_t min, Double_t max)
+  { fDataMin = min; fDataMax = max; }
+  
+  Int_t GetLineColor() const;
+  
+  Int_t GetLineWidth() const;
+  
+  void SetLine(Int_t lineColor, Int_t lineWidth);
+  
+  /// Set the outlined flag
+  void SetOutlined(Bool_t flag=kTRUE) { fIsOutlined = flag; }
+  
+  /// Set the responder flag
+  void SetResponder(Bool_t flag=kTRUE) { fIsResponder = flag; }
+  
+  /// Set the visible flag
+  void SetVisible(Bool_t flag=kTRUE) { fIsVisible = flag; }
+  
+  /// Our type
+  const char* Type() const { return fType.Data(); }
+  
+private:
+  /// Not implemented
+  AliMUONPainterGroup(const AliMUONPainterGroup& rhs);
+  /// Not implemented
+  AliMUONPainterGroup& operator=(const AliMUONPainterGroup& rhs);
+  
+private:
+  TString fType; ///< type of this group (e.g. PADS, MANU, PCB, etc...)
+  Bool_t fIsResponder; ///< whether we are responding to mouse events
+  Bool_t fIsVisible; ///< whether we are visible
+  AliMUONVTrackerData* fData; ///< the data we plot (can be 0x0)
+  Int_t fDataIndex; ///< the index of the data to plot (can be -1 if data=0x0)
+  Double_t fDataMin; ///< min data
+  Double_t fDataMax; ///< max data
+  TObjArray* fPainters; ///< painters of this group
+  Int_t fDepth; ///< depth in the hierarchy of painters
+  Bool_t fIsOutlined; ///< whether we should be outlined
+  
+  ClassDef(AliMUONPainterGroup,1) // Group of AliMUONVPainter
+};
+
+#endif
diff --git a/MUON/AliMUONPainterHelper.cxx b/MUON/AliMUONPainterHelper.cxx
new file mode 100644 (file)
index 0000000..929a07c
--- /dev/null
@@ -0,0 +1,909 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterHelper.h"
+
+#include "AliMUONGeometryDetElement.h"
+#include "AliMUONGeometryTransformer.h"
+#include "AliMUONPainterContour.h"
+#include "AliMUONPainterContourMaker.h"
+#include "AliMUONPainterEnv.h"
+#include "AliMUONPainterMatrix.h"
+#include "AliMUONPainterPadStore.h"
+#include "AliMUONPainterRegistry.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMUONVDigit.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMpCDB.h"
+#include "AliMpConstants.h"
+#include "AliMpDDLStore.h"
+#include "AliMpDEIterator.h"
+#include "AliMpDEManager.h"
+#include "AliMpExMap.h"
+#include "AliMpMotifMap.h"
+#include "AliMpMotifPosition.h"
+#include "AliMpPCB.h"
+#include "AliMpPad.h"
+#include "AliMpSector.h"
+#include "AliMpSectorSegmentation.h"
+#include "AliMpSegmentation.h"
+#include "AliMpSlat.h"
+#include "AliMpSlatSegmentation.h"
+#include "AliMpStationType.h"
+#include "AliMpVPadIterator.h"
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TArrayI.h>
+#include <TCanvas.h>
+#include <TClass.h>
+#include <TCollection.h>
+#include <TFile.h>
+#include <TGLabel.h>
+#include <TGeoMatrix.h>
+#include <TGMsgBox.h>
+#include <TLine.h>
+#include <TList.h>
+#include <TMap.h>
+#include <TObjArray.h>
+#include <TObjString.h>
+#include <TStyle.h>
+#include <TSystem.h>
+#include <TVector2.h>
+#include <TVector3.h>
+#include <TVirtualPad.h>
+#include <TVirtualX.h>
+
+///\class AliMUONPainterHelper
+///
+/// Helper class for painters
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterHelper)
+///\endcond
+
+AliMUONPainterHelper* AliMUONPainterHelper::fgInstance(0x0);
+
+//_____________________________________________________________________________
+AliMUONPainterHelper::AliMUONPainterHelper() : 
+  TObject(),
+  fPadStore(0x0),
+  fExplodedGlobalTransformations(0x0),
+  fRealGlobalTransformations(0x0),
+  fIsModified(kFALSE),
+  fContourMaker(0x0),
+  fPainterMatrices(0x0),
+  fEnv(0x0)
+{
+    /// ctor
+    fExplodeFactor[0] = 1.00;
+    fExplodeFactor[1] = 1.50;
+
+    if ( ! AliMpCDB::LoadMpSegmentation() ) 
+    {
+      AliFatal("Could not access mapping from OCDB !");
+    }
+    
+    // Load DDL store
+    if ( ! AliMpCDB::LoadDDLStore() ) 
+    {
+      AliFatal("Could not access DDL Store from OCDB !");
+    }        
+}
+
+//_____________________________________________________________________________
+AliMUONPainterHelper::~AliMUONPainterHelper()
+{
+  /// dtor
+  if ( fIsModified ) Save();
+  delete fExplodedGlobalTransformations;
+  delete fRealGlobalTransformations;
+  delete fPadStore;
+  delete fContourMaker;
+  delete fPainterMatrices;
+  fgInstance = 0;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour*
+AliMUONPainterHelper::GetContour(const char* contourName) const
+{
+  /// Get a contour by name
+  
+  AliCodeTimerAuto("")
+  
+  if ( fContourMaker ) 
+  {
+    return fContourMaker->GetContour(contourName);
+  }
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterHelper::FindPadID(const TArrayI& pads, Double_t x, Double_t y) const
+{
+  /// Find a pad by position
+  
+  return fPadStore->FindPadID(pads,x,y);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::GenerateDefaultMatrices()
+{
+  /// Kind of bootstrap method to trigger the generation of all contours
+  
+  fPainterMatrices = new TObjArray;
+  fPainterMatrices->SetOwner(kFALSE);
+  
+  TObjArray attributes;
+  
+  AliMUONAttPainter att;
+  
+  att.SetViewPoint(kTRUE,kFALSE);
+  att.SetPlane(kFALSE,kFALSE);
+  att.SetCathode(kTRUE,kFALSE);
+  
+  AliWarningClass("Should generate back views as well here");
+  
+  attributes.Add(new AliMUONAttPainter(att));  
+  att.SetCathode(kFALSE,kTRUE);
+  attributes.Add(new AliMUONAttPainter(att));
+  att.SetCathode(kFALSE,kFALSE);
+  att.SetPlane(kTRUE,kFALSE);
+  attributes.Add(new AliMUONAttPainter(att));
+  att.SetPlane(kFALSE,kTRUE);
+  attributes.Add(new AliMUONAttPainter(att));
+  
+  TIter next(&attributes);
+  AliMUONAttPainter* a;
+  
+  while ( ( a = static_cast<AliMUONAttPainter*>(next()) ) )
+  {
+    AliMUONPainterMatrix* matrix = new AliMUONPainterMatrix("Tracker",5,2);
+    
+    for ( Int_t i = 0; i < 10; ++i )
+    {
+      AliMUONVPainter* painter = AliMUONVPainter::CreatePainter("AliMUONChamberPainter",*a,i,-1);
+      
+      painter->SetResponder("Chamber");
+      
+      painter->SetOutlined("*",kFALSE);
+      
+      painter->SetOutlined("MANU",kTRUE);
+      
+      for ( Int_t j = 0; j < 3; ++j ) 
+      {
+        painter->SetLine(j,1,4-j);
+      }
+      
+      matrix->Adopt(painter);    
+    }
+    AliMUONPainterRegistry::Instance()->Register(matrix);
+    fPainterMatrices->Add(matrix);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::GenerateGeometry()
+{  
+  /// Generate the geometry (FIXME: using transform.dat for the moment)
+  /// The geometry is not the "normal" one as we "explode" it to avoid
+  /// having overlapping detection elements as in the reality, which 
+  /// would be inconvenient for a display ;-)
+  
+  AliDebug(1,Form(" with explodeFactor=%e,%e",fExplodeFactor[0],fExplodeFactor[1]));
+  
+  AliMUONGeometryTransformer transformer;
+  transformer.LoadGeometryData("transform.dat");
+//  transformer.LoadGeometryData("geometry.root"); //FIXME: add a protection if geometry.root file does not exist
+  fExplodedGlobalTransformations = new AliMpExMap(true);
+  fRealGlobalTransformations = new AliMpExMap(true);
+  AliMpDEIterator deIt;
+  deIt.First();
+  while ( !deIt.IsDone() )
+  {
+    Int_t detElemId = deIt.CurrentDEId();
+    const AliMUONGeometryDetElement* de = transformer.GetDetElement(detElemId);
+    
+    fRealGlobalTransformations->Add(detElemId,de->GetGlobalTransformation()->Clone());
+                                    
+    TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(de->GetGlobalTransformation()->Clone());
+    Double_t* translation = matrix->GetTranslation();
+    
+    AliDebug(1,Form("Initial translation for DE %04d is %7.3f, %7.3f",
+                    detElemId,translation[0],translation[1]));
+    
+    if ( AliMpDEManager::GetStationType(detElemId) == AliMp::kStation345 ) 
+    {
+      translation[0] *= fExplodeFactor[0];
+      translation[1] *= fExplodeFactor[1];
+    }
+    else
+    {
+      Double_t shift = 5; // cm
+      Double_t xshift[] = { shift, -shift, -shift, shift };
+      Double_t yshift[] = { shift, shift, -shift, -shift };
+      Int_t ishift = detElemId % 100;
+      
+      translation[0] += xshift[ishift];
+      translation[1] += yshift[ishift];
+    }
+    matrix->SetTranslation(translation);
+    fExplodedGlobalTransformations->Add(detElemId,matrix);
+    deIt.Next();
+  }
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour* 
+AliMUONPainterHelper::GenerateManuContour(Int_t detElemId,
+                                          Int_t manuId,
+                                          AliMUONAttPainter viewType,
+                                          const char* contourName)
+{
+  /// Generate the contour of the list of pads
+  
+  if (!fContourMaker) fContourMaker = new AliMUONPainterContourMaker(fExplodedGlobalTransformations);
+  
+  AliMUONPainterContour* contour = 
+    fContourMaker->GenerateManuContour(contourName,detElemId,manuId,viewType);
+  
+  if (contour) 
+  {
+    RegisterContour(contour);
+  }
+  
+  return contour;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::GeneratePadStore()
+{
+  /// Generate the pad store
+  
+  AliCodeTimerAuto("")
+  AliDebugClass(1,"Generating pad store");
+  fPadStore = new AliMUONPainterPadStore();
+  
+  AliMpDEIterator deIt;
+  
+  deIt.First();
+  while ( !deIt.IsDone() )
+  {
+    Int_t detElemId = deIt.CurrentDEId();
+    if ( AliMpDEManager::GetStationType(detElemId) != AliMp::kStationTrigger )
+    {
+      GeneratePadStore(detElemId);
+    }
+    deIt.Next();
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::GeneratePadStore(Int_t detElemId)
+{
+  /// Generate part of the padstore for one detection element
+  
+  AliMp::CathodType cathode[] = { AliMp::kCath0, AliMp::kCath1 };
+  
+  for ( Int_t i = 0; i < 2; ++i ) 
+  {
+    const AliMpVSegmentation* seg = 
+    AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,cathode[i]);
+    AliMpVPadIterator* it = seg->CreateIterator();
+    it->First();
+    
+    while ( !it->IsDone() )
+    {
+      AliMpPad pad = it->CurrentItem();
+      
+      TVector2 localPosition(pad.Position());
+      Double_t x,y,z;
+      Local2Global(detElemId,localPosition.X(),localPosition.Y(),0,
+                   x,y,z);
+      Int_t manuId = pad.GetLocation().GetFirst();
+      Int_t manuChannel = pad.GetLocation().GetSecond();
+      AliMUONVCalibParam* param = fPadStore->Get(detElemId,manuId);
+      param->SetValueAsDouble(manuChannel,0,x);
+      param->SetValueAsDouble(manuChannel,1,y);
+      param->SetValueAsDouble(manuChannel,2,pad.Dimensions().X());
+      param->SetValueAsDouble(manuChannel,3,pad.Dimensions().Y());
+      it->Next();
+    }          
+    delete it;
+  }
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHelper::GetBoundaries(const TArrayI& pads, Double_t& xmin, Double_t& ymin,
+                                    Double_t& xmax, Double_t& ymax) const
+{
+  /// Get the area covered by an array of pads
+  
+  return fPadStore->GetBoundaries(pads,xmin,ymin,xmax,ymax);
+}
+
+//_____________________________________________________________________________
+AliMp::CathodType
+AliMUONPainterHelper::GetCathodeType(Int_t detElemId, Int_t manuId) const
+{
+  /// Get the cathode type of a given manu
+  
+  AliMp::PlaneType planeType(AliMp::kBendingPlane);
+  if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
+  {
+    planeType = AliMp::kNonBendingPlane;
+  }
+  return AliMpDEManager::GetCathod(detElemId,planeType);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour* 
+AliMUONPainterHelper::GetLocalManuContour(Int_t detElemId, Int_t manuId) const
+{
+  /// Retrieve a manu contour (in local coordinates)
+  return fContourMaker->FindLocalManuContour(detElemId,manuId);
+}
+
+//_____________________________________________________________________________
+AliMpMotifPosition* 
+AliMUONPainterHelper::GetMotifPosition(Int_t detElemId, Int_t manuId) const
+{
+  /// Get a given motif position
+  AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
+  if ( stationType == AliMp::kStation345 ) 
+  {
+    AliMp::PlaneType planeType(AliMp::kBendingPlane);
+    if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
+    {
+      planeType = AliMp::kNonBendingPlane;
+    }
+    const AliMpSlat* slat = GetSlat(detElemId,planeType);
+    return slat->FindMotifPosition(manuId);
+  }
+  else if ( stationType != AliMp::kStationTrigger ) 
+  {
+    AliMp::PlaneType planeType(AliMp::kBendingPlane);
+    if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
+    {
+      planeType = AliMp::kNonBendingPlane;
+    }
+    const AliMpSector* sector = GetSector(detElemId,planeType);
+    return sector->GetMotifMap()->FindMotifPosition(manuId);
+  }
+  AliFatalClass("Not supposed to work with trigger");
+  return 0x0;
+}
+
+
+//_____________________________________________________________________________
+AliMpPCB*
+AliMUONPainterHelper::GetPCB(Int_t detElemId, AliMp::CathodType cathodeType, 
+                             Int_t pcbNumber) const
+{
+  /// Get a given PCB
+  const AliMpSlat* slat = GetSlat(detElemId,cathodeType);
+  if ( slat ) return slat->GetPCB(pcbNumber);
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+AliMpPCB*
+AliMUONPainterHelper::GetPCB(Int_t detElemId, AliMp::PlaneType planeType, 
+                             Int_t pcbNumber) const
+{
+  /// Get a given PCB
+  AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,
+                                                            planeType);
+  return GetPCB(detElemId,cathodeType,pcbNumber);
+}
+
+//_____________________________________________________________________________
+AliMp::PlaneType
+AliMUONPainterHelper::GetPlaneType(Int_t manuId) const
+{
+  /// Get the planeType of a given manu
+  
+  if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
+  {
+    return AliMp::kNonBendingPlane;
+  }
+  return AliMp::kBendingPlane;
+}
+
+//_____________________________________________________________________________
+const AliMpSlat*
+AliMUONPainterHelper::GetSlat(Int_t detElemId, AliMp::PlaneType planeType) const
+{
+  /// Get a given slat
+  
+  AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,
+                                                          planeType);
+
+  return GetSlat(detElemId,cathodeType);
+}
+
+//_____________________________________________________________________________
+const AliMpSector*
+AliMUONPainterHelper::GetSector(Int_t detElemId, AliMp::PlaneType planeType) const
+{
+  /// Get a given sector
+  AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
+  if ( stationType != AliMp::kStation1 && stationType != AliMp::kStation2 ) return 0x0;
+  
+  AliMp::CathodType cathodeType = AliMpDEManager::GetCathod(detElemId,planeType);
+  
+  const AliMpVSegmentation* seg =
+  AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,cathodeType);
+  
+  const AliMpSectorSegmentation* sectorSeg = static_cast<const AliMpSectorSegmentation*>(seg);
+  return sectorSeg->GetSector();
+  
+}
+
+//_____________________________________________________________________________
+const AliMpSlat*
+AliMUONPainterHelper::GetSlat(Int_t detElemId, AliMp::CathodType cathodeType) const
+{
+  /// Get a given slat
+  AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
+  if ( stationType != AliMp::kStation345 ) return 0x0;
+
+  const AliMpVSegmentation* seg =
+    AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,cathodeType);
+  
+  const AliMpSlatSegmentation* slatSeg = static_cast<const AliMpSlatSegmentation*>(seg);
+  return slatSeg->Slat();
+}
+
+//_____________________________________________________________________________
+const AliMpSlat*
+AliMUONPainterHelper::GetSlat(Int_t detElemId, Int_t manuId) const
+{
+  /// Get a given slat
+  const AliMpVSegmentation* seg =
+    AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
+  
+  const AliMpSlatSegmentation* slatSeg = static_cast<const AliMpSlatSegmentation*>(seg);
+  return slatSeg->Slat();
+}
+
+//_____________________________________________________________________________
+AliMUONPainterHelper*
+AliMUONPainterHelper::Instance()
+{
+  /// Return the global and unique instance of this class
+  
+  if (fgInstance) return fgInstance;
+  
+  AliMUONPainterEnv env;
+  
+  TString fileName(gSystem->ExpandPathName(env.String("PadStoreFileName","padstore.root")));
+
+  if ( gSystem->AccessPathName(fileName.Data(),kFileExists) ) // mind the strange return value of that method...   
+  {
+    // file does NOT exist yet. Create it
+    AliDebugClass(1,"Generating instance");
+    
+    Int_t ret;
+    
+    new TGMsgBox(gClient->GetRoot(),gClient->GetRoot(),"",
+                 Form("File %s not found.\nI will generate it, and this will take a while.\n"
+                      "Click OK (and grab a cup of coffee ;-) ) to proceed,\n or Cancel to quit.",fileName.Data()),
+                 kMBIconQuestion,
+                 kMBOk | kMBCancel,
+                 &ret);
+    if ( ret == kMBCancel ) exit(1);
+    
+    fgInstance = new AliMUONPainterHelper;
+    fgInstance->GenerateGeometry();
+    fgInstance->GeneratePadStore();
+    fgInstance->GenerateDefaultMatrices();
+    fgInstance->Modified(kTRUE);
+    fgInstance->fEnv = new AliMUONPainterEnv;
+    fgInstance->Save();
+    
+  }
+  else
+  {
+    AliDebugClass(1,"Reading instance");
+    TFile f(fileName.Data());
+    fgInstance = static_cast<AliMUONPainterHelper*>(f.Get("AliMUONPainterHelper"));
+    
+    TIter next(fgInstance->fPainterMatrices);
+    AliMUONPainterMatrix* matrix;
+    while ( ( matrix = static_cast<AliMUONPainterMatrix*>(next()) ) )
+    {
+      AliMUONPainterRegistry::Instance()->Register(matrix);
+    }
+    fgInstance->fPainterMatrices->SetOwner(kFALSE);
+    fgInstance->fEnv = new AliMUONPainterEnv;
+  }
+  return fgInstance;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHelper::Global2Local(Int_t detElemId, 
+                                    Double_t xg, Double_t yg, Double_t zg,
+                                    Double_t& xl, Double_t& yl, Double_t& zl) const
+{
+  /// Local to global transformation of coordinates
+  
+  TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fExplodedGlobalTransformations->GetValue(detElemId));
+  Double_t pg[3] = { xg, yg, zg };
+  Double_t pl[3] = { 0., 0., 0. };
+  matrix->MasterToLocal(pg, pl);
+  xl = pl[0];
+  yl = pl[1];
+  zl = pl[2];
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHelper::Global2LocalReal(Int_t detElemId, 
+                                       Double_t xg, Double_t yg, Double_t zg,
+                                       Double_t& xl, Double_t& yl, Double_t& zl) const
+{
+  /// Local to global transformation of coordinates
+  
+  TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fRealGlobalTransformations->GetValue(detElemId));
+  Double_t pg[3] = { xg, yg, zg };
+  Double_t pl[3] = { 0., 0., 0. };
+  matrix->MasterToLocal(pg, pl);
+  xl = pl[0];
+  yl = pl[1];
+  zl = pl[2];
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHelper::Local2Global(Int_t detElemId, 
+                                   Double_t xl, Double_t yl, Double_t zl,
+                                   Double_t& xg, Double_t& yg, Double_t& zg) const
+{
+  /// Local to (exploded) global transformation of coordinates
+  
+  TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fExplodedGlobalTransformations->GetValue(detElemId));
+  Double_t pl[3] = { xl, yl, zl };
+  Double_t pg[3] = { 0., 0., 0. };
+  matrix->LocalToMaster(pl, pg);
+  xg = pg[0];
+  yg = pg[1];
+  zg = pg[2];
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHelper::Local2GlobalReal(Int_t detElemId, 
+                                       Double_t xl, Double_t yl, Double_t zl,
+                                       Double_t& xg, Double_t& yg, Double_t& zg) const
+{
+  /// Local to (real) global transformation of coordinates
+  
+  TGeoHMatrix* matrix = static_cast<TGeoHMatrix*>(fRealGlobalTransformations->GetValue(detElemId));
+  Double_t pl[3] = { xl, yl, zl };
+  Double_t pg[3] = { 0., 0., 0. };
+  matrix->LocalToMaster(pl, pg);
+  xg = pg[0];
+  yg = pg[1];
+  zg = pg[2];
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterHelper::ColorFromValue(Double_t value, Double_t min, Double_t max) const
+{ 
+  /// Convert a value into a color, fitting within a given range
+  
+  Int_t rv;
+  
+  if (value > max) rv = 1;
+  else if (value <= min) rv = 0;
+  else
+  {
+    if  ( max == min ) return gStyle->GetColorPalette(1);
+    Double_t range = max - min;
+    Double_t offset = value - min;
+    rv = gStyle->GetColorPalette( 1 + int( offset*(gStyle->GetNumberOfColors()-2)/range - 0.5 ) );
+  }
+  return rv;
+}
+
+//_____________________________________________________________________________
+AliMUONPainterContour* 
+AliMUONPainterHelper::MergeContours(const TObjArray& contours, 
+                                    const char* contourName)
+{
+  /// Merge a set of contours (delegating to the contour maker)
+  if (!fContourMaker) 
+  {
+    fContourMaker = new AliMUONPainterContourMaker(fExplodedGlobalTransformations);
+  }
+  
+  AliMUONPainterContour* contour = fContourMaker->MergeContours(contours,
+                                                                contourName);
+  
+  if (contour) 
+  {
+    RegisterContour(contour);
+  }
+  return contour;
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::Print(Option_t* opt) const
+{
+  /// Printout
+  TString sopt(opt);
+  sopt.ToUpper();
+  
+  if ( sopt.Length() == 0 )
+  {
+    cout << Form("ExplodeFactor=%e,%e",fExplodeFactor[0],fExplodeFactor[1]) << endl;
+    cout << Form("PadStore=%x",fPadStore);
+    if ( fPadStore ) cout << Form(" with %d pads",fPadStore->GetSize());
+    cout << endl;
+    cout << Form("GlobalTransformations=%x",fExplodedGlobalTransformations);
+    if ( fExplodedGlobalTransformations ) cout << Form(" with %d transformations",fExplodedGlobalTransformations->GetSize());
+    cout << endl;
+    if ( fContourMaker ) 
+    {
+      cout << Form(" with %d contours",fContourMaker->Size());
+    }
+    else
+    {
+      cout << "No contour";
+    }
+    cout << endl;
+    cout << "Modified=";
+    if ( IsModified() ) 
+    {
+    cout << "YES";
+  }
+  else
+  {
+    cout << "NO";
+  }
+  cout << endl;
+  }
+  
+  if ( sopt.Contains("CONTOUR") || sopt.Contains("FULL") )
+  {
+    fContourMaker->Print(opt);
+  }
+  
+  if ( sopt.Contains("MATRI") || sopt.Contains("FULL") )
+  {
+    fPainterMatrices->Print(opt);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::RegisterContour(AliMUONPainterContour* contour)
+{
+  /// contour is adopted by contourMaker
+  AliCodeTimerAuto("")
+  AliDebug(1,contour->GetName());
+  if ( fContourMaker->HasContour(contour->GetName()) ) 
+  {
+    AliError(Form("Contour with name %s is already there",contour->GetName()));
+//    Print("CONTOUR");
+    return;
+  }
+  fContourMaker->Add(contour);
+  Modified(kTRUE);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterHelper::Save()
+{
+  /// Save to disk
+  
+  if (!IsModified()) return;
+
+  Modified(kFALSE);
+
+  AliInfo("");
+
+  fgInstance->Print();
+  
+  TString fileName(gSystem->ExpandPathName(fgInstance->Env()->String("PadStoreFileName","padstore.root")));
+
+  AliInfo(Form("Saving to %s",fileName.Data()));
+          
+  TFile f(fileName,"RECREATE");
+
+  fgInstance->Write("");
+  
+  f.Close();
+}
+
+//_____________________________________________________________________________
+AliMpPad 
+AliMUONPainterHelper::PadByExplodedPosition(Int_t detElemId, Int_t manuId, 
+                                            Double_t x, Double_t y) const
+{
+  /// Find a pad by exploded position. FIXME: not really used nor tested !
+  
+  Double_t xr, yr, zr;
+  
+//  Local2Global(detElemId,0.0,0.0,0.0,dummy,dummy,z); // to find z 
+
+  AliDebug(1,Form("DE %04d ManuID %04d x %7.3f y %7.3f",detElemId,manuId,x,y));
+  
+  Exploded2Real(detElemId,x,y,0,xr,yr,zr);
+
+  AliDebug(1,Form("xr %7.3f yr %7.3f zr %7.3f",xr,yr,zr));
+
+  Double_t xl,yl,zl;
+
+  Global2LocalReal(detElemId,xr,yr,zr,xl,yl,zl);
+
+  AliDebug(1,Form("xl %7.3f yl %7.3f zl %7.3f",xl,yl,zl));
+
+  const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentationByElectronics(detElemId,manuId);
+  
+  AliDebug(1,Form("dx,dy=%7.3f,%7.3f",seg->Dimensions().X(),seg->Dimensions().Y()));
+  
+  return seg->PadByPosition(TVector2(xl,yl));
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHelper::Exploded2Real(Int_t detElemId, 
+                                    Double_t xe, Double_t ye, Double_t ze, 
+                                    Double_t& xr, Double_t& yr, Double_t& zr) const
+{
+  /// Convert exploded coordinates into real ones. FIXME: not really used nor tested !
+  
+  // first go back to local
+  
+  Double_t xl,yl,zl;
+  
+  Global2Local(detElemId,xe,ye,ze,xl,yl,zl);
+  
+  // and then back to global but not exploded
+  
+  Local2GlobalReal(detElemId,xl,yl,zl,xr,yr,zr);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::ChamberName(Int_t chamberId) const
+{
+  /// Build a name for one chamber
+  return Form("Chamber%1d",chamberId);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::StationName(Int_t stationId) const
+{
+  /// Build a name for one station
+  return Form("Station%1d",stationId+1);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::DEName(Int_t detElemId) const
+{
+  /// Build a name for one detection element
+  return Form("DE%04d",detElemId);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::ManuName(Int_t manuId) const
+{
+  /// Build a name for one manu
+  return Form("MANU%04d",manuId);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::BusPatchName(Int_t busPatchId) const
+{
+  /// Build a name for one buspatch
+  return Form("BUSPATCH%04d",busPatchId);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::PCBName(Int_t pcbNumber) const
+{
+  /// Build a name for one pcb
+  return Form("PCB%1d",pcbNumber);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::ChamberPathName(Int_t chamberId) const
+{
+  /// Build a name for one chamber
+  return Form("%s/%s",StationName(chamberId/2).Data(),ChamberName(chamberId).Data());
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::StationPathName(Int_t stationId) const
+{
+  /// Build a name for one station
+  return StationName(stationId);
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::DEPathName(Int_t detElemId) const
+{
+  /// Build a name for one detection element
+  
+  Int_t chamberId = AliMpDEManager::GetChamberId(detElemId);
+  
+  return Form("%s/%s/%s",
+              StationName(chamberId/2).Data(),
+              ChamberName(chamberId).Data(),
+              DEName(detElemId).Data());
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::ManuPathName(Int_t detElemId, Int_t manuId) const
+{
+  /// Build a name for one manu
+  return Form("%s/%s",DEPathName(detElemId).Data(),ManuName(manuId).Data());
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::BusPatchPathName(Int_t busPatchId) const
+{
+  /// Build a name for one buspatch
+  Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(busPatchId);
+  
+  return Form("%s/%s",DEPathName(detElemId).Data(),BusPatchName(busPatchId).Data());
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterHelper::PCBPathName(Int_t detElemId, Int_t pcbNumber) const
+{
+  /// Build a name for one pcb
+  return Form("%s/%s",DEPathName(detElemId).Data(),PCBName(pcbNumber).Data());
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONPainterHelper::FormatValue(const char* name, Double_t value) const
+{
+  /// Format a double value to be displayed
+  /// FIXME: should insure we have the right number of significant digits here...
+  
+  return Form("%s = %e",name,value);
+}
diff --git a/MUON/AliMUONPainterHelper.h b/MUON/AliMUONPainterHelper.h
new file mode 100644 (file)
index 0000000..42a4ece
--- /dev/null
@@ -0,0 +1,184 @@
+#ifndef ALIMUONPAINTERHELPER_H
+#define ALIMUONPAINTERHELPER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterHelper
+/// \brief Utility class for the painters display
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+
+#ifndef ROOT_TString
+#  include "TString.h"
+#endif
+
+#ifndef ROOT_TVector2
+#  include "TVector2.h"
+#endif
+
+#ifndef ALI_MP_PLANE_TYPE_H
+#  include "AliMpPlaneType.h"
+#endif
+
+#ifndef ALI_MP_CATHOD_TYPE_H
+#  include "AliMpCathodType.h"
+#endif
+
+#ifndef ALIMUONVPAINTER_H
+#  include "AliMUONVPainter.h"
+#endif
+
+#ifndef ALI_MP_PAD_H
+#  include "AliMpPad.h"
+#endif
+
+class AliMUONAttPainter;
+class AliMUONPainterContour;
+class AliMUONPainterContourMaker;
+class AliMUONPainterEnv;
+class AliMUONPainterPadStore;
+class AliMUONVCalibParam;
+class AliMUONVTrackerData;
+class AliMpExMap;
+class AliMpMotifPosition;
+class AliMpPCB;
+class AliMpSector;
+class AliMpSlat;
+class TArrayI;
+class TList;
+class TMap;
+class TObjArray;
+
+class AliMUONPainterHelper : public TObject
+{
+public:
+  AliMUONPainterHelper();
+  virtual ~AliMUONPainterHelper();
+    
+  TString ChamberName(Int_t chamberId) const;
+  TString StationName(Int_t stationId) const;
+  TString DEName(Int_t detElemId) const;
+  TString ManuName(Int_t manuId) const;
+  TString BusPatchName(Int_t busPatchId) const;
+  TString PCBName(Int_t pcbNumber) const;
+
+  TString ChamberPathName(Int_t chamberId) const;
+  TString StationPathName(Int_t stationId) const;
+  TString DEPathName(Int_t detElemId) const;
+  TString ManuPathName(Int_t detElemId, Int_t manuId) const;
+  TString BusPatchPathName(Int_t busPatchId) const;
+  TString PCBPathName(Int_t detElemId, Int_t pcbNumber) const;
+  
+  Int_t ColorFromValue(Double_t value, Double_t min, Double_t max) const;
+  
+  Int_t FindPadID(const TArrayI& pads, Double_t x, Double_t y) const;
+    
+  AliMp::CathodType GetCathodeType(Int_t detElemId, Int_t manuId) const;
+
+  AliMUONPainterContour* GenerateManuContour(Int_t detElemId, Int_t manuId,
+                                             AliMUONAttPainter viewType,
+                                             const char* contourName);
+
+  void GetBoundaries(const TArrayI& pads, Double_t& xmin, Double_t& ymin,
+                     Double_t& xmax, Double_t& ymax) const;
+
+  AliMUONPainterContour* GetContour(const char* contourName) const;
+
+  AliMUONPainterContour* GetContour(const TString& contourName) const { return GetContour(contourName.Data()); }
+
+  AliMUONPainterContour* GetLocalManuContour(Int_t detElemId, Int_t manuId) const;
+
+  AliMpMotifPosition* GetMotifPosition(Int_t detElemId, Int_t manuId) const;
+  
+  AliMpPCB* GetPCB(Int_t detElemId, AliMp::PlaneType planeType, 
+                   Int_t pcbNumber) const;
+
+  AliMpPCB* GetPCB(Int_t detElemId, AliMp::CathodType cathodType,
+                   Int_t pcbNumber) const;
+
+  AliMp::PlaneType GetPlaneType(Int_t manuId) const;
+  
+  const AliMpSector* GetSector(Int_t detElemId, AliMp::PlaneType planeType) const;
+    
+  const AliMpSlat* GetSlat(Int_t detElemId, AliMp::PlaneType planeType) const;
+
+  const AliMpSlat* GetSlat(Int_t detElemId, AliMp::CathodType cathodeType) const;
+
+  const AliMpSlat* GetSlat(Int_t detElemId, Int_t manuId) const;
+
+  static AliMUONPainterHelper* Instance();
+
+  AliMpPad PadByExplodedPosition(Int_t detElemId, Int_t manuId, Double_t x, Double_t y) const;
+  
+  void Exploded2Real(Int_t detElemId, Double_t xe, Double_t ye, Double_t ze,
+                     Double_t& xr, Double_t& yr, Double_t& zr) const;
+  
+  void Local2Global(Int_t detElemId, Double_t xl, Double_t yl, Double_t zl,
+                    Double_t& xg, Double_t& yg, Double_t& zg) const;
+
+  void Local2GlobalReal(Int_t detElemId, Double_t xl, Double_t yl, Double_t zl,
+                        Double_t& xg, Double_t& yg, Double_t& zg) const;
+
+  void Global2Local(Int_t detElemId, Double_t xg, Double_t yg, Double_t zg,
+                     Double_t& xl, Double_t& yl, Double_t& zl) const;
+
+  void Global2LocalReal(Int_t detElemId, Double_t xg, Double_t yg, Double_t zg,
+                        Double_t& xl, Double_t& yl, Double_t& zl) const;
+
+  AliMUONPainterContour* MergeContours(const TObjArray& contours, 
+                                       const char* contourName);
+  
+  virtual void Print(Option_t* opt="") const;
+  
+  void RegisterContour(AliMUONPainterContour* contour);
+  
+  /// Whether we were modified since our creation
+  Bool_t IsModified() const { return fIsModified; }
+  
+  /// Set the modified flag
+  void Modified(Bool_t value=kTRUE) { fIsModified = value; }
+
+  void Save();
+  
+  const AliMUONPainterPadStore& PadStore() const { return *fPadStore; }
+  
+  TString FormatValue(const char* name, Double_t value) const;
+  
+  AliMUONPainterEnv* Env() { return fEnv; }
+  
+private:
+    
+  /// Not implemented
+  AliMUONPainterHelper(const AliMUONPainterHelper&);
+  /// Not implemented
+  AliMUONPainterHelper& operator=(const AliMUONPainterHelper&);
+  
+  void GenerateDefaultMatrices();
+  void GenerateGeometry();
+  void GeneratePadStore();
+  void GeneratePadStore(Int_t detElemId);  
+
+private:
+  static AliMUONPainterHelper* fgInstance; ///< global instance
+  
+  AliMUONPainterPadStore* fPadStore; ///< the pad store
+  Double_t fExplodeFactor[2]; ///< explosing factors for representation
+  AliMpExMap* fExplodedGlobalTransformations; ///< global geometric transformations (exploded)
+  AliMpExMap* fRealGlobalTransformations; ///< global geometric transformations (real)
+  Bool_t fIsModified; ///< whether we've been modified since creation
+  mutable AliMUONPainterContourMaker* fContourMaker; ///< the contour builder
+  TObjArray* fPainterMatrices; ///< default matrices
+  AliMUONPainterEnv* fEnv; ///< resources
+  
+  ClassDef(AliMUONPainterHelper,1) // Helper class for painters
+};
+
+#endif
diff --git a/MUON/AliMUONPainterHighlighter.cxx b/MUON/AliMUONPainterHighlighter.cxx
new file mode 100644 (file)
index 0000000..ae13218
--- /dev/null
@@ -0,0 +1,71 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterHighlighter.h"
+
+#include "AliMUONVPainter.h"
+#include "AliMUONPainterContour.h"
+#include "AliLog.h"
+
+/// \class AliMUONPainterHighlighter
+///
+/// A special painter which highlights another one.
+/// Highlighting is currently a bold yellow outline of the relevant painter
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterHighlighter)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterHighlighter::AliMUONPainterHighlighter()
+: TObject(), fPainter(0x0), fX(FLT_MAX), fY(FLT_MAX)
+{
+  /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPainterHighlighter::~AliMUONPainterHighlighter()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHighlighter::SetPainter(AliMUONVPainter* painter, Double_t x, Double_t y)
+{
+  /// Set the painte we should highlight
+  
+  AliDebug(1,Form("painter=%s x=%e y=%e",(painter ? painter->GetName() : ""),x,y));
+  fPainter = painter;
+  fX = x;
+  fY = y;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterHighlighter::Paint(Option_t*)
+{
+  /// Actually highlight our painter, if we have one
+  if ( fPainter ) 
+  {
+    AliDebug(1,Form("painter=%s fX=%e fY=%e",fPainter->GetName(),fX,fY));
+    fPainter->PaintOutline(5,5,fX,fY);
+  }
+}
diff --git a/MUON/AliMUONPainterHighlighter.h b/MUON/AliMUONPainterHighlighter.h
new file mode 100644 (file)
index 0000000..77f2f91
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef ALIMUONPAINTERHIGHLIGHTER_H
+#define ALIMUONPAINTERHIGHLIGHTER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterHighlighter
+/// \brief Special painter which highlights (i.e. draws a yellow bold outline) another painter
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+#include <float.h>
+
+class AliMUONVPainter;
+
+class AliMUONPainterHighlighter : public TObject
+{
+public:
+  AliMUONPainterHighlighter();
+  virtual ~AliMUONPainterHighlighter();
+
+  void SetPainter(AliMUONVPainter* painter, Double_t x=FLT_MAX, Double_t y=FLT_MAX);
+  
+  void Paint(Option_t* opt="");
+  
+private:
+  /// Not implemented
+  AliMUONPainterHighlighter(const AliMUONPainterHighlighter& rhs);
+  /// Not implemented
+  AliMUONPainterHighlighter& operator=(const AliMUONPainterHighlighter& rhs);
+  
+private:
+  AliMUONVPainter* fPainter; //!< the painter we should highlight
+  Double_t fX; //!< position within painter to be highlighted
+  Double_t fY; //!< position within painter to be highlighted
+  
+  ClassDef(AliMUONPainterHighlighter,1) // Painter highlighter
+};
+
+#endif
diff --git a/MUON/AliMUONPainterInterfaceHelper.cxx b/MUON/AliMUONPainterInterfaceHelper.cxx
new file mode 100644 (file)
index 0000000..08336b9
--- /dev/null
@@ -0,0 +1,317 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterInterfaceHelper.h"
+
+///\class AliMUONPainterInterfaceHelper
+///
+/// Helper class to work with TGButtonGroup
+///
+/// This class only works if the buttons in the TGButtonGroup have contiguous
+/// ids, and if those ids start at ButtonStartingId().
+/// Not bullet-proof, I admit, but this is the only way I've found with
+/// the current TGButtonGroup implementation which does not allow to loop
+/// easily on all buttons.
+///
+// Author Laurent Aphecetche, Subatech
+
+#include "AliMUONPainterEnv.h"
+#include "AliMUONPainterHelper.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TClass.h>
+#include <TGButtonGroup.h>
+#include <TGButton.h>
+#include <TGClient.h>
+#include <TObjArray.h>
+#include <TObjString.h>
+#include <TString.h>
+#include <RVersion.h>
+#include <cassert>
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterInterfaceHelper)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterInterfaceHelper::AliMUONPainterInterfaceHelper() : TObject()
+{
+  /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPainterInterfaceHelper::~AliMUONPainterInterfaceHelper()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterInterfaceHelper::AddRadioButton(TGButtonGroup& bg,
+                                              const TString& name,
+                                              void* userData,
+                                              Bool_t select)
+{
+  /// Add a radio button to a group
+  Int_t n = bg.GetCount();
+  
+  TGButton* button = new TGRadioButton(&bg,
+                                       name.Data(),
+                                       n+ButtonStartingId());
+  button->SetUserData(userData);
+  button->SetOn(select,kFALSE);  
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterInterfaceHelper::AddCheckButton(TGButtonGroup& bg,
+                                              const TString& name,
+                                              void* userData,
+                                              Bool_t select)
+{
+  /// Add a check button to a group
+  Int_t n = bg.GetCount();
+  
+  TGButton* button = new TGCheckButton(&bg,
+                                       name.Data(),
+                                       n+ButtonStartingId());
+  button->SetUserData(userData);
+  button->SetOn(select,kFALSE);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterInterfaceHelper::ClearButtons(TGButtonGroup& bg)
+{
+  /// Remove all buttons from group.
+  /// Bear in mind that you're thus disconnecting the group from
+  /// any signals it might have. So you must re-connect them after
+  /// a call to this method, if you want to.
+  
+  while ( bg.GetCount() > 0 )
+  {
+    TGTextButton* button = (TGTextButton*)(bg.GetButton(bg.GetCount()));
+    if ( !button ) 
+    {
+      AliFatalClass(Form("Got a null button for bg.Count()=%d",bg.GetCount()));
+    }
+    bg.Remove(button);
+#if ROOT_VERSION_CODE <= ROOT_VERSION(5,16,0)
+    button->DestroyWindow();
+#endif
+    delete button;
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterInterfaceHelper::Copy(const TGButtonGroup& src, TGButtonGroup& dest)
+{
+  /// Copy a button group into another one
+  AliDebugClass(1,Form("src=%p (%s) count=%d dest=%p (%s) count=%d",
+                       &src,src.GetTitle(),src.GetCount(),
+                       &dest,dest.GetTitle(),dest.GetCount()));
+
+  StdoutToAliDebugClass(1,cout << "---copying:" << endl; Dump(src);
+                        cout << "---to:" << endl; Dump(dest));
+  
+  ClearButtons(dest);
+  
+  dest.SetTitle(src.GetTitle());
+  
+  if ( &src != &dest )
+  {
+    for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + src.GetCount(); ++i )
+    {
+      TGTextButton* tb = static_cast<TGTextButton*>(src.GetButton(i));
+      TGButton* button = new TGRadioButton(&dest,tb->GetTitle(),tb->WidgetId());
+      assert(tb->WidgetId()==i);
+      button->SetUserData(tb->GetUserData());
+      button->SetOn(tb->IsOn(),kFALSE);
+    }
+  }
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterInterfaceHelper::Dump(const TGButtonGroup& bg)
+{
+  /// Printout
+  cout << Form("ButtonGroup %s %s",bg.GetName(),bg.GetTitle()) << endl;
+  
+  for ( Int_t i = ButtonStartingId(); i < bg.GetCount() + ButtonStartingId(); ++i ) 
+  {
+    TGTextButton* button = static_cast<TGTextButton*>(bg.GetButton(i));
+    cout << Form("i %2d button %s id %d wid %d ON %d",
+                 i,button->GetTitle(),button->GetId(),
+                 button->WidgetId(),
+                 button->IsOn()) << endl;
+  }
+}
+
+//_____________________________________________________________________________
+TGButton* 
+AliMUONPainterInterfaceHelper::FindButtonByName(const TGButtonGroup& bg, 
+                                                const TString& name)
+{
+  /// Find a button by name
+  
+  for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + bg.GetCount(); ++i )
+  {
+    TGTextButton* button = static_cast<TGTextButton*>(bg.GetButton(i));
+    if ( name == button->GetTitle() )
+    {
+      return button;
+    }
+  }
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+TGButton* 
+AliMUONPainterInterfaceHelper::FindButtonByUserData(const TGButtonGroup& bg, 
+                                                    void* userData)
+{
+  /// Find a button by userData
+  
+  for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + bg.GetCount(); ++i )
+  {
+    TGButton* button = bg.GetButton(i);
+    if ( button->GetUserData() == userData )
+    {
+      return button;
+    }
+  }
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+TGButton* 
+AliMUONPainterInterfaceHelper::FindDownButton(const TGButtonGroup& bg)
+{
+  /// Find which button is down (in a radio group)
+  
+  AliDebugClass(1,Form("bg %s",bg.GetTitle()));
+  
+  for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + bg.GetCount(); ++i )
+  {
+    TGButton* button = bg.GetButton(i);
+    if ( button->IsOn() ) 
+    {
+      AliDebugClass(1,Form("button %s",button->GetTitle()));
+      return button;
+    }
+  }
+  return 0x0;
+}
+
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterInterfaceHelper::SetBackgroundColor(const char* resourceBaseName, 
+                                                  TGWindow& window)
+{
+  /// Set the background color of the window
+  TString rs(Form("%s.BackgroundColor",resourceBaseName));
+  TString colorName = AliMUONPainterHelper::Instance()->Env()->String(rs.Data(),"#c0c0c0");
+
+  Pixel_t color;
+  Bool_t ok = gClient->GetColorByName(colorName, color);
+  if ( ok ) 
+  {
+    window.SetBackgroundColor(color);
+    AliDebugClass(1,Form("Setting %s color to %s",rs.Data(),colorName.Data()));
+  }
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterInterfaceHelper::SetState(TGButtonGroup& bg, Bool_t state)
+{
+  /// should not be needed with root > 5.16/00 as there's a TGButtonGroup::SetState
+  /// method now...
+
+#if ROOT_VERSION_CODE > ROOT_VERSION(5,16,0)
+  bg.SetState(state);
+#else
+  for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + bg.GetCount(); ++i ) 
+  {
+    TGTextButton* button = (TGTextButton*)(bg.GetButton(i));
+    if ( state ) 
+    {
+      button->SetState(kButtonUp);
+    }
+    else
+    {
+      button->SetState(kButtonDisabled);
+    }
+  }
+#endif  
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterInterfaceHelper::Select(TGButtonGroup& bg, 
+                                      const TString& buttonName,
+                                      Bool_t emit)
+{
+  /// Select which button should be on
+  
+  AliDebugClass(1,Form("bg %s buttonName %s",bg.GetTitle(),buttonName.Data()));
+  
+  for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + bg.GetCount(); ++i ) 
+  {
+    TGTextButton* button = (TGTextButton*)(bg.GetButton(i));
+    if ( buttonName == button->GetTitle() || buttonName == "*" ) 
+    {
+      if ( emit ) 
+      {
+        button->Clicked();
+      }
+      else
+      {        
+        button->SetOn(kTRUE);
+      }
+    }
+  }  
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterInterfaceHelper::Unselect(TGButtonGroup& bg, 
+                                        const TString& buttonName,
+                                        Bool_t emit)
+{
+  /// Unselect a given button
+  
+  for ( Int_t i = ButtonStartingId(); i < ButtonStartingId() + bg.GetCount(); ++i ) 
+  {
+    TGTextButton* button = (TGTextButton*)(bg.GetButton(i));
+    if ( buttonName == button->GetTitle() || buttonName == "*" ) 
+    {
+      if ( emit ) 
+      {
+        button->Released();
+      }
+      else
+      {        
+        button->SetOn(kFALSE);
+      }
+    }
+  }  
+}
+
diff --git a/MUON/AliMUONPainterInterfaceHelper.h b/MUON/AliMUONPainterInterfaceHelper.h
new file mode 100644 (file)
index 0000000..360fd2a
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef AliMUONPainterInterfaceHelper_H
+#define AliMUONPainterInterfaceHelper_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterInterfaceHelper
+/// \brief Helper class to ease building a GUI with button groups...
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+
+class TGWindow;
+class TGButton;
+class TGButtonGroup;
+class TString;
+
+class AliMUONPainterInterfaceHelper : public TObject
+{
+public:
+  AliMUONPainterInterfaceHelper();
+  virtual ~AliMUONPainterInterfaceHelper();
+
+  static void AddRadioButton(TGButtonGroup& bg,
+                             const TString& name,
+                             void* userData=0x0,
+                             Bool_t select=kFALSE);
+
+  static void AddCheckButton(TGButtonGroup& bg,
+                             const TString& name,
+                             void* userData=0x0,
+                             Bool_t select=kFALSE);
+  
+  static Int_t ButtonStartingId() { return 1; }
+
+  static void ClearButtons(TGButtonGroup& bg);
+  
+  using TObject::Copy;
+  
+  static void Copy(const TGButtonGroup& src, TGButtonGroup& dest);
+    
+  using TObject::Dump;
+  
+  static void Dump(const TGButtonGroup& bg);
+    
+  static TGButton* FindButtonByName(const TGButtonGroup& bg, const TString& name);
+
+  static TGButton* FindButtonByUserData(const TGButtonGroup& bg, void* userData);
+
+  static TGButton* FindDownButton(const TGButtonGroup& bg);
+  
+  static void SetBackgroundColor(const char* resourceBaseName, TGWindow& window);
+
+  static void SetState(TGButtonGroup& bg, Bool_t state);
+
+  static void Select(TGButtonGroup& bg, const TString& buttonName, Bool_t emit=kFALSE);
+  
+  static void Unselect(TGButtonGroup& bg, const TString& buttonName, Bool_t emit=kFALSE);
+    
+  ClassDef(AliMUONPainterInterfaceHelper,1) // Helper class for TGButtonGroup manipulation
+};
+
+#endif
diff --git a/MUON/AliMUONPainterMasterFrame.cxx b/MUON/AliMUONPainterMasterFrame.cxx
new file mode 100644 (file)
index 0000000..63fdb74
--- /dev/null
@@ -0,0 +1,516 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterMasterFrame.h"
+
+#include "AliMUONChamberPainter.h"
+#include "AliMUONPainterGroup.h"
+#include "AliMUONPainterMatrix.h"
+#include "AliMUONPainterMatrixFrame.h"
+#include "AliMUONPainterInterfaceHelper.h"
+#include "AliMUONPainterRegistry.h"
+#include "AliMUONAttPainterSelectorFrame.h"
+#include "AliMUONVPainter.h"
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TApplication.h>
+#include <TCanvas.h>
+#include <TEnv.h>
+#include <TGComboBox.h>
+#include <TGLabel.h>
+#include <TObjArray.h>
+#include <TObjString.h>
+#include <TGButtonGroup.h>
+#include <TGMsgBox.h>
+
+/// \class AliMUONPainterMasterFrame
+///
+/// Main window of the 2D display
+///
+/// \author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterMasterFrame)
+///\endcond
+
+namespace
+{
+  UInt_t UniqueID(Int_t nx, Int_t ny)
+  {
+    return ny | (nx << 8);
+  }
+  
+  Int_t Nx(UInt_t uniqueID)
+  {
+    return ( uniqueID & 0xFF00 ) >> 8;
+  }
+
+  Int_t Ny(UInt_t uniqueID)
+  {
+    return uniqueID & 0xFF;
+  }
+
+}
+
+const Int_t AliMUONPainterMasterFrame::fgkBorderSize = 10;
+
+//_____________________________________________________________________________
+AliMUONPainterMasterFrame::AliMUONPainterMasterFrame(const TGWindow* p, 
+                                                     UInt_t w, UInt_t h)
+: TGCompositeFrame(p,w,h,kVerticalFrame),
+  fNavigationFrame(0x0),
+  fPainterMatrixFrame(0x0),
+  fBackButton(0x0),
+  fForwardButton(0x0),
+  fGroupTitle(0x0),
+  fNavigation(),
+  fCurrentNavigationPosition(-1),
+  fAttPainterSelectorFrame(0x0)
+{  
+  /// ctor
+    
+  UInt_t wi = w - fgkBorderSize*2;
+  UInt_t hi = h - fgkBorderSize*3;
+  
+  fNavigationFrame = new TGHorizontalFrame(this,wi);
+  
+  AddFrame(fNavigationFrame,new TGLayoutHints(kLHintsExpandX|kLHintsTop,
+                                              fgkBorderSize,fgkBorderSize,
+                                              fgkBorderSize,fgkBorderSize));
+    
+  fBackButton = new TGPictureButton(fNavigationFrame,
+                                       gClient->GetPicture("tb_back.xpm"));
+  
+  fForwardButton = new TGPictureButton(fNavigationFrame,
+                                       gClient->GetPicture("tb_forw.xpm"));
+
+  fAttPainterSelectorFrame = new AliMUONAttPainterSelectorFrame(fNavigationFrame,w/2,20);
+  
+  fGroupTitle = new TGLabel(fNavigationFrame,"");
+  
+  fNavigationFrame->AddFrame(fBackButton,new TGLayoutHints(kLHintsCenterY));
+  fNavigationFrame->AddFrame(fForwardButton,new TGLayoutHints(kLHintsCenterY));
+  
+  fNavigationFrame->AddFrame(fAttPainterSelectorFrame,new TGLayoutHints(kLHintsCenterY,10));
+  
+  fAttPainterSelectorFrame->Connect("Clicked(AliMUONAttPainter*)",
+                                    "AliMUONPainterMasterFrame",
+                                    this,
+                                    "AttributesChanged(AliMUONAttPainter*)");
+  
+  fNavigationFrame->AddFrame(fGroupTitle,new TGLayoutHints(kLHintsExpandX|kLHintsCenterX|kLHintsCenterY,10));
+  
+  fForwardButton->Connect("Clicked()","AliMUONPainterMasterFrame",
+                          this,
+                          "Forward()");
+
+  fBackButton->Connect("Clicked()","AliMUONPainterMasterFrame",
+                          this,
+                          "Backward()");
+    
+  
+                                                                   
+  UInt_t w1 = wi;
+  UInt_t h1 = hi - fNavigationFrame->GetHeight() - 3*fgkBorderSize;
+  
+  MakeTopPainterMatrix(w1,h1);
+
+  AddFrame(fPainterMatrixFrame,new TGLayoutHints(kLHintsExpandX,
+                                                fgkBorderSize,fgkBorderSize,
+                                                0,fgkBorderSize));
+  
+  AliMUONPainterInterfaceHelper::SetBackgroundColor("MasterFrame.Navigation",*fNavigationFrame);
+  AliMUONPainterInterfaceHelper::SetBackgroundColor("MasterFrame.Main",*this);
+  
+  AliDebug(1,Form("fNavigation=%p",&fNavigation));
+  
+  AliMUONPainterRegistry::Instance()->Connect("PainterMatrixWantToShow(AliMUONPainterMatrix*)",
+                                              "AliMUONPainterMasterFrame",
+                                              this,
+                                              "PainterMatrixWantToShow(AliMUONPainterMatrix*)");
+  
+  fPainterMatrixFrame->DataSourceWasChanged("*",0x0,-1);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterMasterFrame::~AliMUONPainterMasterFrame()
+{
+  /// dtor
+  Cleanup();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::AddPainterMatrix(AliMUONPainterMatrix* painterMatrix)
+{
+  /// array is adopted (by the registry)
+
+  AliDebug(1,Form("matrix=%x %s",painterMatrix,painterMatrix->GetName()));
+  
+  Int_t i = AliMUONPainterRegistry::Instance()->Register(painterMatrix);
+
+  SetNavigation(i);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::PainterMatrixWantToShow(AliMUONPainterMatrix* group)
+{
+  // FIXME: should check whether we are the active window before
+  // responding to this message
+
+  AliDebug(1,Form("group=%x %s",group,group->GetName()));
+  
+  Int_t i = AliMUONPainterRegistry::Instance()->FindIndexOf(group);
+
+  Int_t alreadyThere(-1);
+  
+  for ( Int_t j = 0; j < fNavigation.GetSize(); ++j )
+  {
+    if ( fNavigation[j] == i ) alreadyThere = j;
+  }
+  
+  if (alreadyThere<0) 
+  {
+    SetNavigation(i);
+  }
+  else
+  {
+    fCurrentNavigationPosition = alreadyThere;
+  }
+  
+  ShowPainterMatrix(group);  
+}
+                                                
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::SetNavigation(Int_t i)
+{
+  /// Change navigation position
+  
+  ++fCurrentNavigationPosition;
+  fNavigation.Set(fCurrentNavigationPosition+1);
+  fNavigation[fCurrentNavigationPosition] = i;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::ShowPainterMatrix(AliMUONPainterMatrix* painterMatrix)
+{
+  /// Change the painter matrix we show
+  
+  fPainterMatrixFrame->Use(painterMatrix);
+  
+  painterMatrix->Connect("Clicked(AliMUONVPainter*,Double_t*)",
+                         "AliMUONPainterMasterFrame",this,
+                         "Clicked(AliMUONVPainter*,Double_t*)");
+
+  painterMatrix->Connect("ShiftClicked(AliMUONVPainter*,Double_t*)",
+                         "AliMUONPainterMasterFrame",this,
+                         "ShiftClicked(AliMUONVPainter*,Double_t*)");
+  
+  fPainterMatrixFrame->Connect("TitleHasChanged(const char*)",
+                              "AliMUONPainterMasterFrame",this,
+                              "ChangeTitle(const char*)");
+  UpdateNavigation();
+  
+  UpdateAttributes(*(fPainterMatrixFrame->Matrix()));
+  
+  AliMUONPainterRegistry::Instance()->AddToHistory(painterMatrix);
+  
+  Layout();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::ChangeTitle(const char* newTitle)
+{
+  /// Change the top title
+  
+  fGroupTitle->SetText(newTitle);
+  fGroupTitle->Resize();
+  Layout();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::Backward()
+{
+  /// Move back one step in the history
+  --fCurrentNavigationPosition;
+  
+  AliMUONPainterMatrix* group = 
+    AliMUONPainterRegistry::Instance()->PainterMatrix(fNavigation[fCurrentNavigationPosition]);
+  
+  ShowPainterMatrix(group);
+  
+  UpdateNavigation();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::Forward()
+{
+  /// Move forward one step in history
+  
+  ++fCurrentNavigationPosition;
+  
+  AliMUONPainterMatrix* group = 
+    AliMUONPainterRegistry::Instance()->PainterMatrix(fNavigation[fCurrentNavigationPosition]);
+  
+  ShowPainterMatrix(group);
+  
+  UpdateNavigation();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMasterFrame::Clicked(AliMUONVPainter* painter, Double_t* values)
+{
+  /// A given painter was (singly) clicked
+  
+  AliDebug(1,Form("%s x %7.3f y %7.3f",painter->GetName(),values[0],values[1]));
+
+  AliCodeTimerAuto("")
+  
+  fPainterMatrixFrame->MouseLeave(painter);
+  
+  AliMUONPainterMatrix* matrix = new AliMUONPainterMatrix(painter->Name().Data());
+
+  AliMUONVPainter* p = painter->Detach();
+
+  p->SetResponder(1);
+
+  matrix->Adopt(p);
+  
+  AddPainterMatrix(matrix);
+  ShowPainterMatrix(matrix);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMasterFrame::ShiftClicked(AliMUONVPainter* painter, Double_t*)
+{
+  /// A given painter was shift-clicked
+  
+  AliMUONPainterMatrix* currentMatrix = fPainterMatrixFrame->Matrix();
+  
+  AliMUONAttPainter a = painter->Attributes();
+  
+  TString basename(Form("%s-DUAL",painter->GetName()));
+  
+  TString newName = AliMUONPainterMatrix::NameIt(basename.Data(),a);
+  
+  AliMUONPainterMatrix* matrix = 
+    AliMUONPainterRegistry::Instance()->FindPainterMatrix(newName.Data());
+  
+  if (!matrix)
+  {
+    // No. So we must make a new matrix painter from the existing one,
+    // and add to this new matrix the painters of the other one, but
+    // using the new attributes...
+    
+    // create "opposite" attributes
+    AliMUONAttPainter a1(a);
+    AliMUONAttPainter a2(a);
+    
+    if ( a.IsCathodeDefined() ) 
+    {
+      a2.SetCathode(!a.IsCathode0(),!a.IsCathode1());
+    }
+    
+    if ( a.IsPlaneDefined() ) 
+    {
+      a2.SetPlane(!a.IsBendingPlane(),!a.IsNonBendingPlane());
+    }
+    
+    a1.SetCathodeAndPlaneDisabled(kTRUE);
+    a2.SetCathodeAndPlaneDisabled(kTRUE);
+
+    AliMUONVPainter* p1 = AliMUONVPainter::CreatePainter(painter->ClassName(),
+                                                         a1,
+                                                         painter->ID0(),
+                                                         painter->ID1());
+    
+    AliMUONVPainter* p2 = AliMUONVPainter::CreatePainter(painter->ClassName(),
+                                                        a2,
+                                                        painter->ID0(),
+                                                        painter->ID1());
+    
+    if (!p1 || !p2)
+    {
+      Int_t ret;
+      new TGMsgBox(gClient->GetRoot(), this,
+                   "Invalid combination", "Cannot create 2 views from this painter",
+                   kMBIconExclamation, kMBOk, &ret);
+      PainterMatrixWantToShow(currentMatrix);
+      delete p1;
+      delete p2;
+      return;
+    }
+    
+    AliInfo(Form("Starting from %s will generate %s and %s",
+                 a.GetName(),
+                 a1.GetName(),
+                 a2.GetName()));
+    
+    p1->UpdateGroupsFrom(*(painter->Master()));
+    p2->UpdateGroupsFrom(*(painter->Master()));
+    
+    p1->SetResponder(1);
+    p2->SetResponder(1);
+    
+    Int_t nx(2);
+    Int_t ny(1);
+    
+    AliMpArea area(painter->Area());
+
+    if ( area.Dimensions().X() > 1.2*area.Dimensions().Y() ) 
+    {
+      nx = 1;
+      ny = 2;
+    }
+    
+    matrix = new AliMUONPainterMatrix(basename.Data(),nx,ny);
+    
+    matrix->Adopt(p1);
+    matrix->Adopt(p2);
+    
+    AddPainterMatrix(matrix);
+  }
+  
+  matrix->SetData(currentMatrix->DataPattern(),
+                  currentMatrix->Data(),
+                  currentMatrix->DataIndex());
+  
+  fPainterMatrixFrame->MouseLeave(painter);
+  
+  PainterMatrixWantToShow(matrix);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::Update()
+{
+  /// Update ourselves
+  
+  fPainterMatrixFrame->Update();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::UpdateAttributes(const AliMUONPainterMatrix& painterMatrix)
+{
+  /// Update the view buttons from the matrix we actually plot
+  
+  fAttPainterSelectorFrame->Update(painterMatrix.Attributes());
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::MakeTopPainterMatrix(UInt_t w, UInt_t h)
+{
+  /// Create the first painter matrix that appears when we are create
+  /// FIXME: how to make this more flexible ?
+  
+  fPainterMatrixFrame = new AliMUONPainterMatrixFrame(this,w,h);
+
+  AliMUONAttPainter att;
+  
+  att.SetCathode(kTRUE,kFALSE);
+  att.SetViewPoint(kTRUE,kFALSE);
+    
+  TString name = AliMUONPainterMatrix::NameIt("Tracker",att);
+  
+  AliMUONPainterMatrix* painterMatrix = AliMUONPainterRegistry::Instance()->FindPainterMatrix(name);
+  
+  if (!painterMatrix)
+  {
+    AliError(Form("Could not get pre-defined painter matrix %s : check that !",name.Data()));
+  }
+  else
+  {
+    PainterMatrixWantToShow(painterMatrix);
+//    fPainterMatrixFrame->Use(painterMatrix);
+//    ShowPainterMatrix(painterMatrix);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::UpdateNavigation()
+{
+  /// Update navigation frame
+
+  fBackButton->SetEnabled(kTRUE);
+  fForwardButton->SetEnabled(kTRUE);
+
+  if ( fCurrentNavigationPosition == 0 ) 
+  {
+    fBackButton->SetEnabled(kFALSE);
+  }
+  if ( fCurrentNavigationPosition == fNavigation.GetSize()-1 ) 
+  {
+    fForwardButton->SetEnabled(kFALSE);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMasterFrame::AttributesChanged(AliMUONAttPainter* newValues)
+{
+  /// Attributes changed (e.g. from cath0 to cath1 or bending to nonbending, etc...)
+  
+  AliMUONPainterMatrix* currentMatrix = fPainterMatrixFrame->Matrix();
+  
+  AliMUONAttPainter a = currentMatrix->Validate(*newValues);
+  
+  if (!a.IsValid())
+  {
+    Int_t ret;
+    new TGMsgBox(gClient->GetRoot(), this,
+                 "Invalid combination", "Change of attributes not possible for this object",
+                 kMBIconExclamation, kMBOk, &ret);
+    PainterMatrixWantToShow(currentMatrix);
+    return;
+  }
+  
+  // First check if we already have this matrix available
+  
+  TString newName = AliMUONPainterMatrix::NameIt(currentMatrix->Basename(),a);
+  
+  AliMUONPainterMatrix* matrix = 
+    AliMUONPainterRegistry::Instance()->FindPainterMatrix(newName.Data());
+
+  if (!matrix)
+  {
+    // No. So we must make a new matrix painter from the existing one,
+    // and add to this new matrix the painters of the other one, but
+    // using the new attributes...
+    
+    matrix = currentMatrix->Clone(a);
+  
+    AddPainterMatrix(matrix);
+  }
+  
+  matrix->SetData(currentMatrix->DataPattern(),
+                  currentMatrix->Data(),
+                  currentMatrix->DataIndex());
+  
+  PainterMatrixWantToShow(matrix);
+}
diff --git a/MUON/AliMUONPainterMasterFrame.h b/MUON/AliMUONPainterMasterFrame.h
new file mode 100644 (file)
index 0000000..4e87587
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef ALIMUONPAINTERMASTERFRAME_H
+#define ALIMUONPAINTERMASTERFRAME_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterMasterFrame
+/// \brief The main window for the offline "a la mood" display
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TGFrame
+#  include <TGFrame.h>
+#endif
+#ifndef ROOT_TArrayI
+#  include <TArrayI.h>
+#endif
+
+class AliMUONAttPainter;
+class AliMUONPainterMatrix;
+class AliMUONPainterMatrixFrame;
+class AliMUONAttPainterSelectorFrame;
+class AliMUONVPainter;
+class TGButton;
+class TGButtonGroup;
+class TGComboBox;
+class TGLabel;
+class TObjArray;
+
+class AliMUONPainterMasterFrame : public TGCompositeFrame
+{
+public:
+  AliMUONPainterMasterFrame(const TGWindow* p, UInt_t w, UInt_t h);
+  virtual ~AliMUONPainterMasterFrame();
+
+  void Backward();
+
+  void ChangeTitle(const char* newTitle);
+  
+  void Clicked(AliMUONVPainter* painter, Double_t* values);
+
+  void ShiftClicked(AliMUONVPainter* painter, Double_t* values);
+
+  void Forward();
+  
+  void PainterMatrixWantToShow(AliMUONPainterMatrix* group);
+
+  void Update();
+
+  void AttributesChanged(AliMUONAttPainter* newValues);
+  
+private:
+  /// not implemented
+  AliMUONPainterMasterFrame(const AliMUONPainterMasterFrame& rhs);
+  /// not implemented
+  AliMUONPainterMasterFrame& operator=(const AliMUONPainterMasterFrame& rhs);
+  
+  void AddPainterMatrix(AliMUONPainterMatrix* group);
+  void AddPainter(AliMUONVPainter* painter);
+  void MakeTopPainterMatrix(UInt_t w, UInt_t h);
+  void SetNavigation(Int_t i);
+  void ShowPainterMatrix(AliMUONPainterMatrix* group);  
+  void UpdateNavigation();
+  void UpdateAttributes(const AliMUONPainterMatrix& painterMatrix);
+
+private:
+  TGHorizontalFrame* fNavigationFrame; ///< top frame for navigation
+  AliMUONPainterMatrixFrame* fPainterMatrixFrame; ///< main frame with painters
+  
+  TGButton* fBackButton; ///< navigation back 
+  TGButton* fForwardButton; ///< navigation forward
+  TGLabel* fGroupTitle; ///< top title
+  
+  TArrayI fNavigation; ///< navigation "history"
+    
+  Int_t fCurrentNavigationPosition; ///< current position in navigation history
+
+  AliMUONAttPainterSelectorFrame* fAttPainterSelectorFrame; ///< view type selection frame
+  
+  static const Int_t fgkBorderSize; ///< border sizes to use when placing frames
+
+  ClassDef(AliMUONPainterMasterFrame,0) // Main window of display
+};
+
+#endif
diff --git a/MUON/AliMUONPainterMatrix.cxx b/MUON/AliMUONPainterMatrix.cxx
new file mode 100644 (file)
index 0000000..ac82cad
--- /dev/null
@@ -0,0 +1,420 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterMatrix.h"
+
+#include "AliMUONPainterGroup.h"
+#include "AliMUONVPainter.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TObjArray.h>
+#include <float.h>
+#include <TObjString.h>
+
+///\class AliMUONPainterMatrix
+///
+/// Matrix of AliMUONVPainter
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterMatrix)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterMatrix::AliMUONPainterMatrix(const char* name, Int_t nx, Int_t ny)
+: TObject(),
+  fBasename(name),
+  fName(""),
+  fNx(nx),
+  fNy(ny),
+  fPainters(new TObjArray(fNx*fNy)),
+  fAttributes()
+{
+    /// ctor
+
+    fPainters->SetOwner(kTRUE);
+    if ( fNx*fNy > 1 ) 
+    {
+      fAttributes.SetSingle(kFALSE);
+    }
+    
+    fName = NameIt(name,fAttributes);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterMatrix::~AliMUONPainterMatrix()
+{
+  /// dtor
+  delete fPainters;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrix::Adopt(AliMUONVPainter* painter)
+{
+  /// Adopt a given painter
+  fPainters->AddLast(painter);
+  UpdateAttributes();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::UpdateAttributes()
+{
+  /// Update our attributes (using our painters' attributes)
+  
+  Bool_t cathode0(kFALSE);
+  Bool_t cathode1(kFALSE);
+  Bool_t bending(kFALSE);
+  Bool_t nonbending(kFALSE);
+  Bool_t front(kFALSE);
+  Bool_t back(kFALSE);
+  Bool_t cathplaneexclusive(kFALSE);
+  Bool_t cathplanedisabled(kFALSE);
+  
+  for ( Int_t i = 0; i < Size(); ++i )
+  {
+    AliMUONAttPainter att = Painter(i)->Attributes();
+    
+    if ( att.IsCathodeDefined() ) 
+    {
+      if ( att.IsCathode0() ) cathode0 = kTRUE;
+      if ( att.IsCathode1() ) cathode1 = kTRUE;
+    }
+
+    if ( att.IsPlaneDefined() ) 
+    {
+      if ( att.IsBendingPlane() ) bending = kTRUE;
+      if ( att.IsNonBendingPlane() ) nonbending = kTRUE;
+    }
+    
+    if ( att.IsFrontView() ) front = kTRUE;
+    if ( att.IsBackView() ) back = kTRUE;
+    
+    if ( att.IsCathodeAndPlaneMutuallyExclusive() ) cathplaneexclusive = kTRUE;
+    
+    if ( att.IsCathodeAndPlaneDisabled() ) cathplanedisabled = kTRUE;
+  }
+  
+  fAttributes.SetCathode(cathode0,cathode1);
+  fAttributes.SetPlane(bending,nonbending);
+  fAttributes.SetViewPoint(front,back);
+  fAttributes.SetCathodeAndPlaneMutuallyExclusive(cathplaneexclusive);
+  fAttributes.SetCathodeAndPlaneDisabled(cathplanedisabled);
+  
+  fName = NameIt(fBasename,fAttributes);
+}
+
+//_____________________________________________________________________________
+TString
+AliMUONPainterMatrix::NameIt(const TString& basename, const AliMUONAttPainter& att)
+{
+  /// Build a name 
+  TString name(basename);
+  
+  name += "-";
+  name += att.Name();
+  
+  return name;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrix::ComputeDataRange()
+{
+  /// Compute the data range spanned by the painters in this matrix
+  
+  Double_t dataMin(FLT_MAX);
+  Double_t dataMax(-FLT_MAX);
+  Bool_t atLeastOnePlotter(kFALSE);
+  
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    AliMUONVPainter* p = Painter(i);
+    AliMUONPainterGroup* g = p->PlotterGroup();
+
+    Double_t min(FLT_MAX);
+    Double_t max(-FLT_MAX);
+
+    if ( g ) 
+    {
+      atLeastOnePlotter = kTRUE;
+      g->ComputeDataRange(min,max);
+      if ( min <= max ) 
+      {
+        dataMin = TMath::Min(min,dataMin);
+        dataMax = TMath::Max(max,dataMax);
+      }
+    }
+
+    AliDebug(1,Form("painter %s group %s min %e max %e dataMin,Max=%7.3f,%7.3f",
+                    p->GetName(),
+                    g ? g->Type() : "none",
+                    min,max,
+                    dataMin,dataMax));
+  }
+
+  if ( dataMin > dataMax && atLeastOnePlotter ) 
+  {
+    AliError(Form("data min %e > max %e : setting both to 0.0",
+                    dataMin,dataMax));
+    dataMin = dataMax = 0.0;
+  }
+  
+  AliDebug(1,Form("Final dataMin,Max=%7.3f,%7.3f",dataMin,dataMax));
+  
+  SetDataRange(dataMin,dataMax);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrix::Connect(const char* sourceMethod, const char* destClassName, 
+                              void* destObject, const char* destMethod)
+{
+  /// Connect our painters
+  
+  for ( Int_t i = 0; i < Size(); ++i )
+  {
+    Painter(i)->Connect(sourceMethod,destClassName,destObject,destMethod);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::GetDataRange(Double_t& dataMin, Double_t& dataMax) const
+{
+  /// Get the data range spanned by the painters in this matrix
+  
+  dataMin=FLT_MAX;
+  dataMax=-FLT_MAX;
+  
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    AliMUONVPainter* p = Painter(i);
+    if ( p )
+    {
+      AliMUONPainterGroup* g = p->PlotterGroup();
+      if ( g ) 
+      {
+        dataMin = TMath::Min(dataMin,g->DataMin());
+        dataMax = TMath::Max(dataMax,g->DataMax());
+      }
+    }
+  }
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrix::GetTypes(TObjArray& types) const
+{
+  /// Get the types of the painters in this matrix
+  
+  types.SetOwner(kTRUE);
+  types.Clear();
+  
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    AliMUONVPainter* p = Painter(i);
+    TObjArray ptypes;
+    p->GetTypes(ptypes);
+    TIter next(&ptypes);
+    TObject* o;
+    while ( ( o = next() ) )
+    {
+      if ( ! types.FindObject(o) )
+      {
+        types.AddLast(o->Clone());
+      }
+    }
+  }  
+}
+
+//_____________________________________________________________________________
+AliMUONVPainter* 
+AliMUONPainterMatrix::Painter(Int_t index) const
+{
+  /// Get a given painter
+  
+  if ( index <= fPainters->GetLast() ) 
+  {
+    return static_cast<AliMUONVPainter*>(fPainters->At(index));
+  }
+  return 0x0;
+}
+
+//_____________________________________________________________________________
+AliMUONVTrackerData* 
+AliMUONPainterMatrix::Data() const
+{
+  AliMUONPainterGroup* group = Painter(0)->PlotterGroup();
+  return ( group ? group->Data() : 0x0 );
+}
+
+//_____________________________________________________________________________
+TString 
+AliMUONPainterMatrix::DataPattern() const
+{
+  AliMUONPainterGroup* group = Painter(0)->PlotterGroup();
+  return ( group ? group->Type() : "" );
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterMatrix::DataIndex() const
+{
+  AliMUONPainterGroup* group = Painter(0)->PlotterGroup();
+  return ( group ? group->DataIndex() : -1 );
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::SetData(const char* pattern, AliMUONVTrackerData* d,
+                              Int_t indexInData)
+{
+  /// Set the data to be plotted
+  
+  for ( Int_t i = 0; i < Size(); ++i )
+  {
+    AliMUONVPainter* painter = Painter(i);
+    painter->SetData(pattern,d,indexInData);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::SetDataRange(Double_t dataMin, Double_t dataMax)
+{
+  /// Set the data range
+  
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    AliMUONVPainter* p = Painter(i);
+    AliMUONPainterGroup* g = p->PlotterGroup();
+    if ( g ) 
+    {
+      g->SetDataRange(dataMin,dataMax);
+    }
+  }       
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONPainterMatrix::Size() const
+{
+  /// Return the number of painters we actually handle
+  return fPainters->GetLast()+1;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::Print(Option_t*) const
+{
+  /// Printout
+  cout << "Basename=" << fBasename.Data() << " Name=" << fName.Data() 
+  << " Nx=" << fNx << " Ny=" << fNy << " Att=" << fAttributes.GetName() << endl;
+}
+
+//_____________________________________________________________________________
+//void 
+//AliMUONPainterMatrix::ChangeAttributes(const AliMUONAttPainter& attributes)
+//{
+//  /// Change painters' attributes
+//  
+//  AliWarning("Implement me !");
+//  
+//  //  for ( Int_t i = 0; i < Size(); ++i ) 
+//  //  {
+//  //    Painter(i)->SetAttributes(attributes);
+//  //  }
+//}
+
+//_____________________________________________________________________________
+AliMUONPainterMatrix*
+AliMUONPainterMatrix::Clone(const AliMUONAttPainter& attributes) const
+{
+  /// Clone with given attributes
+  
+  AliMUONPainterMatrix* clone = new AliMUONPainterMatrix(Basename().Data(),Nx(),Ny());
+
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    AliMUONVPainter* oldPainter = Painter(i);
+    
+    AliMUONVPainter* newPainter(0x0);
+    
+    newPainter = AliMUONVPainter::CreatePainter(oldPainter->ClassName(),
+                                                attributes,
+                                                oldPainter->ID0(),
+                                                oldPainter->ID1());
+    
+    if (newPainter)
+    {
+      newPainter->UpdateGroupsFrom(*(oldPainter->Master()));
+      clone->Adopt(newPainter);
+    }
+    else
+    {
+      AliError(Form("Failed to create painter of class %s ID0 %d ID1 %d",
+                    oldPainter->ClassName(),
+                    oldPainter->ID0(),
+                    oldPainter->ID1()));
+    }
+  }
+  
+  return clone;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::SetOutlined(const char* pattern, Bool_t value)
+{
+  /// Calls SetOutlined for all our painters
+
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    Painter(i)->SetOutlined(pattern,value);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrix::SetResponder(const char* pattern)
+{
+  /// Calls SetResponder for all our painters
+  for ( Int_t i = 0; i < Size(); ++i ) 
+  {
+    Painter(i)->SetResponder(pattern);
+  }
+}
+
+//_____________________________________________________________________________
+AliMUONAttPainter
+AliMUONPainterMatrix::Validate(const AliMUONAttPainter& att) const
+{
+  /// Normalize attributes
+
+  AliMUONAttPainter a;
+  
+  for ( Int_t i = 0; i < Size() && a.IsValid(); ++i ) 
+  {
+    a = Painter(i)->Validate(att);
+  }
+  return a;
+}
+
+
diff --git a/MUON/AliMUONPainterMatrix.h b/MUON/AliMUONPainterMatrix.h
new file mode 100644 (file)
index 0000000..b5e50a1
--- /dev/null
@@ -0,0 +1,121 @@
+#ifndef ALIMUONPAINTERMATRIX_H
+#define ALIMUONPAINTERMATRIX_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterMatrix
+/// \brief A matrix of AliMUONVPainter
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+#ifndef ROOT_TString
+#  include "TString.h"
+#endif
+#ifndef ALIMUONATTPAINTER_H
+#  include "AliMUONAttPainter.h"
+#endif
+
+class AliMUONVPainter;
+class AliMUONVTrackerData;
+class TObjArray;
+
+class AliMUONPainterMatrix : public TObject
+{
+public:
+  AliMUONPainterMatrix(const char* basename="", Int_t nx=1, Int_t ny=1);
+  virtual ~AliMUONPainterMatrix();
+  
+  /// Adopt a painter in this matrix
+  void Adopt(AliMUONVPainter* painter);
+  
+  using TObject::Clone;
+  
+  AliMUONPainterMatrix* Clone(const AliMUONAttPainter& attributes) const;
+
+  void Connect(const char* sourceMethod, const char* destClassName, 
+               void* destObject, const char* destMethod);
+    
+//  void ChangeAttributes(const AliMUONAttPainter& attributes);
+  
+  /// Get our attributes
+  const AliMUONAttPainter& Attributes() const { return fAttributes; }
+  
+  /// Compute the data range for this matrix
+  void ComputeDataRange();
+  
+  /// Get the data range for this matrix
+  void GetDataRange(Double_t& dataMin, Double_t& dataMax) const;
+  
+  /// Get our name
+  virtual const char* GetName() const { return Name().Data(); }
+
+  static TString NameIt(const TString& basename, const AliMUONAttPainter& att);
+
+  /// Matrix name
+  virtual TString Name() const { return fName; }
+  
+  /// Base name (short name)
+  virtual TString Basename() const { return fBasename; }
+  
+  void GetTypes(TObjArray& types) const;
+
+  /// Number of painters to arrange in x-direction
+  Int_t Nx() const { return fNx; }
+  
+  /// Number of painters to arrange in y-direction
+  Int_t Ny() const { return fNy; }
+  
+  /// Get a painter
+  AliMUONVPainter* Painter(Int_t index) const;
+
+  /// Printout
+  void Print(Option_t* opt="") const;
+  
+  AliMUONVTrackerData* Data() const;
+  
+  TString DataPattern() const;
+  
+  Int_t DataIndex() const;
+  
+  void SetData(const char* pattern, AliMUONVTrackerData* d, Int_t indexInData);
+    
+  /// Force a given data range for all painter groups belonging to this matrix
+  void SetDataRange(Double_t min, Double_t max);
+  
+  void SetOutlined(const char* pattern, Bool_t value);
+
+  void SetResponder(const char* pattern);
+  
+  /// Number of painters (should be <= Nx*Ny)
+  Int_t Size() const;
+
+  /// Normalize attributes
+  AliMUONAttPainter Validate(const AliMUONAttPainter& att) const;
+  
+private:
+  /// Not implemented
+  AliMUONPainterMatrix(const AliMUONPainterMatrix& rhs);
+  /// Not implemented
+  AliMUONPainterMatrix& operator=(const AliMUONPainterMatrix& rhs);
+
+  void UpdateAttributes();
+  
+private:
+  TString fBasename; ///< base name of that matrix
+  TString fName; ///< complete name
+  Int_t fNx; ///< number of rows
+  Int_t fNy; ///< number of columns
+  TObjArray* fPainters; ///< painters in that matrix
+  AliMUONAttPainter fAttributes; ///< attributes of our painter(s)
+  
+  ClassDef(AliMUONPainterMatrix,1) // Matrix of AliMUONVPainter
+};
+
+#endif
diff --git a/MUON/AliMUONPainterMatrixFrame.cxx b/MUON/AliMUONPainterMatrixFrame.cxx
new file mode 100644 (file)
index 0000000..25147a8
--- /dev/null
@@ -0,0 +1,641 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterMatrixFrame.h"
+
+#include "AliMUONPainterColorSlider.h"
+#include "AliMUONPainterMatrix.h"
+#include "AliMUONPainterGroup.h"
+#include "AliMUONPainterHighlighter.h"
+#include "AliMUONPainterInterfaceHelper.h"
+#include "AliMUONPainterPlotSelector.h"
+#include "AliMUONPainterRegistry.h"
+#include "AliMUONVTrackerData.h"
+#include "AliMUONVPainter.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TCanvas.h>
+#include <TEnv.h>
+#include <TGButton.h>
+#include <TGButtonGroup.h>
+#include <TGFrame.h>
+#include <TGListBox.h>
+#include <TObjArray.h>
+#include <TObjString.h>
+#include <TRootEmbeddedCanvas.h>
+#include <TString.h>
+#include <cassert>
+#include <float.h>
+
+/// \class AliMUONPainterMatrixFrame
+///
+/// A widget to draw a painter matrix, and the corresponding interface
+/// to select what to outline or paint, and which part of the painter
+/// is responding to mouse events
+///
+/// \author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterMatrixFrame)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterMatrixFrame::AliMUONPainterMatrixFrame(const TGWindow* window, 
+                                                   UInt_t w, UInt_t h)
+: TGCompositeFrame(window,w,h,kVerticalFrame|kDoubleBorder),
+  fPainterMatrix(0x0),
+  fView(0x0),
+  fInterface(0x0),
+  fResponderButtons(0x0),
+  fOutlineButtons(0x0),
+  fPlotSelector(0x0),
+  fPainterHighlighter(new AliMUONPainterHighlighter),
+  fCanvasWidth(0),
+  fCanvasHeight(0),
+  fMainFrame(0x0),
+  fColorSlider(0x0)
+{
+    /// ctor
+    const Int_t kBorderSize = 10;
+
+    UInt_t wi = w - kBorderSize*0;
+    UInt_t hi = h - kBorderSize*1;
+    
+    fCanvasWidth = wi;
+    fCanvasHeight = (UInt_t)(hi*0.75);
+    
+    fMainFrame = new TGHorizontalFrame(this,fCanvasWidth,hi);
+    
+    const Int_t kColorWidth = 100;
+    
+    fColorSlider = new AliMUONPainterColorSlider(fMainFrame,kColorWidth,hi);
+    
+    fView = new TRootEmbeddedCanvas("ec",fMainFrame,fCanvasWidth-kColorWidth,fCanvasHeight,kChildFrame);
+    
+    fInterface = new TGHorizontalFrame(this,fCanvasWidth);
+    
+    fMainFrame->AddFrame(fView, new TGLayoutHints(kLHintsLeft));
+    fMainFrame->AddFrame(fColorSlider,new TGLayoutHints(kLHintsRight|kLHintsExpandX|kLHintsCenterY,kBorderSize/2));
+
+    AliMUONPainterInterfaceHelper::SetBackgroundColor("MatrixFrame.ColorSlider",*fColorSlider);
+    
+    fResponderButtons = new TGButtonGroup(fInterface,"Responder");
+    
+    fOutlineButtons = new TGButtonGroup(fInterface,"Outline");
+    
+    fInterface->AddFrame(fResponderButtons);
+    fInterface->AddFrame(fOutlineButtons);
+
+    fPlotSelector = 
+      new AliMUONPainterPlotSelector(fInterface);//,wi,interfaceHeight);
+    
+    fInterface->AddFrame(fPlotSelector);//,new TGLayoutHints(kLHintsRight|kLHintsExpandX));
+
+    fOutlineButtons->Show();
+    fResponderButtons->Show();
+        
+    AddFrame(fMainFrame,new TGLayoutHints(kLHintsExpandX|kLHintsTop,
+                                         0,0,0,0));
+
+    AddFrame(fInterface,new TGLayoutHints(kLHintsExpandX|kLHintsBottom,
+             0,0,kBorderSize,0));
+
+
+    // Set the connections
+    
+    fPlotSelector->Connect("DataSourceWasChanged(const char*,AliMUONVTrackerData*,Int_t)",                                
+                                 "AliMUONPainterMatrixFrame",
+                                 this,
+                                 "DataSourceWasChanged(const char*,AliMUONVTrackerData*,Int_t)");
+    
+    fColorSlider->Connect("DataRangeWasChanged(Double_t*)",
+                          "AliMUONPainterMatrixFrame",
+                         this,
+                         "DataRangeWasChanged(Double_t*)");
+
+    fColorSlider->Connect("DataRangeAutoRequested()",
+                          "AliMUONPainterMatrixFrame",
+                         this,
+                         "DataRangeAutoRequested()");
+    
+    // Set the colors (mainly for debugging frame layout)
+
+    AliMUONPainterInterfaceHelper::SetBackgroundColor("MatrixFrame.Main",*this);
+    
+    fMainFrame->HideFrame(fColorSlider);
+    
+    fMainFrame->Resize();
+}
+
+//_____________________________________________________________________________
+AliMUONPainterMatrixFrame::~AliMUONPainterMatrixFrame()
+{
+  /// dtor
+  delete fPainterHighlighter;
+  AliError("Please write a decent dtor for this class !");
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::ChangeTitle(const TString& title)
+{
+  /// Change title
+  
+  TitleHasChanged(title.Data());
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::ChangeTitle(AliMUONVPainter* painter, 
+                                       const char* basename,
+                                       Double_t x, Double_t y)
+{
+  /// Change the title according to painter
+  
+  TString name;
+  
+  if (painter) 
+  {
+
+    if ( basename ) name = basename;
+    else name = painter->PathName();
+    
+    AliMUONVPainter* master = painter->Master();
+    
+    AliMUONPainterGroup* group = master->PlotterGroup();
+
+    AliDebug(1,Form("Painter is %s plotterGroup is %x %s",
+                    painter->PathName().Data(),
+                    group,
+                    ( group ? group->Type() : "")));
+    
+    
+    if ( group && group->Data() ) 
+    {
+      name += "\n";
+      name += painter->Describe(*(group->Data()),group->DataIndex(),x,y);
+    }
+  }
+  else
+  {
+    name = fPainterMatrix->Name();
+  }
+  
+  TitleHasChanged(name.Data());
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::Clear(Option_t*)
+{
+  /// Clear the view(s)
+  
+  fPainterMatrix = 0x0;
+
+  AliMUONPainterInterfaceHelper::ClearButtons(*fOutlineButtons);
+  AliMUONPainterInterfaceHelper::ClearButtons(*fResponderButtons);
+  
+  fView->GetCanvas()->SetEditable(kTRUE);
+  fView->GetCanvas()->Clear();
+  fView->GetCanvas()->Modified();
+  fView->GetCanvas()->Update();
+  fView->GetCanvas()->SetEditable(kFALSE);
+
+  Layout();  
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrixFrame::CreateButtons()
+{
+  /// Create the interface buttons
+  
+  AliDebug(1,"");
+  
+//  AliMUONVPainter* painter = fPainterMatrix->Painter(0);
+  
+  /// create buttons    
+  TObjArray types;
+  
+  fPainterMatrix->GetTypes(types);
+  
+  TIter nextType(&types);
+  TObjString* str;
+  
+  while ( ( str = static_cast<TObjString*>(nextType()) ) )
+  {
+    AliMUONPainterInterfaceHelper::AddRadioButton(*fResponderButtons,str->String());
+    AliMUONPainterInterfaceHelper::AddCheckButton(*fOutlineButtons,str->String());
+  }
+  
+  fOutlineButtons->Connect("Clicked(Int_t)","AliMUONPainterMatrixFrame",
+                        this,"OutlineButtonWasClicked(Int_t)");
+  
+  fResponderButtons->Connect("Clicked(Int_t)","AliMUONPainterMatrixFrame",
+                             this,"ResponderButtonWasClicked(Int_t)");        
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrixFrame::DataRangeAutoRequested()
+{
+  /// Get there when the "Auto" button below the color slider is clicked,
+  /// to compute the data range actually painted.
+  
+  Double_t dataMin, dataMax;
+
+  AliDebug(1,"");
+  
+  fPainterMatrix->ComputeDataRange();
+
+  fPainterMatrix->GetDataRange(dataMin,dataMax);
+  
+  AliDebug(1,Form("dataMin,Max for SetRange=%e,%e",dataMin,dataMax));
+  
+  Bool_t emit(kTRUE);
+  
+  fColorSlider->SetRange(dataMin,dataMax,emit);
+  
+  Update();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrixFrame::DataRangeWasChanged(Double_t* range)
+{
+  /// Get there when the data range is changed
+  
+  AliDebug(1,Form("range=%e,%e",range[0],range[1]));
+
+  fPainterMatrix->SetDataRange(range[0],range[1]);
+  
+  Update();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::DataSourceWasChanged(const char* type,
+                                               AliMUONVTrackerData* data,
+                                               Int_t indexInData)
+{
+  /// Update what to plot
+  TString pattern(type);
+
+  AliDebug(1,Form("type=%s data=%s index=%d",type,
+                  (data ? data->GetName() : "null"),indexInData));
+    
+  AliMUONVTrackerData* d = data;
+  
+  if ( !d || !data || indexInData < 0 || pattern == "" )
+  {
+    pattern = "*";
+    d = 0;
+    indexInData = -1;
+  }
+  
+  fPainterMatrix->SetData(pattern,d,indexInData);
+    
+  Update();
+  
+  ChangeTitle(fPainterMatrix->Painter(0));
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::EventInfo(Int_t event, Int_t px ,Int_t py, TObject* object)
+{
+  /// Used to detect entering/leaving a given painter 
+  
+  if (!gPad || !object) return;
+  
+//  cout << "EventInfo : event " << event << " px " << px << " py " << py
+//    << " object " << object << " " << object->GetName() << endl;
+//  
+//  
+  if ( event == 7 ) 
+  {
+    if ( object->InheritsFrom("AliMUONVPainter") )
+    {
+      AliMUONVPainter* p = static_cast<AliMUONVPainter*>(object);
+      p->ExecuteEvent(7,px,py);
+      return;
+    }      
+  }
+  
+  if ( event == kMouseLeave )
+  {
+    if ( object->InheritsFrom("AliMUONVPainter") )
+    {
+      AliMUONVPainter* p = static_cast<AliMUONVPainter*>(object);
+      MouseLeave(p);
+      fPainterHighlighter->SetPainter(0x0);
+      gPad->Modified();
+      gPad->Update();
+    }
+  }
+
+  if ( event == kMouseEnter )
+  {
+    if ( object->InheritsFrom("AliMUONVPainter") )
+    {
+      AliMUONVPainter* painter = static_cast<AliMUONVPainter*>(object);
+      if ( painter->IsResponder() && !painter->HandleMouseMotion() )
+      {
+        MouseEnter(static_cast<AliMUONVPainter*>(object));
+        fPainterHighlighter->SetPainter(painter);
+        gPad->Modified();
+        gPad->Update();
+      }
+      else if ( !painter->HandleMouseMotion() )
+      {
+        MouseEnter(static_cast<AliMUONVPainter*>(object)); 
+      }
+    }
+  }
+  
+   if ( event == kMouseMotion ) 
+  {
+    if ( object->InheritsFrom("AliMUONVPainter") )
+    {
+      AliMUONVPainter* painter = static_cast<AliMUONVPainter*>(object);
+
+      if ( painter->HandleMouseMotion() && painter->IsResponder() )
+      {
+        Double_t pos[2];
+        TVirtualPad* padsave = gPad;
+        painter->Pad()->cd();
+        painter->PixelToPad(px,py,pos[0],pos[1]);
+        MouseMotion(static_cast<AliMUONVPainter*>(object),pos);
+        fPainterHighlighter->SetPainter(painter,pos[0],pos[1]);
+        gPad->Modified();
+        gPad->Update();
+        gPad = padsave;
+      }
+    }    
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::MouseEnter(AliMUONVPainter* painter)
+{
+  /// Emit a signal to notify that mouse pointer is entering a given painter
+
+  AliDebug(1,Form("painter=%x %s",painter,painter->PathName().Data()));
+  
+  ChangeTitle(painter);
+
+  Long_t params[] = { (Long_t)painter };
+  
+  Emit("MouseEnter(AliMUONVPainter*)",params);  
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::MouseLeave(AliMUONVPainter* painter)
+{
+  /// Emit a signal to notify that mouse pointer is leaving a given painter
+  
+  ChangeTitle(fPainterMatrix->Name());
+
+  Long_t params[] = { (Long_t)painter };
+  
+  Emit("MouseLeave(AliMUONVPainter*)",params);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::MouseMotion(AliMUONVPainter* painter, Double_t* position)
+{
+  /// Emit a signal to notify that mouse pointer is moving within a given painter
+  
+  ChangeTitle(painter,painter->NameAtPosition(position[0],position[1]),
+              position[0],position[1]);
+  
+  Long_t params[] = { (Long_t)painter, (Long_t)position };
+  
+  Emit("MouseMotion(AliMUONVPainter*,Double_t*)",params);
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::ResponderButtonWasClicked(Int_t id)
+{
+  /// One responder button was clicked
+  
+  TGTextButton* button = static_cast<TGTextButton*>(fResponderButtons->GetButton(id));
+  TString pattern = button->GetString();
+  
+//  AliInfo(Form("id=%d button=%d %s",id,button->IsOn(),pattern.Data()));
+
+  assert(button->IsOn()==1);
+  
+  fPainterMatrix->SetResponder(pattern.Data());
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::OutlineButtonWasClicked(Int_t id)
+{
+  /// One outline button was clicked
+  
+  TGTextButton* button = static_cast<TGTextButton*>(fOutlineButtons->GetButton(id));
+  TString pattern = button->GetString();
+  
+  fPainterMatrix->SetOutlined(pattern.Data(),button->IsOn());
+  
+  ViewModified();
+  fView->GetCanvas()->Update();
+    
+  // Update the interface (e.g. list of possible responders can have 
+  // changed due to visibility change)
+  UpdateInterface(kFALSE);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::TitleHasChanged(const char* title)
+{
+  /// Emit the TitleHasChanged signal
+  
+  Long_t params[] = { (Long_t)title };
+  Emit("TitleHasChanged(const char*)",params);
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::Update()
+{
+  /// Force update of all canvases
+
+  UpdateDataRange();
+  
+  fView->GetCanvas()->SetEditable(kTRUE);
+  
+  Bool_t colorSlider = ( fPainterMatrix->Data() != 0x0 );
+  
+  ViewModified();
+
+  fView->GetCanvas()->SetEditable(kFALSE);
+  
+  AliDebug(1,Form("colorSlider=%d",colorSlider));
+  
+  if ( colorSlider )
+  {
+    fMainFrame->ShowFrame(fColorSlider);
+  }
+  else
+  {
+    fMainFrame->HideFrame(fColorSlider);
+  }
+  
+  fMainFrame->Layout();
+  Layout();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterMatrixFrame::UpdateDataRange()
+{
+  /// Update the data range
+  
+  Double_t min, max;
+
+  fPainterMatrix->GetDataRange(min,max);
+
+  AliDebug(1,Form("min %e max %e",min,max));
+
+  if ( min > max ) 
+  {
+    fPainterMatrix->ComputeDataRange();
+    fPainterMatrix->GetDataRange(min,max);
+  }
+
+  fColorSlider->SetRange(min,max,kFALSE);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrixFrame::UpdateInterface(Bool_t fromScratch)
+{
+  /// Update the full interface
+  
+  if ( fromScratch || fOutlineButtons->GetCount() == 0 ) 
+  {
+    CreateButtons();
+  }
+  
+  AliMUONPainterInterfaceHelper::Unselect(*fResponderButtons,"*");
+  AliMUONPainterInterfaceHelper::Unselect(*fOutlineButtons,"*");
+  
+  AliMUONVPainter* painter = fPainterMatrix->Painter(0);
+  
+  TObjArray types;
+  types.SetOwner(kTRUE);
+  
+  fPainterMatrix->GetTypes(types);
+  
+  // update button states
+  TIter next(&types);
+  TObjString* otype;
+  
+  TString theResponder;
+  
+  while ( ( otype = static_cast<TObjString*>(next()) ) )
+  {    
+    AliMUONPainterGroup* group = painter->Group(otype->String());
+    
+    if ( group && group->IsOutlined() ) 
+    {
+      AliMUONPainterInterfaceHelper::Select(*fOutlineButtons,otype->String().Data());
+    }    
+  }
+  
+  if ( painter ) 
+  {
+    AliMUONPainterGroup* responderGroup = painter->ResponderGroup();
+  
+    if (responderGroup)
+    {
+      AliMUONPainterInterfaceHelper::Select(*fResponderButtons,responderGroup->Type());
+    }
+  }
+  
+  // update data source view
+  
+  fPlotSelector->Update(*fPainterMatrix);
+    
+  fResponderButtons->Show();
+  fOutlineButtons->Show();
+
+  Layout();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrixFrame::Use(AliMUONPainterMatrix* group)
+{
+  /// Change the matrix used
+  
+  Clear();
+  
+  fPainterMatrix = group;
+  
+  fView->GetCanvas()->SetEditable(kTRUE);
+  
+  fView->GetCanvas()->Divide(fPainterMatrix->Nx(),fPainterMatrix->Ny());
+  
+  for ( Int_t i = 0; i < fPainterMatrix->Size(); ++i ) 
+  {
+    AliMUONVPainter* painter = fPainterMatrix->Painter(i);
+    fView->GetCanvas()->cd(i+1);
+    painter->Draw("R");
+    fPainterHighlighter->SetPainter(0x0);
+    fPainterHighlighter->Draw();
+  }  
+
+  Update();
+  
+  UpdateInterface(kTRUE);
+  
+  ChangeTitle(fPainterMatrix->Name());
+  
+  fView->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
+                              "AliMUONPainterMatrixFrame",this, 
+                              "EventInfo(Int_t,Int_t,Int_t,TObject*)"); 
+  
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterMatrixFrame::ViewModified()
+{
+  /// Update our canvas
+  
+  for ( Int_t i = 0; i < fPainterMatrix->Size(); ++i ) 
+  {
+    fView->GetCanvas()->GetPad(i+1)->Modified();
+  }
+  fView->GetCanvas()->Modified();
+  fView->GetCanvas()->Update();
+}
+
+
diff --git a/MUON/AliMUONPainterMatrixFrame.h b/MUON/AliMUONPainterMatrixFrame.h
new file mode 100644 (file)
index 0000000..d50f76c
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef ALIMUONPAINTERMATRIXFRAME_H
+#define ALIMUONPAINTERMATRIXFRAME_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterMatrixFrame
+/// \brief Widget to plot a matrix of painters
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TGFrame
+#  include "TGFrame.h"
+#endif
+#ifndef ROOT_RQ_OBJECT
+#   include <RQ_OBJECT.h>
+#endif
+#include <float.h>
+
+class AliMUONPainterColorSlider;
+class AliMUONPainterPlotSelector;
+class AliMUONPainterMatrix;
+class AliMUONPainterHighlighter;
+class AliMUONVPainter;
+class AliMUONVTrackerData;
+class TGButtonGroup;
+class TGToolTip;
+class TList;
+class TObjArray;
+class TRootEmbeddedCanvas;
+
+class AliMUONPainterMatrixFrame : public TGCompositeFrame
+{
+  RQ_OBJECT("AliMUONPainterMatrixFrame")
+  
+public:
+  AliMUONPainterMatrixFrame(const TGWindow* window, UInt_t w, UInt_t h);
+  virtual ~AliMUONPainterMatrixFrame();
+  
+  void Clear(Option_t* opt="");
+
+  void DataRangeAutoRequested();
+  
+  void DataRangeWasChanged(Double_t* range);
+    
+  void DataSourceWasChanged(const char* name, AliMUONVTrackerData* data, Int_t dataIndex);
+
+  void EventInfo(Int_t event, Int_t px, Int_t py, TObject* selected);
+
+  void MouseEnter(AliMUONVPainter* painter); // *SIGNAL*
+
+  void MouseMotion(AliMUONVPainter* painter, Double_t* position); // *SIGNAL*
+
+  void MouseLeave(AliMUONVPainter* painter); // *SIGNAL*
+  
+  void ResponderButtonWasClicked(Int_t id); 
+
+  void OutlineButtonWasClicked(Int_t id); 
+  
+  void Use(AliMUONPainterMatrix* group);
+  
+  void TitleHasChanged(const char* newTitle); // *SIGNAL*
+  
+  void Update(); 
+
+  /// Get the matrix pointer
+  AliMUONPainterMatrix* Matrix() const { return fPainterMatrix; }
+  
+private:
+  /// not implemented
+  AliMUONPainterMatrixFrame(const AliMUONPainterMatrixFrame& rhs);
+  /// not implemented
+  AliMUONPainterMatrixFrame& operator=(const AliMUONPainterMatrixFrame& rhs);
+
+  void ChangeTitle(const TString& title);
+  
+  void ChangeTitle(AliMUONVPainter* painter, const char* basename=0x0,
+                   Double_t x=FLT_MAX, Double_t y=FLT_MAX);
+  
+  void CreateButtons();
+  
+  void UpdateDataRange();
+  
+  void UpdateInterface(Bool_t fromScratch);
+
+  void ViewModified();
+  
+private:
+  AliMUONPainterMatrix* fPainterMatrix; ///< the matrix we plot (not owner)
+  TRootEmbeddedCanvas* fView; ///< the canvas used to plot
+  TGHorizontalFrame* fInterface;  ///< the interface frame
+  TGButtonGroup* fResponderButtons; ///< the responder buttons
+  TGButtonGroup* fOutlineButtons; ///< the outline buttons
+  
+  AliMUONPainterPlotSelector* fPlotSelector; ///< the data source selection
+    
+  AliMUONPainterHighlighter* fPainterHighlighter; ///< the highlighter
+  
+  UInt_t fCanvasWidth; ///< canvas width
+  UInt_t fCanvasHeight; ///< canvas height
+  
+  TGCompositeFrame* fMainFrame; ///< our main frame
+  
+  AliMUONPainterColorSlider* fColorSlider; ///< color slider (for data)
+  
+  ClassDef(AliMUONPainterMatrixFrame,1) // Widget for drawing painter matrix
+};
+
+#endif
diff --git a/MUON/AliMUONPainterPadStore.cxx b/MUON/AliMUONPainterPadStore.cxx
new file mode 100644 (file)
index 0000000..cfa2bd0
--- /dev/null
@@ -0,0 +1,218 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPainterPadStore.h"
+
+#include "AliMUONCalibParamND.h"
+#include "AliMUON2DMap.h"
+#include "AliMUONVStore.h"
+#include "AliMUONVDigit.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TArrayI.h>
+#include <TVector2.h>
+
+///\class AliMUONPainterPadStore
+///
+/// Container for pads
+///
+///\author Laurent Aphecetche, Subatech
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterPadStore)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONPainterPadStore::AliMUONPainterPadStore() : TObject(),
+  fPadStore(new AliMUON2DMap(kTRUE))
+{
+    /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPainterPadStore::~AliMUONPainterPadStore()
+{
+  /// dtor
+  delete fPadStore;
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterPadStore::FindPadID(const TArrayI& pads, Double_t x, Double_t y) const
+{
+  /// Find, in array of pads, the one which contains (x,y). Returns -1 if not
+  /// found
+  
+  for ( Int_t i = 0; i < pads.GetSize(); ++i ) 
+  {
+    Int_t id = pads.At(i);
+    
+    TVector2 position;
+    TVector2 dimensions;
+    
+    GetPadGeometry(id,position,dimensions);
+    
+    TVector2 bl(position-dimensions);
+    TVector2 ur(position+dimensions);    
+    if ( bl.X() <= x && ur.X() >= x && bl.Y() <= y && ur.Y() >= y ) 
+    {
+      return id;
+    }
+  }
+  return -1;
+}
+
+
+//_____________________________________________________________________________
+AliMUONVCalibParam*
+AliMUONPainterPadStore::Get(Int_t detElemId, Int_t manuId) const
+{
+  /// Get the pad container for a given manu
+  
+  AliMUONVCalibParam* param = 
+  static_cast<AliMUONVCalibParam*>(fPadStore->FindObject(detElemId,manuId));
+  
+  if (!param)
+  {
+    param = new AliMUONCalibParamND(4,64,detElemId,manuId,-1.0);
+    fPadStore->Add(param);
+  }
+  
+  return param;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPadStore::GetBoundaries(const TArrayI& pads,
+                                      Double_t& xmin,
+                                      Double_t& ymin,
+                                      Double_t& xmax,
+                                      Double_t& ymax) const
+{
+  /// Get the area covered by an array of pads
+  
+  xmin=ymin=1E9;
+  xmax=ymax=-1E9;
+  
+  for ( Int_t i = 0; i < pads.GetSize(); ++i ) 
+  {
+    Int_t id = pads.At(i);
+    
+    TVector2 position;
+    TVector2 dimensions;
+    
+    GetPadGeometry(id,position,dimensions);
+    
+    TVector2 bl(position-dimensions);
+    TVector2 ur(position+dimensions);
+    xmin = TMath::Min(xmin,bl.X());
+    ymin = TMath::Min(ymin,bl.Y());
+    xmax = TMath::Max(xmax,ur.X());
+    ymax = TMath::Max(ymax,ur.Y());
+  }     
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPadStore::GetPadGeometry(Int_t padId, 
+                                       TVector2& position,
+                                       TVector2& dimensions) const
+{
+  /// Get the geomtry of one pad
+  
+  if ( padId < 0 ) 
+  {
+    AliError(Form("padId is < 0 : %d",padId));
+    position.Set(0.0,0.0);
+    dimensions.Set(-1.0,-1.0);
+    return;
+  }
+  
+  Int_t detElemId = AliMUONVDigit::DetElemId(padId);
+  Int_t manuId = AliMUONVDigit::ManuId(padId);
+  Int_t manuChannel = AliMUONVDigit::ManuChannel(padId);
+  
+  AliMUONVCalibParam* param = 
+    static_cast<AliMUONVCalibParam*>(fPadStore->FindObject(detElemId,manuId));
+  
+  if (!param)
+  {
+    AliError(Form("Could not find object DE %d manu %d",detElemId,manuId));
+    position.Set(0.0,0.0);
+    dimensions.Set(-1.0,-1.0);
+    return;
+  }
+  
+  position.Set(param->ValueAsDouble(manuChannel,0),
+               param->ValueAsDouble(manuChannel,1));
+  
+  dimensions.Set(param->ValueAsDouble(manuChannel,2),
+                 param->ValueAsDouble(manuChannel,3));
+  
+  AliDebug(3,Form("DE %4d Manu %4d Channel %2d Pos %e %e Dim %e %e",
+                       detElemId,manuId,manuChannel,
+                       position.X(),position.Y(),
+                       dimensions.X(),dimensions.Y()));                       
+}
+
+//_____________________________________________________________________________
+Int_t
+AliMUONPainterPadStore::GetSize() const
+{
+  /// Get the number of pads we handle
+  
+  TIter next(fPadStore->CreateIterator());
+  AliMUONVCalibParam* param;
+  Int_t n(0);
+  
+  while ( ( param = static_cast<AliMUONVCalibParam*>(next()) ) )
+  {
+    for ( Int_t i = 0; i < param->Size(); ++i ) 
+    {
+      if ( param->ValueAsDouble(i,2) >= 0 && param->ValueAsDouble(i,3) >= 0 ) 
+      {
+        ++n;
+      }
+    }
+  }
+  
+  return n;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPadStore::PrintPads(const TArrayI& pads) const
+{
+  /// Printout
+  cout << "n=" << pads.GetSize() << endl;
+  
+  for ( Int_t i = 0; i < pads.GetSize(); ++i ) 
+  {
+    Int_t id = pads.At(i);
+    TVector2 position, dimensions;
+    GetPadGeometry(id,position,dimensions);
+    cout << Form("i %4d DE %4d ManuID %4d ManuChannel %2d (X,Y)=(%7.3f,%7.3f)"
+                 " (DX,DY)=(%7.3f,%7.3f)",
+                 i,
+                 AliMUONVDigit::DetElemId(id),
+                 AliMUONVDigit::ManuId(id),
+                 AliMUONVDigit::ManuChannel(id),
+                 position.X(),position.Y(),
+                 dimensions.X(),dimensions.Y()) << endl;
+  }
+}
+
diff --git a/MUON/AliMUONPainterPadStore.h b/MUON/AliMUONPainterPadStore.h
new file mode 100644 (file)
index 0000000..4d8181c
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef ALIMUONPAINTERPADSTORE_H
+#define ALIMUONPAINTERPADSTORE_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup graphics
+/// \class AliMUONPainterPadStore
+/// \brief Container for pads
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+
+class AliMUONVCalibParam;
+class AliMUONVStore;
+class TArrayI;
+class TVector2;
+
+class AliMUONPainterPadStore : public TObject
+{
+public:
+  AliMUONPainterPadStore();
+  virtual ~AliMUONPainterPadStore();
+
+  Int_t FindPadID(const TArrayI& pads, Double_t x, Double_t y) const;
+
+  AliMUONVCalibParam* Get(Int_t detElemId, Int_t manuId) const;
+  
+  void GetBoundaries(const TArrayI& pads, Double_t& xmin, Double_t& ymin,
+                     Double_t& xmax, Double_t& ymax) const;
+    
+  void GetPadGeometry(Int_t padID, TVector2& position, TVector2& dimensions) const;
+  
+  void PrintPads(const TArrayI& pads) const;
+
+  Int_t GetSize() const;
+  
+private:
+  /// not implemented
+  AliMUONPainterPadStore(const AliMUONPainterPadStore& rhs);
+  /// not implemented
+  AliMUONPainterPadStore& operator=(const AliMUONPainterPadStore& rhs);
+private:
+  AliMUONVStore* fPadStore; ///< the pad container
+  
+  ClassDef(AliMUONPainterPadStore,1) // A pad container
+};
+
+#endif
diff --git a/MUON/AliMUONPainterPlotSelector.cxx b/MUON/AliMUONPainterPlotSelector.cxx
new file mode 100644 (file)
index 0000000..c1f21ba
--- /dev/null
@@ -0,0 +1,585 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONPainterPlotSelector
+/// 
+/// Widget to select which data to plot for painters
+/// 
+/// \author Laurent Aphecetche
+///
+/// See AliMUONPainterInterfaceHelper for an important implementation note
+/// about our use of TGButtonGroup
+///
+
+#include "AliMUONPainterPlotSelector.h"
+
+#include "AliMUONPainterGroup.h"
+#include "AliMUONPainterInterfaceHelper.h"
+#include "AliMUONPainterMatrix.h"
+#include "AliMUONPainterRegistry.h"
+#include "AliMUONVPainter.h"
+#include "AliMUONVTrackerData.h"
+#include "AliLog.h"
+#include <Riostream.h>
+#include <TGButton.h>
+#include <TGButtonGroup.h>
+#include <TObjArray.h>
+#include <TObjString.h>
+
+///\cond CLASSIMP
+ClassImp(AliMUONPainterPlotSelector)
+///\endcond
+
+const char* AliMUONPainterPlotSelector::fgkDefaultSourceName = "none";  
+
+//_____________________________________________________________________________
+AliMUONPainterPlotSelector::AliMUONPainterPlotSelector(const TGWindow* window, UInt_t w, UInt_t h)
+: TGCompositeFrame(window,w,h,kHorizontalFrame),
+fTypes(0x0),
+fDataSourceNames(0x0),
+fDataSourceDimensions(0x0),
+fDimensionButtonMap(new TMap),
+fCurrentType(""),
+fCurrentData(0x0),
+fCurrentDimension(-1)
+{
+  /// ctor
+  fTypes = new TGButtonGroup(this,"Plot");
+
+  fDataSourceNames = new TGButtonGroup(this,"Sources");
+      
+  AliMUONPainterRegistry* reg = AliMUONPainterRegistry::Instance();
+  
+  reg->Connect("DataSourceWasRegistered(AliMUONVTrackerData*)",
+               "AliMUONPainterPlotSelector",
+               this,
+               "DataSourceWasRegistered(AliMUONVTrackerData*)");
+  
+  reg->Connect("DataSourceWasUnregistered(AliMUONVTrackerData*)",
+               "AliMUONPainterPlotSelector",
+               this,
+               "DataSourceWasUnregistered(AliMUONVTrackerData*)");
+    
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fDataSourceNames,
+                                                fgkDefaultSourceName,
+                                                0x0,
+                                                kTRUE);
+  
+  CreateDimensionButtons(fgkDefaultSourceName);
+  
+  fDataSourceDimensions = new TGButtonGroup(this,0,3,5,0,"Dimensions");
+  
+  for ( Int_t i = 0; i < reg->NumberOfDataSources(); ++i )
+  {
+    AliMUONVTrackerData* data = reg->DataSource(i);
+    DataSourceWasRegistered(data);
+  }
+  
+  fDataSourceNames->Connect("Clicked(Int_t)","AliMUONPainterPlotSelector",
+                            this,
+                            "SourceButtonWasClicked(Int_t)");
+
+  AddFrame(fTypes);
+  AddFrame(fDataSourceNames);
+  AddFrame(fDataSourceDimensions);
+}
+
+//_____________________________________________________________________________
+AliMUONPainterPlotSelector::~AliMUONPainterPlotSelector()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::BackupDimensionButtons()
+{
+  /// Backup the dimension button group
+  
+  TString name = fDataSourceDimensions->GetTitle();
+
+  AliDebug(1,Form("name %s",name.Data()));
+
+  if ( name !=  fgkDefaultSourceName )
+  {
+    TGButtonGroup* group = static_cast<TGButtonGroup*>(fDimensionButtonMap->GetValue(name));
+    if (!group) 
+    {
+      AliError(Form("Did not find group %s",name.Data()));
+    }
+    else
+    {
+      AliMUONPainterInterfaceHelper::Copy(*fDataSourceDimensions,*group);
+    }
+  
+  }
+  
+  fDataSourceDimensions->Disconnect("Clicked(Int_t)",
+                                    this,
+                                    "DimensionButtonWasClicked(Int_t)");  
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::CreateDimensionButtons(const char* dataSourceName)
+{
+  /// Create the dimension button group for a given data source
+  
+  AliDebug(1,Form("Creating dimension buttons for dataSource %s",dataSourceName));
+  
+  AliMUONVTrackerData* data = AliMUONPainterRegistry::Instance()->FindDataSource(dataSourceName);
+
+  TGButtonGroup* bg = new TGButtonGroup(this,0,3,5,0,dataSourceName);
+  
+  if ( data ) 
+  {
+    for ( Int_t i = 0; i < data->NumberOfDimensions(); ++i ) 
+    {
+      AliMUONPainterInterfaceHelper::AddRadioButton(*bg,
+                                                    data->DimensionName(i),
+                                                    reinterpret_cast<void*>(i));
+    }
+  }
+  
+  fDimensionButtonMap->Add(new TObjString(dataSourceName),bg);
+  
+  AliDebug(1,Form("bg is %p Count=%d",bg,bg->GetCount()));
+  StdoutToAliDebug(1,AliMUONPainterInterfaceHelper::Dump(*bg));
+  
+  bg->Connect("Clicked(Int_t)","AliMUONPainterPlotSelector",this,
+                                "DimensionButtonWasClicked(Int_t)");
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::CreateTypeButtons(const TObjArray& types)
+{
+  /// Create the type button group
+  
+  AliMUONPainterInterfaceHelper::ClearButtons(*fTypes);
+
+  TIter nextType(&types);
+  TObjString* str;
+
+  while ( ( str = static_cast<TObjString*>(nextType()) ) )
+  {
+    AliMUONPainterInterfaceHelper::AddRadioButton(*fTypes,str->String());
+  }
+
+  fTypes->Connect("Clicked(Int_t)","AliMUONPainterPlotSelector",this,
+                  "TypeButtonWasClicked(Int_t)");
+  
+  fTypes->Show();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::DataSourceWasChanged()
+{
+  /// Data source was changed
+  DataSourceWasChanged(fCurrentType.Data(),fCurrentData,fCurrentDimension);
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterPlotSelector::DataSourceWasChanged(const char* type, 
+                                                 AliMUONVTrackerData* data,
+                                                 Int_t dataIndex)
+{
+  /// Emit a signal to tell data source was changed
+  AliDebug(1,Form("type=%s data=%s (%s)",
+                  type,
+                  ( data ? data->GetName() : "" ),
+                  ( ( data && dataIndex >= 0 ) ? data->DimensionName(dataIndex).Data() :
+                    "")));
+  
+  Long_t param[] = { (Long_t)type, (Long_t)data,
+    (Long_t)dataIndex };
+  
+  Emit("DataSourceWasChanged(const char*,AliMUONVTrackerData*,Int_t)",param);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::DataSourceWasRegistered(AliMUONVTrackerData* data)
+{
+  /// A new data source has been registered : add it to the interface
+  
+  AliDebug(1,Form("Registering %s",data->GetName()));
+  
+  AliMUONPainterInterfaceHelper::AddRadioButton(*fDataSourceNames,
+                                                data->GetName(),
+                                                data);
+  
+  data->Connect("NumberOfEventsChanged()",
+                "AliMUONPainterPlotSelector",
+                this,
+                "NumberOfEventsChanged()");
+  
+  CreateDimensionButtons(data->GetName());
+  
+  fDataSourceNames->Show();
+  
+  Layout();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::NumberOfEventsChanged()
+{
+  /// Change the tool tip of the corresponding data source button
+
+  // find first the sender of the signal
+  
+  AliMUONVTrackerData* data = reinterpret_cast<AliMUONVTrackerData*>(gTQSender);
+  
+  TGButton* button = AliMUONPainterInterfaceHelper::FindButtonByUserData(*fDataSourceNames,data);
+  
+  if (button)
+  {
+    button->SetToolTipText(Form("%d events",data->NumberOfEvents()),250);
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::DataSourceWasUnregistered(AliMUONVTrackerData* data)
+{
+  /// A data source has been unregistered : remove it from the interface
+  
+  AliDebug(1,Form("Unregistering %s",data->GetName()));
+
+  TGButton* button = AliMUONPainterInterfaceHelper::FindButtonByName(*fDataSourceNames,
+                                                                     data->GetName());
+  AliMUONVTrackerData* check = reinterpret_cast<AliMUONVTrackerData*>(button->GetUserData());
+  if ( !button || check != data )
+  {
+    AliError("Something is seriously wrong. Please check");
+    return;
+  }
+  
+  fDataSourceNames->Remove(button);
+  delete button;
+  button->DestroyWindow();
+  
+  fDataSourceNames->Show();
+  
+  TObject* o = fDimensionButtonMap->Remove(new TObjString(data->GetName()));
+  
+  if (!o)
+  {
+    AliError("Remove failed. Please check");    
+  }
+  
+  Layout();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterPlotSelector::DimensionButtonWasClicked(Int_t id)
+{
+  /// One dim button was clicked
+  
+  AliDebug(1,Form("id=%d",id));
+  
+  TGTextButton* button = (TGTextButton*)fDataSourceDimensions->GetButton(id);
+  
+  SetCurrentDimension(reinterpret_cast<Int_t>(button->GetUserData()));
+  
+  if ( fCurrentDimension >= 0 )
+  {
+    AliMUONPainterInterfaceHelper::SetState(*fTypes,kTRUE);
+    AliMUONPainterInterfaceHelper::Select(*fTypes,fCurrentType.Data(),kFALSE);
+    fTypes->Show();
+  }
+  
+  AliDebug(1,Form("fCurrentDimension=%d fCurrentData=%p fCurrentType=%s",
+                  fCurrentDimension,fCurrentData,fCurrentType.Data()));
+  
+  DataSourceWasChanged();
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::ResetDimensionButtonMap()
+{
+  /// Reset the button group map
+  
+  TIter next(fDimensionButtonMap);
+  TObjString* str;
+  
+  while ( ( str = static_cast<TObjString*>(next()) ) )
+  {
+    TGButtonGroup* bg = static_cast<TGButtonGroup*>(fDimensionButtonMap->GetValue(str->String()));
+    AliMUONPainterInterfaceHelper::Unselect(*bg,"*");
+  }
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::RestoreDimensionButtons(const char* dataSourceName,
+                                                    Bool_t updateCurrentDimension)
+{
+  /// Restore (i.e. contrary of Backup) a given dimension button group
+  
+  AliDebug(1,Form("name %s",dataSourceName));
+  TGButtonGroup* group = static_cast<TGButtonGroup*>(fDimensionButtonMap->GetValue(dataSourceName));
+  
+  AliMUONPainterInterfaceHelper::Copy(*group,*fDataSourceDimensions);
+  
+  fDataSourceDimensions->Connect("Clicked(Int_t)",
+                                 "AliMUONPainterPlotSelector",this,
+                                 "DimensionButtonWasClicked(Int_t)");    
+  
+  if ( updateCurrentDimension ) 
+  {
+    TGButton* button = AliMUONPainterInterfaceHelper::FindDownButton(*fDataSourceDimensions);
+    if ( button ) 
+    {
+      SetCurrentDimension(reinterpret_cast<Int_t>(button->GetUserData()));
+    }
+    else 
+    {
+      SetCurrentDimension(-1);
+    }
+  }
+  
+  fDataSourceDimensions->Show();
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterPlotSelector::SetCurrentData(AliMUONVTrackerData* data)
+{
+  /// Set the current data pointer
+  AliDebug(1,Form("fCurrentData %p -> %p",fCurrentData,data));
+  fCurrentData = data;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterPlotSelector::SetCurrentDimension(Int_t i)
+{
+  /// Set the current dimension
+  AliDebug(1,Form("fCurrentDimension %d -> %d",fCurrentDimension,i));
+  fCurrentDimension = i;
+}
+
+//_____________________________________________________________________________
+void 
+AliMUONPainterPlotSelector::SetCurrentType(const char* type)
+{
+  /// Set the current type
+  AliDebug(1,Form("fCurrentType %s -> %s",fCurrentType.Data(),type));
+  fCurrentType = type;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPainterPlotSelector::SourceButtonWasClicked(Int_t id)
+{
+  /// A source button was clicked
+  AliDebug(1,Form("BEGIN id %d fCurrentDimension=%d fCurrentData=%p fCurrentType=%s",
+                  id,
+                  fCurrentDimension,fCurrentData,fCurrentType.Data()));
+
+  BackupDimensionButtons();
+  
+  TGButton* button = fDataSourceNames->GetButton(id);
+  if ( !button ) 
+  {
+    AliError(Form("Could not get DataSource button id=%d",id));
+    StdoutToAliDebug(1,AliMUONPainterInterfaceHelper::Dump(*fDataSourceNames));
+    button->GetUserData(); // to trigger a crash so gdb is possible ;-)
+  }
+  
+  AliMUONVTrackerData* data = reinterpret_cast<AliMUONVTrackerData*>(button->GetUserData());
+
+  TString name =  data ? data->GetName() : fgkDefaultSourceName;
+
+  RestoreDimensionButtons(name,kTRUE);
+  
+&n