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);
0074 auto result = arrow.execute( 0);
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
0094 JEventPool parent_pool {jcm, 5, 1, JEventLevel::Timeslice};
0095 JEventPool child_pool {jcm, 5, 1, JEventLevel::PhysicsEvent};
0096
0097
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
0205
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 }
0262 }
0263
0264
0265
0266