The Gaudi Framework  master (e68eea06)
Loading...
Searching...
No Matches
Gaudi::Histograming::Sink::details Namespace Reference

Classes

struct  Axis
 Small helper struct representing the Axis of an Histogram. More...
 
struct  BinAvValue
 
struct  ProfileWrapper
 helper Wrapper around TProfileX to be able to fill it More...
 
struct  TraitsBase
 Common base for Traits dealing with Histogram conversions to Root Provides generic implementation for creating the histogram and filling meta data The filling (method fill) is not implemented. More...
 

Functions

Axis jsonToAxis (nlohmann::json &jAxis)
 extract an Axis from json data
 
void fixNameAndDir (std::string &name, std::string &dir)
 handles cases where name includes '/' character(s) and move needed part of it to dir.
 
template<typename Traits, std::size_t... index>
std::tuple< typename Traits::Histo, std::string > jsonToRootHistogramInternal (std::string &dir, std::string &name, nlohmann::json const &j, std::index_sequence< index... >)
 generic function to convert json to a ROOT Histogram - internal implementation
 
TDirectory * changeDir (TFile &file, std::string_view dir)
 changes to the ROOT directory given in the current ROOT file and returns the current directory before the change
 
template<typename Histo>
nlohmann::json allAxisTojson (Histo const &h)
 
template<typename Histo>
nlohmann::json binsTojson (Histo const &h)
 
template<typename Histo>
nlohmann::json rootHistogramToJson (Histo const &h)
 automatic translation of Root Histograms to json
 

Function Documentation

◆ allAxisTojson()

template<typename Histo>
nlohmann::json Gaudi::Histograming::Sink::details::allAxisTojson ( Histo const & h)

Definition at line 352 of file Utils.h.

352 {
353 if constexpr ( std::is_base_of_v<TH3D, Histo> ) {
354 return { *h.GetXaxis(), *h.GetYaxis(), *h.GetZaxis() };
355 } else if constexpr ( std::is_base_of_v<TProfile2D, Histo> || std::is_base_of_v<TH2D, Histo> ) {
356 return { *h.GetXaxis(), *h.GetYaxis() };
357 } else {
358 return { *h.GetXaxis() };
359 }
360 }

◆ binsTojson()

template<typename Histo>
nlohmann::json Gaudi::Histograming::Sink::details::binsTojson ( Histo const & h)

Definition at line 363 of file Utils.h.

363 {
364 if constexpr ( std::is_base_of_v<TProfile, Histo> || std::is_base_of_v<TProfile2D, Histo> ) {
365 nlohmann::json j;
366 // ROOT TProfile interface being completely inconsistent, we have to play
367 // with different ways to access values of the histogram... one per value !
368 auto* sums = h.GetArray();
369 auto* sums2 = h.GetSumw2();
370 for ( unsigned long n = 0; n < (unsigned long)h.GetSize(); n++ ) {
371 j.push_back( nlohmann::json{ { h.GetBinEntries( n ), sums[n] }, sums2->At( n ) } );
372 }
373 return j;
374 } else {
375 return gsl::span{ h.GetArray(), (unsigned long)h.GetSize() };
376 }
377 }

◆ changeDir()

TDirectory * Gaudi::Histograming::Sink::details::changeDir ( TFile & file,
std::string_view dir )
inline

changes to the ROOT directory given in the current ROOT file and returns the current directory before the change

Definition at line 329 of file Utils.h.

