ATLAS Offline Software
Public Member Functions | Static Public Attributes | Private Attributes | List of all members
python.ConfigBlock.ConfigBlock Class Reference
Inheritance diagram for python.ConfigBlock.ConfigBlock:
Collaboration diagram for python.ConfigBlock.ConfigBlock:

Public Member Functions

def __init__ (self)
 
def setBlockName (self, name)
 
def getBlockName (self)
 
def factoryName (self)
 
def setFactoryName (self, name)
 
def instanceName (self)
 
def isUsedForConfig (self, config)
 
def applyConfigOverrides (self, config)
 
def addDependency (self, dependencyName, required=True)
 
def hasDependencies (self)
 
def getDependencies (self)
 
def addOption (self, name, defaultValue, *type, info='', noneAction='ignore', required=False)
 
def setOptionValue (self, name, value)
 
def getOptionValue (self, name)
 
def getOptions (self)
 
def printOptions (self, verbose=False, width=60, indent=" ")
 
def hasOption (self, name)
 
def __eq__ (self, blockName)
 
def __str__ (self)
 
def get_instance_count (cls)
 
def __new__ (cls, name, bases, dct)
 

Static Public Attributes

dictionary instance_counts = {}
 

Private Attributes

 _blockName
 
 _factoryName
 
 _dependencies
 
 _options
 

Detailed Description

the base class for classes implementing individual blocks of
configuration

A configuration block is a sequence of one or more algorithms that
should always be scheduled together, e.g. the muon four momentum
corrections could be a single block, muon selection could then be
another block.  The blocks themselves generally have their own
configuration options/properties specific to the block, and will
perform a dynamic configuration based on those options as well as
the overall job.

The actual configuration of the algorithms in the block will
depend on what other blocks are scheduled before and afterwards,
most importantly some algorithms will introduce shallow copies
that subsequent algorithms will need to run on, and some
algorithms will add selection decorations that subquent algorithms
should use as preselections.

The algorithms get created in a multi-step process (that may be
extended in the future): As a first step each block retrieves
references to the containers it uses (essentially marking its spot
in the processing chain) and also registering any shallow copies
that will be made.  In the second/last step each block then
creates the fully configured algorithms.

One goal is that when the algorithms get created they will have
their final configuration and there needs to be no
meta-configuration data attached to the algorithms, essentially an
inversion of the approach in AnaAlgSequence in which the
algorithms got created first with associated meta-configuration
and then get modified in susequent configuration steps.

For now this is mostly an empty base class, but another goal of
this approach is to make it easier to build another configuration
layer on top of this one, and this class will likely be extended
and get data members at that point.

The child class needs to implement the method `makeAlgs` which is
given a single `ConfigAccumulator` type argument. This is meant to
create the sequence of algorithms that this block configures. This
is currently (28 Jul 2025) called twice and should do the same thing
during both calls, but the plan is to change that to a single call.

The child class should also implement the method `getInstanceName`
which should return a string that is used to distinguish between
multiple instances of the same block. This is used to append the
instance name to the names of all algorithms created by this block,
and may in the future also be used to distinguish between multiple
instances of the block.

Definition at line 88 of file ConfigBlock.py.

Constructor & Destructor Documentation

◆ __init__()

def python.ConfigBlock.ConfigBlock.__init__ (   self)

Definition at line 143 of file ConfigBlock.py.

