PROOF - Tree Example

Consider an example in which information is read from four branches of a tree, calculated two additional values are filled in histograms, and one of them is fitted. First we give the code in which this problem is solved without PROOF.

A preliminary macro in which four random variables are generated, and the tree is filled:

 void write_chain6 (std::string outputFileName ="myTree.root",unsigned int numDataPoints = 10000) {
 TTree myTree ("myTree","Example Tree");
 float px,py,value,temp,pres;
 myTree.Branch("px",&px,"px/F");
 myTree.Branch("py",&py,"py/F");
 myTree.Branch("Temperature",&temp,"Temperature/F");
 myTree.Branch("Pressure",&pres,"Pressure/F");

 for ( int i=0;i< numDataPoints;++i) {
 px=gRandom->Gaus(1.,2.);
 py=gRandom->Gaus(4.,2.);
 temp=gRandom->Uniform (250.,350.)+gRandom->Gaus(0.,0.3) ;
 pres=gRandom->Uniform (0.5,1.5) *gRandom->Gaus(1.,0.02) ;
 myTree.Fill();
 }

 TFile ofile (outputFileName.c_str( ),"RECREATE") ;
 myTree.Write();
 ofile.Close();
 }
			

Macro for reading the tree (not a parallel version):

#include "TFile.h"
#include "TNtuple.h"
#include < iostream >
#include "TTree.h"
#include "TChain.h"
void read_from_tree(){
TFile* f=new TFile("myTree.root");
TTree* treeData=(TTree*)f->Get("myTree");

float px,py,pt,temp,pres,value;
treeData->SetBranchAddress("px",&px);
treeData->SetBranchAddress("py",&py);
treeData->SetBranchAddress("Temperature",&temp);
treeData->SetBranchAddress("Pressure",&pres);

TH1F* h_px=new TH1F("px","px dixtribution",100,-6,14);
TH1F* h_py=new TH1F("py","py distribution",100,-6,14);
TH1F* h_pt=new TH1F("pt","Pt",100,-2,18);
TH1F* h_value=new TH1F("value","value",100,0.,2.5);
TH1F* h_temp=new TH1F("temp","temperature",100,200.,400.);
TH1F* h_pres=new TH1F("pres","pressure",100,-0.,2.);

Int_t nentries=(Int_t)treeData->GetEntries();
for(Int_t i=0;i < nentries;i++){
treeData->GetEntry(i);
h_px->Fill(py);
h_py->Fill(py);
pt=sqrt(px*px+py*py);
h_pt->Fill(pt);
h_temp->Fill(temp);
h_pres->Fill(pres);
value=pt/(10.*0.05*(temp-300.)-0.2*(pres-1.));
h_value->Fill(value);
}
   TCanvas* c=new TCanvas("c","title",20,20,1200,600);
    c->Divide(3,2);
    c->cd(1);
    h_px->Draw(); 
    c->cd(2);
    h_py->Draw();
    c->cd(3);   
    h_pt->Draw();
    c->cd(4);
    h_temp->Draw();   
    c->cd(5);
    h_pres->Draw();
    c->cd(6);
    h_value->Draw();
    h_value->Fit("landau");
}

We now turn to the parallel method of reading the tree. The TTree class implements the MakeSelector() method, which creates two files, Selector.h and SelectorTree.c, the so-called "skeleton" class or template to add. The following files show in black the instructions generated. automatically by the MakeSelector() method.

#ifndef SelectorTree_h
#define SelectorTree_h

#include < TROOT.h >
#include < TChain.h >
#include < TFile.h >
#include < TSelector.h >
class SelectorTree : public TSelector {
public :
   TTree          *fChain;   //pointer to the analyzed TTree tree or TChain chain

