Does the TBranch order matter in a TTree?

Assume a TTree called myTree with the TBranches branch1, branch2, branch3.

I have noticed different results when applying the same conditions with different order.
For instance

if (branch1 > 100 && branch2 > 2){ ... }

will result in different output than

if (branch2 > 2 && branch1 > 100){ ... }

so I was wondering if the order that the TBranches are parsed in the root file really matters.

TBranch has no value so I don’t understand what you are trying to compare (I think you need to provide some code and a “.root” file which “reproduces” your problem).

Thank you very much for your reply.

You can find a file here

dropbox.com/s/jrc2qi2l080di … .root?dl=0

A sample code is

[code]int main(){

TFile foo = TFile::Open(“run200929.root”);
TTree t = (TTree)foo->Get(“FIMG”);
t->SetBranchStatus("
",0);

double tof, tflash;
int detn, RunNumber, BunchNumber, satuflag, PSpulse;
float amp, PulseIntensity;
char dummy;

float FIMGneutene = 0.0;
float FIMGneuteneCut = 0.0;

t->SetBranchStatus(“tof”,1); t->SetBranchAddress(“tof”,&tof);
t->SetBranchStatus(“tflash”,1); t->SetBranchAddress(“tflash”,&tflash);
t->SetBranchStatus(“detn”,1); t->SetBranchAddress(“detn”,&detn);
t->SetBranchStatus(“RunNumber”,1); t->SetBranchAddress(“RunNumber”,&RunNumber);
t->SetBranchStatus(“BunchNumber”,1); t->SetBranchAddress(“BunchNumber”,&BunchNumber);
t->SetBranchStatus(“amp”,1); t->SetBranchAddress(“amp”,&amp);
t->SetBranchStatus(“dummy”,1); t->SetBranchAddress(“dummy”,&dummy);
t->SetBranchStatus(“satuflag”,1); t->SetBranchAddress(“satuflag”,&satuflag);
t->SetBranchStatus(“PulseIntensity”,1); t->SetBranchAddress(“PulseIntensity”,&PulseIntensity);

int entries = t->GetEntries();
cout << "Total number of entries found : " << entries << endl;

Int_t ndec = E_MAX - E_MIN;
Int_t nbins = (Int_t) ndec*N_BPDEC;
Double_t ebins[nbins+1];
Double_t tbins[nbins+1];
Double_t step = (Double_t) ndec / nbins;

for(Int_t i=0; i <= nbins; i++) {
ebins[i] = (float) pow(10., step * (Double_t) i + E_MIN);
//tbins[i] = (float) Energy_to_Time_relativistic(ebins[i], L_geom[6]);
}

TH1F *hyieldCut6_TEST = new TH1F(“hyieldCut6_TEST”,“Cut Yield - 500 ns - ^{235}U #6; Neutron energy (eV); Counts (arb. units)”,nbins,ebins);

    int event0 = 0; 
double tof06 = 0.0;
for( int i = 0; i < entries; i++ ){
t->GetEntry(i);
if(RunNumber == 201081 || RunNumber == 201082 || RunNumber == 201122) continue;//runs with a few events
if(PulseIntensity <= 5.e12) continue;
if(tflash == 0.) continue;
if(satuflag == 1) continue;


	//if ( detn == 6 ){
		if (BunchNumber == event0 && detn == 6 && i>0){
			//if (detn==6){
			if (tof - tof06 >= 200.){
				FIMGneuteneCut = (Float_t) TOFtoE_relativistic(tflash, (double) tof,19.2);
				if(FIMGneuteneCut <= pow(10.,7) && FIMGneuteneCut >= pow(10.,-2)) {
					if(FIMGneuteneCut < 1e7) {
						if(amp > 30){
							hyieldCut6_TEST->Fill(FIMGneuteneCut);
							FIMGneuteneCut = 0.0;
						}
					}
				}
				tof06 = tof;
			}
		//}
		}
		else{
			event0 = BunchNumber;
			//detn0  = detn;
			tof06  = tof;
		}
	//}
}

}[/code]

If I change

to

I will end up with a different histogram.

I hope it’s a bit more clear now.

In order to “reproduce” it, I need “E_MIN”, “E_MAX”, “N_BPDEC” values and the “TOFtoE_relativistic” function.

Oh I am so sorry…

const int E_MIN = -3; const int E_MAX = 8; const int N_BPDEC = 50; const double C = 299792458.0E-9;// speed of light [m/ns] const double Mn = 939.565378E6;// neutron mass [eV/c2]

and

[code]
// Simple TOF-to-energy conversion (RELATIVISTIC)
double TOFtoE_relativistic(double t_flash, double tof, double L_geom) {
double beta = 0.;
double ggg = 0.; // = 1 / gamma
double gamma = 0.;
double t_light = 0.;
double n_energy = 0.;

t_light  = L_geom / C;
beta     = (double) L_geom / (tof - t_flash + t_light) / C;
ggg      = sqrt((1.-beta*beta));
gamma    = (double) 1. / ggg;
n_energy = (gamma - 1.) * Mn; // energy in eV
return n_energy;

}[/code]

Thank you very much for your time!

So, I replaced: if (BunchNumber == event0 && detn == 6 && i>0){ with: if (detn == 6 && BunchNumber == event0 && i>0){ and in both cases I get the same histogram.


Can you set the Y axis in Log scale as well?
Because the difference was observed in the higher energies!

With the attached “run200929.cxx” macro (I “improved” your code a bit), I get the same picture.



run200929.cxx (3.62 KB)

That’s weird…
Take a look at this code…

[code]
#include “TFile.h”
#include “TTree.h”
#include “TH1.h”
#include “TCanvas.h”

#include
#include

const int E_MIN = -3;
const int E_MAX = 8;
const int N_BPDEC = 50;
const double C = 299792458.0E-9;// speed of light [m/ns]
const double Mn = 939.565378E6;// neutron mass [eV/c2]
// Geometrical Variables
double L_geom[7] = {0,19.2608,19.2438,19.2268,19.2098,19.1928,19.1758};// Geometrical TOF distance [m]

// Simple TOF-to-energy conversion (RELATIVISTIC)
double TOFtoE_relativistic(double t_flash, double tof, double L_geom) {
double beta = 0.;
double ggg = 0.; // = 1 / gamma
double gamma = 0.;
double t_light = 0.;
double n_energy = 0.;

t_light = L_geom / C;
beta = (double) L_geom / (tof - t_flash + t_light) / C;
ggg = sqrt((1.-beta*beta));
gamma = (double) 1. / ggg;
n_energy = (gamma - 1.) * Mn; // energy in eV
return n_energy;
}

int main(){

TFile foo = TFile::Open(“run200929.root”);
TTree t = (TTree)foo->Get(“FIMG”);
t->SetBranchStatus("
",0);

double tof, tflash;
int detn, RunNumber, BunchNumber, satuflag, PSpulse;
float amp, PulseIntensity;
char dummy;

float FIMGneutene = 0.0;
float FIMGneuteneCut = 0.0;

t->SetBranchStatus(“tof”,1); t->SetBranchAddress(“tof”,&tof);
t->SetBranchStatus(“tflash”,1); t->SetBranchAddress(“tflash”,&tflash);
t->SetBranchStatus(“detn”,1); t->SetBranchAddress(“detn”,&detn);
t->SetBranchStatus(“RunNumber”,1); t->SetBranchAddress(“RunNumber”,&RunNumber);
t->SetBranchStatus(“BunchNumber”,1); t->SetBranchAddress(“BunchNumber”,&BunchNumber);
t->SetBranchStatus(“amp”,1); t->SetBranchAddress(“amp”,&amp);
t->SetBranchStatus(“dummy”,1); t->SetBranchAddress(“dummy”,&dummy);
t->SetBranchStatus(“satuflag”,1); t->SetBranchAddress(“satuflag”,&satuflag);
t->SetBranchStatus(“PulseIntensity”,1); t->SetBranchAddress(“PulseIntensity”,&PulseIntensity);

int entries = t->GetEntries();
cout << "Total number of entries found : " << entries << endl;

// Create neutron energy binning
Int_t ndec = E_MAX - E_MIN;
Int_t nbins = (Int_t) ndec*N_BPDEC;
Double_t ebins[nbins+1];
Double_t tbins[nbins+1];
Double_t step = (Double_t) ndec / nbins;

for(Int_t i=0; i <= nbins; i++) {
ebins[i] = (float) pow(10., step * (Double_t) i + E_MIN);
//tbins[i] = (float) Energy_to_Time_relativistic(ebins[i], L_geom[6]);
}

// Create Time Binning
for(Int_t i=0; i <= nbins; i++) {
tbins[i] = (float) Energy_to_Time_relativistic(ebins[nbins - i], L_geom[6]);
}

// Histograms
TH1F *hyield6 = new TH1F(“hyield6”,“Raw Yield - ^{235}U #6; Neutron energy (eV); Counts (arb. units)”,nbins,ebins);
TH1F *hyieldCut6_TEST = new TH1F(“hyieldCut6_TEST”,“Cut Yield - 500 ns - ^{235}U #6; Neutron energy (eV); Counts (arb. units)”,nbins,ebins);
TH1F *hDeadCorFac6_TEST = new TH1F(“hDeadCorFac6_TEST”,“Correction Factor - 500 ns - ^{235}U #6; Neutron energy (eV); Percentage (%)”,nbins,ebins);
TH1F *hYieldDead6_TEST = new TH1F(“hYieldDead6_TEST”,“Corrected Yield - 500 ns - ^{235}U #6; Neutron energy (eV); Counts (arb. units)”,nbins,ebins);
//histograms for proton counting
TH1F *hPROTpulse = new TH1F(“hPROTpulse”,"; Proton pulse type / Total protons; Number of proton pulses / protons",4,0.5,4.5);
TH2F *hPROTinten = new TH2F(“hPROTinten”,“PSpulse vs. PulseIntensity; Pulse type; Pulse intensity;”,2,0.5,2.5,800,1.0E12,9.0E12);

int local_flag = 1;
if(local_flag > 0) {
printf(" 10 20 30 40 50 60 70 80 90 100 %%\n");
printf(" ---------|---------|---------|---------|---------|---------|---------|---------|---------|---------| \n");
}

Float_t j = entries/100.;
Int_t n = 1;

// time difference between consecutive pulses
double tof0 = 0.;
double tflash0 = 0.;
int event0 = 0;
//int detn0 = 0;

// Auxilliary variables for proton/event count
float protons = 0.0; int bunches = 0; int Event_old = 0;

// Amplitude cuts
int FIMGcut[7];

FIMGcut[0] = 0;
FIMGcut[1] = 50;
FIMGcut[2] = 45;
FIMGcut[3] = 45;
FIMGcut[4] = 45;
FIMGcut[5] = 35;
FIMGcut[6] = 25;

//Energy Cuts
Float_t Ehigh = 1.0E7;

//Pulse Intensity Correction Factor
double PulseIntensity_CorFac = 1.;//1.0e-10;
//Proton Correction Factor
double proton_CorFac = 0.96;

for (int i = 0; i < entries; i++) {
if(local_flag > 0) {
if(i == 0) {cout << " ";}
if(i >= n*j) {cout << ‘|’ << flush; n++;}// Progress indicator
}

t->GetEntry(i);
if(PulseIntensity <= 5.e12) continue;
if(detn != 6) continue;
if(tflash == 0.) continue;
if(satuflag == 1) continue;
if(dummy == 3)continue;

if(BunchNumber != Event_old) {
	hPROTpulse->Fill(PSpulse);
	protons += PulseIntensity*PulseIntensity_CorFac;
	bunches++;
	hPROTpulse->SetBinContent(3,protons*proton_CorFac);
	hPROTinten->Fill(PSpulse,PulseIntensity*PulseIntensity_CorFac);
	Event_old = BunchNumber;
}
if(detn == 6) {
	FIMGneutene = (Float_t) TOFtoE_relativistic(tflash, (double) tof, L_geom[6]);
	if(FIMGneutene <= pow(10.,E_MAX) && FIMGneutene >= pow(10.,E_MIN)) {
		if(FIMGneutene < Ehigh) {
			if(amp > FIMGcut[6]){
				hyield6->Fill(FIMGneutene);
			}
		}
	}
}

}// end of loop over entries
cout << endl;
cout << endl;
cout << "Total Number of Bunches : " << bunches << endl;
cout << endl;
hPROTpulse->SetBinContent(4, bunches);
local_flag = 0;
n = 1;
//cout << “Run# PulseIntensity detn tflash satuflag dummy” << endl;
cout << endl;
for( int i = 0; i < entries; i++ ){
if(local_flag > 0) {
if(i == 0) {cout << " ";}
if(i >= n*j) {cout << ‘|’ << flush; n++;}// Progress indicator
}

t->GetEntry(i);
if(PulseIntensity <= 5.e12) continue;
if(detn != 6) continue;//<---------REMOVE FOR TESTING
if(tflash == 0.) continue;
if(satuflag == 1) continue;
if (dummy == 3)continue;
//cout << i << ".   " << RunNumber << "   " << PulseIntensity << "   " << detn << "   " << satuflag << "   " << dummy << endl;
if (BunchNumber == event0){
	if (tof - tof0 >= 200.){
		FIMGneuteneCut = (double) (TOFtoE_relativistic(tflash, tof, L_geom[6]));
		if(FIMGneuteneCut <= pow(10.,E_MAX) && FIMGneuteneCut >= pow(10.,E_MIN)) {
			if(FIMGneuteneCut < Ehigh) {
				if(amp > FIMGcut[6]){
					hyieldCut6_TEST->Fill(FIMGneuteneCut);
					FIMGneuteneCut = 0.0;
				}
			}
		}
		tof0    = tof;
		tflash0 = tflash;
	}
}
else if(BunchNumber != event0){
	event0  = BunchNumber;
	tflash0 = tflash;
	tof0    = tof;
}

}

// (2) Calculate the deadtime correction
cout << “Calculating dead time correction…” << endl;
// detector #6
for (int i=0; iGetNbinsX(); i++){
hDeadCorFac6_TEST->SetBinContent(i+1,1./(1.-(200.*hyieldCut6_TEST->GetBinContent(i+1)/hPROTpulse->GetBinContent(4)/abs(Energy_to_Time_relativistic(hyieldCut6_TEST->GetBinLowEdge(i+1), L_geom[6])-Energy_to_Time_relativistic(hyieldCut6_TEST->GetBinLowEdge(i+1)+hyieldCut6_TEST->GetBinWidth(i+1), L_geom[6])))));
hYieldDead6_TEST->SetBinContent(i+1,hyieldCut6_TEST->GetBinContent(i+1)*hDeadCorFac6_TEST->GetBinContent(i+1)); hYieldDead6_TEST->SetBinError(i+1, sqrt(hYieldDead6_TEST->GetBinContent(i+1)));
}

// (3) Save File
hyield6->SetLineColor(kRed);
hyieldCut6_TEST->SetLineColor(kBlack); hyieldCut6_TEST->SetLineStyle(2);
//Corrected
hYieldDead6_TEST->SetLineColor(kBlack);
hDeadCorFac6_TEST->SetLineColor(kBlack);
cout << endl;
cout << endl;

cout << “Saving file : TEST_Deltat.root” << endl;
TFile fout(“TEST_Deltat.root”,“RECREATE”);
hyield6->Write();
hyieldCut6_TEST->Write();
hYieldDead6_TEST->Write();
hDeadCorFac6_TEST->Write();
fout.Close();

return 0;

}//end of macro[/code]

If I remove

if(detn!=6)continue;

and use

if(detn==6 && BunchNumber == event0 && i>0)

I get different output that using

if(detn!=6)continue;

and

if(BunchNumber == event0 && i>0)

In the following image, you see the first case with red and the second case with black

That’s o.k. for me.
If you (in the beginning) say “if(detn != 6) continue;”, then the event is not processed further at all, as soon as this condition is met.
In particular (in these cases) it will not have any chance to reach the part: else if(BunchNumber != event0){ event0 = BunchNumber; tflash0 = tflash; tof0 = tof; } While if you (later) say “if(detn==6 && BunchNumber == event0 && i>0)” instead, then the above part can be reached also when “detn != 6”.

Hmmm…
In my case all I want to do, is make calculations using detn == 6.
So I would expect that both statements would do the same thing…
I am totally confused…

Well, inside of the “else … {” part, add in the beginning something like: if(detn != 6) std::cout << "Macumba! @ " << detn << " @ " << i << std::endl; and repeat your game with moving conditions.