143  def __init__ (self) :
144  self._blockName = ''
145  self._factoryName = None
146  self._dependencies = []
147  self._options = {}
148  # used with block configuration to set arbitrary option
149  self.addOption('groupName', '', type=str,
150  info=('Used to specify this block when setting an'
151  ' option at an arbitrary location.'))
152  self.addOption('skipOnData', False, type=bool,
153  info=('User option to prevent the block from running'
154  ' on data. This only affects blocks that are'
155  ' intended to run on data.'))
156  self.addOption('skipOnMC', False, type=bool,
157  info=('User option to prevent the block from running'
158  ' on MC. This only affects blocks that are'
159  ' intended to run on MC.'))
160  self.addOption('onlyForDSIDs', [], type=list,
161  info=('Used to specify which MC DSIDs to allow this'
162  ' block to run on. Each element of the list'
163  ' can be a full DSID (e.g. 410470), or a regex'
164  ' (e.g. 410.* to select all 410xxx DSIDs, or'
165  ' ^(?!410) to veto them). An empty list means no'
166  ' DSID restriction.'))
167  self.addOption('propertyOverrides', {}, type=None,
168  info=('EXPERT USE ONLY: A dictionary of properties to'
169  ' override at the end of configuration. This should'
170  ' take the form'
171  ' {"algName.toolName.propertyName": value, ...},'
172  ' without any automatically applied postfixes for'
173  ' the algorithm name. THIS IS MEANT TO BE EXPERT'
174  ' USAGE ONLY. Properties that need to be set by'
175  ' the user should be declared as options on the'
176  ' block itself. EXPERT USE ONLY!'))
177  # Increment the instance count for the current class
178  cls = type(self) # Get the actual class of the instance (also derived!)
179  if cls not in ConfigBlock.instance_counts:
180  ConfigBlock.instance_counts[cls] = 0
181  # Note: we do need to check in the call stack that we are
182  # in a real makeConfig situation, and not e.g. printAlgs
183  stack = inspect.stack()
184  for frame_info in stack:
185  # Get the class name (if any) from the frame
186  parent_cls = frame_info.frame.f_locals.get('self', None)
187  if parent_cls is None or not isinstance(parent_cls, ConfigBlock):
188  # If the frame does not belong to an instance of ConfigBlock, it's an external caller
189  if frame_info.function == "makeConfig":
190  ConfigBlock.instance_counts[cls] += 1
191  break
192 
193 

Member Function Documentation

◆ __eq__()

def python.ConfigBlock.ConfigBlock.__eq__ (   self,
  blockName 
)
Implementation of == operator. Used for seaching configSeque.
E.g. if blockName in configSeq:

Definition at line 402 of file ConfigBlock.py.

402  def __eq__(self, blockName):
403  """
404  Implementation of == operator. Used for seaching configSeque.
405  E.g. if blockName in configSeq:
406  """
407  return self._blockName == blockName
408 
409 

◆ __new__()

def python.ConfigBlock.BlockNameProcessorMeta.__new__ (   cls,
  name,
  bases,
  dct 
)
inherited

Definition at line 49 of file ConfigBlock.py.

49  def __new__(cls, name, bases, dct):
50  # Automatically apply alphanumeric-only decorator to 'instanceName()' method
51  if 'instanceName' in dct and callable(dct['instanceName']):
52  dct['instanceName'] = alphanumeric_block_name(dct['instanceName'])
53  return super().__new__(cls, name, bases, dct)
54 

◆ __str__()

def python.ConfigBlock.ConfigBlock.__str__ (   self)

Definition at line 410 of file ConfigBlock.py.

410  def __str__(self):
411  return self._blockName
412 
413 

◆ addDependency()

def python.ConfigBlock.ConfigBlock.addDependency (   self,
  dependencyName,
  required = True 
)
Add a dependency for the block. Dependency is corresponds to the
blockName of another block. If required is True, will throw an
error if dependency is not present; otherwise will move this
block after the required block. If required is False, will do
nothing if required block is not present; otherwise, it will
move block after required block.

Definition at line 286 of file ConfigBlock.py.

286  def addDependency(self, dependencyName, required=True):
287  """
288  Add a dependency for the block. Dependency is corresponds to the
289  blockName of another block. If required is True, will throw an
290  error if dependency is not present; otherwise will move this
291  block after the required block. If required is False, will do
292  nothing if required block is not present; otherwise, it will
293  move block after required block.
294  """
295  if not self.hasDependencies():
296  # add option to block ignore dependencies
297  self.addOption('ignoreDependencies', [], type=list,
298  info='List of dependencies defined in the ConfigBlock to ignore.')
299  self._dependencies.append(ConfigBlockDependency(dependencyName, required))
300 

◆ addOption()

def python.ConfigBlock.ConfigBlock.addOption (   self,
  name,
  defaultValue,
type,
  info = '',
  noneAction = 'ignore',
  required = False 
)
declare the given option on the configuration block

This should only be called in the constructor of the
configuration block.

NOTE: The backend to option handling is slated to be replaced
at some point.  This particular function should essentially
stay the same, but some behavior may change.

