diff --git a/DAQ/src/STMDigisFromFragments_module.cc b/DAQ/src/STMDigisFromFragments_module.cc index 9f23c10160..8ce80462bc 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,8 @@ #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 @@ -27,794 +30,1382 @@ #include #include #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}; + size_t _totalPHCountMismatch{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 + size_t _totalPHCountMismatchHPGe{0}; + + // 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 + size_t _totalPHCountMismatchLaBr{0}; + + // 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}; + + // 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 { + 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}; + size_t phCountMismatch{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"); + */ + + //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 +// ========================= void STMDigisFromFragments::produce(Event& event) { - - 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" ; + // Extra frag counters for this event + size_t containerFragsThisEvent{0}; + size_t innerFragsThisEvent{0}; + size_t containerFragsHPGeThisEvent{0}; + size_t containerFragsLaBrThisEvent{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"); + } + */ + + // 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 + 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}; + 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{0}; + + // 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; + 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) { + 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; + parentState.index = 0; + ++eventMetrics.raw.seen; + // 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){ + 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 + // 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(); + + // 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(); + + // 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; + ++_totalRawFragsPrescaled; + isHPGe ? ++_totalRawFragsPrescaledHPGe : ++_totalRawFragsPrescaledLaBr; + + parentState.ptr = {}; + parentState.available = false; + continue; + } + + 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){ + 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 non 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){ + auto dataPtr = stm_frag.dataBegin(); + auto dataWords = stm_frag.dataWords(); + // set stm_waveform + stm_waveform.set_data(dataWords,dataPtr); + // 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); + + // 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; + } + // 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); + // 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); + // 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; + } + 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; + + // 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){ + 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) { + // set waveform digi with offset and adcs + mu2e::STMWaveformDigi zsDigi(region.offset, region.adcs); + //if(parentState.available){ + // Set parent pointer if available + // zsDigi.setParent(parentState.ptr); + //} + + // Emplacing + if (isHPGe && _saveZSWaveformsHPGe) { + // 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() + << ", offset : " << zsDigi.trigTimeOffset() << "\n"; + } + + } else if (isLaBr && _saveZSWaveformsLaBr) { + // 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() + << ", 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; + + // 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) { + ++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; + + // 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 + 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); + (*phDigisHPGe)[stm_event_header].emplace_back(PH_digi); + } + if (isLaBr) { + //phDigisLaBr->emplace_back(PH_digi); + (*phDigisLaBr)[stm_event_header].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 + ++unknownFragsThisEvent; + 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( + 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 + ); + + stmFragSummaryLaBr->emplace_back( + 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 + ); } - } //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 << "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 << "\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"; + } + // 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 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"; + 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 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"; + + } } DEFINE_ART_MODULE(STMDigisFromFragments) diff --git a/DAQ/src/STMPrintFragments_module.cc b/DAQ/src/STMPrintFragments_module.cc index adf5f8d0b1..c85ffb95e3 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,189 @@ void STMPrintFragments::analyze(const Event& event) std::cout << STMContainerFragments->size() << " STM fragments." << std::endl; int frag_counter = 0; - for (auto& frag : *STMContainerFragments) { + for (const auto& frag : *STMContainerFragments) { ++frag_counter; - - //New lines - artdaq::ContainerFragment contf(frag); // interpret the fragment as a ContainerFragemnt (Will look inside here) - std::cout<<"N Blocks in the container = " << contf.block_count() << std::endl; //Should be 3 for the 3 STM Fragments - - for (size_t ii = 0; ii< contf.block_count(); ++ii){ - auto inner = contf.at(ii); - const auto dataBegin = inner->dataBegin(); - const auto dataEnd = inner->dataEnd(); - auto frag_id = inner->fragmentID(); - const auto stmDataBegin = reinterpret_cast(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(); + + // 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" + << ", inner # : " << i << "\n" + << ", PhysicalWords : " << physicalWords << "\n" + << ", stmDataWords : " << stmDataWords << "\n"; + size_t seg = 0; + + 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 (current_zs_size > static_cast(dataEnd - adc)){ + std::cout << "Malformed or truncated ZS Region: Declared size extends beyond fragment data " << "\n"; + break; + } + for (size_t j = 0; j < current_zs_size; ++j) { + std::cout << "ZS Payload[" << j << "] = " << adc[j] << ", region = " << seg << "\n"; + } + + std::cout << "Region = " << seg + << " , zs_index = " << current_zs_location + << " , zs_size = " << current_zs_size << "\n" ; + + // Update Variables + ++seg; + dataPtr = adc + current_zs_size; + } // end of while loop + } + + else if (stm_frag.isPH()){ + size_t digiWords = stm_frag.payloadWords(); + auto const* digiPtr = stm_frag.payloadBegin(); + std::cout << "\n=== PH Payload Dump ===\n" << "\n"; + if (digiWords %2 !=0) { + std::cout << "Found a malformed PH frag " << "\n"; + } + + for (size_t i_PH = 0; i_PH + 1 < digiWords ; i_PH +=2){ + uint32_t time = static_cast(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..6a200677e9 100644 --- a/DAQ/test/inspectSTMFile.fcl +++ b/DAQ/test/inspectSTMFile.fcl @@ -19,25 +19,25 @@ physics : { makeSTMDigis : { module_type : STMDigisFromFragments stmTag : "daq:ContainerSTM" - verbosityLevel : 2 + verbosityLevel : 1 saveSTMFragSummary : true - saveRawWithHeaderWaveform_HPGe: false - saveRawWaveform_HPGe: true - saveZSWaveform_HPGe: true - saveRawWithHeaderWaveform_LaBr: false - saveRawWaveform_LaBr: true - saveZSWaveform_LaBr: true - } + saveRawWaveformsWithHeaderHPGe: false + saveRawWaveformsHPGe: true + saveZSWaveformsHPGe: true + saveRawWaveformsWithHeaderLaBr: false + saveRawWaveformsLaBr: true + saveZSWaveformsLaBr: true + } - makeSTMBinary : { - module_type : STMBinaryDigisFromFragments + makeSTMBinary : { + module_type : STMBinaryDigisFromFragments stmTag : "daq:ContainerSTM" verbosityLevel : 1 - rawFile : "raw.bin" - zsFile : "zs.bin" - phFile : "ph.bin" - rawHeaderFile : "rawWithHeader.bin" - eventFile : "event.bin" + rawFile : "raw.bin" + zsFile : "zs.bin" + phFile : "ph.bin" + rawHeaderFile : "rawWithHeader.bin" + eventFile : "event.bin" } } @@ -47,6 +47,9 @@ physics : { stmPrint : { module_type : STMPrintFragments stmTag : "daq:ContainerSTM" + printEverything : false + printInnerFrags : false + printPayloads : false } } diff --git a/RecoDataProducts/inc/STMEventHeader.hh b/RecoDataProducts/inc/STMEventHeader.hh new file mode 100644 index 0000000000..8b0cc4319f --- /dev/null +++ b/RecoDataProducts/inc/STMEventHeader.hh @@ -0,0 +1,35 @@ +#ifndef RecoDataProducts_STMEventHeader_hh_ +#define RecoDataProducts_STMEventHeader_hh_ + +#include "artdaq-core-mu2e/Data/Mu2eEventHeader.hh" + +namespace mu2e +{ + class STMEventHeader + { + public: + explicit STMEventHeader() {} + STMEventHeader(uint64_t ewt, uint8_t mode, uint64_t adcClock, uint64_t dtcClock) : + _mu2eEventHeader(ewt, mode), _adcClock(adcClock), _dtcClock(dtcClock) { } + + uint64_t eventWindowTag() const { return _mu2eEventHeader.EventWindowTag; } + uint8_t eventMode() const { return _mu2eEventHeader.EventMode; } + + uint64_t adcClock() const { return _adcClock; } + uint64_t dtcClock() const { return _dtcClock; } + + // other represents comparison, seperate by EWT + bool operator<(STMEventHeader const& other) const { + return eventWindowTag() < other.eventWindowTag(); + } + + private: + Mu2eEventHeader _mu2eEventHeader; + uint64_t _adcClock; + uint64_t _dtcClock; + }; + typedef std::vector STMEventHeaderCollection; +} // namespace mu2e + + +#endif diff --git a/RecoDataProducts/inc/STMFragmentSummary.hh b/RecoDataProducts/inc/STMFragmentSummary.hh index c9df4b6caf..c4c4d2ef48 100644 --- a/RecoDataProducts/inc/STMFragmentSummary.hh +++ b/RecoDataProducts/inc/STMFragmentSummary.hh @@ -18,23 +18,43 @@ namespace mu2e { public: 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){}; 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) {}; - + // 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; } + + // 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; } @@ -49,9 +69,21 @@ 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{}; + + // Filter/Classifications results + size_t _nPrescaledRawFrags{}; + size_t _nPrescaledZSFrags{}; + size_t _nGoodRawFrags{}; size_t _nGoodZSFrags{}; size_t _nGoodPHFrags{}; @@ -64,7 +96,6 @@ namespace mu2e { size_t _nEmptyZSFrags{}; size_t _nEmptyPHFrags{}; - }; typedef std::vector STMFragmentSummaryCollection; } diff --git a/RecoDataProducts/inc/STMPHDigi.hh b/RecoDataProducts/inc/STMPHDigi.hh index d6d5fc9c1c..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 { @@ -28,6 +31,7 @@ namespace mu2e { }; 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 6d0dc8551c..f12541e720 100644 --- a/RecoDataProducts/inc/STMWaveformDigi.hh +++ b/RecoDataProducts/inc/STMWaveformDigi.hh @@ -10,26 +10,21 @@ #include #include #include +#include #include "Offline/DataProducts/inc/STMChannel.hh" +#include "Offline/RecoDataProducts/inc/STMEventHeader.hh" #include "canvas/Persistency/Common/Ptr.h" namespace mu2e { class STMWaveformDigi { public: - // Initialise all variables - STMWaveformDigi() : _DetID(0), _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), \ -_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) {}; + // Initialise all variables + STMWaveformDigi() : _trigTimeOffset(0), _adcs(std::vector()) {}; + // Basic constructor + STMWaveformDigi(uint32_t trigTimeOffset, std::vector &adcs) : _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; } 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()); } @@ -37,14 +32,11 @@ _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; 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 }; typedef std::vector STMWaveformDigiCollection; + typedef std::map STMWaveformDigiCollectionMap; } #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..2c1b6cda22 100644 --- a/RecoDataProducts/src/classes_def.xml +++ b/RecoDataProducts/src/classes_def.xml @@ -467,6 +467,15 @@ + + + + + + + + + diff --git a/STMReco/fcl/plotSTMWaveformDigis.fcl b/STMReco/fcl/plotSTMWaveformDigis.fcl index e6b1bca596..7b77a14fb5 100644 --- a/STMReco/fcl/plotSTMWaveformDigis.fcl +++ b/STMReco/fcl/plotSTMWaveformDigis.fcl @@ -29,18 +29,18 @@ physics: { verbosityLevel : 0 xAxis : "sample_number" } - - plotZSWaveformDigisHPGe : { + + plotRawWaveformDigisTimeHPGe : { module_type : PlotSTMWaveformDigis - stmWaveformDigisTag : "makeSTMDigis:zsHPGe" + stmWaveformDigisTag : "makeSTMDigis:rawHPGe" subtractPedestal : false verbosityLevel : 0 - xAxis : "sample_number" + xAxis: "waveform_time" } - - plotPHWaveformDigisHPGe : { + + plotZSWaveformDigisHPGe : { module_type : PlotSTMWaveformDigis - stmWaveformDigisTag : "makeSTMDigis:phHPGe" + stmWaveformDigisTag : "makeSTMDigis:zsHPGe" subtractPedestal : false verbosityLevel : 0 xAxis : "sample_number" @@ -61,19 +61,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, plotZSWaveformDigisHPGe, plotRawWaveformDigisLaBr, plotZSWaveformDigisLaBr ] end_paths: [anaPath] } 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/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)); diff --git a/STMReco/src/PlotSTMPHSpectrum_module.cc b/STMReco/src/PlotSTMPHSpectrum_module.cc index 4995dc4aef..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,38 +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", 1000, 0, 1e4); - _twoDhist=tfs->make("twoDhist","Pulse Height vs events;Event Bins; Pulse Height", - 1000,0,1000, // X-axis scale - 1000,0,1e5); // Y-axis scale + 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); - int binBlock = eventCount/100; - - for (const auto& phDigi : *phDigisHandle) { - 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) diff --git a/STMReco/src/PlotSTMWaveformDigis_module.cc b/STMReco/src/PlotSTMWaveformDigis_module.cc index 9fb9437c79..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; @@ -122,12 +122,19 @@ 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"){ + hWaveform->GetXaxis()->SetTitle("Waveform Time [nsec]"); + } else if (_xAxis == "event_time"){ + hWaveform->GetXaxis()->SetTitle("Event Time [nsec]"); + } if (plotZSOffsetWaveforms){ //For offset waveforms -> Better organize this area @@ -143,22 +150,15 @@ 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 + trigtimeOffset"); - // 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 + hWaveformOffset->GetXaxis()->SetTitle("Sample Number (Includes + Time Offset)"); }//PlotZSOffset 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; } 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()); diff --git a/STMReco/src/STMPHDigiTree_module.cc b/STMReco/src/STMPHDigiTree_module.cc new file mode 100644 index 0000000000..8f96d966e7 --- /dev/null +++ b/STMReco/src/STMPHDigiTree_module.cc @@ -0,0 +1,146 @@ +// NTuple dumper for Detector pulse heights + +// stdlib includes +#include +#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 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 STMPHDigiCollectionMap")}; + // 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; + + // New token for map + art::ProductToken _stmPHDigisMapToken; + STMChannel _channel; + + // Store STM PH Digi information + int16_t pulseHeight = 0; + uint32_t uncalibratedTime = 0; + + // Store file information + 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; + + // STM PH spectrum + TH1D* _phSpectrum = nullptr; + }; + + STMPHDigiTree::STMPHDigiTree(const Parameters& config) : + art::EDAnalyzer{config}, + _stmPHDigisMapToken(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("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) + + _phSpectrum = tfs->make("phSpectrum", + (phSpectrumTitle +";PulseHeight;Count").c_str(), + 10000, -10000, 0); + }; + + void STMPHDigiTree::analyze(const art::Event& event) { + // We fill art based information here + art_evt = event.event(); + run = event.run(); + subrun = event.subRun(); + + // Get handle for PH Digis + 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 + +DEFINE_ART_MODULE(mu2e::STMPHDigiTree) 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";