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

Classes

struct  Axis
 Small helper struct representing the Axis of an Histogram. 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...
struct  ProfileWrapper
 helper Wrapper around TProfileX to be able to fill it More...
struct  BinAvValue

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 421 of file Utils.h.

421 {
422 if constexpr ( std::is_base_of_v<TH3D, Histo> ) {
423 return { *h.GetXaxis(), *h.GetYaxis(), *h.GetZaxis() };
424 } else if constexpr ( std::is_base_of_v<TProfile2D, Histo> || std::is_base_of_v<TH2D, Histo> ) {
425 return { *h.GetXaxis(), *h.GetYaxis() };
426 } else {
427 return { *h.GetXaxis() };
428 }
429 }

◆ binsTojson()

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

Definition at line 432 of file Utils.h.

432 {
433 if constexpr ( std::is_base_of_v<TProfile, Histo> || std::is_base_of_v<TProfile2D, Histo> ) {
434 nlohmann::json j;
435 // ROOT TProfile interface being completely inconsistent, we have to play
436 // with different ways to access values of the histogram... one per value !
437 auto* sums = h.GetArray();
438 auto* sums2 = h.GetSumw2();
439 for ( unsigned long n = 0; n < (unsigned long)h.GetSize(); n++ ) {
440 j.push_back( nlohmann::json{ { h.GetBinEntries( n ), sums[n] }, sums2->At( n ) } );
441 }
442 return j;
443 } else {
444 return gsl::span{ h.GetArray(), (unsigned long)h.GetSize() };
445 }
446 }

◆ 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 398 of file Utils.h.

