Back to home page

EIC code displayed by LXR

 
 

    


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

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 
0006 #include <JANA/JEventSource.h>
0007 #include <JANA/JEventSourceGeneratorT.h>
0008 
0009 #include <PodioDatamodel/EventInfoCollection.h>
0010 #include <PodioDatamodel/TimesliceInfoCollection.h>
0011 #include <PodioDatamodel/ExampleHitCollection.h>
0012 #include <PodioDatamodel/ExampleClusterCollection.h>
0013 
0014 #include <podio/podioVersion.h>
0015 #if podio_VERSION_MAJOR == 0 && podio_VERSION_MINOR < 99
0016 #include <podio/ROOTFrameReader.h>
0017 namespace podio {
0018     using ROOTReader = podio::ROOTFrameReader;
0019 }
0020 #else
0021 #include <podio/ROOTReader.h>
0022 #endif
0023 
0024 
0025 
0026 class PodioFileReader : public JEventSource {
0027 
0028 private:
0029     uint64_t m_entry_count = 0;
0030     podio::ROOTReader m_reader;
0031     // ROOTReader emits a lot of deprecation warnings, but the supposed replacement
0032     // won't actually be a replacement until the next version
0033 
0034 public:
0035     PodioFileReader() {
0036         SetCallbackStyle(CallbackStyle::ExpertMode);
0037     }
0038 
0039     static std::string GetDescription() {
0040         return "Example that reads a PODIO file into JANA. This example uses `PodioDatamodel`, but it is trivial to adapt it to any data model. For now this only works on files containing events, not timeslices or any other levels.";
0041     }
0042 
0043     void Open() final {
0044         m_reader.openFile(GetResourceName());
0045         m_entry_count = m_reader.getEntries("events");
0046     }
0047 
0048     void Close() final {
0049         // ROOT(Frame)Reader doesn't support closing the file (!). 
0050         // Maybe we can do this via ROOT. 
0051     }
0052 
0053     Result Emit(JEvent& event) final {
0054 
0055         // Figure out which entry to read
0056 
0057         uint64_t event_index = event.GetEventNumber(); // Event number starts from zero by default
0058         if (event_index >= m_entry_count) return Result::FailureFinished;
0059 
0060         // Read entry
0061 
0062         auto frame_data = m_reader.readEntry("events", event_index);
0063         auto frame = std::make_unique<podio::Frame>(std::move(frame_data));
0064 
0065         // Extract event key (event nr, run nr, timeslice nr, etc)
0066 
0067         auto& eventinfo = frame->get<EventInfoCollection>("eventinfos");
0068         if (eventinfo.size() != 1) throw JException("Bad eventinfo: Entry %d contains %d items, 1 expected.", event_index, eventinfo.size());
0069         event.SetEventNumber(eventinfo[0].EventNumber());
0070         event.SetRunNumber(eventinfo[0].RunNumber());
0071 
0072         // Make all PODIO collections available to JANA
0073 
0074         for (const std::string& coll_name : frame->getAvailableCollections()) {
0075 
0076             // It is possible to only put a subset of the collections into the JEvent.
0077             // However this is risky because PODIO tracks inter-object associations but
0078             // doesn't track the resulting inter-collection associations. Thus if the user
0079             // omits any collections when they read a file, they risk introducing dangling 
0080             // pointers. This can segfault or silently corrupt the data in the output file.
0081 
0082             const podio::CollectionBase* coll = frame->get(coll_name);
0083             const auto& coll_type = coll->getValueTypeName();
0084 
0085             if (coll_type == "EventInfo") {
0086                 event.InsertCollectionAlreadyInFrame<EventInfo>(coll, coll_name);
0087             }
0088             else if (coll_type == "TimesliceInfo") {
0089                 event.InsertCollectionAlreadyInFrame<TimesliceInfo>(coll, coll_name);
0090             }
0091             else if (coll_type == "ExampleHit") {
0092                 event.InsertCollectionAlreadyInFrame<ExampleHit>(coll, coll_name);
0093             }
0094             else if (coll_type == "ExampleCluster") {
0095                 event.InsertCollectionAlreadyInFrame<ExampleCluster>(coll, coll_name);
0096             }
0097             else {
0098                 throw JException("Collection '%s' has typename '%s' which is not known to PodioFileReader", coll_name.c_str(), coll_type.data());
0099             }
0100         }
0101 
0102         // Put the frame in the events as well, tying their lifetimes together
0103 
0104         event.Insert(frame.release()); // Transfer ownership from unique_ptr to JFactoryT<podio::Frame>
0105         return Result::Success;
0106     }
0107 };
0108 
0109 
0110 
0111 extern "C" {
0112 void InitPlugin(JApplication* app) {
0113     InitJANAPlugin(app);
0114     app->Add(new JEventSourceGeneratorT<PodioFileReader>);
0115 }
0116 }
0117