14 #include <TDirectory.h>
21 #include <TProfile2D.h>
25 #include <nlohmann/json.hpp>
26 #include <range/v3/numeric/accumulate.hpp>
27 #include <range/v3/range/conversion.hpp>
28 #include <range/v3/view/split_when.hpp>
29 #include <range/v3/view/transform.hpp>
34 #if RANGE_V3_VERSION < 900
36 using namespace ranges::view;
54 template <
bool isProfile,
typename RootHisto,
unsigned int N>
63 template <
typename Traits>
72 template <
typename Histo>
78 template <
typename Traits>
87 template <
unsigned int N,
bool isProfile,
typename ROOTHisto>
102 return { jAxis.at(
"nBins" ).get<
unsigned int>(), jAxis.at(
"minValue" ).get<
double>(),
103 jAxis.at(
"maxValue" ).get<
double>(),
113 std::index_sequence<index...> ) {
115 auto jsonAxis =
j.at(
"axis" );
119 auto nentries =
j.at(
"nEntries" ).get<
unsigned int>();
121 title += ( axis[index].title + ... );
123 auto totNBins = ( ( axis[index].nBins + 2 ) * ... );
124 assert( weights.size() == totNBins );
126 if (
name[0] ==
'/' ) {
133 if (
auto pos =
name.rfind(
'/' ); pos != std::string::npos ) {
134 dir +=
'/' +
name.substr( 0, pos );
139 auto histo = Traits::create(
name, title, axis[index]... );
142 for (
unsigned int i = 0; i < totNBins; i++ )
Traits::fill( histo, i, weights[i] );
144 Traits::fillMetaData( histo, jsonAxis, nentries );
146 return { histo, dir };
154 template <
typename RootHisto,
unsigned int N>
156 static constexpr
unsigned int Dimension{
N };
158 template <
typename AxisArray,
std::size_t... index>
160 return std::make_from_tuple<RootHisto>(
162 std::tuple{ std::get<index>( axis ).nBins, std::get<index>( axis ).minValue,
163 std::get<index>( axis ).maxValue }... ) );
166 template <
typename...
Axis>
172 auto try_set_bin_labels = [&histo, &jsonAxis](
auto idx ) {
173 if ( jsonAxis[idx].contains(
"labels" ) ) {
174 TAxis* axis =
nullptr;
177 axis = histo.GetXaxis();
180 axis = histo.GetYaxis();
183 axis = histo.GetZaxis();
189 const auto labels = jsonAxis[idx].at(
"labels" );
190 for (
unsigned int i = 0; i < labels.size(); i++ ) {
191 axis->SetBinLabel( i + 1, labels[i].
template get<std::string>().c_str() );
196 for (
unsigned int i = 0; i < jsonAxis.size(); i++ ) try_set_bin_labels( i );
198 histo.SetEntries( nentries );
203 template <
typename TP>
205 template <
typename... Args>
211 this->Sumw2(
false );
218 void setBinW2( Int_t i, Double_t
v ) { this->fSumw2.fArray[i] =
v; }
227 auto previousDir = gDirectory;
230 auto is_delimiter = [](
auto c ) {
return c ==
'/' ||
c ==
'.'; };
231 auto transform_to_string = views::transform( [](
auto&& rng ) {
return rng | to<std::string>; } );
232 auto currentDir =
accumulate( dir | views::split_when( is_delimiter ) | transform_to_string,
233 file.GetDirectory(
"" ), [](
auto current,
auto&& dir_level ) {
236 auto nextDir = current->GetDirectory( dir_level.c_str() );
238 if ( !nextDir ) nextDir = current->mkdir( dir_level.c_str() );
251 template <
typename Histo>
253 if constexpr ( std::is_base_of_v<TH3D, Histo> ) {
254 return { *
h.GetXaxis(), *
h.GetYaxis(), *
h.GetZaxis() };
255 }
else if constexpr ( std::is_base_of_v<TProfile2D, Histo> || std::is_base_of_v<TH2D, Histo> ) {
256 return { *
h.GetXaxis(), *
h.GetYaxis() };
258 return { *
h.GetXaxis() };
262 template <
typename Histo>
264 if constexpr ( std::is_base_of_v<TProfile, Histo> || std::is_base_of_v<TProfile2D, Histo> ) {
268 auto* sums =
h.GetArray();
269 auto* sums2 =
h.GetSumw2();
270 for (
unsigned long n = 0;
n < (
unsigned long)
h.GetSize();
n++ ) {
275 return gsl::span{
h.GetArray(), (
unsigned long)
h.GetSize() };
280 template <
typename Histo>
282 std::string type = std::is_base_of_v<TProfile, Histo> || std::is_base_of_v<TProfile2D, Histo>
283 ?
"histogram:ProfileHistogram:double"
284 :
"histogram:Histogram:double";
286 {
"title",
h.GetTitle() },
287 {
"dimension",
h.GetDimension() },
288 {
"empty", (int)
h.GetEntries() == 0 },
289 {
"nEntries", (int)
h.GetEntries() },
299 template <
typename RootHisto,
unsigned int N>
303 static void fill(
Histo& histo,
unsigned int i,
const WeightType& weight ) { histo.SetBinContent( i, weight ); }
309 template <
typename RootHisto,
unsigned int N>
314 auto [
c, sumWeight2] = weight;
317 histo.SetBinContent( i, sumWeight );
322 template <
typename Traits>
325 return details::jsonToRootHistogramInternal<Traits>( dir,
name,
j, std::make_index_sequence<Traits::Dimension>() );
328 template <
typename Traits>
331 auto [histo, newDir] = jsonToRootHistogram<Traits>( dir,
name,
j );
340 template <
unsigned int N,
bool isProfile,
typename ROOTHisto>
351 {
"minValue", axis.GetXmin() },
352 {
"maxValue", axis.GetXmax() },
353 {
"title", axis.GetTitle() } };