Skip to content

Wrong behaviour in TTree::[GetMinimum,GetMaximum] #22652

@vepadulano

Description

@vepadulano

Check duplicate issues.

  • Checked for duplicates

Description

TTree::[GetMinimum,GetMaximum] behave wrongly in case the input column name comes from a friend tree.

See for example this implementation, where the address of the branch is never updated (thus if the branch belongs to a friend TChain it is not updated to point to the branch of the current tree being traversed in the friend TChain)

Double_t TTree::GetMinimum(const char* columname)

This issue originates from https://root-forum.cern.ch/t/ttree-getminimum-getmaximum-only-scan-one-file-of-a-friend-tchain/64905

Reproducer

#include <TChain.h>
#include <TFile.h>
#include <TTree.h>
#include <iostream>
#include <memory>
#include <string>
void getminimum_friend_chain() {
  const int per = 100;
  const int nfiles = 3;
  // file 0: w in [4,5)   file 1: w in [0,1)   file 2: w in [9,10)
  const double lo[nfiles] = {4.0, 0.0, 9.0};

  {
    // Main TTree with cumulated number of entries
    auto fd = std::make_unique<TFile>("main_global.root", "RECREATE");
    auto td = std::make_unique<TTree>("main", "main");
    double x{};
    td->Branch("x", &x);
    for (int f = 0; f < nfiles; ++f) {
      for (int i = 0; i < per; ++i) {
        td->Fill();
      }
    }
    fd->Write();
  }

  for (int f = 0; f < nfiles; ++f) {
    // Trees for the main chain
    {
      auto fd = std::make_unique<TFile>(
          ("main_" + std::to_string(f) + ".root").c_str(), "RECREATE");
      auto td = std::make_unique<TTree>("main", "main");
      double x{};
      td->Branch("x", &x);
      for (int i = 0; i < per; ++i) {
        // x in [-0.5, 0.495]
        x = i * 0.01 - 0.5;
        td->Fill();
      }
      fd->Write();
    }

    // Trees for the friend chain
    {
      auto ff = std::make_unique<TFile>(
          ("friend_" + std::to_string(f) + ".root").c_str(), "RECREATE");
      auto tf = std::make_unique<TTree>("friend", "friend");
      double w{};
      tf->Branch("w", &w);
      for (int i = 0; i < per; ++i) {
        // w in [lo[i], lo[i] + 1)
        w = lo[i] + i * (1.0 / per);
        tf->Fill();
      }
      ff->Write();
    }
  }

  std::cout
      << "friend \"w\":  file0 in [4,5), file1 in [0,1), file2 in [9,10)\n";
  std::cout << "TRUE min = 0 , TRUE max ~ 9.99\n";

  // Main is a TChain, friend is a TChain, entries are aligned
  {
    auto m = std::make_unique<TChain>("main");
    for (int f = 0; f < nfiles; ++f)
      m->Add(("main_" + std::to_string(f) + ".root").c_str());

    auto f = std::make_unique<TChain>("friend");
    for (auto i = 0; i < nfiles; i++)
      f->Add(("friend_" + std::to_string(i) + ".root").c_str());

    m->AddFriend(f.get());

    std::cout << "Main TChain: GetMinimum=" << m->GetMinimum("w")
              << ", GetMaximum=" << m->GetMaximum("w") << "\n";
  }

  // Main is a TTree, friend is a TChain, entries are aligned
  {

    auto fm = std::make_unique<TFile>("main_global.root");
    std::unique_ptr<TTree> m{fm->Get<TTree>("main")};

    auto f = std::make_unique<TChain>("friend");
    for (auto i = 0; i < nfiles; i++)
      f->Add(("friend_" + std::to_string(i) + ".root").c_str());

    m->AddFriend(f.get());

    std::cout << "Main TTree: GetMinimum=" << m->GetMinimum("w")
              << ", GetMaximum=" << m->GetMaximum("w") << "\n";
  }
}

int main() { getminimum_friend_chain(); }

ROOT version

Any

Installation method

Any

Operating system

Any

Additional context

No response

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions