The Gaudi Framework  master (69a68366)
Loading...
Searching...
No Matches
Writer.h
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 2024-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/Algorithm.h>
18#include <TFile.h>
19#include <TTree.h>
20#include <fmt/format.h>
21#include <gsl/pointers>
22#include <gsl/span>
23#include <mutex>
24#include <numeric>
25#include <tuple>
26#include <utility>
27
28namespace Gaudi::NTuple {
29
43 template <typename... COLUMNS>
44 class Wrapper {
45 public:
46 // Initialize the TTree and creates branches
47 void initTree( TFile& file, std::string const& algName, std::string const& name,
48 std::array<std::string, sizeof...( COLUMNS )> const& branchNames ) {
49 file.cd();
50 m_tree = std::make_unique<TTree>( name.c_str(), "Tree of Writer Algorithm" ).release();
51 m_branchWrappers.reserve( m_branchWrappers.size() + sizeof...( COLUMNS ) );
52 createBranches( std::make_index_sequence<sizeof...( COLUMNS )>{}, algName, branchNames );
53 }
54
59 void fillTree( std::tuple<COLUMNS...> const& data ) const {
60 std::scoped_lock lock{ m_mtx };
61 std::apply(
62 [&]( const auto&... elems ) {
63 size_t index = 0;
64 ( ..., m_branchWrappers[index++].setDataPtr( const_cast<void*>( static_cast<const void*>( &elems ) ) ) );
65 },
66 data );
67 m_tree->Fill();
68 }
69
70 // Write the TTree to the given ROOT file
71 void writeTree( TFile& file, std::string const& algName ) {
72 file.cd();
73 if ( m_tree->Write() <= 0 ) {
74 throw GaudiException( "Failed to write TTree to ROOT file.", algName, StatusCode::FAILURE );
75 }
76 m_tree = nullptr;
77 }
78
79 private:
80 TTree* m_tree{ nullptr }; // Pointer to the TTree being written to
81 mutable std::vector<details::BranchWrapper> m_branchWrappers{}; // Container for BranchWrapper objects
82 mutable std::mutex m_mtx; // Mutex for thread-safe operations
83
84 // Create branches in the TTree based on the provided names and output data types
85 template <std::size_t... Is>
86 void createBranches( std::index_sequence<Is...> const, std::string const& algName,
87 std::array<std::string, sizeof...( COLUMNS )> const& branchNames ) const {
88 ( ..., m_branchWrappers.emplace_back(
89 m_tree, System::typeinfoName( typeid( std::tuple_element_t<Is, std::tuple<COLUMNS...>> ) ),
90 branchNames[Is], "", algName ) );
91 }
92 };
93
102 template <typename Base>
103 struct FileHolder : Base {
104 using Base::Base;
105 TFile* file() { return m_file.get(); }
106 // Initialize the algorithm, set up the ROOT file and a TTree branch for each input location
107 virtual StatusCode initialize() override {
108 return Base::initialize().andThen( [this]() {
109 m_file = m_fileSvc->getFile( m_fileId );
110 if ( !m_file ) {
111 this->error() << "Failed to retrieve TFile." << endmsg;
112 return StatusCode::FAILURE;
113 }
114 return StatusCode::SUCCESS;
115 } );
116 }
117
118 private:
119 Gaudi::Property<std::string> m_fileId{ this, "OutputFile", "NTuple", "Identifier for the TFile to write to." };
121 std::shared_ptr<TFile> m_file = nullptr; // Pointer to the ROOT file
122 };
123
128 template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::BaseClass_t<Gaudi::Algorithm>>
130 SimpleWriter() = delete;
131 };
132
151 template <typename... OUTPUTs, typename... INPUTs, typename Traits_>
152 struct SimpleWriter<std::tuple<OUTPUTs...>( const INPUTs&... ), Traits_>
153 : FileHolder<Gaudi::Functional::Consumer<void( const INPUTs&... ), Traits_>> {
154 using Consumer_t = FileHolder<Gaudi::Functional::Consumer<void( const INPUTs&... ), Traits_>>;
155 using Consumer_t::Consumer_t;
156
157 Gaudi::Property<std::string> m_ntupleTname{ this, "NTupleName", this->name(), "Name of the TTree." };
158 Gaudi::Property<std::array<std::string, sizeof...( OUTPUTs )>> m_branchNames{
159 this, "BranchNames", {}, "Names of the tree branches." }; // Names for the tree branches
160
161 // Initialize the algorithm, set up the ROOT file and a TTree branch for each input location
162 virtual StatusCode initialize() override {
163 return Consumer_t::initialize().andThen( [this]() {
164 m_ntuple.initTree( *this->file(), this->name(), m_ntupleTname.value(), m_branchNames.value() );
165 return StatusCode::SUCCESS;
166 } );
167 }
168
169 // Fill the TTree with transformed data
170 void fillTree( const std::tuple<OUTPUTs...>& data ) const { m_ntuple.fillTree( data ); }
171
172 // Finalize the algorithm by writing the TTree to the file and closing it
173 virtual StatusCode finalize() override {
174 m_ntuple.writeTree( *this->file(), this->name() );
175 return Consumer_t::finalize();
176 }
177
178 private:
179 Wrapper<OUTPUTs...> m_ntuple;
180 };
181
186 template <typename Signature, typename Traits_ = Gaudi::Functional::Traits::BaseClass_t<Gaudi::Algorithm>>
187 struct Writer {
188 Writer() = delete; // If you wish to not provide any transformation for your data, please use the
189 // NTuple::GenericWriter
190 // algorithm
191 };
192
204 template <typename... OUTPUTs, typename... INPUTs, typename Traits_>
205 struct Writer<std::tuple<OUTPUTs...>( const INPUTs&... ), Traits_>
206 : SimpleWriter<std::tuple<OUTPUTs...>( const INPUTs&... ), Traits_> {
207
208 using SimpleWriter_t = SimpleWriter<std::tuple<OUTPUTs...>( const INPUTs&... ), Traits_>;
209 using SimpleWriter_t::SimpleWriter_t;
210
216 virtual std::tuple<OUTPUTs...> transform( const INPUTs&... inputs ) const = 0;
217
218 // Execute the algorithm for each event, retrieving data from the event store and writing it to the TTree
219 void operator()( const INPUTs&... inputs ) const override {
220 auto transformedData = transform( inputs... );
221 this->fillTree( transformedData );
222 }
223 };
224
225} // namespace Gaudi::NTuple
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
Collection of utilities, which allows to use class std::array as property for Gaudi-components.
Wrapper around a given NTuple.
Definition Writer.h:44
std::mutex m_mtx
Definition Writer.h:82
void fillTree(std::tuple< COLUMNS... > const &data) const
fills the tree with given data this is safe to be called in the threaded context
Definition Writer.h:59
void initTree(TFile &file, std::string const &algName, std::string const &name, std::array< std::string, sizeof...(COLUMNS)> const &branchNames)
Definition Writer.h:47
std::vector< details::BranchWrapper > m_branchWrappers
Definition Writer.h:81
void writeTree(TFile &file, std::string const &algName)
Definition Writer.h:71
void createBranches(std::index_sequence< Is... > const, std::string const &algName, std::array< std::string, sizeof...(COLUMNS)> const &branchNames) const
Definition Writer.h:86
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
Define general base for Gaudi exception.
Handle to be used in lieu of naked pointers to services.
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
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
details::Consumer< Signature, Traits_, details::isLegacy< Traits_ > > Consumer
Definition Consumer.h:69
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition System.cpp:260
STL namespace.
Small class wrapping an algorithm and adding management of a Root File via the FileSvc.
Definition Writer.h:103
virtual StatusCode initialize() override
Definition Writer.h:107
FileHolder< Gaudi::Functional::Consumer< void(const INPUTs &...), Traits_ > > Consumer_t
Definition Writer.h:154
Gaudi::Property< std::array< std::string, sizeof...(OUTPUTs)> > m_branchNames
Definition Writer.h:158
virtual std::tuple< OUTPUTs... > transform(const INPUTs &... inputs) const =0
Transform input data to the desired output format.
SimpleWriter< std::tuple< OUTPUTs... >(const INPUTs &...), Traits_ > SimpleWriter_t
Definition Writer.h:208