ATLAS Offline Software
Loading...
Searching...
No Matches
python.ConfigSequence.ConfigSequence Class Reference
Collaboration diagram for python.ConfigSequence.ConfigSequence:

Public Member Functions

 __init__ (self)
 append (self, block)
 makeAlgs (self, config)
 applyConfigOverrides (self, config)
 reorderAlgs (self)
 fullConfigure (self, config)
 setOptionValue (self, name, value, **kwargs)
 printOptions (self, verbose=False)
 getOptions (self)
 setOptions (self, options)
 groupBlocks (self, groupName='')
 setFactoryName (self, factoryName)
 __iadd__ (self, sequence, index=None)
 __iter__ (self)

Protected Attributes

list _blocks = []

Detailed Description

a sequence of ConfigBlock objects

This could in principle just be a simple python list, and maybe we
change it to that at some point (10 Mar 22).  Having it as its own
class allows to implement some helper functions.

This implements an interface similar to ConfigBlock, but it
doesn't derive from it, as ConfigBlock will likely gain
functionality in the future that wouldn't work for a sequence (or
wouldn't work in the same way).

Definition at line 28 of file ConfigSequence.py.

Constructor & Destructor Documentation

◆ __init__()

python.ConfigSequence.ConfigSequence.__init__ ( self)

Definition at line 42 of file ConfigSequence.py.

42 def __init__ (self) :
43 self._blocks = []
44
45

Member Function Documentation

◆ __iadd__()

python.ConfigSequence.ConfigSequence.__iadd__ ( self,
sequence,
index = None )
Add another sequence to this one

This function is used to add another sequence to this sequence
using the '+=' operator.

Definition at line 271 of file ConfigSequence.py.

271 def __iadd__( self, sequence, index = None ):
272 """Add another sequence to this one
273
274 This function is used to add another sequence to this sequence
275 using the '+=' operator.
276 """
277 # Check that the received object is of the right type:
278 if not isinstance( sequence, ConfigSequence ):
279 raise TypeError( 'The received object is not of type ConfigSequence' )
280
281 for block in sequence._blocks :
282 self._blocks.append (block)
283
284 # Return the modified object:
285 return self
286
287

◆ __iter__()

python.ConfigSequence.ConfigSequence.__iter__ ( self)
Create an iterator over all the configurations in this sequence

This is to allow for a Python-like iteration over all
configuration blocks that are part of the sequence.

Definition at line 288 of file ConfigSequence.py.

288 def __iter__( self ):
289 """Create an iterator over all the configurations in this sequence
290
291 This is to allow for a Python-like iteration over all
292 configuration blocks that are part of the sequence.
293 """
294 # Create the iterator to process the internal list of algorithms:
295 return self._blocks.__iter__()

◆ append()

python.ConfigSequence.ConfigSequence.append ( self,
block )
append a configuration block to the sequence

Definition at line 46 of file ConfigSequence.py.

46 def append (self, block) :
47 """append a configuration block to the sequence"""
48 self._blocks.append (block)
49
50

◆ applyConfigOverrides()

python.ConfigSequence.ConfigSequence.applyConfigOverrides ( self,
config )
Apply any properties that were set in the block's
'propertyOverrides' option.

Definition at line 66 of file ConfigSequence.py.

66 def applyConfigOverrides(self, config):
67 """
68 Apply any properties that were set in the block's
69 'propertyOverrides' option.
70 """
71 for block in self._blocks:
72 if not block.isUsedForConfig(config):
73 continue
74 config.setAlgPostfix(block.instanceName())
75 block.applyConfigOverrides(config)
76 config.setAlgPostfix('') # reset algPostfix after all blocks are configured
77

◆ fullConfigure()

python.ConfigSequence.ConfigSequence.fullConfigure ( self,
config )
do the full configuration on this sequence

This sequence needs to be the only sequence, i.e. it needs to
contain all the blocks that will be configured, as it will
perform all configuration steps at once.

Definition at line 124 of file ConfigSequence.py.

124 def fullConfigure (self, config) :
125 """do the full configuration on this sequence
126
127 This sequence needs to be the only sequence, i.e. it needs to
128 contain all the blocks that will be configured, as it will
129 perform all configuration steps at once.
130 """
131 for block in self._blocks:
132 if re.compile ('^[_a-zA-Z0-9]*$').match (block.instanceName()) is None :
133 raise ValueError (f'invalid block instance name: {block.instanceName()} for {block.factoryName()}')
134
135 self.reorderAlgs()
136 self.makeAlgs (config)
137 config.nextPass ()
138 self.makeAlgs (config)
139 self.applyConfigOverrides(config)
140
141

