Project

General

Profile

Configuration validation and fhiclcpp types » History » Version 27

Kyle Knoepfel, 09/09/2016 01:38 PM

1 1 Kyle Knoepfel
h1. Configuration validation and @fhiclcpp@ types
2 1 Kyle Knoepfel
3 1 Kyle Knoepfel
The purpose of introducing @fhiclcpp@ types is to enable:
4 1 Kyle Knoepfel
* a way to validate a user-provided, run-time configuration against a supported configuration,
5 1 Kyle Knoepfel
* a way to provide a description of a supported configuration for a given module, service, or other plugin library,
6 1 Kyle Knoepfel
* an improvement over using the @'pset.get<T>("key",optional_default)'@ pattern. 
7 1 Kyle Knoepfel
8 1 Kyle Knoepfel
The @fhiclcpp@ type system was designed so that users would not need to interact directly with a @fhicl::ParameterSet@ object, but can do so if they desire.
9 1 Kyle Knoepfel
10 1 Kyle Knoepfel
----
11 1 Kyle Knoepfel
12 1 Kyle Knoepfel
h1. %{color:blue}Table of contents%
13 1 Kyle Knoepfel
14 3 Kyle Knoepfel
* [[Configuration_validation_and_fhiclcpp_types#intro|Introduction]]
15 5 Kyle Knoepfel
** [[Configuration_validation_and_fhiclcpp_types#types|fhiclcpp types vs. FHiCL categories]]
16 13 Kyle Knoepfel
** [[Configuration_validation_and_fhiclcpp_types#depend|Necessary header files]]
17 3 Kyle Knoepfel
** [[Configuration_validation_and_fhiclcpp_types#usage|Usage pattern]]
18 3 Kyle Knoepfel
### [[Configuration_validation_and_fhiclcpp_types#declare|fhiclcpp parameter declaration]]
19 3 Kyle Knoepfel
### [[Configuration_validation_and_fhiclcpp_types#validation|ParameterSet validation]]
20 3 Kyle Knoepfel
### [[Configuration_validation_and_fhiclcpp_types#filling|Parameter value filling]]
21 20 Kyle Knoepfel
### [[Configuration_validation_and_fhiclcpp_types#retrieve|Parameter retrieval]]
22 3 Kyle Knoepfel
** [[Configuration_validation_and_fhiclcpp_types#description|Configuration description]]
23 7 Kyle Knoepfel
** [[Configuration_validation_and_fhiclcpp_types#nonart|For users outside of art]]
24 1 Kyle Knoepfel
* [[Fhiclcpp_examples|Examples]]
25 1 Kyle Knoepfel
* [[fhiclcpp types in detail]]
26 14 Kyle Knoepfel
* [[Auxiliary classes]]
27 22 Kyle Knoepfel
* [[Conditional configuration]]
28 1 Kyle Knoepfel
* [[System details]]
29 1 Kyle Knoepfel
30 1 Kyle Knoepfel
----
31 1 Kyle Knoepfel
32 1 Kyle Knoepfel
h1(#intro). %{color:blue}Introduction%
33 1 Kyle Knoepfel
34 4 Kyle Knoepfel
h2(#types). @fhiclcpp@ types vs. FHiCL categories
35 1 Kyle Knoepfel
36 1 Kyle Knoepfel
The mapping between the @fhiclcpp@ and FHiCL types is shown in this table:
37 1 Kyle Knoepfel
38 2 Kyle Knoepfel
|{background:#fba}.*@fhiclcpp@ type*|{background:#fba}.*FHiCL category* |{background:#fba}.*FHiCL example*|
39 1 Kyle Knoepfel
|\3{background:#ddd}. _Each of the @fhiclcpp@ types below reside in the @fhicl@ namespace._|
40 15 Kyle Knoepfel
| *@Atom<T>@*
41 15 Kyle Knoepfel
@OptionalAtom<T>@| atom | <pre>parameter : value</pre> |
42 15 Kyle Knoepfel
|*@Sequence<T>@*
43 15 Kyle Knoepfel
@OptionalSequence<T>@|/3.sequence |<pre><code class="ruby">sequence : [1, 2, 3]</code></pre>|
44 27 Kyle Knoepfel
|*@Sequence<T, std::size_t>@*
45 27 Kyle Knoepfel
@OptionalSequence<T, std::size_t>@|<pre><code class="ruby">sequence : [1, 2, 3] # bounded</code></pre>|
46 15 Kyle Knoepfel
|*@Tuple<T...>@*
47 1 Kyle Knoepfel
@OptionalTuple<T...>@|<pre><code class="ruby">sequence : [1, "two", true]</code></pre>|
48 15 Kyle Knoepfel
|*@Table<T>@*
49 27 Kyle Knoepfel
@Table<T, KeysToIgnore>@
50 15 Kyle Knoepfel
@OptionalTable<T>@|table|<pre><code class="ruby">table : { 
51 1 Kyle Knoepfel
  parameter : value
52 1 Kyle Knoepfel
  sequence  : [4,5,6]
53 1 Kyle Knoepfel
}</code></pre>|
54 1 Kyle Knoepfel
55 26 Kyle Knoepfel
Since the FHiCL _sequence_ type is very flexible, three @fhiclcpp@ types have been introduced to improve the semantics of the C++ code.  Formally speaking, the types @Sequence<T>@ and @Sequence<T, std::size_t>@ map to the same FHiCL _sequence_ category.  However, @Sequence<T,std::size_t>@ is a bounded sequence, which is explained below.  The @Optional*@ parameters above are described [[Fhiclcpp_types_in_detail#Optional-parameters-argument-types|here]].
56 1 Kyle Knoepfel
57 1 Kyle Knoepfel
----
58 1 Kyle Knoepfel
59 12 Kyle Knoepfel
h2(#depend). Necessary header files
60 12 Kyle Knoepfel
61 12 Kyle Knoepfel
<pre><code class="cpp">
62 25 Kyle Knoepfel
#include "fhiclcpp/types/Atom.h"               // fhicl::Atom<T>
63 25 Kyle Knoepfel
#include "fhiclcpp/types/DelegatedParameter.h" // fhicl::DelegatedParameter
64 25 Kyle Knoepfel
#include "fhiclcpp/types/Sequence.h"           // fhicl::Sequence<T> & fhicl::Sequence<T,size_t>
65 25 Kyle Knoepfel
#include "fhiclcpp/types/Tuple.h"              // fhicl::Tuple<T...>
66 25 Kyle Knoepfel
#include "fhiclcpp/types/TupleAs.h"            // fhicl::TupleAs<T(U...)>
67 25 Kyle Knoepfel
#include "fhiclcpp/types/Table.h"              // fhicl::Table<T> 
68 25 Kyle Knoepfel
#include "fhiclcpp/types/TableFragment.h"      // fhicl::TableFragment<T> 
69 23 Kyle Knoepfel
70 25 Kyle Knoepfel
#include "fhiclcpp/types/OptionalAtom.h"                // fhicl::OptionalAtom<T>
71 25 Kyle Knoepfel
#include "fhiclcpp/types/OptionalDelegatedParameter.h"  // fhicl::OptionalDelegatedParameter
72 25 Kyle Knoepfel
#include "fhiclcpp/types/OptionalSequence.h"            // fhicl::OptionalSequence<T> & fhicl::OptionalSequence<T,size_t>
73 25 Kyle Knoepfel
#include "fhiclcpp/types/OptionalTuple.h"               // fhicl::OptionalTuple<T...>
74 25 Kyle Knoepfel
#include "fhiclcpp/types/OptionalTupleAs.h"             // fhicl::OptionalTupleAs<T(U...)>
75 25 Kyle Knoepfel
#include "fhiclcpp/types/OptionalTable.h"               // fhicl::OptionalTable<T> 
76 16 Kyle Knoepfel
77 1 Kyle Knoepfel
// Headers that can be included
78 23 Kyle Knoepfel
//  - 'fhicl::Name', 'fhicl::Comment', and 
79 23 Kyle Knoepfel
//    'fhicl::use_if' and 'fhicl::use_unless' are already 
80 12 Kyle Knoepfel
//    provided by each of the headers above
81 12 Kyle Knoepfel
#include "fhiclcpp/types/Name.h"
82 12 Kyle Knoepfel
#include "fhiclcpp/types/Comment.h"
83 23 Kyle Knoepfel
#include "fhiclcpp/types/ConfigPredicate.h"
84 12 Kyle Knoepfel
</code></pre>
85 12 Kyle Knoepfel
86 12 Kyle Knoepfel
----
87 1 Kyle Knoepfel
88 1 Kyle Knoepfel
h2(#usage). Usage pattern
89 1 Kyle Knoepfel
90 1 Kyle Knoepfel
The order in which the system is used is the following:
91 1 Kyle Knoepfel
92 1 Kyle Knoepfel
# *@fhiclcpp@ parameter declarations*: @fhiclcpp@ parameters are declarated
93 1 Kyle Knoepfel
# *@ParameterSet@ validation*: @fhicl::ParameterSet@ is validated against the @fhiclcpp@ parameter collection
94 1 Kyle Knoepfel
# *Value filling*: Values are filled for @fhiclcpp@ parameters from the @ParameterSet@
95 1 Kyle Knoepfel
# *Value retrieval*: Values are usable in C++ code
96 1 Kyle Knoepfel
97 1 Kyle Knoepfel
Steps 1 and 4 are exposed to the user.  Steps 2 and 3 can be exposed to the user, in principle, but we do not encourage the user to do them unless there is a good reason (please consult artists@fnal.gov for guidance).  
98 11 Kyle Knoepfel
99 1 Kyle Knoepfel
For _art_ users, please consult [[art:Configuration_validation_and_description|here]].  Users outside of art should consult the link [[Configuration_validation_and_fhiclcpp_types#nonart|below]].
100 1 Kyle Knoepfel
101 1 Kyle Knoepfel
----
102 1 Kyle Knoepfel
103 1 Kyle Knoepfel
h2(#declare). 1. @fhiclcpp@ parameter declaration
104 1 Kyle Knoepfel
105 1 Kyle Knoepfel
A @fhiclcpp@ parameter declaration follows the pattern:
106 1 Kyle Knoepfel
107 6 Kyle Knoepfel
<pre><code class="cpp">
108 1 Kyle Knoepfel
fhiclcpp_type < arg_type(s) > name { Name("name"), [Optional arguments] };
109 1 Kyle Knoepfel
</code></pre>
110 1 Kyle Knoepfel
111 1 Kyle Knoepfel
where @fhiclcpp_type@ is either @Atom@, @Sequence@, @Tuple@, or @Table@.  
112 1 Kyle Knoepfel
113 1 Kyle Knoepfel
h3. @arg_type(s)@
114 1 Kyle Knoepfel
115 1 Kyle Knoepfel
The allowed set of @arg_type(s)@ values depends on the specific value of @fhiclcpp_type@ (and described in detail <HERE>).  In general, almost any C++ type that is currently supported in a @ParameterSet::get@ call is allowed.  The @std@ containers, however, are *not* allowed for any @fhiclcpp@ type:
116 1 Kyle Knoepfel
* @std::array@
117 1 Kyle Knoepfel
* @std::pair@
118 1 Kyle Knoepfel
* @std::tuple@
119 1 Kyle Knoepfel
* @std::vector@
120 6 Kyle Knoepfel
121 1 Kyle Knoepfel
h3. @Name("name")@
122 6 Kyle Knoepfel
123 1 Kyle Knoepfel
All @fhiclcpp@ types must be initialized with a @fhicl::Name@ rvalue as its first argument.  The @"name"@ string corresponds to the sequence of characters corresponding to the parameter name in a FHiCL configuration:
124 1 Kyle Knoepfel
125 1 Kyle Knoepfel
<pre>
126 1 Kyle Knoepfel
name : "some value for name"
127 1 Kyle Knoepfel
</pre>
128 6 Kyle Knoepfel
129 1 Kyle Knoepfel
In general, we suggest the same character sequence for the variable name @'name'@ as the string supplied in the @fhicl::Name@.  For example, 
130 6 Kyle Knoepfel
<pre><code class="cpp">
131 1 Kyle Knoepfel
Atom<int> debugValue { Name("threshold") }; // discouraged
132 1 Kyle Knoepfel
</code></pre>
133 1 Kyle Knoepfel
is discouraged as the mismatch in @debugValue@ vs. @threshold@ is likely to cause confusion when parameter value retrievals are performed (see <HERE>).
134 1 Kyle Knoepfel
135 1 Kyle Knoepfel
h3. Optional arguments
136 6 Kyle Knoepfel
137 1 Kyle Knoepfel
All optional arguments must be specified after the @fhicl::Name@ argument.  Both options below can be specified with the same @fhiclcpp@ parameter declaration.
138 1 Kyle Knoepfel
139 1 Kyle Knoepfel
p. %{color:blue}@fhicl::Comment@%
140 1 Kyle Knoepfel
141 1 Kyle Knoepfel
Each of the types may include a @fhicl::Comment@ rvalue argument, whose string will be printed whenever the description of the configuration is requested:
142 1 Kyle Knoepfel
143 1 Kyle Knoepfel
<pre><code class="cpp">
144 6 Kyle Knoepfel
Atom<int> param { 
145 1 Kyle Knoepfel
  Name("param"),           // 'Name' is NOT optional
146 1 Kyle Knoepfel
  Comment("A description") // 'Comment' is optional
147 1 Kyle Knoepfel
};
148 22 Kyle Knoepfel
</code></pre>
149 22 Kyle Knoepfel
150 22 Kyle Knoepfel
p. %{color:blue}@std::function<bool()>@ - conditional configuration predicate%
151 22 Kyle Knoepfel
152 1 Kyle Knoepfel
In some cases, it is desirable to introduce components of a configuration only if the value of a previously-supplied parameter satisfies a given condition (i.e a predicate).  This is done by the user providing an @std::function@ object whose function type receives no arguments, and whose return type is @bool@.  Details as to how a user can enable this feature are given [[Conditional_configuration|here]].
153 1 Kyle Knoepfel
154 1 Kyle Knoepfel
p. %{color:blue}Parameter value default%
155 1 Kyle Knoepfel
156 1 Kyle Knoepfel
All @fhiclcpp@ types can receive a default parameter value except for @fhicl::Table@ objects.  If a FHiCL configuration does not provide the parameter value, then the default value will be used.  For example,
157 6 Kyle Knoepfel
<pre><code class="cpp">
158 1 Kyle Knoepfel
Atom<int> param { Name("param"), 4 };
159 1 Kyle Knoepfel
</code></pre>will yield the same behavior as 
160 1 Kyle Knoepfel
<pre><code class="cpp">
161 1 Kyle Knoepfel
auto param = pset.get<int>("param", 4);
162 1 Kyle Knoepfel
</code></pre>whenever the value of @"parm"@ is retrieved.  A significant difference, however, is that all parameter values are loaded prior to retrieval with the @fhiclcpp@-typed system.
163 1 Kyle Knoepfel
164 1 Kyle Knoepfel
----
165 1 Kyle Knoepfel
166 1 Kyle Knoepfel
h2(#validation). 2. Configuration validation
167 1 Kyle Knoepfel
168 1 Kyle Knoepfel
The validation feature is designed to catch 
169 1 Kyle Knoepfel
* missing parameters as determined by the declared @fhiclcpp@ parameters in the C++ code
170 1 Kyle Knoepfel
* extra parameters in a user's configuration file that are not supported by any corresponding declared @fhiclcpp@ parameters
171 6 Kyle Knoepfel
172 1 Kyle Knoepfel
For @fhiclcpp@ parameters that receive a default value, a corresponding FHiCL parameter that is absent in a configuration file is not an error.  Any misspelled FHiCL parameters -- i.e. those that do not match the string supplied in the @fhicl::Name@ argument of the @fhiclcpp@ parameter constructor -- are classified as extra parameters and are thus caught.
173 1 Kyle Knoepfel
174 1 Kyle Knoepfel
Consider the following allowed configuration:
175 1 Kyle Knoepfel
176 1 Kyle Knoepfel
<pre><code class="cpp">
177 6 Kyle Knoepfel
struct Config {
178 1 Kyle Knoepfel
  Atom<std::string> name { Name("name"), "Gustav" };
179 1 Kyle Knoepfel
};
180 6 Kyle Knoepfel
181 1 Kyle Knoepfel
Table<Config> pset { Name("pset") };
182 1 Kyle Knoepfel
</code></pre>
183 1 Kyle Knoepfel
184 1 Kyle Knoepfel
An attempt is made to provide a configuration to the file that uses this configuration.  However the file FHiCL file is misconfigured:
185 1 Kyle Knoepfel
186 1 Kyle Knoepfel
<pre><code class="ruby">
187 1 Kyle Knoepfel
# config.fcl
188 1 Kyle Knoepfel
pset : {
189 1 Kyle Knoepfel
   nam  : Mahler # attempt to override default value of "Gustav"
190 1 Kyle Knoepfel
   flag : false
191 1 Kyle Knoepfel
}
192 1 Kyle Knoepfel
</code></pre>
193 6 Kyle Knoepfel
194 1 Kyle Knoepfel
The parameter @nam@ is misspelled with respect to the allowed configuration name @"name"@, and @flag@ is not supported.  When the configuration validation step is performed, an exception is thrown and the following error message is printed to STDOUT:
195 1 Kyle Knoepfel
196 1 Kyle Knoepfel
<pre>
197 1 Kyle Knoepfel
Unsupported parameters:
198 1 Kyle Knoepfel
199 1 Kyle Knoepfel
 + flag                           [ ./config.fcl:3 ]
200 1 Kyle Knoepfel
 + nam                            [ ./config.fcl:2 ]
201 1 Kyle Knoepfel
</pre>
202 1 Kyle Knoepfel
203 1 Kyle Knoepfel
The characters in brackets denote the location of the unsupported parameter [ @file-name:line-number@ ].  The listing order of the unsupported parameters is based on the @std::string@ ordering operator, which is lexicographical.
204 1 Kyle Knoepfel
205 1 Kyle Knoepfel
----
206 1 Kyle Knoepfel
207 1 Kyle Knoepfel
h2(#filling). 3. Parameter value filling
208 1 Kyle Knoepfel
209 1 Kyle Knoepfel
If the validation step (2) is successful -- i.e. the @fhicl::ParameterSet@ object conforms to the supported configuration as declared in the C++ code -- then the values of the parameters are filled using the specified values in the configuration file, or the default values as specified in the C++ code if the corresponding FHiCL parameter has not been provided.  After this step, the @fhiclcpp@ parameter now has a value corresponding to the user-provided ones.
210 1 Kyle Knoepfel
211 1 Kyle Knoepfel
The parameter-value-filling step is done internally, the details of which are not necessary to understand for the user.
212 1 Kyle Knoepfel
213 1 Kyle Knoepfel
----
214 18 Kyle Knoepfel
215 1 Kyle Knoepfel
h2(#retrieve). 4. Parameter retrieval
216 18 Kyle Knoepfel
217 18 Kyle Knoepfel
h3. Standard parameters
218 18 Kyle Knoepfel
219 1 Kyle Knoepfel
For a standard @fhiclcpp@ parameter declared as:
220 6 Kyle Knoepfel
<pre><code class="cpp">
221 18 Kyle Knoepfel
Atom<int> param { Name("param"), 4 };
222 1 Kyle Knoepfel
</code></pre>the integer value of the parameter can be retrieved using the function-call syntax @'()'@:
223 1 Kyle Knoepfel
<pre><code class="cpp">
224 1 Kyle Knoepfel
auto param_value = param(); // 'param_value' is int
225 18 Kyle Knoepfel
</code></pre>assuming the supplied value in the FHiCL configuration can be decoded to the C++ type @int@.
226 18 Kyle Knoepfel
227 18 Kyle Knoepfel
h3. Optional parameters
228 18 Kyle Knoepfel
229 18 Kyle Knoepfel
For an optional @fhiclcpp@ parameter declared as:
230 18 Kyle Knoepfel
231 18 Kyle Knoepfel
<pre><code class="cpp">
232 18 Kyle Knoepfel
OptionalAtom<int> optParam { Name("optParam") };
233 18 Kyle Knoepfel
</code></pre>the integer value of the parameter can be retrieved *if present* in a configuration file by passing a variable by reference using the function-call syntax @'()'@:
234 18 Kyle Knoepfel
<pre><code class="cpp">
235 18 Kyle Knoepfel
int j{};
236 18 Kyle Knoepfel
if ( optParam(j) ) {
237 18 Kyle Knoepfel
   // 'j' can now be used
238 18 Kyle Knoepfel
}
239 18 Kyle Knoepfel
</code></pre>
240 19 Kyle Knoepfel
241 18 Kyle Knoepfel
If @'optParam'@ is present with a non-nil value in a configuration file, the value of @optParam(j)@ will return @true@, and @j@ will be filled with the configuration-set value.  Otherwise, @j@ retains its initial value ('0' in this case).  Note that optional parameters can receive no default value.
242 18 Kyle Knoepfel
243 1 Kyle Knoepfel
h3. General structure
244 1 Kyle Knoepfel
245 1 Kyle Knoepfel
The @fhiclcpp@-typed system has been designed in such a way that the parameter declaration and retrieval syntaxes are similar.  For example, the FHiCL configuration:
246 1 Kyle Knoepfel
<pre><code class="ruby">
247 1 Kyle Knoepfel
# FHiCL parameter declarations
248 1 Kyle Knoepfel
settings : {
249 1 Kyle Knoepfel
  verbosity : true
250 1 Kyle Knoepfel
}
251 1 Kyle Knoepfel
252 1 Kyle Knoepfel
# FHiCL value retrieval
253 1 Kyle Knoepfel
verbosity : @local::settings.verbosity
254 1 Kyle Knoepfel
</code></pre>would have a @fhiclcpp@ representation of:
255 1 Kyle Knoepfel
<pre><code class="cpp">
256 1 Kyle Knoepfel
// fhiclcpp parameter declarations
257 6 Kyle Knoepfel
struct Settings{
258 1 Kyle Knoepfel
  Atom<bool> verbosity { Name("verbosity") };
259 6 Kyle Knoepfel
};
260 1 Kyle Knoepfel
Table<Settings> settings { Name("settings") };
261 1 Kyle Knoepfel
262 1 Kyle Knoepfel
// fhiclcpp value retrieval
263 1 Kyle Knoepfel
auto verbosity = settings().verbosity();
264 1 Kyle Knoepfel
</code></pre>Details are [[Fhiclcpp_types_in_detail#return|here]] regarding specific return values for the different @fhiclcpp@ types.
265 1 Kyle Knoepfel
266 1 Kyle Knoepfel
----
267 1 Kyle Knoepfel
268 1 Kyle Knoepfel
h2(#description). Configuration description
269 1 Kyle Knoepfel
270 1 Kyle Knoepfel
Consider the following @fhiclcpp@ parameter configuration:
271 1 Kyle Knoepfel
<pre><code class="cpp">
272 6 Kyle Knoepfel
struct G4Settings {
273 6 Kyle Knoepfel
  Atom<double> energyCutoff { Name("energyCutoff") };
274 1 Kyle Knoepfel
  Atom<string> physicsList  { Name("physicsList"), "QGSP_BERT" };
275 1 Kyle Knoepfel
};
276 1 Kyle Knoepfel
277 21 Kyle Knoepfel
struct Config {
278 21 Kyle Knoepfel
  Atom<bool> flag       { Name("flag"), false };
279 21 Kyle Knoepfel
  Atom<int>  threshold  { Name("threshold"), Comment("ADC count threshold") };
280 21 Kyle Knoepfel
  OptionalTable<G4Settings> g4Settings { Name("g4Settings") }; 
281 1 Kyle Knoepfel
  Sequence<string,2u>       particles  { Name("particles")  };
282 6 Kyle Knoepfel
};
283 1 Kyle Knoepfel
Table<Config> config { Name("config") };
284 1 Kyle Knoepfel
</code></pre>
285 1 Kyle Knoepfel
286 1 Kyle Knoepfel
h3. Formation
287 1 Kyle Knoepfel
288 1 Kyle Knoepfel
The description of the allowed FHiCL configuration (as shown above) is formed based on the order of initialization of the class members.  In addition to registering the expected key, the expected type and any user-provided defaults are also registered with the @fhiclcpp@ system.  The below table shows the order of initialization and the corresponding FHiCL keys and types for each @fhiclcpp@ parameter.
289 1 Kyle Knoepfel
290 1 Kyle Knoepfel
|{background:#fba}.*Order*|{background:#fba}.*C++ variable* |{background:#fba}.*Registered FHiCL key*|{background:#fba}. *Registered FHiCL type*|
291 1 Kyle Knoepfel
|={background:#ddd}. 1|@config@|@"config"@|=. table |
292 1 Kyle Knoepfel
|={background:#ddd}.2|&nbsp;&nbsp;&nbsp;&nbsp;@flag@|@"config.flag"@|=. atom |
293 1 Kyle Knoepfel
|={background:#ddd}.3|&nbsp;&nbsp;&nbsp;&nbsp;@threshold@|@"config.threshold"@|=. atom |
294 1 Kyle Knoepfel
|={background:#ddd}.4|&nbsp;&nbsp;&nbsp;&nbsp;@g4Settings@|@"config.g4Settings"@|=. table |
295 1 Kyle Knoepfel
|={background:#ddd}.5|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@energyCutoff@|@"config.g4Settings.energyCutoff"@|=. atom |
296 1 Kyle Knoepfel
|={background:#ddd}.6|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@physicsList@|@"config.g4Settings.physicsList"@|=. atom |
297 1 Kyle Knoepfel
|={background:#ddd}.7|&nbsp;&nbsp;&nbsp;&nbsp;@particles@|@"config.particles"@|=. sequence |
298 1 Kyle Knoepfel
|={background:#ddd}.8|/2.&nbsp;&nbsp;&nbsp;&nbsp;@particles[*]@|/2.@"config.particles[*]"@|=. atom |
299 1 Kyle Knoepfel
|={background:#ddd}.9|=. atom |
300 1 Kyle Knoepfel
301 1 Kyle Knoepfel
The asterisk @'*'@ means that the order of initialization of the individual @Sequence@ elements is unknown and therefore the key assignment needs to be handled specially.
302 1 Kyle Knoepfel
303 1 Kyle Knoepfel
h3. Print-out
304 1 Kyle Knoepfel
305 1 Kyle Knoepfel
For users that have access to the 'config' object, a print-out of the allowed description can be produced using:
306 1 Kyle Knoepfel
<pre><code class="cpp">
307 17 Kyle Knoepfel
Table<Config> config { Name("config") };
308 1 Kyle Knoepfel
config.print_allowed_configuration(std::cout); // Any 'std::ostream' object can be provided
309 1 Kyle Knoepfel
</code></pre>
310 1 Kyle Knoepfel
311 1 Kyle Knoepfel
The printed description is sent to STDOUT:
312 17 Kyle Knoepfel
<pre>
313 1 Kyle Knoepfel
   config: {
314 17 Kyle Knoepfel
315 1 Kyle Knoepfel
      flag: false  # default
316 1 Kyle Knoepfel
317 1 Kyle Knoepfel
      # ADC count threshold
318 17 Kyle Knoepfel
319 1 Kyle Knoepfel
      threshold: <int>
320 17 Kyle Knoepfel
321 17 Kyle Knoepfel
    ( g4Settings: {
322 17 Kyle Knoepfel
    (
323 17 Kyle Knoepfel
    (    energyCutoff: <double>
324 17 Kyle Knoepfel
    (
325 17 Kyle Knoepfel
    (    physicsList: "QGSP_BERT"  # default
326 1 Kyle Knoepfel
    ( }
327 17 Kyle Knoepfel
328 1 Kyle Knoepfel
      particles: [
329 1 Kyle Knoepfel
         <string>,
330 1 Kyle Knoepfel
         <string>
331 1 Kyle Knoepfel
      ]
332 1 Kyle Knoepfel
   }
333 1 Kyle Knoepfel
</pre>
334 17 Kyle Knoepfel
335 17 Kyle Knoepfel
The open parentheses (@'('@) indicate that the @g4Settings@ table is an optional table, which the user is not required to specify in the configuration file.  
336 17 Kyle Knoepfel
337 7 Kyle Knoepfel
For _art_ users, printing out the allowed configuration is described [[art:Art|here]].
338 7 Kyle Knoepfel
339 7 Kyle Knoepfel
----
340 7 Kyle Knoepfel
341 7 Kyle Knoepfel
h2(#nonart). Non-@art@ users
342 7 Kyle Knoepfel
343 7 Kyle Knoepfel
For users outside of _art_, it is possible to use the @fhiclcpp@ types system.  The following pattern is recommended:
344 7 Kyle Knoepfel
<pre><code class="cpp">
345 7 Kyle Knoepfel
namespace {
346 7 Kyle Knoepfel
347 7 Kyle Knoepfel
  struct MyConfig {
348 7 Kyle Knoepfel
    // fhiclcpp parameter declarations ...
349 7 Kyle Knoepfel
  };
350 7 Kyle Knoepfel
351 7 Kyle Knoepfel
  fhicl::Table<MyConfig>
352 7 Kyle Knoepfel
  retrieveConfiguration( fhicl::ParameterSet const & pset )
353 7 Kyle Knoepfel
  {
354 7 Kyle Knoepfel
     std::set<std::string> ignorable_keys {}; // keys that should be ignored 
355 7 Kyle Knoepfel
                                              // by the validation system (can be empty)
356 7 Kyle Knoepfel
357 7 Kyle Knoepfel
     fhicl::Table<MyConfig> const result { pset, ignorable_keys }; // performs validation and value setting
358 7 Kyle Knoepfel
359 7 Kyle Knoepfel
     return result;
360 7 Kyle Knoepfel
  }
361 7 Kyle Knoepfel
362 7 Kyle Knoepfel
} // anon. namespace
363 7 Kyle Knoepfel
364 7 Kyle Knoepfel
void some_func( fhicl::ParameterSet const & pset )
365 7 Kyle Knoepfel
{
366 7 Kyle Knoepfel
  auto config = retrieveConfiguration( pset );
367 7 Kyle Knoepfel
  // 'config' now usable
368 7 Kyle Knoepfel
}
369 7 Kyle Knoepfel
370 1 Kyle Knoepfel
</code></pre>