All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pmtTriggerProducer_module.cc
Go to the documentation of this file.
1 /*
2  File: pmtTriggerProducer_module.cc
3  Purpose: Simulates pmt hardware trigger
4  Author: Erin Yandel (eyandel@fnal.gov)
5  Date: October 26, 2021
6  Version: 1.0
7 
8  This is a module to simulate the PMT hardware trigger on simulated data.
9  It takes a largeant file with optical detectors waveforms and produces a
10  vector whose index is time within the trigger (beam) window and content
11  is number of PMT pairs passsing the trigger threshold.
12 
13  More information can be found at:
14  https://sbnsoftware.github.io/sbndcode_wiki/SBND_Trigger
15  and
16  sbn-docdb: 23922
17 
18  The trigger logic implemented currently:
19  - Turn raw OpDetWaveforms (in ADC) into binary waveforms (0=not above threshold, 1=above threshold)
20  - Downsample binary waveform by 4 (simulate 2ns rate, hardware reads every 8ns)
21  - Pair waveforms -> combine 2 downsampled waveforms based on parameters set in fhicl files
22  - Extend wavelength when a rising edge is seen
23  - Count the number of paired waveforms above threshold for various times within the trigger window
24 
25  Input:
26  - output from OpDetSim module (in particular, OpDetWaveforms)
27 
28  Output:
29  - std::vector<sbnd::comm::pmtTrigger> > : PMT trigger array
30 
31  fhicl: run_pmttriggerproducer.fcl
32 */
33 
34 // Framework includes
35 #include "art/Framework/Core/EDProducer.h"
36 #include "art/Framework/Core/ModuleMacros.h"
37 #include "art/Framework/Principal/Event.h"
38 #include "art/Framework/Principal/Handle.h"
39 #include "art/Framework/Principal/Run.h"
40 #include "art/Framework/Principal/SubRun.h"
41 #include "canvas/Utilities/InputTag.h"
42 #include "fhiclcpp/ParameterSet.h"
43 #include "canvas/Persistency/Common/Ptr.h"
44 #include "canvas/Persistency/Common/PtrVector.h"
45 #include "art/Framework/Services/Registry/ServiceHandle.h"
46 #include "art_root_io/TFileService.h"
47 #include "messagefacility/MessageLogger/MessageLogger.h"
48 #include "canvas/Utilities/Exception.h"
49 
50 // LArSoft includes
60 #include "lardataobj/RawData/raw.h"
61 
70 
71 // SBN/SBND includes
75 
76 // ROOT includes
77 #include "TH1D.h"
78 #include "TFile.h"
79 #include "TTree.h"
80 
81 // C++ includes
82 #include <algorithm>
83 #include <vector>
84 #include <cmath>
85 #include <memory>
86 #include <string>
87 
88 class pmtTriggerProducer: public art::EDProducer {
89 public:
90  // The destructor generated by the compiler is fine for classes
91  // without bare pointers or other resource use.
92  // Plugins should not be copied or assigned.
93  explicit pmtTriggerProducer(fhicl::ParameterSet const & p);
94  pmtTriggerProducer(pmtTriggerProducer const &) = delete;
98 
99  // Required functions.
100  void produce(art::Event & evt) override;
101  void reconfigure(fhicl::ParameterSet const & p);
102 
103  opdet::sbndPDMapAlg pdMap; //map for photon detector types
104 
105 private:
106  // Define producer-specific functions
107 
108 
109  // Define global variables
110  int run;
111  int subrun;
112  int event;
113  size_t fEvNumber;
114  size_t fChNumber; //channel number
115  double fSampling; //sampling rate
116  double fStartTime; //start time (in us) of raw waveform
117  double fEndTime; //end time (in us) of raw waveform
118 
119  // double fBaseline = 8000.0; //baseline ADC (set in simulation)
120  std::stringstream histname; //raw waveform hist name
121  std::stringstream histname2; //other hists names
122  std::string opdetType; //opdet wavform's opdet type (required to be pmt_coated or pmt_uncoated)
123 
124  std::vector<int> passed_trigger; //index =time (us, triger window only), content = number of pmt pairs passed threshold
125  int max_passed = 0; //maximum number of pmt pairs passing threshold at the same time within trigger window
126  std::vector<int> channel_numbers = {6,7,8,9,10,11,12,13,14,15,16,17,36,37,38,39,40,41,60,61,62,63,64,65,66,67,68,69,70,71,
127  84,85,86,87,88,89,90,91,92,93,94,95,114,115,116,117,118,119,138,139,140,141,142,143,144,145,146,147,148,149,
128  162,163,164,165,166,167,168,169,170,171,172,173,192,193,194,195,196,197,216,217,218,219,220,221,222,223,224,225,226,227,
129  240,241,242,243,244,245,246,247,248,249,250,251,270,271,272,273,274,275,294,295,296,297,298,299,300,301,302,303,304,305};
130  std::vector<std::vector<char>> channel_bin_wvfs;
131  std::vector<char> wvf_bin_0;
132  std::vector<char> paired;
133  std::vector<std::vector<char>> unpaired_wvfs;
134 
135  // List parameters for the fcl file
136  std::vector<double> fThreshold = {7960.0,7976.0}; //individual pmt threshold in ADC (set in fcl, passes if ADC is LESS THAN threshold), [coated, uncoated]
138  int fOVTHRWidth;//over-threshold width, page 40 of manual (set in fcl)
139  std::vector<int> fPair1 = {6,8,10,12,14,16,36,38,40,84,86,88,90,92,94,114,116,118,138,140,142,144,146,148,162,164,166,168,170,172,192,194,196,216,218,220,222,224,226,240,242,244,246,248,250,270,272,274,294,296}; //channel numbers for first set of paired pmts (set in fcl)
140  std::vector<int> fPair2 = {7,9,11,13,15,17,37,39,41,85,87,89,91,93,95,115,117,119,139,141,143,145,147,149,163,165,167,169,171,173,193,195,197,217,219,221,223,225,227,241,243,245,247,249,251,271,273,275,295,297}; //channel numbers for second set of paired pmts (set in fcl)
141  std::vector<int> fUnpaired = {298,299,300,301,302,303,304,305};//channel numbers for unpired pmts (set in fcl)
142  std::string fPairLogic;
143  double fWindowStart; //start time (in us) of trigger window (set in fcl, 0 for beam spill)
144  double fWindowEnd; //end time (in us) of trigger window (set in fcl, 1.6 for beam spill)
145  std::string fInputModuleName; //opdet waveform module name (set in fcl)
146  std::vector<std::string> fOpDetsToPlot = {"pmt_coated", "pmt_uncoated"}; //types of optical detetcors (e.g. "pmt_coated", "xarapuca_vuv", etc.), should only be pmt_coated and pmt_uncoated (set in fcl)
147  bool fSaveHists; //save raw, binary, etc. histograms (set in fcl)
148  std::vector<int> fEvHists = {1,2,3}; //if fSaveHists=true, which event hists to save? (set in fcl)
149  bool fVerbose; //true=output all cout statements, false=no non-error cout statements (set in fcl)
150 
151  // services
152  art::ServiceHandle<art::TFileService> tfs;
153 
154 }; // class pmtTriggerProducer
155 
156 pmtTriggerProducer::pmtTriggerProducer(fhicl::ParameterSet const & p)
157  : EDProducer(p)
158 {
159  produces< std::vector<sbnd::comm::pmtTrigger> >();
160 
161  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
162  fSampling = clockData.OpticalClock().Frequency(); // MHz
163  this->reconfigure(p);
164 }
165 
166 // Constructor
167 void pmtTriggerProducer::reconfigure(fhicl::ParameterSet const & p)
168 {
169  // Initialize member data here
170  fInputModuleName = p.get< std::string >("InputModule", "opdaq");
171  fOpDetsToPlot = p.get<std::vector<std::string> >("OpDetsToPlot");
172  fIndividualThresholds = p.get<bool>("IndividualThresholds",false);
173  fThreshold = p.get<std::vector<double> >("Threshold");
174  fOVTHRWidth = p.get<int>("OVTHRWidth",11);
175  fPair1 = p.get<std::vector<int> >("Pair1");
176  fPair2 = p.get<std::vector<int> >("Pair2");
177  fUnpaired = p.get<std::vector<int> >("Unpaired");
178  fPairLogic = p.get<std::string>("PairLogic","OR");
179  fWindowStart = p.get<double>("WindowStart",0.0);
180  fWindowEnd = p.get<double>("WindowEnd",1.8);
181  fSaveHists = p.get<bool>("SaveHists",true);
182  fEvHists = p.get<std::vector<int> >("EvHists");
183  fVerbose = p.get<bool>("Verbose", true);
184 
185 }
186 
187 void pmtTriggerProducer::produce(art::Event & e)
188 {
189  // load event info here:
190 
191  if (fVerbose){std::cout << "Processing event " << e.id().event() << std::endl;}
192 
193  std::unique_ptr< std::vector<sbnd::comm::pmtTrigger> > pmts_passed( new std::vector<sbnd::comm::pmtTrigger>);
194 
195  fEvNumber = e.id().event();
196  run = e.run();
197  subrun = e.subRun();
198  event = e.id().event();
199 
200  art::Handle< std::vector< raw::OpDetWaveform > > waveHandle;
201  e.getByLabel(fInputModuleName, waveHandle);
202 
203  if(!waveHandle.isValid()) {
204  std::cout << Form("Did not find any G4 photons from a producer: %s", "largeant") << std::endl;
205  }
206 
207  // // example of usage for pdMap.getCollectionWithProperty()
208  // //
209  // // define a container
210  // auto inBoxTwo = pdMap.getCollectionWithProperty("pds_box", 2);
211  // // you can cout the whole json object
212  // std::cout << "inBoxTwo:\t" << inBoxTwo << "\n";
213  // // traverse its components in a loop
214  // for (auto const &e: inBoxTwo) {
215  // std::cout << e["pd_type"] << " " << e["channel"] << ' ' << "\n";
216  // }
217 
218  // // example of usage for pdMap.getCollectionFromCondition()
219  // // define a lambda function with the conditions
220  // auto subsetCondition = [](auto const& e)->bool
221  // // modify conditions as you want in the curly braces below
222  // {return e["pd_type"] == "pmt_uncoated" && e["tpc"] == 0;};
223  // // get the container that satisfies the conditions
224  // auto uncoatedsInTPC0 = pdMap.getCollectionFromCondition(subsetCondition);
225  // std::cout << "uncoatedsInTPC0.size():\t" << uncoatedsInTPC0.size() << "\n";
226  // for(auto const& e:uncoatedsInTPC0){
227  // std::cout << "e:\t" << e << "\n";
228  // }
229 
230  // determine whether to this event should be plotted
231  int i_ev = -1;
232  auto iev = std::find(fEvHists.begin(), fEvHists.end(), fEvNumber);
233  if (iev != fEvHists.end() && fSaveHists){
234  i_ev = iev - fEvHists.begin();
235  }
236 
237  if (i_ev!=-1 && i_ev<4){if (fVerbose){std::cout << "Outputting Hists" << std::endl;}}
238 
239  max_passed = 0;
240 
241  int num_pmt_wvf = 0;
242  int num_pmt_ch = 0;
243 
244  if (fVerbose){
245  std::cout << "fOpDetsToPlot:\t";
246  for (auto const& opdet : fOpDetsToPlot){std::cout << opdet << " ";}
247  std::cout << std::endl;
248  }
249 
250  //find min and max start and end times to initialize all vectors to same full waveform length
251  double fMinStartTime = -1510.0;//in us
252  double fMaxEndTime = 1510.0;//in us
253 
254  for(auto const& wvf : (*waveHandle)) {
255  fChNumber = wvf.ChannelNumber();
257  if (std::find(fOpDetsToPlot.begin(), fOpDetsToPlot.end(), opdetType) == fOpDetsToPlot.end()) {continue;}
258  if (wvf.TimeStamp() < fMinStartTime){ fMinStartTime = wvf.TimeStamp(); }
259  if ((double(wvf.size()) / fSampling + wvf.TimeStamp()) > fMaxEndTime){ fMaxEndTime = double(wvf.size()) / fSampling + wvf.TimeStamp();}
260  }
261  if (fVerbose){std::cout<<"MinStartTime: "<<fMinStartTime<<" MaxEndTime: "<<fMaxEndTime<<std::endl;}
262 
263  wvf_bin_0.reserve(int((fMaxEndTime-fMinStartTime)/(1./fSampling)));
264  channel_bin_wvfs.reserve(120);
265  paired.reserve(fPair1.size());
266  unpaired_wvfs.reserve(fPair1.size());
267  passed_trigger.reserve(int((fWindowEnd-fWindowStart)/(4./fSampling)));
268 
269  // create a vector w/ the number of entries necessary for the sampling rate
270  // e.g. if sampling rate is 500 MHz, each bin has width of 0.002 us or 2 ns, vector length of ~75000
271  for (double i = fMinStartTime; i<fMaxEndTime+(1./fSampling); i+=(1./fSampling)){
272  wvf_bin_0.push_back(0);
273  }
274  for (size_t i = 0; i<120; i++){
275  channel_bin_wvfs.push_back(wvf_bin_0);
276  }
277  for (size_t i = 0; i<fPair1.size(); i++){
278  paired.push_back(0);
279  }
280  for (size_t i = 0; i<fPair1.size(); i++){
281  unpaired_wvfs.push_back(wvf_bin_0);
282  }
283  // window of the beam spill, 0.0 to 1.6 us
284  // e.g. if sampling rate is 500 MHz, each bin has width of 0.008 us or 8 ns
285  for (double i = fWindowStart; i<fWindowEnd+(4./fSampling); i+=(4./fSampling)){
286  passed_trigger.push_back(0);
287  }
288 
289 
290  if (fPair2.size()!=paired.size()){std::cout<<"Pair lists mismatched sizes!"<<std::endl;}
291 
292  size_t wvf_id = -1;
293  int hist_id = -1;
294  for(auto const& wvf : (*waveHandle)) {
295  wvf_id++;
296  hist_id++;
297  fChNumber = wvf.ChannelNumber();
299  if (std::find(fOpDetsToPlot.begin(), fOpDetsToPlot.end(), opdetType) == fOpDetsToPlot.end()) {continue;}
300  num_pmt_wvf++;
301 
302  fStartTime = wvf.TimeStamp(); //in us
303  fEndTime = double(wvf.size()) / fSampling + fStartTime; //in us
304 
305  //find threshold in ADC
306  double adc_threshold = 0;
307  if(fThreshold.size()>0){
308  adc_threshold = fThreshold.at(0); //if fIndividualThresholds=false, coated threshold
309  if (!fIndividualThresholds){
310  if (opdetType == "pmt_uncoated" && fThreshold.size()>1.){
311  adc_threshold = fThreshold.at(1); //if fIndividualThresholds=false, uncoated threshold
312  }
313  }else{
314  adc_threshold = fThreshold.at(num_pmt_wvf-1); //if fIndividualThresholds=true, pmt threshold
315  }
316  }else{
317  std::cout<<"Threshold Array Empty!"<<std::endl;
318  }
319  if(fVerbose){std::cout<<"Channel "<<fChNumber<<" is "<<opdetType<<" and is using theshold "<<adc_threshold<<" ADC."<<std::endl;}
320 
321  //create binary waveform
322  std::vector<char> wvf_bin;
323  wvf_bin.reserve(wvf.size());
324  // start histo
325  if (i_ev!=-1 && i_ev<3){
326  histname.str(std::string());
327  histname << "event_" << fEvNumber
328  << "_opchannel_" << fChNumber
329  << "_" << opdetType
330  << "_" << hist_id
331  << "_raw";
332  //Create a new histogram for binary waveform
333  TH1D *wvfHist = tfs->make< TH1D >(histname.str().c_str(), "Raw Waveform", wvf.size(), fStartTime, fEndTime);
334  wvfHist->GetXaxis()->SetTitle("t (#mus)");
335  for(unsigned int i = 0; i < wvf.size(); i++) {
336  wvfHist->SetBinContent(i + 1, (double)wvf[i]);
337  }
338  } // end histo
339 
340  if (fStartTime > fMinStartTime){
341  for (double i = fStartTime-fMinStartTime; i>0.; i-=(1./fSampling)){
342  wvf_bin.push_back(0);
343  }
344  }
345 
346  for(unsigned int i = 0; i < wvf.size(); i++) {
347  if((double)wvf[i]<adc_threshold){wvf_bin.push_back(1);}else{wvf_bin.push_back(0);}
348  }
349 
350  if (fEndTime < fMaxEndTime){
351  for (double i = fMaxEndTime-fEndTime; i>0.; i-=(1./fSampling)){
352  wvf_bin.push_back(0);
353  }
354  }
355 
356  //combine wavform with any other waveforms from same channel
357  int i_ch = -1.;
358  auto ich = std::find(channel_numbers.begin(), channel_numbers.end(), fChNumber);
359  if (ich != channel_numbers.end()){
360  i_ch = ich - channel_numbers.begin(); // the index for the channel of interest
361  }
362  // if the number of bins is mismatched
363  if (channel_bin_wvfs.at(i_ch).size() < wvf_bin.size()){
364  std::cout<<"Previous Channel" << fChNumber <<" Size: "<<channel_bin_wvfs.at(i_ch).size()<<"New Channel" << fChNumber <<" Size: "<<wvf_bin.size()<<std::endl;
365  for(unsigned int i = channel_bin_wvfs.at(i_ch).size(); i < wvf_bin.size(); i++) {
366  channel_bin_wvfs.at(i_ch).push_back(0);
367  }
368  }
369  for(unsigned int i = 0; i < wvf_bin.size(); i++) {
370  if(channel_bin_wvfs.at(i_ch).at(i)==1 || wvf_bin[i]==1){channel_bin_wvfs.at(i_ch)[i]=1;}else{channel_bin_wvfs.at(i_ch)[i]=0;}
371  }
372  wvf_bin.clear();
373  wvf_bin.shrink_to_fit();
374  waveHandle.clear();
375 
376  }//wave handle loop
377 
378  int wvf_num = -1;
379 
380  for (auto wvf_bin : channel_bin_wvfs){ // wvf_bin is a vector with entries making up the wvf, one for every channel
381  wvf_num++;
382  fChNumber = channel_numbers.at(wvf_num);
383  fStartTime = fMinStartTime;
384  fEndTime = fMaxEndTime;
385 
386  //downscale binary waveform by 4
387  std::vector<char> wvf_bin_down;
388  wvf_bin_down.reserve(int(wvf_bin.size()/4));
389  for(unsigned int i = 0; i < wvf_bin.size(); i++) {
390  if(i%4==0){wvf_bin_down.push_back(wvf_bin[i]);}
391  }
392 
393  num_pmt_ch++;
394 
395  if (i_ev!=-1 && i_ev<3){
396  histname2.str(std::string());
397  histname2 << "event_" << fEvNumber
398  << "_opchannel_" << fChNumber
399  << "_binary";
400  TH1D *wvfbHist = tfs->make< TH1D >(histname2.str().c_str(), "Binary Waveform", wvf_bin.size(), fStartTime, fEndTime);
401  wvfbHist->GetXaxis()->SetTitle("t (#mus)");
402  for(unsigned int i = 0; i < wvf_bin.size(); i++) {
403  wvfbHist->SetBinContent(i + 1, wvf_bin[i]);
404  }
405  }
406 
407  if (i_ev!=-1 && i_ev<3){
408  histname2.str(std::string());
409  histname2 << "event_" << fEvNumber
410  << "_opchannel_" << fChNumber
411  << "_binary_down";
412 
413  TH1D *wvfbdHist = tfs->make< TH1D >(histname2.str().c_str(), "Downsampled Binary Waveform", wvf_bin_down.size(), fStartTime, fEndTime);
414  wvfbdHist->GetXaxis()->SetTitle("t (#mus)");
415  for(unsigned int i = 0; i < wvf_bin_down.size(); i++) {
416  wvfbdHist->SetBinContent(i + 1, wvf_bin_down[i]);
417  }
418  }
419 
420  bool combine = false;
421  bool found = false;
422  bool unpaired = false;
423  size_t pair_num = -1;
424 
425  for (size_t i = 0; i < fUnpaired.size(); i++){
426  if (fUnpaired.at(i) == (int)fChNumber){found=true; unpaired=true;}
427  }
428 
429  if (!found){
430  // if a pmt is found in pair1 vector and has passed threshold (for some reason)
431  // set found == true, set pair_num = index of location in Pair1
432  for (size_t i = 0; i < fPair1.size(); i++){
433  if (fPair1.at(i) == (int)fChNumber && paired.at(i)==1){found=true; pair_num=i; combine=true; break;}
434  // else if pmt is found in pair1 vector and has not yet passed threshold,
435  // set found == true, set the corresponding channel's wvf equal to downscaled wvf in the unpaired vector
436  // should be paired now
437  else if (fPair1.at(i) == (int)fChNumber && paired.at(i)==0){found=true; unpaired_wvfs.at(i)=wvf_bin_down; paired.at(i)=1; break;}
438  }
439  if (!found){
440  // if still not found in pair1, check pair2 channels
441  for (size_t i = 0; i < fPair2.size(); i++){
442  if (fPair2.at(i) == (int)fChNumber && paired.at(i)==1){found=true; pair_num=i; combine=true; break;}
443  else if (fPair2.at(i) == (int)fChNumber && paired.at(i)==0){found=true; unpaired_wvfs.at(i)=wvf_bin_down; paired.at(i)=1; break;}
444  }
445  }
446  }
447 
448  //pair waveforms
449  if (combine || unpaired){
450  std::vector<char> wvf_combine;
451  wvf_combine.reserve(wvf_bin_down.size());
452  if (combine){
453  if (unpaired_wvfs.at(pair_num).size()!=wvf_bin_down.size()){std::cout<<"Mismatched paired waveform size"<<std::endl;}
454  for(unsigned int i = 0; i < wvf_bin_down.size(); i++) {
455  if (fPairLogic=="OR"){
456  if(unpaired_wvfs.at(pair_num)[i]==1 || wvf_bin_down[i]==1){wvf_combine.push_back(1);}else{wvf_combine.push_back(0);}
457  }else if (fPairLogic=="AND"){
458  if(unpaired_wvfs.at(pair_num)[i]==1 && wvf_bin_down[i]==1){wvf_combine.push_back(1);}else{wvf_combine.push_back(0);}
459  }
460  }
461  }else if(unpaired){
462  wvf_combine = wvf_bin_down;
463  }
464 
465  if (i_ev!=-1 && i_ev<3){
466  histname2.str(std::string());
467  if (unpaired){
468  histname2 << "event_" << fEvNumber
469  << "_opchannels_" << fChNumber
470  << "_unpaired"
471  << "_combined";
472  }else{
473  histname2 << "event_" << fEvNumber
474  << "_opchannels_" << fPair1.at(pair_num)
475  << "_" << fPair2.at(pair_num)
476  << "_combined";
477  }
478 
479  TH1D *wvfcHist = tfs->make< TH1D >(histname2.str().c_str(), "Paired Waveform", wvf_combine.size(), fStartTime, fEndTime);
480  wvfcHist->GetXaxis()->SetTitle("t (#mus)");
481  for(unsigned int i = 0; i < wvf_combine.size(); i++) {
482  wvfcHist->SetBinContent(i + 1, wvf_combine[i]);
483  }
484  }
485 
486  //implement over threshold trigger signal width
487  //(Every time the combined waveform transitions from 0 to 1, change the next fOVTHRWidth values to 1 (ex: fOVTHRWidth=11 -> 12 high -> 12*8=96 ns true) )
488  for(unsigned int i = 1; i < wvf_combine.size()-fOVTHRWidth; i++) {
489  if(wvf_combine[i]==1 && wvf_combine[i-1]==0){
490  for(unsigned int j = i+1; j < i+fOVTHRWidth+1; j++){
491  wvf_combine[j] = 1;
492  }
493  }
494  }
495 
496  if (i_ev!=-1 && i_ev<3){
497  histname2.str(std::string());
498  if (unpaired){
499  histname2 << "event_" << fEvNumber
500  << "_opchannels_" << fChNumber
501  << "_unpaired"
502  << "_combined_width";
503  }else{
504  histname2 << "event_" << fEvNumber
505  << "_opchannels_" << fPair1.at(pair_num)
506  << "_" << fPair2.at(pair_num)
507  << "_combined_width";
508  }
509 
510  TH1D *wvfcwHist = tfs->make< TH1D >(histname2.str().c_str(), "Over Threshold Paired Waveform", wvf_combine.size(), fStartTime, fEndTime);
511  wvfcwHist->GetXaxis()->SetTitle("t (#mus)");
512  for(unsigned int i = 0; i < wvf_combine.size(); i++) {
513  wvfcwHist->SetBinContent(i + 1, wvf_combine[i]);
514  }
515  }
516 
517  //Combine the waveforms to get a 1D array of integers where the value corresponds to the number of pairs ON and the
518  //index corresponds to the tick in the waveform
519  double binspermus = wvf_combine.size()/(fEndTime-fStartTime);
520  unsigned int startbin = std::floor(binspermus*(fWindowStart - fStartTime));
521  unsigned int endbin = std::ceil(binspermus*(fWindowEnd - fStartTime));
522  if (startbin<0.){startbin=0;}
523  if (endbin > wvf_combine.size() - 1){endbin = wvf_combine.size() - 1;}
524  if (passed_trigger.size() < endbin-startbin){
525  for (unsigned int i = passed_trigger.size(); i<endbin; i++){
526  passed_trigger.push_back(0);
527  }
528  }
529  unsigned int i_p = 0;
530  for(unsigned int i = startbin; i<endbin; i++){
531  if (wvf_combine.at(i)==1){passed_trigger.at(i_p)++;}
532  i_p++;
533  }
534 
535  wvf_bin_down.clear();
536  wvf_bin_down.shrink_to_fit();
537  wvf_combine.clear();
538  wvf_combine.shrink_to_fit();
539 
540  }
541 
542  }
543 
544 
545  if (i_ev!=-1 && i_ev<3){
546  histname.str(std::string());
547  histname << "event_" << fEvNumber
548  << "_passed_trigger";
549 
550  TH1D *passedHist = tfs->make< TH1D >(histname.str().c_str(), "Number of PMTs Passing Trigger During Beam", passed_trigger.size(), fWindowStart, fWindowEnd+(4./fSampling));
551  passedHist->GetXaxis()->SetTitle("t (#mus)");
552  for(unsigned int i = 0; i < passed_trigger.size(); i++) {
553  passedHist->SetBinContent(i + 1, passed_trigger[i]);
554  }
555  }
556 
557  sbnd::comm::pmtTrigger pmt_time;
558 
559  for (int pmts: passed_trigger){
560  pmt_time.numPassed.push_back(pmts);
561  if (pmts > max_passed) max_passed = pmts;
562  }
563  pmt_time.maxPMTs = max_passed;
564  pmts_passed->push_back(pmt_time);
565 
566  if (fVerbose){std::cout << "Length of passed trigger: " << pmt_time.numPassed.size() << std::endl;}
567  if (fVerbose){std::cout << "Max number of PMTs passed: " << pmt_time.maxPMTs << std::endl;}
568 
569  // the following lines "push" the relevant products you want to produce
570  // EXAMPLE:
571  // evt.put(std::move(muon_tracks));
572  // evt.put(std::move(muon_tracks_assn));
573 
574  e.put(std::move(pmts_passed));
575 
576  //clear variables
577  passed_trigger.clear();
578  passed_trigger.shrink_to_fit();
579  max_passed = 0;
580 
581  if (fVerbose){std::cout << "Number of PMT waveforms: " << num_pmt_wvf << std::endl;}
582  if (fVerbose){std::cout << "Number of PMT channels: " << num_pmt_ch << std::endl;}
583 
584  channel_bin_wvfs.clear();
585  channel_bin_wvfs.shrink_to_fit();
586  paired.clear();
587  paired.shrink_to_fit();
588  unpaired_wvfs.clear();
589  unpaired_wvfs.shrink_to_fit();
590 
591  wvf_bin_0.clear();
592  wvf_bin_0.shrink_to_fit();
593 
594 } // pmtTriggerProducer::produce()
595 
596 // A macro required for a JobControl module.
597 DEFINE_ART_MODULE(pmtTriggerProducer)
std::vector< char > wvf_bin_0
void produce(art::Event &evt) override
std::vector< std::string > fOpDetsToPlot
Declaration of signal hit object.
pdgs p
Definition: selectors.fcl:22
std::vector< double > fThreshold
Definition of basic raw digits.
std::vector< int > passed_trigger
Access the description of detector geometry.
Simulation objects for optical detectors.
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Service to provide microboone-specific signal shaping for simulation (convolution) and reconstruction...
Collect all the RawData header files together.
art framework interface to geometry description for auxiliary detectors
std::vector< int > numPassed
Definition: pmtTrigger.hh:11
pmtTriggerProducer(fhicl::ParameterSet const &p)
void reconfigure(fhicl::ParameterSet const &p)
Definition of data types for geometry description.
Encapsulate the geometry of a wire.
Encapsulate the construction of a single detector plane.
object containing MC truth information necessary for making RawDigits and doing back tracking ...
do i e
std::vector< int > channel_numbers
TCEvent evt
Definition: DataStructs.cxx:8
std::string pdType(size_t ch) const override
std::vector< std::vector< char > > channel_bin_wvfs
Tools and modules for checking out the basics of the Monte Carlo.
pmtTriggerProducer & operator=(pmtTriggerProducer const &)=delete
art framework interface to geometry description
BEGIN_PROLOG could also be cout
std::vector< std::vector< char > > unpaired_wvfs
art::ServiceHandle< art::TFileService > tfs