Storing a TH1 object in a TTree

I have a TTree that I would like to store a histogram for each event in. I have the following code:

void storeData(vector<Result> &results, string filename, TH1 *sideband = 0x0, TH1 *signal = 0x0) {
  // Ok, so lets open a root file and create some leafs

  Result tmpres;

  TFile output(filename.c_str(), "RECREATE");
  TTree *tree = new TTree("results", "results", 0);

  tree->Branch("delta", &tmpres.delta, "delta/D");
  tree->Branch("obs", &tmpres.obs, "obs/D");
  tree->Branch("obs_err", &tmpres.obs_err, "obs_err/D");
  tree->Branch("exp", &tmpres.exp, "exp/D");
  tree->Branch("exp_err", &tmpres.exp_err, "exp_err/D");
  tree->Branch("pull", &tmpres.pull, "pull/D");
  tree->Branch("side_fit_status", &tmpres.side_fit_status, "side_fit_status/I");
  tree->Branch("side_cov_status", &tmpres.side_cov_status, "side_cov_status/I");
  tree->Branch("signal_fit_status", &tmpres.signal_fit_status, "signal_fit_status/I");
  tree->Branch("signal_cov_status", &tmpres.signal_cov_status, "signal_cov_status/I");
  tree->Branch("norm", &tmpres.norm, "norm/D");
  tree->Branch("norm_err", &tmpres.norm_err, "norm_err/D");
  tree->Branch("offset", &tmpres.offset, "offset/D");
  tree->Branch("offset_err", &tmpres.offset_err, "offset_err/D");
  tree->Branch("power", &tmpres.power, "power/D");
  tree->Branch("power_err", &tmpres.power_err, "power_err/D");
  tree->Branch("coeff1", &tmpres.coeff1, "coeff1/D");
  tree->Branch("coeff1_err", &tmpres.coeff1_err, "coeff1_err/D");
  tree->Branch("coeff2", &tmpres.coeff2, "coeff2/D");
  tree->Branch("coeff2_err", &tmpres.coeff2_err, "coeff2_err/D");

  tree->Branch("signal_histogram", "TH1D", &tmpres.signal_histo, sizeof(TH1D), 0);
  tree->Branch("sideband_histogram", "TH1D", &tmpres.sideband_histo, sizeof(TH1D), 0);

  for(int i = 0; i < results.size(); i++) {
    tmpres = results.at(i);
    tree->Fill();
  }

  if(sideband != 0x0) {
    sideband->Write();
  }

  if(signal != 0x0) {
    signal->Write();
  }

  output.Write();
  output.Close();
}

Where the Results structure is defined in the following way:

typedef struct {
  double delta;
  double obs;
  double obs_err;
  double exp;
  double exp_err;
  double pull;
  int side_fit_status;
  int side_cov_status;
  int signal_fit_status;
  int signal_cov_status;
  double norm;
  double norm_err;
  double offset;
  double offset_err;
  double power;
  double power_err;
  double coeff1;
  double coeff1_err;
  double coeff2;
  double coeff2_err;
  TH1D signal_histo;
  TH1D sideband_histo;
} Result;

When I run I get a segfault with the following backtrace:

#0  0xfffffe90 in ?? ()
#1  0xb7abae1b in TObject::Streamer () from /usr/lib/root/libCore.so.5.18
#2  0xb7346d36 in TStreamerInfo::WriteBufferAux<char**> () from /usr/lib/root/libRIO.so.5.18
#3  0xb72c4b37 in TBufferFile::WriteClassBuffer () from /usr/lib/root/libRIO.so.5.18
#4  0xb7d18c64 in TNamed::Streamer () from /usr/lib/root/libCore.so.5.18
#5  0xb7346676 in TStreamerInfo::WriteBufferAux<char**> () from /usr/lib/root/libRIO.so.5.18
#6  0xb72c4b37 in TBufferFile::WriteClassBuffer () from /usr/lib/root/libRIO.so.5.18
#7  0xb6f7d42d in TH1::Streamer () from /usr/lib/root/libHist.so.5.18
#8  0xb712afca in TH1::StreamerNVirtual () from /usr/lib/root/libHist.so.5.18
#9  0xb710bb28 in G__G__Hist_106_0_211 () from /usr/lib/root/libHist.so.5.18
#10 0xb7427fce in Cint::G__CallFunc::Execute () from /usr/lib/root/libCint.so.5.18
#11 0xb7b52841 in TMethodCall::Execute () from /usr/lib/root/libCore.so.5.18
#12 0xb7b55576 in TStreamerBase::WriteBuffer () from /usr/lib/root/libCore.so.5.18
#13 0xb73471fd in TStreamerInfo::WriteBufferAux<char**> () from /usr/lib/root/libRIO.so.5.18
#14 0xb69609b3 in TBranchElement::FillLeaves () from /usr/lib/root/libTree.so.5.18
#15 0xb6952c3e in TBranch::Fill () from /usr/lib/root/libTree.so.5.18
#16 0xb696029b in TBranchElement::Fill () from /usr/lib/root/libTree.so.5.18
#17 0xb69959ed in TTree::Fill () from /usr/lib/root/libTree.so.5.18
#18 0x0805363c in storeData (results=@0xbfcbbaa8, filename=
        {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xbfcbbfe0 "\234$a\b.N=ö\020I1\b@ÕC\bàíC\bè\003"}}, sideband=0x8314910, signal=0x843d540) at check.cc:124
#19 0x08054146 in main () at check.cc:234

Am I totally off the mark here? Thanks for any info.

Hi,

Which version of ROOT are using? Until v5.19/04, the only option to create a branch with an object is to pass a pointer to a pointer to the object (i.e. your struct would need to contains TH1D *signal_histo; TH1D *sideband_histo; } Result; If you have a newer version then you ought to create the branches with:tree->Branch("signal_histogram", &tmpres.signal_histo, sizeof(TH1D), 0); tree->Branch("sideband_histogram", &tmpres.sideband_histo, sizeof(TH1D), 0);
Also in term of efficiency you may want to create basket/buffer than hold more than one histogram (ie instead of sizeof(TH1D) use a larger number).

Cheers,
Philippe.