Definition at line 309 of file ConfigBlock.py.

309  def addOption (self, name, defaultValue, *,
310  type, info='', noneAction='ignore', required=False) :
311  """declare the given option on the configuration block
312 
313  This should only be called in the constructor of the
314  configuration block.
315 
316  NOTE: The backend to option handling is slated to be replaced
317  at some point. This particular function should essentially
318  stay the same, but some behavior may change.
319  """
320  if name in self._options :
321  raise KeyError (f'duplicate option: {name}')
322  if type not in [str, bool, int, float, list, None] :
323  raise TypeError (f'unknown option type: {type}')
324  noneActions = ['error', 'set', 'ignore']
325  if noneAction not in noneActions :
326  raise ValueError (f'invalid noneAction: {noneAction} [allowed values: {noneActions}]')
327  setattr (self, name, defaultValue)
328  self._options[name] = ConfigBlockOption(type=type, info=info,
329  noneAction=noneAction, required=required, default=defaultValue)
330 
331 

◆ applyConfigOverrides()

def python.ConfigBlock.ConfigBlock.applyConfigOverrides (   self,
  config 
)
Apply any configuration overrides specified in the block's
`propertyOverrides` option. This is meant to be called at the
end of the configuration process, after all algorithms have been
created and configured.

Definition at line 261 of file ConfigBlock.py.

261  def applyConfigOverrides(self, config):
262  """
263  Apply any configuration overrides specified in the block's
264  `propertyOverrides` option. This is meant to be called at the
265  end of the configuration process, after all algorithms have been
266  created and configured.
267  """
268  for key, value in self.propertyOverrides.items():
269  # Split the key into algorithm name, tool name, and property name
270  parts = key.split('.')
271  if len(parts) < 2:
272  raise Exception(f"Invalid override key format: {key}")
273  alg = config.getAlgorithm(parts[0])
274  if alg is None:
275  raise Exception(f"Algorithm {parts[0]} not found in config for override: {key}")
276  for name in parts[1:-1]:
277  # Navigate through tools if necessary
278  if hasattr(alg, name):
279  alg = getattr(alg, name)
280  else:
281  raise Exception(f"Tool {name} not found for override: {key}")
282  # Set the property on the algorithm/tool. This is probably a
283  # horrible hack, but `setattr` didn't work for me.
284  alg.__setattr__(parts[-1], value)
285 

◆ factoryName()

def python.ConfigBlock.ConfigBlock.factoryName (   self)
get the factory name for this block

This is mostly to give a reliable means of identifying the type
of block we have in error messages. This is meant to be
automatically set by the factory based on the requested block
name, but there are a number of fallbacks. It is best not to
assume a specific format, this is mostly meant to be used as an
identifier in output messages.

Definition at line 202 of file ConfigBlock.py.

202  def factoryName(self):
203  """get the factory name for this block
204 
205  This is mostly to give a reliable means of identifying the type
206  of block we have in error messages. This is meant to be
207  automatically set by the factory based on the requested block
208  name, but there are a number of fallbacks. It is best not to
209  assume a specific format, this is mostly meant to be used as an
210  identifier in output messages.
211  """
212  if self._factoryName is not None and self._factoryName != '':
213  return self._factoryName
214  # If no factory name is set and the block has a name, use that
215  if self._blockName is not None and self._blockName != '':
216  return self._blockName
217  # Use the class name as a fallback
218  return self.__class__.__name__
219 

◆ get_instance_count()

def python.ConfigBlock.ConfigBlock.get_instance_count (   cls)

Definition at line 415 of file ConfigBlock.py.

415  def get_instance_count(cls):
416  # Access the current count for this class
417  return ConfigBlock.instance_counts.get(cls, 0)

◆ getBlockName()

def python.ConfigBlock.ConfigBlock.getBlockName (   self)
Get blockName

Definition at line 198 of file ConfigBlock.py.

198  def getBlockName(self):
199  """Get blockName"""
200  return self._blockName
201 

◆ getDependencies()

def python.ConfigBlock.ConfigBlock.getDependencies (   self)
Return the list of dependencies. 

Definition at line 305 of file ConfigBlock.py.

305  def getDependencies(self):
306  """Return the list of dependencies. """
307  return self._dependencies
308 

◆ getOptions()

