Skip to content

Wrong interaction between indexed TTree friend, GetEntries, GetListOfFriends #17820

Description

@vepadulano

Check duplicate issues.

  • Checked for duplicates

Description

In a scenario with TTree friends for which an index was built, if the TTree::GetEntries function is called, then the list of friends for the main tree is not properly populated. This in turn leads to bad interactions with other tools. For example, the list of all branches of the dataset cannot be properly created since the branches of the friend trees will simply be absent due to the list of friends being unavailable.

Reproducer

#include <TChain.h>
#include <TFile.h>
#include <TTree.h>

#include <filesystem>
#include <iostream>
#include <memory>

void write_data(std::string_view treename, std::string_view filename)
{
    TFile f{filename.data(), "update"};
    TTree t{treename.data(), treename.data()};
    int runNumber{};
    int eventNumber{};
    float val{};
    t.Branch("runNumber", &runNumber, "runNumber/I");
    t.Branch("eventNumber", &eventNumber, "eventNumber/I");
    t.Branch("val", &val, "val/F");
    if (treename == "main")
    {
        for (auto rn = 0; rn < 3; rn++)
        {
            runNumber = rn;
            for (auto en = 0; en < 5; en++)
            {
                eventNumber = en;
                val = en * rn;
                t.Fill();
            }
        }
    }
    else
    {
        for (auto rn = 0; rn < 3; rn++)
        {
            runNumber = rn;
            for (auto en = 4; en >= 0; en--)
            {
                eventNumber = en;
                val = en * rn;
                t.Fill();
            }
        }
    }

    f.Write();
}

void simple()
{
    if (!std::filesystem::exists("test_file.root"))
    {
        write_data("main", "test_file.root");
        write_data("friend", "test_file.root");
    }

    auto main = std::make_unique<TChain>("main");
    main->AddFile("test_file.root");
    auto frChain = std::make_unique<TChain>("friend");
    frChain->AddFile("test_file.root");
    frChain->BuildIndex("runNumber", "eventNumber");
    main->AddFriend(frChain.get());

    // Calling GetEntries() will make the following GetListOfFriends call
    // return a nullptr
    main->GetEntries();

    // If we don't call GetEntries we still need to call LoadTree for the first
    // entry so that the chain populates the fTree data member and the GetTree
    // method can return the correct pointer. In this case, the list of friends
    // is connected.
    // main->LoadTree(0);

    auto *listOfFriends = main->GetTree()->GetListOfFriends();
    if (listOfFriends)
        std::cout << "List of friends was found.\n";
    else
        std::cout << "List of friends was not found!\n";
}

int main()
{
    simple();
}

ROOT version

Any

Installation method

Any

Operating system

Any

Additional context

No response

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions