//*CMZ : 2.22/01 12/05/99 16.35.37 by Rene Brun
//*CMZ : 2.21/06 15/02/99 10.04.00 by Rene Brun
//*CMZ : 2.21/04 03/02/99 16.47.16 by Rene Brun
//*CMZ : 2.20/06 17/12/98 09.30.48 by Rene Brun
//*CMZ : 2.20/05 15/12/98 13.08.11 by Rene Brun
//*CMZ : 2.20/04 11/12/98 16.19.08 by Rene Brun
//*-- Author : Rene Brun 08/12/98
//*KEEP,CopyRight,T=C.
/*************************************************************************
* Copyright(c) 1995-1999, The ROOT System, All rights reserved. *
* Authors: Rene Brun, Fons Rademakers. *
* For list of contributors see $ROOTSYS/AA_CREDITS. *
* *
* Permission to use, copy, modify and distribute this software and its *
* documentation 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. *
*************************************************************************/
//*KEND.
//*KEEP,TROOT.
#include "TROOT.h"
//*KEEP,TSystem.
#include "TSystem.h"
//*KEEP,TTreeViewer,T=C++.
#include "TTreeViewer.h"
//*KEEP,TPaveVar,T=C++.
#include "TPaveVar.h"
//*KEEP,TLeaf,T=C++.
#include "TLeaf.h"
//*KEEP,TH1.
#include "TH1.h"
//*KEEP,TSliderBox.
#include "TSliderBox.h"
//*KEND.
const Int_t kDrawExecuting = BIT(17);
ClassImp(TTreeViewer)
//______________________________________________________________________________//*-*
//*-* A TreeViewer is a canvas specialized to view TTree attributes.
//
// The TTreeViewer canvas (see example below) shows the list
// of TTree variables represented by TPaveVar objects.
// A set of buttons allows to execute the following operations:
// "Draw" display the active variable(s) below the X,Y,Z buttons
// "Scan" same with TTree::Scan output style
// "Break" interrupt current event loop
// "List Out" to create a new TEventList using the current selection (see below)
// "List In" to activate a TEventList as an input selection
// "Hist" to redefine the default histogram (default htemp)
// "Cpad" to specify the output pad (default c1)
// "Gopt" to specify a graphics option
// "X" to select the X variable
// "Y" to select the Y variable
// "Z" to select the Z variable
// "W" to select the Weight/Selection expression
//
// A vertical slider can be used to select the events range (min/max)
// When the "Draw" button is clicked, The TTreeViewer object assembles
// the information from the above widgets and call TTree::Draw with
// the corresponding arguments.
// While the event loop is executing, a red box inside the slider bar
// indicates the progress in the loop. The event loop can be interrupted
// by clicking on the "Break" button.
//
// A new variable can be created by clicking on the canvas with the right
// button and selecting "CreateNewVar".
// New variables can be created by ANDing/ORing a stack of overlapping
// TPaveVars on the screen. Click on a TPaveVar and select "Merge".
//
// The selection list TPaveVar (empty by default) can be edited
// by clicking with the right button and selecting the item "SetLabel".
//
// TPaveVar objects may be dragged/droped to their destination (X,Y,X
// or W/Selection).
// Clicking on the canvas and selecting "MakeClass" generates the C++ code
// corresponding to the current selections in the canvas.
//
// While the "Draw" button is executed, the event loop can be interrupted
// by pressing the button "Break". The current histogram is shown.
//
// While the "Draw" button is executed, one can display the status
// of the histogram by clicking on the button "Hist".
//
// Instead of clicking on the "Draw" button, one can also double-click
// on a TPaveVar. This will automatically invoke "Draw" with the
// current setup (cuts, events range, graphics options,etc).
//
// At any time the canvas history can be saved in a Root file via the
// standard tool bar menu "File" and item "Save as Canvas.root".
// Assuming the current canvas is called TreeViewer, this generates
// the file TreeViewer.root. One can continue a previous session via
// Root > TFile f("TreeViewer.root");
// Root > TreeViewer.Draw();
//
// Assume an existing file f containing a TTree T, one can start
// the TreeViewer with the sequence:
// Root > TFile f("Event.root");
// Root > TTreeViewer TV("T");
//
//
/*
*/
//
//
const Int_t kBranchObject = BIT(15);
//______________________________________________________________________________
TTreeViewer::TTreeViewer() : TCanvas()
{
//*-*-*-*-*-*-*-*-*-*-*-*TreeViewer default constructor*-*-*-*-*-*-*-*-*-*-*
//*-* ================================
fTree = 0;
fDraw = 0;
fScan = 0;
fBreak = 0;
fGopt = 0;
fIList = 0;
fOList = 0;
fX = 0;
fY = 0;
fZ = 0;
fW = 0;
fCpad = 0;
fHist = 0;
fSlider = 0;
fTimer = 0;
SetTimerInterval();
}
//_____________________________________________________________________________
TTreeViewer::TTreeViewer(const char *treename, const Text_t *title, UInt_t ww, UInt_t wh)
: TCanvas(title,title,ww,wh)
{
//*-*-*-*-*-*-*-*-*-*-*-*TreeViewer constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ========================
fTree = 0;
fDraw = 0;
fScan = 0;
fBreak = 0;
fGopt = 0;
fIList = 0;
fOList = 0;
fX = 0;
fY = 0;
fZ = 0;
fW = 0;
fCpad = 0;
fHist = 0;
fSlider = 0;
SetBorderMode(0);
SetFillColor(36);
SetTimerInterval();
SetTreeName(treename);
fTimer = new TTimer(this,fTimerInterval,kTRUE);
}
//______________________________________________________________________________
TTreeViewer::~TTreeViewer()
{
//*-*-*-*-*-*-*-*-*-*-*TreeViewer default destructor*-*-*-*-*-*-*-*-*-*-*-*
//*-* ===============================
delete fTree;
delete fDraw;
delete fScan;
delete fBreak;
delete fGopt;
delete fIList;
delete fOList;
delete fX;
delete fY;
delete fZ ;
delete fW ;
delete fCpad ;
delete fHist;
delete fSlider;
delete fTimer;
}
//______________________________________________________________________________
void TTreeViewer::BuildInterface()
{
//*-*-*-*-*-*-*-*-*Create all viewer control buttons*-*-*-*-*-*-*-*-*-*-*
//*-* =================================
// Clear viewer is buttons already drawn
delete fDraw;
delete fScan;
delete fBreak;
delete fGopt;
delete fIList;
delete fOList;
delete fX;
delete fY;
delete fZ ;
delete fW ;
delete fCpad ;
delete fHist;
delete fSlider;
Clear();
Int_t nbuttons = 11;
Float_t dy = 1/Float_t(nbuttons);
Float_t dyb = 13./GetWh(); //choose 13 pixels for the button half height
Float_t y = 0.001+dyb;
Float_t xbl = 0.050;
Float_t xbr = xbl+0.11;
Float_t dxx = 0.003;
Float_t xin = 0.3*(xbr-xbl);
Float_t dyp = 0.6*dyb;
// Draw slider on left side of canvas
fSlider = new TSlider("SlideEvents", "events",0.001,0.01,xbl-dxx,0.99);
fSlider->SetFillColor(33);
// Draw control buttons or functions paves
char *action = new char[100];
sprintf(action,"((TTreeViewer*)gROOT->GetListOfCanvases()->FindObject("%s"))->ExecuteDraw("Scan")",GetName());
fScan = new TButton("Scan",action,xbl,y-dyb,xbr,y+dyb);
fScan->SetName("Scan");
fScan->SetFillColor(38);
fScan->Draw(); y += dy;
sprintf(action,"((TTreeViewer*)gROOT->GetListOfCanvases()->FindObject("%s"))->ExecuteDraw()",GetName());
fDraw = new TButton("Draw",action,xbl,y-dyb,xbr,y+dyb);
fDraw->SetName("Draw");
fDraw->SetFillColor(38);
fDraw->Draw(); y += dy;
TPaveVar *pl;
fGopt = new TButton("Gopt","",xbl,y-dyb,xbr,y+dyb);
fGopt->SetName("Gopt");
fGopt->SetFillColor(16);
fGopt->Draw();
pl = new TPaveVar(xbr-xin,y-dyp,xbr+0.1,y+dyp,"",this);
pl->Draw();
y += dy;
fOList = new TButton("OList","",xbl,y-dyb,xbr,y+dyb);
fOList->SetName("ListOut");
fOList->SetFillColor(16);
fOList->Draw();
pl = new TPaveVar(xbr-xin,y-dyp,xbr+0.1,y+dyp,"",this);
pl->Draw();
y += dy;
sprintf(action,"((TTreeViewer*)gROOT->GetListOfCanvases()->FindObject("%s"))->ExecuteDraw("Hist")",GetName());
fHist = new TButton("Hist",action,xbl,y-dyb,xbr,y+dyb);
fHist->SetName("Hist");
fHist->SetFillColor(16);
fHist->Draw();
fHist->Draw();
pl = new TPaveVar(xbr-xin,y-dyp,xbr+0.1,y+dyp,"htemp",this);
pl->Draw();
y += dy;
fCpad = new TButton("Cpad","",xbl,y-dyb,xbr,y+dyb);
fCpad->SetName("Cpad");
fCpad->SetFillColor(16);
fCpad->Draw();
fCpad->Draw();
pl = new TPaveVar(xbr-xin,y-dyp,xbr+0.1,y+dyp,"c1",this);
pl->SetName("TreeViewer_Drawpad");
pl->Draw();
y += dy;
fZ = new TButton("Z","",xbl,y-dyb,xbr,y+dyb);
fZ->SetName("Z");
fZ->SetFillColor(45);
fZ->Draw(); y += dy;
fY = new TButton("Y","",xbl,y-dyb,xbr,y+dyb);
fY->SetName("Y");
fY->SetFillColor(45);
fY->Draw(); y += dy;
fX = new TButton("X","",xbl,y-dyb,xbr,y+dyb);
fX->SetName("X");
fX->SetFillColor(45);
fX->Draw(); y += dy;
fIList = new TButton("IList","",xbl,y-dyb,xbr,y+dyb);
fIList->SetName("IList");
fIList->SetFillColor(16);
fIList->Draw();
pl = new TPaveVar(xbr-xin,y-dyp,xbr+0.1,y+dyp,"",this);
pl->Draw();
y += dy;
fBreak= new TButton("Break","gROOT->SetInterrupt()",xbl,y-dyb,xbr,y+dyb);
fBreak->SetName("Break");
fBreak->SetFillColor(38);
fBreak->Draw(); y += dy;
// Draw Selection/weight pave
Float_t xbwl = xbr+0.1;
Float_t xbwr = 0.99;
y = 0.001+dyb;
fW = new TButton("Weight - Selection","",xbwl,y-dyb,xbwr,y+dyb);
fW->SetName("W");
fW->SetFillColor(45);
fW->Draw();
y += dyb-0.1*dyb;
pl = new TPaveVar(xbwl+0.1,y,xbwr-0.1,y+2.5*dyp,"",this);
pl->Draw();
delete [] action;
// Draw leaves
TObjArray *leaves = fTree->GetListOfLeaves();
Int_t nleaves = leaves->GetEntries();
Int_t npixvar = 75; //Number of pixels along x for each variable
Float_t xll = 2*xbr - xbl;
Int_t nl = (GetWw() -XtoPixel(xll))/(npixvar+5);
Float_t xlr = 0.99;
Float_t dlx = (xlr-xll)/nl;
Float_t dleaf = 0.8*dlx;
xll += 0.2*dleaf;
Int_t i, k = 0;
y = 0.98-dyp;
dy = 3*dyp;
for (i=0;i<nleaves;i++) {
TLeaf *leaf = (TLeaf*)leaves->At(i);
TBranch *branch = leaf->GetBranch();
pl = new TPaveVar(xll+k*dlx,y-dyp,xll+k*dlx+dleaf,y+dyp,branch->GetName(),this);
if (branch->InheritsFrom("TBranchObject")) {
pl->SetFillColor(16);
pl->SetBit(kBranchObject);
}
pl->Draw();
k++;
if (k == nl) {
k = 0;
y -= dy; if (y < 0.3) break;
}
}
cd();
}
//______________________________________________________________________________
TPaveVar *TTreeViewer::CreateNewVar(const char *varname)
{
//*-*-*-*-*-*-*-*-*Create a new variable TPaveVar*-*-*-*-*-*-*-*-*-*-*
//*-* ==============================
Int_t px = GetEventX();
Int_t py = GetEventY();
Float_t x = AbsPixeltoX(px);
Float_t y = AbsPixeltoY(py);
Float_t dyp = 0.6*13./GetWh();
Float_t dxx = 0.6/8;
TPaveVar *pl = new TPaveVar(x-dxx,y-dyp,x+dxx,y+dyp,varname,this);
pl->Draw();
return pl;
}
//______________________________________________________________________________
void TTreeViewer::ExecuteDraw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*Called when the DRAW button is executed*-*-*-*-*-*-*-*-*-*-*
//*-* ========================================
//
// Look for TPaveVar objects below the action buttons X,Y,Z,W
// Check if an Entry range is given via the slider
// Check if a new histogram name is selected (instead of default "htemp")
// Check if there is an Output Event List or/and an Input Event List
//
// Special cases when option contains:
// -"Break" the event loop is interrupted. Show current histogram status
// -"Hist" show current histogram without interrupting the event loop
// -"VarDraw:" User has double clicked on one variable
//
TString opt = option;
if (opt.Contains("Break")) {
printf("Breaking event loopn");
return;
}
char *VarDraw = 0;
if (opt.Contains("VarDraw:")) { //we double clicked on a TPaveVar
VarDraw = strstr(option,":");
}
char varexp[80];
varexp[0] = 0;
// find label under X
TPaveVar *plx = IsUnder(fX);
// find label under Y
TPaveVar *ply = IsUnder(fY);
// find label under Z
TPaveVar *plz = IsUnder(fZ);
if (VarDraw) {
plx = (TPaveVar*)GetListOfPrimitives()->FindObject(VarDraw+1);
if (plx == 0) return;
ply = 0;
plz = 0;
}
if (plz) sprintf(varexp,"%s",plz->GetLabel());
if (plz && (ply || plx)) strcat(varexp,":");
if (ply) strcat(varexp,ply->GetLabel());
if (ply && plx) strcat(varexp,":");
if (plx) strcat(varexp,plx->GetLabel());
// find ListIn
fTree->SetEventList(0);
TPaveVar *plin = IsUnder(fIList);
TEventList *elist = 0;
if (plin) {
if (strlen(plin->GetLabel()) == 0) plin = 0;
if (plin) elist = (TEventList*)gROOT->FindObject(plin->GetLabel());
if (elist) fTree->SetEventList(elist);
}
// find ListOut
TPaveVar *plout = IsUnder(fOList);
if (plout) {
if (strlen(plout->GetLabel()) == 0) plout = 0;
if (plout) sprintf(varexp,">>%s",plout->GetLabel());
}
// find histogram name
TPaveVar *plhist = IsUnder(fHist);
char histname[80];
strcpy(histname,"htemp");
if (plout) plhist = 0;
if (plhist && strcmp("htemp",plhist->GetLabel())) {
strcat(varexp,">>");
strcat(varexp,plhist->GetLabel());
strcpy(histname,plhist->GetLabel());
}
// find selection/weight
char select[500];
select[0] = 0;
TPaveVar *plw = IsUnderW(fW);
if (plw) strncat(select,plw->GetLabel(),500);
// find graphics option
char gopt[80];
gopt[0] = 0;
TPaveVar *plgopt = IsUnder(fGopt);
if (plgopt) sprintf(gopt,"%s",plgopt->GetLabel());
// find slider to get number of events and first event
Float_t smin = fSlider->GetMinimum();
Float_t smax = fSlider->GetMaximum();
Int_t nentries = Int_t(fTree->GetEntries());
Int_t nevents = Int_t(nentries*(smax-smin));
Int_t firstEntry = Int_t(nentries*smin);
// find canvas/pad where to draw
TPaveVar *plcpad = IsUnder(fCpad);
if (plcpad) {
TPad *pad = (TPad*)gROOT->FindObject(plcpad->GetLabel());
if (pad && !pad->InheritsFrom(TPad::Class())) pad = 0;
if (pad) {
pad->cd();
} else {
new TCanvas(plcpad->GetLabel(),plcpad->GetLabel());
}
} else {
new TCanvas("c1");
}
gROOT->SetInterrupt(kFALSE); // just in case a BREAK had been set
TH1 *hist = 0;
if (opt.Contains("Hist")) {
hist = (TH1*)gDirectory->GetList()->FindObject(histname);
if (hist) {
hist->Draw(gopt);
gPad->Update();
}
return;
}
if (opt.Contains("Scan")) {
fTree->Scan(varexp,select,gopt,nevents,firstEntry);
return;
}
// Draw mode
if (TestBit(kDrawExecuting)) return;
SetBit(kDrawExecuting);
fTree->SetTimerInterval(fTimerInterval);
fTimer->TurnOn();
fTree->Draw(varexp,select,gopt,nevents,firstEntry);
HandleTimer(fTimer); //call necessary to show last slider status
fTimer->TurnOff();
fTree->SetTimerInterval(0);
ResetBit(kDrawExecuting);
if (gROOT->IsInterrupted()) {
printf("Break event loop at event: %dn",fTree->GetReadEntry());
}
gPad->Update();
}
//__________________________________________________________
Bool_t TTreeViewer::HandleTimer(TTimer *timer)
{
// This function is called by the fTimer object
// Paint a vertical red box in the slider box to show the progress
// in the event loop
if (TestBit(kDrawExecuting)) {
Float_t smin = fSlider->GetMinimum();
Float_t ymax = Float_t(fTree->GetReadEntry())/fTree->GetEntries();
Int_t px1 = fSlider->XtoAbsPixel(0)+3;
Int_t px2 = fSlider->XtoAbsPixel(1)-2;
Int_t py1 = fSlider->YtoAbsPixel(smin)-1;
Int_t py2 = fSlider->YtoAbsPixel(ymax);
gGXW->SelectWindow(GetCanvasID());
gGXW->SetFillColor(kRed);
gGXW->DrawBox(px1,py1,px2,py2,TGXW::kFilled);
gGXW->UpdateWindow(1);
gPad->SetCursor(kWatch);
}
timer->Reset();
return kFALSE;
}
//__________________________________________________________
TPaveVar *TTreeViewer::IsUnder(TButton *button)
{
//look for a TPaveVar under button
Float_t xmin = button->GetXlowNDC();
Float_t xmax = xmin + button->GetWNDC();
Float_t ymin = button->GetYlowNDC();
Float_t ymax = ymin + button->GetHNDC();
TIter next(GetListOfPrimitives());
TPaveVar *pl;
TObject *obj;
while ((obj=next())) {
if (obj->InheritsFrom(TPaveVar::Class())) {
pl = (TPaveVar*)obj;
if (pl->GetX1() < xmax) {
Float_t ymean = 0.5*(pl->GetY1()+pl->GetY2());
if (ymean > ymin && ymean < ymax) return pl;
}
}
}
return 0;
}
//__________________________________________________________
TPaveVar *TTreeViewer::IsUnderW(TButton *button)
{
//look for a TPaveVar under button W
Float_t xmin = button->GetXlowNDC();
Float_t xmax = xmin + button->GetWNDC();
Float_t ymin = button->GetYlowNDC();
Float_t ymax = ymin + button->GetHNDC();
TIter next(GetListOfPrimitives());
TPaveVar *pl;
TObject *obj;
while ((obj=next())) {
if (obj->InheritsFrom(TPaveVar::Class())) {
pl = (TPaveVar*)obj;
if (pl->GetY1() < ymax) {
Float_t xmean = 0.5*(pl->GetX1()+pl->GetX2());
if (xmean > xmin && xmean < xmax) return pl;
}
}
}
return 0;
}
//______________________________________________________________________________
void TTreeViewer::MakeClass(const char *classname)
{
//*-*-*-*-*-*-*-*-*Create all viewer control buttons*-*-*-*-*-*-*-*-*-*-*
//*-* =================================
printf("TTreeViewer::MakeClass for %s not yet implementedn",classname);
}
//______________________________________________________________________________
void TTreeViewer::Reorganize()
{
BuildInterface();
}
//______________________________________________________________________________
void TTreeViewer::SetTreeName(const char *treename)
{
// Set the current TTree to treename
delete fTree;
fTree = (TTree*)gROOT->FindObject(treename);
if (!fTree) {
printf("ERROR: Cannot find TTree with name: %s in current filen",treename);
return;
}
fTreeName = treename;
Int_t nch = 30;
nch += strlen(fTree->GetName())+strlen(fTree->GetTitle());
char *name = new char[nch];
sprintf(name,"%s","TreeViewer: ");
sprintf(&name[13],"%s : %s",fTree->GetName(),fTree->GetTitle());
SetTitle(name);
delete [] name;
fIsEditable = kIsNotEditable;
BuildInterface();
}
//______________________________________________________________________________
void TTreeViewer::Streamer(TBuffer &R__b)
{
// Stream an object of class TTreeViewer.
if (R__b.IsReading()) {
Version_t R__v = R__b.ReadVersion(); if (R__v) { }
TCanvas::Streamer(R__b);
TAttText::Streamer(R__b);
fTreeName.Streamer(R__b);
R__b >> fDraw;
R__b >> fScan;
R__b >> fBreak;
R__b >> fGopt;
R__b >> fIList;
R__b >> fOList;
R__b >> fX;
R__b >> fY;
R__b >> fZ;
R__b >> fW;
R__b >> fCpad;
R__b >> fHist;
R__b >> fSlider;
fTimer = new TTimer(this,40,kTRUE);
} else {
R__b.WriteVersion(TTreeViewer::IsA());
TCanvas::Streamer(R__b);
TAttText::Streamer(R__b);
fTreeName.Streamer(R__b);
R__b << fDraw;
R__b << fScan;
R__b << fBreak;
R__b << fGopt;
R__b << fIList;
R__b << fOList;
R__b << fX;
R__b << fY;
R__b << fZ;
R__b << fW;
R__b << fCpad;
R__b << fHist;
R__b << fSlider;
}
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.