EICrecon
JANA based reconstruction for the EPIC detector
Loading...
Searching...
No Matches
JOmniFactory.h
Go to the documentation of this file.
1// Copyright 2023, Jefferson Science Associates, LLC.
2// Subject to the terms in the LICENSE file found in the top-level directory.
3// Created by Nathan Brei
4
5#pragma once
6
13#include <JANA/JEvent.h>
14#include <JANA/JMultifactory.h>
15#include <spdlog/spdlog.h>
16#include <spdlog/version.h>
17#if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
18#include <spdlog/mdc.h>
19#endif
20
23
24#include <string>
25#include <vector>
26
27struct EmptyConfig {};
28
29template <typename AlgoT, typename ConfigT = EmptyConfig>
30class JOmniFactory : public JMultifactory {
31public:
35
36 struct InputBase {
37 std::string type_name;
38 std::vector<std::string> collection_names;
39 bool is_variadic = false;
40
41 virtual void GetCollection(const JEvent& event) = 0;
42 };
43
44 template <typename T, bool IsOptional = false> class Input : public InputBase {
45
46 std::vector<const T*> m_data;
47
48 public:
49 Input(JOmniFactory* owner, std::string default_tag = "") {
50 owner->RegisterInput(this);
51 this->collection_names.push_back(default_tag);
52 this->type_name = JTypeInfo::demangle<T>();
53 }
54
55 const std::vector<const T*>& operator()() { return m_data; }
56
57 private:
58 friend class JOmniFactory;
59
60 void GetCollection(const JEvent& event) {
61 try {
62 m_data = event.Get<T>(this->collection_names[0], !IsOptional);
63 } catch (const JException& e) {
64 if constexpr (!IsOptional) {
65 throw JException("JOmniFactory: Failed to get collection %s: %s",
66 this->collection_names[0].c_str(), e.what());
67 }
68 }
69 }
70 };
71
72 template <typename PodioT, bool IsOptional = false> class PodioInput : public InputBase {
73
74 const typename PodioTypeMap<PodioT>::collection_t* m_data;
75
76 public:
78 owner->RegisterInput(this);
80 this->type_name = JTypeInfo::demangle<PodioT>();
81 }
82
83 const typename PodioTypeMap<PodioT>::collection_t* operator()() { return m_data; }
84
85 private:
86 friend class JOmniFactory;
87
88 void GetCollection(const JEvent& event) {
89 try {
90 m_data = event.GetCollection<PodioT>(this->collection_names[0], !IsOptional);
91 } catch (const JException& e) {
92 if constexpr (!IsOptional) {
93 throw JException("JOmniFactory: Failed to get collection %s: %s",
94 this->collection_names[0].c_str(), e.what());
95 }
96 }
97 }
98 };
99
100 template <typename PodioT, bool IsOptional = false> class VariadicPodioInput : public InputBase {
101
102 std::vector<const typename PodioTypeMap<PodioT>::collection_t*> m_data;
103
104 public:
105 VariadicPodioInput(JOmniFactory* owner, std::vector<std::string> default_names = {}) {
106 owner->RegisterInput(this);
108 this->type_name = JTypeInfo::demangle<PodioT>();
109 this->is_variadic = true;
110 }
111
112 const std::vector<const typename PodioTypeMap<PodioT>::collection_t*> operator()() {
113 return m_data;
114 }
115
116 private:
117 friend class JOmniFactory;
118
119 void GetCollection(const JEvent& event) {
120 m_data.clear();
121 for (auto& coll_name : this->collection_names) {
122 try {
123 m_data.push_back(event.GetCollection<PodioT>(coll_name, !IsOptional));
124 } catch (const JException& e) {
125 if constexpr (!IsOptional) {
126 throw JException("JOmniFactory: Failed to get collection %s: %s", coll_name.c_str(),
127 e.what());
128 }
129 }
130 }
131 }
132 };
133
135
139
140 struct OutputBase {
141 std::string type_name;
142 std::vector<std::string> collection_names;
143 bool is_variadic = false;
144
146 virtual void SetCollection(JOmniFactory& fac) = 0;
147 virtual void Reset() = 0;
148 };
149
150 template <typename T> class Output : public OutputBase {
151 std::vector<T*> m_data;
152
153 public:
155 owner->RegisterOutput(this);
156 this->collection_names.push_back(default_tag_name);
157 this->type_name = JTypeInfo::demangle<T>();
158 }
159
160 std::vector<T*>& operator()() { return m_data; }
161
162 private:
163 friend class JOmniFactory;
164
165 void CreateHelperFactory(JOmniFactory& fac) override {
166 fac.DeclareOutput<T>(this->collection_names[0]);
167 }
168
169 void SetCollection(JOmniFactory& fac) override {
170 fac.SetData<T>(this->collection_names[0], this->m_data);
171 }
172
173 void Reset() override { m_data.clear(); }
174 };
175
176 template <typename PodioT> class PodioOutput : public OutputBase {
177
178 std::unique_ptr<typename PodioTypeMap<PodioT>::collection_t> m_data;
179
180 public:
182 owner->RegisterOutput(this);
184 this->type_name = JTypeInfo::demangle<PodioT>();
185 }
186
187 std::unique_ptr<typename PodioTypeMap<PodioT>::collection_t>& operator()() { return m_data; }
188
189 private:
190 friend class JOmniFactory;
191
192 void CreateHelperFactory(JOmniFactory& fac) override {
193 fac.DeclarePodioOutput<PodioT>(this->collection_names[0]);
194 }
195
196 void SetCollection(JOmniFactory& fac) override {
197 if (m_data == nullptr) {
198 throw JException("JOmniFactory: SetCollection failed due to missing output collection '%s'",
199 this->collection_names[0].c_str());
200 // Otherwise this leads to a PODIO segfault
201 }
202 fac.SetCollection<PodioT>(this->collection_names[0], std::move(this->m_data));
203 }
204
205 void Reset() override {
206 m_data = std::move(std::make_unique<typename PodioTypeMap<PodioT>::collection_t>());
207 }
208 };
209
210 template <typename PodioT> class VariadicPodioOutput : public OutputBase {
211
212 std::vector<std::unique_ptr<typename PodioTypeMap<PodioT>::collection_t>> m_data;
213
214 public:
216 std::vector<std::string> default_collection_names = {}) {
217 owner->RegisterOutput(this);
219 this->type_name = JTypeInfo::demangle<PodioT>();
220 this->is_variadic = true;
221 }
222
223 std::vector<std::unique_ptr<typename PodioTypeMap<PodioT>::collection_t>>& operator()() {
224 return m_data;
225 }
226
227 private:
228 friend class JOmniFactory;
229
230 void CreateHelperFactory(JOmniFactory& fac) override {
231 for (auto& coll_name : this->collection_names) {
232 fac.DeclarePodioOutput<PodioT>(coll_name);
233 }
234 }
235
236 void SetCollection(JOmniFactory& fac) override {
237 if (m_data.size() != this->collection_names.size()) {
238 throw JException("JOmniFactory: VariadicPodioOutput SetCollection failed: Declared %d "
239 "collections, but provided %d.",
240 this->collection_names.size(), m_data.size());
241 // Otherwise this leads to a PODIO segfault
242 }
243 std::size_t i = 0;
244 for (auto& coll_name : this->collection_names) {
245 fac.SetCollection<PodioT>(coll_name, std::move(this->m_data[i++]));
246 }
247 }
248
249 void Reset() override {
250 m_data.clear();
251 for (auto& coll_name [[maybe_unused]] : this->collection_names) {
252 m_data.push_back(std::make_unique<typename PodioTypeMap<PodioT>::collection_t>());
253 }
254 }
255 };
256
258
259 // =================
260 // Handle parameters
261 // =================
262
264 std::string m_name;
265 std::string m_description;
266 virtual void Configure(JParameterManager& parman, const std::string& prefix) = 0;
267 virtual void Configure(std::map<std::string, std::string> fields) = 0;
268 };
269
270 template <typename T> class ParameterRef : public ParameterBase {
271
272 T* m_data;
273
274 public:
275 ParameterRef(JOmniFactory* owner, std::string name, T& slot, std::string description = "") {
276 owner->RegisterParameter(this);
277 this->m_name = name;
279 m_data = &slot;
280 }
281
282 const T& operator()() { return *m_data; }
283
284 private:
285 friend class JOmniFactory;
286
287 void Configure(JParameterManager& parman, const std::string& prefix) override {
288 parman.SetDefaultParameter(prefix + ":" + this->m_name, *m_data, this->m_description);
289 }
290 void Configure(std::map<std::string, std::string> fields) override {
291 auto it = fields.find(this->m_name);
292 if (it != fields.end()) {
293 const auto& value_str = it->second;
294 JParameterManager::Parse(value_str, *m_data);
295 }
296 }
297 };
298
299 template <typename T> class Parameter : public ParameterBase {
300
301 T m_data;
302
303 public:
304 Parameter(JOmniFactory* owner, std::string name, T default_value, std::string description) {
305 owner->RegisterParameter(this);
306 this->m_name = name;
307 this->m_description = description;
308 m_data = default_value;
309 }
310
311 const T& operator()() { return m_data; }
312
313 private:
314 friend class JOmniFactory;
315
316 void Configure(JParameterManager& parman, const std::string& /* prefix */) override {
317 parman.SetDefaultParameter(m_prefix + ":" + this->m_name, m_data, this->m_description);
318 }
319 void Configure(std::map<std::string, std::string> fields) override {
320 auto it = fields.find(this->m_name);
321 if (it != fields.end()) {
322 const auto& value_str = it->second;
323 if constexpr (10000 * JVersion::major + 100 * JVersion::minor + 1 * JVersion::patch <
324 20102) {
325 m_data = JParameterManager::Parse<T>(value_str);
326 } else {
327 JParameterManager::Parse(value_str, m_data);
328 }
329 }
330 }
331 };
332
334
335 void ConfigureAllParameters(std::map<std::string, std::string> fields) {
336 for (auto* parameter : this->m_parameters) {
337 parameter->Configure(fields);
338 }
339 }
340
341 // ===============
342 // Handle services
343 // ===============
344
345 struct ServiceBase {
346 virtual void Init(JApplication* app) = 0;
347 };
348
349 template <typename ServiceT> class Service : public ServiceBase {
350
351 std::shared_ptr<ServiceT> m_data;
352
353 public:
354 Service(JOmniFactory* owner) { owner->RegisterService(this); }
355
356 ServiceT& operator()() { return *m_data; }
357
358 private:
359 friend class JOmniFactory;
360
361 void Init(JApplication* app) { m_data = app->GetService<ServiceT>(); }
362 };
363
365
366 // ================
367 // Handle resources
368 // ================
369
371 virtual void ChangeRun(const JEvent& event) = 0;
372 };
373
374 template <typename ServiceT, typename ResourceT, typename LambdaT>
375 class Resource : public ResourceBase {
376 ResourceT m_data;
377 LambdaT m_lambda;
378
379 public:
381 owner->RegisterResource(this);
382 };
383
384 const ResourceT& operator()() { return m_data; }
385
386 private:
387 friend class JOmniFactory;
388
389 void ChangeRun(const JEvent& event) {
390 auto run_nr = event.GetRunNumber();
391 std::shared_ptr<ServiceT> service = event.GetJApplication()->template GetService<ServiceT>();
392 m_data = m_lambda(service, run_nr);
393 }
394 };
395
397
398public:
399 std::vector<InputBase*> m_inputs;
400 std::vector<OutputBase*> m_outputs;
401 std::vector<ParameterBase*> m_parameters;
402 std::vector<ServiceBase*> m_services;
403 std::vector<ResourceBase*> m_resources;
404
405private:
406 // App belongs on JMultifactory, it is just missing temporarily
407 JApplication* m_app;
408
409 // Plugin name belongs on JMultifactory, it is just missing temporarily
410 std::string m_plugin_name;
411
412 // Prefix for parameters and loggers, derived from plugin name and tag in PreInit().
413 std::string m_prefix;
414
416 std::shared_ptr<spdlog::logger> m_logger;
417
419 ConfigT m_config;
420
421public:
423 std::size_t variadic_input_count,
424 std::size_t total_collection_count, bool is_input) {
425
426 std::size_t variadic_collection_count =
428
429 if (variadic_input_count == 0) {
430 // No variadic inputs: check that collection_name count matches input count exactly
432 throw JException(
433 "JOmniFactory '%s': Wrong number of %s collection names: %d expected, %d found.",
434 m_prefix.c_str(), (is_input ? "input" : "output"), total_input_count,
436 }
437 } else {
438 // Variadic inputs: check that we have enough collection names for the non-variadic inputs
440 throw JException("JOmniFactory '%s': Not enough %s collection names: %d needed, %d found.",
441 m_prefix.c_str(), (is_input ? "input" : "output"),
443 }
444
445 // Variadic inputs: check that the variadic collection names is evenly divided by the variadic input count
447 throw JException("JOmniFactory '%s': Wrong number of %s collection names: %d found total, "
448 "but %d can't be distributed among %d variadic inputs evenly.",
449 m_prefix.c_str(), (is_input ? "input" : "output"), total_collection_count,
451 }
452 }
454 }
455
456 inline void PreInit(std::string tag, std::vector<std::string> default_input_collection_names,
457 std::vector<std::string> default_output_collection_names) {
458
459 m_prefix = (this->GetPluginName().empty()) ? tag : this->GetPluginName() + ":" + tag;
460
461 // Obtain collection name overrides if provided.
462 // Priority = [JParameterManager, JOmniFactoryGenerator]
463 m_app->SetDefaultParameter(m_prefix + ":InputTags", default_input_collection_names,
464 "Input collection names");
465 m_app->SetDefaultParameter(m_prefix + ":OutputTags", default_output_collection_names,
466 "Output collection names");
467
468 // Figure out variadic inputs
469 std::size_t variadic_input_count = 0;
470 for (auto* input : m_inputs) {
471 if (input->is_variadic) {
473 }
474 }
477
478 // Set input collection names
479 for (std::size_t i = 0; auto* input : m_inputs) {
480 input->collection_names.clear();
481 if (input->is_variadic) {
482 for (std::size_t j = 0; j < (variadic_input_collection_count / variadic_input_count); ++j) {
484 }
485 } else {
487 }
488 }
489
490 // Figure out variadic outputs
491 std::size_t variadic_output_count = 0;
492 for (auto* output : m_outputs) {
493 if (output->is_variadic) {
495 }
496 }
499
500 // Set output collection names and create corresponding helper factories
501 for (std::size_t i = 0; auto* output : m_outputs) {
502 output->collection_names.clear();
503 if (output->is_variadic) {
504 for (std::size_t j = 0; j < (variadic_output_collection_count / variadic_output_count);
505 ++j) {
507 }
508 } else {
510 }
511 output->CreateHelperFactory(*this);
512 }
513
514 // Obtain logger (defines the parameter option)
515 m_logger = m_app->GetService<Log_service>()->logger(m_prefix);
516 }
517
518 void Init() override {
519 auto app = GetApplication();
520 for (auto* parameter : m_parameters) {
521 parameter->Configure(*(app->GetJParameterManager()), m_prefix);
522 }
523 for (auto* service : m_services) {
524 service->Init(app);
525 }
526 static_cast<AlgoT*>(this)->Configure();
527 }
528
529 void BeginRun(const std::shared_ptr<const JEvent>& event) override {
530 for (auto* resource : m_resources) {
531 resource->ChangeRun(*event);
532 }
533 static_cast<AlgoT*>(this)->ChangeRun(event->GetRunNumber());
534 }
535
536 virtual void ChangeRun(int32_t /* run_number */) override {};
537
538 virtual void Process(int32_t /* run_number */, uint64_t /* event_number */) {};
539
540 void Process(const std::shared_ptr<const JEvent>& event) override {
541 try {
542 for (auto* input : m_inputs) {
543 input->GetCollection(*event);
544 }
545 for (auto* output : m_outputs) {
546 output->Reset();
547 }
548#if SPDLOG_VERSION >= 11400 && (!defined(SPDLOG_NO_TLS) || !SPDLOG_NO_TLS)
549 spdlog::mdc::put("e", std::to_string(event->GetEventNumber()));
550#endif
551 static_cast<AlgoT*>(this)->Process(event->GetRunNumber(), event->GetEventNumber());
552 for (auto* output : m_outputs) {
553 output->SetCollection(*this);
554 }
555 } catch (std::exception& e) {
556 throw JException(e.what());
557 }
558 }
559
561
562 void SetApplication(JApplication* app) { m_app = app; }
563
564 JApplication* GetApplication() { return m_app; }
565
566 void SetPluginName(std::string plugin_name) { m_plugin_name = plugin_name; }
567
568 std::string GetPluginName() { return m_plugin_name; }
569
570 inline std::string GetPrefix() { return m_prefix; }
571
573 std::shared_ptr<spdlog::logger>& logger() { return m_logger; }
574
576 ConfigT& config() { return m_config; }
577};
Definition JOmniFactory.h:44
Input(JOmniFactory *owner, std::string default_tag="")
Definition JOmniFactory.h:49
const std::vector< const T * > & operator()()
Definition JOmniFactory.h:55
Definition JOmniFactory.h:150
std::vector< T * > & operator()()
Definition JOmniFactory.h:160
Output(JOmniFactory *owner, std::string default_tag_name="")
Definition JOmniFactory.h:154
Definition JOmniFactory.h:270
const T & operator()()
Definition JOmniFactory.h:282
ParameterRef(JOmniFactory *owner, std::string name, T &slot, std::string description="")
Definition JOmniFactory.h:275
Definition JOmniFactory.h:299
const T & operator()()
Definition JOmniFactory.h:311
Parameter(JOmniFactory *owner, std::string name, T default_value, std::string description)
Definition JOmniFactory.h:304
Definition JOmniFactory.h:72
PodioInput(JOmniFactory *owner, std::string default_collection_name="")
Definition JOmniFactory.h:77
const PodioTypeMap< PodioT >::collection_t * operator()()
Definition JOmniFactory.h:83
Definition JOmniFactory.h:176
PodioOutput(JOmniFactory *owner, std::string default_collection_name="")
Definition JOmniFactory.h:181
std::unique_ptr< typename PodioTypeMap< PodioT >::collection_t > & operator()()
Definition JOmniFactory.h:187
Definition JOmniFactory.h:375
Resource(JOmniFactory *owner, LambdaT lambda)
Definition JOmniFactory.h:380
const ResourceT & operator()()
Definition JOmniFactory.h:384
Definition JOmniFactory.h:349
ServiceT & operator()()
Definition JOmniFactory.h:356
Service(JOmniFactory *owner)
Definition JOmniFactory.h:354
Definition JOmniFactory.h:100
const std::vector< const typename PodioTypeMap< PodioT >::collection_t * > operator()()
Definition JOmniFactory.h:112
VariadicPodioInput(JOmniFactory *owner, std::vector< std::string > default_names={})
Definition JOmniFactory.h:105
Definition JOmniFactory.h:210
std::vector< std::unique_ptr< typename PodioTypeMap< PodioT >::collection_t > > & operator()()
Definition JOmniFactory.h:223
VariadicPodioOutput(JOmniFactory *owner, std::vector< std::string > default_collection_names={})
Definition JOmniFactory.h:215
Definition JOmniFactory.h:30
std::vector< ParameterBase * > m_parameters
Definition JOmniFactory.h:401
void RegisterInput(InputBase *input)
Definition JOmniFactory.h:134
std::string GetPluginName()
Definition JOmniFactory.h:568
JApplication * GetApplication()
Definition JOmniFactory.h:564
void RegisterResource(ResourceBase *resource)
Definition JOmniFactory.h:396
ConfigT & config()
Retrieve reference to embedded config object.
Definition JOmniFactory.h:576
void ConfigureAllParameters(std::map< std::string, std::string > fields)
Definition JOmniFactory.h:335
std::vector< ResourceBase * > m_resources
Definition JOmniFactory.h:403
std::shared_ptr< spdlog::logger > & logger()
Retrieve reference to already-configured logger.
Definition JOmniFactory.h:573
std::vector< InputBase * > m_inputs
Definition JOmniFactory.h:399
void SetApplication(JApplication *app)
Definition JOmniFactory.h:562
virtual void ChangeRun(int32_t) override
Definition JOmniFactory.h:536
void SetPluginName(std::string plugin_name)
Definition JOmniFactory.h:566
void Init() override
Definition JOmniFactory.h:518
void RegisterOutput(OutputBase *output)
Definition JOmniFactory.h:257
std::string GetPrefix()
Definition JOmniFactory.h:570
std::vector< OutputBase * > m_outputs
Definition JOmniFactory.h:400
std::vector< ServiceBase * > m_services
Definition JOmniFactory.h:402
void RegisterParameter(ParameterBase *parameter)
Definition JOmniFactory.h:333
void PreInit(std::string tag, std::vector< std::string > default_input_collection_names, std::vector< std::string > default_output_collection_names)
Definition JOmniFactory.h:456
void RegisterService(ServiceBase *service)
Definition JOmniFactory.h:364
virtual void Process(int32_t, uint64_t)
Definition JOmniFactory.h:538
void Process(const std::shared_ptr< const JEvent > &event) override
Definition JOmniFactory.h:540
void BeginRun(const std::shared_ptr< const JEvent > &event) override
Definition JOmniFactory.h:529
std::size_t FindVariadicCollectionCount(std::size_t total_input_count, std::size_t variadic_input_count, std::size_t total_collection_count, bool is_input)
Definition JOmniFactory.h:422
Definition Log_service.h:15
Definition JOmniFactory.h:27
Definition JOmniFactory.h:36
bool is_variadic
Definition JOmniFactory.h:39
std::string type_name
Definition JOmniFactory.h:37
virtual void GetCollection(const JEvent &event)=0
std::vector< std::string > collection_names
Definition JOmniFactory.h:38
Definition JOmniFactory.h:140
virtual void SetCollection(JOmniFactory &fac)=0
std::string type_name
Definition JOmniFactory.h:141
virtual void CreateHelperFactory(JOmniFactory &fac)=0
bool is_variadic
Definition JOmniFactory.h:143
virtual void Reset()=0
std::vector< std::string > collection_names
Definition JOmniFactory.h:142
Definition JOmniFactory.h:263
std::string m_description
Definition JOmniFactory.h:265
std::string m_name
Definition JOmniFactory.h:264
virtual void Configure(JParameterManager &parman, const std::string &prefix)=0
virtual void Configure(std::map< std::string, std::string > fields)=0
Definition JOmniFactory.h:370
virtual void ChangeRun(const JEvent &event)=0
Definition JOmniFactory.h:345
virtual void Init(JApplication *app)=0
typename T::collection_type collection_t
Definition datamodel_glue.h:24