Using TChain in an h file to include in a C file

Hello,

I’m trying to chain multiple root files together to use in a C file and print out specific histograms. I’m mostly reusing a C file and an h file that is able to connect to one root file at a time, but I want the h file to connect to multiple root files that are copies of one another. I can include some code that only works for one root file and another code that attempts to use multiple root files. I believe that this h file is using TChain (or includes TChain) to establish the branches, but not to chain multiple root files that are copies of one another. I can answer any questions if it doesn’t seem clear right now. Thanks in advance.

-Charlie Clark

ROOT Version: 6.26/06
Platform: Ubuntu 22
Compiler: from file root_v6.26.06.Linux-ubuntu22-x86_64-gcc11.2.tar.gz

Code:

//////////////////////////////////////////////////////////
// This class has been automatically generated on
// Wed Oct  5 12:01:55 2022 by ROOT version 6.26/06
// from TTree T/Geant4 Moller Polarimetry Simulation
// found on file: results_beamOn_C16.root
//////////////////////////////////////////////////////////

#ifndef results_beamOn_C16_h
#define results_beamOn_C16_h

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

// Header file for the classes stored in the TTree if any.

class results_beamOn_C16 {
public :
   TTree          *fChain;   //!pointer to the analyzed TTree or TChain
   Int_t           fCurrent; //!current Tree number in a TChain

// Fixed size dimensions of array or collections stored in the TTree if any.

   // Declaration of leaf types
   Int_t           evNpart;
   Int_t           evPid[1];   //[ev.npart]
   Double_t        evVx[1];   //[ev.npart]
   Double_t        evVy[1];   //[ev.npart]
   Double_t        evVz[1];   //[ev.npart]
   Double_t        evP[1];   //[ev.npart]
   Double_t        evPx[1];   //[ev.npart]
   Double_t        evPy[1];   //[ev.npart]
   Double_t        evPz[1];   //[ev.npart]
   Double_t        evTh[1];   //[ev.npart]
   Double_t        evPh[1];   //[ev.npart]
   Double_t        evPhcom;
   Double_t        evThcom;
   Double_t        evXs;
   Double_t        evAsym;
   Double_t        evUnpolWght;
   Double_t        evPolPlusWghtX;
   Double_t        evPolPlusWghtY;
   Double_t        evPolPlusWghtZ;
   Double_t        evPolMinusWghtX;
   Double_t        evPolMinusWghtY;
   Double_t        evPolMinusWghtZ;
   Double_t        evTargMom;
   Int_t           hitN;
   Int_t           hitDet[1];   //[hit.n]
   Int_t           hitVid[1];   //[hit.n]
   Int_t           hitPid[1];   //[hit.n]
   Int_t           hitTrid[1];   //[hit.n]
   Int_t           hitMtrid[1];   //[hit.n]
   Int_t           hitGen[1];   //[hit.n]
   Double_t        hitX[1];   //[hit.n]
   Double_t        hitY[1];   //[hit.n]
   Double_t        hitZ[1];   //[hit.n]
   Double_t        hitLx[1];   //[hit.n]
   Double_t        hitLy[1];   //[hit.n]
   Double_t        hitLz[1];   //[hit.n]
   Double_t        hitPx[1];   //[hit.n]
   Double_t        hitPy[1];   //[hit.n]
   Double_t        hitPz[1];   //[hit.n]
   Double_t        hitVx[1];   //[hit.n]
   Double_t        hitVy[1];   //[hit.n]
   Double_t        hitVz[1];   //[hit.n]
   Double_t        hitVdx[1];   //[hit.n]
   Double_t        hitVdy[1];   //[hit.n]
   Double_t        hitVdz[1];   //[hit.n]
   Double_t        hitP[1];   //[hit.n]
   Double_t        hitE[1];   //[hit.n]
   Double_t        hitM[1];   //[hit.n]

   // List of branches
   TBranch        *b_ev_npart;   //!
   TBranch        *b_evPid;   //!
   TBranch        *b_evVx;   //!
   TBranch        *b_evVy;   //!
   TBranch        *b_evVz;   //!
   TBranch        *b_evP;   //!
   TBranch        *b_evPx;   //!
   TBranch        *b_evPy;   //!
   TBranch        *b_evPz;   //!
   TBranch        *b_evTh;   //!
   TBranch        *b_evPh;   //!
   TBranch        *b_ev_phcom;   //!
   TBranch        *b_ev_thcom;   //!
   TBranch        *b_ev_xs;   //!
   TBranch        *b_ev_asym;   //!
   TBranch        *b_ev_unpolWght;   //!
   TBranch        *b_ev_polPlusWghtX;   //!
   TBranch        *b_ev_polPlusWghtY;   //!
   TBranch        *b_ev_polPlusWghtZ;   //!
   TBranch        *b_ev_polMinusWghtX;   //!
   TBranch        *b_ev_polMinusWghtY;   //!
   TBranch        *b_ev_polMinusWghtZ;   //!
   TBranch        *b_ev_targMom;   //!
   TBranch        *b_hit_n;   //!
   TBranch        *b_hitDet;   //!
   TBranch        *b_hitVid;   //!
   TBranch        *b_hitPid;   //!
   TBranch        *b_hitTrid;   //!
   TBranch        *b_hitMtrid;   //!
   TBranch        *b_hitGen;   //!
   TBranch        *b_hitX;   //!
   TBranch        *b_hitY;   //!
   TBranch        *b_hitZ;   //!
   TBranch        *b_hitLx;   //!
   TBranch        *b_hitLy;   //!
   TBranch        *b_hitLz;   //!
   TBranch        *b_hitPx;   //!
   TBranch        *b_hitPy;   //!
   TBranch        *b_hitPz;   //!
   TBranch        *b_hitVx;   //!
   TBranch        *b_hitVy;   //!
   TBranch        *b_hitVz;   //!
   TBranch        *b_hitVdx;   //!
   TBranch        *b_hitVdy;   //!
   TBranch        *b_hitVdz;   //!
   TBranch        *b_hitP;   //!
   TBranch        *b_hitE;   //!
   TBranch        *b_hitM;   //!

