Warning, /tutorial-reconstruction-algorithms/episodes/03-calling-a-factory.md is written in an unsupported language. File is not indexed.
0001 ---
0002 title: "Calling a factory"
0003 teaching: 10
0004 exercises: 1
0005 ---
0006
0007 ::::::::::::::::::::::::::::::::::::::::::::: questions
0008
0009 - How do I wire a factory into JANA2 using a factory generator?
0010 - How do I make my factory's outputs available, either once-off or every time?
0011
0012 :::::::::::::::::::::::::::::::::::::::::::::
0013
0014 ::::::::::::::::::::::::::::::::::::::::::::: objectives
0015
0016 - Learn how to wire a factory using a factory generator.
0017 - Learn how to call the factory as a once-off.
0018 - Learn how to call the factory every time.
0019
0020 :::::::::::::::::::::::::::::::::::::::::::::
0021
0022 ## Wiring a factory using a factory generator
0023
0024 Instead of handing over the OmniFactory to JANA directly, we create a `JOmniFactoryGeneratorT` which is basically a recipe that JANA uses to create factories later. There are several reasons we need this:
0025
0026 1. JANA is designed to process events in parallel, when enabled. Factories are allowed to cache *local* state using member variables (e.g. calibrations and resources) Despite this, factories don't need to be thread-safe, because each factory is only used by one thread at a time. This means that JANA needs to spin up at least one instance of each factory for each thread.
0027
0028 2. We want to be able to spin up separate instances of the same factory class (within the context of a single event and thread), and give them different parameter values and collection names. The way we manage these different instances is by giving each factory instance a unique prefix which will be used to namespace its parameters, inputs, outputs, and logger. This happens at the JFactoryGenerator level.
0029
0030 Here is how you set up a factory generator:
0031
0032 ```c++
0033 app->Add(new JOmniFactoryGeneratorT<MC2ReconstructedParticle_factory>(
0034 "GeneratedParticles",
0035 {"MCParticles"},
0036 {"GeneratedParticles"},
0037 app
0038 ));
0039 ```
0040
0041 In this example, "GeneratedParticles" is the factory instance's unique tag, `{"MCParticles"}` is the list of input collection names, and `{"GeneratedParticles"}` is the list of output collection names. Some observations:
0042
0043 - If you are only creating one instance of this factory, feel free to use the "primary" output collection name as the factory prefix. (This has to be unique because PODIO collection names have to be unique.)
0044
0045 - Collection names are positional, so they need to be in the same order as the `PodioInput` and `VariadicPodioInput` declarations in the factory.
0046
0047 - Variadic inputs are a little bit interesting: You can have any number of variadic inputs mixed in among the non-variadic inputs, as long as there are the same number of collection names for each variadic input. If this confuses you, just restrict yourself to one variadic input and put it as the very last input, like most programming languages do.
0048
0049 - When assigning names to collections and `JOmniFactory` prefixes, uniqueness is extremely important! JANA will throw an error if it detects a naming collision, but because of the dynamic plugin loading, some collisions can't be detected. DO NOT use the same output collection name or prefix in different plugins, and DO NOT rely the plugin loading order to make sure you ran the "correct" factory! To swap out different versions of a factory, change or override the *input* collection name on the factories and processors downstream.
0050
0051 ## Where to put factory generators
0052
0053 Factory generators need to be added inside an `InitPlugin` for a particular plugin. If the factory generator is specific to one particular detector, it would go in that detector's plugin. Because electron reconstruction is not, the generator is set up in one of the plugins under `src/global`. Because this falls in the category of reconstruction, we put it in `src/global/reco/reco.cc`.
0054
0055 ## Calling the factory
0056
0057
0058 #### To temporarily include your factory's outputs in the output file
0059
0060 On the command line, set the `podio:output_collections` parameter to include your collection names:
0061
0062 ```bash
0063 eicrecon -Ppodio:output_collections=MyNewCollectionName1,MyNewCollectionName2 in.root
0064 ```
0065
0066 #### To permanently include your factory's outputs in the output file:
0067
0068 Add your collection name to the `output_collections` list in `src/services/io/podio/JEventProcessorPODIO.cc`:
0069 ```c++
0070 std::vector<std::string> output_collections = {
0071 // Header and other metadata
0072 "EventHeader",
0073
0074 // Truth record
0075 "MCParticles",
0076 "MCBeamElectrons",
0077 "MCBeamProtons",
0078 // ...
0079 ```
0080
0081 ### To temporarily use your factory's outputs as inputs to another factory
0082
0083 ```bash
0084 eicrecon -Ptargetfactory:InputTags=MyNewCollectionName1,MyNewCollection2 in.root
0085 ```
0086
0087 ### To permanently use your factory's outputs as inputs to another factory
0088
0089 Change the collection name in the `JOmniFactoryGeneratorT`:
0090 ```c++
0091 app->Add(new JOmniFactoryGeneratorT<MC2ReconstructedParticle_factory>(
0092 "GeneratedParticles",
0093 {"MCParticlesSmeared"}, // <== Used to be "MCParticles"
0094 {"GeneratedParticles"},
0095 app
0096 ));
0097 ```
0098
0099 ::::::::::::::::::::::::::::::::::::::::::::: challenge
0100
0101 ## Exercise
0102
0103 - Create a JOmniFactoryGenerator for your ElectronReconstruction factory.
0104 - Give your factory's output collection a fun name.
0105 - Call your factory from the command line and verify that you see its logger output.
0106 - Add it to the `JEventProcessorPODIO::output_collections`, so that it gets called automatically.
0107 - Experiment with multiple factory generators so you can have multiple instances of the same factory.
0108
0109 ::::::::::::::: solution
0110
0111 Register a `JOmniFactoryGeneratorT<...>` inside `src/global/reco/reco.cc` with your chosen output
0112 collection name. Running `eicrecon` with a raised log level (for example
0113 `eicrecon -Pjana:loglevel=debug ...`) shows your `Process()` log lines. Adding the collection name
0114 to `output_collections` in `JEventProcessorPODIO.cc` makes it persist to the output file
0115 automatically. Adding a second generator with a different tag and different collection names
0116 produces a second, independent instance of the same factory class.
0117
0118 :::::::::::::::
0119
0120 :::::::::::::::::::::::::::::::::::::::::::::
0121
0122 ::::::::::::::::::::::::::::::::::::::::::::: keypoints
0123
0124 - A `JOmniFactoryGeneratorT` is a recipe JANA2 uses to instantiate factories, one per thread.
0125 - Each generator assigns a unique prefix plus positional input and output collection names.
0126 - Use `podio:output_collections` (or `JEventProcessorPODIO.cc`) to persist outputs, and `InputTags` (or the generator) to rewire inputs.
0127 - Collection names and prefixes must be globally unique across plugins.
0128
0129 :::::::::::::::::::::::::::::::::::::::::::::