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