398 {
399 // remember the current directory
400 auto previousDir = gDirectory;
401 // find or create the directory for the histogram
402 auto currentDir = ranges::accumulate(
403 dir | std::views::transform( []( char c ) { return c == '.' ? '/' : c; } ) | std::views::split( '/' ) |
404 std::views::transform( []<std::ranges::input_range R>( R&& r ) {
405 return std::string( std::ranges::begin( r ), std::ranges::end( r ) );
406 } ),
407 file.GetDirectory( "" ), []( TDirectory* current, std::string const& d ) -> TDirectory* {
408 if ( !current ) return current;
409 if ( auto next = current->GetDirectory( d.c_str() ); next ) return next;
410 return current->mkdir( d.c_str() );
411 } );
412 if ( !currentDir )
413 throw GaudiException( fmt::format( "Could not create directory {}", dir ), "Histogram::Sink::Root",
415 // switch to the directory
416 currentDir->cd();
417 return previousDir;
418 }
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 248 of file Utils.h.

248 {
249 if ( name[0] == '/' ) {
250 dir = "";
251 name = name.substr( 1 );
252 }
253 // take into account the case where name contains '/'s (e.g. "Group/Name") by
254 // moving the prefix into dir
255 if ( auto pos = name.rfind( '/' ); pos != std::string::npos ) {
256 dir += '/' + name.substr( 0, pos );
257 name = name.substr( pos + 1 );
258 }
259 }

◆ jsonToAxis()

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

extract an Axis from json data

Definition at line 238 of file Utils.h.

238 {
239 return { jAxis.at( "nBins" ).get<unsigned int>(), jAxis.at( "minValue" ).get<double>(),
240 jAxis.at( "maxValue" ).get<double>(),
241 ";" + jAxis.at( "title" ).get<std::string>() }; // ";" to prepare concatenations of titles
242 }

◆ 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 265 of file Utils.h.

267 {
268 // extract data from json
269 auto jsonAxis = j.at( "axis" );
270 auto axis = std::array{ jsonToAxis( jsonAxis[index] )... };
271 auto weights = j.at( "bins" ).get<typename Traits::WeightType>();
272 auto title = j.at( "title" ).get<std::string>();
273 auto nentries = j.at( "nEntries" ).get<unsigned int>();
274 // weird way ROOT has to give titles to axis
275 title += ( axis[index].title + ... );
276 // compute total number of bins, multiplying bins per axis
277 auto totNBins = ( ( axis[index].nBins + 2 ) * ... );
278 // fix name and dir if needed
279 fixNameAndDir( name, dir );
280 // Create Root histogram calling constructors with the args tuple
281 auto histo = Traits::create( name, title, axis[index]... );
282 // fill Histo
283 Traits::fill( histo, totNBins, weights );
284 // in case we have sums, overwrite them in the histogram with our more precise values
285 // FIXME This is only supporting regular histograms. It won't work in case of weighted histograms
286 if constexpr ( sizeof...( index ) == 1 ) {
287 if ( j.find( "sum" ) != j.end() ) {
288 double s[13];
289 s[0] = j.at( "nTotEntries" ).get<double>();
290 s[1] = j.at( "nTotEntries" ).get<double>();
291 s[2] = j.at( "sum" ).get<double>();
292 s[3] = j.at( "sum2" ).get<double>();
293 histo.PutStats( s );
294 }
295 } else {
296 if ( j.find( "sumx" ) != j.end() ) {
297 double s[13];
298 s[0] = j.at( "nTotEntries" ).get<double>();
299 s[1] = j.at( "nTotEntries" ).get<double>();
300 s[2] = j.at( "sumx" ).get<double>();
301 s[3] = j.at( "sumx2" ).get<double>();
302 s[4] = j.at( "sumy" ).get<double>();
303 s[5] = j.at( "sumy2" ).get<double>();
304 s[6] = j.at( "sumxy" ).get<double>();
305 if constexpr ( sizeof...( index ) > 2 ) {
306 s[7] = j.at( "sumz" ).get<double>();
307 s[8] = j.at( "sumz2" ).get<double>();
308 s[9] = j.at( "sumxz" ).get<double>();
309 s[10] = j.at( "sumyz" ).get<double>();
310 }
311 histo.PutStats( s );
312 }
313 }
314 // fill histo metadata, e.g. bins and number of entries
315 Traits::fillMetaData( histo, jsonAxis, nentries );
316 return { histo, dir };
317 }
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:248
Axis jsonToAxis(nlohmann::json &jAxis)
extract an Axis from json data
Definition Utils.h:238

◆ rootHistogramToJson()

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

automatic translation of Root Histograms to json

Definition at line 450 of file Utils.h.

450 {
451 bool isProfile = std::is_base_of_v<TProfile, Histo> || std::is_base_of_v<TProfile2D, Histo>;
452 std::string type = isProfile ? "histogram:ProfileHistogram:double" : "histogram:Histogram:double";
453 auto j = nlohmann::json{ { "type", type },
454 { "title", h.GetTitle() },
455 { "dimension", h.GetDimension() },
456 { "empty", (int)h.GetEntries() == 0 },
457 { "nEntries", (int)h.GetEntries() },
458 { "axis", allAxisTojson( h ) },
459 { "bins", binsTojson( h ) } };
460 if ( !isProfile ) {
461 double s[13];
462 h.GetStats( s );
463 if ( h.GetDimension() == 1 ) {
464 j["nTotEntries"] = s[0];
465 j["sum"] = s[2];
466 j["sum2"] = s[3];
467 j["mean"] = s[2] / s[0];
468 } else {
469 j["nTotEntries"] = s[0];
470 j["sumx"] = s[2];
471 j["sumx2"] = s[3];
472 j["meanx"] = s[2] / s[0];
473 j["sumy"] = s[4];
474 j["sumy2"] = s[5];
475 j["sumxy"] = s[6];
476 j["meany"] = s[4] / s[0];
477 if ( h.GetDimension() >= 3 ) {
478 j["sumz"] = s[7];
479 j["sumz2"] = s[8];
480 j["sumxz"] = s[9];
481 j["sumyz"] = s[10];
482 j["meanz"] = s[7] / s[0];
483 }
484 }
485 }
486 return j;
487 }
nlohmann::json binsTojson(Histo const &h)
Definition Utils.h:432
nlohmann::json allAxisTojson(Histo const &h)
Definition Utils.h:421