ATLAS Offline Software
Loading...
Searching...
No Matches
CaloGPUClusterAndCellDataMonitorOptions.h
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2026 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 //cppcheck-suppress unknownMacro
139 //cppcheck-suppress syntaxError
141 //If we needed structs with more than 9 elements, just add more numbers to the left in descending order...
142
143 template <class T,
144 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
145 void tuple_safe_copy(T & s, const typename T::TupleType & tuple)
146 {
148 }
149
150 template <class T,
151 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
152 void tuple_safe_copy(typename T::TupleType & tuple, const T & s)
153 {
155 }
156
157 template <class T,
158 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
159 void tuple_safe_copy(std::vector<typename T::TupleType> & t_v, const std::vector<T> & s_v)
160 {
161 t_v.resize(s_v.size());
162 for (size_t i = 0; i < s_v.size(); ++i)
163 {
164 tuple_safe_copy(t_v[i], s_v[i]);
165 }
166 }
167
168 template <class T,
169 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
170 void tuple_safe_copy(std::vector<T> & s_v, const std::vector<typename T::TupleType> & t_v)
171 {
172 s_v.resize(t_v.size());
173 for (size_t i = 0; i < t_v.size(); ++i)
174 {
175 tuple_safe_copy(s_v[i], t_v[i]);
176 }
177 }
178
179
180 template <class T>
181 auto to_tuple_type_helper(const T &)
182 {
183 return T{};
184 }
185 /*
186 template <class T,
187 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
188 auto to_tuple_type_helper(const T&)
189 {
190 return typename T::TupleType{};
191 }
192 */
193 template <class T,
194 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
195 auto to_tuple_type_helper(const std::vector<T> &)
196 {
197 return std::vector<typename T::TupleType> {};
198 }
199
200 /*
201 template <class ... Elems>
202 auto to_tuple_type_helper(const std::tuple<Elems...> &)
203 {
204 return std::tuple<decltype(to_tuple_type_helper(std::declval<Elems>))...>{};
205 }
206 */
207 //More specializations if needed?
208
209
210 template <class T>
211 using to_tuple_type = decltype(to_tuple_type_helper(std::declval<T>()));
212
213 template <class T, class ... Elems> struct simple_tuple_conversion
214 {
215 using TupleType = std::tuple<to_tuple_type<Elems>...>;
216
217 inline static constexpr size_t TupleSize = sizeof...(Elems);
218
219 static TupleType to_tuple (const T & s)
220 {
221 TupleType ret;
223 return ret;
224 }
225 static T from_tuple(const TupleType & tup)
226 {
227 T ret;
229 return ret;
230 }
231 /*
232 friend
233 std::ostream & operator<< (std::ostream & s, const T & t)
234 {
235 return s << to_tuple(t);
236 }
237 */
238 };
239
240 //If we had reflection, this would be so much easier...
241
242 template <class Stream, class T>
243 void output_helper(Stream & s, const T & t, const std::string & after)
244 {
246 s << after;
247 }
248
249 template <class Stream, class T>
250 void output_helper(Stream & s, const std::vector<T> & v, const std::string & after)
251 {
252 s << "[";
253 for (size_t i = 0; i < v.size(); ++i)
254 {
255 if (i > 0)
256 {
257 s << ", ";
258 }
259 impl::output_helper(s, v[i], "");
260 }
261 s << "]" << after;
262 }
263 /*
264 template <class Stream, class T,
265 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
266 void output_helper(Stream & s, const T & t, const std::string & after)
267 {
268 s << t << after;
269 }
270 */
271}
272
273namespace Gaudi
274{
275 namespace Parsers
276 {
277
278 template <typename Iterator, typename Skipper, class T>
279 struct Grammar_< Iterator, T, Skipper, typename std::enable_if_t < impl::class_can_be_tuple_v<T> > >
280 {
281 using Grammar = typename Grammar_<Iterator, typename T::TupleType, Skipper>::Grammar;
282 };
283
284 template <class ... Tup>
285 StatusCode parse(std::tuple<Tup...> & tup, const Gaudi::Parsers::InputData & input)
286 {
287 return parse_(tup, input);
288 }
289
290 template <class T>
291 StatusCode parse(std::vector<T> & v, const Gaudi::Parsers::InputData & input)
292 {
293 return parse_(v, input);
294 }
295
296 }
297}
298
299template <class ... Tup>
300std::ostream & operator<<(std::ostream & s, const std::tuple<Tup...> & tup )
301{
302 std::apply( [&] (const Tup & ... arg)
303 {
304 s << "(";
305
306 size_t num = 0;
307
308 (void) ( (void) impl::output_helper(s, arg, (++num < sizeof...(Tup) ? ", " : "")), ... );
309
310 s << ")";
311
312 }, tup );
313
314 return s;
315}
316
317template < class T,
318 std::enable_if_t< impl::class_can_be_tuple_v<T>>* = nullptr>
319std::ostream & operator<<(std::ostream & s, const T & t )
320{
321 return s << T::to_tuple(t);
322}
323
324//And now for the classes proper.
325//
326//In general:
327//
328//struct ClassName: impl::simple_tuple_conversion<ClassName, T1, T2, ... , TN>
329//{
330// T1 name1;
331// T2 name2;
332// ...
333// TN nameN;
334//
335// ClassName() = default;
336// ClassName(const TupleType & t)
337// {
338// (*this) = from_tuple(t);
339// }
340//};
341//
342//One could use the helper macro below.
343//
344//If there are mismatches in the types on the simple_tuple_conversion list,
345//ugly compilation issues may ensue!
346
347#define CALORECGPU_OPTIONCLASS_CONSTRUCTORS(CLASSNAME) \
348 CLASSNAME() = default; \
349 CLASSNAME(const TupleType & t) \
350 { \
351 (*this) = from_tuple(t); \
352 } \
353
355 impl::simple_tuple_conversion<MatchingOptions, double, double, double, double>
356{
357 double min_similarity = 0.50, term_w = 250., grow_w = 500., seed_w = 1000.;
358
360};
361
363 impl::simple_tuple_conversion<SimpleSingleTool, std::string, std::string>
364{
365 std::string tool, plot_id;
366
368};
369
371 impl::simple_tuple_conversion<SimpleToolPair, std::string, std::string, std::string, bool, bool, bool>
372{
374 bool match_in_energy = false;
376 bool match_perfectly = false;
377
379};
380
381//This was used more heavily when we had the standalone plotter,
382//but I would like to keep it here in case more changes are necessary...
383
384#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