10 #include "art/Framework/Core/EDProducer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "canvas/Utilities/InputTag.h"
16 #include "canvas/Utilities/Exception.h"
17 #include "fhiclcpp/types/Atom.h"
18 #include "fhiclcpp/types/TableFragment.h"
19 #include "messagefacility/MessageLogger/MessageLogger.h"
21 #include "nurandom/RandomUtils/NuRandomService.h"
22 #include "CLHEP/Random/JamesRandom.h"
29 #include <unordered_map>
82 class opDetDigitizerSBND;
92 Comment(
"Simulated photons to be digitized")
96 Comment(
"Value to initialize the waveform vector in ns. It is resized in the algorithms according to readout window of PDs")
99 Name(
"UseSimPhotonsLite"),
100 Comment(
"Whether SimPhotonsLite or SimPhotons will be used")
104 Name(
"ApplyTriggers"),
105 Comment(
"Whether to apply trigger algorithm to waveforms"),
111 Comment(
"Number of threads to split waveform process into. Defaults to 1.\
112 Set 0 to autodetect. Autodection will first check $SBNDCODE_OPDETSIM_NTHREADS for number of threads. \
113 If this is not set, then NThreads is set to the number of hardware cores on the host machine."),
137 void produce(art::Event &
e)
override;
171 , fApplyTriggers(config().ApplyTriggers())
172 , fUseSimPhotonsLite(config().UseSimPhotonsLite())
173 , fPMTBaseline(config().pmtAlgoConfig().pmtbaseline())
174 , fArapucaBaseline(config().araAlgoConfig().
baseline())
175 , fTriggerAlg(config().trigAlgoConfig())
179 fNThreads = config().NThreads();
180 if (fNThreads == 0) {
181 const char *env = std::getenv(
"SBNDCODE_OPDETSIM_NTHREADS");
185 int n_threads = std::stoi(env);
186 if (n_threads <= 0) {
187 throw std::invalid_argument(
"Expect positive integer");
189 fNThreads = n_threads;
192 mf::LogError(
"OpDetDigitizer") <<
"Unable to parse number of threads "
193 <<
"in environment variable (SBNDCODE_OPDETSIM_NTHREADS): (" << env <<
").\n"
194 <<
"Setting Number opdet threads to 1." << std::endl;
200 if (fNThreads == 0) {
201 fNThreads = std::thread::hardware_concurrency();
203 if (fNThreads == 0) {
206 mf::LogInfo(
"OpDetDigitizer") <<
"Digitizing on n threads: " << fNThreads << std::endl;
208 wConfig.nThreads = fNThreads;
210 wConfig.UseSimPhotonsLite = config().UseSimPhotonsLite();
211 wConfig.InputModuleName = config().InputModuleName();
213 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
214 auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob(clockData);
215 wConfig.Sampling = (clockData.OpticalClock().Frequency()) / 1000.0;
216 wConfig.Sampling_Daphne = config().araAlgoConfig().DaphneFrequency() / 1000.0;
217 wConfig.EnableWindow = fTriggerAlg.TriggerEnableWindow(clockData,
detProp);
218 wConfig.Nsamples = (wConfig.EnableWindow[1] - wConfig.EnableWindow[0]) * 1000. * wConfig.Sampling ;
219 wConfig.Nsamples_Daphne = (wConfig.EnableWindow[1] - wConfig.EnableWindow[0]) * 1000. * wConfig.Sampling_Daphne ;
223 fWorkers.reserve(fNThreads);
224 fTriggeredWaveforms.reserve(fNThreads);
225 for (
unsigned i = 0; i < fNThreads; i++) {
227 art::ServiceHandle<rndm::NuRandomService> seedSvc;
228 CLHEP::HepJamesRandom *engine =
new CLHEP::HepJamesRandom;
229 seedSvc->registerEngine(rndm::NuRandomService::CLHEPengineSeeder(engine),
"opDetDigitizerSBND" +
std::to_string(i));
231 fTriggeredWaveforms.emplace_back();
234 fWorkers.emplace_back(i, wConfig, engine, fTriggerAlg);
235 fWorkers[i].SetPhotonLiteHandles(&fPhotonLiteHandles);
236 fWorkers[i].SetPhotonHandles(&fPhotonHandles);
237 fWorkers[i].SetWaveformHandle(&fWaveforms);
238 fWorkers[i].SetTriggeredWaveformHandle(&fTriggeredWaveforms[i]);
242 std::cref(fWorkers[i]),
245 std::ref(fSemFinish),
251 produces< std::vector< raw::OpDetWaveform > >();
267 std::unique_ptr< std::vector< raw::OpDetWaveform > > pulseVecPtr(std::make_unique< std::vector< raw::OpDetWaveform > > ());
269 mf::LogInfo(
"opDetDigitizer") <<
"Event: " << e.id().event() << std::endl;
274 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
275 auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e, clockData);
282 mf::LogError(
"OpDetDigitizer") <<
"sim::SimPhotonsLite not found -> No Optical Detector Simulation!\n";
289 mf::LogError(
"OpDetDigitizer") <<
"sim::SimPhotons not found -> No Optical Detector Simulation!\n";
301 if (ch == std::numeric_limits<raw::Channel_t>::max() ) {
318 pulseVecPtr->reserve(pulseVecPtr->size() + waveforms.size());
319 std::move(waveforms.begin(), waveforms.end(), std::back_inserter(*pulseVecPtr));
322 for (
unsigned i = 0; i < fTriggeredWaveforms.size(); i++) {
323 fTriggeredWaveforms[i] = std::vector<raw::OpDetWaveform>();
327 e.put(std::move(pulseVecPtr));
335 if (waveform.ChannelNumber() == std::numeric_limits<raw::Channel_t>::max() ) {
338 pulseVecPtr->push_back(waveform);
340 e.put(std::move(pulseVecPtr));
fhicl::Atom< double > WaveformSize
std::vector< art::Handle< std::vector< sim::SimPhotons > > > fPhotonHandles
void opDetDigitizerWorkerThread(const opDetDigitizerWorker &worker, detinfo::DetectorClocksData const &clockData, opDetDigitizerWorker::Semaphore &sem_start, opDetDigitizerWorker::Semaphore &sem_finish, bool ApplyTriggerLocations, bool *finished)
std::vector< opdet::opDetDigitizerWorker > fWorkers
art::EDProducer::Table< Config > Parameters
fhicl::TableFragment< opdet::DigiPMTSBNDAlgMaker::Config > pmtAlgoConfig
void StartopDetDigitizerWorkers(unsigned n_workers, opDetDigitizerWorker::Semaphore &sem_start)
fhicl::Atom< bool > UseSimPhotonsLite
fhicl::TableFragment< opdet::DigiArapucaSBNDAlgMaker::Config > araAlgoConfig
void FindTriggerLocations(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const raw::OpDetWaveform &waveform, raw::ADC_Count_t baseline)
bool isPDType(size_t ch, std::string pdname) const override
std::vector< art::Handle< std::vector< sim::SimPhotonsLite > > > fPhotonLiteHandles
unsigned fArapucaBaseline
void WaitopDetDigitizerWorkers(unsigned n_workers, opDetDigitizerWorker::Semaphore &sem_finish)
opdet::opDetDigitizerWorker::Semaphore fSemStart
fhicl::TableFragment< opdet::opDetSBNDTriggerAlg::Config > trigAlgoConfig
void MergeTriggerLocations()
Simulation objects for optical detectors.
BEGIN_PROLOG vertical distance to the surface Name
fhicl::Atom< unsigned > NThreads
opdet::opDetDigitizerWorker::Semaphore fSemFinish
std::unordered_map< raw::Channel_t, std::vector< double > > fFullWaveforms
std::string to_string(WindowPattern const &pattern)
std::vector< std::thread > fWorkerThreads
object containing MC truth information necessary for making RawDigits and doing back tracking ...
std::vector< raw::OpDetWaveform > fWaveforms
opDetDigitizerSBND & operator=(opDetDigitizerSBND const &)=delete
void produce(art::Event &e) override
std::vector< std::vector< raw::OpDetWaveform > > fTriggeredWaveforms
opdet::opDetSBNDTriggerAlg fTriggerAlg
fhicl::Atom< bool > ApplyTriggers
fhicl::Atom< art::InputTag > InputModuleName
Tools and modules for checking out the basics of the Monte Carlo.
art framework interface to geometry description
opDetDigitizerSBND(Parameters const &config)