LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
WaveformDenoiseTest_module.cc
Go to the documentation of this file.
1 //
2 // This is for testing the 1d denoising AE
3 //
4 // Framework includes
15 #include "fhiclcpp/ParameterSet.h"
17 
18 // LArSoft libraries
21 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
25 #include "lardataobj/RawData/raw.h"
28 #include "larrecodnn/ImagePatternAlgs/ToolInterfaces/IWaveformDenoise.h"
29 #include "larrecodnn/ImagePatternAlgs/ToolInterfaces/IWaveformRecog.h"
30 
31 #include "c2numpy.h"
32 
33 using std::cout;
34 using std::endl;
35 using std::ofstream;
36 using std::string;
37 
38 struct CnnROI {
39  unsigned int start;
40  unsigned int end;
41 };
42 
43 namespace nnet {
44  class WaveformDenoiseTest;
45 }
46 
48 
49 public:
50  explicit WaveformDenoiseTest(fhicl::ParameterSet const& p);
51 
52  // Plugins should not be copied or assigned.
55  WaveformDenoiseTest& operator=(WaveformDenoiseTest const&) = delete;
56  WaveformDenoiseTest& operator=(WaveformDenoiseTest&&) = delete;
57 
58  // Required functions.
59  void analyze(art::Event const& e) override;
60 
61  //void reconfigure(fhicl::ParameterSet const & p);
62 
63  void beginJob() override;
64  void endJob() override;
65 
66 private:
69  std::string fDumpDenoisedFileName;
70  unsigned int fDisplayWindowSize;
71 
72  std::string fSimChannelLabel;
73  std::string fDigitModuleLabel;
75 
76  std::string fPlaneToDump;
77  std::string fCollectionPlaneLabel;
79 
80  std::vector<std::unique_ptr<wavrec_tool::IWaveformRecog>> fWaveformRecogToolVec;
81  std::vector<std::unique_ptr<wavdenoise_tool::IWaveformDenoise>> fWaveformDenoiseToolVec;
82  int fNPlanes;
83 
84  std::ofstream _fileout1;
85 
89 };
90 
91 //-----------------------------------------------------------------------
93  : EDAnalyzer{p}
94  , fDumpWaveformsFileName(p.get<std::string>("DumpWaveformsFileName", "dumpwaveforms"))
95  , fDumpCleanSignalFileName(p.get<std::string>("CleanSignalFileName", "dumpcleansignal"))
96  , fDumpDenoisedFileName(p.get<std::string>("DenoisedFileName", "dumpdenoised"))
97  , fDisplayWindowSize(p.get<unsigned int>("DisplayWindowSize", 500))
98  , fSimChannelLabel(p.get<std::string>("SimChannelLabel", "elecDrift"))
99  , fDigitModuleLabel(p.get<std::string>("DigitModuleLabel", "simWire"))
101  p.get<std::string>("CleanSignalDigitModuleLabel", "simWire:signal"))
102  , fPlaneToDump(p.get<std::string>("PlaneToDump", "U"))
103  , fCollectionPlaneLabel(p.get<std::string>("CollectionPlaneLabel", "Z"))
104 {
105 
106  if (fDigitModuleLabel.empty() && fCleanSignalDigitModuleLabel.empty()) {
107  throw cet::exception("WaveformDenoiseTest")
108  << "Both DigitModuleLabel and CleanSignalModuleLabel are empty";
109  }
110 
111  fNPlanes = fgeom->Nplanes();
112 
113  // Signal/Noise waveform recognition tool
115  auto const tool_psets1 = p.get<std::vector<fhicl::ParameterSet>>("WaveformRecogs");
116  for (auto const& pset : tool_psets1) {
117  fWaveformRecogToolVec.push_back(art::make_tool<wavrec_tool::IWaveformRecog>(pset));
118  }
119 
120  // AE based waveform denoising tool
122  auto const tool_psets2 = p.get<std::vector<fhicl::ParameterSet>>("WaveformDenoisers");
123  for (auto const& pset : tool_psets2) {
124  fWaveformDenoiseToolVec.push_back(art::make_tool<wavdenoise_tool::IWaveformDenoise>(pset));
125  }
126 }
127 
128 //-----------------------------------------------------------------------
130 {
131 
137  for (unsigned int i = 0; i < fDisplayWindowSize; i++) {
138  std::ostringstream name;
139  name << "tck_" << i;
140  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT16);
141  }
142 
143  // ... this is for storing the clean signal (no noise) waveform
145 
146  for (unsigned int i = 0; i < fDisplayWindowSize; i++) {
147  std::ostringstream name;
148  name << "tck_" << i;
149  c2numpy_addcolumn(&npywriter2, name.str().c_str(), C2NUMPY_INT16);
150  }
151 
152  // ... this is for storing the denoised raw waveform
154 
155  for (unsigned int i = 0; i < fDisplayWindowSize; i++) {
156  std::ostringstream name;
157  name << "tck_" << i;
158  c2numpy_addcolumn(&npywriter3, name.str().c_str(), C2NUMPY_FLOAT32);
159  }
160 }
161 
162 //-----------------------------------------------------------------------
164 {
168 }
169 
170 //-----------------------------------------------------------------------
172 {
173  cout << "Event "
174  << " " << evt.id().run() << " " << evt.id().subRun() << " " << evt.id().event() << endl;
175 
176  // ... Read in the digit List object(s).
177  auto digitVecHandle = evt.getValidHandle<std::vector<raw::RawDigit>>(fDigitModuleLabel);
178 
179  // ... Read in the signal-only digit List object(s).
180  auto digitVecHandle2 =
181  evt.getValidHandle<std::vector<raw::RawDigit>>(fCleanSignalDigitModuleLabel);
182 
183  if (!digitVecHandle->size() || !digitVecHandle2->size()) {
184  throw cet::exception("NoiseWaveformRoiAnalyzer")
185  << "At least one of the raw digits lists is empty.";
186  }
187 
188  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
189  auto const detProp =
191 
192  // ... Use the handle to get a particular (0th) element of collection.
193  std::vector<raw::RawDigit> const& rawDigits = *digitVecHandle;
194  raw::RawDigit const& digitVec0 = rawDigits[0];
195  unsigned int dataSize = digitVec0.Samples(); //size of raw data vectors
196  if (dataSize != detProp.ReadOutWindowSize()) {
197  throw cet::exception("NoiseWaveformRoiAnalyzer") << "Bad dataSize: " << dataSize;
198  }
199  std::vector<raw::RawDigit> const& rawDigits2 = *digitVecHandle2;
200  raw::RawDigit const& digitVec20 = rawDigits2[0];
201  unsigned int dataSize2 = digitVec20.Samples(); //size of raw data vectors
202  if (dataSize != dataSize2) {
203  throw cet::exception("NoiseWaveformRoiAnalyzer")
204  << "RawDigits from the 2 data products have different dataSizes: " << dataSize << "not eq to"
205  << dataSize2;
206  }
207 
208  // ... Build a map from channel number -> rawdigitVec
209  std::map<raw::ChannelID_t, art::Ptr<raw::RawDigit>> rawdigitMap;
210  raw::ChannelID_t chnum = raw::InvalidChannelID; // channel number
211  for (size_t rdIter = 0; rdIter < rawDigits.size(); ++rdIter) {
212  art::Ptr<raw::RawDigit> digitVec(digitVecHandle, rdIter);
213  chnum = digitVec->Channel();
214  if (chnum == raw::InvalidChannelID) continue;
215  if (geo::PlaneGeo::ViewName(fgeom->View(chnum)) != fPlaneToDump[0]) continue;
216  rawdigitMap[chnum] = digitVec;
217  }
218  std::map<raw::ChannelID_t, art::Ptr<raw::RawDigit>> rawdigitMap2;
219  raw::ChannelID_t chnum2 = raw::InvalidChannelID; // channel number
220  for (size_t rdIter = 0; rdIter < rawDigits2.size(); ++rdIter) {
221  art::Ptr<raw::RawDigit> digitVec2(digitVecHandle2, rdIter);
222  chnum2 = digitVec2->Channel();
223  if (chnum2 == raw::InvalidChannelID) continue;
224  if (geo::PlaneGeo::ViewName(fgeom->View(chnum2)) != fPlaneToDump[0]) continue;
225  rawdigitMap2[chnum2] = digitVec2;
226  }
227 
228  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
229  // ... First find all channels that have non-zero raw digits and erase them
230  // from the raw digit maps
231  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
232 
233  std::vector<raw::ChannelID_t> signalchannels;
234 
235  for (std::map<raw::ChannelID_t, art::Ptr<raw::RawDigit>>::iterator iter = rawdigitMap2.begin();
236  iter != rawdigitMap2.end();
237  ++iter) {
238  std::vector<short> rawadc(dataSize); // vector to hold uncompressed adc values later
239  std::vector<short> adcvec2(dataSize); // vector to pedestal-subtracted adc values
240 
241  auto rawdig2 = iter->second;
242  raw::Uncompress(rawdig2->ADCs(), rawadc, rawdig2->GetPedestal(), rawdig2->Compression());
243  for (size_t j = 0; j < rawadc.size(); ++j) {
244  adcvec2[j] = rawadc[j] - rawdig2->GetPedestal();
245  }
246 
247  auto itnz = find_if(adcvec2.begin(), adcvec2.end(), [](auto x) { return x != 0; });
248  if (itnz != adcvec2.end()) signalchannels.push_back(iter->first);
249  }
250 
251  for (size_t ich = 0; ich < signalchannels.size(); ++ich) {
252 
253  // .. get signal-containing channel number
254  auto ch1 = signalchannels[ich];
255  if (ch1 == raw::InvalidChannelID) continue;
256  if (geo::PlaneGeo::ViewName(fgeom->View(ch1)) != fPlaneToDump[0]) continue;
257 
258  std::vector<short> rawadc(dataSize); // vector to hold uncompressed adc values later
259  std::vector<short> adcvec(dataSize); // vector to hold zero-padded full waveform
260  std::vector<short> adcvec2(dataSize); // vector to hold zero-padded full signal-only waveform
261  std::vector<float> inputsignal(dataSize); // float version of adcvec
262 
263  auto search = rawdigitMap.find(ch1);
264  if (search == rawdigitMap.end()) continue;
265  auto rawdig = (*search).second;
266  raw::Uncompress(rawdig->ADCs(), rawadc, rawdig->GetPedestal(), rawdig->Compression());
267  for (size_t j = 0; j < rawadc.size(); ++j) {
268  adcvec[j] = rawadc[j] - rawdig->GetPedestal();
269  inputsignal[j] = adcvec[j];
270  }
271 
272  auto search2 = rawdigitMap2.find(ch1);
273  if (search2 == rawdigitMap2.end()) continue;
274  auto rawdig2 = (*search2).second;
275  raw::Uncompress(rawdig2->ADCs(), rawadc, rawdig2->GetPedestal(), rawdig2->Compression());
276  for (size_t i = 0; i < rawadc.size(); ++i) {
277  adcvec2[i] = rawadc[i] - rawdig2->GetPedestal();
278  }
279 
280  // ... use waveform recognition CNN to perform inference on each window
281  std::vector<bool> inroi(dataSize, false);
282  inroi = fWaveformRecogToolVec[fgeom->View(ch1)]->findROI(inputsignal);
283 
284  auto itnf = find_if(inroi.begin(), inroi.end(), [](auto x) { return x; });
285  if (itnf == inroi.end()) continue;
286 
287  CnnROI roi;
288  std::vector<CnnROI> cnn_rois;
289 
290  bool is_roi = false;
291  bool was_roi = false;
292 
293  for (size_t itck = 0; itck < inroi.size() - 1; ++itck) {
294  is_roi = inroi[itck];
295  if (is_roi && !was_roi) { roi.start = itck; }
296  else if (!is_roi && was_roi) {
297  roi.end = itck - 1;
298  cnn_rois.push_back(roi);
299  }
300  was_roi = is_roi;
301  }
302 
303  for (size_t i = 0; i < cnn_rois.size(); ++i) {
304  std::vector<short> wavraw(fDisplayWindowSize, 0);
305  std::vector<short> wavcln(fDisplayWindowSize, 0);
306  std::vector<float> wavdns(fDisplayWindowSize, 0);
307 
308  unsigned int tcka = cnn_rois[i].start;
309  unsigned int tckb = cnn_rois[i].end;
310  unsigned int ntcks_roi = tckb - tcka + 1;
311  unsigned int ntcks_dis = ntcks_roi;
312  if (ntcks_dis > fDisplayWindowSize) {
313  tckb = tcka + fDisplayWindowSize - 1;
314  ntcks_dis = tckb - tcka + 1;
315  }
316 
317  unsigned jtck = 0;
318  for (unsigned int itck = tcka; itck < tckb; ++itck) {
319  wavraw[jtck] = adcvec[itck];
320  wavcln[jtck] = adcvec2[itck];
321  jtck++;
322  }
323 
324  std::vector<float> wavinp(ntcks_roi, 0);
325  std::vector<float> wavout(ntcks_roi, 0);
326 
327  jtck = 0;
328  for (unsigned int itck = tcka; itck < tcka + ntcks_roi; ++itck) {
329  wavinp[jtck] = float(adcvec[itck]);
330  jtck++;
331  }
332  wavout = fWaveformDenoiseToolVec[fgeom->View(ch1)]->denoiseWaveform(wavinp);
333 
334  for (unsigned int itck = 0; itck < ntcks_dis; ++itck) {
335  wavdns[itck] = wavout[itck];
336  }
337 
338  c2numpy_uint32(&npywriter, evt.id().event());
339  c2numpy_uint32(&npywriter, ch1);
340  c2numpy_uint16(&npywriter, i); // roi
342 
343  for (unsigned int j = 0; j < fDisplayWindowSize; ++j) {
344  c2numpy_int16(&npywriter, wavraw[j]);
345  }
346  for (unsigned int j = 0; j < fDisplayWindowSize; ++j) {
347  c2numpy_int16(&npywriter2, wavcln[j]);
348  }
349  for (unsigned int j = 0; j < fDisplayWindowSize; ++j) {
350  c2numpy_float32(&npywriter3, wavdns[j]);
351  }
352  }
353  }
354 }
Float_t x
Definition: compare.C:6
int c2numpy_init(c2numpy_writer *writer, const std::string outputFilePrefix, int32_t numRowsPerFile)
Definition: c2numpy.h:140
std::string fCleanSignalDigitModuleLabel
module that made the signal-only digits
art::ServiceHandle< geo::Geometry > fgeom
static std::string ViewName(geo::View_t view)
Returns the name of the specified view.
Definition: PlaneGeo.cxx:682
ULong64_t Samples() const
Number of samples in the uncompressed ADC data.
Definition: RawDigit.h:217
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:68
c2numpy_type
Definition: c2numpy.h:29
WaveformDenoiseTest(fhicl::ParameterSet const &p)
std::string fSimChannelLabel
module that made simchannels
Declaration of signal hit object.
ChannelID_t Channel() const
DAQ channel this raw data was read from.
Definition: RawDigit.h:213
Definition of basic raw digits.
std::vector< std::unique_ptr< wavrec_tool::IWaveformRecog > > fWaveformRecogToolVec
RunNumber_t run() const
Definition: EventID.h:98
int c2numpy_close(c2numpy_writer *writer)
Definition: c2numpy.h:425
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
Definition: RawTypes.h:31
int c2numpy_addcolumn(c2numpy_writer *writer, const std::string name, c2numpy_type type)
Definition: c2numpy.h:157
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
void beginJob()
Definition: Breakpoints.cc:14
Collect all the RawData header files together.
Definition: EmTrack.h:40
void analyze(art::Event const &e) override
std::string fDigitModuleLabel
module that made digits
int c2numpy_uint32(c2numpy_writer *writer, uint32_t data)
Definition: c2numpy.h:334
int c2numpy_float32(c2numpy_writer *writer, float data)
Definition: c2numpy.h:369
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Encapsulate the construction of a single detector plane.
View_t View(PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
int c2numpy_uint16(c2numpy_writer *writer, uint16_t data)
Definition: c2numpy.h:325
object containing MC truth information necessary for making RawDigits and doing back tracking ...
int c2numpy_int16(c2numpy_writer *writer, int16_t data)
Definition: c2numpy.h:289
EventNumber_t event() const
Definition: EventID.h:116
unsigned int Nplanes(TPCID const &tpcid=tpc_zero) const
Returns the total number of planes in the specified TPC.
Definition: GeometryCore.h:977
unsigned int start
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:744
Float_t e
Definition: plot.C:35
std::vector< std::unique_ptr< wavdenoise_tool::IWaveformDenoise > > fWaveformDenoiseToolVec
SubRunNumber_t subRun() const
Definition: EventID.h:110
int c2numpy_string(c2numpy_writer *writer, const char *data)
Definition: c2numpy.h:411
EventID id() const
Definition: Event.cc:23
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33