Project

General

Profile

Configuration validation and description


Validation and description use in user code

Guidelines for defining the configuration

The documentation for defining an allowed configuration is given here. Here, we will consider how the configuration should be defined in different contexts.

If your configuration needs to be used in multiple places, you can place the configuration in a header file. However, you should not invoke a using directive (e.g. using namespace fhicl). Rather, you must qualify the types with their fhiclcpp namespace:

namespace yours {

  struct MyConfig {
    fhicl::Atom<int>         threshold { fhicl::Name("threshold") };
    fhicl::Atom<std::string> tagLabel  { fhicl::Name("tagLabel")  };
    fhicl::Sequence<int,3u>  offset    { fhicl::Name("offset")    };
  };

}

For lengthy configurations, it is safe to include type/template aliases within the configuration definition:

namespace yours {

  struct MyConfig {

    // aliases (these are NOT 'using' directives)
    using Name = fhicl::Name;

    template<typename T> 
    using Atom = fhicl::Atom<T>;

    template<typename T, std::size_t SZ> 
    using Sequence = fhicl::Sequence<T,SZ>;

    // configuration
    Atom<int>         threshold { Name("threshold") };
    Atom<std::string> tagLabel  { Name("tagLabel")  };
    Sequence<int,3u>  offset    { Name("offset")    };
    // etc.

  };

}

Configurations local to the plugin

For configurations that do not need to be shared with other files, they should be placed in an anonymous namespace local to the source file:

// MyModule_module.cc

namespace {

  using namespace fhicl;

  struct MyConfig {
    Atom<int>         threshold { Name("threshold") };
    Atom<std::string> tagLabel  { Name("tagLabel")  };
    Sequence<int,3u>  offset    { Name("offset")    };
  };
}

namespace experiment {
    class MyModule : public art::EDAnalyzer { ... };
}

DEFINE_ART_MODULE(experiment::MyModule);

By placing the configuration in an anonymous namespace, this ensures that the MyConfig definition is local to the library corresponding to this source file. If the MyConfig definition is placed inside of the experiment namespace, and if another module places a different MyConfig struct definition in the experiment namespace, then the library-loading system will likely not invoke the correct definition for each module.

art-provided and -injected parameters

Provided parameters

For all modules, a required FHiCL parameter is module_type, followed by a string of characters corresponding to prefix of the dynamic library prefix_module.so. Because of this requirement, art provides the parameter declaration for the user, and the user does not have to specify a declaration like:

Atom<string> module_type { Name("module_type") }; // Not required

If the user does specify such a parameter, the program will execute correctly, although the description will specify 'module_type' twice in the printout.

Injected parameters

The art executable injects various parameters into the fhicl::ParameterSet object, depending on the context. For example, the post-processed configuration corresponding to:

label: {
  module_type: MyModule
}

will be

label: {
  module_type : MyModule
  module_label: "label"   # inserted by 'art'
}

The user is not required to specify these injected parameters in his/her configuration. In general, the parameters are not even accessible unless one interacts with the fhicl::ParameterSet object itself via a call to pset.get<std::string>("module_label").

Since the injected parameters are meant to be internal to art, we do not explicitly list each of them here.

Enabling configuration validation

For the following cases, all validation is enabled by declaring a constructor that receives a Table argument instead of a ParameterSet one. The validation will be performed just prior to module/service construction. If there is a configuration error, the following type of message will be sent to STDOUT, and the program will terminate.

---- Configuration BEGIN

  ====================================================================================================

  !! The following modules have been misconfigured: !!

  ----------------------------------------------------------------------------------------------------

  Module label: m1a
  module_type : IntProducer

  Missing parameters:

   -    ivalue : <int>

  Unsupported parameters:

   + ivalu                          [ ./test_simple_01.fcl:50 ]

  ====================================================================================================

---- Configuration END

In this case, a user attempted to supply a value for ivalue, but misspelled the parameter.

For all modules, the appropriate Table class templates are provided automatically by the corresponding producer, filter, or analyzer header file.

Producers

#include "art/Framework/Core/EDProducer.h" 

// ... hopefully in a namespace ...

struct Config { ... }; // fhicl-cpp parameter declarations

class MyProducer : public art::EDProducer {

  explicit MyProducer(art::EDProducer::Table<Config> const& config);

};

Filters

#include "art/Framework/Core/EDFilter.h" 

// ... hopefully in a namespace ...

struct Config { ... }; // fhicl-cpp parameter declarations

class MyFilter : public art::EDFilter {

  explicit MyFilter(art::EDFilter::Table<Config> const& config);

};

Analyzers

#include "art/Framework/Core/EDAnalyzer.h" 

// ... hopefully in a namespace ...

struct Config { ... }; // fhicl-cpp parameter declarations

class MyAnalyzer : public art::EDAnalyzer {

  explicit MyAnalyzer(art::EDAnalyzer::Table<Config> const& config);

};

Results producers (validation/description supported as of art 2.11.00)

#include "art/Framework/Core/ResultsProducer.h" 

// ... hopefully in a namespace ...

struct Config { ... }; // fhicl-cpp parameter declarations

class MyAnalyzer : public art::ResultsProducer {

  explicit MyAnalyzer(art::ResultsProducer::Table<Config> const& config);

};

Services

For services, the relevant table must be explicitly #included.

#include "art/Framework/Services/Registry/ServiceTable.h" 

// ... hopefully in a namespace ...

struct Config { ... }; // fhicl-cpp parameter declarations

class MyService {

  explicit MyService(art::ServiceTable<Config> const& config,
                     art::ActivityRegistry& aReg);

};

Ignoring keys during validation

As described here, specific keys can be ignored during validation if a suitable type is supplied. For example:

struct KeysToIgnore {
  std::set<std::string> operator()()
  {
    return {"myTable1", "mySequence", "myTable2.mySequence"};
  }
};

indicates to the validation system that myTable1 (and its members), mySequence and myTable2.mySequence are permitted to be present, in addition to the supported configuration. To make use of this feature, provide the KeysToIgnore type as an additional template argument to any of the art-provided tables:

art::EDProducer::Table<T> = Replaced by => art::EDProducer::Table<T, KeysToIgnore>
art::EDFilter::Table<T> art::EDFilter::Table<T, KeysToIgnore>
art::EDAnalyzer::Table<T> art::EDAnalyzer::Table<T, KeysToIgnore>
art::ResultsProducer::Table<T> art::ResultsProducer::Table<T, KeysToIgnore>
art::ServiceTable<T> art::ServiceTable<T, KeysToIgnore>

The KeysToIgnore type must contain an operator()() function that returns an std::set<std::string> object.

N.B. Supplying a KeysToIgnore type yields different behavior than the (Optional)DelegatedParameter class, which is explained here.

Required configuration validation for users

An unintentional consequence of enabling configuration validation for art-provided modules (see below) is that users who provide a detail class to art::ProvenanceDumper must provide a configuration struct named Config. For example:

class PDDetail {

  // The configuration here MUST be called 'Config'
  struct Config : art::ProvenanceDumperConfig {
    fhicl::Atom<bool> flag { fhicl::Name("flag"), false };
    fhicl::Atom<int> num { fhicl::Name("num"), 2 };
  };

  explicit PDDetail(art::OutputModule::Table<Config> const & ps)
    : flag_{ps().flag()}
    , num_{ps().num()}
  {}

  // ... 
}

The inheritance from art::ProvenanceDumperConfig is, strictly speaking, not necessary. The constructor for the detail class is permitted to receive the fhicl::Parameter const& pset argument, although there is not much benefit in doing so since configuration validation must be enabled anyway. It is permitted to have an empty Config struct if no FHiCL parameters are used in the detail class.

A fix has been committed so that configuration validation will not be required for ProvenanceDumper detail classes. This will be included with a future art release.

Enabling description printouts

Enabling configuration description requires introducing the Parameters typedef or type alias. For an analyzer,

class MyAnalyzer : public art::EDAnalyzer {

  // The following type alias is necessary to provide 
  // a description of the allowed configuration

  using Parameters = art::EDAnalyzer::Table<MyConfig>; 

  MyAnalyzer( Parameters const& config ) : ... {}

};

The presence of the type alias allows the description-printing system to find the relevant configuration. No other steps are necessary. As an example, for the IntProducer module referenced above and an additional module called IntTestAnalyzer, the following descriptions are printed:

[knoepfel@woof build-art-prof]$ art --print-description IntProducer IntTestAnalyzer

====================================================================================================

    module_type : IntProducer (or "test/Integration/IntProducer")

        provider: user
        type    : producer
        source  : /home/knoepfel/art/test/Integration/IntProducer_module.cc
        library : /home/knoepfel/scratch/build-art-prof/lib/libtest_Integration_IntProducer_module.so

    Allowed configuration
    ---------------------

        module_label: {

           module_type: IntProducer

           errorOnFailureToPut: true  # default

           ivalue: <int>

           branchType: 0  # default
        }

====================================================================================================

    module_type : IntTestAnalyzer (or "test/Integration/IntTestAnalyzer")

        provider: user
        type    : analyzer
        source  : /home/knoepfel/art/test/Integration/IntTestAnalyzer_module.cc
        library : /home/knoepfel/scratch/build-art-prof/lib/libtest_Integration_IntTestAnalyzer_module.so

    Allowed configuration
    ---------------------

        [ None provided ]

====================================================================================================

Note that for modules that have not provided a Parameters type alias/typedef, no configuration can be provided.


Validation and description use in art-provided facilities

As agreed to by the art stakeholders, art enables configuration validation and description for art-provided facilities.

Modules

All art-provided modules (e.g. RootOutput, RandomNumberSaver, etc.) enable configuration validation and description.

Services

As of art 2.08, all art-provided services (e.g. TimeTracker, message, etc.) enable configuration validation and description.

Sources

The EmptyEvent and RootInput sources also use configuration validation. The EmptyEvent source allows an optional configuration-specified plugin called timestampPlugin, for which configuration validation and description are not yet supported. The configuration validation and description system is also not yet supported for detail arguments ('T') to the art::Source<T> template.

Other plugins

There are other plugins that are recognized by art's library manager system. If you have need of enabling configuration validation and description for them, please contact .