"""
"""
import numpy as np
import logging
import os
[docs]def islistoflists(arg):
"""Return True if item is a list of lists."""
claim = False
if isinstance(arg, list):
if isinstance(arg[0], list):
claim = True
return claim
[docs]def f2prange(rng):
"""Convert fortran range definition to a python one.
Args:
rng (2-sequence): [low, high] index range boundaries,
inclusive, counting starts from 1.
Returns:
2-tuple: (low-1, high)
"""
lo, hi = rng
msg = (
"Invalid range specification {}, {}.".format(lo, hi)
+ " Range should be of two integers, both being >= 1."
)
assert lo >= 1 and hi >= lo, msg
return lo - 1, hi
[docs]def get_ranges(data):
"""Return list of tuples ready to use as python ranges.
Args:
data (int, list of int, list of lists of int):
A single index, a list of indexes, or a list of
2-tuple range of indexes in Fortran convention,
i.e. from low to high, counting from 1, and inclusive
Return:
list of lists of 2-tuple ranges, in Python convention -
from 0, exclusive.
"""
try:
rngs = []
for rng in data:
try:
lo, hi = rng
except TypeError:
lo, hi = rng, rng
rngs.append(f2prange((lo, hi)))
except TypeError:
# data not iterable -> single index, convert to list of lists
rngs = [f2prange((data, data))]
return rngs
[docs]def get_logger(name, filename=None, verbosity=logging.INFO):
"""Return a named logger with file and console handlers.
Get a `name`-logger. Check if it is(has) a parent logger.
If parent logger is not configured, configure it, and if a child logger
is needed, return the child.
The check for parent logger is based on `name`: a child if it contains '.',
i.e. looking for 'parent.child' form of `name`.
A parent logger is configured by defining a console handler at `verbosity`
level, and a file handler at DEBUG level, writing to `filename`.
"""
parent = name.split(".")[0]
if filename is None:
filename = parent + ".log"
parent_logger = logging.getLogger(parent)
if not parent_logger.handlers:
configure_logger(parent, filename, verbosity)
return logging.getLogger(name)
[docs]def normalise(a):
"""Normalise the given array so that sum of its elements yields 1.
Args:
a (array): input array
Returns:
a/norm (array): The norm is the sum of all elements across all dimensions.
"""
norm = np.sum(np.asarray(a))
return np.asarray(a) / norm
[docs]def arr2s(aa, precision=3, suppress_small=True, max_line_width=75):
"""Helper for compact string representation of numpy arrays."""
ss = np.array2string(
aa,
precision=precision,
suppress_small=suppress_small,
max_line_width=max_line_width,
)
return ss
[docs]def is_monotonic(x):
dx = np.diff(x)
return np.all(dx <= 0) or np.all(dx >= 0)
[docs]def normaliseWeights(weights):
"""
normalise weights so that their sum evaluates to 1
"""
return np.asarray(weights) / np.sum(np.asarray(weights))
[docs]def flatten(dd):
"""
Take a dictionary or list of dictionaries/lists dd,
and produce a lists of values corresponding, dropping the keys.
"""
try: # assume current item is a dictionary; iterate over its items
for key, val in dd.items():
for nested_val in flatten(val):
yield nested_val
except AttributeError: # not a dictionary
try: # assume current item is a list; iterate over its items
for i, val in enumerate(dd):
for nested_val in flatten(val):
yield nested_val
except TypeError: # it is just a number then; return it
yield dd
[docs]def flatten_two(d1, d2):
"""
Take two dictionaries or lists of dictionaries/lists d1 and d2,
and produce two lists of values corresponding to the keys/order in d1.
d2 is optional.
Assume that the keys of d1 are a subset of the keys of d2.
Assume nesting, i.e. some of the items in d1 are dictionaries
and some are lists, numpy arrays, or a non-sequence type.
The assumption is again: nested dictionaries in d2 must have
at least the keys of the corresponding nested dictionaries in d1,
and the lists in d1 must be no shorter than the lists in d2.
...some assertions may help here...
"""
try: # assume current item is a dictionary; iterate over its items
for key, val in d1.items():
for nested_val_1, nested_val_2 in flatten_two(val, d2[key]):
yield nested_val_1, nested_val_2
except AttributeError: # not a dictionary
try: # assume current item is a list; iterate over its items
for i, val in enumerate(d1):
for nested_val_1, nested_val_2 in flatten_two(val, d2[i]):
yield nested_val_1, nested_val_2
except TypeError: # it is just a number then; return it
# this fails if one number is native python number while
# the other is a numpy scalar
# assert isinstance(d2,type(d1)), (
# '\n{0} \n and \n{1} \nare of different type '
# '\n{2} \n and \n{3}'
# '\nand cannot be flattened simultaneously.'.
# format(d2,d1,type(d2),type(d1)))
assert not (hasattr(d1, "__iter__") or hasattr(d2, "__iter__")), (
"\n\t{0}\n{1}"
"\n\tand"
"\n\t{2}\n{3}"
"\n\tcannot be flattened simultaneously.".format(
type(d1), d1, type(d2), d2
)
)
yield d1, d2