Using global TCut object in a loop "for" when reading a tree

_ROOT Version: 6.30
_Platform: Windows 11
Compiler: Not Provided
__
Hello,

I have a TCut variable (TCut cut_all) defined in my script and the script is automatically loaded when starting root session using .rootlogon.C, making my cut_all to be global now

What I want to do is to use my TCut cut_all when reading a tree using loop “for”. I have found a solution involving TTreeFormula:

    //my definitions 

    TTreeFormula* formula = new TTreeFormula("formula", cut_all.GetTitle(), tree);

    Long64_t nEntries = tree->GetEntries();

    for (Long64_t entryNum = 0; entryNum < nEntries; ++entryNum) {
        tree->GetEntry(entryNum);

        if (formula->EvalInstance() != 0) {
            hist->Fill(mf0[1]);
        }
    }

    //returning the histogram

The problem is that my histogram is EMPTY after the loop: formula->EvalInstance() equals to 0 for all entries.
Why is this happening :red_question_mark:
And generally, how to use globally defined TCut variable when reading a tree using loop “for” :red_question_mark:

This is very important for me, because I often interactively work with trees using tree->Draw(“mf0[1]”, cut_all), but sometimes I need to control every entry, but I don’t want to manually type out the whole cut in if(…) condition, because my TCut variable is very lengthy.

Are there any other solutions available? I greatly appreciate any assistance provided!

Hi Dash,
Welcome to the ROOT forum.

@pcanal could you please take a look at this question?

What you wrote ‘should’ have worked unless tree is a TChain (in which case you need to add more code to handle the transition from one tree to the other) or if cut_all contains references to collections (in which case you need to not just look at one value for loop through the multiple values for each entries of the tree)

Thank you for your response, @pcanal.

  1. My tree object is indeed a TChain. However, I’ve tested my function on a single tree, and it still produces an empty histogram.

  2. I didn’t understand you on the second part of your answer. I’m using standard TCut definitions.

TCut cut_base = "(neu == 1) && (trin > 0) && (cnp > 2) && (etot >= 0.65*2.0*beam) && (sqrt(ptrn*ptrn + plrn*plrn) <= 0.3)";
TCut cut_angles_0 = "(thkn[0] > 36.0*TMath::Pi()/180.0) && (thkn[0] < 144.0*TMath::Pi()/180.0)";
TCut cut_angles_1 = "(thkn[1] > 36.0*TMath::Pi()/180.0) && (thkn[1] < 144.0*TMath::Pi()/180.0)";
TCut cut_angles_2 = "(thkn[2] > 36.0*TMath::Pi()/180.0) && (thkn[2] < 144.0*TMath::Pi()/180.0)";
TCut cut_angles = cut_angles_0 && cut_angles_1 && cut_angles_2;
TCut cut_chi2 = "chi2n < 30.0";
TCut cut_M = "(mf0[1] >= 70.0) && (mf0[1] <= 200.0)";
TCut cut_all = cut_base && cut_angles && cut_chi2 && cut_M;

It looks like as if TCut was only created for the tree->Draw() method.

I think that the simplest solution would be to just copy and paste my cuts directly into the loop, defining them as booleans
:sad_but_relieved_face:

Thank you.

Is a hint that indeed some of the branch used contains collection (at least thkn, mf0, etc.)

How is mf0 defined? How is it connected to the TTree.

@pcanal

   //...
   UChar_t neu;
   Int_t trin, cnp;
   Float_t etot, ptrn, plrn, beam, chi2n, momkn[3], thkn[3], mf0[2];

   tree->SetBranchAddress("neu", &neu);
   tree->SetBranchAddress("trin", &trin);
   tree->SetBranchAddress("cnp", &cnp);
   tree->SetBranchAddress("etot", &etot);
   tree->SetBranchAddress("ptrn", &ptrn);
   tree->SetBranchAddress("plrn", &plrn);
   tree->SetBranchAddress("beam", &beam);
   tree->SetBranchAddress("chi2n", &chi2n);
   tree->SetBranchAddress("momkn", momkn);
   tree->SetBranchAddress("thkn", thkn);
   tree->SetBranchAddress("mf0", mf0);
   //...

In addition for a TChain you need to do something like:

    Long_t treenumber = tree->GetTreeNumber();
    for( int i=0; i<t.GetEntriesFast(); i++ ) 
    { 
        if ( tree->LoadEntry(i) < 0 ) break;
        if (tree->GetTreeNumber() != treenumber) {
           formula->UpdateFormulaLeaves();
           treenumber = tree->GetTreeNumber();
        }
    }

Instead of

try

        if (formula->EvalInstance(0) != 0) {

@pcanal
What is t? Is it my tree? If yes, then it says that there is no such method: tree->LoadEntry(i).

@pcanal
This is my function

TH1D* readTreeToHist(TTree* tree, const std::string& histName)  {    
    TH1D* hist = new TH1D(histName.c_str(), histName.c_str(), 65, 70.0, 200.0);

    UChar_t neu;
    Int_t trin, cnp;
    Float_t etot, ptrn, plrn, beam, chi2n, momkn[3], thkn[3], mf0[2];

    tree->SetBranchAddress("neu", &neu);
    tree->SetBranchAddress("trin", &trin);
    tree->SetBranchAddress("cnp", &cnp);
    tree->SetBranchAddress("etot", &etot);
    tree->SetBranchAddress("ptrn", &ptrn);
    tree->SetBranchAddress("plrn", &plrn);
    tree->SetBranchAddress("beam", &beam);
    tree->SetBranchAddress("chi2n", &chi2n);
    tree->SetBranchAddress("momkn", momkn);
    tree->SetBranchAddress("thkn", thkn);
    tree->SetBranchAddress("mf0", mf0);

    TTreeFormula* formula = new TTreeFormula("formula", cut_all.GetTitle(), tree);
    
    //Long_t treenumber = tree->GetTreeNumber();
    //for( int i=0; i<tree->GetEntriesFast(); i++ ) { 
    //    if ( tree->LoadEntry(i) < 0 ) break;
    //    if (tree->GetTreeNumber() != treenumber) {
    //       formula->UpdateFormulaLeaves();
    //       treenumber = tree->GetTreeNumber();
    //    }
    //}

    Long64_t nEntries = tree->GetEntries();
    for (Long64_t entryNum = 0; entryNum < nEntries; ++entryNum) {
        tree->GetEntry(entryNum);

        if (formula->EvalInstance(0) != 0) {
            hist->Fill(mf0[1]);
        }
    }

    return hist;
}

P.S why my code tags are not highlighting the syntax :red_question_mark:

yes. it was a typo. (corrected)

That is quite weird … :frowning:

Note in your example the loop needs to be the same:

    // Calling this for a TChain is very ineffecient, it request to open and then immediately
    // close all the file.
    // Long64_t nEntries = tree->GetEntries();
    Long_t treenumber = tree->GetTreeNumber();
    for (Long64_t entryNum = 0; entryNum < tree->GetEntriesFast(); ++entryNum) {

        if ( tree->LoadEntry(entryNum) < 0 ) break;
        if (tree->GetTreeNumber() != treenumber) {
           formula->UpdateFormulaLeaves();
           treenumber = tree->GetTreeNumber();
        }
        tree->GetEntry(entryNum);

        if (formula->EvalInstance(0) != 0) {
            hist->Fill(mf0[1]);
        }
    }

@pcanal