Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
1c2323c
Added Container Frag ID for exception
Jun 29, 2026
089bd01
Structural Changes to STM Unpacking module with added comments for cl…
Aug 4, 2026
b779d43
Changes to the Unpacking module, waveformDigis plotting and stmprint…
Aug 12, 2026
89d8942
Saving changes to the files before rebuilding
Aug 12, 2026
9591f60
Latest Changes pull down
Aug 12, 2026
c07cd32
New muse config
Aug 12, 2026
681dc59
Merge remote-tracking branch 'mu2e/main' into stm-unpacking
Aug 12, 2026
685c2c1
Changes to Unpacking for better quakity and readbility
Aug 12, 2026
d4318f9
Adressing PR comments,
Aug 18, 2026
58a4d42
ntuple for phDigis module
Aug 19, 2026
bbb55c4
Fix whitespace
AndrewEdmonds11 Aug 19, 2026
258a8fd
TODO items for coding session
AndrewEdmonds11 Aug 19, 2026
47aaf11
Remove DetID from STMWaveformDigi. Detectors are kept track in collec…
AndrewEdmonds11 Aug 19, 2026
0750b6e
Remove EWT, ADC clock, and DTC clock from STMWaveformDigi. Will be ad…
AndrewEdmonds11 Aug 19, 2026
77fbcd6
Create new STMEventHeader data product
AndrewEdmonds11 Aug 19, 2026
322b18d
work in progress
Aug 19, 2026
6d9cdcb
std::map added to unpacking
Aug 20, 2026
691c9ea
updated std::map to use typedef def
Aug 20, 2026
54eb5c9
Need a couple more things defined in classes_def.xml
AndrewEdmonds11 Aug 20, 2026
3164613
Update Validation module for STMWaveformDigiCollectionMap
AndrewEdmonds11 Aug 20, 2026
e4f7cda
Update MakeSTMHits module for new map
AndrewEdmonds11 Aug 20, 2026
49992f3
STMPHDigiTree with new map format
Aug 20, 2026
78bea68
PlotSTMPHSpectrum now includes map
Aug 20, 2026
10510b0
PlotSTMWaveformDigis uses map now
Aug 24, 2026
2de6400
Changes to plotSTMWaveformDigis to reference EWT and a new switch
Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,101 changes: 1,346 additions & 755 deletions DAQ/src/STMDigisFromFragments_module.cc

Large diffs are not rendered by default.

217 changes: 194 additions & 23 deletions DAQ/src/STMPrintFragments_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ class art::STMPrintFragments : public EDAnalyzer
public:
struct Config
{
fhicl::Atom<art::InputTag> stmTag {fhicl::Name("stmTag"), fhicl::Comment("stmTag for new file")};
fhicl::Atom<art::InputTag> stmTag {fhicl::Name("stmTag"),
fhicl::Comment("stmTag for new file")};
fhicl::Atom<bool> printEverything {fhicl::Name("printEverything"),
fhicl::Comment("Switch to print everything in STM File ")};
fhicl::Atom<bool> printPayloads {fhicl::Name("printPayloads"),
fhicl::Comment("Switch to print only fragment payloads ")};
fhicl::Atom<bool> printInnerFrags {fhicl::Name("printInnerFrags"),
fhicl::Comment("Switch to print inner frags begining from header to end of payload ")};
};

// --- C'tor/d'tor:
Expand All @@ -45,13 +52,19 @@ class art::STMPrintFragments : public EDAnalyzer
private:

art::InputTag _stmFragmentsTag;
bool _printEverything{false};
bool _printPayloads{false};
bool _printInnerFrags{false};
}; // STMPrintFragments

// ======================================================================

STMPrintFragments::STMPrintFragments(const art::EDAnalyzer::Table<Config>& config) :
art::EDAnalyzer{config}
,_stmFragmentsTag(config().stmTag())
,_printEverything(config().printEverything())
,_printPayloads(config().printPayloads())
,_printInnerFrags(config().printInnerFrags())
{}

// ----------------------------------------------------------------------
Expand All @@ -67,31 +80,189 @@ void STMPrintFragments::analyze(const Event& event)
std::cout << STMContainerFragments->size() << " STM fragments." << std::endl;

