All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RecoWireROIICARUS_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // RecoWireROIICARUS class - variant of CalWire that deconvolves in
4 // Regions Of Interest
5 //
6 // baller@fnal.gov
7 //
8 //
9 ////////////////////////////////////////////////////////////////////////
10 
11 // C/C++ standard libraries
12 #include <string>
13 #include <vector>
14 #include <utility> // std::pair<>
15 #include <memory> // std::unique_ptr<>
16 #include <iomanip>
17 #include <fstream>
18 #include <random>
19 
20 // ROOT libraries
21 #include "TH1D.h"
22 #include "TProfile.h"
23 
24 // framework libraries
25 #include "fhiclcpp/ParameterSet.h"
26 #include "messagefacility/MessageLogger/MessageLogger.h"
27 #include "art/Framework/Core/ModuleMacros.h"
28 #include "art/Framework/Core/EDProducer.h"
29 #include "art/Framework/Principal/Event.h"
30 #include "art/Framework/Principal/Handle.h"
31 #include "art/Utilities/make_tool.h"
32 #include "canvas/Persistency/Common/Ptr.h"
33 #include "canvas/Persistency/Common/PtrVector.h"
34 #include "art/Framework/Services/Registry/ServiceHandle.h"
35 #include "art_root_io/TFileService.h"
36 #include "canvas/Utilities/Exception.h"
37 
38 // LArSoft libraries
39 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
41 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
43 #include "lardataobj/RawData/raw.h"
52 
56 #include "icarus_signal_processing/WaveformTools.h"
57 
58 ///creation of calibrated signals on wires
59 namespace caldata {
60 
61 class RecoWireROIICARUS : public art::EDProducer
62 {
63  public:
64  // create calibrated signals on wires. this class runs
65  // an fft to remove the electronics shaping.
66  explicit RecoWireROIICARUS(fhicl::ParameterSet const& pset);
67  virtual ~RecoWireROIICARUS();
68 
69  void produce(art::Event& evt);
70  void beginJob();
71  void endJob();
72  void reconfigure(fhicl::ParameterSet const& p);
73 
74  private:
75  // It seems there are pedestal shifts that need correcting
76  float fixTheFreakingWaveform(const std::vector<float>&, raw::ChannelID_t, std::vector<float>&);
77 
78  float getTruncatedRMS(const std::vector<float>&) const;
79 
80  std::string fDigitModuleLabel; ///< module that made digits
81  std::string fSpillName; ///< nominal spill is an empty string
82  ///< it is set by the DigitModuleLabel
83  ///< ex.: "daq:preSpill" for prespill data
84  unsigned short fNoiseSource; ///< Used to determine ROI threshold
85  int fSaveWireWF; ///< Save recob::wire object waveforms
86  size_t fEventCount; ///< count of event processed
87  int fMinAllowedChanStatus; ///< Don't consider channels with lower status
88 
89  float fTruncRMSThreshold; ///< Calculate RMS up to this threshold...
90  float fTruncRMSMinFraction; ///< or at least this fraction of time bins
91  bool fOutputHistograms; ///< Output histograms?
92 
93  std::vector<std::unique_ptr<icarus_tool::IROIFinder>> fROIFinderVec; ///< ROI finders per plane
94  std::unique_ptr<icarus_tool::IDeconvolution> fDeconvolution;
95 
96  icarus_signal_processing::WaveformTools<float> fWaveformTool;
97 
98  const geo::GeometryCore* fGeometry = lar::providerFrom<geo::Geometry>();
99 
100  // Define here a temporary set of histograms...
101  std::vector<TH1F*> fPedestalOffsetVec;
102  std::vector<TH1F*> fFullRMSVec;
103  std::vector<TH1F*> fTruncRMSVec;
104  std::vector<TH1F*> fNumTruncBinsVec;
105  std::vector<TProfile*> fPedByChanVec;
106  std::vector<TProfile*> fTruncRMSByChanVec;
107  std::vector<TH1F*> fNumROIsHistVec;
108  std::vector<TH1F*> fROILenHistVec;
109 
110 }; // class RecoWireROIICARUS
111 
112 DEFINE_ART_MODULE(RecoWireROIICARUS)
113 
114 //-------------------------------------------------
115 RecoWireROIICARUS::RecoWireROIICARUS(fhicl::ParameterSet const& pset) : EDProducer{pset}
116 {
117  this->reconfigure(pset);
118 
119  produces< std::vector<recob::Wire> >(fSpillName);
120  produces<art::Assns<raw::RawDigit, recob::Wire>>(fSpillName);
121 }
122 
123 //-------------------------------------------------
125 {
126 }
127 
128 //////////////////////////////////////////////////////
129 void RecoWireROIICARUS::reconfigure(fhicl::ParameterSet const& pset)
130 {
131  // Recover the vector of fhicl parameters for the ROI tools
132  const fhicl::ParameterSet& roiFinderTools = pset.get<fhicl::ParameterSet>("ROIFinderToolVec");
133 
134  fROIFinderVec.resize(roiFinderTools.get_pset_names().size());
135 
136  for(const std::string& roiFinderTool : roiFinderTools.get_pset_names())
137  {
138  const fhicl::ParameterSet& roiFinderToolParamSet = roiFinderTools.get<fhicl::ParameterSet>(roiFinderTool);
139  size_t planeIdx = roiFinderToolParamSet.get<size_t>("Plane");
140 
141  fROIFinderVec.at(planeIdx) = art::make_tool<icarus_tool::IROIFinder>(roiFinderToolParamSet);
142  }
143 
144  std::sort(fROIFinderVec.begin(),fROIFinderVec.end(),[](const auto& left,const auto& right){return left->plane() < right->plane();});
145 
146  fDeconvolution = art::make_tool<icarus_tool::IDeconvolution>(pset.get<fhicl::ParameterSet>("Deconvolution"));
147 
148  fDigitModuleLabel = pset.get< std::string > ("DigitModuleLabel", "daq");
149  fNoiseSource = pset.get< unsigned short >("NoiseSource", 3);
150  fSaveWireWF = pset.get< int > ("SaveWireWF" );
151  fMinAllowedChanStatus = pset.get< int > ("MinAllowedChannelStatus");
152  fTruncRMSThreshold = pset.get< float > ("TruncRMSThreshold", 6.);
153  fTruncRMSMinFraction = pset.get< float > ("TruncRMSMinFraction", 0.6);
154  fOutputHistograms = pset.get< bool > ("OutputHistograms", true);
155 
156  fSpillName.clear();
157 
158  size_t pos = fDigitModuleLabel.find(":");
159  if( pos!=std::string::npos )
160  {
161  fSpillName = fDigitModuleLabel.substr( pos+1 );
162  fDigitModuleLabel = fDigitModuleLabel.substr( 0, pos );
163  }
164 
165  if (fOutputHistograms)
166  {
167  // Access ART's TFileService, which will handle creating and writing
168  // histograms and n-tuples for us.
169  art::ServiceHandle<art::TFileService> tfs;
170 
171  fPedestalOffsetVec.resize(3);
172  fFullRMSVec.resize(3);
173  fTruncRMSVec.resize(3);
174  fNumTruncBinsVec.resize(3);
175  fPedByChanVec.resize(3);
176  fTruncRMSByChanVec.resize(3);
177  fNumROIsHistVec.resize(3);
178  fROILenHistVec.resize(3);
179 
180  for(size_t planeIdx = 0; planeIdx < 3; planeIdx++)
181  {
182  fPedestalOffsetVec[planeIdx] = tfs->make<TH1F>( Form("PedPlane_%02zu",planeIdx), ";Pedestal Offset (ADC);", 100, -5., 5.);
183  fFullRMSVec[planeIdx] = tfs->make<TH1F>( Form("RMSFPlane_%02zu",planeIdx), "Full RMS;RMS (ADC);", 100, 0., 10.);
184  fTruncRMSVec[planeIdx] = tfs->make<TH1F>( Form("RMSTPlane_%02zu",planeIdx), "Truncated RMS;RMS (ADC);", 100, 0., 10.);
185  fNumTruncBinsVec[planeIdx] = tfs->make<TH1F>( Form("NTruncBins_%02zu",planeIdx), ";# bins", 640, 0., 6400.);
186  fPedByChanVec[planeIdx] = tfs->make<TProfile>(Form("PedByWirePlane_%02zu",planeIdx), ";Wire#", fGeometry->Nwires(planeIdx), 0., fGeometry->Nwires(planeIdx), -5., 5.);
187  fTruncRMSByChanVec[planeIdx] = tfs->make<TProfile>(Form("TruncRMSByWirePlane_%02zu",planeIdx), ";Wire#", fGeometry->Nwires(planeIdx), 0., fGeometry->Nwires(planeIdx), 0., 10.);
188  fNumROIsHistVec[planeIdx] = tfs->make<TH1F>( Form("NROISplane_%02zu",planeIdx), ";# ROIs;", 100, 0, 100);
189  fROILenHistVec[planeIdx] = tfs->make<TH1F>( Form("ROISIZEplane_%02zu",planeIdx), ";ROI size;", 500, 0, 500);
190  }
191  }
192 
193  return;
194 }
195 
196 //-------------------------------------------------
198 {
199  fEventCount = 0;
200 } // beginJob
201 
202 //////////////////////////////////////////////////////
204 {
205 }
206 
207 //////////////////////////////////////////////////////
209 {
210  //get pedestal conditions
211  const lariov::DetPedestalProvider& pedestalRetrievalAlg = art::ServiceHandle<lariov::DetPedestalService>()->GetPedestalProvider();
212 
213  // make a collection of Wires
214  std::unique_ptr<std::vector<recob::Wire> > wirecol(new std::vector<recob::Wire>);
215  // ... and an association set
216  std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire> > WireDigitAssn(new art::Assns<raw::RawDigit,recob::Wire>);
217 
218  // Read in the digit List object(s).
219  art::Handle< std::vector<raw::RawDigit> > digitVecHandle;
220 
221  if(fSpillName.size()>0) evt.getByLabel(fDigitModuleLabel, fSpillName, digitVecHandle);
222  else evt.getByLabel(fDigitModuleLabel, digitVecHandle);
223 
224  if (!digitVecHandle->size())
225  {
226  evt.put(std::move(wirecol), fSpillName);
227  evt.put(std::move(WireDigitAssn), fSpillName);
228  return;
229  }
230 
231  raw::ChannelID_t channel = raw::InvalidChannelID; // channel number
232 
233  const lariov::ChannelStatusProvider& chanFilt = art::ServiceHandle<lariov::ChannelStatusService>()->GetProvider();
234 
235  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
236  double const samplingRate = sampling_rate(clockData);
237  // loop over all wires
238  wirecol->reserve(digitVecHandle->size());
239  for(size_t rdIter = 0; rdIter < digitVecHandle->size(); ++rdIter)
240  {
241  // vector that will be moved into the Wire object
243 
244  // get the reference to the current raw::RawDigit
245  art::Ptr<raw::RawDigit> digitVec(digitVecHandle, rdIter);
246  channel = digitVec->Channel();
247 
248  // The following test is meant to be temporary until the "correct" solution is implemented
249  if (!chanFilt.IsPresent(channel)) continue;
250 
251  // Testing an idea about rejecting channels
252  if (digitVec->GetPedestal() < 0.) continue;
253 
254  float pedestal = 0.;
255 
256  // skip bad channels
257  if( chanFilt.Status(channel) >= fMinAllowedChanStatus)
258  {
259  size_t dataSize = digitVec->Samples();
260 
261  // Recover the plane info
262  std::vector<geo::WireID> wids = fGeometry->ChannelToWire(channel);
263  const geo::PlaneID& planeID = wids[0].planeID();
264 
265  // vector holding uncompressed adc values
266  std::vector<short> rawadc(dataSize);
267 
268  // uncompress the data
269  raw::Uncompress(digitVec->ADCs(), rawadc, digitVec->Compression());
270 
271  // loop over all adc values and subtract the pedestal
272  // When we have a pedestal database, can provide the digit timestamp as the third argument of GetPedestalMean
273  pedestal = pedestalRetrievalAlg.PedMean(channel);
274 
275  // Get the pedestal subtracted data, centered in the deconvolution vector
276  std::vector<float> rawAdcLessPedVec(dataSize);
277 
278  std::transform(rawadc.begin(),rawadc.end(),rawAdcLessPedVec.begin(),std::bind(std::minus<short>(),std::placeholders::_1,pedestal));
279 
280  // It seems there are deviations from the pedestal when using wirecell for noise filtering
281  float raw_noise = fixTheFreakingWaveform(rawAdcLessPedVec, channel, rawAdcLessPedVec);
282 
283  // Recover a measure of the noise on the channel for use in the ROI finder
284  //float raw_noise = getTruncatedRMS(rawAdcLessPedVec);
285 
286  // Try smoothing the input waveform
287 // std::vector<float> rawAdcSmoothVec;
288 // fWaveformTool->medianSmooth(rawAdcLessPedVec,rawAdcSmoothVec);
289 
290  // vector of candidate ROI begin and end bins
292 
293  // Now find the candidate ROI's
294  fROIFinderVec.at(planeID.Plane)->FindROIs(rawAdcLessPedVec, channel, fEventCount, raw_noise, candRoiVec);
295 
296  // Do the deconvolution
297  fDeconvolution->Deconvolve(rawAdcLessPedVec, samplingRate, channel, candRoiVec, ROIVec);
298 
299  // Make some histograms?
300  if (fOutputHistograms)
301  {
302  // First up, determine what kind of wire we have
303  std::vector<geo::WireID> wids = fGeometry->ChannelToWire(channel);
304  const geo::PlaneID& planeID = wids[0].planeID();
305 
306  fNumROIsHistVec.at(planeID.Plane)->Fill(candRoiVec.size(), 1.);
307 
308  for(const auto& pair : candRoiVec)
309  fROILenHistVec.at(planeID.Plane)->Fill(pair.second-pair.first, 1.);
310  }
311  } // end if not a bad channel
312 
313  // create the new wire directly in wirecol
314  wirecol->push_back(recob::WireCreator(std::move(ROIVec),*digitVec).move());
315 
316  // add an association between the last object in wirecol
317  // (that we just inserted) and digitVec
318  if (!util::CreateAssn(*this, evt, *wirecol, digitVec, *WireDigitAssn, fSpillName))
319  {
320  throw art::Exception(art::errors::ProductRegistrationFailure)
321  << "Can't associate wire #" << (wirecol->size() - 1)
322  << " with raw digit #" << digitVec.key();
323  } // if failed to add association
324  // DumpWire(wirecol->back()); // for debugging
325  }
326 
327  if(wirecol->size() == 0)
328  mf::LogWarning("RecoWireROIICARUS") << "No wires made for this event.";
329 
330  //Make Histogram of recob::wire objects from Signal() vector
331  // get access to the TFile service
332  if ( fSaveWireWF ){
333  art::ServiceHandle<art::TFileService> tfs;
334  for (size_t wireN = 0; wireN < wirecol->size(); wireN++){
335  std::vector<float> sigTMP = wirecol->at(wireN).Signal();
336  TH1D* fWire = tfs->make<TH1D>(Form("Noise_Evt%04zu_N%04zu",fEventCount,wireN), ";Noise (ADC);",
337  sigTMP.size(),-0.5,sigTMP.size()-0.5);
338  for (size_t tick = 0; tick < sigTMP.size(); tick++){
339  fWire->SetBinContent(tick+1, sigTMP.at(tick) );
340  }
341  }
342  }
343 
344  evt.put(std::move(wirecol), fSpillName);
345  evt.put(std::move(WireDigitAssn), fSpillName);
346 
347  fEventCount++;
348 
349  return;
350 } // produce
351 
352 float RecoWireROIICARUS::getTruncatedRMS(const std::vector<float>& waveform) const
353 {
354  // do rms calculation - the old fashioned way and over all adc values
355  std::vector<float> locWaveform = waveform;
356 
357  // sort in ascending order so we can truncate the sume
358  std::sort(locWaveform.begin(), locWaveform.end(),[](const auto& left, const auto& right){return std::fabs(left) < std::fabs(right);});
359 
360  float threshold = fTruncRMSThreshold;
361 
362  std::vector<float>::iterator threshItr = std::find_if(locWaveform.begin(),locWaveform.end(),[threshold](const auto& val){return std::fabs(val) > threshold;});
363 
364  int minNumBins = std::max(int(fTruncRMSMinFraction * locWaveform.size()),int(std::distance(locWaveform.begin(),threshItr)));
365 
366  // Get the truncated sum
367  float truncRms = std::inner_product(locWaveform.begin(), locWaveform.begin() + minNumBins, locWaveform.begin(), 0.);
368 
369  truncRms = std::sqrt(std::max(0.,truncRms / double(minNumBins)));
370 
371  return truncRms;
372 }
373 
374 float RecoWireROIICARUS::fixTheFreakingWaveform(const std::vector<float>& waveform, raw::ChannelID_t channel, std::vector<float>& fixedWaveform)
375 {
376  // Get the truncated mean and rms
377  float fullRMS;
378  float truncRMS;
379  float truncMean;
380  float nSig(2.0); // make tight constraint
381  int nTrunc;
382  int range;
383 
384  fixedWaveform.resize(waveform.size());
385 
386  fWaveformTool.getPedestalCorrectedWaveform(waveform, fixedWaveform, nSig, truncMean, fullRMS, truncRMS, nTrunc, range);
387 
388  // Fill histograms
389  if (fOutputHistograms)
390  {
391  std::vector<geo::WireID> wids = fGeometry->ChannelToWire(channel);
392 
393  // Recover plane and wire in the plane
394  size_t plane = wids[0].Plane;
395  size_t wire = wids[0].Wire;
396 
397  fPedestalOffsetVec[plane]->Fill(truncMean,1.);
398  fFullRMSVec[plane]->Fill(fullRMS, 1.);
399  fTruncRMSVec[plane]->Fill(truncRMS, 1.);
400  fNumTruncBinsVec[plane]->Fill(nTrunc, 1.);
401  fPedByChanVec[plane]->Fill(wire, truncMean, 1.);
402  fTruncRMSByChanVec[plane]->Fill(wire, truncRMS, 1.);
403  }
404 
405  return truncRMS;
406 }
407 
408 } // end namespace caldata
std::vector< TH1F * > fPedestalOffsetVec
Utilities related to art service access.
bool fOutputHistograms
Output histograms?
static constexpr Sample_t transform(Sample_t sample)
This provides an interface for tools which are tasked with running the deconvolution algorithm...
icarus_signal_processing::WaveformTools< float > fWaveformTool
const geo::GeometryCore * fGeometry
Helper functions to create a wire.
walls no right
Definition: selectors.fcl:105
pdgs p
Definition: selectors.fcl:22
std::vector< std::unique_ptr< icarus_tool::IROIFinder > > fROIFinderVec
ROI finders per plane.
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< TProfile * > fPedByChanVec
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
Definition of basic raw digits.
for pfile in ack l reconfigure(.*) override"` do echo "checking $
float fixTheFreakingWaveform(const std::vector< float > &, raw::ChannelID_t, std::vector< float > &)
Class managing the creation of a new recob::Wire object.
Definition: WireCreator.h:53
This provides an interface for tools which are tasked with finding the baselines in input waveforms...
std::vector< TH1F * > fNumTruncBinsVec
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 fEventCount
count of event processed
unsigned short fNoiseSource
Used to determine ROI threshold.
void reconfigure(fhicl::ParameterSet const &p)
virtual bool IsPresent(raw::ChannelID_t channel) const =0
Returns whether the specified channel is physical and connected to wire.
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
Definition: RawTypes.h:32
float getTruncatedRMS(const std::vector< float > &) const
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Collect all the RawData header files together.
float fTruncRMSMinFraction
or at least this fraction of time bins
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
virtual Status_t Status(raw::ChannelID_t channel) const
Returns a status integer with arbitrary meaning.
float fTruncRMSThreshold
Calculate RMS up to this threshold...
walls no left
Definition: selectors.fcl:105
Class providing information about the quality of channels.
int fSaveWireWF
Save recob::wire object waveforms.
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Description of geometry of one entire detector.
virtual float PedMean(raw::ChannelID_t ch) const =0
Retrieve pedestal information.
std::unique_ptr< icarus_tool::IDeconvolution > fDeconvolution
bool CreateAssn(art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t index=UINT_MAX)
Creates a single one-to-one association.
Interface for experiment-specific channel quality info provider.
RecoWireROIICARUS(fhicl::ParameterSet const &pset)
std::string fDigitModuleLabel
module that made digits
Declaration of basic channel signal object.
std::vector< TProfile * > fTruncRMSByChanVec
art::ServiceHandle< art::TFileService > tfs
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
Interface for experiment-specific service for channel quality info.
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:776
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
process_name can override from command line with o or output caldata
Definition: pid.fcl:40
art framework interface to geometry description
int fMinAllowedChanStatus
Don&#39;t consider channels with lower status.