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
191 private:
192 std::string branch_name_;
193 std::vector<RawDataType> output_data_;
194 TClonesArray* data_ = nullptr;
195
196 void check_element_type(bool is_optional, const boost::source_location& loc)
197 {
198 if (std::string_view{ data_->GetClass()->GetName() } != InputType::Class_Name())
199 {
200 const auto msg = fmt::format(
201 "The type of the retrieved data {:?} is not the same as the type given by the connector class {}!",
202 data_->GetClass()->GetName(),
203 InputType::Class_Name());
204 if (is_optional)
205 {
206 R3BLOG(warn, msg.c_str());
207 return;
208 }
209 throw R3B::runtime_error(msg, loc);
210 }
211 }
212 };
213
214 template <typename OutputType>
216 {
217 public:
218 using RawDataType = std::remove_const_t<std::remove_cv_t<OutputType>>;
219 explicit OutputConnector(std::string_view branchName)
220 : branch_name_{ branchName }
221 {
222 }
223
224 // rule of 5
225 ~OutputConnector() = default;
230
231 void init(bool persistance = true, const boost::source_location& loc = BOOST_CURRENT_LOCATION)
232 {
233 if (auto* ioman = FairRootManager::Instance(); ioman != nullptr)
234 {
235 ioman->RegisterAny(branch_name_.c_str(), data_ptr_, persistance);
236 }
237 else
238 {
239 throw R3B::runtime_error(fmt::format("FairRootManager is nullptr during the initialisation of the "
240 "output data with the branch name \"{}\"",
242 loc);
243 }
244 }
245
246 [[nodiscard]] auto get() -> RawDataType& { return data_; }
247 [[nodiscard]] auto get_constref() const -> const RawDataType& { return data_; }
248
249 void clear() { data_.clear(); }
250
251 template <typename ResetOp>
252 void clear(ResetOp opn)
253 {
254 opn(data_);
255 }
256
257 auto size() const { return data_.size(); }
258
259 private:
260 std::string branch_name_;
263 };
264
265 template <typename ElementType>
267
268 template <typename ElementType>
270
271 template <typename KeyType, typename ValueType>
273
274 template <typename KeyType, typename ValueType>
276
277 template <typename KeyType, typename ValueType>
279
280 template <typename KeyType, typename ValueType>
282} // 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 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
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