PROOF crashing upon drawing canvas

Hi guys,

First time posting on the forum, so please let me know if I do anything incorrect.

I am currently attempting to get my TSelector framework script to run successfully using PROOF (PROOF lite for now) but am encountering issues. My script runs successfully on my desktop by running:

TChain ch("T");
ch.Add("/path/to/ROOTfile");
ch.Process("path/to/script.C+");

where the script outputs some lines to the command line, but no new canvases are created without specifying an option. However when I try to run the script using PROOF (following the directions on ROOT’s website):

TChain ch("T");
ch.Add("/path/to/ROOTfile");
TProof *p = TProof::Open("lite://");
ch.SetProof(p);
ch.Process("/path/to/script.C+");

the script opens a canvas and attempts to fill it, at which point there is a segmentation violation and the script crashes. The PROOF Query Progress GUI opens on the screen and seems to indicate that all 1959653 events were successfully Processed, which makes sense since the script apparently fails in the Terminate step where canvases are created.

Unfortunately I could not find much support online about PROOF issues. I am running ROOT 6.10/02.

Thanks for your help.

Dear rambrose,

Can you

  1. post the content of script or explain what it does?

  2. post what you get on the screen before the crash?

  3. post, perhaps as a tarball, the logs from the proof workers you should find under

    ~/.proof/something-related-to-your-dir/last-lite-session
    

where ‘something-related-to-your-dir’ is a name derived from the directory where you run.

G Ganis

ganis,

After playing around with my script I found where the issue was. I structured my histograms in an array for ease of filling them over a loop i.e.

TH1F *fhistogram[4];

which is fine if I process without using PROOF, but using PROOF these histograms simply wouldn’t be accessed. By changing to four explicit histograms,

TH1F *fhistogram1;
TH1F *fhistogram2;
TH1F *fhistogram3;
TH1F *fhistogram4;

the script runs successfully. I can see how it may be dangerous to allow arrays of histograms when using PROOF, I’ll just change my code accordingly.

Dear rambrose,

Not sure to understand what the problem was.
If you added the histograms in the selector output list it should have worked.
I cannot say more without seeing the code.
However, it is good that you have found a solution.

G Ganis

The issue was that retrieving an array of histograms from the selector output list is more complicated than I thought. My original TSelector code was:

TSelector_test.h

#ifndef TSelector_test_h
#define TSelector_test_h

#include "TROOT.h"
#include "TChain.h"
#include "TFile.h"
#include "TSelector.h"
#include "TProofServ.h"
#include "TH1.h"
#include <iostream>

const Int_t kMaxfParticles = 1293;

class TSelector_test : public TSelector {
public :
   TTree          *fChain;   //!pointer to the analyzed TTree or TChain

   // Declaration of leaf types
   TH1         *fPosX; // X position of the particles
   TH1F        fIndexHis[4];

   // Declaration of leaf types
   Int_t        Ndata_P_tr_p;
   Double_t     P_tr_x[kMaxfParticles];       //[fNParticles]
   Double_t     P_gtr_dp[kMaxfParticles];   //[fNParticles]
   Double_t     P_hgcer_npe[4];

   // List of branches
   TBranch     *b_Ndata_P_tr_p;
   TBranch     *b_P_tr_x;
   TBranch     *b_P_gtr_dp;
   TBranch     *b_P_hgcer_npe;

 TSelector_test(TTree * = 0): fChain(0), fPosX(0), fIndexHis{0,0,0,0} {  }
   virtual ~TSelector_test() { }
   virtual Int_t   Version() const { return 2; }
   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    Terminate();

   ClassDef(TSelector_test,0);
};

#endif

#ifdef TSelector_test_cxx
void TSelector_test::Init(TTree *tree)
{
   // Set branch addresses and branch pointers
   if (!tree) return;
   fChain = tree;
   fChain->SetMakeClass(1);

   // Connect the branches with their member variables.
   tree->SetBranchAddress("Ndata.P.tr.p", &Ndata_P_tr_p, &b_Ndata_P_tr_p);
   tree->SetBranchAddress("P.tr.x", P_tr_x, &b_P_tr_x);
   tree->SetBranchAddress("P.gtr.dp", &P_gtr_dp, &b_P_gtr_dp);
   tree->SetBranchAddress("P.hgcer.npe", &P_hgcer_npe, &b_P_hgcer_npe);
}

