Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:39

0001 
0002 // Copyright 2023, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #pragma once
0006 
0007 #include "JANA/Utils/JTypeInfo.h"
0008 #include <JANA/JFactoryT.h>
0009 #include <JANA/JFactorySet.h>
0010 #include <JANA/Components/JComponent.h>
0011 #include <JANA/Components/JHasRunCallbacks.h>
0012 #include <JANA/JVersion.h>
0013 
0014 #if JANA2_HAVE_PODIO
0015 #include "JANA/Podio/JFactoryPodioT.h"
0016 #endif
0017 
0018 class JMultifactory;
0019 
0020 template <typename T>
0021 class JMultifactoryHelper : public JFactoryT<T>{
0022 
0023     JMultifactory* mMultiFactory;
0024 
0025 public:
0026     JMultifactoryHelper(JMultifactory* parent) : mMultiFactory(parent) {}
0027     virtual ~JMultifactoryHelper() = default;
0028     // This does NOT own mMultiFactory; the enclosing JFactorySet does
0029 
0030     void Process(const std::shared_ptr<const JEvent>&) override;
0031     // We really want to override Create, not Process!!!
0032     // It might make more sense to (1) put Create() back on JFactory, (2) make Create() virtual, (3) override Create()
0033     // Alternatively, we could move all the JMultiFactoryHelper functionality into JFactoryT directly
0034 
0035     JMultifactory* GetMultifactory() { return mMultiFactory; }
0036 
0037     // Helpers do not produce any summary information
0038     void Summarize(JComponentSummary&) const override { }
0039 };
0040 
0041 
0042 #if JANA2_HAVE_PODIO
0043 // TODO: This redundancy goes away if we merge JFactoryPodioT with JFactoryT
0044 template <typename T>
0045 class JMultifactoryHelperPodio : public JFactoryPodioT<T>{
0046 
0047     JMultifactory* mMultiFactory;
0048 
0049 public:
0050     JMultifactoryHelperPodio(JMultifactory* parent) : mMultiFactory(parent) {}
0051 
0052     virtual ~JMultifactoryHelperPodio() = default;
0053     // This does NOT own mMultiFactory; the enclosing JFactorySet does
0054 
0055     void Process(const std::shared_ptr<const JEvent>&) override;
0056     // We really want to override Create, not Process!!!
0057     // It might make more sense to (1) put Create() back on JFactory, (2) make Create() virtual, (3) override Create()
0058     // Alternatively, we could move all of the JMultiFactoryHelper functionality into JFactoryT directly
0059 
0060     JMultifactory* GetMultifactory() { return mMultiFactory; }
0061 
0062     // Helpers do not produce any summary information
0063     void Summarize(JComponentSummary&) const override { }
0064 };
0065 #endif // JANA2_HAVE_PODIO
0066 
0067 
0068 class JMultifactory : public jana::components::JComponent,
0069                       public jana::components::JHasRunCallbacks {
0070 
0071     JFactorySet mHelpers; // This has ownership UNTIL JFactorySet::Add() takes it over
0072 
0073     // Remember where we are in the stream so that the correct sequence of callbacks get called.
0074     // However, don't worry about a Status variable. Every time Execute() gets called, so does Process().
0075     // The JMultifactoryHelpers will control calls to Execute().
0076 
0077 #if JANA2_HAVE_PODIO
0078     bool mNeedPodio = false;      // Whether we need to retrieve the podio::Frame
0079     podio::Frame* mPodioFrame = nullptr;  // To provide the podio::Frame to SetPodioData, SetCollection
0080 #endif
0081 
0082 public:
0083     JMultifactory() = default;
0084     virtual ~JMultifactory() = default;
0085 
0086     // IMPLEMENTED BY USERS
0087 
0088     virtual void Init() {}
0089     void BeginRun(const std::shared_ptr<const JEvent>&) override {}
0090     virtual void Process(const std::shared_ptr<const JEvent>&) {}
0091     void EndRun() override {}
0092     virtual void Finish() {}
0093     // I'm tempted to factor out something like JEventCallback from JFactory, JMultifactory, and JEventProcessor.
0094 
0095 
0096     // CALLED BY USERS
0097 
0098     template <typename T>
0099     void DeclareOutput(std::string tag, bool owns_data=true);
0100 
0101     template <typename T>
0102     void SetData(std::string tag, std::vector<T*> data);
0103 
0104 #if JANA2_HAVE_PODIO
0105 
0106     template <typename T>
0107     void DeclarePodioOutput(std::string tag, bool owns_data=true);
0108 
0109     template <typename T>
0110     void SetCollection(std::string tag, typename JFactoryPodioT<T>::CollectionT&& collection);
0111 
0112     template <typename T>
0113     void SetCollection(std::string tag, std::unique_ptr<typename JFactoryPodioT<T>::CollectionT> collection);
0114 
0115 #endif
0116 
0117     /// CALLED BY JANA
0118     
0119     void DoInit();
0120 
0121     void DoFinish();
0122 
0123     void Execute(const std::shared_ptr<const JEvent>&);
0124 
0125     JFactorySet* GetHelpers();
0126     // This exposes the mHelpers JFactorySet, which contains a JFactoryT<T> for each declared output of the multifactory.
0127     // This is meant to be called from JFactorySet, which will take ownership of the helpers while leaving the pointers
0128     // in place. This method is only supposed to be called by JFactorySet::Add(JMultifactory).
0129 
0130     // These are set by JFactoryGeneratorT (just like JFactories) and get propagated to each of the JMultifactoryHelpers
0131     void SetTag(std::string tag) { SetPrefix(tag); }
0132 
0133     void SetFactoryName(std::string factoryName) { 
0134         SetTypeName(factoryName);
0135     }
0136     
0137     void Summarize(JComponentSummary& summary) const override;
0138 };
0139 
0140 
0141 
0142 template <typename T>
0143 void JMultifactory::DeclareOutput(std::string tag, bool owns_data) {
0144     JFactory* helper = new JMultifactoryHelper<T>(this);
0145     if (!owns_data) helper->SetFactoryFlag(JFactory::JFactory_Flags_t::NOT_OBJECT_OWNER);
0146     helper->SetPluginName(m_plugin_name);
0147     helper->SetFactoryName(GetTypeName()+"::Helper<" + JTypeInfo::demangle<T>() + ">");
0148     helper->SetTag(std::move(tag));
0149     helper->SetLevel(GetLevel());
0150     mHelpers.SetLevel(GetLevel());
0151     mHelpers.Add(helper);
0152 }
0153 
0154 template <typename T>
0155 void JMultifactory::SetData(std::string tag, std::vector<T*> data) {
0156     JFactoryT<T>* helper = mHelpers.GetFactory<T>(tag);
0157     if (helper == nullptr) {
0158         auto ex = JException("JMultifactory: Attempting to SetData() without corresponding DeclareOutput()");
0159         ex.function_name = "JMultifactory::SetData";
0160         ex.type_name = m_type_name;
0161         ex.instance_name = m_prefix;
0162         ex.plugin_name = m_plugin_name;
0163         throw ex;
0164     }
0165 #if JANA2_HAVE_PODIO
0166     // This may or may not be a Podio factory. We find out if it is, and if so, set the frame before calling Set().
0167     auto* typed = dynamic_cast<JFactoryPodio*>(helper);
0168     if (typed != nullptr) {
0169         typed->SetFrame(mPodioFrame); // Needs to be called before helper->Set(), otherwise Set() excepts
0170     }
0171 #endif
0172     helper->Set(data);
0173 }
0174 
0175 
0176 #if JANA2_HAVE_PODIO
0177 
0178 template <typename T>
0179 void JMultifactory::DeclarePodioOutput(std::string tag, bool owns_data) {
0180     // TODO: Decouple tag name from collection name
0181     auto* helper = new JMultifactoryHelperPodio<T>(this);
0182     if (!owns_data) helper->SetSubsetCollection(true);
0183 
0184     helper->SetTag(std::move(tag));
0185     helper->SetPluginName(m_plugin_name);
0186     helper->SetFactoryName(GetTypeName() + "::Helper<" + JTypeInfo::demangle<T>() + ">");
0187     helper->SetLevel(GetLevel());
0188     mHelpers.SetLevel(GetLevel());
0189     mHelpers.Add(helper);
0190     mNeedPodio = true;
0191 }
0192 
0193 template <typename T>
0194 void JMultifactory::SetCollection(std::string tag, typename JFactoryPodioT<T>::CollectionT&& collection) {
0195     JFactoryT<T>* helper = mHelpers.GetFactory<T>(tag);
0196     if (helper == nullptr) {
0197         auto ex = JException("JMultifactory: Attempting to SetData() without corresponding DeclareOutput()");
0198         ex.function_name = "JMultifactory::SetCollection";
0199         ex.type_name = m_type_name;
0200         ex.instance_name = m_prefix;
0201         ex.plugin_name = m_plugin_name;
0202         throw ex;
0203     }
0204     auto* typed = dynamic_cast<JFactoryPodioT<T>*>(helper);
0205     if (typed == nullptr) {
0206         auto ex = JException("JMultifactory: Helper needs to be a JFactoryPodioT (this shouldn't be reachable)");
0207         ex.function_name = "JMultifactory::SetCollection";
0208         ex.type_name = m_type_name;
0209         ex.instance_name = m_prefix;
0210         ex.plugin_name = m_plugin_name;
0211         throw ex;
0212     }
0213 
0214     typed->SetFrame(mPodioFrame);
0215     typed->SetCollection(std::move(collection));
0216 }
0217 
0218 template <typename T>
0219 void JMultifactory::SetCollection(std::string tag, std::unique_ptr<typename JFactoryPodioT<T>::CollectionT> collection) {
0220     JFactoryT<T>* helper = mHelpers.GetFactory<T>(tag);
0221     if (helper == nullptr) {
0222         auto ex = JException("JMultifactory: Attempting to SetData() without corresponding DeclareOutput()");
0223         ex.function_name = "JMultifactory::SetCollection";
0224         ex.type_name = m_type_name;
0225         ex.instance_name = m_prefix;
0226         ex.plugin_name = m_plugin_name;
0227         throw ex;
0228     }
0229     auto* typed = dynamic_cast<JFactoryPodioT<T>*>(helper);
0230     if (typed == nullptr) {
0231         auto ex = JException("JMultifactory: Helper needs to be a JFactoryPodioT (this shouldn't be reachable)");
0232         ex.function_name = "JMultifactory::SetCollection";
0233         ex.type_name = m_type_name;
0234         ex.instance_name = m_prefix;
0235         ex.plugin_name = m_plugin_name;
0236         throw ex;
0237     }
0238 
0239     typed->SetFrame(mPodioFrame);
0240     typed->SetCollection(std::move(collection));
0241 }
0242 
0243 #endif // JANA2_HAVE_PODIO
0244 
0245 
0246 template <typename T>
0247 void JMultifactoryHelper<T>::Process(const std::shared_ptr<const JEvent> &event) {
0248     mMultiFactory->Execute(event);
0249 }
0250 
0251 #if JANA2_HAVE_PODIO
0252 template <typename T>
0253 void JMultifactoryHelperPodio<T>::Process(const std::shared_ptr<const JEvent> &event) {
0254     mMultiFactory->Execute(event);
0255 }
0256 #endif // JANA2_HAVE_PODIO
0257 
0258