All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TriggerConfigurationExtractor.h
Go to the documentation of this file.
1 /**
2  * @file icaruscode/Decode/DecoderTools/TriggerConfigurationExtractor.h
3  * @brief Utility to extract Trigger readout configuration from data.
4  * @author Andrea Scarpelli (ascarpell@bnl.gov)
5  * @date March 23 2022
6  * @file icaruscode/Decode/DecoderTools/TriggerConfigurationExtractor.h
7  *
8  */
9 
10 #ifndef ICARUSCODE_DECODE_DECODERTOOLS_TRIGGERCONFIGURATIONEXTRACTOR_H
11 #define ICARUSCODE_DECODE_DECODERTOOLS_TRIGGERCONFIGURATIONEXTRACTOR_H
12 
13 // ICARUS libraries
14 #include "icaruscode/Utilities/ReadArtConfiguration.h" // util::readConfigurationFromArtPrincipal()
17 
18 // framework libraries
19 #include "art/Framework/Principal/DataViewImpl.h"
20 #include "messagefacility/MessageLogger/MessageLogger.h"
21 #include "fhiclcpp/ParameterSet.h"
22 #include "cetlib_except/exception.h"
23 
24 // ROOT libraries
25 #include "TFile.h"
26 
27 // C/C++ standard libraries
28 #include <regex>
29 #include <string>
30 #include <optional>
31 #include <utility> // std::move(), std::pair<>
32 #include <initializer_list>
33 
34 // -----------------------------------------------------------------------------
35 namespace icarus {
36 
37  class TriggerConfigurationExtractorBase;
38  class TriggerConfigurationExtractor;
39 
41  (std::string const& srcFileName, icarus::TriggerConfigurationExtractor extractor);
43  (TFile& srcFile, icarus::TriggerConfigurationExtractor extractor);
44  template <typename Principal>
46  (Principal const& data, icarus::TriggerConfigurationExtractor extractor);
47 
48 } // namespace icarus
49 
50 
51 // -----------------------------------------------------------------------------
53 
54  public:
55 
57 
58  // --- BEGIN -- Interface ----------------------------------------------------
59  /// @name Interface
60  /// @{
61 
62  /// Returns whether `pset` may contain the needed configuration.
63  static bool mayHaveConfiguration(fhicl::ParameterSet const& pset)
64  { return pset.has_key("configuration_documents"); }
65 
66 
67  /**
68  * @brief Extracts all supported Trigger configuration from `config`.
69  * @param config a FHiCL parameter set with component configuration
70  * @return an object with the supported Trigger configuration
71  *
72  * All Trigger-related configuration that is known to this code is extracted and
73  * returned.
74  *
75  * This function is undefined here: it must be overridden.
76  */
77  ConfigurationData_t extract(fhicl::ParameterSet const& config) const;
78 
79  /// @}
80  // --- END ---- Interface ----------------------------------------------------
81 
82 
83  // --- BEGIN -- Utility ------------------------------------------------------
84  /// @name Utility
85  /// @{
86 
87  /**
88  * @brief Returns a parameter set with the content of
89  * `configuration_documents` key from `container`.
90  * @param container parameter set including a table with key `configListKey`
91  * @param configListKey name of the key in `container` with the configuration
92  * @param components keys to be converted (as regular expressions)
93  * @return a parameter set
94  *
95  * The `configuration_documents` element of `container` is processed: for
96  * each of its keys which match at least one of the `components` regular
97  * expression patterns (`std::regex_match()`), the associated string value
98  * is parsed with FHiCL parser, and the result is set as a FHiCL table in
99  * the output parameter set.
100  * For example, if the `components` are
101  * `{ std::regex{".*pmt.*"}, std::regex{".*trigger.*"} }`, the returned
102  * value is a parameter set that may have keys like `icaruspmtee01`,
103  * `icaruspmtew02`, `icarustrigger` etc., each one with a FHiCL table as
104  * `value.
105  */
106  static fhicl::ParameterSet convertConfigurationDocuments(
107  fhicl::ParameterSet const& container,
108  std::string const& configListKey,
109  std::initializer_list<std::regex const> components
110  );
111 
112  /// Returns whether `key` matches at least one of the regular expressions
113  /// in the [ `rbegin`, `rend` [ range.
114  template <typename RBegin, typename REnd>
115  static bool matchKey(std::string const& key, RBegin rbegin, REnd rend);
116 
117  /// @}
118  // --- END ---- Utility ------------------------------------------------------
119 
120 }; // icarus::TriggerConfigurationExtractorBase
121 
122 
123 // -----------------------------------------------------------------------------
124 /**
125  * @brief Class to extract PMT readout board configuration.
126  *
127  * This is an example of PMT readout board configuration taken from ICARUS run
128  * 4774 (`destinations` and `metrics` have been omitted):
129  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
130  *daq: {
131  * fragment_receiver: {
132  *
133  * ....
134  *
135  * fpga_init_params: {
136  * MajLevelBeamCryo1: {
137  * name: "Majority level inside Beam Gate cryo1"
138  * value: "5"
139  * }
140  * MajLevelBeamCryo2: {
141  * name: "Majority level inside Beam Gate cryo2"
142  * value: "5"
143  * }
144  * MajLevelEnableCryo1: {
145  * name: "Majority level inside enable and outside Beam Gate cryo1"
146  * value: "10"
147  * }
148  * MajLevelEnableCryo2: {
149  * name: "Majority level inside enable and outside Beam Gate cryo2"
150  * value: "10"
151  * }
152  * MajorityTriggerType: {
153  * name: "Majority Trigger Type"
154  * value: "majo1or2"
155  * }
156  * RunType: {
157  * name: "Run type"
158  * value: "Majority"
159  * }
160  * SlidingWindowCryo1: {
161  * name: "Sliding window option cryo1"
162  * value: "Separated Window"
163  * }
164  * SlidingWindowCryo2: {
165  * name: "Sliding window option cryo2"
166  * value: "Separated Window"
167  * }
168  * Veto: {
169  * name: "Veto beam gate [ns]"
170  * value: "4000"
171  * }
172  * }
173  *
174  * ....
175  *
176  * generator: "ICARUSTriggerUDP"
177  *
178  * ....
179  *
180  * spexi_init_params: {
181  * BNB1DOffset: {
182  * name: "BNB ($1D) Early Warning Offset"
183  * value: "0"
184  * }
185  * BNBBESOffset: {
186  * name: "BNB (gatedBES) Early Warning Offset"
187  * value: "0"
188  * }
189  * BNBBeamWidth: {
190  * name: "BNB Beam Gate Width [ns]"
191  * value: "8000"
192  * }
193  * BNBEnableWidth: {
194  * name: "BNB Enable Gate Width [ns]"
195  * value: "2000000"
196  * }
197  * GateSelection: {
198  * name: "Gate Selection [hex]"
199  * value: "FF"
200  * }
201  * MI12Ethertype: {
202  * name: "MI12 Ethertype"
203  * value: "5752"
204  * }
205  * MI12MACAddressLSB: {
206  * name: "MI12 MAC Address (LSB)"
207  * value: "30E971C8"
208  * }
209  * MI12MACAddressMSB: {
210  * name: "MI12 MAC Address (MSB)"
211  * value: "0800"
212  * }
213  * MI60Ethertype: {
214  * name: "MI60 Ethertype"
215  * value: "5752"
216  * }
217  * MI60MACAddressLSB: {
218  * name: "MI60 MAC Address (LSB)"
219  * value: "30E93B4F"
220  * }
221  * MI60MACAddressMSB: {
222  * name: "MI60 MAC Address (MSB)"
223  * value: "0800"
224  * }
225  * NuMIADOffset: {
226  * name: "NUMI ($AD) Early Warning Offset"
227  * value: "0"
228  * }
229  * NuMIBeamWidth: {
230  * name: "NuMI Beam Gate Width [ns]"
231  * value: "18000"
232  * }
233  * NuMIEnableWidth: {
234  * name: "NuMI Enable Gate Width [ns]"
235  * value: "2000000"
236  * }
237  * NuMIMIBSOffset: {
238  * name: "NuMI (MIBS$74) Early Warning Offset"
239  * value: "0"
240  * }
241  * OffBeamBNBBeamWidth: {
242  * name: "OffBeam-BNB Gate Width [ns]"
243  * value: "8000"
244  * }
245  * OffBeamBNBEnableWidth: {
246  * name: "OffBeam-BNB Enable Gate Width [ns]"
247  * value: "2000000"
248  * }
249  * OffBeamGateRate: {
250  * name: "OffBeam Gate Rate"
251  * value: "00010003"
252  * }
253  * OffBeamNuMIBeamWidth: {
254  * name: "OffBeam-NuMI Gate Width [ns]"
255  * value: "18000"
256  * }
257  * OffBeamNuMIEnableWidth: {
258  * name: "OffBeam-NuMI Enable Gate Width [ns]"
259  * value: "2000000"
260  * }
261  * PPSWidth: {
262  * name: "PPS Pulse Width [ns]"
263  * value: "1000"
264  * }
265  * PreScaleBNBNuMI: {
266  * name: "Prescale BNB-NuMI Number"
267  * value: "00010001"
268  * }
269  * PreScaleOffBeam: {
270  * name: "Prescale OffBeam Number"
271  * value: "00020002"
272  * }
273  * PrescaleZeroBias: {
274  * name: "Prescale ZeroBias Number"
275  * value: "0064"
276  * }
277  * TPCTriggerDelay: {
278  * name: "TPC Trigger Delay/400"
279  * value: "3250"
280  * }
281  * ZeroBiasEnableWidth: {
282  * name: "ZeroBias Enable Gate Width [ns]"
283  * value: "2000000"
284  * }
285  * ZeroBiasFreq: {
286  * name: "ZeroBias Frequency Period [ns]"
287  * value: "1000000000"
288  * }
289  * ZeroBiasWidth: {
290  * name: "ZeroBias Gate Width [ns]"
291  * value: "1600"
292  * }
293  * }
294  * use_wr_time: true
295  * wr_time_offset_ns: 1e9
296  * }
297  *
298  * ....
299  *
300  *}
301  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
302  *
303  *
304  *
305  *
306  */
307 
308 
311 {
312 
313  public:
314 
315  /// Learns the name of the trigger fragment type.
317  (std::string const& expectedFragmentType = "ICARUSTriggerUDP")
318  : fExpectedFragmentType{ expectedFragmentType }
319  {}
320 
321  // --- BEGIN -- Interface ----------------------------------------------------
322  /// @name Interface
323  /// @{
324 
325  /// Returns whether `pset` may contain the needed configuration.
326  static bool mayHaveConfiguration(fhicl::ParameterSet const& pset)
327  { return pset.has_key("configuration_documents"); }
328 
329  /// Returns whether the specified `key` of `pset` is a good configuration.
330  static bool isGoodConfiguration
331  (fhicl::ParameterSet const& pset, std::string const& key);
332 
333 
334  /**
335  * @brief Extracts all supported Trigger configuration from `config`.
336  * @param config a FHiCL parameter set with component configuration
337  * @return an object with the supported Trigger configuration
338  *
339  * All Trigger-related configuration that is known to this code is extracted and
340  * returned.
341  */
342  icarus::TriggerConfiguration extract(fhicl::ParameterSet const& config) const;
343 
344  /// @}
345  // --- END ---- Interface ----------------------------------------------------
346 
347  private:
348 
349  std::string const fExpectedFragmentType;
350 
351  /// Regular expressions matching all names of supported Trigger configurations.
352  static std::vector<std::regex> const ConfigurationNames;
353 
354  /**
355  * @brief Extracts trigger readout board configuration from `pset`.
356  * @param pset information source (FHiCL configuration)
357  * @param boardName name of the board we are given the configuration of
358  * @return the requested configuration
359  *
360  *
361  */
363  (fhicl::ParameterSet const& pset)
364  const;
365 
366  /**
367  * @brief Returns the specified Trigger readout board configuration.
368  * @param pset parameter set including `key`
369  * @param key key of the Trigger readout configuration candidate
370  * @return the configuration, or an empty object if key does not represent one
371  */
372  std::optional<fhicl::ParameterSet> readTriggerConfig
373  (fhicl::ParameterSet const& pset, std::string const& key) const;
374 
375  unsigned long parsePrescaleString( std::string prescaleString, std::size_t source ) const;
376 
377  unsigned int parseWindowMode(std::string bitStr) const;
378 
379 }; // icarus::TriggerConfigurationExtractor
380 
381 
382 
383 // -----------------------------------------------------------------------------
384 // --- Template implementation
385 // -----------------------------------------------------------------------------
386 namespace icarus::details {
387 
388  template <typename ConfigMap>
390  (ConfigMap const& configMap, icarus::TriggerConfigurationExtractor extractor)
391  {
392 
393  /*
394  * Requirements: ConfigMap is a mapping type supporting iteration and whose
395  * elements support structured assignment into a pair, the first element
396  * being an identifier (process name, parameter set ID...) and the second
397  * being a `fhicl::ParameterSet` with the configuration (or something
398  * offering the same interface).
399  *
400  * The plan is to look in all the FHiCL configuration fragments we can find
401  * in the input config, and find all the useful configuration therein.
402  * Given that there may be multiple input files, there may also be multiple
403  * configurations for the same detector components.
404  * In that case, we will extract parameters from each and every one of the
405  * configurations, and throw an exception if they are not all consistent.
406  *
407  * Consistency is tested only for the extracted parameters, not for the whole
408  * FHiCL configuration fragment.
409  */
410 
411  using Key_t = std::tuple_element_t<0U, typename ConfigMap::value_type>;
412 
413  std::optional<std::pair<Key_t, icarus::TriggerConfiguration>> config;
414 
415  // look in the global configuration for all parameter sets which contain
416  // `configuration_documents` as a (direct) name;
417  for (auto const& [ id, pset ]: configMap) {
418  if (!extractor.mayHaveConfiguration(pset)) continue;
419 
420  fhicl::ParameterSet const configDocs
422  (pset, "configuration_documents", { std::regex{ "icarustrigger.*" } })
423  ;
424 
425  icarus::TriggerConfiguration candidateConfig = extractor.extract(configDocs);
426  if (config) {
427  if (config->second == candidateConfig) continue;
428  mf::LogError log("extractTriggerReadoutConfiguration");
429  log << "Found two candidate configurations differring:"
430  "\nFirst [" << config->first << "]:\n" << config->second
431  << "\nSecond [" << id << "]:\n" << candidateConfig
432  ;
433  throw cet::exception("extractTriggerReadoutConfiguration")
434  << "extractTriggerReadoutConfiguration() found inconsistent configurations.\n";
435  } // if incompatible configurations
436 
437  config.emplace(std::move(id), std::move(candidateConfig));
438  } // for all configuration documents
439 
440  if (!config) {
441  throw cet::exception("extractTriggerReadoutConfiguration")
442  << "extractTriggerReadoutConfiguration() could not find a suitable configuration.\n";
443  }
444 
445  return std::move(config->second);
446  } // extractPMTreadoutConfigurationImpl(ConfigMap)
447 
448 
449 } // namespace icarus::details
450 
451 
452 // -----------------------------------------------------------------------------
453 template <typename RBegin, typename REnd>
455  (std::string const& key, RBegin rbegin, REnd rend)
456 {
457  for (auto iRegex = rbegin; iRegex != rend; ++iRegex)
458  if (std::regex_match(key, *iRegex)) return true;
459  return false;
460 } // icarus::PMTconfigurationExtractorBase::matchKey()
461 
462 
463 // -----------------------------------------------------------------------------
464 template <typename Principal>
466  (Principal const& principal, icarus::TriggerConfigurationExtractor extractor)
467 {
468 
470  (util::readConfigurationFromArtPrincipal(principal), std::move(extractor));
471 
472 } // icarus::extracatTriggerReadoutConfiguration(Principal)
473 
474 
475 // ---------------------------------------------------------------------------
476 
477 
478 #endif // ICARUSCODE_DECODE_DECODERTOOLS_TRIGGERCONFIGURATIONEXTRACTOR_H
Definitions of the trigger bits for SBN.
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.
static bool matchKey(std::string const &key, RBegin rbegin, REnd rend)
do source
static bool isGoodConfiguration(fhicl::ParameterSet const &pset, std::string const &key)
Returns whether the specified key of pset is a good configuration.
Information from the configuration of the ICARUS trigger readout.
static bool mayHaveConfiguration(fhicl::ParameterSet const &pset)
Returns whether pset may contain the needed configuration.
static bool mayHaveConfiguration(fhicl::ParameterSet const &pset)
Returns whether pset may contain the needed configuration.
Utilities to extract art FHiCL configuration from different sources.
ConfigurationData_t extract(fhicl::ParameterSet const &config) const
Extracts all supported Trigger configuration from config.
icarus::TriggerConfiguration extractTriggerReadoutConfigurationImpl(ConfigMap const &configMap, icarus::TriggerConfigurationExtractor extractor)
icarus::TriggerConfiguration extractTriggerReadoutConfiguration(std::string const &srcFileName, icarus::TriggerConfigurationExtractor extractor)
std::optional< fhicl::ParameterSet > readTriggerConfig(fhicl::ParameterSet const &pset, std::string const &key) const
Returns the specified Trigger readout board configuration.
unsigned long parsePrescaleString(std::string prescaleString, std::size_t source) const
static std::vector< std::regex > const ConfigurationNames
Regular expressions matching all names of supported Trigger configurations.
TriggerConfigurationExtractor(std::string const &expectedFragmentType="ICARUSTriggerUDP")
Learns the name of the trigger fragment type.
std::map< std::string, fhicl::ParameterSet > readConfigurationFromArtPrincipal(Principal const &principal)
Reads and returns the complete art configuration in the principal.
unsigned int parseWindowMode(std::string bitStr) const
Class to extract PMT readout board configuration.
icarus::TriggerConfiguration extractTriggerConfiguration(fhicl::ParameterSet const &pset) const
Extracts trigger readout board configuration from pset.
icarus::TriggerConfiguration extract(fhicl::ParameterSet const &config) const
Extracts all supported Trigger configuration from config.