Logo ROOT   6.21/01
Reference Guide
THnChain.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 // Author: Benjamin Bannier, August 2016
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "THnChain.h"
13 
14 #include "TArray.h"
15 #include "TAxis.h"
16 #include "TDirectory.h"
17 #include "TFile.h"
18 #include "TH1.h"
19 #include "TH2.h"
20 #include "TH3.h"
21 #include "THnBase.h"
22 #include "TMath.h"
23 
24 void THnChain::AddFile(const char* fileName)
25 {
26  fFiles.emplace_back(fileName);
27 
28  // Initialize axes from first seen instance.
29  if (fAxes.empty()) {
30  THnBase* hs = ReadHistogram(fileName);
31 
32  if (hs) {
33  const Int_t naxes = hs->GetNdimensions();
34  for (Int_t i = 0; i < naxes; ++i) {
35  fAxes.push_back(hs->GetAxis(i));
36  }
37  } else {
38  Warning("AddFile",
39  "Could not find histogram %s in file %s",
40  fName.c_str(),
41  fileName);
42  }
43  }
44 }
45 
47 {
48  if (i < 0 || i >= static_cast<Int_t>(fAxes.size())) {
49  return nullptr;
50  }
51 
52  return fAxes[i];
53 }
54 
55 TObject* THnChain::ProjectionAny(Int_t ndim, const Int_t* dim, Option_t* option) const
56 {
57  if (ndim <= 0) {
58  return nullptr;
59  }
60 
61  TObject* h_merged = nullptr;
62  for (const auto& file : fFiles) {
63  THnBase* hs = ReadHistogram(file.c_str());
64 
65  if (!hs) {
66  Warning("ProjectionAny",
67  "Could not find histogram %s in file %s",
68  fName.c_str(),
69  file.c_str());
70 
71  continue;
72  }
73 
74  if (!CheckConsistency(*hs, fAxes)) {
75  Warning("ProjectionAny",
76  "Histogram %s from file %s is inconsistent with the histogram from file %s",
77  fName.c_str(),
78  file.c_str(),
79  fFiles[0].c_str());
80 
81  continue;
82  }
83 
84  SetupAxes(*hs);
85 
86  // Perform projection.
87  TObject* h = nullptr;
88 
89  if (ndim == 1) {
90  h = hs->Projection(dim[0], option);
91  } else if (ndim == 2) {
92  h = hs->Projection(dim[0], dim[1], option);
93  } else if (ndim == 3) {
94  h = hs->Projection(dim[0], dim[1], dim[2], option);
95  } else {
96  h = hs->ProjectionND(ndim, dim, option);
97  }
98 
99  delete hs;
100 
101  // Add this histogram.
102  if (h_merged) {
103  if (ndim < 3) {
104  static_cast<TH1*>(h_merged)->Add(static_cast<TH1*>(h));
105  } else {
106  static_cast<THnBase*>(h_merged)->Add(static_cast<THnBase*>(h));
107  }
108 
109  delete h;
110  } else {
111  h_merged = h;
112  }
113  }
114 
115  return h_merged;
116 }
117 
118 THnBase* THnChain::ReadHistogram(const char* fileName) const
119 {
121 
122  TFile* f = TFile::Open(fileName);
123 
124  if (!f) {
125  return nullptr;
126  }
127 
128  THnBase* hs = nullptr;
129  f->GetObject(fName.c_str(), hs);
130  delete f;
131 
132  return hs;
133 }
134 
136 {
137  const Int_t naxes = fAxes.size();
138  for (Int_t i = 0; i < naxes; ++i) {
139  const TAxis* ax_ref = fAxes[i];
140  TAxis* ax = hs.GetAxis(i);
141  ax_ref->Copy(*ax);
142  }
143 }
144 
145 bool THnChain::CheckConsistency(const THnBase& h, const std::vector<TAxis*>& axes)
146 {
147  // We would prefer to directly use `TH1::CheckEqualAxes` here;
148  // however it is protected so we inherit the parts we care about.
149  // FIXME(bbannier): It appears that functionality like `TH1::CheckEqualAxes` could
150  // just as well live in `TAxis` so that anyone using axes could make use of it.
151  const Int_t naxes = h.GetNdimensions();
152  const Int_t naxes2 = axes.size();
153 
154  if (naxes != naxes2) {
155  return false;
156  }
157 
158  for (Int_t i = 0; i < naxes; ++i) {
159  const TAxis* ax1 = h.GetAxis(i);
160  const TAxis* ax2 = axes[i];
161 
162  if (ax1->GetNbins() != ax2->GetNbins()) {
163  return false;
164  }
165 
166  // Copied from `TH1::CheckAxisLimits.`
167  if (!TMath::AreEqualRel(ax1->GetXmin(), ax2->GetXmin(), 1.E-12) ||
168  !TMath::AreEqualRel(ax1->GetXmax(), ax2->GetXmax(), 1.E-12)) {
169  return false;
170  }
171 
172  // Copied from `TH1::CheckBinLimits`.
173  const TArrayD* h1Array = ax1->GetXbins();
174  const TArrayD* h2Array = ax2->GetXbins();
175  Int_t fN = h1Array->fN;
176  if (fN != 0) {
177  if (h2Array->fN != fN) {
178  return false;
179  } else {
180  for (int ibin = 0; ibin < fN; ++ibin) {
181  if (!TMath::AreEqualRel(h1Array->GetAt(ibin), h2Array->GetAt(ibin), 1E-10)) {
182  return false;
183  }
184  }
185  }
186  }
187 
188  // We ignore checking for equal bin labels here. A check
189  // for that is implemented in `TH1::CheckBinLabels`.
190  }
191 
192  return true;
193 }
194 
195 TH1* THnChain::Projection(Int_t xDim, Option_t* option) const
196 {
197  // Forwards to `THnBase::Projection()`.
198  Int_t dim[1] = {xDim};
199  return static_cast<TH1*>(ProjectionAny(1, dim, option));
200 }
201 
202 TH2* THnChain::Projection(Int_t yDim, Int_t xDim, Option_t* option) const
203 {
204  // Forwards to `THnBase::Projection()`.
205  Int_t dim[2] = {xDim, yDim};
206  return static_cast<TH2*>(ProjectionAny(2, dim, option));
207 }
208 
209 TH3* THnChain::Projection(Int_t xDim, Int_t yDim, Int_t zDim, Option_t* option) const
210 {
211  // Forwards to `THnBase::Projection()`.
212  Int_t dim[3] = {xDim, yDim, zDim};
213  return static_cast<TH3*>(ProjectionAny(3, dim, option));
214 }
215 
216 THnBase* THnChain::ProjectionND(Int_t ndim, const Int_t* dim, Option_t* option) const
217 {
218  // Forwards to `THnBase::ProjectionND()`.
219  return static_cast<THnBase*>(ProjectionAny(ndim, dim, option));
220 }
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3925
const char Option_t
Definition: RtypesCore.h:62
static bool CheckConsistency(const THnBase &h, const std::vector< TAxis *> &axes)
Ensure a histogram has axes similar to the ones we expect.
Definition: THnChain.cxx:145
TObject * ProjectionAny(Int_t ndim, const Int_t *dim, Option_t *option="") const
Projects all histograms in the chain.
Definition: THnChain.cxx:55
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:48
std::string fName
name of the histogram
Definition: THnChain.h:87
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
virtual void Copy(TObject &axis) const
Copy axis structure to another axis.
Definition: TAxis.cxx:208
Double_t GetXmin() const
Definition: TAxis.h:133
void Add(RHist< DIMENSIONS, PRECISION, STAT_TO... > &to, const RHist< DIMENSIONS, PRECISION, STAT_FROM... > &from)
Add two histograms.
Definition: RHist.hxx:320
TH1D * Projection(Int_t xDim, Option_t *option="") const
Project all bins into a 1-dimensional histogram, keeping only axis "xDim".
Definition: THnBase.h:197
The 3-D histogram classes derived from the 1-D histogram classes.
Definition: TH3.h:31
TH1 * Projection(Int_t xDim, Option_t *option="") const
See THnBase::Projection for the intended behavior.
Definition: THnChain.cxx:195
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Definition: TMath.h:418
TAxis * GetAxis(Int_t i) const
Get an axis from the histogram.
Definition: THnChain.cxx:46
Int_t fN
Definition: TArray.h:38
void SetupAxes(THnBase &hs) const
Copy the properties of all axes to a histogram.
Definition: THnChain.cxx:135
TAxis * GetAxis(Int_t dim) const
Definition: THnBase.h:125
Service class for 2-Dim histogram classes.
Definition: TH2.h:30
Class to manage histogram axis.
Definition: TAxis.h:30
std::vector< std::string > fFiles
a list of files to extract the histogram from
Definition: THnChain.h:89
constexpr Double_t E()
Base of natural log: .
Definition: TMath.h:97
#define h(i)
Definition: RSha256.hxx:106
THnBase * ProjectionND(Int_t ndim, const Int_t *dim, Option_t *option="") const
Definition: THnBase.h:228
The TH1 histogram class.
Definition: TH1.h:56
Array of doubles (64 bits per element).
Definition: TArrayD.h:27
Int_t GetNdimensions() const
Definition: THnBase.h:135
Mother of all ROOT objects.
Definition: TObject.h:37
Small helper to keep current directory context.
Definition: TDirectory.h:41
std::vector< TAxis * > fAxes
the list of histogram axes
Definition: THnChain.h:90
Definition: file.py:1
THnBase * ReadHistogram(const char *fileName) const
Retrieve a histogram from a file.
Definition: THnChain.cxx:118
Double_t GetAt(Int_t i) const
Definition: TArrayD.h:45
THnBase * ProjectionND(Int_t ndim, const Int_t *dim, Option_t *option="") const
See THnBase::Projection for the intended behavior.
Definition: THnChain.cxx:216
#define gDirectory
Definition: TDirectory.h:223
void AddFile(const char *fileName)
Add a new file to this chain.
Definition: THnChain.cxx:24
Multidimensional histogram base.
Definition: THnBase.h:43
Int_t GetNbins() const
Definition: TAxis.h:121
Double_t GetXmax() const
Definition: TAxis.h:134
const TArrayD * GetXbins() const
Definition: TAxis.h:130
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866