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