RawWaveformDump_module.cc
Go to the documentation of this file.
1 #include <random>
2 
3 // Framework includes
12 #include "canvas/Persistency/Common/FindManyP.h"
13 #include "fhiclcpp/ParameterSet.h"
15 
16 // LArSoft libraries
19 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
24 #include "lardataobj/RawData/raw.h"
28 
29 // DUNETPC specific includes
30 //#include "dune/DAQTriggerSim/TriggerDataProducts/TriggerTypes.h"
31 //#include "dune/DAQTriggerSim/TriggerDataProducts/BasicTrigger.h"
32 #include "dune/DuneInterface/Data/AdcTypes.h"
33 #include "dune/DuneInterface/Service/SimChannelExtractService.h"
34 
35 #include "c2numpy.h"
36 
37 using std::string;
38 using std::cout;
39 using std::endl;
40 using std::ofstream;
41 
42 struct WireSigInfo {
43  int pdgcode;
46  unsigned int tdcmin;
47  unsigned int tdcmax;
48  int numel;
49  double edep;
50 };
51 
52 namespace pdune {
53  class RawWaveformDump;
54 }
55 
57 
58 public:
59 
60  explicit RawWaveformDump(fhicl::ParameterSet const& p);
61 
62  // Plugins should not be copied or assigned.
63  RawWaveformDump(RawWaveformDump const&) = delete;
64  RawWaveformDump(RawWaveformDump&&) = delete;
65  RawWaveformDump& operator=(RawWaveformDump const&) = delete;
66  RawWaveformDump& operator=(RawWaveformDump&&) = delete;
67 
68  // Required functions.
69  void analyze(art::Event const& e) override;
70 
71  void reconfigure(fhicl::ParameterSet const & p);
72 
73  void beginJob() override;
74  void endJob() override;
75 
76 private:
77 
79 
80  std::string fSimulationProducerLabel; ///< The name of the producer that tracked simulated particles through the detector
81  std::string fDigitModuleLabel; ///< module that made digits
82 
93  //art::ServiceHandle<SimChannelExtractService> m_pscx;
94 
95  std::default_random_engine rndm_engine;
96 
98 };
99 
100 //-----------------------------------------------------------------------
101 struct genFinder{
102  private:
103  typedef std::pair<int, std::string> track_id_to_string;
104  std::vector<track_id_to_string> track_id_map;
105  std::set<std::string> generator_names;
106  bool isSorted=false;
107 
108  public:
109  void sort_now(){
110  std::sort(this->track_id_map.begin(), this->track_id_map.end(), [](const auto &a, const auto &b){return (a.first < b.first) ; } );
111  isSorted=true;
112  }
113  void add(const int& track_id, const std::string& gname){
114  this->track_id_map.push_back(std::make_pair(track_id, gname));
115  generator_names.emplace(gname);
116  isSorted=false;
117  }
118  bool has_gen(std::string gname){
119  return static_cast<bool>(generator_names.count(gname));
120  };
122  if( !isSorted ){
123  this->sort_now();
124  }
125  return std::lower_bound(track_id_map.begin(), track_id_map.end(), tid,[](const auto &a, const auto &b){return (a.first < b) ; } )->second;
126  };
127 
128 };
130 
131 //-----------------------------------------------------------------------
133  : EDAnalyzer{p}
134 {
135  this->reconfigure(p);
136 }
137 
138 //-----------------------------------------------------------------------
140 {
141  fDumpWaveformsFileName = p.get<std::string>("DumpWaveformsFileName","dumpwaveforms");
142 
143  fSimulationProducerLabel = p.get<std::string>("SimulationProducerLabel", "largeant");
144  fDigitModuleLabel = p.get<std::string>("DigitModuleLabel", "daq");
145 
146  fSelectGenLabel = p.get<std::string>("SelectGenLabel","ANY");
147  fSelectProcID = p.get<std::string>("SelectProcID", "ANY");
148  fSelectPDGCode = p.get<int>("SelectPDGCode", 0);
149 
150  fPlaneToDump = p.get<std::string>("PlaneToDump", "U");
151  fMinParticleEnergyGeV = p.get<double>("MinParticleEnergyGeV",0.);
152  fMinEnergyDepositedMeV = p.get<double>("MinEnergyDepositedMeV",0.);
153  fMinNumberOfElectrons = p.get<int>("MinNumberOfElectrons",1000);
154  fMaxNumberOfElectrons = p.get<int>("MaxNumberOfElectrons",100000);
155 
156  return;
157 }
158 
159 //-----------------------------------------------------------------------
161 {
162  std::random_device rndm_device; // this will give us our seed
163  rndm_engine.seed(rndm_device());
164 
168  c2numpy_addcolumn(&npywriter, "view", (c2numpy_type)((int)C2NUMPY_STRING + 1) );
170 
171  for(unsigned int i=0; i<5; i++){
172  std::ostringstream name;
173 
174  name.str("");
175  name << "tid" << i;
176  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT32);
177 
178  name.str("");
179  name << "pdg" << i;
180  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT32);
181 
182  name.str("");
183  name << "gen" << i;
184  c2numpy_addcolumn(&npywriter, name.str().c_str(), (c2numpy_type)((int)C2NUMPY_STRING + 6));
185 
186  name.str("");
187  name << "pid" << i;
188  c2numpy_addcolumn(&npywriter, name.str().c_str(), (c2numpy_type)((int)C2NUMPY_STRING + 7));
189 
190  name.str("");
191  name << "edp" << i;
192  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_FLOAT32);
193 
194  name.str("");
195  name << "nel" << i;
196  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_UINT32);
197 
198  name.str("");
199  name << "sti" << i;
200  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_UINT16);
201 
202  name.str("");
203  name << "stf" << i;
204  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_UINT16);
205  }
206 
207  for(unsigned int i=0; i<6000; i++){
208  std::ostringstream name;
209  name << "tck_" << i;
210  c2numpy_addcolumn(&npywriter, name.str().c_str(), C2NUMPY_INT16);
211  }
212 }
213 
214 //-----------------------------------------------------------------------
216 {
218 }
219 
220 //-----------------------------------------------------------------------
222 {
223  cout << "Event "
224  << " " << evt.id().run()
225  << " " << evt.id().subRun()
226  << " " << evt.id().event() << endl;
227 
228  // ... Read in the digit List object(s).
229  auto digitVecHandle = evt.getHandle< std::vector<raw::RawDigit> >(fDigitModuleLabel);
230 
231  if (!digitVecHandle || !digitVecHandle->size()) return;
232 
233  // ... Use the handle to get a particular (0th) element of collection.
234  art::Ptr<raw::RawDigit> digitVec0(digitVecHandle, 0);
235  unsigned int dataSize = digitVec0->Samples(); //size of raw data vectors
236  if (dataSize!=6000){
237  std::cout << "!!!!! Bad dataSize: " << dataSize << std::endl;
238  return;
239  }
240 
241  std::vector<short> rawadc(dataSize); // vector to hold uncompressed adc values later
242 
243  // ... Build a map from channel number -> rawdigitVec
244  std::map< raw::ChannelID_t, art::Ptr<raw::RawDigit> > rawdigitMap;
245  raw::ChannelID_t chnum = raw::InvalidChannelID; // channel number
246  for ( size_t rdIter = 0; rdIter < digitVecHandle->size(); ++rdIter ) {
247  art::Ptr<raw::RawDigit> digitVec(digitVecHandle, rdIter);
248  chnum = digitVec->Channel();
249  if(chnum==raw::InvalidChannelID)continue;
250  rawdigitMap[chnum]=digitVec;
251  }
252 
253  // ... Read in MC particle list
254  auto particleHandle = evt.getHandle< std::vector<simb::MCParticle> >(fSimulationProducerLabel);
255  if (!particleHandle){
256  throw cet::exception("AnalysisExample")
257  << " No simb::MCParticle objects in this event - "
258  << " Line " << __LINE__ << " in file " << __FILE__ << std::endl;
259  }
260 
261  // ... Read in sim channel list
262  auto simChannelHandle = evt.getValidHandle<std::vector<sim::SimChannel>>(fSimulationProducerLabel);
263 
264  if (!simChannelHandle->size()) return;
265 
266  // ... Create a map of track IDs to generator labels
267  //Get a list of generator names.
268  auto mcHandles = evt.getMany<std::vector<simb::MCTruth>>();
269  std::vector< std::pair<int, std::string>> track_id_to_label;
270 
271  for( auto const& mcHandle : mcHandles ){
272  const std::string& sModuleLabel = mcHandle.provenance()->moduleLabel();
273  art::FindManyP<simb::MCParticle> findMCParts(mcHandle, evt, "largeant");
274  std::vector<art::Ptr<simb::MCParticle> > mcParts = findMCParts.at(0);
275  for( const art::Ptr<simb::MCParticle> ptr : mcParts){
276  int track_id = ptr->TrackId();
277  gf->add(track_id, sModuleLabel);
278  }
279  }
280 
281  std::string dummystr6="none ";
282  std::string dummystr7="none ";
283 
284  // .. create a channel number to trackid-wire signal info map
285  std::map<raw::ChannelID_t,std::map<int,WireSigInfo>>Ch2TrkWSInfoMap;
286 
287  // .. create a track ID to vector of channel numbers (in w/c this track deposited energy) map
288  std::map<int,std::vector<raw::ChannelID_t>>Trk2ChVecMap;
289 
290  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(evt);
291  // ... Loop over simChannels
292  for ( auto const& channel : (*simChannelHandle) ){
293 
294  // .. get simChannel channel number
295  const raw::ChannelID_t ch1 = channel.Channel();
296  if(ch1==raw::InvalidChannelID)continue;
297  if(geo::PlaneGeo::ViewName(fgeom->View(ch1))!=fPlaneToDump[0])continue;
298 
299  bool selectThisChannel=false;
300 
301  // .. create a track ID to wire signal info map
302  std::map<int,WireSigInfo>Trk2WSInfoMap;
303 
304  // ... Loop over all ticks with ionization energy deposited
305  auto const& timeSlices = channel.TDCIDEMap();
306  for ( auto const& timeSlice : timeSlices ){
307 
308  auto const& energyDeposits = timeSlice.second;
309  auto const tpctime = timeSlice.first;
310  unsigned int tdctick = static_cast<unsigned int>(clockData.TPCTDC2Tick(double(tpctime)));
311  if(tdctick!=tpctime)std::cout << "tpctime: " << tpctime << ", tdctick: " << tdctick << std::endl;
312  if(tdctick<0||tdctick>(dataSize-1))continue;
313 
314  // ... Loop over all energy depositions in this tick
315  for ( auto const& energyDeposit : energyDeposits ){
316 
317  if (!energyDeposit.trackID) continue;
318  int trkid = energyDeposit.trackID;
319  simb::MCParticle particle = PIS->TrackIdToMotherParticle(trkid);
320  std::cout << energyDeposit.trackID << " " << trkid << " " << particle.TrackId() << std::endl;
321 
322  // .. ignore this energy deposition if incident particle energy below some threshold
323  if ( particle.E() < fMinParticleEnergyGeV ) continue;
324 
325  int eve_id = PIS->TrackIdToEveTrackId(trkid);
326  if (!eve_id) continue;
327  std::string genlab = gf->get_gen(eve_id);
328 
329  if (Trk2WSInfoMap.find(trkid) == Trk2WSInfoMap.end()){
330  WireSigInfo wsinf;
331  wsinf.pdgcode = particle.PdgCode();
332  wsinf.genlab = genlab;
333  wsinf.procid = particle.Process();
334  wsinf.tdcmin=dataSize-1;
335  wsinf.tdcmax=0;
336  wsinf.edep=0.;
337  wsinf.numel=0;
338  Trk2WSInfoMap.insert(std::pair<int,WireSigInfo>(trkid,wsinf));
339  }
340  if (tdctick<Trk2WSInfoMap.at(trkid).tdcmin)Trk2WSInfoMap.at(trkid).tdcmin=tdctick;
341  if (tdctick>Trk2WSInfoMap.at(trkid).tdcmax)Trk2WSInfoMap.at(trkid).tdcmax=tdctick;
342  Trk2WSInfoMap.at(trkid).edep +=energyDeposit.energy;
343  Trk2WSInfoMap.at(trkid).numel+=energyDeposit.numElectrons;
344  }
345  }
346 
347  if(!Trk2WSInfoMap.empty()){
348  for(std::pair<int,WireSigInfo> itmap : Trk2WSInfoMap){
349  if (fSelectGenLabel!="ANY"){
350  if(itmap.second.genlab!=fSelectGenLabel)continue;
351  }
352  if (fSelectProcID!="ANY"){
353  if(itmap.second.procid!=fSelectProcID)continue;
354  }
355  if (fSelectPDGCode!=0){
356  if(itmap.second.pdgcode!=fSelectPDGCode)continue;
357  }
358  itmap.second.genlab.resize(6,' ');
359  itmap.second.procid.resize(7,' ');
360  if(itmap.second.numel>=fMinNumberOfElectrons && itmap.second.edep>=fMinEnergyDepositedMeV){
361  if(fMaxNumberOfElectrons>=0 && itmap.second.numel>=fMaxNumberOfElectrons){
362  continue;
363  } else {
364  int trkid = itmap.first;
365  if (Trk2ChVecMap.find(trkid) == Trk2ChVecMap.end()){
366  std::vector<raw::ChannelID_t>chvec;
367  Trk2ChVecMap.insert(std::pair<int,std::vector<raw::ChannelID_t>>(trkid,chvec));
368  }
369  Trk2ChVecMap.at(trkid).push_back(ch1);
370  selectThisChannel=true;
371  }
372  }
373  } // loop over Trk2WSinfoMap
374  if(selectThisChannel){
375  Ch2TrkWSInfoMap.insert(std::pair<raw::ChannelID_t,std::map<int,WireSigInfo>>(ch1,Trk2WSInfoMap));
376  }
377  } // if Trk2WSInfoMap not empty
378 
379  } // loop over SimChannels
380 
381  // ... Now write out the signal waveforms for each track
382  if(!Trk2ChVecMap.empty()){
383  for(auto const& ittrk : Trk2ChVecMap){
384  std::uniform_int_distribution<int> rndm_dist(0,ittrk.second.size()-1);
385  int i = rndm_dist(rndm_engine); // randomly select one channel with a signal from this particle
386  chnum=ittrk.second[i];
387 
388  std::map<raw::ChannelID_t,std::map<int,WireSigInfo>>::iterator itchn;
389  itchn = Ch2TrkWSInfoMap.find(chnum);
390  if( itchn != Ch2TrkWSInfoMap.end() ){
391  auto search = rawdigitMap.find(chnum);
392  if ( search == rawdigitMap.end() ) continue;
393  art::Ptr<raw::RawDigit> rawdig = (*search).second;
394  raw::Uncompress(rawdig->ADCs(), rawadc, rawdig->GetPedestal(), rawdig->Compression());
395 
396  c2numpy_uint32(&npywriter, evt.id().event());
397  c2numpy_uint32(&npywriter, chnum);
399  c2numpy_uint16(&npywriter, itchn->second.size()); // size of Trk2WSInfoMap, or number of peaks
400 
401  // .. write out info for each peak
402  unsigned int icnt=0;
403  for ( auto const& it : itchn->second ){
404  c2numpy_int32(&npywriter, it.first); // trackid
405  c2numpy_int32(&npywriter, it.second.pdgcode); // pdgcode
406  c2numpy_string(&npywriter, it.second.genlab.c_str()); // genlab
407  c2numpy_string(&npywriter, it.second.procid.c_str()); // procid
408  c2numpy_float32(&npywriter, it.second.edep); // edepo
409  c2numpy_uint32(&npywriter, it.second.numel); // numelec
410  c2numpy_uint16(&npywriter, it.second.tdcmin); // stck1
411  c2numpy_uint16(&npywriter, it.second.tdcmax); // stc2
412  icnt++;
413  if(icnt==5)break;
414  }
415 
416  // .. pad with 0's if number of peaks less than 5
417  for ( unsigned int i=icnt; i<5; ++i){
420  c2numpy_string(&npywriter, dummystr6.c_str());
421  c2numpy_string(&npywriter, dummystr7.c_str());
426  }
427 
428  // .. now write out the ADC values
429  for ( unsigned int itck=0; itck<dataSize; ++itck ){
430  rawadc[itck] -= rawdig->GetPedestal();
431  c2numpy_int16(&npywriter, rawadc[itck]);
432  }
433  }
434  }
435  }
436 
437 }
def analyze(root, level, gtrees, gbranches, doprint)
Definition: rootstat.py:69
static QCString name
Definition: declinfo.cpp:673
double E(const int i=0) const
Definition: MCParticle.h:233
float GetPedestal() const
Definition: RawDigit.h:214
art::ServiceHandle< geo::Geometry > fgeom
bool has_gen(std::string gname)
int c2numpy_int32(c2numpy_writer *writer, int32_t data)
Definition: c2numpy.h:290
const ADCvector_t & ADCs() const
Reference to the compressed ADC count vector.
Definition: RawDigit.h:210
int c2numpy_init(c2numpy_writer *writer, const std::string outputFilePrefix, int32_t numRowsPerFile)
Definition: c2numpy.h:142
int PdgCode() const
Definition: MCParticle.h:212
static std::string ViewName(geo::View_t view)
Returns the name of the specified view.
Definition: PlaneGeo.cxx:763
ULong64_t Samples() const
Number of samples in the uncompressed ADC data.
Definition: RawDigit.h:213
std::string fDigitModuleLabel
module that made digits
int c2numpy_int16(c2numpy_writer *writer, int16_t data)
Definition: c2numpy.h:282
void add(const int &track_id, const std::string &gname)
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
ChannelID_t Channel() const
DAQ channel this raw data was read from.
Definition: RawDigit.h:212
uint8_t channel
Definition: CRTFragment.hh:201
std::string Process() const
Definition: MCParticle.h:215
int c2numpy_close(c2numpy_writer *writer)
Definition: c2numpy.h:407
Particle class.
int c2numpy_uint16(c2numpy_writer *writer, uint16_t data)
Definition: c2numpy.h:314
RunNumber_t run() const
Definition: EventID.h:98
art framework interface to geometry description
int TrackId() const
Definition: MCParticle.h:210
std::pair< int, std::string > track_id_to_string
int c2numpy_addcolumn(c2numpy_writer *writer, const std::string name, c2numpy_type type)
Definition: c2numpy.h:158
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
Definition: RawTypes.h:32
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
void beginJob()
Definition: Breakpoints.cc:14
virtual void reconfigure(fhicl::ParameterSet const &pset)
void analyze(art::Event const &e) override
const double a
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
Definition: DataViewImpl.h:479
T get(std::string const &key) const
Definition: ParameterSet.h:271
int c2numpy_uint32(c2numpy_writer *writer, uint32_t data)
Definition: c2numpy.h:322
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
Definition: DataViewImpl.h:441
p
Definition: test.py:223
Definition: search.py:1
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
int c2numpy_string(c2numpy_writer *writer, const char *data)
Definition: c2numpy.h:394
raw::Compress_t Compression() const
Compression algorithm used to store the ADC counts.
Definition: RawDigit.h:216
c2numpy_type
Definition: c2numpy.h:29
simb::MCParticle TrackIdToMotherParticle(int const id) const
Declaration of signal hit object.
Encapsulate the construction of a single detector plane.
RawWaveformDump(fhicl::ParameterSet const &p)
int c2numpy_float32(c2numpy_writer *writer, float data)
Definition: c2numpy.h:354
genFinder * gf
static bool * b
Definition: config.cpp:1043
std::string fSimulationProducerLabel
The name of the producer that tracked simulated particles through the detector.
EventNumber_t event() const
Definition: EventID.h:116
void reconfigure(fhicl::ParameterSet const &p)
TCEvent evt
Definition: DataStructs.cxx:7
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:776
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:85
art::ServiceHandle< cheat::ParticleInventoryService > PIS
std::default_random_engine rndm_engine
std::string get_gen(int tid)
SubRunNumber_t subRun() const
Definition: EventID.h:110
EventID id() const
Definition: Event.cc:34
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)