TTree won't update with new values

ROOT Version: 6.18
Platform: macOS Catalina
Compiler: gcc

I am trying to run a simulation and some reconstruction of the simulated data. I do this in two different pieces of code - that is in one piece of code I create a root file called GeneratedSignals.root with a TTree called SigTree, which I then read in a second piece of code using TTree *readtree = (TTree*)file->Get("SigTree");

After I’ve done the reconstruction I want to save the reconstructed data to new branches in the same TTree as before so that I can then directly compare “truth” level and reconstructed data in a separate macro.

I write the TTree using readtree->Write(nullptr,TObject::kOverwrite); but it won’t overwrite the new branches, meaning that every time I change something I have to rerun both pieces of code.

I feel there must surely be a way of stopping this from happening but I haven’t yet found anything on here that helps.

Here’s a shortened version of the problematic code, and I’m attaching a dropbox link to GeneratedSignals.root as it is immediately after creation with only the truth level values in it:
(https://www.dropbox.com/s/ko49ftskopyrxi6/GeneratedSignals.root?dl=0)

#include <iostream>
#include <vector>
#include "TFile.h"
#include "TTree.h"

#define NPOINTS 1024
#define BinsPerNs 1024./400.
#define NoEventsToPrint 10

Int_t fProcessing = 2;

int main(Int_t argc, char **argv){
  TFile *file = TFile::Open("GeneratedSignals.root","update");
  if (!file) {
    std::cout<<"No file named GeneratedSignals.root found"<<std::endl;
    return 0;
  }
  
  TTree *readtree = (TTree*)file->Get("SigTree");
  //file->GetObject("SigTree",readtree);
  
  Int_t TotEvents=readtree->GetEntries();
  
  Double_t sigfinal[1024];//Final signal - what the DAQ would register, so the sum of all individual hits
  Double_t  sigProc[NPOINTS];

  Int_t EventIndex;//Index of event
  Int_t HitsPerEvent;//Number of hits per event
  Int_t tbins[NPOINTS];//Time in bins
  
  std::vector<Int_t> *HitTimes = 0;//Hit arrival time in bins
  std::vector<Double_t> *HitAmp = 0;//Hit amplitude

  //read branches written in SignalGeneratorToy.cpp
  readtree->SetBranchAddress("SigFinal",sigfinal);
  readtree->SetBranchAddress("EventNo",&EventIndex);
  readtree->SetBranchAddress("HitsPerEvent",&HitsPerEvent);
  readtree->SetBranchAddress("HitTimes",&HitTimes);//Hit arrival time in bins
  readtree->SetBranchAddress("HitAmplitude",&HitAmp);
  readtree->SetBranchAddress("TBins",&tbins);//Runs from 1 to 1024

  std::vector<Double_t> *tProcRecoBins= new std::vector<Double_t>; //Reconstructed hit times from TSpectrum on raw data
  std::vector<Double_t> *tUnProcRecoBins =new std::vector<Double_t>; //Reconstructed hit times from TSpectrum on RRC processed data

  Int_t NoRecoUnProc=0;//Number of hits reconstructed by TSpectrum without digital processing
  Int_t NoRecoProc=0;//Number of hits reconstructed by TSpectrum from digitally processed signals

  //create new branch for reconstructed time
  TBranch *BTRecoUnProc=readtree->Branch("TRecoUnProc","vector<Double_t>",&tUnProcRecoBins);
  TBranch *BTRecoProc  =readtree->Branch("TRecoProc","vector<Double_t>",&tProcRecoBins);
  TBranch *BNoRecoUnProc=readtree->Branch("NoRecoUnProc",&NoRecoUnProc,"NoRecoUnProc/I");
  TBranch *BNoRecoProc=readtree->Branch("NoRecoProc",&NoRecoProc,"NoRecoProc/I");
  
  readtree->Print();
  std::cout<<TotEvents<<std::endl;

  for(Int_t eventno=0;eventno<TotEvents;eventno++){
    readtree->GetEntry(eventno);
    tProcRecoBins->clear();
    tUnProcRecoBins->clear();

    //Changing these variables and rerunning only this piece of code doesn't update the TTree
    NoRecoUnProc = 10;
    tUnProcRecoBins->push_back(6);
    
    if(fProcessing==2){
      NoRecoProc = 20;
      tProcRecoBins->push_back(12);
    }

    if(fProcessing==1&&eventno%100==0) std::cout<<"Event "<<eventno<<" HitsPerEvent "<<HitsPerEvent<<" NoRecoUnProc "<<NoRecoUnProc<<std::endl;
    if(fProcessing==2&&eventno%100==0) std::cout<<"Event "<<eventno<<" HitsPerEvent "<<HitsPerEvent<<" NoRecoUnProc "<<NoRecoUnProc<<" NoRecoProc "<<NoRecoProc<<std::endl;

    BNoRecoUnProc->Fill();
    BNoRecoProc->Fill();
    BTRecoUnProc->Fill();
    BTRecoProc->Fill();
  }
  
  readtree->Write(nullptr,TObject::kOverwrite);
  
  delete file;
}

See “${ROOTSYS}/tutorials/tree/copytree*.C” tutorials (particularly if you want to modify some existing branches).

Thanks for the reply but I don’t understand how to apply this to my case. I don’t want to copy a subset of an old tree to a new tree, rather I want to add new entries to an old tree…

I don’t think I understand your problem.
After i run your macro, the tree in the file is modified (it gets four new branches and they seem to be filled):

SigTree->Print();
SigTree->Scan("TRecoUnProc:TRecoProc:NoRecoUnProc:NoRecoProc");

Humm … this implies that your have 3 steps:

  • Write main tree part.
  • Open the same file in update mode, add branches …

so far, if I understood correctly, it all works.

  • Open the same file again and add the 2nd set of branches again

If that the case you will end up with the data in the file but you will have duplicate branches (several branches with the same name).

So major question before proceeding, is the intent of the 3rd steps to add more branches or to replace the 2nd set of branches?

The point of step 3 would be to replace the data in the new branches. If I change the reconstruction that I do in step 2/3, or if I’ve made a mistake in step 2 or for any reason I want to do step 2 again without doing step 1 again, I would like to be able to do so.
Currently when I do step 2 a second time (so that it becomes step 3) the file isn’t re-written - the data that was inserted into the new branches in step 2 stays there and is not updated. This is the problem.
I’ve tried deleting the new branches before re-adding them but this always results either in the code not compiling or in a segmentation violation when I run it.

It seems to me that the best idea would be to (re)create a separate new tree with these new branches only (e.g. in a separate new file) and then simply use the standard “TTree friends” mechanism.

1 Like

That works a charm. Thanks!

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