329 {
330 // remember the current directory
331 auto previousDir = gDirectory;
332 // find or create the directory for the histogram
333 auto currentDir = ranges::accumulate(
334 dir | std::views::transform( []( char c ) { return c == '.' ? '/' : c; } ) | std::views::split( '/' ) |
335 std::views::transform( []<std::ranges::input_range R>( R&& r ) {
336 return std::string( std::ranges::begin( r ), std::ranges::end( r ) );
337 } ),
338 file.GetDirectory( "" ), []( TDirectory* current, std::string const& d ) -> TDirectory* {
339 if ( !current ) return current;
340 if ( auto next = current->GetDirectory( d.c_str() ); next ) return next;
341 return current->mkdir( d.c_str() );
342 } );
343 if ( !currentDir )
344 throw GaudiException( fmt::format( "Could not create directory {}", dir ), "Histogram::Sink::Root",
346 // switch to the directory
347 currentDir->cd();
348 return previousDir;
349 }
Define general base for Gaudi exception.
constexpr static const auto FAILURE
Definition StatusCode.h:100

◆ fixNameAndDir()

void Gaudi::Histograming::Sink::details::fixNameAndDir ( std::string & name,
std::string & dir )
inline

handles cases where name includes '/' character(s) and move needed part of it to dir.

Also handle case of absolute names

Definition at line 179 of file Utils.h.

179 {
180 if ( name[0] == '/' ) {
181 dir = "";
182 name = name.substr( 1 );
183 }
184 // take into account the case where name contains '/'s (e.g. "Group/Name") by
185 // moving the prefix into dir
186 if ( auto pos = name.rfind( '/' ); pos != std::string::npos ) {
187 dir += '/' + name.substr( 0, pos );
188 name = name.substr( pos + 1 );
189 }
190 }

◆ jsonToAxis()

Axis Gaudi::Histograming::Sink::details::jsonToAxis ( nlohmann::json & jAxis)
inline

extract an Axis from json data

Definition at line 169 of file Utils.h.

169 {
170 return { jAxis.at( "nBins" ).get<unsigned int>(), jAxis.at( "minValue" ).get<double>(),
171 jAxis.at( "maxValue" ).get<double>(),
172 ";" + jAxis.at( "title" ).get<std::string>() }; // ";" to prepare concatenations of titles
173 }

◆ jsonToRootHistogramInternal()

template<typename Traits, std::size_t... index>
std::tuple< typename Traits::Histo, std::string > Gaudi::Histograming::Sink::details::jsonToRootHistogramInternal ( std::string & dir,
std::string & name,
nlohmann::json const & j,
std::index_sequence< index... >  )

generic function to convert json to a ROOT Histogram - internal implementation

Definition at line 196 of file Utils.h.

198 {
199 // extract data from json
200 auto jsonAxis = j.at( "axis" );
201 auto axis = std::array{ jsonToAxis( jsonAxis[index] )... };
202 auto weights = j.at( "bins" ).get<typename Traits::WeightType>();
203 auto title = j.at( "title" ).get<std::string>();
204 auto nentries = j.at( "nEntries" ).get<unsigned int>();
205 // weird way ROOT has to give titles to axis
206 title += ( axis[index].title + ... );
207 // compute total number of bins, multiplying bins per axis
208 auto totNBins = ( ( axis[index].nBins + 2 ) * ... );
209 // fix name and dir if needed
210 fixNameAndDir( name, dir );
211 // Create Root histogram calling constructors with the args tuple
212 auto histo = Traits::create( name, title, axis[index]... );
213 // fill Histo
214 Traits::fill( histo, totNBins, weights );
215 // in case we have sums, overwrite them in the histogram with our more precise values
216 // FIXME This is only supporting regular histograms. It won't work in case of weighted histograms
217 if constexpr ( sizeof...( index ) == 1 ) {
218 if ( j.find( "sum" ) != j.end() ) {
219 double s[13];
220 s[0] = j.at( "nTotEntries" ).get<double>();
221 s[1] = j.at( "nTotEntries" ).get<double>();
222 s[2] = j.at( "sum" ).get<double>();
223 s[3] = j.at( "sum2" ).get<double>();
224 histo.PutStats( s );
225 }
226 } else {
227 if ( j.find( "sumx" ) != j.end() ) {
228 double s[13];
229 s[0] = j.at( "nTotEntries" ).get<double>();
230 s[1] = j.at( "nTotEntries" ).get<double>();
231 s[2] = j.at( "sumx" ).get<double>();
232 s[3] = j.at( "sumx2" ).get<double>();
233 s[4] = j.at( "sumy" ).get<double>();
234 s[5] = j.at( "sumy2" ).get<double>();
235 s[6] = j.at( "sumxy" ).get<double>();
236 if constexpr ( sizeof...( index ) > 2 ) {
237 s[7] = j.at( "sumz" ).get<double>();
238 s[8] = j.at( "sumz2" ).get<double>();
239 s[9] = j.at( "sumxz" ).get<double>();
240 s[10] = j.at( "sumyz" ).get<double>();
241 }
242 histo.PutStats( s );
243 }
244 }
245 // fill histo metadata, e.g. bins and number of entries
246 Traits::fillMetaData( histo, jsonAxis, nentries );
247 return { histo, dir };
248 }
void fixNameAndDir(std::string &name, std::string &dir)
handles cases where name includes '/' character(s) and move needed part of it to dir.
Definition Utils.h:179
Axis jsonToAxis(nlohmann::json &jAxis)
extract an Axis from json data
Definition Utils.h:169

◆ rootHistogramToJson()

template<typename Histo>
nlohmann::json Gaudi::Histograming::Sink::details::rootHistogramToJson ( Histo const & h)

automatic translation of Root Histograms to json

Definition at line 381 of file Utils.h.

381 {
382 bool isProfile = std::is_base_of_v<TProfile, Histo> || std::is_base_of_v<TProfile2D, Histo>;
383 std::string type = isProfile ? "histogram:ProfileHistogram:double" : "histogram:Histogram:double";
384 auto j = nlohmann::json{ { "type", type },
385 { "title", h.GetTitle() },
386 { "dimension", h.GetDimension() },
387 { "empty", (int)h.GetEntries() == 0 },
388 { "nEntries", (int)h.GetEntries() },
389 { "axis", allAxisTojson( h ) },
390 { "bins", binsTojson( h ) } };
391 if ( !isProfile ) {
392 double s[13];
393 h.GetStats( s );
394 if ( h.GetDimension() == 1 ) {
395 j["nTotEntries"] = s[0];
396 j["sum"] = s[2];
397 j["sum2"] = s[3];
398 j["mean"] = s[2] / s[0];
399 } else {
400 j["nTotEntries"] = s[0];
401 j["sumx"] = s[2];
402 j["sumx2"] = s[3];
403 j["meanx"] = s[2] / s[0];
404 j["sumy"] = s[4];
405 j["sumy2"] = s[5];
406 j["sumxy"] = s[6];
407 j["meany"] = s[4] / s[0];
408 if ( h.GetDimension() >= 3 ) {
409 j["sumz"] = s[7];
410 j["sumz2"] = s[8];
411 j["sumxz"] = s[9];
412 j["sumyz"] = s[10];
413 j["meanz"] = s[7] / s[0];
414 }
415 }
416 }
417 return j;
418 }
nlohmann::json binsTojson(Histo const &h)
Definition Utils.h:363
nlohmann::json allAxisTojson(Histo const &h)
Definition Utils.h:352