   results_beamOn_C16(TTree *tree=0);
   virtual ~results_beamOn_C16();
   virtual Int_t    Cut(Long64_t entry);
   virtual Int_t    GetEntry(Long64_t entry);
   virtual Long64_t LoadTree(Long64_t entry);
   virtual void     Init(TTree *tree);
   virtual void     Loop();
   virtual Bool_t   Notify();
   virtual void     Show(Long64_t entry = -1);
};

#endif

#ifdef results_beamOn_C16_cxx
results_beamOn_C16::results_beamOn_C16(TTree *tree) : fChain(0)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
   if (tree == 0) {
      TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("results_beamOn_C16.root");
      if (!f || !f->IsOpen()) {
         f = new TFile("results_beamOn_C16.root");
      }
      f->GetObject("T",tree);

   }
   Init(tree);
}

results_beamOn_C16::~results_beamOn_C16()
{
   if (!fChain) return;
   delete fChain->GetCurrentFile();
}

Int_t results_beamOn_C16::GetEntry(Long64_t entry)
{
// Read contents of entry.
   if (!fChain) return 0;
   return fChain->GetEntry(entry);
}
Long64_t results_beamOn_C16::LoadTree(Long64_t entry)
{
// Set the environment to read one entry
   if (!fChain) return -5;
   Long64_t centry = fChain->LoadTree(entry);
   if (centry < 0) return centry;
   if (fChain->GetTreeNumber() != fCurrent) {
      fCurrent = fChain->GetTreeNumber();
      Notify();
   }
   return centry;
}

void results_beamOn_C16::Init(TTree *tree)
{
   // The Init() function is called when the selector needs to initialize
   // a new tree or chain. Typically here the branch addresses and branch
   // pointers of the tree will be set.
   // It is normally not necessary to make changes to the generated
   // code, but the routine can be extended by the user if needed.
   // Init() will be called many times when running on PROOF
   // (once per file to be processed).

   // Set branch addresses and branch pointers
   if (!tree) return;
   fChain = tree;
   fCurrent = -1;
   fChain->SetMakeClass(1);

   fChain->SetBranchAddress("evNpart", &evNpart, &b_ev_npart);
   fChain->SetBranchAddress("evPid", evPid, &b_evPid);
   fChain->SetBranchAddress("evVx", evVx, &b_evVx);
   fChain->SetBranchAddress("evVy", evVy, &b_evVy);
   fChain->SetBranchAddress("evVz", evVz, &b_evVz);
   fChain->SetBranchAddress("evP", evP, &b_evP);
   fChain->SetBranchAddress("evPx", evPx, &b_evPx);
   fChain->SetBranchAddress("evPy", evPy, &b_evPy);
   fChain->SetBranchAddress("evPz", evPz, &b_evPz);
   fChain->SetBranchAddress("evTh", evTh, &b_evTh);
   fChain->SetBranchAddress("evPh", evPh, &b_evPh);
   fChain->SetBranchAddress("evPhcom", &evPhcom, &b_ev_phcom);
   fChain->SetBranchAddress("evThcom", &evThcom, &b_ev_thcom);
   fChain->SetBranchAddress("evXs", &evXs, &b_ev_xs);
   fChain->SetBranchAddress("evAsym", &evAsym, &b_ev_asym);
   fChain->SetBranchAddress("evUnpolWght", &evUnpolWght, &b_ev_unpolWght);
   fChain->SetBranchAddress("evPolPlusWghtX", &evPolPlusWghtX, &b_ev_polPlusWghtX);
   fChain->SetBranchAddress("evPolPlusWghtY", &evPolPlusWghtY, &b_ev_polPlusWghtY);
   fChain->SetBranchAddress("evPolPlusWghtZ", &evPolPlusWghtZ, &b_ev_polPlusWghtZ);
   fChain->SetBranchAddress("evPolMinusWghtX", &evPolMinusWghtX, &b_ev_polMinusWghtX);
   fChain->SetBranchAddress("evPolMinusWghtY", &evPolMinusWghtY, &b_ev_polMinusWghtY);
   fChain->SetBranchAddress("evPolMinusWghtZ", &evPolMinusWghtZ, &b_ev_polMinusWghtZ);
   fChain->SetBranchAddress("evTargMom", &evTargMom, &b_ev_targMom);
   fChain->SetBranchAddress("hitN", &hitN, &b_hit_n);
   fChain->SetBranchAddress("hitDet", hitDet, &b_hitDet);
   fChain->SetBranchAddress("hitVid", hitVid, &b_hitVid);
   fChain->SetBranchAddress("hitPid", hitPid, &b_hitPid);
   fChain->SetBranchAddress("hitTrid", hitTrid, &b_hitTrid);
   fChain->SetBranchAddress("hitMtrid", hitMtrid, &b_hitMtrid);
   fChain->SetBranchAddress("hitGen", hitGen, &b_hitGen);
   fChain->SetBranchAddress("hitX", hitX, &b_hitX);
   fChain->SetBranchAddress("hitY", hitY, &b_hitY);
   fChain->SetBranchAddress("hitZ", hitZ, &b_hitZ);
   fChain->SetBranchAddress("hitLx", hitLx, &b_hitLx);
   fChain->SetBranchAddress("hitLy", hitLy, &b_hitLy);
   fChain->SetBranchAddress("hitLz", hitLz, &b_hitLz);
   fChain->SetBranchAddress("hitPx", hitPx, &b_hitPx);
   fChain->SetBranchAddress("hitPy", hitPy, &b_hitPy);
   fChain->SetBranchAddress("hitPz", hitPz, &b_hitPz);
   fChain->SetBranchAddress("hitVx", hitVx, &b_hitVx);
   fChain->SetBranchAddress("hitVy", hitVy, &b_hitVy);
   fChain->SetBranchAddress("hitVz", hitVz, &b_hitVz);
   fChain->SetBranchAddress("hitVdx", hitVdx, &b_hitVdx);
   fChain->SetBranchAddress("hitVdy", hitVdy, &b_hitVdy);
   fChain->SetBranchAddress("hitVdz", hitVdz, &b_hitVdz);
   fChain->SetBranchAddress("hitP", hitP, &b_hitP);
   fChain->SetBranchAddress("hitE", hitE, &b_hitE);
   fChain->SetBranchAddress("hitM", hitM, &b_hitM);
   Notify();
}

