16 #include <TDirectory.h>
22 #include <TProfile2D.h>
23 #include <TProfile3D.h>
27 #include <range/v3/numeric/accumulate.hpp>
28 #include <range/v3/range/conversion.hpp>
29 #include <range/v3/view/split_when.hpp>
30 #include <range/v3/view/transform.hpp>
32 #if RANGE_V3_VERSION < 900
34 using namespace ranges::view;
50 return { jAxis.
at(
"nBins" ).get<
unsigned int>(), jAxis.at(
"minValue" ).get<
double>(),
51 jAxis.at(
"maxValue" ).get<
double>(),
57 std::index_sequence<index...> ) {
59 auto jsonAxis = j.at(
"axis" );
60 auto axis =
std::array{ toAxis( jsonAxis[index] )... };
63 auto nentries = j.
at(
"nEntries" ).get<
unsigned int>();
65 title += ( axis[index].title + ... );
67 auto totNBins = ( ( axis[index].nBins + 2 ) * ... );
68 assert( weights.size() == totNBins );
70 if (
name[0] ==
'/' ) {
77 if (
auto pos =
name.rfind(
'/' ); pos != std::string::npos ) {
78 dir +=
'/' +
name.substr( 0, pos );
83 auto previousDir = gDirectory;
88 auto is_delimiter = [](
auto c ) {
return c ==
'/' ||
c ==
'.'; };
89 auto transform_to_string = views::transform( [](
auto&& rng ) {
return rng | to<std::string>; } );
91 auto currentDir =
accumulate( dir | views::split_when( is_delimiter ) | transform_to_string,
92 file.GetDirectory(
"" ), [](
auto current,
auto&& dir_level ) {
95 auto nextDir = current->GetDirectory( dir_level.c_str() );
97 if ( !nextDir ) nextDir = current->mkdir( dir_level.c_str() );
111 auto histo = std::make_from_tuple<typename Traits::Histo>(
113 std::tuple{ axis[index].nBins, axis[index].minValue, axis[index].maxValue }... ) );
115 for (
unsigned int i = 0; i < totNBins; i++ )
Traits::fill(
histo, i, weights[i] );
116 auto try_set_bin_labels = [&
histo, &jsonAxis](
auto idx ) {
117 if ( jsonAxis[idx].contains(
"labels" ) ) {
118 TAxis* axis =
nullptr;
121 axis =
histo.GetXaxis();
124 axis =
histo.GetYaxis();
127 axis =
histo.GetZaxis();
133 const auto labels = jsonAxis[idx].at(
"labels" );
134 for (
unsigned int i = 0; i < labels.size(); i++ ) {
135 axis->SetBinLabel( i + 1, labels[i].
template get<std::string>().c_str() );
140 ( try_set_bin_labels( index ), ... );
142 histo.SetEntries( nentries );
150 template <
bool isProfile,
typename RootHisto>
153 template <
typename RootHisto>
154 struct Traits<false, RootHisto> {
155 using Histo = RootHisto;
156 using WeightType = double;
157 static auto fill( Histo&
histo,
unsigned int i,
const WeightType& weight ) {
histo.SetBinContent( i, weight ); }
159 template <
typename RootHisto>
160 struct Traits<true, RootHisto> {
162 template <
typename TP>
163 struct ProfileWrapper : TP {
165 void setBinNEntries( Int_t i, Int_t
n ) { this->fBinEntries.fArray[i] =
n; }
166 void setBinW2( Int_t i, Double_t
v ) { this->fSumw2.fArray[i] =
v; }
168 using Histo = ProfileWrapper<RootHisto>;
170 static constexpr
auto fill( Histo&
histo,
unsigned int i,
const WeightType& weight ) {
171 auto [
c, sumWeight2] = weight;
174 histo.SetBinContent( i, sumWeight );
175 histo.setBinW2( i, sumWeight2 );
179 template <
unsigned int N,
bool isProfile,
typename ROOTHisto>
182 std::make_index_sequence<N>() );
185 using namespace std::string_literals;
188 std::pair{
std::pair{
"histogram:WeightedHistogram"s, 1 }, &saveRootHisto<1, false, TH1D> },
190 std::pair{
std::pair{
"histogram:WeightedHistogram"s, 2 }, &saveRootHisto<2, false, TH2D> },
192 std::pair{
std::pair{
"histogram:WeightedHistogram"s, 3 }, &saveRootHisto<3, false, TH3D> },
193 std::pair{
std::pair{
"histogram:ProfileHistogram"s, 1 }, &saveRootHisto<1, true, TProfile> },
194 std::pair{
std::pair{
"histogram:WeightedProfileHistogram"s, 1 }, &saveRootHisto<1, true, TProfile> },
195 std::pair{
std::pair{
"histogram:ProfileHistogram"s, 2 }, &saveRootHisto<2, true, TProfile2D> },
196 std::pair{
std::pair{
"histogram:WeightedProfileHistogram"s, 2 }, &saveRootHisto<2, true, TProfile2D> },
197 std::pair{
std::pair{
"histogram:ProfileHistogram"s, 3 }, &saveRootHisto<3, true, TProfile3D> },
198 std::pair{
std::pair{
"histogram:WeightedProfileHistogram"s, 3 }, &saveRootHisto<3, true, TProfile3D> } };
214 if ( !ok )
return ok;
215 std::sort(
begin( m_monitoringEntities ),
end( m_monitoringEntities ), [](
const auto& a,
const auto& b ) {
218 TFile histoFile( m_fileName.value().c_str(),
"RECREATE" );
219 std::for_each(
begin( m_monitoringEntities ),
end( m_monitoringEntities ), [&histoFile](
auto& ent ) {
220 auto j = ent.toJSON();
221 auto dim = j.at(
"dimension" ).
template get<unsigned int>();
222 auto type = j.at(
"type" ).
template get<std::string>();
226 auto saver =
registry.find( { type, dim } );
230 ( *saver->second )( histoFile, ent.component, ent.name, j );
236 if ( std::string_view( ent.
type ).substr( 0, 10 ) ==
"histogram:" ) {
237 m_monitoringEntities.emplace_back(
std::move( ent ) );
242 auto it =
std::find(
begin( m_monitoringEntities ),
end( m_monitoringEntities ), ent );
243 if ( it != m_monitoringEntities.end() ) { m_monitoringEntities.erase( it ); }
250 "Name of file where to save histograms" };