All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PMTconfigurationExtractor.h
Go to the documentation of this file.
1 /**
2  * @file icaruscode/Decode/DecoderTools/PMTconfigurationExtractor.h
3  * @brief Utility to extract PMT readout configuration from data.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date February 18, 2021
6  * @file icaruscode/Decode/DecoderTools/PMTconfigurationExtractor.cxx
7  *
8  * The design of this thing is still a big mess, winking to a templated
9  * class hierarchy to be used for other components as well, but not getting
10  * quite there.
11  *
12  * Extra linking is required for `extractPMTreadoutConfiguration(Principal)`
13  * to pick up the class used as `Principal`.
14  *
15  */
16 
17 #ifndef ICARUSCODE_DECODE_DECODERTOOLS_PMTCONFIGURATIONEXTRACTOR_H
18 #define ICARUSCODE_DECODE_DECODERTOOLS_PMTCONFIGURATIONEXTRACTOR_H
19 
20 
21 // ICARUS libraries
23 #include "icaruscode/Utilities/ReadArtConfiguration.h" // util::readConfigurationFromArtPrincipal()
26 
27 // framework libraries
28 #include "art/Framework/Principal/DataViewImpl.h"
29 #include "messagefacility/MessageLogger/MessageLogger.h"
30 #include "fhiclcpp/ParameterSet.h"
31 #include "cetlib_except/exception.h"
32 
33 // ROOT libraries
34 #include "TFile.h"
35 
36 // C/C++ standard libraries
37 #include <regex>
38 #include <string>
39 #include <optional>
40 #include <utility> // std::move(), std::pair<>
41 #include <initializer_list>
42 
43 
44 
45 // -----------------------------------------------------------------------------
46 namespace icarus {
47 
48  class PMTconfigurationExtractorBase;
49  class PMTconfigurationExtractor;
50 
52  (std::string const& srcFileName, icarus::PMTconfigurationExtractor extractor);
54  (TFile& srcFile, icarus::PMTconfigurationExtractor extractor);
55  template <typename Principal>
57  (Principal const& data, icarus::PMTconfigurationExtractor extractor);
58 
59 } // namespace icarus
60 
61 
62 // -----------------------------------------------------------------------------
64 
65  public:
66 
68 
69  // --- BEGIN -- Interface ----------------------------------------------------
70  /// @name Interface
71  /// @{
72 
73  /// Returns whether `pset` may contain the needed configuration.
74  static bool mayHaveConfiguration(fhicl::ParameterSet const& pset)
75  { return pset.has_key("configuration_documents"); }
76 
77 
78  /**
79  * @brief Extracts all supported PMT configuration from `config`.
80  * @param config a FHiCL parameter set with component configuration
81  * @return an object with the supported PMT configuration
82  *
83  * All PMT-related configuration that is known to this code is extracted and
84  * returned.
85  *
86  * This function is undefined here: it must be overridden.
87  */
88  ConfigurationData_t extract(fhicl::ParameterSet const& config) const;
89 
90 
91  /// Finalizes the content of `config` and returns it.
93  { return config; }
94 
95 
96  /// @}
97  // --- END ---- Interface ----------------------------------------------------
98 
99 
100  // --- BEGIN -- Utility ------------------------------------------------------
101  /// @name Utility
102  /// @{
103 
104  /**
105  * @brief Returns a parameter set with the content of
106  * `configuration_documents` key from `container`.
107  * @param container parameter set including a table with key `configListKey`
108  * @param configListKey name of the key in `container` with the configuration
109  * @param components keys to be converted (as regular expressions)
110  * @return a parameter set
111  *
112  * The `configuration_documents` element of `container` is processed: for
113  * each of its keys which match at least one of the `components` regular
114  * expression patterns (`std::regex_match()`), the associated string value
115  * is parsed with FHiCL parser, and the result is set as a FHiCL table in
116  * the output parameter set.
117  * For example, if the `components` are
118  * `{ std::regex{".*pmt.*"}, std::regex{".*trigger.*"} }`, the returned
119  * value is a parameter set that may have keys like `icaruspmtee01`,
120  * `icaruspmtew02`, `icarustrigger` etc., each one with a FHiCL table as
121  * `value.
122  */
123  static fhicl::ParameterSet convertConfigurationDocuments(
124  fhicl::ParameterSet const& container,
125  std::string const& configListKey,
126  std::initializer_list<std::regex const> components
127  );
128 
129  /// Returns whether `key` matches at least one of the regular expressions
130  /// in the [ `rbegin`, `rend` [ range.
131  template <typename RBegin, typename REnd>
132  static bool matchKey(std::string const& key, RBegin rbegin, REnd rend);
133 
134  /// @}
135  // --- END ---- Utility ------------------------------------------------------
136 
137 }; // icarus::PMTconfigurationExtractorBase
138 
139 
140 // -----------------------------------------------------------------------------
141 /**
142  * @brief Class to extract PMT readout board configuration.
143  *
144  * This is an example of PMT readout board configuration taken from ICARUS run
145  * 4774 (`destinations` and `metrics` have been omitted):
146  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
147  * icaruspmteetop01: {
148  * daq: {
149  * fragment_receiver: {
150  * BaselineCh1: 14768
151  * BaselineCh10: 14843
152  * BaselineCh11: 14846
153  * BaselineCh12: 14840
154  * BaselineCh13: 14981
155  * BaselineCh14: 14896
156  * BaselineCh15: 14966
157  * BaselineCh16: 14800
158  * BaselineCh2: 14836
159  * BaselineCh3: 14806
160  * BaselineCh4: 14954
161  * BaselineCh5: 14766
162  * BaselineCh6: 14835
163  * BaselineCh7: 14861
164  * BaselineCh8: 14857
165  * BaselineCh9: 14949
166  * BoardChainNumber: 0
167  * CalibrateOnConfig: true
168  * ChargePedstalBitCh1: 14400
169  * CircularBufferSize: 5e8
170  * CombineReadoutWindows: false
171  * GetNextFragmentBunchSize: 20
172  * GetNextSleep: 100
173  * InterruptEventNumber: 1
174  * InterruptLevel: 0
175  * InterruptStatusID: 0
176  * LVDSLogicValueG1: 3
177  * LVDSLogicValueG2: 3
178  * LVDSLogicValueG3: 3
179  * LVDSLogicValueG4: 3
180  * LVDSLogicValueG5: 3
181  * LVDSLogicValueG6: 3
182  * LVDSLogicValueG7: 3
183  * LVDSLogicValueG8: 3
184  * LVDSOutWidthC1: 20
185  * LVDSOutWidthC10: 20
186  * LVDSOutWidthC11: 20
187  * LVDSOutWidthC12: 20
188  * LVDSOutWidthC13: 20
189  * LVDSOutWidthC14: 20
190  * LVDSOutWidthC15: 20
191  * LVDSOutWidthC16: 20
192  * LVDSOutWidthC2: 20
193  * LVDSOutWidthC3: 20
194  * LVDSOutWidthC4: 20
195  * LVDSOutWidthC5: 20
196  * LVDSOutWidthC6: 20
197  * LVDSOutWidthC7: 20
198  * LVDSOutWidthC8: 20
199  * LVDSOutWidthC9: 20
200  * LockTempCalibration: false
201  * MajorityCoincidenceWindow: 1
202  * MajorityLevel: 0
203  * MajorityTimeWindow: 4
204  * ModeLVDS: 1
205  * SWTrigger: false
206  * SelfTrigBit: 16
207  * SelfTriggerMask: 255
208  * SelfTriggerMode: 0
209  * TimeOffsetNanoSec: 0
210  * UseTimeTagForTimeStamp: false
211  * Verbosity: 1
212  * acqMode: 0
213  * allowTriggerOverlap: false
214  * analogMode: 1
215  * boardId: 0
216  * board_id: 18
217  * channelEnable0: true
218  * channelEnable1: true
219  * channelEnable10: true
220  * channelEnable11: true
221  * channelEnable12: true
222  * channelEnable13: true
223  * channelEnable14: true
224  * channelEnable15: true
225  * channelEnable2: true
226  * channelEnable3: true
227  * channelEnable4: true
228  * channelEnable5: true
229  * channelEnable6: true
230  * channelEnable7: true
231  * channelEnable8: true
232  * channelEnable9: true
233  * channelPedestal0: 6554
234  * channelPedestal1: 6554
235  * channelPedestal10: 6554
236  * channelPedestal11: 6554
237  * channelPedestal12: 6554
238  * channelPedestal13: 6554
239  * channelPedestal14: 6554
240  * channelPedestal15: 6554
241  * channelPedestal2: 6554
242  * channelPedestal3: 6554
243  * channelPedestal4: 6554
244  * channelPedestal5: 6554
245  * channelPedestal6: 6554
246  * channelPedestal7: 6554
247  * channelPedestal8: 6554
248  * channelPedestal9: 6554
249  * dacValue: 32768
250  * data_buffer_depth_fragments: 10000
251  * data_buffer_depth_mb: 2000
252  * debugLevel: 7
253  * destinations: {} # ...
254  * dynamicRange: 0
255  * enableReadout: 1
256  * eventCounterWarning: 1
257  * eventsPerInterrupt: 1
258  * extTrgMode: 3
259  * fragment_id: 18
260  * fragment_type: "CAENV1730"
261  * generator: "CAENV1730Readout"
262  * ioLevel: 1
263  * irqWaitTime: 1
264  * link: 2
265  * maxEventsPerTransfer: 1
266  * max_fragment_size_bytes: 1e7
267  * memoryAlmostFull: 2
268  * multicast_interface_ip: "192.168.191.0"
269  * nChannels: 16
270  * outputSignalMode: 0
271  * postPercent: 70
272  * readoutMode: 0
273  * receive_requests: true
274  * recordLength: 25000
275  * request_address: "227.128.1.129"
276  * request_mode: "sequence"
277  * request_port: 3502
278  * routing_table_config: { use_routing_master: false }
279  * runSyncMode: 0
280  * separate_data_thread: true
281  * swTrgMode: 0
282  * testPattern: 0
283  * triggerPolarity: 0
284  * triggerPulseWidth: 20
285  * triggerThreshold0: 14368
286  * triggerThreshold1: 14436
287  * triggerThreshold10: 14446
288  * triggerThreshold11: 14440
289  * triggerThreshold12: 14581
290  * triggerThreshold13: 14596
291  * triggerThreshold14: 14566
292  * triggerThreshold15: 14400
293  * triggerThreshold2: 14406
294  * triggerThreshold3: 14554
295  * triggerThreshold4: 14366
296  * triggerThreshold5: 14435
297  * triggerThreshold6: 14461
298  * triggerThreshold7: 14457
299  * triggerThreshold8: 14549
300  * triggerThreshold9: 14443
301  * usePedestals: false
302  * }
303  * metrics: {} # ...
304  * }
305  * }
306  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
307  *
308  *
309  *
310  *
311  */
314 {
315 
316  public:
317 
318  /// Constructor: no channel mapping, channel IDs won't be `finalize()`'d.
319  PMTconfigurationExtractor() = default;
320 
321  /// Constructor: use channel mapping to `finalize()` channel IDs.
323  (icarusDB::IICARUSChannelMap const& channelMappingService);
324 
325 
326  // --- BEGIN -- Interface ----------------------------------------------------
327  /// @name Interface
328  /// @{
329 
330  /// Returns whether `pset` may contain the needed configuration.
331  static bool mayHaveConfiguration(fhicl::ParameterSet const& pset)
332  { return pset.has_key("configuration_documents"); }
333 
334  /// Returns whether the specified `key` of `pset` is a good configuration.
335  static bool isGoodConfiguration
336  (fhicl::ParameterSet const& pset, std::string const& key);
337 
338 
339  /**
340  * @brief Extracts all supported PMT configuration from `config`.
341  * @param config a FHiCL parameter set with component configuration
342  * @return an object with the supported PMT configuration
343  *
344  * All PMT-related configuration that is known to this code is extracted and
345  * returned.
346  */
347  sbn::PMTconfiguration extract(fhicl::ParameterSet const& config) const;
348 
349 
350  /// Assigns unique channel IDs to the channel information.
352 
353  /// @}
354  // --- END ---- Interface ----------------------------------------------------
355 
356  private:
357 
358  /// Regular expressions matching all names of supported PMT configurations.
359  static std::vector<std::regex> const ConfigurationNames;
360 
361  /// Hardware PMT channel mapping to LArSoft's.
363 
364  /**
365  * @brief Extracts PMT readout board configuration from `pset`.
366  * @param pset information source (FHiCL configuration)
367  * @param boardName name of the board we are given the configuration of
368  * @return the requested configuration
369  *
370  *
371  */
373  (fhicl::ParameterSet const& pset, std::string const& boardName)
374  const;
375 
376  /**
377  * @brief Returns the specified V1730 readout channel configuration.
378  * @param boardPSet readout board configuration
379  * @param channelNo number of channel on board (0-15)
380  * @return the configuration of the specified channel
381  */
383  (fhicl::ParameterSet const& boardPSet, unsigned short int channelNo) const;
384 
385  /**
386  * @brief Returns the specified PMT readout board configuration.
387  * @param pset parameter set including `key`
388  * @param key key of the PMT readout configuration candidate
389  * @return the configuration, or an empty object if key does not represent one
390  */
391  std::optional<fhicl::ParameterSet> readBoardConfig
392  (fhicl::ParameterSet const& pset, std::string const& key) const;
393 
394 
395  /// Returns the fragment ID of the specified board as known by the database.
396  static unsigned int readoutBoardDBfragmentID
397  (sbn::V1730Configuration const& boardConfig);
398 
399 }; // icarus::PMTconfigurationExtractor
400 
401 
402 // -----------------------------------------------------------------------------
403 // --- Inline implementation
404 // -----------------------------------------------------------------------------
406  (icarusDB::IICARUSChannelMap const& channelMappingService)
407  : fChannelMap(&channelMappingService)
408  {}
409 
410 
411 // -----------------------------------------------------------------------------
412 // --- Template implementation
413 // -----------------------------------------------------------------------------
414 namespace icarus::details {
415 
416  template <typename ConfigMap>
418  (ConfigMap const& configMap, icarus::PMTconfigurationExtractor extractor)
419  {
420 
421  /*
422  * Requirements: ConfigMap is a mapping type supporting iteration and whose
423  * elements support structured assignment into a pair, the first element
424  * being an identifier (process name, parameter set ID...) and the second
425  * being a `fhicl::ParameterSet` with the configuration (or something
426  * offering the same interface).
427  *
428  * The plan is to look in all the FHiCL configuration fragments we can find
429  * in the input config, and find all the useful configuration therein.
430  * Given that there may be multiple input files, there may also be multiple
431  * configurations for the same detector components.
432  * In that case, we will extract parameters from each and every one of the
433  * configurations, and throw an exception if they are not all consistent.
434  *
435  * Consistency is tested only for the extracted parameters, not for the whole
436  * FHiCL configuration fragment.
437  */
438 
439  using Key_t = std::tuple_element_t<0U, typename ConfigMap::value_type>;
440 
441  std::optional<std::pair<Key_t, sbn::PMTconfiguration>> config;
442 
443  // look in the global configuration for all parameter sets which contain
444  // `configuration_documents` as a (direct) name;
445  for (auto const& [ id, pset ]: configMap) {
446  if (!extractor.mayHaveConfiguration(pset)) continue;
447 
448  fhicl::ParameterSet const configDocs
450  (pset, "configuration_documents", { std::regex{ "icaruspmt.*" } })
451  ;
452 
453  sbn::PMTconfiguration candidateConfig = extractor.extract(configDocs);
454  if (config) {
455  if (config->second == candidateConfig) continue;
456  mf::LogError log("extractPMTreadoutConfiguration");
457  log << "Found two candidate configurations differring:"
458  "\nFirst [" << config->first << "]:\n" << config->second
459  << "\nSecond [" << id << "]:\n" << candidateConfig
460  ;
461  throw cet::exception("extractPMTreadoutConfiguration")
462  << "extractPMTreadoutConfiguration() found inconsistent configurations.\n";
463  } // if incompatible configurations
464 
465  config.emplace(std::move(id), std::move(candidateConfig));
466  } // for all configuration documents
467 
468  if (!config) {
469  throw cet::exception("extractPMTreadoutConfiguration")
470  << "extractPMTreadoutConfiguration() could not find a suitable configuration.\n";
471  }
472 
473  return extractor.finalize(std::move(config->second));
474  } // extractPMTreadoutConfigurationImpl(ConfigMap)
475 
476 
477 } // namespace icarus::details
478 
479 
480 // -----------------------------------------------------------------------------
481 template <typename RBegin, typename REnd>
483  (std::string const& key, RBegin rbegin, REnd rend)
484 {
485  for (auto iRegex = rbegin; iRegex != rend; ++iRegex)
486  if (std::regex_match(key, *iRegex)) return true;
487  return false;
488 } // icarus::PMTconfigurationExtractorBase::matchKey()
489 
490 
491 // -----------------------------------------------------------------------------
492 template <typename Principal>
494  (Principal const& principal, icarus::PMTconfigurationExtractor extractor)
495 {
496 
498  (util::readConfigurationFromArtPrincipal(principal), std::move(extractor));
499 
500 } // icarus::extractPMTreadoutConfiguration(Principal)
501 
502 
503 // ---------------------------------------------------------------------------
504 
505 
506 #endif // ICARUSCODE_DECODE_DECODERTOOLS_PMTCONFIGURATIONEXTRACTOR_H
ConfigurationData_t extract(fhicl::ParameterSet const &config) const
Extracts all supported PMT configuration from config.
static unsigned int readoutBoardDBfragmentID(sbn::V1730Configuration const &boardConfig)
Returns the fragment ID of the specified board as known by the database.
sbn::V1730channelConfiguration extractChannelConfiguration(fhicl::ParameterSet const &boardPSet, unsigned short int channelNo) const
Returns the specified V1730 readout channel configuration.
static std::vector< std::regex > const ConfigurationNames
Regular expressions matching all names of supported PMT configurations.
static fhicl::ParameterSet convertConfigurationDocuments(fhicl::ParameterSet const &container, std::string const &configListKey, std::initializer_list< std::regex const > components)
Returns a parameter set with the content of configuration_documents key from container.
icarusDB::IICARUSChannelMap const * fChannelMap
Hardware PMT channel mapping to LArSoft&#39;s.
static bool mayHaveConfiguration(fhicl::ParameterSet const &pset)
Returns whether pset may contain the needed configuration.
sbn::PMTconfiguration extractPMTreadoutConfiguration(std::string const &srcFileName, icarus::PMTconfigurationExtractor extractor)
sbn::PMTconfiguration finalize(sbn::PMTconfiguration config) const
Assigns unique channel IDs to the channel information.
static bool matchKey(std::string const &key, RBegin rbegin, REnd rend)
Information from the configuration of a V1730 PMT readout board.
Utilities to extract art FHiCL configuration from different sources.
ConfigurationData_t finalize(ConfigurationData_t config) const
Finalizes the content of config and returns it.
Information from the configuration of PMT readout.
sbn::V1730Configuration extractV1730configuration(fhicl::ParameterSet const &pset, std::string const &boardName) const
Extracts PMT readout board configuration from pset.
PMTconfigurationExtractor()=default
Constructor: no channel mapping, channel IDs won&#39;t be finalize()&#39;d.
static bool isGoodConfiguration(fhicl::ParameterSet const &pset, std::string const &key)
Returns whether the specified key of pset is a good configuration.
std::map< std::string, fhicl::ParameterSet > readConfigurationFromArtPrincipal(Principal const &principal)
Reads and returns the complete art configuration in the principal.
std::optional< fhicl::ParameterSet > readBoardConfig(fhicl::ParameterSet const &pset, std::string const &key) const
Returns the specified PMT readout board configuration.
Class to extract PMT readout board configuration.
static bool mayHaveConfiguration(fhicl::ParameterSet const &pset)
Returns whether pset may contain the needed configuration.
sbn::PMTconfiguration extract(fhicl::ParameterSet const &config) const
Extracts all supported PMT configuration from config.
Class containing configuration for a V1730 channel.
Class containing configuration for PMT readout.
sbn::PMTconfiguration extractPMTreadoutConfigurationImpl(ConfigMap const &configMap, icarus::PMTconfigurationExtractor extractor)
Class containing configuration for a V1730 board.