The Gaudi Framework  master (d98a2936)
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 
12 #include <Gaudi/BaseSink.h>
14 #include <Gaudi/MonitoringHub.h>
16 #include <TFile.h>
17 #include <filesystem>
18 #include <map>
19 #include <memory>
20 #include <nlohmann/json.hpp>
21 #include <string>
22 #include <vector>
23 
24 namespace Gaudi::Histograming::Sink {
25 
26  /*
27  * a Base class for Root related Sinks dealing with Histograms.
28  *
29  * provides the common method plus a generic way of registering handler for different types
30  */
31  class Base : public Monitoring::BaseSink {
32  public:
33  using HistoIdentification = std::pair<std::string, int>;
34  using HistoHandler = std::function<void( TFile& file, std::string, std::string, nlohmann::json const& )>;
35  using HistoRegistry = std::map<HistoIdentification, HistoHandler>;
36 
37  using HistoBinIdentification = std::type_index;
39  std::function<void( TFile& file, std::string, std::string, Monitoring::Hub::Entity const& )>;
40  using HistoBinRegistry = std::map<HistoBinIdentification, HistoBinHandler>;
41 
42  Base( const std::string& name, ISvcLocator* svcloc ) : Monitoring::BaseSink( name, svcloc ) {
43  // only deal with histograms
44  setProperty( "TypesToSave", std::vector<std::string>{ "histogram:.*" } )
45  .orThrow( "Unable to set typesToSaveProperty", "Histograming::Sink::Base" );
46  }
47 
48  StatusCode initialize() override {
49  return BaseSink::initialize().andThen( [&] {
51  // the target files is available through FileSvc
52  info() << "Writing ROOT histograms to: " << m_fileName.value() << " ("
53  << m_fileSvc->getFile( m_fileName )->GetName() << ')' << endmsg;
54  } else {
55  // we are not using FileSvc to open the TFile, so we have to
56  // empty output file if it exists, as we will update it at the end
57  // This allows multiple Sinks to write to the same ROOT file
58  std::filesystem::remove( m_fileName.value() );
59  info() << "Writing ROOT histograms to: " << m_fileName.value() << endmsg;
60  }
61  } );
62  }
63 
64  void flush( bool ) override {
65  std::shared_ptr<TFile> histoFile;
67  histoFile = m_fileSvc->getFile( m_fileName );
68  } else {
69  // File is updated so that multiple sinks can write to the same file
70  // As we are in stop, there is no multithreading so it is safe
71  // As we dropped the file at initialization, no old data from a previous
72  // run may be mixed with new one
73  histoFile = std::make_shared<TFile>( m_fileName.value().c_str(), "UPDATE" );
74  }
75  // get all entities, sorted by component and name
76  applyToAllSortedEntities( [this, &histoFile]( std::string const& component, std::string const& name,
77  Monitoring::Hub::Entity const& ent ) {
78  // try first a dedicated flush, bypassing json (more efficient)
79  auto typeIndex = ent.typeIndex();
80  auto binSaver = m_binRegistry.find( typeIndex );
81  if ( binSaver != m_binRegistry.end() ) {
82  binSaver->second( *histoFile, component, name, ent );
83  return;
84  }
85  // no fast track, let's use json intermediate format
86  nlohmann::json j = ent;
87  auto dim = j.at( "dimension" ).template get<unsigned int>();
88  auto type = j.at( "type" ).template get<std::string>();
89  // cut type after last ':' if there is one. The rest is precision parameter that we do not need here
90  // as ROOT anyway treats everything as doubles in histograms
91  type = type.substr( 0, type.find_last_of( ':' ) );
92  auto saver = m_registry.find( { type, dim } );
93  if ( saver != m_registry.end() ) ( saver->second )( *histoFile, component, name, j );
94  } );
95  info() << "Completed update of ROOT histograms in: " << m_fileName.value() << endmsg;
96  }
97 
99  m_binRegistry.emplace( std::piecewise_construct, std::make_tuple( id ), std::make_tuple( func ) );
100  }
101 
103  m_registry.emplace( std::piecewise_construct, std::make_tuple( id ), std::make_tuple( func ) );
104  }
105 
106  private:
111 
112  Gaudi::Property<std::string> m_fileName{ this, "FileName", "testHisto.root",
113  "Name of file where to save histograms" };
114 
116  };
117 
118 } // namespace Gaudi::Histograming::Sink
Gaudi::Histograming::Sink::Base::m_fileName
Gaudi::Property< std::string > m_fileName
Definition: Base.h:112
Gaudi::Monitoring::BaseSink
Base class for all Sinks registering to the Monitoring Hub Should be extended by actual Sinks.
Definition: BaseSink.h:40
StatusCode::andThen
StatusCode andThen(F &&f, ARGS &&... args) const
Chain code blocks making the execution conditional a success result.
Definition: StatusCode.h:163
MonitoringHub.h
ServiceHandle< Gaudi::Interfaces::IFileSvc >
PropertyHolder< CommonMessaging< implements< IService, IProperty, IStateful > > >::setProperty
StatusCode setProperty(const Gaudi::Details::PropertyBase &p)
Set the property from a property.
Definition: IProperty.h:38
ISvcLocator
Definition: ISvcLocator.h:42
jsonFromLHCbLog.json
json
Definition: jsonFromLHCbLog.py:86
Gaudi::Histograming::Sink::Base::initialize
StatusCode initialize() override
Definition: Base.h:48
Gaudi::Histograming::Sink::Base::flush
void flush(bool) override
pure virtual method to be defined by children and responsible for flushing current data of the Sink.
Definition: Base.h:64
Gaudi::Histograming::Sink::Base::HistoIdentification
std::pair< std::string, int > HistoIdentification
Definition: Base.h:33
ServiceHandle.h
Gaudi::Histograming::Sink::Base::HistoBinIdentification
std::type_index HistoBinIdentification
Definition: Base.h:37
Gaudi::Histograming::Sink::Base::HistoRegistry
std::map< HistoIdentification, HistoHandler > HistoRegistry
Definition: Base.h:35
ServiceHandle::get
T * get() const
Allow non const access to the service, even from a const handle...
Definition: ServiceHandle.h:77
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:333
StatusCode
Definition: StatusCode.h:64
cpluginsvc.func
func
Definition: cpluginsvc.py:235
Gaudi::Histograming::Sink::Base::registerHandler
void registerHandler(HistoBinIdentification const &id, HistoBinHandler const &func)
Definition: Base.h:98
ProduceConsume.j
j
Definition: ProduceConsume.py:104
Gaudi::Histograming::Sink
Definition: RootHistogramSink.cpp:23
Gaudi::Histograming::Sink::Base::registerHandler
void registerHandler(HistoIdentification const &id, HistoHandler const &func)
Definition: Base.h:102
IFileSvc.h
Gaudi::Property::value
const ValueType & value() const
Definition: Property.h:229
Gaudi::Monitoring::Hub::Entity::typeIndex
std::type_index typeIndex() const
function to get internal type
Definition: MonitoringHub.h:87
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:198
Gaudi::Monitoring::BaseSink::applyToAllSortedEntities
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:110
ServiceHandle::retrieve
StatusCode retrieve(T *&service) const override
Do the real retrieval of the Service.
Definition: ServiceHandle.h:85
Gaudi::Histograming::Sink::Base::m_registry
HistoRegistry m_registry
map of supported type and the way to handle them
Definition: Base.h:110
Gaudi::Histograming::Sink::Base::HistoHandler
std::function< void(TFile &file, std::string, std::string, nlohmann::json const &)> HistoHandler
Definition: Base.h:34
Gaudi::Histograming::Sink::Base::HistoBinHandler
std::function< void(TFile &file, std::string, std::string, Monitoring::Hub::Entity const &)> HistoBinHandler
Definition: Base.h:39
gaudirun.type
type
Definition: gaudirun.py:160
Gaudi::Interfaces::IFileSvc::hasIdentifier
virtual bool hasIdentifier(const std::string &identifier) const =0
Check if a given identifier is known to the service.
Gaudi::Histograming::Sink::Base::HistoBinRegistry
std::map< HistoBinIdentification, HistoBinHandler > HistoBinRegistry
Definition: Base.h:40
Gaudi::Histograming::Sink::Base
Definition: Base.h:31
BaseSink.h
Gaudi::Histograming::Sink::Base::m_fileSvc
ServiceHandle< Gaudi::Interfaces::IFileSvc > m_fileSvc
Definition: Base.h:115
Gaudi::Interfaces::IFileSvc::getFile
virtual std::shared_ptr< TFile > getFile(const std::string &identifier)=0
Get a shared pointer to a TFile based on an identifier.
Gaudi::Monitoring::Hub::Entity
Wrapper class for arbitrary monitoring objects.
Definition: MonitoringHub.h:62
Gaudi::Histograming::Sink::Base::m_binRegistry
HistoBinRegistry m_binRegistry
map of supported type and the way to handle them
Definition: Base.h:108
Gaudi::Property< std::string >
Gaudi::Histograming::Sink::Base::Base
Base(const std::string &name, ISvcLocator *svcloc)
Definition: Base.h:42