""" This is an auxiliary module for reading input .ini files.
It is based on Python's stdlib
`ConfigParser <http://docs.python.org/2/library/configparser.html/>`_
This module also provides functionality for setting run sets where
one or more of the parameters run over a list of values.
"""
import os, os.path, socket
from ConfigParser import SafeConfigParser, RawConfigParser, NoOptionError
from warnings import warn
from itertools import product
import re
import numpy
[docs]def guess_type(s):
""" Converts s into int or float if possible. If not, leave it as a
string. This will give us problems if the user wants to e.g. use
filenames or run names that can be parser as a number. So have to
implement a better approach whereby parameter names are associated with
types.
"""
try:
return int(s)
except ValueError:
pass
try:
return float(s)
except ValueError:
pass
return s
# These are decorators to check allowed values.
[docs]def positive(func):
""" A decorator to constraint the parameter to positive values. """
def f(s):
r = func(s)
if not r >= 0:
raise ValueError("%s must be positive" % func.func_name)
return r
f.__doc__ = func.__doc__
f.func_name = func.func_name
return f
# These are decorators to check allowed values.
[docs]def nonnegative(func):
""" A decorator to constraint the parameter to nonnegative values. """
def f(s):
r = func(s)
if r < 0:
raise ValueError("%s must be positive" % func.func_name)
return r
f.__doc__ = func.__doc__
f.func_name = func.func_name
return f
# A decorator to set a default value, stored in the dictionary PARAM_DEFAULTS
PARAM_DEFAULTS = {}
def default(value):
def deco(func):
global PARAM_DEFAULTS
PARAM_DEFAULTS[func.func_name] = value
return func
return deco
RE_LIST = re.compile(r'@\((.+)\)')
RE_LOOP = re.compile(r'@@\(([\d.-]+):([\d.-]+)(:([\d.-]+))?\)')
[docs]def expand(s, parser):
""" Expands special characters to produce e.g. lists of many parameters.
"""
# All expansions start with the symbol '@':
if not '@' in s:
return parser(s)
m = RE_LIST.match(s)
if m:
return [parser(x) for x in m.group(1).split()]
m = RE_LOOP.match(s)
if m:
if m.group(4) is not None:
a, b, c = parser(m.group(1)), parser(m.group(2)), parser(m.group(4))
else:
a, b, c = parser(m.group(1)), parser(m.group(2)), None
r = numpy.arange(a, b, c)
print r
print [parser(x) for x in r]
return [parser(str(x)) for x in r]
[docs]def expand_dict(d):
""" Takes a dictionary that may contain a few lists as values and returns
an iterator over dictionaries where each of these elements is iterated. """
keys, lists = zip(*[(k, v) for k, v in d.iteritems()
if isinstance(v, list)])
for tpl in product(*lists):
d0 = d.copy()
for k, v in zip(keys, tpl):
d0[k] = v
yield d0
def main():
import sys
import parameters
expand_input(sys.argv[1], parameters)
# d = load_input(sys.argv[1], parameters, d={}, upper=True)
# for d0 in expand_dict(d):
# print d0
if __name__ == '__main__':
main()