int frag_counter = 0;
for (auto& frag : *STMContainerFragments) {
for (const auto& frag : *STMContainerFragments) {
++frag_counter;

//New lines
artdaq::ContainerFragment contf(frag); // interpret the fragment as a ContainerFragemnt (Will look inside here)
std::cout<<"N Blocks in the container = " << contf.block_count() << std::endl; //Should be 3 for the 3 STM Fragments

for (size_t ii = 0; ii< contf.block_count(); ++ii){
auto inner = contf.at(ii);
const auto dataBegin = inner->dataBegin();
const auto dataEnd = inner->dataEnd();
auto frag_id = inner->fragmentID();
const auto stmDataBegin = reinterpret_cast<int16_t const*>(dataBegin);
const auto stmDataEnd = reinterpret_cast<int16_t const*>(dataEnd);
std::cout << "Frag_ID = " << frag_id << std::endl;
std::cout << "Container block_count = "<<contf.block_count()<<std::endl;

for (auto i = stmDataBegin; i != stmDataEnd; ++i) {
std::cout << "Frag #" << frag_counter << ", inner #" << ii << ": *(stmDataBegin+" << i - stmDataBegin << ") = " << *i << std::endl;
artdaq::ContainerFragment cont_frag(frag);
std::cout << "N blocks in the container = " << cont_frag.block_count() << std::endl;

if (_printEverything){//Print Eveyrthing Block-----------------------------------------
mu2e::STMFragment container_stm_frag(frag);

const auto dataBegin = frag.dataBegin();
const auto dataEnd = frag.dataEnd();
const auto containerDataBegin = reinterpret_cast<int16_t const*>(dataBegin);
const auto containerDataEnd = reinterpret_cast<int16_t const*>(dataEnd);
auto frag_id = frag.fragmentID();

std::cout << "\n==== FULL CONTAINER DUMP ====\n"
<< "Container Frag_ID : " << frag_id << "\n"
<< "Container Frag # : " << frag_counter << "\n"
<< std::boolalpha
<< "HPGe Container : " << container_stm_frag.isHPGeContainer() << "\n"
<< "LaBr Container : " << container_stm_frag.isLaBrContainer() << "\n"
<< "Container block_count : " << cont_frag.block_count() << std::endl;

for (auto ii = containerDataBegin ; ii !=containerDataEnd; ++ii){
std::cout << "Container frag # " << frag_counter << ": *(containerDataBegin+" << ii - containerDataBegin << ") = " << *ii << std::endl;
}

}
}
}// produce()

// ======================================================================
} //Print Everything Option -----------------------------------------

if (_printInnerFrags){ //Print Inner Fragment Block----------------------------------------
for (size_t i = 0; i < cont_frag.block_count(); ++i){
auto inner_frag = cont_frag.at(i);
mu2e::STMFragment stm_frag(*inner_frag);
const auto frag_id = inner_frag->fragmentID();
const auto stmDataBegin = stm_frag.dataBegin();
const auto stmDataWords = stm_frag.dataWords();

const auto stmPayloadBegin = stm_frag.payloadBegin();
const auto stmPayloadWords = stm_frag.payloadWords();
const auto physicalWords = inner_frag->dataSizeBytes() / sizeof(int16_t);

// Pick smallest of the two so we don't read beyond
size_t const wordsToPrint = std::min<size_t>(stmDataWords, physicalWords);
const auto stmDataEnd = stmDataBegin + wordsToPrint;

//Always print
std::cout << "Frag_ID = " << frag_id << std::endl;
std::cout << "Container block count = " << cont_frag.block_count() << std::endl;
std::cout << "stmdataWords = " << stmDataWords
<< ", physicalWords = " << physicalWords
<< ", payloadWords = " << stmPayloadWords << std::endl;
if ( stm_frag.isRaw() ){
std::cout << "Following information comes from Raw Header:\n" << std::boolalpha
<< ", hasValidAnchors = " << stm_frag.hasValidAnchors()
<< ", rawLength = " << stm_frag.rawLength()
<< ", badData = " << stm_frag.badData()
<< ", missingData = " << stm_frag.missing()
<< ", zsPrescale = " << stm_frag.zsPrescaled()
<< ", rawPrescale = " << stm_frag.rawPrescaled()
<< ", zsPrescaleValue = " << unsigned(stm_frag.zsPrescaleValue())
<< ", rawPrescaleValue = " << unsigned(stm_frag.rawPrescaleValue())
<< "\n";
}

for (auto ii = stmDataBegin; ii != stmDataEnd; ++ii){
std::cout << "Frag #" << frag_counter
<< ", inner #" << i
<< ": *(stmDataBegin+" << ii - stmDataBegin << ") = "
<< *ii << std::endl;
}//should print the whole data set

size_t physicalPayloadWords{0};
if ( stm_frag.isRaw() ){
physicalPayloadWords = physicalWords > stm::RawHeader::WORDS ? physicalWords - stm::RawHeader::WORDS : 0;
size_t nPrintLimit = std::min<size_t>(physicalPayloadWords,20);
std::cout << "\n";

//Print preview of the payload to use as cross reference
//with dataset printed out for raw frags
for (auto ii = stmPayloadBegin; ii != stmPayloadBegin + nPrintLimit; ++ii){
std::cout << "Frag #" << frag_counter
<< ", inner #" << i
<< ": *(stmPayloadBegin+" << ii - stmPayloadBegin << ")="
<< *ii << std::endl;
}
}

}//inner frag loop
}// DataSets Block Option-------------------------------------------------------

if (_printPayloads){
for (size_t i = 0; i < cont_frag.block_count(); ++i){
auto inner_frag = cont_frag.at(i);
mu2e::STMFragment stm_frag(*inner_frag);
size_t physicalPayloadWords{0};

if (stm_frag.isRaw()) {
const auto stmDataWords = stm_frag.dataWords();

const auto stmPayloadBegin = stm_frag.payloadBegin();
const auto physicalWords = inner_frag->dataSizeBytes() / sizeof(int16_t);
physicalPayloadWords = physicalWords > stm::RawHeader::WORDS ? physicalWords - stm::RawHeader::WORDS : 0;

std::cout << "\n=== Raw Payload Dump ===\n"
<< "Frag # : " << frag_counter << "\n"
<< ", inner # : " << i << "\n"
<< ", PhysicalWords : " << physicalWords << "\n"
<< ", stmDataWords : " << stmDataWords << "\n"
<< ", rawLength from Header : " << stm_frag.rawLength() << std::endl;
for (auto ii = stmPayloadBegin ; ii != stmPayloadBegin + physicalPayloadWords ; ++ii){
std::cout << "Raw payload[" << ii - stmPayloadBegin << "] = " << *ii << "\n";
}

}
else if (stm_frag.isZS()){
const auto stmDataWords = stm_frag.dataWords();
const auto physicalWords = inner_frag->dataSizeBytes() / sizeof(int16_t);

auto dataPtr = stm_frag.dataBegin();
auto dataWords = stm_frag.dataWords();

// Limit what you read here
size_t const wordsToRead = std::min<size_t>(dataWords, physicalWords);
auto dataEnd = dataPtr + wordsToRead;

std::cout << "\n=== ZS Payload Dump ===\n"
<< "Frag # : " << frag_counter << "\n"
<< ", inner # : " << i << "\n"
<< ", PhysicalWords : " << physicalWords << "\n"
<< ", stmDataWords : " << stmDataWords << "\n";
size_t seg = 0;

while (dataEnd - dataPtr >= 2){
uint16_t current_zs_location = static_cast<uint16_t>(dataPtr[0]);
uint16_t current_zs_size = static_cast<uint16_t>(dataPtr[1]);
std::cout << "Currnent ZS Index : " << current_zs_location
<< ", current ZS Length : " << current_zs_size << "\n" ;
auto adc = dataPtr + 2;
if (current_zs_size > static_cast<size_t>(dataEnd - adc)){
std::cout << "Malformed or truncated ZS Region: Declared size extends beyond fragment data " << "\n";
break;
}
for (size_t j = 0; j < current_zs_size; ++j) {
std::cout << "ZS Payload[" << j << "] = " << adc[j] << ", region = " << seg << "\n";
}

std::cout << "Region = " << seg
<< " , zs_index = " << current_zs_location
<< " , zs_size = " << current_zs_size << "\n" ;

// Update Variables
++seg;
dataPtr = adc + current_zs_size;
} // end of while loop
}

else if (stm_frag.isPH()){
size_t digiWords = stm_frag.payloadWords();
auto const* digiPtr = stm_frag.payloadBegin();
std::cout << "\n=== PH Payload Dump ===\n" << "\n";
if (digiWords %2 !=0) {
std::cout << "Found a malformed PH frag " << "\n";
}

for (size_t i_PH = 0; i_PH + 1 < digiWords ; i_PH +=2){
uint32_t time = static_cast<uint16_t>(digiPtr[i_PH]);
int16_t PH = digiPtr[i_PH + 1];

std::cout << "PH PayloadTime[" << i_PH << "] = " << time << "\n"
<< "PH PayloadHit[" << i_PH+1 << "] = " << PH << "\n";
}
}
else {
std::cout << "Unread Inner fragment" << "\n"
<< "Inner frag i : " << i << "\n"
<< "Frag ID : " << inner_frag->fragmentID() << "\n";
}

}// End of container frag loop

}// Payload Block Option------------------------------------------------------

} //container frag loop
}//analyze
// ======================================================================
DEFINE_ART_MODULE(STMPrintFragments)
33 changes: 18 additions & 15 deletions DAQ/test/inspectSTMFile.fcl
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ physics : {
makeSTMDigis : {
module_type : STMDigisFromFragments
stmTag : "daq:ContainerSTM"
verbosityLevel : 2
verbosityLevel : 1
saveSTMFragSummary : true
saveRawWithHeaderWaveform_HPGe: false
saveRawWaveform_HPGe: true
saveZSWaveform_HPGe: true
saveRawWithHeaderWaveform_LaBr: false
saveRawWaveform_LaBr: true
saveZSWaveform_LaBr: true
}
saveRawWaveformsWithHeaderHPGe: false
saveRawWaveformsHPGe: true
saveZSWaveformsHPGe: true
saveRawWaveformsWithHeaderLaBr: false
saveRawWaveformsLaBr: true
saveZSWaveformsLaBr: true
}

