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?

1 Like

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)

1 Like

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();
        }
    }
1 Like

Instead of

try

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

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

1 Like

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]);
        }
    }
1 Like

@pcanal

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