All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
opDetDigitizerWorker.cc
Go to the documentation of this file.
1 // TODO: plenty of refactoring potential in here! ~icaza
2 
5 
7  const opdet::DigiArapucaSBNDAlgMaker::Config &arapuca_config):
8  makePMTDigi(pmt_config),
9  makeArapucaDigi(arapuca_config) {}
10 
12  const Config &config,
13  CLHEP::HepRandomEngine *Engine,
14  const opDetSBNDTriggerAlg &trigger_alg):
15  fConfig(config),
16  fThreadNo(no),
17  fEngine(Engine),
18  fTriggerAlg(trigger_alg)
19 {}
20 
22  detinfo::DetectorClocksData const& clockData,
25  bool ApplyTriggerLocations,
26  bool *finished)
27 {
28 
29  bool do_apply_trigger_locations = false;
30  while (1) {
31  sem_start.decrement();
32 
33  if (*finished) break;
34 
35  if (do_apply_trigger_locations) {
36  worker.ApplyTriggerLocations(clockData);
37  do_apply_trigger_locations = false;
38  }
39  else {
40  worker.Start(clockData);
41  do_apply_trigger_locations = ApplyTriggerLocations;
42  }
43 
44  sem_finish.increment();
45  }
46 
47 }
48 
49 void opdet::StartopDetDigitizerWorkers(unsigned n_workers,
51 {
52  sem_start.increment(n_workers);
53 }
54 
55 void opdet::WaitopDetDigitizerWorkers(unsigned n_workers,
57 {
58  sem_finish.decrement(n_workers);
59 }
60 
62 {
63  std::unique_lock<std::mutex> lock(mtx);
64  count += n;
65  cv.notify_all();
66 }
67 
69 {
70  std::unique_lock<std::mutex> lock(mtx);
71 
72  while (count < n) {
73  cv.wait(lock);
74  }
75  count -= n;
76 }
77 
79 {
80  return (n + fConfig.nThreads - fThreadNo - 1) / fConfig.nThreads;
81 }
82 
84 {
85  unsigned n_per_job = n / fConfig.nThreads;
86  unsigned leftover = std::min(fThreadNo, n % fConfig.nThreads);
87  return n_per_job * fThreadNo + leftover;
88 }
89 
91 {
92  auto arapucaDigitizer = fConfig.makeArapucaDigi(
93  *(lar::providerFrom<detinfo::LArPropertiesService>()),
94  clockData,
95  fEngine
96  );
97 
98  auto pmtDigitizer = fConfig.makePMTDigi(
99  *(lar::providerFrom<detinfo::LArPropertiesService>()),
100  clockData,
101  fEngine
102  );
103  MakeWaveforms(pmtDigitizer.get(), arapucaDigitizer.get());
104 
105 }
106 
108 {
109  delete fEngine;
110 }
111 
113 {
114  unsigned start = StartChannelToProcess(fConfig.nChannels);
115  unsigned n = NChannelsToProcess(fConfig.nChannels);
116 
117  fTriggeredWaveforms->clear();
118 
119  // apply the triggers and save the output
120  for (const raw::OpDetWaveform &waveform : *fWaveforms){
121  if (waveform.ChannelNumber() == std::numeric_limits<raw::Channel_t>::max() /* "NULL" value*/) {
122  continue;
123  }
124  // only work on the prescribed channels
125  if (waveform.ChannelNumber() < start || waveform.ChannelNumber() >= start + n) continue;
126 
127  std::vector<raw::OpDetWaveform> waveforms = fTriggerAlg.ApplyTriggerLocations(clockData, waveform);
128 
129  std::move(waveforms.begin(), waveforms.end(), std::back_inserter(*fTriggeredWaveforms));
130  }
131 }
132 
134  opdet::DigiArapucaSBNDAlg *arapucaDigitizer) const
135 {
136  if(fConfig.UseSimPhotonsLite) {
137  const std::vector<art::Handle<std::vector<sim::SimPhotonsLite>>> &photon_handles = *fPhotonLiteHandles;
138 
139  // TODO: Instead of looping and evaluating if/else through all the photon_handles
140  // we should get smaller containers with only the relevant handles for each case
141  // ~icaza
142  // std::vector<art::Handle<std::vector<sim::SimPhotonsLite>> const*> ptr_photon_handles(photon_handles.size());
143  // std::transform(photon_handles.begin(), photon_handles.end(), ptr_photon_handles.begin(),
144  // [](auto& p) {return std::addressof(p);});
145 
146  // to temporarily store channel and combine PMT (direct and converted) time profiles
147 
148 
149  //need to combine direct and reflected photons
150  std::unordered_map<std::string, std::unordered_map<int, sim::SimPhotonsLite> > AllPhotonsMap;
151  AllPhotonsMap["Direct"] = std::unordered_map<int, sim::SimPhotonsLite>();
152  AllPhotonsMap["Reflected"] = std::unordered_map<int, sim::SimPhotonsLite>();
153  for (const art::Handle<std::vector<sim::SimPhotonsLite>> &opdetHandle : photon_handles) {
154  const bool Reflected = (opdetHandle.provenance()->productInstanceName() == "Reflected");
155  for (auto const& litesimphotons : (*opdetHandle)){
156 
157  if(Reflected){
158  auto it = AllPhotonsMap["Reflected"].find(litesimphotons.OpChannel);
159  if(it==AllPhotonsMap["Reflected"].end())
160  AllPhotonsMap["Reflected"][litesimphotons.OpChannel] = litesimphotons;
161  else
162  AllPhotonsMap["Reflected"][litesimphotons.OpChannel] += litesimphotons;
163  }
164 
165  else{ //Direct
166  auto it = AllPhotonsMap["Direct"].find(litesimphotons.OpChannel);
167  if(it==AllPhotonsMap["Direct"].end())
168  AllPhotonsMap["Direct"][litesimphotons.OpChannel] = litesimphotons;
169  else
170  AllPhotonsMap["Direct"][litesimphotons.OpChannel] += litesimphotons;
171  }
172  }
173  }
174 
175  const double startTime = fConfig.EnableWindow[0] * 1000. /*ns for digitizer*/;
176 
177  std::unordered_map<int, sim::SimPhotonsLite> DirectPhotonsMap;
178  std::unordered_map<int, sim::SimPhotonsLite> ReflectedPhotonsMap;
179  std::unordered_set<short unsigned int> coatedpmts_todigitize;
180 
181  const unsigned start = StartChannelToProcess(fConfig.nChannels);
182  const unsigned n = NChannelsToProcess(fConfig.nChannels);
183  for (auto const& simphotons_cols : AllPhotonsMap){
184  // this now tells you if light collection is reflected
185  const bool Reflected = (simphotons_cols.first=="Reflected");
186  for (auto const& simphotons_map : simphotons_cols.second) {
187 
188  auto const& litesimphotons = simphotons_map.second;
189 
190  std::vector<short unsigned int> waveform;
191  waveform.reserve(fConfig.Nsamples);
192  const unsigned ch = litesimphotons.OpChannel;
193  const std::string pdtype = fConfig.pdsMap.pdType(ch);
194 
195  // only work on the prescribed channels
196  if (ch < start || ch >= start + n) continue;
197 
198 
199  if( pdtype == "pmt_coated" ){
200  if(Reflected)
201  ReflectedPhotonsMap.insert(std::make_pair(ch, litesimphotons));
202  else
203  DirectPhotonsMap.insert(std::make_pair(ch, litesimphotons));
204 
205  coatedpmts_todigitize.insert(ch);
206  }
207  else if( (Reflected) && (pdtype == "pmt_uncoated") ) { //Uncoated PMT channels
208  pmtDigitizer->ConstructWaveformLite(ch,
209  litesimphotons,
210  waveform,
211  pdtype,
212  startTime,
213  fConfig.Nsamples);
214  // including pre trigger window and transit time
215  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
216  (unsigned int)ch,
217  waveform);
218  }
219  // getting only xarapuca channels with appropriate type of light
220  else if((pdtype == "xarapuca_vuv" && !Reflected) ||
221  (pdtype == "xarapuca_vis" && Reflected) ) {
222  const bool is_daphne= fConfig.pdsMap.isElectronics(ch,"daphne");
223  if(is_daphne){
224  arapucaDigitizer->ConstructWaveformLite(ch,
225  litesimphotons,
226  waveform,
227  pdtype,
228  is_daphne,
229  startTime,
230  fConfig.Nsamples_Daphne);
231  // including pre trigger window and transit time
232  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
233  (unsigned int)ch,
234  waveform);
235  }
236  else{
237  arapucaDigitizer->ConstructWaveformLite(ch,
238  litesimphotons,
239  waveform,
240  pdtype,
241  is_daphne,
242  startTime,
243  fConfig.Nsamples);
244  // including pre trigger window and transit time
245  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
246  (unsigned int)ch,
247  waveform);
248  }
249  }
250  }
251  } //end loop on simphoton lite collections
252 
253  //Constructing Waveforms for hybrid OpChannels (coated pmts)
254  for(auto ch : coatedpmts_todigitize){
255  std::vector<short unsigned int> waveform;
256  waveform.reserve(fConfig.Nsamples);
257  pmtDigitizer->ConstructWaveformLiteCoatedPMT(ch, waveform, DirectPhotonsMap, ReflectedPhotonsMap, startTime, fConfig.Nsamples);
258  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
259  (unsigned int)ch,
260  waveform);
261  }
262  }
263  else { // for SimPhotons
264  const std::vector<art::Handle<std::vector<sim::SimPhotons>>> &photon_handles = *fPhotonHandles;
265 
266  //need to combine direct and reflected photons
267  std::unordered_map<std::string, std::unordered_map<int, sim::SimPhotons> > AllPhotonsMap;
268  AllPhotonsMap["Direct"] = std::unordered_map<int, sim::SimPhotons>();
269  AllPhotonsMap["Reflected"] = std::unordered_map<int, sim::SimPhotons>();
270  for (const art::Handle<std::vector<sim::SimPhotons>> &opdetHandle : photon_handles) {
271  const bool Reflected = (opdetHandle.provenance()->productInstanceName() == "Reflected");
272  for (auto const& simphotons : (*opdetHandle)){
273 
274  if(Reflected){
275  auto it = AllPhotonsMap["Reflected"].find(simphotons.OpChannel());
276  if(it==AllPhotonsMap["Reflected"].end())
277  AllPhotonsMap["Reflected"][simphotons.OpChannel()] = simphotons;
278  else
279  AllPhotonsMap["Reflected"][simphotons.OpChannel()] += simphotons;
280  }
281 
282  else{ //Direct
283  auto it = AllPhotonsMap["Direct"].find(simphotons.OpChannel());
284  if(it==AllPhotonsMap["Direct"].end())
285  AllPhotonsMap["Direct"][simphotons.OpChannel()] = simphotons;
286  else
287  AllPhotonsMap["Direct"][simphotons.OpChannel()] += simphotons;
288  }
289  }
290  }
291 
292 
293  // to temporarily store channel and direct light distribution
294  std::unordered_map<int, sim::SimPhotons> DirectPhotonsMap;
295  std::unordered_map<int, sim::SimPhotons> ReflectedPhotonsMap;
296  std::unordered_set<short unsigned int> coatedpmts_todigitize;
297 
298  const double startTime = fConfig.EnableWindow[0] * 1000. /*ns for digitizer*/;
299 
300  const unsigned start = StartChannelToProcess(fConfig.nChannels);
301  const unsigned n = NChannelsToProcess(fConfig.nChannels);
302  for (auto const& simphotons_cols : AllPhotonsMap){
303  // this now tells you if light collection is reflected
304  const bool Reflected = (simphotons_cols.first=="Reflected");
305  for (auto const& simphotons_map : simphotons_cols.second) {
306 
307  auto const& simphotons = simphotons_map.second;
308 
309  std::vector<short unsigned int> waveform;
310  const unsigned ch = simphotons.OpChannel();
311  const std::string pdtype = fConfig.pdsMap.pdType(ch);
312  const bool is_daphne = fConfig.pdsMap.isElectronics(ch,"daphne");
313  // only work on the prescribed channels
314  if (ch < start || ch >= start + n) continue;
315  //coated PMTs
316  if( pdtype == "pmt_coated" ){
317  if(Reflected)
318  ReflectedPhotonsMap.insert(std::make_pair(ch, simphotons));
319  else
320  DirectPhotonsMap.insert(std::make_pair(ch, simphotons));
321 
322  coatedpmts_todigitize.insert(ch);
323  }
324  // uncoated PMTs
325  else if(Reflected && pdtype == "pmt_uncoated") {
326  pmtDigitizer->ConstructWaveform(ch,
327  simphotons,
328  waveform,
329  pdtype,
330  startTime,
331  fConfig.Nsamples);
332  // including pre trigger window and transit time
333  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
334  (unsigned int)ch,
335  waveform);
336  }
337  // getting only xarapuca channels with appropriate type of light
338  if((pdtype == "xarapuca_vuv" && !Reflected) ||
339  (pdtype == "xarapuca_vis" && Reflected)) {
340  if(is_daphne){
341  arapucaDigitizer->ConstructWaveform(ch,
342  simphotons,
343  waveform,
344  pdtype,
345  is_daphne,
346  startTime,
347  fConfig.Nsamples_Daphne);
348  // including pre trigger window and transit time
349  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
350  (unsigned int)ch,
351  waveform);
352  }
353  else{
354  arapucaDigitizer->ConstructWaveform(ch,
355  simphotons,
356  waveform,
357  pdtype,
358  is_daphne,
359  startTime,
360  fConfig.Nsamples);
361  // including pre trigger window and transit time
362  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
363  (unsigned int)ch,
364  waveform);
365  }
366  }
367  }//optical channel loop
368  }//type of light loop
369  //Constructing Waveforms for hybrid OpChannels (coated pmts)
370  for(auto ch : coatedpmts_todigitize){
371  std::vector<short unsigned int> waveform;
372  waveform.reserve(fConfig.Nsamples);
373  pmtDigitizer->ConstructWaveformCoatedPMT(ch, waveform, DirectPhotonsMap, ReflectedPhotonsMap, startTime, fConfig.Nsamples);
374  fWaveforms->at(ch) = raw::OpDetWaveform(fConfig.EnableWindow[0],
375  (unsigned int)ch,
376  waveform);
377  }
378  }//simphotons end
379 }
unsigned StartChannelToProcess(unsigned n) const
void ConstructWaveform(int ch, sim::SimPhotons const &simphotons, std::vector< short unsigned int > &waveform, std::string pdtype, double start_time, unsigned n_sample)
Utilities related to art service access.
void opDetDigitizerWorkerThread(const opDetDigitizerWorker &worker, detinfo::DetectorClocksData const &clockData, opDetDigitizerWorker::Semaphore &sem_start, opDetDigitizerWorker::Semaphore &sem_finish, bool ApplyTriggerLocations, bool *finished)
void StartopDetDigitizerWorkers(unsigned n_workers, opDetDigitizerWorker::Semaphore &sem_start)
void ConstructWaveformLiteCoatedPMT(int ch, std::vector< short unsigned int > &waveform, std::unordered_map< int, sim::SimPhotonsLite > &DirectPhotonsMap, std::unordered_map< int, sim::SimPhotonsLite > &ReflectedPhotonsMap, double start_time, unsigned n_sample)
void WaitopDetDigitizerWorkers(unsigned n_workers, opDetDigitizerWorker::Semaphore &sem_finish)
void ConstructWaveformLite(int ch, sim::SimPhotonsLite const &litesimphotons, std::vector< short unsigned int > &waveform, std::string pdtype, double start_time, unsigned n_sample)
unsigned NChannelsToProcess(unsigned n) const
void ConstructWaveformLite(int ch, sim::SimPhotonsLite const &litesimphotons, std::vector< short unsigned int > &waveform, std::string pdtype, bool is_daphne, double start_time, unsigned n_samples)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
fEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this, pset,"Seed"))
void ConstructWaveformCoatedPMT(int ch, std::vector< short unsigned int > &waveform, std::unordered_map< int, sim::SimPhotons > &DirectPhotonsMap, std::unordered_map< int, sim::SimPhotons > &ReflectedPhotonsMap, double start_time, unsigned n_sample)
opDetDigitizerWorker(unsigned no, const Config &config, CLHEP::HepRandomEngine *Engine, const opDetSBNDTriggerAlg &trigger_alg)
void Start(detinfo::DetectorClocksData const &clockData) const
Contains all timing reference information for the detector.
CLHEP::HepRandomEngine * fEngine
void MakeWaveforms(opdet::DigiPMTSBNDAlg *pmtDigitizer, opdet::DigiArapucaSBNDAlg *arapucaDigitizer) const
void ApplyTriggerLocations(detinfo::DetectorClocksData const &clockData) const
Config(const opdet::DigiPMTSBNDAlgMaker::Config &pmt_config, const opdet::DigiArapucaSBNDAlgMaker::Config &arapuca_config)
std::size_t count(Cont const &cont)
void ConstructWaveform(int ch, sim::SimPhotons const &simphotons, std::vector< short unsigned int > &waveform, std::string pdtype, bool is_daphne, double start_time, unsigned n_samples)
const opDetSBNDTriggerAlg & fTriggerAlg