multi_domain.py 2.79 KB
Newer Older
Martin Reinecke's avatar
Martin Reinecke committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# 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/>.
#
# Copyright(C) 2013-2018 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik
# and financially supported by the Studienstiftung des deutschen Volkes.

Martin Reinecke's avatar
Martin Reinecke committed
19
from __future__ import absolute_import, division, print_function
20

Martin Reinecke's avatar
Martin Reinecke committed
21
from ..compat import *
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
22
from ..domain_tuple import DomainTuple
23
from ..utilities import frozendict
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
24 25


Martin Reinecke's avatar
Martin Reinecke committed
26
class MultiDomain(object):
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
27 28
    _domainCache = {}

Martin Reinecke's avatar
Martin Reinecke committed
29
    def __init__(self, dict, _callingfrommake=False):
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
30
        if not _callingfrommake:
Martin Reinecke's avatar
Martin Reinecke committed
31 32
            raise NotImplementedError(
                'To create a MultiDomain call `MultiDomain.make()`.')
Martin Reinecke's avatar
Martin Reinecke committed
33 34
        self._keys = tuple(sorted(dict.keys()))
        self._domains = tuple(dict[key] for key in self._keys)
Martin Reinecke's avatar
Martin Reinecke committed
35
        self._idx = frozendict({key: i for i, key in enumerate(self._keys)})
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
36 37

    @staticmethod
Martin Reinecke's avatar
Martin Reinecke committed
38 39 40 41
    def make(inp):
        if isinstance(inp, MultiDomain):
            return inp
        if not isinstance(inp, dict):
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
42 43
            raise TypeError("dict expected")
        tmp = {}
Martin Reinecke's avatar
Martin Reinecke committed
44
        for key, value in inp.items():
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
45 46 47
            if not isinstance(key, str):
                raise TypeError("keys must be strings")
            tmp[key] = DomainTuple.make(value)
Martin Reinecke's avatar
Martin Reinecke committed
48 49
        tmp = frozendict(tmp)
        obj = MultiDomain._domainCache.get(tmp)
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
50 51
        if obj is not None:
            return obj
Martin Reinecke's avatar
Martin Reinecke committed
52 53
        obj = MultiDomain(tmp, _callingfrommake=True)
        MultiDomain._domainCache[tmp] = obj
Martin Reinecke's avatar
step 1  
Martin Reinecke committed
54
        return obj
Martin Reinecke's avatar
Martin Reinecke committed
55

Martin Reinecke's avatar
Martin Reinecke committed
56 57 58 59 60 61
    def keys(self):
        return self._keys

    def domains(self):
        return self._domains

Martin Reinecke's avatar
Martin Reinecke committed
62 63 64 65
    @property
    def idx(self):
        return self._idx

Martin Reinecke's avatar
Martin Reinecke committed
66 67 68 69
    def items(self):
        return zip(self._keys, self._domains)

    def __getitem__(self, key):
Martin Reinecke's avatar
Martin Reinecke committed
70
        return self._domains[self._idx[key]]
Martin Reinecke's avatar
Martin Reinecke committed
71 72 73 74 75 76 77

    def __len__(self):
        return len(self._keys)

    def __hash__(self):
        return self._keys.__hash__() ^ self._domains.__hash__()

Martin Reinecke's avatar
Martin Reinecke committed
78
    def __eq__(self, x):
Martin Reinecke's avatar
Martin Reinecke committed
79 80
        if self is x:
            return True
Martin Reinecke's avatar
Martin Reinecke committed
81
        return self is MultiDomain.make(x)
Martin Reinecke's avatar
Martin Reinecke committed
82 83 84

    def __ne__(self, x):
        return not self.__eq__(x)
Martin Reinecke's avatar
Martin Reinecke committed
85 86 87

    def __str__(self):
        res = "MultiDomain:\n"
Martin Reinecke's avatar
Martin Reinecke committed
88
        for key, dom in zip(self._keys, self._domains):
Martin Reinecke's avatar
Martin Reinecke committed
89 90
            res += key+": "+str(dom)+"\n"
        return res