All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CalWireSBND_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // CalWireSBND class
4 //
5 // brebel@fnal.gov
6 //
7 // 11-3-09 Pulled all FFT code out and put into Utilitiess/LArFFT
8 // copied over to 1053 - andrzej.szelc@yale.edu
9 // copied over and modified to SBND
10 ////////////////////////////////////////////////////////////////////////
11 
12 #include <string>
13 #include <vector>
14 #include <stdint.h>
15 
16 #include "art/Framework/Core/ModuleMacros.h"
17 #include "art/Framework/Core/EDProducer.h"
18 #include "art/Framework/Principal/Event.h"
19 #include "art/Framework/Principal/Handle.h"
20 #include "canvas/Persistency/Common/Ptr.h"
21 #include "canvas/Persistency/Common/PtrVector.h"
22 #include "art/Framework/Services/Registry/ServiceHandle.h"
23 #include "art_root_io/TFileService.h"
24 #include "art_root_io/TFileDirectory.h"
25 #include "fhiclcpp/ParameterSet.h"
26 #include "messagefacility/MessageLogger/MessageLogger.h"
27 #include "cetlib_except/exception.h"
28 #include "cetlib/search_path.h"
29 #include "art/Utilities/make_tool.h"
31 
35 //#include "Filters/ChannelFilter.h"
36 
38 #include "lardataobj/RawData/raw.h"
42 #include "lardata/Utilities/AssociationUtil.h" //--Hec
44 
45 #include "TComplex.h"
46 #include "TFile.h"
47 #include "TH1F.h"
48 
49 ///creation of calibrated signals on wires
50 namespace caldata {
51 
52  class CalWireSBND : public art::EDProducer {
53 
54  public:
55 
56  //typedef lar::sparse_vector<float> RegionsOfInterest_t;
57 
58  // create calibrated signals on wires. this class runs
59  // an fft to remove the electronics shaping.
60  explicit CalWireSBND(fhicl::ParameterSet const& pset);
61  virtual ~CalWireSBND();
62 
63  void produce(art::Event& evt);
64  void beginJob();
65  void endJob();
66  void reconfigure(fhicl::ParameterSet const& p);
67 
68  std::unique_ptr<sbnd_tool::IROIFinder> fROITool;
69 
70  // Define the waveform container
71  using Waveform = std::vector<float>;
72 
73  // Define the ROI and its container
74  using CandidateROI = std::pair<size_t, size_t>;
75  using CandidateROIVec = std::vector<CandidateROI>;
76 
77  private:
78 
79  bool fDoBaselineSub; ///< subtract baseline to restore DC component post-deconvolution
80  bool fDoAdvBaselineSub; ///< use interpolation-based baseline subtraction
81  int fBaseSampleBins; ///< bin grouping size in "interpolate" method
82  float fBaseVarCut; ///< baseline variance cut used in "interpolate" method
83 
84  std::string fDigitModuleLabel; ///< module that made digits
85 
86  std::string fSpillName; ///< nominal spill is an empty string
87  ///< it is set by the DigitModuleLabel
88  ///< ex.: "daq:preSpill" for prespill data
89 
90  void SubtractBaseline(std::vector<float>& holder);
91  void SubtractBaselineAdv(std::vector<float>& holder);
92 
93 
94  protected:
95 
96  }; // class CalWireSBND
97 
98  DEFINE_ART_MODULE(CalWireSBND)
99 
100  //-------------------------------------------------
101  CalWireSBND::CalWireSBND(fhicl::ParameterSet const& pset)
102  : EDProducer(pset)
103  {
104  fSpillName="";
105  this->reconfigure(pset);
106 
107  fROITool = art::make_tool<sbnd_tool::IROIFinder>(pset.get<fhicl::ParameterSet>("ROITool"));
108 
109  //--Hec if(fSpillName.size()<1) produces< std::vector<recob::Wire> >();
110  //--Hec else produces< std::vector<recob::Wire> >(fSpillName);
111  produces< std::vector<recob::Wire> >(fSpillName);
112  produces<art::Assns<raw::RawDigit, recob::Wire>>(fSpillName);
113 
114  }
115  //-------------------------------------------------
117  {
118  }
119 
120  //////////////////////////////////////////////////////
121  void CalWireSBND::reconfigure(fhicl::ParameterSet const& p)
122  {
123  fDigitModuleLabel = p.get< std::string >("DigitModuleLabel", "daq");
124  fDoBaselineSub = p.get< bool > ("DoBaselineSub");
125  fDoAdvBaselineSub = p.get< bool > ("DoAdvBaselineSub");
126  fBaseSampleBins = p.get< int > ("BaseSampleBins");
127  fBaseVarCut = p.get< int > ("BaseVarCut");
128 
129  fSpillName="";
130 
131  size_t pos = fDigitModuleLabel.find(":");
132  if( pos!=std::string::npos ) {
133  fSpillName = fDigitModuleLabel.substr( pos+1 );
134  fDigitModuleLabel = fDigitModuleLabel.substr( 0, pos );
135  }
136 
137  }
138 
139  //-------------------------------------------------
141  {
142  }
143 
144  //////////////////////////////////////////////////////
146  {
147  }
148 
149  //////////////////////////////////////////////////////
150  void CalWireSBND::produce(art::Event& evt)
151  {
152  // get the geometry
153  art::ServiceHandle<geo::Geometry> geom;
154 
155  // get the FFT service to have access to the FFT size
156  art::ServiceHandle<util::LArFFT> fFFT;
157  int transformSize = fFFT->FFTSize();
158 
159  // Get signal shaping service.
160  art::ServiceHandle<util::SignalShapingServiceSBND> sss;
161  double DeconNorm = sss->GetDeconNorm();
162 
163  // make a collection of Wires
164  std::unique_ptr<std::vector<recob::Wire> > wirecol(new std::vector<recob::Wire>);
165 
166  // ... and an association set --Hec
167  std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire> > WireDigitAssn
168  (new art::Assns<raw::RawDigit,recob::Wire>);
169 
170  // Read in the digit List object(s).
171  art::Handle< std::vector<raw::RawDigit> > digitVecHandle;
172  if(fSpillName.size()>0) evt.getByLabel(fDigitModuleLabel, fSpillName, digitVecHandle);
173  else evt.getByLabel(fDigitModuleLabel, digitVecHandle);
174 
175  if (!digitVecHandle->size()) return;
176  mf::LogInfo("CalWireSBND") << "CalWireSBND:: digitVecHandle size is " << digitVecHandle->size();
177 
178  // Use the handle to get a particular (0th) element of collection.
179  art::Ptr<raw::RawDigit> digitVec0(digitVecHandle, 0);
180 
181  unsigned int dataSize = digitVec0->Samples(); //size of raw data vectors
182 
183 
184  if( (unsigned int)transformSize < dataSize){
185  mf::LogWarning("CalWireSBND")<<"FFT size (" << transformSize << ") "
186  << "is smaller than the data size (" << dataSize << ") "
187  << "\nResizing the FFT now...";
188  fFFT->ReinitializeFFT(dataSize,fFFT->FFTOptions(),fFFT->FFTFitBins());
189  transformSize = fFFT->FFTSize();
190  mf::LogWarning("CalWireSBND")<<"FFT size is now (" << transformSize << ") "
191  << "and should be larger than the data size (" << dataSize << ")";
192  }
193 
194  mf::LogInfo("CalWireSBND") << "Data size is " << dataSize << " and transform size is " << transformSize;
195 
196  if(fBaseSampleBins > 0 && dataSize % fBaseSampleBins != 0) {
197  mf::LogError("CalWireSBND")<<"Set BaseSampleBins modulo dataSize= "<<dataSize;
198  }
199 
200  uint32_t channel(0); // channel number
201  unsigned int bin(0); // time bin loop variable
202 
203 /// filter::ChannelFilter *chanFilt = new filter::ChannelFilter();
204 
205  std::vector<float> holder; // holds signal data
206  std::vector<short> rawadc(transformSize); // vector holding uncompressed adc values
207  std::vector<TComplex> freqHolder(transformSize+1); // temporary frequency data
208 
209  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
210 
211  // loop over all wires
212  wirecol->reserve(digitVecHandle->size());
213  for(size_t rdIter = 0; rdIter < digitVecHandle->size(); ++rdIter){ // ++ move
214  holder.clear();
215 
216  // get the reference to the current raw::RawDigit
217  art::Ptr<raw::RawDigit> digitVec(digitVecHandle, rdIter);
218  channel = digitVec->Channel();
219 
220  // skip bad channels
221  // if(!chanFilt->BadChannel(channel)) {
222  if(true) {
223 
224  // resize and pad with zeros
225  holder.resize(transformSize, 0.);
226 
227  // uncompress the data
228  raw::Uncompress(digitVec->ADCs(), rawadc, digitVec->Compression());
229 
230  // loop over all adc values and subtract the pedestal
231  float pdstl = digitVec->GetPedestal();
232 
233  for(bin = 0; bin < dataSize; ++bin)
234  holder[bin]=(rawadc[bin]-pdstl);
235 
236  //fill the remaining bin with data
237  for(bin = dataSize; bin < holder.size(); bin++){
238  // philosophy change - don't repeat data but instead fill extra space with zeros.
239  // not sure that one is better than the other.
240  // holder[bin] = (rawadc[bin-dataSize]-pdstl);
241  holder[bin] = 0.0;
242  }
243 
244  // Do deconvolution.
245  sss->Deconvolute(clockData, channel, holder);
246  for(bin = 0; bin < holder.size(); ++bin) holder[bin]=holder[bin]/DeconNorm;
247  } // end if not a bad channel
248 
249  holder.resize(dataSize,1e-5);
250 
251  // restore DC component through baseline subtraction
252  if( fDoBaselineSub ) SubtractBaseline(holder);
253  // more advanced, interpolation-based subtraction alg
254  // that uses the BaseSampleBins and BaseVarCut params
256 
257  // Make a single ROI that spans the entire data size
258  //RegionsOfInterest_t sparse_holder;
259  //sparse_holder.add_range(0,holder.begin(),holder.end());
260  CandidateROIVec candROIVec;
261  fROITool->FindROIs( holder, channel, candROIVec);//calculates ROI and returns it to roiVec.
262  //auto view = geom->View(channel);
264 
265  //looping over roiVec to make a RegionOfInterest_t object.
266  for(auto const& CandidateROI: candROIVec){
267  size_t roiStart = CandidateROI.first;
268  size_t roiStop = CandidateROI.second;
269  std::vector<float> roiHolder;
270  for(size_t i_holder=roiStart; i_holder<=roiStop; i_holder++){
271  roiHolder.push_back(holder[i_holder]);
272  }
273  roiVec.add_range(roiStart, std::move(roiHolder));
274  }
275  wirecol->push_back(recob::WireCreator(std::move(roiVec),*digitVec).move());
276 
277 
278  // add an association between the last object in wirecol--Hec
279  // (that we just inserted) and digitVec
280  if (!util::CreateAssn(*this, evt, *wirecol, digitVec, *WireDigitAssn, fSpillName)) {
281  throw cet::exception("CalWireSBND")
282  << "Can't associate wire #" << (wirecol->size() - 1)
283  << " with raw digit #" << digitVec.key() << "\n";
284  } // if failed to add association
285  }
286 
287 
288  if(wirecol->size() == 0)
289  mf::LogWarning("CalWireSBND") << "No wires made for this event.";
290 
291  //--Hec if(fSpillName.size()>0)
292  //--Hec evt.put(std::move(wirecol), fSpillName);
293  //--Hec else evt.put(std::move(wirecol));
294 
295  evt.put(std::move(wirecol), fSpillName); //--Hec
296  evt.put(std::move(WireDigitAssn), fSpillName); //--Hec
297 
298  // delete chanFilt;
299  return;
300  }
301 
302 
303  void CalWireSBND::SubtractBaseline(std::vector<float>& holder)
304  {
305  // Robust baseline calculation that effectively ignores outlier
306  // samples from large pulses:
307  // (1) fill a histogram with every sample's value,
308  // (2) find mode (bin with most entries),
309  // (3) calculate the mean along the entire waveform using
310  // only samples with values close to this mode.
311  unsigned int bin(0);
312  float min = 0, max = 0;
313  for(bin = 0; bin < holder.size(); bin++){
314  if (holder[bin] > max) max = holder[bin];
315  if (holder[bin] < min) min = holder[bin];
316  }
317  int nbin = max - min;
318  if (nbin > 0) {
319  TH1F h("h","h",nbin,min,max);
320  for(bin = 0; bin < holder.size(); bin++) h.Fill(holder[bin]);
321  float x_max = h.GetXaxis()->GetBinCenter(h.GetMaximumBin());
322  float ped = x_max;
323  float sum = 0;
324  int ncount = 0;
325  for(bin = 0; bin < holder.size(); bin++){
326  if( fabs(holder[bin]-x_max) < 2. ) {
327  sum += holder[bin];
328  ncount++;
329  }
330  }
331  if (ncount) ped = sum/ncount;
332  for(bin = 0; bin < holder.size(); bin++) holder[bin] -= ped;
333  }
334  }
335 
336  void CalWireSBND::SubtractBaselineAdv(std::vector<float>& holder)
337  {
338  // Subtract baseline using linear interpolation between regions defined
339  // by the datasize and fBaseSampleBins
340 
341  // number of points to characterize the baseline
342  unsigned short nBasePts = holder.size() / fBaseSampleBins;
343 
344  // the baseline offset vector
345  std::vector<float> base;
346  for(unsigned short ii = 0; ii < nBasePts; ++ii) base.push_back(0.);
347  // find the average value in each region, using values that are
348  // similar
349  float fbins = fBaseSampleBins;
350  unsigned short nfilld = 0;
351  for(unsigned short ii = 0; ii < nBasePts; ++ii) {
352  unsigned short loBin = ii * fBaseSampleBins;
353  unsigned short hiBin = loBin + fBaseSampleBins;
354  float ave = 0.;
355  float sum = 0.;
356  for(unsigned short bin = loBin; bin < hiBin; ++bin) {
357  ave += holder[bin];
358  sum += holder[bin] * holder[bin];
359  } // jj
360  ave = ave / fbins;
361  float var = (sum - fbins * ave * ave) / (fbins - 1.);
362  // Set the baseline for this region if the variance is small
363  if(var < fBaseVarCut) {
364  base[ii] = ave;
365  ++nfilld;
366  }
367  } // ii
368  // fill in any missing points if there aren't too many missing
369  if(nfilld < nBasePts && nfilld > nBasePts / 2) {
370  bool baseOK = true;
371  // check the first region
372  if(base[0] == 0) {
373  unsigned short ii1 = 0;
374  for(unsigned short ii = 1; ii < nBasePts; ++ii) {
375  if(base[ii] != 0) {
376  ii1 = ii;
377  break;
378  }
379  } // ii
380  unsigned short ii2 = 0;
381  for(unsigned short ii = ii1 + 1; ii < nBasePts; ++ii) {
382  if(base[ii] != 0) {
383  ii2 = ii;
384  break;
385  }
386  } // ii
387  // failure
388  if(ii2 > 0) {
389  float slp = (base[ii2] - base[ii1]) / (float)(ii2 - ii1);
390  base[0] = base[ii1] - slp * ii1;
391  } else {
392  baseOK = false;
393  }
394  } // base[0] == 0
395  // check the last region
396  if(baseOK && base[nBasePts] == 0) {
397  unsigned short ii2 = 0;
398  for(unsigned short ii = nBasePts - 1; ii > 0; --ii) {
399  if(base[ii] != 0) {
400  ii2 = ii;
401  break;
402  }
403  } // ii
404  baseOK = false; // assume the worst, hope for better
405  unsigned short ii1 = 0;
406  if (ii2 >= 1) {
407  for(unsigned short ii = ii2 - 1; ii > 0; --ii) {
408  if(base[ii] != 0) {
409  ii1 = ii;
410  baseOK = true;
411  break;
412  } // if base[ii]
413  } // ii
414  } // if ii2
415  if (baseOK) {
416  float slp = (base[ii2] - base[ii1]) / (float)(ii2 - ii1);
417  base[nBasePts] = base[ii2] + slp * (nBasePts - ii2);
418  }
419  } // baseOK && base[nBasePts] == 0
420  // now fill in any intermediate points
421  for(unsigned short ii = 1; ii < nBasePts - 1; ++ii) {
422  if(base[ii] == 0) {
423  // find the next non-zero region
424  for(unsigned short jj = ii + 1; jj < nBasePts; ++jj) {
425  if(base[jj] != 0) {
426  float slp = (base[jj] - base[ii - 1]) / (jj - ii + 1);
427  base[ii] = base[ii - 1] + slp;
428  break;
429  }
430  } // jj
431  } // base[ii] == 0
432  } // ii
433  } // nfilld < nBasePts
434 
435  // interpolate and subtract
436  float slp = (base[1] - base[0]) / (float)fBaseSampleBins;
437  // bin offset to the origin (the center of the region)
438  unsigned short bof = fBaseSampleBins / 2;
439  unsigned short lastRegion = 0;
440  for(unsigned short bin = 0; bin < holder.size(); ++bin) {
441  // in a new region?
442  unsigned short region = bin / fBaseSampleBins;
443  if(region > lastRegion) {
444  // update the slope and offset
445  slp = (base[region] - base[lastRegion]) / (float)fBaseSampleBins;
446  bof += fBaseSampleBins;
447  lastRegion = region;
448  }
449  holder[bin] -= base[region] + (bin - bof) * slp;
450  }
451  }
452 
453 
454 } // end namespace caldata
bool fDoAdvBaselineSub
use interpolation-based baseline subtraction
std::vector< float > Waveform
Helper functions to create a wire.
pdgs p
Definition: selectors.fcl:22
bool fDoBaselineSub
subtract baseline to restore DC component post-deconvolution
void produce(art::Event &evt)
std::unique_ptr< sbnd_tool::IROIFinder > fROITool
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.
for pfile in ack l reconfigure(.*) override"` do echo "checking $
Class managing the creation of a new recob::Wire object.
Definition: WireCreator.h:53
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
while getopts h
CalWireSBND(fhicl::ParameterSet const &pset)
void reconfigure(fhicl::ParameterSet const &p)
Service to provide microboone-specific signal shaping for simulation (convolution) and reconstruction...
Collect all the RawData header files together.
void SubtractBaseline(std::vector< float > &holder)
float fBaseVarCut
baseline variance cut used in &quot;interpolate&quot; method
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.
int fBaseSampleBins
bin grouping size in &quot;interpolate&quot; method
std::string fDigitModuleLabel
module that made digits
std::pair< size_t, size_t > CandidateROI
do i e
Declaration of basic channel signal object.
TCEvent evt
Definition: DataStructs.cxx:8
Class defining a sparse vector (holes are zeroes)
void SubtractBaselineAdv(std::vector< float > &holder)
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:776
process_name can override from command line with o or output caldata
Definition: pid.fcl:40
art framework interface to geometry description
std::vector< CandidateROI > CandidateROIVec