Bool_t TSelector_test::Notify()
{
   return kTRUE;
}

#endif // #ifdef TSelector_test_cxx

TSelector_test.C

#define TSelector_test_cxx

#include "TSelector_test.h"
#include "TH1.h"
#include "TStyle.h"


void TSelector_test::SlaveBegin(TTree * /*tree*/)
{
   TString option = GetOption();

   fPosX = new TH1F("hPosX", "Position in X", 20, -5, 5);
   // enable bin errors:
   fPosX->Sumw2();
   // Add to output list (needed for PROOF)
   GetOutputList()->Add(fPosX);
   fIndexHis[0] = new TH1F("IndexHis1", "TEST OF INDEX", 20, -5, 5);
   fIndexHis[1] = new TH1F("IndexHis2", "TEST OF INDEX", 20, -5, 5);
   fIndexHis[2] = new TH1F("IndexHis3", "TEST OF INDEX", 20, -5, 5);
   fIndexHis[3] = new TH1F("IndexHis4", "TEST OF INDEX", 20, -5, 5);
			       
   GetOutputList()->Add(fIndexHis[0]);
   GetOutputList()->Add(fIndexHis[1]);
   GetOutputList()->Add(fIndexHis[2]);
   GetOutputList()->Add(fIndexHis[3]);
}

Bool_t TSelector_test::Process(Long64_t entry)
{
   // We only need the number of particles...
  b_Ndata_P_tr_p->GetEntry(entry);
  // ... and their position in X...
  b_P_tr_x->GetEntry(entry);
  // ... and their momentum
  b_P_gtr_dp->GetEntry(entry);
  //TEST OF INDEX HISTOGRAM
  b_P_hgcer_npe->GetEntry(entry);

  for (int iParticle = 0; iParticle < Ndata_P_tr_p; ++iParticle) {
    if (P_gtr_dp[iParticle] < 40.0)
      {
	fPosX->Fill(P_tr_x[iParticle]);
	for (Int_t ipmt = 0; ipmt < 4; ipmt++)
	  {
	    fIndexHis[ipmt]->Fill(P_tr_x[iParticle]);
	    cout << fIndexHis[ipmt]->GetEntries() << endl;
	  }
      }
  }
  return kTRUE;
}


void TSelector_test::Terminate()
{
  // Fit the histogram:
  fPosX->Fit("pol2");

   // and draw it:
   fPosX->Draw();

   cout << fIndexHis[0]->GetEntries() << endl;
}

The cout statement in the Process section accessing fIndexHis[] would work as intended, I could see it’s output on each worker’s .log file. However when I try to cout in the Terminate section, the cout would cause a segmentation fault, due to that histogram not actually existing. Clearly the histograms were not added to the output list properly. The solution was to change how I define the array of histograms:

new TSelector_test.h

#ifndef TSelector_test_h
#define TSelector_test_h

#include "TROOT.h"
#include "TChain.h"
#include "TFile.h"
#include "TSelector.h"
#include "TProofServ.h"
#include "TH1.h"
#include <iostream>

const Int_t kMaxfParticles = 1293;

class TSelector_test : public TSelector {
public :
   TTree        *fChain;   //!pointer to the analyzed TTree or TChain

   // Declaration of leaf types
   TH1          *fPosX; // X position of the particles
   TH1F         **fIndexHis;

   // Declaration of leaf types
   Int_t        Ndata_P_tr_p;
   Double_t     P_tr_x[kMaxfParticles];       //[fNParticles]
   Double_t     P_gtr_dp[kMaxfParticles];   //[fNParticles]
   Double_t     P_hgcer_npe[4];

