Root Macro stops compiling

Hello!

I have a macro that takes a File A with X graphs inside of it, divides the graphs into groups of 10 and creates a graph that is the average of those 10 graphs, and then creates a new File B with X/10 graphs inside of it. I set it on a loop to go over 45 files, but every time I compile it the macro stops running midway through the 5th file. When I remove the code that takes the data from the graphs and averages and creates new graphs, the code works and prints out numbers from 0 to 44. Is there some sort of limit to the number of files I can create or something?

Hi Stefano,
and welcome to the ROOT forum!

ROOT does not impose limits on the number of open files, although your operating system might (but even then, the maximum number of open file descriptors is typically much higher than 50).

My best guess would be that there is a bug in the macro. We could help figure it out if you could share a simple recipe (smallest amount of code that reproduces the problem, smallest amount of data required to run the code correctly) to reproduce the problem.

Cheers,
Enrico

Hi Enrico!
Thanks for the help! The file is too large to upload here, so this is a link to my google drive where it is stored: https://drive.google.com/file/d/121OcacqyD30xwsQJfr9kpz5SA435OCW_/view?usp=sharing

This is the code, I modified it to run over the same file multiple times. This should reproduce the problem, and stop after the 4th time.

This is the code:

void exampleaveraging(){

//Waveforms to average over
int avg_num = 10;

string channel[] = {“3”}

string filenames[] = {“examplewaveform.ch”}

int nfiles = (sizeof(filenames)/sizeof(filenames[0]));

cout<< "Looping over " << nfiles*2 << " files " << endl;

//Going over every file
for (int counting=0; counting<7; counting++){

cout << "Performing for the " << counting+1 << " time" <<  endl;

//Getting the file                                                                                                                                                            
TString filename;
filename = (filenames[0]+channel[0]+".traces.root").c_str;

//Opening our file                                                                                                                                                            
TFile *f = new TFile(filename, "read");
//Creating a new file                                                                                                                                                         
TFile *fout = new TFile((filenames[0]+channel[0]+counting+".10_averaged.root").c_str(), "recreate");

//Number of graphs we'll have                                                                                                                                                 
int point_num = 100;

//For every graph we will create                                                                                                                                              
for (int counter = 0; counter < point_num; counter ++){

  //Creating arrays for storing values                                                                                                                                        
  double ytemp[100002];
  double xtemp[100002];
  int graphpoints = 100002;

  //Setting all y values to 0                                                                                                                                                 
  memset(ytemp, 0, sizeof(ytemp));

  //For all the graphs that need to be averaged                                                                                                                               
  for (int subcounter = 0; subcounter < avg_num; subcounter ++){

    //Getting our graphs to be averaged      
    int currentgraphnumber = counter * avg_num + subcounter + 1;
    TGraph *g1;
    TString graphnumber;
    graphnumber.Form("%d",currentgraphnumber);
    g1 = (TGraph*)f->Get("graph"+graphnumber);

    //Performing the average                                                                                                                                                  
    for (int ip=0; ip<graphpoints; ip++){
      ytemp[ip] += g1->GetY()[ip]/avg_num;
    }

    //Getting our x-axis                                                                                                                                                      
    if(counter==0){
      for (int ip=0; ip<graphpoints; ip++){
        xtemp[ip] = g1->GetX()[ip];
      }
    }
  }

  //Making a graph for the averaged waveforms and writing it in the new file                                                                                                  
  TGraph *gtemp = new TGraph (graphpoints, xtemp, ytemp);
  fout->cd();
  gtemp->Write(Form("graph_%d", counter));
}
fout->Close();
f->Close();

}
}

(Not sure why it isn’t displaying properly, apologies for that!)

I have attempted moving

//Creating arrays for storing values
double ytemp[100002];
double xtemp[100002];
int graphpoints = 100002;

and

TGraph *g1;

outside of the loop, but the problem persists.

Managed to find a solution! deleted both TGraphs and files after having used them.

1 Like

Glad you found the problem!

It makes sense: if you do not delete/destruct the TFile, it remains open and you might indeed run out of available file descriptors. And anyway, memory leaks are bad :smiley:

Modern C++ guidelines recommend using std::unique_ptr to avoid these kind of problems. E.g. for TFile:

std::unique_ptr<TFile> f(TFile::Open(filename, ...));

Cheers,
Enrico

1 Like