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 objectives:
0006 - "Learn how to set parameters on a factory"
0007 - "Learn how to override factories via a generator"
0008 - "Learn how to override factories via the command line"
0009 - "Learn how to access services from a factory"
0010 ---
0011 
0012 ## Setting parameters on a factory
0013 
0014 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.
0015 
0016 ```c++
0017     ParameterRef<double> m_samplingFraction {this, "samplingFraction", config().sampFrac};
0018     ParameterRef<std::string> m_energyWeight {this, "energyWeight", config().energyWeight};
0019 ```
0020 
0021 Parameters are fetched immediately before `Init()` is called, so you may access them from any of the callbacks like so:
0022 
0023 ```c++
0024     void Process(int64_t run_number, uint64_t event_number) {
0025         logger()->debug( "Event {}: samplingFraction = {}", event_number, m_samplingFraction() );
0026     }
0027 
0028 ```
0029 Because we are using ParameterRefs, we can also access the field the ref points to directly:
0030 ```c++
0031     void Process(int64_t run_number, uint64_t event_number) {
0032         logger()->debug( "Event {}: samplingFraction = {}", event_number, config().sampFrac );
0033     }
0034 ```
0035 
0036 ## Config objects
0037 
0038 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.
0039 
0040 ```c++
0041 struct ReconstructedElectrons_config {
0042     double threshold = 0.9;
0043     int bucket_count = 4;
0044     // ...
0045 }
0046 ```
0047 
0048 By passing it in to the JOmniFactory base class, we can make it automatically available via the `config()` method.
0049 
0050 ```c++
0051 class ReconstructedElectrons_factory : public JOmniFactory<ReconstructedElectrons_factory, ElectronReconstructionConfig> {
0052     ...
0053 }
0054 ```
0055 
0056 
0057 ## Overriding parameters via a generator
0058 
0059 If you use a Config object for your parameters, you can pass it in directly to the factory generator:
0060 
0061 ```c++
0062     app->Add(new JOmniFactoryGeneratorT<BasicTestAlg>(
0063         "FunTest", {"MyHits"}, {"MyClusters"}, 
0064         {
0065           .threshold = 6.1,
0066           .bucket_count = 22
0067         },
0068         app));
0069 ```
0070 
0071 ## Overriding parameters via the command line
0072 
0073 We can override parameters on the command line like so:
0074 
0075 ```bash
0076 eicrecon -PFunTest:threshold=12.0 in.root
0077 ```
0078 
0079 
0080 ## Accessing services from a factory
0081 
0082 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:
0083 
0084 ```c++
0085     Service<DD4hep_service> m_geoSvc {this};
0086 ```
0087 
0088 Oftentimes we want to retrieve a resource from a Service and refresh it whenever the run number changes. OmniFactory provides `Resource` for this purpose.
0089 
0090 > Exercise:
0091 > - Give your factory a Config struct
0092 > - Give your Config struct some parameters
0093 > - Experiment with overriding parameter values in the generator and on the command line.
0094 {: .challenge}