ROOT Version: 6.18/04
Platform: Ubuntu 18.04
Compiler: gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
Dear co-rooters,
I’m trying to perform a rather simple task: open a root file, read a TTree
, do some calculation and add a new TBranch
to the TTree
.
Things work fine in small size files (i.e. <5Gb)
I tried to run that code in a ~30Gb file but I can’t get it to execute. It returns a negative number of entries and then aborts without any errors.
I believe that his is due to the file size, but is it?
Oddly enough, opening the root file in an interactive root session and issuing Tree->GetEntries()
returns a reasonable number so I’m not convinced it’s that.
Any ideas?
Thanks in advance!
//Executing the macro
root [1] add_coincidences("runs_26068_26766.root.root", 500.)
Total entries found: -1747421737
10 20 30 40 50 60 70 80 90 100 %
---------|---------|---------|---------|---------|---------|---------|---------|---------|---------|
Real time 0:00:00, CP time 0.060
//Get the entries by manually opening the file
root [2] new TFile("runs_26068_26766.root.root")
(TFile *) 0x55bfadb69100
root [3] tree->GetEntries()
(long long) 2547545559
My code is the following
#include "TFile.h"
#include "TTree.h"
#include "TBranch.h"
#include "TSystem.h"
#include "TStopwatch.h"
#include <iostream>
using namespace std;
void add_coincidences(TString filename_in, float coincidence_cut){
//This is to time the execution
TStopwatch timer;
timer.Start();
//_____________________________________________________________________________________________________________________
//(0) Usefull variables
//(a) To read and add the new TBranch to the tree
double tof, tof0;
double dt_min;
int detn;
//(b) To calculate coincidences while looping over the tree
double tof_current = -1.e10;
double dt = 0.;
double dt_current = 0.;
int detn_current = 0;
int ii = 0;// For the nested loop over the tree
//(c) To store the entry/row when the coincidence is found; saves a loooot of time
float dt_min_pair_23 = 6.e6;
float dt_min_pair_67 = 6.e6;
int ii_pair_23 = -1;
int ii_pair_67 = -1;
//_____________________________________________________________________________________________________________________
//(1) Copy the root file, open it and get the branches
// (a) Copy the file - the new filename will end in .root.root - I will change it in the future
//TString new_filename_in = filename_out;
//cout << "Copying file " << filename_in.Data() << " to " << new_filename_in.Data() << endl;
//gSystem->Exec( TString::Format("cp %s %s", filename_in.Data(), new_filename_in.Data()) );
// (b) Open the copied file and get the DICER tree
TFile *f_root = TFile::Open(filename_in, "UPDATE");
TTree *t = (TTree*)f_root->Get("DICER");
// (c) Assign the branch addresses
t->SetBranchAddress("ntof0", &tof0);
t->SetBranchAddress("detn" , &detn);
t->SetBranchAddress("ntof" , &tof);
// (d) Define the new TBranch
TBranch *bdt = t->Branch("dt_min", &dt_min);
// (e) Get the TTree entries
int entries = t->GetEntries();
std::cout << "Total entries found: " << entries << std::endl;
//_____________________________________________________________________________________________________________________
// (2) Loop over the entries
//(a) These are for the progress bar
float j = entries/100.;
int n = 1;
n =1;
printf(" 10 20 30 40 50 60 70 80 90 100 %%\n");
printf(" ---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| \n");
// (b) Start looping
for (int i=0; i<entries; ++i){
if(i == 0) {cout << "|";}
if(i >= n*j) {cout << '|' << flush; n++;}// Progress indicator
t->GetEntry(i);
//Makes no sense to calculate coincidences when the T0 is bad
if(tof0<=0){
dt_min = -1.e10;
bdt->Fill();
continue;
}
//We care about coincidences only in the pairs 2/3 and 6/7
if(detn!=2 && detn!=3 && detn!=6 && detn!= 7){
dt_min = -detn*1.e10;
bdt->Fill();
continue;
}
//If the current event is in coincidence with a previous one, we don't need to re-calculate - 2/3 pair
if ( i==ii_pair_23 ){
ii_pair_23 = -1.;
dt_min = -dt_min_pair_23;
dt_min_pair_23 = -6.e6;
bdt->Fill();
continue;
}
//If the current event is in coincidence with a previous one, we don't need to re-calculate - 6/7 pair
if ( i==ii_pair_67 ){
ii_pair_67 = -1.;
dt_min = -dt_min_pair_67;
dt_min_pair_67 = -6.e6;
bdt->Fill();
continue;
}
// Look for coincidences in the 2/3 pair
if(detn==2 || detn==3){
dt = detn*1.e10; // Initialise dt with a huge value
detn_current = detn; // Store which detector we are currently looking at
tof_current = tof; // Store the tof of the current detector
//Let's start nest-looping from the next line onwards; I'm relying on my break conditions here
for( ii=i+1; ii<entries; ++ii){
t->GetEntry(ii);
// Applying a coincidence window/cut makes it run ~25% faster
if ( fabs(dt)>coincidence_cut && dt!=detn_current*1.e10 ){
ii_pair_23 = ii; //Grab the entry; I won't have to re-calculate coincidences in the other end
dt_min = 2.*coincidence_cut; //Just fill the TTree with a (maybe not so) meaningless
dt_min_pair_23 = dt_min; //Grab also the coincidence time
bdt->Fill();
break;
}
// If there's a new T0 stop
if( detn==200 ){
dt_min = dt;
bdt->Fill();
break;
}
//Don't waste time looking detectors in the other pair
if(detn!=2 && detn!=3){
continue;
}
//At last, calculate the time difference in the opposite end
if( detn!=detn_current ){
dt_current = tof_current-tof;
if ( fabs(dt_current) < fabs(dt) ){// |current| < |minimum|
dt = dt_current;
ii_pair_23 = ii;
dt_min_pair_23 = dt;
}
else{//It makes no sense to continue calculating if we no longer have a minimum dt
dt_min = dt;
bdt->Fill();
break;
}
}
}//_loop over the second loop over entries
}//_detn = 2 || 3
// Look for coincidences in the 6/7 pair
else if(detn==6 || detn==7){
dt = detn*1.e10;
detn_current = detn;//Store which detector we are looking at
tof_current = tof;
//Let's start nest-looping from the next line onwards; I'm relying on my break conditions here
for( ii=i+1; ii<entries; ++ii){
t->GetEntry(ii);
// Applying a coincidence window/cut makes it run ~25% faster
if ( fabs(dt)>coincidence_cut && dt!=detn_current*1.e10 ){
ii_pair_67 = ii; //Grab the entry; I won't have to re-calculate coincidences in the other end
dt_min = 2.*coincidence_cut; //Just fill the TTree with a (maybe not so) meaningless
dt_min_pair_67 = dt_min; //Grab also the coincidence time
bdt->Fill();
break;
}
// If there's a new T0 stop
if( detn==200 ){
dt_min = dt;
bdt->Fill();
break;
}
//Don't waste time looking detectors in the other pair
if(detn!=6 && detn!=7){
continue;
}
//At last, calculate the time difference in the opposite end
if( detn!=detn_current ){
dt_current = tof_current-tof;
if ( fabs(dt_current) < fabs(dt) ){// |current| < |minimum|
dt = dt_current;
ii_pair_67 = ii;
dt_min_pair_67 = dt;
}
else{//It makes no sense to continue calculating if we no longer have a minimum dt
dt_min = dt;
bdt->Fill();
break;
}
}
}//_loop over the second loop over entries
}//_detn = 6 || 7
}//_loop over entries
std::cout << std::endl;
t->Write();
f_root->Close();
timer.Stop();
timer.Print();
}