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
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