Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:22

0001 """Helper object to identify configuration parameters so we can easily overwrite
0002 them via command line magic or via the steering file
0003 
0004 To add additional arguments create either a member variable or a property to a
0005 subclass of the ConfigHelper. To add additional arguments to the add_argument
0006 call for the parser object create an additional member::
0007 
0008   self.member = [1,2]
0009   self._member_EXTRA = {'help': 'description for parameter',
0010                         'nargs': '+',
0011                        }
0012 
0013 """
0014 
0015 
0016 class ConfigHelper(object):
0017   """Base class for configuration helper"""
0018 
0019   # We need a static set of properties, because steeringFile parsing creates new Helper objects!
0020   _setOfProperties = dict()
0021 
0022   def __init__(self):
0023     pass
0024 
0025   def _name(self):
0026     return self.__class__.__name__
0027 
0028   def _closeProperties(self):
0029     """Store the list of properties."""
0030     self._setOfProperties[self._name()] = set(vars(self))
0031 
0032   def _checkProperties(self):
0033     newProps = set(vars(self))
0034     if existingProps := self._setOfProperties.get(self._name(), set()):
0035       if unknownProps := newProps - existingProps:
0036         raise RuntimeError(f"{self._name()} error: Trying to add unknown propert(y/ies): {unknownProps}!")
0037 
0038   def getOptions(self):
0039     finalVars = {}
0040 
0041     # get all direct members not starting with underscore
0042     allVars = vars(self)
0043     for var, val in allVars.items():
0044       if not var.startswith('_'):
0045         extraArgumentsName = "_%s_EXTRA" % var
0046         options = getattr(self, extraArgumentsName) if hasattr(self, extraArgumentsName) else None
0047         finalVars[var] = {'default': val}
0048         if options:
0049           finalVars[var].update(options)
0050 
0051     # now get things defined with @property
0052     props = [(p, getattr(type(self), p)) for p in dir(type(self)) if isinstance(getattr(type(self), p), property)]
0053     for propName, prop in props:
0054       optName = "_%s_EXTRA" % propName
0055       doc = prop.__doc__
0056       options = getattr(self, optName) if hasattr(self, optName) else None
0057       finalVars[propName] = {'default': getattr(self, propName)}
0058       if doc:
0059         finalVars[propName]['help'] = doc
0060       if options:
0061         finalVars[propName].update(options)
0062 
0063     return finalVars
0064 
0065   def __repr__(self):
0066     return self.printOptions()
0067 
0068   def printOptions(self):
0069     """print all parameters"""
0070     options = []
0071     for opt, val in self.getOptions().items():
0072       options.append("\n\t'%s': '%s'" % (opt, val['default']))
0073     return "".join(options)
0074 
0075   def setOption(self, name, val):
0076     """ set the attribute name to val """
0077     setattr(self, name, val)
0078 
0079   @staticmethod
0080   def makeList(stringVal, sep=" "):
0081     """returns a list from a string separated by sep"""
0082     if not stringVal:
0083       return []
0084     if isinstance(stringVal, list):
0085       return stringVal
0086     else:
0087       return stringVal.split(sep)
0088 
0089   @staticmethod
0090   def makeSet(stringVal, sep=" "):
0091     """returns a set from a string separated by sep"""
0092     if not stringVal:
0093       return set()
0094     if isinstance(stringVal, (list, set, tuple)):
0095       return set(stringVal)
0096     else:
0097       return set(stringVal.split(sep))
0098 
0099   @staticmethod
0100   def makeString(container):
0101     """Return a string that can be parsed by dd4hep into a vector."""
0102     if not container:
0103       return ""
0104     if isinstance(container, set):
0105       return '{%s}' % ','.join([str(s) for s in container])
0106 
0107   @staticmethod
0108   def makeTuple(val):
0109     """ returns a tuple of the string, separators are space or comma """
0110     myTuple = None
0111     if isinstance(val, tuple):
0112       myTuple = val
0113     if isinstance(val, list):
0114       myTuple = tuple(val)
0115     if isinstance(val, str):
0116       sep = ',' if ',' in val else ' '
0117       myTuple = tuple([_.strip("(), ") for _ in val.split(sep)])
0118     if myTuple is None:
0119       raise RuntimeError("Cannot parse input value %s" % val)
0120     return myTuple
0121 
0122   @staticmethod
0123   def makeBool(val):
0124     """check if val is a bool or a string of true/false, otherwise raise exception"""
0125     if isinstance(val, bool):
0126       return val
0127     elif isinstance(val, str):
0128       if val.lower() == 'true':
0129         return True
0130       elif val.lower() == 'false':
0131         return False
0132     raise RuntimeError(val)
0133 
0134   @staticmethod
0135   def addAllHelper(ddsim, parser):
0136     """all configHelper objects to commandline args"""
0137     for name, obj in vars(ddsim).items():
0138       if isinstance(obj, ConfigHelper):
0139         for var, optionsDict in obj.getOptions().items():
0140           optionsDict['action'] = ('store_true' if var.startswith(("enable", "force"))
0141                                    else optionsDict.get('action', 'store'))
0142           parser.add_argument("--%s.%s" % (name, var),
0143                               dest="%s.%s" % (name, var),
0144                               **optionsDict
0145                               )