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 );
72 if (
auto pos =
name.rfind(
'/' ); pos != std::string::npos ) {
73 dir +=
'/' +
name.substr( 0, pos );
78 auto previousDir = gDirectory;
83 auto is_delimiter = [](
auto c ) {
return c ==
'/' ||
c ==
'.'; };
84 auto transform_to_string = views::transform( [](
auto&& rng ) {
return rng | to<std::string>; } );
86 auto currentDir =
accumulate( dir | views::split_when( is_delimiter ) | transform_to_string,
87 file.GetDirectory(
"" ), [](
auto current,
auto&& dir_level ) {
90 auto nextDir = current->GetDirectory( dir_level.c_str() );
92 if ( !nextDir ) nextDir = current->mkdir( dir_level.c_str() );
106 auto histo = std::make_from_tuple<typename Traits::Histo>(
108 std::tuple{axis[index].nBins, axis[index].minValue, axis[index].maxValue}... ) );
110 for (
unsigned int i = 0; i < totNBins; i++ )
Traits::fill(
histo, i, weights[i] );
111 auto try_set_bin_labels = [&
histo, &jsonAxis](
auto idx ) {
112 if ( jsonAxis[idx].contains(
"labels" ) ) {
113 TAxis* axis =
nullptr;
116 axis =
histo.GetXaxis();
119 axis =
histo.GetYaxis();
122 axis =
histo.GetZaxis();
128 const auto labels = jsonAxis[idx].at(
"labels" );
129 for (
unsigned int i = 0; i < labels.size(); i++ ) {
130 axis->SetBinLabel( i + 1, labels[i].
template get<std::string>().c_str() );
135 ( try_set_bin_labels( index ), ... );
137 histo.SetEntries( nentries );
145 template <
bool isProfile,
typename RootHisto>
148 template <
typename RootHisto>
149 struct Traits<false, RootHisto> {
150 using Histo = RootHisto;
151 using WeightType = double;
152 static auto fill( Histo&
histo,
unsigned int i,
const WeightType& weight ) {
histo.SetBinContent( i, weight ); }
154 template <
typename RootHisto>
155 struct Traits<true, RootHisto> {
157 template <
typename TP>
158 struct ProfileWrapper : TP {
160 void setBinNEntries( Int_t i, Int_t
n ) { this->fBinEntries.fArray[i] =
n; }
161 void setBinW2( Int_t i, Double_t
v ) { this->fSumw2.fArray[i] =
v; }
163 using Histo = ProfileWrapper<RootHisto>;
165 static constexpr
auto fill( Histo&
histo,
unsigned int i,
const WeightType& weight ) {
166 auto [
c, sumWeight2] = weight;
169 histo.SetBinContent( i, sumWeight );
170 histo.setBinW2( i, sumWeight2 );
174 template <
unsigned int N,
bool isProfile,
typename ROOTHisto>
177 std::make_index_sequence<N>() );
180 using namespace std::string_literals;
189 std::pair{
std::pair{
"histogram:WeightedProfileHistogram"s, 1}, &saveRootHisto<1, true, TProfile>},
190 std::pair{
std::pair{
"histogram:ProfileHistogram"s, 2}, &saveRootHisto<2, true, TProfile2D>},
191 std::pair{
std::pair{
"histogram:WeightedProfileHistogram"s, 2}, &saveRootHisto<2, true, TProfile2D>},
192 std::pair{
std::pair{
"histogram:ProfileHistogram"s, 3}, &saveRootHisto<3, true, TProfile3D>},
193 std::pair{
std::pair{
"histogram:WeightedProfileHistogram"s, 3}, &saveRootHisto<3, true, TProfile3D>}};
209 if ( !ok )
return ok;
210 std::sort(
begin( m_monitoringEntities ),
end( m_monitoringEntities ), [](
const auto& a,
const auto& b ) {
213 TFile histoFile( m_fileName.value().c_str(),
"RECREATE" );
214 std::for_each(
begin( m_monitoringEntities ),
end( m_monitoringEntities ), [&histoFile](
auto& ent ) {
215 auto j = ent.toJSON();
216 auto dim = j.at(
"dimension" ).
template get<unsigned int>();
217 auto type = j.at(
"type" ).
template get<std::string>();
221 auto saver =
registry.find( {type, dim} );
225 ( *saver->second )( histoFile, ent.component, ent.name, j );
231 if ( std::string_view( ent.
type ).substr( 0, 10 ) ==
"histogram:" ) {
232 m_monitoringEntities.emplace_back(
std::move( ent ) );
237 auto it =
std::find(
begin( m_monitoringEntities ),
end( m_monitoringEntities ), ent );
238 if ( it != m_monitoringEntities.end() ) { m_monitoringEntities.erase( it ); }
245 "Name of file where to save histograms"};