Config Block Factories¶
To allow users to create your blocks, you need to register them with the factory system. This enables the YAML configuration parser to find and instantiate your blocks when users reference them by name.
Central Registration (athena repository)¶
For blocks defined within the athena repository, registration is done
centrally in
ConfigFactory.py
within the addDefaultAlgs method.
To register a new block, add an import and registration call to
addDefaultAlgs:
def addDefaultAlgs(self):
# ... existing registrations ...
# my new block
from MyPackage.MyConfig import MyCalibrationConfig
self.addAlgConfigBlock(algName="MyCalibration", alg=MyCalibrationConfig)
You can also provide default values that override the defaults defined in the block class:
self.addAlgConfigBlock(algName="MyBlock", alg=MyBlockConfig,
defaults={'selectionName': ''})
Block Ordering¶
The order in which blocks are registered in addDefaultAlgs defines
their default execution order. When block A depends on block B (e.g. MET
needing fully corrected good objects), block A should be registered
after block B in the factory.
While there are more advanced mechanisms for controlling block ordering, this basic approach of placing dependent blocks after their dependencies in the registration order is usually sufficient.
Sub-blocks¶
For sub-blocks that should appear nested under a parent block, use the
superBlocks parameter:
from MyPackage.MyConfig import MyWorkingPointConfig
self.addAlgConfigBlock(algName="WorkingPoint", alg=MyWorkingPointConfig,
superBlocks="MyCalibration")
This creates a hierarchical structure where the sub-block appears nested under its parent in YAML. Users then configure it as:
Jets:
containerName: AnaJets
JVT:
workingPoint: "Tight"
This organizational pattern keeps related options grouped together in the configuration.
Sub-blocks should be registered after their parent block, so that they can rely on containers and decorations it created. In this example, the JVT block should come after the Jets block. Similarly, working point blocks for electrons and muons come after their respective calibration blocks.
Class-Based vs Function-Based Registration¶
Class-based registration (preferred)¶
When you register a ConfigBlock class directly, the factory instantiates
it and sets options via setOptionValue():
factory.addAlgConfigBlock(algName="MyMuons", alg=MyMuonCalibrationConfig)
This is the preferred approach because all options are declared on the block itself and the system can automatically discover them for documentation and validation.
Function-based registration¶
You can also register a factory function that receives a seq parameter
(the ConfigSequence) and creates blocks programmatically:
def makeMyConfig(seq, containerName, someOption=True):
config = MyConfigBlock()
config.setOptionValue('containerName', containerName)
config.setOptionValue('someOption', someOption)
seq.append(config)
factory.addAlgConfigBlock(algName="MyBlocks", alg=makeMyConfig)
The function's parameters (other than seq) become the user-facing
options. Use this approach sparingly; prefer declaring options on the
block itself rather than as function parameters.
Factories Producing Multiple Blocks¶
A factory function can add multiple blocks to the sequence, which is useful when you need prerequisite blocks or want to bundle related functionality:
def makeMultiBlockConfig(seq, containerName):
# Add prerequisite block
prereqBlock = PrerequisiteConfig()
prereqBlock.setOptionValue('containerName', containerName)
seq.append(prereqBlock)
# Add main block
mainBlock = MainConfig()
mainBlock.setOptionValue('containerName', containerName)
seq.append(mainBlock)
Registering Blocks via YAML (user-defined blocks)¶
For blocks defined outside the athena repository, the recommended
approach is to register them dynamically using AddConfigBlocks in your
YAML configuration. The preferred format uses a map with the block name
as the key:
AddConfigBlocks:
MyMuons:
modulePath: "MyPackage.MyConfig"
functionName: "MyMuonCalibrationConfig"
This tells the system to import MyMuonCalibrationConfig from
MyPackage.MyConfig and register it under the name MyMuons. Users can
then use it in their configuration:
MyMuons:
containerName: AnalysisMuonsCalib
extraVariables: true
The AddConfigBlocks entry supports additional optional fields:
AddConfigBlocks:
MyMuons:
modulePath: "MyPackage.MyConfig"
functionName: "MyMuonCalibrationConfig"
defaults:
inputContainer: "CustomMuons" # Override default option values
superBlocks: "Muons" # Register as sub-block of Muons
Alternatively AddConfigBlocks also supports a list format, but it is
deprecated because it doesn't work well with YAML file merging:
# List format (not recommended)
AddConfigBlocks:
- modulePath: "MyPackage.MyConfig"
functionName: "MyMuonCalibrationConfig"
algName: "MyMuons"