R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BIOConnector.h
Go to the documentation of this file.
1#pragma once
2/******************************************************************************
3 * Copyright (C) 2023 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
4 * Copyright (C) 2023-2026 Members of R3B Collaboration *
5 * *
6 * This software is distributed under the terms of the *
7 * GNU General Public Licence (GPL) version 3, *
8 * copied verbatim in the file "LICENSE". *
9 * *
10 * In applying this license GSI does not waive the privileges and immunities *
11 * granted to it by virtue of its status as an Intergovernmental Organization *
12 * or submit itself to any jurisdiction. *
13 ******************************************************************************/
14
15// TODO: use C++20 std::source_location
16#include <boost/assert/source_location.hpp>
17
18#include <FairRootManager.h>
19#include <R3BException.h>
20#include <R3BLogger.h>
21#include <TClonesArray.h>
22#include <TCollection.h>
23#include <TObject.h>
24#include <cstddef>
25#include <fmt/core.h>
26#include <fmt/format.h>
27#include <map>
28#include <string>
29#include <string_view>
30#include <type_traits>
31#include <unordered_map>
32#include <vector>
33
34#if CPP_STANDARD > 20
35#include <concepts>
36#endif
37
38// TODO: Use C++20 Concept to put more constains on the template parameters
39namespace R3B
40{
41 template <typename InputType>
43 {
44 public:
45 using RawDataType = std::remove_const_t<std::remove_cv_t<InputType>>;
46 explicit InputConnector(std::string_view branchName)
47 : branch_name_{ branchName }
48 {
49 }
50
58 void init(bool is_optional = false, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
59 {
60 auto* ioman = FairRootManager::Instance();
61 if (ioman == nullptr)
62 {
63 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
64 "input data with the branch name \"{}\"",
66 loc);
67 }
68
69 data_ = ioman->InitObjectAs<const RawDataType*>(branch_name_.c_str());
70
71 if (data_ == nullptr)
72 {
73 if (is_optional)
74 {
75 R3BLOG(warn,
76 fmt::format("The data branch {:?} doesn't exist in the input root file!", branch_name_));
77 }
78 else
79 {
81 fmt::format("Initialisation of the input data with the branch name \"{}\" failed!",
83 loc);
84 }
85 }
86 }
87
88 [[nodiscard]] auto get(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const -> const RawDataType&
89 {
90 check_init(loc);
91 return *data_;
92 }
93
94 auto size(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const
95 {
96 check_init(loc);
97 return data_->size();
98 }
99
100 // implement range-based for loop:
101 // TODO: is there a simpler way?
102 auto begin(const boost::source_location& loc = BOOST_CURRENT_LOCATION)
103 {
104 check_init(loc);
105 return data_->cbegin();
106 }
107 auto begin(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const
108 {
109 check_init(loc);
110 return data_->cbegin();
111 }
112 auto end(const boost::source_location& loc = BOOST_CURRENT_LOCATION)
113 {
114 check_init(loc);
115 return data_->cend();
116 }
117 auto end(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const
118 {
119 check_init(loc);
120 return data_->cend();
121 }
122
123 private:
124 std::string branch_name_;
125 const RawDataType* data_ = nullptr;
126 void check_init(const boost::source_location& loc) const
127 {
128 if (data_ == nullptr)
129 {
130 throw R3B::runtime_error(fmt::format("Input data with the branch name \"{}\" cannot be "
131 "queried without an initialisation!",
133 loc);
134 }
135 }
136 };
137
138 template <typename InputType,
139 typename = std::enable_if_t<std::is_base_of_v<TObject, std::remove_const_t<std::remove_cv_t<InputType>>>>>
141 {
142 public:
143 using RawDataType = std::remove_const_t<std::remove_cv_t<InputType>>;
144 explicit InputTCAConnector(std::string_view branchName)
145 : branch_name_{ branchName }
146 {
147 }
148
149 void init(bool is_optional = false, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
150 {
151 auto* ioman = FairRootManager::Instance();
152 if (ioman == nullptr)
153 {
154 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
155 "input data with the branch name \"{}\"",
157 loc);
158 }
159
160 data_ = dynamic_cast<TClonesArray*>(ioman->GetObject(branch_name_.c_str()));
161 if (data_ == nullptr)
162 {
163 const auto msg = fmt::format(
164 "Input TCA data with the branch name {:?} cannot be retrieved from the input file !", branch_name_);
165 if (is_optional)
166 {
167 R3BLOG(warn, msg.c_str());
168 return;
169 }
170 throw R3B::runtime_error(msg, loc);
171 }
172
173 check_element_type(is_optional, loc);
174 }
175
176 auto read() -> const std::vector<RawDataType>&
177 {
178 output_data_.clear();
179 if (data_ == nullptr)
180 {
181 return output_data_;
182 }
183
184 output_data_.reserve(data_->GetEntriesFast());
185 for (auto* element : TRangeDynCast<RawDataType>(data_))
186 {
187 output_data_.emplace_back(*element);
188 }
189 return output_data_;
190 }
191
192 [[nodiscard]] auto size() const -> std::size_t { return data_ == nullptr ? 0 : data_->GetEntriesFast(); }
193
194 [[nodiscard]] auto get() const -> const std::vector<RawDataType>& { return output_data_; }
195 [[nodiscard]] auto get_name() const -> const std::string& { return branch_name_; }
196
197 private:
198 std::string branch_name_;
199 std::vector<RawDataType> output_data_;
200 TClonesArray* data_ = nullptr;
201
202 void check_element_type(bool is_optional, const boost::source_location& loc)
203 {
204 if (std::string_view{ data_->GetClass()->GetName() } != InputType::Class_Name())
205 {
206 const auto msg = fmt::format(
207 "The type of the retrieved data {:?} is not the same as the type given by the connector class {}!",
208 data_->GetClass()->GetName(),
209 InputType::Class_Name());
210 if (is_optional)
211 {
212 R3BLOG(warn, msg.c_str());
213 return;
214 }
215 throw R3B::runtime_error(msg, loc);
216 }
217 }
218 };
219
220#if CPP_STANDARD >= 20
221 template <typename T>
222 concept CanOutput = requires(T data) {
223 { data.clear() } -> std::convertible_to<void>;
224 };
225
226 template <CanOutput OutputType>
227#else
228 template <typename OutputType>
229#endif
231 {
232 public:
233 using RawDataType = std::remove_const_t<std::remove_cv_t<OutputType>>;
234 explicit OutputConnector(std::string_view branchName)
235 : branch_name_{ branchName }
236 {
237 }
238
239 // rule of 5
240 ~OutputConnector() = default;
245
247 {
248 data_ = data;
249 return *this;
250 }
251 auto operator*() -> RawDataType& { return data_; }
252 auto operator->() -> RawDataType* { return &data_; }
253
254 void init(bool persistence = true, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
255 {
256 if (auto* ioman = FairRootManager::Instance(); ioman != nullptr)
257 {
258 ioman->RegisterAny(branch_name_.c_str(), data_ptr_, persistence);
259 }
260 else
261 {
262 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
263 "output data with the branch name \"{}\"",
265 loc);
266 }
267 }
268
269 [[nodiscard]] auto get() -> RawDataType& { return data_; }
270 [[nodiscard]] auto get_constref() const -> const RawDataType& { return data_; }
271 [[nodiscard]] auto get_name() const -> const std::string& { return branch_name_; }
272
273 void clear() { data_.clear(); }
274
275 template <typename ResetOp>
276 void clear(ResetOp opn)
277 {
278 opn(data_);
279 }
280
281 auto size() const { return data_.size(); }
282
283 private:
284 std::string branch_name_;
287 };
288
289 template <typename ElementType>
291
292 template <typename ElementType>
294
295 template <typename KeyType, typename ValueType>
297
298 template <typename KeyType, typename ValueType>
300
301 template <typename KeyType, typename ValueType>
303
304 template <typename KeyType, typename ValueType>
306} // namespace R3B
#define R3BLOG(severity, x)
Definition R3BLogger.h:33
auto size(const boost::source_location &loc=BOOST_CURRENT_LOCATION) const
auto begin(const boost::source_location &loc=BOOST_CURRENT_LOCATION)
void check_init(const boost::source_location &loc) const
std::remove_const_t< std::remove_cv_t< InputType > > RawDataType
InputConnector(std::string_view branchName)
void init(bool is_optional=false, const boost::source_location &loc=BOOST_CURRENT_LOCATION)
Initialisation for the connector of non-TCA input data.
auto begin(const boost::source_location &loc=BOOST_CURRENT_LOCATION) const
auto end(const boost::source_location &loc=BOOST_CURRENT_LOCATION) const
auto end(const boost::source_location &loc=BOOST_CURRENT_LOCATION)
auto get(const boost::source_location &loc=BOOST_CURRENT_LOCATION) const -> const RawDataType &
void init(bool is_optional=false, const boost::source_location &loc=BOOST_CURRENT_LOCATION)
void check_element_type(bool is_optional, const boost::source_location &loc)
InputTCAConnector(std::string_view branchName)
auto read() -> const std::vector< RawDataType > &
auto get() const -> const std::vector< RawDataType > &
auto get_name() const -> const std::string &
auto size() const -> std::size_t
std::remove_const_t< std::remove_cv_t< InputType > > RawDataType
std::vector< RawDataType > output_data_
OutputConnector & operator=(const RawDataType &data)
OutputConnector & operator=(OutputConnector &&)=delete
auto operator*() -> RawDataType &
OutputConnector(OutputConnector &&)=delete
OutputConnector(std::string_view branchName)
std::remove_const_t< std::remove_cv_t< OutputType > > RawDataType
auto get_name() const -> const std::string &
auto operator->() -> RawDataType *
~OutputConnector()=default
OutputConnector & operator=(const OutputConnector &other)=delete
auto get_constref() const -> const RawDataType &
auto get() -> RawDataType &
void clear(ResetOp opn)
void init(bool persistence=true, const boost::source_location &loc=BOOST_CURRENT_LOCATION)
OutputConnector(const OutputConnector &)=delete
InputConnector< std::vector< ElementType > > InputVectorConnector
OutputConnector< std::map< KeyType, ValueType > > OutputMapConnector
InputConnector< std::map< KeyType, ValueType > > InputMapConnector
OutputConnector< std::unordered_map< KeyType, ValueType > > OutputHashConnector
InputConnector< std::unordered_map< KeyType, ValueType > > InputHashConnector
OutputConnector< std::vector< ElementType > > OutputVectorConnector