19 #include "fhiclcpp/ParameterSet.h"
20 #include "messagefacility/MessageLogger/MessageLogger.h"
21 #include "art/Framework/Core/ModuleMacros.h"
22 #include "art/Framework/Core/EDProducer.h"
23 #include "art/Framework/Principal/Event.h"
24 #include "art/Framework/Principal/Handle.h"
25 #include "art/Utilities/make_tool.h"
26 #include "canvas/Persistency/Common/Ptr.h"
27 #include "canvas/Persistency/Common/PtrVector.h"
28 #include "art/Framework/Services/Registry/ServiceHandle.h"
29 #include "art_root_io/TFileService.h"
30 #include "canvas/Utilities/Exception.h"
32 #include "cetlib_except/coded_exception.h"
50 #include "icarus_signal_processing/WaveformTools.h"
51 #include "icarus_signal_processing/Denoising.h"
55 #include "tbb/parallel_for.h"
56 #include "tbb/blocked_range.h"
57 #include "tbb/task_arena.h"
58 #include "tbb/spin_mutex.h"
59 #include "tbb/concurrent_hash_map.h"
67 std::size_t
size()
const {
return wires.size(); }
68 void resize(std::size_t nWires)
69 { wires.clear(); wires.resize(nWires,
nullptr); }
70 void addWire(std::size_t iWire,
recob::Wire const& wire)
71 { wires.at(iWire) = &wire; }
72 icarus_signal_processing::ArrayFloat operator() ()
const
74 icarus_signal_processing::ArrayFloat data;
75 data.resize(wires.size());
78 if (wire) data[iWire] = wire->
Signal();
79 else data[iWire] = std::vector<float>(4096,0.);
83 const recob::Wire* getWirePtr(
size_t idx)
const {
return wires[idx];}
85 std::vector<recob::Wire const*> wires;
101 explicit ROIFinder(fhicl::ParameterSet
const& pset);
120 std::vector<recob::Wire>& wireColVec,
121 std::vector<recob::Wire>& morphedVec,
122 std::vector<recob::ChannelROI>& channelROIVec)
131 void operator()(
const tbb::blocked_range<size_t>& range)
const
133 for (
size_t idx = range.begin(); idx < range.end(); idx++)
151 std::vector<recob::Wire>&,
152 std::vector<recob::Wire>&,
153 std::vector<recob::ChannelROI>&)
const;
156 float getMedian(
const icarus_signal_processing::VectorFloat,
const unsigned int)
const;
168 std::map<size_t,std::unique_ptr<icarus_tool::IROILocator>>
fROIToolMap;
181 for(
const auto& wireLabel : fOutInstanceLabelVec)
183 produces< std::vector<recob::Wire>>(wireLabel);
184 produces< std::vector<recob::ChannelROI>>(wireLabel);
186 if (fOutputMorphed) produces<std::vector<recob::Wire>>(wireLabel+
"M");
199 fWireModuleLabelVec = pset.get<std::vector<art::InputTag>>(
"WireModuleLabelVec", std::vector<art::InputTag>()={
"decon1droi"});
200 fOutInstanceLabelVec = pset.get<std::vector<std::string>> (
"OutInstanceLabelVec", {
"PHYSCRATEDATA"});
210 art::ServiceHandle<art::TFileService>
tfs;
213 const fhicl::ParameterSet& roiFinderTools = pset.get<fhicl::ParameterSet>(
"ROIFinderToolVec");
217 for(
const std::string& roiFinderTool : roiFinderTools.get_pset_names())
219 const fhicl::ParameterSet& roiFinderToolParamSet = roiFinderTools.get<fhicl::ParameterSet>(roiFinderTool);
220 size_t planeIdx = roiFinderToolParamSet.get<
size_t>(
"Plane");
222 fROIToolMap[planeIdx] = art::make_tool<icarus_tool::IROILocator> (roiFinderToolParamSet);
224 if (fOutputHistograms)
228 art::TFileDirectory
dir = tfs->mkdir(dirName);
230 fROIToolMap[planeIdx]->initializeHistograms(dir);
257 std::unique_ptr<std::vector<recob::Wire>> wireCol(
new std::vector<recob::Wire>);
259 std::unique_ptr<std::vector<recob::Wire>> morphedCol(
new std::vector<recob::Wire>);
262 std::unique_ptr<std::vector<recob::ChannelROI>> channelROICol(
new std::vector<recob::ChannelROI>);
264 mf::LogInfo(
"ROIFinder") <<
"ROIFinder, looking for decon1droi data at " << wireLabel << std::endl;
268 art::Handle< std::vector<recob::Wire>> wireVecHandle;
270 evt.getByLabel(wireLabel, wireVecHandle);
272 mf::LogInfo(
"ROIFinder") <<
"--> Recovered wire data, size: " << wireVecHandle->size() << std::endl;
274 if (!wireVecHandle->size())
276 evt.put(std::move(wireCol), wireLabel.instance());
285 size_t numChannels(0);
287 for(
const auto& wire : *wireVecHandle)
293 if (wireIDVec.empty())
continue;
295 for(
const auto& wireID : wireIDVec)
299 PlaneIDToDataPairMap::iterator mapItr = planeIDToDataPairMap.find(planeID);
302 if (mapItr == planeIDToDataPairMap.end())
306 std::pair<PlaneIDToDataPairMap::iterator,bool> mapInsert = planeIDToDataPairMap.insert({planeID,
PlaneIDToDataPair()});
308 if (!mapInsert.second)
std::cout <<
"Failed to insert, is this possible?" << std::endl;
310 mapItr = mapInsert.first;
312 mapItr->second.first.resize(nWires);
313 mapItr->second.second.resize(nWires);
315 planeIDVec.emplace_back(planeID);
319 mapItr->second.first[wireID.Wire] = channel;
320 mapItr->second.second.addWire(wireID.Wire, wire);
326 std::vector<recob::Wire> tempWireVec(numChannels/4);
329 for(
auto& mapInfo : planeIDToDataPairMap)
331 const std::vector<raw::ChannelID_t>& channelVec = mapInfo.second.first;
332 const icarus_signal_processing::ArrayFloat& dataArray = mapInfo.second.second();
334 for(
size_t idx = 0; idx < channelVec.size(); idx++)
336 if (dataArray[idx].
size() < 100)
338 mf::LogInfo(
"ROIFinder") <<
" **> Found truncated wire, size: " << dataArray[idx].size() <<
", channel: " << channelVec[idx] << std::endl;
340 std::vector<float> zeroVec(4096,0.);
348 mapInfo.second.first[idx] = 100000 + idx;
352 mapInfo.second.second.addWire(idx,tempWireVec.back());
358 wireCol->reserve(wireVecHandle->size());
363 tbb::parallel_for(tbb::blocked_range<size_t>(0, planeIDVec.size()), deconvolutionProcessing);
366 if(wireCol->size() == 0) mf::LogWarning(
"ROIFinder") <<
"No wires made for this event.";
368 evt.put(std::move(wireCol), fOutInstanceLabelVec[labelIdx]);
369 evt.put(std::move(channelROICol), fOutInstanceLabelVec[labelIdx]);
371 if (
fOutputMorphed) evt.put(std::move(morphedCol), fOutInstanceLabelVec[labelIdx]+
"M");
383 std::vector<recob::Wire>& wireColVec,
384 std::vector<recob::Wire>& morphedVec,
385 std::vector<recob::ChannelROI>& channelROIVec)
const
391 PlaneIDToDataPairMap::const_iterator mapItr = planeIDToDataPairMap.find(planeID);
393 if (mapItr == planeIDToDataPairMap.end())
395 std::cout <<
"We know this cannot happen" << std::endl;
401 const icarus_signal_processing::ArrayFloat& dataArray = planeIDToDataPair.second();
402 const std::vector<raw::ChannelID_t>& channelVec = planeIDToDataPair.first;
405 icarus_signal_processing::ArrayFloat outputArray(dataArray.size(),icarus_signal_processing::VectorFloat(dataArray[0].
size(),0.));
406 icarus_signal_processing::ArrayBool selectedVals(dataArray.size(),icarus_signal_processing::VectorBool(dataArray[0].
size(),
false));
408 fROIToolMap.at(planeID.
Plane)->FindROIs(event, dataArray, channelVec, mapItr->first, outputArray, selectedVals);
415 for(
size_t waveIdx = 0; waveIdx < outputArray.size(); waveIdx++)
418 if (channelVec[idx] >= 100000)
continue;
425 ROIVec.
add_range(0, std::move(outputArray[waveIdx]));
438 using CandidateROI = std::pair<size_t, size_t>;
439 using CandidateROIVec = std::vector<CandidateROI>;
443 for(
size_t waveIdx = 0; waveIdx < selectedVals.size(); waveIdx++)
446 if (channelVec[waveIdx] >= 100000)
448 std::cout <<
"==> found an unexpected channel number: " << channelVec[waveIdx] << std::endl;
453 CandidateROIVec candidateROIVec;
456 const icarus_signal_processing::VectorBool& selVals = selectedVals[waveIdx];
460 while(idx < selVals.size())
464 Size_t startTick = idx >= leadTrail ? idx - leadTrail : 0;
466 while(idx < selVals.size() && selVals[idx]) idx++;
468 size_t stopTick = idx < selVals.size() - leadTrail ? idx + leadTrail : selVals.size();
470 candidateROIVec.emplace_back(startTick, stopTick);
477 if(candidateROIVec.size() > 1)
480 CandidateROIVec tempRoiVec;
483 size_t startRoi = candidateROIVec.front().first;
484 size_t stopRoi = candidateROIVec.front().second;
486 for(
auto& roi : candidateROIVec)
489 if (roi.first <= stopRoi)
492 startRoi = std::min(startRoi,roi.first);
493 stopRoi = std::max(stopRoi,roi.second);
497 tempRoiVec.emplace_back(startRoi,stopRoi);
499 startRoi = roi.first;
500 stopRoi = roi.second;
505 tempRoiVec.emplace_back(startRoi,stopRoi);
507 candidateROIVec = tempRoiVec;
511 if (!candidateROIVec.empty())
518 if (planeID.
Plane > 0)
524 if (wireIDVec.size() > 1)
526 std::vector<recob::Wire>::iterator wireItr = std::find_if(wireColVec.begin(),wireColVec.end(),[channel](
const auto& wire){
return wire.
Channel() == channel;});
528 if (wireItr != wireColVec.end())
530 ROIVec = wireItr->SignalROI();
533 wireColVec.erase(wireItr);
536 std::vector<recob::ChannelROI>::iterator channelItr = std::find_if(channelROIVec.begin(),channelROIVec.end(),[channel](
const auto& channelROI){
return channelROI.Channel() == channel;});
538 if (channelItr != channelROIVec.end())
540 intROIVec = channelItr->SignalROI();
543 channelROIVec.erase(channelItr);
548 if (ROIVec.
size() != intROIVec.
size())
549 throw art::Exception(art::errors::LogicError) <<
"===> ROIVec mismatch to intROIVec, ROIVec size: " << ROIVec.
size() <<
", intROIVec size: " << intROIVec.
size() <<
"\n";
551 const icarus_signal_processing::VectorFloat& waveform = dataArray[waveIdx];
554 for(
const auto& candROI : candidateROIVec)
557 size_t roiLen = candROI.second - candROI.first;
558 size_t firstBin = candROI.first;
560 icarus_signal_processing::VectorFloat holder(roiLen);
562 std::copy(waveform.begin()+candROI.first, waveform.begin()+candROI.second, holder.begin());
570 size_t nBins = holder.size()/3;
571 icarus_signal_processing::VectorFloat::iterator firstItr = std::min_element(holder.begin(),holder.begin()+nBins);
572 icarus_signal_processing::VectorFloat::iterator lastItr = std::min_element(holder.end()-nBins,holder.end());
575 float dADC = (*lastItr - *firstItr) /
float(newSize);
578 for(
size_t binIdx = 0; binIdx < newSize; binIdx++)
580 holder[binIdx] = *(firstItr + binIdx) - offset;
586 holder.resize(newSize);
590 icarus_signal_processing::VectorShort intHolder(holder.size());
592 for(
size_t binIdx = 0; binIdx < holder.size(); binIdx++) intHolder[binIdx] = std::round(holder[binIdx]);
595 ROIVec.
add_range(firstBin, std::move(holder));
596 intROIVec.
add_range(firstBin, std::move(intHolder));
612 if (channelROIVec.size() != wireColVec.size())
613 throw art::Exception(art::errors::LogicError) <<
"===> ROI output mismatch, channelROIVec, size: " << channelROIVec.size() <<
", wireColVec, size: " << wireColVec.size() <<
"\n";
632 const auto m1 = vals.begin() + nVals / 2 - 1;
633 const auto m2 = vals.begin() + nVals / 2;
634 std::nth_element(vals.begin(), m1, vals.begin() + nVals);
636 std::nth_element(vals.begin(), m2, vals.begin() + nVals);
638 median = (e1 + e2) / 2.0;
642 const auto m = vals.begin() + nVals / 2;
643 std::nth_element(vals.begin(),
m, vals.begin() + nVals);
multiThreadDeconvolutionProcessing(ROIFinder const &parent, art::Event &event, const PlaneIDVec &planeIDVec, const PlaneIDToDataPairMap &planeIDToDataPairMap, std::vector< recob::Wire > &wireColVec, std::vector< recob::Wire > &morphedVec, std::vector< recob::ChannelROI > &channelROIVec)
std::vector< recob::Wire > & fMorphedVec
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
Utilities related to art service access.
const PlaneIDToDataPairMap & fPlaneIDToDataPairMap
std::vector< geo::PlaneID > PlaneIDVec
size_type size() const
Returns the size of the vector.
Definition of util::enumerate().
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
Helper functions to create a wire.
The data type to uniquely identify a Plane.
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
Definition of basic raw digits.
std::size_t size(FixedBins< T, C > const &) noexcept
Wire && move()
Prepares the constructed wire to be moved away.
Class managing the creation of a new recob::Wire object.
std::map< size_t, std::unique_ptr< icarus_tool::IROILocator > > fROIToolMap
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
unsigned int Nwires(unsigned int p, unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wires in the specified plane.
size_t fMinSizeForCorrection
Minimum ROI length to do correction.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
std::vector< std::string > fOutInstanceLabelVec
The output instance labels to apply.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
const geo::GeometryCore * fGeometry
std::vector< recob::ChannelROI > & fChannelROIVec
raw::ChannelID_t Channel() const
Returns the ID of the channel (or InvalidChannelID)
bool fCorrectROIBaseline
Correct the ROI baseline.
std::map< geo::PlaneID, PlaneIDToDataPair > PlaneIDToDataPairMap
bool fOutputHistograms
Output tuples/histograms?
void produce(art::Event &evt)
float getMedian(const icarus_signal_processing::VectorFloat, const unsigned int) const
PlaneID_t Plane
Index of the plane within its TPC.
Description of geometry of one entire detector.
const PlaneIDVec & fPlaneIDVec
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
size_t fMaxSizeForCorrection
Maximum ROI length for baseline correction.
std::vector< float > Signal() const
Return a zero-padded full length vector filled with RoI signal.
bool fOutputMorphed
Output the morphed waveforms.
Helper functions to create a wire.
tbb::spin_mutex roifinderSpinMutex
std::string to_string(WindowPattern const &pattern)
bool empty() const
Returns whether the vector is empty.
Class managing the creation of a new recob::Wire object.
Declaration of basic channel signal object for ICARUS.
This provides an interface for tools which are tasked with finding ROI's in input waveforms...
Class holding the regions of interest of signal from a channel.
void operator()(const tbb::blocked_range< size_t > &range) const
Declaration of basic channel signal object.
void processPlane(size_t, art::Event &, const PlaneIDVec &, const PlaneIDToDataPairMap &, std::vector< recob::Wire > &, std::vector< recob::Wire > &, std::vector< recob::ChannelROI > &) const
art::ServiceHandle< art::TFileService > tfs
unsigned int ChannelID_t
Type representing the ID of a readout channel.
size_t fEventCount
count of event processed
std::vector< recob::Wire > & fWireColVec
void reconfigure(fhicl::ParameterSet const &p)
process_name can override from command line with o or output caldata
ROIFinder(fhicl::ParameterSet const &pset)
const ROIFinder & fROIFinder
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::pair< std::vector< raw::ChannelID_t >, PlaneWireData > PlaneIDToDataPair
bool fDiagnosticOutput
secret diagnostics flag
std::vector< art::InputTag > fWireModuleLabelVec
vector of modules that made digits