ATLAS Offline Software
Loading...
Searching...
No Matches
CaloGPUClusterAndCellDataMonitorOptions.h
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3//
4// Dear emacs, this is -*- c++ -*-
5//
6
7#ifndef CALORECGPU_CALOGPUCLUSTERANDCELLDATAMONITOROPTIONS_H
8#define CALORECGPU_CALOGPUCLUSTERANDCELLDATAMONITOROPTIONS_H
9
10//This sets up some classes to be usable as options within Gaudi (and thus Athena),
11//so that we can more ergonomically specify our plotter's options.
12//
13//For reference, see Gaudi/GaudiExamples/src/Properties/CustomPropertiesAlg.cpp
14
15
16#include <tuple>
17#include <iostream>
18#include <string>
19#include <type_traits>
20
21
22
24
25#include "GaudiKernel/StatusCode.h"
26
27#include <Gaudi/Parsers/Factory.h>
28
29//Suppress the warning that comes up from simply including Factory.h.
30
31//First, generic handling of tuples.
32//This does set us up for handling more than we strictly need,
33//but since this is only a local include
34//and shouldn't bleed over to other parts of the code,
35//we'll behave and (hopefully) not do anything too crazy.
36
37
38//Since we're at C++17 level,
39//we'll use SFINAE and enable_if
40//to provide the *actual* parse and grammar and output
41//that are necessary for custom types for Gaudi options.
42//In C++20, of course we could use concepts
43//for a more elegant implementation...
44
45namespace impl
46{
47 template <class Check> struct class_can_be_tuple
48 {
49 template<class T> inline static constexpr
50 auto tuple_type_checker(T *) -> decltype(typename T::TupleType {});
51 template<class T> inline static constexpr
53 template <class T> using tuple_type_checker_type = decltype( tuple_type_checker<T>(nullptr) );
54 template <class T> inline static constexpr
55 bool tuple_type_exists = !std::is_same_v<tuple_type_checker_type<T>, void>;
56
57 template<class T> inline static constexpr
58 auto to_tuple_checker(T *) -> decltype(&T::to_tuple);
59 template<class T> inline static constexpr
61 template <class T> inline static constexpr
62 bool to_tuple_exists = std::is_pointer_v<decltype( to_tuple_checker<T>(nullptr) )>;
63
64 template<class T> inline static constexpr
65 auto from_tuple_checker(T *) -> decltype(&T::from_tuple);
66 template<class T> inline static constexpr
68 template <class T> inline static constexpr
69 bool from_tuple_exists = std::is_pointer_v<decltype( from_tuple_checker<T>(nullptr) )>;
70
71 template<class T> inline static constexpr
72 auto tuple_size_checker(T *) -> decltype(T::TupleSize);
73 template<class T> inline static constexpr
75 template <class T> inline static constexpr
76 bool tuple_size_exists = !std::is_void_v<decltype(tuple_size_checker<T>(nullptr))>;
77
79 };
80
81 template <class T>
82 inline static constexpr bool class_can_be_tuple_v = class_can_be_tuple<T>::value;
83
84 template <class T>
85 void tuple_safe_copy(T & dest, const T & source)
86 {
87 dest = source;
88 }
89}
90
91//We use our macros to write a relatively limited form of variadic structured bindings
92//for the tuple <-> struct conversions.
93
94#include "MacroHelpers.h"
95
96#define CALORECGPU_VARSB_APPENDER(THIS, PREFIX, IGNORE) , CRGPU_CONCAT(PREFIX, THIS)
97#define CALORECGPU_VARSB_ASSIGNER(THIS, IGNORE1, IGNORE2) tuple_safe_copy(CRGPU_CONCAT(b, THIS), CRGPU_CONCAT(a, THIS));
98
99#define CALORECGPU_VARSB_ENCAPSULATOR_A(...) CRGPU_MACRO_EXPANSION(CALORECGPU_VARSB_APPENDER, a, __VA_ARGS__ )
100#define CALORECGPU_VARSB_ENCAPSULATOR_B(...) CRGPU_MACRO_EXPANSION(CALORECGPU_VARSB_APPENDER, b, __VA_ARGS__ )
101
102#define CALORECGPU_VARSB_ENCAPSULATOR_ASSIGN(...) CRGPU_MACRO_EXPANSION(CALORECGPU_VARSB_ASSIGNER, _ , __VA_ARGS__, )
103
104
105#define CALORECGPU_VARSB_EXPANDER(THIS_NUM, IGNORE, SMALLER_NUMS) \
106 template <> struct struct_tuple_conversion<THIS_NUM> \
107 { \
108 template <class T, class TupleT> \
109 static void s2t(const T & t, TupleT & tup) \
110 { \
111 const auto & [CRGPU_CONCAT(a, THIS_NUM) CALORECGPU_VARSB_ENCAPSULATOR_A SMALLER_NUMS] = t; \
112 auto & [CRGPU_CONCAT(b, THIS_NUM) CALORECGPU_VARSB_ENCAPSULATOR_B SMALLER_NUMS] = tup; \
113 tuple_safe_copy(CRGPU_CONCAT(b, THIS_NUM), CRGPU_CONCAT(a, THIS_NUM)); \
114 CALORECGPU_VARSB_ENCAPSULATOR_ASSIGN SMALLER_NUMS \
115 } \
116 template <class TupleT, class T> \
117 static void t2s(const TupleT & tup, T & t) \
118 { \
119 const auto & [CRGPU_CONCAT(a, THIS_NUM) CALORECGPU_VARSB_ENCAPSULATOR_A SMALLER_NUMS] = tup; \
120 auto & [CRGPU_CONCAT(b, THIS_NUM) CALORECGPU_VARSB_ENCAPSULATOR_B SMALLER_NUMS] = t; \
121 tuple_safe_copy(CRGPU_CONCAT(b, THIS_NUM), CRGPU_CONCAT(a, THIS_NUM)); \
122 CALORECGPU_VARSB_ENCAPSULATOR_ASSIGN SMALLER_NUMS \
123 } \
124 }; \
125
126//If only there were truly variadic structured bindings...
127
128namespace impl
129{
130
131 template <size_t n> struct struct_tuple_conversion
132 {
133 template <class T, class TupleT>
134 static void s2t(const T &, TupleT &) { }
135 template <class T, class TupleT>
136 static T t2s(const TupleT &, T &) { }
137 };
138
140 //If we needed structs with more than 9 elements, just add more numbers to the left in descending order...
141
142 template <class T,
143 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
144 void tuple_safe_copy(T & s, const typename T::TupleType & tuple)
145 {
147 }
148
149 template <class T,
150 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
151 void tuple_safe_copy(typename T::TupleType & tuple, const T & s)
152 {
154 }
155
156 template <class T,
157 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
158 void tuple_safe_copy(std::vector<typename T::TupleType> & t_v, const std::vector<T> & s_v)
159 {
160 t_v.resize(s_v.size());
161 for (size_t i = 0; i < s_v.size(); ++i)
162 {
163 tuple_safe_copy(t_v[i], s_v[i]);
164 }
165 }
166
167 template <class T,
168 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
169 void tuple_safe_copy(std::vector<T> & s_v, const std::vector<typename T::TupleType> & t_v)
170 {
171 s_v.resize(t_v.size());
172 for (size_t i = 0; i < t_v.size(); ++i)
173 {
174 tuple_safe_copy(s_v[i], t_v[i]);
175 }
176 }
177
178
179 template <class T>
180 auto to_tuple_type_helper(const T &)
181 {
182 return T{};
183 }
184 /*
185 template <class T,
186 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
187 auto to_tuple_type_helper(const T&)
188 {
189 return typename T::TupleType{};
190 }
191 */
192 template <class T,
193 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
194 auto to_tuple_type_helper(const std::vector<T> &)
195 {
196 return std::vector<typename T::TupleType> {};
197 }
198
199 /*
200 template <class ... Elems>
201 auto to_tuple_type_helper(const std::tuple<Elems...> &)
202 {
203 return std::tuple<decltype(to_tuple_type_helper(std::declval<Elems>))...>{};
204 }
205 */
206 //More specializations if needed?
207
208
209 template <class T>
210 using to_tuple_type = decltype(to_tuple_type_helper(std::declval<T>()));
211
212 template <class T, class ... Elems> struct simple_tuple_conversion
213 {
214 using TupleType = std::tuple<to_tuple_type<Elems>...>;
215
216 inline static constexpr size_t TupleSize = sizeof...(Elems);
217
218 static TupleType to_tuple (const T & s)
219 {
220 TupleType ret;
222 return ret;
223 }
224 static T from_tuple(const TupleType & tup)
225 {
226 T ret;
228 return ret;
229 }
230 /*
231 friend
232 std::ostream & operator<< (std::ostream & s, const T & t)
233 {
234 return s << to_tuple(t);
235 }
236 */
237 };
238
239 //If we had reflection, this would be so much easier...
240
241 template <class Stream, class T>
242 void output_helper(Stream & s, const T & t, const std::string & after)
243 {
245 s << after;
246 }
247
248 template <class Stream, class T>
249 void output_helper(Stream & s, const std::vector<T> & v, const std::string & after)
250 {
251 s << "[";
252 for (size_t i = 0; i < v.size(); ++i)
253 {
254 if (i > 0)
255 {
256 s << ", ";
257 }
258 impl::output_helper(s, v[i], "");
259 }
260 s << "]" << after;
261 }
262 /*
263 template <class Stream, class T,
264 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
265 void output_helper(Stream & s, const T & t, const std::string & after)
266 {
267 s << t << after;
268 }
269 */
270}
271
272namespace Gaudi
273{
274 namespace Parsers
275 {
276
277 template <typename Iterator, typename Skipper, class T>
278 struct Grammar_< Iterator, T, Skipper, typename std::enable_if_t < impl::class_can_be_tuple_v<T> > >
279 {
280 using Grammar = typename Grammar_<Iterator, typename T::TupleType, Skipper>::Grammar;
281 };
282
283 template <class ... Tup>
284 StatusCode parse(std::tuple<Tup...> & tup, const Gaudi::Parsers::InputData & input)
285 {
286 return parse_(tup, input);
287 }
288
289 template <class T>
290 StatusCode parse(std::vector<T> & v, const Gaudi::Parsers::InputData & input)
291 {
292 return parse_(v, input);
293 }
294
295 }
296}
297
298template <class ... Tup>
299std::ostream & operator<<(std::ostream & s, const std::tuple<Tup...> & tup )
300{
301 std::apply( [&] (const Tup & ... arg)
302 {
303 s << "(";
304
305 size_t num = 0;
306
307 (void) ( (void) impl::output_helper(s, arg, (++num < sizeof...(Tup) ? ", " : "")), ... );
308
309 s << ")";
310
311 }, tup );
312
313 return s;
314}
315
316template < class T,
317 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
318std::ostream & operator<<(std::ostream & s, const T & t )
319{
320 return s << T::to_tuple(t);
321}
322
323//And now for the classes proper.
324//
325//In general:
326//
327//struct ClassName: impl::simple_tuple_conversion<ClassName, T1, T2, ... , TN>
328//{
329// T1 name1;
330// T2 name2;
331// ...
332// TN nameN;
333//
334// ClassName() = default;
335// ClassName(const TupleType & t)
336// {
337// (*this) = from_tuple(t);
338// }
339//};
340//
341//One could use the helper macro below.
342//
343//If there are mismatches in the types on the simple_tuple_conversion list,
344//ugly compilation issues may ensue!
345
346#define CALORECGPU_OPTIONCLASS_CONSTRUCTORS(CLASSNAME) \
347 CLASSNAME() = default; \
348 CLASSNAME(const TupleType & t) \
349 { \
350 (*this) = from_tuple(t); \
351 } \
352
354 impl::simple_tuple_conversion<MatchingOptions, double, double, double, double>
355{
356 double min_similarity = 0.50, term_w = 250., grow_w = 500., seed_w = 1000.;
357
359};
360
362 impl::simple_tuple_conversion<SimpleSingleTool, std::string, std::string>
363{
364 std::string tool, plot_id;
365
367};
368
370 impl::simple_tuple_conversion<SimpleToolPair, std::string, std::string, std::string, bool, bool, bool>
371{
373 bool match_in_energy = false;
375 bool match_perfectly = false;
376
378};
379
380//This was used more heavily when we had the standalone plotter,
381//but I would like to keep it here in case more changes are necessary...
382
383#endif //CALORECGPU_CALOGPUCLUSTERANDCELLDATAMONITOROPTIONS_H
#define CALORECGPU_VARSB_EXPANDER(THIS_NUM, IGNORE, SMALLER_NUMS)
std::ostream & operator<<(std::ostream &s, const std::tuple< Tup... > &tup)
#define CALORECGPU_OPTIONCLASS_CONSTRUCTORS(CLASSNAME)
Contains some helpful macros to help with repetitive code...
#define CRGPU_MACRO_EXPANSION(MACRO, EXTRA_ARG,...)
Helper macro to apply a macro to all elements of the variadic list, with EXTRA_ARG and the parenthesi...
#define CRGPU_RECURSIVE_MACRO(...)
Expands recursive macros.
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
std::ostream & toStream(const SG::VarHandleKeyArray &v, std::ostream &o)
Gaudi function used to convert a property to a string.
=============================================================================
void output_helper(Stream &s, const T &t, const std::string &after)
static constexpr bool class_can_be_tuple_v
void tuple_safe_copy(T &dest, const T &source)
decltype(to_tuple_type_helper(std::declval< T >())) to_tuple_type
STL namespace.
decltype(tuple_type_checker< T >(nullptr)) tuple_type_checker_type
static constexpr auto tuple_type_checker(T *) -> decltype(typename T::TupleType {})
static constexpr auto from_tuple_checker(T *) -> decltype(&T::from_tuple)
static constexpr auto tuple_size_checker(T *) -> decltype(T::TupleSize)
static constexpr void tuple_type_checker(...)
static constexpr void tuple_size_checker(...)
static constexpr auto to_tuple_checker(T *) -> decltype(&T::to_tuple)
static constexpr void from_tuple_checker(...)
static constexpr void to_tuple_checker(...)
std::tuple< to_tuple_type< Elems >... > TupleType