def python.ConfigBlock.ConfigBlock.getOptions (   self)
Return a copy of the options associated with the block

Definition at line 365 of file ConfigBlock.py.

365  def getOptions(self):
366  """Return a copy of the options associated with the block"""
367  return self._options.copy()
368 
369 

◆ getOptionValue()

def python.ConfigBlock.ConfigBlock.getOptionValue (   self,
  name 
)
Returns config option value, if present; otherwise return None

Definition at line 359 of file ConfigBlock.py.

359  def getOptionValue(self, name):
360  """Returns config option value, if present; otherwise return None"""
361  if name in self._options:
362  return getattr(self, name)
363 
364 

◆ hasDependencies()

def python.ConfigBlock.ConfigBlock.hasDependencies (   self)
Return True if there is a dependency.

Definition at line 301 of file ConfigBlock.py.

301  def hasDependencies(self):
302  """Return True if there is a dependency."""
303  return bool(self._dependencies)
304 

◆ hasOption()

def python.ConfigBlock.ConfigBlock.hasOption (   self,
  name 
)
whether the configuration block has the given option

WARNING: The backend to option handling is slated to be
replaced at some point.  This particular function may change
behavior, interface or be removed/replaced entirely.

Definition at line 392 of file ConfigBlock.py.

392  def hasOption (self, name) :
393  """whether the configuration block has the given option
394 
395  WARNING: The backend to option handling is slated to be
396  replaced at some point. This particular function may change
397  behavior, interface or be removed/replaced entirely.
398  """
399  return name in self._options
400 
401 

◆ instanceName()

def python.ConfigBlock.ConfigBlock.instanceName (   self)
Get the name of the instance

The name of the instance is used to distinguish between multiple
instances of the same block. Most importantly, this will be
appended to the names of all algorithms created by this block.
This defaults to an empty string, but block implementations
should override it with an appropriate name based on identifying
options set on this instance. A typical example would be the
name of the (main) container, plus potentially the selection or
working point.

Ideally all blocks should override this method, but for backward
compatibility (28 Jul 25) it defaults to an empty string.

Definition at line 229 of file ConfigBlock.py.

229  def instanceName(self):
230  """Get the name of the instance
231 
232  The name of the instance is used to distinguish between multiple
233  instances of the same block. Most importantly, this will be
234  appended to the names of all algorithms created by this block.
235  This defaults to an empty string, but block implementations
236  should override it with an appropriate name based on identifying
237  options set on this instance. A typical example would be the
238  name of the (main) container, plus potentially the selection or
239  working point.
240 
241  Ideally all blocks should override this method, but for backward
242  compatibility (28 Jul 25) it defaults to an empty string.
243  """
244  return ''
245 

◆ isUsedForConfig()

def python.ConfigBlock.ConfigBlock.isUsedForConfig (   self,
  config 
)
whether this block should be used for the given configuration

This is used by `ConfigSequence` to determine whether this block
should be included in the configuration.

Definition at line 246 of file ConfigBlock.py.

246  def isUsedForConfig(self, config):
247  """
248  whether this block should be used for the given configuration
249 
250  This is used by `ConfigSequence` to determine whether this block
251  should be included in the configuration.
252  """
253  if self.skipOnData and config.dataType() is DataType.Data:
254  return False
255  if self.skipOnMC and config.dataType() is not DataType.Data:
256  return False
257  if not filter_dsids(self.onlyForDSIDs, config):
258  return False
259  return True
260 

◆ printOptions()

def python.ConfigBlock.ConfigBlock.printOptions (   self,
  verbose = False,
  width = 60,
  indent = "    " 
)
Prints options and their values

Definition at line 370 of file ConfigBlock.py.

