R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BIOConnector.h
Go to the documentation of this file.
1#pragma once
2/******************************************************************************
3 * Copyright (C) 2019 GSI Helmholtzzentrum für Schwerionenforschung GmbH *
4 * Copyright (C) 2019-2025 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 <map>
27#include <string>
28#include <string_view>
29#include <type_traits>
30#include <unordered_map>
31#include <vector>
32
33// TODO: Use C++20 Concept to put more constains on the template parameters
34namespace R3B
35{
36 template <typename InputType>
38 {
39 public:
40 using RawDataType = std::remove_const_t<std::remove_cv_t<InputType>>;
41 explicit InputConnector(std::string_view branchName)
42 : branch_name_{ branchName }
43 {
44 }
45
53 void init(bool is_optional = false, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
54 {
55 auto* ioman = FairRootManager::Instance();
56 if (ioman == nullptr)
57 {
58 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
59 "input data with the branch name \"{}\"",
61 loc);
62 }
63
64 data_ = ioman->InitObjectAs<const RawDataType*>(branch_name_.c_str());
65
66 if (data_ == nullptr)
67 {
68 if (is_optional)
69 {
70 R3BLOG(warn,
71 fmt::format("The data branch {:?} doesn't exist in the input root file!", branch_name_));
72 }
73 else
74 {
76 fmt::format("Initialisation of the input data with the branch name \"{}\" failed!",
78 loc);
79 }
80 }
81 }
82
83 [[nodiscard]] auto get(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const -> const RawDataType&
84 {
85 check_init(loc);
86 return *data_;
87 }
88
89 auto size(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const
90 {
91 check_init(loc);
92 return data_->size();
93 }
94
95 // implement range-based for loop:
96 // TODO: is there a simpler way?
97 auto begin(const boost::source_location& loc = BOOST_CURRENT_LOCATION)
98 {
99 check_init(loc);
100 return data_->cbegin();
101 }
102 auto begin(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const
103 {
104 check_init(loc);
105 return data_->cbegin();
106 }
107 auto end(const boost::source_location& loc = BOOST_CURRENT_LOCATION)
108 {
109 check_init(loc);
110 return data_->cend();
111 }
112 auto end(const boost::source_location& loc = BOOST_CURRENT_LOCATION) const
113 {
114 check_init(loc);
115 return data_->cend();
116 }
117
118 private:
119 std::string branch_name_;
120 const RawDataType* data_ = nullptr;
121 void check_init(const boost::source_location& loc) const
122 {
123 if (data_ == nullptr)
124 {
125 throw R3B::runtime_error(fmt::format("Input data with the branch name \"{}\" cannot be "
126 "queried without an initialisation!",
128 loc);
129 }
130 }
131 };
132
133 template <typename InputType,
134 typename = std::enable_if_t<std::is_base_of_v<TObject, std::remove_const_t<std::remove_cv_t<InputType>>>>>
136 {
137 public:
138 using RawDataType = std::remove_const_t<std::remove_cv_t<InputType>>;
139 explicit InputTCAConnector(std::string_view branchName)
140 : branch_name_{ branchName }
141 {
142 }
143
144 void init(bool is_optional = false, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
145 {
146 auto* ioman = FairRootManager::Instance();
147 if (ioman == nullptr)
148 {
149 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
150 "input data with the branch name \"{}\"",
152 loc);
153 }
154
155 data_ = dynamic_cast<TClonesArray*>(ioman->GetObject(branch_name_.c_str()));
156 if (data_ == nullptr)
157 {
158 const auto msg = fmt::format(
159 "Input TCA data with the branch name {:?} cannot be retrieved from the input file !", branch_name_);
160 if (is_optional)
161 {
162 R3BLOG(warn, msg.c_str());
163 return;
164 }
165 throw R3B::runtime_error(msg, loc);
166 }
167
168 check_element_type(is_optional, loc);
169 }
170
171 auto read() -> const std::vector<RawDataType>&
172 {
173 output_data_.clear();
174 if (data_ == nullptr)
175 {
176 return output_data_;
177 }
178
179 output_data_.reserve(data_->GetEntriesFast());
180 for (auto* element : TRangeDynCast<RawDataType>(data_))
181 {
182 output_data_.emplace_back(*element);
183 }
184 return output_data_;
185 }
186
187 [[nodiscard]] auto size() const -> std::size_t { return data_ == nullptr ? 0 : data_->GetEntriesFast(); }
188
189 [[nodiscard]] auto get() const -> const std::vector<RawDataType>& { return output_data_; }
190 [[nodiscard]] auto get_name() const -> const std::string& { return branch_name_; }
191
192 private:
193 std::string branch_name_;
194 std::vector<RawDataType> output_data_;
195 TClonesArray* data_ = nullptr;
196
197 void check_element_type(bool is_optional, const boost::source_location& loc)
198 {
199 if (std::string_view{ data_->GetClass()->GetName() } != InputType::Class_Name())
200 {
201 const auto msg = fmt::format(
202 "The type of the retrieved data {:?} is not the same as the type given by the connector class {}!",
203 data_->GetClass()->GetName(),
204 InputType::Class_Name());
205 if (is_optional)
206 {
207 R3BLOG(warn, msg.c_str());
208 return;
209 }
210 throw R3B::runtime_error(msg, loc);
211 }
212 }
213 };
214
215 template <typename OutputType>
217 {
218 public:
219 using RawDataType = std::remove_const_t<std::remove_cv_t<OutputType>>;
220 explicit OutputConnector(std::string_view branchName)
221 : branch_name_{ branchName }
222 {
223 }
224
225 // rule of 5
226 ~OutputConnector() = default;
231
232 void init(bool persistance = true, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
233 {
234 if (auto* ioman = FairRootManager::Instance(); ioman != nullptr)
235 {
236 ioman->RegisterAny(branch_name_.c_str(), data_ptr_, persistance);
237 }
238 else
239 {
240 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
241 "output data with the branch name \"{}\"",
243 loc);
244 }
245 }
246
247 [[nodiscard]] auto get() -> RawDataType& { return data_; }
248 [[nodiscard]] auto get_constref() const -> const RawDataType& { return data_; }
249 [[nodiscard]] auto get_name() const -> const std::string& { return branch_name_; }
250
251 void clear() { data_.clear(); }
252
253 template <typename ResetOp>
254 void clear(ResetOp opn)
255 {
256 opn(data_);
257 }
258
259 auto size() const { return data_.size(); }
260
261 private:
262 std::string branch_name_;
265 };
266
267 template <typename ElementType>
269
270 template <typename ElementType>
272
273 template <typename KeyType, typename ValueType>
275
276 template <typename KeyType, typename ValueType>
278
279 template <typename KeyType, typename ValueType>
281
282 template <typename KeyType, typename ValueType>
284} // namespace R3B
#define R3BLOG(severity, x)
Definition R3BLogger.h:32
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=(OutputConnector &&)=delete
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 &
void init(bool persistance=true, const boost::source_location &loc=BOOST_CURRENT_LOCATION)
~OutputConnector()=default
OutputConnector & operator=(const OutputConnector &other)=delete
auto get_constref() const -> const RawDataType &
auto get() -> RawDataType &
void clear(ResetOp opn)
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