Skip to content

Commit 2f4a7ed

Browse files
authored
Merge branch 'develop' into eflumerf/CFOZmqReceiver
2 parents 7ad3e96 + 1fd864c commit 2f4a7ed

3 files changed

Lines changed: 334 additions & 1 deletion

File tree

artdaq-mu2e/ArtModules/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ cet_build_plugin(Mu2eArtdaqTimeTrackerService art::service LIBRARIES REG
2626
cetlib::sqlite
2727
artdaq::DAQdata
2828
art::Framework_Principal
29-
)
29+
)
30+
31+
cet_build_plugin(DTCEVTPrint art::module LIBRARIES REG
32+
art_root_io::TFileService_service
33+
artdaq-core-mu2e::Data
34+
)
3035

3136
# Subdirectories.
3237
add_subdirectory(fcl)
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
2+
// Sam Grant 2025
3+
// Decode fragments and print everything
4+
// Independent of Offline
5+
6+
// C++ includes
7+
#include <iomanip>
8+
#include <map>
9+
#include <string>
10+
#include <thread>
11+
12+
// art includes
13+
#include "art/Framework/Core/EDAnalyzer.h"
14+
#include "art/Framework/Core/ModuleMacros.h"
15+
#include "art/Framework/Principal/Event.h"
16+
#include "art/Framework/Principal/Handle.h"
17+
#include "art/Framework/Principal/Run.h"
18+
19+
// artdaq includes
20+
// #include "artdaq-core-mu2e/Data/CRVDataDecoder.hh"
21+
#include "artdaq-core-mu2e/Overlays/DTCEventFragment.hh"
22+
#include "artdaq-core-mu2e/Overlays/FragmentType.hh"
23+
#include "artdaq-core/Data/ContainerFragment.hh"
24+
#include "artdaq-core/Data/Fragment.hh"
25+
26+
namespace ots {
27+
28+
// Utility to convert enum values to strings for better logging
29+
std::string subsystemToString(uint8_t subsystem)
30+
{
31+
switch (subsystem)
32+
{
33+
case 0:
34+
return "Tracker";
35+
case 1:
36+
return "Calorimeter";
37+
case 2:
38+
return "CRV";
39+
case 3:
40+
return "Other";
41+
case 4:
42+
return "STM";
43+
case 5:
44+
return "ExtMon";
45+
case 7:
46+
return "TDAQ";
47+
default:
48+
return "Unknown (" + std::to_string(subsystem) + ")";
49+
}
50+
}
51+
52+
class DTCEVTPrint : public art::EDAnalyzer
53+
{
54+
public:
55+
// Constructor
56+
explicit DTCEVTPrint(fhicl::ParameterSet const &ps);
57+
// Destructor
58+
~DTCEVTPrint() override;
59+
60+
private:
61+
// Functions
62+
void beginJob() override;
63+
void analyze(art::Event const &e) override;
64+
void endJob() override;
65+
66+
// Parameters
67+
int diagLevel_;
68+
69+
std::string outputPrefix_;
70+
size_t fragmentCounts_{0};
71+
size_t subEventCounts_{0};
72+
size_t blockCounts_{0};
73+
size_t eventWindowTagCounts_{0};
74+
size_t packetCounts_{0};
75+
};
76+
77+
// Constructor implementation
78+
DTCEVTPrint::DTCEVTPrint(fhicl::ParameterSet const &ps)
79+
: art::EDAnalyzer(ps), diagLevel_(ps.get<int>("diagLevel", 1))
80+
{
81+
outputPrefix_ = "[DTCEVTPrint] ";
82+
}
83+
84+
// Destructor implementation
85+
DTCEVTPrint::~DTCEVTPrint() {}
86+
87+
void DTCEVTPrint::beginJob()
88+
{
89+
std::cout << outputPrefix_ << "Beginning job with debug level (diagLevel_) " << diagLevel_ << std::endl;
90+
}
91+
92+
void DTCEVTPrint::analyze(art::Event const &e)
93+
{
94+
// Get fragments
95+
std::vector<art::Handle<artdaq::Fragments>> fragmentHandles;
96+
fragmentHandles = e.getMany<std::vector<artdaq::Fragment>>();
97+
artdaq::FragmentPtrs containerFragments;
98+
artdaq::Fragments fragments;
99+
100+
if (diagLevel_ > 0)
101+
{
102+
std::cout << outputPrefix_ << "=================== " << e.id() << " ===================" << std::endl;
103+
std::cout << outputPrefix_ << "Number of fragment handles: " << fragmentHandles.size() << std::endl;
104+
}
105+
106+
// Iterate through fragment handles
107+
for (const auto &handle : fragmentHandles)
108+
{
109+
// Catch invalid or empty handles
110+
if (!handle.isValid() || handle->empty())
111+
{
112+
if (diagLevel_ > 0)
113+
{
114+
std::cout << outputPrefix_ << "Found invalid or empty handle" << std::endl;
115+
}
116+
continue;
117+
}
118+
119+
if (handle->front().type() == artdaq::Fragment::ContainerFragmentType)
120+
{
121+
// Iterate through containers
122+
if (diagLevel_ > 1)
123+
{
124+
std::cout << outputPrefix_ << "Container fragments (ContainerFragmentType) in handle: " << handle->size() << std::endl;
125+
}
126+
for (const auto &cont : *handle)
127+
{
128+
artdaq::ContainerFragment contf(cont);
129+
130+
if (diagLevel_ > 1)
131+
{
132+
std::cout << outputPrefix_ << "Container fragment type: " << contf.fragment_type() << std::endl;
133+
std::cout << outputPrefix_ << "Container block count: " << contf.block_count() << std::endl;
134+
}
135+
136+
// Break if this is single fragment rather than a container
137+
if (contf.fragment_type() != mu2e::FragmentType::DTCEVT)
138+
{
139+
if (diagLevel_ > 1)
140+
{
141+
std::cout << outputPrefix_ << "Container fragment type is not DTCEVT" << std::endl;
142+
}
143+
break;
144+
}
145+
// Iterate through fragments in container and fill fragments vector
146+
for (size_t i = 0; i < contf.block_count(); ++i)
147+
{
148+
containerFragments.push_back(contf[i]);
149+
fragments.push_back(*containerFragments.back());
150+
}
151+
}
152+
}
153+
else if (handle->front().type() == mu2e::FragmentType::DTCEVT)
154+
{ // If the first object in the handle a single fragment
155+
if (diagLevel_ > 1)
156+
{
157+
std::cout << outputPrefix_ << "DTC Event (DTCEVT) fragments in handle: " << handle->size() << std::endl;
158+
}
159+
// Iterate through fragments and fill fragments vector
160+
for (auto frag : *handle)
161+
{
162+
fragments.emplace_back(frag);
163+
}
164+
}
165+
else
166+
{
167+
std::cerr << outputPrefix_ << "Handle type '" << handle->front().type() << "' not recognised" << std::endl;
168+
}
169+
}
170+
171+
fragmentCounts_ += fragments.size();
172+
173+
// Summary counters for current event
174+
size_t currentEventSubEvents = 0;
175+
size_t currentEventBlocks = 0;
176+
size_t currentEventPackets = 0;
177+
178+
// Handle the fragments
179+
for (const auto &frag : fragments)
180+
{
181+
try
182+
{
183+
mu2e::DTCEventFragment bb(frag);
184+
auto data = bb.getData();
185+
auto event = &data;
186+
187+
auto EWT = event->GetEventWindowTag().GetEventWindowTag(true);
188+
189+
if (diagLevel_ > 1)
190+
{
191+
std::cout << outputPrefix_ << "Event Window Tag: " << EWT << std::dec << std::endl;
192+
}
193+
++eventWindowTagCounts_;
194+
195+
// Event header
196+
DTCLib::DTC_EventHeader *eventHeader = event->GetHeader();
197+
size_t subEventsCount = event->GetSubEventCount();
198+
currentEventSubEvents += subEventsCount;
199+
200+
if (diagLevel_ > 1)
201+
{
202+
std::cout << outputPrefix_ << "Subevents count: " << subEventsCount << std::endl;
203+
std::cout << outputPrefix_ << eventHeader->toJson() << std::endl;
204+
}
205+
206+
for (unsigned int iSubEvent = 0; iSubEvent < subEventsCount; ++iSubEvent)
207+
{
208+
// Subevent
209+
DTCLib::DTC_SubEvent &subevent = *(event->GetSubEvent(iSubEvent));
210+
211+
// Subevent header
212+
const DTCLib::DTC_SubEventHeader *subeventHeader = subevent.GetHeader();
213+
size_t blockCount = subevent.GetDataBlockCount();
214+
215+
if (diagLevel_ > 1)
216+
{
217+
std::cout << outputPrefix_ << "---> Subevent [" << iSubEvent << "]:" << std::endl;
218+
std::cout << outputPrefix_ << "Number of Data Blocks: " << blockCount << std::endl;
219+
std::cout << outputPrefix_ << subeventHeader->toJson() << std::endl;
220+
}
221+
222+
currentEventBlocks += blockCount;
223+
224+
for (size_t iBlock = 0; iBlock < blockCount; ++iBlock)
225+
{
226+
auto block = subevent.GetDataBlock(iBlock);
227+
auto blockheader = block->GetHeader();
228+
auto subsystem = blockheader->GetSubsystem();
229+
size_t packetCount = blockheader->GetPacketCount();
230+
currentEventPackets += packetCount;
231+
232+
if (diagLevel_ > 1)
233+
{
234+
std::cout << outputPrefix_ << "---> Block [" << iBlock << "]:" << std::endl;
235+
std::cout << outputPrefix_ << "Packet Count: " << blockheader->GetPacketCount() << std::endl;
236+
std::cout << outputPrefix_ << blockheader->toJSON() << std::endl;
237+
std::cout << outputPrefix_ << "Block details:" << std::endl
238+
<< outputPrefix_ << " Subsystem: " << subsystemToString(subsystem) << std::endl
239+
<< outputPrefix_ << " Valid: " << (blockheader->isValid() ? "Yes" : "No") << std::endl
240+
<< outputPrefix_ << " Version: 0x" << std::hex << (int)blockheader->GetVersion() << std::dec << std::endl
241+
<< outputPrefix_ << " DTC ID: " << (int)blockheader->GetID() << std::endl
242+
<< outputPrefix_ << " Byte Count: " << block->byteSize << std::endl
243+
<< outputPrefix_ << " Event Window Tag: " << blockheader->GetEventWindowTag().GetEventWindowTag(true) << std::endl; // " (0x"
244+
245+
if (diagLevel_ > 2)
246+
{
247+
for (int iPacket = 0; iPacket < blockheader->GetPacketCount(); ++iPacket)
248+
{
249+
std::cout << outputPrefix_ << "---> Packet [" << iPacket << "]: " << DTCLib::DTC_DataPacket(((uint8_t *)block->blockPointer) + ((iPacket + 1) * 16)).toJSON() << std::endl;
250+
}
251+
}
252+
}
253+
254+
// Make sure we only process CRV data
255+
/*
256+
if (blockheader->GetSubsystem() == DTCLib::DTC_Subsystem_CRV) {
257+
}*/
258+
}
259+
}
260+
}
261+
catch (const std::exception &e)
262+
{
263+
if (diagLevel_ > 0)
264+
{
265+
std::cerr << outputPrefix_ << "Error processing fragment: " << e.what() << std::endl;
266+
}
267+
continue;
268+
}
269+
}
270+
271+
// Print summary for this event
272+
if (diagLevel_ > 0)
273+
{
274+
std::cout << outputPrefix_ << "Event Summary: "
275+
<< currentEventSubEvents << " SubEvents; "
276+
<< currentEventBlocks << " Blocks; "
277+
<< currentEventPackets << " Packets; "
278+
<< std::endl;
279+
}
280+
281+
subEventCounts_ += currentEventSubEvents;
282+
blockCounts_ += currentEventBlocks;
283+
packetCounts_ += currentEventPackets;
284+
}
285+
286+
void DTCEVTPrint::endJob()
287+
{
288+
// Print job-level statistics
289+
std::cout << outputPrefix_ << "================= Job Summary =================" << std::endl;
290+
std::cout << outputPrefix_ << "Total Fragments: " << fragmentCounts_ << std::endl;
291+
std::cout << outputPrefix_ << "Total SubEvents: " << subEventCounts_ << std::endl;
292+
std::cout << outputPrefix_ << "Total Blocks: " << blockCounts_ << std::endl;
293+
std::cout << outputPrefix_ << "===============================================" << std::endl;
294+
}
295+
296+
DEFINE_ART_MODULE(DTCEVTPrint)
297+
} // namespace ots
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
process_name : CrvDQMOffline
2+
3+
source: {
4+
module_type: RootInput # EmptyEvent
5+
maxEvents: -1
6+
}
7+
8+
physics : {
9+
10+
producers: {
11+
}
12+
13+
analyzers : {
14+
print: {
15+
module_type: DTCEVTPrint
16+
diagLevel : 2
17+
}
18+
}
19+
20+
t1 : []
21+
a1 : [print]
22+
e1 : [fileDump]
23+
24+
trigger_paths : [t1]
25+
end_paths : [a1] # , e1]
26+
}
27+
28+
outputs: {
29+
fileDump: {
30+
}
31+
}

0 commit comments

Comments
 (0)