domain_object.py 3.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Theo Steininger's avatar
Theo Steininger committed
13 14 15 16 17
#
# Copyright(C) 2013-2017 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik
# and financially supported by the Studienstiftung des deutschen Volkes.
18

Martin Reinecke's avatar
Martin Reinecke committed
19
from __future__ import division
20
import abc
Martin Reinecke's avatar
Martin Reinecke committed
21
from .utilities import NiftyMeta
Martin Reinecke's avatar
Martin Reinecke committed
22
from future.utils import with_metaclass
Martin Reinecke's avatar
Martin Reinecke committed
23
import numpy as np
24 25


26
class DomainObject(with_metaclass(
Martin Reinecke's avatar
Martin Reinecke committed
27
        NiftyMeta, type('NewBase', (object,), {}))):
28
    """The abstract class that can be used as a domain for a field.
29 30 31

    This holds all the information and functionality a field needs to know
    about its domain and how the data of the field are stored.
32
    """
33

Martin Reinecke's avatar
Martin Reinecke committed
34
    def __init__(self):
35
        self._needed_for_hash = []
36

37 38 39 40
    @abc.abstractmethod
    def __repr__(self):
        raise NotImplementedError

41 42
    def __hash__(self):
        result_hash = 0
43 44
        for key in self._needed_for_hash:
            result_hash ^= hash(vars(self)[key])
45 46 47
        return result_hash

    def __eq__(self, x):
Martin Reinecke's avatar
Martin Reinecke committed
48
        """Checks if two domain_objects are equal.
Theo Steininger's avatar
Theo Steininger committed
49

50 51 52
        Parameters
        ----------
        x: domain_object
Theo Steininger's avatar
Theo Steininger committed
53 54
            The domain_object `self` is compared to.

55 56
        Returns
        -------
Martin Reinecke's avatar
Martin Reinecke committed
57
        bool: True iff `self` and x describe the same manifold.
58
        """
Martin Reinecke's avatar
Martin Reinecke committed
59 60
        if self is x:  # shortcut for simple case
            return True
Martin Reinecke's avatar
Martin Reinecke committed
61
        if not isinstance(x, type(self)):
62
            return False
63 64 65
        for key in self._needed_for_hash:
            if vars(self)[key] != vars(x)[key]:
                return False
Martin Reinecke's avatar
Martin Reinecke committed
66
        return True
67 68 69 70 71 72

    def __ne__(self, x):
        return not self.__eq__(x)

    @abc.abstractproperty
    def shape(self):
Martin Reinecke's avatar
Martin Reinecke committed
73
        """The domain-object's shape contribution to the underlying array.
Theo Steininger's avatar
Theo Steininger committed
74

75 76
        Returns
        -------
Martin Reinecke's avatar
Martin Reinecke committed
77
        tuple of ints: shape of the underlying array-like object
78
        """
Martin Reinecke's avatar
Martin Reinecke committed
79
        raise NotImplementedError
80 81 82

    @abc.abstractproperty
    def dim(self):
Theo Steininger's avatar
Theo Steininger committed
83 84
        """ Returns the number of pixel-dimensions the object has.

85 86
        Returns
        -------
Martin Reinecke's avatar
Martin Reinecke committed
87
        int: number of pixels
88
        """
Martin Reinecke's avatar
Martin Reinecke committed
89
        raise NotImplementedError
90

91
    @abc.abstractmethod
92
    def scalar_dvol(self):
Martin Reinecke's avatar
Martin Reinecke committed
93
        """Returns the volume factors of this domain as a floating
94 95 96 97 98
        point scalar, if the volume factors are all identical, otherwise
        returns None.

        Returns
        -------
Martin Reinecke's avatar
Martin Reinecke committed
99
        float or None: Volume factor
100
        """
Martin Reinecke's avatar
Martin Reinecke committed
101
        raise NotImplementedError
102

103
    def dvol(self):
Martin Reinecke's avatar
Martin Reinecke committed
104
        """Returns the volume factors of this domain, either as a floating
105 106
        point scalar (if the volume factors are all identical) or as a
        floating point array with a shape of `self.shape`.
Theo Steininger's avatar
Theo Steininger committed
107

108 109
        Returns
        -------
Martin Reinecke's avatar
Martin Reinecke committed
110
        float or numpy.ndarray(dtype=float): Volume factors
111
        """
112
        return self.scalar_dvol()
Martin Reinecke's avatar
Martin Reinecke committed
113 114 115 116 117 118 119 120

    @property
    def total_volume(self):
        tmp = self.dvol()
        if np.isscalar(tmp):
            return self.dim * tmp
        else:
            return np.sum(tmp)