   // Leaf types ad
   Float_t         px;
   Float_t         py;
   
Float_t pt; Float_t value;
Float_t Temperature; Float_t Pressure; // Branch lifts TBranch *b_px; TBranch *b_py; TBranch *b_Temperature; //! TBranch *b_Pressure; //! SelectorTree(TTree * /*tree*/ =0) : fChain(0) { } virtual ~SelectorTree() { } virtual Int_t Version() const { return 2; } virtual void Begin(TTree *tree); virtual void SlaveBegin(TTree *tree); virtual void Init(TTree *tree); virtual Bool_t Notify(); virtual Bool_t Process(Long64_t entry); virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; } virtual void SetOption(const char *option) { fOption = option; } virtual void SetObject(TObject *obj) { fObject = obj; } virtual void SetInputList(TList *input) { fInput = input; } virtual TList *GetOutputList() const { return fOutput; } virtual void SlaveTerminate(); virtual void Terminate(); ClassDef(SelectorTree,1); }; #endif #ifdef SelectorTree_cxx void SelectorTree::Init(TTree *tree) { // The Init () function is called when the selector must initialize a new     // tree or chain. Usually, the addresses of the branches and pointers to them are set here.     // Usually there is no need to make changes to the generated code     // but if necessary, the program can be expanded by the user.     // Init () will be called many times when PROOF is running     // (once for each file processed).     // Set branch addresses and pointers to branches if (!tree) return; fChain = tree; fChain->SetMakeClass(1); fChain->SetBranchAddress("px",&px, &b_px); fChain->SetBranchAddress("py",&py,&b_py); fChain->SetBranchAddress("Temperature", &Temperature, &b_Temperature); fChain->SetBranchAddress("Pressure", &Pressure, &b_Pressure); } Bool_t SelectorTree::Notify() { // The Notify () function is called when a new file is opened. it // can occur either for a new TTree in TChain, or when a new TTree // starts when using PROOF. Usually there is no need to make changes. // into the generated code, but if necessary, the procedure can be extended with // user The return value is currently not used. return kTRUE; } #endif // #ifdef SelectorTree_cxx
#define SelectorTree_cxx
The following methods are defined in this file:
//    Begin (): called every time a loop starts on a tree,
//                convenient place to create your histograms.
//     SlaveBegin (): called after Begin (), when PROOF is called only on
//                  secondary server.
//      Process (): is called for each event, in this function you decide
//                  read and fill your histograms.
//     SlaveTerminate: called at the end of the tree processing cycle, if PROOF
//                   invoked on secondary servers only.
//      Terminate (): called at the end of the tree processing cycle
//                     convenient place to draw / fit histograms.
//
// To use this file, try the following commands for your Tree T:
//
// Root > T->Process("SelectorTree.C")
// Root > T->Process("SelectorTree.C","some options")
// Root > T->Process("SelectorTree.C+")
//

#include "SelectorTree.h"
#include < TH2.h >
#include < TStyle.h >
#include < TCanvas.h >
#include < iostream >
using namespace std;
UInt_t fNumberOfEvents; TDatime tBegin,tNow; TH1F *h_px,*h_py, *h_pt, *h_value,*h_temp,*h_pres;
void SelectorTree::Begin(TTree * /*tree*/) { TString option = GetOption(); tBegin.Set(); printf("*==* ------------- Begin of Job -------------"); tBegin.Print(); } void SelectorTree::SlaveBegin(TTree * /*tree*/) { TString option = GetOption(); h_px=new TH1F("px","px dixtribution",100,-6,14); h_py=new TH1F("py","py distribution",100,-6,14); h_pt=new TH1F("pt","Pt",100,-2,18); h_temp=new TH1F("temp","temperature",100,200.,400.); h_pres=new TH1F("pres","pressure",100,-0.,2.); h_value=new TH1F("value","value",100,0.,2.5); fOutput->AddAll(gDirectory->GetList()); } Bool_t SelectorTree::Process(Long64_t entry) { GetEntry(entry); ++fNumberOfEvents; h_px->Fill(px); h_py->Fill(py); pt=sqrt(px*px+py*py); h_pt->Fill(pt); h_temp->Fill(Temperature); h_pres->Fill(Pressure); value=pt/(10.*0.05*(Temperature-300.)-0.2*(Pressure-1.)); h_value->Fill(value); return kTRUE; } void SelectorTree::SlaveTerminate() { printf("\n *==* --------- End of Slave Job --------"); tNow.Set(); tNow.Print(); printf("Number of Events: %i, elapsed time: %i sec, rate: %g evts/sec\n", fNumberOfEvents, tNow.Convert()-tBegin.Convert(), float(fNumberOfEvents)/(tNow.Convert()-tBegin.Convert())); } void SelectorTree::Terminate() { TFile hfile("MySelector_Result.root","RECREATE","MuonResults"); fOutput->Write(); TCanvas* c=new TCanvas("c","title",20,20,1200,600); c->Divide(3,2); h_px=dynamic_cast<TH1F *>(fOutput->FindObject("px")); c->cd(1); h_px->Draw(); h_py=dynamic_cast<TH1F *>(fOutput->FindObject("py")); c->cd(2); h_py->Draw(); h_pt=dynamic_cast<TH1F *>(fOutput->FindObject("pt")); c->cd(3); h_pt->Draw(); h_temp=dynamic_cast<TH1F *>(fOutput->FindObject("temp")); c->cd(4); h_temp->Draw(); h_pres=dynamic_cast<TH1F *>(fOutput->FindObject("pres")); c->cd(5); h_pres->Draw(); h_value=dynamic_cast<TH1F *>(fOutput->FindObject("value")); c->cd(6); h_value->Draw(); h_value->Fit("landau"); tNow.Set(); printf("*==* -------- End of Job ------- "); tNow.Print(); }

Create a chain:

 root [0] TChain* ch = new TChain ("treeMy", "MyTree") 

Attaching the file to the root chain:

 root [1] ch-> Add ("treeMy.root") 

Open PROOF session:

 root [2] TProof * proof = TProof::Open ("lite://","workers=12") 

Turn on processing:

 root [3] ch-> SetProof() 

We process all the entries in this chain by calling functions in the SelectorTree file:

 root [4] ch-> Process ("SelectorTree.C++") 

Here is what you should see on your screens: