diff --git a/DDSim/DD4hepSimulation.py b/DDSim/DD4hepSimulation.py index 44c0b3745a088baae4e1074e73932b6667fd8592..57ec1693332c0e914f3316a014a2825978ea57a2 100644 --- a/DDSim/DD4hepSimulation.py +++ b/DDSim/DD4hepSimulation.py @@ -196,7 +196,7 @@ class DD4hepSimulation(object): help="print an example steering file to stdout") #output, or do something smarter with fullHelp only for example - self.__addAllHelper( parser ) + ConfigHelper.addAllHelper(self, parser) ## now parse everything. The default values are now taken from the ## steeringFile if they were set so that the steering file parameters can be ## overwritten from the command line @@ -545,30 +545,6 @@ class DD4hepSimulation(object): vSmear.Mask = mask actionList.append(vSmear) - def __addAllHelper( self , parser ): - """all configHelper objects to commandline args""" - for name, obj in vars(self).iteritems(): - if isinstance( obj, ConfigHelper ): - for var,valAndDoc in obj.getOptions().iteritems(): - if var.startswith("enable"): - parser.add_argument("--%s.%s" % (name, var), - action="store_true", - dest="%s.%s" % (name, var), - default = valAndDoc[0], - help = valAndDoc[1], - #choices = valAndDoc[2], ##not allowed for store_true - # type = type(val), - ) - else: - parser.add_argument("--%s.%s" % (name, var), - action="store", - dest="%s.%s" % (name, var), - default = valAndDoc[0], - help = valAndDoc[1], - choices = valAndDoc[2], - # type = type(val), - ) - def __parseAllHelper( self, parsed ): """ parse all the options for the helper """ @@ -607,8 +583,8 @@ class DD4hepSimulation(object): for parName, parameter in parameters.iteritems(): if isinstance( parameter, ConfigHelper ): options = parameter.getOptions() - for opt,valAndDoc in options.iteritems(): - runHeader["%s.%s"%(parName, opt)] = str(valAndDoc[0]) + for opt,optionsDict in options.iteritems(): + runHeader["%s.%s"%(parName, opt)] = str(optionsDict['default']) else: runHeader[parName] = str(parameter) @@ -687,12 +663,12 @@ SIM = DD4hepSimulation() steeringFileBase += "## %s \n" % "\n## ".join( parameter.__doc__.splitlines() ) steeringFileBase += "################################################################################\n" options = parameter.getOptions() - for opt,valAndDoc in sorted( options.iteritems(), sortParameters ): + for opt, optionsDict in sorted( options.iteritems(), sortParameters ): if opt.startswith("_"): continue - parValue, parDoc, _parOptions = valAndDoc - if parDoc: - steeringFileBase += "\n## %s\n" % "\n## ".join(parDoc.splitlines()) + parValue = optionsDict['default'] + if isinstance(optionsDict.get('help'), basestring): + steeringFileBase += "\n## %s\n" % "\n## ".join(optionsDict.get('help').splitlines()) ## add quotes if it is a string if isinstance( parValue, basestring ): steeringFileBase += "SIM.%s.%s = \"%s\"\n" %(parName, opt, parValue) diff --git a/DDSim/Helper/ConfigHelper.py b/DDSim/Helper/ConfigHelper.py index 540fbeeeb1606616d7770cb3b7cb85839b786265..e4bac6a1e984b319b5af7c705a2438bb7ef65d29 100644 --- a/DDSim/Helper/ConfigHelper.py +++ b/DDSim/Helper/ConfigHelper.py @@ -1,8 +1,15 @@ -""" - -Helper object to identify configuration parameters so we can easily overwrite +"""Helper object to identify configuration parameters so we can easily overwrite them via command line magic or via the steering file +To add additional arguments create either a member variable or a property to a +subclass of the ConfigHelper. To add additional arguments to the add_argument +call for the parser object create an additional member:: + + self.member = [1,2] + self._member_EXTRA = {'help': 'description for parameter', + 'nargs': '+', + } + """ from pprint import pprint @@ -19,18 +26,23 @@ class ConfigHelper( object ): allVars = vars(self) for var,val in allVars.iteritems(): if not var.startswith('_'): - helpName = "_%s_HELP" % var - optName = "_%s_OPTIONS" % var - doc = getattr(self, helpName) if hasattr(self, helpName) else '' - choices = getattr(self, optName) if hasattr(self, optName) else None - finalVars[var] = (val, doc, choices) + extraArgumentsName = "_%s_EXTRA" % var + options = getattr(self, extraArgumentsName) if hasattr(self, extraArgumentsName) else None + finalVars[var] = {'default': val} + if options: + finalVars[var].update(options) # now get things defined with @property props = [(p, getattr(type(self),p)) for p in dir(type(self)) if isinstance(getattr(type(self),p),property)] for propName, prop in props: - optName = "_%s_OPTIONS" % propName - choices = getattr(self, optName) if hasattr(self, optName) else None - finalVars[propName] = (getattr(self, propName), prop.__doc__, choices) + optName = "_%s_EXTRA" % propName + doc = prop.__doc__ + options = getattr(self, optName) if hasattr(self, optName) else None + finalVars[propName] = {'default': getattr(self, propName)} + if doc: + finalVars[propName]['help'] = doc + if options: + finalVars[propName].update(options) return finalVars @@ -84,3 +96,16 @@ class ConfigHelper( object ): elif val.lower() == 'false': return False raise RuntimeError( val ) + + + @staticmethod + def addAllHelper(ddsim, parser): + """all configHelper objects to commandline args""" + for name, obj in vars(ddsim).iteritems(): + if isinstance(obj, ConfigHelper): + for var,optionsDict in obj.getOptions().iteritems(): + optionsDict['action']='store_true' if var.startswith("enable") else 'store' + parser.add_argument("--%s.%s" % (name, var), + dest="%s.%s" % (name, var), + **optionsDict + ) diff --git a/DDSim/Helper/Gun.py b/DDSim/Helper/Gun.py index 4b3ab599fa9bde60d4107ed4c225245a9badebf4..fb3fcde02736dd244ec63ccea01ded0e85b2e9d4 100644 --- a/DDSim/Helper/Gun.py +++ b/DDSim/Helper/Gun.py @@ -14,13 +14,15 @@ class Gun( ConfigHelper ): self._isotrop = False self._direction = (0,0,1) - self._phiMin_HELP = "Minimal azimuthal angle for random distribution" + self._phiMin_EXTRA = {'help': "Minimal azimuthal angle for random distribution"} self.phiMin = None self.phiMax = None self.thetaMin = None self.thetaMax = None - self._distribution_OPTIONS = ['uniform', 'cos(theta)', 'eta', 'pseudorapidity', 'ffbar'] ## (1+cos^2 theta) + self._distribution_EXTRA = {'choices': ['uniform', 'cos(theta)', + 'eta', 'pseudorapidity', + 'ffbar']} ## (1+cos^2 theta) self._distribution = None diff --git a/DDSim/Helper/Output.py b/DDSim/Helper/Output.py index 747e4c540c09272d4516f376378599ad459364bb..63e42895ec1efb33d24ec2d25fd3b3c406dfc80d 100644 --- a/DDSim/Helper/Output.py +++ b/DDSim/Helper/Output.py @@ -7,16 +7,16 @@ class Output( ConfigHelper ): """Configuration for the output levels of DDG4 components""" def __init__( self ): super(Output, self).__init__() - self._kernel_OPTIONS = (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS') + self._kernel_EXTRA = {'choices': (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS')} self._kernel = outputLevel('INFO') - self._part_OPTIONS = (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS') + self._part_EXTRA = {'choices': (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS')} self._part = outputLevel('INFO') - self._inputStage_OPTIONS = (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS') + self._inputStage_EXTRA = {'choices': (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS')} self._inputStage = outputLevel('INFO') - self._random_OPTIONS = (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS') + self._random_EXTRA = {'choices': (1,2,3,4,5,6,7,'VERBOSE','DEBUG', 'INFO', 'WARNING', 'ERROR', 'FATAL', 'ALWAYS')} self._random = outputLevel('FATAL') @property diff --git a/DDSim/Helper/Random.py b/DDSim/Helper/Random.py index 4a355f6446cbeec435956af0963c473d81f896fd..ec6a67a7aace2cbffd9dda4067217153065169e4 100644 --- a/DDSim/Helper/Random.py +++ b/DDSim/Helper/Random.py @@ -15,8 +15,9 @@ class Random (ConfigHelper): self.file = None self._random = None - self._enableEventSeed_HELP = "If True, calculate random seed for each event based on eventID and runID\n" \ - "allows reproducibility even when SkippingEvents" + self._enableEventSeed_EXTRA = {'help': "If True, calculate random seed for each event based" \ + "on eventID and runID\nAllows reproducibility even when" \ + "SkippingEvents"} self.enableEventSeed = False def initialize(self, DDG4, kernel, output):