From 1c2323cb58af46b1337b509955208633f1b9b354 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Mon, 29 Jun 2026 15:11:32 -0500 Subject: [PATCH 01/21] Added Container Frag ID for exception --- DAQ/src/STMDigisFromFragments_module.cc | 11 ++++++++--- DAQ/test/inspectSTMFile.fcl | 8 ++++---- STMReco/src/PlotSTMPHSpectrum_module.cc | 9 +++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 9f23c10160..b94ce7bbda 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -557,14 +557,18 @@ void STMDigisFromFragments::produce(Event& event) } //Throw out if ZSLengthfromRaw != totalLen, throw out if length mismatch - if (readZSinfoFromRawHeader){ + if (readZSinfoFromRawHeader && stm_frag.zsPrescaled() == 0){ if (expectedZSLength != totalLen){ throw cet::exception("STM_UNPACKING") << "\n=== ZS Length count mismatch ===\n" << "ZS length from Raw header : " << expectedZSLength << "\n" << "ZS length calculated from file : " << totalLen << "\n" << "Found at inner frag i : " << i << "\n" - << "Encountered at event : " << _totalEvents << "\n" ; + << std::boolalpha //enables text output for booleans below + << "Found at HPGe container : " << stm_frag.isHPGe() << "\n" + << "Found at LaBr container : " << stm_frag.isLaBr() << "\n" + << "Encountered at event : " << _totalEvents << "\n"; + }//Also throw out if regions for ZS pulse do not match if ( expectedZSRegions != seg){ throw cet::exception("STM_UNPACKING") @@ -572,7 +576,8 @@ void STMDigisFromFragments::produce(Event& event) << "ZS Region count from Raw header : " << expectedZSRegions << "\n" << "ZS Regionc count calculated from file : " << seg << "\n" << "Found at inner frag i : " << i << "\n" - << "Encountered at event : " << _totalEvents << "\n" ; + << "Encountered at event : " << _totalEvents << "\n"; + } } diff --git a/DAQ/test/inspectSTMFile.fcl b/DAQ/test/inspectSTMFile.fcl index dffab29f63..a6cc09075b 100644 --- a/DAQ/test/inspectSTMFile.fcl +++ b/DAQ/test/inspectSTMFile.fcl @@ -19,7 +19,7 @@ physics : { makeSTMDigis : { module_type : STMDigisFromFragments stmTag : "daq:ContainerSTM" - verbosityLevel : 2 + verbosityLevel : 1 saveSTMFragSummary : true saveRawWithHeaderWaveform_HPGe: false saveRawWaveform_HPGe: true @@ -52,12 +52,12 @@ physics : { } t1 : [ makeSTMDigis ] - e1 : [ stmOutput ] + #e1 : [ stmOutput ] #e1 : [ ] #e1 : [ frag, stmOutput ] trigger_paths : [t1] - end_paths : [e1] + #end_paths : [e1] } @@ -68,7 +68,7 @@ services.TimeTracker.printSummary: true outputs : { stmOutput : { module_type : RootOutput - fileName : "dig.stm.art" + fileName : "dig.stm.art" outputCommands : [ "keep *_*_*_*", "drop artdaq::*_*_*_*" ] } } diff --git a/STMReco/src/PlotSTMPHSpectrum_module.cc b/STMReco/src/PlotSTMPHSpectrum_module.cc index 4995dc4aef..f53ab20340 100644 --- a/STMReco/src/PlotSTMPHSpectrum_module.cc +++ b/STMReco/src/PlotSTMPHSpectrum_module.cc @@ -59,18 +59,19 @@ namespace mu2e { void PlotSTMPHSpectrum::beginJob() { art::ServiceHandle tfs; // create histograms - _phSpectrum=tfs->make("phSpectrum", "PH Spectrum", 1000, 0, 1e4); + _phSpectrum=tfs->make("phSpectrum", "PH Spectrum", 600, -300, 300); _twoDhist=tfs->make("twoDhist","Pulse Height vs events;Event Bins; Pulse Height", - 1000,0,1000, // X-axis scale - 1000,0,1e5); // Y-axis scale + 1000,-1000,1000, // X-axis scale + 1000,0,1e5); // Y-axis scale } void PlotSTMPHSpectrum::analyze(const art::Event& event) { auto phDigisHandle = event.getValidHandle(_stmPHDigisToken); + const auto& phDigis = *phDigisHandle; int binBlock = eventCount/100; - for (const auto& phDigi : *phDigisHandle) { + for (const auto& phDigi : phDigis) { auto energy = phDigi.energy(); _phSpectrum->Fill(energy); _twoDhist->Fill(binBlock, energy); From 089bd01d5327f6f5737d65fe5bb4855332bd7ff6 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Tue, 4 Aug 2026 15:10:30 -0500 Subject: [PATCH 02/21] Structural Changes to STM Unpacking module with added comments for clairty. Changed STMFragmentSummary to include optional tools for debugging. --- DAQ/src/STMDigisFromFragments_module.cc | 1869 ++++++++++++-------- DAQ/src/STMPrintFragments_module.cc | 214 ++- DAQ/test/inspectSTMFile.fcl | 19 +- RecoDataProducts/inc/STMFragmentSummary.hh | 43 +- 4 files changed, 1359 insertions(+), 786 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 9f23c10160..380d2a8831 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -1,4 +1,4 @@ -// ===================================================================== +// ==================================================================== // // STMDigisFromFragments: create all types of STMDigis from STMFragments // @@ -28,793 +28,1156 @@ #include #include +// This is version 2 +// Meant to clean up and make the code more maintainable and readable + namespace art { - class STMDigisFromFragments; + class STMDigisFromFragments; } - using art::STMDigisFromFragments; class art::STMDigisFromFragments : public EDProducer { public: - struct Config { - fhicl::Atom stmTag {fhicl::Name("stmTag"), fhicl::Comment("Input module")}; - fhicl::OptionalAtom verbosityLevel{fhicl::Name("verbosityLevel"), fhicl::Comment("Verbosity level")}; - fhicl::Atom saveSTMFragSummary{fhicl::Name("saveSTMFragSummary"),false}; - - fhicl::Atom saveRawWithHeaderWaveform_HPGe {fhicl::Name("saveRawWithHeaderWaveform_HPGe"), false}; - fhicl::Atom saveRawWaveform_HPGe {fhicl::Name("saveRawWaveform_HPGe"), false}; - fhicl::Atom saveZSWaveform_HPGe{fhicl::Name("saveZSWaveform_HPGe"), false}; - - fhicl::Atom saveRawWithHeaderWaveform_LaBr{fhicl::Name("saveRawWithHeaderWaveform_LaBr"), false}; - fhicl::Atom saveRawWaveform_LaBr{fhicl::Name("saveRawWaveform_LaBr"), false}; - fhicl::Atom saveZSWaveform_LaBr{fhicl::Name("saveZSWaveform_LaBr"), false}; - - }; - - explicit STMDigisFromFragments(const art::EDProducer::Table& config); // constructor created, config via fcl - virtual void produce(Event &) override; - void endJob() override; + struct Config { + //General Configs + fhicl::Atom stmTag {fhicl::Name("stmTag"), fhicl::Comment("Input module")}; + fhicl::OptionalAtom verbosityLevel {fhicl::Name("verbosityLevel"), + fhicl::Comment("Verbosity Level for debugging purposes")}; + fhicl::Atom saveSTMFragSummary{fhicl::Name("saveSTMFragSummary"), + fhicl::Comment("Whether to save Fragment Summary"), false}; + + //HPGe Configs + fhicl::Atom saveRawWaveformsWithHeaderHPGe {fhicl::Name("saveRawWaveformsWithHeaderHPGe"), + fhicl::Comment("Whether to save raw fragment waveforms with header for HPGe for debugging purposes"), false}; + fhicl::Atom saveRawWaveformsHPGe {fhicl::Name("saveRawWaveformsHPGe"), + fhicl::Comment("Whether to save raw waveforms for HPGe for debugging purposes"), false}; + fhicl::Atom saveZSWaveformsHPGe {fhicl::Name("saveZSWaveformsHPGe"), + fhicl::Comment("Whether to save zero-suppressed waveforms for HPGe for debugging purposes"), false}; + + //LaBr Configs + fhicl::Atom saveRawWaveformsWithHeaderLaBr {fhicl::Name("saveRawWaveformsWithHeaderLaBr"), + fhicl::Comment("Whether to save raw fragment waveforms with header for LaBr for debugging purposes"), false}; + fhicl::Atom saveRawWaveformsLaBr {fhicl::Name("saveRawWaveformsLaBr"), + fhicl::Comment("Whether to save raw waveforms for LaBr for debugging purposes"), false}; + fhicl::Atom saveZSWaveformsLaBr {fhicl::Name("saveZSWaveformsLaBr"), + fhicl::Comment("Whether to save zero-suppressed waveforms for LaBr for debugging purposes"), false}; + }; + + explicit STMDigisFromFragments (const art::EDProducer::Table& config); + virtual void produce(Event &) override; + void endJob() override; private: - art::InputTag _stmFragmentsTag; - - //Metrics - size_t _totalEvents{0}; - size_t _totalFragments{0}; - size_t _totalContainers{0}; - size_t _totalContainersHPGe{0}; - size_t _totalContainersLaBr{0}; - size_t _totalInner{0}; - size_t _totalRaw{0}; - size_t _totalZS{0}; - size_t _totalPH{0}; - size_t _totalZeroRaw{0}; - size_t _totalZeroZS{0}; - size_t _totalZeroPH{0}; - size_t _totalEmptyRaw{0}; - size_t _totalEmptyZS{0}; - size_t _totalEmptyPH{0}; - size_t _unreadInnerFrags{0}; - size_t _totalEventsWithHPGeLaBr{0}; - size_t _totalEventsWithOnlyHPGe{0}; - size_t _totalEventsWithOnlyLaBr{0}; - size_t _totalEventsWithNone{0}; - size_t _totalNonContainerFrags{0}; - - //Additional metrics - //HPGe - size_t _totalRawHPGe{0}; - size_t _totalZSHPGe{0}; - size_t _totalPHHPGe{0}; - size_t _totalGoodRawHPGe{0}; - size_t _totalGoodZSHPGe{0}; - size_t _totalGoodPHHPGe{0}; - size_t _totalZeroRawHPGe{0}; - size_t _totalZeroZSHPGe{0}; - size_t _totalZeroPHHPGe{0}; - size_t _totalEmptyRawHPGe{0}; - size_t _totalEmptyZSHPGe{0}; - size_t _totalEmptyPHHPGe{0}; - - //LaBr - size_t _totalRawLaBr{0}; - size_t _totalZSLaBr{0}; - size_t _totalPHLaBr{0}; - size_t _totalGoodRawLaBr{0}; - size_t _totalGoodZSLaBr{0}; - size_t _totalGoodPHLaBr{0}; - size_t _totalZeroRawLaBr{0}; - size_t _totalZeroZSLaBr{0}; - size_t _totalZeroPHLaBr{0}; - size_t _totalEmptyRawLaBr{0}; - size_t _totalEmptyZSLaBr{0}; - size_t _totalEmptyPHLaBr{0}; - - //fhicl varibales - bool _saveRawWithHeaderWaveform_HPGe{false}; - bool _saveRawWaveform_HPGe{false}; - bool _saveZSWaveform_HPGe{false}; - bool _saveRawWithHeaderWaveform_LaBr{false}; - bool _saveRawWaveform_LaBr{false}; - bool _saveZSWaveform_LaBr{false}; - bool _saveSTMFragSummary{false}; - int _verbosityLevel{0}; + // art input tags + art::InputTag _stmFragmentsTag; + + // Fhicl parameters + int _verbosityLevel{0}; + bool _saveSTMFragSummary{false}; + // HPGe fhicl parameters + bool _saveRawWaveformsWithHeaderHPGe{false}; + bool _saveRawWaveformsHPGe{false}; + bool _saveZSWaveformsHPGe{false}; + // LaBr fhicl parameters + bool _saveRawWaveformsWithHeaderLaBr{false}; + bool _saveRawWaveformsLaBr{false}; + bool _saveZSWaveformsLaBr{false}; + + // General Fragment variables + size_t _totalEvents{0}; + size_t _totalNonContainers{0}; + size_t _totalFragments{0}; + size_t _totalContainers{0}; + size_t _totalInnerFrags{0}; + size_t _totalUnreadInnerFrags{0}; + size_t _totalRawFragsSeen{0}; + size_t _totalZSFragsSeen{0}; + size_t _totalPHFragsSeen{0}; + size_t _totalGoodRawFrags{0}; + size_t _totalGoodZSFrags{0}; + size_t _totalGoodPHFrags{0}; + size_t _totalZeroRawFrags{0}; + size_t _totalZeroZSFrags{0}; + size_t _totalZeroPHFrags{0}; + size_t _totalEmptyRawFrags{0}; + size_t _totalEmptyZSFrags{0}; + size_t _totalEmptyPHFrags{0}; + + // Header-related variables + size_t _totalRawFragsPrescaled{0}; + size_t _totalZSFragsPrescaled{0}; + size_t _totalRawFragsFlaggedBadOnly{0}; + size_t _totalRawFragsFlaggedMissingOnly{0}; + size_t _totalRawFragsFlaggedBadAndMissing{0}; + size_t _totalRawFragsWithInvalidHeader{0}; + + // Detector Summary variables + size_t _totalEventsWithBothDetectors{0}; + size_t _totalEventsWithOnlyHPGe{0}; + size_t _totalEventsWithOnlyLaBr{0}; + size_t _totalEventsWithNeitherDetector{0}; // Should sum to total art events + + // HPGe job-level variables + size_t _totalContainersHPGe{0}; + size_t _totalInnerFragsHPGe{0}; + size_t _totalRawFragsSeenHPGe{0}; + size_t _totalZSFragsSeenHPGe{0}; + size_t _totalPHFragsSeenHPGe{0}; + size_t _totalGoodRawFragsHPGe{0};//Good means fragment has data + size_t _totalGoodZSFragsHPGe{0}; + size_t _totalGoodPHFragsHPGe{0}; + size_t _totalZeroRawFragsHPGe{0};// Zero means fragment has data but all values are zero + size_t _totalZeroZSFragsHPGe{0}; + size_t _totalZeroPHFragsHPGe{0}; + size_t _totalEmptyRawFragsHPGe{0};// Empty means fragment has no data + size_t _totalEmptyZSFragsHPGe{0}; + size_t _totalEmptyPHFragsHPGe{0}; + size_t _totalRawFragsFlaggedBadOnlyHPGe{0}; + size_t _totalRawFragsFlaggedMissingOnlyHPGe{0}; + size_t _totalRawFragsFlaggedBadAndMissingHPGe{0}; + size_t _totalRawFragsWithInvalidHeaderHPGe{0}; + size_t _totalZSFragsSkippedDueToRawFlagHPGe{0};// We want to skip ZS if raw is flagged bad/missing + size_t _totalPHFragsSkippedDueToRawFlagHPGe{0};// We want to skip PH if raw is flagged bad/missing + size_t _totalRawFragsPrescaledHPGe{0};// track how many raw fragments were prescaled + size_t _totalZSFragsPrescaledHPGe{0};// track how many zs fragments were prescaled + + // LaBr job-level variables + size_t _totalContainersLaBr{0}; + size_t _totalInnerFragsLaBr{0}; + size_t _totalRawFragsSeenLaBr{0}; + size_t _totalZSFragsSeenLaBr{0}; + size_t _totalPHFragsSeenLaBr{0}; + size_t _totalGoodRawFragsLaBr{0};//Good means fragment has data + size_t _totalGoodZSFragsLaBr{0}; + size_t _totalGoodPHFragsLaBr{0}; + size_t _totalZeroRawFragsLaBr{0};// Zero means fragment has data but all values are zero + size_t _totalZeroZSFragsLaBr{0}; + size_t _totalZeroPHFragsLaBr{0}; + size_t _totalEmptyRawFragsLaBr{0};// Empty means fragment has no data + size_t _totalEmptyZSFragsLaBr{0}; + size_t _totalEmptyPHFragsLaBr{0}; + size_t _totalRawFragsFlaggedBadOnlyLaBr{0}; + size_t _totalRawFragsFlaggedMissingOnlyLaBr{0}; + size_t _totalRawFragsFlaggedBadAndMissingLaBr{0}; + size_t _totalRawFragsWithInvalidHeaderLaBr{0}; + size_t _totalZSFragsSkippedDueToRawFlagLaBr{0};// We want to skip ZS if raw is flagged bad/missing + size_t _totalPHFragsSkippedDueToRawFlagLaBr{0};// We want to skip PH if raw is flagged bad/missing + size_t _totalRawFragsPrescaledLaBr{0};// track how many raw fragments were prescaled + size_t _totalZSFragsPrescaledLaBr{0};// track how many ZS fragments were prescaled + + // Used to set and verify the state of the raw parent fragment for zs fragments, event based + struct RawParentState { + art::Ptr ptr; + art::ProductID productID; + size_t index{0}; + bool available{false}; + }; + + // Used to save ZS information + struct ZSRegion{ + uint32_t offset; + std::vector adcs; + }; + + // Used to track the expected raw header information, event based + struct RawHeaderState { + uint16_t expectedZSLength{0}; + uint16_t expectedZSRegions{0}; + uint16_t expectedPHCount{0}; + + bool containsZSInfo{false}; + bool containsPHInfo{false}; + + bool rawPrescaled{false}; + bool zsPrescaled{false}; + + uint16_t rawPrescaleValue{0}; + uint16_t zsPrescaleValue{0}; + + bool rawHeaderIsValid{false}; + bool skipCurrentSet{false}; + }; + + struct FragmentCounters { + size_t seen{0}; + size_t prescaled{0}; + size_t unread{0}; + size_t empty{0}; + size_t zero{0}; + size_t good{0}; + }; + + struct DetectorSpecificEventMetrics { + FragmentCounters raw; + FragmentCounters zs; + FragmentCounters ph; + + size_t rawFragsFlaggedBadOnly{0}; + size_t rawFragsFlaggedMissingOnly{0}; + size_t rawFragsFlaggedBadAndMissing{0}; + size_t rawFragsWithInvalidHeader{0}; + + size_t zsFragsSkippedDueToRawFlag{0}; + size_t phFragsSkippedDueToRawFlag{0}; + size_t setsSkippedDueToRawFlag{0}; + size_t setsSkippedDueToInvalidHeader{0}; + + size_t unknownFrags{0}; + }; }; // STMDigisFromFragments -// ====================================================================== - - +// Configuration section +// ===================== STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table& config) - : art::EDProducer{config} - ,_stmFragmentsTag(config().stmTag()) - ,_saveRawWithHeaderWaveform_HPGe(config().saveRawWithHeaderWaveform_HPGe()) - ,_saveRawWaveform_HPGe(config().saveRawWaveform_HPGe()) - ,_saveZSWaveform_HPGe(config().saveZSWaveform_HPGe()) - ,_saveRawWithHeaderWaveform_LaBr(config().saveRawWithHeaderWaveform_LaBr()) - ,_saveRawWaveform_LaBr(config().saveRawWaveform_LaBr()) - ,_saveZSWaveform_LaBr(config().saveZSWaveform_LaBr()) - ,_saveSTMFragSummary(config().saveSTMFragSummary()) - ,_verbosityLevel(config().verbosityLevel() ? *(config().verbosityLevel()) : 0) - + :art::EDProducer{config} + ,_stmFragmentsTag(config().stmTag()) + ,_verbosityLevel(config().verbosityLevel() ? *(config().verbosityLevel()) : 0) + ,_saveSTMFragSummary(config().saveSTMFragSummary()) + ,_saveRawWaveformsWithHeaderHPGe(config().saveRawWaveformsWithHeaderHPGe()) + ,_saveRawWaveformsHPGe(config().saveRawWaveformsHPGe()) + ,_saveZSWaveformsHPGe(config().saveZSWaveformsHPGe()) + ,_saveRawWaveformsWithHeaderLaBr(config().saveRawWaveformsWithHeaderLaBr()) + ,_saveRawWaveformsLaBr(config().saveRawWaveformsLaBr()) + ,_saveZSWaveformsLaBr(config().saveZSWaveformsLaBr()) + // By default we save PH Digis { - if (_saveSTMFragSummary) { - produces("stmFragSummaryHPGe"); - produces("stmFragSummaryLaBr"); - } - // Set the size of vectors for HPGe - if (_saveRawWithHeaderWaveform_HPGe){produces("rawWithHeaderHPGe");} - if (_saveRawWaveform_HPGe){produces("rawHPGe");}//Waveforms - if (_saveZSWaveform_HPGe){produces("zsHPGe");} - produces("phHPGe"); // digi series - - - //Set the size of vectors for LaBr - if (_saveRawWithHeaderWaveform_LaBr){produces("rawWithHeaderLaBr");} - if (_saveRawWaveform_LaBr){produces("rawLaBr");} - if (_saveZSWaveform_LaBr){produces("zsLaBr");} - produces("phLaBr"); // digi series - + // Products depending on configuration switches + if (_saveSTMFragSummary){ + produces("stmFragSummaryHPGe"); + produces("stmFragSummaryLaBr"); + } + // HPGe + if (_saveRawWaveformsWithHeaderHPGe){ produces("rawWithHeaderHPGe"); } + if (_saveRawWaveformsHPGe){ produces("rawHPGe"); } + if (_saveZSWaveformsHPGe){ produces("zsHPGe"); } + produces("phHPGe"); + // LaBr + if (_saveRawWaveformsWithHeaderLaBr){ produces("rawWithHeaderLaBr"); } + if (_saveRawWaveformsLaBr){ produces("rawLaBr"); } + if (_saveZSWaveformsLaBr){ produces("zsLaBr"); } + produces("phLaBr"); } -// ---------------------------------------------------------------------- - +// Start of Event processing +// ========================= void STMDigisFromFragments::produce(Event& event) { + // Frag counters for this event + size_t ContainerFragsThisEvent{0}; + size_t InnerFragsThisEvent{0}; + size_t badHPGeFragsThisEvent{0}; + size_t missingHPGeFragsThisEvent{0}; + size_t badLaBrFragsThisEvent{0}; + size_t missingLaBrFragsThisEvent{0}; + + ++_totalEvents; // Increments total event counter + + // Each RawParentState keeps track of the last Raw Fragment + RawParentState rawParentHPGe; + RawParentState rawParentLaBr; + RawHeaderState rawHeaderHPGe; + RawHeaderState rawHeaderLaBr; + DetectorSpecificEventMetrics LaBrEventMetrics; + DetectorSpecificEventMetrics HPGeEventMetrics; + + // Set product ID + if (_saveRawWaveformsHPGe){ + rawParentHPGe.productID = event.getProductID("rawHPGe"); + } + if (_saveRawWaveformsLaBr){ + rawParentLaBr.productID = event.getProductID("rawLaBr"); + } - art::Ptr lastRawHPGePtr; - art::Ptr lastRawLaBrPtr; - - bool haveLastRawHPGePtr{false}; - bool haveLastRawLaBrPtr{false}; - - std::vector zsToRawIndexHPGe; // creates vector - std::vector zsToRawIndexLaBr; - ++_totalEvents; //Increment Total Event Counter - - //Frag Summaries - std::unique_ptr stmFragSummaryHPGe(new mu2e::STMFragmentSummaryCollection); - std::unique_ptr stmFragSummaryLaBr(new mu2e::STMFragmentSummaryCollection); - //HPGe - std::unique_ptr raw_HPGe_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr zs_HPGe_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr ph_HPGe_digis(new mu2e::STMPHDigiCollection); - std::unique_ptr raw_HPGe_header_waveform_digis(new mu2e::STMWaveformDigiCollection); - - //LaBr - std::unique_ptr raw_LaBr_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr zs_LaBr_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr ph_LaBr_digis(new mu2e::STMPHDigiCollection); - std::unique_ptr raw_LaBr_header_waveform_digis(new mu2e::STMWaveformDigiCollection); - - art::Handle STMFragmentsH; - event.getByLabel(_stmFragmentsTag, STMFragmentsH); - const auto& STMFragments = STMFragmentsH.product(); - - auto rawHPGeProductID = event.getProductID("rawHPGe"); - auto rawLaBrProductID = event.getProductID("rawLaBr"); - - //Event Metrics - - //HPGe - size_t totalRawHPGeFrags{0}; - size_t totalZSHPGeFrags{0}; - size_t totalPHHPGeFrags{0}; - size_t goodRawHPGeFrags{0}; - size_t goodZSHPGeFrags{0}; - size_t goodPHHPGeFrags{0}; - size_t zeroRawHPGeFrags{0}; - size_t zeroZSHPGeFrags{0}; - size_t zeroPHHPGeFrags{0}; - size_t emptyRawHPGeFrags{0}; - size_t emptyZSHPGeFrags{0}; - size_t emptyPHHPGeFrags{0}; - - //LaBr - size_t totalRawLaBrFrags{0}; - size_t totalZSLaBrFrags{0}; - size_t totalPHLaBrFrags{0}; - size_t goodRawLaBrFrags{0}; - size_t goodZSLaBrFrags{0}; - size_t goodPHLaBrFrags{0}; - size_t zeroRawLaBrFrags{0}; - size_t zeroZSLaBrFrags{0}; - size_t zeroPHLaBrFrags{0}; - size_t emptyRawLaBrFrags{0}; - size_t emptyZSLaBrFrags{0}; - size_t emptyPHLaBrFrags{0}; - - //Additional - size_t unread_InnerFrags{0}; - uint16_t outerFragID{0}; - bool eventHasHPGe{false}; - bool eventHasLaBr{false}; - - //HPGe - uint16_t expectedZSLengthHPGe{0}; - uint16_t expectedZSRegionsHPGe{0}; - bool readZSinfoFromRawHeaderHPGe{false}; - - //LaBr - uint16_t expectedZSLengthLaBr{0}; - uint16_t expectedZSRegionsLaBr{0}; - bool readZSinfoFromRawHeaderLaBr{false}; - - //Frag counters - size_t nContainerFragsThisEvent{0}; - size_t nInnerFragsThisEvent{0}; - - //loop over outer frags - for (const auto& frag : *STMFragments) { - ++_totalFragments; //Increment Total Frag counter - - outerFragID = frag.fragmentID(); - if (_verbosityLevel >= 3){std::cout << "\nFrag_id : " << outerFragID << "\n";} - - - //Check if this is a container fragment - if (frag.type() == artdaq::Fragment::ContainerFragmentType){ - - mu2e::STMFragment container_frag(frag); - if ( container_frag.isHPGeContainer()){ ++_totalContainersHPGe; eventHasHPGe = true; } - else if ( container_frag.isLaBrContainer() ) { ++_totalContainersLaBr; eventHasLaBr = true; } - else { - if (_verbosityLevel >= 1){ - std::cout << "Encounter an unknown STM Container frag ID\n" - << "Frag ID : " << frag.fragmentID() <<"\n" - << "Event : " << _totalEvents <<"\n"; - } - continue; - } - artdaq::ContainerFragment cont_frag(frag); - ++_totalContainers; - ++nContainerFragsThisEvent; - size_t blocks = cont_frag.block_count(); - _totalInner += blocks; - nInnerFragsThisEvent += blocks; - - //loop over container where i corresponds to inner frag - for (size_t i = 0; i < cont_frag.block_count(); ++i){ - - auto inner_frag = cont_frag.at(i); - mu2e::STMFragment stm_frag(*inner_frag); - mu2e::STMWaveformDigi stm_waveform; - - if ( stm_frag.isRaw() ) { - - if (stm_frag.isHPGe()){ - readZSinfoFromRawHeaderHPGe = false; - expectedZSLengthHPGe = 0; - expectedZSRegionsHPGe = 0; - } else if (stm_frag.isLaBr()){ - readZSinfoFromRawHeaderLaBr = false; - expectedZSLengthLaBr = 0; - expectedZSRegionsLaBr = 0; - } - //Job Counter - ++_totalRaw; - - //Conditional Job and Event Counter - if( stm_frag.isHPGe() ){ - ++_totalRawHPGe ; - ++totalRawHPGeFrags; - - } else if ( stm_frag.isLaBr() ){ - ++_totalRawLaBr ; - ++totalRawLaBrFrags; - } - - auto payloadPtr = stm_frag.payloadBegin(); - auto payloadWords = stm_frag.payloadWords(); - bool allZeros = true;//Assume raw frag is zero filled - - //Checks for empty frag - if (payloadWords == 0) { - if(_verbosityLevel >=3){std::cout<< "\nFound an empty frag, i = " << i <<" @Raw\n";} - ++_totalEmptyRaw;//Job counter - //Eventcounter - if( stm_frag.isHPGe() ){ - ++_totalEmptyRawHPGe; ++emptyRawHPGeFrags; } - else if (stm_frag.isLaBr()){ - ++_totalEmptyRawLaBr; ++emptyRawLaBrFrags; } - continue;//stops this loop check and goes to next frag - } - - //Check if any data points are not zero - for (size_t k =0; k < payloadWords; ++k){ - if (payloadPtr[k] != 0){ - allZeros = false; - break; - } - } - - //Check if zero filled - if (allZeros){ - if (_verbosityLevel >=3){std::cout << "\nFound a zero filled frag, i = " << i << " @Raw\n";} - ++_totalZeroRaw;//Increment counters - //Eventcounter - if( stm_frag.isHPGe() ){ - ++_totalZeroRawHPGe; ++zeroRawHPGeFrags; } - else if ( stm_frag.isLaBr() ){ - ++_totalZeroRawLaBr; ++zeroRawLaBrFrags; } - continue; - } - - //Print first 20 values - if (_verbosityLevel >=3){std::cout << "\nFound a good frag, i = " << i <<" @Raw\n";} - - if (_verbosityLevel >= 4){ - std::cout << "\nFirst 20 adcs: "; - for (size_t kk = 0; kk < std::min(payloadWords,20); ++kk){ - std::cout << payloadPtr[kk] << " ,"; - } - if(_verbosityLevel >=5){ - std::cout << "\nRaw header : Raw Length = " << stm_frag.rawLength() - <<" , ZS Length = " << stm_frag.zsLength() - << " , ZS Regions = " << stm_frag.zsRegions() - << " , i = " << i << " @Raw\n"; - } - } - - //Ideally only good frags get up to here - if ( stm_frag.isHPGe() ){ - expectedZSRegionsHPGe = stm_frag.zsRegions(); - expectedZSLengthHPGe = stm_frag.zsLength(); - readZSinfoFromRawHeaderHPGe = true; - - ++ _totalGoodRawHPGe; - ++ goodRawHPGeFrags; - - if (_saveRawWithHeaderWaveform_HPGe){ - auto dataPtr = stm_frag.dataBegin();//memory check for emplace_back - auto dataWords = stm_frag.dataWords(); - stm_waveform.set_data(dataWords, dataPtr); - raw_HPGe_header_waveform_digis->emplace_back(stm_waveform); - } - if(_saveRawWaveform_HPGe) { - stm_waveform.set_data(payloadWords, payloadPtr); - raw_HPGe_waveform_digis->emplace_back(stm_waveform); - size_t parentRawWfmIdx = raw_HPGe_waveform_digis->size()-1; - - lastRawHPGePtr = art::Ptr(rawHPGeProductID,parentRawWfmIdx, - event.productGetter(rawHPGeProductID)); - haveLastRawHPGePtr = true; - } - - } else if ( stm_frag.isLaBr() ){ - expectedZSRegionsLaBr = stm_frag.zsRegions(); - expectedZSLengthLaBr = stm_frag.zsLength(); - readZSinfoFromRawHeaderLaBr = true; - - ++ _totalGoodRawLaBr; - ++ goodRawLaBrFrags; - - if (_saveRawWithHeaderWaveform_LaBr){ - auto dataPtr = stm_frag.dataBegin(); - auto dataWords = stm_frag.dataWords(); - stm_waveform.set_data(dataWords, dataPtr); - raw_LaBr_header_waveform_digis->emplace_back(stm_waveform); - } - if(_saveRawWaveform_LaBr){ - stm_waveform.set_data(payloadWords, payloadPtr); - raw_LaBr_waveform_digis->emplace_back(stm_waveform); - size_t parentRawWfmIdx = raw_LaBr_waveform_digis->size()-1; - lastRawLaBrPtr = art::Ptr(rawLaBrProductID,parentRawWfmIdx, - event.productGetter(rawLaBrProductID)); - haveLastRawLaBrPtr = true; - - } - - } - - } // End of isRaw Block - - - else if (stm_frag.isZS()){ - ++_totalZS; //Incremenet ZS counter - - if ( stm_frag.isHPGe() ){ - ++_totalZSHPGe; ++totalZSHPGeFrags; } - else if ( stm_frag.isLaBr() ){ ++_totalZSLaBr; ++totalZSLaBrFrags; - } - - auto payloadPtr = stm_frag.payloadBegin(); - auto payloadWords = stm_frag.payloadWords(); - bool allZeros = true; //assumes all adcs are zero - - // Extract variables from Raw Header - bool readZSinfoFromRawHeader = stm_frag.isHPGe() ? readZSinfoFromRawHeaderHPGe : readZSinfoFromRawHeaderLaBr; - uint16_t expectedZSRegions = stm_frag.isHPGe() ? expectedZSRegionsHPGe : expectedZSRegionsLaBr; - uint16_t expectedZSLength = stm_frag.isHPGe() ? expectedZSLengthHPGe : expectedZSLengthLaBr; - - //After copying varibales, reset detector specific variables - if (stm_frag.isHPGe()){ - readZSinfoFromRawHeaderHPGe = false; - expectedZSLengthHPGe = 0; - expectedZSRegionsHPGe = 0; - } else if (stm_frag.isLaBr()){ - readZSinfoFromRawHeaderLaBr = false; - expectedZSLengthLaBr = 0; - expectedZSRegionsLaBr = 0; - } - - //Check if payload is empty - if ( payloadWords == 0) { - if (_verbosityLevel >=3){std::cout << "\nFound an empty frag, i = " << i << " @ZS\n";} - ++_totalEmptyZS; - if ( stm_frag.isHPGe() ){ - ++_totalEmptyZSHPGe; ++emptyZSHPGeFrags; } - else if ( stm_frag.isLaBr() ){ - ++_totalEmptyZSLaBr; ++emptyZSLaBrFrags; } - continue; - } - //Check if any adc are non-zero - for (size_t k = 0 ; k < payloadWords ; ++k){ - if(payloadPtr[k] != 0 ){ - allZeros = false; - break; - } - } - //Check if zero filled - if (allZeros) { - if (_verbosityLevel >=3){std::cout << "\nFound a zero filled frag, i = "<< i << " @ZS\n";} - ++_totalZeroZS; - if ( stm_frag.isHPGe() ){ - ++_totalZeroZSHPGe; ++zeroZSHPGeFrags; } - else if ( stm_frag.isLaBr() ){ - ++_totalZeroZSLaBr; ++zeroZSLaBrFrags; } - continue; - } - //Print first 20 payload adcs - if (_verbosityLevel >=3){std::cout << "\nFound a good frag, i = " << i << " @ZS\n";} - - if (_verbosityLevel >=4){ - std::cout << "\nFirst 20 adcs: "; - for (size_t kk = 0 ; kk < std::min(payloadWords,20) ; ++kk){ - std::cout << payloadPtr[kk] << " , "; - } - std::cout << "i = " << i << " @ZS\n"; - } - - //Defintions for payload references - auto dataPtr = stm_frag.dataBegin(); - auto dataWords = stm_frag.dataWords(); - auto dataEnd = dataPtr + dataWords; - size_t seg = 0; - size_t totalLen = 0; - uint16_t lastZSindex = 0; //keeps track of last recorded index from header -> with respect to what? - uint16_t lastLen = 0; //keeps track of last recoded length from header - - if(_verbosityLevel >= 6){std::cout << "dataWords : " << dataWords - << " dataWords%4 : " << dataWords%4 - <<" @ZS" << "\n"; } - - while (dataPtr + 2 <= dataEnd){ - if ( readZSinfoFromRawHeader && seg >= expectedZSRegions ) break; - uint16_t current_zs_location = static_cast(dataPtr[0]); - uint16_t current_zs_size = static_cast(dataPtr[1]); - auto adc = dataPtr + 2; - if (adc + current_zs_size > dataEnd) - break; - - uint32_t trigTimeOffset = current_zs_location; - - //emplacing - if ( stm_frag.isHPGe() && _saveZSWaveform_HPGe){ - std::vector segADCS(adc, adc + current_zs_size); //1D array, contains adcs to this_zs_size - 1 - mu2e::STMWaveformDigi zsDigi(trigTimeOffset, segADCS); - - if (readZSinfoFromRawHeader && haveLastRawHPGePtr) { - zsDigi.setParent(lastRawHPGePtr); - } - - zs_HPGe_waveform_digis->emplace_back(zsDigi); - if(_verbosityLevel >= 3 && zsDigi.hasParent()){ - std::cout << "ZS HPGe segment has parent Raw index " - << zsDigi.parent().key() - << "with offset " - << zsDigi.trigTimeOffset() - << "\n"; - } - } - else if ( stm_frag.isLaBr() && _saveZSWaveform_LaBr){ - std::vector segADCS(adc, adc + current_zs_size); - mu2e::STMWaveformDigi zsDigi(trigTimeOffset, segADCS); - - if (readZSinfoFromRawHeader && haveLastRawLaBrPtr){ - zsDigi.setParent(lastRawLaBrPtr); - } - - zs_LaBr_waveform_digis->emplace_back(zsDigi); - - } - - if (_verbosityLevel >=6){ - - //A print check per segment - std::cout << "Region = " << seg << " , zs_index = " - << current_zs_location << " , zs_size = " << current_zs_size - << " , trigTimeOffset = " << trigTimeOffset << "\n" ; + // Frag Summaries + std::unique_ptr stmFragSummaryHPGe(new mu2e::STMFragmentSummaryCollection); + std::unique_ptr stmFragSummaryLaBr(new mu2e::STMFragmentSummaryCollection); + + // HPGe + std::unique_ptr rawWaveformDigisWithHeaderHPGe(new mu2e::STMWaveformDigiCollection); + std::unique_ptr rawWaveformDigisHPGe(new mu2e::STMWaveformDigiCollection); + std::unique_ptr zsWaveformDigisHPGe(new mu2e::STMWaveformDigiCollection); + std::unique_ptr phDigisHPGe(new mu2e::STMPHDigiCollection); + + // LaBr waveforms + std::unique_ptr rawWaveformDigisWithHeaderLaBr(new mu2e::STMWaveformDigiCollection); + std::unique_ptr rawWaveformDigisLaBr(new mu2e::STMWaveformDigiCollection); + std::unique_ptr zsWaveformDigisLaBr(new mu2e::STMWaveformDigiCollection); + std::unique_ptr phDigisLaBr(new mu2e::STMPHDigiCollection); + + // booleans for tracking what detectors are present in the event + bool eventHasHPGe{false}; + bool eventHasLaBr{false}; + + // Get STM Fragments from the event, via handle + art::Handle STMFragmentsHandle; + event.getByLabel(_stmFragmentsTag, STMFragmentsHandle); + const auto& STMFragments = STMFragmentsHandle.product(); + uint16_t outerFragID; + + // Loop over outer fragments + for (const auto& frag : *STMFragments) { + ++_totalFragments; + outerFragID = frag.fragmentID(); + if (_verbosityLevel > 2) { std::cout << "Processing outer fragment with ID: " << outerFragID << "\n"; } + + // Check if this is a container fragment + if (frag.type() == artdaq::Fragment::ContainerFragmentType) { + + mu2e::STMFragment container_frag(frag); + artdaq::ContainerFragment cont_frag(frag); + size_t blocks = cont_frag.block_count(); + + if (container_frag.isHPGeContainer()) { + if (_verbosityLevel > 2) { std::cout << "Processing HPGe container fragment with ID: " << outerFragID << "\n"; } + ++_totalContainersHPGe; eventHasHPGe = true; _totalInnerFragsHPGe += blocks; + } else if (container_frag.isLaBrContainer()) { + if (_verbosityLevel > 2) { std::cout << "Processing LaBr container fragment with ID: " << outerFragID << "\n"; } + ++_totalContainersLaBr; eventHasLaBr = true; _totalInnerFragsLaBr += blocks; + } else { + if (_verbosityLevel > 0) { + std::cout << "Encountered an unknown STM Container Fragment \n" + << "Frag ID : " << outerFragID << "\n" + << "Event : " << _totalEvents << "\n"; + } + continue; // Skips the rest of this container frag if it is unknown } - - //Update variables - lastZSindex = current_zs_location; - lastLen = current_zs_size; - totalLen += lastLen; - ++seg; - dataPtr = adc + current_zs_size; - } // end of while loop - - if (_verbosityLevel >=5){ - //Summary - std::cout << "ZS Regions = " << seg - << " , lastZSindex = " << lastZSindex - << " , lastZSLen = " << lastLen - << " , ZS total length = " << totalLen - << " , i = " << i << " @ZS\n"; - } - - //Throw out if ZSLengthfromRaw != totalLen, throw out if length mismatch - if (readZSinfoFromRawHeader){ - if (expectedZSLength != totalLen){ - throw cet::exception("STM_UNPACKING") - << "\n=== ZS Length count mismatch ===\n" - << "ZS length from Raw header : " << expectedZSLength << "\n" - << "ZS length calculated from file : " << totalLen << "\n" - << "Found at inner frag i : " << i << "\n" - << "Encountered at event : " << _totalEvents << "\n" ; - }//Also throw out if regions for ZS pulse do not match - if ( expectedZSRegions != seg){ - throw cet::exception("STM_UNPACKING") - << "\n=== ZS Region count mismatch ===\n" - << "ZS Region count from Raw header : " << expectedZSRegions << "\n" - << "ZS Regionc count calculated from file : " << seg << "\n" - << "Found at inner frag i : " << i << "\n" - << "Encountered at event : " << _totalEvents << "\n" ; + ++ContainerFragsThisEvent; + ++_totalContainers; + _totalInnerFrags += blocks; + InnerFragsThisEvent += blocks; + + // loop over container blocks + for (size_t i = 0 ; i < cont_frag.block_count(); ++i) { + auto inner_frag = cont_frag.at(i); + mu2e::STMFragment stm_frag(*inner_frag); + mu2e::STMWaveformDigi stm_waveform; + + if (stm_frag.isRaw()){ + ++_totalRawFragsSeen; + // Determine which detector this raw fragment is in + bool const isHPGe = stm_frag.isHPGe(); + bool const isLaBr = stm_frag.isLaBr(); + + + if (!isHPGe && !isLaBr) { + if (_verbosityLevel > 1) { + std::cout << "Encountered raw fragment that is neither HPGe nor LaBr\n"; + } + ++_totalUnreadInnerFrags; + continue; + } + + isHPGe ? ++_totalRawFragsSeenHPGe : ++_totalRawFragsSeenLaBr; + + auto& headerState = isHPGe ? rawHeaderHPGe : rawHeaderLaBr; + auto& parentState = isHPGe ? rawParentHPGe : rawParentLaBr; + auto& eventMetrics = isHPGe ? HPGeEventMetrics : LaBrEventMetrics; + + // reset current raw header and parent state bool + headerState = RawHeaderState{}; + parentState.ptr = {}; + parentState.available = false; + ++eventMetrics.raw.seen; + + // check header+adcs is not less than expected header length (22) + if(stm_frag.dataWords() < stm::RawHeader::WORDS){ + if (_verbosityLevel > 1) { + std::cout << "Raw fragment has fewer data words than expected header length\n"; + } + ++_totalUnreadInnerFrags; + ++eventMetrics.setsSkippedDueToInvalidHeader; + headerState.skipCurrentSet = true; + parentState.ptr = {}; + parentState.available = false; + continue; + } + + // Confirm Raw Header has Valid Anchors + // For now just use as a diagnostic tool + if (!stm_frag.hasValidAnchors()) { + ++eventMetrics.rawFragsWithInvalidHeader; + ++_totalRawFragsWithInvalidHeader; + isHPGe ? ++_totalRawFragsWithInvalidHeaderHPGe : ++_totalRawFragsWithInvalidHeaderLaBr; + } + headerState.rawHeaderIsValid = stm_frag.hasValidAnchors(); + + // Check if bad or missing or both + if (stm_frag.badData() && stm_frag.missing()) { + ++eventMetrics.rawFragsFlaggedBadAndMissing; + ++_totalRawFragsFlaggedBadAndMissing; + isHPGe ? ++_totalRawFragsFlaggedBadAndMissingHPGe : ++_totalRawFragsFlaggedBadAndMissingLaBr; + } else if (stm_frag.badData()) { + ++eventMetrics.rawFragsFlaggedBadOnly; + ++_totalRawFragsFlaggedBadOnly; + isHPGe ? ++_totalRawFragsFlaggedBadOnlyHPGe : ++_totalRawFragsFlaggedBadOnlyLaBr; + } else if (stm_frag.missing()) { + ++eventMetrics.rawFragsFlaggedMissingOnly; + ++_totalRawFragsFlaggedMissingOnly; + isHPGe ? ++_totalRawFragsFlaggedMissingOnlyHPGe : ++_totalRawFragsFlaggedMissingOnlyLaBr; + } + + bool const badOrMissing = stm_frag.badData() || stm_frag.missing(); + if (badOrMissing) { + headerState.skipCurrentSet = true; + parentState.ptr = {}; + parentState.available = false; + ++eventMetrics.setsSkippedDueToRawFlag; + continue; + } + + //Check if raw fragment is prescaled to determine whether to skip checks + headerState.rawPrescaled = stm_frag.rawPrescaled(); + headerState.rawPrescaleValue = stm_frag.rawPrescaleValue(); + + if (headerState.rawPrescaled) { + ++eventMetrics.raw.prescaled; + ++_totalRawFragsPrescaled; + isHPGe ? ++_totalRawFragsPrescaledHPGe : ++_totalRawFragsPrescaledLaBr; + } + + // Check if raw frag is empty + auto payloadPtr = stm_frag.payloadBegin(); + auto payloadWords = stm_frag.payloadWords(); + bool allZeros = true; + if (payloadWords == 0) { + if (_verbosityLevel > 2){ + std::cout << "\nFound an empty raw fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--Raw Frag\n"; + } + //increment + ++eventMetrics.raw.empty; + ++_totalEmptyRawFrags; + isHPGe ? ++_totalEmptyRawFragsHPGe : ++_totalEmptyRawFragsLaBr; + continue; + } + // Check if any payload words exist + for (size_t k = 0; k < payloadWords; ++k){ + if (payloadPtr[k] != 0) { + allZeros = false; + break; + } + } + if (allZeros) { + if (_verbosityLevel > 2){ + std::cout << "\nFound an all-zero raw fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--Raw Frag\n"; + } + //counter increment for all-zero raw fragments + ++eventMetrics.raw.zero; + ++_totalZeroRawFrags; + isHPGe? ++_totalZeroRawFragsHPGe: ++_totalZeroRawFragsLaBr; + continue; + } + // At this point the raw fragment has payload words and is no zero filled + // We continue processing this raw fragment + if (_verbosityLevel > 2) { + std::cout << "\nFound a good raw fragment at Event : " << _totalEvents << "\n" + << "Fragment Index : " << i << "\n" + << "--Raw Frag\n"; + } + + //Print first few payload words for inspection + if (_verbosityLevel > 3) { + std::cout << "First few payload words(adcs) for inspection : " ; + for (size_t w = 0; w < std::min(payloadWords, static_cast(10)); ++w){ + std::cout << payloadPtr[w] << " ,"; + } + std::cout << "\n"; + } + //Raw Header inspection + if (_verbosityLevel > 4) { + std::cout << "\nRaw Header for inspection \n" + << "Raw Length : " << stm_frag.rawLength() << "\n" + << "ZS Length : " << stm_frag.zsLength() << "\n" + << "ZS Regions : " << stm_frag.zsRegions() << "\n" + << "Event : " << _totalEvents << "\n" + << "Inner Frag Index : " << i << "\n"; + } + // From here good raw frags end up and get saved + ++eventMetrics.raw.good; + ++_totalGoodRawFrags; + isHPGe ? ++_totalGoodRawFragsHPGe : ++_totalGoodRawFragsLaBr; + + // Extract rest of the raw header information + headerState.containsZSInfo = true; + headerState.containsPHInfo = true; + headerState.zsPrescaled = stm_frag.zsPrescaled(); + headerState.zsPrescaleValue = stm_frag.zsPrescaleValue(); + headerState.expectedZSLength = stm_frag.zsLength(); + headerState.expectedZSRegions = stm_frag.zsRegions(); + headerState.expectedPHCount = stm_frag.phCount(); + + // Save waveforms based on fcl configurations + // Save Raw Waveform With Header Info - HPGe + if (_saveRawWaveformsWithHeaderHPGe && isHPGe && !headerState.rawPrescaled){ + auto dataPtr = stm_frag.dataBegin(); + auto dataWords = stm_frag.dataWords(); + stm_waveform.set_data(dataWords,dataPtr); + rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); + } + // Save Raw Waveform and Save parent Ptr - HPGe + if (_saveRawWaveformsHPGe && isHPGe && !headerState.rawPrescaled){ + stm_waveform.set_data(payloadWords, payloadPtr); + rawWaveformDigisHPGe->emplace_back(stm_waveform); + + //Save raw parent index + parentState.index = rawWaveformDigisHPGe->size() - 1; + parentState.ptr = art::Ptr(parentState.productID, parentState.index, + event.productGetter(parentState.productID)); + parentState.available = true; + } + // Save Raw Waveform With Header Info - LaBr + if (_saveRawWaveformsWithHeaderLaBr && isLaBr && !headerState.rawPrescaled){ + auto dataPtr = stm_frag.dataBegin(); + auto dataWords = stm_frag.dataWords(); + stm_waveform.set_data(dataWords,dataPtr); + rawWaveformDigisWithHeaderLaBr->emplace_back(stm_waveform); + } + // Save Raw Waveform and Save parent Ptr - LaBr + if (_saveRawWaveformsLaBr && isLaBr && !headerState.rawPrescaled){ + stm_waveform.set_data(payloadWords, payloadPtr); + rawWaveformDigisLaBr->emplace_back(stm_waveform); + + //Save raw parent index + parentState.index = rawWaveformDigisLaBr->size() - 1; + parentState.ptr = art::Ptr(parentState.productID, parentState.index, + event.productGetter(parentState.productID)); + parentState.available = true; + } + + }// End of Raw fragment check + else if (stm_frag.isZS()){ + ++_totalZSFragsSeen; + // Determine which detector this ZS fragment belongs to + bool const isHPGe = stm_frag.isHPGe(); + bool const isLaBr = stm_frag.isLaBr(); + + // Double check that the fragment belongs to one of the expected detectors + if (!isHPGe && !isLaBr){ + ++_totalUnreadInnerFrags; + continue; + } + + auto& headerState = isHPGe ? rawHeaderHPGe : rawHeaderLaBr; + auto& parentState = isHPGe ? rawParentHPGe : rawParentLaBr; + auto& eventMetrics = isHPGe ? HPGeEventMetrics : LaBrEventMetrics; + + isHPGe ? ++_totalZSFragsSeenHPGe : ++_totalZSFragsSeenLaBr; + ++eventMetrics.zs.seen; + + // Extract zs variables from Raw Header + bool skipCurrentSet = headerState.skipCurrentSet; + bool zsInfoWasExtracted = headerState.containsZSInfo; + bool zsPrescaled = headerState.zsPrescaled; + bool rawPrescaled = headerState.rawPrescaled; + uint16_t zsRegions = headerState.expectedZSRegions; + uint16_t zsLength = headerState.expectedZSLength; + uint16_t rawPrescaleValue = headerState.rawPrescaleValue; + uint16_t zsPrescaleValue = headerState.zsPrescaleValue; + + // Decide Here to skip based on previous raw fragment information + if (skipCurrentSet){ + isHPGe ? ++_totalZSFragsSkippedDueToRawFlagHPGe : ++_totalZSFragsSkippedDueToRawFlagLaBr; + ++eventMetrics.zsFragsSkippedDueToRawFlag; + continue; + } + // Decide Here to skip based on zs prescale information + if (zsPrescaled) { + isHPGe ? ++_totalZSFragsPrescaledHPGe : ++_totalZSFragsPrescaledLaBr; + ++_totalZSFragsPrescaled; + ++eventMetrics.zs.prescaled; + } + + auto payloadPtr = stm_frag.payloadBegin(); + auto payloadWords = stm_frag.payloadWords(); + + // Check if Empty + if (payloadWords == 0) { + if (_verbosityLevel > 2) { + std::cout << "\nFound an empty zs fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--ZS Frag\n"; + } + ++_totalEmptyZSFrags; + isHPGe ? ++_totalEmptyZSFragsHPGe : ++_totalEmptyZSFragsLaBr; + ++eventMetrics.zs.empty; + continue; + } + + // At this point the zs fragmant is non-empty + // May contain valid data + + // Print first 20 payload adcs for inspection + if (_verbosityLevel > 3) { + std::cout << "\nFirst few payload words for inspection : "; + for (size_t w = 0; w < std::min(payloadWords, static_cast(10)); ++w) { + std::cout << payloadPtr[w] << ","; + } + std::cout << "\n"; + } + + // Definitions for payload references + auto const* dataPtr = stm_frag.dataBegin(); + auto const dataWords = stm_frag.dataWords(); + auto dataEndPtr = dataPtr + dataWords; + size_t regionCounter {0}; + size_t zsTotalLengthCalculated {0}; + uint16_t lastZSIndexRecorded {0}; + uint16_t lastZSLengthRecorded {0}; + bool malformedZS {false}; + std::vector regions; + + // Check if data is zero filled using parsing for ZS + bool sawADC{false}; + bool allADCSZero{true}; + // May need to be adjusted, we would only read the first pulse + + if (_verbosityLevel > 5) { + std::cout << "\nData Words for inspection : " << "\n" + << "Data Words % 4 : " << dataWords % 4 << "\n" + << "--ZS Frag\n"; + } + + + while (dataPtr + 2 <= dataEndPtr){ + if (zsInfoWasExtracted && regionCounter >= zsRegions) { + break; + } + uint16_t currentZSIndex = static_cast(dataPtr[0]); + uint16_t currentZSLength = static_cast(dataPtr[1]); + auto adc = dataPtr + 2; + + if (adc + currentZSLength > dataEndPtr) { + malformedZS = true; + break; + } + + // Check if any is zero filled payload for this region + for (size_t sample = 0; sample < currentZSLength; ++sample){ + sawADC = true; + if (adc[sample] !=0) { + allADCSZero = false; + } + } + // Record the region + bool const saveZS = isHPGe ? _saveZSWaveformsHPGe : _saveZSWaveformsLaBr; + if (saveZS){ + regions.push_back({currentZSIndex, std::vector(adc, adc + currentZSLength)}); + } + + uint32_t trigTimeOffset = currentZSIndex; + + // Print Check per segment + if (_verbosityLevel > 5) { + std::cout << "\nZS Segment Check :" << "\n" + << " , ZS Index = " << currentZSIndex + << " , ZS Length = " << currentZSLength + << " , ZS Offset = " << trigTimeOffset << "\n"; + } + // Update Variables + lastZSIndexRecorded = currentZSIndex; + lastZSLengthRecorded = currentZSLength; + zsTotalLengthCalculated += lastZSLengthRecorded; + ++regionCounter; + dataPtr = adc + currentZSLength; + } // End of While loop + + if (_verbosityLevel > 4){ + //Summary + std::cout << "ZS Summary : " + << " , last ZS Index = " << lastZSIndexRecorded + << " , last ZS Length = " << lastZSLengthRecorded + << " , ZS Total Length = " << zsTotalLengthCalculated + << " , Region Counter = " << regionCounter << "\n" + << ", Frag Index = " << i << "\n"; + } + + // In case ZS has some weird behavior + if (malformedZS) { + if (_verbosityLevel > 2){ + std::cout << "\nMalformed ZS detected at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n"; + } + ++eventMetrics.zs.unread; + ++_totalUnreadInnerFrags; + continue; + } + + // Add exceptions + if (zsInfoWasExtracted && !zsPrescaled) { + if (zsLength != zsTotalLengthCalculated) { + throw cet::exception("STM_UNPACKING") + << "\n=== ZS LENGTH MISMATCH ===\n" + << "ZS Length Count from Raw Header : " << zsLength << "\n" + << "ZS Length Calculated : " << zsTotalLengthCalculated << "\n" + // General Information about where error was found + << "Found at Event : " << _totalEvents << "\n" + << "Found at Frag Index : " << i << "\n" + << "Raw Prescaled : " << (rawPrescaled ? "Yes" : "No") << "\n" + << "Raw Prescale Value : " << rawPrescaleValue << "\n" + << "ZS Prescaled : " << (zsPrescaled ? "Yes" : "No") << "\n" + << "ZS Prescale Value : " << zsPrescaleValue << "\n" + << "Found at HPGe Container Frag : " << (isHPGe ? "Yes" : "No") << "\n" + << "Found at LaBr Container Frag : " << (isLaBr ? "Yes" : "No") << "\n"; + + } + if ( zsRegions != regionCounter) { + throw cet::exception("STM_UNPACKING") + << "\n=== ZS REGION COUNT MISMATCH ===\n" + << "ZS Region Count from Raw Header : " << zsRegions << "\n" + << "ZS Region Count Calculated : " << regionCounter << "\n" + // General Information about where error was found + << "Found at Event : " << _totalEvents << "\n" + << "Found at Frag Index : " << i << "\n" + << "Raw Prescaled : " << (rawPrescaled ? "Yes" : "No") << "\n" + << "Raw Prescale Value : " << rawPrescaleValue << "\n" + << "ZS Prescaled : " << (zsPrescaled ? "Yes" : "No") << "\n" + << "ZS Prescale Value : " << zsPrescaleValue << "\n" + << "Found at HPGe Container Frag : " << (isHPGe ? "Yes" : "No") << "\n" + << "Found at LaBr Container Frag : " << (isLaBr ? "Yes" : "No") << "\n"; + } + } + + if (sawADC && allADCSZero) { + if (_verbosityLevel > 2) { + std::cout << "\nFound a zero-filled zs fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--ZS Frag\n"; + } + ++eventMetrics.zs.zero; + ++_totalZeroZSFrags; + isHPGe ? ++_totalZeroZSFragsHPGe : ++_totalZeroZSFragsLaBr; + continue; + } + + // At this point we know the fragment was good + if (_verbosityLevel > 2) { + std::cout << "\nFound a good ZS fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--ZS Frag\n"; + } + for (auto& region : regions) { + mu2e::STMWaveformDigi zsDigi(region.offset, region.adcs); + if(parentState.available){ + // Set parent pointer if available + zsDigi.setParent(parentState.ptr); + } + // Emplacing + if (isHPGe && _saveZSWaveformsHPGe) { + // emplacing HPGe waveform digi + zsWaveformDigisHPGe->emplace_back(zsDigi); + if (_verbosityLevel > 2 && zsDigi.hasParent()) { + std::cout << "\nZS HPGe Parent Raw index : " << zsDigi.parent().key() + << ", offset : " << zsDigi.trigTimeOffset() << "\n"; + } + + } else if (isLaBr && _saveZSWaveformsLaBr) { + // emplacing LaBr waveform digi + zsWaveformDigisLaBr->emplace_back(zsDigi); + if (_verbosityLevel > 2 && zsDigi.hasParent()) { + std::cout << "\nZS LaBr Parent Raw index : " << zsDigi.parent().key() + << ", offset : " << zsDigi.trigTimeOffset() << "\n"; + } + } + } + + // Increment remaining counters + ++_totalGoodZSFrags; + isHPGe ? ++_totalGoodZSFragsHPGe : ++_totalGoodZSFragsLaBr; + ++eventMetrics.zs.good; + + }// End of ZS fragmment check + else if (stm_frag.isPH()){ + ++_totalPHFragsSeen; + // Determine which detector this PH fragment belongs to + bool const isHPGe = stm_frag.isHPGe(); + bool const isLaBr = stm_frag.isLaBr(); + + if (!isHPGe && !isLaBr) { + ++_totalUnreadInnerFrags; + continue; + } + auto& headerState = isHPGe ? rawHeaderHPGe : rawHeaderLaBr; + auto& eventMetrics = isHPGe ? HPGeEventMetrics : LaBrEventMetrics; + + isHPGe ? ++_totalPHFragsSeenHPGe : ++_totalPHFragsSeenLaBr; + ++eventMetrics.ph.seen; + + // Extract ph varibales from Raw Header + bool skipCurrentSet = headerState.skipCurrentSet; + bool extractedPHInfo = headerState.containsPHInfo; + uint16_t phCount = headerState.expectedPHCount; + + // Skip if Raw Fragment was Bad or Missing + if (skipCurrentSet) { + ++eventMetrics.phFragsSkippedDueToRawFlag; + isHPGe ? ++_totalPHFragsSkippedDueToRawFlagHPGe : ++_totalPHFragsSkippedDueToRawFlagLaBr; + continue; + } + + // Check if PH fragment is empty + auto payloadPtr = stm_frag.payloadBegin(); + auto payloadWords = stm_frag.payloadWords(); + bool allPHAreZeros= true; + + if (payloadWords == 0) { + if (_verbosityLevel > 2) { + std::cout << "\nFound an empty PH fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--PH Frag\n"; + } + //increment + ++eventMetrics.ph.empty; + ++_totalEmptyPHFrags; + isHPGe ? ++_totalEmptyPHFragsHPGe : ++_totalEmptyPHFragsLaBr; + continue; + } + + // Check that the payload has pairs (time, pulse height) + if (payloadWords % 2 != 0) { + if(_verbosityLevel > 2) { + std::cout << "\nFound a PH Fragment with odd number of payload words at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + ++eventMetrics.ph.unread; + ++_totalUnreadInnerFrags; + continue; + } + + // Check if PH Pair count matches expected count from raw header + size_t nPairsInFragment = payloadWords / 2; + if (extractedPHInfo && nPairsInFragment != phCount) { + if (_verbosityLevel > 2) { + std::cout << "\nSkipping PH pair due to mismatch in expected count at Event : " << _totalEvents << "\n" + << "Expected PH Pair Count : " << phCount << "\n" + << "Actual PH Pair Count : " << nPairsInFragment << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + ++eventMetrics.ph.unread; + ++_totalUnreadInnerFrags; + continue; + } + + // Check if zero filled + // Since its a (time,PH) pair we will check every second entry for the PH value + for (size_t k = 1; k < payloadWords; k += 2) { + if (payloadPtr[k] !=0) { + allPHAreZeros = false; + break; + } + } + + if (allPHAreZeros) { + if (_verbosityLevel > 2) { + std:: cout << "\nFound a zero-filled PH Fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + // counter + ++eventMetrics.ph.zero; + ++_totalZeroPHFrags; + isHPGe ? ++_totalZeroPHFragsHPGe : ++_totalZeroPHFragsLaBr; + continue; + } + + if (_verbosityLevel > 4) { + std::cout << "\nFirst Few Payload Words : " ; + for (size_t k = 0; k < std::min(payloadWords,20); ++k) { + std::cout << payloadPtr[k] << " ,"; + } + std::cout << "Frag Index : " << i << "\n"; + } + + for (size_t i_phPair = 0; i_phPair < nPairsInFragment ; ++i_phPair){ + size_t i_PH = 2 * i_phPair; + uint32_t time = static_cast(payloadPtr[i_PH]); + int16_t const pulseHeight = payloadPtr[i_PH + 1]; + mu2e::STMPHDigi PH_digi(time,pulseHeight); + + // Emplace Back (Always On) + if (isHPGe) { + phDigisHPGe->emplace_back(PH_digi); + } + if (isLaBr) { + phDigisLaBr->emplace_back(PH_digi); + } + } + + // At this point we have a good PH fragment + if (_verbosityLevel > 2) { + std::cout << "\nFound a good PH Fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + + // Last counter increment + ++_totalGoodPHFrags; + isHPGe ? ++_totalGoodPHFragsHPGe : ++_totalGoodPHFragsLaBr; + ++eventMetrics.ph.good; + + }// End of PH fragment check + else { + // fallback for unreadable fragment + ++_totalUnreadInnerFrags; //Job Summary Counter + if (_verbosityLevel > 0 ) { + std::cout << "Encountered an unreadable inner fragment " << "\n" + << "Frag Index : " << i << "\n" + << "Frag ID : " << inner_frag->fragmentID() << "\n" + << "Event : " << _totalEvents << "\n"; + } + }// End of else non-raw/zs/pg frag } - } - - //Increment counter after checking if there is a match - if ( stm_frag.isHPGe()){ ++_totalGoodZSHPGe; ++goodZSHPGeFrags; } - else if(stm_frag.isLaBr()){++ _totalGoodZSLaBr; ++goodZSLaBrFrags; } - - }//End of isZS - - else if ( stm_frag.isPH() ){ - - ++_totalPH; - if ( stm_frag.isHPGe() ){ ++_totalPHHPGe; ++totalPHHPGeFrags;} - else if ( stm_frag.isLaBr() ){ ++_totalPHLaBr; ++totalPHLaBrFrags; } - - //Check if zero filled - auto payloadPtr = stm_frag.payloadBegin(); - auto payloadWords = stm_frag.payloadWords(); - bool allZeros = true; - - - if (payloadWords ==0){ - if (_verbosityLevel >= 3){std::cout << "\nFound an empty frag, i = " << i<< " @PH\n";} - ++_totalEmptyPH; - if ( stm_frag.isHPGe() ){ ++_totalEmptyPHHPGe; ++emptyPHHPGeFrags; } - else if ( stm_frag.isLaBr() ){ ++_totalEmptyPHLaBr; ++emptyPHLaBrFrags;} - continue; - } - - //Check if zero filled - for (size_t k = 0; k< payloadWords; ++k) { - if (payloadPtr[k] !=0){ - allZeros = false; - break; + } else { + // fallback for non-container fragment + if (_verbosityLevel > 0) { + std::cout << "\nEncountered a non-container fragment " << "\n" + << "Fragment ID : " << frag.fragmentID() << "\n" + << "Event : " << _totalEvents << "\n"; } - } - //count if zero filled - if (allZeros){ - if (_verbosityLevel >=3){ std::cout<< "\nFound a zero filled frag, i = " << i<< " @PH\n";} - ++_totalZeroPH; - - if ( stm_frag.isHPGe() ){ ++_totalZeroPHHPGe; ++zeroPHHPGeFrags; } - else if ( stm_frag.isLaBr() ){ ++_totalZeroPHLaBr; ++zeroPHLaBrFrags; } + ++_totalNonContainers; continue; - } - - if (_verbosityLevel >= 3){std::cout << "\nFound a good frag, i = " << i <<" @PH\n";} - - if ( stm_frag.isHPGe() ){ ++ _totalGoodPHHPGe; ++goodPHHPGeFrags; } - else if ( stm_frag.isLaBr() ) { ++ _totalGoodPHLaBr; ++goodPHLaBrFrags; } + } + } // End of frags loop + + // Update event type counters based on the detectors in event + if (eventHasHPGe && eventHasLaBr) { + ++_totalEventsWithBothDetectors; + } else if (eventHasHPGe) { + ++_totalEventsWithOnlyHPGe; + } else if (eventHasLaBr) { + ++_totalEventsWithOnlyLaBr; + } else { + ++_totalEventsWithNeitherDetector; + } - size_t digiWords = stm_frag.payloadWords(); - auto const* digiPtr = stm_frag.payloadBegin(); + // HPGe Remaining Fragment Counts + badHPGeFragsThisEvent = HPGeEventMetrics.rawFragsFlaggedBadOnly + + HPGeEventMetrics.rawFragsFlaggedBadAndMissing; - for (size_t i_PH = 0; i_PH < digiWords ; ++i_PH){ - int16_t PH = digiPtr[i_PH]; - mu2e::STMPHDigi PH_digi(0, PH); + missingHPGeFragsThisEvent = HPGeEventMetrics.rawFragsFlaggedMissingOnly + + HPGeEventMetrics.rawFragsFlaggedBadAndMissing; - if( stm_frag.isHPGe() ){ - ph_HPGe_digis->emplace_back(PH_digi); } - else if ( stm_frag.isLaBr() ){ - ph_LaBr_digis->emplace_back(PH_digi); } + // LaBr Remaining Fragment Counts + badLaBrFragsThisEvent = LaBrEventMetrics.rawFragsFlaggedBadOnly + + LaBrEventMetrics.rawFragsFlaggedBadAndMissing; - } + missingLaBrFragsThisEvent = LaBrEventMetrics.rawFragsFlaggedMissingOnly + + LaBrEventMetrics.rawFragsFlaggedBadAndMissing; - }//End of isPH and is checks - else{ - ++ _unreadInnerFrags; //For Job summary - ++ unread_InnerFrags; //For event summary - if(_verbosityLevel >=3){ - std::cout << "Unread Inner fragment" << "\n" - << "Inner frag i : " << i << "\n" - << "Frag ID : " << inner_frag->fragmentID() << "\n" - << "Event : " <<_totalEvents << "\n"; - } + // Save STMFrag Summary here + if (_saveSTMFragSummary) { + if (_verbosityLevel > 2) { + std::cout << "\nSaving STMFragSummary\n"; } - } - - } else { - //fallback (non-container case) - if (_verbosityLevel >=1){ - std::cout << "Found non-container STM Fragment " <<"\n" - << "Fragment ID : " << frag.fragmentID() << "\n" - << "Event : " << _totalEvents << "\n"; - } - ++ _totalNonContainerFrags; - continue; + stmFragSummaryHPGe->emplace_back( + ContainerFragsThisEvent,InnerFragsThisEvent, + badHPGeFragsThisEvent, missingHPGeFragsThisEvent, + HPGeEventMetrics.zsFragsSkippedDueToRawFlag, HPGeEventMetrics.phFragsSkippedDueToRawFlag, + HPGeEventMetrics.raw.good, HPGeEventMetrics.zs.good, HPGeEventMetrics.ph.good, + HPGeEventMetrics.raw.zero, HPGeEventMetrics.zs.zero, HPGeEventMetrics.ph.zero, + HPGeEventMetrics.raw.empty, HPGeEventMetrics.zs.empty, HPGeEventMetrics.ph.empty + ); + + stmFragSummaryLaBr->emplace_back( + ContainerFragsThisEvent,InnerFragsThisEvent, + badLaBrFragsThisEvent, missingLaBrFragsThisEvent, + LaBrEventMetrics.zsFragsSkippedDueToRawFlag, LaBrEventMetrics.phFragsSkippedDueToRawFlag, + LaBrEventMetrics.raw.good, LaBrEventMetrics.zs.good, LaBrEventMetrics.ph.good, + LaBrEventMetrics.raw.zero, LaBrEventMetrics.zs.zero, LaBrEventMetrics.ph.zero, + LaBrEventMetrics.raw.empty, LaBrEventMetrics.zs.empty, LaBrEventMetrics.ph.empty + ); } - } //End of frags loop - - if (eventHasHPGe && eventHasLaBr){ ++_totalEventsWithHPGeLaBr; } - else if (eventHasHPGe){ ++_totalEventsWithOnlyHPGe; } - else if (eventHasLaBr){ ++_totalEventsWithOnlyLaBr; } - else { ++_totalEventsWithNone; } - - if(_saveSTMFragSummary){ - stmFragSummaryHPGe->emplace_back(nContainerFragsThisEvent,nInnerFragsThisEvent, - goodRawHPGeFrags, goodZSHPGeFrags, goodPHHPGeFrags, - zeroRawHPGeFrags, zeroZSHPGeFrags, zeroPHHPGeFrags, - emptyRawHPGeFrags, emptyZSHPGeFrags, emptyPHHPGeFrags); - - stmFragSummaryLaBr->emplace_back(nContainerFragsThisEvent,nInnerFragsThisEvent, - goodRawLaBrFrags, goodZSLaBrFrags, goodPHLaBrFrags, - zeroRawLaBrFrags, zeroZSLaBrFrags, zeroPHLaBrFrags, - emptyRawLaBrFrags, emptyZSLaBrFrags, emptyPHLaBrFrags); - - } - if (_verbosityLevel >= 2 ){ - //Event Summary -> tells us what happens per art event - std::cout << "\n========== STM EVENT SUMMARY - (Unpacking Module) ==========\n"; - std::cout << "\n--- Products extracted ---\n"; - std::cout << "Extracted Raw HPGe waveforms : " << raw_HPGe_waveform_digis->size() <<"\n"; - std::cout << "Extracted ZS HPGe waveforms : " << zs_HPGe_waveform_digis->size() <<"\n"; - std::cout << "Extracted PH HPGe digis : " << ph_HPGe_digis->size() <<"\n"; - std::cout << "\n"; - std::cout << "Extracted Raw LaBr waveforms : " << raw_LaBr_waveform_digis->size() <<"\n"; - std::cout << "Extracted ZS LaBr waveforms : " << zs_LaBr_waveform_digis->size() <<"\n"; - std::cout << "Extracted PH LaBr digis : " << ph_LaBr_digis->size() <<"\n"; - - - std::cout << "\n--- Frags Seen ---\n"; // Counts all HPGe and LaBr frags, no filter - std::cout << "Raw HPGe frags seen : " << totalRawHPGeFrags << "\n"; - std::cout << "ZS HPGe frags seen : " << totalZSHPGeFrags << "\n"; - std::cout << "PH HPGe frags seen : " << totalPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Raw LaBr frags seen : " << totalRawLaBrFrags << "\n"; - std::cout << "ZS LaBr frags seen : " << totalZSLaBrFrags << "\n"; - std::cout << "PH LaBr frags seen : " << totalPHLaBrFrags << "\n"; - std::cout << "\nUnread frags : " << unread_InnerFrags << "\n"; - - - std::cout << "\n--- Filtered results ---\n"; - std::cout << "Good Raw HPGe frags : " << goodRawHPGeFrags << "\n"; - std::cout << "Good ZS HPGe frags : " << goodZSHPGeFrags << "\n"; - std::cout << "Good PH HPGe frags : " << goodPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Good Raw LaBr frags : " << goodRawLaBrFrags << "\n"; - std::cout << "Good ZS LaBr frags : " << goodZSLaBrFrags << "\n"; - std::cout << "Good PH LaBr frags : " << goodPHLaBrFrags << "\n"; - std::cout << "\n"; - std::cout << "Zero Raw HPGe frags : " << zeroRawHPGeFrags << "\n"; - std::cout << "Zero ZS HPGe frags : " << zeroZSHPGeFrags << "\n"; - std::cout << "Zero PH HPGe frags : " << zeroPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Zero Raw LaBr frags : " << zeroRawLaBrFrags << "\n"; - std::cout << "Zero ZS LaBr frags : " << zeroZSLaBrFrags << "\n"; - std::cout << "Zero PH LaBr frags : " << zeroPHLaBrFrags << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw HPGe frags : " << emptyRawHPGeFrags <<"\n"; - std::cout << "Empty ZS HPGe frags : " << emptyZSHPGeFrags << "\n"; - std::cout << "Empty PH HPGe frags : " << emptyPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw LaBr frags : " << emptyRawLaBrFrags <<"\n"; - std::cout << "Empty ZS LaBr frags : " << emptyZSLaBrFrags << "\n"; - std::cout << "Empty PH LaBr frags : " << emptyPHLaBrFrags << "\n"; - - std::cout << "=================================\n"; - } - - //Final move - if (_saveSTMFragSummary) { - event.put(std::move(stmFragSummaryHPGe),"stmFragSummaryHPGe"); - event.put(std::move(stmFragSummaryLaBr),"stmFragSummaryLaBr"); - } - - //HPGe - if (_saveRawWithHeaderWaveform_HPGe){ event.put(std::move(raw_HPGe_header_waveform_digis), "rawWithHeaderHPGe"); } - if (_saveRawWaveform_HPGe){event.put(std::move(raw_HPGe_waveform_digis), "rawHPGe");} - if (_saveZSWaveform_HPGe){event.put(std::move(zs_HPGe_waveform_digis), "zsHPGe");} - event.put(std::move(ph_HPGe_digis), "phHPGe"); - - //LaBr - if (_saveRawWithHeaderWaveform_LaBr){ event.put(std::move(raw_LaBr_header_waveform_digis), "rawWithHeaderLaBr"); } - if (_saveRawWaveform_LaBr){event.put(std::move(raw_LaBr_waveform_digis), "rawLaBr");} - if (_saveZSWaveform_LaBr){event.put(std::move(zs_LaBr_waveform_digis), "zsLaBr");} - event.put(std::move(ph_LaBr_digis), "phLaBr"); - -} // produce() -// ====================================================================== + // Final Move + if (_verbosityLevel > 1) { + // Event Summary -> tells us what happened per event + std::cout << "\n========== STM EVENT SUMMARY - (Unpacking Module) ==========\n"; + std::cout << "\n--- Module Configuration ---\n"; + std::cout << "Raw Waveforms with Header HPGe : " << (_saveRawWaveformsWithHeaderHPGe ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms HPGe : " << (_saveRawWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms HPGe : " << (_saveZSWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "PH Digis HPGe : Yes\n"; + std::cout << "Raw Waveforms with Header LaBr : " << (_saveRawWaveformsWithHeaderLaBr ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms LaBr : " << (_saveRawWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms LaBr : " << (_saveZSWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "PH Digis LaBr : Yes\n"; + + std::cout << "\n--- Products Saved ---\n"; + std::cout << "Extracted Raw Waveforms With Header (HPGe) : " << rawWaveformDigisWithHeaderHPGe->size() << "\n"; + std::cout << "Extracted Raw Waveforms (HPGe) : " << rawWaveformDigisHPGe->size() << "\n"; + std::cout << "Extracted ZS Waveforms (HPGe) : " << zsWaveformDigisHPGe->size() << "\n"; + std::cout << "Extracted PH Digis (HPGe) : " << phDigisHPGe->size() << "\n"; + std::cout << "\n"; + std::cout << "Extracted Raw Waveforms With Header (LaBr) : " << rawWaveformDigisWithHeaderLaBr->size() << "\n"; + std::cout << "Extracted Raw Waveforms (LaBr) : " << rawWaveformDigisLaBr->size() << "\n"; + std::cout << "Extracted ZS Waveforms (LaBr) : " << zsWaveformDigisLaBr->size() << "\n"; + std::cout << "Extracted PH Digis (LaBr) : " << phDigisLaBr->size() << "\n"; + + std::cout << "\n--- Filtered Products (HPGe) ---\n"; + std::cout << "Good Raw Frags (HPGe) : " << HPGeEventMetrics.raw.good << "\n"; + std::cout << "Good ZS Frags (HPGe) : " << HPGeEventMetrics.zs.good << "\n"; + std::cout << "Good PH Frags (HPGe) : " << HPGeEventMetrics.ph.good << "\n"; + std::cout << "\n"; + std::cout << "Empty Raw Frags (HPGe) : " << HPGeEventMetrics.raw.empty << "\n"; + std::cout << "Empty ZS Frags (HPGe) : " << HPGeEventMetrics.zs.empty << "\n"; + std::cout << "Empty PH Frags (HPGe) : " << HPGeEventMetrics.ph.empty << "\n"; + std::cout << "\n"; + std::cout << "Zero Raw Frags (HPGe) : " << HPGeEventMetrics.raw.zero << "\n"; + std::cout << "Zero ZS Frags (HPGe) : " << HPGeEventMetrics.zs.zero << "\n"; + std::cout << "Zero PH Frags (HPGe) : " << HPGeEventMetrics.ph.zero << "\n"; + std::cout << "\n"; + std::cout << "Bad Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedBadOnly << "\n"; + std::cout << "Missing Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedMissingOnly << "\n"; + std::cout << "\n"; + + std::cout << "\n--- Filtered Products (LaBr) ---\n"; + std::cout << "Good Raw Frags (LaBr) : " << LaBrEventMetrics.raw.good << "\n"; + std::cout << "Good ZS Frags (LaBr) : " << LaBrEventMetrics.zs.good << "\n"; + std::cout << "Good PH Frags (LaBr) : " << LaBrEventMetrics.ph.good << "\n"; + std::cout << "\n"; + std::cout << "Empty Raw Frags (LaBr) : " << LaBrEventMetrics.raw.empty << "\n"; + std::cout << "Empty ZS Frags (LaBr) : " << LaBrEventMetrics.zs.empty << "\n"; + std::cout << "Empty PH Frags (LaBr) : " << LaBrEventMetrics.ph.empty << "\n"; + std::cout << "\n"; + std::cout << "Zero Raw Frags (LaBr) : " << LaBrEventMetrics.raw.zero << "\n"; + std::cout << "Zero ZS Frags (LaBr) : " << LaBrEventMetrics.zs.zero << "\n"; + std::cout << "Zero PH Frags (LaBr) : " << LaBrEventMetrics.ph.zero << "\n"; + std::cout << "\n"; + std::cout << "Bad Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedBadOnly << "\n"; + std::cout << "Missing Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedMissingOnly << "\n"; + + std::cout << "=================================\n"; + + } + // Frag Summary + if (_saveSTMFragSummary) { + event.put(std::move(stmFragSummaryHPGe), "stmFragSummaryHPGe"); + event.put(std::move(stmFragSummaryLaBr), "stmFragSummaryLaBr"); + } + // HPGe + if (_saveRawWaveformsWithHeaderHPGe) { event.put(std::move(rawWaveformDigisWithHeaderHPGe), "rawWithHeaderHPGe"); } + if (_saveRawWaveformsHPGe) { event.put(std::move(rawWaveformDigisHPGe), "rawHPGe"); } + if (_saveZSWaveformsHPGe) { event.put(std::move(zsWaveformDigisHPGe), "zsHPGe"); } + //default to always save PH Digis + event.put(std::move(phDigisHPGe), "phHPGe"); + // LaBr + if (_saveRawWaveformsWithHeaderLaBr) { event.put(std::move(rawWaveformDigisWithHeaderLaBr), "rawWithHeaderLaBr"); } + if (_saveRawWaveformsLaBr) { event.put(std::move(rawWaveformDigisLaBr), "rawLaBr"); } + if (_saveZSWaveformsLaBr) { event.put(std::move(zsWaveformDigisLaBr), "zsLaBr"); } + //default to always save PH Digis + event.put(std::move(phDigisLaBr), "phLaBr"); + +}// End of produce() void STMDigisFromFragments::endJob() { - if (_verbosityLevel >= 1){ - //Art job summary for the unpacking - std::cout << "\n========== STM JOB SUMMARY - (Unpacking Module) ==========\n"; - - std::cout << "Total Art events : " << _totalEvents << "\n"; - std::cout << "Total Art events w/HPGe&LaBr : " << _totalEventsWithHPGeLaBr << "\n"; - std::cout << "Total Art events w/only HPGe : " << _totalEventsWithOnlyHPGe << "\n"; - std::cout << "Total Art events w/only LaBr : " << _totalEventsWithOnlyLaBr << "\n"; - std::cout << "Total Art events w/Neither : " << _totalEventsWithNone << "\n"; - std::cout << "Total frags : " << _totalFragments << "\n"; - std::cout << "Total Container frags : " << _totalContainers << "\n"; - std::cout << "Total HPGe Containers : " << _totalContainersHPGe << "\n"; - std::cout << "Total LaBr Containers : " << _totalContainersLaBr << "\n"; - std::cout << "Total Inner frags : " << _totalInner << "\n"; - std::cout << "Unread frags : " << _unreadInnerFrags << "\n"; - std::cout << "Non Container frags : " << _totalNonContainerFrags << "\n"; - - std::cout << "\n--- Data types read pre filtering ---\n"; - std::cout << "Total RAW frags seen : " << _totalRaw << "\n"; - std::cout << "Total ZS frags seen : " << _totalZS << "\n"; - std::cout << "total PH frags seen : " << _totalPH << "\n"; - std::cout << "\n"; - std::cout << "Total RAW HPGe frags seen : " << _totalRawHPGe << "\n"; - std::cout << "Total ZS HPGe frags seen : " << _totalZSHPGe << "\n"; - std::cout << "Total PH HPGe frags seen : " << _totalPHHPGe << "\n"; - std::cout << "\n"; - std::cout << "Total RAW LaBr frags seen : " << _totalRawLaBr << "\n"; - std::cout << "Total ZS LaBr frags seen : " << _totalZSLaBr << "\n"; - std::cout << "Total PH LaBr frags seen : " << _totalPHLaBr << "\n"; - - std::cout << "\n--- Data types filtered HPGe ---\n"; - std::cout << "Good RAW HPGe frags : " << _totalGoodRawHPGe << "\n"; - std::cout << "Good ZS HPGe frags : " << _totalGoodZSHPGe << "\n"; - std::cout << "Good PH HPGe frags : " << _totalGoodPHHPGe << "\n"; - std::cout << "\n"; - std::cout << "Zero RAW HPGe frags : " << _totalZeroRawHPGe << "\n"; - std::cout << "Zero ZS HPGe frags : " << _totalZeroZSHPGe << "\n"; - std::cout << "Zero PH HPGe frags : " << _totalZeroPHHPGe << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw HPGe frags : " << _totalEmptyRawHPGe << "\n"; - std::cout << "Empty ZS HPGe frags : " << _totalEmptyZSHPGe << "\n"; - std::cout << "Empty PH HPGe frags : " << _totalEmptyPHHPGe << "\n"; - - std::cout << "\n--- Data types filtered LaBr ---\n"; - std::cout << "Good RAW LaBr frags : " << _totalGoodRawLaBr << "\n"; - std::cout << "Good ZS LaBr frags : " << _totalGoodZSLaBr << "\n"; - std::cout << "Good PH LaBr frags : " << _totalGoodPHLaBr << "\n"; - std::cout << "\n"; - std::cout << "Zero RAW LaBr frags : " << _totalZeroRawLaBr << "\n"; - std::cout << "Zero ZS LaBr frags : " << _totalZeroZSLaBr << "\n"; - std::cout << "Zero PH LaBr frags : " << _totalZeroPHLaBr << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw LaBr frags : " << _totalEmptyRawLaBr << "\n"; - std::cout << "Empty ZS LaBr frags : " << _totalEmptyZSLaBr << "\n"; - std::cout << "Empty PH LaBr frags : " << _totalEmptyPHLaBr << "\n"; - - std::cout << "=================================\n"; - - } + if (_verbosityLevel > 0 ){ + // Print job Summary + std::cout << "\n========== STM JOB SUMMARY - (Unpacking Module) ==========\n"; + std::cout << "\n--- Module Configuration ---\n"; + std::cout << "Raw Waveforms with Header HPGe : " << (_saveRawWaveformsWithHeaderHPGe ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms HPGe : " << (_saveRawWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms HPGe : " << (_saveZSWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "PH Digis HPGe : Yes\n"; + std::cout << "Raw Waveforms with Header LaBr : " << (_saveRawWaveformsWithHeaderLaBr ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms LaBr : " << (_saveRawWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms LaBr : " << (_saveZSWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "PH Digis LaBr : Yes\n"; + + // Container and Inner Fragment Summary + std::cout << "\n--- Container and Inner Fragment Summary ---\n"; + std::cout << "Total Art Events Processed : " << _totalEvents << "\n"; + std::cout << "Total Art Events w/ HPGe & LaBr : " << _totalEventsWithBothDetectors << "\n"; + std::cout << "Total Art Events w/ HPGe Only : " << _totalEventsWithOnlyHPGe << "\n"; + std::cout << "Total Art Events w/ LaBr Only : " << _totalEventsWithOnlyLaBr << "\n"; + std::cout << "Total Art Events w/ Neither HPGe nor LaBr : " << _totalEventsWithNeitherDetector << "\n"; + + std::cout << "Total HPGe Containers : " << _totalContainersHPGe << "\n"; + std::cout << "Total LaBr Containers : " << _totalContainersLaBr << "\n"; + std::cout << "Total Container Processed : " << _totalContainers << "\n"; + std::cout << "Total Non Container Processed : " << _totalNonContainers << "\n"; + + std::cout << "Total Inner Fragments Processed : " << _totalInnerFrags << "\n"; + std::cout << "Total Unreadable Inner Fragments : " << _totalUnreadInnerFrags << "\n"; + + // Data Type Summary - pre-filtering + std::cout << "\n--- Data Types Read (Pre - Filtering) ---\n"; + std::cout << "Total Raw Frags Seen : " << _totalRawFragsSeen << "\n"; + std::cout << "Total ZS Frags Seen : " << _totalZSFragsSeen << "\n"; + std::cout << "Total PH Frags Seen : " << _totalPHFragsSeen << "\n"; + std::cout << "Total Raw Prescaled Frags : " << _totalRawFragsPrescaled << "\n"; + std::cout << "Total ZS Prescaled Frags : " << _totalZSFragsPrescaled << "\n"; + std::cout << "Total Raw Frags Flagged Bad : " << _totalRawFragsFlaggedBadOnly << "\n"; + std::cout << "Total Raw Frags Flagged Missing : " << _totalRawFragsFlaggedMissingOnly << "\n"; + std::cout << "\n"; + std::cout << "Total RAW Frags seen (HPGe) : " << _totalRawFragsSeenHPGe << "\n"; + std::cout << "Total ZS Frags seen (HPGe) : " << _totalZSFragsSeenHPGe << "\n"; + std::cout << "Total PH Frags seen (HPGe) : " << _totalPHFragsSeenHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total RAW Frags seen (LaBr) : " << _totalRawFragsSeenLaBr << "\n"; + std::cout << "Total ZS Frags seen (LaBr) : " << _totalZSFragsSeenLaBr << "\n"; + std::cout << "Total PH Frags seen (LaBr) : " << _totalPHFragsSeenLaBr << "\n"; + + // Data Type Summary - post-filtering (HPGe) + std::cout << "\n--- Data Types Read HPGe (Post - Filtering) ---\n"; + std::cout << "Total Good Raw Frags (HPGe) : " << _totalGoodRawFragsHPGe << "\n"; + std::cout << "Total Good ZS Frags (HPGe) : " << _totalGoodZSFragsHPGe << "\n"; + std::cout << "Total Good PH Frags (HPGe) : " << _totalGoodPHFragsHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total Zero Raw Frags (HPGe) : " << _totalZeroRawFragsHPGe << "\n"; + std::cout << "Total Zero ZS Frags (HPGe) : " << _totalZeroZSFragsHPGe << "\n"; + std::cout << "Total Zero PH Frags (HPGe) : " << _totalZeroPHFragsHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total Empty Raw Frags (HPGe) : " << _totalEmptyRawFragsHPGe << "\n"; + std::cout << "Total Empty ZS Frags (HPGe) : " << _totalEmptyZSFragsHPGe << "\n"; + std::cout << "Total Empty PH Frags (HPGe) : " << _totalEmptyPHFragsHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total Raw Prescaled Frags (HPGe) : " << _totalRawFragsPrescaledHPGe << "\n"; + std::cout << "Total ZS Prescaled Frags (HPGe) : " << _totalZSFragsPrescaledHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Bad (HPGe) : " << _totalRawFragsFlaggedBadOnlyHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Missing (HPGe) : " << _totalRawFragsFlaggedMissingOnlyHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Bad & Missing (HPGe) : " << _totalRawFragsFlaggedBadAndMissingHPGe << "\n"; + + // Data Type Summary - post-filtering (LaBr) + std::cout << "\n--- Data Types Read LaBr (Post - Filtering) ---\n"; + std::cout << "Total Good Raw Frags (LaBr) : " << _totalGoodRawFragsLaBr << "\n"; + std::cout << "Total Good ZS Frags (LaBr) : " << _totalGoodZSFragsLaBr << "\n"; + std::cout << "Total Good PH Frags (LaBr) : " << _totalGoodPHFragsLaBr << "\n"; + std::cout << "\n"; + std::cout << "Total Zero Raw Frags (LaBr) : " << _totalZeroRawFragsLaBr << "\n"; + std::cout << "Total Zero ZS Frags (LaBr) : " << _totalZeroZSFragsLaBr << "\n"; + std::cout << "Total Zero PH Frags (LaBr) : " << _totalZeroPHFragsLaBr << "\n"; + std::cout << "\n"; + std::cout << "Total Empty Raw Frags (LaBr) : " << _totalEmptyRawFragsLaBr << "\n"; + std::cout << "Total Empty ZS Frags (LaBr) : " << _totalEmptyZSFragsLaBr << "\n"; + std::cout << "Total Empty PH Frags (LaBr) : " << _totalEmptyPHFragsLaBr << "\n"; + std::cout << "\n"; + std::cout << "Total Raw Prescaled Frags (LaBr) : " << _totalRawFragsPrescaledLaBr << "\n"; + std::cout << "Total ZS Prescaled Frags (LaBr) : " << _totalZSFragsPrescaledLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Bad (LaBr) : " << _totalRawFragsFlaggedBadOnlyLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Missing (LaBr) : " << _totalRawFragsFlaggedMissingOnlyLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Bad & Missing (LaBr) : " << _totalRawFragsFlaggedBadAndMissingLaBr << "\n"; + + std::cout << "\n=== Extra Filters ===\n"; + std::cout << "Invalid Raw Headers : " << _totalRawFragsWithInvalidHeader << "\n"; + std::cout << "Invalid Raw Headers (HPGe) : " << _totalRawFragsWithInvalidHeaderHPGe << "\n"; + std::cout << "Invalid Raw Headers (LaBr) : " << _totalRawFragsWithInvalidHeaderLaBr << "\n"; + std::cout << "ZS Skipped Due to Raw Flag (HPGe) : " << _totalZSFragsSkippedDueToRawFlagHPGe << "\n"; + std::cout << "ZS Skipped Due to Raw Flag (LaBr) : " << _totalZSFragsSkippedDueToRawFlagLaBr << "\n"; + std::cout << "PH Skipped Due to Raw Flag (HPGe) : " << _totalPHFragsSkippedDueToRawFlagHPGe << "\n"; + std::cout << "PH Skipped Due to Raw Flag (LaBr) : " << _totalPHFragsSkippedDueToRawFlagLaBr << "\n"; + + + std::cout << "\n===========================================================\n"; + + } } DEFINE_ART_MODULE(STMDigisFromFragments) diff --git a/DAQ/src/STMPrintFragments_module.cc b/DAQ/src/STMPrintFragments_module.cc index adf5f8d0b1..6b50383f53 100644 --- a/DAQ/src/STMPrintFragments_module.cc +++ b/DAQ/src/STMPrintFragments_module.cc @@ -33,7 +33,14 @@ class art::STMPrintFragments : public EDAnalyzer public: struct Config { - fhicl::Atom stmTag {fhicl::Name("stmTag"), fhicl::Comment("stmTag for new file")}; + fhicl::Atom stmTag {fhicl::Name("stmTag"), + fhicl::Comment("stmTag for new file")}; + fhicl::Atom printEverything {fhicl::Name("printEverything"), + fhicl::Comment("Switch to print everything in STM File ")}; + fhicl::Atom printPayloads {fhicl::Name("printPayloads"), + fhicl::Comment("Switch to print only fragment payloads ")}; + fhicl::Atom printInnerFrags {fhicl::Name("printInnerFrags"), + fhicl::Comment("Switch to print inner frags begining from header to end of payload ")}; }; // --- C'tor/d'tor: @@ -45,6 +52,9 @@ class art::STMPrintFragments : public EDAnalyzer private: art::InputTag _stmFragmentsTag; + bool _printEverything{false}; + bool _printPayloads{false}; + bool _printInnerFrags{false}; }; // STMPrintFragments // ====================================================================== @@ -52,6 +62,9 @@ class art::STMPrintFragments : public EDAnalyzer STMPrintFragments::STMPrintFragments(const art::EDAnalyzer::Table& config) : art::EDAnalyzer{config} ,_stmFragmentsTag(config().stmTag()) + ,_printEverything(config().printEverything()) + ,_printPayloads(config().printPayloads()) + ,_printInnerFrags(config().printInnerFrags()) {} // ---------------------------------------------------------------------- @@ -67,31 +80,186 @@ 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(dataBegin); - const auto stmDataEnd = reinterpret_cast(dataEnd); - std::cout << "Frag_ID = " << frag_id << std::endl; - std::cout << "Container block_count = "<dataSizeBytes() / sizeof(int16_t); + + auto dataPtr = stm_frag.dataBegin(); + auto dataWords = stm_frag.dataWords(); + auto dataEnd = dataPtr + dataWords; + + std::cout << "\n=== ZS Payload Dump ===\n" + << "Frag # : " << frag_counter << "\n" + << ", inner # : " << i << "\n" + << ", PhysicalWords : " << physicalWords << "\n" + << ", stmDataWords : " << stmDataWords << "\n"; + size_t seg = 0; + size_t totalLen= 0; + uint16_t lastZSindex = 0; + uint16_t lastLen = 0; + + while (dataPtr+2 <= dataEnd){ + uint16_t current_zs_location = static_cast(dataPtr[0]); + uint16_t current_zs_size = static_cast(dataPtr[1]); + std::cout << "Currnent ZS Index : " << current_zs_location + << ", current ZS Length : " << current_zs_size << "\n" ; + auto adc = dataPtr + 2; + if (adc + current_zs_size > dataEnd){ + 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(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) diff --git a/DAQ/test/inspectSTMFile.fcl b/DAQ/test/inspectSTMFile.fcl index dffab29f63..026394656f 100644 --- a/DAQ/test/inspectSTMFile.fcl +++ b/DAQ/test/inspectSTMFile.fcl @@ -19,14 +19,14 @@ 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 : { @@ -47,6 +47,9 @@ physics : { stmPrint : { module_type : STMPrintFragments stmTag : "daq:ContainerSTM" + printEverything: false + printInnerFragments: false + printPayloads : false } } @@ -68,7 +71,7 @@ services.TimeTracker.printSummary: true outputs : { stmOutput : { module_type : RootOutput - fileName : "dig.stm.art" + fileName : "data/dig.stm.art" outputCommands : [ "keep *_*_*_*", "drop artdaq::*_*_*_*" ] } } diff --git a/RecoDataProducts/inc/STMFragmentSummary.hh b/RecoDataProducts/inc/STMFragmentSummary.hh index c9df4b6caf..9b36595348 100644 --- a/RecoDataProducts/inc/STMFragmentSummary.hh +++ b/RecoDataProducts/inc/STMFragmentSummary.hh @@ -18,23 +18,46 @@ namespace mu2e { public: STMFragmentSummary() : _nContainerFrags(0), _nInnerFrags(0), + _nRawFragsFlaggedBad(0), _nRawFragsFlaggedMissing(0), + _nZSFragsSkippedDueToRawFlag(0), _nPHFragsSkippedDueToRawFlag(0), _nGoodRawFrags(0),_nGoodZSFrags(0),_nGoodPHFrags(0), _nZeroRawFrags(0),_nZeroZSFrags(0),_nZeroPHFrags(0), _nEmptyRawFrags(0),_nEmptyZSFrags(0),_nEmptyPHFrags(0){}; STMFragmentSummary(size_t nContainerFrags, size_t nInnerFrags, + size_t nRawFragsFlaggedBad, size_t nRawFragsFlaggedMissing, + size_t nZSFragsSkippedDueToRawFlag, size_t nPHFragsSkippedDueToRawFlag, size_t nGoodRawFrags,size_t nGoodZSFrags, size_t nGoodPHFrags, size_t nZeroRawFrags, size_t nZeroZSFrags, size_t nZeroPHFrags, size_t nEmptyRawFrags, size_t nEmptyZSFrags, size_t nEmptyPHFrags) : _nContainerFrags(nContainerFrags), _nInnerFrags(nInnerFrags), + _nRawFragsFlaggedBad(nRawFragsFlaggedBad), _nRawFragsFlaggedMissing(nRawFragsFlaggedMissing), + _nZSFragsSkippedDueToRawFlag(nZSFragsSkippedDueToRawFlag), _nPHFragsSkippedDueToRawFlag(nPHFragsSkippedDueToRawFlag), _nGoodRawFrags(nGoodRawFrags),_nGoodZSFrags(nGoodZSFrags),_nGoodPHFrags(nGoodPHFrags), _nZeroRawFrags(nZeroRawFrags),_nZeroZSFrags(nZeroZSFrags),_nZeroPHFrags(nZeroPHFrags), _nEmptyRawFrags(nEmptyRawFrags),_nEmptyZSFrags(nEmptyZSFrags),_nEmptyPHFrags(nEmptyPHFrags) {}; - + // Container/Fragment structure size_t nContainerFrags() const { return _nContainerFrags; } size_t nInnerFrags() const { return _nInnerFrags; } + // Raw Header Quality + size_t nRawFragsFlaggedBad() const {return _nRawFragsFlaggedBad; } + size_t nRawFragsFlaggedMissing() const { return _nRawFragsFlaggedMissing; } + + size_t nZSFragsSkippedDueToRawFlag() const { return _nZSFragsSkippedDueToRawFlag; } + size_t nPHFragsSkippedDueToRawFlag() const { return _nPHFragsSkippedDueToRawFlag; } + + // Skip decisions + /* ->Maybe add later, for now just want general skipped summary + size_t nZSFragsSkippedDueToBadFlag() const { return _nZSFragsSkippedDueToBadRaw; } + size_t nZSFragsSkippedDueToMissingRaw() const { return _nZSFragsSkippedDueToMissingRaw{}; } + + size_t nPHFragsSkippedDueToBadRaw() const {return _nPHFragsSkippedDueToBadRaw; } + size_t nPHFragsSkippedDueToMissingRaw() const { return _nPHFragsSkippedDueToMissingRaw; } + */ + + // Filter/Classifications results size_t nGoodRawFrags() const { return _nGoodRawFrags; } size_t nGoodZSFrags() const { return _nGoodZSFrags; } size_t nGoodPHFrags() const { return _nGoodPHFrags; } @@ -49,9 +72,26 @@ namespace mu2e { private: + // Container/Fragment size_t _nContainerFrags{}; size_t _nInnerFrags{}; + // Raw Header Quality + size_t _nRawFragsFlaggedBad{}; + size_t _nRawFragsFlaggedMissing{}; + + size_t _nZSFragsSkippedDueToRawFlag{}; + size_t _nPHFragsSkippedDueToRawFlag{}; + + /* ->Maybe add later, for now just want general skipped summary + size_t _nZSFragsSkippedDueToBadRaw{}; + size_t _nZSFragsSkippedDueToMissingRaw{}; + + size_t _nPHFragsSkippedDueToBadRaw{}; + size_t _nPHFragsSkippedDueToMissingRaw{}; + */ + + // Filter/Classifications results size_t _nGoodRawFrags{}; size_t _nGoodZSFrags{}; size_t _nGoodPHFrags{}; @@ -64,7 +104,6 @@ namespace mu2e { size_t _nEmptyZSFrags{}; size_t _nEmptyPHFrags{}; - }; typedef std::vector STMFragmentSummaryCollection; } From b779d435db678024568451a8e0d53c2add15ff6d Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Wed, 12 Aug 2026 11:52:28 -0500 Subject: [PATCH 03/21] Changes to the Unpacking module, waveformDigis plotting and stmprinting (for debugging) --- DAQ/src/STMDigisFromFragments_module.cc | 189 ++++++++++++++------- DAQ/test/inspectSTMFile.fcl | 16 +- STMReco/fcl/plotSTMWaveformDigis.fcl | 16 -- STMReco/src/PlotSTMWaveformDigis_module.cc | 19 ++- 4 files changed, 149 insertions(+), 91 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 380d2a8831..572e3f95e9 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -111,7 +111,8 @@ class art::STMDigisFromFragments : public EDProducer size_t _totalRawFragsFlaggedBadOnly{0}; size_t _totalRawFragsFlaggedMissingOnly{0}; size_t _totalRawFragsFlaggedBadAndMissing{0}; - size_t _totalRawFragsWithInvalidHeader{0}; + size_t _totalRawFragsWithInvalidHeaders{0}; + size_t _totalRawFragsWithInvalidAnchors{0}; // Detector Summary variables size_t _totalEventsWithBothDetectors{0}; @@ -137,7 +138,8 @@ class art::STMDigisFromFragments : public EDProducer size_t _totalRawFragsFlaggedBadOnlyHPGe{0}; size_t _totalRawFragsFlaggedMissingOnlyHPGe{0}; size_t _totalRawFragsFlaggedBadAndMissingHPGe{0}; - size_t _totalRawFragsWithInvalidHeaderHPGe{0}; + size_t _totalRawFragsWithInvalidHeadersHPGe{0}; + size_t _totalRawFragsWithInvalidAnchorsHPGe{0}; size_t _totalZSFragsSkippedDueToRawFlagHPGe{0};// We want to skip ZS if raw is flagged bad/missing size_t _totalPHFragsSkippedDueToRawFlagHPGe{0};// We want to skip PH if raw is flagged bad/missing size_t _totalRawFragsPrescaledHPGe{0};// track how many raw fragments were prescaled @@ -161,7 +163,8 @@ class art::STMDigisFromFragments : public EDProducer size_t _totalRawFragsFlaggedBadOnlyLaBr{0}; size_t _totalRawFragsFlaggedMissingOnlyLaBr{0}; size_t _totalRawFragsFlaggedBadAndMissingLaBr{0}; - size_t _totalRawFragsWithInvalidHeaderLaBr{0}; + size_t _totalRawFragsWithInvalidHeadersLaBr{0}; + size_t _totalRawFragsWithInvalidAnchorsLaBr{0}; size_t _totalZSFragsSkippedDueToRawFlagLaBr{0};// We want to skip ZS if raw is flagged bad/missing size_t _totalPHFragsSkippedDueToRawFlagLaBr{0};// We want to skip PH if raw is flagged bad/missing size_t _totalRawFragsPrescaledLaBr{0};// track how many raw fragments were prescaled @@ -217,14 +220,13 @@ class art::STMDigisFromFragments : public EDProducer size_t rawFragsFlaggedBadOnly{0}; size_t rawFragsFlaggedMissingOnly{0}; size_t rawFragsFlaggedBadAndMissing{0}; - size_t rawFragsWithInvalidHeader{0}; - + size_t rawFragsWithInvalidHeaders{0}; + size_t rawFragsWithInvalidAnchors{0}; size_t zsFragsSkippedDueToRawFlag{0}; size_t phFragsSkippedDueToRawFlag{0}; size_t setsSkippedDueToRawFlag{0}; - size_t setsSkippedDueToInvalidHeader{0}; + size_t setsSkippedDueToInvalidHeaders{0}; - size_t unknownFrags{0}; }; }; // STMDigisFromFragments @@ -242,7 +244,7 @@ STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table 2) { std::cout << "Processing HPGe container fragment with ID: " << outerFragID << "\n"; } ++_totalContainersHPGe; eventHasHPGe = true; _totalInnerFragsHPGe += blocks; + ++containerFragsHPGeThisEvent; } else if (container_frag.isLaBrContainer()) { if (_verbosityLevel > 2) { std::cout << "Processing LaBr container fragment with ID: " << outerFragID << "\n"; } ++_totalContainersLaBr; eventHasLaBr = true; _totalInnerFragsLaBr += blocks; + ++containerFragsLaBrThisEvent; } else { if (_verbosityLevel > 0) { std::cout << "Encountered an unknown STM Container Fragment \n" @@ -344,10 +354,10 @@ void STMDigisFromFragments::produce(Event& event) } continue; // Skips the rest of this container frag if it is unknown } - ++ContainerFragsThisEvent; + ++containerFragsThisEvent; ++_totalContainers; _totalInnerFrags += blocks; - InnerFragsThisEvent += blocks; + innerFragsThisEvent += blocks; // loop over container blocks for (size_t i = 0 ; i < cont_frag.block_count(); ++i) { @@ -361,7 +371,6 @@ void STMDigisFromFragments::produce(Event& event) bool const isHPGe = stm_frag.isHPGe(); bool const isLaBr = stm_frag.isLaBr(); - if (!isHPGe && !isLaBr) { if (_verbosityLevel > 1) { std::cout << "Encountered raw fragment that is neither HPGe nor LaBr\n"; @@ -380,6 +389,7 @@ void STMDigisFromFragments::produce(Event& event) headerState = RawHeaderState{}; parentState.ptr = {}; parentState.available = false; + parentState.index = 0; ++eventMetrics.raw.seen; // check header+adcs is not less than expected header length (22) @@ -387,8 +397,12 @@ void STMDigisFromFragments::produce(Event& event) if (_verbosityLevel > 1) { std::cout << "Raw fragment has fewer data words than expected header length\n"; } + ++_totalRawFragsWithInvalidHeaders; ++_totalUnreadInnerFrags; - ++eventMetrics.setsSkippedDueToInvalidHeader; + ++eventMetrics.rawFragsWithInvalidHeaders; + isHPGe ? ++_totalRawFragsWithInvalidHeadersHPGe : ++_totalRawFragsWithInvalidHeadersLaBr; + ++eventMetrics.setsSkippedDueToInvalidHeaders; + headerState.skipCurrentSet = true; parentState.ptr = {}; parentState.available = false; @@ -398,11 +412,12 @@ void STMDigisFromFragments::produce(Event& event) // Confirm Raw Header has Valid Anchors // For now just use as a diagnostic tool if (!stm_frag.hasValidAnchors()) { - ++eventMetrics.rawFragsWithInvalidHeader; - ++_totalRawFragsWithInvalidHeader; - isHPGe ? ++_totalRawFragsWithInvalidHeaderHPGe : ++_totalRawFragsWithInvalidHeaderLaBr; + ++eventMetrics.rawFragsWithInvalidAnchors; + ++_totalRawFragsWithInvalidAnchors; + isHPGe ? ++_totalRawFragsWithInvalidAnchorsHPGe : ++_totalRawFragsWithInvalidAnchorsLaBr; } - headerState.rawHeaderIsValid = stm_frag.hasValidAnchors(); + // Not needed for the moment + // headerState.rawHeaderIsValid = stm_frag.hasValidAnchors(); // Check if bad or missing or both if (stm_frag.badData() && stm_frag.missing()) { @@ -438,6 +453,18 @@ void STMDigisFromFragments::produce(Event& event) isHPGe ? ++_totalRawFragsPrescaledHPGe : ++_totalRawFragsPrescaledLaBr; } + // Extract rest of the raw header information + // Even if raw is prescaled we still want to save zs info just in case + // before checking whats in the payload + headerState.containsZSInfo = true; + headerState.containsPHInfo = true; + headerState.zsPrescaled = stm_frag.zsPrescaled(); + headerState.zsPrescaleValue = stm_frag.zsPrescaleValue(); + headerState.expectedZSLength = stm_frag.zsLength(); + headerState.expectedZSRegions = stm_frag.zsRegions(); + headerState.expectedPHCount = stm_frag.phCount(); + + // Check if raw frag is empty auto payloadPtr = stm_frag.payloadBegin(); auto payloadWords = stm_frag.payloadWords(); @@ -503,14 +530,6 @@ void STMDigisFromFragments::produce(Event& event) ++_totalGoodRawFrags; isHPGe ? ++_totalGoodRawFragsHPGe : ++_totalGoodRawFragsLaBr; - // Extract rest of the raw header information - headerState.containsZSInfo = true; - headerState.containsPHInfo = true; - headerState.zsPrescaled = stm_frag.zsPrescaled(); - headerState.zsPrescaleValue = stm_frag.zsPrescaleValue(); - headerState.expectedZSLength = stm_frag.zsLength(); - headerState.expectedZSRegions = stm_frag.zsRegions(); - headerState.expectedPHCount = stm_frag.phCount(); // Save waveforms based on fcl configurations // Save Raw Waveform With Header Info - HPGe @@ -546,10 +565,20 @@ void STMDigisFromFragments::produce(Event& event) //Save raw parent index parentState.index = rawWaveformDigisLaBr->size() - 1; parentState.ptr = art::Ptr(parentState.productID, parentState.index, - event.productGetter(parentState.productID)); + event.productGetter(parentState.productID)); parentState.available = true; } + if (_verbosityLevel > 2) { + std::cout << "Raw with frag index" << i + << ", detector = " << (isHPGe? "HPGe": "LaBr") << std::boolalpha + << ", prescaled = " << headerState.rawPrescaled + << ", saved parent = " << parentState.available; + if (parentState.available) { + std::cout << ", raw index saved = " << parentState.index; + } + std::cout << "\n"; + } }// End of Raw fragment check else if (stm_frag.isZS()){ ++_totalZSFragsSeen; @@ -570,6 +599,17 @@ void STMDigisFromFragments::produce(Event& event) isHPGe ? ++_totalZSFragsSeenHPGe : ++_totalZSFragsSeenLaBr; ++eventMetrics.zs.seen; + // Check + if (_verbosityLevel > 2) { + std::cout << "ZS frag index = " << i + << ", detector = " << (isHPGe ? "HPGe" : "LaBr") << std::boolalpha + << ", parent available = " << parentState.available; + if (parentState.available) { + std::cout << ", raw index saved = " << parentState.index; + } + std::cout << "\n"; + } + // Extract zs variables from Raw Header bool skipCurrentSet = headerState.skipCurrentSet; bool zsInfoWasExtracted = headerState.containsZSInfo; @@ -591,6 +631,7 @@ void STMDigisFromFragments::produce(Event& event) isHPGe ? ++_totalZSFragsPrescaledHPGe : ++_totalZSFragsPrescaledLaBr; ++_totalZSFragsPrescaled; ++eventMetrics.zs.prescaled; + continue; } auto payloadPtr = stm_frag.payloadBegin(); @@ -645,14 +686,14 @@ void STMDigisFromFragments::produce(Event& event) while (dataPtr + 2 <= dataEndPtr){ - if (zsInfoWasExtracted && regionCounter >= zsRegions) { - break; - } + if (zsInfoWasExtracted && regionCounter >= zsRegions) { + break; + } uint16_t currentZSIndex = static_cast(dataPtr[0]); uint16_t currentZSLength = static_cast(dataPtr[1]); auto adc = dataPtr + 2; - if (adc + currentZSLength > dataEndPtr) { + if (currentZSLength > static_cast(dataEndPtr - adc)) { malformedZS = true; break; } @@ -709,7 +750,7 @@ void STMDigisFromFragments::produce(Event& event) } // Add exceptions - if (zsInfoWasExtracted && !zsPrescaled) { + if (zsInfoWasExtracted) { if (zsLength != zsTotalLengthCalculated) { throw cet::exception("STM_UNPACKING") << "\n=== ZS LENGTH MISMATCH ===\n" @@ -851,24 +892,15 @@ void STMDigisFromFragments::produce(Event& event) } // Check if PH Pair count matches expected count from raw header - size_t nPairsInFragment = payloadWords / 2; - if (extractedPHInfo && nPairsInFragment != phCount) { - if (_verbosityLevel > 2) { - std::cout << "\nSkipping PH pair due to mismatch in expected count at Event : " << _totalEvents << "\n" - << "Expected PH Pair Count : " << phCount << "\n" - << "Actual PH Pair Count : " << nPairsInFragment << "\n" - << "Frag Index : " << i << "\n" - << "---PH Frag\n"; - } - ++eventMetrics.ph.unread; - ++_totalUnreadInnerFrags; - continue; - } + size_t const nPairsInFragment = payloadWords / 2; + // Here you either read the lowest pair count from raw header or what is in fragment + // If not you read what what is in the fragment anyway + size_t const nPairsToRead = extractedPHInfo ? std::min(nPairsInFragment, phCount) : nPairsInFragment; // Check if zero filled // Since its a (time,PH) pair we will check every second entry for the PH value - for (size_t k = 1; k < payloadWords; k += 2) { - if (payloadPtr[k] !=0) { + for (size_t k = 0; k < nPairsToRead; ++k) { + if (payloadPtr[k*2+1] !=0) { allPHAreZeros = false; break; } @@ -895,7 +927,7 @@ void STMDigisFromFragments::produce(Event& event) std::cout << "Frag Index : " << i << "\n"; } - for (size_t i_phPair = 0; i_phPair < nPairsInFragment ; ++i_phPair){ + for (size_t i_phPair = 0; i_phPair < nPairsToRead ; ++i_phPair){ size_t i_PH = 2 * i_phPair; uint32_t time = static_cast(payloadPtr[i_PH]); int16_t const pulseHeight = payloadPtr[i_PH + 1]; @@ -977,7 +1009,7 @@ void STMDigisFromFragments::produce(Event& event) std::cout << "\nSaving STMFragSummary\n"; } stmFragSummaryHPGe->emplace_back( - ContainerFragsThisEvent,InnerFragsThisEvent, + containerFragsHPGeThisEvent,innerFragsHPGeThisEvent, badHPGeFragsThisEvent, missingHPGeFragsThisEvent, HPGeEventMetrics.zsFragsSkippedDueToRawFlag, HPGeEventMetrics.phFragsSkippedDueToRawFlag, HPGeEventMetrics.raw.good, HPGeEventMetrics.zs.good, HPGeEventMetrics.ph.good, @@ -986,7 +1018,7 @@ void STMDigisFromFragments::produce(Event& event) ); stmFragSummaryLaBr->emplace_back( - ContainerFragsThisEvent,InnerFragsThisEvent, + containerFragsLaBrThisEvent,innerFragsLaBrThisEvent, badLaBrFragsThisEvent, missingLaBrFragsThisEvent, LaBrEventMetrics.zsFragsSkippedDueToRawFlag, LaBrEventMetrics.phFragsSkippedDueToRawFlag, LaBrEventMetrics.raw.good, LaBrEventMetrics.zs.good, LaBrEventMetrics.ph.good, @@ -1035,6 +1067,7 @@ void STMDigisFromFragments::produce(Event& event) std::cout << "\n"; std::cout << "Bad Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedBadOnly << "\n"; std::cout << "Missing Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedMissingOnly << "\n"; + std::cout << "Bad and Missing Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedBadAndMissing << "\n"; std::cout << "\n"; std::cout << "\n--- Filtered Products (LaBr) ---\n"; @@ -1052,7 +1085,21 @@ void STMDigisFromFragments::produce(Event& event) std::cout << "\n"; std::cout << "Bad Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedBadOnly << "\n"; std::cout << "Missing Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedMissingOnly << "\n"; - + std::cout << "Bad and Missing Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedBadAndMissing << "\n"; + // Extra Filters + std::cout << "\n=== Extra Filters ===\n"; + std::cout << "Raw Frags With Invalid Headers (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidHeaders; + std::cout << "Raw Frags With Invalid Anchors (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidAnchors; + std::cout << "ZS Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.zsFragsSkippedDueToRawFlag; + std::cout << "PH Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.phFragsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.setsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (HPGe) : " << HPGeEventMetrics.setsSkippedDueToInvalidHeaders; + std::cout << "\n"; + std::cout << "Raw Frags With Invalid Headers (LaBr) : " << LaBrEventMetrics.rawFragsWithInvalidHeaders; + std::cout << "ZS Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.zsFragsSkippedDueToRawFlag; + std::cout << "PH Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.phFragsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.setsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (LaBr) : " << LaBrEventMetrics.setsSkippedDueToInvalidHeaders; std::cout << "=================================\n"; } @@ -1114,8 +1161,9 @@ void STMDigisFromFragments::endJob() { std::cout << "Total PH Frags Seen : " << _totalPHFragsSeen << "\n"; std::cout << "Total Raw Prescaled Frags : " << _totalRawFragsPrescaled << "\n"; std::cout << "Total ZS Prescaled Frags : " << _totalZSFragsPrescaled << "\n"; - std::cout << "Total Raw Frags Flagged Bad : " << _totalRawFragsFlaggedBadOnly << "\n"; - std::cout << "Total Raw Frags Flagged Missing : " << _totalRawFragsFlaggedMissingOnly << "\n"; + std::cout << "Total Raw Frags Flagged Bad Only : " << _totalRawFragsFlaggedBadOnly << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only : " << _totalRawFragsFlaggedMissingOnly << "\n"; + std::cout << "Total Raw Frags Flagged Bad And Missing : " << _totalRawFragsFlaggedBadAndMissing << "\n"; std::cout << "\n"; std::cout << "Total RAW Frags seen (HPGe) : " << _totalRawFragsSeenHPGe << "\n"; std::cout << "Total ZS Frags seen (HPGe) : " << _totalZSFragsSeenHPGe << "\n"; @@ -1125,6 +1173,20 @@ void STMDigisFromFragments::endJob() { std::cout << "Total ZS Frags seen (LaBr) : " << _totalZSFragsSeenLaBr << "\n"; std::cout << "Total PH Frags seen (LaBr) : " << _totalPHFragsSeenLaBr << "\n"; + // Data Type Summary - post-filtering (General) + std::cout << "\n--- Data Types Read General (Post - Filtering) ---\n"; + std::cout << "Total Good Raw Frags : " << _totalGoodRawFrags << "\n"; + std::cout << "Total Good ZS Frags : " << _totalGoodZSFrags << "\n"; + std::cout << "Total Good PH Frags : " << _totalGoodPHFrags << "\n"; + std::cout << "\n"; + std::cout << "Total Zero Raw Frags : " << _totalZeroRawFrags << "\n"; + std::cout << "Total Zero ZS Frags : " << _totalZeroZSFrags << "\n"; + std::cout << "Total Zero PH Frags : " << _totalZeroPHFrags << "\n"; + std::cout << "\n"; + std::cout << "Total Empty Raw Frags : " << _totalEmptyRawFrags << "\n"; + std::cout << "Total Empty ZS Frags : " << _totalEmptyZSFrags << "\n"; + std::cout << "Total Empty PH Frags : " << _totalEmptyPHFrags << "\n"; + // Data Type Summary - post-filtering (HPGe) std::cout << "\n--- Data Types Read HPGe (Post - Filtering) ---\n"; std::cout << "Total Good Raw Frags (HPGe) : " << _totalGoodRawFragsHPGe << "\n"; @@ -1140,9 +1202,11 @@ void STMDigisFromFragments::endJob() { std::cout << "Total Empty PH Frags (HPGe) : " << _totalEmptyPHFragsHPGe << "\n"; std::cout << "\n"; std::cout << "Total Raw Prescaled Frags (HPGe) : " << _totalRawFragsPrescaledHPGe << "\n"; + // Raw Prescaled Frags can still be considered good -> data simply was not sent + // Still be classified as good for now, however we do not save the waveform std::cout << "Total ZS Prescaled Frags (HPGe) : " << _totalZSFragsPrescaledHPGe << "\n"; - std::cout << "Total Raw Frags Flagged Bad (HPGe) : " << _totalRawFragsFlaggedBadOnlyHPGe << "\n"; - std::cout << "Total Raw Frags Flagged Missing (HPGe) : " << _totalRawFragsFlaggedMissingOnlyHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Bad Only (HPGe) : " << _totalRawFragsFlaggedBadOnlyHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only (HPGe) : " << _totalRawFragsFlaggedMissingOnlyHPGe << "\n"; std::cout << "Total Raw Frags Flagged Bad & Missing (HPGe) : " << _totalRawFragsFlaggedBadAndMissingHPGe << "\n"; // Data Type Summary - post-filtering (LaBr) @@ -1161,14 +1225,17 @@ void STMDigisFromFragments::endJob() { std::cout << "\n"; std::cout << "Total Raw Prescaled Frags (LaBr) : " << _totalRawFragsPrescaledLaBr << "\n"; std::cout << "Total ZS Prescaled Frags (LaBr) : " << _totalZSFragsPrescaledLaBr << "\n"; - std::cout << "Total Raw Frags Flagged Bad (LaBr) : " << _totalRawFragsFlaggedBadOnlyLaBr << "\n"; - std::cout << "Total Raw Frags Flagged Missing (LaBr) : " << _totalRawFragsFlaggedMissingOnlyLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Bad Only (LaBr) : " << _totalRawFragsFlaggedBadOnlyLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only (LaBr) : " << _totalRawFragsFlaggedMissingOnlyLaBr << "\n"; std::cout << "Total Raw Frags Flagged Bad & Missing (LaBr) : " << _totalRawFragsFlaggedBadAndMissingLaBr << "\n"; std::cout << "\n=== Extra Filters ===\n"; - std::cout << "Invalid Raw Headers : " << _totalRawFragsWithInvalidHeader << "\n"; - std::cout << "Invalid Raw Headers (HPGe) : " << _totalRawFragsWithInvalidHeaderHPGe << "\n"; - std::cout << "Invalid Raw Headers (LaBr) : " << _totalRawFragsWithInvalidHeaderLaBr << "\n"; + std::cout << "Invalid Raw Headers : " << _totalRawFragsWithInvalidHeaders << "\n"; + std::cout << "Invalid Raw Headers (HPGe) : " << _totalRawFragsWithInvalidHeadersHPGe << "\n"; + std::cout << "Invalid Raw Headers (LaBr) : " << _totalRawFragsWithInvalidHeadersLaBr << "\n"; + std::cout << "Invalid Raw Anchors : " << _totalRawFragsWithInvalidAnchors << "\n"; + std::cout << "Invalid Raw Anchors (HPGe) : " << _totalRawFragsWithInvalidAnchorsHPGe << "\n"; + std::cout << "Invalid Raw Anchors (LaBr) : " << _totalRawFragsWithInvalidAnchorsLaBr << "\n"; std::cout << "ZS Skipped Due to Raw Flag (HPGe) : " << _totalZSFragsSkippedDueToRawFlagHPGe << "\n"; std::cout << "ZS Skipped Due to Raw Flag (LaBr) : " << _totalZSFragsSkippedDueToRawFlagLaBr << "\n"; std::cout << "PH Skipped Due to Raw Flag (HPGe) : " << _totalPHFragsSkippedDueToRawFlagHPGe << "\n"; diff --git a/DAQ/test/inspectSTMFile.fcl b/DAQ/test/inspectSTMFile.fcl index 026394656f..63a1739205 100644 --- a/DAQ/test/inspectSTMFile.fcl +++ b/DAQ/test/inspectSTMFile.fcl @@ -27,17 +27,17 @@ physics : { 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" } } diff --git a/STMReco/fcl/plotSTMWaveformDigis.fcl b/STMReco/fcl/plotSTMWaveformDigis.fcl index e6b1bca596..dd8a615039 100644 --- a/STMReco/fcl/plotSTMWaveformDigis.fcl +++ b/STMReco/fcl/plotSTMWaveformDigis.fcl @@ -38,14 +38,6 @@ physics: { xAxis : "sample_number" } - plotPHWaveformDigisHPGe : { - module_type : PlotSTMWaveformDigis - stmWaveformDigisTag : "makeSTMDigis:phHPGe" - subtractPedestal : false - verbosityLevel : 0 - xAxis : "sample_number" - } - plotRawWaveformDigisLaBr : { module_type : PlotSTMWaveformDigis stmWaveformDigisTag : "makeSTMDigis:rawLaBr" @@ -61,14 +53,6 @@ physics: { verbosityLevel : 0 xAxis : "sample_number" } - - plotPHWaveformDigisLaBr : { - module_type : PlotSTMWaveformDigis - stmWaveformDigisTag : "makeSTMDigis:phLaBr" - subtractPedestal : false - verbosityLevel : 0 - xAxis : "sample_number" - } } # setup paths diff --git a/STMReco/src/PlotSTMWaveformDigis_module.cc b/STMReco/src/PlotSTMWaveformDigis_module.cc index 9fb9437c79..046d8e0964 100644 --- a/STMReco/src/PlotSTMWaveformDigis_module.cc +++ b/STMReco/src/PlotSTMWaveformDigis_module.cc @@ -122,12 +122,20 @@ namespace mu2e { //None empty waveforms go in here _hist->Fill(waveform.adcs().size()); //_hist was created outside so there should be no problem here - Binning binning = STMUtils::getBinning(waveform, _xAxis, nsPerCt); - TH1F* hWaveform = tfs->make(histname.str().c_str(), histtitle.str().c_str(), binning.nbins(),binning.low(),binning.high()); + Binning binning = STMUtils::getBinning(waveform, _xAxis, nsPerCt);//nanoSecondPerCount + TH1F* hWaveform = tfs->make(histname.str().c_str(), histtitle.str().c_str(), + binning.nbins(), binning.low(), binning.high()); TH1F* hWaveformOffset = nullptr; // Standby hWaveform->GetYaxis()->SetTitle("ADCs"); - hWaveform->GetXaxis()->SetTitle("Sample Number"); + if (_xAxis == "sample_number"){ + hWaveform->GetXaxis()->SetTitle("Sample Number"); + + } else if (_xAxis == "waveform_time [nsec]"){ + hWaveform->GetXaxis()->SetTitle("Waveform Time"); + } else if (_xAxis == "event_time"){ + hWaveform->GetXaxis()->SetTitle("Event Time[nsec]"); + } if (plotZSOffsetWaveforms){ //For offset waveforms -> Better organize this area @@ -147,7 +155,7 @@ namespace mu2e { hWaveformOffset = tfs->make( histname2.str().c_str(), histtitle2.str().c_str(), binning.nbins(), binning.low()+zs_offset, binning.high()+zs_offset );//Shifting bins using offset hWaveformOffset->GetYaxis()->SetTitle("ADCs"); - hWaveformOffset->GetXaxis()->SetTitle("Sample Number (Includes + trigtimeOffset"); + hWaveformOffset->GetXaxis()->SetTitle("Sample Number (Includes + Time Offset)"); // int n_bins = hWaveformOffset->GetNbinsX(); //Grabs already contained nbins from waveform //double xmin = hWaveformOffset->GetXaxis()->GetXmin();// gets xmin from waveform //double xmax = hWaveformOffset->GetXaxis()->GetXmax();//gets xman from waveform @@ -156,9 +164,8 @@ namespace mu2e { for (size_t i_adc = 0; i_adc < waveform.adcs().size(); ++i_adc){ - const auto adc = waveform.adcs().at(i_adc); - auto content = adc; + auto content = adc; //y-axis if (_subtractPedestal) { content -= pedestal; } From 89d894299b5c0f05f674f522c8bd027f550fda82 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Wed, 12 Aug 2026 12:34:17 -0500 Subject: [PATCH 04/21] Saving changes to the files before rebuilding --- DAQ/src/STMDigisFromFragments_module.cc | 22 +++++++++++++++------- STMReco/fcl/plotSTMWaveformDigis.fcl | 20 ++++++++++---------- STMReco/src/PlotSTMPHSpectrum_module.cc | 8 ++++---- STMReco/src/PlotSTMWaveformDigis_module.cc | 19 +++++++++++++------ 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index b94ce7bbda..ea564e0a84 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -557,7 +557,7 @@ void STMDigisFromFragments::produce(Event& event) } //Throw out if ZSLengthfromRaw != totalLen, throw out if length mismatch - if (readZSinfoFromRawHeader && stm_frag.zsPrescaled() == 0){ + if (readZSinfoFromRawHeader){ if (expectedZSLength != totalLen){ throw cet::exception("STM_UNPACKING") << "\n=== ZS Length count mismatch ===\n" @@ -626,15 +626,23 @@ void STMDigisFromFragments::produce(Event& event) if (_verbosityLevel >= 3){std::cout << "\nFound a good frag, i = " << i <<" @PH\n";} - if ( stm_frag.isHPGe() ){ ++ _totalGoodPHHPGe; ++goodPHHPGeFrags; } - else if ( stm_frag.isLaBr() ) { ++ _totalGoodPHLaBr; ++goodPHLaBrFrags; } - size_t digiWords = stm_frag.payloadWords(); auto const* digiPtr = stm_frag.payloadBegin(); - for (size_t i_PH = 0; i_PH < digiWords ; ++i_PH){ - int16_t PH = digiPtr[i_PH]; - mu2e::STMPHDigi PH_digi(0, PH); + if (digiWords % 2 !=0){ + if (_verbosityLevel >=3){ + std::cout << "Found a malformmed frag of PH Digis" << std::endl; + } + continue; + } + + if ( stm_frag.isHPGe() ){ ++ _totalGoodPHHPGe; ++goodPHHPGeFrags; } + else if ( stm_frag.isLaBr() ) { ++ _totalGoodPHLaBr; ++goodPHLaBrFrags; } + + for (size_t i_PH = 0; i_PH + 1 < digiWords ; i_PH += 2){ + uint32_t time = static_cast(digiPtr[i_PH]); + int16_t PH = digiPtr[i_PH + 1]; + mu2e::STMPHDigi PH_digi(time, PH); if( stm_frag.isHPGe() ){ ph_HPGe_digis->emplace_back(PH_digi); } diff --git a/STMReco/fcl/plotSTMWaveformDigis.fcl b/STMReco/fcl/plotSTMWaveformDigis.fcl index e6b1bca596..4c1fc9f269 100644 --- a/STMReco/fcl/plotSTMWaveformDigis.fcl +++ b/STMReco/fcl/plotSTMWaveformDigis.fcl @@ -14,7 +14,7 @@ source : { services : { @table::Services.Core - TFileService : { fileName : "stmWaveformDigis.root" } + TFileService : { fileName : "data/stmWaveformDigis.root" } } physics: { @@ -29,6 +29,14 @@ physics: { verbosityLevel : 0 xAxis : "sample_number" } + + plotRawWaveformDigisTimeHPGe : { + module_type : PlotSTMWaveformDigis + stmWaveformDigisTag : "makeSTMDigis:rawHPGe" + subtractPedestal : false + verbosityLevel : 0 + xAxis: "waveform_time" + } plotZSWaveformDigisHPGe : { module_type : PlotSTMWaveformDigis @@ -61,19 +69,11 @@ physics: { verbosityLevel : 0 xAxis : "sample_number" } - - plotPHWaveformDigisLaBr : { - module_type : PlotSTMWaveformDigis - stmWaveformDigisTag : "makeSTMDigis:phLaBr" - subtractPedestal : false - verbosityLevel : 0 - xAxis : "sample_number" - } } # setup paths trigger_paths: [ ] - anaPath : [ plotRawWaveformDigisHPGe, plotZSWaveformDigisHPGe, plotRawWaveformDigisLaBr, plotZSWaveformDigisLaBr ] + anaPath : [ plotRawWaveformDigisHPGe, plotRawWaveformDigisTimeHPGe, plotRawWaveformDigisEvTimeHPGe, plotZSWaveformDigisHPGe, plotRawWaveformDigisLaBr, plotZSWaveformDigisLaBr ] end_paths: [anaPath] } diff --git a/STMReco/src/PlotSTMPHSpectrum_module.cc b/STMReco/src/PlotSTMPHSpectrum_module.cc index f53ab20340..bd20c44a2a 100644 --- a/STMReco/src/PlotSTMPHSpectrum_module.cc +++ b/STMReco/src/PlotSTMPHSpectrum_module.cc @@ -59,10 +59,10 @@ namespace mu2e { void PlotSTMPHSpectrum::beginJob() { art::ServiceHandle tfs; // create histograms - _phSpectrum=tfs->make("phSpectrum", "PH Spectrum", 600, -300, 300); - _twoDhist=tfs->make("twoDhist","Pulse Height vs events;Event Bins; Pulse Height", - 1000,-1000,1000, // X-axis scale - 1000,0,1e5); // Y-axis scale + _phSpectrum=tfs->make("phSpectrum", "PH Spectrum;PulseHeight;Count", 10000, -10000, 0); //bins,min,max + _twoDhist=tfs->make("phEvent","Pulse Height vs events;Event Bins; Pulse Height", // (name, title;xtitle;ytitle, nbinsX, xlow, xup, nbinsY, ylow, yup) + 2000,-1000,1000, // X-axis scale + 10000,-10000,0); // Y-axis scale } void PlotSTMPHSpectrum::analyze(const art::Event& event) { diff --git a/STMReco/src/PlotSTMWaveformDigis_module.cc b/STMReco/src/PlotSTMWaveformDigis_module.cc index 9fb9437c79..046d8e0964 100644 --- a/STMReco/src/PlotSTMWaveformDigis_module.cc +++ b/STMReco/src/PlotSTMWaveformDigis_module.cc @@ -122,12 +122,20 @@ namespace mu2e { //None empty waveforms go in here _hist->Fill(waveform.adcs().size()); //_hist was created outside so there should be no problem here - Binning binning = STMUtils::getBinning(waveform, _xAxis, nsPerCt); - TH1F* hWaveform = tfs->make(histname.str().c_str(), histtitle.str().c_str(), binning.nbins(),binning.low(),binning.high()); + Binning binning = STMUtils::getBinning(waveform, _xAxis, nsPerCt);//nanoSecondPerCount + TH1F* hWaveform = tfs->make(histname.str().c_str(), histtitle.str().c_str(), + binning.nbins(), binning.low(), binning.high()); TH1F* hWaveformOffset = nullptr; // Standby hWaveform->GetYaxis()->SetTitle("ADCs"); - hWaveform->GetXaxis()->SetTitle("Sample Number"); + if (_xAxis == "sample_number"){ + hWaveform->GetXaxis()->SetTitle("Sample Number"); + + } else if (_xAxis == "waveform_time [nsec]"){ + hWaveform->GetXaxis()->SetTitle("Waveform Time"); + } else if (_xAxis == "event_time"){ + hWaveform->GetXaxis()->SetTitle("Event Time[nsec]"); + } if (plotZSOffsetWaveforms){ //For offset waveforms -> Better organize this area @@ -147,7 +155,7 @@ namespace mu2e { hWaveformOffset = tfs->make( histname2.str().c_str(), histtitle2.str().c_str(), binning.nbins(), binning.low()+zs_offset, binning.high()+zs_offset );//Shifting bins using offset hWaveformOffset->GetYaxis()->SetTitle("ADCs"); - hWaveformOffset->GetXaxis()->SetTitle("Sample Number (Includes + trigtimeOffset"); + hWaveformOffset->GetXaxis()->SetTitle("Sample Number (Includes + Time Offset)"); // int n_bins = hWaveformOffset->GetNbinsX(); //Grabs already contained nbins from waveform //double xmin = hWaveformOffset->GetXaxis()->GetXmin();// gets xmin from waveform //double xmax = hWaveformOffset->GetXaxis()->GetXmax();//gets xman from waveform @@ -156,9 +164,8 @@ namespace mu2e { for (size_t i_adc = 0; i_adc < waveform.adcs().size(); ++i_adc){ - const auto adc = waveform.adcs().at(i_adc); - auto content = adc; + auto content = adc; //y-axis if (_subtractPedestal) { content -= pedestal; } From c07cd3289923e933ef268ef0928ea166ee617b3d Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Wed, 12 Aug 2026 13:25:44 -0500 Subject: [PATCH 05/21] New muse config --- .muse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.muse b/.muse index 5a508dd6aa..925feef0c4 100644 --- a/.muse +++ b/.muse @@ -1,5 +1,5 @@ # prefer to build with this environment -ENVSET p101 +ENVSET p106 # add Offline/bin to path PATH bin # recent commits can take enforce these flags From 685c2c196bcefc2a94837305566d183d79ffe292 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Wed, 12 Aug 2026 17:36:16 -0500 Subject: [PATCH 06/21] Changes to Unpacking for better quakity and readbility Also changed STMPrint to have three general options for debugging --- DAQ/src/STMDigisFromFragments_module.cc | 1949 ++++++++++++++--------- DAQ/src/STMPrintFragments_module.cc | 6 +- 2 files changed, 1186 insertions(+), 769 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index ea564e0a84..1bbcd822c8 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -1,4 +1,4 @@ -// ===================================================================== +// ==================================================================== // // STMDigisFromFragments: create all types of STMDigis from STMFragments // @@ -28,806 +28,1223 @@ #include #include +// This is version 2 +// Meant to clean up and make the code more maintainable and readable + namespace art { - class STMDigisFromFragments; + class STMDigisFromFragments; } - using art::STMDigisFromFragments; class art::STMDigisFromFragments : public EDProducer { public: - struct Config { - fhicl::Atom stmTag {fhicl::Name("stmTag"), fhicl::Comment("Input module")}; - fhicl::OptionalAtom verbosityLevel{fhicl::Name("verbosityLevel"), fhicl::Comment("Verbosity level")}; - fhicl::Atom saveSTMFragSummary{fhicl::Name("saveSTMFragSummary"),false}; - - fhicl::Atom saveRawWithHeaderWaveform_HPGe {fhicl::Name("saveRawWithHeaderWaveform_HPGe"), false}; - fhicl::Atom saveRawWaveform_HPGe {fhicl::Name("saveRawWaveform_HPGe"), false}; - fhicl::Atom saveZSWaveform_HPGe{fhicl::Name("saveZSWaveform_HPGe"), false}; - - fhicl::Atom saveRawWithHeaderWaveform_LaBr{fhicl::Name("saveRawWithHeaderWaveform_LaBr"), false}; - fhicl::Atom saveRawWaveform_LaBr{fhicl::Name("saveRawWaveform_LaBr"), false}; - fhicl::Atom saveZSWaveform_LaBr{fhicl::Name("saveZSWaveform_LaBr"), false}; - - }; - - explicit STMDigisFromFragments(const art::EDProducer::Table& config); // constructor created, config via fcl - virtual void produce(Event &) override; - void endJob() override; + struct Config { + //General Configs + fhicl::Atom stmTag {fhicl::Name("stmTag"), fhicl::Comment("Input module")}; + fhicl::OptionalAtom verbosityLevel {fhicl::Name("verbosityLevel"), + fhicl::Comment("Verbosity Level for debugging purposes")}; + fhicl::Atom saveSTMFragSummary{fhicl::Name("saveSTMFragSummary"), + fhicl::Comment("Whether to save Fragment Summary"), false}; + + //HPGe Configs + fhicl::Atom saveRawWaveformsWithHeaderHPGe {fhicl::Name("saveRawWaveformsWithHeaderHPGe"), + fhicl::Comment("Whether to save raw fragment waveforms with header for HPGe for debugging purposes"), false}; + fhicl::Atom saveRawWaveformsHPGe {fhicl::Name("saveRawWaveformsHPGe"), + fhicl::Comment("Whether to save raw waveforms for HPGe for debugging purposes"), false}; + fhicl::Atom saveZSWaveformsHPGe {fhicl::Name("saveZSWaveformsHPGe"), + fhicl::Comment("Whether to save zero-suppressed waveforms for HPGe for debugging purposes"), false}; + + //LaBr Configs + fhicl::Atom saveRawWaveformsWithHeaderLaBr {fhicl::Name("saveRawWaveformsWithHeaderLaBr"), + fhicl::Comment("Whether to save raw fragment waveforms with header for LaBr for debugging purposes"), false}; + fhicl::Atom saveRawWaveformsLaBr {fhicl::Name("saveRawWaveformsLaBr"), + fhicl::Comment("Whether to save raw waveforms for LaBr for debugging purposes"), false}; + fhicl::Atom saveZSWaveformsLaBr {fhicl::Name("saveZSWaveformsLaBr"), + fhicl::Comment("Whether to save zero-suppressed waveforms for LaBr for debugging purposes"), false}; + }; + + explicit STMDigisFromFragments (const art::EDProducer::Table& config); + virtual void produce(Event &) override; + void endJob() override; private: - art::InputTag _stmFragmentsTag; - - //Metrics - size_t _totalEvents{0}; - size_t _totalFragments{0}; - size_t _totalContainers{0}; - size_t _totalContainersHPGe{0}; - size_t _totalContainersLaBr{0}; - size_t _totalInner{0}; - size_t _totalRaw{0}; - size_t _totalZS{0}; - size_t _totalPH{0}; - size_t _totalZeroRaw{0}; - size_t _totalZeroZS{0}; - size_t _totalZeroPH{0}; - size_t _totalEmptyRaw{0}; - size_t _totalEmptyZS{0}; - size_t _totalEmptyPH{0}; - size_t _unreadInnerFrags{0}; - size_t _totalEventsWithHPGeLaBr{0}; - size_t _totalEventsWithOnlyHPGe{0}; - size_t _totalEventsWithOnlyLaBr{0}; - size_t _totalEventsWithNone{0}; - size_t _totalNonContainerFrags{0}; - - //Additional metrics - //HPGe - size_t _totalRawHPGe{0}; - size_t _totalZSHPGe{0}; - size_t _totalPHHPGe{0}; - size_t _totalGoodRawHPGe{0}; - size_t _totalGoodZSHPGe{0}; - size_t _totalGoodPHHPGe{0}; - size_t _totalZeroRawHPGe{0}; - size_t _totalZeroZSHPGe{0}; - size_t _totalZeroPHHPGe{0}; - size_t _totalEmptyRawHPGe{0}; - size_t _totalEmptyZSHPGe{0}; - size_t _totalEmptyPHHPGe{0}; - - //LaBr - size_t _totalRawLaBr{0}; - size_t _totalZSLaBr{0}; - size_t _totalPHLaBr{0}; - size_t _totalGoodRawLaBr{0}; - size_t _totalGoodZSLaBr{0}; - size_t _totalGoodPHLaBr{0}; - size_t _totalZeroRawLaBr{0}; - size_t _totalZeroZSLaBr{0}; - size_t _totalZeroPHLaBr{0}; - size_t _totalEmptyRawLaBr{0}; - size_t _totalEmptyZSLaBr{0}; - size_t _totalEmptyPHLaBr{0}; - - //fhicl varibales - bool _saveRawWithHeaderWaveform_HPGe{false}; - bool _saveRawWaveform_HPGe{false}; - bool _saveZSWaveform_HPGe{false}; - bool _saveRawWithHeaderWaveform_LaBr{false}; - bool _saveRawWaveform_LaBr{false}; - bool _saveZSWaveform_LaBr{false}; - bool _saveSTMFragSummary{false}; - int _verbosityLevel{0}; + // art input tags + art::InputTag _stmFragmentsTag; + + // Fhicl parameters + int _verbosityLevel{0}; + bool _saveSTMFragSummary{false}; + // HPGe fhicl parameters + bool _saveRawWaveformsWithHeaderHPGe{false}; + bool _saveRawWaveformsHPGe{false}; + bool _saveZSWaveformsHPGe{false}; + // LaBr fhicl parameters + bool _saveRawWaveformsWithHeaderLaBr{false}; + bool _saveRawWaveformsLaBr{false}; + bool _saveZSWaveformsLaBr{false}; + + // General Fragment variables + size_t _totalEvents{0}; + size_t _totalNonContainers{0}; + size_t _totalFragments{0}; + size_t _totalContainers{0}; + size_t _totalInnerFrags{0}; + size_t _totalUnreadInnerFrags{0}; + size_t _totalRawFragsSeen{0}; + size_t _totalZSFragsSeen{0}; + size_t _totalPHFragsSeen{0}; + size_t _totalGoodRawFrags{0}; + size_t _totalGoodZSFrags{0}; + size_t _totalGoodPHFrags{0}; + size_t _totalZeroRawFrags{0}; + size_t _totalZeroZSFrags{0}; + size_t _totalZeroPHFrags{0}; + size_t _totalEmptyRawFrags{0}; + size_t _totalEmptyZSFrags{0}; + size_t _totalEmptyPHFrags{0}; + + // Header-related variables + size_t _totalRawFragsPrescaled{0}; + size_t _totalZSFragsPrescaled{0}; + size_t _totalRawFragsFlaggedBadOnly{0}; + size_t _totalRawFragsFlaggedMissingOnly{0}; + size_t _totalRawFragsFlaggedBadAndMissing{0}; + size_t _totalRawFragsWithInvalidHeaders{0}; + size_t _totalRawFragsWithInvalidAnchors{0}; + + // Detector Summary variables + size_t _totalEventsWithBothDetectors{0}; + size_t _totalEventsWithOnlyHPGe{0}; + size_t _totalEventsWithOnlyLaBr{0}; + size_t _totalEventsWithNeitherDetector{0}; // Should sum to total art events + + // HPGe job-level variables + size_t _totalContainersHPGe{0}; + size_t _totalInnerFragsHPGe{0}; + size_t _totalRawFragsSeenHPGe{0}; + size_t _totalZSFragsSeenHPGe{0}; + size_t _totalPHFragsSeenHPGe{0}; + size_t _totalGoodRawFragsHPGe{0};//Good means fragment has data + size_t _totalGoodZSFragsHPGe{0}; + size_t _totalGoodPHFragsHPGe{0}; + size_t _totalZeroRawFragsHPGe{0};// Zero means fragment has data but all values are zero + size_t _totalZeroZSFragsHPGe{0}; + size_t _totalZeroPHFragsHPGe{0}; + size_t _totalEmptyRawFragsHPGe{0};// Empty means fragment has no data + size_t _totalEmptyZSFragsHPGe{0}; + size_t _totalEmptyPHFragsHPGe{0}; + size_t _totalRawFragsFlaggedBadOnlyHPGe{0}; + size_t _totalRawFragsFlaggedMissingOnlyHPGe{0}; + size_t _totalRawFragsFlaggedBadAndMissingHPGe{0}; + size_t _totalRawFragsWithInvalidHeadersHPGe{0}; + size_t _totalRawFragsWithInvalidAnchorsHPGe{0}; + size_t _totalZSFragsSkippedDueToRawFlagHPGe{0};// We want to skip ZS if raw is flagged bad/missing + size_t _totalPHFragsSkippedDueToRawFlagHPGe{0};// We want to skip PH if raw is flagged bad/missing + size_t _totalRawFragsPrescaledHPGe{0};// track how many raw fragments were prescaled + size_t _totalZSFragsPrescaledHPGe{0};// track how many zs fragments were prescaled + + // LaBr job-level variables + size_t _totalContainersLaBr{0}; + size_t _totalInnerFragsLaBr{0}; + size_t _totalRawFragsSeenLaBr{0}; + size_t _totalZSFragsSeenLaBr{0}; + size_t _totalPHFragsSeenLaBr{0}; + size_t _totalGoodRawFragsLaBr{0};//Good means fragment has data + size_t _totalGoodZSFragsLaBr{0}; + size_t _totalGoodPHFragsLaBr{0}; + size_t _totalZeroRawFragsLaBr{0};// Zero means fragment has data but all values are zero + size_t _totalZeroZSFragsLaBr{0}; + size_t _totalZeroPHFragsLaBr{0}; + size_t _totalEmptyRawFragsLaBr{0};// Empty means fragment has no data + size_t _totalEmptyZSFragsLaBr{0}; + size_t _totalEmptyPHFragsLaBr{0}; + size_t _totalRawFragsFlaggedBadOnlyLaBr{0}; + size_t _totalRawFragsFlaggedMissingOnlyLaBr{0}; + size_t _totalRawFragsFlaggedBadAndMissingLaBr{0}; + size_t _totalRawFragsWithInvalidHeadersLaBr{0}; + size_t _totalRawFragsWithInvalidAnchorsLaBr{0}; + size_t _totalZSFragsSkippedDueToRawFlagLaBr{0};// We want to skip ZS if raw is flagged bad/missing + size_t _totalPHFragsSkippedDueToRawFlagLaBr{0};// We want to skip PH if raw is flagged bad/missing + size_t _totalRawFragsPrescaledLaBr{0};// track how many raw fragments were prescaled + size_t _totalZSFragsPrescaledLaBr{0};// track how many ZS fragments were prescaled + + // Used to set and verify the state of the raw parent fragment for zs fragments, event based + struct RawParentState { + art::Ptr ptr; + art::ProductID productID; + size_t index{0}; + bool available{false}; + }; + + // Used to save ZS information + struct ZSRegion{ + uint32_t offset; + std::vector adcs; + }; + + // Used to track the expected raw header information, event based + struct RawHeaderState { + uint16_t expectedZSLength{0}; + uint16_t expectedZSRegions{0}; + uint16_t expectedPHCount{0}; + + bool containsZSInfo{false}; + bool containsPHInfo{false}; + + bool rawPrescaled{false}; + bool zsPrescaled{false}; + + uint16_t rawPrescaleValue{0}; + uint16_t zsPrescaleValue{0}; + + bool rawHeaderIsValid{false}; + bool skipCurrentSet{false}; + }; + + struct FragmentCounters { + size_t seen{0}; + size_t prescaled{0}; + size_t unread{0}; + size_t empty{0}; + size_t zero{0}; + size_t good{0}; + }; + + struct DetectorSpecificEventMetrics { + FragmentCounters raw; + FragmentCounters zs; + FragmentCounters ph; + + size_t rawFragsFlaggedBadOnly{0}; + size_t rawFragsFlaggedMissingOnly{0}; + size_t rawFragsFlaggedBadAndMissing{0}; + size_t rawFragsWithInvalidHeaders{0}; + size_t rawFragsWithInvalidAnchors{0}; + size_t zsFragsSkippedDueToRawFlag{0}; + size_t phFragsSkippedDueToRawFlag{0}; + size_t setsSkippedDueToRawFlag{0}; + size_t setsSkippedDueToInvalidHeaders{0}; + + }; }; // STMDigisFromFragments -// ====================================================================== - - +// Configuration section +// ===================== STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table& config) - : art::EDProducer{config} - ,_stmFragmentsTag(config().stmTag()) - ,_saveRawWithHeaderWaveform_HPGe(config().saveRawWithHeaderWaveform_HPGe()) - ,_saveRawWaveform_HPGe(config().saveRawWaveform_HPGe()) - ,_saveZSWaveform_HPGe(config().saveZSWaveform_HPGe()) - ,_saveRawWithHeaderWaveform_LaBr(config().saveRawWithHeaderWaveform_LaBr()) - ,_saveRawWaveform_LaBr(config().saveRawWaveform_LaBr()) - ,_saveZSWaveform_LaBr(config().saveZSWaveform_LaBr()) - ,_saveSTMFragSummary(config().saveSTMFragSummary()) - ,_verbosityLevel(config().verbosityLevel() ? *(config().verbosityLevel()) : 0) - + :art::EDProducer{config} + ,_stmFragmentsTag(config().stmTag()) + ,_verbosityLevel(config().verbosityLevel() ? *(config().verbosityLevel()) : 0) + ,_saveSTMFragSummary(config().saveSTMFragSummary()) + ,_saveRawWaveformsWithHeaderHPGe(config().saveRawWaveformsWithHeaderHPGe()) + ,_saveRawWaveformsHPGe(config().saveRawWaveformsHPGe()) + ,_saveZSWaveformsHPGe(config().saveZSWaveformsHPGe()) + ,_saveRawWaveformsWithHeaderLaBr(config().saveRawWaveformsWithHeaderLaBr()) + ,_saveRawWaveformsLaBr(config().saveRawWaveformsLaBr()) + ,_saveZSWaveformsLaBr(config().saveZSWaveformsLaBr()) + // PH digis are always produced { - if (_saveSTMFragSummary) { - produces("stmFragSummaryHPGe"); - produces("stmFragSummaryLaBr"); - } - // Set the size of vectors for HPGe - if (_saveRawWithHeaderWaveform_HPGe){produces("rawWithHeaderHPGe");} - if (_saveRawWaveform_HPGe){produces("rawHPGe");}//Waveforms - if (_saveZSWaveform_HPGe){produces("zsHPGe");} - produces("phHPGe"); // digi series - - - //Set the size of vectors for LaBr - if (_saveRawWithHeaderWaveform_LaBr){produces("rawWithHeaderLaBr");} - if (_saveRawWaveform_LaBr){produces("rawLaBr");} - if (_saveZSWaveform_LaBr){produces("zsLaBr");} - produces("phLaBr"); // digi series - + // Products depending on configuration switches + if (_saveSTMFragSummary){ + produces("stmFragSummaryHPGe"); + produces("stmFragSummaryLaBr"); + } + // HPGe + if (_saveRawWaveformsWithHeaderHPGe){ produces("rawWithHeaderHPGe"); } + if (_saveRawWaveformsHPGe){ produces("rawHPGe"); } + if (_saveZSWaveformsHPGe){ produces("zsHPGe"); } + produces("phHPGe"); + // LaBr + if (_saveRawWaveformsWithHeaderLaBr){ produces("rawWithHeaderLaBr"); } + if (_saveRawWaveformsLaBr){ produces("rawLaBr"); } + if (_saveZSWaveformsLaBr){ produces("zsLaBr"); } + produces("phLaBr"); } -// ---------------------------------------------------------------------- - +// Start of Event processing +// ========================= void STMDigisFromFragments::produce(Event& event) { + // extra frag counters for this event + size_t containerFragsThisEvent{0}; + size_t containerFragsHPGeThisEvent{0}; + size_t containerFragsLaBrThisEvent{0}; + size_t innerFragsThisEvent{0}; + size_t innerFragsHPGeThisEvent{0}; + size_t innerFragsLaBrThisEvent{0}; + // Quality of frags + //size_t unknownFragsThisEvent{0}; + size_t badHPGeFragsThisEvent{0}; + size_t missingHPGeFragsThisEvent{0}; + size_t badLaBrFragsThisEvent{0}; + size_t missingLaBrFragsThisEvent{0}; + + ++_totalEvents; // Increments total event counter + + // Each RawParentState keeps track of the last Raw Fragment + RawParentState rawParentHPGe; + RawParentState rawParentLaBr; + RawHeaderState rawHeaderHPGe; + RawHeaderState rawHeaderLaBr; + DetectorSpecificEventMetrics LaBrEventMetrics; + DetectorSpecificEventMetrics HPGeEventMetrics; + + // Set product ID + if (_saveRawWaveformsHPGe){ + rawParentHPGe.productID = event.getProductID("rawHPGe"); + } + if (_saveRawWaveformsLaBr){ + rawParentLaBr.productID = event.getProductID("rawLaBr"); + } - art::Ptr lastRawHPGePtr; - art::Ptr lastRawLaBrPtr; - - bool haveLastRawHPGePtr{false}; - bool haveLastRawLaBrPtr{false}; - - std::vector zsToRawIndexHPGe; // creates vector - std::vector zsToRawIndexLaBr; - ++_totalEvents; //Increment Total Event Counter - - //Frag Summaries - std::unique_ptr stmFragSummaryHPGe(new mu2e::STMFragmentSummaryCollection); - std::unique_ptr stmFragSummaryLaBr(new mu2e::STMFragmentSummaryCollection); - //HPGe - std::unique_ptr raw_HPGe_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr zs_HPGe_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr ph_HPGe_digis(new mu2e::STMPHDigiCollection); - std::unique_ptr raw_HPGe_header_waveform_digis(new mu2e::STMWaveformDigiCollection); - - //LaBr - std::unique_ptr raw_LaBr_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr zs_LaBr_waveform_digis(new mu2e::STMWaveformDigiCollection); - std::unique_ptr ph_LaBr_digis(new mu2e::STMPHDigiCollection); - std::unique_ptr raw_LaBr_header_waveform_digis(new mu2e::STMWaveformDigiCollection); - - art::Handle STMFragmentsH; - event.getByLabel(_stmFragmentsTag, STMFragmentsH); - const auto& STMFragments = STMFragmentsH.product(); - - auto rawHPGeProductID = event.getProductID("rawHPGe"); - auto rawLaBrProductID = event.getProductID("rawLaBr"); - - //Event Metrics - - //HPGe - size_t totalRawHPGeFrags{0}; - size_t totalZSHPGeFrags{0}; - size_t totalPHHPGeFrags{0}; - size_t goodRawHPGeFrags{0}; - size_t goodZSHPGeFrags{0}; - size_t goodPHHPGeFrags{0}; - size_t zeroRawHPGeFrags{0}; - size_t zeroZSHPGeFrags{0}; - size_t zeroPHHPGeFrags{0}; - size_t emptyRawHPGeFrags{0}; - size_t emptyZSHPGeFrags{0}; - size_t emptyPHHPGeFrags{0}; - - //LaBr - size_t totalRawLaBrFrags{0}; - size_t totalZSLaBrFrags{0}; - size_t totalPHLaBrFrags{0}; - size_t goodRawLaBrFrags{0}; - size_t goodZSLaBrFrags{0}; - size_t goodPHLaBrFrags{0}; - size_t zeroRawLaBrFrags{0}; - size_t zeroZSLaBrFrags{0}; - size_t zeroPHLaBrFrags{0}; - size_t emptyRawLaBrFrags{0}; - size_t emptyZSLaBrFrags{0}; - size_t emptyPHLaBrFrags{0}; - - //Additional - size_t unread_InnerFrags{0}; - uint16_t outerFragID{0}; - bool eventHasHPGe{false}; - bool eventHasLaBr{false}; - - //HPGe - uint16_t expectedZSLengthHPGe{0}; - uint16_t expectedZSRegionsHPGe{0}; - bool readZSinfoFromRawHeaderHPGe{false}; - - //LaBr - uint16_t expectedZSLengthLaBr{0}; - uint16_t expectedZSRegionsLaBr{0}; - bool readZSinfoFromRawHeaderLaBr{false}; - - //Frag counters - size_t nContainerFragsThisEvent{0}; - size_t nInnerFragsThisEvent{0}; - - //loop over outer frags - for (const auto& frag : *STMFragments) { - ++_totalFragments; //Increment Total Frag counter - - outerFragID = frag.fragmentID(); - if (_verbosityLevel >= 3){std::cout << "\nFrag_id : " << outerFragID << "\n";} - - - //Check if this is a container fragment - if (frag.type() == artdaq::Fragment::ContainerFragmentType){ - - mu2e::STMFragment container_frag(frag); - if ( container_frag.isHPGeContainer()){ ++_totalContainersHPGe; eventHasHPGe = true; } - else if ( container_frag.isLaBrContainer() ) { ++_totalContainersLaBr; eventHasLaBr = true; } - else { - if (_verbosityLevel >= 1){ - std::cout << "Encounter an unknown STM Container frag ID\n" - << "Frag ID : " << frag.fragmentID() <<"\n" - << "Event : " << _totalEvents <<"\n"; - } - continue; - } - artdaq::ContainerFragment cont_frag(frag); - ++_totalContainers; - ++nContainerFragsThisEvent; - size_t blocks = cont_frag.block_count(); - _totalInner += blocks; - nInnerFragsThisEvent += blocks; - - //loop over container where i corresponds to inner frag - for (size_t i = 0; i < cont_frag.block_count(); ++i){ - - auto inner_frag = cont_frag.at(i); - mu2e::STMFragment stm_frag(*inner_frag); - mu2e::STMWaveformDigi stm_waveform; - - if ( stm_frag.isRaw() ) { - - if (stm_frag.isHPGe()){ - readZSinfoFromRawHeaderHPGe = false; - expectedZSLengthHPGe = 0; - expectedZSRegionsHPGe = 0; - } else if (stm_frag.isLaBr()){ - readZSinfoFromRawHeaderLaBr = false; - expectedZSLengthLaBr = 0; - expectedZSRegionsLaBr = 0; - } - //Job Counter - ++_totalRaw; - - //Conditional Job and Event Counter - if( stm_frag.isHPGe() ){ - ++_totalRawHPGe ; - ++totalRawHPGeFrags; - - } else if ( stm_frag.isLaBr() ){ - ++_totalRawLaBr ; - ++totalRawLaBrFrags; - } - - auto payloadPtr = stm_frag.payloadBegin(); - auto payloadWords = stm_frag.payloadWords(); - bool allZeros = true;//Assume raw frag is zero filled - - //Checks for empty frag - if (payloadWords == 0) { - if(_verbosityLevel >=3){std::cout<< "\nFound an empty frag, i = " << i <<" @Raw\n";} - ++_totalEmptyRaw;//Job counter - //Eventcounter - if( stm_frag.isHPGe() ){ - ++_totalEmptyRawHPGe; ++emptyRawHPGeFrags; } - else if (stm_frag.isLaBr()){ - ++_totalEmptyRawLaBr; ++emptyRawLaBrFrags; } - continue;//stops this loop check and goes to next frag - } - - //Check if any data points are not zero - for (size_t k =0; k < payloadWords; ++k){ - if (payloadPtr[k] != 0){ - allZeros = false; - break; - } - } - - //Check if zero filled - if (allZeros){ - if (_verbosityLevel >=3){std::cout << "\nFound a zero filled frag, i = " << i << " @Raw\n";} - ++_totalZeroRaw;//Increment counters - //Eventcounter - if( stm_frag.isHPGe() ){ - ++_totalZeroRawHPGe; ++zeroRawHPGeFrags; } - else if ( stm_frag.isLaBr() ){ - ++_totalZeroRawLaBr; ++zeroRawLaBrFrags; } - continue; - } - - //Print first 20 values - if (_verbosityLevel >=3){std::cout << "\nFound a good frag, i = " << i <<" @Raw\n";} - - if (_verbosityLevel >= 4){ - std::cout << "\nFirst 20 adcs: "; - for (size_t kk = 0; kk < std::min(payloadWords,20); ++kk){ - std::cout << payloadPtr[kk] << " ,"; - } - if(_verbosityLevel >=5){ - std::cout << "\nRaw header : Raw Length = " << stm_frag.rawLength() - <<" , ZS Length = " << stm_frag.zsLength() - << " , ZS Regions = " << stm_frag.zsRegions() - << " , i = " << i << " @Raw\n"; - } - } - - //Ideally only good frags get up to here - if ( stm_frag.isHPGe() ){ - expectedZSRegionsHPGe = stm_frag.zsRegions(); - expectedZSLengthHPGe = stm_frag.zsLength(); - readZSinfoFromRawHeaderHPGe = true; - - ++ _totalGoodRawHPGe; - ++ goodRawHPGeFrags; - - if (_saveRawWithHeaderWaveform_HPGe){ - auto dataPtr = stm_frag.dataBegin();//memory check for emplace_back - auto dataWords = stm_frag.dataWords(); - stm_waveform.set_data(dataWords, dataPtr); - raw_HPGe_header_waveform_digis->emplace_back(stm_waveform); - } - if(_saveRawWaveform_HPGe) { - stm_waveform.set_data(payloadWords, payloadPtr); - raw_HPGe_waveform_digis->emplace_back(stm_waveform); - size_t parentRawWfmIdx = raw_HPGe_waveform_digis->size()-1; - - lastRawHPGePtr = art::Ptr(rawHPGeProductID,parentRawWfmIdx, - event.productGetter(rawHPGeProductID)); - haveLastRawHPGePtr = true; - } - - } else if ( stm_frag.isLaBr() ){ - expectedZSRegionsLaBr = stm_frag.zsRegions(); - expectedZSLengthLaBr = stm_frag.zsLength(); - readZSinfoFromRawHeaderLaBr = true; - - ++ _totalGoodRawLaBr; - ++ goodRawLaBrFrags; - - if (_saveRawWithHeaderWaveform_LaBr){ - auto dataPtr = stm_frag.dataBegin(); - auto dataWords = stm_frag.dataWords(); - stm_waveform.set_data(dataWords, dataPtr); - raw_LaBr_header_waveform_digis->emplace_back(stm_waveform); + // Frag Summaries + std::unique_ptr stmFragSummaryHPGe(new mu2e::STMFragmentSummaryCollection); + std::unique_ptr stmFragSummaryLaBr(new mu2e::STMFragmentSummaryCollection); + + // HPGe + std::unique_ptr rawWaveformDigisWithHeaderHPGe(new mu2e::STMWaveformDigiCollection); + std::unique_ptr rawWaveformDigisHPGe(new mu2e::STMWaveformDigiCollection); + std::unique_ptr zsWaveformDigisHPGe(new mu2e::STMWaveformDigiCollection); + std::unique_ptr phDigisHPGe(new mu2e::STMPHDigiCollection); + + // LaBr waveforms + std::unique_ptr rawWaveformDigisWithHeaderLaBr(new mu2e::STMWaveformDigiCollection); + std::unique_ptr rawWaveformDigisLaBr(new mu2e::STMWaveformDigiCollection); + std::unique_ptr zsWaveformDigisLaBr(new mu2e::STMWaveformDigiCollection); + std::unique_ptr phDigisLaBr(new mu2e::STMPHDigiCollection); + + // booleans for tracking what detectors are present in the event + bool eventHasHPGe{false}; + bool eventHasLaBr{false}; + + // Get STM Fragments from the event, via handle + art::Handle STMFragmentsHandle; + event.getByLabel(_stmFragmentsTag, STMFragmentsHandle); + const auto& STMFragments = STMFragmentsHandle.product(); + uint16_t outerFragID; + + // Loop over outer fragments + for (const auto& frag : *STMFragments) { + ++_totalFragments; + outerFragID = frag.fragmentID(); + if (_verbosityLevel > 2) { std::cout << "Processing outer fragment with ID: " << outerFragID << "\n"; } + + // Check if this is a container fragment + if (frag.type() == artdaq::Fragment::ContainerFragmentType) { + + mu2e::STMFragment container_frag(frag); + artdaq::ContainerFragment cont_frag(frag); + size_t blocks = cont_frag.block_count(); + + if (container_frag.isHPGeContainer()) { + if (_verbosityLevel > 2) { std::cout << "Processing HPGe container fragment with ID: " << outerFragID << "\n"; } + ++_totalContainersHPGe; eventHasHPGe = true; _totalInnerFragsHPGe += blocks; + ++containerFragsHPGeThisEvent; + } else if (container_frag.isLaBrContainer()) { + if (_verbosityLevel > 2) { std::cout << "Processing LaBr container fragment with ID: " << outerFragID << "\n"; } + ++_totalContainersLaBr; eventHasLaBr = true; _totalInnerFragsLaBr += blocks; + ++containerFragsLaBrThisEvent; + } else { + if (_verbosityLevel > 0) { + std::cout << "Encountered an unknown STM Container Fragment \n" + << "Frag ID : " << outerFragID << "\n" + << "Event : " << _totalEvents << "\n"; + } + continue; // Skips the rest of this container frag if it is unknown } - if(_saveRawWaveform_LaBr){ - stm_waveform.set_data(payloadWords, payloadPtr); - raw_LaBr_waveform_digis->emplace_back(stm_waveform); - size_t parentRawWfmIdx = raw_LaBr_waveform_digis->size()-1; - lastRawLaBrPtr = art::Ptr(rawLaBrProductID,parentRawWfmIdx, - event.productGetter(rawLaBrProductID)); - haveLastRawLaBrPtr = true; - + ++containerFragsThisEvent; + ++_totalContainers; + _totalInnerFrags += blocks; + innerFragsThisEvent += blocks; + + // loop over container blocks + for (size_t i = 0 ; i < cont_frag.block_count(); ++i) { + auto inner_frag = cont_frag.at(i); + mu2e::STMFragment stm_frag(*inner_frag); + mu2e::STMWaveformDigi stm_waveform; + + if (stm_frag.isRaw()){ + ++_totalRawFragsSeen; + // Determine which detector this raw fragment is in + bool const isHPGe = stm_frag.isHPGe(); + bool const isLaBr = stm_frag.isLaBr(); + + if (!isHPGe && !isLaBr) { + if (_verbosityLevel > 1) { + std::cout << "Encountered raw fragment that is neither HPGe nor LaBr\n"; + } + ++_totalUnreadInnerFrags; + continue; + } + + isHPGe ? ++_totalRawFragsSeenHPGe : ++_totalRawFragsSeenLaBr; + + auto& headerState = isHPGe ? rawHeaderHPGe : rawHeaderLaBr; + auto& parentState = isHPGe ? rawParentHPGe : rawParentLaBr; + auto& eventMetrics = isHPGe ? HPGeEventMetrics : LaBrEventMetrics; + + // reset current raw header and parent state bool + headerState = RawHeaderState{}; + parentState.ptr = {}; + parentState.available = false; + parentState.index = 0; + ++eventMetrics.raw.seen; + + // check header+adcs is not less than expected header length (22) + if(stm_frag.dataWords() < stm::RawHeader::WORDS){ + if (_verbosityLevel > 1) { + std::cout << "Raw fragment has fewer data words than expected header length\n"; + } + ++_totalRawFragsWithInvalidHeaders; + ++_totalUnreadInnerFrags; + ++eventMetrics.rawFragsWithInvalidHeaders; + isHPGe ? ++_totalRawFragsWithInvalidHeadersHPGe : ++_totalRawFragsWithInvalidHeadersLaBr; + ++eventMetrics.setsSkippedDueToInvalidHeaders; + + headerState.skipCurrentSet = true; + parentState.ptr = {}; + parentState.available = false; + continue; + } + + // Confirm Raw Header has Valid Anchors + // For now just use as a diagnostic tool + if (!stm_frag.hasValidAnchors()) { + ++eventMetrics.rawFragsWithInvalidAnchors; + ++_totalRawFragsWithInvalidAnchors; + isHPGe ? ++_totalRawFragsWithInvalidAnchorsHPGe : ++_totalRawFragsWithInvalidAnchorsLaBr; + } + // Not needed for the moment + // headerState.rawHeaderIsValid = stm_frag.hasValidAnchors(); + + // Check if bad or missing or both + if (stm_frag.badData() && stm_frag.missing()) { + ++eventMetrics.rawFragsFlaggedBadAndMissing; + ++_totalRawFragsFlaggedBadAndMissing; + isHPGe ? ++_totalRawFragsFlaggedBadAndMissingHPGe : ++_totalRawFragsFlaggedBadAndMissingLaBr; + } else if (stm_frag.badData()) { + ++eventMetrics.rawFragsFlaggedBadOnly; + ++_totalRawFragsFlaggedBadOnly; + isHPGe ? ++_totalRawFragsFlaggedBadOnlyHPGe : ++_totalRawFragsFlaggedBadOnlyLaBr; + } else if (stm_frag.missing()) { + ++eventMetrics.rawFragsFlaggedMissingOnly; + ++_totalRawFragsFlaggedMissingOnly; + isHPGe ? ++_totalRawFragsFlaggedMissingOnlyHPGe : ++_totalRawFragsFlaggedMissingOnlyLaBr; + } + + bool const badOrMissing = stm_frag.badData() || stm_frag.missing(); + if (badOrMissing) { + headerState.skipCurrentSet = true; + parentState.ptr = {}; + parentState.available = false; + ++eventMetrics.setsSkippedDueToRawFlag; + continue; + } + + //Check if raw fragment is prescaled to determine whether to skip checks + headerState.rawPrescaled = stm_frag.rawPrescaled(); + headerState.rawPrescaleValue = stm_frag.rawPrescaleValue(); + + if (headerState.rawPrescaled) { + ++eventMetrics.raw.prescaled; + ++_totalRawFragsPrescaled; + isHPGe ? ++_totalRawFragsPrescaledHPGe : ++_totalRawFragsPrescaledLaBr; + } + + // Extract rest of the raw header information + // Even if raw is prescaled we still want to save zs info just in case + // before checking whats in the payload + headerState.containsZSInfo = true; + headerState.containsPHInfo = true; + headerState.zsPrescaled = stm_frag.zsPrescaled(); + headerState.zsPrescaleValue = stm_frag.zsPrescaleValue(); + headerState.expectedZSLength = stm_frag.zsLength(); + headerState.expectedZSRegions = stm_frag.zsRegions(); + headerState.expectedPHCount = stm_frag.phCount(); + + + // Check if raw frag is empty + auto payloadPtr = stm_frag.payloadBegin(); + auto payloadWords = stm_frag.payloadWords(); + bool allZeros = true; + if (payloadWords == 0) { + if (_verbosityLevel > 2){ + std::cout << "\nFound an empty raw fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--Raw Frag\n"; + } + //increment + ++eventMetrics.raw.empty; + ++_totalEmptyRawFrags; + isHPGe ? ++_totalEmptyRawFragsHPGe : ++_totalEmptyRawFragsLaBr; + continue; + } + // Check if any payload words exist + for (size_t k = 0; k < payloadWords; ++k){ + if (payloadPtr[k] != 0) { + allZeros = false; + break; + } + } + if (allZeros) { + if (_verbosityLevel > 2){ + std::cout << "\nFound an all-zero raw fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--Raw Frag\n"; + } + //counter increment for all-zero raw fragments + ++eventMetrics.raw.zero; + ++_totalZeroRawFrags; + isHPGe? ++_totalZeroRawFragsHPGe: ++_totalZeroRawFragsLaBr; + continue; + } + // At this point the raw fragment has payload words and is no zero filled + // We continue processing this raw fragment + if (_verbosityLevel > 2) { + std::cout << "\nFound a good raw fragment at Event : " << _totalEvents << "\n" + << "Fragment Index : " << i << "\n" + << "--Raw Frag\n"; + } + + //Print first few payload words for inspection + if (_verbosityLevel > 3) { + std::cout << "First few payload words(adcs) for inspection : " ; + for (size_t w = 0; w < std::min(payloadWords, static_cast(10)); ++w){ + std::cout << payloadPtr[w] << " ,"; + } + std::cout << "\n"; + } + //Raw Header inspection + if (_verbosityLevel > 4) { + std::cout << "\nRaw Header for inspection \n" + << "Raw Length : " << stm_frag.rawLength() << "\n" + << "ZS Length : " << stm_frag.zsLength() << "\n" + << "ZS Regions : " << stm_frag.zsRegions() << "\n" + << "Event : " << _totalEvents << "\n" + << "Inner Frag Index : " << i << "\n"; + } + // From here good raw frags end up and get saved + ++eventMetrics.raw.good; + ++_totalGoodRawFrags; + isHPGe ? ++_totalGoodRawFragsHPGe : ++_totalGoodRawFragsLaBr; + + + // Save waveforms based on fcl configurations + // Save Raw Waveform With Header Info - HPGe + if (_saveRawWaveformsWithHeaderHPGe && isHPGe && !headerState.rawPrescaled){ + auto dataPtr = stm_frag.dataBegin(); + auto dataWords = stm_frag.dataWords(); + stm_waveform.set_data(dataWords,dataPtr); + rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); + } + // Save Raw Waveform and Save parent Ptr - HPGe + if (_saveRawWaveformsHPGe && isHPGe && !headerState.rawPrescaled){ + stm_waveform.set_data(payloadWords, payloadPtr); + rawWaveformDigisHPGe->emplace_back(stm_waveform); + + //Save raw parent index + parentState.index = rawWaveformDigisHPGe->size() - 1; + parentState.ptr = art::Ptr(parentState.productID, parentState.index, + event.productGetter(parentState.productID)); + parentState.available = true; + } + // Save Raw Waveform With Header Info - LaBr + if (_saveRawWaveformsWithHeaderLaBr && isLaBr && !headerState.rawPrescaled){ + auto dataPtr = stm_frag.dataBegin(); + auto dataWords = stm_frag.dataWords(); + stm_waveform.set_data(dataWords,dataPtr); + rawWaveformDigisWithHeaderLaBr->emplace_back(stm_waveform); + } + // Save Raw Waveform and Save parent Ptr - LaBr + if (_saveRawWaveformsLaBr && isLaBr && !headerState.rawPrescaled){ + stm_waveform.set_data(payloadWords, payloadPtr); + rawWaveformDigisLaBr->emplace_back(stm_waveform); + + //Save raw parent index + parentState.index = rawWaveformDigisLaBr->size() - 1; + parentState.ptr = art::Ptr(parentState.productID, parentState.index, + event.productGetter(parentState.productID)); + parentState.available = true; + } + if (_verbosityLevel > 2) { + std::cout << "Raw with frag index" << i + << ", detector = " << (isHPGe? "HPGe": "LaBr") << std::boolalpha + << ", prescaled = " << headerState.rawPrescaled + << ", saved parent = " << parentState.available; + + if (parentState.available) { + std::cout << ", raw index saved = " << parentState.index; + } + std::cout << "\n"; + } + }// End of Raw fragment check + else if (stm_frag.isZS()){ + ++_totalZSFragsSeen; + // Determine which detector this ZS fragment belongs to + bool const isHPGe = stm_frag.isHPGe(); + bool const isLaBr = stm_frag.isLaBr(); + + // Double check that the fragment belongs to one of the expected detectors + if (!isHPGe && !isLaBr){ + ++_totalUnreadInnerFrags; + continue; + } + + auto& headerState = isHPGe ? rawHeaderHPGe : rawHeaderLaBr; + auto& parentState = isHPGe ? rawParentHPGe : rawParentLaBr; + auto& eventMetrics = isHPGe ? HPGeEventMetrics : LaBrEventMetrics; + + isHPGe ? ++_totalZSFragsSeenHPGe : ++_totalZSFragsSeenLaBr; + ++eventMetrics.zs.seen; + + // Check + if (_verbosityLevel > 2) { + std::cout << "ZS frag index = " << i + << ", detector = " << (isHPGe ? "HPGe" : "LaBr") << std::boolalpha + << ", parent available = " << parentState.available; + if (parentState.available) { + std::cout << ", raw index saved = " << parentState.index; + } + std::cout << "\n"; + } + + // Extract zs variables from Raw Header + bool skipCurrentSet = headerState.skipCurrentSet; + bool zsInfoWasExtracted = headerState.containsZSInfo; + bool zsPrescaled = headerState.zsPrescaled; + bool rawPrescaled = headerState.rawPrescaled; + uint16_t zsRegions = headerState.expectedZSRegions; + uint16_t zsLength = headerState.expectedZSLength; + uint16_t rawPrescaleValue = headerState.rawPrescaleValue; + uint16_t zsPrescaleValue = headerState.zsPrescaleValue; + + // Decide Here to skip based on previous raw fragment information + if (skipCurrentSet){ + isHPGe ? ++_totalZSFragsSkippedDueToRawFlagHPGe : ++_totalZSFragsSkippedDueToRawFlagLaBr; + ++eventMetrics.zsFragsSkippedDueToRawFlag; + continue; + } + // Decide Here to skip based on zs prescale information + if (zsPrescaled) { + isHPGe ? ++_totalZSFragsPrescaledHPGe : ++_totalZSFragsPrescaledLaBr; + ++_totalZSFragsPrescaled; + ++eventMetrics.zs.prescaled; + continue; + } + + auto payloadPtr = stm_frag.payloadBegin(); + auto payloadWords = stm_frag.payloadWords(); + + // Check if Empty + if (payloadWords == 0) { + if (_verbosityLevel > 2) { + std::cout << "\nFound an empty zs fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--ZS Frag\n"; + } + ++_totalEmptyZSFrags; + isHPGe ? ++_totalEmptyZSFragsHPGe : ++_totalEmptyZSFragsLaBr; + ++eventMetrics.zs.empty; + continue; + } + + // At this point the zs fragmant is non-empty + // May contain valid data + + // Print first 20 payload adcs for inspection + if (_verbosityLevel > 3) { + std::cout << "\nFirst few payload words for inspection : "; + for (size_t w = 0; w < std::min(payloadWords, static_cast(10)); ++w) { + std::cout << payloadPtr[w] << ","; + } + std::cout << "\n"; + } + + // Definitions for payload references + auto const* dataPtr = stm_frag.dataBegin(); + auto const dataWords = stm_frag.dataWords(); + auto dataEndPtr = dataPtr + dataWords; + size_t regionCounter {0}; + size_t zsTotalLengthCalculated {0}; + uint16_t lastZSIndexRecorded {0}; + uint16_t lastZSLengthRecorded {0}; + bool malformedZS {false}; + std::vector regions; + + // Check if data is zero filled using parsing for ZS + bool sawADC{false}; + bool allADCSZero{true}; + // May need to be adjusted, we would only read the first pulse + + if (_verbosityLevel > 5) { + std::cout << "\nData Words for inspection : " << "\n" + << "Data Words % 4 : " << dataWords % 4 << "\n" + << "--ZS Frag\n"; + } + + + while (dataPtr + 2 <= dataEndPtr){ + if (zsInfoWasExtracted && regionCounter >= zsRegions) { + break; + } + uint16_t currentZSIndex = static_cast(dataPtr[0]); + uint16_t currentZSLength = static_cast(dataPtr[1]); + auto adc = dataPtr + 2; + + if (currentZSLength > static_cast(dataEndPtr - adc)) { + malformedZS = true; + break; + } + + // Check if any is zero filled payload for this region + for (size_t sample = 0; sample < currentZSLength; ++sample){ + sawADC = true; + if (adc[sample] !=0) { + allADCSZero = false; + } + } + // Record the region + bool const saveZS = isHPGe ? _saveZSWaveformsHPGe : _saveZSWaveformsLaBr; + if (saveZS){ + regions.push_back({currentZSIndex, std::vector(adc, adc + currentZSLength)}); + } + + uint32_t trigTimeOffset = currentZSIndex; + + // Print Check per segment + if (_verbosityLevel > 5) { + std::cout << "\nZS Segment Check :" << "\n" + << " , ZS Index = " << currentZSIndex + << " , ZS Length = " << currentZSLength + << " , ZS Offset = " << trigTimeOffset << "\n"; + } + // Update Variables + lastZSIndexRecorded = currentZSIndex; + lastZSLengthRecorded = currentZSLength; + zsTotalLengthCalculated += lastZSLengthRecorded; + ++regionCounter; + dataPtr = adc + currentZSLength; + } // End of While loop + + if (_verbosityLevel > 4){ + //Summary + std::cout << "ZS Summary : " + << " , last ZS Index = " << lastZSIndexRecorded + << " , last ZS Length = " << lastZSLengthRecorded + << " , ZS Total Length = " << zsTotalLengthCalculated + << " , Region Counter = " << regionCounter << "\n" + << ", Frag Index = " << i << "\n"; + } + + // In case ZS has some weird behavior + if (malformedZS) { + if (_verbosityLevel > 2){ + std::cout << "\nMalformed ZS detected at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n"; + } + ++eventMetrics.zs.unread; + ++_totalUnreadInnerFrags; + continue; + } + + // Add exceptions + if (zsInfoWasExtracted) { + if (zsLength != zsTotalLengthCalculated) { + throw cet::exception("STM_UNPACKING") + << "\n=== ZS LENGTH MISMATCH ===\n" + << "ZS Length Count from Raw Header : " << zsLength << "\n" + << "ZS Length Calculated : " << zsTotalLengthCalculated << "\n" + // General Information about where error was found + << "Found at Event : " << _totalEvents << "\n" + << "Found at Frag Index : " << i << "\n" + << "Raw Prescaled : " << (rawPrescaled ? "Yes" : "No") << "\n" + << "Raw Prescale Value : " << rawPrescaleValue << "\n" + << "ZS Prescaled : " << (zsPrescaled ? "Yes" : "No") << "\n" + << "ZS Prescale Value : " << zsPrescaleValue << "\n" + << "Found at HPGe Container Frag : " << (isHPGe ? "Yes" : "No") << "\n" + << "Found at LaBr Container Frag : " << (isLaBr ? "Yes" : "No") << "\n"; + + } + if ( zsRegions != regionCounter) { + throw cet::exception("STM_UNPACKING") + << "\n=== ZS REGION COUNT MISMATCH ===\n" + << "ZS Region Count from Raw Header : " << zsRegions << "\n" + << "ZS Region Count Calculated : " << regionCounter << "\n" + // General Information about where error was found + << "Found at Event : " << _totalEvents << "\n" + << "Found at Frag Index : " << i << "\n" + << "Raw Prescaled : " << (rawPrescaled ? "Yes" : "No") << "\n" + << "Raw Prescale Value : " << rawPrescaleValue << "\n" + << "ZS Prescaled : " << (zsPrescaled ? "Yes" : "No") << "\n" + << "ZS Prescale Value : " << zsPrescaleValue << "\n" + << "Found at HPGe Container Frag : " << (isHPGe ? "Yes" : "No") << "\n" + << "Found at LaBr Container Frag : " << (isLaBr ? "Yes" : "No") << "\n"; + } + } + + if (sawADC && allADCSZero) { + if (_verbosityLevel > 2) { + std::cout << "\nFound a zero-filled zs fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--ZS Frag\n"; + } + ++eventMetrics.zs.zero; + ++_totalZeroZSFrags; + isHPGe ? ++_totalZeroZSFragsHPGe : ++_totalZeroZSFragsLaBr; + continue; + } + + // At this point we know the fragment was good + if (_verbosityLevel > 2) { + std::cout << "\nFound a good ZS fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--ZS Frag\n"; + } + for (auto& region : regions) { + mu2e::STMWaveformDigi zsDigi(region.offset, region.adcs); + if(parentState.available){ + // Set parent pointer if available + zsDigi.setParent(parentState.ptr); + } + // Emplacing + if (isHPGe && _saveZSWaveformsHPGe) { + // emplacing HPGe waveform digi + zsWaveformDigisHPGe->emplace_back(zsDigi); + if (_verbosityLevel > 2 && zsDigi.hasParent()) { + std::cout << "\nZS HPGe Parent Raw index : " << zsDigi.parent().key() + << ", offset : " << zsDigi.trigTimeOffset() << "\n"; + } + + } else if (isLaBr && _saveZSWaveformsLaBr) { + // emplacing LaBr waveform digi + zsWaveformDigisLaBr->emplace_back(zsDigi); + if (_verbosityLevel > 2 && zsDigi.hasParent()) { + std::cout << "\nZS LaBr Parent Raw index : " << zsDigi.parent().key() + << ", offset : " << zsDigi.trigTimeOffset() << "\n"; + } + } + } + + // Increment remaining counters + ++_totalGoodZSFrags; + isHPGe ? ++_totalGoodZSFragsHPGe : ++_totalGoodZSFragsLaBr; + ++eventMetrics.zs.good; + + }// End of ZS fragmment check + else if (stm_frag.isPH()){ + ++_totalPHFragsSeen; + // Determine which detector this PH fragment belongs to + bool const isHPGe = stm_frag.isHPGe(); + bool const isLaBr = stm_frag.isLaBr(); + + if (!isHPGe && !isLaBr) { + ++_totalUnreadInnerFrags; + continue; + } + auto& headerState = isHPGe ? rawHeaderHPGe : rawHeaderLaBr; + auto& eventMetrics = isHPGe ? HPGeEventMetrics : LaBrEventMetrics; + + isHPGe ? ++_totalPHFragsSeenHPGe : ++_totalPHFragsSeenLaBr; + ++eventMetrics.ph.seen; + + // Extract ph varibales from Raw Header + bool skipCurrentSet = headerState.skipCurrentSet; + bool extractedPHInfo = headerState.containsPHInfo; + uint16_t phCount = headerState.expectedPHCount; + + // Skip if Raw Fragment was Bad or Missing + if (skipCurrentSet) { + ++eventMetrics.phFragsSkippedDueToRawFlag; + isHPGe ? ++_totalPHFragsSkippedDueToRawFlagHPGe : ++_totalPHFragsSkippedDueToRawFlagLaBr; + continue; + } + + // Check if PH fragment is empty + auto payloadPtr = stm_frag.payloadBegin(); + auto payloadWords = stm_frag.payloadWords(); + bool allPHAreZeros= true; + + if (payloadWords == 0) { + if (_verbosityLevel > 2) { + std::cout << "\nFound an empty PH fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "--PH Frag\n"; + } + //increment + ++eventMetrics.ph.empty; + ++_totalEmptyPHFrags; + isHPGe ? ++_totalEmptyPHFragsHPGe : ++_totalEmptyPHFragsLaBr; + continue; + } + + // Check that the payload has pairs (time, pulse height) + if (payloadWords % 2 != 0) { + if(_verbosityLevel > 2) { + std::cout << "\nFound a PH Fragment with odd number of payload words at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + ++eventMetrics.ph.unread; + ++_totalUnreadInnerFrags; + continue; + } + + // Check if PH Pair count matches expected count from raw header + size_t const nPairsInFragment = payloadWords / 2; + // Here you either read the lowest pair count from raw header or what is in fragment + // If not you read what what is in the fragment anyway + size_t const nPairsToRead = extractedPHInfo ? std::min(nPairsInFragment, phCount) : nPairsInFragment; + + // Check if zero filled + // Since its a (time,PH) pair we will check every second entry for the PH value + for (size_t k = 0; k < nPairsToRead; ++k) { + if (payloadPtr[k*2+1] !=0) { + allPHAreZeros = false; + break; + } + } + + if (allPHAreZeros) { + if (_verbosityLevel > 2) { + std:: cout << "\nFound a zero-filled PH Fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + // counter + ++eventMetrics.ph.zero; + ++_totalZeroPHFrags; + isHPGe ? ++_totalZeroPHFragsHPGe : ++_totalZeroPHFragsLaBr; + continue; + } + + if (_verbosityLevel > 4) { + std::cout << "\nFirst Few Payload Words : " ; + for (size_t k = 0; k < std::min(payloadWords,20); ++k) { + std::cout << payloadPtr[k] << " ,"; + } + std::cout << "Frag Index : " << i << "\n"; + } + + for (size_t i_phPair = 0; i_phPair < nPairsToRead ; ++i_phPair){ + size_t i_PH = 2 * i_phPair; + uint32_t time = static_cast(payloadPtr[i_PH]); + int16_t const pulseHeight = payloadPtr[i_PH + 1]; + mu2e::STMPHDigi PH_digi(time,pulseHeight); + + // Emplace Back (Always On) + if (isHPGe) { + phDigisHPGe->emplace_back(PH_digi); + } + if (isLaBr) { + phDigisLaBr->emplace_back(PH_digi); + } + } + + // At this point we have a good PH fragment + if (_verbosityLevel > 2) { + std::cout << "\nFound a good PH Fragment at Event : " << _totalEvents << "\n" + << "Frag Index : " << i << "\n" + << "---PH Frag\n"; + } + + // Last counter increment + ++_totalGoodPHFrags; + isHPGe ? ++_totalGoodPHFragsHPGe : ++_totalGoodPHFragsLaBr; + ++eventMetrics.ph.good; + + }// End of PH fragment check + else { + // fallback for unreadable fragment + ++_totalUnreadInnerFrags; //Job Summary Counter + if (_verbosityLevel > 0 ) { + std::cout << "Encountered an unreadable inner fragment " << "\n" + << "Frag Index : " << i << "\n" + << "Frag ID : " << inner_frag->fragmentID() << "\n" + << "Event : " << _totalEvents << "\n"; + } + }// End of else non-raw/zs/pg frag } - - } - - } // End of isRaw Block - - - else if (stm_frag.isZS()){ - ++_totalZS; //Incremenet ZS counter - - if ( stm_frag.isHPGe() ){ - ++_totalZSHPGe; ++totalZSHPGeFrags; } - else if ( stm_frag.isLaBr() ){ ++_totalZSLaBr; ++totalZSLaBrFrags; - } - - auto payloadPtr = stm_frag.payloadBegin(); - auto payloadWords = stm_frag.payloadWords(); - bool allZeros = true; //assumes all adcs are zero - - // Extract variables from Raw Header - bool readZSinfoFromRawHeader = stm_frag.isHPGe() ? readZSinfoFromRawHeaderHPGe : readZSinfoFromRawHeaderLaBr; - uint16_t expectedZSRegions = stm_frag.isHPGe() ? expectedZSRegionsHPGe : expectedZSRegionsLaBr; - uint16_t expectedZSLength = stm_frag.isHPGe() ? expectedZSLengthHPGe : expectedZSLengthLaBr; - - //After copying varibales, reset detector specific variables - if (stm_frag.isHPGe()){ - readZSinfoFromRawHeaderHPGe = false; - expectedZSLengthHPGe = 0; - expectedZSRegionsHPGe = 0; - } else if (stm_frag.isLaBr()){ - readZSinfoFromRawHeaderLaBr = false; - expectedZSLengthLaBr = 0; - expectedZSRegionsLaBr = 0; - } - - //Check if payload is empty - if ( payloadWords == 0) { - if (_verbosityLevel >=3){std::cout << "\nFound an empty frag, i = " << i << " @ZS\n";} - ++_totalEmptyZS; - if ( stm_frag.isHPGe() ){ - ++_totalEmptyZSHPGe; ++emptyZSHPGeFrags; } - else if ( stm_frag.isLaBr() ){ - ++_totalEmptyZSLaBr; ++emptyZSLaBrFrags; } - continue; - } - //Check if any adc are non-zero - for (size_t k = 0 ; k < payloadWords ; ++k){ - if(payloadPtr[k] != 0 ){ - allZeros = false; - break; + } else { + // fallback for non-container fragment + if (_verbosityLevel > 0) { + std::cout << "\nEncountered a non-container fragment " << "\n" + << "Fragment ID : " << frag.fragmentID() << "\n" + << "Event : " << _totalEvents << "\n"; } - } - //Check if zero filled - if (allZeros) { - if (_verbosityLevel >=3){std::cout << "\nFound a zero filled frag, i = "<< i << " @ZS\n";} - ++_totalZeroZS; - if ( stm_frag.isHPGe() ){ - ++_totalZeroZSHPGe; ++zeroZSHPGeFrags; } - else if ( stm_frag.isLaBr() ){ - ++_totalZeroZSLaBr; ++zeroZSLaBrFrags; } + ++_totalNonContainers; continue; - } - //Print first 20 payload adcs - if (_verbosityLevel >=3){std::cout << "\nFound a good frag, i = " << i << " @ZS\n";} - - if (_verbosityLevel >=4){ - std::cout << "\nFirst 20 adcs: "; - for (size_t kk = 0 ; kk < std::min(payloadWords,20) ; ++kk){ - std::cout << payloadPtr[kk] << " , "; - } - std::cout << "i = " << i << " @ZS\n"; - } - - //Defintions for payload references - auto dataPtr = stm_frag.dataBegin(); - auto dataWords = stm_frag.dataWords(); - auto dataEnd = dataPtr + dataWords; - size_t seg = 0; - size_t totalLen = 0; - uint16_t lastZSindex = 0; //keeps track of last recorded index from header -> with respect to what? - uint16_t lastLen = 0; //keeps track of last recoded length from header - - if(_verbosityLevel >= 6){std::cout << "dataWords : " << dataWords - << " dataWords%4 : " << dataWords%4 - <<" @ZS" << "\n"; } - - while (dataPtr + 2 <= dataEnd){ - if ( readZSinfoFromRawHeader && seg >= expectedZSRegions ) break; - uint16_t current_zs_location = static_cast(dataPtr[0]); - uint16_t current_zs_size = static_cast(dataPtr[1]); - auto adc = dataPtr + 2; - if (adc + current_zs_size > dataEnd) - break; - - uint32_t trigTimeOffset = current_zs_location; - - //emplacing - if ( stm_frag.isHPGe() && _saveZSWaveform_HPGe){ - std::vector segADCS(adc, adc + current_zs_size); //1D array, contains adcs to this_zs_size - 1 - mu2e::STMWaveformDigi zsDigi(trigTimeOffset, segADCS); - - if (readZSinfoFromRawHeader && haveLastRawHPGePtr) { - zsDigi.setParent(lastRawHPGePtr); - } - - zs_HPGe_waveform_digis->emplace_back(zsDigi); - if(_verbosityLevel >= 3 && zsDigi.hasParent()){ - std::cout << "ZS HPGe segment has parent Raw index " - << zsDigi.parent().key() - << "with offset " - << zsDigi.trigTimeOffset() - << "\n"; - } - } - else if ( stm_frag.isLaBr() && _saveZSWaveform_LaBr){ - std::vector segADCS(adc, adc + current_zs_size); - mu2e::STMWaveformDigi zsDigi(trigTimeOffset, segADCS); - - if (readZSinfoFromRawHeader && haveLastRawLaBrPtr){ - zsDigi.setParent(lastRawLaBrPtr); - } - - zs_LaBr_waveform_digis->emplace_back(zsDigi); - - } - - if (_verbosityLevel >=6){ - - //A print check per segment - std::cout << "Region = " << seg << " , zs_index = " - << current_zs_location << " , zs_size = " << current_zs_size - << " , trigTimeOffset = " << trigTimeOffset << "\n" ; - } - - //Update variables - lastZSindex = current_zs_location; - lastLen = current_zs_size; - totalLen += lastLen; - ++seg; - dataPtr = adc + current_zs_size; - } // end of while loop - - if (_verbosityLevel >=5){ - //Summary - std::cout << "ZS Regions = " << seg - << " , lastZSindex = " << lastZSindex - << " , lastZSLen = " << lastLen - << " , ZS total length = " << totalLen - << " , i = " << i << " @ZS\n"; - } - - //Throw out if ZSLengthfromRaw != totalLen, throw out if length mismatch - if (readZSinfoFromRawHeader){ - if (expectedZSLength != totalLen){ - throw cet::exception("STM_UNPACKING") - << "\n=== ZS Length count mismatch ===\n" - << "ZS length from Raw header : " << expectedZSLength << "\n" - << "ZS length calculated from file : " << totalLen << "\n" - << "Found at inner frag i : " << i << "\n" - << std::boolalpha //enables text output for booleans below - << "Found at HPGe container : " << stm_frag.isHPGe() << "\n" - << "Found at LaBr container : " << stm_frag.isLaBr() << "\n" - << "Encountered at event : " << _totalEvents << "\n"; - - }//Also throw out if regions for ZS pulse do not match - if ( expectedZSRegions != seg){ - throw cet::exception("STM_UNPACKING") - << "\n=== ZS Region count mismatch ===\n" - << "ZS Region count from Raw header : " << expectedZSRegions << "\n" - << "ZS Regionc count calculated from file : " << seg << "\n" - << "Found at inner frag i : " << i << "\n" - << "Encountered at event : " << _totalEvents << "\n"; - - } - } - - //Increment counter after checking if there is a match - if ( stm_frag.isHPGe()){ ++_totalGoodZSHPGe; ++goodZSHPGeFrags; } - else if(stm_frag.isLaBr()){++ _totalGoodZSLaBr; ++goodZSLaBrFrags; } - - }//End of isZS - - else if ( stm_frag.isPH() ){ - - ++_totalPH; - if ( stm_frag.isHPGe() ){ ++_totalPHHPGe; ++totalPHHPGeFrags;} - else if ( stm_frag.isLaBr() ){ ++_totalPHLaBr; ++totalPHLaBrFrags; } - - //Check if zero filled - auto payloadPtr = stm_frag.payloadBegin(); - auto payloadWords = stm_frag.payloadWords(); - bool allZeros = true; - + } + } // End of frags loop + + // Update event type counters based on the detectors in event + if (eventHasHPGe && eventHasLaBr) { + ++_totalEventsWithBothDetectors; + } else if (eventHasHPGe) { + ++_totalEventsWithOnlyHPGe; + } else if (eventHasLaBr) { + ++_totalEventsWithOnlyLaBr; + } else { + ++_totalEventsWithNeitherDetector; + } - if (payloadWords ==0){ - if (_verbosityLevel >= 3){std::cout << "\nFound an empty frag, i = " << i<< " @PH\n";} - ++_totalEmptyPH; - if ( stm_frag.isHPGe() ){ ++_totalEmptyPHHPGe; ++emptyPHHPGeFrags; } - else if ( stm_frag.isLaBr() ){ ++_totalEmptyPHLaBr; ++emptyPHLaBrFrags;} - continue; - } + // HPGe Remaining Fragment Counts + badHPGeFragsThisEvent = HPGeEventMetrics.rawFragsFlaggedBadOnly + + HPGeEventMetrics.rawFragsFlaggedBadAndMissing; - //Check if zero filled - for (size_t k = 0; k< payloadWords; ++k) { - if (payloadPtr[k] !=0){ - allZeros = false; - break; - } - } - //count if zero filled - if (allZeros){ - if (_verbosityLevel >=3){ std::cout<< "\nFound a zero filled frag, i = " << i<< " @PH\n";} - ++_totalZeroPH; - - if ( stm_frag.isHPGe() ){ ++_totalZeroPHHPGe; ++zeroPHHPGeFrags; } - else if ( stm_frag.isLaBr() ){ ++_totalZeroPHLaBr; ++zeroPHLaBrFrags; } - continue; - } + missingHPGeFragsThisEvent = HPGeEventMetrics.rawFragsFlaggedMissingOnly + + HPGeEventMetrics.rawFragsFlaggedBadAndMissing; - if (_verbosityLevel >= 3){std::cout << "\nFound a good frag, i = " << i <<" @PH\n";} + // LaBr Remaining Fragment Counts + badLaBrFragsThisEvent = LaBrEventMetrics.rawFragsFlaggedBadOnly + + LaBrEventMetrics.rawFragsFlaggedBadAndMissing; - size_t digiWords = stm_frag.payloadWords(); - auto const* digiPtr = stm_frag.payloadBegin(); + missingLaBrFragsThisEvent = LaBrEventMetrics.rawFragsFlaggedMissingOnly + + LaBrEventMetrics.rawFragsFlaggedBadAndMissing; - if (digiWords % 2 !=0){ - if (_verbosityLevel >=3){ - std::cout << "Found a malformmed frag of PH Digis" << std::endl; - } - continue; - } - - if ( stm_frag.isHPGe() ){ ++ _totalGoodPHHPGe; ++goodPHHPGeFrags; } - else if ( stm_frag.isLaBr() ) { ++ _totalGoodPHLaBr; ++goodPHLaBrFrags; } - - for (size_t i_PH = 0; i_PH + 1 < digiWords ; i_PH += 2){ - uint32_t time = static_cast(digiPtr[i_PH]); - int16_t PH = digiPtr[i_PH + 1]; - mu2e::STMPHDigi PH_digi(time, PH); - - if( stm_frag.isHPGe() ){ - ph_HPGe_digis->emplace_back(PH_digi); } - else if ( stm_frag.isLaBr() ){ - ph_LaBr_digis->emplace_back(PH_digi); } - - } - - }//End of isPH and is checks - else{ - ++ _unreadInnerFrags; //For Job summary - ++ unread_InnerFrags; //For event summary - if(_verbosityLevel >=3){ - std::cout << "Unread Inner fragment" << "\n" - << "Inner frag i : " << i << "\n" - << "Frag ID : " << inner_frag->fragmentID() << "\n" - << "Event : " <<_totalEvents << "\n"; - } + // Save STMFrag Summary here + if (_saveSTMFragSummary) { + if (_verbosityLevel > 2) { + std::cout << "\nSaving STMFragSummary\n"; } - } - - } else { - //fallback (non-container case) - if (_verbosityLevel >=1){ - std::cout << "Found non-container STM Fragment " <<"\n" - << "Fragment ID : " << frag.fragmentID() << "\n" - << "Event : " << _totalEvents << "\n"; - } - ++ _totalNonContainerFrags; - continue; + stmFragSummaryHPGe->emplace_back( + containerFragsHPGeThisEvent,innerFragsHPGeThisEvent, + badHPGeFragsThisEvent, missingHPGeFragsThisEvent, + HPGeEventMetrics.zsFragsSkippedDueToRawFlag, HPGeEventMetrics.phFragsSkippedDueToRawFlag, + HPGeEventMetrics.raw.good, HPGeEventMetrics.zs.good, HPGeEventMetrics.ph.good, + HPGeEventMetrics.raw.zero, HPGeEventMetrics.zs.zero, HPGeEventMetrics.ph.zero, + HPGeEventMetrics.raw.empty, HPGeEventMetrics.zs.empty, HPGeEventMetrics.ph.empty + ); + + stmFragSummaryLaBr->emplace_back( + containerFragsLaBrThisEvent,innerFragsLaBrThisEvent, + badLaBrFragsThisEvent, missingLaBrFragsThisEvent, + LaBrEventMetrics.zsFragsSkippedDueToRawFlag, LaBrEventMetrics.phFragsSkippedDueToRawFlag, + LaBrEventMetrics.raw.good, LaBrEventMetrics.zs.good, LaBrEventMetrics.ph.good, + LaBrEventMetrics.raw.zero, LaBrEventMetrics.zs.zero, LaBrEventMetrics.ph.zero, + LaBrEventMetrics.raw.empty, LaBrEventMetrics.zs.empty, LaBrEventMetrics.ph.empty + ); } - } //End of frags loop - - if (eventHasHPGe && eventHasLaBr){ ++_totalEventsWithHPGeLaBr; } - else if (eventHasHPGe){ ++_totalEventsWithOnlyHPGe; } - else if (eventHasLaBr){ ++_totalEventsWithOnlyLaBr; } - else { ++_totalEventsWithNone; } - - if(_saveSTMFragSummary){ - stmFragSummaryHPGe->emplace_back(nContainerFragsThisEvent,nInnerFragsThisEvent, - goodRawHPGeFrags, goodZSHPGeFrags, goodPHHPGeFrags, - zeroRawHPGeFrags, zeroZSHPGeFrags, zeroPHHPGeFrags, - emptyRawHPGeFrags, emptyZSHPGeFrags, emptyPHHPGeFrags); - - stmFragSummaryLaBr->emplace_back(nContainerFragsThisEvent,nInnerFragsThisEvent, - goodRawLaBrFrags, goodZSLaBrFrags, goodPHLaBrFrags, - zeroRawLaBrFrags, zeroZSLaBrFrags, zeroPHLaBrFrags, - emptyRawLaBrFrags, emptyZSLaBrFrags, emptyPHLaBrFrags); - - } - if (_verbosityLevel >= 2 ){ - //Event Summary -> tells us what happens per art event - std::cout << "\n========== STM EVENT SUMMARY - (Unpacking Module) ==========\n"; - std::cout << "\n--- Products extracted ---\n"; - std::cout << "Extracted Raw HPGe waveforms : " << raw_HPGe_waveform_digis->size() <<"\n"; - std::cout << "Extracted ZS HPGe waveforms : " << zs_HPGe_waveform_digis->size() <<"\n"; - std::cout << "Extracted PH HPGe digis : " << ph_HPGe_digis->size() <<"\n"; - std::cout << "\n"; - std::cout << "Extracted Raw LaBr waveforms : " << raw_LaBr_waveform_digis->size() <<"\n"; - std::cout << "Extracted ZS LaBr waveforms : " << zs_LaBr_waveform_digis->size() <<"\n"; - std::cout << "Extracted PH LaBr digis : " << ph_LaBr_digis->size() <<"\n"; - - - std::cout << "\n--- Frags Seen ---\n"; // Counts all HPGe and LaBr frags, no filter - std::cout << "Raw HPGe frags seen : " << totalRawHPGeFrags << "\n"; - std::cout << "ZS HPGe frags seen : " << totalZSHPGeFrags << "\n"; - std::cout << "PH HPGe frags seen : " << totalPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Raw LaBr frags seen : " << totalRawLaBrFrags << "\n"; - std::cout << "ZS LaBr frags seen : " << totalZSLaBrFrags << "\n"; - std::cout << "PH LaBr frags seen : " << totalPHLaBrFrags << "\n"; - std::cout << "\nUnread frags : " << unread_InnerFrags << "\n"; - - - std::cout << "\n--- Filtered results ---\n"; - std::cout << "Good Raw HPGe frags : " << goodRawHPGeFrags << "\n"; - std::cout << "Good ZS HPGe frags : " << goodZSHPGeFrags << "\n"; - std::cout << "Good PH HPGe frags : " << goodPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Good Raw LaBr frags : " << goodRawLaBrFrags << "\n"; - std::cout << "Good ZS LaBr frags : " << goodZSLaBrFrags << "\n"; - std::cout << "Good PH LaBr frags : " << goodPHLaBrFrags << "\n"; - std::cout << "\n"; - std::cout << "Zero Raw HPGe frags : " << zeroRawHPGeFrags << "\n"; - std::cout << "Zero ZS HPGe frags : " << zeroZSHPGeFrags << "\n"; - std::cout << "Zero PH HPGe frags : " << zeroPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Zero Raw LaBr frags : " << zeroRawLaBrFrags << "\n"; - std::cout << "Zero ZS LaBr frags : " << zeroZSLaBrFrags << "\n"; - std::cout << "Zero PH LaBr frags : " << zeroPHLaBrFrags << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw HPGe frags : " << emptyRawHPGeFrags <<"\n"; - std::cout << "Empty ZS HPGe frags : " << emptyZSHPGeFrags << "\n"; - std::cout << "Empty PH HPGe frags : " << emptyPHHPGeFrags << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw LaBr frags : " << emptyRawLaBrFrags <<"\n"; - std::cout << "Empty ZS LaBr frags : " << emptyZSLaBrFrags << "\n"; - std::cout << "Empty PH LaBr frags : " << emptyPHLaBrFrags << "\n"; - - std::cout << "=================================\n"; - } - - //Final move - if (_saveSTMFragSummary) { - event.put(std::move(stmFragSummaryHPGe),"stmFragSummaryHPGe"); - event.put(std::move(stmFragSummaryLaBr),"stmFragSummaryLaBr"); - } - - //HPGe - if (_saveRawWithHeaderWaveform_HPGe){ event.put(std::move(raw_HPGe_header_waveform_digis), "rawWithHeaderHPGe"); } - if (_saveRawWaveform_HPGe){event.put(std::move(raw_HPGe_waveform_digis), "rawHPGe");} - if (_saveZSWaveform_HPGe){event.put(std::move(zs_HPGe_waveform_digis), "zsHPGe");} - event.put(std::move(ph_HPGe_digis), "phHPGe"); - - //LaBr - if (_saveRawWithHeaderWaveform_LaBr){ event.put(std::move(raw_LaBr_header_waveform_digis), "rawWithHeaderLaBr"); } - if (_saveRawWaveform_LaBr){event.put(std::move(raw_LaBr_waveform_digis), "rawLaBr");} - if (_saveZSWaveform_LaBr){event.put(std::move(zs_LaBr_waveform_digis), "zsLaBr");} - event.put(std::move(ph_LaBr_digis), "phLaBr"); - -} // produce() -// ====================================================================== + // Final Move + if (_verbosityLevel > 1) { + // Event Summary -> tells us what happened per event + std::cout << "\n========== STM EVENT SUMMARY - (Unpacking Module) ==========\n"; + std::cout << "\n--- Module Configuration ---\n"; + std::cout << "Raw Waveforms with Header HPGe : " << (_saveRawWaveformsWithHeaderHPGe ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms HPGe : " << (_saveRawWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms HPGe : " << (_saveZSWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "PH Digis HPGe : Yes\n"; + std::cout << "Raw Waveforms with Header LaBr : " << (_saveRawWaveformsWithHeaderLaBr ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms LaBr : " << (_saveRawWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms LaBr : " << (_saveZSWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "PH Digis LaBr : Yes\n"; + + std::cout << "\n--- Products Saved ---\n"; + std::cout << "Extracted Raw Waveforms With Header (HPGe) : " << rawWaveformDigisWithHeaderHPGe->size() << "\n"; + std::cout << "Extracted Raw Waveforms (HPGe) : " << rawWaveformDigisHPGe->size() << "\n"; + std::cout << "Extracted ZS Waveforms (HPGe) : " << zsWaveformDigisHPGe->size() << "\n"; + std::cout << "Extracted PH Digis (HPGe) : " << phDigisHPGe->size() << "\n"; + std::cout << "\n"; + std::cout << "Extracted Raw Waveforms With Header (LaBr) : " << rawWaveformDigisWithHeaderLaBr->size() << "\n"; + std::cout << "Extracted Raw Waveforms (LaBr) : " << rawWaveformDigisLaBr->size() << "\n"; + std::cout << "Extracted ZS Waveforms (LaBr) : " << zsWaveformDigisLaBr->size() << "\n"; + std::cout << "Extracted PH Digis (LaBr) : " << phDigisLaBr->size() << "\n"; + + std::cout << "\n--- Filtered Products (HPGe) ---\n"; + std::cout << "Good Raw Frags (HPGe) : " << HPGeEventMetrics.raw.good << "\n"; + std::cout << "Good ZS Frags (HPGe) : " << HPGeEventMetrics.zs.good << "\n"; + std::cout << "Good PH Frags (HPGe) : " << HPGeEventMetrics.ph.good << "\n"; + std::cout << "\n"; + std::cout << "Empty Raw Frags (HPGe) : " << HPGeEventMetrics.raw.empty << "\n"; + std::cout << "Empty ZS Frags (HPGe) : " << HPGeEventMetrics.zs.empty << "\n"; + std::cout << "Empty PH Frags (HPGe) : " << HPGeEventMetrics.ph.empty << "\n"; + std::cout << "\n"; + std::cout << "Zero Raw Frags (HPGe) : " << HPGeEventMetrics.raw.zero << "\n"; + std::cout << "Zero ZS Frags (HPGe) : " << HPGeEventMetrics.zs.zero << "\n"; + std::cout << "Zero PH Frags (HPGe) : " << HPGeEventMetrics.ph.zero << "\n"; + std::cout << "\n"; + std::cout << "Bad Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedBadOnly << "\n"; + std::cout << "Missing Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedMissingOnly << "\n"; + std::cout << "Bad and Missing Raw Frags (HPGe) : " << HPGeEventMetrics.rawFragsFlaggedBadAndMissing << "\n"; + std::cout << "\n"; + + std::cout << "\n--- Filtered Products (LaBr) ---\n"; + std::cout << "Good Raw Frags (LaBr) : " << LaBrEventMetrics.raw.good << "\n"; + std::cout << "Good ZS Frags (LaBr) : " << LaBrEventMetrics.zs.good << "\n"; + std::cout << "Good PH Frags (LaBr) : " << LaBrEventMetrics.ph.good << "\n"; + std::cout << "\n"; + std::cout << "Empty Raw Frags (LaBr) : " << LaBrEventMetrics.raw.empty << "\n"; + std::cout << "Empty ZS Frags (LaBr) : " << LaBrEventMetrics.zs.empty << "\n"; + std::cout << "Empty PH Frags (LaBr) : " << LaBrEventMetrics.ph.empty << "\n"; + std::cout << "\n"; + std::cout << "Zero Raw Frags (LaBr) : " << LaBrEventMetrics.raw.zero << "\n"; + std::cout << "Zero ZS Frags (LaBr) : " << LaBrEventMetrics.zs.zero << "\n"; + std::cout << "Zero PH Frags (LaBr) : " << LaBrEventMetrics.ph.zero << "\n"; + std::cout << "\n"; + std::cout << "Bad Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedBadOnly << "\n"; + std::cout << "Missing Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedMissingOnly << "\n"; + std::cout << "Bad and Missing Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedBadAndMissing << "\n"; + // Extra Filters + std::cout << "\n=== Extra Filters ===\n"; + std::cout << "Raw Frags With Invalid Headers (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidHeaders; + std::cout << "Raw Frags With Invalid Anchors (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidAnchors; + std::cout << "ZS Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.zsFragsSkippedDueToRawFlag; + std::cout << "PH Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.phFragsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.setsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (HPGe) : " << HPGeEventMetrics.setsSkippedDueToInvalidHeaders; + std::cout << "\n"; + std::cout << "Raw Frags With Invalid Headers (LaBr) : " << LaBrEventMetrics.rawFragsWithInvalidHeaders; + std::cout << "ZS Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.zsFragsSkippedDueToRawFlag; + std::cout << "PH Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.phFragsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.setsSkippedDueToRawFlag; + std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (LaBr) : " << LaBrEventMetrics.setsSkippedDueToInvalidHeaders; + std::cout << "=================================\n"; + + } + // Frag Summary + if (_saveSTMFragSummary) { + event.put(std::move(stmFragSummaryHPGe), "stmFragSummaryHPGe"); + event.put(std::move(stmFragSummaryLaBr), "stmFragSummaryLaBr"); + } + // HPGe + if (_saveRawWaveformsWithHeaderHPGe) { event.put(std::move(rawWaveformDigisWithHeaderHPGe), "rawWithHeaderHPGe"); } + if (_saveRawWaveformsHPGe) { event.put(std::move(rawWaveformDigisHPGe), "rawHPGe"); } + if (_saveZSWaveformsHPGe) { event.put(std::move(zsWaveformDigisHPGe), "zsHPGe"); } + //default to always save PH Digis + event.put(std::move(phDigisHPGe), "phHPGe"); + // LaBr + if (_saveRawWaveformsWithHeaderLaBr) { event.put(std::move(rawWaveformDigisWithHeaderLaBr), "rawWithHeaderLaBr"); } + if (_saveRawWaveformsLaBr) { event.put(std::move(rawWaveformDigisLaBr), "rawLaBr"); } + if (_saveZSWaveformsLaBr) { event.put(std::move(zsWaveformDigisLaBr), "zsLaBr"); } + //default to always save PH Digis + event.put(std::move(phDigisLaBr), "phLaBr"); + +}// End of produce() void STMDigisFromFragments::endJob() { - if (_verbosityLevel >= 1){ - //Art job summary for the unpacking - std::cout << "\n========== STM JOB SUMMARY - (Unpacking Module) ==========\n"; - - std::cout << "Total Art events : " << _totalEvents << "\n"; - std::cout << "Total Art events w/HPGe&LaBr : " << _totalEventsWithHPGeLaBr << "\n"; - std::cout << "Total Art events w/only HPGe : " << _totalEventsWithOnlyHPGe << "\n"; - std::cout << "Total Art events w/only LaBr : " << _totalEventsWithOnlyLaBr << "\n"; - std::cout << "Total Art events w/Neither : " << _totalEventsWithNone << "\n"; - std::cout << "Total frags : " << _totalFragments << "\n"; - std::cout << "Total Container frags : " << _totalContainers << "\n"; - std::cout << "Total HPGe Containers : " << _totalContainersHPGe << "\n"; - std::cout << "Total LaBr Containers : " << _totalContainersLaBr << "\n"; - std::cout << "Total Inner frags : " << _totalInner << "\n"; - std::cout << "Unread frags : " << _unreadInnerFrags << "\n"; - std::cout << "Non Container frags : " << _totalNonContainerFrags << "\n"; - - std::cout << "\n--- Data types read pre filtering ---\n"; - std::cout << "Total RAW frags seen : " << _totalRaw << "\n"; - std::cout << "Total ZS frags seen : " << _totalZS << "\n"; - std::cout << "total PH frags seen : " << _totalPH << "\n"; - std::cout << "\n"; - std::cout << "Total RAW HPGe frags seen : " << _totalRawHPGe << "\n"; - std::cout << "Total ZS HPGe frags seen : " << _totalZSHPGe << "\n"; - std::cout << "Total PH HPGe frags seen : " << _totalPHHPGe << "\n"; - std::cout << "\n"; - std::cout << "Total RAW LaBr frags seen : " << _totalRawLaBr << "\n"; - std::cout << "Total ZS LaBr frags seen : " << _totalZSLaBr << "\n"; - std::cout << "Total PH LaBr frags seen : " << _totalPHLaBr << "\n"; - - std::cout << "\n--- Data types filtered HPGe ---\n"; - std::cout << "Good RAW HPGe frags : " << _totalGoodRawHPGe << "\n"; - std::cout << "Good ZS HPGe frags : " << _totalGoodZSHPGe << "\n"; - std::cout << "Good PH HPGe frags : " << _totalGoodPHHPGe << "\n"; - std::cout << "\n"; - std::cout << "Zero RAW HPGe frags : " << _totalZeroRawHPGe << "\n"; - std::cout << "Zero ZS HPGe frags : " << _totalZeroZSHPGe << "\n"; - std::cout << "Zero PH HPGe frags : " << _totalZeroPHHPGe << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw HPGe frags : " << _totalEmptyRawHPGe << "\n"; - std::cout << "Empty ZS HPGe frags : " << _totalEmptyZSHPGe << "\n"; - std::cout << "Empty PH HPGe frags : " << _totalEmptyPHHPGe << "\n"; - - std::cout << "\n--- Data types filtered LaBr ---\n"; - std::cout << "Good RAW LaBr frags : " << _totalGoodRawLaBr << "\n"; - std::cout << "Good ZS LaBr frags : " << _totalGoodZSLaBr << "\n"; - std::cout << "Good PH LaBr frags : " << _totalGoodPHLaBr << "\n"; - std::cout << "\n"; - std::cout << "Zero RAW LaBr frags : " << _totalZeroRawLaBr << "\n"; - std::cout << "Zero ZS LaBr frags : " << _totalZeroZSLaBr << "\n"; - std::cout << "Zero PH LaBr frags : " << _totalZeroPHLaBr << "\n"; - std::cout << "\n"; - std::cout << "Empty Raw LaBr frags : " << _totalEmptyRawLaBr << "\n"; - std::cout << "Empty ZS LaBr frags : " << _totalEmptyZSLaBr << "\n"; - std::cout << "Empty PH LaBr frags : " << _totalEmptyPHLaBr << "\n"; - - std::cout << "=================================\n"; - - } + if (_verbosityLevel > 0 ){ + // Print job Summary + std::cout << "\n========== STM JOB SUMMARY - (Unpacking Module) ==========\n"; + std::cout << "\n--- Module Configuration ---\n"; + std::cout << "Raw Waveforms with Header HPGe : " << (_saveRawWaveformsWithHeaderHPGe ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms HPGe : " << (_saveRawWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms HPGe : " << (_saveZSWaveformsHPGe ? "Yes" : "No") << "\n"; + std::cout << "PH Digis HPGe : Yes\n"; + std::cout << "Raw Waveforms with Header LaBr : " << (_saveRawWaveformsWithHeaderLaBr ? "Yes" : "No") << "\n"; + std::cout << "Raw Waveforms LaBr : " << (_saveRawWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "ZS Waveforms LaBr : " << (_saveZSWaveformsLaBr ? "Yes" : "No") << "\n"; + std::cout << "PH Digis LaBr : Yes\n"; + + // Container and Inner Fragment Summary + std::cout << "\n--- Container and Inner Fragment Summary ---\n"; + std::cout << "Total Art Events Processed : " << _totalEvents << "\n"; + std::cout << "Total Art Events w/ HPGe & LaBr : " << _totalEventsWithBothDetectors << "\n"; + std::cout << "Total Art Events w/ HPGe Only : " << _totalEventsWithOnlyHPGe << "\n"; + std::cout << "Total Art Events w/ LaBr Only : " << _totalEventsWithOnlyLaBr << "\n"; + std::cout << "Total Art Events w/ Neither HPGe nor LaBr : " << _totalEventsWithNeitherDetector << "\n"; + + std::cout << "Total HPGe Containers : " << _totalContainersHPGe << "\n"; + std::cout << "Total LaBr Containers : " << _totalContainersLaBr << "\n"; + std::cout << "Total Container Processed : " << _totalContainers << "\n"; + std::cout << "Total Non Container Processed : " << _totalNonContainers << "\n"; + + std::cout << "Total Inner Fragments Processed : " << _totalInnerFrags << "\n"; + std::cout << "Total Unreadable Inner Fragments : " << _totalUnreadInnerFrags << "\n"; + + // Data Type Summary - pre-filtering + std::cout << "\n--- Data Types Read (Pre - Filtering) ---\n"; + std::cout << "Total Raw Frags Seen : " << _totalRawFragsSeen << "\n"; + std::cout << "Total ZS Frags Seen : " << _totalZSFragsSeen << "\n"; + std::cout << "Total PH Frags Seen : " << _totalPHFragsSeen << "\n"; + std::cout << "Total Raw Prescaled Frags : " << _totalRawFragsPrescaled << "\n"; + std::cout << "Total ZS Prescaled Frags : " << _totalZSFragsPrescaled << "\n"; + std::cout << "Total Raw Frags Flagged Bad Only : " << _totalRawFragsFlaggedBadOnly << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only : " << _totalRawFragsFlaggedMissingOnly << "\n"; + std::cout << "Total Raw Frags Flagged Bad And Missing : " << _totalRawFragsFlaggedBadAndMissing << "\n"; + std::cout << "\n"; + std::cout << "Total RAW Frags seen (HPGe) : " << _totalRawFragsSeenHPGe << "\n"; + std::cout << "Total ZS Frags seen (HPGe) : " << _totalZSFragsSeenHPGe << "\n"; + std::cout << "Total PH Frags seen (HPGe) : " << _totalPHFragsSeenHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total RAW Frags seen (LaBr) : " << _totalRawFragsSeenLaBr << "\n"; + std::cout << "Total ZS Frags seen (LaBr) : " << _totalZSFragsSeenLaBr << "\n"; + std::cout << "Total PH Frags seen (LaBr) : " << _totalPHFragsSeenLaBr << "\n"; + + // Data Type Summary - post-filtering (General) + std::cout << "\n--- Data Types Read General (Post - Filtering) ---\n"; + std::cout << "Total Good Raw Frags : " << _totalGoodRawFrags << "\n"; + std::cout << "Total Good ZS Frags : " << _totalGoodZSFrags << "\n"; + std::cout << "Total Good PH Frags : " << _totalGoodPHFrags << "\n"; + std::cout << "\n"; + std::cout << "Total Zero Raw Frags : " << _totalZeroRawFrags << "\n"; + std::cout << "Total Zero ZS Frags : " << _totalZeroZSFrags << "\n"; + std::cout << "Total Zero PH Frags : " << _totalZeroPHFrags << "\n"; + std::cout << "\n"; + std::cout << "Total Empty Raw Frags : " << _totalEmptyRawFrags << "\n"; + std::cout << "Total Empty ZS Frags : " << _totalEmptyZSFrags << "\n"; + std::cout << "Total Empty PH Frags : " << _totalEmptyPHFrags << "\n"; + + // Data Type Summary - post-filtering (HPGe) + std::cout << "\n--- Data Types Read HPGe (Post - Filtering) ---\n"; + std::cout << "Total Good Raw Frags (HPGe) : " << _totalGoodRawFragsHPGe << "\n"; + std::cout << "Total Good ZS Frags (HPGe) : " << _totalGoodZSFragsHPGe << "\n"; + std::cout << "Total Good PH Frags (HPGe) : " << _totalGoodPHFragsHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total Zero Raw Frags (HPGe) : " << _totalZeroRawFragsHPGe << "\n"; + std::cout << "Total Zero ZS Frags (HPGe) : " << _totalZeroZSFragsHPGe << "\n"; + std::cout << "Total Zero PH Frags (HPGe) : " << _totalZeroPHFragsHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total Empty Raw Frags (HPGe) : " << _totalEmptyRawFragsHPGe << "\n"; + std::cout << "Total Empty ZS Frags (HPGe) : " << _totalEmptyZSFragsHPGe << "\n"; + std::cout << "Total Empty PH Frags (HPGe) : " << _totalEmptyPHFragsHPGe << "\n"; + std::cout << "\n"; + std::cout << "Total Raw Prescaled Frags (HPGe) : " << _totalRawFragsPrescaledHPGe << "\n"; + // Raw Prescaled Frags can still be considered good -> data simply was not sent + // Still be classified as good for now, however we do not save the waveform + std::cout << "Total ZS Prescaled Frags (HPGe) : " << _totalZSFragsPrescaledHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Bad Only (HPGe) : " << _totalRawFragsFlaggedBadOnlyHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only (HPGe) : " << _totalRawFragsFlaggedMissingOnlyHPGe << "\n"; + std::cout << "Total Raw Frags Flagged Bad & Missing (HPGe) : " << _totalRawFragsFlaggedBadAndMissingHPGe << "\n"; + + // Data Type Summary - post-filtering (LaBr) + std::cout << "\n--- Data Types Read LaBr (Post - Filtering) ---\n"; + std::cout << "Total Good Raw Frags (LaBr) : " << _totalGoodRawFragsLaBr << "\n"; + std::cout << "Total Good ZS Frags (LaBr) : " << _totalGoodZSFragsLaBr << "\n"; + std::cout << "Total Good PH Frags (LaBr) : " << _totalGoodPHFragsLaBr << "\n"; + std::cout << "\n"; + std::cout << "Total Zero Raw Frags (LaBr) : " << _totalZeroRawFragsLaBr << "\n"; + std::cout << "Total Zero ZS Frags (LaBr) : " << _totalZeroZSFragsLaBr << "\n"; + std::cout << "Total Zero PH Frags (LaBr) : " << _totalZeroPHFragsLaBr << "\n"; + std::cout << "\n"; + std::cout << "Total Empty Raw Frags (LaBr) : " << _totalEmptyRawFragsLaBr << "\n"; + std::cout << "Total Empty ZS Frags (LaBr) : " << _totalEmptyZSFragsLaBr << "\n"; + std::cout << "Total Empty PH Frags (LaBr) : " << _totalEmptyPHFragsLaBr << "\n"; + std::cout << "\n"; + std::cout << "Total Raw Prescaled Frags (LaBr) : " << _totalRawFragsPrescaledLaBr << "\n"; + std::cout << "Total ZS Prescaled Frags (LaBr) : " << _totalZSFragsPrescaledLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Bad Only (LaBr) : " << _totalRawFragsFlaggedBadOnlyLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only (LaBr) : " << _totalRawFragsFlaggedMissingOnlyLaBr << "\n"; + std::cout << "Total Raw Frags Flagged Bad & Missing (LaBr) : " << _totalRawFragsFlaggedBadAndMissingLaBr << "\n"; + + std::cout << "\n=== Extra Filters ===\n"; + std::cout << "Invalid Raw Headers : " << _totalRawFragsWithInvalidHeaders << "\n"; + std::cout << "Invalid Raw Headers (HPGe) : " << _totalRawFragsWithInvalidHeadersHPGe << "\n"; + std::cout << "Invalid Raw Headers (LaBr) : " << _totalRawFragsWithInvalidHeadersLaBr << "\n"; + std::cout << "Invalid Raw Anchors : " << _totalRawFragsWithInvalidAnchors << "\n"; + std::cout << "Invalid Raw Anchors (HPGe) : " << _totalRawFragsWithInvalidAnchorsHPGe << "\n"; + std::cout << "Invalid Raw Anchors (LaBr) : " << _totalRawFragsWithInvalidAnchorsLaBr << "\n"; + std::cout << "ZS Skipped Due to Raw Flag (HPGe) : " << _totalZSFragsSkippedDueToRawFlagHPGe << "\n"; + std::cout << "ZS Skipped Due to Raw Flag (LaBr) : " << _totalZSFragsSkippedDueToRawFlagLaBr << "\n"; + std::cout << "PH Skipped Due to Raw Flag (HPGe) : " << _totalPHFragsSkippedDueToRawFlagHPGe << "\n"; + std::cout << "PH Skipped Due to Raw Flag (LaBr) : " << _totalPHFragsSkippedDueToRawFlagLaBr << "\n"; + + + std::cout << "\n===========================================================\n"; + + } } DEFINE_ART_MODULE(STMDigisFromFragments) diff --git a/DAQ/src/STMPrintFragments_module.cc b/DAQ/src/STMPrintFragments_module.cc index fa6d9e56f9..042818ab2a 100644 --- a/DAQ/src/STMPrintFragments_module.cc +++ b/DAQ/src/STMPrintFragments_module.cc @@ -205,9 +205,9 @@ void STMPrintFragments::analyze(const Event& event) << ", PhysicalWords : " << physicalWords << "\n" << ", stmDataWords : " << stmDataWords << "\n"; size_t seg = 0; - size_t totalLen= 0; - uint16_t lastZSindex = 0; - uint16_t lastLen = 0; + //size_t totalLen= 0; + //uint16_t lastZSindex = 0; + //uint16_t lastLen = 0; while (dataPtr+2 <= dataEnd){ uint16_t current_zs_location = static_cast(dataPtr[0]); From d4318f956f3e1c356d04746d65b9c42fff71ac15 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Mon, 17 Aug 2026 21:22:58 -0500 Subject: [PATCH 07/21] Adressing PR comments, Fixed plotSTMWaveformDigis to properly include path and xAxis Fixed STMPrintFragments mispelling of fcl parameter Fixed the xrange in PlotSTMPHSpectrum to STMDigis now reports if there is a mismatch in nPairsInFragment and phCount We now save how many raw and zs are prescaled in STMFragSummaries to keep them seperate from the other data classifications PH Digis are being saved from ph peak to (time,ph) --- DAQ/src/STMDigisFromFragments_module.cc | 132 +++++++++++++++------ DAQ/src/STMPrintFragments_module.cc | 17 +-- DAQ/test/inspectSTMFile.fcl | 12 +- RecoDataProducts/inc/STMFragmentSummary.hh | 26 ++-- STMReco/fcl/plotSTMWaveformDigis.fcl | 4 +- STMReco/src/PlotSTMPHSpectrum_module.cc | 2 +- STMReco/src/PlotSTMWaveformDigis_module.cc | 15 +-- 7 files changed, 128 insertions(+), 80 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 1bbcd822c8..0a69274d84 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -113,6 +113,7 @@ class art::STMDigisFromFragments : public EDProducer size_t _totalRawFragsFlaggedBadAndMissing{0}; size_t _totalRawFragsWithInvalidHeaders{0}; size_t _totalRawFragsWithInvalidAnchors{0}; + size_t _totalPHCountMismatch{0}; // Detector Summary variables size_t _totalEventsWithBothDetectors{0}; @@ -144,6 +145,7 @@ class art::STMDigisFromFragments : public EDProducer size_t _totalPHFragsSkippedDueToRawFlagHPGe{0};// We want to skip PH if raw is flagged bad/missing size_t _totalRawFragsPrescaledHPGe{0};// track how many raw fragments were prescaled size_t _totalZSFragsPrescaledHPGe{0};// track how many zs fragments were prescaled + size_t _totalPHCountMismatchHPGe{0}; // LaBr job-level variables size_t _totalContainersLaBr{0}; @@ -169,6 +171,7 @@ class art::STMDigisFromFragments : public EDProducer size_t _totalPHFragsSkippedDueToRawFlagLaBr{0};// We want to skip PH if raw is flagged bad/missing size_t _totalRawFragsPrescaledLaBr{0};// track how many raw fragments were prescaled size_t _totalZSFragsPrescaledLaBr{0};// track how many ZS fragments were prescaled + size_t _totalPHCountMismatchLaBr{0}; // Used to set and verify the state of the raw parent fragment for zs fragments, event based struct RawParentState { @@ -226,6 +229,7 @@ class art::STMDigisFromFragments : public EDProducer size_t phFragsSkippedDueToRawFlag{0}; size_t setsSkippedDueToRawFlag{0}; size_t setsSkippedDueToInvalidHeaders{0}; + size_t phCountMismatch{0}; }; @@ -267,15 +271,15 @@ STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table STMFragmentsHandle; event.getByLabel(_stmFragmentsTag, STMFragmentsHandle); const auto& STMFragments = STMFragmentsHandle.product(); - uint16_t outerFragID; + uint16_t outerFragID{0}; // Loop over outer fragments for (const auto& frag : *STMFragments) { @@ -341,10 +345,12 @@ void STMDigisFromFragments::produce(Event& event) if (container_frag.isHPGeContainer()) { if (_verbosityLevel > 2) { std::cout << "Processing HPGe container fragment with ID: " << outerFragID << "\n"; } ++_totalContainersHPGe; eventHasHPGe = true; _totalInnerFragsHPGe += blocks; + innerFragsHPGeThisEvent += blocks; ++containerFragsHPGeThisEvent; } else if (container_frag.isLaBrContainer()) { if (_verbosityLevel > 2) { std::cout << "Processing LaBr container fragment with ID: " << outerFragID << "\n"; } ++_totalContainersLaBr; eventHasLaBr = true; _totalInnerFragsLaBr += blocks; + innerFragsLaBrThisEvent += blocks; ++containerFragsLaBrThisEvent; } else { if (_verbosityLevel > 0) { @@ -443,16 +449,13 @@ void STMDigisFromFragments::produce(Event& event) continue; } - //Check if raw fragment is prescaled to determine whether to skip checks + // Check if raw fragment is prescaled to determine whether to skip checks + // If the fragment is prescaled we do not save the waveform + // If the fragment is prescaled we also do not want to check its payload + // We do want relevant infrormation for the zs and ph headerState.rawPrescaled = stm_frag.rawPrescaled(); headerState.rawPrescaleValue = stm_frag.rawPrescaleValue(); - if (headerState.rawPrescaled) { - ++eventMetrics.raw.prescaled; - ++_totalRawFragsPrescaled; - isHPGe ? ++_totalRawFragsPrescaledHPGe : ++_totalRawFragsPrescaledLaBr; - } - // Extract rest of the raw header information // Even if raw is prescaled we still want to save zs info just in case // before checking whats in the payload @@ -464,10 +467,35 @@ void STMDigisFromFragments::produce(Event& event) headerState.expectedZSRegions = stm_frag.zsRegions(); headerState.expectedPHCount = stm_frag.phCount(); + if (headerState.rawPrescaled) { + ++eventMetrics.raw.prescaled; + ++_totalRawFragsPrescaled; + isHPGe ? ++_totalRawFragsPrescaledHPGe : ++_totalRawFragsPrescaledLaBr; + + parentState.ptr = {}; + parentState.available = false; + continue; + } - // Check if raw frag is empty auto payloadPtr = stm_frag.payloadBegin(); auto payloadWords = stm_frag.payloadWords(); + + // 22 Header Words + adcs < = dataWords + // This check comes after ensuring raw is not prescaled + if (stm::RawHeader::WORDS + payloadWords > stm_frag.dataWords()) { + // this is an invalid-header case + ++_totalRawFragsWithInvalidHeaders; + isHPGe ? ++_totalRawFragsWithInvalidHeadersHPGe : ++_totalRawFragsWithInvalidHeadersLaBr; + ++eventMetrics.rawFragsWithInvalidHeaders; + ++eventMetrics.setsSkippedDueToInvalidHeaders; + ++_totalUnreadInnerFrags; + headerState.skipCurrentSet = true; + parentState.available = false; + continue; + } + + // Ideally by here we know the raw frag is good and its payload can be checked + // Check if raw frag is empty bool allZeros = true; if (payloadWords == 0) { if (_verbosityLevel > 2){ @@ -500,7 +528,7 @@ void STMDigisFromFragments::produce(Event& event) isHPGe? ++_totalZeroRawFragsHPGe: ++_totalZeroRawFragsLaBr; continue; } - // At this point the raw fragment has payload words and is no zero filled + // At this point the raw fragment has payload words and is non zero filled // We continue processing this raw fragment if (_verbosityLevel > 2) { std::cout << "\nFound a good raw fragment at Event : " << _totalEvents << "\n" @@ -533,14 +561,14 @@ void STMDigisFromFragments::produce(Event& event) // Save waveforms based on fcl configurations // Save Raw Waveform With Header Info - HPGe - if (_saveRawWaveformsWithHeaderHPGe && isHPGe && !headerState.rawPrescaled){ + if (_saveRawWaveformsWithHeaderHPGe && isHPGe){ auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); stm_waveform.set_data(dataWords,dataPtr); rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); } // Save Raw Waveform and Save parent Ptr - HPGe - if (_saveRawWaveformsHPGe && isHPGe && !headerState.rawPrescaled){ + if (_saveRawWaveformsHPGe && isHPGe){ stm_waveform.set_data(payloadWords, payloadPtr); rawWaveformDigisHPGe->emplace_back(stm_waveform); @@ -551,14 +579,14 @@ void STMDigisFromFragments::produce(Event& event) parentState.available = true; } // Save Raw Waveform With Header Info - LaBr - if (_saveRawWaveformsWithHeaderLaBr && isLaBr && !headerState.rawPrescaled){ + if (_saveRawWaveformsWithHeaderLaBr && isLaBr){ auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); stm_waveform.set_data(dataWords,dataPtr); rawWaveformDigisWithHeaderLaBr->emplace_back(stm_waveform); } // Save Raw Waveform and Save parent Ptr - LaBr - if (_saveRawWaveformsLaBr && isLaBr && !headerState.rawPrescaled){ + if (_saveRawWaveformsLaBr && isLaBr){ stm_waveform.set_data(payloadWords, payloadPtr); rawWaveformDigisLaBr->emplace_back(stm_waveform); @@ -684,7 +712,6 @@ void STMDigisFromFragments::produce(Event& event) << "--ZS Frag\n"; } - while (dataPtr + 2 <= dataEndPtr){ if (zsInfoWasExtracted && regionCounter >= zsRegions) { break; @@ -893,9 +920,33 @@ void STMDigisFromFragments::produce(Event& event) // Check if PH Pair count matches expected count from raw header size_t const nPairsInFragment = payloadWords / 2; + + // Add a print out to compare the two if there is a mismatch + // Maybe add an if (nPairsInfragment != phCount) + // Include a counter for this -> future decide whether to throw or not + if (extractedPHInfo && nPairsInFragment != phCount) { + if (_verbosityLevel > 2) { + std::cout << "\nPH Count Comparison\n" + << "Number of PH pairs we read in fragment : " << nPairsInFragment <<"\n" + << "Number of PH pars from raw header : " << phCount << "\n"; + } + ++_totalPHCountMismatch; + isHPGe ? ++_totalPHCountMismatchHPGe : ++_totalPHCountMismatchLaBr; + ++eventMetrics.phCountMismatch; + } + // Here you either read the lowest pair count from raw header or what is in fragment // If not you read what what is in the fragment anyway size_t const nPairsToRead = extractedPHInfo ? std::min(nPairsInFragment, phCount) : nPairsInFragment; + if (_verbosityLevel > 2) { + std::cout << "\nPH Pair Count We Will Processes : " << nPairsToRead << "\n" + << "Pair Count coming from Fragment : " << (nPairsInFragment < phCount ? "Yes" : "No") << "\n" + << "Pair Count coming from Raw Header : " << (phCount < nPairsInFragment ? "Yes" : "No") << "\n"; + } + + if (nPairsToRead ==0){ + continue; + } // Check if zero filled // Since its a (time,PH) pair we will check every second entry for the PH value @@ -958,6 +1009,7 @@ void STMDigisFromFragments::produce(Event& event) else { // fallback for unreadable fragment ++_totalUnreadInnerFrags; //Job Summary Counter + ++unknownFragsThisEvent; if (_verbosityLevel > 0 ) { std::cout << "Encountered an unreadable inner fragment " << "\n" << "Frag Index : " << i << "\n" @@ -1012,6 +1064,7 @@ void STMDigisFromFragments::produce(Event& event) containerFragsHPGeThisEvent,innerFragsHPGeThisEvent, badHPGeFragsThisEvent, missingHPGeFragsThisEvent, HPGeEventMetrics.zsFragsSkippedDueToRawFlag, HPGeEventMetrics.phFragsSkippedDueToRawFlag, + HPGeEventMetrics.raw.prescaled, HPGeEventMetrics.zs.prescaled, HPGeEventMetrics.raw.good, HPGeEventMetrics.zs.good, HPGeEventMetrics.ph.good, HPGeEventMetrics.raw.zero, HPGeEventMetrics.zs.zero, HPGeEventMetrics.ph.zero, HPGeEventMetrics.raw.empty, HPGeEventMetrics.zs.empty, HPGeEventMetrics.ph.empty @@ -1021,6 +1074,7 @@ void STMDigisFromFragments::produce(Event& event) containerFragsLaBrThisEvent,innerFragsLaBrThisEvent, badLaBrFragsThisEvent, missingLaBrFragsThisEvent, LaBrEventMetrics.zsFragsSkippedDueToRawFlag, LaBrEventMetrics.phFragsSkippedDueToRawFlag, + LaBrEventMetrics.raw.prescaled, LaBrEventMetrics.zs.prescaled, LaBrEventMetrics.raw.good, LaBrEventMetrics.zs.good, LaBrEventMetrics.ph.good, LaBrEventMetrics.raw.zero, LaBrEventMetrics.zs.zero, LaBrEventMetrics.ph.zero, LaBrEventMetrics.raw.empty, LaBrEventMetrics.zs.empty, LaBrEventMetrics.ph.empty @@ -1088,18 +1142,22 @@ void STMDigisFromFragments::produce(Event& event) std::cout << "Bad and Missing Raw Frags (LaBr) : " << LaBrEventMetrics.rawFragsFlaggedBadAndMissing << "\n"; // Extra Filters std::cout << "\n=== Extra Filters ===\n"; - std::cout << "Raw Frags With Invalid Headers (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidHeaders; - std::cout << "Raw Frags With Invalid Anchors (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidAnchors; - std::cout << "ZS Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.zsFragsSkippedDueToRawFlag; - std::cout << "PH Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.phFragsSkippedDueToRawFlag; - std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.setsSkippedDueToRawFlag; - std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (HPGe) : " << HPGeEventMetrics.setsSkippedDueToInvalidHeaders; + std::cout << "Container Frags : " << containerFragsThisEvent << "\n"; + std::cout << "Inner Frags This Event : " << innerFragsThisEvent << "\n"; + std::cout << "Unknown Frags : " << unknownFragsThisEvent << "\n"; + std::cout << "Raw Frags With Invalid Headers (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidHeaders << "\n"; + std::cout << "Raw Frags With Invalid Anchors (HPGe) : " << HPGeEventMetrics.rawFragsWithInvalidAnchors << "\n"; + std::cout << "ZS Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.zsFragsSkippedDueToRawFlag << "\n"; + std::cout << "PH Frags Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.phFragsSkippedDueToRawFlag << "\n"; + std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (HPGe) : " << HPGeEventMetrics.setsSkippedDueToRawFlag << "\n"; + std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (HPGe) : " << HPGeEventMetrics.setsSkippedDueToInvalidHeaders << "\n"; std::cout << "\n"; - std::cout << "Raw Frags With Invalid Headers (LaBr) : " << LaBrEventMetrics.rawFragsWithInvalidHeaders; - std::cout << "ZS Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.zsFragsSkippedDueToRawFlag; - std::cout << "PH Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.phFragsSkippedDueToRawFlag; - std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.setsSkippedDueToRawFlag; - std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (LaBr) : " << LaBrEventMetrics.setsSkippedDueToInvalidHeaders; + std::cout << "Raw Frags With Invalid Headers (LaBr) : " << LaBrEventMetrics.rawFragsWithInvalidHeaders << "\n"; + std::cout << "Raw Frags With Inavlid Anchors (LaBr) : " << LaBrEventMetrics.rawFragsWithInvalidAnchors << "\n"; + std::cout << "ZS Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.zsFragsSkippedDueToRawFlag << "\n"; + std::cout << "PH Frags Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.phFragsSkippedDueToRawFlag << "\n"; + std::cout << "Raw/ZS/PH Sets Skipped Due To Raw Flags (LaBr) : " << LaBrEventMetrics.setsSkippedDueToRawFlag << "\n"; + std::cout << "Raw/ZS/PH Sets Skipped Due To Invalid Raw Headers (LaBr) : " << LaBrEventMetrics.setsSkippedDueToInvalidHeaders << "\n"; std::cout << "=================================\n"; } @@ -1162,7 +1220,7 @@ void STMDigisFromFragments::endJob() { std::cout << "Total Raw Prescaled Frags : " << _totalRawFragsPrescaled << "\n"; std::cout << "Total ZS Prescaled Frags : " << _totalZSFragsPrescaled << "\n"; std::cout << "Total Raw Frags Flagged Bad Only : " << _totalRawFragsFlaggedBadOnly << "\n"; - std::cout << "Total Raw Frags Flagged Missing Only : " << _totalRawFragsFlaggedMissingOnly << "\n"; + std::cout << "Total Raw Frags Flagged Missing Only : " << _totalRawFragsFlaggedMissingOnly << "\n"; std::cout << "Total Raw Frags Flagged Bad And Missing : " << _totalRawFragsFlaggedBadAndMissing << "\n"; std::cout << "\n"; std::cout << "Total RAW Frags seen (HPGe) : " << _totalRawFragsSeenHPGe << "\n"; @@ -1202,8 +1260,7 @@ void STMDigisFromFragments::endJob() { std::cout << "Total Empty PH Frags (HPGe) : " << _totalEmptyPHFragsHPGe << "\n"; std::cout << "\n"; std::cout << "Total Raw Prescaled Frags (HPGe) : " << _totalRawFragsPrescaledHPGe << "\n"; - // Raw Prescaled Frags can still be considered good -> data simply was not sent - // Still be classified as good for now, however we do not save the waveform + // Raw Prescaled Frags should be classified as their own data for now std::cout << "Total ZS Prescaled Frags (HPGe) : " << _totalZSFragsPrescaledHPGe << "\n"; std::cout << "Total Raw Frags Flagged Bad Only (HPGe) : " << _totalRawFragsFlaggedBadOnlyHPGe << "\n"; std::cout << "Total Raw Frags Flagged Missing Only (HPGe) : " << _totalRawFragsFlaggedMissingOnlyHPGe << "\n"; @@ -1236,10 +1293,13 @@ void STMDigisFromFragments::endJob() { std::cout << "Invalid Raw Anchors : " << _totalRawFragsWithInvalidAnchors << "\n"; std::cout << "Invalid Raw Anchors (HPGe) : " << _totalRawFragsWithInvalidAnchorsHPGe << "\n"; std::cout << "Invalid Raw Anchors (LaBr) : " << _totalRawFragsWithInvalidAnchorsLaBr << "\n"; - std::cout << "ZS Skipped Due to Raw Flag (HPGe) : " << _totalZSFragsSkippedDueToRawFlagHPGe << "\n"; - std::cout << "ZS Skipped Due to Raw Flag (LaBr) : " << _totalZSFragsSkippedDueToRawFlagLaBr << "\n"; - std::cout << "PH Skipped Due to Raw Flag (HPGe) : " << _totalPHFragsSkippedDueToRawFlagHPGe << "\n"; - std::cout << "PH Skipped Due to Raw Flag (LaBr) : " << _totalPHFragsSkippedDueToRawFlagLaBr << "\n"; + std::cout << "ZS Skipped Due To Raw Flags (HPGe) : " << _totalZSFragsSkippedDueToRawFlagHPGe << "\n"; + std::cout << "ZS Skipped Due To Raw Flags (LaBr) : " << _totalZSFragsSkippedDueToRawFlagLaBr << "\n"; + std::cout << "PH Skipped Due To Raw Flags (HPGe) : " << _totalPHFragsSkippedDueToRawFlagHPGe << "\n"; + std::cout << "PH Skipped Due To Raw Flags (LaBr) : " << _totalPHFragsSkippedDueToRawFlagLaBr << "\n"; + std::cout << "PH Count Mismatches Encountered : " << _totalPHCountMismatch << "\n"; + std::cout << "PH Count Mismatches Encountered (HPGe) : " << _totalPHCountMismatchHPGe << "\n"; + std::cout << "PH Count Mismatches Encountered (LaBr) : " << _totalPHCountMismatchLaBr << "\n"; std::cout << "\n===========================================================\n"; diff --git a/DAQ/src/STMPrintFragments_module.cc b/DAQ/src/STMPrintFragments_module.cc index 042818ab2a..c85ffb95e3 100644 --- a/DAQ/src/STMPrintFragments_module.cc +++ b/DAQ/src/STMPrintFragments_module.cc @@ -116,12 +116,15 @@ void STMPrintFragments::analyze(const Event& event) const auto frag_id = inner_frag->fragmentID(); const auto stmDataBegin = stm_frag.dataBegin(); const auto stmDataWords = stm_frag.dataWords(); - const auto stmDataEnd = stmDataBegin + stmDataWords; 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(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; @@ -197,7 +200,10 @@ void STMPrintFragments::analyze(const Event& event) auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); - auto dataEnd = dataPtr + dataWords; + + // Limit what you read here + size_t const wordsToRead = std::min(dataWords, physicalWords); + auto dataEnd = dataPtr + wordsToRead; std::cout << "\n=== ZS Payload Dump ===\n" << "Frag # : " << frag_counter << "\n" @@ -205,17 +211,14 @@ void STMPrintFragments::analyze(const Event& event) << ", PhysicalWords : " << physicalWords << "\n" << ", stmDataWords : " << stmDataWords << "\n"; size_t seg = 0; - //size_t totalLen= 0; - //uint16_t lastZSindex = 0; - //uint16_t lastLen = 0; - while (dataPtr+2 <= dataEnd){ + while (dataEnd - dataPtr >= 2){ uint16_t current_zs_location = static_cast(dataPtr[0]); uint16_t current_zs_size = static_cast(dataPtr[1]); std::cout << "Currnent ZS Index : " << current_zs_location << ", current ZS Length : " << current_zs_size << "\n" ; auto adc = dataPtr + 2; - if (adc + current_zs_size > dataEnd){ + if (current_zs_size > static_cast(dataEnd - adc)){ std::cout << "Malformed or truncated ZS Region: Declared size extends beyond fragment data " << "\n"; break; } diff --git a/DAQ/test/inspectSTMFile.fcl b/DAQ/test/inspectSTMFile.fcl index b630e85543..6a200677e9 100644 --- a/DAQ/test/inspectSTMFile.fcl +++ b/DAQ/test/inspectSTMFile.fcl @@ -47,20 +47,20 @@ physics : { stmPrint : { module_type : STMPrintFragments stmTag : "daq:ContainerSTM" - printEverything: false - printInnerFragments: false - printPayloads : false + printEverything : false + printInnerFrags : false + printPayloads : false } } t1 : [ makeSTMDigis ] - #e1 : [ stmOutput ] + e1 : [ stmOutput ] #e1 : [ ] #e1 : [ frag, stmOutput ] trigger_paths : [t1] - #end_paths : [e1] + end_paths : [e1] } @@ -71,7 +71,7 @@ services.TimeTracker.printSummary: true outputs : { stmOutput : { module_type : RootOutput - fileName : "data/dig.stm.art" + fileName : "dig.stm.art" outputCommands : [ "keep *_*_*_*", "drop artdaq::*_*_*_*" ] } } diff --git a/RecoDataProducts/inc/STMFragmentSummary.hh b/RecoDataProducts/inc/STMFragmentSummary.hh index 089f7d59b1..c4c4d2ef48 100644 --- a/RecoDataProducts/inc/STMFragmentSummary.hh +++ b/RecoDataProducts/inc/STMFragmentSummary.hh @@ -20,6 +20,7 @@ namespace mu2e { STMFragmentSummary() : _nContainerFrags(0), _nInnerFrags(0), _nRawFragsFlaggedBad(0), _nRawFragsFlaggedMissing(0), _nZSFragsSkippedDueToRawFlag(0), _nPHFragsSkippedDueToRawFlag(0), + _nPrescaledRawFrags(0),_nPrescaledZSFrags(0), _nGoodRawFrags(0),_nGoodZSFrags(0),_nGoodPHFrags(0), _nZeroRawFrags(0),_nZeroZSFrags(0),_nZeroPHFrags(0), _nEmptyRawFrags(0),_nEmptyZSFrags(0),_nEmptyPHFrags(0){}; @@ -27,12 +28,14 @@ namespace mu2e { STMFragmentSummary(size_t nContainerFrags, size_t nInnerFrags, size_t nRawFragsFlaggedBad, size_t nRawFragsFlaggedMissing, size_t nZSFragsSkippedDueToRawFlag, size_t nPHFragsSkippedDueToRawFlag, + size_t nPrescaledRawFrags, size_t nPrescaledZSFrags, size_t nGoodRawFrags,size_t nGoodZSFrags, size_t nGoodPHFrags, size_t nZeroRawFrags, size_t nZeroZSFrags, size_t nZeroPHFrags, size_t nEmptyRawFrags, size_t nEmptyZSFrags, size_t nEmptyPHFrags) : _nContainerFrags(nContainerFrags), _nInnerFrags(nInnerFrags), _nRawFragsFlaggedBad(nRawFragsFlaggedBad), _nRawFragsFlaggedMissing(nRawFragsFlaggedMissing), _nZSFragsSkippedDueToRawFlag(nZSFragsSkippedDueToRawFlag), _nPHFragsSkippedDueToRawFlag(nPHFragsSkippedDueToRawFlag), + _nPrescaledRawFrags(nPrescaledRawFrags),_nPrescaledZSFrags(nPrescaledZSFrags), _nGoodRawFrags(nGoodRawFrags),_nGoodZSFrags(nGoodZSFrags),_nGoodPHFrags(nGoodPHFrags), _nZeroRawFrags(nZeroRawFrags),_nZeroZSFrags(nZeroZSFrags),_nZeroPHFrags(nZeroPHFrags), _nEmptyRawFrags(nEmptyRawFrags),_nEmptyZSFrags(nEmptyZSFrags),_nEmptyPHFrags(nEmptyPHFrags) {}; @@ -48,16 +51,10 @@ namespace mu2e { size_t nZSFragsSkippedDueToRawFlag() const { return _nZSFragsSkippedDueToRawFlag; } size_t nPHFragsSkippedDueToRawFlag() const { return _nPHFragsSkippedDueToRawFlag; } - // Skip decisions - /* ->Maybe add later, for now just want general skipped summary - size_t nZSFragsSkippedDueToBadFlag() const { return _nZSFragsSkippedDueToBadRaw; } - size_t nZSFragsSkippedDueToMissingRaw() const { return _nZSFragsSkippedDueToMissingRaw{}; } - - size_t nPHFragsSkippedDueToBadRaw() const {return _nPHFragsSkippedDueToBadRaw; } - size_t nPHFragsSkippedDueToMissingRaw() const { return _nPHFragsSkippedDueToMissingRaw; } - */ - // Filter/Classifications results + size_t nPrescaledRawFrags() const {return _nPrescaledRawFrags; } + size_t nPrescaledZSFrags() const{return _nPrescaledZSFrags; } + size_t nGoodRawFrags() const { return _nGoodRawFrags; } size_t nGoodZSFrags() const { return _nGoodZSFrags; } size_t nGoodPHFrags() const { return _nGoodPHFrags; } @@ -83,15 +80,10 @@ namespace mu2e { size_t _nZSFragsSkippedDueToRawFlag{}; size_t _nPHFragsSkippedDueToRawFlag{}; - /* ->Maybe add later, for now just want general skipped summary - size_t _nZSFragsSkippedDueToBadRaw{}; - size_t _nZSFragsSkippedDueToMissingRaw{}; - - size_t _nPHFragsSkippedDueToBadRaw{}; - size_t _nPHFragsSkippedDueToMissingRaw{}; - */ - // Filter/Classifications results + size_t _nPrescaledRawFrags{}; + size_t _nPrescaledZSFrags{}; + size_t _nGoodRawFrags{}; size_t _nGoodZSFrags{}; size_t _nGoodPHFrags{}; diff --git a/STMReco/fcl/plotSTMWaveformDigis.fcl b/STMReco/fcl/plotSTMWaveformDigis.fcl index d47fd38b4e..7b77a14fb5 100644 --- a/STMReco/fcl/plotSTMWaveformDigis.fcl +++ b/STMReco/fcl/plotSTMWaveformDigis.fcl @@ -14,7 +14,7 @@ source : { services : { @table::Services.Core - TFileService : { fileName : "data/stmWaveformDigis.root" } + TFileService : { fileName : "stmWaveformDigis.root" } } physics: { @@ -65,7 +65,7 @@ physics: { } # setup paths trigger_paths: [ ] - anaPath : [ plotRawWaveformDigisHPGe, plotRawWaveformDigisTimeHPGe, plotRawWaveformDigisEvTimeHPGe, plotZSWaveformDigisHPGe, plotRawWaveformDigisLaBr, plotZSWaveformDigisLaBr ] + anaPath : [ plotRawWaveformDigisHPGe, plotRawWaveformDigisTimeHPGe, plotZSWaveformDigisHPGe, plotRawWaveformDigisLaBr, plotZSWaveformDigisLaBr ] end_paths: [anaPath] } diff --git a/STMReco/src/PlotSTMPHSpectrum_module.cc b/STMReco/src/PlotSTMPHSpectrum_module.cc index bd20c44a2a..f29c8bbffe 100644 --- a/STMReco/src/PlotSTMPHSpectrum_module.cc +++ b/STMReco/src/PlotSTMPHSpectrum_module.cc @@ -61,7 +61,7 @@ namespace mu2e { // create histograms _phSpectrum=tfs->make("phSpectrum", "PH Spectrum;PulseHeight;Count", 10000, -10000, 0); //bins,min,max _twoDhist=tfs->make("phEvent","Pulse Height vs events;Event Bins; Pulse Height", // (name, title;xtitle;ytitle, nbinsX, xlow, xup, nbinsY, ylow, yup) - 2000,-1000,1000, // X-axis scale + 10,0,10, // X-axis scale 10000,-10000,0); // Y-axis scale } diff --git a/STMReco/src/PlotSTMWaveformDigis_module.cc b/STMReco/src/PlotSTMWaveformDigis_module.cc index 046d8e0964..3162f9686a 100644 --- a/STMReco/src/PlotSTMWaveformDigis_module.cc +++ b/STMReco/src/PlotSTMWaveformDigis_module.cc @@ -37,7 +37,7 @@ namespace mu2e { struct Config { fhicl::Atom stmWaveformDigisTag{ Name("stmWaveformDigisTag"), Comment("InputTag for STMWaveformDigiCollection")}; fhicl::Atom subtractPedestal{ Name("subtractPedestal"), Comment("True/False whether to subtract the pedestal before plotting")}; - fhicl::Atom xAxis{ Name("xAxis"), Comment("Choice of x-axis unit: \"sample_number\", \"adcs_time\", or \"event_time\"")} ; + fhicl::Atom xAxis{ Name("xAxis"), Comment("Choice of x-axis unit: \"sample_number\", \"waveform_time\", or \"event_time\"")} ; fhicl::Atom verbosityLevel{ Name("verbosityLevel"), Comment("Verbosity level")}; }; using Parameters = art::EDAnalyzer::Table; @@ -130,11 +130,10 @@ namespace mu2e { hWaveform->GetYaxis()->SetTitle("ADCs"); if (_xAxis == "sample_number"){ hWaveform->GetXaxis()->SetTitle("Sample Number"); - - } else if (_xAxis == "waveform_time [nsec]"){ - hWaveform->GetXaxis()->SetTitle("Waveform Time"); + } else if (_xAxis == "waveform_time"){ + hWaveform->GetXaxis()->SetTitle("Waveform Time [nsec]"); } else if (_xAxis == "event_time"){ - hWaveform->GetXaxis()->SetTitle("Event Time[nsec]"); + hWaveform->GetXaxis()->SetTitle("Event Time [nsec]"); } if (plotZSOffsetWaveforms){ @@ -151,15 +150,9 @@ namespace mu2e { } histtitle2 << ", offset: " << zs_offset; - //histtitle2 << histtitle2.str() << instance << " , offset : " << zs_offset; - hWaveformOffset = tfs->make( histname2.str().c_str(), histtitle2.str().c_str(), binning.nbins(), binning.low()+zs_offset, binning.high()+zs_offset );//Shifting bins using offset hWaveformOffset->GetYaxis()->SetTitle("ADCs"); hWaveformOffset->GetXaxis()->SetTitle("Sample Number (Includes + Time Offset)"); - // int n_bins = hWaveformOffset->GetNbinsX(); //Grabs already contained nbins from waveform - //double xmin = hWaveformOffset->GetXaxis()->GetXmin();// gets xmin from waveform - //double xmax = hWaveformOffset->GetXaxis()->GetXmax();//gets xman from waveform - //hWaveformOffset->SetBins(n_bins, xmin + zs_offset, xmax + zs_offset);// shifts the xmin and xmax by offset, keeps numbers of bins }//PlotZSOffset for (size_t i_adc = 0; i_adc < waveform.adcs().size(); ++i_adc){ From 58a4d4264f0db626c984471937c5fd56590da072 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Wed, 19 Aug 2026 13:11:10 -0500 Subject: [PATCH 08/21] ntuple for phDigis module --- STMReco/fcl/stmPHTrees.fcl | 38 +++++++++ STMReco/src/STMPHDigiTree_module.cc | 127 ++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 STMReco/fcl/stmPHTrees.fcl create mode 100644 STMReco/src/STMPHDigiTree_module.cc diff --git a/STMReco/fcl/stmPHTrees.fcl b/STMReco/fcl/stmPHTrees.fcl new file mode 100644 index 0000000000..d8d743f378 --- /dev/null +++ b/STMReco/fcl/stmPHTrees.fcl @@ -0,0 +1,38 @@ +# +# Make STMPHDigisTrees +# + +#include "Offline/fcl/standardServices.fcl" +#include "Offline/STMReco/fcl/prolog.fcl" +#include "Offline/STMReco/fcl/prolog_testbeam.fcl" + +process_name: STMPHDigiTree + +source: { + module_type : RootInput +} + +services : { + @table::Services.Core + TFileService : { fileName : "stmPHTree.root" } +} + +physics: { + producers : { } + filters : { } + analyzers : { + + phTreeHPGe : { + module_type : STMPHDigiTree + phDigiTag : "makeSTMDigis:phHPGe" + } + + phTreeLaBr : { + module_type : STMPHDigiTree + phDigiTag : "makeSTMDigis:phLaBr" + } + + } + anaPath : [phTreeHPGe, phTreeLaBr] + end_paths: [anaPath] +} diff --git a/STMReco/src/STMPHDigiTree_module.cc b/STMReco/src/STMPHDigiTree_module.cc new file mode 100644 index 0000000000..69a011376e --- /dev/null +++ b/STMReco/src/STMPHDigiTree_module.cc @@ -0,0 +1,127 @@ +// NTuple dumper for Detector pulse heights + +// stdlib includes +#include + +// art includes +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" + +// exception handling +#include "cetlib_except/exception.h" + +// fhicl includes +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/types/Atom.h" +#include "fhiclcpp/ParameterSet.h" + +// message handling +#include "messagefacility/MessageLogger/MessageLogger.h" + +// Offline includes +#include "Offline/GlobalConstantsService/inc/ParticleDataList.hh" +#include "Offline/MCDataProducts/inc/SimParticle.hh" +#include "Offline/MCDataProducts/inc/StepPointMC.hh" + +// Offline includes I added +#include "Offline/RecoDataProducts/inc/STMPHDigi.hh" +#include "Offline/Mu2eUtilities/inc/STMUtils.hh" + +// ROOT includes +#include "art_root_io/TFileService.h" +#include "TTree.h" +#include "TH1D.h" + +// Mu2e type definitions + +namespace mu2e { + class STMPHDigiTree : public art::EDAnalyzer { + public: + using Name=fhicl::Name; + using Comment=fhicl::Comment; + struct Config { + fhicl::Atom phDigiTag{ Name("phDigiTag"), Comment("Input Tag for STMPHDigiCollection")}; + // Already seperates by detector name -> makeSTMDigis:phHPGe or phLaBr + }; + using Parameters = art::EDAnalyzer::Table; + explicit STMPHDigiTree(const Parameters& conf); + + private: + void analyze(const art::Event& event) override; + void beginJob() override; + //void endJob() override; + + // Token for STM PH Digis + art::ProductToken _stmPHDigisToken; + STMChannel _channel; + + // Store STM PH Digi information + int16_t pulseHeight_ = 0; + uint32_t uncalibratedTime_ = 0; + + // Store file information + Int_t evt_; + Int_t run_; + Int_t subrun_; + + // Tree reference + TTree* ttree = nullptr; + + // STM PH spectrum + TH1D* _phSpectrum = nullptr; + }; + + STMPHDigiTree::STMPHDigiTree(const Parameters& config) : + art::EDAnalyzer{config}, + _stmPHDigisToken(consumes(config().phDigiTag())), + _channel(STMUtils::getChannel(config().phDigiTag())) + {} + + void STMPHDigiTree::beginJob(){ + // Set up TTree here + art::ServiceHandle tfs; + ttree = tfs->make("ttree", "Detector ttree"); + ttree->Branch("pulse_height", &pulseHeight_, "pulse_height/S"); + ttree->Branch("uncalibrated_time", &uncalibratedTime_, "uncalibrated_time/i"); + + // Event Information + ttree->Branch("event", &evt_, "event/I"); + ttree->Branch("run", &run_, "run/I"); + ttree->Branch("subrun", &subrun_, "subrun/I"); + + // Set up histogram + std::string phSpectrumTitle = "PH Spectrum (" + _channel.name() + ")" ; // Builds title PH Spectrum (HPGe/ LaBr) + + _phSpectrum = tfs->make("phSpectrum", + (phSpectrumTitle +";PulseHeight;Count").c_str(), + 10000, -10000, 0); + }; + + void STMPHDigiTree::analyze(const art::Event& event) { + + // We fill here information + // you can reference event and get ifno + evt_ = event.event(); + run_ = event.run(); + subrun_=event.subRun(); + + // Get handle for PH Digis + auto phDigisHandle = event.getValidHandle(_stmPHDigisToken); + const auto& phDigis = *phDigisHandle; + for (const auto& phDigi : phDigis){ + pulseHeight_= phDigi.energy(); + uncalibratedTime_ = phDigi.time(); + + // Fill one row per PH Digi + ttree->Fill(); + _phSpectrum->Fill(pulseHeight_); + + } + + } // end of analyze + +}; // end namespace mu2e + +DEFINE_ART_MODULE(mu2e::STMPHDigiTree) From bbb55c4cda9401956129951e27c0e8360003d356 Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Wed, 19 Aug 2026 13:26:38 -0500 Subject: [PATCH 09/21] Fix whitespace --- RecoDataProducts/inc/STMWaveformDigi.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecoDataProducts/inc/STMWaveformDigi.hh b/RecoDataProducts/inc/STMWaveformDigi.hh index 6d0dc8551c..97a16a05aa 100644 --- a/RecoDataProducts/inc/STMWaveformDigi.hh +++ b/RecoDataProducts/inc/STMWaveformDigi.hh @@ -18,12 +18,12 @@ namespace mu2e { class STMWaveformDigi { public: - // Initialise all variables + // Initialise all variables STMWaveformDigi() : _DetID(0), _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(0), _adcs(std::vector()) {}; - // Constructor for timing plus trig offset + // Constructor for timing plus trig offset STMWaveformDigi(int16_t DetID, uint64_t EWT, uint64_t DTCtime, uint64_t ADCtime, uint32_t trigTimeOffset, std::vector &adcs) : _DetID(DetID), _EWT(EWT), _DTCtime(DTCtime), _ADCtime(ADCtime), \ _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; - // Basic constructor + // Basic constructor STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _DetID(0), _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; int16_t DetID () const { return _DetID; } From 258a8fd908af540303d236c93651758a1524b3e8 Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Wed, 19 Aug 2026 13:48:39 -0500 Subject: [PATCH 10/21] TODO items for coding session --- DAQ/src/STMDigisFromFragments_module.cc | 12 ++++++++++++ RecoDataProducts/inc/STMPHDigi.hh | 1 + RecoDataProducts/inc/STMWaveformDigi.hh | 8 ++++---- STMReco/src/STMPHDigiTree_module.cc | 7 +++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 0a69274d84..36df363be6 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -397,6 +397,7 @@ void STMDigisFromFragments::produce(Event& event) parentState.available = false; parentState.index = 0; ++eventMetrics.raw.seen; + // TODO: set EWT = header_frag.eventWindowTag(); // check header+adcs is not less than expected header length (22) if(stm_frag.dataWords() < stm::RawHeader::WORDS){ @@ -566,6 +567,8 @@ void STMDigisFromFragments::produce(Event& event) auto dataWords = stm_frag.dataWords(); stm_waveform.set_data(dataWords,dataPtr); rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); + // TODO: + // rawWaveformDigisWithHeaderHPGe->emplace(std::make_pair(EWT, std::vector(stm_waveform)); } // Save Raw Waveform and Save parent Ptr - HPGe if (_saveRawWaveformsHPGe && isHPGe){ @@ -613,6 +616,7 @@ void STMDigisFromFragments::produce(Event& event) // Determine which detector this ZS fragment belongs to bool const isHPGe = stm_frag.isHPGe(); bool const isLaBr = stm_frag.isLaBr(); + // TODO: std::vector zs_waveforms; // Double check that the fragment belongs to one of the expected detectors if (!isHPGe && !isLaBr){ @@ -838,6 +842,7 @@ void STMDigisFromFragments::produce(Event& event) // Emplacing if (isHPGe && _saveZSWaveformsHPGe) { // emplacing HPGe waveform digi + //TODO: change to the temporary zs_waveforms defined earlier zsWaveformDigisHPGe->emplace_back(zsDigi); if (_verbosityLevel > 2 && zsDigi.hasParent()) { std::cout << "\nZS HPGe Parent Raw index : " << zsDigi.parent().key() @@ -859,6 +864,9 @@ void STMDigisFromFragments::produce(Event& event) isHPGe ? ++_totalGoodZSFragsHPGe : ++_totalGoodZSFragsLaBr; ++eventMetrics.zs.good; + // TODO: emplace into the map + // zs_waveform_map->emplace(std::make_pair(EWT, zs_waveforms)); + }// End of ZS fragmment check else if (stm_frag.isPH()){ ++_totalPHFragsSeen; @@ -866,6 +874,8 @@ void STMDigisFromFragments::produce(Event& event) bool const isHPGe = stm_frag.isHPGe(); bool const isLaBr = stm_frag.isLaBr(); + // TODO: make a temporary std::vector + if (!isHPGe && !isLaBr) { ++_totalUnreadInnerFrags; continue; @@ -986,6 +996,7 @@ void STMDigisFromFragments::produce(Event& event) // Emplace Back (Always On) if (isHPGe) { + // TODO: change to fill the temporary ph_digis vector phDigisHPGe->emplace_back(PH_digi); } if (isLaBr) { @@ -1004,6 +1015,7 @@ void STMDigisFromFragments::produce(Event& event) ++_totalGoodPHFrags; isHPGe ? ++_totalGoodPHFragsHPGe : ++_totalGoodPHFragsLaBr; ++eventMetrics.ph.good; + // TODO: insert into PHDigi map }// End of PH fragment check else { diff --git a/RecoDataProducts/inc/STMPHDigi.hh b/RecoDataProducts/inc/STMPHDigi.hh index d6d5fc9c1c..86d5398ee5 100644 --- a/RecoDataProducts/inc/STMPHDigi.hh +++ b/RecoDataProducts/inc/STMPHDigi.hh @@ -27,6 +27,7 @@ namespace mu2e { int16_t _energy; // uncalibrated energy [ADC units] }; + // TODO: change typedef to std::map > typedef std::vector STMPHDigiCollection; bool lessByTime(const STMPHDigi& a, const STMPHDigi& b) { diff --git a/RecoDataProducts/inc/STMWaveformDigi.hh b/RecoDataProducts/inc/STMWaveformDigi.hh index 97a16a05aa..7ce1ab3313 100644 --- a/RecoDataProducts/inc/STMWaveformDigi.hh +++ b/RecoDataProducts/inc/STMWaveformDigi.hh @@ -26,10 +26,10 @@ _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; // Basic constructor STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _DetID(0), _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; - int16_t DetID () const { return _DetID; } - uint64_t EWT () const { return _EWT; } - uint64_t DTCtime() const { return _DTCtime; } - uint64_t ADCtime() const { return _ADCtime; } + int16_t DetID () const { return _DetID; } // TODO: remove DetID (we keep track of which detector through the collection names) + uint64_t EWT () const { return _EWT; } // TODO: want this in a separate class (EventWindowMarker?) + uint64_t DTCtime() const { return _DTCtime; } // TODO: " " " + uint64_t ADCtime() const { return _ADCtime; } // TODO: " " " uint32_t trigTimeOffset() const { return _trigTimeOffset; } const std::vector& adcs () const { return _adcs; } void set_data ( size_t n_data, int16_t const* data ) { _adcs.resize(n_data); std::copy(data, data+n_data, _adcs.begin()); } diff --git a/STMReco/src/STMPHDigiTree_module.cc b/STMReco/src/STMPHDigiTree_module.cc index 69a011376e..6f3190ace3 100644 --- a/STMReco/src/STMPHDigiTree_module.cc +++ b/STMReco/src/STMPHDigiTree_module.cc @@ -90,6 +90,7 @@ namespace mu2e { ttree->Branch("event", &evt_, "event/I"); ttree->Branch("run", &run_, "run/I"); ttree->Branch("subrun", &subrun_, "subrun/I"); + // TODO: add branch for EWT // Set up histogram std::string phSpectrumTitle = "PH Spectrum (" + _channel.name() + ")" ; // Builds title PH Spectrum (HPGe/ LaBr) @@ -103,6 +104,7 @@ namespace mu2e { // We fill here information // you can reference event and get ifno + // TODO: change to art_event evt_ = event.event(); run_ = event.run(); subrun_=event.subRun(); @@ -110,6 +112,11 @@ namespace mu2e { // Get handle for PH Digis auto phDigisHandle = event.getValidHandle(_stmPHDigisToken); const auto& phDigis = *phDigisHandle; + // TODO: now a map + // for (const auto& i_phDigiMap : phDigiMap) { + // uint64_t evt_ = i_phDigiMap->first; + // const auto& phDigis = i_phMap->second; + // can continue as below for (const auto& phDigi : phDigis){ pulseHeight_= phDigi.energy(); uncalibratedTime_ = phDigi.time(); From 47aaf11c2016b66fc0af2b76ab930e760aafde35 Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Wed, 19 Aug 2026 13:56:14 -0500 Subject: [PATCH 11/21] Remove DetID from STMWaveformDigi. Detectors are kept track in collection names --- RecoDataProducts/inc/STMWaveformDigi.hh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/RecoDataProducts/inc/STMWaveformDigi.hh b/RecoDataProducts/inc/STMWaveformDigi.hh index 7ce1ab3313..cf92b8b69c 100644 --- a/RecoDataProducts/inc/STMWaveformDigi.hh +++ b/RecoDataProducts/inc/STMWaveformDigi.hh @@ -19,14 +19,13 @@ namespace mu2e { public: // Initialise all variables - STMWaveformDigi() : _DetID(0), _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(0), _adcs(std::vector()) {}; + STMWaveformDigi() : _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(0), _adcs(std::vector()) {}; // Constructor for timing plus trig offset - STMWaveformDigi(int16_t DetID, uint64_t EWT, uint64_t DTCtime, uint64_t ADCtime, uint32_t trigTimeOffset, std::vector &adcs) : _DetID(DetID), _EWT(EWT), _DTCtime(DTCtime), _ADCtime(ADCtime), \ + STMWaveformDigi(uint64_t EWT, uint64_t DTCtime, uint64_t ADCtime, uint32_t trigTimeOffset, std::vector &adcs) : _EWT(EWT), _DTCtime(DTCtime), _ADCtime(ADCtime), \ _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; // Basic constructor - STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _DetID(0), _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; + STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; - int16_t DetID () const { return _DetID; } // TODO: remove DetID (we keep track of which detector through the collection names) uint64_t EWT () const { return _EWT; } // TODO: want this in a separate class (EventWindowMarker?) uint64_t DTCtime() const { return _DTCtime; } // TODO: " " " uint64_t ADCtime() const { return _ADCtime; } // TODO: " " " @@ -37,7 +36,6 @@ _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; bool hasParent() const { return _parent.isNonnull(); } void setParent(art::Ptr const& parent) {_parent = parent; } private: - int16_t _DetID; uint64_t _EWT; uint64_t _DTCtime; uint64_t _ADCtime; From 0750b6e8e08557cb7ef2bde3245dced7e0e777ad Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Wed, 19 Aug 2026 14:01:08 -0500 Subject: [PATCH 12/21] Remove EWT, ADC clock, and DTC clock from STMWaveformDigi. Will be added to a separate data product --- RecoDataProducts/inc/STMWaveformDigi.hh | 13 ++----------- STMReco/src/STMAnalyzeDigis_module.cc | 7 ++++--- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/RecoDataProducts/inc/STMWaveformDigi.hh b/RecoDataProducts/inc/STMWaveformDigi.hh index cf92b8b69c..466898f9bb 100644 --- a/RecoDataProducts/inc/STMWaveformDigi.hh +++ b/RecoDataProducts/inc/STMWaveformDigi.hh @@ -19,16 +19,10 @@ namespace mu2e { public: // Initialise all variables - STMWaveformDigi() : _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(0), _adcs(std::vector()) {}; - // Constructor for timing plus trig offset - STMWaveformDigi(uint64_t EWT, uint64_t DTCtime, uint64_t ADCtime, uint32_t trigTimeOffset, std::vector &adcs) : _EWT(EWT), _DTCtime(DTCtime), _ADCtime(ADCtime), \ -_trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; + STMWaveformDigi() : _trigTimeOffset(0), _adcs(std::vector()) {}; // Basic constructor - STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _EWT(0), _DTCtime(0), _ADCtime(0), _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; + STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; - uint64_t EWT () const { return _EWT; } // TODO: want this in a separate class (EventWindowMarker?) - uint64_t DTCtime() const { return _DTCtime; } // TODO: " " " - uint64_t ADCtime() const { return _ADCtime; } // TODO: " " " uint32_t trigTimeOffset() const { return _trigTimeOffset; } const std::vector& adcs () const { return _adcs; } void set_data ( size_t n_data, int16_t const* data ) { _adcs.resize(n_data); std::copy(data, data+n_data, _adcs.begin()); } @@ -36,9 +30,6 @@ _trigTimeOffset(trigTimeOffset), _adcs(adcs) {}; bool hasParent() const { return _parent.isNonnull(); } void setParent(art::Ptr const& parent) {_parent = parent; } private: - uint64_t _EWT; - uint64_t _DTCtime; - uint64_t _ADCtime; uint32_t _trigTimeOffset; // time offset from EWT? to first ADC value [ct] std::vector _adcs; // vector of ADC values for the waveform art::Ptr _parent; // get parent raw waveform for zs diff --git a/STMReco/src/STMAnalyzeDigis_module.cc b/STMReco/src/STMAnalyzeDigis_module.cc index 70c54de0de..3fb9940d76 100644 --- a/STMReco/src/STMAnalyzeDigis_module.cc +++ b/STMReco/src/STMAnalyzeDigis_module.cc @@ -370,9 +370,10 @@ void STMAnalyzeDigis::analyze(const Event& event) auto stm_Digi = static_cast(Digi); std::vector adcs = stm_Digi.adcs(); // Get EWT and DTC time from the digi - EWT = stm_Digi.EWT(); - DTCtime = stm_Digi.DTCtime(); - ADCtime = stm_Digi.ADCtime(); + // TODO: these will now come from a dedicated data products rather than be assigned directly to a (possible prescaled away) digi + // EWT = stm_Digi.EWT(); + // DTCtime = stm_Digi.DTCtime(); + // ADCtime = stm_Digi.ADCtime(); // Plot the first waveform if(firstEvent){ fEvent->Set(adcs.size()); From 77fbcd63f32758349ce48131d8c86e74ff750160 Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Wed, 19 Aug 2026 14:37:18 -0500 Subject: [PATCH 13/21] Create new STMEventHeader data product --- DAQ/src/STMDigisFromFragments_module.cc | 13 +++++++++++ RecoDataProducts/inc/STMEventHeader.hh | 31 +++++++++++++++++++++++++ RecoDataProducts/src/classes.h | 1 + RecoDataProducts/src/classes_def.xml | 3 +++ 4 files changed, 48 insertions(+) create mode 100644 RecoDataProducts/inc/STMEventHeader.hh diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 36df363be6..a5d8b5e267 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -1,6 +1,7 @@ // ==================================================================== // // STMDigisFromFragments: create all types of STMDigis from STMFragments +// Note that for the STM, a single art event contains many EWTs // // ====================================================================== @@ -13,6 +14,7 @@ #include "Offline/ProditionsService/inc/ProditionsHandle.hh" #include "Offline/RecoDataProducts/inc/STMWaveformDigi.hh" #include "Offline/RecoDataProducts/inc/STMPHDigi.hh" +#include "Offline/RecoDataProducts/inc/STMEventHeader.hh" #include "art/Framework/Principal/Handle.h" #include "artdaq-core-mu2e/Overlays/STMFragment.hh" #include @@ -265,6 +267,8 @@ STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table("rawLaBr"); } if (_saveZSWaveformsLaBr){ produces("zsLaBr"); } produces("phLaBr"); + + produces(); } // Start of Event processing @@ -303,6 +307,9 @@ void STMDigisFromFragments::produce(Event& event) rawParentLaBr.productID = event.getProductID("rawLaBr"); } + // STM Event Headers + std::unique_ptr stmEventHeaders(new mu2e::STMEventHeaderCollection); + // Frag Summaries std::unique_ptr stmFragSummaryHPGe(new mu2e::STMFragmentSummaryCollection); std::unique_ptr stmFragSummaryLaBr(new mu2e::STMFragmentSummaryCollection); @@ -372,6 +379,10 @@ void STMDigisFromFragments::produce(Event& event) mu2e::STMWaveformDigi stm_waveform; if (stm_frag.isRaw()){ + uint8_t mode = 0; // TODO: this goes to the Mu2eEventHeader but I'm not sure where we get it from in the STMFragment + mu2e::STMEventHeader stm_event_header(stm_frag.eventWindowTag(), mode, stm_frag.adcClock(), stm_frag.dtcClock()); + stmEventHeaders->emplace_back(stm_event_header); + ++_totalRawFragsSeen; // Determine which detector this raw fragment is in bool const isHPGe = stm_frag.isHPGe(); @@ -1174,6 +1185,8 @@ void STMDigisFromFragments::produce(Event& event) } + // save the STMEventHeaders + event.put(std::move(stmEventHeaders)); // Frag Summary if (_saveSTMFragSummary) { event.put(std::move(stmFragSummaryHPGe), "stmFragSummaryHPGe"); diff --git a/RecoDataProducts/inc/STMEventHeader.hh b/RecoDataProducts/inc/STMEventHeader.hh new file mode 100644 index 0000000000..2965c70241 --- /dev/null +++ b/RecoDataProducts/inc/STMEventHeader.hh @@ -0,0 +1,31 @@ +#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; } + + private: + Mu2eEventHeader _mu2eEventHeader; + uint64_t _adcClock; + uint64_t _dtcClock; + }; + typedef std::vector STMEventHeaderCollection; + +} // namespace mu2e + + +#endif diff --git a/RecoDataProducts/src/classes.h b/RecoDataProducts/src/classes.h index 10f747d571..3848f38611 100644 --- a/RecoDataProducts/src/classes.h +++ b/RecoDataProducts/src/classes.h @@ -99,6 +99,7 @@ #include "Offline/RecoDataProducts/inc/STMPHDigi.hh" #include "Offline/RecoDataProducts/inc/STMHit.hh" #include "Offline/RecoDataProducts/inc/STMFragmentSummary.hh" +#include "Offline/RecoDataProducts/inc/STMEventHeader.hh" // MSD #include "Offline/RecoDataProducts/inc/MSDHit.hh" diff --git a/RecoDataProducts/src/classes_def.xml b/RecoDataProducts/src/classes_def.xml index a27607d56f..fb84cd267a 100644 --- a/RecoDataProducts/src/classes_def.xml +++ b/RecoDataProducts/src/classes_def.xml @@ -467,6 +467,9 @@ + + + From 322b18d814c6eb3158b0a93bab24add5367b5c02 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Wed, 19 Aug 2026 16:38:05 -0500 Subject: [PATCH 14/21] work in progress --- DAQ/src/STMDigisFromFragments_module.cc | 53 +++++++++++++++++++++---- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index a5d8b5e267..e7c2116734 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -206,6 +206,8 @@ class art::STMDigisFromFragments : public EDProducer bool rawHeaderIsValid{false}; bool skipCurrentSet{false}; + + uint64_t EWT{0}; }; struct FragmentCounters { @@ -409,6 +411,7 @@ void STMDigisFromFragments::produce(Event& event) parentState.index = 0; ++eventMetrics.raw.seen; // TODO: set EWT = header_frag.eventWindowTag(); + headerState.EWT = 0; // check header+adcs is not less than expected header length (22) if(stm_frag.dataWords() < stm::RawHeader::WORDS){ @@ -479,6 +482,9 @@ void STMDigisFromFragments::produce(Event& event) headerState.expectedZSRegions = stm_frag.zsRegions(); headerState.expectedPHCount = stm_frag.phCount(); + // extracted EWT + headerState.EWT = stm_frag.eventWindowTag(); + if (headerState.rawPrescaled) { ++eventMetrics.raw.prescaled; ++_totalRawFragsPrescaled; @@ -577,14 +583,16 @@ void STMDigisFromFragments::produce(Event& event) auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); stm_waveform.set_data(dataWords,dataPtr); - rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); + //rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); // TODO: + rawWaveformDigisWithHeaderHPGe->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); // rawWaveformDigisWithHeaderHPGe->emplace(std::make_pair(EWT, std::vector(stm_waveform)); } // Save Raw Waveform and Save parent Ptr - HPGe if (_saveRawWaveformsHPGe && isHPGe){ stm_waveform.set_data(payloadWords, payloadPtr); - rawWaveformDigisHPGe->emplace_back(stm_waveform); + //rawWaveformDigisHPGe->emplace_back(stm_waveform); + rawWaveformDigisHPGe->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); //Save raw parent index parentState.index = rawWaveformDigisHPGe->size() - 1; @@ -597,12 +605,14 @@ void STMDigisFromFragments::produce(Event& event) auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); stm_waveform.set_data(dataWords,dataPtr); - rawWaveformDigisWithHeaderLaBr->emplace_back(stm_waveform); + //rawWaveformDigisWithHeaderLaBr->emplace_back(stm_waveform); + rawWaveformDigisWithHeaderLaBr->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); } // Save Raw Waveform and Save parent Ptr - LaBr if (_saveRawWaveformsLaBr && isLaBr){ stm_waveform.set_data(payloadWords, payloadPtr); - rawWaveformDigisLaBr->emplace_back(stm_waveform); + //rawWaveformDigisLaBr->emplace_back(stm_waveform); + rawWaveformDigisLaBr->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); //Save raw parent index parentState.index = rawWaveformDigisLaBr->size() - 1; @@ -628,6 +638,8 @@ void STMDigisFromFragments::produce(Event& event) bool const isHPGe = stm_frag.isHPGe(); bool const isLaBr = stm_frag.isLaBr(); // TODO: std::vector zs_waveforms; + std::vector zs_waveformsHPGe; + std::vector zs_waveformsLaBr; // Double check that the fragment belongs to one of the expected detectors if (!isHPGe && !isLaBr){ @@ -662,6 +674,7 @@ void STMDigisFromFragments::produce(Event& event) uint16_t zsLength = headerState.expectedZSLength; uint16_t rawPrescaleValue = headerState.rawPrescaleValue; uint16_t zsPrescaleValue = headerState.zsPrescaleValue; + uint64_t zsEWT = headerState.EWT; // Decide Here to skip based on previous raw fragment information if (skipCurrentSet){ @@ -850,11 +863,15 @@ void STMDigisFromFragments::produce(Event& event) // Set parent pointer if available zsDigi.setParent(parentState.ptr); } + //std::vector zs_waveformsHPGe; + //std::vector zs_waveformsLaBr; + // Emplacing if (isHPGe && _saveZSWaveformsHPGe) { // emplacing HPGe waveform digi //TODO: change to the temporary zs_waveforms defined earlier - zsWaveformDigisHPGe->emplace_back(zsDigi); + zs_waveformsHPGe->emplace_back(zsDigi); + //zsWaveformDigisHPGe->emplace_back(zsDigi); if (_verbosityLevel > 2 && zsDigi.hasParent()) { std::cout << "\nZS HPGe Parent Raw index : " << zsDigi.parent().key() << ", offset : " << zsDigi.trigTimeOffset() << "\n"; @@ -862,7 +879,8 @@ void STMDigisFromFragments::produce(Event& event) } else if (isLaBr && _saveZSWaveformsLaBr) { // emplacing LaBr waveform digi - zsWaveformDigisLaBr->emplace_back(zsDigi); + zs_WaveformDigisLaBr->emplace_back(zsDigi); + //zsWaveformDigisLaBr->emplace_back(zsDigi); if (_verbosityLevel > 2 && zsDigi.hasParent()) { std::cout << "\nZS LaBr Parent Raw index : " << zsDigi.parent().key() << ", offset : " << zsDigi.trigTimeOffset() << "\n"; @@ -876,7 +894,13 @@ void STMDigisFromFragments::produce(Event& event) ++eventMetrics.zs.good; // TODO: emplace into the map + //zsWaveformDigisLaBr + if (isHPGe){ + zsWaveformDigisHPGe->empalce(std::make_pairempalce(std::make_pairemplace(std::make_pair(EWT, zs_waveforms)); + } }// End of ZS fragmment check else if (stm_frag.isPH()){ @@ -886,6 +910,8 @@ void STMDigisFromFragments::produce(Event& event) bool const isLaBr = stm_frag.isLaBr(); // TODO: make a temporary std::vector + std::vector temp_phHPGe; + std::vector temp_phLaBr; if (!isHPGe && !isLaBr) { ++_totalUnreadInnerFrags; @@ -901,6 +927,7 @@ void STMDigisFromFragments::produce(Event& event) bool skipCurrentSet = headerState.skipCurrentSet; bool extractedPHInfo = headerState.containsPHInfo; uint16_t phCount = headerState.expectedPHCount; + uint16_t phEWT = headerState.EWT; // Skip if Raw Fragment was Bad or Missing if (skipCurrentSet) { @@ -1008,10 +1035,12 @@ void STMDigisFromFragments::produce(Event& event) // Emplace Back (Always On) if (isHPGe) { // TODO: change to fill the temporary ph_digis vector - phDigisHPGe->emplace_back(PH_digi); + temp_phHPGe->emplace_back(PH_digi); + //phDigisHPGe->emplace_back(PH_digi); } if (isLaBr) { - phDigisLaBr->emplace_back(PH_digi); + temp_phLaBr->emplace_back(PH_digi); + //phDigisLaBr->emplace_back(PH_digi); } } @@ -1026,7 +1055,15 @@ void STMDigisFromFragments::produce(Event& event) ++_totalGoodPHFrags; isHPGe ? ++_totalGoodPHFragsHPGe : ++_totalGoodPHFragsLaBr; ++eventMetrics.ph.good; + + // std::vector temp_phHPGe; + // std::vector temp_phLaBr; // TODO: insert into PHDigi map + if (isHPGe){ + phDigisHPGe->emplace(std::make_pair(phEWT, std::vector(temp_phHPGe))); + } else if (isLaBR){ + phDigisLaBr->emplace(std::make_pair(phEWT, std::vector(temp_phLaBr))); + } }// End of PH fragment check else { From 6d9cdcb136927d1be399fc3da72866f20bfa87f0 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Thu, 20 Aug 2026 12:53:11 -0500 Subject: [PATCH 15/21] std::map added to unpacking --- DAQ/src/STMDigisFromFragments_module.cc | 194 ++++++++++++++---------- RecoDataProducts/inc/STMEventHeader.hh | 6 +- RecoDataProducts/src/classes_def.xml | 4 + 3 files changed, 127 insertions(+), 77 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index e7c2116734..7be122b671 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -15,6 +15,7 @@ #include "Offline/RecoDataProducts/inc/STMWaveformDigi.hh" #include "Offline/RecoDataProducts/inc/STMPHDigi.hh" #include "Offline/RecoDataProducts/inc/STMEventHeader.hh" + #include "art/Framework/Principal/Handle.h" #include "artdaq-core-mu2e/Overlays/STMFragment.hh" #include @@ -29,6 +30,7 @@ #include #include #include +#include // This is version 2 // Meant to clean up and make the code more maintainable and readable @@ -38,6 +40,8 @@ namespace art class STMDigisFromFragments; } using art::STMDigisFromFragments; +// can make easier but lets be explicit for now +//using STMWaveformDigiMap = std::map>; class art::STMDigisFromFragments : public EDProducer { @@ -207,7 +211,11 @@ class art::STMDigisFromFragments : public EDProducer bool rawHeaderIsValid{false}; bool skipCurrentSet{false}; - uint64_t EWT{0}; + // save the following now for mapping + uint64_t eventWindowTag{0}; + uint8_t eventMode{0}; // Not sure what this is right now + uint64_t adcClock{0}; + uint64_t dtcClock{0}; }; struct FragmentCounters { @@ -259,6 +267,7 @@ STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table("stmFragSummaryHPGe"); produces("stmFragSummaryLaBr"); } + /* // HPGe if (_saveRawWaveformsWithHeaderHPGe){ produces("rawWithHeaderHPGe"); } if (_saveRawWaveformsHPGe){ produces("rawHPGe"); } @@ -269,8 +278,19 @@ STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table("rawLaBr"); } if (_saveZSWaveformsLaBr){ produces("zsLaBr"); } produces("phLaBr"); + */ - produces(); + //change products to be maps of event headers + // HPGe + if (_saveRawWaveformsWithHeaderHPGe){produces>("rawWithHeaderHPGe"); } + if (_saveRawWaveformsHPGe){produces>("rawHPGe"); } + if (_saveZSWaveformsHPGe){produces>("zsHPGe"); } + produces>("phHPGe"); + // LaBr + if (_saveRawWaveformsWithHeaderLaBr){ produces>("rawWithHeaderLaBr"); } + if (_saveRawWaveformsLaBr){ produces>("rawLaBr"); } + if (_saveZSWaveformsLaBr){ produces>("zsLaBr"); } + produces>("phLaBr"); } // Start of Event processing @@ -302,31 +322,45 @@ void STMDigisFromFragments::produce(Event& event) DetectorSpecificEventMetrics HPGeEventMetrics; // Set product ID + + /* if (_saveRawWaveformsHPGe){ rawParentHPGe.productID = event.getProductID("rawHPGe"); } if (_saveRawWaveformsLaBr){ rawParentLaBr.productID = event.getProductID("rawLaBr"); } - - // STM Event Headers - std::unique_ptr stmEventHeaders(new mu2e::STMEventHeaderCollection); + */ // Frag Summaries std::unique_ptr stmFragSummaryHPGe(new mu2e::STMFragmentSummaryCollection); std::unique_ptr stmFragSummaryLaBr(new mu2e::STMFragmentSummaryCollection); + /* // HPGe std::unique_ptr rawWaveformDigisWithHeaderHPGe(new mu2e::STMWaveformDigiCollection); std::unique_ptr rawWaveformDigisHPGe(new mu2e::STMWaveformDigiCollection); std::unique_ptr zsWaveformDigisHPGe(new mu2e::STMWaveformDigiCollection); std::unique_ptr phDigisHPGe(new mu2e::STMPHDigiCollection); - // LaBr waveforms + // LaBr std::unique_ptr rawWaveformDigisWithHeaderLaBr(new mu2e::STMWaveformDigiCollection); std::unique_ptr rawWaveformDigisLaBr(new mu2e::STMWaveformDigiCollection); std::unique_ptr zsWaveformDigisLaBr(new mu2e::STMWaveformDigiCollection); std::unique_ptr phDigisLaBr(new mu2e::STMPHDigiCollection); + */ + + // map start - keep explicit for now + // HPGe + std::unique_ptr> rawWaveformDigisWithHeaderHPGe(new std::map); + std::unique_ptr> rawWaveformDigisHPGe(new std::map); + std::unique_ptr> zsWaveformDigisHPGe(new std::map); + std::unique_ptr> phDigisHPGe(new std::map); + // LaBr + std::unique_ptr> rawWaveformDigisWithHeaderLaBr(new std::map); + std::unique_ptr> rawWaveformDigisLaBr(new std::map); + std::unique_ptr> zsWaveformDigisLaBr(new std::map); + std::unique_ptr> phDigisLaBr(new std::map); // booleans for tracking what detectors are present in the event bool eventHasHPGe{false}; @@ -381,10 +415,6 @@ void STMDigisFromFragments::produce(Event& event) mu2e::STMWaveformDigi stm_waveform; if (stm_frag.isRaw()){ - uint8_t mode = 0; // TODO: this goes to the Mu2eEventHeader but I'm not sure where we get it from in the STMFragment - mu2e::STMEventHeader stm_event_header(stm_frag.eventWindowTag(), mode, stm_frag.adcClock(), stm_frag.dtcClock()); - stmEventHeaders->emplace_back(stm_event_header); - ++_totalRawFragsSeen; // Determine which detector this raw fragment is in bool const isHPGe = stm_frag.isHPGe(); @@ -410,8 +440,11 @@ void STMDigisFromFragments::produce(Event& event) parentState.available = false; parentState.index = 0; ++eventMetrics.raw.seen; - // TODO: set EWT = header_frag.eventWindowTag(); - headerState.EWT = 0; + // reset eventHeader related variables + headerState.eventWindowTag = 0; + headerState.eventMode = 0; + headerState.adcClock = 0; + headerState.dtcClock = 0; // check header+adcs is not less than expected header length (22) if(stm_frag.dataWords() < stm::RawHeader::WORDS){ @@ -482,8 +515,18 @@ void STMDigisFromFragments::produce(Event& event) headerState.expectedZSRegions = stm_frag.zsRegions(); headerState.expectedPHCount = stm_frag.phCount(); - // extracted EWT - headerState.EWT = stm_frag.eventWindowTag(); + // extract EWT, mode/spillFlags, adcClock, dtcClock + headerState.eventWindowTag = stm_frag.eventWindowTag(); + headerState.eventMode = stm_frag.spillFlag(); + headerState.adcClock = stm_frag.adcClock(); + headerState.dtcClock = stm_frag.dtcClock(); + + // create stmEventHeader + mu2e::STMEventHeader stm_event_header( + headerState.eventWindowTag, + headerState.eventMode, + headerState.adcClock, + headerState.dtcClock); if (headerState.rawPrescaled) { ++eventMetrics.raw.prescaled; @@ -582,43 +625,49 @@ void STMDigisFromFragments::produce(Event& event) if (_saveRawWaveformsWithHeaderHPGe && isHPGe){ auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); + // set stm_waveform stm_waveform.set_data(dataWords,dataPtr); - //rawWaveformDigisWithHeaderHPGe->emplace_back(stm_waveform); - // TODO: - rawWaveformDigisWithHeaderHPGe->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); - // rawWaveformDigisWithHeaderHPGe->emplace(std::make_pair(EWT, std::vector(stm_waveform)); + // use map + (*rawWaveformDigisWithHeaderHPGe)[stm_event_header].push_back(stm_waveform); } // Save Raw Waveform and Save parent Ptr - HPGe if (_saveRawWaveformsHPGe && isHPGe){ + // set stm_waveform stm_waveform.set_data(payloadWords, payloadPtr); - //rawWaveformDigisHPGe->emplace_back(stm_waveform); - rawWaveformDigisHPGe->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); + + // Give map a key and value, key is stmHeader, + // *rawwaveformDigisHPGe is the map + // stm_event_header is the collection stored under this header + // .push_back(stm_waveform) adds waveform to the collection + (*rawWaveformDigisHPGe)[stm_event_header].push_back(stm_waveform); //Save raw parent index - parentState.index = rawWaveformDigisHPGe->size() - 1; - parentState.ptr = art::Ptr(parentState.productID, parentState.index, - event.productGetter(parentState.productID)); - parentState.available = true; + //parentState.index = rawWaveformDigisHPGe->size() - 1; + //parentState.ptr = art::Ptr(parentState.productID, parentState.index, + // event.productGetter(parentState.productID)); + //parentState.available = true; } // Save Raw Waveform With Header Info - LaBr if (_saveRawWaveformsWithHeaderLaBr && isLaBr){ auto dataPtr = stm_frag.dataBegin(); auto dataWords = stm_frag.dataWords(); + // set stm_waveform stm_waveform.set_data(dataWords,dataPtr); - //rawWaveformDigisWithHeaderLaBr->emplace_back(stm_waveform); - rawWaveformDigisWithHeaderLaBr->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); + // set map here + (*rawWaveformDigisWithHeaderLaBr)[stm_event_header].push_back(stm_waveform); } // Save Raw Waveform and Save parent Ptr - LaBr if (_saveRawWaveformsLaBr && isLaBr){ + // set stm_waveform stm_waveform.set_data(payloadWords, payloadPtr); - //rawWaveformDigisLaBr->emplace_back(stm_waveform); - rawWaveformDigisLaBr->emplace(std::make_pair(headerState.EWT, std::vector(stm_waveform)); + // set map here + (*rawWaveformDigisLaBr)[stm_event_header].push_back(stm_waveform); //Save raw parent index - parentState.index = rawWaveformDigisLaBr->size() - 1; - parentState.ptr = art::Ptr(parentState.productID, parentState.index, - event.productGetter(parentState.productID)); - parentState.available = true; + //parentState.index = rawWaveformDigisLaBr->size() - 1; + //parentState.ptr = art::Ptr(parentState.productID, parentState.index, + //event.productGetter(parentState.productID)); + //parentState.available = true; } if (_verbosityLevel > 2) { std::cout << "Raw with frag index" << i @@ -637,9 +686,6 @@ void STMDigisFromFragments::produce(Event& event) // Determine which detector this ZS fragment belongs to bool const isHPGe = stm_frag.isHPGe(); bool const isLaBr = stm_frag.isLaBr(); - // TODO: std::vector zs_waveforms; - std::vector zs_waveformsHPGe; - std::vector zs_waveformsLaBr; // Double check that the fragment belongs to one of the expected detectors if (!isHPGe && !isLaBr){ @@ -674,7 +720,19 @@ void STMDigisFromFragments::produce(Event& event) uint16_t zsLength = headerState.expectedZSLength; uint16_t rawPrescaleValue = headerState.rawPrescaleValue; uint16_t zsPrescaleValue = headerState.zsPrescaleValue; - uint64_t zsEWT = headerState.EWT; + + // Extract for eventHeader (EWT, mode/spillFlag, adcClock, dtcClock) + uint64_t zsEWT = headerState.eventWindowTag; + uint8_t zsMode = headerState.eventMode; + uint64_t zsAdcClock = headerState.adcClock; + uint64_t zsdtcClock = headerState.dtcClock; + + // create stmEventHeader + mu2e::STMEventHeader stm_event_header( + zsEWT, + zsMode, + zsAdcClock, + zsdtcClock); // Decide Here to skip based on previous raw fragment information if (skipCurrentSet){ @@ -858,19 +916,17 @@ void STMDigisFromFragments::produce(Event& event) << "--ZS Frag\n"; } for (auto& region : regions) { + // set waveform digi with offset and adcs mu2e::STMWaveformDigi zsDigi(region.offset, region.adcs); - if(parentState.available){ + //if(parentState.available){ // Set parent pointer if available - zsDigi.setParent(parentState.ptr); - } - //std::vector zs_waveformsHPGe; - //std::vector zs_waveformsLaBr; + // zsDigi.setParent(parentState.ptr); + //} // Emplacing if (isHPGe && _saveZSWaveformsHPGe) { - // emplacing HPGe waveform digi - //TODO: change to the temporary zs_waveforms defined earlier - zs_waveformsHPGe->emplace_back(zsDigi); + // set map for HPGe + (*zsWaveformDigisHPGe)[stm_event_header].push_back(zsDigi); //zsWaveformDigisHPGe->emplace_back(zsDigi); if (_verbosityLevel > 2 && zsDigi.hasParent()) { std::cout << "\nZS HPGe Parent Raw index : " << zsDigi.parent().key() @@ -878,8 +934,8 @@ void STMDigisFromFragments::produce(Event& event) } } else if (isLaBr && _saveZSWaveformsLaBr) { - // emplacing LaBr waveform digi - zs_WaveformDigisLaBr->emplace_back(zsDigi); + // set map for LaBr + (*zsWaveformDigisLaBr)[stm_event_header].push_back(zsDigi); //zsWaveformDigisLaBr->emplace_back(zsDigi); if (_verbosityLevel > 2 && zsDigi.hasParent()) { std::cout << "\nZS LaBr Parent Raw index : " << zsDigi.parent().key() @@ -893,15 +949,6 @@ void STMDigisFromFragments::produce(Event& event) isHPGe ? ++_totalGoodZSFragsHPGe : ++_totalGoodZSFragsLaBr; ++eventMetrics.zs.good; - // TODO: emplace into the map - //zsWaveformDigisLaBr - if (isHPGe){ - zsWaveformDigisHPGe->empalce(std::make_pairempalce(std::make_pairemplace(std::make_pair(EWT, zs_waveforms)); - } - }// End of ZS fragmment check else if (stm_frag.isPH()){ ++_totalPHFragsSeen; @@ -909,10 +956,6 @@ void STMDigisFromFragments::produce(Event& event) bool const isHPGe = stm_frag.isHPGe(); bool const isLaBr = stm_frag.isLaBr(); - // TODO: make a temporary std::vector - std::vector temp_phHPGe; - std::vector temp_phLaBr; - if (!isHPGe && !isLaBr) { ++_totalUnreadInnerFrags; continue; @@ -927,7 +970,19 @@ void STMDigisFromFragments::produce(Event& event) bool skipCurrentSet = headerState.skipCurrentSet; bool extractedPHInfo = headerState.containsPHInfo; uint16_t phCount = headerState.expectedPHCount; - uint16_t phEWT = headerState.EWT; + + // Extract for eventHeader (EWT, mode/spillFlag, adcClock, dtcClock) + uint64_t phEWT = headerState.eventWindowTag; + uint8_t phMode = headerState.eventMode; + uint64_t phAdcClock = headerState.adcClock; + uint64_t phdtcClock = headerState.dtcClock; + + // Construct stmEventHeader for PH fragment + mu2e::STMEventHeader stm_event_header( + phEWT, + phMode, + phAdcClock, + phdtcClock); // Skip if Raw Fragment was Bad or Missing if (skipCurrentSet) { @@ -1034,13 +1089,12 @@ void STMDigisFromFragments::produce(Event& event) // Emplace Back (Always On) if (isHPGe) { - // TODO: change to fill the temporary ph_digis vector - temp_phHPGe->emplace_back(PH_digi); //phDigisHPGe->emplace_back(PH_digi); + (*phDigisHPGe)[stm_event_header].emplace_back(PH_digi); } if (isLaBr) { - temp_phLaBr->emplace_back(PH_digi); - //phDigisLaBr->emplace_back(PH_digi); + //phDigisLaBr->emplace_back(PH_digi); + (*phDigisLaBr)[stm_event_header].emplace_back(PH_digi); } } @@ -1056,15 +1110,6 @@ void STMDigisFromFragments::produce(Event& event) isHPGe ? ++_totalGoodPHFragsHPGe : ++_totalGoodPHFragsLaBr; ++eventMetrics.ph.good; - // std::vector temp_phHPGe; - // std::vector temp_phLaBr; - // TODO: insert into PHDigi map - if (isHPGe){ - phDigisHPGe->emplace(std::make_pair(phEWT, std::vector(temp_phHPGe))); - } else if (isLaBR){ - phDigisLaBr->emplace(std::make_pair(phEWT, std::vector(temp_phLaBr))); - } - }// End of PH fragment check else { // fallback for unreadable fragment @@ -1221,9 +1266,6 @@ void STMDigisFromFragments::produce(Event& event) std::cout << "=================================\n"; } - - // save the STMEventHeaders - event.put(std::move(stmEventHeaders)); // Frag Summary if (_saveSTMFragSummary) { event.put(std::move(stmFragSummaryHPGe), "stmFragSummaryHPGe"); diff --git a/RecoDataProducts/inc/STMEventHeader.hh b/RecoDataProducts/inc/STMEventHeader.hh index 2965c70241..8b0cc4319f 100644 --- a/RecoDataProducts/inc/STMEventHeader.hh +++ b/RecoDataProducts/inc/STMEventHeader.hh @@ -18,13 +18,17 @@ namespace mu2e 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 STMEventHeaderCollection; - } // namespace mu2e diff --git a/RecoDataProducts/src/classes_def.xml b/RecoDataProducts/src/classes_def.xml index fb84cd267a..34d63dd8e7 100644 --- a/RecoDataProducts/src/classes_def.xml +++ b/RecoDataProducts/src/classes_def.xml @@ -470,6 +470,10 @@ + + + + From 691c9ead8c6175434ab43f3c108704d7ecb898e4 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Thu, 20 Aug 2026 15:00:19 -0500 Subject: [PATCH 16/21] updated std::map to use typedef def --- DAQ/src/STMDigisFromFragments_module.cc | 19 ++++++++----------- RecoDataProducts/inc/STMPHDigi.hh | 5 ++++- RecoDataProducts/inc/STMWaveformDigi.hh | 3 +++ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 7be122b671..8ce80462bc 100644 --- a/DAQ/src/STMDigisFromFragments_module.cc +++ b/DAQ/src/STMDigisFromFragments_module.cc @@ -40,9 +40,6 @@ namespace art class STMDigisFromFragments; } using art::STMDigisFromFragments; -// can make easier but lets be explicit for now -//using STMWaveformDigiMap = std::map>; - class art::STMDigisFromFragments : public EDProducer { public: @@ -282,15 +279,15 @@ STMDigisFromFragments::STMDigisFromFragments(const art::EDProducer::Table>("rawWithHeaderHPGe"); } - if (_saveRawWaveformsHPGe){produces>("rawHPGe"); } - if (_saveZSWaveformsHPGe){produces>("zsHPGe"); } - produces>("phHPGe"); + if (_saveRawWaveformsWithHeaderHPGe){produces("rawWithHeaderHPGe"); } + if (_saveRawWaveformsHPGe){produces("rawHPGe"); } + if (_saveZSWaveformsHPGe){produces("zsHPGe"); } + produces("phHPGe"); // LaBr - if (_saveRawWaveformsWithHeaderLaBr){ produces>("rawWithHeaderLaBr"); } - if (_saveRawWaveformsLaBr){ produces>("rawLaBr"); } - if (_saveZSWaveformsLaBr){ produces>("zsLaBr"); } - produces>("phLaBr"); + if (_saveRawWaveformsWithHeaderLaBr){ produces("rawWithHeaderLaBr"); } + if (_saveRawWaveformsLaBr){ produces("rawLaBr"); } + if (_saveZSWaveformsLaBr){ produces("zsLaBr"); } + produces("phLaBr"); } // Start of Event processing diff --git a/RecoDataProducts/inc/STMPHDigi.hh b/RecoDataProducts/inc/STMPHDigi.hh index 86d5398ee5..66b941bd73 100644 --- a/RecoDataProducts/inc/STMPHDigi.hh +++ b/RecoDataProducts/inc/STMPHDigi.hh @@ -9,6 +9,9 @@ #include #include #include +#include + +#include "Offline/RecoDataProducts/inc/STMEventHeader.hh" namespace mu2e { @@ -27,8 +30,8 @@ namespace mu2e { int16_t _energy; // uncalibrated energy [ADC units] }; - // TODO: change typedef to std::map > typedef std::vector STMPHDigiCollection; + typedef std::map STMPHDigiCollectionMap; bool lessByTime(const STMPHDigi& a, const STMPHDigi& b) { if (a.time() < b.time()) { return true; } diff --git a/RecoDataProducts/inc/STMWaveformDigi.hh b/RecoDataProducts/inc/STMWaveformDigi.hh index 466898f9bb..f12541e720 100644 --- a/RecoDataProducts/inc/STMWaveformDigi.hh +++ b/RecoDataProducts/inc/STMWaveformDigi.hh @@ -10,8 +10,10 @@ #include #include #include +#include #include "Offline/DataProducts/inc/STMChannel.hh" +#include "Offline/RecoDataProducts/inc/STMEventHeader.hh" #include "canvas/Persistency/Common/Ptr.h" namespace mu2e { @@ -35,5 +37,6 @@ namespace mu2e { art::Ptr _parent; // get parent raw waveform for zs }; typedef std::vector STMWaveformDigiCollection; + typedef std::map STMWaveformDigiCollectionMap; } #endif From 54eb5c9c538b3557f40490b876e623259984c76a Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Thu, 20 Aug 2026 15:24:07 -0500 Subject: [PATCH 17/21] Need a couple more things defined in classes_def.xml --- RecoDataProducts/src/classes_def.xml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/RecoDataProducts/src/classes_def.xml b/RecoDataProducts/src/classes_def.xml index 34d63dd8e7..2c1b6cda22 100644 --- a/RecoDataProducts/src/classes_def.xml +++ b/RecoDataProducts/src/classes_def.xml @@ -470,10 +470,12 @@ - - - - + + + + + + From 3164613d2b69991a36929ac3939d951d170f820e Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Thu, 20 Aug 2026 16:01:38 -0500 Subject: [PATCH 18/21] Update Validation module for STMWaveformDigiCollectionMap --- Validation/inc/ValSTMWaveformDigi.hh | 1 + Validation/src/ValSTMWaveformDigi.cc | 15 +++++++++++++++ Validation/src/Validation_module.cc | 2 ++ 3 files changed, 18 insertions(+) diff --git a/Validation/inc/ValSTMWaveformDigi.hh b/Validation/inc/ValSTMWaveformDigi.hh index 8191b38045..f5f783351a 100644 --- a/Validation/inc/ValSTMWaveformDigi.hh +++ b/Validation/inc/ValSTMWaveformDigi.hh @@ -14,6 +14,7 @@ class ValSTMWaveformDigi { ValSTMWaveformDigi(std::string name) : _name(name) {} int declare(const art::TFileDirectory& tfs); int fill(const STMWaveformDigiCollection& coll, art::Event const& event); + int fill(const STMWaveformDigiCollectionMap& coll, art::Event const& event); std::string& name() { return _name; } private: diff --git a/Validation/src/ValSTMWaveformDigi.cc b/Validation/src/ValSTMWaveformDigi.cc index 26a5437b80..85b63c7383 100644 --- a/Validation/src/ValSTMWaveformDigi.cc +++ b/Validation/src/ValSTMWaveformDigi.cc @@ -31,3 +31,18 @@ int mu2e::ValSTMWaveformDigi::fill( } return 0; } + +int mu2e::ValSTMWaveformDigi::fill( + const mu2e::STMWaveformDigiCollectionMap& map, art::Event const& event) { + // increment this by 1 any time the defnitions of the histograms or the + // histogram contents change, and will not match previous versions + _hVer->Fill(0.0); + + // for STM data, each art::Event contains many mu2e events (EWTs) and so we + // are storing them in a map + for (auto& mu2e_evt : map) { + const auto& coll = mu2e_evt.second; + fill(coll, event); + } + return 0; +} diff --git a/Validation/src/Validation_module.cc b/Validation/src/Validation_module.cc index 5586bee679..45f678791a 100644 --- a/Validation/src/Validation_module.cc +++ b/Validation/src/Validation_module.cc @@ -156,6 +156,7 @@ void mu2e::Validation::analyze(art::Event const& event) { analyzeProduct(_hxsd, event); analyzeProduct(_klsd, event); analyzeProduct(_stmw, event); + analyzeProduct(_stmw, event); analyzeProduct(_trrs, event); analyzeProduct(_tris, event); } @@ -184,6 +185,7 @@ int mu2e::Validation::analyzeProduct(std::vector>& list, if (fcn == "mu2e::BkgQualDetailmu2e::MVAStructs") fcn = "BkgQual"; if (fcn.find("mu2e::", 0) == 0) fcn.erase(0, 6); if (fcn.find("art::", 0) == 0) fcn.erase(0, 5); + if (fcn.find("STMEventHeadermu2e::STMWaveformDigisstd::map", 0) == 0) fcn = "STMWaveformDigiCollectionMap"; std::string inst = prov->productInstanceName(); if (inst.size() == 0) inst = "noName"; From e4f7cda967f41bc5b20f5d1950d52bde5e08c855 Mon Sep 17 00:00:00 2001 From: Andrew Edmonds Date: Thu, 20 Aug 2026 16:18:51 -0500 Subject: [PATCH 19/21] Update MakeSTMHits module for new map --- STMReco/src/MakeSTMHits_module.cc | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/STMReco/src/MakeSTMHits_module.cc b/STMReco/src/MakeSTMHits_module.cc index abde7f2e4b..b545690d78 100644 --- a/STMReco/src/MakeSTMHits_module.cc +++ b/STMReco/src/MakeSTMHits_module.cc @@ -37,7 +37,7 @@ namespace mu2e { using Name=fhicl::Name; using Comment=fhicl::Comment; struct Config { - fhicl::Atom stmPHDigisTag{ Name("stmPHDigisTag"), Comment("InputTag for STMPHDigiCollection")}; + fhicl::Atom stmPHDigisTag{ Name("stmPHDigisTag"), Comment("InputTag for STMPHDigiCollectionMap")}; }; using Parameters = art::EDProducer::Table; explicit MakeSTMHits(const Parameters& conf); @@ -45,21 +45,20 @@ namespace mu2e { private: void produce(art::Event& e) override; - art::ProductToken _stmPHDigisToken; + art::ProductToken _stmPHDigisToken; STMChannel _channel; ProditionsHandle _stmEnergyCalib_h; }; MakeSTMHits::MakeSTMHits(const Parameters& config ) : art::EDProducer{config} - ,_stmPHDigisToken(consumes(config().stmPHDigisTag())) + ,_stmPHDigisToken(consumes(config().stmPHDigisTag())) ,_channel(STMUtils::getChannel(config().stmPHDigisTag())) ,_stmEnergyCalib_h() { produces(); } - //Originally had _channel(STMChannel::LaBr) - + void MakeSTMHits::produce(art::Event& event) { // create output unique_ptr outputSTMHits(new STMHitCollection); @@ -70,14 +69,18 @@ namespace mu2e { const auto nsPerCt = stmEnergyCalib.nsPerCt(_channel); const auto& pars = stmEnergyCalib.calib(_channel); - for (const auto& ph_digi : *phDigisHandle) { - auto uncalib_time = ph_digi.time(); - auto uncalib_energy = ph_digi.energy(); - float time = uncalib_time*nsPerCt; - float energy = pars.p0 + pars.p1*uncalib_energy + pars.p2*uncalib_energy*uncalib_energy; + for (const auto& mu2e_evt : *phDigisHandle) { + // const auto& stm_evt_header = mu2e_evt.first; // not used at the moment but left here for future reference + const auto& ph_digis = mu2e_evt.second; + for (const auto& ph_digi : ph_digis) { + auto uncalib_time = ph_digi.time(); + auto uncalib_energy = ph_digi.energy(); + float time = uncalib_time*nsPerCt; + float energy = pars.p0 + pars.p1*uncalib_energy + pars.p2*uncalib_energy*uncalib_energy; - STMHit stm_hit(time,energy); - outputSTMHits->push_back(stm_hit); + STMHit stm_hit(time,energy); + outputSTMHits->push_back(stm_hit); + } } event.put(std::move(outputSTMHits)); From 49992f3420e198d70855823f8c0c954a73eb7a29 Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Thu, 20 Aug 2026 15:27:55 -0500 Subject: [PATCH 20/21] STMPHDigiTree with new map format --- STMReco/src/STMPHDigiTree_module.cc | 98 ++++++++++++++++------------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/STMReco/src/STMPHDigiTree_module.cc b/STMReco/src/STMPHDigiTree_module.cc index 6f3190ace3..8f96d966e7 100644 --- a/STMReco/src/STMPHDigiTree_module.cc +++ b/STMReco/src/STMPHDigiTree_module.cc @@ -2,6 +2,7 @@ // stdlib includes #include +#include // art includes #include "art/Framework/Core/EDAnalyzer.h" @@ -20,11 +21,6 @@ // message handling #include "messagefacility/MessageLogger/MessageLogger.h" -// Offline includes -#include "Offline/GlobalConstantsService/inc/ParticleDataList.hh" -#include "Offline/MCDataProducts/inc/SimParticle.hh" -#include "Offline/MCDataProducts/inc/StepPointMC.hh" - // Offline includes I added #include "Offline/RecoDataProducts/inc/STMPHDigi.hh" #include "Offline/Mu2eUtilities/inc/STMUtils.hh" @@ -34,6 +30,7 @@ #include "TTree.h" #include "TH1D.h" + // Mu2e type definitions namespace mu2e { @@ -42,7 +39,7 @@ namespace mu2e { using Name=fhicl::Name; using Comment=fhicl::Comment; struct Config { - fhicl::Atom phDigiTag{ Name("phDigiTag"), Comment("Input Tag for STMPHDigiCollection")}; + fhicl::Atom phDigiTag{ Name("phDigiTag"), Comment("Input Tag for STMPHDigiCollectionMap")}; // Already seperates by detector name -> makeSTMDigis:phHPGe or phLaBr }; using Parameters = art::EDAnalyzer::Table; @@ -53,18 +50,24 @@ namespace mu2e { void beginJob() override; //void endJob() override; - // Token for STM PH Digis - art::ProductToken _stmPHDigisToken; + // New token for map + art::ProductToken _stmPHDigisMapToken; STMChannel _channel; // Store STM PH Digi information - int16_t pulseHeight_ = 0; - uint32_t uncalibratedTime_ = 0; + int16_t pulseHeight = 0; + uint32_t uncalibratedTime = 0; // Store file information - Int_t evt_; - Int_t run_; - Int_t subrun_; + Int_t art_evt; + Int_t run; + Int_t subrun; + + // Store from EventHeader + uint64_t ewt = 0; + uint8_t evtMode = 0; + uint64_t adcClock = 0; + uint64_t dtcClock = 0; // Tree reference TTree* ttree = nullptr; @@ -75,7 +78,7 @@ namespace mu2e { STMPHDigiTree::STMPHDigiTree(const Parameters& config) : art::EDAnalyzer{config}, - _stmPHDigisToken(consumes(config().phDigiTag())), + _stmPHDigisMapToken(consumes(config().phDigiTag())), _channel(STMUtils::getChannel(config().phDigiTag())) {} @@ -83,14 +86,19 @@ namespace mu2e { // Set up TTree here art::ServiceHandle tfs; ttree = tfs->make("ttree", "Detector ttree"); - ttree->Branch("pulse_height", &pulseHeight_, "pulse_height/S"); - ttree->Branch("uncalibrated_time", &uncalibratedTime_, "uncalibrated_time/i"); + ttree->Branch("pulse_height", &pulseHeight, "pulse_height/S"); + ttree->Branch("uncalibrated_time", &uncalibratedTime, "uncalibrated_time/i"); // Event Information - ttree->Branch("event", &evt_, "event/I"); - ttree->Branch("run", &run_, "run/I"); - ttree->Branch("subrun", &subrun_, "subrun/I"); - // TODO: add branch for EWT + ttree->Branch("art_event", &art_evt, "art_event/I"); + ttree->Branch("run", &run, "run/I"); + ttree->Branch("subrun", &subrun, "subrun/I"); + + // EventHeader information + ttree->Branch("EWT", &ewt, "EWT/l"); + ttree->Branch("event_mode", &evtMode, "event_mode/b"); + ttree->Branch("adc_clock", &adcClock, "adc_clock/l"); + ttree->Branch("dtc_clock", &dtcClock, "dtc_clock/l"); // Set up histogram std::string phSpectrumTitle = "PH Spectrum (" + _channel.name() + ")" ; // Builds title PH Spectrum (HPGe/ LaBr) @@ -101,32 +109,36 @@ namespace mu2e { }; void STMPHDigiTree::analyze(const art::Event& event) { - - // We fill here information - // you can reference event and get ifno - // TODO: change to art_event - evt_ = event.event(); - run_ = event.run(); - subrun_=event.subRun(); + // We fill art based information here + art_evt = event.event(); + run = event.run(); + subrun = event.subRun(); // Get handle for PH Digis - auto phDigisHandle = event.getValidHandle(_stmPHDigisToken); - const auto& phDigis = *phDigisHandle; - // TODO: now a map - // for (const auto& i_phDigiMap : phDigiMap) { - // uint64_t evt_ = i_phDigiMap->first; - // const auto& phDigis = i_phMap->second; - // can continue as below - for (const auto& phDigi : phDigis){ - pulseHeight_= phDigi.energy(); - uncalibratedTime_ = phDigi.time(); - - // Fill one row per PH Digi - ttree->Fill(); - _phSpectrum->Fill(pulseHeight_); - + auto phDigisMapHandle = event.getValidHandle(_stmPHDigisMapToken); + const auto& phDigiMap = *phDigisMapHandle; + for (const auto& i_phDigiMap : phDigiMap){ + // get EventHeader + const auto& header = i_phDigiMap.first; + // store related info + ewt = header.eventWindowTag(); + evtMode = header.eventMode(); + adcClock = header.adcClock(); + dtcClock = header.dtcClock(); + + // get PH Digi Collection + const auto& phDigis = i_phDigiMap.second; + + // Second loop for PH Digis + for (const auto& phDigi : phDigis){ + pulseHeight = phDigi.energy(); + uncalibratedTime = phDigi.time(); + // fill tree + ttree->Fill(); + // fill histogram + _phSpectrum->Fill(pulseHeight); + } } - } // end of analyze }; // end namespace mu2e From 78bea688ff9bb729b164d999125541a23cbda50d Mon Sep 17 00:00:00 2001 From: Bryan Gonzalez Date: Thu, 20 Aug 2026 17:04:31 -0500 Subject: [PATCH 21/21] PlotSTMPHSpectrum now includes map --- STMReco/src/PlotSTMPHSpectrum_module.cc | 47 +++++++++++++++---------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/STMReco/src/PlotSTMPHSpectrum_module.cc b/STMReco/src/PlotSTMPHSpectrum_module.cc index f29c8bbffe..6dd87495db 100644 --- a/STMReco/src/PlotSTMPHSpectrum_module.cc +++ b/STMReco/src/PlotSTMPHSpectrum_module.cc @@ -1,6 +1,7 @@ // // Analyzer module to create a histogram of the STMPHDigi uncalibrated energies // + #include "art/Framework/Principal/Event.h" #include "art/Framework/Core/EDAnalyzer.h" #include "art/Framework/Principal/Handle.h" @@ -13,9 +14,11 @@ #include "art_root_io/TFileService.h" #include "Offline/GlobalConstantsService/inc/GlobalConstantsHandle.hh" #include "Offline/GlobalConstantsService/inc/ParticleDataList.hh" +#include "Offline/Mu2eUtilities/inc/STMUtils.hh" #include "Offline/MCDataProducts/inc/StepPointMC.hh" #include +#include // root #include "TH2F.h" #include "TH1F.h" @@ -35,7 +38,7 @@ namespace mu2e { using Name=fhicl::Name; using Comment=fhicl::Comment; struct Config { - fhicl::Atom stmPHDigisTag{ Name("stmPHDigisTag"), Comment("InputTag for STMPHDigiCollection")}; + fhicl::Atom stmPHDigisTag{ Name("stmPHDigisTag"), Comment("InputTag for STMPHDigiCollectionMap")}; }; using Parameters = art::EDAnalyzer::Table; explicit PlotSTMPHSpectrum(const Parameters& conf); @@ -45,39 +48,47 @@ namespace mu2e { void analyze(const art::Event& e) override; TH2F* _twoDhist; //Histograms of Energy vs binned event - int eventCount = 0; - + int artEventCount = 0; + TH1D* _phSpectrum; - art::ProductToken _stmPHDigisToken; + art::ProductToken _stmPHDigisMapToken; + STMChannel _channel; }; PlotSTMPHSpectrum::PlotSTMPHSpectrum(const Parameters& config ) : art::EDAnalyzer{config}, - _stmPHDigisToken(consumes(config().stmPHDigisTag())) + _stmPHDigisMapToken(consumes(config().stmPHDigisTag())), + _channel(STMUtils::getChannel(config().stmPHDigisTag())) { } void PlotSTMPHSpectrum::beginJob() { art::ServiceHandle tfs; // create histograms - _phSpectrum=tfs->make("phSpectrum", "PH Spectrum;PulseHeight;Count", 10000, -10000, 0); //bins,min,max - _twoDhist=tfs->make("phEvent","Pulse Height vs events;Event Bins; Pulse Height", // (name, title;xtitle;ytitle, nbinsX, xlow, xup, nbinsY, ylow, yup) + std::string phSpectrumTitle = "PH Spectrum (" +_channel.name() + ")"; // Builds title for PH Spectrum + _phSpectrum=tfs->make("phSpectrum", (phSpectrumTitle + ";Pulse Height;Count").c_str(), 10000, -10000, 0); //bins,min,max + + _twoDhist=tfs->make("phEvent",("Pulse Height vs Art Events (" + _channel.name() + ");Event Bins; Pulse Height").c_str(), // (name, title;xtitle;ytitle, nbinsX, xlow, xup, nbinsY, ylow, yup) 10,0,10, // X-axis scale 10000,-10000,0); // Y-axis scale } void PlotSTMPHSpectrum::analyze(const art::Event& event) { - - auto phDigisHandle = event.getValidHandle(_stmPHDigisToken); - const auto& phDigis = *phDigisHandle; - int binBlock = eventCount/100; - - for (const auto& phDigi : phDigis) { - auto energy = phDigi.energy(); - _phSpectrum->Fill(energy); - _twoDhist->Fill(binBlock, energy); + // get map handle + auto phDigisMapHandle = event.getValidHandle(_stmPHDigisMapToken); + const auto& phDigiMap = *phDigisMapHandle; + int binBlock = artEventCount/100; + for (const auto& i_phDigiMap : phDigiMap){ + // get PH Digi Collection + const auto& phDigis = i_phDigiMap.second; + for (const auto& phDigi : phDigis) { + // get uncalibrated energy (adc) + auto energy = phDigi.energy(); + _phSpectrum->Fill(energy); + _twoDhist->Fill(binBlock, energy); + } + } + ++artEventCount; } - ++eventCount; - } } DEFINE_ART_MODULE(mu2e::PlotSTMPHSpectrum)