Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:22:26

0001 
0002 #include <catch.hpp>
0003 #include <JANA/JEventProcessor.h>
0004 #include <JANA/Topology/JUnfoldArrow.h>
0005 #include <JANA/Topology/JFoldArrow.h>
0006 
0007 #if JANA2_HAVE_PODIO
0008 #include <PodioDatamodel/ExampleHitCollection.h>
0009 #endif
0010 
0011 namespace jana {
0012 namespace unfoldtests {
0013 
0014 
0015 struct TestUnfolder : public JEventUnfolder {
0016     mutable std::vector<int> preprocessed_event_nrs;
0017     mutable std::vector<JEventLevel> preprocessed_event_levels;
0018     std::vector<int> unfolded_parent_nrs;
0019     std::vector<JEventLevel> unfolded_parent_levels;
0020     std::vector<int> unfolded_child_nrs;
0021     std::vector<JEventLevel> unfolded_child_levels;
0022 
0023     TestUnfolder() {
0024         SetParentLevel(JEventLevel::Timeslice);
0025         SetChildLevel(JEventLevel::PhysicsEvent);
0026     }
0027 
0028     void Preprocess(const JEvent& parent) const override {
0029         LOG << "Preprocessing " << parent.GetLevel() << " event " << parent.GetEventNumber() << LOG_END;
0030         preprocessed_event_nrs.push_back(parent.GetEventNumber());
0031         preprocessed_event_levels.push_back(parent.GetLevel());
0032     }
0033 
0034     Result Unfold(const JEvent& parent, JEvent& child, int iter) override {
0035         auto child_nr = iter + 100 + parent.GetEventNumber();
0036         unfolded_parent_nrs.push_back(parent.GetEventNumber());
0037         unfolded_parent_levels.push_back(parent.GetLevel());
0038         unfolded_child_nrs.push_back(child_nr);
0039         unfolded_child_levels.push_back(child.GetLevel());
0040         child.SetEventNumber(child_nr);
0041         LOG << "Unfolding " << parent.GetLevel() << " event " << parent.GetEventNumber() << " into " << child.GetLevel() << " " << child_nr << "; iter=" << iter << LOG_END;
0042         return (iter == 2 ? Result::NextChildNextParent : Result::NextChildKeepParent);
0043     }
0044 };
0045 
0046 TEST_CASE("UnfoldTests_Basic") {
0047 
0048     JApplication app;
0049     app.Initialize();
0050     auto jcm = app.GetService<JComponentManager>();
0051 
0052     JEventPool parent_pool {jcm, 5, 1, JEventLevel::Timeslice};
0053     JEventPool child_pool {jcm, 5, 1, JEventLevel::PhysicsEvent};
0054     JEventQueue parent_queue {3, 1};
0055     JEventQueue child_queue {3, 1};
0056 
0057     auto ts1 = parent_pool.Pop(0);
0058     ts1->SetEventNumber(17);
0059 
0060     auto ts2 = parent_pool.Pop(0);
0061     ts2->SetEventNumber(28);
0062 
0063     parent_queue.Push(ts1, 0);
0064     parent_queue.Push(ts2, 0);
0065 
0066     TestUnfolder unfolder;
0067     JUnfoldArrow arrow("sut", &unfolder);
0068     arrow.attach(&parent_queue, JUnfoldArrow::PARENT_IN);
0069     arrow.attach(&child_pool, JUnfoldArrow::CHILD_IN);
0070     arrow.attach(&child_queue, JUnfoldArrow::CHILD_OUT);
0071 
0072     arrow.initialize();
0073     arrow.execute( 0); // First call to execute() picks up the parent and exits early
0074     auto result = arrow.execute( 0); // Second call to execute() picks up the child, calls Unfold(), and emits the newly parented child
0075     REQUIRE(result == JArrow::FireResult::KeepGoing);
0076     REQUIRE(child_queue.GetSize(0) == 1);
0077     REQUIRE(unfolder.preprocessed_event_nrs.size() == 0);
0078     REQUIRE(unfolder.unfolded_parent_nrs.size() == 1);
0079     REQUIRE(unfolder.unfolded_parent_nrs[0] == 17);
0080     REQUIRE(unfolder.unfolded_parent_levels[0] == JEventLevel::Timeslice);
0081     REQUIRE(unfolder.unfolded_child_nrs.size() == 1);
0082     REQUIRE(unfolder.unfolded_child_nrs[0] == 117);
0083     REQUIRE(unfolder.unfolded_child_levels[0] == JEventLevel::PhysicsEvent);
0084 
0085 }
0086 
0087 TEST_CASE("FoldArrowTests") {
0088 
0089     JApplication app;
0090     app.Initialize();
0091     auto jcm = app.GetService<JComponentManager>();
0092 
0093     // We only use these to obtain preconfigured JEvents
0094     JEventPool parent_pool {jcm, 5, 1, JEventLevel::Timeslice};
0095     JEventPool child_pool {jcm, 5, 1, JEventLevel::PhysicsEvent};
0096 
0097     // We set up our test cases by putting events on these queues
0098     JEventQueue child_in(5, 1);
0099     JEventQueue child_out(5, 1);
0100     JEventQueue parent_out(5, 1);
0101 
0102     JFoldArrow arrow("sut", JEventLevel::Timeslice, JEventLevel::PhysicsEvent);
0103     arrow.attach(&child_in, JFoldArrow::CHILD_IN);
0104     arrow.attach(&child_out, JFoldArrow::CHILD_OUT);
0105     arrow.attach(&parent_out, JFoldArrow::PARENT_OUT);
0106     arrow.initialize();
0107 
0108     SECTION("One-to-one relationship between timeslices and events") {
0109 
0110         auto ts1 = parent_pool.Pop(0);
0111         ts1->SetEventNumber(17);
0112         REQUIRE(ts1->GetLevel() == JEventLevel::Timeslice);
0113 
0114         auto ts2 = parent_pool.Pop(0);
0115         ts2->SetEventNumber(28);
0116 
0117         auto evt1 = child_pool.Pop(0);
0118         evt1->SetEventNumber(111);
0119 
0120         auto evt2 = child_pool.Pop(0);
0121         evt2->SetEventNumber(112);
0122 
0123 
0124         evt1->SetParent(ts1);
0125         child_in.Push(evt1, 0);
0126 
0127         evt2->SetParent(ts2);
0128         child_in.Push(evt2, 0);
0129     
0130         arrow.execute(0);
0131 
0132         REQUIRE(child_in.GetSize(0) == 1);
0133         REQUIRE(child_out.GetSize(0) == 1);
0134         REQUIRE(parent_out.GetSize(0) == 1);
0135 
0136     }
0137 
0138 
0139     SECTION("One-to-two relationship between timeslices and events") {
0140 
0141         auto ts1 = parent_pool.Pop(0);
0142         ts1->SetEventNumber(17);
0143         REQUIRE(ts1->GetLevel() == JEventLevel::Timeslice);
0144 
0145         auto ts2 = parent_pool.Pop(0);
0146         ts2->SetEventNumber(28);
0147 
0148         auto evt1 = child_pool.Pop(0);
0149         evt1->SetEventNumber(111);
0150 
0151         auto evt2 = child_pool.Pop(0);
0152         evt2->SetEventNumber(112);
0153 
0154         auto evt3 = child_pool.Pop(0);
0155         evt3->SetEventNumber(113);
0156 
0157         auto evt4 = child_pool.Pop(0);
0158         evt4->SetEventNumber(114);
0159 
0160 
0161         evt1->SetParent(ts1);
0162         evt2->SetParent(ts1);
0163         
0164         evt3->SetParent(ts2);
0165         evt4->SetParent(ts2);
0166    
0167         child_in.Push(evt1, 0);
0168         child_in.Push(evt2, 0);
0169         child_in.Push(evt3, 0);
0170         child_in.Push(evt4, 0);
0171 
0172         arrow.execute(0);
0173 
0174         REQUIRE(child_in.GetSize(0) == 3);
0175         REQUIRE(child_out.GetSize(0) == 1);
0176         REQUIRE(parent_out.GetSize(0) == 0);
0177 
0178         arrow.execute(0);
0179 
0180         REQUIRE(child_in.GetSize(0) == 2);
0181         REQUIRE(child_out.GetSize(0) == 2);
0182         REQUIRE(parent_out.GetSize(0) == 1);
0183 
0184         arrow.execute(0);
0185 
0186         REQUIRE(child_in.GetSize(0) == 1);
0187         REQUIRE(child_out.GetSize(0) == 3);
0188         REQUIRE(parent_out.GetSize(0) == 1);
0189 
0190         arrow.execute(0);
0191 
0192         REQUIRE(child_in.GetSize(0) == 0);
0193         REQUIRE(child_out.GetSize(0) == 4);
0194         REQUIRE(parent_out.GetSize(0) == 2);
0195     }
0196 
0197 
0198 }
0199 
0200 
0201 class NoOpUnfolder : public JEventUnfolder {
0202 #if JANA2_HAVE_PODIO
0203     PodioOutput<ExampleHit> m_hits_out {this}; 
0204     // We never insert these hits, and that should be fine 
0205     // because they should never get pushed to the frame
0206 #endif
0207 
0208 public:
0209     NoOpUnfolder() {
0210         SetParentLevel(JEventLevel::Timeslice);
0211         SetChildLevel(JEventLevel::PhysicsEvent);
0212     }
0213     Result Unfold(const JEvent&, JEvent&, int) {
0214         return Result::KeepChildNextParent;
0215     }
0216 };
0217 
0218 class PhysEvtProc : public JEventProcessor {
0219     int m_events_seen = 0;
0220 public:
0221     PhysEvtProc() {
0222         SetCallbackStyle(CallbackStyle::ExpertMode);
0223     }
0224     void ProcessSequential(const JEvent&) {
0225         m_events_seen += 1;
0226     }
0227     void Finish() {
0228         REQUIRE(m_events_seen == 0);
0229     }
0230 };
0231 
0232 class TimesliceProc : public JEventProcessor {
0233     int m_events_seen = 0;
0234 public:
0235     TimesliceProc() {
0236         SetLevel(JEventLevel::Timeslice);
0237         SetCallbackStyle(CallbackStyle::ExpertMode);
0238     }
0239     void ProcessSequential(const JEvent&) {
0240         m_events_seen += 1;
0241     }
0242     void Finish() {
0243         REQUIRE(m_events_seen == 10);
0244     }
0245 };
0246 
0247 TEST_CASE("NoOpUnfolder_Tests") {
0248     JApplication app;
0249     auto source = new JEventSource();
0250     source->SetLevel(JEventLevel::Timeslice);
0251     app.Add(source);
0252     app.Add(new NoOpUnfolder);
0253     app.Add(new PhysEvtProc);
0254     app.Add(new TimesliceProc);
0255     app.SetParameterValue("jana:nevents", 10);
0256     app.SetParameterValue("jana:loglevel", "debug");
0257     app.Run();
0258 }
0259 
0260 
0261 } // namespace arrowtests
0262 } // namespace jana
0263 
0264 
0265 
0266