base.py 3.93 KB
Newer Older
Dion Haefner's avatar
Dion Haefner committed
1 2 3 4 5 6 7 8 9 10 11
import h5py
import os
import sys
import numpy as np

try: # Python 2.x
    raw_input
except NameError: # Python 3.x
    raw_input = input

from dorie.parfield import configparser
12
from dorie.parfield.parameter_file import write_parameter_file
Dion Haefner's avatar
Dion Haefner committed
13 14 15
from dorie.parfield.parameterization import parameterizations
from dorie.utilities.text_to_bool import text_to_bool

16
class BaseConverter(object):
Dion Haefner's avatar
Dion Haefner committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
    """
    Base class for all parameter field generator modules. Implements the writing
    of the parameter field to an H5 file, and supplies some utilities.

    Derived classes only need to implement the :meth:`read_data` method, and call
    the base class constructor.

    """
    data_dict = None #: Dictionary containing parameter name as key, and a numpy array representing the parameter field as value
    ParClass = None #: Class that is used to instantiate a parameter of the given parameterization
    _cp = None #: RawConfigParser instance

    def __init__(self, param, input_file = None):
        self._cp = configparser.cp(param)

        parType = self.read_parameter('general','parameterization')
        for p in parameterizations:
            if parType.lower() == p.classname.lower():
                self.ParClass = p
                break
            raise RuntimeError("Unrecognized parameterization type: {}".format(parType))

        if input_file is None:
            input_file = self.read_parameter('general','inputFile')

        out_path = self.read_parameter('general','outputFile')
        overwrite = text_to_bool(self.read_parameter('general','overwrite'))
        millerSimilarity = text_to_bool(self.read_parameter('generator','millerSimilarity'))
45
        self.dim = int(self.read_parameter('generator','dimensions'))
Dion Haefner's avatar
Dion Haefner committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

        self.data_dict = self.read_data(input_file,millerSimilarity)
        self.write(out_path,overwrite)

    def read_data(self,in_path):
        """
        To be implemented in a derived class. Should return a dictionary containing
        parameter name as key, and a numpy array representing the parameter field as value.

        """
        raise NotImplementedError

    def write(self,out_path,overwrite=False):
        if not self.data_dict:
            raise RuntimeError("Encountered empty data array (call read_data first)")

62 63
        for v in self.data_dict.values():
            if v.ndim != self.dim:
64
                raise ValueError("Data shape ({}) does not match field dimensions ({})".format(", ".join(v.shape), self.dim))
Dion Haefner's avatar
Dion Haefner committed
65
        h5_attrs = self._get_attributes()
66 67 68
        groupname = self.ParClass.classname
        write_parameter_file(groupname, self.data_dict, out_path,
                             attrs=h5_attrs, overwrite=overwrite)
Dion Haefner's avatar
Dion Haefner committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93

    def create_parclass(self,n):
        """
        Reads the ``parameters.<p>.<x>`` section from the parameter file and
        writes the contents into a :class:`dict`.

        :param cp: ConfigParser instance
        :param n: Suffix of the parameter section to be read
        :returns: Instance of :class:`Parameterization`

        """
        items = self._cp.items("parameters.{}.{}".format(self.ParClass.classname,int(n)))
        return self.ParClass(dict(items))

    def read_parameter(self,section,key):
        """
        Reads a parameter from the configuration file.

        """
        try:
            return self._cp[section][key]
        except KeyError:
            raise RuntimeError("Missing option {}.{} in parameter file".format(section,key))

    def _get_attributes(self):
94 95 96 97
        extensions = np.array(self.read_parameter("generator","extensions").split(), dtype=np.float64)
        if not extensions.size == self.dim:
            raise ValueError("Extensions do not match field dimensions")
        attr = {
Dion Haefner's avatar
Dion Haefner committed
98 99
                "millerSimilarity": np.bool(text_to_bool(self.read_parameter('generator','millerSimilarity'))),
                "variance": np.float64(self.read_parameter("generator","variance")),
100
                "extensions": extensions
Dion Haefner's avatar
Dion Haefner committed
101
            }
102
        return attr