LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
RawWaveformClnSigDump_module.cc
Go to the documentation of this file.
1 //
3 // Module to dump raw data for ROI training
4 //
5 // mwang@fnal.gov
6 // tjyang@fnal.gov
7 // wwu@fnal.gov
8 //
9 // This version:
10 // a) uses only RawDigits, not WireProducer
11 // b) reads in two separate RawDigits:
12 // - signal+noise
13 // - same signal as above but no noise
14 // c) saves full waveform or short waveform
15 // - for short waveform, picks signal
16 // associated with largest energy
17 // deposit & saves only tdcmin/tdcmaxes
18 // that are within window extents
19 // d) selects only signal waveforms that have
20 // minimum ADC count associated with the
21 // pure signal
22 // e) produces a 2nd npy file for pure signal
23 // waveform
24 //
26 
27 // LArSoft libraries
30 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
34 #include "lardataobj/RawData/raw.h"
39 
40 // Framework includes
51 #include "cetlib_except/exception.h"
52 #include "fhiclcpp/ParameterSet.h"
57 
58 #include "CLHEP/Random/RandFlat.h"
59 #include "c2numpy.h"
60 
61 #include <algorithm>
62 #include <chrono>
63 #include <cstdlib>
64 #include <iostream>
65 #include <map>
66 #include <random>
67 #include <set>
68 #include <sstream>
69 #include <string>
70 #include <utility>
71 #include <vector>
72 
73 using std::cout;
74 using std::endl;
75 using std::ofstream;
76 using std::string;
77 
78 struct WireSigInfo {
79  int pdgcode;
80  std::string genlab;
81  std::string procid;
82  unsigned int tdcmin;
83  unsigned int tdcmax;
84  int tdcpeak;
85  int adcpeak;
86  int numel;
87  double edep;
88 };
89 
90 namespace nnet {
91  class RawWaveformClnSigDump;
92 }
93 
95 
96 public:
97  explicit RawWaveformClnSigDump(fhicl::ParameterSet const& p);
98 
99  // Plugins should not be copied or assigned.
102  RawWaveformClnSigDump& operator=(RawWaveformClnSigDump const&) = delete;
103  RawWaveformClnSigDump& operator=(RawWaveformClnSigDump&&) = delete;
104 
105  // Required functions.
106  void analyze(art::Event const& e) override;
107 
108  //void reconfigure(fhicl::ParameterSet const & p);
109 
110  void beginJob() override;
111  void endJob() override;
112 
113 private:
116 
118  std::string fSimChannelLabel;
119  std::string fDigitModuleLabel;
122  unsigned int fShortWaveformSize;
125 
126  std::string fSelectGenLabel;
127  std::string fSelectProcID;
129  std::string fPlaneToDump;
139  geo::WireReadoutGeom const* fWireReadoutGeom{
142 
143  CLHEP::RandFlat fRandFlat;
144 
147 };
148 
149 //-----------------------------------------------------------------------
150 struct genFinder {
151 private:
152  typedef std::pair<int, std::string> track_id_to_string;
153  std::vector<track_id_to_string> track_id_map;
154  std::set<std::string> generator_names;
155  bool isSorted = false;
156 
157 public:
158  void sort_now()
159  {
160  std::sort(this->track_id_map.begin(),
161  this->track_id_map.end(),
162  [](const auto& a, const auto& b) { return (a.first < b.first); });
163  isSorted = true;
164  }
165  void add(const int& track_id, const std::string& gname)
166  {
167  this->track_id_map.push_back(std::make_pair(track_id, gname));
168  generator_names.emplace(gname);
169  isSorted = false;
170  }
171  bool has_gen(std::string gname) { return static_cast<bool>(generator_names.count(gname)); };
172  std::string get_gen(int tid)
173  {
174  if (!isSorted) { this->sort_now(); }
175  return std::lower_bound(track_id_map.begin(),
176  track_id_map.end(),
177  tid,
178  [](const auto& a, const auto& b) { return (a.first < b); })
179  ->second;
180  };
181 };
182 
183 // Create the random number generator
184 namespace {
185  std::string const instanceName = "RawWaveformClnSigDump";
186 }
187 
188 //-----------------------------------------------------------------------
190  : EDAnalyzer{p}
191  , fDumpWaveformsFileName(p.get<std::string>("DumpWaveformsFileName", "dumpwaveforms"))
192  , fDumpCleanSignalFileName(p.get<std::string>("CleanSignalFileName", "dumpcleansignal"))
193  , fSimulationProducerLabel(p.get<std::string>("SimulationProducerLabel", "larg4Main"))
194  , fSimChannelLabel(p.get<std::string>("SimChannelLabel", "elecDrift"))
195  , fDigitModuleLabel(p.get<std::string>("DigitModuleLabel", "simWire"))
197  p.get<std::string>("CleanSignalDigitModuleLabel", "simWire:signal"))
198  , fUseFullWaveform(p.get<bool>("UseFullWaveform", true))
199  , fShortWaveformSize(p.get<unsigned int>("ShortWaveformSize"))
200  , fEstIndFWForOffset(p.get<int>("EstIndFWForOffset"))
201  , fEstColFWForOffset(p.get<int>("EstIndFWForOffset"))
202  , fSelectGenLabel(p.get<std::string>("SelectGenLabel", "ANY"))
203  , fSelectProcID(p.get<std::string>("SelectProcID", "ANY"))
204  , fSelectPDGCode(p.get<int>("SelectPDGCode", 0))
205  , fPlaneToDump(p.get<std::string>("PlaneToDump"))
206  , fMinParticleEnergyGeV(p.get<double>("MinParticleEnergyGeV", 0.))
207  , fMinEnergyDepositedMeV(p.get<double>("MinEnergyDepositedMeV", 0.))
208  , fMinNumberOfElectrons(p.get<int>("MinNumberOfElectrons", 600))
209  , fMaxNumberOfElectrons(p.get<int>("MaxNumberOfElectrons", -1))
210  , fMinPureSignalADCs(p.get<int>("MinPureSignalADCs", 0))
211  , fSaveSignal(p.get<bool>("SaveSignal", true))
212  , fMaxSignalChannelsPerEvent(p.get<int>("MaxSignalChannelsPerEvent", -1))
213  , fMaxNoiseChannelsPerEvent(p.get<int>("MaxNoiseChannelsPerEvent"))
214  , fCollectionPlaneLabel(p.get<std::string>("CollectionPlaneLabel"))
217  -> declareEngine(instanceName, p, "SeedForRawWaveformDump"),
218  "HepJamesRandom",
219  instanceName)}
220 {
221  if (std::getenv("CLUSTER") && std::getenv("PROCESS")) {
223  string(std::getenv("CLUSTER")) + "-" + string(std::getenv("PROCESS")) + "-";
225  string(std::getenv("CLUSTER")) + "-" + string(std::getenv("PROCESS")) + "-";
226  }
227 
228  if (fDigitModuleLabel.empty() && fCleanSignalDigitModuleLabel.empty()) {
229  throw cet::exception("RawWaveformClnSigDump")
230  << "Both DigitModuleLabel and CleanSignalModuleLabel are empty";
231  }
232 }
233 
234 //-----------------------------------------------------------------------
236 {
237  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
238 
244 
245  for (unsigned int i = 0; i < 5; i++) {
246  std::ostringstream name;
247 
248  name.str("");
249  name << "tid" << i;
250  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT32);
251 
252  name.str("");
253  name << "pdg" << i;
254  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT32);
255 
256  name.str("");
257  name << "gen" << i;
258  c2numpy_addcolumn(&npywriter, name.str().c_str(), (c2numpy_type)((int)C2NUMPY_STRING + 6));
259 
260  name.str("");
261  name << "pid" << i;
262  c2numpy_addcolumn(&npywriter, name.str().c_str(), (c2numpy_type)((int)C2NUMPY_STRING + 7));
263 
264  name.str("");
265  name << "edp" << i;
266  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_FLOAT32);
267 
268  name.str("");
269  name << "nel" << i;
270  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_UINT32);
271 
272  name.str("");
273  name << "sti" << i;
274  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_UINT16);
275 
276  name.str("");
277  name << "stf" << i;
278  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_UINT16);
279 
280  name.str("");
281  name << "stp" << i;
282  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT32);
283 
284  name.str("");
285  name << "adc" << i;
286  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT32);
287  }
288 
289  for (unsigned int i = 0;
290  i < (fUseFullWaveform ? detProp.ReadOutWindowSize() : fShortWaveformSize);
291  i++) {
292  std::ostringstream name;
293  name << "tck_" << i;
294  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT16);
295  }
296 
297  // ... this is for storing the clean signal (no noise) waveform
299 
300  for (unsigned int i = 0;
301  i < (fUseFullWaveform ? detProp.ReadOutWindowSize() : fShortWaveformSize);
302  i++) {
303  std::ostringstream name;
304  name << "tck_" << i;
305  c2numpy_addcolumn(&npywriter2, name.str().c_str(), C2NUMPY_INT16);
306  }
307 }
308 
309 //-----------------------------------------------------------------------
311 {
314 }
315 
316 //-----------------------------------------------------------------------
318 {
319  cout << "Event "
320  << " " << evt.id().run() << " " << evt.id().subRun() << " " << evt.id().event() << endl;
321 
322  std::unique_ptr<genFinder> gf(new genFinder());
323 
324  // ... Read in the digit List object(s).
326  std::vector<art::Ptr<raw::RawDigit>> rawdigitlist;
327  if (evt.getByLabel(fDigitModuleLabel, digitVecHandle)) {
328  //std::cout << " !!!! RawWaveformClnSigDump: fDigitModuleLabel -> " << fDigitModuleLabel << std::endl;
329  art::fill_ptr_vector(rawdigitlist, digitVecHandle);
330  }
331 
332  // ... Read in the signal-only digit List object(s).
334  std::vector<art::Ptr<raw::RawDigit>> rawdigitlist2;
335  if (evt.getByLabel(fCleanSignalDigitModuleLabel, digitVecHandle2)) {
336  //std::cout << " !!!! RawWaveformClnSigDump: fCleanSignalDigitModuleLabel -> " << fCleanSignalDigitModuleLabel << std::endl;
337  art::fill_ptr_vector(rawdigitlist2, digitVecHandle2);
338  }
339 
340  if (rawdigitlist.empty() && rawdigitlist2.empty()) return;
341 
342  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
343  auto const detProp =
345 
346  // ... Use the handle to get a particular (0th) element of collection.
347  unsigned int dataSize;
348  art::Ptr<raw::RawDigit> digitVec0(digitVecHandle, 0);
349  dataSize = digitVec0->Samples(); //size of raw data vectors
350  if (dataSize != detProp.ReadOutWindowSize()) {
351  throw cet::exception("RawWaveformClnSigDump") << "Bad dataSize: " << dataSize;
352  }
353  art::Ptr<raw::RawDigit> digitVec20(digitVecHandle2, 0);
354  unsigned int dataSize2 = digitVec20->Samples();
355  if (dataSize != dataSize2) {
356  throw cet::exception("RawWaveformClnSigDump")
357  << "RawDigits from the 2 data products have different dataSizes: " << dataSize << "not eq to"
358  << dataSize2;
359  }
360 
361  // ... Build a map from channel number -> rawdigitVec
362  std::map<raw::ChannelID_t, art::Ptr<raw::RawDigit>> rawdigitMap;
363  raw::ChannelID_t chnum = raw::InvalidChannelID; // channel number
364  if (rawdigitlist.size()) {
365  for (size_t rdIter = 0; rdIter < digitVecHandle->size(); ++rdIter) {
366  art::Ptr<raw::RawDigit> digitVec(digitVecHandle, rdIter);
367  chnum = digitVec->Channel();
368  if (chnum == raw::InvalidChannelID) continue;
369  rawdigitMap[chnum] = digitVec;
370  }
371  }
372  std::map<raw::ChannelID_t, art::Ptr<raw::RawDigit>> rawdigitMap2;
373  raw::ChannelID_t chnum2 = raw::InvalidChannelID; // channel number
374  if (rawdigitlist2.size()) {
375  for (size_t rdIter = 0; rdIter < digitVecHandle2->size(); ++rdIter) {
376  art::Ptr<raw::RawDigit> digitVec2(digitVecHandle2, rdIter);
377  chnum2 = digitVec2->Channel();
378  if (chnum2 == raw::InvalidChannelID) continue;
379  rawdigitMap2[chnum2] = digitVec2;
380  }
381  }
382 
383  // ... Read in MC particle list
385  if (!evt.getByLabel(fSimulationProducerLabel, particleHandle)) {
386  throw cet::exception("AnalysisExample")
387  << " No simb::MCParticle objects in this event - "
388  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
389  }
390 
391  // ... Read in sim channel list
392  auto simChannelHandle = evt.getValidHandle<std::vector<sim::SimChannel>>(fSimChannelLabel);
393 
394  if (!simChannelHandle->size()) return;
395 
396  // ... Create a map of track IDs to generator labels
397  //Get a list of generator names.
398  //std::vector<art::Handle<std::vector<simb::MCTruth>>> mcHandles;
399  //evt.getManyByType(mcHandles);
400  auto mcHandles = evt.getMany<std::vector<simb::MCTruth>>();
401  std::vector<std::pair<int, std::string>> track_id_to_label;
402 
403  for (auto const& mcHandle : mcHandles) {
404  const std::string& sModuleLabel = mcHandle.provenance()->moduleLabel();
406  std::vector<art::Ptr<simb::MCParticle>> mcParts = findMCParts.at(0);
407  for (const art::Ptr<simb::MCParticle> ptr : mcParts) {
408  int track_id = ptr->TrackId();
409  gf->add(track_id, sModuleLabel);
410  }
411  }
412 
413  std::string dummystr6 = "none ";
414  std::string dummystr7 = "none ";
415 
416  if (fSaveSignal) {
417  // .. create a channel number to trackid-wire signal info map
418  std::map<raw::ChannelID_t, std::map<int, WireSigInfo>> Ch2TrkWSInfoMap;
419 
420  // .. create a track ID to vector of channel numbers (in w/c this track deposited energy) map
421  std::map<int, std::vector<raw::ChannelID_t>> Trk2ChVecMap;
422 
423  // ... Loop over simChannels
424  for (auto const& channel : (*simChannelHandle)) {
425 
426  // .. get simChannel channel number
427  const raw::ChannelID_t ch1 = channel.Channel();
428  if (ch1 == raw::InvalidChannelID) continue;
429  if (geo::PlaneGeo::ViewName(fWireReadoutGeom->View(ch1)) != fPlaneToDump[0]) continue;
430 
431  bool selectThisChannel = false;
432 
433  // .. create a track ID to wire signal info map
434  std::map<int, WireSigInfo> Trk2WSInfoMap;
435 
436  // ... Loop over all ticks with ionization energy deposited
437  auto const& timeSlices = channel.TDCIDEMap();
438  for (auto const& timeSlice : timeSlices) {
439 
440  auto const& energyDeposits = timeSlice.second;
441  auto const tpctime = timeSlice.first;
442  unsigned int tdctick = static_cast<unsigned int>(clockData.TPCTDC2Tick(double(tpctime)));
443  if (tdctick < 0 || tdctick > (dataSize - 1)) continue;
444 
445  // ... Loop over all energy depositions in this tick
446  for (auto const& energyDeposit : energyDeposits) {
447 
448  if (!energyDeposit.trackID) continue;
449  int trkid = energyDeposit.trackID;
450  simb::MCParticle particle = PIS->TrackIdToMotherParticle(trkid);
451  //std::cout << energyDeposit.trackID << " " << trkid << " " << particle.TrackId() << std::endl;
452 
453  // .. ignore this energy deposition if incident particle energy below some threshold
454  if (particle.E() < fMinParticleEnergyGeV) continue;
455 
456  int eve_id = PIS->TrackIdToEveTrackId(trkid);
457  if (!eve_id) continue;
458  std::string genlab = gf->get_gen(eve_id);
459 
460  if (Trk2WSInfoMap.find(trkid) == Trk2WSInfoMap.end()) {
461  WireSigInfo wsinf;
462  wsinf.pdgcode = particle.PdgCode();
463  wsinf.genlab = genlab;
464  wsinf.procid = particle.Process();
465  wsinf.tdcmin = dataSize - 1;
466  wsinf.tdcmax = 0;
467  wsinf.tdcpeak = -1;
468  wsinf.adcpeak = 0;
469  wsinf.edep = 0.;
470  wsinf.numel = 0;
471  Trk2WSInfoMap.insert(std::pair<int, WireSigInfo>(trkid, wsinf));
472  }
473  if (tdctick < Trk2WSInfoMap.at(trkid).tdcmin) Trk2WSInfoMap.at(trkid).tdcmin = tdctick;
474  if (tdctick > Trk2WSInfoMap.at(trkid).tdcmax) Trk2WSInfoMap.at(trkid).tdcmax = tdctick;
475  Trk2WSInfoMap.at(trkid).edep += energyDeposit.energy;
476  Trk2WSInfoMap.at(trkid).numel += energyDeposit.numElectrons;
477  }
478  } // loop over timeSlices
479 
480  auto search2 = rawdigitMap2.find(ch1);
481  if (search2 == rawdigitMap2.end()) continue;
482  art::Ptr<raw::RawDigit> rawdig2 = (*search2).second;
483  std::vector<short> rawadc(dataSize);
484  raw::Uncompress(rawdig2->ADCs(), rawadc, rawdig2->GetPedestal(), rawdig2->Compression());
485  std::vector<short> adcvec2(dataSize);
486  for (size_t j = 0; j < rawadc.size(); ++j) {
487  adcvec2[j] = rawadc[j] - rawdig2->GetPedestal();
488  }
489 
490  if (!Trk2WSInfoMap.empty()) {
491  for (std::pair<int, WireSigInfo> itmap : Trk2WSInfoMap) {
492  // find the peak adc value in the signal-only raw digits within the range tdcmin->tdcmax
493  int pkadc = 0;
494  int pktdc = -1;
495  for (size_t i = itmap.second.tdcmin; i <= itmap.second.tdcmax; i++) {
496  if (abs(adcvec2[i]) > abs(pkadc)) {
497  pkadc = adcvec2[i];
498  pktdc = i;
499  }
500  }
501  Trk2WSInfoMap.at(itmap.first).tdcpeak = pktdc;
502  Trk2WSInfoMap.at(itmap.first).adcpeak = pkadc;
503 
504  if (fSelectGenLabel != "ANY") {
505  if (itmap.second.genlab != fSelectGenLabel) continue;
506  }
507  if (fSelectProcID != "ANY") {
508  if (itmap.second.procid != fSelectProcID) continue;
509  }
510  if (fSelectPDGCode != 0) {
511  if (itmap.second.pdgcode != fSelectPDGCode) continue;
512  }
513  itmap.second.genlab.resize(6, ' ');
514  itmap.second.procid.resize(7, ' ');
515  if (itmap.second.numel >= fMinNumberOfElectrons &&
516  itmap.second.edep >= fMinEnergyDepositedMeV && abs(pkadc) >= fMinPureSignalADCs) {
517  if (fMaxNumberOfElectrons >= 0 && itmap.second.numel >= fMaxNumberOfElectrons) {
518  continue;
519  }
520  else {
521  int trkid = itmap.first;
522  if (Trk2ChVecMap.find(trkid) == Trk2ChVecMap.end()) {
523  std::vector<raw::ChannelID_t> chvec;
524  Trk2ChVecMap.insert(std::pair<int, std::vector<raw::ChannelID_t>>(trkid, chvec));
525  }
526  Trk2ChVecMap.at(trkid).push_back(ch1);
527  selectThisChannel = true;
528  }
529  }
530  } // loop over Trk2WSinfoMap
531  if (selectThisChannel) {
532  Ch2TrkWSInfoMap.insert(
533  std::pair<raw::ChannelID_t, std::map<int, WireSigInfo>>(ch1, Trk2WSInfoMap));
534  }
535  } // if Trk2WSInfoMap not empty
536 
537  } // loop over SimChannels
538 
539  std::set<raw::ChannelID_t> selected_channels;
540 
541  // ... Now write out the signal waveforms for each track
542  if (!Trk2ChVecMap.empty()) {
543  // .. first put each pair of the map in a new vector of pairs, then randomly shuffle that vector;
544  // after that loop over the shuffled vector of pairs
545  using trk2chvecpair = std::pair<const int, std::vector<raw::ChannelID_t>>;
546  std::vector<const trk2chvecpair*> tchpv;
547  for (auto const& ittrk : Trk2ChVecMap) {
548  tchpv.emplace_back(&ittrk);
549  }
550  auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
551  std::shuffle(std::begin(tchpv), std::end(tchpv), std::mt19937(seed));
552 
553  int signalchancount = 0;
554  for (auto const& itpr : tchpv) {
555  if (signalchancount == fMaxSignalChannelsPerEvent) break;
556  int i = fRandFlat.fireInt(
557  itpr->second.size()); // randomly select one channel with a signal from this particle
558  chnum = itpr->second[i];
559 
560  if (not selected_channels.insert(chnum).second) { continue; }
561 
562  std::map<raw::ChannelID_t, std::map<int, WireSigInfo>>::iterator itchn;
563  itchn = Ch2TrkWSInfoMap.find(chnum);
564  if (itchn != Ch2TrkWSInfoMap.end()) {
565 
566  std::vector<short> adcvec(dataSize); // vector to hold zero-padded full waveform
567 
568  auto search = rawdigitMap.find(chnum);
569  if (search == rawdigitMap.end()) continue;
570  art::Ptr<raw::RawDigit> rawdig = (*search).second;
571  std::vector<short> rawadc(dataSize); // vector to hold uncompressed adc values later
572  raw::Uncompress(rawdig->ADCs(), rawadc, rawdig->GetPedestal(), rawdig->Compression());
573  for (size_t j = 0; j < rawadc.size(); ++j) {
574  adcvec[j] = rawadc[j] - rawdig->GetPedestal();
575  }
576 
577  std::vector<short> adcvec2(
578  dataSize); // vector to hold zero-padded full signal-only waveform
579 
580  auto search2 = rawdigitMap2.find(chnum);
581  if (search2 == rawdigitMap2.end()) continue;
582  art::Ptr<raw::RawDigit> rawdig2 = (*search2).second;
583  raw::Uncompress(rawdig2->ADCs(), rawadc, rawdig2->GetPedestal(), rawdig2->Compression());
584  for (size_t j = 0; j < rawadc.size(); ++j) {
585  adcvec2[j] = rawadc[j] - rawdig2->GetPedestal();
586  }
587 
588  // .. write out info for each peak
589  // a full waveform has at least one peak; the output will save up to 5 peaks (if there is
590  // only 1 peak, will fill the other 4 with 0);
591  // for fShortWaveformSize: only use the first peak's start_tick
592 
593  if (fUseFullWaveform) {
594 
595  c2numpy_uint32(&npywriter, evt.id().event());
596  c2numpy_uint32(&npywriter, chnum);
599  c2numpy_uint16(&npywriter, itchn->second.size()); // size of Trk2WSInfoMap, or #peaks
600  unsigned int icnt = 0;
601  for (auto& it : itchn->second) {
602  c2numpy_int32(&npywriter, it.first); // trackid
603  c2numpy_int32(&npywriter, it.second.pdgcode); // pdgcode
604  c2numpy_string(&npywriter, it.second.genlab.c_str()); // genlab
605  c2numpy_string(&npywriter, it.second.procid.c_str()); // procid
606  c2numpy_float32(&npywriter, it.second.edep); // edepo
607  c2numpy_uint32(&npywriter, it.second.numel); // numelec
608 
609  c2numpy_uint16(&npywriter, it.second.tdcmin); // stck1
610  c2numpy_uint16(&npywriter, it.second.tdcmax); // stck2
611  c2numpy_int32(&npywriter, it.second.tdcpeak); // pktdc
612  c2numpy_int32(&npywriter, it.second.adcpeak); // pkadc
613 
614  icnt++;
615  if (icnt == 5) break;
616  }
617 
618  // .. pad with 0's if number of peaks less than 5
619  for (unsigned int i = icnt; i < 5; ++i) {
622  c2numpy_string(&npywriter, dummystr6.c_str());
623  c2numpy_string(&npywriter, dummystr7.c_str());
630  }
631 
632  for (unsigned int itck = 0; itck < dataSize; ++itck) {
633  c2numpy_int16(&npywriter, adcvec[itck]);
634  }
635  for (unsigned int itck = 0; itck < dataSize; ++itck) {
636  c2numpy_int16(&npywriter2, adcvec2[itck]);
637  }
638  ++signalchancount;
639  }
640  else {
641 
642  // .. first loop to find largest signal
643  double EDep = 0.;
644  unsigned int TDCMin, TDCMax;
645  bool foundmaxsig = false;
646  for (auto& it : itchn->second) {
647  if (it.second.edep > EDep && it.second.adcpeak != 0 && it.second.numel > 0) {
648  EDep = it.second.edep;
649  TDCMin = it.second.tdcmin;
650  TDCMax = it.second.tdcmax;
651  foundmaxsig = true;
652  }
653  }
654  if (foundmaxsig) {
655  int sigtdc1, sigtdc2, sighwid, sigfwid, sigtdcm;
657  sigtdc1 = TDCMin - fEstIndFWForOffset / 2;
658  sigtdc2 = TDCMax + 3 * fEstIndFWForOffset / 2;
659  }
660  else {
661  sigtdc1 = TDCMin - fEstColFWForOffset / 2;
662  sigtdc2 = TDCMax + fEstColFWForOffset / 2;
663  }
664  sigfwid = sigtdc2 - sigtdc1;
665  sighwid = sigfwid / 2;
666  sigtdcm = sigtdc1 + sighwid;
667 
668  int start_tick = -1;
669  int end_tick = -1;
670  // .. set window edges to contain the largest signal
671  if (sigfwid < (int)fShortWaveformSize) {
672  // --> case 1: signal range fits within window
673  int dt = fShortWaveformSize - sigfwid;
674  start_tick = sigtdc1 - dt * fRandFlat.fire(0, 1);
675  }
676  else {
677  // --> case 2: signal range larger than window
678  int mrgn = fShortWaveformSize / 20;
679  int dt = fShortWaveformSize - 2 * mrgn;
680  start_tick = sigtdcm - mrgn - dt * fRandFlat.fire(0, 1);
681  }
682  if (start_tick < 0) start_tick = 0;
683  end_tick = start_tick + fShortWaveformSize - 1;
684  if (end_tick > int(dataSize - 1)) {
685  end_tick = dataSize - 1;
686  start_tick = end_tick - fShortWaveformSize + 1;
687  }
688 
689  c2numpy_uint32(&npywriter, evt.id().event());
690  c2numpy_uint32(&npywriter, chnum);
693 
694  // .. second loop to select only signals that are within the window
695 
696  int it_trk[5], it_pdg[5], it_nel[5], pk_tdc[5], pk_adc[5];
697  unsigned int stck_1[5], stck_2[5];
698  std::string it_glb[5], it_prc[5];
699  double it_edp[5];
700 
701  unsigned int icnt = 0;
702 
703  for (auto& it : itchn->second) {
704  if (abs(it.second.adcpeak) < fMinPureSignalADCs) continue;
705  if ((it.second.tdcmin >= (unsigned int)start_tick &&
706  it.second.tdcmin < (unsigned int)end_tick) ||
707  (it.second.tdcmax > (unsigned int)start_tick &&
708  it.second.tdcmax <= (unsigned int)end_tick)) {
709 
710  it_trk[icnt] = it.first;
711  it_pdg[icnt] = it.second.pdgcode;
712  it_glb[icnt] = it.second.genlab;
713  it_prc[icnt] = it.second.procid;
714  it_edp[icnt] = it.second.edep;
715  it_nel[icnt] = it.second.numel;
716 
717  unsigned int mintdc = it.second.tdcmin;
718  unsigned int maxtdc = it.second.tdcmax;
719  if (mintdc < (unsigned int)start_tick) mintdc = start_tick;
720  if (maxtdc > (unsigned int)end_tick) maxtdc = end_tick;
721 
722  stck_1[icnt] = mintdc - start_tick;
723  stck_2[icnt] = maxtdc - start_tick;
724  pk_tdc[icnt] = it.second.tdcpeak - start_tick;
725  pk_adc[icnt] = it.second.adcpeak;
726 
727  icnt++;
728  if (icnt == 5) break;
729  }
730  }
731 
732  c2numpy_uint16(&npywriter, icnt); // number of peaks
733 
734  for (unsigned int i = 0; i < icnt; ++i) {
735  c2numpy_int32(&npywriter, it_trk[i]); // trackid
736  c2numpy_int32(&npywriter, it_pdg[i]); // pdgcode
737  c2numpy_string(&npywriter, it_glb[i].c_str()); // genlab
738  c2numpy_string(&npywriter, it_prc[i].c_str()); // procid
739  c2numpy_float32(&npywriter, it_edp[i]); // edepo
740  c2numpy_uint32(&npywriter, it_nel[i]); // numelec
741  c2numpy_uint16(&npywriter, stck_1[i]); // stck1
742  c2numpy_uint16(&npywriter, stck_2[i]); // stck2
743  c2numpy_int32(&npywriter, pk_tdc[i]); // pktdc
744  c2numpy_int32(&npywriter, pk_adc[i]); // pkadc
745  }
746 
747  // .. pad with 0's if number of peaks less than 5
748  for (unsigned int i = icnt; i < 5; ++i) {
751  c2numpy_string(&npywriter, dummystr6.c_str());
752  c2numpy_string(&npywriter, dummystr7.c_str());
759  }
760 
761  for (unsigned int itck = start_tick; itck < (start_tick + fShortWaveformSize);
762  ++itck) {
763  c2numpy_int16(&npywriter, adcvec[itck]);
764  }
765  for (unsigned int itck = start_tick; itck < (start_tick + fShortWaveformSize);
766  ++itck) {
767  c2numpy_int16(&npywriter2, adcvec2[itck]);
768  }
769  ++signalchancount;
770  } // foundmaxsig
771  }
772  }
773  }
774  }
775  }
776  else {
777  //save noise
778  int noisechancount = 0;
779  std::map<raw::ChannelID_t, bool> signalMap;
780  for (auto const& channel : (*simChannelHandle)) {
781  signalMap[channel.Channel()] = true;
782  }
783  // .. create a vector for shuffling the wire channel indices
784  auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
785  std::vector<size_t> randigitmap;
786  for (size_t i = 0; i < rawdigitlist.size(); ++i)
787  randigitmap.push_back(i);
788  std::shuffle(randigitmap.begin(), randigitmap.end(), std::mt19937(seed));
789 
790  for (size_t rdIter = 0; rdIter < rawdigitlist.size(); ++rdIter) {
791 
792  if (noisechancount == fMaxNoiseChannelsPerEvent) break;
793 
794  std::vector<float> adcvec(dataSize); // vector to wire adc values
795 
796  size_t ranIdx = randigitmap[rdIter];
797  art::Ptr<raw::RawDigit> digitVec(digitVecHandle, ranIdx);
798  if (signalMap[digitVec->Channel()]) continue;
799 
800  std::vector<short> rawadc(dataSize); // vector to hold uncompressed adc values later
802  continue;
803  raw::Uncompress(digitVec->ADCs(), rawadc, digitVec->GetPedestal(), digitVec->Compression());
804  for (size_t j = 0; j < rawadc.size(); ++j) {
805  adcvec[j] = rawadc[j] - digitVec->GetPedestal();
806  }
807  c2numpy_uint32(&npywriter, evt.id().event());
808  c2numpy_uint32(&npywriter, digitVec->Channel());
810  geo::PlaneGeo::ViewName(fWireReadoutGeom->View(digitVec->Channel())).c_str());
811 
812  c2numpy_uint16(&npywriter, 0); //number of peaks
813  for (unsigned int i = 0; i < 5; ++i) {
816  c2numpy_string(&npywriter, dummystr6.c_str());
817  c2numpy_string(&npywriter, dummystr7.c_str());
824  }
825 
826  if (fUseFullWaveform) {
827  for (unsigned int itck = 0; itck < dataSize; ++itck) {
828  c2numpy_int16(&npywriter, short(adcvec[itck]));
829  }
830  }
831  else {
832  int start_tick = int((dataSize - fShortWaveformSize) * fRandFlat.fire(0, 1));
833  for (unsigned int itck = start_tick; itck < (start_tick + fShortWaveformSize); ++itck) {
834  c2numpy_int16(&npywriter, short(adcvec[itck]));
835  }
836  }
837 
838  ++noisechancount;
839  }
840  std::cout << "Total number of noise channels " << noisechancount << std::endl;
841  }
842 }
double E(const int i=0) const
Definition: MCParticle.h:234
float GetPedestal() const
Definition: RawDigit.h:221
int c2numpy_init(c2numpy_writer *writer, const std::string outputFilePrefix, int32_t numRowsPerFile)
Definition: c2numpy.h:140
base_engine_t & createEngine(seed_t seed)
bool has_gen(std::string gname)
int c2numpy_int32(c2numpy_writer *writer, int32_t data)
Definition: c2numpy.h:298
const ADCvector_t & ADCs() const
Reference to the compressed ADC count vector.
Definition: RawDigit.h:209
int PdgCode() const
Definition: MCParticle.h:213
ULong64_t Samples() const
Number of samples in the uncompressed ADC data.
Definition: RawDigit.h:217
c2numpy_type
Definition: c2numpy.h:29
static std::string ViewName(View_t view)
Returns the name of the specified view.
Definition: PlaneGeo.cxx:584
void add(const int &track_id, const std::string &gname)
Declaration of signal hit object.
ChannelID_t Channel() const
DAQ channel this raw data was read from.
Definition: RawDigit.h:213
constexpr auto abs(T v)
Returns the absolute value of the argument.
Definition of basic raw digits.
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
std::string Process() const
Definition: MCParticle.h:216
Particle class.
RunNumber_t run() const
Definition: EventID.h:98
int c2numpy_close(c2numpy_writer *writer)
Definition: c2numpy.h:425
std::pair< int, std::string > track_id_to_string
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::string fDigitModuleLabel
module that made digits
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
long seed
Definition: chem4.cc:67
geo::WireReadoutGeom const * fWireReadoutGeom
Interface for a class providing readout channel mapping to geometry.
Collect all the RawData header files together.
std::vector< track_id_to_string > track_id_map
Definition: EmTrack.h:40
RawWaveformClnSigDump(fhicl::ParameterSet const &p)
int c2numpy_uint32(c2numpy_writer *writer, uint32_t data)
Definition: c2numpy.h:334
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
std::string fSimChannelLabel
module that made simchannels
std::string fSimulationProducerLabel
producer that tracked simulated part. through detector
int c2numpy_float32(c2numpy_writer *writer, float data)
Definition: c2numpy.h:369
raw::Compress_t Compression() const
Compression algorithm used to store the ADC counts.
Definition: RawDigit.h:229
std::set< std::string > generator_names
simb::MCParticle TrackIdToMotherParticle(int const id) const
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Encapsulate the construction of a single detector plane .
View_t View(raw::ChannelID_t const channel) const
Returns the view (wire orientation) on the specified TPC channel.
void analyze(art::Event const &e) override
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
Declaration of basic channel signal object.
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
std::string fCleanSignalDigitModuleLabel
module that made the signal-only digits
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
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
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:82
std::string get_gen(int tid)
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
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
art::ServiceHandle< cheat::ParticleInventoryService > PIS
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const