Skip to content

Bug: TEntryList and TTree inconsitency of entry number returned by tree if entry list has been already used #13338

Open
@romainbqt

Description

@romainbqt

Check duplicate issues.

  • Checked for duplicates

Description

Hello,

I am creating this issue because there is a bug when setting an entry list that has already been used to a TTree.
The entry number returned by tree->GetEntryNumber(index) are messed up until that function is called 2 times in a row for the same index.

You can find a standalone simple reproducer of the bug below.

In that code by setting numTest to 0, 1 or 2 you will obtain the different print below.
With that example by calling tree->GetEntryNumber(index) it should return the value index
e.g. tree->GetEntryNumber(2) should return 2. However until the GetEntryNumber() function has not been called 2 times for the same index then the returned entry number is NOT the expected one.

Here it is simple to solve the issue i.e. not call entryList->GetEntry(15); before setting the entry list to the tree
but I find this behaviour really error prone as one would need to be sure the entry list has never been used basically.

On the other hand using the copy constructor allows not having this issue because I think the fLastIndexQueried is reset to -1

tree->SetEntryList( new TEntryList(*entryList) );

Tagging @pcanal and @Axel-Naumann

For numTest=0

tree->GetEntryNumber(0)=16
tree->GetEntryNumber(0)=0
tree->GetEntryNumber(0)=0
tree->GetEntryNumber(0)=0

For numTest=1

tree->GetEntryNumber(0)=16
tree->GetEntryNumber(1)=17
tree->GetEntryNumber(1)=1
tree->GetEntryNumber(1)=1

For numTest=2

tree->GetEntryNumber(0)=16
tree->GetEntryNumber(1)=17
tree->GetEntryNumber(2)=18
tree->GetEntryNumber(2)=2
tree->GetEntryNumber(2)=2

Reproducer

#include "TFile.h"
#include "TTree.h"
#include "TError.h"
#include "TEntryList.h"

#include<string>
#include<vector>
#include<iostream>


// function defined after main 
void createTree(const std::string &outputFile);

int main(){
  
  // number of the test 
  // set to 0, 1 or 2
  int numTest = 2; 

  // Define an entry list 
  TEntryList *entryList = new TEntryList(); 
  std::vector<long long int> entries={
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
  };

  // fill the entry list 
  for (long long int entry : entries){
    entryList->Enter(entry);
  }

  // Create tree 
  std::string inFileName = "myFile.root"; 
  createTree(inFileName);

  // Read tree 
  TFile *file = nullptr; 
  TTree *tree = nullptr;

  file = TFile::Open(inFileName.c_str());
  tree = (TTree*) file->Get("myTree");

  // On purpose get entry 15 
  // before setting entry list for tree 
  entryList->GetEntry(15);
  tree->SetEntryList(entryList);
  
  if (numTest == 0){
    std::cout << "tree->GetEntryNumber(0)=" << tree->GetEntryNumber(0) << std::endl; 
    std::cout << "tree->GetEntryNumber(0)=" << tree->GetEntryNumber(0) << std::endl;
    std::cout << "tree->GetEntryNumber(0)=" << tree->GetEntryNumber(0) << std::endl;
    std::cout << "tree->GetEntryNumber(0)=" << tree->GetEntryNumber(0) << std::endl;
  }
  
  if (numTest == 1){
    std::cout << "tree->GetEntryNumber(0)=" << tree->GetEntryNumber(0) << std::endl; 
    std::cout << "tree->GetEntryNumber(1)=" << tree->GetEntryNumber(1) << std::endl;
    std::cout << "tree->GetEntryNumber(1)=" << tree->GetEntryNumber(1) << std::endl;
    std::cout << "tree->GetEntryNumber(1)=" << tree->GetEntryNumber(1) << std::endl;
  }

  if (numTest == 2){
    std::cout << "tree->GetEntryNumber(0)=" << tree->GetEntryNumber(0) << std::endl; 
    std::cout << "tree->GetEntryNumber(1)=" << tree->GetEntryNumber(1) << std::endl;
    std::cout << "tree->GetEntryNumber(2)=" << tree->GetEntryNumber(2) << std::endl;
    std::cout << "tree->GetEntryNumber(2)=" << tree->GetEntryNumber(2) << std::endl;
    std::cout << "tree->GetEntryNumber(2)=" << tree->GetEntryNumber(2) << std::endl;
  }

  return 0; 
}

void createTree(const std::string &outputFile){

  unsigned int NEntries = 100;
  TTree *tree = nullptr;
  double x1;

  // create file 
  TFile *file = TFile::Open(outputFile.c_str(),"recreate"); 
  // init tree 
  tree = new TTree("myTree","myTree"); 
  tree->Branch("x1", &x1);

  for (unsigned int iEntry = 0 ; iEntry < NEntries; iEntry++){
    x1 = iEntry;
    tree->Fill();
  }

  file->Write(); 
  delete file;
}

ROOT version

ROOT Version: 6.26/08
I believe all versions are affected by that bug even the most recent ones

Installation method

Built from source

Operating system

Linux

Additional context

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions