Module simuOpt handles options to specify which simuPOP module to load and how this module should be loaded, using function simuOpt.setOptionswith parameters alleleType (short, long, or binary ), optimized (standard or optimized), gui (whether or not use a graphical user interface and which graphical toolkit to use), revision (minimal required version/revision), quiet (with or without banner message, and debug (which debug code to turn on). These options have been discussed in Example lst_Use_of_standard_module and lst_Use_of_optimized_module and other related sections. Note that most options can be set by environmental variables and command line options which are sometimes more versatile to use.
The simuOpt module also provides a class Params to help users handle and manage script parameters. There are many other standard or third-party parameter handling modules in Python but this class is designed to help users run a simuPOP script in both batch and GUI modes, using a combination of parameter determination methods. More specifically, if a script uses the simuOpt.Params class to handle parameters,
NOTE: simuOpt.Params was designed when getopt was the only parameter handling module of python. Although it still has some unique features (gui mode, validation etc) compared to the newly introduced standard module argparse, it is less extensible and powerful than argparse. This class is therefore deprecated although it will be kept in simuPOP for backward- compatibility reasons.
The following sections describes how to use the simuOpt class in a simuPOP script.
A Params object is created from a list of parameter specification dictionaries, and optional short and long descriptions of a script. Each parameter specification dictionary consits of the following fields:
Field validator is very useful in that it helps simuPOP determine whether or not a user input should be accepted. It accepts a function or an expression. Module simuOpt defines a number of functions that you can use. For example, if a parameter defines a probability, you might want to use
simuOpt.valueBetween(0, 1)
to validate if the input is between 0 and 1. If a list of probabilities is needed, you can use
simuOpt.valueListOf(simuOpt.valueBetween(0, 1))
More complex logics can be defined using simuOpt.valueOr or simuOpt.valueAnd. If validation of one parameter involves the values of other parameters, a Python expression can be used. For example, if two parameters need to have the same length, you can use
'len(opt1) == len(opt2)'
to validate opt1 or opt2.
Example getParam shows a parameter specification list that defines parameter help, rate, rep and pops. What is special about each parameter is that help will not be listed in the parameter input dialog (no label) and setting help to True during interactive parameter input will ignore all other options (jump); rate has to be between 0 and 1 (using a validation function valueBetween), rep has to be a positive integer, and pops can be one of the three HapMap populations. Please refer to the simuPOP reference manual for details about each dictionary key. The description of parameter pop demonstrates a special rule in the formatting of such description texts, namely lines with symbol ‘|’ as the first non-space/tab character are outputed as a separate line without the leading ‘|’ character.
Example: A sample parameter specification list
import simuPOP as sim
import types, simuOpt
options = [
{'name': 'rate',
'default': [0.01],
'label': 'Recombination rate',
'type': 'numbers',
'description': '''Recombination rate for each replicate. If a single value
is given, it will be used for all replicates.''',
'validator': simuOpt.valueListOf(simuOpt.valueBetween(0, 1))
},
{'name': 'rep',
'default': 5,
'label': 'Number of replicates',
'type': 'number',
'description': 'Number of replicates to simulate.',
'validator': simuOpt.valueGT(0)
},
{'name': 'pop',
'default': 'CEU',
'label': 'Initial population',
'type': ('chooseOneOf', ['CEU', 'YRI', 'CHB+JPT']),
'description': '''Use one of the HapMap sim.populations as the initial
sim.Population for this simulation. You can choose from:
|YRI: 33 trios from the Yoruba people in Nigeria (Africa)
|CEU: 30 trios from Utah with European ancestry (European)
|CHB+JPT: 90 unrelated individuals from China and Japan (Asia)
''',
}
]
pars = simuOpt.Params(options, 'A demo simulation')
print(pars.usage())
# You can manually feed parameters...
pars.processArgs(['--rep=10'])
If you dislike an explicit list of dictionaries, you can use function simuOpt.addOption to add options one by one. Example paramFunc shows an equivalent way of specifying three options using this function. This style is used by Python modules such as optparse and argparse, and is preferred by some simuPOP users.
Example: Using simuOpt.param to specify parameters
import types, simuOpt
pars = simuOpt.Params(doc='A demo simulation')
pars.addOption('rate', [0.01], label = 'Recombination rate',
type = 'numbers', description = '''Recombination rate for each replicate.
If a single value is given, it will be used for all replicates.''')
pars.addOption('rep', 5, label = 'Number of replicates', type = 'integer',
description = 'Number of replicates to simulate.',
validator = simuOpt.valueGT(0))
pars.addOption('pop', 'CEU', label = 'Initial population',
type = ('chooseOneOf', ['CEU', 'YRI', 'CHB+JPT']),
description = '''Use one of the HapMap sim.populations as the initial
sim.Population for this simulation. You can choose from:
|YRI: 33 trios from the Yoruba people in Nigeria (Africa)
|CEU: 30 trios from Utah with European ancestry (European)
|CHB+JPT: 90 unrelated individuals from China and Japan (Asia)
''')
print(pars.usage())
A Params object can be created from a parameter specification list. A few member functions are immediately usable. For example, usage() returns a detailed usage message about the script and all its parameters (although the usage message will be displayed automatically if command line option -h or --help is detected). The parameters become attributes of this object using longarg names so that you can access them easily (e.g. par.rate). Not surprosingly, all parameters now have the default value you assigned to them.
Function saveConfig(filename) saves current values of parameters to a configuraiton file filename. Parameters that do not have a label are ignored. This configuration file can be loaded later using command line option --config filename, perhaps with option --gui=False to run the script in batch mode. A less noticed feature of this function is that it also writes a complete command that specifies the same parameters using command line options. This can be handy if you would like to use real parameter definitions instead of --config filename in a batch file.
The params.Params class provides a number of member functions that allow you to acquire user input in a number of ways. For example loadConfig reads a configuration file, processArgs checks commandline options, termGetParam asks user input interactively, and guiGetParam generates and uses a parameter input dialog. These functions can be used several times, on different sets of parameters. In addition, new options could be added programmatically using function addOption and allows further flexibility on how parameters are generated. Please refer to the simuPOP reference manual on how to use these functions.
Example: Get prameters using function getParam
usage: runSampleCode.py [--opt[=arg]] ...
options:
-h, --help
Display this help message and exit.
--config=ARG (default: None)
Load parameters from a configuration file ARG.
--optimized
Run the script using an optimized simuPOP module.
--gui=[batch|interactive|True|Tkinter|wxPython] (default: None)
Run the script in batch, interactive or GUI mode.
--rate=ARG (default: [0.01])
Recombination rate for each replicate. If a single value is given, it
will be used for all replicates.
--rep=ARG (default: 5)
Number of replicates to simulate.
--pop=ARG (default: 'CEU')
Use one of the HapMap sim.populations as the initial sim.Population for
this simulation. You can choose from:
YRI: 33 trios from the Yoruba people in Nigeria (Africa)
CEU: 30 trios from Utah with European ancestry (European)
CHB+JPT: 90 unrelated individuals from China and Japan (Asia)
>>> # You can manually feed parameters...
>>> pars.processArgs(['--rep=10'])
True
>>> pars.rep
10
Example getParam lists some methods to determine parameter values but the last function, getParam(), will be used most of the time. This function processes each parameter in the following order:
getParam returns False if this process fails (e.g. users click cancel in the parameter input dialog). The parameter input dialog for Example getParam is shown in Figure fig_parameter_input_dialog.
Figure: A sample parameter input dialog
A parameter input dialog for a script that uses the same parameter specification list as Example getParam. The command line is simu.py --pop=YRI. The first parameter is in red because its input is invalid.
If getParam runs successfully, the Params object should have valid value for each parameter. They can be retrieved as attributes (such as par.rate) and manipulated easily. Example useSimuOpt demonstrates how to extend parameter par.rate to have the same length as par.rep.
When there are a large number of parameters, passing this Params object, instead of tens of parameters, is a good way to provide clean interfaces. Alternatively, you can get a list or a dictionary of parameters using member functions asList() and asDict().
Example: Use the simuOpt object
>>> if not pars.getParam():
... sys.exit(1)
...
>>> pars.saveConfig('sample.cfg')
>>> # post-process parameters
>>> pars.rate
[0.25]
>>> pars.rep
5
>>> pars.rate = pars.rate * pars.rep
>>> # extract parameters as a dictionary or a list
>>> pars.asDict()
{'rate': [0.25, 0.25, 0.25, 0.25, 0.25], 'rep': 5, 'pop': 'CEU'}
>>> pars.asList()
[[0.25, 0.25, 0.25, 0.25, 0.25], 5, 'CEU']
>>> # Default value of parameter rep is changed
>>> # additional attribute is added.
>>> par1 = simuOpt.Params(options, # all parameters with default values
... rep=50, # default value of rep is changed
... additional=10 # derived parameters are added
... )
>>> # print all parameters except for derived ones.
>>> print(par1.asDict())
{'rate': [0.01], 'rep': 50, 'pop': 'CEU'}
>>> # All parameters are derived ...
>>> par2 = simuOpt.Params(rep=50, pop='CEU', rate=[0.5])
>>> print(par2.asDict())
{}
>>> print(par2.rep, par2.pop)
(50, 'CEU')
It is easy to set additional attributes to a Params object, using either par.name = value statement or additional name=value pairs in the constructor of a simuOpt object. These attributes are not considered as parameters of an simuOpt object (e.g. they are not returned by function asDict()) but could be used just like regular parameters.
Additional attributes can be used to create a Params object without user interaction. For example, objects par1 and par2 in Example useSimuOpt are created with needed attributes. They can be passed to functions where a Params object is needed, although some of the attributes are not real parameters (in the sense that they are not created by a parameter specification dictionary and will not be used to handle user input).