Bool_t results_beamOn_C16::Notify()
{
   // The Notify() function is called when a new file is opened. This
   // can be either for a new TTree in a TChain or when when a new TTree
   // is started when using PROOF. It is normally not necessary to make changes
   // to the generated code, but the routine can be extended by the
   // user if needed. The return value is currently not used.

   return kTRUE;
}

void results_beamOn_C16::Show(Long64_t entry)
{
// Print contents of entry.
// If entry is not specified, print current entry
   if (!fChain) return;
   fChain->Show(entry);
}
Int_t results_beamOn_C16::Cut(Long64_t entry)
{
// This function may be called from Loop.
// returns  1 if entry is accepted.
// returns -1 otherwise.
   return 1;
}
#endif // #ifdef results_beamOn_C16_cxx

Code that attempts to anaylize multiple files:

#ifdef ScatteringAngle_cxx
ScatteringAngle::ScatteringAngle(TTree *tree) : fChain(0)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
   Int_t n = 2;
   TFile * f[n];
   for (Int_t i = 0; i < n; i++){
     if (tree == 0) {
      TString filename = Form("beam_run_%d.root",i+1);
      f[i] = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
      if (!f[i] || !f[i]->IsOpen()) {
         f[i] = new TFile(filename);//("moller_run.root");
        }
        f[i]->GetObject("T",tree);
      }
      /*TFile *f2 = (TFile*)gROOT->GetListOfFiles()->FindObject("beam_run_2.root");
      if (!f2 || !f2->IsOpen()) {
         f2 = new TFile("beam_run_2.root");//("moller_run.root");
      }
      f2->GetObject("T",tree);*/

   }
   Init(tree);
}

This code above tries to chain multiple files together under the function name fChain. Is it possible that I need TChain somewhere for this to look at multiple root files?

#ifdef ScatteringAngle_cxx
ScatteringAngle::ScatteringAngle(TTree *tree) : fChain(0)
{
// if parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
   if (tree == 0) {
      TChain *chain = new TChain("T", "");
      Int_t n = 2;
      for (Int_t i = 0; i < n; i++) {
         chain->Add(Form("beam_run_%d.root", i + 1));
      }
      tree = chain;
   }
   Init(tree);
}

Hello Wile_E_Coyote,

I’ll try this code right now and report back later if there are any issues.

After running the code that chains two root files, it outputs histograms with a # of entries that is equal to only one root file. I’m not sure why it’s still doing that. Any other suggestions?

Generate your analysis skeleton using:

{
  TChain *t = new TChain("T");
  t->Add("beam_run_[12].root");
  // t->Print();
  t->MakeClass("MyAnalysis");
  delete t; // no longer needed
}

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