   // List of branches
   TBranch     *b_Ndata_P_tr_p;
   TBranch     *b_P_tr_x;
   TBranch     *b_P_gtr_dp;
   TBranch     *b_P_hgcer_npe;

   TSelector_test(TTree * = 0): fChain(0) {fPosX = 0, fIndexHis = 0; }
   virtual ~TSelector_test() { }
   virtual Int_t   Version() const { return 2; }
   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    Terminate();

   ClassDef(TSelector_test,0);
};

#endif

#ifdef TSelector_test_cxx
void TSelector_test::Init(TTree *tree)
{
   // Set branch addresses and branch pointers
   if (!tree) return;
   fChain = tree;
   // To use SetBranchAddress() with simple types (e.g. double, int)
   // instead of objects (e.g. std::vector<Particle>).
   fChain->SetMakeClass(1);

   // Connect the branches with their member variables.
   tree->SetBranchAddress("Ndata.P.tr.p", &Ndata_P_tr_p, &b_Ndata_P_tr_p);
   tree->SetBranchAddress("P.tr.x", P_tr_x, &b_P_tr_x);
   tree->SetBranchAddress("P.gtr.dp", &P_gtr_dp, &b_P_gtr_dp);
   tree->SetBranchAddress("P.hgcer.npe", &P_hgcer_npe, &b_P_hgcer_npe);
}

Bool_t TSelector_test::Notify()
{
   return kTRUE;
}

#endif // #ifdef TSelector_test_cxx

TSelector_test.C

#define TSelector_test_cxx
#include "TSelector_test.h"
#include "TH1.h"
#include "TStyle.h"


void TSelector_test::SlaveBegin(TTree * /*tree*/)
{
   TString option = GetOption();

   fPosX = new TH1F("hPosX", "Position in X", 20, -5, 5);
   // enable bin errors:
   fPosX->Sumw2();
   // Add to output list (needed for PROOF)
   GetOutputList()->Add(fPosX);

   fIndexHis = new TH1F*[4];
   fIndexHis[0] = new TH1F("IndexHis1", "TEST OF INDEX", 20, -5, 5);
   fIndexHis[1] = new TH1F("IndexHis2", "TEST OF INDEX", 20, -5, 5);
   fIndexHis[2] = new TH1F("IndexHis3", "TEST OF INDEX", 20, -5, 5);
   fIndexHis[3] = new TH1F("IndexHis4", "TEST OF INDEX", 20, -5, 5);
 
   GetOutputList()->Add(fIndexHis[0]);
   GetOutputList()->Add(fIndexHis[1]);
   GetOutputList()->Add(fIndexHis[2]);
   GetOutputList()->Add(fIndexHis[3]);

}

Bool_t TSelector_test::Process(Long64_t entry)
{
   // We only need the number of particles...
  b_Ndata_P_tr_p->GetEntry(entry);
  // ... and their position in X...
  b_P_tr_x->GetEntry(entry);
  // ... and their momentum
  b_P_gtr_dp->GetEntry(entry);
  //TEST OF INDEX HISTOGRAM
  b_P_hgcer_npe->GetEntry(entry);

  // *** 2. *** Do the actual analysis
  for (int iParticle = 0; iParticle < Ndata_P_tr_p; ++iParticle) {
    if (P_gtr_dp[iParticle] < 40.0)
      {
	fPosX->Fill(P_tr_x[iParticle]);
	fIndexHis[0]->Fill(P_tr_x[iParticle]);
      }
  }


   return kTRUE;
}

void TSelector_test::Terminate()
{
  // Fit the histogram:
  fPosX->Fit("pol2");

   // and draw it:
   fPosX->Draw();

   TH1F* ccc[4]; 

   ccc[0] = dynamic_cast<TH1F*> (GetOutputList()->FindObject("IndexHis1"));
   cout << "WHAT: " << ccc[0]->GetEntries() << endl;
}

Where using this method I can access the histogram information on the client. It is a little annoying to have to change all the histogram names, but at least I can have arrays of histograms in PROOF this way.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.