TChain not reading second (and later) files

I am having trouble processing a TChain. It seems to know the first file in the chain, but then does not get any new events for the following files. I have read here and in other places that this is related to refreshing branch pointers, but how do I know when I need to do that? It seems very inefficient to do it on every event if it is only needed when encountering a new file.

I have pared this down to a simple test. I have tried it both as compiled code and in the root interpreter and get the same result. Below are three sets of code, one to make a few files to chain together (makeTree.cc), one to try to read the chain (readTree.cc), and finally a common .h definition file.

Thanks for your help,

Paul

makeTree.cc

#include <iostream>
#include <unistd.h>
#include <cstdlib>
	

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

#include "myBranches.h"

void makeTree() {
  
  TRandom* myRandom = new TRandom();
  
  int maxEvt = 5;
  int maxFile = 3;
  
  for (int iFile = 1; iFile < maxFile; iFile++) {
    char fileName[128];
    snprintf(fileName, 128, "myfile%.3i.root", iFile);
    
    TFile *myFile = new TFile(fileName, "create");
    TTree *myTree = new TTree("testTree", "testTree");
    myTree->Branch("branch1", &branch1, "iEvt:random_flat:one");
    myTree->Branch("branch2", &branch2, "iEvt:random_gauss:two");
    
    for (int iEvt = 0; iEvt < maxEvt; iEvt++) {
      branch1.iEvt = iEvt;
      branch1.random_flat = myRandom->Rndm();
      branch1.one = 1.0;

      branch2.iEvt = iEvt;
      branch2.random_gauss = myRandom->Gaus();
      branch2.two = 2.0;

      std::cout << branch2.random_gauss << " " ;
      myTree->Fill();
    }
    myTree->Print();
    myFile->Write();
    myFile->Close();
  }
}


#ifndef __CINT__
int main() {

  makeTree();
  return 1;

}
#endif

readTree.cc

#include <iostream>
#include <unistd.h>

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

#include "myBranches.h"

void myTest() {

  int maxFile = 3;
  TChain* dataTree = new TChain("testTree");
  for (int iFile = 1; iFile < maxFile; iFile++) {
    char fileName[128];
    snprintf(fileName, 128, "myfile%.3i.root", iFile);
    dataTree->Add(fileName);
  }

  
  TBranch* b1_Branch = new TBranch();
  dataTree->SetBranchAddress("branch1", &branch1, &(b1_Branch));
  TBranch* b2_Branch = new TBranch();
  dataTree->SetBranchAddress("branch2", &branch2, &(b2_Branch));
  
  Long64_t nEvtMax = dataTree->GetEntries();
  std::cout << "Total Entries seen in testTree = " << nEvtMax << std::endl;
  Long64_t iEvt = 1;
  int getEntryReturn = 0;
  for (Long64_t iEvt = 0; iEvt <=nEvtMax; iEvt++ ) {
    getEntryReturn = b1_Branch->GetEntry(iEvt);
    std::cout << " branch 1 " << branch1.iEvt << " "
	      << branch1.random_flat << " "
	      << branch1.one;
    getEntryReturn = b2_Branch->GetEntry(iEvt);
    std::cout << " branch 2 " << branch2.iEvt << " "
	      << branch2.random_gauss << " "
	      << branch2.two << std::endl; 
  }
}

#ifndef __CINT__
int main() {

  myTest();
  return 1;

}
#endif

myBranches.h

#ifndef MYBRANCHES_H
#define MYBRANCHES_H

struct branch1Struct {
  int iEvt;
  float random_flat;
  float one;
} branch1;

struct branch2Struct {
  int iEvt;
  float random_gauss;
  float two;
} branch2;

#endif


| Welcome to ROOT 6.29/01 https://root.cern |
| (c) 1995-2022, The ROOT Team; conception: R. Brun, F. Rademakers |
| Built for macosx64 on Aug 20 2023, 16:04:00 |
| From tag , 21 December 2022 |
| With Apple clang version 14.0.0 (clang-1400.0.29.202) |

Try ‘.help’/‘.?’, ‘.demo’, ‘.license’, ‘.credits’, ‘.quit’/‘.q’
ROOT Version: 6.29/01
Platform: macosx64
Compiler: Apple clang 14.0.0

I ran your example and I get this output:

% .x readtree.cc
root [0] 
Processing readtree.cc...
Error in <TChain::SetBranchAddress>: The pointer type given "branch1Struct" does not correspond to the type needed "Float_t" (5) by the branch: branch1
Error in <TChain::SetBranchAddress>: The pointer type given "branch2Struct" does not correspond to the type needed "Float_t" (5) by the branch: branch2
Total Entries seen in testTree = 10
 branch 1 0 0.0444927 1 branch 2 0 0.38067 2
 branch 1 1 0.39031 1 branch 2 1 -1.46627 2
 branch 1 2 0.0542479 1 branch 2 2 0.398669 2
 branch 1 3 0.520053 1 branch 2 3 -0.218599 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
root [1] 

is it what you get too ?

Hello,

I have been running it in compiled mode and get

[8:03 reimer@CSI358562 Process] ./readTree
Total Entries seen in testTree = 10
 branch 1 0 0.0444927 1 branch 2 0 0.38067 2
 branch 1 1 0.39031 1 branch 2 1 -1.46627 2
 branch 1 2 0.0542479 1 branch 2 2 0.398669 2
 branch 1 3 0.520053 1 branch 2 3 -0.218599 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2

Note that the error message is missing!
However, when I run it within root, I do get the error message:

