The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
Base.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#pragma once
12
13#include <Gaudi/BaseSink.h>
15#include <Gaudi/MonitoringHub.h>
17#include <TFile.h>
18#include <filesystem>
19#include <map>
20#include <memory>
21#include <nlohmann/json.hpp>
22#include <string>
23#include <vector>
24
26
27 /*
28 * a Base class for Root related Sinks dealing with Histograms.
29 *
30 * provides the common method plus a generic way of registering handler for different types
31 */
32 class Base : public Monitoring::BaseSink {
33 public:
34 using HistoIdentification = std::pair<std::string, int>;
35 using HistoHandler = std::function<void( TFile& file, std::string, std::string, nlohmann::json const& )>;
36 using HistoRegistry = std::map<HistoIdentification, HistoHandler>;
37
38 using HistoBinIdentification = std::type_index;
40 std::function<void( TFile& file, std::string, std::string, Monitoring::Hub::Entity const& )>;
41 using HistoBinRegistry = std::map<HistoBinIdentification, HistoBinHandler>;
42
43 Base( const std::string& name, ISvcLocator* svcloc ) : Monitoring::BaseSink( name, svcloc ) {
44 // only deal with histograms
45 setProperty( "TypesToSave", std::vector<std::string>{ "histogram:.*" } )
46 .orThrow( "Unable to set typesToSaveProperty", "Histograming::Sink::Base" );
47 }
48
50 return BaseSink::initialize().andThen( [&] {
51 if ( m_fileSvc.retrieve() && m_fileSvc->hasIdentifier( m_fileName ) ) {
52 // the target files is available through FileSvc
53 info() << "Writing ROOT histograms to: " << m_fileName.value() << " ("
54 << m_fileSvc->getFile( m_fileName )->GetName() << ')' << endmsg;
55 } else {
56 // we are not using FileSvc to open the TFile, so we have to
57 // empty output file if it exists, as we will update it at the end
58 // This allows multiple Sinks to write to the same ROOT file
59 std::filesystem::remove( m_fileName.value() );
60 info() << "Writing ROOT histograms to: " << m_fileName.value() << endmsg;
61 }
62 } );
63 }
64
65 void flush( bool ) override {
66 std::shared_ptr<TFile> histoFile;
67 if ( m_fileSvc.get() && m_fileSvc->hasIdentifier( m_fileName ) ) {
68 histoFile = m_fileSvc->getFile( m_fileName );
69 } else {
70 // File is updated so that multiple sinks can write to the same file
71 // As we are in stop, there is no multithreading so it is safe
72 // As we dropped the file at initialization, no old data from a previous
73 // run may be mixed with new one
74 histoFile = std::make_shared<TFile>( m_fileName.value().c_str(), "UPDATE" );
75 }
76 // get all entities, sorted by component and name
77 applyToAllSortedEntities( [this, &histoFile]( std::string const& component, std::string const& name,
78 Monitoring::Hub::Entity const& ent ) {
79 // try first a dedicated flush, bypassing json (more efficient)
80 auto typeIndex = ent.typeIndex();
81 auto binSaver = m_binRegistry.find( typeIndex );
82 if ( binSaver != m_binRegistry.end() ) {
83 binSaver->second( *histoFile, component, name, ent );
84 return;
85 }
86 // no fast track, let's use json intermediate format
87 nlohmann::json j = ent;
88 auto dim = j.at( "dimension" ).template get<unsigned int>();
89 auto type = j.at( "type" ).template get<std::string>();
90 // cut type after last ':' if there is one. The rest is precision parameter that we do not need here
91 // as ROOT anyway treats everything as doubles in histograms
92 type = type.substr( 0, type.find_last_of( ':' ) );
93 auto saver = m_registry.find( { type, dim } );
94 if ( saver != m_registry.end() ) ( saver->second )( *histoFile, component, name, j );
95 } );
96 info() << "Completed update of ROOT histograms in: " << m_fileName.value() << endmsg;
97 }
98
100 m_binRegistry.emplace( std::piecewise_construct, std::make_tuple( id ), std::make_tuple( func ) );
101 }
102
103 void registerHandler( HistoIdentification const& id, HistoHandler const& func ) {
104 m_registry.emplace( std::piecewise_construct, std::make_tuple( id ), std::make_tuple( func ) );
105 }
106
107 private:
112
113 Gaudi::Property<std::string> m_fileName{ this, "FileName", "testHisto.root",
114 "Name of file where to save histograms" };
115
117 };
118
119} // namespace Gaudi::Histograming::Sink
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
std::function< void(TFile &file, std::string, std::string, nlohmann::json const &)> HistoHandler
Definition Base.h:35
void flush(bool) override
pure virtual method to be defined by children and responsible for flushing current data of the Sink.
Definition Base.h:65
ServiceHandle< Gaudi::Interfaces::IFileSvc > m_fileSvc
Definition Base.h:116
Base(const std::string &name, ISvcLocator *svcloc)
Definition Base.h:43
Gaudi::Property< std::string > m_fileName
Definition Base.h:113
std::type_index HistoBinIdentification
Definition Base.h:38
HistoBinRegistry m_binRegistry
map of supported type and the way to handle them
Definition Base.h:109
std::map< HistoBinIdentification, HistoBinHandler > HistoBinRegistry
Definition Base.h:41
std::function< void(TFile &file, std::string, std::string, Monitoring::Hub::Entity const &)> HistoBinHandler
Definition Base.h:39
StatusCode initialize() override
Definition Base.h:49
void registerHandler(HistoIdentification const &id, HistoHandler const &func)
Definition Base.h:103
void registerHandler(HistoBinIdentification const &id, HistoBinHandler const &func)
Definition Base.h:99
std::map< HistoIdentification, HistoHandler > HistoRegistry
Definition Base.h:36
HistoRegistry m_registry
map of supported type and the way to handle them
Definition Base.h:111
std::pair< std::string, int > HistoIdentification
Definition Base.h:34
Base class for all Sinks registering to the Monitoring Hub Should be extended by actual Sinks.
Definition BaseSink.h:41
void applyToAllSortedEntities(Callable func) const
applies a callable to all monitoring entities ordered by component the callable will be called once p...
Definition BaseSink.h:111
Wrapper class for arbitrary monitoring objects.
std::type_index typeIndex() const
function to get internal type
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition ISvcLocator.h:42
Handle to be used in lieu of naked pointers to services.
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
Definition StatusCode.h:163