◆ getOptions()

python.ConfigSequence.ConfigSequence.getOptions ( self)
get information on options for last block in sequence

Definition at line 199 of file ConfigSequence.py.

199 def getOptions(self):
200 """get information on options for last block in sequence"""
201 # get groupName for last added block
202 groupName = self._blocks[-1].getOptionValue('groupName')
203 blocks = [self._blocks[-1]]
204 # get all blocks with the same groupName
205 if groupName:
206 for block in self._blocks[:-1]:
207 if block.getOptionValue('groupName') == groupName:
208 blocks.append(block)
209 options = []
210 # get options for all blocks with same groupName
211 for block in blocks:
212 for name, o in block.getOptions().items():
213 val = getattr(block, name)
214 valDefault = o.default
215 valType = o.type
216 valRequired = o.required
217 noneAction = o.noneAction
218 options.append({'name': name, 'defaultValue': valDefault,
219 'type': valType, 'required': valRequired,
220 'noneAction': noneAction, 'value': val})
221 return options
222
223

◆ groupBlocks()

python.ConfigSequence.ConfigSequence.groupBlocks ( self,
groupName = '' )
Assigns all blocks in configSequence groupName. If no name is
provided, the name is set to group_ plus an integer.

Blocks with the same groupName can be configured together.

Definition at line 244 of file ConfigSequence.py.

244 def groupBlocks(self, groupName=''):
245 """
246 Assigns all blocks in configSequence groupName. If no name is
247 provided, the name is set to group_ plus an integer.
248
249 Blocks with the same groupName can be configured together.
250 """
251 if not groupName:
252 groupName = f"group_{randrange(10**8):08}"
253 for block in self._blocks:
254 block.setOptionValue('groupName', groupName)
255
256

◆ makeAlgs()

python.ConfigSequence.ConfigSequence.makeAlgs ( self,
config )
call makeAlgs() on all blocks

This will create the actual algorithm configurables based on
how the blocks are configured right now.

Definition at line 51 of file ConfigSequence.py.

51 def makeAlgs (self, config) :
52 """call makeAlgs() on all blocks
53
54 This will create the actual algorithm configurables based on
55 how the blocks are configured right now.
56 """
57 for block in self._blocks:
58 if not block.isUsedForConfig(config):
59 continue
60 config.setAlgPostfix(block.instanceName())
61 block.checkExpertSettings (config)
62 block.makeAlgs (config)
63 config.setAlgPostfix('') # reset algPostfix after all blocks are configured
64
65

◆ printOptions()

python.ConfigSequence.ConfigSequence.printOptions ( self,
verbose = False )
Prints options and their values for each config block in a config sequence

Definition at line 190 of file ConfigSequence.py.

190 def printOptions(self, verbose=False):
191 """
192 Prints options and their values for each config block in a config sequence
193 """
194 for config in self:
195 logCPAlgCfgSeq.info(config.__class__.__name__)
196 config.printOptions(verbose=verbose)
197
198

◆ reorderAlgs()

python.ConfigSequence.ConfigSequence.reorderAlgs ( self)
Check for blocks with dependencies.

If a block required another block that is not present, will
throw an error; Otherwise, will move block immediately after
required block. If dependency is not required, will move
after other block, if it is present.

Note: this implementation can only move blocks forward.

Definition at line 78 of file ConfigSequence.py.

78 def reorderAlgs(self):
79 """
80 Check for blocks with dependencies.
81
82 If a block required another block that is not present, will
83 throw an error; Otherwise, will move block immediately after
84 required block. If dependency is not required, will move
85 after other block, if it is present.
86
87 Note: this implementation can only move blocks forward.
88 """
89 def moveBlock(blocks):
90 for i, block in enumerate(blocks):
91 # the 'ignoreDependencies' option is added with a dep.
92 ignore = block.getOptionValue('ignoreDependencies')
93 if block.hasDependencies():
94 depIdx = i
95 for dep in block.getDependencies():
96 if dep in ignore:
97 continue
98 # find dep with largest idx
99 if dep in blocks:
100 lastIdx = max(index for index,value in enumerate(blocks) if value == dep.blockName)
101 if lastIdx > depIdx:
102 depIdx = lastIdx
103 elif dep.required:
104 raise ValueError(f"{dep} block is required"
105 f" for {block} but was not found.")
106 # check to see if block is already infront of deps
107 if depIdx > i:
108 logCPAlgCfgSeq.info(f"Moving {block} after {blocks[depIdx]}")
109 # depIdx > i so after pop, depIdx -= 1 -> depIdx is after dep
110 blocks.insert(depIdx, blocks.pop(i))
111 return False
112 # nothing to move
113 return True
114 MAXTRIES = 1000
115 for _ in range(MAXTRIES):
116 if moveBlock(self._blocks):
117 # sorted
118 break
119 else:
120 raise Exception("Could not order blocks based on dependencies"
121 f" in {MAXTRIES} moves.")
122
123
#define max(a, b)
Definition cfImp.cxx:41

