Back to home page

EIC code displayed by LXR

 
 

    


Warning, /tutorial-reconstruction-algorithms/episodes/04-parameterizing-a-factory.md is written in an unsupported language. File is not indexed.

0001 ---
0002 title: "Parameterizing a factory"
0003 teaching: 5
0004 exercises: 0
0005 ---
0006 
0007 ::::::::::::::::::::::::::::::::::::::::::::: questions
0008 
0009 - How do I give a factory configurable parameters?
0010 - How do I override those parameters from a generator or the command line?
0011 - How do I access services such as geometry from a factory?
0012 
0013 :::::::::::::::::::::::::::::::::::::::::::::
0014 
0015 ::::::::::::::::::::::::::::::::::::::::::::: objectives
0016 
0017 - Learn how to set parameters on a factory.
0018 - Learn how to override factories via a generator.
0019 - Learn how to override factories via the command line.
0020 - Learn how to access services from a factory.
0021 
0022 :::::::::::::::::::::::::::::::::::::::::::::
0023 
0024 ## Setting parameters on a factory
0025 
0026 Parameters are also handled using registered members. JOmniFactory provides a `Parameter` class template which can hold its own value, but in EICrecon we prefer to use Config structs. Thus JOmniFactory provides `ParameterRef`, which stores a reference into the Config object.
0027 
0028 ```c++
0029     ParameterRef<double> m_samplingFraction {this, "samplingFraction", config().sampFrac};
0030     ParameterRef<std::string> m_energyWeight {this, "energyWeight", config().energyWeight};
0031 ```
0032 
0033 Parameters are fetched immediately before `Configure()` is called, so you may access them from any of the callbacks like so:
0034 
0035 ```c++
0036     void Process(int32_t run_number, uint64_t event_number) {
0037         logger()->debug( "Event {}: samplingFraction = {}", event_number, m_samplingFraction() );
0038     }
0039 
0040 ```
0041 Because we are using ParameterRefs, we can also access the field the ref points to directly:
0042 ```c++
0043     void Process(int32_t run_number, uint64_t event_number) {
0044         logger()->debug( "Event {}: samplingFraction = {}", event_number, config().sampFrac );
0045     }
0046 ```
0047 
0048 ## Config objects
0049 
0050 We create a plain-old struct to hold our parameters. For now this config struct can live in the same header file as our factory, although eventually it should belong with the algorithm instead.
0051 
0052 ```c++
0053 struct ReconstructedElectrons_config {
0054     double threshold = 0.9;
0055     int bucket_count = 4;
0056     // ...
0057 }
0058 ```
0059 
0060 By passing it in to the JOmniFactory base class, we can make it automatically available via the `config()` method.
0061 
0062 ```c++
0063 class ReconstructedElectrons_factory : public JOmniFactory<ReconstructedElectrons_factory, ElectronReconstructionConfig> {
0064     ...
0065 }
0066 ```
0067 
0068 
0069 ## Overriding parameters via a generator
0070 
0071 If you use a Config object for your parameters, you can pass it in directly to the factory generator:
0072 
0073 ```c++
0074     app->Add(new JOmniFactoryGeneratorT<BasicTestAlg>(
0075         "FunTest", {"MyHits"}, {"MyClusters"}, 
0076         {
0077           .threshold = 6.1,
0078           .bucket_count = 22
0079         },
0080         app));
0081 ```
0082 
0083 ## Overriding parameters via the command line
0084 
0085 We can override parameters on the command line like so:
0086 
0087 ```bash
0088 eicrecon -PFunTest:threshold=12.0 in.root
0089 ```
0090 
0091 
0092 ## Accessing services from a factory
0093 
0094 Services are singletons that provide access to resources such as loggers, geometry, magnetic field maps, etc. Services need to be thread-safe because they are shared by different threads. The most relevant service right now is `DD4hep_service`. You obtain a service using a registered member like this:
0095 
0096 ```c++
0097     Service<DD4hep_service> m_geoSvc {this};
0098 ```
0099 
0100 Oftentimes we want to retrieve a resource from a Service and refresh it whenever the run number changes. OmniFactory provides `Resource` for this purpose.
0101 
0102 ::::::::::::::::::::::::::::::::::::::::::::: challenge
0103 
0104 ## Exercise
0105 
0106 - Give your factory a Config struct.
0107 - Give your Config struct some parameters.
0108 - Experiment with overriding parameter values in the generator and on the command line.
0109 
0110 ::::::::::::::: solution
0111 
0112 Add a `struct` with a couple of fields (for example a `double threshold`) and pass it as the second
0113 template argument to `JOmniFactory`. Register `ParameterRef` members pointing at those fields. You
0114 can then set them in the generator with brace-initialization (`{.threshold = 6.1}`) or on the
0115 command line with `-P<prefix>:threshold=12.0`; the command-line value takes precedence.
0116 
0117 :::::::::::::::
0118 
0119 :::::::::::::::::::::::::::::::::::::::::::::
0120 
0121 ::::::::::::::::::::::::::::::::::::::::::::: keypoints
0122 
0123 - Parameters are registered members; in EICrecon we back them with a Config struct via `ParameterRef`.
0124 - Pass the Config type as the second `JOmniFactory` template argument to make it available through `config()`.
0125 - Override parameters in the generator with brace-initialization, or on the command line with `-P<prefix>:<name>=<value>`.
0126 - Access shared resources (geometry, fields) through thread-safe `Service` members.
0127 
0128 :::::::::::::::::::::::::::::::::::::::::::::