[8:09 reimer@CSI358562 Process] root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.29/01                        https://root.cern |
  | (c) 1995-2022, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for macosx64 on Aug 20 2023, 16:04:00                      |
  | From tag , 21 December 2022                                      |
  | With Apple clang version 14.0.0 (clang-1400.0.29.202)            |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

(int) 1
Loading local ./rootSetup.C
Loading ~/Documents/local/lib/mysql/libmysqlclient.22.dylib
Loading $KTRACKER_ROOT/lib/libkTracker.so
root [0] .x src/readTree.cc
Error in <TChain::SetBranchAddress>: The pointer type given "branch1Struct" does not correspond to the type needed "Float_t" (5) by the branch: branch1
Error in <TChain::SetBranchAddress>: The pointer type given "branch2Struct" does not correspond to the type needed "Float_t" (5) by the branch: branch2
Total Entries seen in testTree = 10
 branch 1 0 0.0444927 1 branch 2 0 0.38067 2
 branch 1 1 0.39031 1 branch 2 1 -1.46627 2
 branch 1 2 0.0542479 1 branch 2 2 0.398669 2
 branch 1 3 0.520053 1 branch 2 3 -0.218599 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2
 branch 1 4 0.33476 1 branch 2 4 0.701484 2

Paul

So you get the same, and those 2 errors don’t seem related to your original question, or how are they related? Anyway, the messages seem clear: you are not using a Float_t where you should somewhere when reading the branches; looking at your branch1 and branch2, you are trying to use int for iEvt when in your tree you defined iEvt as a float. So you should either change int to float in the branch structures or the other way in the tree.

You are correct that the source of the error messages was that I didn’t type iEvt when writing the tree. Replacing

    myTree->Branch("branch1", &branch1, "iEvt:random_flat:one");
    myTree->Branch("branch2", &branch2, "iEvt:random_gauss:two");

with

    myTree->Branch("branch1", &branch1, "iEvt/I:random_flat:one");
    myTree->Branch("branch2", &branch2, "iEvt/I:random_gauss:two");

in makeTree.cc (full code below) removes the error messages.

You are also correct that those two error messages are not related to my original problem, which still remains: readTree.cc still does not read past the first file in the TChain, but rather keeps the last entry from the first file for all other entries in the TChain.

makeTree.cc

void makeTree() {
  
  TRandom* myRandom = new TRandom();
  
  int maxEvt = 5;
  int maxFile = 3;
  
  for (int iFile = 1; iFile < maxFile; iFile++) {
    char fileName[128];
    snprintf(fileName, 128, "myfile%.3i.root", iFile);
    
    TFile *myFile = new TFile(fileName, "create");
    TTree *myTree = new TTree("testTree", "testTree");
    myTree->Branch("branch1", &branch1, "iEvt/I:random_flat:one");
    myTree->Branch("branch2", &branch2, "iEvt/I:random_gauss:two");
    
    for (int32_t iEvt = 0; iEvt < maxEvt; iEvt++) {
      branch1.iEvt = iEvt;
      branch1.random_flat = myRandom->Rndm();
      branch1.one = 1.0;

      branch2.iEvt = iEvt;
      branch2.random_gauss = myRandom->Gaus();
      branch2.two = 2.0;

      std::cout << branch2.random_gauss << " " ;
      myTree->Fill();
    }
    myTree->Print();
    myFile->Write();
    myFile->Close();
  }
}


#ifndef __CINT__
int main() {

  makeTree();
  return 1;

}
#endif

readTree.cc

#include <iostream>
#include <unistd.h>

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

#include "myBranches.h"

void readTree() {

  int maxFile = 3;
  TChain* dataTree = new TChain("testTree");
  for (int iFile = 1; iFile < maxFile; iFile++) {
    char fileName[128];
    snprintf(fileName, 128, "myfile%.3i.root", iFile);
    dataTree->Add(fileName);
  }

  
  TBranch* b1_Branch = new TBranch();
  dataTree->SetBranchAddress("branch1", &branch1, &(b1_Branch));
  TBranch* b2_Branch = new TBranch();
  dataTree->SetBranchAddress("branch2", &branch2, &(b2_Branch));
  
  Long64_t nEvtMax = dataTree->GetEntries();
  std::cout << "Total Entries seen in testTree = " << nEvtMax << std::endl;
  int getEntryReturn = 0;
  for (Long64_t i = 0; i <=nEvtMax; i++ ) {
    getEntryReturn = b1_Branch->GetEntry(i);
    std::cout << " branch 1 " << branch1.iEvt << " "
	      << branch1.random_flat << " "
	      << branch1.one;
    getEntryReturn = b2_Branch->GetEntry(i);
    std::cout << " branch 2 " << branch2.iEvt << " "
	      << branch2.random_gauss << " "
	      << branch2.two << std::endl; 
  }
}

#ifndef __CINT__
int main() {
  readTree();
  return 1;
}
#endif

myBranches.h

#ifndef MYBRANCHES_H
#define MYBRANCHES_H

struct branch1Struct {
  int iEvt;
  float random_flat;
  float one;
} branch1;

struct branch2Struct {
  int iEvt;
  float random_gauss;
  float two;
} branch2;

#endif

Hello,

No comments on how to get root to read the second file in the chain?

Paul

You meant to write:

  for (Long64_t iEvt = 0; iEvt <=nEvtMax; iEvt++ ) {
    Long64_t localEvt = dataTree->LoadTree( iEvt );
    getEntryReturn = b1_Branch->GetEntry(localEvt);

The call to LoadTree is compulsory to move the TChain ‘cursor’ to the read file and tree. TBranch::GetEntry takes as a parameter the local entry number (entry number within a single TTree) which is return by LoadTree.

Works perfectly!
Thanks,
Paul

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