◆ setFactoryName()

python.ConfigSequence.ConfigSequence.setFactoryName ( self,
factoryName )
Set the factory name for all blocks in the sequence.

This is used to set a common factory name for all blocks, which
can be useful for debugging or logging purposes.

Definition at line 257 of file ConfigSequence.py.

257 def setFactoryName(self, factoryName):
258 """
259 Set the factory name for all blocks in the sequence.
260
261 This is used to set a common factory name for all blocks, which
262 can be useful for debugging or logging purposes.
263 """
264 if len(self._blocks) == 1:
265 self._blocks[0].setFactoryName(factoryName)
266 else:
267 # append [index] to factoryName for each block
268 for index, block in enumerate(self._blocks):
269 block.setFactoryName(f"{factoryName}[{index}:{block.__class__.__name__}]")
270

◆ setOptions()

python.ConfigSequence.ConfigSequence.setOptions ( self,
options )
Set options for a ConfigBlock

Definition at line 224 of file ConfigSequence.py.

224 def setOptions(self, options):
225 """Set options for a ConfigBlock"""
226 algOptions = self.getOptions()
227 for opt in algOptions:
228 name = opt['name']
229 if name in options:
230 self.setOptionValue (f'.{name}', options[name])
231 logCPAlgCfgSeq.info(f" {name}: {options[name]}")
232 else:
233 if opt['required']:
234 raise ValueError(f'{name} is required but not included in config')
235 # add default used to config
236 defaultVal = opt['value'] if opt['value'] else opt['defaultValue']
237 # do not overwright groupName unless set by user
238 if name != 'groupName':
239 options[name] = defaultVal
240 logCPAlgCfgSeq.info(f" {name}: {defaultVal}")
241 return algOptions
242
243

◆ setOptionValue()

python.ConfigSequence.ConfigSequence.setOptionValue ( self,
name,
value,
** kwargs )
set the given option on the sequence

The name should generally be of the form
"groupName.optionName" to identify what group the option
belongs to.

For simplicity I also allow a ".optionName" here, which will
then set the property in the last group added.  That makes it
fairly straightforward to add new blocks, set options on them,
and then move on to the next blocks.  Please note that this
mechanism ought to be viewed as strictly as a temporary
convenience, and this short cut may go away once better
alternatives are available.

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 142 of file ConfigSequence.py.

142 def setOptionValue (self, name, value, **kwargs) :
143 """set the given option on the sequence
144
145 The name should generally be of the form
146 "groupName.optionName" to identify what group the option
147 belongs to.
148
149 For simplicity I also allow a ".optionName" here, which will
150 then set the property in the last group added. That makes it
151 fairly straightforward to add new blocks, set options on them,
152 and then move on to the next blocks. Please note that this
153 mechanism ought to be viewed as strictly as a temporary
154 convenience, and this short cut may go away once better
155 alternatives are available.
156
157 WARNING: The backend to option handling is slated to be
158 replaced at some point. This particular function may change
159 behavior, interface or be removed/replaced entirely.
160 """
161 names = name.split('.')
162 # <optionName>
163 optionName = names.pop(-1)
164 # <groupName>.<optionName>, or
165 # .<optionName> (backwards compatability)
166 groupName = names.pop(0) if names else ''
167 if names:
168 raise ValueError(f'Option name can be either <groupName>.<optionName>'
169 f' or <optionName> not {name}')
170 blocks = self._blocks
171 # check if last block added has an instance name
172 if not groupName:
173 groupName = blocks[-1].getOptionValue('groupName')
174 if groupName:
175 used = False
176 # set optionName for all blocks with groupName
177 for block in blocks:
178 if ( block.getOptionValue('groupName') == groupName
179 and block.hasOption(optionName) ):
180 block.setOptionValue (optionName, value, **kwargs)
181 used = True
182 if not used:
183 raise ValueError(f'{optionName} not found in blocks with '
184 f'group name {groupName}')
185 else:
186 # set opyion for last added block
187 blocks[-1].setOptionValue (optionName, value, **kwargs)
188
189

Member Data Documentation

◆ _blocks

python.ConfigSequence.ConfigSequence._blocks = []
protected

Definition at line 43 of file ConfigSequence.py.


The documentation for this class was generated from the following file: