diff --git a/DAQ/src/CaloDigisToFragments_module.cc b/DAQ/src/CaloDigisToFragments_module.cc index 041429e05b..9bfe85a828 100644 --- a/DAQ/src/CaloDigisToFragments_module.cc +++ b/DAQ/src/CaloDigisToFragments_module.cc @@ -131,10 +131,6 @@ class mu2e::CaloDigisToFragments : public art::EDProducer { public: struct Config { fhicl::Atom diagLevel{fhicl::Name("diagLevel"), fhicl::Comment("diagnostic level"), 0}; - fhicl::Atom skipFragmentOnSizeMismatch{ - fhicl::Name("skipFragmentOnSizeMismatch"), - fhicl::Comment("Skip emitting fragment when packed bytes and event header size differ"), - false}; fhicl::Atom caloDigiTag{fhicl::Name("caloDigiTag"), fhicl::Comment("Input CaloDigiCollection"), art::InputTag("CaloDigisFromDTCEvents")}; @@ -150,25 +146,26 @@ class mu2e::CaloDigisToFragments : public art::EDProducer { mu2e::ProditionsHandle calodaqconds_h_; int diagLevel_; - bool skipFragmentOnSizeMismatch_; art::InputTag caloDigiTag_; long int total_events_; long int total_digis_; + const int fragment_id_offset_ = 100; // IDs start from here + static size_t waveformMaximumIndex(const std::vector& waveform); static void putBlockInEvent(DTCLib::DTC_Event& currentEvent, uint8_t dtcID, DTCLib::DTC_DataBlock const& thisBlock); - void buildDtcEventFromDigis(art::Event const& event, mu2e::CaloDigiCollection const& caloDigis, - DTCLib::DTC_Event& dtcEvent); + void buildDtcEventsFromDigis(art::Event const& event, + mu2e::CaloDigiCollection const& caloDigis, + std::map& dtcEvents); }; mu2e::CaloDigisToFragments::CaloDigisToFragments(const art::EDProducer::Table& config) : art::EDProducer{config} , diagLevel_(config().diagLevel()) - , skipFragmentOnSizeMismatch_(config().skipFragmentOnSizeMismatch()) , caloDigiTag_(config().caloDigiTag()) { produces(); total_events_ = 0; @@ -196,9 +193,9 @@ void mu2e::CaloDigisToFragments::putBlockInEvent(DTCLib::DTC_Event& currentEvent } } -void mu2e::CaloDigisToFragments::buildDtcEventFromDigis(art::Event const& event, - mu2e::CaloDigiCollection const& caloDigis, - DTCLib::DTC_Event& dtcEvent) { +void mu2e::CaloDigisToFragments::buildDtcEventsFromDigis( + art::Event const& event, mu2e::CaloDigiCollection const& caloDigis, + std::map& dtcEvents) { auto const& calodaqconds = calodaqconds_h_.get(event.id()); std::map> byDtcAndLink; @@ -242,6 +239,9 @@ void mu2e::CaloDigisToFragments::buildDtcEventFromDigis(art::Event const& event, } for (auto& [dtcID, linkMap] : byDtcAndLink) { + auto& dtcEvent = dtcEvents[dtcID]; + dtcEvent.SetEventWindowTag(DTCLib::DTC_EventWindowTag(static_cast(event.event()))); + for (uint8_t linkID = 0; linkID < kCaloRocsPerDtc; ++linkID) { auto& block = linkMap[linkID]; block.dtcID = dtcID; @@ -322,24 +322,27 @@ void mu2e::CaloDigisToFragments::produce(art::Event& event) { auto const& caloDigis = *caloDigiHandle; total_digis_ += caloDigis.size(); - DTCLib::DTC_Event dtcEvent; - dtcEvent.SetEventWindowTag(DTCLib::DTC_EventWindowTag(static_cast(event.event()))); - buildDtcEventFromDigis(event, caloDigis, dtcEvent); + std::map dtcEvents; + buildDtcEventsFromDigis(event, caloDigis, dtcEvents); + + for (auto& [dtcID, dtcEvent] : dtcEvents) { + auto const eventBytes = dtcEvent.GetEventByteCount(); + if (eventBytes == 0 || dtcEvent.GetSubEventCount() == 0) { + continue; + } - auto const eventBytes = dtcEvent.GetEventByteCount(); - if (eventBytes > 0 && dtcEvent.GetSubEventCount() > 0) { // Build the exact in-memory layout consumed by DTCEventFragment::SetupEvent. std::vector packed; packed.reserve(eventBytes); auto const* evHdr = dtcEvent.GetHeader(); packed.insert(packed.end(), reinterpret_cast(evHdr), - reinterpret_cast(evHdr) + kDtcEventHeaderBytes); + reinterpret_cast(evHdr) + kDtcEventHeaderBytes); for (auto const& subEvt : dtcEvent.GetSubEvents()) { auto const* subHdr = subEvt.GetHeader(); packed.insert(packed.end(), reinterpret_cast(subHdr), - reinterpret_cast(subHdr) + kDtcSubEventHeaderBytes); + reinterpret_cast(subHdr) + kDtcSubEventHeaderBytes); for (auto const& block : subEvt.GetDataBlocks()) { auto const* blk = reinterpret_cast(block.GetRawBufferPointer()); @@ -347,55 +350,42 @@ void mu2e::CaloDigisToFragments::produce(art::Event& event) { } } - bool sizeMismatch = packed.size() != eventBytes; - if (sizeMismatch) { - if (skipFragmentOnSizeMismatch_) { - if (diagLevel_ > 0) { - std::cout << "[CaloDigisToFragments::produce] WARNING: packed size " << packed.size() - << " differs from header event size " << eventBytes - << " - skipping fragment" << std::endl; - } - event.put(std::move(fragments)); - return; - } - if (diagLevel_ > 0) { - std::cout << "[CaloDigisToFragments::produce] WARNING: packed size " << packed.size() - << " differs from header event size " << eventBytes - << " - emitting fragment" << std::endl; - } + if (diagLevel_ > 0 && packed.size() != eventBytes) { + std::cout << "[CaloDigisToFragments::produce] WARNING: DTC " << static_cast(dtcID) + << " packed size " << packed.size() << " differs from header event size " + << eventBytes << " - emitting fragment" << std::endl; } - { - auto fragPtr = artdaq::Fragment::FragmentBytes(packed.size()); - fragPtr->setUserType(mu2e::FragmentType::DTCEVT); - fragPtr->setSequenceID(static_cast(event.event())); - fragPtr->setFragmentID(0); - fragPtr->setTimestamp(static_cast(event.event())); - if (!packed.empty()) { - std::memcpy(fragPtr->dataBeginBytes(), packed.data(), packed.size()); - } + auto fragPtr = artdaq::Fragment::FragmentBytes(packed.size()); + fragPtr->setUserType(mu2e::FragmentType::DTCEVT); + fragPtr->setSequenceID(static_cast(event.event())); + fragPtr->setFragmentID(static_cast(dtcID + fragment_id_offset_)); + fragPtr->setTimestamp(static_cast(event.event())); + if (!packed.empty()) { + std::memcpy(fragPtr->dataBeginBytes(), packed.data(), packed.size()); + } - if (diagLevel_ > 0) { - mu2e::DTCEventFragment testFragment(*fragPtr); - auto testSubevents = - testFragment.getSubsystemData(DTCLib::DTC_Subsystem::DTC_Subsystem_Calorimeter); - size_t decodedHits = 0; - for (auto const& se : testSubevents) { - mu2e::CalorimeterDataDecoder decoder(se); - for (size_t i = 0; i < decoder.block_count(); ++i) { - auto hitVec = decoder.GetCalorimeterHitData(i); - if (hitVec != nullptr) { - decodedHits += hitVec->size(); - } + if (diagLevel_ > 0) { + mu2e::DTCEventFragment testFragment(*fragPtr); + auto testSubevents = + testFragment.getSubsystemData(DTCLib::DTC_Subsystem::DTC_Subsystem_Calorimeter); + size_t decodedHits = 0; + for (auto const& se : testSubevents) { + mu2e::CalorimeterDataDecoder decoder(se); + for (size_t i = 0; i < decoder.block_count(); ++i) { + auto hitVec = decoder.GetCalorimeterHitData(i); + if (hitVec != nullptr) { + decodedHits += hitVec->size(); } } - std::cout << "[CaloDigisToFragments::produce] Validation: " << testSubevents.size() - << " CALO subevent(s), " << decodedHits << " decodable hit(s) in output" - << std::endl; } - - fragments->emplace_back(std::move(*fragPtr)); + std::cout << "[CaloDigisToFragments::produce] Validation: DTC " + << static_cast(dtcID) << ", " << testSubevents.size() + << " CALO subevent(s), " << decodedHits << " decodable hit(s) in output" + << std::endl; } + + fragments->emplace_back(std::move(*fragPtr)); } if (diagLevel_ > 0) { diff --git a/DAQ/src/StrawDigisToFragments_module.cc b/DAQ/src/StrawDigisToFragments_module.cc index ca321b3de8..e3c42a3d4a 100644 --- a/DAQ/src/StrawDigisToFragments_module.cc +++ b/DAQ/src/StrawDigisToFragments_module.cc @@ -193,13 +193,15 @@ class mu2e::StrawDigisToFragments : public art::EDProducer { long int total_events_; long int total_digis_; + const int fragment_id_offset_ = 0; // IDs start from here + static void putBlockInEvent(DTCLib::DTC_Event& currentEvent, uint8_t dtcID, DTCLib::DTC_DataBlock const& thisBlock); - void buildDtcEventFromDigis(art::Event const& event, - mu2e::StrawDigiCollection const& strawDigis, - mu2e::StrawDigiADCWaveformCollection const& strawADCs, - DTCLib::DTC_Event& dtcEvent); + void buildDtcEventsFromDigis(art::Event const& event, + mu2e::StrawDigiCollection const& strawDigis, + mu2e::StrawDigiADCWaveformCollection const& strawADCs, + std::map& dtcEvents); }; mu2e::StrawDigisToFragments::StrawDigisToFragments(const art::EDProducer::Table& config) @@ -216,7 +218,7 @@ mu2e::StrawDigisToFragments::StrawDigisToFragments(const art::EDProducer::Table< } void mu2e::StrawDigisToFragments::putBlockInEvent(DTCLib::DTC_Event& currentEvent, uint8_t dtcID, - DTCLib::DTC_DataBlock const& thisBlock) { + DTCLib::DTC_DataBlock const& thisBlock) { auto subEvt = currentEvent.GetSubEventByDTCID(dtcID, DTCLib::DTC_Subsystem_Tracker); if (subEvt == nullptr) { DTCLib::DTC_SubEvent newSubEvt; @@ -229,9 +231,9 @@ void mu2e::StrawDigisToFragments::putBlockInEvent(DTCLib::DTC_Event& currentEven } } -void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( - art::Event const& event, mu2e::StrawDigiCollection const& strawDigis, - mu2e::StrawDigiADCWaveformCollection const& strawADCs, DTCLib::DTC_Event& dtcEvent) { +void mu2e::StrawDigisToFragments::buildDtcEventsFromDigis(art::Event const& event, mu2e::StrawDigiCollection const& strawDigis, + mu2e::StrawDigiADCWaveformCollection const& strawADCs, + std::map& dtcEvents) { auto const& trackerPanelMap = trackerPanelMap_h_.get(event.id()); if (diagLevel_ > 1 && !printedTrackerPanelMap_) { printTrackerPanelMap(trackerPanelMap); @@ -241,7 +243,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( size_t const nHits = std::min(strawDigis.size(), strawADCs.size()); if (strawDigis.size() != strawADCs.size() && diagLevel_ > 0) { - std::cout << "[StrawDigisToFragments::buildDtcEventFromDigis] WARNING: StrawDigi count " + std::cout << "[StrawDigisToFragments::buildDtcEventsFromDigis] WARNING: StrawDigi count " << strawDigis.size() << " differs from StrawDigiADCWaveform count " << strawADCs.size() << "; using first " << nHits << " entries" << std::endl; } @@ -255,7 +257,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( if (panel >= kTrackerRocsPerDtc) { if (diagLevel_ > 0) { - std::cout << "[StrawDigisToFragments::buildDtcEventFromDigis] WARNING: panel " << panel + std::cout << "[StrawDigisToFragments::buildDtcEventsFromDigis] WARNING: panel " << panel << " outside expected ROC link range [0," << static_cast(kTrackerRocsPerDtc) << ") - skipping digi" << std::endl; } @@ -281,7 +283,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( } else { if (!fallbackToOfflineWhenMapMissing_) { if (diagLevel_ > 0) { - std::cout << "[StrawDigisToFragments::buildDtcEventFromDigis] WARNING: no TrackerPanelMap" + std::cout << "[StrawDigisToFragments::buildDtcEventsFromDigis] WARNING: no TrackerPanelMap" << " entry for offline plane=" << plane << " panel=" << panel << " - skipping digi" << std::endl; } @@ -291,7 +293,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( linkID = static_cast(panel); strawIndexWord = digi.strawId().asUint16(); if (diagLevel_ > 1) { - std::cout << "[StrawDigisToFragments::buildDtcEventFromDigis] INFO: no TrackerPanelMap" + std::cout << "[StrawDigisToFragments::buildDtcEventsFromDigis] INFO: no TrackerPanelMap" << " entry for offline plane=" << plane << " panel=" << panel << " - using offline fallback DTC/link" << std::endl; } @@ -299,7 +301,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( if (linkID >= kTrackerRocsPerDtc) { if (diagLevel_ > 0) { - std::cout << "[StrawDigisToFragments::buildDtcEventFromDigis] WARNING: mapped link " + std::cout << "[StrawDigisToFragments::buildDtcEventsFromDigis] WARNING: mapped link " << static_cast(linkID) << " outside expected ROC link range [0," << static_cast(kTrackerRocsPerDtc) << ") for plane=" << plane << " panel=" << panel << " dtc=" << static_cast(dtcID) @@ -318,6 +320,9 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( } for (auto& [dtcID, linkMap] : byDtcAndLink) { + auto& dtcEvent = dtcEvents[dtcID]; + dtcEvent.SetEventWindowTag(DTCLib::DTC_EventWindowTag(static_cast(event.event()))); + // Emit all tracker ROC links in order so decoders expecting contiguous // ROC indices (0..5) can parse mixed-subdetector streams robustly. for (uint8_t linkID = 0; linkID < kTrackerRocsPerDtc; ++linkID) { @@ -338,7 +343,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( block.transferByteCount = static_cast((numPackets + 1) * 16); if (diagLevel_ > 1) { - std::cout << "[buildDtcEventFromDigis] DTC " << static_cast(dtcID) + std::cout << "[buildDtcEventsFromDigis] DTC " << static_cast(dtcID) << " Link " << static_cast(linkID) << " hits: " << block.hits.size() << " numPackets: " << numPackets @@ -348,7 +353,7 @@ void mu2e::StrawDigisToFragments::buildDtcEventFromDigis( DTCLib::DTC_DataBlock thisBlock(block.transferByteCount); if (thisBlock.blockPointer == nullptr) { if (diagLevel_ > 0) { - std::cout << "[buildDtcEventFromDigis] Failed to allocate DTC_DataBlock with size " + std::cout << "[buildDtcEventsFromDigis] Failed to allocate DTC_DataBlock with size " << block.transferByteCount << std::endl; } continue; @@ -411,42 +416,39 @@ void mu2e::StrawDigisToFragments::produce(art::Event& event) { auto const& strawADCs = *strawADCsHandle; total_digis_ += strawDigis.size(); - DTCLib::DTC_Event dtcEvent; - dtcEvent.SetEventWindowTag(DTCLib::DTC_EventWindowTag(static_cast(event.event()))); - buildDtcEventFromDigis(event, strawDigis, strawADCs, dtcEvent); - - auto const eventBytes = dtcEvent.GetEventByteCount(); - if (diagLevel_ > 1) { - std::cout << "[StrawDigisToFragments::produce] eventBytes from DTC_Event: " << eventBytes - << ", subEventCount: " << dtcEvent.GetSubEventCount() << std::endl; - for (size_t i = 0; i < dtcEvent.GetSubEvents().size(); ++i) { - auto const& subEvt = dtcEvent.GetSubEvents()[i]; - std::cout << " SubEvent " << i << " blockCount: " << subEvt.GetDataBlocks().size() << std::endl; - for (size_t j = 0; j < subEvt.GetDataBlocks().size(); ++j) { - auto const& block = subEvt.GetDataBlocks()[j]; - std::cout << " Block " << j << " byteSize: " << block.byteSize << std::endl; + std::map dtcEvents; + buildDtcEventsFromDigis(event, strawDigis, strawADCs, dtcEvents); + + for (auto& [dtcID, dtcEvent] : dtcEvents) { + auto const eventBytes = dtcEvent.GetEventByteCount(); + + if (diagLevel_ > 1) { + std::cout << "[StrawDigisToFragments::produce] DTC " << static_cast(dtcID) + << " eventBytes: " << eventBytes + << ", subEventCount: " << dtcEvent.GetSubEventCount() << std::endl; + for (size_t i = 0; i < dtcEvent.GetSubEvents().size(); ++i) { + auto const& subEvt = dtcEvent.GetSubEvents()[i]; + std::cout << " SubEvent " << i << " blockCount: " << subEvt.GetDataBlocks().size() + << std::endl; + for (size_t j = 0; j < subEvt.GetDataBlocks().size(); ++j) { + auto const& block = subEvt.GetDataBlocks()[j]; + std::cout << " Block " << j << " byteSize: " << block.byteSize << std::endl; + } } } - } - - if (dtcEvent.GetSubEventCount() > 0) { - // Emit one fragment per tracker subevent (per DTC). The downstream decoder - // processes a single subevent per artdaq fragment payload. - for (size_t seIdx = 0; seIdx < dtcEvent.GetSubEvents().size(); ++seIdx) { - auto const& subEvt = dtcEvent.GetSubEvents()[seIdx]; - size_t calcEventBytes = kDtcEventHeaderBytes + kDtcSubEventHeaderBytes; - for (auto const& block : subEvt.GetDataBlocks()) { - calcEventBytes += block.byteSize; - } + if (eventBytes == 0 || dtcEvent.GetSubEventCount() == 0) { + continue; + } - std::vector packed; - packed.reserve(calcEventBytes); + std::vector packed; + packed.reserve(eventBytes); - auto const* evHdr = dtcEvent.GetHeader(); - packed.insert(packed.end(), reinterpret_cast(evHdr), - reinterpret_cast(evHdr) + kDtcEventHeaderBytes); + auto const* evHdr = dtcEvent.GetHeader(); + packed.insert(packed.end(), reinterpret_cast(evHdr), + reinterpret_cast(evHdr) + kDtcEventHeaderBytes); + for (auto const& subEvt : dtcEvent.GetSubEvents()) { auto const* subHdr = subEvt.GetHeader(); packed.insert(packed.end(), reinterpret_cast(subHdr), reinterpret_cast(subHdr) + kDtcSubEventHeaderBytes); @@ -455,43 +457,24 @@ void mu2e::StrawDigisToFragments::produce(art::Event& event) { auto const* blk = reinterpret_cast(block.GetRawBufferPointer()); packed.insert(packed.end(), blk, blk + block.byteSize); } + } - // Each output fragment carries exactly one subevent payload. Patch the - // copied event header so generic DTC decoders see consistent metadata. - auto* packedEventHdr = reinterpret_cast(packed.data()); - packedEventHdr->inclusive_event_byte_count = static_cast(calcEventBytes); - packedEventHdr->num_dtcs = 1; - - if (diagLevel_ > 1 && packed.size() != calcEventBytes) { - std::cout << "[StrawDigisToFragments::produce] WARNING: subevent " << seIdx - << " packed size " << packed.size() - << " differs from recalculated " << calcEventBytes << std::endl; - } - - auto fragPtr = artdaq::Fragment::FragmentBytes(packed.size()); - fragPtr->setUserType(mu2e::FragmentType::DTCEVT); - fragPtr->setSequenceID(static_cast(event.event())); - fragPtr->setFragmentID(static_cast(seIdx)); - fragPtr->setTimestamp(static_cast(event.event())); - if (!packed.empty()) { - std::memcpy(fragPtr->dataBeginBytes(), packed.data(), packed.size()); - } - - fragments->emplace_back(std::move(*fragPtr)); + if (diagLevel_ > 0 && packed.size() != eventBytes) { + std::cout << "[StrawDigisToFragments::produce] WARNING: DTC " << static_cast(dtcID) + << " packed size " << packed.size() + << " differs from event header size " << eventBytes << std::endl; } - if (diagLevel_ > 0 && eventBytes != 0) { - size_t aggregatePacked = 0; - for (auto const& subEvt : dtcEvent.GetSubEvents()) { - aggregatePacked += kDtcEventHeaderBytes + kDtcSubEventHeaderBytes; - for (auto const& block : subEvt.GetDataBlocks()) aggregatePacked += block.byteSize; - } - if (aggregatePacked != eventBytes * dtcEvent.GetSubEventCount()) { - std::cout << "[StrawDigisToFragments::produce] INFO: GetEventByteCount()=" << eventBytes - << " is unreliable for multi-subevent packing; emitted " - << fragments->size() << " per-subevent fragment(s)" << std::endl; - } + auto fragPtr = artdaq::Fragment::FragmentBytes(packed.size()); + fragPtr->setUserType(mu2e::FragmentType::DTCEVT); + fragPtr->setSequenceID(static_cast(event.event())); + fragPtr->setFragmentID(static_cast(dtcID + fragment_id_offset_)); + fragPtr->setTimestamp(static_cast(event.event())); + if (!packed.empty()) { + std::memcpy(fragPtr->dataBeginBytes(), packed.data(), packed.size()); } + + fragments->emplace_back(std::move(*fragPtr)); } if (diagLevel_ > 0) { diff --git a/DAQ/test/digi_to_frag.fcl b/DAQ/test/digi_to_frag.fcl new file mode 100644 index 0000000000..de72fa5605 --- /dev/null +++ b/DAQ/test/digi_to_frag.fcl @@ -0,0 +1,96 @@ +# Produce fragments from digis, and validate the results from digi -> fragment -> digi are identical + +#include "Offline/fcl/minimalMessageService.fcl" +#include "Offline/fcl/standardServices.fcl" + +process_name : DigiTest +source : { + module_type : RootInput + fileNames : @nil +} + +services : @local::Services.Reco +services.GeometryService.bFieldFile : "Offline/Mu2eG4/geom/bfgeom_reco_v01.txt" + +physics : { + + producers : { + CaloDigisToFragments : { + module_type : CaloDigisToFragments + diagLevel : 0 + caloDigiTag : "CaloDigiMaker" + } + CaloFragmentsToDigis : { + module_type : "CaloDigisFromDTCEvents" + dataType : 0 + diagLevel : 0 + useOfflineID : true + useDTCROCID : false + } + + StrawDigisToFragments : { + module_type : StrawDigisToFragments + diagLevel : 0 + fallbackToOfflineWhenMapMissing : true + forceOfflineAddressing : true + strawDigiTag : "makeSD" + strawDigiADCTag : "makeSD" + } + StrawFragmentsToDigis : { + module_type : "StrawDigisFromArtdaqFragments" + diagLevel : 0 + debugMode : 0 + debugBits : [ "bit0:0", "bit1:0" ] + saveWaveforms : true + missingDTCHeaders : false + keyOnMnid : false + allowOfflineFallbackWhenPanelMapMissing : true + forceOfflineAddressing : true + geography : [] + } + } + + analyzers : { + CompareCaloDigis : { + module_type : CaloDigiCollectionsComparator + referenceTag : "CaloDigiMaker" + candidateTag : "CaloFragmentsToDigis" + failOnMismatch : true + diagLevel : 0 + } + CompareStrawDigis : { + module_type : StrawDigiCollectionsComparator + referenceDigiTag : "makeSD" + candidateDigiTag : "StrawFragmentsToDigis" + compareWaveforms : true + normalizeWaveformsTo10Bit : true + normalizePmpTo10Bit : true + referenceWaveformTag : "makeSD" + candidateWaveformTag : "StrawFragmentsToDigis" + failOnMismatch : true + diagLevel : 1 + } + } + + TrigPath : [ CaloDigisToFragments, StrawDigisToFragments, CaloFragmentsToDigis, StrawFragmentsToDigis ] + CaloEndPath : [ CompareCaloDigis ] + TrkEndPath : [ CompareStrawDigis ] + OutputPath : [ out ] + trigger_paths : [ TrigPath ] + end_paths : [ CaloEndPath, TrkEndPath, OutputPath ] +} + +outputs : { + out : { + module_type : RootOutput + fileName : "digi_to_frag.art" + SelectEvents : [ ] + outputCommands : [ + "drop *_*_*_*", + "keep *_CaloDigisToFragments_*_*", + "keep *_StrawDigisToFragments_*_*", + "keep mu2e::ProtonBunchTime_*_*_*", + "keep mu2e::EventWindowMarker_*_*_*" + ] + } +}