26 #include "art/Framework/Core/ReplicatedProducer.h"
27 #include "art/Framework/Principal/Event.h"
28 #include "art/Framework/Services/Registry/ServiceHandle.h"
29 #include "art_root_io/TFileService.h"
30 #include "art/Framework/Core/ModuleMacros.h"
31 #include "art/Utilities/Globals.h"
32 #include "art/Utilities/make_tool.h"
33 #include "canvas/Persistency/Common/Ptr.h"
34 #include "messagefacility/MessageLogger/MessageLogger.h"
35 #include "cetlib/cpu_timer.h"
37 #include "tbb/parallel_for.h"
38 #include "tbb/blocked_range.h"
39 #include "tbb/task_arena.h"
40 #include "tbb/spin_mutex.h"
41 #include "tbb/concurrent_vector.h"
65 virtual void configure(fhicl::ParameterSet
const & pset);
66 virtual void produce(art::Event &
e, art::ProcessingFrame
const& frame);
67 virtual void beginJob(art::ProcessingFrame
const& frame);
68 virtual void endJob(art::ProcessingFrame
const& frame);
90 using ChannelArrayPair = std::pair<daq::INoiseFilter::ChannelPlaneVec,icarus_signal_processing::ArrayFloat>;
106 const art::InputTag&,
121 size_t const& coherentNoiseGrouping,
136 void operator()(
const tbb::blocked_range<size_t>& range)
const
138 for (
size_t idx = range.begin(); idx < range.end(); idx++)
157 void saveRawDigits(
const icarus_signal_processing::ArrayFloat&,
158 const icarus_signal_processing::VectorFloat&,
159 const icarus_signal_processing::VectorFloat&,
160 const icarus_signal_processing::VectorInt&,
212 art::ReplicatedProducer(pset, frame),
215 fGeometry = art::ServiceHandle<geo::Geometry const>{}.get();
216 fChannelMap = art::ServiceHandle<icarusDB::IICARUSChannelMap const>{}.get();
223 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
" ==> concurrency: " << max_concurrency << std::endl;
226 const fhicl::ParameterSet& decoderToolParams = pset.get<fhicl::ParameterSet>(
"DecoderTool");
228 fDecoderToolVec.resize(max_concurrency);
230 for(
auto& decoderTool : fDecoderToolVec)
233 decoderTool = art::make_tool<INoiseFilter>(decoderToolParams);
239 for(
const auto& instanceLabel : fOutInstanceLabelVec)
241 produces<std::vector<raw::RawDigit>>(instanceLabel);
242 produces<std::vector<recob::Wire>>(instanceLabel);
244 if (fOutputRawWaveform)
245 produces<std::vector<raw::RawDigit>>(instanceLabel + fOutputRawWavePath);
247 if (fOutputCorrection)
248 produces<std::vector<raw::RawDigit>>(instanceLabel + fOutputCoherentPath);
254 for(
size_t cryoIdx = 0; cryoIdx < 2; cryoIdx++)
256 for(
size_t logicalTPCIdx = 0; logicalTPCIdx < 4; logicalTPCIdx++)
258 for(
size_t planeIdx = 0; planeIdx < 3; planeIdx++)
266 fPlaneToROPPlaneMap[planeID] = ropID.
ROP;
267 fPlaneToWireOffsetMap[planeID] = channel;
268 planeToLastWireOffsetMap[planeID] = fGeometry->PlaneWireToChannel(planeID.
Plane, fGeometry->Nwires(planeID), planeID.
TPC, planeID.
Cryostat);
269 fROPToNumWiresMap[ropID.
ROP] = fGeometry->Nwires(planeID);
274 if (ropID.
ROP > fNumROPs) fNumROPs = ropID.
ROP;
277 if (ropID.
ROP > 1 && (logicalTPCIdx == 1 || logicalTPCIdx == 3))
281 fPlaneToWireOffsetMap[planeID] = fPlaneToWireOffsetMap[tempID];
282 fROPToNumWiresMap[ropID.
ROP] = planeToLastWireOffsetMap[planeID] - fPlaneToWireOffsetMap[planeID];
286 mf::LogDebug(
fLogCategory) <<
"Initializing C/T/P: " << planeID.
Cryostat <<
"/" << planeID.
TPC <<
"/" << planeID.
Plane <<
", base channel: " << fPlaneToWireOffsetMap[planeID] <<
", ROP: " << ropID <<
", index: " << ropID.
ROP;
298 for(
const auto& boardPair : readoutBoardToChannelMap)
301 unsigned int readoutBoardID = boardPair.first;
304 for(
unsigned int wireIdx = 0; wireIdx < boardPair.second.second.size(); wireIdx++)
306 unsigned int channelID = boardPair.second.second[wireIdx].first;
307 unsigned int planeID = boardPair.second.second[wireIdx].second;
315 mf::LogInfo(
"MCDecoderICARUSTPCwROI") <<
"MCDecoderICARUSTPCwROI configured\n";
332 fRawDigitLabelVec = pset.get<std::vector<art::InputTag>>(
"FragmentsLabelVec", {
"daq:PHYSCRATEDATA"});
333 fOutInstanceLabelVec = pset.get<std::vector<std::string>> (
"OutInstanceLabelVec", {
"PHYSCRATEDATA"});
363 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
"**** Processing raw data fragments ****" << std::endl;
366 int max_concurrency = tbb::this_task_arena::max_concurrency();
368 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
" ==> concurrency: " << max_concurrency << std::endl;
370 cet::cpu_timer theClockTotal;
372 theClockTotal.start();
377 size_t instanceIdx(0);
381 art::Handle<artdaq::Fragments> daq_handle;
382 event.getByLabel(rawDigitLabel, daq_handle);
395 for(
size_t ropIdx = 0; ropIdx <
fNumROPs; ropIdx++)
400 channelArrayPair.second.resize(
fROPToNumWiresMap[ropIdx],icarus_signal_processing::VectorFloat(4096));
402 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
"**> Initializing ropIdx: " << ropIdx <<
" channelPairVec to " << channelArrayPair.first.size() <<
" channels with " << channelArrayPair.second[0].size() <<
" ticks" << std::endl;
405 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
"****> Let's get ready to rumble!" << std::endl;
408 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(event);
418 RawDigitCollectionPtr rawDigitCollection = std::make_unique<std::vector<raw::RawDigit>>(std::move_iterator(concurrentRawDigits.begin()),
419 std::move_iterator(concurrentRawDigits.end()));
422 std::sort(rawDigitCollection->begin(),rawDigitCollection->end(),[](
const auto&
left,
const auto&
right){
return left.Channel() <
right.Channel();});
425 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
"****> Total size of map: " << planeIdxToImageMap.size() << std::endl;
426 for(
const auto& planeImagePair : planeIdxToImageMap)
428 mf::LogDebug(
"MCDecoderICARUSTPCwROI") <<
" - plane: " << planeImagePair.first <<
" has " << planeImagePair.second.size() <<
" wires" << std::endl;
435 WireCollectionPtr wireCollection = std::make_unique<std::vector<recob::Wire>>(std::move_iterator(concurrentROIs.begin()),
436 std::move_iterator(concurrentROIs.end()));
438 std::sort(wireCollection->begin(),wireCollection->end(),[](
const auto&
left,
const auto&
right){
return left.Channel() <
right.Channel();});
445 RawDigitCollectionPtr rawRawDigitCollection = std::make_unique<std::vector<raw::RawDigit>>(std::move_iterator(concurrentRawRawDigits.begin()),
446 std::move_iterator(concurrentRawRawDigits.end()));
449 std::sort(rawRawDigitCollection->begin(),rawRawDigitCollection->end(),[](
const auto&
left,
const auto&
right){
return left.Channel() <
right.Channel();});
458 RawDigitCollectionPtr coherentCollection = std::make_unique<std::vector<raw::RawDigit>>(std::move_iterator(coherentRawDigits.begin()),
459 std::move_iterator(coherentRawDigits.end()));
462 std::sort(coherentCollection->begin(),coherentCollection->end(),[](
const auto&
left,
const auto&
right){
return left.Channel() <
right.Channel();});
471 theClockTotal.stop();
473 double totalTime = theClockTotal.accumulated_real_time();
475 mf::LogInfo(
fLogCategory) <<
"==> MCDecoderICARUSTPCwROI total time: " << totalTime << std::endl;
481 const art::InputTag& inputLabel,
484 size_t const& coherentNoiseGrouping,
490 cet::cpu_timer theClockProcess;
492 theClockProcess.start();
495 art::Handle< std::vector<raw::RawDigit> > digitVecHandle;
496 event.getByLabel(inputLabel, digitVecHandle);
499 if (digitVecHandle.isValid() && digitVecHandle->size()>0 )
503 std::vector<const raw::RawDigit*> rawDigitVec;
506 for(
size_t idx = 0; idx < digitVecHandle->size(); idx++) rawDigitVec.emplace_back(&digitVecHandle->at(idx));
512 unsigned int dataSize = art::Ptr<raw::RawDigit>(digitVecHandle,0)->Samples();
515 using BoardToChannelArrayPairMap = std::map<unsigned int, ChannelArrayPair>;
517 BoardToChannelArrayPairMap boardToChannelArrayPairMap;
518 std::map<unsigned int, int> boardWireCountMap;
519 const unsigned int MAXCHANNELS(64);
522 for(
const auto& rawDigit : rawDigitVec)
530 std::cout <<
"********************************************************************************" << std::endl;
531 std::cout <<
"********* We did not find channel " << channel <<
"*****************************" << std::endl;
532 std::cout <<
"********************************************************************************" << std::endl;
536 unsigned int readoutBoardID = channelToBoardItr->second.first;
537 unsigned int wireIdx = channelToBoardItr->second.second.first;
538 unsigned int planeIdx = channelToBoardItr->second.second.second;
540 BoardToChannelArrayPairMap::iterator boardMapItr = boardToChannelArrayPairMap.find(readoutBoardID);
542 if (boardMapItr == boardToChannelArrayPairMap.end())
544 const auto [mapItr, success] =
545 boardToChannelArrayPairMap.insert({readoutBoardID,{
daq::INoiseFilter::ChannelPlaneVec(MAXCHANNELS,{0,3}),icarus_signal_processing::ArrayFloat(MAXCHANNELS,icarus_signal_processing::VectorFloat(dataSize))}});
549 std::cout <<
"+++> failed to insert data structure! " << std::endl;
553 boardMapItr = mapItr;
554 boardWireCountMap[readoutBoardID] = 0;
558 raw::Uncompress(rawDigit->ADCs(), rawDataVec, rawDigit->Compression());
561 icarus_signal_processing::VectorFloat& boardDataVec = boardMapItr->second.second[wireIdx];
567 if (++boardWireCountMap[readoutBoardID] == MAXCHANNELS)
569 processSingleImage(clockData, boardMapItr->second, coherentNoiseGrouping, concurrentRawDigits, concurrentRawRawDigits, coherentRawDigits, concurrentROIs);
571 boardToChannelArrayPairMap.erase(boardMapItr);
598 for(
auto& boardInfo : boardToChannelArrayPairMap)
600 if (boardWireCountMap[boardInfo.first] < 64)
602 processSingleImage(clockData, boardInfo.second, boardWireCountMap[boardInfo.first], concurrentRawDigits, concurrentRawRawDigits, coherentRawDigits, concurrentROIs);
608 theClockProcess.stop();
610 double totalTime = theClockProcess.accumulated_real_time();
612 mf::LogDebug(
fLogCategory) <<
"--> Exiting fragment processing for thread: " << tbb::this_task_arena::current_thread_index() <<
", time: " << totalTime << std::endl;
619 size_t coherentNoiseGrouping,
627 const icarus_signal_processing::ArrayFloat& dataArray = channelArrayPair.second;
629 unsigned int numChannels = dataArray.size();
630 unsigned int numTicks = dataArray[0].size();
636 decoderTool->
process_fragment(clockData, channelVec, dataArray, coherentNoiseGrouping);
642 for(
size_t chanIdx = 0; chanIdx < numChannels; chanIdx++)
645 if (channelVec[chanIdx].
second > 2)
continue;
651 const icarus_signal_processing::VectorFloat& waveform = decoderTool->
getPedCorWaveforms()[chanIdx];
654 std::transform(waveform.begin(),waveform.end(),wvfm.begin(),[](
const auto& val){
return short(std::round(val));});
656 ConcurrentRawDigitCol::iterator newRawObjItr = concurrentRawRawDigitCol.emplace_back(channel,wvfm.size(),wvfm);
663 const icarus_signal_processing::VectorFloat& corrections = decoderTool->
getCorrectedMedians()[chanIdx];
666 std::transform(corrections.begin(),corrections.end(),wvfm.begin(),[](
const auto& val){
return short(std::round(val));});
669 ConcurrentRawDigitCol::iterator newRawObjItr = coherentRawDigitCol.push_back(
raw::RawDigit(channel,wvfm.size(),wvfm));
671 newRawObjItr->SetPedestal(0.,0.);
675 const icarus_signal_processing::VectorFloat& denoised = decoderTool->
getWaveLessCoherent()[chanIdx];
678 std::transform(denoised.begin(),denoised.end(),wvfm.begin(),[](
const auto& val){
return short(std::round(val));});
680 ConcurrentRawDigitCol::iterator newObjItr = concurrentRawDigitCol.emplace_back(channel,wvfm.size(),wvfm);
685 const icarus_signal_processing::VectorBool& chanROIs = decoderTool->
getROIVals()[chanIdx];
691 while(roiIdx < chanROIs.size())
693 size_t roiStartIdx = roiIdx;
695 while(roiIdx < chanROIs.size() && chanROIs[roiIdx]) roiIdx++;
697 if (roiIdx > roiStartIdx)
699 std::vector<float> holder(roiIdx - roiStartIdx, 10.);
701 ROIVec.
add_range(roiStartIdx, std::move(holder));
714 const icarus_signal_processing::VectorFloat& pedestalVec,
715 const icarus_signal_processing::VectorFloat& rmsVec,
716 const icarus_signal_processing::VectorInt& channelVec,
719 if (!dataArray.empty())
721 cet::cpu_timer theClockSave;
723 theClockSave.start();
727 mf::LogDebug(
fLogCategory) <<
" --> saving rawdigits for " << dataArray.size() <<
" channels" << std::endl;
730 for(
size_t chanIdx = 0; chanIdx != dataArray.size(); chanIdx++)
733 if (channelVec[chanIdx] < 0)
continue;
735 const icarus_signal_processing::VectorFloat& dataVec = dataArray[chanIdx];
738 std::transform(dataVec.begin(),dataVec.end(),wvfm.begin(),[](
const auto& val){
return short(std::round(val));});
740 ConcurrentRawDigitCol::iterator newObjItr = rawDigitCol.emplace_back(channelVec[chanIdx],wvfm.size(),wvfm);
741 newObjItr->SetPedestal(pedestalVec[chanIdx],rmsVec[chanIdx]);
746 double totalTime = theClockSave.accumulated_real_time();
748 mf::LogDebug(
fLogCategory) <<
" --> done with save, time: " << totalTime << std::endl;
virtual const icarus_signal_processing::ArrayFloat & getWaveLessCoherent() const =0
Recover the waveforms less coherent noise.
std::pair< unsigned int, icarus_signal_processing::ArrayFloat > PlaneIdxToImagePair
ConcurrentWireCol & fConcurrentROIs
std::pair< unsigned int, ChannelVec > PlaneIdxToChannelPair
Collection of charge vs time digitized from a single readout channel.
std::vector< raw::RawDigit > RawDigitCollection
ChannelToBoardWirePlaneMap fChannelToBoardWirePlaneMap
const icarusDB::IICARUSChannelMap * fChannelMap
bool fOutputRawWaveform
Should we output pedestal corrected (not noise filtered)?
std::vector< raw::ChannelID_t > ChannelVec
std::map< unsigned int, unsigned int > ROPToNumWiresMap
virtual void produce(art::Event &e, art::ProcessingFrame const &frame)
size_t fCoherentNoiseGrouping
channels in common for coherent noise
const ChannelArrayPairVec & fChannelArrayPairVec
std::vector< ChannelArrayPair > ChannelArrayPairVec
Helper functions to create a wire.
This provides an art tool interface definition for tools which "decode" artdaq fragments into LArSoft...
virtual void endJob(art::ProcessingFrame const &frame)
End job method.
bool fOutputCorrection
Should we output the coherent noise correction vectors?
The data type to uniquely identify a Plane.
virtual const icarus_signal_processing::ArrayFloat & getPedCorWaveforms() const =0
Recover the pedestal corrected waveforms.
ChannelID_t Channel() const
DAQ channel this raw data was read from.
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
const std::string instance
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
CryostatID_t Cryostat
Index of cryostat.
Definition of basic raw digits.
std::size_t size(FixedBins< T, C > const &) noexcept
std::map< geo::PlaneID, unsigned int > PlaneToROPPlaneMap
void processSingleImage(const detinfo::DetectorClocksData &, const ChannelArrayPair &, size_t, ConcurrentRawDigitCol &, ConcurrentRawDigitCol &, ConcurrentRawDigitCol &, ConcurrentWireCol &) const
virtual const icarus_signal_processing::ArrayBool & getROIVals() const =0
Recover the ROI values.
Class managing the creation of a new recob::Wire object.
void operator()(const tbb::blocked_range< size_t > &range) const
ConcurrentRawDigitCol & fCoherentRawDigits
virtual void process_fragment(detinfo::DetectorClocksData const &, const daq::INoiseFilter::ChannelPlaneVec &, const icarus_signal_processing::ArrayFloat &, const size_t &)=0
std::pair< unsigned int, unsigned int > ChannelPlanePair
Given a set of recob hits, run DBscan to form 3D clusters.
std::map< unsigned int, icarus_signal_processing::ArrayFloat > PlaneIdxToImageMap
tbb::concurrent_vector< recob::Wire > ConcurrentWireCol
virtual ~MCDecoderICARUSTPCwROI()
Destructor.
virtual const icarus_signal_processing::VectorFloat & getTruncRMSVals() const =0
Recover the truncated RMS noise.
std::unique_ptr< RawDigitCollection > RawDigitCollectionPtr
int fNumEvent
Number of events seen.
ROPID_t ROP
Index of the readout plane within its TPC set.
ROPToNumWiresMap fROPToNumWiresMap
std::pair< daq::INoiseFilter::ChannelPlaneVec, icarus_signal_processing::ArrayFloat > ChannelArrayPair
Collect all the RawData header files together.
std::string fOutputCoherentPath
Path to assign to the output if asked for.
std::unique_ptr< WireCollection > WireCollectionPtr
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
virtual const icarus_signal_processing::ArrayFloat & getCorrectedMedians() const =0
Recover the correction median values.
std::vector< art::InputTag > fRawDigitLabelVec
The input artdaq fragment label vector (for more than one)
virtual void configure(fhicl::ParameterSet const &pset)
geo::GeometryCore const * fGeometry
pointer to Geometry service
PlaneID_t Plane
Index of the plane within its TPC.
Description of geometry of one entire detector.
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
IDecoderFilter interface class definiton.
Class identifying a set of planes sharing readout channels.
size_t fCoherentNoiseGrouping
PlaneToWireOffsetMap fPlaneToWireOffsetMap
virtual const icarus_signal_processing::VectorFloat & getPedestalVals() const =0
Recover the pedestals for each channel.
bool fDiagnosticOutput
Set this to get lots of messages.
std::string fOutputRawWavePath
Path to assign to the output if asked for.
virtual void beginJob(art::ProcessingFrame const &frame)
Begin job method.
multiThreadImageProcessing(MCDecoderICARUSTPCwROI const &parent, detinfo::DetectorClocksData const &clockData, ChannelArrayPairVec const &channelArrayPairVec, size_t const &coherentNoiseGrouping, ConcurrentRawDigitCol &concurrentRawDigits, ConcurrentRawDigitCol &concurrentRawRawDigits, ConcurrentRawDigitCol &coherentRawDigits, ConcurrentWireCol &concurrentROIs)
std::pair< unsigned int, unsigned int > WirePlanePair
Contains all timing reference information for the detector.
std::map< unsigned int, ChannelVec > PlaneIdxToChannelMap
std::map< unsigned int, SlotChannelVecPair > TPCReadoutBoardToChannelMap
std::map< geo::PlaneID, raw::ChannelID_t > PlaneToWireOffsetMap
ConcurrentRawDigitCol & fConcurrentRawRawDigits
void processSingleLabel(art::Event &, const art::InputTag &, detinfo::DetectorClocksData const &, ChannelArrayPairVec const &, size_t const &, ConcurrentRawDigitCol &, ConcurrentRawDigitCol &, ConcurrentRawDigitCol &, ConcurrentWireCol &) const
Declaration of basic channel signal object.
virtual const icarus_signal_processing::VectorFloat & getFullRMSVals() const =0
Recover the full RMS before coherent noise.
std::vector< std::unique_ptr< INoiseFilter > > fDecoderToolVec
Decoder tools.
const detinfo::DetectorClocksData & fClockData
PlaneToROPPlaneMap fPlaneToROPPlaneMap
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
void saveRawDigits(const icarus_signal_processing::ArrayFloat &, const icarus_signal_processing::VectorFloat &, const icarus_signal_processing::VectorFloat &, const icarus_signal_processing::VectorInt &, ConcurrentRawDigitCol &) const
const MCDecoderICARUSTPCwROI & fMCDecoderICARUSTPCwROI
std::map< unsigned int, BoardWirePlanePair > ChannelToBoardWirePlaneMap
std::vector< recob::Wire > WireCollection
MCDecoderICARUSTPCwROI(fhicl::ParameterSet const &pset, art::ProcessingFrame const &frame)
std::pair< unsigned int, WirePlanePair > BoardWirePlanePair
const std::string fLogCategory
Output category when logging messages.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
tbb::concurrent_vector< raw::RawDigit > ConcurrentRawDigitCol
ConcurrentRawDigitCol & fConcurrentRawDigits
std::vector< ChannelPlanePair > ChannelPlaneVec
std::vector< std::string > fOutInstanceLabelVec
The output instance labels to apply.