How to check conditions entry by entry in a nested loop

Dear Developers,

I want to apply different conditions in the form of a nested loop and check them entry by entry like

(if z1_mass>z2_mass){
double diff_12 = z1_mass-z2_mass }
(if z2_mass>z3_mass){
double diff_23 = z2_mass-z3_mass }
(if z3_mass>z1_mass){
double diff_31 = z3_mass-z31_mass }

How I will apply it to check the result entry by entry. There are 1107 entries. Also I want to save the result of each entry just to compare the values.
Here is my script.

for (int i=0;i<10000;i++)   {

 TLorentzVector tmp1, tmp2, tmp3;

         t->GetEntry(i);

// for(int m=0; m<VetoMu;m++)   {

          if(VetoMu<2)continue;

int m1=0, m2=1, m3=2;

if(m1==0) tmp1.SetPxPyPzE(VetoMu_px[m1], VetoMu_py[m1], VetoMu_pz[m1], VetoMu_en[m1]);
if(m2==1) tmp2.SetPxPyPzE(VetoMu_px[m2], VetoMu_py[m2], VetoMu_pz[m2], VetoMu_en[m2]);
if(m3==2) tmp3.SetPxPyPzE(VetoMu_px[m3], VetoMu_py[m3], VetoMu_pz[m3], VetoMu_en[m3]);

if (VetoMu_charge[m1]*VetoMu_charge[m2] < 0.) {

        double z1_mass = (tmp1 + tmp2).M();
}
if (VetoMu_charge[m2]*VetoMu_charge[m3] < 0.) {

        double z2_mass = (tmp2 + tmp3).M();
}
if (VetoMu_charge[m3]*VetoMu_charge[m1] < 0.) {

        double z3_mass = (tmp1 + tmp3).M();
}
}

Cheers,
Nab

Hi Nab,

your code already does almost what you want, there’s just the tiny matter of the scope of variables. To paraphrase your code a bit:

if (someCondition) { // a new basic block starts here
    int flag = 1;          // create a new variable
    SomeObject obj(flag);  // create an object
    doSomeWork(flag, obj); // work with your new variables
} // basic block ends: variables die here (destructors called), and become undefined again

So the rule in C++ is that variables on the stack go out of scope once the basic block is exited in which they’re defined. For your variables z1_mass, diff_12, and so on, the problem likely is that these variables go out of scope before you can use them. If you change your code like this, you may be more successful:

for (ULong64_t nEntry = 0; nEntry < 10000; ++nEntry) {
   tree->GetEntry(nEntry);

   TLorentzVector tmp1(VetoMu_px[0], VetoMu_py[0], VeloMu_pz[0], VetoMu_en[0]);
   TLorentzVector tmp2(VetoMu_px[1], VetoMu_py[1], VeloMu_pz[1], VetoMu_en[1]);
   TLorentzVector tmp3(VetoMu_px[2], VetoMu_py[2], VeloMu_pz[2], VetoMu_en[2]);

   double z1_mass, z2_mass, z3_mass;
   if (VetoMu_charge[m1]*VetoMu_charge[m2] < 0.) z1_mass = (tmp1 + tmp2).M();
   if (VetoMu_charge[m2]*VetoMu_charge[m3] < 0.) z2_mass = (tmp2 + tmp3).M();
   if (VetoMu_charge[m3]*VetoMu_charge[m1] < 0.) z3_mass = (tmp1 + tmp3).M();
   // now you can work with z1_mass etc., e.g. print them
   std::printf("z1_mass %g z2_mass %g z3_mass %g\n", z1_mass, z2_mass, z3_mass);
}
// the following line would not work, because we're outside the basic block in which
// z1_mass etc. are defined:
// std::printf("z1_mass %g z2_mass %g z3_mass %g\n", z1_mass, z2_mass, z3_mass); // illegal!

I hope this helps.

Cheers,

Manuel

Small comments to Manuel’s code:

  • change the nEntry < 10000 to sometime useful (especially because nab wrote that the tree has 1107 entries), i.e. auto entries = tree->GetEntries(); for (Long64_t nEntry = 0; nEntry < entries; ++nEntry) {...} ROOT is using a signed value for GetEntry, so no need for U.
  • if any of your three ifs is false, you have no initialization for one of the z*_mass variables -> you will be printing an uninitialized value. Don’t do that, it is undefined behavior.
1 Like

Hi,

I started from the example above and reformulated it in terms of TDataFrame in order to show this new functionality of ROOT 6.10.
I attach the macro which I used to generate some fake input, also created with TDataFrame createInput.C.

The analysis code looks like:

// analyse.C
void analyse() {

ROOT::Experimental::TDataFrame d("mytree","myfile.root");
using floats = std::vector<float>;
using ints = std::vector<int>;

auto printM = [](floats& x, floats& y, floats& z, floats& t, ints& c){
   std::vector<TLorentzVector> tmp = {{x[0], y[0], z[0], t[0]},
                                     {x[1], y[1], z[1], t[1]},
                                     {x[2], y[2], z[2], t[2]}};
   if (c[0]*c[1] < 0) printf("z1_mass = %g\n", (tmp[1] + tmp[2]).M());
   if (c[1]*c[2] < 0) printf("z2_mass = %g\n", (tmp[2] + tmp[3]).M());
   if (c[0]*c[2] < 0) printf("z3_mass = %g\n", (tmp[1] + tmp[3]).M());
};

d.Foreach(printM, {"VetoMu_px","VetoMu_py","VetoMu_pz","VetoMu_en","VetoMu_charge"});

}

Cheers,
D

Dear all,

Thank you so much for your help.

Cheers,
Nab

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