Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8308851
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Subscribers
None
View Options
diff --git a/include/YODA/ROOTCnv.h b/include/YODA/ROOTCnv.h
--- a/include/YODA/ROOTCnv.h
+++ b/include/YODA/ROOTCnv.h
@@ -1,476 +1,480 @@
// -*- C++ -*-
//
// This file is part of YODA -- Yet more Objects for Data Analysis
// Copyright (C) 2008-2015 The YODA collaboration (see AUTHORS for details)
//
#ifndef YODA_ROOTCnv_h
#define YODA_ROOTCnv_h
#include "YODA/Histo1D.h"
#include "YODA/Histo2D.h"
#include "YODA/Profile1D.h"
#include "TH1.h"
#include "TH2.h"
#include "TProfile.h"
#include "TGraphAsymmErrors.h"
#include "TVectorF.h"
namespace YODA {
/// @name Conversion functions from ROOT to YODA data types
//@{
/// @todo Check that direct Scatter filling gives the same result at mkScatter(h) for ROOT -> YODA
/// @todo toProfile1D: TProfile -> Profile1D
/// @todo toScatter2D: TGraph(AsymmErrs) -> Scatter2D
// /// @brief Convert a ROOT 1D histogram to a YODA Histo1D
// ///
// /// Note that ROOT's histograms do not contain enough information to properly rebuild
// /// @a x distributions within bins, in underflow and overflow bins, or across the whole histogram.
// inline Histo1D toHisto1D(const TH1& th1) {
// std::vector<HistoBin1D> bins;
// TArrayD sumw2s = *th1.GetSumw2();
// Dbn1D dbn_uflow, dbn_oflow;
// double sumWtot(0), sumW2tot(0)
// for (int i = 0; i =< th1.GetNbinsX()+1; ++i) {
// Dbn1D dbn(static_cast<unsigned long>(th1.GetBinContent(i)), th1.GetBinContent(i), sumw2s[i], 0, 0);
// // th1.GetBinContent(i)*th1.GetBinCenter(i), th1.GetBinContent(i)*sqr(th1.GetBinCenter(i)));
// if (i == 0) dbn_uflow = dbn;
// else if (i == th1.GetNbinsX()+1) dbn_oflow = dbn;
// else bins.push_back(HistoBin1D(std::make_pair(th1.GetBinLowEdge(i), th1.GetBinLowEdge(i+1)), dbn));
// sumWtot += th1.GetBinContent(i);
// sumW2tot += sumw2s[i];
// }
// Dbn1D dbn_tot(static_cast<unsigned long>(th1.GetEntries()), sumWtot, sumW2tot, 0, 0);
// Histo1D rtn(bins, dbn_tot, dbn_uflow, const Dbn1D& dbn_oflow, th1.GetName(), th1.GetTitle());
// rtn.addAnnotation("XLabel", th1.GetXaxis->GetTitle());
// rtn.addAnnotation("YLabel", th1.GetYaxis->GetTitle());
// return rtn;
// }
// /// @brief Convert a ROOT 1D histogram to a YODA Histo1D
// ///
// /// Note that ROOT's histograms do not contain enough information to properly rebuild
// /// @a x distributions within bins, in underflow and overflow bins, or across the whole histogram.
// inline Histo1D toHisto1D(const TH1* th1) {
// return toHisto1D(*th1);
// }
/////////////////////
/// Convert a ROOT 1D histogram (excluding TProfile) to a YODA Scatter2D
///
/// The optional bool arg specifies whether or not to divide y vals/errs by bin width.
inline Scatter2D toScatter2D(const TH1& th1, bool scalebywidth=true) {
Scatter2D rtn;
for (int ix = 1; ix <= th1.GetNbinsX(); ++ix) {
const TAxis& axx = *th1.GetXaxis();
const double x = axx.GetBinCenter(ix);
const double exminus = x - axx.GetBinLowEdge(ix);
const double explus = axx.GetBinUpEdge(ix) - x;
const double xwidth = axx.GetBinWidth(ix);
//
const double val = th1.GetBinContent(ix) / (scalebywidth ? xwidth : 1);
const double evalminus = th1.GetBinErrorLow(ix) / (scalebywidth ? xwidth : 1);
const double evalplus = th1.GetBinErrorUp(ix) / (scalebywidth ? xwidth : 1);
rtn.addPoint(x, val,
exminus, explus,
evalminus, evalplus);
}
+ rtn.setPath(th1.GetName());
+ rtn.setTitle(th1.GetTitle());
rtn.addAnnotation("XLabel", th1.GetXaxis()->GetTitle());
rtn.addAnnotation("YLabel", th1.GetYaxis()->GetTitle());
return rtn;
}
/// Convert a ROOT 1D histogram (excluding TProfile) to a YODA Scatter2D
inline Scatter2D toScatter2D(const TH1* th1, bool scalebywidth=true) {
if (th1 == NULL) throw UserError("Null TH1 pointer passed as argument");
return toScatter2D(*th1, scalebywidth);
}
/// Convert a ROOT 1D histogram (excluding TProfile) to a new'd YODA Scatter2D
inline Scatter2D* toNewScatter2D(const TH1& th1, bool scalebywidth=true) {
return toScatter2D(th1, scalebywidth).newclone();
}
/// Convert a ROOT 1D histogram (excluding TProfile) to a new'd YODA Scatter2D
inline Scatter2D* toNewScatter2D(const TH1* th1, bool scalebywidth=true) {
return toScatter2D(th1, scalebywidth).newclone();
}
////////////////
/// Convert a ROOT TProfile to a YODA Scatter2D
inline Scatter2D toScatter2D(const TProfile& tp1) {
return toScatter2D((TH1&)tp1, false);
}
/// Convert a ROOT TProfile to a YODA Scatter2D
inline Scatter2D toScatter2D(const TProfile* tp1) {
if (tp1 == NULL) throw UserError("Null TProfile pointer passed as argument");
return toScatter2D(*tp1); //< TProfile inherits from TH1, so this just uses the function above
}
/// Convert a ROOT TProfile to a new'd YODA Scatter2D
inline Scatter2D* toNewScatter2D(const TProfile& tp1) {
return toScatter2D(tp1).newclone();
}
/// Convert a ROOT TProfile to a new'd YODA Scatter2D
inline Scatter2D* toNewScatter2D(const TProfile* tp1) {
return toScatter2D(tp1).newclone();
}
/////////////////////
/// Convert a ROOT 2D histogram to a YODA Scatter3D
///
/// The optional bool arg specifies whether or not to divide y vals/errs by bin area.
inline Scatter3D toScatter3D(const TH2& th2, bool scalebyarea=true) {
Scatter3D rtn;
for (int ix = 1; ix <= th2.GetNbinsX(); ++ix) {
for (int iy = 1; iy <= th2.GetNbinsY(); ++iy) {
const TAxis& axx = *th2.GetXaxis();
const double x = axx.GetBinCenter(ix);
const double exminus = x - axx.GetBinLowEdge(ix);
const double explus = axx.GetBinUpEdge(ix) - x;
const double xwidth = axx.GetBinWidth(ix);
//
const TAxis& axy = *th2.GetYaxis();
const double y = axy.GetBinCenter(iy);
const double eyminus = y - axy.GetBinLowEdge(iy);
const double eyplus = axy.GetBinUpEdge(iy) - y;
const double ywidth = axy.GetBinWidth(iy);
//
const int ixy = th2.GetBin(ix, iy);
const double area = xwidth*ywidth;
const double val = th2.GetBinContent(ixy) / (scalebyarea ? area : 1);
const double evalminus = th2.GetBinErrorLow(ixy) / (scalebyarea ? area : 1);
const double evalplus = th2.GetBinErrorUp(ixy) / (scalebyarea ? area : 1);
rtn.addPoint(x, y, val,
exminus, explus,
eyminus, eyplus,
evalminus, evalplus);
}
}
+ rtn.setPath(th2.GetName());
+ rtn.setTitle(th2.GetTitle());
rtn.addAnnotation("XLabel", th2.GetXaxis()->GetTitle());
rtn.addAnnotation("YLabel", th2.GetYaxis()->GetTitle());
- rtn.addAnnotation("YLabel", th2.GetZaxis()->GetTitle());
+ rtn.addAnnotation("ZLabel", th2.GetZaxis()->GetTitle());
return rtn;
}
/// Convert a ROOT 2D histogram to a YODA Scatter3D
inline Scatter3D toScatter3D(const TH2* th2, bool scalebyarea=true) {
if (th2 == NULL) throw UserError("Null TH2 pointer passed as argument");
return toScatter3D(*th2, scalebyarea);
}
/// Convert a ROOT 2D histogram to a new'd YODA Scatter3D
inline Scatter3D* toNewScatter3D(const TH2& th2, bool scalebyarea=true) {
return toScatter3D(th2).newclone();
}
/// Convert a ROOT 2D histogram to a new'd YODA Scatter3D
inline Scatter3D* toNewScatter3D(const TH2* th2, bool scalebyarea=true) {
return toScatter3D(th2).newclone();
}
////////////////////
/// @todo Add toScatter2D(TGraph&/*) and toScatter3D(TGraph2D&/*)
//@}
/////////////////////
/// @name Conversion functions from YODA to ROOT data types
//@{
/// @brief Convert a YODA Histo1D to a ROOT 1D histogram
///
/// @todo Check/improve/extend -- needs SetBinError or not?
inline TH1D toTH1D(const Histo1D& h) {
// Work out bin edges first
std::vector<double> edges;
edges.reserve(h.numBins()+1);
edges.push_back(h.bin(0).xMin());
for (size_t i = 0; i < h.numBins(); ++i) {
const HistoBin1D& b = h.bin(i);
if (!fuzzyEquals(edges.back(), b.xMin())) edges.push_back(b.xMin());
if (!fuzzyEquals(edges.back(), b.xMax())) edges.push_back(b.xMax());
}
// Book ROOT histogram
TH1D rtn(h.path().c_str(), h.title().c_str(), edges.size()-1, &edges[0]);
rtn.Sumw2();
TArrayD& sumw2s = *rtn.GetSumw2();
for (int i = 1; i <= rtn.GetNbinsX(); ++i) {
try {
const HistoBin1D& b = h.binAt(rtn.GetBinCenter(i)); // throws if in a gap
rtn.SetBinContent(i, b.sumW());
sumw2s[i] = b.sumW2();
} catch (const Exception& e) { }
}
// Overflows
rtn.SetBinContent(0, h.underflow().sumW());
rtn.SetBinContent(rtn.GetNbinsX()+1, h.overflow().sumW());
sumw2s[0] = h.underflow().sumW2();
sumw2s[rtn.GetNbinsX()+1] = h.overflow().sumW2();
// Labels
if (h.hasAnnotation("XLabel")) rtn.SetXTitle(h.annotation("XLabel").c_str());
if (h.hasAnnotation("YLabel")) rtn.SetYTitle(h.annotation("YLabel").c_str());
return rtn;
}
/// @brief Convert a YODA Histo1D to a ROOT 1D histogram as new'd pointer
inline TH1D* toNewTH1D(const Histo1D& h, const std::string& rootname) {
return (TH1D*) toTH1D(h).Clone(rootname.c_str());
}
/// @brief Convert a YODA Histo2D to a ROOT 2D histogram
///
/// @todo Check/improve/extend -- needs SetBinError or not?
inline TH2D toTH2D(const Histo2D& h) {
// Work out bin edges first
std::vector<double> xedges, yedges;
xedges.reserve(h.numBins()+1);
yedges.reserve(h.numBins()+1);
xedges.push_back(h.bin(0).xMin());
yedges.push_back(h.bin(0).yMin());
for (size_t i = 0; i < h.numBins(); ++i) {
const HistoBin2D& b = h.bin(i);
xedges.push_back(b.xMin());
xedges.push_back(b.xMax());
yedges.push_back(b.yMin());
yedges.push_back(b.yMax());
}
// Sort and remove (fuzzy) duplicate edges
std::sort(xedges.begin(), xedges.end());
std::sort(yedges.begin(), yedges.end());
const std::vector<double>::iterator xlast = std::unique(xedges.begin(), xedges.end());
const std::vector<double>::iterator ylast = std::unique(yedges.begin(), yedges.end());
xedges.erase(xlast, xedges.end());
yedges.erase(ylast, yedges.end());
// Book ROOT histogram
TH2D rtn(h.path().c_str(), h.title().c_str(), xedges.size()-1, &xedges[0], yedges.size()-1, &yedges[0]);
rtn.Sumw2();
TArrayD& sumw2s = *rtn.GetSumw2();
for (int ix = 1; ix <= rtn.GetNbinsX(); ++ix) {
for (int iy = 1; iy <= rtn.GetNbinsY(); ++iy) {
const int i = rtn.GetBin(ix, iy);
try {
//const HistoBin2D& b = h.binAt(rtn.GetBinCenter(ix), rtn.GetBinCenter(iy)); // throws if in a gap
const HistoBin2D& b = h.binAt(rtn.GetXaxis()->GetBinCenter(ix), rtn.GetYaxis()->GetBinCenter(iy)); // throws if in a gap
rtn.SetBinContent(i, b.sumW());
sumw2s[i] = b.sumW2();
} catch (const Exception& e) { }
}
}
// Overflows
/// @todo Connect up when supported in YODA... if 2D overflows are possible in ROOT?!
// rtn.SetBinContent(0, h.underflow().sumW());
// rtn.SetBinContent(rtn.GetNbinsX()+1, h.overflow().sumW());
// sumw2s[0] = h.underflow().sumW2();
// sumw2s[rtn.GetNbinsX()+1] = h.overflow().sumW2();
// Labels
if (h.hasAnnotation("XLabel")) rtn.SetXTitle(h.annotation("XLabel").c_str());
if (h.hasAnnotation("YLabel")) rtn.SetYTitle(h.annotation("YLabel").c_str());
if (h.hasAnnotation("ZLabel")) rtn.SetZTitle(h.annotation("ZLabel").c_str());
return rtn;
}
/// @brief Convert a YODA Histo2D to a ROOT 2D histogram as new'd pointer
inline TH2D* toNewTH2D(const Histo2D& h, const std::string& rootname) {
return (TH2D*) toTH2D(h).Clone(rootname.c_str());
}
/// @brief Convert a YODA Scatter2D to a ROOT TH1D
/// @brief Convert a YODA Profile1D to a ROOT TProfile
///
/// @warning Reported not to work, and maybe not to be possible at all...
///
/// @todo Check/improve/extend. How to set all the y-weights in ROOT profiles?
inline TProfile toTProfile(const Profile1D& p) {
// Work out bin edges first
std::vector<double> edges;
edges.reserve(p.numBins()+1);
edges.push_back(p.bin(0).xMin());
for (size_t i = 0; i < p.numBins(); ++i) {
const ProfileBin1D& b = p.bin(i);
if (!fuzzyEquals(edges.back(), b.xMin())) edges.push_back(b.xMin());
if (!fuzzyEquals(edges.back(), b.xMax())) edges.push_back(b.xMax());
}
// Book ROOT histogram
TProfile rtn(p.path().c_str(), p.title().c_str(), edges.size()-1, &edges[0]);
rtn.Sumw2();
Double_t* sumwys = rtn.GetArray(); //< YUCK!!!
TArrayD& sumwy2s = *rtn.GetSumw2(); //< YUCK!!!
for (int i = 1; i <= rtn.GetNbinsX(); ++i) {
try {
const ProfileBin1D& b = p.binAt(rtn.GetBinCenter(i)); // throws if in a gap
// rtn.SetBinContent(i, b.mean());
// rtn.SetBinError(i, b.stdErr());
/// @todo Need to set the following, according to Roman Lysak:
// - for sum(y*y): TProfile::GetSumw2()
// - for sum(y): TProfile::GetArray()
// - for sum(w): TProfile::SetBinEntries(bin, w)
// Clearly, the names of accessors/methods are confusing...
rtn.SetBinEntries(i, b.sumW());
sumwys[i] = b.sumWY();
sumwy2s[i] = b.sumWY2();
} catch (const Exception& e) { }
}
// Overflows
rtn.SetBinEntries(0, p.underflow().sumW());
rtn.SetBinEntries(rtn.GetNbinsX()+1, p.overflow().sumW());
sumwys[0] = p.underflow().sumWY();
sumwys[0] = p.underflow().sumWY();
sumwy2s[rtn.GetNbinsX()+1] = p.overflow().sumWY2();
sumwy2s[rtn.GetNbinsX()+1] = p.overflow().sumWY2();
// Labels
if (p.hasAnnotation("XLabel")) rtn.SetXTitle(p.annotation("XLabel").c_str());
if (p.hasAnnotation("YLabel")) rtn.SetYTitle(p.annotation("YLabel").c_str());
return rtn;
}
/// @brief Convert a YODA Profile1D to a ROOT TH1D
inline TH1D toTH1D(const Profile1D& p) {
// Work out bin edges first
std::vector<double> edges;
edges.reserve(p.numBins()+1);
edges.push_back(p.bin(0).xMin());
for (size_t i = 0; i < p.numBins(); ++i) {
const ProfileBin1D& b = p.bin(i);
if (!fuzzyEquals(edges.back(), b.xMin())) edges.push_back(b.xMin());
if (!fuzzyEquals(edges.back(), b.xMax())) edges.push_back(b.xMax());
}
// Book ROOT histogram
TH1D rtn(p.path().c_str(), p.title().c_str(), edges.size()-1, &edges[0]);
for (int i = 1; i <= rtn.GetNbinsX(); ++i) {
try {
const ProfileBin1D& b = p.binAt(rtn.GetBinCenter(i)); // throws if in a gap
rtn.SetBinContent(i, b.mean());
rtn.SetBinError(i, b.stdErr());
} catch (const Exception& e) { }
}
// Overflows
rtn.SetBinContent(0, p.underflow().yMean());
rtn.SetBinContent(rtn.GetNbinsX()+1, p.overflow().yMean());
rtn.SetBinError(0, p.underflow().yStdErr());
rtn.SetBinError(rtn.GetNbinsX()+1, p.overflow().yStdErr());
// Labels
if (p.hasAnnotation("XLabel")) rtn.SetXTitle(p.annotation("XLabel").c_str());
if (p.hasAnnotation("YLabel")) rtn.SetYTitle(p.annotation("YLabel").c_str());
return rtn;
}
/// @brief Convert a YODA Profile1D to a ROOT TProfile as new'd pointer
inline TProfile* toNewTProfile(const Profile1D& p, const std::string& rootname) {
return (TProfile*) toTProfile(p).Clone(rootname.c_str());
}
/// @todo Convert a YODA Profile2D to a ROOT TProfile2D
/// @brief Convert a YODA Scatter2D to a ROOT TGraphAsymmErrors
///
/// @todo Check/improve/extend.
inline TGraphAsymmErrors toTGraph(const Scatter2D& s) {
TVectorF xs(s.numPoints()), ys(s.numPoints());
TVectorF exls(s.numPoints()), exhs(s.numPoints());
TVectorF eyls(s.numPoints()), eyhs(s.numPoints());
for (size_t i = 0; i < s.numPoints(); ++i) {
const Point2D& p = s.point(i);
xs[i] = p.x();
ys[i] = p.y();
exls[i] = p.xErrMinus();
exhs[i] = p.xErrPlus();
eyls[i] = p.yErrMinus();
eyhs[i] = p.yErrPlus();
}
// Make the ROOT object... mm, the constructors don't take name+title, unlike all this histos!
TGraphAsymmErrors rtn(xs, ys, exls, exhs, eyls, eyhs);
rtn.SetName(s.path().c_str());
rtn.SetTitle(s.title().c_str());
// Labels
if (s.hasAnnotation("XLabel")) rtn.GetXaxis()->SetTitle(s.annotation("XLabel").c_str());
if (s.hasAnnotation("YLabel")) rtn.GetYaxis()->SetTitle(s.annotation("YLabel").c_str());
return rtn;
}
/// @brief Convert a YODA Scatter2D to a ROOT TGraphAsymmErrors as new'd pointer
inline TGraphAsymmErrors* toNewTGraph(const Scatter2D& s, const std::string& rootname) {
return (TGraphAsymmErrors*) toTGraph(s).Clone(rootname.c_str());
}
/// @brief Convert a YODA Histo1D to a ROOT TGraphAsymmErrors
inline TGraphAsymmErrors toTGraph(const Histo1D& h) {
return toTGraph(mkScatter(h));
}
/// @brief Convert a YODA Histo1D to a ROOT TGraphAsymmErrors as new'd pointer
inline TGraphAsymmErrors* toNewTGraph(const Histo1D& h, const std::string& rootname) {
return (TGraphAsymmErrors*) toTGraph(h).Clone(rootname.c_str());
}
/// @brief Convert a YODA Profile1D to a ROOT TGraphAsymmErrors
inline TGraphAsymmErrors toTGraph(const Profile1D& p) {
return toTGraph(mkScatter(p));
}
/// @brief Convert a YODA Profile1D to a ROOT TGraphAsymmErrors as new'd pointer
inline TGraphAsymmErrors* toNewTGraph(const Profile1D& p, const std::string& rootname) {
return (TGraphAsymmErrors*) toTGraph(p).Clone(rootname.c_str());
}
/// @todo Convert YODA Scatter3D, Histo2D and Profile2D to TGraph2D
//@}
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 1:22 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4022939
Default Alt Text
(17 KB)
Attached To
rYODAHG yodahg
Event Timeline
Log In to Comment