Back to home page

EIC code displayed by LXR

 
 

    


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

0001 
0002 // Copyright 2020, 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/JObject.h>
0008 #include <JANA/JException.h>
0009 #include <JANA/JFactoryT.h>
0010 #include <JANA/JFactorySet.h>
0011 #include <JANA/JLogger.h>
0012 #include <JANA/JVersion.h>
0013 
0014 #include <JANA/Utils/JEventLevel.h>
0015 #include <JANA/Utils/JTypeInfo.h>
0016 #include <JANA/Utils/JCpuInfo.h>
0017 #include <JANA/Utils/JCallGraphRecorder.h>
0018 #include <JANA/Utils/JCallGraphEntryMaker.h>
0019 #include <JANA/Utils/JInspector.h>
0020 
0021 #include <vector>
0022 #include <cstddef>
0023 #include <memory>
0024 #include <atomic>
0025 
0026 #if JANA2_HAVE_PODIO
0027 #include <JANA/Podio/JFactoryPodioT.h>
0028 namespace podio {
0029 class CollectionBase;
0030 }
0031 #endif
0032 
0033 class JApplication;
0034 class JEventSource;
0035 
0036 
0037 class JEvent : public std::enable_shared_from_this<JEvent> {
0038 
0039 private:
0040     JApplication* mApplication = nullptr;
0041     int32_t mRunNumber = 0;
0042     uint64_t mEventNumber = 0;
0043     mutable JFactorySet* mFactorySet = nullptr;
0044     mutable JCallGraphRecorder mCallGraph;
0045     mutable JInspector mInspector;
0046     bool mUseDefaultTags = false;
0047     std::map<std::string, std::string> mDefaultTags;
0048     JEventSource* mEventSource = nullptr;
0049     bool mIsBarrierEvent = false;
0050     bool mIsWarmedUp = false;
0051 
0052     // Hierarchical event memory management
0053     std::vector<std::pair<JEventLevel, JEvent*>> mParents;
0054     std::atomic_int mReferenceCount {1};
0055     int64_t mEventIndex = -1;
0056 
0057 #if JANA2_HAVE_PODIO
0058     std::map<std::string, JFactory*> mPodioFactories;
0059 #endif
0060 
0061 
0062 public:
0063     JEvent();
0064     explicit JEvent(JApplication* app);
0065     virtual ~JEvent();
0066 
0067     void SetFactorySet(JFactorySet* aFactorySet);
0068     void SetRunNumber(int32_t aRunNumber){mRunNumber = aRunNumber;}
0069     void SetEventNumber(uint64_t aEventNumber){mEventNumber = aEventNumber;}
0070     void SetJApplication(JApplication* app){mApplication = app;}
0071     void SetJEventSource(JEventSource* aSource){mEventSource = aSource;}
0072     void SetDefaultTags(std::map<std::string, std::string> aDefaultTags){mDefaultTags=aDefaultTags; mUseDefaultTags = !mDefaultTags.empty();}
0073     void SetSequential(bool isSequential) {mIsBarrierEvent = isSequential;}
0074 
0075     JFactorySet* GetFactorySet() const { return mFactorySet; }
0076     int32_t GetRunNumber() const {return mRunNumber;}
0077     uint64_t GetEventNumber() const {return mEventNumber;}
0078     JApplication* GetJApplication() const {return mApplication;}
0079     JEventSource* GetJEventSource() const {return mEventSource; }
0080     JCallGraphRecorder* GetJCallGraphRecorder() const {return &mCallGraph;}
0081     JInspector* GetJInspector() const {return &mInspector;}
0082     void Inspect() const { mInspector.Loop();}
0083     bool GetSequential() const {return mIsBarrierEvent;}
0084     bool IsWarmedUp() { return mIsWarmedUp; }
0085 
0086     // Hierarchical
0087     JEventLevel GetLevel() const { return mFactorySet->GetLevel(); }
0088     void SetLevel(JEventLevel level) { mFactorySet->SetLevel(level); }
0089     void SetEventIndex(int event_index) { mEventIndex = event_index; }
0090     int64_t GetEventIndex() const { return mEventIndex; }
0091 
0092     bool HasParent(JEventLevel level) const;
0093     const JEvent& GetParent(JEventLevel level) const;
0094     void SetParent(JEvent* parent);
0095     JEvent* ReleaseParent(JEventLevel level);
0096     void Release();
0097 
0098     // Lifecycle
0099     void Clear();
0100     void Finish();
0101 
0102     JFactory* GetFactory(const std::string& object_name, const std::string& tag) const;
0103     std::vector<JFactory*> GetAllFactories() const;
0104 
0105 
0106     template<class T> JFactoryT<T>* GetFactory(const std::string& tag = "", bool throw_on_missing=false) const;
0107     template<class T> std::vector<JFactoryT<T>*> GetFactoryAll(bool throw_on_missing = false) const;
0108 
0109     // C style getters
0110     template<class T> JFactoryT<T>* GetSingle(const T* &t, const char *tag="", bool exception_if_not_one=true) const;
0111     template<class T> JFactoryT<T>* Get(const T** item, const std::string& tag="") const;
0112     template<class T> JFactoryT<T>* Get(std::vector<const T*> &vec, const std::string& tag = "", bool strict=true) const;
0113     template<class T> void GetAll(std::vector<const T*> &vec) const;
0114 
0115     // C++ style getters
0116     template<class T> const T* GetSingle(const std::string& tag = "") const;
0117     template<class T> const T* GetSingleStrict(const std::string& tag = "") const;
0118     template<class T> std::vector<const T*> Get(const std::string& tag = "", bool strict=true) const;
0119     template<class T> typename JFactoryT<T>::PairType GetIterators(const std::string& aTag = "") const;
0120     template<class T> std::vector<const T*> GetAll() const;
0121     template<class T> std::map<std::pair<std::string,std::string>,std::vector<T*>> GetAllChildren() const;
0122 
0123     // Insert
0124     template <class T> JFactoryT<T>* Insert(T* item, const std::string& aTag = "") const;
0125     template <class T> JFactoryT<T>* Insert(const std::vector<T*>& items, const std::string& tag = "") const;
0126 
0127     // PODIO
0128 #if JANA2_HAVE_PODIO
0129     std::vector<std::string> GetAllCollectionNames() const;
0130     const podio::CollectionBase* GetCollectionBase(std::string name, bool throw_on_missing=true) const;
0131     template <typename T> const typename JFactoryPodioT<T>::CollectionT* GetCollection(std::string name, bool throw_on_missing=true) const;
0132     template <typename T> JFactoryPodioT<T>* InsertCollection(typename JFactoryPodioT<T>::CollectionT&& collection, std::string name);
0133     template <typename T> JFactoryPodioT<T>* InsertCollectionAlreadyInFrame(const podio::CollectionBase* collection, std::string name);
0134 #endif
0135 
0136 
0137 };
0138 
0139 
0140 /// GetFactory() should be used with extreme care because it subverts the JEvent abstraction.
0141 /// Most historical uses of GetFactory are far better served by JMultifactory.
0142 template<class T>
0143 inline JFactoryT<T>* JEvent::GetFactory(const std::string& tag, bool throw_on_missing) const
0144 {
0145     std::string resolved_tag = tag;
0146     if (mUseDefaultTags && tag.empty()) {
0147         auto defaultTag = mDefaultTags.find(JTypeInfo::demangle<T>());
0148         if (defaultTag != mDefaultTags.end()) resolved_tag = defaultTag->second;
0149     }
0150     auto factory = mFactorySet->GetFactory<T>(resolved_tag);
0151     if (factory == nullptr) {
0152         if (throw_on_missing) {
0153             JException ex("Could not find JFactoryT<" + JTypeInfo::demangle<T>() + "> with tag=" + tag);
0154             ex.show_stacktrace = false;
0155             throw ex;
0156         }
0157     };
0158     return factory;
0159 }
0160 
0161 
0162 /// GetFactoryAll returns all JFactoryT's for type T (each corresponds to a different tag).
0163 /// This is useful when there are many different tags, or the tags are unknown, and the user
0164 /// wishes to examine them all together.
0165 template<class T>
0166 inline std::vector<JFactoryT<T>*> JEvent::GetFactoryAll(bool throw_on_missing) const {
0167     auto factories = mFactorySet->GetAllFactories<T>();
0168     if (factories.size() == 0) {
0169         if (throw_on_missing) {
0170             JException ex("Could not find any JFactoryT<" + JTypeInfo::demangle<T>() + "> (from any tag)");
0171             ex.show_stacktrace = false;
0172             throw ex;
0173         }
0174     };
0175     return factories;
0176 }
0177 
0178 
0179 /// C-style getters
0180 
0181 template<class T>
0182 JFactoryT<T>* JEvent::GetSingle(const T* &t, const char *tag, bool exception_if_not_one) const
0183 {
0184     /// This is a convenience method that can be used to get a pointer to the single
0185     /// object of type T from the specified factory. It simply calls the Get(vector<...>) method
0186     /// and copies the first pointer into "t" (or NULL if something other than 1 object is returned).
0187     ///
0188     /// This is intended to address the common situation in which there is an interest
0189     /// in the event if and only if there is exactly 1 object of type T. If the event
0190     /// has no objects of that type or more than 1 object of that type (for the specified
0191     /// factory) then an exception of type "unsigned long" is thrown with the value
0192     /// being the number of objects of type T. You can supress the exception by setting
0193     /// exception_if_not_one to false. In that case, you will have to check if t==NULL to
0194     /// know if the call succeeded.
0195 
0196     std::vector<const T*> v;
0197     auto fac = GetFactory<T>(tag, true); // throw exception if factory not found
0198     JCallGraphEntryMaker cg_entry(mCallGraph, fac); // times execution until this goes out of scope
0199     Get(v, tag);
0200     if(v.size()!=1){
0201         t = NULL;
0202         if(exception_if_not_one) throw v.size();
0203     }
0204     t = v[0];
0205     return fac;
0206 }
0207 
0208 /// Get conveniently returns one item from inside the JFactory. This should be used when the data in question
0209 /// is optional and the caller wants to examine the result and decide how to proceed. The caller should embed this
0210 /// inside an if-block. Get updates the `destination` out parameter and returns a pointer to the enclosing JFactory.
0211 /// - If the factory is missing, GetSingle throws an exception.
0212 /// - If the factory exists but contains no items, GetSingle updates the `destination` to point to nullptr.
0213 /// - If the factory contains exactly one item, GetSingle updates the `destination` to point to that item.
0214 /// - If the factory contains more than one item, GetSingle updates the `destination` to point to the first time.
0215 template<class T>
0216 JFactoryT<T>* JEvent::Get(const T** destination, const std::string& tag) const
0217 {
0218     auto factory = GetFactory<T>(tag, true);
0219     JCallGraphEntryMaker cg_entry(mCallGraph, factory); // times execution until this goes out of scope
0220     auto iterators = factory->CreateAndGetData(this->shared_from_this());
0221     if (std::distance(iterators.first, iterators.second) == 0) {
0222         *destination = nullptr;
0223     }
0224     else {
0225         *destination = *iterators.first;
0226     }
0227     return factory;
0228 }
0229 
0230 
0231 template<class T>
0232 JFactoryT<T>* JEvent::Get(std::vector<const T*>& destination, const std::string& tag, bool strict) const
0233 {
0234     auto factory = GetFactory<T>(tag, strict);
0235     if (factory == nullptr) return nullptr; // Will have thrown already if strict==true
0236     JCallGraphEntryMaker cg_entry(mCallGraph, factory); // times execution until this goes out of scope
0237     auto iterators = factory->CreateAndGetData(this->shared_from_this());
0238     for (auto it=iterators.first; it!=iterators.second; it++) {
0239         destination.push_back(*it);
0240     }
0241     return factory;
0242 }
0243 
0244 
0245 /// GetAll returns all JObjects of (child) type T, regardless of tag.
0246 template<class T>
0247 void JEvent::GetAll(std::vector<const T*>& destination) const {
0248     auto factories = GetFactoryAll<T>(true);
0249     for (auto factory : factories) {
0250         auto iterators = factory->CreateAndGetData(this->shared_from_this());
0251         for (auto it = iterators.first; it != iterators.second; it++) {
0252             destination.push_back(*it);
0253         }
0254     }
0255 }
0256 
0257 
0258 
0259 /// C++ style getters
0260 
0261 /// GetSingle conveniently returns one item from inside the JFactory. This should be used when the data in question
0262 /// is optional and the caller wants to examine the result and decide how to proceed. The caller should embed this
0263 /// inside an if-block.
0264 /// - If the factory is missing, GetSingle throws an exception
0265 /// - If the factory exists but contains no items, GetSingle returns nullptr
0266 /// - If the factory contains more than one item, GetSingle returns the first item
0267 
0268 template<class T> const T* JEvent::GetSingle(const std::string& tag) const {
0269     auto factory = GetFactory<T>(tag, true);
0270     JCallGraphEntryMaker cg_entry(mCallGraph, factory); // times execution until this goes out of scope
0271     auto iterators = factory->CreateAndGetData(this->shared_from_this());
0272     if (std::distance(iterators.first, iterators.second) == 0) {
0273         return nullptr;
0274     }
0275     return *iterators.first;
0276 }
0277 
0278 
0279 
0280 /// GetSingleStrict conveniently returns one item from inside the JFactory. This should be used when the data in
0281 /// question is mandatory, and its absence indicates an error which should stop execution. The caller does not need
0282 /// to embed this in an if- or try-catch block; it can be a one-liner.
0283 /// - If the factory is missing, GetSingleStrict throws an exception
0284 /// - If the factory exists but contains no items, GetSingleStrict throws an exception
0285 /// - If the factory contains more than one item, GetSingleStrict throws an exception
0286 template<class T> const T* JEvent::GetSingleStrict(const std::string& tag) const {
0287     auto factory = GetFactory<T>(tag, true);
0288     JCallGraphEntryMaker cg_entry(mCallGraph, factory); // times execution until this goes out of scope
0289     auto iterators = factory->CreateAndGetData(this->shared_from_this());
0290     if (std::distance(iterators.first, iterators.second) == 0) {
0291         JException ex("GetSingle failed due to missing %d", NAME_OF(T));
0292         ex.show_stacktrace = false;
0293         throw ex;
0294     }
0295     else if (std::distance(iterators.first, iterators.second) > 1) {
0296         JException ex("GetSingle failed due to too many %d", NAME_OF(T));
0297         ex.show_stacktrace = false;
0298         throw ex;
0299     }
0300     return *iterators.first;
0301 }
0302 
0303 
0304 template<class T>
0305 std::vector<const T*> JEvent::Get(const std::string& tag, bool strict) const {
0306 
0307     auto factory = GetFactory<T>(tag, strict);
0308     std::vector<const T*> vec;
0309     if (factory == nullptr) return vec; // Will have thrown already if strict==true
0310     JCallGraphEntryMaker cg_entry(mCallGraph, factory); // times execution until this goes out of scope
0311     auto iters = factory->CreateAndGetData(this->shared_from_this());
0312     for (auto it=iters.first; it!=iters.second; ++it) {
0313         vec.push_back(*it);
0314     }
0315     return vec; // Assumes RVO
0316 }
0317 
0318 template<class T>
0319 typename JFactoryT<T>::PairType JEvent::GetIterators(const std::string& tag) const {
0320     auto factory = GetFactory<T>(tag, true);
0321     JCallGraphEntryMaker cg_entry(mCallGraph, factory); // times execution until this goes out of scope
0322     auto iters = factory->CreateAndGetData(this->shared_from_this());
0323     return iters;
0324 }
0325 
0326 /// GetAll returns all JObjects of (child) type T, regardless of tag.
0327 template<class T>
0328 std::vector<const T*> JEvent::GetAll() const {
0329     std::vector<const T*> vec;
0330     auto factories = GetFactoryAll<T>(true);
0331 
0332     for (auto factory : factories) {
0333         auto iters = factory->CreateAndGetData(this->shared_from_this());
0334         std::vector<const T*> vec;
0335         for (auto it = iters.first; it != iters.second; ++it) {
0336             vec.push_back(*it);
0337         }
0338     }
0339     return vec; // Assumes RVO
0340 }
0341 
0342 // GetAllChildren will furnish a map { (type_name,tag_name) : [BaseClass*] } containing all JFactoryT<T> data where
0343 // T inherits from BaseClass. Note that this _won't_ compute any results (unlike GetAll) because this is meant for
0344 // things like visualizing and persisting DSTs.
0345 // TODO: This is conceptually inconsistent with GetAll. Reconcile.
0346 
0347 template<class S>
0348 std::map<std::pair<std::string, std::string>, std::vector<S*>> JEvent::GetAllChildren() const {
0349     std::map<std::pair<std::string, std::string>, std::vector<S*>> results;
0350     for (JFactory* factory : mFactorySet->GetAllFactories()) {
0351         auto val = factory->GetAs<S>();
0352         if (!val.empty()) {
0353             auto key = std::make_pair(factory->GetObjectName(), factory->GetTag());
0354             results.insert(std::make_pair(key, val));
0355         }
0356     }
0357     return results;
0358 }
0359 
0360 
0361 
0362 /// Insert() allows an EventSource to insert items directly into the JEvent,
0363 /// removing the need for user-extended JEvents and/or JEventSource::GetObjects(...)
0364 /// Repeated calls to Insert() will append to the previous data rather than overwrite it,
0365 /// which saves the user from having to allocate a throwaway vector and requires less error handling.
0366 template <class T>
0367 inline JFactoryT<T>* JEvent::Insert(T* item, const std::string& tag) const {
0368 
0369     std::string resolved_tag = tag;
0370     if (mUseDefaultTags && tag.empty()) {
0371         auto defaultTag = mDefaultTags.find(JTypeInfo::demangle<T>());
0372         if (defaultTag != mDefaultTags.end()) resolved_tag = defaultTag->second;
0373     }
0374     auto factory = mFactorySet->GetFactory<T>(resolved_tag);
0375     if (factory == nullptr) {
0376         factory = new JFactoryT<T>;
0377         factory->SetTag(tag);
0378         factory->SetLevel(mFactorySet->GetLevel());
0379         mFactorySet->Add(factory);
0380     }
0381     factory->Insert(item);
0382     factory->SetInsertOrigin( mCallGraph.GetInsertDataOrigin() ); // (see note at top of JCallGraphRecorder.h)
0383     return factory;
0384 }
0385 
0386 template <class T>
0387 inline JFactoryT<T>* JEvent::Insert(const std::vector<T*>& items, const std::string& tag) const {
0388 
0389     std::string resolved_tag = tag;
0390     if (mUseDefaultTags && tag.empty()) {
0391         auto defaultTag = mDefaultTags.find(JTypeInfo::demangle<T>());
0392         if (defaultTag != mDefaultTags.end()) resolved_tag = defaultTag->second;
0393     }
0394     auto factory = mFactorySet->GetFactory<T>(resolved_tag);
0395     if (factory == nullptr) {
0396         factory = new JFactoryT<T>;
0397         factory->SetTag(tag);
0398         factory->SetLevel(mFactorySet->GetLevel());
0399         mFactorySet->Add(factory);
0400     }
0401     for (T* item : items) {
0402         factory->Insert(item);
0403     }
0404     factory->SetStatus(JFactory::Status::Inserted); // for when items is empty
0405     factory->SetCreationStatus(JFactory::CreationStatus::Inserted); // for when items is empty
0406     factory->SetInsertOrigin( mCallGraph.GetInsertDataOrigin() ); // (see note at top of JCallGraphRecorder.h)
0407     return factory;
0408 }
0409 
0410 
0411 
0412 #if JANA2_HAVE_PODIO
0413 
0414 inline std::vector<std::string> JEvent::GetAllCollectionNames() const {
0415     std::vector<std::string> keys;
0416     for (auto pair : mPodioFactories) {
0417         keys.push_back(pair.first);
0418     }
0419     return keys;
0420 }
0421 
0422 inline const podio::CollectionBase* JEvent::GetCollectionBase(std::string name, bool throw_on_missing) const {
0423     auto it = mPodioFactories.find(name);
0424     if (it == mPodioFactories.end()) {
0425         if (throw_on_missing) {
0426             throw JException("No factory with tag '%s' found", name.c_str());
0427         }
0428         else {
0429             return nullptr;
0430         }
0431     }
0432     JFactoryPodio* factory = dynamic_cast<JFactoryPodio*>(it->second);
0433     if (factory == nullptr) {
0434         // Should be no way to get here if we encapsulate mPodioFactories correctly
0435         throw JException("Factory with tag '%s' does not inherit from JFactoryPodio!", name.c_str());
0436     }
0437     JCallGraphEntryMaker cg_entry(mCallGraph, it->second); // times execution until this goes out of scope
0438     it->second->Create(this->shared_from_this());
0439     return factory->GetCollection();
0440 }
0441 
0442 
0443 template <typename T>
0444 const typename JFactoryPodioT<T>::CollectionT* JEvent::GetCollection(std::string name, bool throw_on_missing) const {
0445     JFactoryT<T>* factory = GetFactory<T>(name, throw_on_missing);
0446     if (factory == nullptr) {
0447         return nullptr;
0448     }
0449     JFactoryPodioT<T>* typed_factory = dynamic_cast<JFactoryPodioT<T>*>(factory);
0450     if (typed_factory == nullptr) {
0451         throw JException("Factory must inherit from JFactoryPodioT in order to use JEvent::GetCollection()");
0452     }
0453     JCallGraphEntryMaker cg_entry(mCallGraph, typed_factory); // times execution until this goes out of scope
0454     typed_factory->Create(this->shared_from_this());
0455     return static_cast<const typename JFactoryPodioT<T>::CollectionT*>(typed_factory->GetCollection());
0456 }
0457 
0458 
0459 template <typename T>
0460 JFactoryPodioT<T>* JEvent::InsertCollection(typename JFactoryPodioT<T>::CollectionT&& collection, std::string name) {
0461     /// InsertCollection inserts the provided PODIO collection into both the podio::Frame and then a JFactoryPodioT<T>
0462 
0463     auto frame = GetOrCreateFrame(shared_from_this());
0464     const auto& owned_collection = frame->put(std::move(collection), name);
0465     return InsertCollectionAlreadyInFrame<T>(&owned_collection, name);
0466 }
0467 
0468 
0469 template <typename T>
0470 JFactoryPodioT<T>* JEvent::InsertCollectionAlreadyInFrame(const podio::CollectionBase* collection, std::string name) {
0471     /// InsertCollection inserts the provided PODIO collection into a JFactoryPodioT<T>. It assumes that the collection pointer
0472     /// is _already_ owned by the podio::Frame corresponding to this JEvent. This is meant to be used if you are starting out
0473     /// with a PODIO frame (e.g. a JEventSource that uses podio::ROOTReader).
0474     
0475     const auto* typed_collection = dynamic_cast<const typename T::collection_type*>(collection);
0476     if (typed_collection == nullptr) {
0477         throw JException("Attempted to insert a collection of the wrong type! name='%s', expected type='%s', actual type='%s'",
0478             name.c_str(), JTypeInfo::demangle<typename T::collection_type>().c_str(), collection->getDataTypeName().data());
0479     }
0480 
0481     // Users are allowed to Insert with tag="" if and only if that tag gets resolved by default tags.
0482     if (mUseDefaultTags && name.empty()) {
0483         auto defaultTag = mDefaultTags.find(JTypeInfo::demangle<T>());
0484         if (defaultTag != mDefaultTags.end()) name = defaultTag->second;
0485     }
0486 
0487     // Retrieve factory if it already exists, else create it
0488     JFactoryT<T>* factory = mFactorySet->GetFactory<T>(name);
0489     if (factory == nullptr) {
0490         factory = new JFactoryPodioT<T>();
0491         factory->SetTag(name);
0492         factory->SetLevel(GetLevel());
0493         mFactorySet->Add(factory);
0494 
0495         auto it = mPodioFactories.find(name);
0496         if (it != mPodioFactories.end()) {
0497             throw JException("InsertCollection failed because tag '%s' is not unique", name.c_str());
0498         }
0499         mPodioFactories[name] = factory;
0500     }
0501 
0502     // PODIO collections can only be inserted once, unlike regular JANA factories.
0503     if (factory->GetStatus() == JFactory::Status::Inserted  ||
0504         factory->GetStatus() == JFactory::Status::Processed) {
0505 
0506         throw JException("PODIO collections can only be inserted once, but factory with tag '%s' already has data", name.c_str());
0507     }
0508 
0509     // There's a chance that some user already added to the event's JFactorySet a
0510     // JFactoryT<PodioT> which ISN'T a JFactoryPodioT<T>. In this case, we cannot set the collection.
0511     JFactoryPodioT<T>* typed_factory = dynamic_cast<JFactoryPodioT<T>*>(factory);
0512     if (typed_factory == nullptr) {
0513         throw JException("Factory must inherit from JFactoryPodioT in order to use JEvent::GetCollection()");
0514     }
0515 
0516     typed_factory->SetCollectionAlreadyInFrame(typed_collection);
0517     typed_factory->SetInsertOrigin( mCallGraph.GetInsertDataOrigin() );
0518     return typed_factory;
0519 }
0520 
0521 #endif // JANA2_HAVE_PODIO
0522 
0523 
0524