370  def printOptions(self, verbose=False, width=60, indent=" "):
371  """
372  Prints options and their values
373  """
374  def printWrap(text, width=60, indent=" "):
375  wrapper = textwrap.TextWrapper(width=width, initial_indent=indent,
376  subsequent_indent=indent)
377  for line in wrapper.wrap(text=text):
378  logCPAlgCfgBlock.info(line)
379 
380  for opt, vals in self.getOptions().items():
381  if verbose:
382  logCPAlgCfgBlock.info(indent + f"\033[4m{opt}\033[0m: {self.getOptionValue(opt)}")
383  logCPAlgCfgBlock.info(indent*2 + f"\033[4mtype\033[0m: {vals.type}")
384  logCPAlgCfgBlock.info(indent*2 + f"\033[4mdefault\033[0m: {vals.default}")
385  logCPAlgCfgBlock.info(indent*2 + f"\033[4mrequired\033[0m: {vals.required}")
386  logCPAlgCfgBlock.info(indent*2 + f"\033[4mnoneAction\033[0m: {vals.noneAction}")
387  printWrap(f"\033[4minfo\033[0m: {vals.info}", indent=indent*2)
388  else:
389  logCPAlgCfgBlock.info(indent + f"{ opt}: {self.getOptionValue(opt)}")
390 
391 

◆ setBlockName()

def python.ConfigBlock.ConfigBlock.setBlockName (   self,
  name 
)
Set blockName

Definition at line 194 of file ConfigBlock.py.

194  def setBlockName(self, name):
195  """Set blockName"""
196  self._blockName = name
197 

◆ setFactoryName()

def python.ConfigBlock.ConfigBlock.setFactoryName (   self,
  name 
)
set the factory name for this block

This is meant to be called automatically by the factory based on
the requested block name. If you are creating a block without a factory,
you can call this method to set the factory name manually.

Definition at line 220 of file ConfigBlock.py.

220  def setFactoryName(self, name):
221  """set the factory name for this block
222 
223  This is meant to be called automatically by the factory based on
224  the requested block name. If you are creating a block without a factory,
225  you can call this method to set the factory name manually.
226  """
227  self._factoryName = name
228 

◆ setOptionValue()

def python.ConfigBlock.ConfigBlock.setOptionValue (   self,
  name,
  value 
)
set the given option on the configuration block

NOTE: The backend to option handling is slated to be replaced
at some point.  This particular function should essentially
stay the same, but some behavior may change.

Definition at line 332 of file ConfigBlock.py.

332  def setOptionValue (self, name, value) :
333  """set the given option on the configuration block
334 
335  NOTE: The backend to option handling is slated to be replaced
336  at some point. This particular function should essentially
337  stay the same, but some behavior may change.
338  """
339 
340  if name not in self._options :
341  raise KeyError (f'unknown option "{name}" in block "{self.__class__.__name__}"')
342  noneAction = self._options[name].noneAction
343  if value is not None or noneAction == 'set' :
344  # check type if specified
345  optType = self._options[name].type
346  # convert int to float to prevent crash
347  if optType is float and type(value) is int:
348  value = float(value)
349  if optType is not None and optType != type(value):
350  raise ValueError(f'{name} for block {self.__class__.__name__} should '
351  f'be of type {optType} not {type(value)}')
352  setattr (self, name, value)
353  elif noneAction == 'ignore' :
354  pass
355  elif noneAction == 'error' :
356  raise ValueError (f'passed None for setting option {name} with noneAction=error')
357 
358 

Member Data Documentation

◆ _blockName

python.ConfigBlock.ConfigBlock._blockName
private

Definition at line 144 of file ConfigBlock.py.

◆ _dependencies

python.ConfigBlock.ConfigBlock._dependencies
private

Definition at line 146 of file ConfigBlock.py.

◆ _factoryName

python.ConfigBlock.ConfigBlock._factoryName
private

Definition at line 145 of file ConfigBlock.py.

◆ _options

python.ConfigBlock.ConfigBlock._options
private

Definition at line 147 of file ConfigBlock.py.

◆ instance_counts

dictionary python.ConfigBlock.ConfigBlock.instance_counts = {}
static

Definition at line 141 of file ConfigBlock.py.


The documentation for this class was generated from the following file:
python.ConfigBlock.alphanumeric_block_name
def alphanumeric_block_name(func)
Definition: ConfigBlock.py:30
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
FlavorTagInference::getOptions
GNNOptions getOptions(const GNNToolProperties &)
Definition: GNNToolifiers.cxx:24
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.processes.powheg.ZZ.ZZ.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZ.py:18
python.ConfigBlock.filter_dsids
def filter_dsids(filterList, config)
Definition: ConfigBlock.py:13
calibdata.copy
bool copy
Definition: calibdata.py:26
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65