Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 08:57:23

0001 // Copyright 2024, Jefferson Science Associates, LLC.
0002 // Subject to the terms in the LICENSE file found in the top-level directory.
0003 
0004 #pragma once
0005 
0006 #include <JANA/Components/JComponent.h>
0007 #include <JANA/Components/JHasInputs.h>
0008 #include <JANA/Components/JHasOutputs.h>
0009 #include <JANA/Components/JHasRunCallbacks.h>
0010 #include <JANA/JEvent.h>
0011 
0012 class JApplication;
0013 class JEventUnfolder : public jana::components::JComponent, 
0014                        public jana::components::JHasRunCallbacks,
0015                        public jana::components::JHasInputs, 
0016                        public jana::components::JHasOutputs {
0017 
0018 private:
0019     int32_t m_last_run_number = -1;
0020     bool m_enable_simplified_callbacks = false;
0021     JEventLevel m_child_level;
0022     int m_child_number = 0;
0023     bool m_call_preprocess_upstream = true;
0024 
0025 
0026 public:
0027     // JEventUnfolder interface
0028     
0029     virtual ~JEventUnfolder() {};
0030  
0031     enum class Result { NextChildNextParent, NextChildKeepParent, KeepChildNextParent };
0032 
0033     virtual void Init() {};
0034     
0035     virtual void Preprocess(const JEvent& /*parent*/) const {};
0036 
0037     virtual Result Unfold(const JEvent& /*parent*/, JEvent& /*child*/, int /*item_nr*/) {
0038         throw JException("Not implemented yet!");
0039     };
0040 
0041     virtual Result Unfold(uint64_t /*parent_nr*/, uint64_t /*child_nr*/, int /*item_nr*/) {
0042         throw JException("Not implemented yet!");
0043     };
0044 
0045     virtual void Finish() {};
0046 
0047 
0048     // Configuration
0049 
0050     void SetParentLevel(JEventLevel level) { m_level = level; }
0051 
0052     void SetChildLevel(JEventLevel level) { m_child_level = level; }
0053 
0054     void SetCallPreprocessUpstream(bool call_upstream) { m_call_preprocess_upstream = call_upstream; }
0055     
0056     JEventLevel GetChildLevel() { return m_child_level; }
0057 
0058 
0059  public:
0060     // Backend
0061     
0062     void DoInit() {
0063         std::lock_guard<std::mutex> lock(m_mutex);
0064         if (m_status != Status::Uninitialized) {
0065             throw JException("JEventUnfolder: Attempting to initialize twice or from an invalid state");
0066         }
0067         // TODO: Obtain overrides of collection names from param manager
0068         for (auto* parameter : m_parameters) {
0069             parameter->Init(*(m_app->GetJParameterManager()), m_prefix);
0070         }
0071         for (auto* service : m_services) {
0072             service->Fetch(m_app);
0073         }
0074         CallWithJExceptionWrapper("JEventUnfolder::Init", [&](){Init();});
0075         m_status = Status::Initialized;
0076     }
0077 
0078     void DoPreprocess(const JEvent& parent) {
0079         {
0080             std::lock_guard<std::mutex> lock(m_mutex);
0081             if (m_status != Status::Initialized) {
0082                 throw JException("JEventUnfolder: Component needs to be initialized and not finalized before Unfold can be called");
0083                 // TODO: Consider calling Initialize(with_lock=false) like we do elsewhere
0084             }
0085         }
0086         for (auto* input : m_inputs) {
0087             input->PrefetchCollection(parent);
0088         }
0089         for (auto* variadic_input : m_variadic_inputs) {
0090             variadic_input->PrefetchCollection(parent);
0091         }
0092         if (m_callback_style != CallbackStyle::DeclarativeMode) {
0093             CallWithJExceptionWrapper("JEventUnfolder::Preprocess", [&](){
0094                 Preprocess(parent);
0095             });
0096         }
0097     }
0098 
0099     Result DoUnfold(const JEvent& parent, JEvent& child) {
0100         std::lock_guard<std::mutex> lock(m_mutex);
0101         if (m_status == Status::Initialized) {
0102             if (!m_call_preprocess_upstream) {
0103                 if (!m_enable_simplified_callbacks) {
0104                     CallWithJExceptionWrapper("JEventUnfolder::Preprocess", [&](){
0105                         Preprocess(parent);
0106                     });
0107                 }
0108             }
0109             if (m_last_run_number != parent.GetRunNumber()) {
0110                 for (auto* resource : m_resources) {
0111                     resource->ChangeRun(parent.GetRunNumber(), m_app);
0112                 }
0113                 if (m_callback_style == CallbackStyle::DeclarativeMode) {
0114                     CallWithJExceptionWrapper("JEventUnfolder::ChangeRun", [&](){
0115                         ChangeRun(parent.GetRunNumber());
0116                     });
0117                 }
0118                 else {
0119                     CallWithJExceptionWrapper("JEventUnfolder::ChangeRun", [&](){
0120                         ChangeRun(parent);
0121                     });
0122                 }
0123                 m_last_run_number = parent.GetRunNumber();
0124             }
0125             for (auto* input : m_inputs) {
0126                 input->GetCollection(parent);
0127                 // TODO: This requires that all inputs come from the parent.
0128                 //       However, eventually we will want to support inputs 
0129                 //       that come from the child.
0130             }
0131             for (auto* variadic_input : m_variadic_inputs) {
0132                 variadic_input->GetCollection(parent);
0133             }
0134             for (auto* output : m_outputs) {
0135                 output->Reset();
0136             }
0137             Result result;
0138             child.SetEventIndex(m_child_number);
0139             if (m_enable_simplified_callbacks) {
0140                 CallWithJExceptionWrapper("JEventUnfolder::Unfold", [&](){
0141                     result = Unfold(parent.GetEventNumber(), child.GetEventNumber(), m_child_number);
0142                 });
0143             }
0144             else {
0145                 CallWithJExceptionWrapper("JEventUnfolder::Unfold", [&](){
0146                     result = Unfold(parent, child, m_child_number);
0147                 });
0148             }
0149             if (result != Result::KeepChildNextParent) {
0150                 // If the user returns KeepChildNextParent, JANA cannot publish any output databundles (not even empty ones)
0151                 // because on the next call to Unfold(), podio will throw an exception about inserting the collection twice.
0152                 // Any data put in an output databundle will be automatically cleared via OutputBase::Reset() before the next Unfold().
0153                 for (auto* output : m_outputs) {
0154                     output->InsertCollection(child);
0155                 }
0156             }
0157             m_child_number += 1;
0158             if (result == Result::NextChildNextParent || result == Result::KeepChildNextParent) {
0159                 m_child_number = 0;
0160             }
0161             return result;
0162         }
0163         else {
0164             throw JException("Component needs to be initialized and not finalized before Unfold can be called");
0165         }
0166     }
0167 
0168     void DoFinish() {
0169         std::lock_guard<std::mutex> lock(m_mutex);
0170         if (m_status != Status::Finalized) {
0171             CallWithJExceptionWrapper("JEventUnfolder::Finish", [&](){
0172                 Finish();
0173             });
0174             m_status = Status::Finalized;
0175         }
0176     }
0177 
0178     void Summarize(JComponentSummary& summary) const override {
0179         auto* us = new JComponentSummary::Component( 
0180             "Unfolder", GetPrefix(), GetTypeName(), GetLevel(), GetPluginName());
0181 
0182         for (const auto* input : m_inputs) {
0183             us->AddInput(new JComponentSummary::Collection("", input->GetDatabundleName(), input->GetTypeName(), input->GetLevel()));
0184         }
0185         for (const auto* input : m_variadic_inputs) {
0186             size_t subinput_count = input->GetRequestedDatabundleNames().size();
0187             for (size_t i=0; i<subinput_count; ++i) {
0188                 us->AddInput(new JComponentSummary::Collection("", input->GetRequestedDatabundleNames().at(i), input->GetTypeName(), input->GetLevel()));
0189             }
0190         }
0191         for (const auto* output : m_outputs) {
0192             size_t suboutput_count = output->collection_names.size();
0193             for (size_t i=0; i<suboutput_count; ++i) {
0194                 us->AddOutput(new JComponentSummary::Collection("", output->collection_names[i], output->type_name, GetLevel()));
0195             }
0196         }
0197         summary.Add(us);
0198     }
0199 
0200 };
0201 
0202