// @(#)root/treeplayer:$Name: $:$Id: TTreePlayer.cxx,v 1.22 2000/09/12 15:45:11 brun Exp $
// Author: Rene Brun 12/01/96
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// TTree //
// //
// a TTree object has a header with a name and a title.
// It consists of a list of independent branches (TBranch). Each branch
// has its own definition and list of buffers. Branch buffers may be
// automatically written to disk or kept in memory until the Tree attribute
// fMaxVirtualSize is reached.
// Variables of one branch are written to the same buffer.
// A branch buffer is automatically compressed if the file compression
// attribute is set (default).
//
// Branches may be written to different files (see TBranch::SetFile).
//
// The ROOT user can decide to make one single branch and serialize one
// object into one single I/O buffer or to make several branches.
// Making one single branch and one single buffer can be the right choice
// when one wants to process only a subset of all entries in the tree.
// (you know for example the list of entry numbers you want to process).
// Making several branches is particularly interesting in the data analysis
// phase, when one wants to histogram some attributes of an object (entry)
// without reading all the attributes.
//
/*
*/
//
//
// ==> TTree *tree = new TTree(name, title, maxvirtualsize)
// Creates a Tree with name and title. Maxvirtualsize is by default 64Mbytes,
// maxvirtualsize = 64000000(default) means: Keeps as many buffers in memory until
// the sum of all buffers is greater than 64 Megabyte. When this happens,
// memory buffers are written to disk and deleted until the size of all
// buffers is again below the threshold.
// maxvirtualsize = 0 means: keep only one buffer in memory.
//
// Various kinds of branches can be added to a tree:
// A - simple structures or list of variables. (may be for C or Fortran structures)
// B - any object (inheriting from TObject). (we expect this option be the most frequent)
// C - a ClonesArray. (a specialized object for collections of same class objects)
//
// ==> Case A
// ======
// TBranch *branch = tree->Branch(branchname,address, leaflist, bufsize)
// * address is the address of the first item of a structure
// * leaflist is the concatenation of all the variable names and types
// separated by a colon character :
// The variable name and the variable type are separated by a slash (/).
// The variable type may be 0,1 or 2 characters. If no type is given,
// the type of the variable is assumed to be the same as the previous
// variable. If the first variable does not have a type, it is assumed
// of type F by default. The list of currently supported types is given below:
// - C : a character string terminated by the 0 character
// - B : an 8 bit signed integer (Char_t)
// - b : an 8 bit unsigned integer (UChar_t)
// - S : a 16 bit signed integer (Short_t)
// - s : a 16 bit unsigned integer (UShort_t)
// - I : a 32 bit signed integer (Int_t)
// - i : a 32 bit unsigned integer (UInt_t)
// - F : a 32 bit floating point (Float_t)
// - D : a 64 bit floating point (Double_t)
//
// ==> Case B
// ======
// TBranch *branch = tree->Branch(branchname,className,object, bufsize, splitlevel)
// object is the address of a pointer to an existing object (derived from TObject).
// if splitlevel=1 (default), this branch will automatically be split
// into subbranches, with one subbranch for each data member or object
// of the object itself. In case the object member is a TClonesArray,
// the mechanism described in case C is applied to this array.
// if splitlevel=0, the object is serialized in the branch buffer.
//
// ==> Case C
// ======
// TBranch *branch = tree->Branch(branchname,clonesarray, bufsize, splitlevel)
// clonesarray is the address of a pointer to a TClonesArray.
// The TClonesArray is a direct access list of objects of the same class.
// For example, if the TClonesArray is an array of TTrack objects,
// this function will create one subbranch for each data member of
// the object TTrack.
//
//
// ==> branch->SetAddress(Void *address)
// In case of dynamic structures changing with each entry for example, one must
// redefine the branch address before filling the branch again.
// This is done via the TBranch::SetAddress member function.
//
// ==> tree->Fill()
// loops on all defined branches and for each branch invokes the Fill function.
//
// See also the class TNtuple (a simple Tree with only one branch)
//
/*
*/
//
// =============================================================================
//______________________________________________________________________________
//*-*-*-*-*-*-*A simple example with histograms and a tree*-*-*-*-*-*-*-*-*-*
//*-* ===========================================
//
// This program creates :
// - a one dimensional histogram
// - a two dimensional histogram
// - a profile histogram
// - a tree
//
// These objects are filled with some random numbers and saved on a file.
//
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//
// #include "TROOT.h"
// #include "TFile.h"
// #include "TH1.h"
// #include "TH2.h"
// #include "TProfile.h"
// #include "TRandom.h"
// #include "TTree.h"
//
//
// TROOT simple("simple","Histograms and trees");
//
// //______________________________________________________________________________
// main(int argc, char **argv)
// {
// // Create a new ROOT binary machine independent file.
// // Note that this file may contain any kind of ROOT objects, histograms,trees
// // pictures, graphics objects, detector geometries, tracks, events, etc..
// // This file is now becoming the current directory.
// TFile hfile("htree.root","RECREATE","Demo ROOT file with histograms & trees");
//
// // Create some histograms and a profile histogram
// TH1F *hpx = new TH1F("hpx","This is the px distribution",100,-4,4);
// TH2F *hpxpy = new TH2F("hpxpy","py ps px",40,-4,4,40,-4,4);
// TProfile *hprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
//
// // Define some simple structures
// typedef struct {Float_t x,y,z;} POINT;
// typedef struct {
// Int_t ntrack,nseg,nvertex;
// UInt_t flag;
// Float_t temperature;
// } EVENTN;
// static POINT point;
// static EVENTN eventn;
//
// // Create a ROOT Tree
// TTree *tree = new TTree("T","An example of ROOT tree with a few branches");
// tree->Branch("point",&point,"x:y:z");
// tree->Branch("eventn",&eventn,"ntrack/I:nseg:nvertex:flag/i:temperature/F");
// tree->Branch("hpx","TH1F",&hpx,128000,0);
//
// Float_t px,py,pz;
// static Float_t p[3];
//
// //--------------------Here we start a loop on 1000 events
// for ( Int_t i=0; i<1000; i++) {
// gRandom->Rannor(px,py);
// pz = px*px + py*py;
// Float_t random = gRandom->::Rndm(1);
//
// // Fill histograms
// hpx->Fill(px);
// hpxpy->Fill(px,py,1);
// hprof->Fill(px,pz,1);
//
// // Fill structures
// p[0] = px;
// p[1] = py;
// p[2] = pz;
// point.x
// point.y
// point.z
// eventn.ntrack = Int_t(100*random);
// eventn.nseg = Int_t(2*eventn.ntrack);
// eventn.nvertex = 1;
// eventn.flag = Int_t(random+0.5);
// eventn.temperature = 20+random;
//
// // Fill the tree. For each event, save the 2 structures and 3 objects
// // In this simple example, the objects hpx, hprof and hpxpy are slightly
// // different from event to event. We expect a big compression factor!
// tree->Fill();
// }
// //--------------End of the loop
//
// tree->Print();
//
// // Save all objects in this file
// hfile.Write();
//
// // Close the file. Note that this is automatically done when you leave
// // the application.
// hfile.Close();
//
// return 0;
// }
// //
//////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include <float.h>
#include "TTreePlayer.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TFile.h"
#include "TSelector.h"
#include "TEventList.h"
#include "TBranchObject.h"
#include "TLeafObject.h"
#include "TLeafF.h"
#include "TLeafD.h"
#include "TLeafC.h"
#include "TLeafB.h"
#include "TLeafI.h"
#include "TLeafS.h"
#include "TMath.h"
#include "TH2.h"
#include "TH3.h"
#include "TView.h"
#include "TPolyMarker.h"
#include "TPolyMarker3D.h"
#include "TDirectory.h"
#include "TClonesArray.h"
#include "TClass.h"
#include "TVirtualPad.h"
#include "TProfile.h"
#include "TTreeFormula.h"
#include "TGaxis.h"
#include "TBrowser.h"
#include "TStyle.h"
#include "TProof.h"
#include "TProofServ.h"
#include "TSocket.h"
#include "TSlave.h"
#include "TMessage.h"
#include "TPacketGenerator.h"
#include "TInterpreter.h"
#include "Foption.h"
#include "TTreeResult.h"
#include "TTreeRow.h"
#include "TPrincipal.h"
#include "Api.h"
R__EXTERN Foption_t Foption;
ClassImp(TTreePlayer)
//______________________________________________________________________________
TTreePlayer::TTreePlayer()
{
//*-*-*-*-*-*-*-*-*-*-*Default Tree constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ========================
fTree = 0;
fV1 = 0;
fV2 = 0;
fV3 = 0;
fW = 0;
fVar1 = 0;
fVar2 = 0;
fVar3 = 0;
fVar4 = 0;
fSelect = 0;
fDraw = 0;
fPacketGen = 0;
fPacketSize = 100;
fHistogram = 0;
}
//______________________________________________________________________________
TTreePlayer::~TTreePlayer()
{
//*-*-*-*-*-*-*-*-*-*-*Tree destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =================
ClearFormula();
if (fV1) delete [] fV1;
if (fV2) delete [] fV2;
if (fV3) delete [] fV3;
if (fW) delete [] fW;
delete fPacketGen;
}
//______________________________________________________________________________
void TTreePlayer::ClearFormula()
{
//*-*-*-*-*-*-*Delete internal buffers*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =======================
delete fVar1; fVar1 = 0;
delete fVar2; fVar2 = 0;
delete fVar3; fVar3 = 0;
delete fVar4; fVar4 = 0;
delete fSelect; fSelect = 0;
}
//______________________________________________________________________________
void TTreePlayer::CompileVariables(const char *varexp, const char *selection)
{
//*-*-*-*-*-*-*Compile input variables and selection expression*-*-*-*-*-*
//*-* ================================================
//
// varexp is an expression of the general form e1:e2:e3
// where e1,etc is a formula referencing a combination of the columns
// Example:
// varexp = x simplest case: draw a 1-Dim distribution of column named x
// = sqrt(x) : draw distribution of sqrt(x)
// = x*y/z
// = y:sqrt(x) 2-Dim dsitribution of y versus sqrt(x)
//
// selection is an expression with a combination of the columns
// Example:
// selection = "x<y && sqrt(z)>3.2"
// in a selection all the C++ operators are authorized
//
//
const Int_t MAXCOL = 4;
TString title;
Int_t i,nch,ncols;
Int_t index[MAXCOL];
//*-*- Compile selection expression if there is one
fDimension = 0;
ClearFormula();
fMultiplicity = 0;
Int_t force = 0;
if (strlen(selection)) {
fSelect = new TTreeFormula("Selection",selection,fTree);
if (!fSelect->GetNdim()) {delete fSelect; fSelect = 0; return; }
if (fSelect->GetMultiplicity() >= 1) fMultiplicity = fSelect;
if (fSelect->GetMultiplicity() == -1) force = 4;
}
//*-*- if varexp is empty, take first column by default
nch = strlen(varexp);
if (nch == 0) {fDimension = 0; return;}
title = varexp;
//*-*- otherwise select only the specified columns
ncols = 1;
for (i=0;i<nch;i++) if (title[i] == ':') ncols++;
if (ncols > 3 ) return;
MakeIndex(title,index);
fTree->ResetBit(TTree::kForceRead);
if (ncols >= 1) {
fVar1 = new TTreeFormula("Var1",GetNameByIndex(title,index,0),fTree);
if (!fVar1->GetNdim()) { ClearFormula(); return;}
if (!fMultiplicity && fVar1->GetMultiplicity() >= 1) fMultiplicity = fVar1;
if (!force && fVar1->GetMultiplicity() == -1) force = 1;
}
if (ncols >= 2) {
fVar2 = new TTreeFormula("Var2",GetNameByIndex(title,index,1),fTree);
if (!fVar2->GetNdim()) { ClearFormula(); return;}
if (!fMultiplicity && fVar2->GetMultiplicity() >= 1) fMultiplicity = fVar2;
if (!force && fVar2->GetMultiplicity() == -1) force = 2;
}
if (ncols >= 3) {
fVar3 = new TTreeFormula("Var3",GetNameByIndex(title,index,2),fTree);
if (!fVar3->GetNdim()) { ClearFormula(); return;}
if (!fMultiplicity && fVar3->GetMultiplicity() >= 1) fMultiplicity = fVar3;
if (!force && fVar3->GetMultiplicity() == -1) force = 3;
}
if (force) fTree->SetBit(TTree::kForceRead);
fDimension = ncols;
}
//______________________________________________________________________________
TTree *TTreePlayer::CopyTree(const char *selection, Option_t *option, Int_t nentries, Int_t firstentry)
{
// copy a Tree with selection
// make a clone of this Tree header.
// then copy the selected entries
//
// selection is a standard selection expression (see TTreePlayer::Draw)
// option is reserved for possible future use
// nentries is the number of entries to process (default is all)
// first is the first entry to process (default is 0)
//
// Note that the branch addresses must be correctly set before calling this function
// The following example illustrates how to copy some events from the Tree
// generated in $ROOTSYS/test/Event
//
// gSystem->Load("libEvent");
// TFile f("Event.root");
// TTree *T = (TTree*)f.Get("T");
// Event *event = new Event();
// T->SetBranchAddress("event",&event);
// TFile f2("Event2.root","recreate");
// TTree *T2 = T->CopyTree("fNtrack<595");
// T2->Write();
// we make a copy of the tree header
TTree *tree = (TTree*)fTree->CloneTree(0);
if (tree == 0) return 0;
Int_t entry,entryNumber;
Int_t lastentry = firstentry + nentries -1;
if (lastentry > fTree->GetEntries()-1) {
lastentry = (Int_t)fTree->GetEntries() -1;
nentries = lastentry - firstentry + 1;
}
// Compile selection expression if there is one
TTreeFormula *select = 0;
if (strlen(selection)) {
select = new TTreeFormula("Selection",selection,fTree);
if (!select || !select->GetNdim()) { delete select; select = 0; }
}
//loop on the specified entries
for (entry=firstentry;entry<firstentry+nentries;entry++) {
entryNumber = fTree->GetEntryNumber(entry);
if (entryNumber < 0) break;
fTree->LoadTree(entryNumber);
if (select) {
select->GetNdata();
if (select->EvalInstance(0) == 0) continue;
}
fTree->GetEntry(entryNumber);
tree->Fill();
}
delete select;
return tree;
}
//_______________________________________________________________________
void TTreePlayer::CreatePacketGenerator(Int_t nentries, Stat_t firstEntry)
{
// Create or reset the packet generator.
if (!gProof) return;
Stat_t lastEntry = firstEntry + nentries - 1;
if (lastEntry > fTree->GetEntries()-1)
lastEntry = fTree->GetEntries() - 1;
if (!fPacketGen)
fPacketGen = new TPacketGenerator(firstEntry, lastEntry, fTree, gProof->GetListOfActiveSlaves());
else
fPacketGen->Reset(firstEntry, lastEntry, gProof->GetListOfActiveSlaves());
}
//______________________________________________________________________________
Int_t TTreePlayer::DrawSelect(const char *varexp0, const char *selection, Option_t *option,Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*-*-*-*-*-*-*Draw expression varexp for specified entries-*-*-*-*-*
//*-* ===========================================
//
// varexp is an expression of the general form e1:e2:e3
// where e1,etc is a formula referencing a combination of the columns
// Example:
// varexp = x simplest case: draw a 1-Dim distribution of column named x
// = sqrt(x) : draw distribution of sqrt(x)
// = x*y/z
// = y:sqrt(x) 2-Dim dsitribution of y versus sqrt(x)
// Note that the variables e1, e2 or e3 may contain a selection.
// example, if e1= x*(y<0), the value histogrammed will be x if y<0
// and will be 0 otherwise.
//
// selection is an expression with a combination of the columns.
// In a selection all the C++ operators are authorized.
// The value corresponding to the selection expression is used as a weight
// to fill the histogram.
// If the expression includes only boolean operations, the result
// is 0 or 1. If the result is 0, the histogram is not filled.
// In general, the expression may be of the form:
// value*(boolean expression)
// if boolean expression is true, the histogram is filled with
// a weight = value.
// Examples:
// selection1 = "x<y && sqrt(z)>3.2"
// selection2 = "(x+y)*(sqrt(z)>3.2"
// selection1 returns a weigth = 0 or 1
// selection2 returns a weight = x+y if sqrt(z)>3.2
// returns a weight = 0 otherwise.
//
// option is the drawing option
// see TH1::Draw for the list of all drawing options.
// If option contains the string "goff", no graphics is generated.
//
// nentries is the number of entries to process (default is all)
// first is the first entry to process (default is 0)
//
// Drawing expressions using arrays and array elements
// ===================================================
// Let assumes, a leaf fMatrix, on the branch fEvent, which is a 3 by 3 array,
// or a TClonesArray.
// In a TTree::Draw expression you can now access fMatrix using the following
// syntaxes:
//
// String passed What is used for each entry of the tree
//
// "fMatrix" the 9 elements of fMatrix
// "fMatrix[][]" the 9 elements of fMatrix
// "fMatrix[2][2]" only the elements fMatrix[2][2]
// "fMatrix[1]" the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2]
// "fMatrix[1][]" the 3 elements fMatrix[1][0], fMatrix[1][1] and fMatrix[1][2]
// "fMatrix[][0]" the 3 elements fMatrix[0][0], fMatrix[1][0] and fMatrix[2][0]
//
// "fEvent.fMatrix...." same as "fMatrix..." (unless there is more than one leaf named fMatrix!).
//
// In summary, if a specific index is not specified for a dimension, TTree::Draw
// will loop through all the indices along this dimension. Leaving off the
// last (right most) dimension of specifying then with the two characters '[]'
// is equivalent. For variable size arrays (and TClonesArray) the range
// of the first dimension is recalculated for each entry of the tree.
//
// TTree::Draw also now properly handling operations involving 2 or more arrays.
//
// Let assume a second matrix fResults[5][2], here are a sample of some
// of the possible combinations, the number of elements they produce and
// the loop used:
//
// expression element(s) Loop
//
// "fMatrix[2][1] - fResults[5][2]" one no loop
// "fMatrix[2][] - fResults[5][2]" three on 2nd dim fMatrix
// "fMatrix[2][] - fResults[5][]" two on both 2nd dimensions
// "fMatrix[][2] - fResults[][1]" three on both 1st dimensions
// "fMatrix[][2] - fResults[][]" six on both 1st and 2nd dimensions of
// fResults
// "fMatrix[][2] - fResults[3][]" two on 1st dim of fMatrix and 2nd of
// fResults (at the same time)
// "fMatrix[][] - fResults[][]" six on 1st dim then on 2nd dim
//
//
// In summary, TTree::Draw loops through all un-specified dimensions. To
// figure out the range of each loop, we match each unspecified dimension
// from left to right (ignoring ALL dimensions for which an index has been
// specified), in the equivalent loop matched dimensions use the same index
// and are restricted to the smallest range (of only the matched dimensions).
// When involving variable arrays, the range can of course be different
// for each entry of the tree.
//
// So the loop equivalent to "fMatrix[][2] - fResults[3][]" is:
//
// for (Int_t i0; i < min(3,2); i++) {
// use the value of (fMatrix[i0][2] - fMatrix[3][i0])
// }
//
// So the loop equivalent to "fMatrix[][2] - fResults[][]" is:
//
// for (Int_t i0; i < min(3,5); i++) {
// for (Int_t i1; i1 < 2; i1++) {
// use the value of (fMatrix[i0][2] - fMatrix[i0][i1])
// }
// }
//
// So the loop equivalent to "fMatrix[][] - fResults[][]" is:
//
// for (Int_t i0; i < min(3,5); i++) {
// for (Int_t i1; i1 < min(3,2); i1++) {
// use the value of (fMatrix[i0][i1] - fMatrix[i0][i1])
// }
// }
//
// Saving the result of Draw to an histogram
// =========================================
// By default the temporary histogram created is called htemp.
// If varexp0 contains >>hnew (following the variable(s) name(s),
// the new histogram created is called hnew and it is kept in the current
// directory.
// Example:
// tree.Draw("sqrt(x)>>hsqrt","y>0")
// will draw sqrt(x) and save the histogram as "hsqrt" in the current
// directory.
//
// By default, the specified histogram is reset.
// To continue to append data to an existing histogram, use "+" in front
// of the histogram name;
// tree.Draw("sqrt(x)>>+hsqrt","y>0")
// will not reset hsqrt, but will continue filling.
// This works for 1-D, 2-D and 3-D histograms.
//
// Making a Profile histogram
// ==========================
// In case of a 2-Dim expression, one can generate a TProfile histogram
// instead of a TH2F histogram by specyfying option=prof or option=profs.
// The option=prof is automatically selected in case of y:x>>pf
// where pf is an existing TProfile histogram.
//
// Saving the result of Draw to a TEventList
// =========================================
// TTree::Draw can be used to fill a TEventList object (list of entry numbers)
// instead of histogramming one variable.
// If varexp0 has the form >>elist , a TEventList object named "elist"
// is created in the current directory. elist will contain the list
// of entry numbers satisfying the current selection.
// Example:
// tree.Draw(">>yplus","y>0")
// will create a TEventList object named "yplus" in the current directory.
// In an interactive session, one can type (after TTree::Draw)
// yplus.Print("all")
// to print the list of entry numbers in the list.
//
// By default, the specified entry list is reset.
// To continue to append data to an existing list, use "+" in front
// of the list name;
// tree.Draw(">>+yplus","y>0")
// will not reset yplus, but will enter the selected entries at the end
// of the existing list.
//
// Using a TEventList as Input
// ===========================
// Once a TEventList object has been generated, it can be used as input
// for TTree::Draw. Use TTree::SetEventList to set the current event list
// Example:
// TEventList *elist = (TEventList*)gDirectory->Get("yplus");
// tree->SetEventList(elist);
// tree->Draw("py");
//
// Note: Use tree->SetEventList(0) if you do not want use the list as input.
//
// How to obtain more info from TTree::Draw
// ========================================
//
// Once TTree::Draw has been called, it is possible to access useful
// information still stored in the TTree object via the following functions:
// -GetSelectedRows() // return the number of entries accepted by the
// //selection expression. In case where no selection
// //was specified, returns the number of entries processed.
// -GetV1() //returns a pointer to the float array of V1
// -GetV2() //returns a pointer to the float array of V2
// -GetV3() //returns a pointer to the float array of V3
// -GetW() //returns a pointer to the double array of Weights
// //where weight equal the result of the selection expression.
// where V1,V2,V3 correspond to the expressions in
// TTree::Draw("V1:V2:V3",selection);
//
// Example:
// Root > ntuple->Draw("py:px","pz>4");
// Root > TGraph *gr = new TGraph(ntuple->GetSelectedRows(),
// ntuple->GetV2(), ntuple->GetV1());
// Root > gr->Draw("ap"); //draw graph in current pad
// creates a TGraph object with a number of points corresponding to the
// number of entries selected by the expression "pz>4", the x points of the graph
// being the px values of the Tree and the y points the py values.
//
// Important note: By default TTree::Draw creates the arrays obtained
// with GetV1, GetV2, GetV3, GetW with a length corresponding to the
// parameter fEstimate. By default fEstimate=10000 and can be modified
// via TTree::SetEstimate. A possible recipee is to do
// tree->SetEstimate(tree->GetEntries());
// You must call SetEstimate if the expected number of selected rows
// is greater than 10000.
//
// You can use the option "goff" to turn off the graphics output
// of TTree::Draw in the above example.
//
// Automatic interface to TTree::Draw via the TTreeViewer
// ======================================================
//
// A complete graphical interface to this function is implemented
// in the class TTreeViewer.
// To start the TTreeViewer, three possibilities:
// - select TTree context menu item "StartViewer"
// - type the command "TTreeViewer TV(treeName)"
// - execute statement "tree->StartViewer();"
//
if (fTree->GetEntries() == 0) return 0;
TString opt;
char *hdefault = (char *)"htemp";
char *varexp;
Int_t i,j,hkeep, action;
opt = option;
opt.ToLower();
char *hname = (char*)strstr(varexp0,">>");
TH1 *oldh1 = 0;
TEventList *elist = 0;
char htitle[2560]; htitle[0] = '0';
Bool_t profile = kFALSE;
fHistogram = 0;
if (hname) {
hname += 2;
hkeep = 1;
i = strcspn(varexp0,">>");
varexp = new char[i+1];
varexp[0] = 0; //necessary if i=0
Bool_t hnameplus = kFALSE;
while (*hname == ' ') hname++;
if (*hname == '+') {
hnameplus = kTRUE;
hname++;
while (*hname == ' ') hname++;
j = strlen(hname)-1;
while (j) {
if (hname[j] != ' ') break;
hname[j] = 0;
j--;
}
}
if (i) {
strncpy(varexp,varexp0,i); varexp[i]=0;
oldh1 = (TH1*)gDirectory->Get(hname);
if (oldh1 && !hnameplus) oldh1->Reset();
} else {
elist = (TEventList*)gDirectory->Get(hname);
if (!elist) {
elist = new TEventList(hname,selection,1000,0);
}
if (elist && !hnameplus) elist->Reset();
}
} else {
hname = hdefault;
hkeep = 0;
varexp = (char*)varexp0;
if (gDirectory) {
oldh1 = (TH1*)gDirectory->Get(hname);
if (oldh1 && !gProofServ) { oldh1->Delete(); oldh1 = 0;}
}
}
//*-* Do not process more than fMaxEntryLoop entries
if (nentries > fTree->GetMaxEntryLoop()) nentries = fTree->GetMaxEntryLoop();
//*-*- Decode varexp and selection
CompileVariables(varexp, selection);
if (!fVar1 && !elist) return -1;
//*-*- In case oldh1 exists, check dimensionality
Int_t nsel = strlen(selection);
if (nsel > 1) {
sprintf(htitle,"%s {%s}",varexp,selection);
} else {
sprintf(htitle,"%s",varexp);
}
if (oldh1) {
Int_t olddim = oldh1->GetDimension();
Int_t mustdelete = 0;
if (oldh1->InheritsFrom("TProfile")) {
profile = kTRUE;
olddim = 2;
}
if (opt.Contains("prof")) {
if (!profile) mustdelete = 1;
} else {
if (olddim != fDimension) mustdelete = 1;
}
if (mustdelete) {
Warning("Draw","Deleting old histogram with different dimensions");
delete oldh1; oldh1 = 0;
}
}
//*-*- Create a default canvas if none exists
fDraw = 0;
if (!gPad && !gProofServ && !opt.Contains("goff") && fDimension > 0) {
if (!gROOT->GetMakeDefCanvas()) return -1;
(gROOT->GetMakeDefCanvas())();
}
//*-*- 1-D distribution
if (fDimension == 1) {
action = 1;
if (!oldh1) {
fNbins[0] = 100;
if (gPad && opt.Contains("same")) {
TListIter np(gPad->GetListOfPrimitives());
TObject *op;
TH1 *oldhtemp = 0;
while ((op = np()) && !oldhtemp) {
if (op->InheritsFrom("TH1")) oldhtemp = (TH1 *)op;
}
if (oldhtemp) {
fNbins[0] = oldhtemp->GetXaxis()->GetNbins();
fVmin[0] = oldhtemp->GetXaxis()->GetXmin();
fVmax[0] = oldhtemp->GetXaxis()->GetXmax();
} else {
fVmin[0] = gPad->GetUxmin();
fVmax[0] = gPad->GetUxmax();
}
} else {
action = -1;
}
}
TH1F *h1;
if (oldh1) {
h1 = (TH1F*)oldh1;
fNbins[0] = h1->GetXaxis()->GetNbins(); // for proofserv
} else {
h1 = new TH1F(hname,htitle,fNbins[0],fVmin[0],fVmax[0]);
h1->SetLineColor(fTree->GetLineColor());
h1->SetLineWidth(fTree->GetLineWidth());
h1->SetLineStyle(fTree->GetLineStyle());
h1->SetFillColor(fTree->GetFillColor());
h1->SetFillStyle(fTree->GetFillStyle());
h1->SetMarkerStyle(fTree->GetMarkerStyle());
h1->SetMarkerColor(fTree->GetMarkerColor());
h1->SetMarkerSize(fTree->GetMarkerSize());
if (!opt.Contains("same"))h1->SetBit(TH1::kCanRebin);
if (!hkeep) {
h1->SetBit(kCanDelete);
h1->SetDirectory(0);
}
if (opt.Length() && opt[0] == 'e') h1->Sumw2();
}
if (TProof::IsActive()) {
CreatePacketGenerator(nentries, firstentry);
gProof->SendCurrentState();
if (action == -1) h1->SetBinContent(0,1.0);
gProof->SendObject(h1);
if (!hkeep) delete h1;
char *mess = new char[strlen(varexp0)+strlen(selection)+strlen(option)+128];
sprintf(mess, "%s %d %d", fTree->GetName(), fTree->GetMaxVirtualSize(), fTree->GetEstimate());
gProof->Broadcast(mess, kPROOF_TREEDRAW);
sprintf(mess,"%s->Draw("%s","%s","%s",%d,%d)", fTree->GetName(), varexp0,
selection, option, nentries, firstentry);
gProof->Broadcast(mess, kMESS_CINT);
delete [] mess;
gProof->Loop(fTree);
if (gDirectory) {
h1 = (TH1F*)gDirectory->Get(hname);
if (!h1) {
Error("Draw", "histogram %s not returned by PROOF", hname);
fDraw = 1;
} else if (!hkeep) {
h1->SetBit(kCanDelete);
h1->SetDirectory(0);
}
}
} else if (gProofServ) {
Stat_t first;
fNfill = 0;
if (h1->GetBinContent(0) > 0) {
h1->SetBinContent(0,0.0);
action = -1;
}
while (gProofServ->GetNextPacket(nentries, first))
EntryLoop(action, h1, nentries, (Int_t)first, option);
EntryLoop(action, h1, nentries, (Int_t)first, option);
// Send all created objects back to client
TObject *obj;
TIter next(gDirectory->GetList());
while ((obj = next()))
if (obj->InheritsFrom(TH1::Class())) { // send only histograms back
if (gProofServ->GetLogLevel() > 2)
printf("Slave %d: %s: Nentries is %.0fn",
gProofServ->GetOrdinal(), obj->GetName(),
((TH1*)obj)->GetEntries());
gProofServ->GetSocket()->SendObject(obj);
}
fDraw = 1; // do not draw histogram
} else
EntryLoop(action, h1, nentries, firstentry, option);
if (!fDraw && !opt.Contains("goff")) h1->Draw(option);
//*-*- 2-D distribution
} else if (fDimension == 2) {
action = 2;
// if (!opt.Contains("same") && !opt.Contains("goff") && gPad) gPad->Clear();
if (!oldh1 || !opt.Contains("same")) {
fNbins[0] = 40;
fNbins[1] = 40;
if (opt.Contains("prof")) fNbins[1] = 100;
if (opt.Contains("same")) {
TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
if (oldhtemp) {
fNbins[1] = oldhtemp->GetXaxis()->GetNbins();
fVmin[1] = oldhtemp->GetXaxis()->GetXmin();
fVmax[1] = oldhtemp->GetXaxis()->GetXmax();
fNbins[0] = oldhtemp->GetYaxis()->GetNbins();
fVmin[0] = oldhtemp->GetYaxis()->GetXmin();
fVmax[0] = oldhtemp->GetYaxis()->GetXmax();
} else {
fNbins[1] = 40;
fVmin[1] = gPad->GetUxmin();
fVmax[1] = gPad->GetUxmax();
fNbins[0] = 40;
fVmin[0] = gPad->GetUymin();
fVmax[0] = gPad->GetUymax();
}
} else {
if (!oldh1) action = -2;
}
}
if (profile || opt.Contains("prof")) {
TProfile *hp;
if (oldh1) {
action = 4;
hp = (TProfile*)oldh1;
} else {
if (action < 0) action = -4;
if (opt.Contains("profs"))
hp = new TProfile(hname,htitle,fNbins[1],fVmin[1], fVmax[1],"s");
else
hp = new TProfile(hname,htitle,fNbins[1],fVmin[1], fVmax[1],"");
if (!hkeep) {
hp->SetBit(kCanDelete);
hp->SetDirectory(0);
}
hp->SetLineColor(fTree->GetLineColor());
hp->SetLineWidth(fTree->GetLineWidth());
hp->SetLineStyle(fTree->GetLineStyle());
hp->SetFillColor(fTree->GetFillColor());
hp->SetFillStyle(fTree->GetFillStyle());
hp->SetMarkerStyle(fTree->GetMarkerStyle());
hp->SetMarkerColor(fTree->GetMarkerColor());
hp->SetMarkerSize(fTree->GetMarkerSize());
}
EntryLoop(action,hp,nentries, firstentry, option);
if (!fDraw && !opt.Contains("goff")) hp->Draw(option);
} else {
TH2F *h2;
if (oldh1) {
h2 = (TH2F*)oldh1;
} else {
h2 = new TH2F(hname,htitle,fNbins[1],fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
h2->SetLineColor(fTree->GetLineColor());
h2->SetFillColor(fTree->GetFillColor());
h2->SetFillStyle(fTree->GetFillStyle());
h2->SetMarkerStyle(fTree->GetMarkerStyle());
h2->SetMarkerColor(fTree->GetMarkerColor());
h2->SetMarkerSize(fTree->GetMarkerSize());
if (!opt.Contains("same"))h2->SetBit(TH1::kCanRebin);
if (!hkeep) {
h2->SetBit(kCanDelete);
h2->SetBit(TH1::kNoStats);
h2->SetDirectory(0);
}
}
Int_t noscat = strlen(option);
if (opt.Contains("same")) noscat -= 4;
if (noscat) {
EntryLoop(action,h2,nentries, firstentry, option);
if (!fDraw && !opt.Contains("goff")) h2->Draw(option);
} else {
action = 12;
if (!oldh1 && !opt.Contains("same")) action = -12;
EntryLoop(action,h2,nentries, firstentry, option);
if (oldh1 && !fDraw && !opt.Contains("goff")) h2->Draw(option);
}
}
//*-*- 3-D distribution
} else if (fDimension == 3) {
action = 3;
// if (!opt.Contains("same") && !opt.Contains("goff") && gPad) gPad->Clear();
if (!oldh1 || !opt.Contains("same")) {
fNbins[0] = 20;
fNbins[1] = 20;
fNbins[2] = 20;
if (opt.Contains("same")) {
TH1 *oldhtemp = (TH1*)gPad->FindObject(hdefault);
if (oldhtemp) {
fNbins[2] = oldhtemp->GetXaxis()->GetNbins();
fVmin[2] = oldhtemp->GetXaxis()->GetXmin();
fVmax[2] = oldhtemp->GetXaxis()->GetXmax();
fNbins[1] = oldhtemp->GetYaxis()->GetNbins();
fVmin[1] = oldhtemp->GetYaxis()->GetXmin();
fVmax[1] = oldhtemp->GetYaxis()->GetXmax();
fNbins[0] = oldhtemp->GetZaxis()->GetNbins();
fVmin[0] = oldhtemp->GetZaxis()->GetXmin();
fVmax[0] = oldhtemp->GetZaxis()->GetXmax();
} else {
TView *view = gPad->GetView();
Double_t *rmin = view->GetRmin();
Double_t *rmax = view->GetRmax();
fNbins[2] = 20;
fVmin[2] = rmin[0];
fVmax[2] = rmax[0];
fNbins[1] = 20;
fVmin[1] = rmin[1];
fVmax[1] = rmax[1];
fNbins[0] = 20;
fVmin[0] = rmin[2];
fVmax[0] = rmax[2];
}
} else {
if (!oldh1) action = -3;
}
}
TH3F *h3;
if (oldh1) {
h3 = (TH3F*)oldh1;
} else {
h3 = new TH3F(hname,htitle,fNbins[2],fVmin[2], fVmax[2],fNbins[1],fVmin[1], fVmax[1], fNbins[0], fVmin[0], fVmax[0]);
h3->SetLineColor(fTree->GetLineColor());
h3->SetFillColor(fTree->GetFillColor());
h3->SetFillStyle(fTree->GetFillStyle());
h3->SetMarkerStyle(fTree->GetMarkerStyle());
h3->SetMarkerColor(fTree->GetMarkerColor());
h3->SetMarkerSize(fTree->GetMarkerSize());
if (!opt.Contains("same"))h3->SetBit(TH1::kCanRebin);
if (!hkeep) {
h3->SetBit(kCanDelete);
h3->SetBit(TH1::kNoStats);
h3->SetDirectory(0);
}
}
Int_t noscat = strlen(option);
if (opt.Contains("same")) noscat -= 4;
if (noscat) {
EntryLoop(action,h3,nentries, firstentry, option);
if (!fDraw && !opt.Contains("goff")) h3->Draw(option);
} else {
action = 13;
if (!oldh1 && !opt.Contains("same")) action = -13;
EntryLoop(action,h3,nentries, firstentry, option);
if (oldh1 && !fDraw && !opt.Contains("goff")) h3->Draw(option);
}
//*-* an Event List
} else {
action = 5;
Int_t oldEstimate = fTree->GetEstimate();
fTree->SetEstimate(1);
EntryLoop(action,elist,nentries, firstentry, option);
fTree->SetEstimate(oldEstimate);
}
if (hkeep) delete [] varexp;
return fSelectedRows;
}
//______________________________________________________________________________
void TTreePlayer::EntryLoop(Int_t &action, TObject *obj, Int_t nentries, Int_t firstentry, Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Loop on all entries*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ==================
//
// nentries is the number of entries to process (default is all)
// first is the first entry to process (default is 0)
//
// action = 1 Fill 1-D histogram obj
// = 2 Fill 2-D histogram obj
// = 3 Fill 3-D histogram obj
// = 4 Fill Profile histogram obj
// = 5 Fill a TEventlist
// = 11 Estimate Limits
// = 12 Fill 2-D PolyMarker obj
// = 13 Fill 3-D PolyMarker obj
// action < 0 Evaluate Limits for case abs(action)
//
Int_t i,entry,entryNumber, lastentry,ndata,nfill0;
Double_t ww;
Int_t npoints;
lastentry = firstentry + nentries - 1;
if (lastentry > fTree->GetEntries()-1) {
lastentry = (Int_t)fTree->GetEntries() - 1;
nentries = lastentry - firstentry + 1;
}
TDirectory *cursav = gDirectory;
if (!gProofServ) fNfill = 0;
//Create a timer to get control in the entry loop(s)
TProcessEventTimer *timer = 0;
Int_t interval = fTree->GetTimerInterval();
if (!gROOT->IsBatch() && !gProofServ && interval)
timer = new TProcessEventTimer(interval);
npoints = 0;
if (!fV1 && fVar1) fV1 = new Double_t[fTree->GetEstimate()];
if (!fV2 && fVar2) fV2 = new Double_t[fTree->GetEstimate()];
if (!fV3 && fVar3) fV3 = new Double_t[fTree->GetEstimate()];
if (!fW) fW = new Double_t[fTree->GetEstimate()];
Int_t force = fTree->TestBit(TTree::kForceRead);
if (!fMultiplicity || !fDimension) {
Bool_t available = kTRUE;
for (entry=firstentry;entry<firstentry+nentries;entry++) {
entryNumber = fTree->GetEntryNumber(entry);
if (entryNumber < 0) break;
if (timer && timer->ProcessEvents()) break;
if (gROOT->IsInterrupted()) break;
fTree->LoadTree(entryNumber);
if (fSelect) {
if (force) { available = (fSelect->GetNdata()>0); };
fW[fNfill] = fSelect->EvalInstance(0);
if (!fW[fNfill]) continue;
} else fW[fNfill] = 1;
if (fVar1) {
if (force) { available = (fVar1->GetNdata()>0); };
fV1[fNfill] = fVar1->EvalInstance(0);
}
if (fVar2) {
if (force) { available = (fVar2->GetNdata()>0); };
fV2[fNfill] = fVar2->EvalInstance(0);
if (fVar3) {
if (force) { available = (fVar3->GetNdata()>0); };
fV3[fNfill] = fVar3->EvalInstance(0);
}
}
if (available) {
fNfill++;
if (fNfill >= fTree->GetEstimate()) {
TakeAction(fNfill,npoints,action,obj,option);
fNfill = 0;
}
} else available = kTRUE;
}
// nentries == -1 when all entries have been processed by proofserver
if (gProofServ && nentries != -1) return;
if (fNfill) {
TakeAction(fNfill,npoints,action,obj,option);
}
fSelectedRows = npoints;
if (npoints == 0) fDraw = 1; // do not draw
delete timer;
return;
}
Bool_t Var1Multiple = kFALSE;
Bool_t Var2Multiple = kFALSE;
Bool_t Var3Multiple = kFALSE;
Bool_t SelectMultiple = kFALSE;
if (fVar1 && fVar1->GetMultiplicity()) Var1Multiple = kTRUE;
if (fVar2 && fVar2->GetMultiplicity()) Var2Multiple = kTRUE;
if (fVar3 && fVar3->GetMultiplicity()) Var3Multiple = kTRUE;
if (fSelect && fSelect->GetMultiplicity()) SelectMultiple = kTRUE;
for (entry=firstentry;entry<firstentry+nentries;entry++) {
entryNumber = fTree->GetEntryNumber(entry);
if (entryNumber < 0) break;
if (timer && timer->ProcessEvents()) break;
if (gROOT->IsInterrupted()) break;
fTree->LoadTree(entryNumber);
nfill0 = fNfill;
// Look for the lowest common array size amongst the
// variable and selection cut.
ndata = fMultiplicity->GetNdata();
if (Var1Multiple && (fMultiplicity!=fVar1))
ndata = TMath::Min(ndata,fVar1->GetNdata());
if (Var2Multiple && (fMultiplicity!=fVar2))
ndata = TMath::Min(ndata,fVar2->GetNdata());
if (Var3Multiple && (fMultiplicity!=fVar3))
ndata = TMath::Min(ndata,fVar3->GetNdata());
// no data at all, let's move on to the next entry.
if (!ndata) continue;
// Calculate the first values
if (fSelect) {
fW[fNfill] = fSelect->EvalInstance(0);
if (!fW[fNfill] && !SelectMultiple) continue;
} else fW[fNfill] = 1;
fV1[fNfill] = fVar1->EvalInstance(0);
if (fVar2) {
fV2[fNfill] = fVar2->EvalInstance(0);
if (fVar3) {
fV3[fNfill] = fVar3->EvalInstance(0);
}
}
if (fW[fNfill]) {
fNfill++;
if (fNfill >= fTree->GetEstimate()) {
TakeAction(fNfill,npoints,action,obj,option);
fNfill = 0;
}
}
ww = 1;
for (i=1;i<ndata;i++) {
if (SelectMultiple) {
ww = fSelect->EvalInstance(i);
if (ww == 0) continue;
}
if (Var1Multiple) fV1[fNfill] = fVar1->EvalInstance(i);
else fV1[fNfill] = fV1[nfill0];
if (fVar2) {
if (Var2Multiple) fV2[fNfill] = fVar2->EvalInstance(i);
else fV2[fNfill] = fV2[nfill0];
if (fVar3) {
if (Var3Multiple) fV3[fNfill] = fVar3->EvalInstance(i);
else fV3[fNfill] = fV3[nfill0];
}
}
fW[fNfill] = ww;
fNfill++;
if (fNfill >= fTree->GetEstimate()) {
TakeAction(fNfill,npoints,action,obj,option);
fNfill = 0;
}
}
}
delete timer;
// nentries == -1 when all entries have been processed by proofserver
if (gProofServ && nentries != -1) return;
if (fNfill) {
TakeAction(fNfill,npoints,action,obj,option);
}
fSelectedRows = npoints;
if (npoints == 0) fDraw = 1; // do not draw
if (cursav) cursav->cd();
}
//______________________________________________________________________________
void TTreePlayer::EstimateLimits(Int_t, Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*Estimate histogram limits for conditions of input parameters*-*-*-*
//*-* ============================================================
//
// The estimation of the limits is based on estimate entries
// The first estimate/2 and the last esstimate/2 entries are used.
// This algorithm is in general good enough to make a reasonable estimation
// with a small number of entries.
//
// nentries is the number of entries to process (default is all)
// first is the first entry to process (default is 0)
//
Int_t lastentry;
lastentry = firstentry + nentries -1;
if (lastentry > fTree->GetEntries()-1) {
lastentry = (Int_t)fTree->GetEntries() -1;
nentries = lastentry - firstentry + 1;
}
fVmin[0] = fVmin[1] = fVmin[2] = FLT_MAX; //in float.h
fVmax[0] = fVmax[1] = fVmax[2] = -fVmin[0];
Int_t action = 11;
EntryLoop(action,0,nentries,firstentry);
//*-*- Compute nice limits
Int_t nchans = fNbins[0];
if (fVar1) {
if (fVmin[0] >= fVmax[0]) { fVmin[0] -= 1; fVmax[0] += 1;}
FindGoodLimits(nchans,fNbins[0],fVmin[0],fVmax[0]);
}
if (fVar2) {
if (fVmin[1] >= fVmax[1]) { fVmin[1] -= 1; fVmax[1] += 1;}
FindGoodLimits(nchans,fNbins[1],fVmin[1],fVmax[1]);
}
if (fVar3) {
if (fVmin[2] >= fVmax[2]) { fVmin[2] -= 1; fVmax[2] += 1;}
FindGoodLimits(nchans,fNbins[2],fVmin[2],fVmax[2]);
}
}
//______________________________________________________________________________
void TTreePlayer::FindGoodLimits(Int_t nbins, Int_t &newbins, Double_t &xmin, Double_t &xmax)
{
//*-*-*-*-*-*-*-*-*Find reasonable bin values*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ==========================
static TGaxis gaxis_tree;
Double_t binlow,binhigh,binwidth;
Int_t n;
Double_t dx = 0.1*(xmax-xmin);
Double_t umin = xmin - dx;
Double_t umax = xmax + dx;
if (umin < 0 && xmin >= 0) umin = 0;
if (umax > 0 && xmax <= 0) umax = 0;
gaxis_tree.Optimize(umin,umax,nbins,binlow,binhigh,n,binwidth);
if (binwidth <= 0 || binwidth > 1.e+39) {
xmin = -1;
xmax = 1;
} else {
xmin = binlow;
xmax = binhigh;
}
newbins = nbins;
}
//______________________________________________________________________________
Int_t TTreePlayer::Fit(const char *formula ,const char *varexp, const char *selection,Option_t *option ,Option_t *goption,Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*-*-*-*-*Fit a projected item(s) from a Tree*-*-*-*-*-*-*-*-*-*
//*-* ======================================
//
// formula is a TF1 expression.
//
// See TTree::Draw for explanations of the other parameters.
//
// By default the temporary histogram created is called htemp.
// If varexp contains >>hnew , the new histogram created is called hnew
// and it is kept in the current directory.
// Example:
// tree.Fit("pol4","sqrt(x)>>hsqrt","y>0")
// will fit sqrt(x) and save the histogram as "hsqrt" in the current
// directory.
//
Int_t nch = strlen(option) + 10;
char *opt = new char[nch];
if (option) sprintf(opt,"%sgoff",option);
else strcpy(opt,"goff");
Int_t nsel = DrawSelect(varexp,selection,opt,nentries,firstentry);
delete [] opt;
if (fHistogram) {
fHistogram->Fit(formula,option,goption);
}
return nsel;
}
//______________________________________________________________________________
const char *TTreePlayer::GetNameByIndex(TString &varexp, Int_t *index,Int_t colindex)
{
//*-*-*-*-*-*-*-*-*Return name corresponding to colindex in varexp*-*-*-*-*-*
//*-* ===============================================
//
// varexp is a string of names separated by :
// index is an array with pointers to the start of name[i] in varexp
//
Int_t i1,n;
static TString column;
if (colindex<0 ) return "";
i1 = index[colindex] + 1;
n = index[colindex+1] - i1;
column = varexp(i1,n);
// return (const char*)Form((const char*)column);
return column.Data();
}
//______________________________________________________________________________
void TTreePlayer::GetNextPacket(TSlave *sl, Int_t &nentries, Stat_t &firstentry, Stat_t &processed)
{
// Return in nentries and firstentry the optimal range of entries (packet)
// to be processed by slave sl. See TPacketGenerator for the algorithm
// used to get the packet size.
fPacketGen->GetNextPacket(sl, nentries, firstentry);
processed = fPacketGen->GetEntriesProcessed();
}
//______________________________________________________________________________
void TTreePlayer::Loop(Option_t *option, Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*-*-*-*-*Loop on nentries of this tree starting at firstentry
//*-* ===================================================
Warning("Loop","Obsolete function");
}
//______________________________________________________________________________
Int_t TTreePlayer::MakeClass(const char *classname, const char *option)
{
//====>
//*-*-*-*-*-*-*Generate skeleton analysis class for this Tree*-*-*-*-*-*-*
//*-* ==============================================
//
// The following files are produced: classname.h and classname.C
// if classname is NULL, classname will be nameoftree.
//
// When the option "selector" is specified, the function generates the
// selector class described in TTree::MakeSelector.
//
// The generated code in classname.h includes the following:
// - Identification of the original Tree and Input file name
// - Definition of analysis class (data and functions)
// - the following class functions:
// -constructor (connecting by default the Tree file)
// -GetEntry(Int_t entry)
// -Init(TTree *tree) to initialize a new TTree
// -Show(Int_t entry) to read and Dump entry
//
// The generated code in classname.C includes only the main
// analysis function Loop.
//
// To use this function:
// - connect your Tree file (eg: TFile f("myfile.root");)
// - T->MakeClass("MyClass");
// where T is the name of the Tree in file myfile.root
// and MyClass.h, MyClass.C the name of the files created by this function.
// In a Root session, you can do:
// Root > .L MyClass.C
// Root > MyClass t
// Root > t.GetEntry(12); // Fill t data members with entry number 12
// Root > t.Show(); // Show values of entry 12
// Root > t.Show(16); // Read and show values of entry 16
// Root > t.Loop(); // Loop on all entries
//
//====>
TString opt = option;
opt.ToLower();
// Connect output files
char *thead = new char[256];
if (!classname) classname = fTree->GetName();
sprintf(thead,"%s.h",classname);
FILE *fp = fopen(thead,"w");
if (!fp) {
printf("Cannot open output file:%sn",thead);
delete [] thead;
return 3;
}
char *tcimp = new char[256];
sprintf(tcimp,"%s.C",classname);
FILE *fpc = fopen(tcimp,"w");
if (!fpc) {
printf("Cannot open output file:%sn",tcimp);
delete [] thead;
delete [] tcimp;
return 3;
}
char *treefile = new char[1000];
if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile())
strcpy(treefile,fTree->GetDirectory()->GetFile()->GetName());
else strcpy(treefile,"Memory Directory");
//======================Generate classname.h=====================
// Print header
TObjArray *leaves = fTree->GetListOfLeaves();
Int_t nleaves = leaves->GetEntriesFast();
TDatime td;
fprintf(fp,"//////////////////////////////////////////////////////////n");
fprintf(fp,"// This class has been automatically generated n");
fprintf(fp,"// (%s by ROOT version%s)n",td.AsString(),gROOT->GetVersion());
fprintf(fp,"// from TTree %s/%sn",fTree->GetName(),fTree->GetTitle());
fprintf(fp,"// found on file: %sn",treefile);
fprintf(fp,"//////////////////////////////////////////////////////////n");
fprintf(fp,"n");
fprintf(fp,"n");
fprintf(fp,"#ifndef %s_hn",classname);
fprintf(fp,"#define %s_hn",classname);
fprintf(fp,"n");
fprintf(fp,"#include <TChain.h>n");
fprintf(fp,"#include <TFile.h>n");
if (opt.Contains("selector")) fprintf(fp,"#include <TSelector.h>n");
// First loop on all leaves to generate dimension declarations
Int_t len, lenb,l;
char blen[128];
char *bname;
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
strcpy(blen,leaf->GetName());
bname = &blen[0];
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
lenb = strlen(blen);
if (blen[lenb-1] == '_') {
blen[lenb-1] = 0;
fprintf(fp," const Int_t kMax%s = %d;n",blen,leaf->GetMaximum());
}
}
// second loop on all leaves to generate type declarations
fprintf(fp,"n");
if (opt.Contains("selector")) {
fprintf(fp,"class %s : public TSelector {n",classname);
fprintf(fp," public :n");
fprintf(fp," TTree *fChain; //pointer to the analyzed TTree or TChainn");
} else {
fprintf(fp,"class %s {n",classname);
fprintf(fp," public :n");
fprintf(fp," TTree *fChain; //pointer to the analyzed TTree or TChainn");
fprintf(fp," Int_t fCurrent; //current Tree number in a TChainn");
}
fprintf(fp,"//Declaration of leaves typesn");
TLeaf *leafcount;
TLeafObject *leafobj;
const char *headOK = " ";
const char *headcom = " //";
const char *head;
char branchname[128];
TObjArray branches(100);
Int_t *leafStatus = new Int_t[nleaves];
for (l=0;l<nleaves;l++) {
leafStatus[l] = 0;
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
branchname[0] = 0;
strcpy(branchname,branch->GetName());
Int_t nch = strlen(branchname);
if (!branches.FindObject(branch)) branches.Add(branch);
else leafStatus[l] = 1;
if ( branch->GetNleaves() > 1) {
// More than one leaf for the branch we need to distinguish them
strcat(branchname,".");
strcat(branchname,leaf->GetTitle());
if (leafcount) {
// remove any dimension in title
char *dim = (char*)strstr(branchname,"[");
dim[0] = 0;
}
} else {
if (leafcount) strcpy(branchname,branch->GetName());
else {
if (branchname[nch-1] == '.') strcat(branchname,leaf->GetTitle());
}
}
char *twodim = (char*)strstr(leaf->GetTitle(),"][");
bname = branchname;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
if (branch->IsA() == TBranchObject::Class()) {
if (branch->GetListOfBranches()->GetEntriesFast()) continue;
leafobj = (TLeafObject*)leaf;
if (leafobj->GetClass()) head = headOK;
else head = headcom;
fprintf(fp,"%s%-15s *%s;n",head,leafobj->GetTypeName(), leafobj->GetName());
continue;
}
if (leafcount) {
len = leafcount->GetMaximum();
strcpy(blen,leafcount->GetName());
bname = &blen[0];
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
lenb = strlen(blen);
Int_t kmax = 0;
if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
else sprintf(blen,"%d",len);
// Dimensions can be in the branchname for a split Object with a fix length C array.
// Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
char *dimInName = (char*) strstr(branchname,"[");
char *dimensions = 0;
if ( twodim || dimInName ) {
int dimlen = 0;
if (dimInName) dimlen += strlen(dimInName) + 1;
if (twodim) dimlen += strlen(twodim) + 1;
dimensions = new char[dimlen];
if (dimInName) {
strcpy(dimensions,dimInName);
dimInName[0] = 0; // terminate branchname before the array dimensions.
} else dimensions[0] = 0;
if (twodim) strcat(dimensions,(char*)(twodim+1));
}
if (dimensions) {
if (kmax) fprintf(fp," %-15s %s[kMax%s]%s;n",leaf->GetTypeName(),
branchname,blen,dimensions);
else fprintf(fp," %-15s %s[%d]%s;n",leaf->GetTypeName(),
branchname,len,dimensions);
delete dimensions;
} else {
if (kmax) fprintf(fp," %-15s %s[kMax%s];n",leaf->GetTypeName(), branchname,blen);
else fprintf(fp," %-15s %s[%d];n",leaf->GetTypeName(), branchname,len);
}
} else {
if (strstr(branchname,"[")) len = 1;
if (len < 2) fprintf(fp," %-15s %s;n",leaf->GetTypeName(), branchname);
else fprintf(fp," %-15s %s[%d];n",leaf->GetTypeName(), branchname,len);
}
}
// generate list of branches
fprintf(fp,"n");
fprintf(fp,"//List of branchesn");
for (l=0;l<nleaves;l++) {
if (leafStatus[l]) continue;
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
TBranch *branch = leaf->GetBranch();
strcpy(branchname,branch->GetName());
bname = branchname;
char *twodim = (char*)strstr(bname,"[");
if (twodim) *twodim = 0;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
fprintf(fp," TBranch *b_%s;n",branchname);
}
// generate class member functions prototypes
if (opt.Contains("selector")) {
fprintf(fp,"n");
fprintf(fp," %s(TTree *tree=0) {;}n",classname) ;
fprintf(fp," ~%s() {;}n",classname);
fprintf(fp," void Begin(TTree *tree);n");
fprintf(fp," void Init(TTree *tree);n");
fprintf(fp," Bool_t Notify();n");
fprintf(fp," Bool_t ProcessCut(Int_t entry);n");
fprintf(fp," void ProcessFill(Int_t entry);n");
fprintf(fp," void Terminate();n");
fprintf(fp,"};n");
fprintf(fp,"n");
fprintf(fp,"#endifn");
fprintf(fp,"n");
} else {
fprintf(fp,"n");
fprintf(fp," %s(TTree *tree=0);n",classname);
fprintf(fp," ~%s();n",classname);
fprintf(fp," Int_t Cut(Int_t entry);n");
fprintf(fp," Int_t GetEntry(Int_t entry);n");
fprintf(fp," Int_t LoadTree(Int_t entry);n");
fprintf(fp," void Init(TTree *tree);n");
fprintf(fp," void Loop();n");
fprintf(fp," Bool_t Notify();n");
fprintf(fp," void Show(Int_t entry = -1);n");
fprintf(fp,"};n");
fprintf(fp,"n");
fprintf(fp,"#endifn");
fprintf(fp,"n");
}
// generate code for class constructor
fprintf(fp,"#ifdef %s_cxxn",classname);
if (!opt.Contains("selector")) {
fprintf(fp,"%s::%s(TTree *tree)n",classname,classname);
fprintf(fp,"{n");
fprintf(fp,"// if parameter tree is not specified (or zero), connect the filen");
fprintf(fp,"// used to generate this class and read the Tree.n");
fprintf(fp," if (tree == 0) {n");
fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("%s");n",treefile);
fprintf(fp," if (!f) {n");
fprintf(fp," f = new TFile("%s");n",treefile);
if (gDirectory != gFile) {
fprintf(fp," f->cd("%s");n",gDirectory->GetPath());
}
fprintf(fp," }n");
fprintf(fp," tree = (TTree*)gDirectory->Get("%s");n\n",fTree->GetName());
fprintf(fp," }n");
fprintf(fp," Init(tree);n");
fprintf(fp,"}n");
fprintf(fp,"n");
}
// generate code for class destructor()
if (!opt.Contains("selector")) {
fprintf(fp,"%s::~%s()n",classname,classname);
fprintf(fp,"{n");
fprintf(fp," if (!fChain) return;n");
fprintf(fp," delete fChain->GetCurrentFile();n");
fprintf(fp,"}n");
fprintf(fp,"n");
}
// generate code for class member function GetEntry()
if (!opt.Contains("selector")) {
fprintf(fp,"Int_t %s::GetEntry(Int_t entry)n",classname);
fprintf(fp,"{n");
fprintf(fp,"// Read contents of entry.n");
fprintf(fp," if (!fChain) return 0;n");
fprintf(fp," return fChain->GetEntry(entry);n");
fprintf(fp,"}n");
}
// generate code for class member function LoadTree()
if (!opt.Contains("selector")) {
fprintf(fp,"Int_t %s::LoadTree(Int_t entry)n",classname);
fprintf(fp,"{n");
fprintf(fp,"// Set the environment to read one entryn");
fprintf(fp," if (!fChain) return -5;n");
fprintf(fp," Int_t centry = fChain->LoadTree(entry);n");
fprintf(fp," if (centry < 0) return centry;n");
fprintf(fp," if (fChain->IsA() != TChain::Class()) return centry;n");
fprintf(fp," TChain *chain = (TChain*)fChain;n");
fprintf(fp," if (chain->GetTreeNumber() != fCurrent) {n");
fprintf(fp," fCurrent = chain->GetTreeNumber();n");
fprintf(fp," Notify();n");
fprintf(fp," }n");
fprintf(fp," return centry;n");
fprintf(fp,"}n");
fprintf(fp,"n");
}
// generate code for class member function Init(), first pass = get branch pointer
fprintf(fp,"void %s::Init(TTree *tree)n",classname);
fprintf(fp,"{n");
fprintf(fp,"// Set branch addressesn");
fprintf(fp," if (tree == 0) return;n");
fprintf(fp," fChain = tree;n");
if (!opt.Contains("selector")) fprintf(fp," fCurrent = -1;n");
fprintf(fp,"n");
for (l=0;l<nleaves;l++) {
if (leafStatus[l]) continue;
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
if ( branch->GetNleaves() > 1) {
// More than one leaf for the branch we need to distinguish them
strcpy(branchname,branch->GetName());
strcat(branchname,".");
strcat(branchname,leaf->GetTitle());
if (leafcount) {
// remove any dimension in title
char *dim = (char*)strstr(branchname,"[");
dim[0] = 0;
}
} else {
if (leafcount) strcpy(branchname,branch->GetName());
else strcpy(branchname,leaf->GetTitle());
}
bname = branchname;
char *twodim = (char*)strstr(bname,"[");
if (twodim) *twodim = 0;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
char *brak = strstr(branchname,"[");
if (brak) *brak = 0;
head = headOK;
if (branch->IsA() == TBranchObject::Class()) {
if (branch->GetListOfBranches()->GetEntriesFast()) {
fprintf(fp,"%sfChain->SetBranchAddress("%s",(void*)-1);n",head,branch->GetName());
continue;
}
leafobj = (TLeafObject*)leaf;
if (!leafobj->GetClass()) head = headcom;
strcpy(branchname,branch->GetName());
}
if (leafcount) len = leafcount->GetMaximum()+1;
if (len > 1) fprintf(fp,"%sfChain->SetBranchAddress("%s",%s);n",head,branch->GetName(),branchname);
else fprintf(fp,"%sfChain->SetBranchAddress("%s",&%s);n",head,branch->GetName(),branchname);
}
fprintf(fp,"}n");
fprintf(fp,"n");
// generate code for class member function Notify()
fprintf(fp,"Bool_t %s::Notify()n",classname);
fprintf(fp,"{n");
fprintf(fp,"// called when loading a new filen");
fprintf(fp,"// get branch pointersn");
for (l=0;l<nleaves;l++) {
if (leafStatus[l]) continue;
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
strcpy(branchname,branch->GetName());
bname = branchname;
char *twodim = (char*)strstr(bname,"[");
if (twodim) *twodim = 0;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
head = headOK;
if (branch->IsA() == TBranchObject::Class()) {
if (branch->GetListOfBranches()->GetEntriesFast()) {
fprintf(fp,"%sb_%s = fChain->GetBranch("%s");n",head,branchname,branch->GetName());
continue;
}
leafobj = (TLeafObject*)leaf;
if (!leafobj->GetClass()) head = headcom;
strcpy(branchname,branch->GetName());
}
fprintf(fp,"%sb_%s = fChain->GetBranch("%s");n",head,branchname,branch->GetName());
}
fprintf(fp," return kTRUE;n");
fprintf(fp,"}n");
fprintf(fp,"n");
// generate code for class member function Show()
if (!opt.Contains("selector")) {
fprintf(fp,"void %s::Show(Int_t entry)n",classname);
fprintf(fp,"{n");
fprintf(fp,"// Print contents of entry.n");
fprintf(fp,"// If entry is not specified, print current entryn");
fprintf(fp," if (!fChain) return;n");
fprintf(fp," fChain->Show(entry);n");
fprintf(fp,"}n");
}
// generate code for class member function Cut()
if (!opt.Contains("selector")) {
fprintf(fp,"Int_t %s::Cut(Int_t entry)n",classname);
fprintf(fp,"{n");
fprintf(fp,"// This function may be called from Loop.n");
fprintf(fp,"// returns 1 if entry is accepted.n");
fprintf(fp,"// returns -1 otherwise.n");
fprintf(fp," return 1;n");
fprintf(fp,"}n");
}
fprintf(fp,"#endif // #ifdef %s_cxxn",classname);
fprintf(fp,"n");
//======================Generate classname.C=====================
if (!opt.Contains("selector")) {
// generate code for class member function Loop()
fprintf(fpc,"#define %s_cxxn",classname);
fprintf(fpc,"#include "%s"n",thead);
fprintf(fpc,"#include "%s"n","TH2.h");
fprintf(fpc,"#include "%s"n","TStyle.h");
fprintf(fpc,"#include "%s"n","TCanvas.h");
fprintf(fpc,"n");
fprintf(fpc,"void %s::Loop()n",classname);
fprintf(fpc,"{n");
fprintf(fpc,"// In a Root session, you can do:n");
fprintf(fpc,"// Root > .L %s.Cn",classname);
fprintf(fpc,"// Root > %s tn",classname);
fprintf(fpc,"// Root > t.GetEntry(12); // Fill t data members with entry number 12n");
fprintf(fpc,"// Root > t.Show(); // Show values of entry 12n");
fprintf(fpc,"// Root > t.Show(16); // Read and show values of entry 16n");
fprintf(fpc,"// Root > t.Loop(); // Loop on all entriesn");
fprintf(fpc,"//n");
fprintf(fpc,"n// This is the loop skeletonn");
fprintf(fpc,"// To read only selected branches, Insert statements like:n");
fprintf(fpc,"// METHOD1:n");
fprintf(fpc,"// fChain->SetBranchStatus("*",0); // disable all branchesn");
fprintf(fpc,"// fChain->SetBranchStatus("branchname",1); // activate branchnamen");
fprintf(fpc,"// METHOD2: replace linen");
fprintf(fpc,"// fChain->GetEntry(i); // read all branchesn");
fprintf(fpc,"//by b_branchname->GetEntry(i); //read only this branchn");
fprintf(fpc," if (fChain == 0) return;n");
fprintf(fpc,"n Int_t nentries = Int_t(fChain->GetEntries());n");
fprintf(fpc,"n Int_t nbytes = 0, nb = 0;n");
fprintf(fpc," for (Int_t jentry=0; jentry<nentries;jentry++) {n");
fprintf(fpc," Int_t ientry = LoadTree(jentry); //in case of a TChain, ientry is the entry number in the current filen");
fprintf(fpc," nb = fChain->GetEntry(jentry); nbytes += nb;n");
fprintf(fpc," // if (Cut(ientry) < 0) continue;n");
fprintf(fpc," }n");
fprintf(fpc,"}n");
}
if (opt.Contains("selector")) {
// generate usage comments and list of includes
fprintf(fpc,"#define %s_cxxn",classname);
fprintf(fpc,"// The class definition in %s.h has been generated automaticallyn",classname);
fprintf(fpc,"// by the Root utility TTree::MakeSelector.n");
fprintf(fpc,"//n");
fprintf(fpc,"// This class is derived from the Root class TSelector.n");
fprintf(fpc,"// The following members functions are called by the TTree::Process functions.n");
fprintf(fpc,"// Begin: called everytime a loop on the tree starts.n");
fprintf(fpc,"// a convenient place to create your histograms.n");
fprintf(fpc,"// Notify(): This function is called at the first entry of a new Treen");
fprintf(fpc,"// in a chain.n");
fprintf(fpc,"// ProcessCut: called at the beginning of each entry to return a flagn");
fprintf(fpc,"// true if the entry must be analyzed.n");
fprintf(fpc,"// ProcessFill: called in the entry loop for all entries accepted n");
fprintf(fpc,"// by Select.n");
fprintf(fpc,"// Terminate: called at the end of a loop on a TTree.n");
fprintf(fpc,"// a convenient place to draw/fit your histograms.n");
fprintf(fpc,"//n");
fprintf(fpc,"// To use this file, try the following session on your Tree Tn");
fprintf(fpc,"//n");
fprintf(fpc,"// Root > T.Process("%s.C")n",classname);
fprintf(fpc,"// Root > T.Process("%s.C,"some options"")n",classname);
fprintf(fpc,"// Root > T.Process("%s.C+")n",classname);
fprintf(fpc,"//n");
fprintf(fpc,"#include "%s"n",thead);
fprintf(fpc,"#include "%s"n","TH2.h");
fprintf(fpc,"#include "%s"n","TStyle.h");
fprintf(fpc,"#include "%s"n","TCanvas.h");
fprintf(fpc,"n");
// generate code for class member function Begin
fprintf(fpc,"n");
fprintf(fpc,"void %s::Begin(TTree *tree)n",classname);
fprintf(fpc,"{n");
fprintf(fpc,"// function called before starting the event loopn");
fprintf(fpc,"// initialize the tree branchesn");
fprintf(fpc,"n");
fprintf(fpc," Init(tree);n");
fprintf(fpc,"n");
fprintf(fpc," TString option = GetOption();n");
fprintf(fpc,"n");
fprintf(fpc,"}n");
// generate code for class member function ProcessCut
fprintf(fpc,"n");
fprintf(fpc,"Bool_t %s::ProcessCut(Int_t entry)n",classname);
fprintf(fpc,"{n");
fprintf(fpc,"// Selection functionn");
fprintf(fpc,"// Read only the necessary branches to select entries.n");
fprintf(fpc,"// return as soon as a bad entry is detected.n");
fprintf(fpc,"n");
fprintf(fpc," return kTRUE;n");
fprintf(fpc,"}n");
// generate code for class member function ProcessFill
fprintf(fpc,"n");
fprintf(fpc,"void %s::ProcessFill(Int_t entry)n",classname);
fprintf(fpc,"{n");
fprintf(fpc,"// function called for selected entries onlyn");
fprintf(fpc,"// read branches not processed in ProcessCut and fill histogramsn");
fprintf(fpc,"n");
fprintf(fpc,"n");
fprintf(fpc,"}n");
// generate code for class member function Terminate
fprintf(fpc,"n");
fprintf(fpc,"void %s::Terminate()n",classname);
fprintf(fpc,"{n");
fprintf(fpc,"// function called at the end of the event loopn");
fprintf(fpc,"n");
fprintf(fpc,"n");
fprintf(fpc,"}n");
}
printf("Files: %s and %s generated from Tree: %sn",thead,tcimp,fTree->GetName());
delete [] leafStatus;
delete [] thead;
delete [] tcimp;
delete [] treefile;
fclose(fp);
fclose(fpc);
return 0;
}
//______________________________________________________________________________
Int_t TTreePlayer::MakeCode(const char *filename)
{
//====>
//*-*-*-*-*-*-*-*-*Generate skeleton function for this Tree*-*-*-*-*-*-*
//*-* ========================================
//
// The function code is written on filename
// if filename is NULL, filename will be nameoftree.C
//
// The generated code includes the following:
// - Identification of the original Tree and Input file name
// - Connection of the Tree file
// - Declaration of Tree variables
// - Setting of branches addresses
// - a skeleton for the entry loop
//
// To use this function:
// - connect your Tree file (eg: TFile f("myfile.root");)
// - T->MakeCode("user.C");
// where T is the name of the Tree in file myfile.root
// and user.C the name of the file created by this function.
//
// NOTE: Since the implementation of this function, new and better
// function TTree::MakeClass and TTree::MakeSelector have been developped.
//
// Author: Rene Brun
//====>
// Connect output file
char *tfile = new char[1000];
if (filename) strcpy(tfile,filename);
else sprintf(tfile,"%s.C",fTree->GetName());
FILE *fp = fopen(tfile,"w");
if (!fp) {
printf("Cannot open output file:%sn",tfile);
return 3;
}
char *treefile = new char[1000];
if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile())
strcpy(treefile,fTree->GetDirectory()->GetFile()->GetName());
else strcpy(treefile,"Memory Directory");
// Print header
TObjArray *leaves = fTree->GetListOfLeaves();
Int_t nleaves = leaves->GetEntriesFast();
TDatime td;
fprintf(fp,"{n");
fprintf(fp,"//////////////////////////////////////////////////////////n");
fprintf(fp,"// This file has been automatically generated n");
fprintf(fp,"// (%s by ROOT version%s)n",td.AsString(),gROOT->GetVersion());
fprintf(fp,"// from TTree %s/%sn",fTree->GetName(),fTree->GetTitle());
fprintf(fp,"// found on file: %sn",treefile);
fprintf(fp,"//////////////////////////////////////////////////////////n");
fprintf(fp,"n");
fprintf(fp,"n");
// Reset and file connect
fprintf(fp,"//Reset ROOT and connect tree filen");
fprintf(fp," gROOT->Reset();n");
fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("%s");n",treefile);
fprintf(fp," if (!f) {n");
fprintf(fp," f = new TFile("%s");n",treefile);
if (gDirectory != gFile) {
fprintf(fp," f->cd("%s");n",gDirectory->GetPath());
}
fprintf(fp," }n");
fprintf(fp," TTree *%s = (TTree*)gDirectory->Get("%s");n\n",fTree->GetName(),fTree->GetName());
// First loop on all leaves to generate type declarations
fprintf(fp,"//Declaration of leaves typesn");
Int_t len, l;
TLeaf *leafcount;
TLeafObject *leafobj;
char *bname;
const char *headOK = " ";
const char *headcom = " //";
const char *head;
char branchname[128];
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
if (branch->GetListOfBranches()->GetEntriesFast() > 0) continue;
if ( branch->GetNleaves() > 1) {
// More than one leaf for the branch we need to distinguish them
strcpy(branchname,branch->GetName());
strcat(branchname,".");
strcat(branchname,leaf->GetTitle());
if (leafcount) {
// remove any dimension in title
char *dim = (char*)strstr(branchname,"[");
dim[0] = 0;
}
} else {
if (leafcount) strcpy(branchname,branch->GetName());
else strcpy(branchname,leaf->GetTitle());
}
char *twodim = (char*)strstr(leaf->GetTitle(),"][");
bname = branchname;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
if (branch->IsA() == TBranchObject::Class()) {
leafobj = (TLeafObject*)leaf;
if (leafobj->GetClass()) head = headOK;
else head = headcom;
fprintf(fp,"%s%-15s *%s = 0;n",head,leafobj->GetTypeName(), leafobj->GetName());
continue;
}
if (leafcount) {
len = leafcount->GetMaximum();
// Dimensions can be in the branchname for a split Object with a fix length C array.
// Theses dimensions HAVE TO be placed after the dimension explicited by leafcount
char *dimInName = (char*) strstr(branchname,"[");
char *dimensions = 0;
if ( twodim || dimInName ) {
int dimlen = 0;
if (dimInName) dimlen += strlen(dimInName) + 1;
if (twodim) dimlen += strlen(twodim) + 1;
dimensions = new char[dimlen];
if (dimInName) {
strcpy(dimensions,dimInName);
dimInName[0] = 0; // terminate branchname before the array dimensions.
} else dimensions[0] = 0;
if (twodim) strcat(dimensions,(char*)(twodim+1));
}
if (dimensions) {
fprintf(fp," %-15s %s[%d]%s;n",leaf->GetTypeName(), branchname,len,dimensions);
delete dimensions;
} else {
fprintf(fp," %-15s %s[%d];n",leaf->GetTypeName(), branchname,len);
}
} else {
if (strstr(branchname,"[")) len = 1;
if (len < 2) fprintf(fp," %-15s %s;n",leaf->GetTypeName(), branchname);
else fprintf(fp," %-15s %s[%d];n",leaf->GetTypeName(), branchname,len);
}
}
// Second loop on all leaves to set the corresponding branch address
fprintf(fp,"n//Set branch addressesn");
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
if ( branch->GetNleaves() > 1) {
// More than one leaf for the branch we need to distinguish them
strcpy(branchname,branch->GetName());
strcat(branchname,".");
strcat(branchname,leaf->GetTitle());
if (leafcount) {
// remove any dimension in title
char *dim = (char*)strstr(branchname,"[");
dim[0] = 0;
}
} else {
if (leafcount) strcpy(branchname,branch->GetName());
else strcpy(branchname,leaf->GetTitle());
}
bname = branchname;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
char *brak = strstr(branchname,"[");
if (brak) *brak = 0;
head = headOK;
if (branch->IsA() == TBranchObject::Class()) {
strcpy(branchname,branch->GetName());
leafobj = (TLeafObject*)leaf;
if (!leafobj->GetClass()) head = headcom;
}
if (leafcount) len = leafcount->GetMaximum()+1;
if (len > 1 || brak) fprintf(fp,"%s%s->SetBranchAddress("%s",%s);n",head,fTree->GetName(),branch->GetName(),branchname);
else fprintf(fp,"%s%s->SetBranchAddress("%s",&%s);n",head,fTree->GetName(),branch->GetName(),branchname);
}
//Generate instructions to make the loop on entries
fprintf(fp,"n// This is the loop skeletonn");
fprintf(fp,"// To read only selected branches, Insert statements like:n");
fprintf(fp,"// %s->SetBranchStatus("*",0); // disable all branchesn",fTree->GetName());
fprintf(fp,"// %s->SetBranchStatus("branchname",1); // activate branchnamen",GetName());
fprintf(fp,"n Int_t nentries = %s->GetEntries();n",fTree->GetName());
fprintf(fp,"n Int_t nbytes = 0;n");
fprintf(fp,"// for (Int_t i=0; i<nentries;i++) {n");
fprintf(fp,"// nbytes += %s->GetEntry(i);n",fTree->GetName());
fprintf(fp,"// }n");
fprintf(fp,"}n");
printf("Macro: %s generated from Tree: %sn",tfile,fTree->GetName());
delete [] tfile;
delete [] treefile;
fclose(fp);
return 0;
}
//______________________________________________________________________________
void TTreePlayer::MakeIndex(TString &varexp, Int_t *index)
{
//*-*-*-*-*-*-*-*-*Build Index array for names in varexp*-*-*-*-*-*-*-*-*-*-*
//*-* =====================================
Int_t ivar = 1;
index[0] = -1;
for (Int_t i=0;i<varexp.Length();i++) {
if (varexp[i] == ':') {
index[ivar] = i;
ivar++;
}
}
index[ivar] = varexp.Length();
}
//______________________________________________________________________________
TPrincipal *TTreePlayer::Principal(const char *varexp, const char *selection, Option_t *option, Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*-*-*-*-*Interface to the Principal Components Analysis class*-*-*
//*-* ====================================================
//
// Create an instance of TPrincipal
// Fill it with the selected variables
// if option "n" is specified, the TPrincipal object is filled with
// normalized variables.
// If option "p" is specified, compute the principal components
// If option "p" and "d" print results of analysis
// If option "p" and "h" generate standard histograms
// If option "p" and "c" generate code of conversion functions
// return a pointer to the TPrincipal object. It is the user responsability
// to delete this object.
// The option default value is "np"
//
// see TTreePlayer::DrawSelect for explanation of the other parameters.
TTreeFormula *select, **var;
TString *cnames;
TString onerow;
TString opt = option;
opt.ToLower();
TPrincipal *principal = 0;
Int_t entry,entryNumber,i,nch;
Int_t *index = 0;
Int_t ncols = 8; // by default first 8 columns are printed only
TObjArray *leaves = fTree->GetListOfLeaves();
Int_t nleaves = leaves->GetEntriesFast();
if (nleaves < ncols) ncols = nleaves;
nch = varexp ? strlen(varexp) : 0;
Int_t lastentry = firstentry + nentries -1;
if (lastentry > fTree->GetEntries()-1) {
lastentry = (Int_t)fTree->GetEntries() -1;
nentries = lastentry - firstentry + 1;
}
//*-*- Compile selection expression if there is one
select = 0;
if (strlen(selection)) {
select = new TTreeFormula("Selection",selection,fTree);
if (!select) return principal;
if (!select->GetNdim()) { delete select; return principal; }
}
//*-*- if varexp is empty, take first 8 columns by default
int allvar = 0;
if (!strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
if (nch == 0 || allvar) {
cnames = new TString[ncols];
for (i=0;i<ncols;i++) {
cnames[i] = ((TLeaf*)leaves->At(i))->GetName();
}
//*-*- otherwise select only the specified columns
} else {
ncols = 1;
onerow = varexp;
for (i=0;i<onerow.Length();i++) if (onerow[i] == ':') ncols++;
cnames = new TString[ncols];
index = new Int_t[ncols+1];
MakeIndex(onerow,index);
for (i=0;i<ncols;i++) {
cnames[i] = GetNameByIndex(onerow,index,i);
}
}
var = new TTreeFormula* [ncols];
Double_t *xvars = new Double_t[ncols];
//*-*- Create the TreeFormula objects corresponding to each column
for (i=0;i<ncols;i++) {
var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
}
//*-* Build the TPrincipal object
if (opt.Contains("n")) principal = new TPrincipal(ncols, "n");
else principal = new TPrincipal(ncols);
//*-*- loop on all selected entries
fSelectedRows = 0;
for (entry=firstentry;entry<firstentry+nentries;entry++) {
entryNumber = fTree->GetEntryNumber(entry);
if (entryNumber < 0) break;
fTree->LoadTree(entryNumber);
if (select) {
select->GetNdata();
if (select->EvalInstance(0) == 0) continue;
}
onerow = Form("* %8d ",entryNumber);
for (i=0;i<ncols;i++) {
xvars[i] = var[i]->EvalInstance(0);
}
principal->AddRow(xvars);
}
//*-* some actions with principal ?
if (opt.Contains("p")) {
principal->MakePrincipals(); // Do the actual analysis
if (opt.Contains("d")) principal->Print();
if (opt.Contains("h")) principal->MakeHistograms();
if (opt.Contains("c")) principal->MakeCode();
}
//*-*- delete temporary objects
delete select;
for (i=0;i<ncols;i++) {
delete var[i];
}
delete [] var;
delete [] cnames;
delete [] index;
delete [] xvars;
return principal;
}
//______________________________________________________________________________
Int_t TTreePlayer::Process(const char *filename,Option_t *option, Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*-*-*-*-*Process this tree executing the code in filename*-*-*-*-*
//*-* ================================================
//
// The code in filename is loaded (interpreted or compiled , see below)
// filename must contain a valid class implementation derived from TSelector.
// where TSelector has the following member functions:
//
// void TSelector::Begin(). This function is called before looping on the
// events in the Tree. The user can create his histograms in this function.
//
// Bool_t TSelector::Notify(). This function is called at the first entry
// of a new file in a chain.
//
// Bool_t TSelector::ProcessCut(Int_t entry). This function is called
// before processing entry. It is the user's responsability to read
// the corresponding entry in memory (may be just a partial read).
// The function returns kTRUE if the entry must be processed,
// kFALSE otherwise.
//
// void TSelector::ProcessFill(Int_t entry). This function is called for
// all selected events. User fills histograms in this function.
//
// void TSelector::Terminate(). This function is called at the end of
// the loop on all events.
//
// if filename is of the form file.C, the file will be interpreted.
// if filename is of the form file.C++, the file file.C will be compiled
// and dynamically loaded. The corresponding binary file and shared library
// will be deleted at the end of the function.
// if filename is of the form file.C+, the file file.C will be compiled
// and dynamically loaded. The corresponding binary file and shared library
// will be kept at the end of the function. At next call, if file.C
// is older than file.o and file.so, the file.C is not compiled, only
// file.so is loaded.
//Get a pointer to the TSelector object
static TSelector *selector = 0;
delete selector; //delete previous selector if any
// This might reloads the script and delete your option
// string! so let copy it first:
TString opt(option);
TString file(filename);
selector = TSelector::GetSelector(file);
if (!selector) return -1;
Int_t nsel = Process(selector,opt,nentries,firstentry);
return nsel;
}
//______________________________________________________________________________
Int_t TTreePlayer::Process(TSelector *selector,Option_t *option, Int_t nentries, Int_t firstentry)
{
//*-*-*-*-*-*-*-*-*Process this tree executing the code in selector*-*-*-*-*
//*-* ================================================
//
// The TSelector class has the following member functions:
//
// void TSelector::Begin(). This function is called before looping on the
// events in the Tree. The user can create his histograms in this function.
//
// Bool_t TSelector::Notify(). This function is called at the first entry
// of a new file in a chain.
//
// Bool_t TSelector::ProcessCut(Int_t entry). This function is called
// before processing entry. It is the user's responsability to read
// the corresponding entry in memory (may be just a partial read).
// The function returns kTRUE if the entry must be processed,
// kFALSE otherwise.
//
// void TSelector::ProcessFill(Int_t entry). This function is called for
// all selected events. User fills histograms in this function.
//
// void TSelector::Terminate(). This function is called at the end of
// the loop on all events.
//
// If the Tree (Chain) has an associated EventList, the loop is on the nentries
// of the EventList, starting at firstentry, otherwise the loop is on the
// specified Tree entries.
selector->SetOption(option);
selector->Begin(fTree); //<===call user initialisation function
//Create a timer to get control in the entry loop(s)
TProcessEventTimer *timer = 0;
Int_t interval = fTree->GetTimerInterval();
if (!gROOT->IsBatch() && !gProofServ && interval)
timer = new TProcessEventTimer(interval);
//loop on entries (elist or all entries)
Int_t treeNumber = -1;
Long_t entry, entryNumber;
fSelectedRows = 0;
Int_t nent = Int_t(fTree->GetEntries());
TEventList *elist = fTree->GetEventList();
if (elist) nent = elist->GetN();
Int_t lastentry = firstentry + nentries -1;
if (lastentry > nent) {
lastentry = nent -1;
nentries = lastentry - firstentry + 1;
}
for (entry=firstentry;entry<firstentry+nentries;entry++) {
if (timer && timer->ProcessEvents()) break;
if (gROOT->IsInterrupted()) break;
if (elist) entryNumber = fTree->LoadTree(elist->GetEntry(entry));
else entryNumber = fTree->LoadTree(entry);
if (fTree->GetTreeNumber() != treeNumber) {
treeNumber = fTree->GetTreeNumber();
selector->Notify();
}
if (selector->ProcessCut (entryNumber))
selector->ProcessFill(entryNumber); //<==call user analysis function
}
selector->Terminate(); //<==call user termination function
return fSelectedRows;
}
//______________________________________________________________________________
Int_t TTreePlayer::Scan(const char *varexp, const char *selection, Option_t *,
Int_t nentries, Int_t firstentry)
{
// Loop on Tree and print entries passing selection. If varexp is 0 (or "")
// then print only first 8 columns. If varexp = "*" print all columns.
// Otherwise a columns selection can be made using "var1:var2:var3".
TTreeFormula *select, **var;
TString *cnames;
TString onerow;
Int_t entry,entryNumber,i,nch;
Int_t *index = 0;
Int_t ncols = 8; // by default first 8 columns are printed only
TObjArray *leaves = fTree->GetListOfLeaves();
Int_t nleaves = leaves->GetEntriesFast();
if (nleaves < ncols) ncols = nleaves;
nch = varexp ? strlen(varexp) : 0;
Int_t lastentry = firstentry + nentries -1;
if (lastentry > fTree->GetEntries()-1) {
lastentry = (Int_t)fTree->GetEntries() -1;
nentries = lastentry - firstentry + 1;
}
//*-*- Compile selection expression if there is one
select = 0;
if (strlen(selection)) {
select = new TTreeFormula("Selection",selection,fTree);
if (!select) return -1;
if (!select->GetNdim()) { delete select; return -1; }
}
//*-*- if varexp is empty, take first 8 columns by default
int allvar = 0;
if (!strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
if (nch == 0 || allvar) {
cnames = new TString[ncols];
for (i=0;i<ncols;i++) {
cnames[i] = ((TLeaf*)leaves->At(i))->GetName();
}
//*-*- otherwise select only the specified columns
} else {
ncols = 1;
onerow = varexp;
for (i=0;i<onerow.Length();i++) if (onerow[i] == ':') ncols++;
cnames = new TString[ncols];
index = new Int_t[ncols+1];
MakeIndex(onerow,index);
for (i=0;i<ncols;i++) {
cnames[i] = GetNameByIndex(onerow,index,i);
}
}
var = new TTreeFormula* [ncols];
//*-*- Create the TreeFormula objects corresponding to each column
for (i=0;i<ncols;i++) {
var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
}
//*-*- Print header
onerow = "***********";
for (i=0;i<ncols;i++) {
onerow += Form("*%11.11s",var[i]->PrintValue(-2));
}
printf("%s*n",onerow.Data());
onerow = "* Row ";
for (i=0;i<ncols;i++) {
onerow += Form("* %9.9s ",var[i]->PrintValue(-1));
}
printf("%s*n",onerow.Data());
onerow = "***********";
for (i=0;i<ncols;i++) {
onerow += Form("*%11.11s",var[i]->PrintValue(-2));
}
printf("%s*n",onerow.Data());
//*-*- loop on all selected entries
fSelectedRows = 0;
for (entry=firstentry;entry<firstentry+nentries;entry++) {
entryNumber = fTree->GetEntryNumber(entry);
if (entryNumber < 0) break;
fTree->LoadTree(entryNumber);
if (select) {
select->GetNdata();
if (select->EvalInstance(0) == 0) continue;
}
onerow = Form("* %8d ",entryNumber);
for (i=0;i<ncols;i++) {
onerow += Form("* %9.9s ",var[i]->PrintValue(0));
}
fSelectedRows++;
printf("%s*n",onerow.Data());
if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
if (fSelectedRows%fTree->GetScanField() == 0) {
fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
int answer, readch;
readch = getchar();
answer = readch;
while (readch != 'n' && readch != EOF) readch = getchar();
if (answer == 'q' || answer == 'Q') break;
}
}
}
onerow = "***********";
for (i=0;i<ncols;i++) {
onerow += Form("*%11.11s",var[i]->PrintValue(-2));
}
printf("%s*n",onerow.Data());
if (select) Printf("==> %d selected %s", fSelectedRows,
fSelectedRows == 1 ? "entry" : "entries");
//*-*- delete temporary objects
delete select;
for (i=0;i<ncols;i++) {
delete var[i];
}
delete [] var;
delete [] cnames;
delete [] index;
return fSelectedRows;
}
//______________________________________________________________________________
TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
Option_t *, Int_t nentries, Int_t firstentry)
{
// Loop on Tree and return TSQLResult object containing entries passing
// selection. If varexp is 0 (or "") then print only first 8 columns.
// If varexp = "*" print all columns. Otherwise a columns selection can
// be made using "var1:var2:var3". In case of error 0 is returned otherwise
// a TSQLResult object which must be deleted by the user.
TTreeFormula *select, **var;
TString *cnames;
TString onerow;
Int_t entry,entryNumber,i,nch;
Int_t *index = 0;
Int_t ncols = 8; // by default first 8 columns are printed only
TObjArray *leaves = fTree->GetListOfLeaves();
Int_t nleaves = leaves->GetEntriesFast();
if (nleaves < ncols) ncols = nleaves;
nch = varexp ? strlen(varexp) : 0;
Int_t lastentry = firstentry + nentries -1;
if (lastentry > fTree->GetEntries()-1) {
lastentry = (Int_t)fTree->GetEntries() -1;
nentries = lastentry - firstentry + 1;
}
// compile selection expression if there is one
select = 0;
if (strlen(selection)) {
select = new TTreeFormula("Selection",selection,fTree);
if (!select) return 0;
if (!select->GetNdim()) { delete select; return 0; }
}
// if varexp is empty, take first 8 columns by default
int allvar = 0;
if (!strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
if (nch == 0 || allvar) {
cnames = new TString[ncols];
for (i=0;i<ncols;i++) {
cnames[i] = ((TLeaf*)leaves->At(i))->GetName();
}
} else {
// otherwise select only the specified columns
ncols = 1;
onerow = varexp;
for (i=0;i<onerow.Length();i++) if (onerow[i] == ':') ncols++;
cnames = new TString[ncols];
index = new Int_t[ncols+1];
MakeIndex(onerow,index);
for (i=0;i<ncols;i++) {
cnames[i] = GetNameByIndex(onerow,index,i);
}
}
var = new TTreeFormula* [ncols];
// create the TreeFormula objects corresponding to each column
for (i=0;i<ncols;i++) {
var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
}
// fill header info into result object
TTreeResult *res = new TTreeResult(ncols);
for (i = 0; i < ncols; i++) {
res->AddField(i, var[i]->PrintValue(-1));
}
// loop on all selected entries
fSelectedRows = 0;
for (entry=firstentry;entry<firstentry+nentries;entry++) {
entryNumber = fTree->GetEntryNumber(entry);
if (entryNumber < 0) break;
fTree->LoadTree(entryNumber);
if (select) {
select->GetNdata();
if (select->EvalInstance(0) == 0) continue;
}
TTreeRow *row = new TTreeRow(ncols);
for (i=0;i<ncols;i++) {
row->AddField(i, var[i]->PrintValue(0));
}
res->AddRow(row);
fSelectedRows++;
}
// delete temporary objects
delete select;
for (i=0;i<ncols;i++) {
delete var[i];
}
delete [] var;
delete [] cnames;
delete [] index;
return res;
}
//_______________________________________________________________________
void TTreePlayer::SetEstimate(Int_t )
{
//*-*-*-*-*-*-*-*-*Set number of entries to estimate variable limits*-*-*-*
//*-* ================================================
//
delete [] fV1; fV1 = 0;
delete [] fV2; fV2 = 0;
delete [] fV3; fV3 = 0;
delete [] fW; fW = 0;
}
//_______________________________________________________________________
void TTreePlayer::SetPacketSize(Int_t size)
{
//*-*-*-*-*-*-*-*-*Set number of entries per packet for parallel root*-*-*-*-*
//*-* =================================================
fPacketSize = size;
}
//_______________________________________________________________________
void TTreePlayer::StartViewer(Int_t ww, Int_t wh)
{
//*-*-*-*-*-*-*-*-*Start the TTreeViewer on this TTree*-*-*-*-*-*-*-*-*-*
//*-* ===================================
//
// ww is the width of the canvas in pixels
// wh is the height of the canvas in pixels
gROOT->LoadClass("TTreeViewer","TreeViewer");
gROOT->ProcessLine(Form("new TTreeViewer("%s","TreeViewer",%d,%d);",fTree->GetName(),ww,wh));
}
//______________________________________________________________________________
void TTreePlayer::TakeAction(Int_t nfill, Int_t &npoints, Int_t &action, TObject *obj, Option_t *option)
{
//*-*-*-*-*-*Execute action for object obj nfill times*-*-*-*-*-*-*-*-*-*
//*-* =========================================
Int_t i;
if (action == 1) ((TH1*)obj)->FillN(nfill,fV1,fW);
else if (action == 2) {
TH2 *h2 = (TH2*)obj;
for(i=0;i<nfill;i++) h2->Fill(fV2[i],fV1[i],fW[i]);
}
else if (action == 4) ((TProfile*)obj)->FillN(nfill,fV2,fV1,fW);
else if (action == 5) {
TEventList *elist = (TEventList*)obj;
Int_t enumb = fTree->GetChainOffset() + fTree->GetReadEntry();
if (elist->GetIndex(enumb) < 0) elist->Enter(enumb);
}
else if (action == 12) {
TPolyMarker *pm = new TPolyMarker(nfill);
pm->SetMarkerStyle(fTree->GetMarkerStyle());
pm->SetMarkerColor(fTree->GetMarkerColor());
pm->SetMarkerSize(fTree->GetMarkerSize());
Float_t *x = pm->GetX();
Float_t *y = pm->GetY();
Double_t u, v;
Double_t umin = gPad->GetUxmin();
Double_t umax = gPad->GetUxmax();
Double_t vmin = gPad->GetUymin();
Double_t vmax = gPad->GetUymax();
for (i=0;i<nfill;i++) {
u = gPad->XtoPad(fV2[i]);
v = gPad->YtoPad(fV1[i]);
if (u < umin) u = umin;
if (u > umax) u = umax;
if (v < vmin) v = vmin;
if (v > vmax) v = vmax;
x[i] = u;
y[i] = v;
}
pm->Draw();
TH2 *h2 = (TH2*)obj;
for(i=0;i<nfill;i++) h2->Fill(fV2[i],fV1[i],fW[i]);
}
//----------------------------------------------------------
else if (action == 3) {
TH3 *h3 =(TH3*)obj;
for(i=0;i<nfill;i++) h3->Fill(fV3[i],fV2[i],fV1[i],fW[i]);
}
else if (action == 13) {
TPolyMarker3D *pm3d = new TPolyMarker3D(nfill);
pm3d->SetMarkerStyle(fTree->GetMarkerStyle());
pm3d->SetMarkerColor(fTree->GetMarkerColor());
pm3d->SetMarkerSize(fTree->GetMarkerSize());
for (i=0;i<nfill;i++) { pm3d->SetPoint(i,fV3[i],fV2[i],fV1[i]);}
pm3d->Draw();
TH3 *h3 =(TH3*)obj;
for(i=0;i<nfill;i++) h3->Fill(fV3[i],fV2[i],fV1[i],fW[i]);
}
else if (action < 0) {
action = -action;
TakeEstimate(nfill,npoints,action,obj,option);
}
//*-* Do we need to update screen?
npoints += nfill;
if (!fTree->GetUpdate()) return;
if (npoints > fDraw+fTree->GetUpdate()) {
if (fDraw) gPad->Modified();
else obj->Draw(option);
gPad->Update();
fDraw = npoints;
}
}
//______________________________________________________________________________
void TTreePlayer::TakeEstimate(Int_t nfill, Int_t &, Int_t action, TObject *obj, Option_t *option)
{
//*-*-*-*-*-*Estimate limits for 1-D, 2-D or 3-D objects*-*-*-*-*-*-*-*-*-*
//*-* ===========================================
Int_t i;
Double_t rmin[3],rmax[3];
fVmin[0] = fVmin[1] = fVmin[2] = FLT_MAX; //in float.h
fVmax[0] = fVmax[1] = fVmax[2] = -fVmin[0];
//__________________________1-D histogram_______________________
if (action == 1) {
for (i=0;i<nfill;i++) {
if (fVmin[0] > fV1[i]) fVmin[0] = fV1[i];
if (fVmax[0] < fV1[i]) fVmax[0] = fV1[i];
}
Int_t nchans = fNbins[0];
if (fVmin[0] >= fVmax[0]) { fVmin[0] -= 1; fVmax[0] += 1;}
FindGoodLimits(nchans,fNbins[0],fVmin[0],fVmax[0]);
// When a PROOF client ask master for limits
if (gProofServ) {
if (gProofServ->GetLogLevel() > 2)
printf("have limits: (nfill=%d) %d, %f, %fn", nfill, fNbins[0], fVmin[0], fVmax[0]);
gProofServ->GetLimits(1, nfill, fNbins, fVmin, fVmax);
if (gProofServ->GetLogLevel() > 2)
printf("got limits: (nfill=%d) %d, %f, %fn", nfill, fNbins[0], fVmin[0], fVmax[0]);
}
TH1 *h1 = (TH1*)obj;
h1->SetBins(fNbins[0],fVmin[0],fVmax[0]);
h1->FillN(nfill, fV1, fW);
fHistogram = h1;
//__________________________2-D histogram_______________________
} else if (action == 2) {
for (i=0;i<nfill;i++) {
if (fVmin[0] > fV1[i]) fVmin[0] = fV1[i];
if (fVmax[0] < fV1[i]) fVmax[0] = fV1[i];
if (fVmin[1] > fV2[i]) fVmin[1] = fV2[i];
if (fVmax[1] < fV2[i]) fVmax[1] = fV2[i];
}
Int_t nchans = fNbins[0];
if (fVmin[0] >= fVmax[0]) { fVmin[0] -= 1; fVmax[0] += 1;}
FindGoodLimits(nchans,fNbins[0],fVmin[0],fVmax[0]);
if (fVmin[1] >= fVmax[1]) { fVmin[1] -= 1; fVmax[1] += 1;}
FindGoodLimits(nchans,fNbins[1],fVmin[1],fVmax[1]);
TH2 *h2 = (TH2*)obj;
h2->SetBins(fNbins[1],fVmin[1],fVmax[1],fNbins[0],fVmin[0],fVmax[0]);
for(i=0;i<nfill;i++) h2->Fill(fV2[i],fV1[i],fW[i]);
fHistogram = h2;
//__________________________Profile histogram_______________________
} else if (action == 4) {
for (i=0;i<nfill;i++) {
if (fVmin[0] > fV1[i]) fVmin[0] = fV1[i];
if (fVmax[0] < fV1[i]) fVmax[0] = fV1[i];
if (fVmin[1] > fV2[i]) fVmin[1] = fV2[i];
if (fVmax[1] < fV2[i]) fVmax[1] = fV2[i];
}
Int_t nchans = fNbins[1];
if (fVmin[1] >= fVmax[1]) { fVmin[1] -= 1; fVmax[1] += 1;}
FindGoodLimits(nchans,fNbins[1],fVmin[1],fVmax[1]);
TProfile *hp = (TProfile*)obj;
hp->SetBins(fNbins[1],fVmin[1],fVmax[1]);
hp->FillN(nfill, fV2, fV1, fW);
fHistogram = hp;
//__________________________2D scatter plot_______________________
} else if (action == 12) {
for (i=0;i<nfill;i++) {
if (fVmin[0] > fV1[i]) fVmin[0] = fV1[i];
if (fVmax[0] < fV1[i]) fVmax[0] = fV1[i];
if (fVmin[1] > fV2[i]) fVmin[1] = fV2[i];
if (fVmax[1] < fV2[i]) fVmax[1] = fV2[i];
}
Int_t nchans = fNbins[0];
if (fVmin[0] >= fVmax[0]) { fVmin[0] -= 1; fVmax[0] += 1;}
FindGoodLimits(nchans,fNbins[0],fVmin[0],fVmax[0]);
if (fVmin[1] >= fVmax[1]) { fVmin[1] -= 1; fVmax[1] += 1;}
FindGoodLimits(nchans,fNbins[1],fVmin[1],fVmax[1]);
TH2 *h2 = (TH2*)obj;
h2->SetBins(fNbins[1],fVmin[1],fVmax[1],fNbins[0],fVmin[0],fVmax[0]);
if (!strstr(option,"same") && !strstr(option,"goff")) {
h2->DrawCopy(option);
gPad->Update();
}
TPolyMarker *pm = new TPolyMarker(nfill);
pm->SetMarkerStyle(fTree->GetMarkerStyle());
pm->SetMarkerColor(fTree->GetMarkerColor());
pm->SetMarkerSize(fTree->GetMarkerSize());
Float_t *x = pm->GetX();
Float_t *y = pm->GetY();
Double_t u, v;
Double_t umin = gPad->GetUxmin();
Double_t umax = gPad->GetUxmax();
Double_t vmin = gPad->GetUymin();
Double_t vmax = gPad->GetUymax();
for (i=0;i<nfill;i++) {
u = gPad->XtoPad(fV2[i]);
v = gPad->YtoPad(fV1[i]);
if (u < umin) u = umin;
if (u > umax) u = umax;
if (v < vmin) v = vmin;
if (v > vmax) v = vmax;
x[i] = u;
y[i] = v;
}
if (!fDraw && !strstr(option,"goff")) pm->Draw();
if (!h2->TestBit(kCanDelete)) {
for (i=0;i<nfill;i++) h2->Fill(fV2[i],fV1[i],fW[i]);
}
fHistogram = h2;
//__________________________3D scatter plot_______________________
} else if (action == 3 || action == 13) {
for (i=0;i<nfill;i++) {
if (fVmin[0] > fV1[i]) fVmin[0] = fV1[i];
if (fVmax[0] < fV1[i]) fVmax[0] = fV1[i];
if (fVmin[1] > fV2[i]) fVmin[1] = fV2[i];
if (fVmax[1] < fV2[i]) fVmax[1] = fV2[i];
if (fVmin[2] > fV3[i]) fVmin[2] = fV3[i];
if (fVmax[2] < fV3[i]) fVmax[2] = fV3[i];
}
Int_t nchans = fNbins[0];
if (fVmin[0] >= fVmax[0]) { fVmin[0] -= 1; fVmax[0] += 1;}
FindGoodLimits(nchans,fNbins[0],fVmin[0],fVmax[0]);
if (fVmin[1] >= fVmax[1]) { fVmin[1] -= 1; fVmax[1] += 1;}
FindGoodLimits(nchans,fNbins[1],fVmin[1],fVmax[1]);
if (fVmin[2] >= fVmax[2]) { fVmin[2] -= 1; fVmax[2] += 1;}
FindGoodLimits(nchans,fNbins[2],fVmin[2],fVmax[2]);
TH3 *h3 = (TH3*)obj;
h3->SetBins(fNbins[2],fVmin[2],fVmax[2],fNbins[1],fVmin[1],fVmax[1],fNbins[0],fVmin[0],fVmax[0]);
if (!h3->TestBit(kCanDelete)) {
for (i=0;i<nfill;i++) h3->Fill(fV3[i],fV2[i],fV1[i],1.);
}
fHistogram = h3;
if (action == 3) return;
if (!strstr(option,"same") && !strstr(option,"goff")) {
h3->DrawCopy(option);
gPad->Update();
} else {
rmin[0] = fVmin[2]; rmin[1] = fVmin[1]; rmin[2] = fVmin[0];
rmax[0] = fVmax[2]; rmax[1] = fVmax[1]; rmax[2] = fVmax[0];
gPad->Clear();
gPad->Range(-1,-1,1,1);
new TView(rmin,rmax,1);
}
TPolyMarker3D *pm3d = new TPolyMarker3D(nfill);
pm3d->SetMarkerStyle(fTree->GetMarkerStyle());
pm3d->SetMarkerColor(fTree->GetMarkerColor());
pm3d->SetMarkerSize(fTree->GetMarkerSize());
for (i=0;i<nfill;i++) { pm3d->SetPoint(i,fV3[i],fV2[i],fV1[i]);}
if (!fDraw && !strstr(option,"goff")) pm3d->Draw();
}
}
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.