makeSTMBinary : {
module_type : STMBinaryDigisFromFragments
makeSTMBinary : {
module_type : STMBinaryDigisFromFragments
stmTag : "daq:ContainerSTM"
verbosityLevel : 1
rawFile : "raw.bin"
zsFile : "zs.bin"
phFile : "ph.bin"
rawHeaderFile : "rawWithHeader.bin"
eventFile : "event.bin"
rawFile : "raw.bin"
zsFile : "zs.bin"
phFile : "ph.bin"
rawHeaderFile : "rawWithHeader.bin"
eventFile : "event.bin"
}
}

Expand All @@ -47,6 +47,9 @@ physics : {
stmPrint : {
module_type : STMPrintFragments
stmTag : "daq:ContainerSTM"
printEverything : false
printInnerFrags : false
printPayloads : false
}

}
Expand Down
35 changes: 35 additions & 0 deletions RecoDataProducts/inc/STMEventHeader.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef RecoDataProducts_STMEventHeader_hh_
#define RecoDataProducts_STMEventHeader_hh_

#include "artdaq-core-mu2e/Data/Mu2eEventHeader.hh"

namespace mu2e
{
class STMEventHeader
{
public:
explicit STMEventHeader() {}
STMEventHeader(uint64_t ewt, uint8_t mode, uint64_t adcClock, uint64_t dtcClock) :
_mu2eEventHeader(ewt, mode), _adcClock(adcClock), _dtcClock(dtcClock) { }

uint64_t eventWindowTag() const { return _mu2eEventHeader.EventWindowTag; }
uint8_t eventMode() const { return _mu2eEventHeader.EventMode; }

uint64_t adcClock() const { return _adcClock; }
uint64_t dtcClock() const { return _dtcClock; }

// other represents comparison, seperate by EWT
bool operator<(STMEventHeader const& other) const {
return eventWindowTag() < other.eventWindowTag();
}

private:
Mu2eEventHeader _mu2eEventHeader;
uint64_t _adcClock;
uint64_t _dtcClock;
};
typedef std::vector<STMEventHeader> STMEventHeaderCollection;
} // namespace mu2e


#endif
Loading