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: