All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SBNDOpHitFinder_module.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 2; -*-
2 // Gleb Sinev, Duke, 2016
3 //
4 // This module finds periods of time-localized activity
5 // on each channel of the optical system and creates OpHits.
6 //
7 // Split from OpFlashFinder_module.cc
8 // by Ben Jones, MIT, 2013
9 //
10 // Ported to SBND by Marco Del Tutto, March 2018
11 
12 // LArSoft includes
14 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
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/Utilities/make_tool.h"
39 #include "fhiclcpp/ParameterSet.h"
40 #include "art/Framework/Principal/Handle.h"
41 #include "canvas/Utilities/Exception.h"
42 
44 // #include "sbndcode/OpDetReco/OpFlash/FlashFinder/FlashFinderFMWKInterface.h"
45 
46 
47 // ROOT includes
48 
49 // C++ Includes
50 #include <map>
51 #include <string>
52 #include <memory>
53 #include <algorithm>
54 
55 namespace {
56  template <typename T>
57  pmtana::PMTPulseRecoBase* thresholdAlgorithm(fhicl::ParameterSet const& hit_alg_pset,
58  std::optional<fhicl::ParameterSet> const& rise_alg_pset)
59  {
60  if (rise_alg_pset)
61  return new T(hit_alg_pset, art::make_tool<pmtana::RiseTimeCalculatorBase>(*rise_alg_pset) );
62  else
63  return new T(hit_alg_pset, nullptr);
64  }
65 }
66 
67 namespace opdet {
68 
69  class SBNDOpHitFinder : public art::EDProducer{
70  public:
71 
72  // Standard constructor and destructor for an ART module.
73  explicit SBNDOpHitFinder(const fhicl::ParameterSet&);
74  virtual ~SBNDOpHitFinder();
75 
76  // The producer routine, called once per event.
77  void produce(art::Event&);
78 
79  private:
80  std::map< int, int > GetChannelMap();
81  std::vector< double > GetSPEScales();
82  std::vector< double > GetSPEShifts();
83  std::vector<int> PDNamesToList(std::vector<std::string>);
84 
85 
86  // The parameters we'll read from the .fcl file.
87  std::string fInputModule; // Input tag for OpDetWaveform collection
88  std::string fGenModule;
89  std::vector< std::string > fInputLabels;
90  std::set< unsigned int > fChannelMasks;
91  std::vector<std::string> _pd_to_use; ///< PDS to use (ex: "pmt", "barepmt")
92  std::string fElectronics; ///< PDS readouts to use (ex: "CAEN", "Daphne")
93  std::vector<int> _opch_to_use; ///< List of of opch (will be infered from _pd_to_use)
94 
98 
100  unsigned int fMaxOpChannel;
101 
103 
104  opdet::sbndPDMapAlg _pds_map; ///< map for photon detector types
105  };
106 
107 }
108 
109 namespace opdet {
110  DEFINE_ART_MODULE(SBNDOpHitFinder)
111 }
112 
113 namespace opdet {
114 
115  //----------------------------------------------------------------------------
116  // Constructor
117  SBNDOpHitFinder::SBNDOpHitFinder(const fhicl::ParameterSet & pset):
118  EDProducer{pset},
119  fPulseRecoMgr()
120  {
121  // Indicate that the Input Module comes from .fcl
122  fInputModule = pset.get< std::string >("InputModule");
123  fGenModule = pset.get< std::string >("GenModule");
124  fInputLabels = pset.get< std::vector< std::string > >("InputLabels");
125 
126  for (auto const& ch : pset.get< std::vector< unsigned int > >
127  ("ChannelMasks", std::vector< unsigned int >()))
128  fChannelMasks.insert(ch);
129 
130  _pd_to_use = pset.get< std::vector< std::string > >("PD", _pd_to_use);
131  fElectronics = pset.get< std::string >("Electronics");
132  _opch_to_use = this->PDNamesToList(_pd_to_use);
133 
134  fDaphne_Freq = pset.get< float >("DaphneFreq");
135  fHitThreshold = pset.get< float >("HitThreshold");
136  bool useCalibrator = pset.get< bool > ("UseCalibrator", false);
137 
138  auto const& geometry(*lar::providerFrom< geo::Geometry >());
139  fMaxOpChannel = geometry.MaxOpChannel();
140 
141  if (useCalibrator) {
142  // If useCalibrator, get it from ART
143  fCalib = lar::providerFrom<calib::IPhotonCalibratorService>();
144  }
145  else {
146  // If not useCalibrator, make an internal one based
147  // on fhicl settings to hit finder.
148  bool areaToPE = pset.get< bool > ("AreaToPE");
149  float SPEArea = pset.get< float >("SPEArea");
150  float SPEShift = pset.get< float >("SPEShift", 0.);
151 
152  // Reproduce behavior from GetSPEScales()
153  if (!areaToPE) SPEArea = 20;
154 
155  // Delete and replace if we are reconfiguring
156  if (fCalib) {
157  delete fCalib;
158  }
159 
160  fCalib = new calib::PhotonCalibratorStandard(SPEArea, SPEShift, areaToPE);
161  }
162 
163  // Initialize the rise time calculator tool
164  auto const rise_alg_pset = pset.get_if_present<fhicl::ParameterSet>("RiseTimeCalculator");
165 
166  // Initialize the hit finder algorithm
167  auto const hit_alg_pset = pset.get<fhicl::ParameterSet>("HitAlgoPset");
168  std::string threshAlgName = hit_alg_pset.get<std::string>("Name");
169  if (threshAlgName == "Threshold")
170  fThreshAlg = thresholdAlgorithm<pmtana::AlgoThreshold>(hit_alg_pset, rise_alg_pset);
171  else if (threshAlgName == "SiPM")
172  fThreshAlg = thresholdAlgorithm<pmtana::AlgoSiPM>(hit_alg_pset, rise_alg_pset);
173  else if (threshAlgName == "SlidingWindow")
174  fThreshAlg = thresholdAlgorithm<pmtana::AlgoSlidingWindow>(hit_alg_pset, rise_alg_pset);
175  else if (threshAlgName == "FixedWindow")
176  fThreshAlg = thresholdAlgorithm<pmtana::AlgoFixedWindow>(hit_alg_pset, rise_alg_pset);
177  else if (threshAlgName == "CFD")
178  fThreshAlg = thresholdAlgorithm<pmtana::AlgoCFD>(hit_alg_pset, rise_alg_pset);
179  else
180  throw art::Exception(art::errors::UnimplementedFeature)
181  << "Cannot find implementation for " << threshAlgName << " algorithm.\n";
182 
183  // Initialize the pedestal estimation algorithm
184  auto const ped_alg_pset = pset.get< fhicl::ParameterSet >("PedAlgoPset");
185  std::string pedAlgName = ped_alg_pset.get< std::string >("Name");
186  if (pedAlgName == "Edges")
187  fPedAlg = new pmtana::PedAlgoEdges(ped_alg_pset);
188  else if (pedAlgName == "RollingMean")
189  fPedAlg = new pmtana::PedAlgoRollingMean(ped_alg_pset);
190  else if (pedAlgName == "UB" )
191  fPedAlg = new pmtana::PedAlgoUB(ped_alg_pset);
192  else throw art::Exception(art::errors::UnimplementedFeature)
193  << "Cannot find implementation for "
194  << pedAlgName << " algorithm.\n";
195 
196  produces< std::vector< recob::OpHit > >();
197 
198  fPulseRecoMgr.AddRecoAlgo(fThreshAlg);
199  fPulseRecoMgr.SetDefaultPedAlgo(fPedAlg);
200 
201  }
202 
203  //----------------------------------------------------------------------------
204  // Destructor
206  {
207 
208  delete fThreshAlg;
209  delete fPedAlg;
210 
211  }
212 
213  //----------------------------------------------------------------------------
214  void SBNDOpHitFinder::produce(art::Event& evt)
215  {
216 
217  // These is the storage pointer we will put in the event
218  std::unique_ptr< std::vector< recob::OpHit > >
219  HitPtrFinal(new std::vector< recob::OpHit >);
220 
221  // These is a temporary storage pointer
222  std::unique_ptr< std::vector< recob::OpHit > >
223  HitPtr(new std::vector< recob::OpHit >);
224 
225  std::vector< const sim::BeamGateInfo* > beamGateArray;
226  try
227  {
228  evt.getView(fGenModule, beamGateArray);
229  }
230  catch (art::Exception const& err)
231  {
232  if ( err.categoryCode() != art::errors::ProductNotFound ) throw;
233  }
234 
235  auto const& geometry(*lar::providerFrom< geo::Geometry >());
236  auto const clockData_CAEN = art::ServiceHandle<detinfo::DetectorClocksService>()->DataFor(evt);
237  auto const& calibrator(*fCalib);
238  detinfo::ElecClock const optical_clock_daphne = detinfo::ElecClock(clockData_CAEN.OpticalClock().Time(),
239  clockData_CAEN.OpticalClock().FramePeriod(),
240  fDaphne_Freq);
241  detinfo::DetectorClocksData const& clockData_Daphne = detinfo::DetectorClocksData(-clockData_CAEN.G4ToElecTime(0),
242  clockData_CAEN.TriggerOffsetTPC(),
243  clockData_CAEN.TriggerTime(),
244  clockData_CAEN.BeamGateTime(),
245  clockData_CAEN.TPCClock(),
246  optical_clock_daphne,
247  clockData_CAEN.TriggerClock(),
248  clockData_CAEN.ExternalClock());
249  detinfo::DetectorClocksData const& clockData = (fElectronics=="Daphne") ? clockData_Daphne : clockData_CAEN;
250  // std::cout<<"@rodrigoa debug: frecuencies "<<clockData_Daphne.OpticalClock().Frequency()<<" "<<clockData.OpticalClock().Frequency()<<std::endl;
251  //
252  // Get the pulses from the event
253  //
254 
255  // Load pulses into WaveformVector
256  if(fChannelMasks.empty() && _opch_to_use.empty() && fInputLabels.size()<2) {
257  art::Handle< std::vector< raw::OpDetWaveform > > wfHandle;
258  if(fInputLabels.empty())
259  evt.getByLabel(fInputModule, wfHandle);
260  else
261  evt.getByLabel(fInputModule, fInputLabels.front(), wfHandle);
262  assert(wfHandle.isValid());
263  RunHitFinder(*wfHandle,
264  *HitPtr,
266  *fThreshAlg,
267  geometry,
268  fHitThreshold,
269  clockData,
270  calibrator);
271  } else {
272 
273  // Reserve a large enough array
274  int totalsize = 0;
275  for (auto label : fInputLabels)
276  {
277  art::Handle< std::vector< raw::OpDetWaveform > > wfHandle;
278  evt.getByLabel(fInputModule, label, wfHandle);
279  if (!wfHandle.isValid()) continue; // Skip non-existent collections
280  totalsize += wfHandle->size();
281  }
282 
283  std::vector< raw::OpDetWaveform > WaveformVector;
284  WaveformVector.reserve(totalsize);
285 
286  for (auto label : fInputLabels)
287  {
288  art::Handle< std::vector< raw::OpDetWaveform > > wfHandle;
289  evt.getByLabel(fInputModule, label, wfHandle);
290  if (!wfHandle.isValid()) continue; // Skip non-existent collections
291 
292  for(auto const& wf : *wfHandle)
293  {
294  // If this channel is in the channel mask, ingore it
295  if ( fChannelMasks.find(wf.ChannelNumber()) != fChannelMasks.end() ) continue;
296  // If this PDS in not in the list of PDS to use, ingore it
297  if ( std::find(_opch_to_use.begin(), _opch_to_use.end(), wf.ChannelNumber()) == _opch_to_use.end() ) continue;
298 
299  WaveformVector.push_back(wf);
300  }
301  }
302 
303  RunHitFinder(WaveformVector,
304  *HitPtr,
306  *fThreshAlg,
307  geometry,
308  fHitThreshold,
309  clockData,
310  calibrator);
311  // for (auto h : *HitPtr)
312  // std::cout << "> ophit time " << h.PeakTime()
313  // << ", corrected " << h.PeakTime() - clockData.TriggerTime()
314  // << ", area " << h.Area()
315  // << ", pe " << h.PE() << std::endl;
316  }
317 
318  // Now correct the time. Unfortunately, there are no setter methods for OpHits,
319  // so we have to make a new OpHit vector.
320  for (auto h : *HitPtr) {
321  (*HitPtrFinal).emplace_back(h.OpChannel(),
322  h.PeakTime() + clockData.TriggerTime(),
323  h.PeakTimeAbs(),
324  h.StartTime() + clockData.TriggerTime(),
325  h.RiseTime(),
326  h.Frame(),
327  h.Width(),
328  h.Area(),
329  h.Amplitude(),
330  h.PE(),
331  0.0);
332  }
333  // Store results into the event
334  evt.put(std::move(HitPtrFinal));
335 
336  }
337 
338  std::vector<int> SBNDOpHitFinder::PDNamesToList(std::vector<std::string> pd_names) {
339 
340  std::vector<int> out_ch_v;
341 
342  for (auto name : pd_names) {
343  std::vector<int> ch_v;
344  // std::cout<<"@rodrigoa debug: Electronics="<<fElectronics<<std::endl;
345 
346  if (fElectronics=="Daphne"){
347  //take only daphne xarapuca channels (80 Mhz) for now ~rodrigoa
348  ch_v = _pds_map.getChannelsOfType(name, "daphne");
349  }else{
351  }
352  out_ch_v.insert(out_ch_v.end(), ch_v.begin(), ch_v.end());
353  }
354 
355  return out_ch_v;
356 
357  }
358 } // namespace opdet
std::vector< std::string > fInputLabels
Utilities related to art service access.
const geo::GeometryCore * geometry
std::vector< int > PDNamesToList(std::vector< std::string >)
std::set< unsigned int > fChannelMasks
EResult err(const char *call)
std::vector< int > _opch_to_use
List of of opch (will be infered from _pd_to_use)
SBNDOpHitFinder(const fhicl::ParameterSet &)
calib::IPhotonCalibrator const * fCalib
std::vector< double > GetSPEScales()
std::vector< int > PDNamesToList(std::vector< std::string > pd_names)
BEGIN_PROLOG xarapuca_vuv SBNDDecoOpHitFinderXArapuca SPEArea
while getopts h
std::vector< double > GetSPEShifts()
Class definition file of PedAlgoRollingMean.
Class definition file of AlgoCFD.
opdet::sbndPDMapAlg _pds_map
map for photon detector types
Class definition file of PedAlgoUB.
unsigned int MaxOpChannel() const
Largest optical channel number.
std::vector< int > getChannelsOfType(std::string pdname) const
pmtana::PMTPulseRecoBase * fThreshAlg
Class definition file of AlgoFixedWindow.
Contains all timing reference information for the detector.
void RunHitFinder(std::vector< raw::OpDetWaveform > const &opDetWaveformVector, std::vector< recob::OpHit > &hitVector, pmtana::PulseRecoManager const &pulseRecoMgr, pmtana::PMTPulseRecoBase const &threshAlg, geo::GeometryCore const &geometry, float hitThreshold, detinfo::DetectorClocksData const &clocksData, calib::IPhotonCalibrator const &calibrator, bool use_start_time)
Definition: OpHitAlg.cxx:30
Class definition file of AlgoSlidingWindow.
Class definition file of AlgoThreshold.
std::map< int, int > GetChannelMap()
then echo fcl name
pmtana::PulseRecoManager fPulseRecoMgr
Class definition file of PMTPulseRecoBase.
pmtana::PMTPedestalBase * fPedAlg
Class definition file of PedAlgoEdges.
Class representing the time measured by an electronics clock.
Definition: ElecClock.h:91
TCEvent evt
Definition: DataStructs.cxx:8
std::vector< std::string > _pd_to_use
PDS to use (ex: &quot;pmt&quot;, &quot;barepmt&quot;)
art framework interface to geometry description
Class definition file of PulseRecoManager.
std::string fElectronics
PDS readouts to use (ex: &quot;CAEN&quot;, &quot;Daphne&quot;)