test_power_space.py 8.43 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

19
20
21
22
23
24
25
26
from __future__ import division

import unittest
import numpy as np

from d2o import distributed_data_object
from numpy.testing import assert_, assert_equal, assert_almost_equal,\
        assert_raises
27
from nifty import PowerSpace, RGSpace, Space, LMSpace
28
from test.common import expand
Reimar H Leike's avatar
Reimar H Leike committed
29
from itertools import product, chain
Martin Reinecke's avatar
Martin Reinecke committed
30
# needed to check wether fftw is available
Theo Steininger's avatar
Theo Steininger committed
31
from nifty import dependency_injector as gdi
Martin Reinecke's avatar
Martin Reinecke committed
32
from nose.plugins.skip import SkipTest
33

34
HARMONIC_SPACES = [RGSpace((8,), harmonic=True),
Martin Reinecke's avatar
Martin Reinecke committed
35
36
37
38
39
40
41
42
43
44
45
46
47
                   RGSpace((7,), harmonic=True, zerocenter=True),
                   RGSpace((8,), harmonic=True, zerocenter=True),
                   RGSpace((7, 8), harmonic=True),
                   RGSpace((7, 8), harmonic=True, zerocenter=True),
                   RGSpace((6, 6), harmonic=True, zerocenter=True),
                   RGSpace((7, 5), harmonic=True, zerocenter=True),
                   RGSpace((5, 5), harmonic=True),
                   RGSpace((4, 5, 7), harmonic=True),
                   RGSpace((4, 5, 7), harmonic=True, zerocenter=True),
                   LMSpace(6),
                   LMSpace(9)]


48
#Try all sensible kinds of combinations of spaces, distributuion strategy and
49
#binning parameters
50
51
_maybe_fftw = ["fftw"] if ('pyfftw' in gdi) else []

Martin Reinecke's avatar
Martin Reinecke committed
52
53
54
55
56
57
58
59
CONSISTENCY_CONFIGS_IMPLICIT = product(HARMONIC_SPACES,
                                       ["not", "equal", "fftw"],
                                       [None], [None, 3, 4], [True, False])
CONSISTENCY_CONFIGS_EXPLICIT = product(HARMONIC_SPACES,
                                       ["not", "equal", "fftw"],
                                       [[0., 1.3]], [None], [False])
CONSISTENCY_CONFIGS = chain(CONSISTENCY_CONFIGS_IMPLICIT,
                            CONSISTENCY_CONFIGS_EXPLICIT)
60

Theo Steininger's avatar
Theo Steininger committed
61
# [harmonic_partner, distribution_strategy,
Theo Steininger's avatar
Theo Steininger committed
62
#  logarithmic, nbin, binbounds, expected]
63
CONSTRUCTOR_CONFIGS = [
Martin Reinecke's avatar
Martin Reinecke committed
64
65
66
    [1, 'not', False, None, None, {'error': ValueError}],
    [RGSpace((8,)), 'not', False, None, None, {'error': ValueError}],
    [RGSpace((8,), harmonic=True), 'not', False, None, None, {
67
68
69
70
        'harmonic': True,
        'shape': (5,),
        'dim': 5,
        'total_volume': 8.0,
Theo Steininger's avatar
Theo Steininger committed
71
        'harmonic_partner': RGSpace((8,), harmonic=True),
Theo Steininger's avatar
Theo Steininger committed
72
        'config': {'logarithmic': False, 'nbin': None, 'binbounds': None},
73
74
75
76
77
78
        'pindex': distributed_data_object([0, 1, 2, 3, 4, 3, 2, 1]),
        'kindex': np.array([0., 1., 2., 3., 4.]),
        'rho': np.array([1, 2, 2, 2, 1]),
        'pundex': np.array([0, 1, 2, 3, 4]),
        'k_array': np.array([0., 1., 2., 3., 4., 3., 2., 1.]),
        }],
Martin Reinecke's avatar
Martin Reinecke committed
79
    [RGSpace((8,), harmonic=True), 'not', True, None, None, {
80
81
82
83
        'harmonic': True,
        'shape': (2,),
        'dim': 2,
        'total_volume': 8.0,
Theo Steininger's avatar
Theo Steininger committed
84
        'harmonic_partner': RGSpace((8,), harmonic=True),
Theo Steininger's avatar
Theo Steininger committed
85
        'config': {'logarithmic': True, 'nbin': None, 'binbounds': None},
86
87
88
89
90
91
92
93
94
95
96
        'pindex': distributed_data_object([0, 1, 1, 1, 1, 1, 1, 1]),
        'kindex': np.array([0., 2.28571429]),
        'rho': np.array([1, 7]),
        'pundex': np.array([0, 1]),
        'k_array': np.array([0., 2.28571429, 2.28571429, 2.28571429,
                             2.28571429, 2.28571429, 2.28571429, 2.28571429]),
        }],
    ]


def get_distance_array_configs():
Martin Reinecke's avatar
Martin Reinecke committed
97
    da_0 = np.array([0, 1.0, 1.41421356, 2., 2.23606798, 2.82842712])
98
    return [
Martin Reinecke's avatar
Martin Reinecke committed
99
        [RGSpace((4, 4), harmonic=True),  da_0],
100
101
102
103
        ]


def get_weight_configs():
Martin Reinecke's avatar
Martin Reinecke committed
104
105
106
107
108
109
110
111
112
    np.random.seed(42)

    # power 1
    w_0_x = np.random.rand(32, 16, 6)
    # RGSpace((4, 4), harmonic=True)
    # using rho directly
    weight_0 = np.array([1, 4, 4, 2, 4, 1])
    weight_0 = weight_0.reshape([1, 1, 6])
    w_0_res = w_0_x * weight_0
113
114
    return [
        [RGSpace((4, 4), harmonic=True),
Martin Reinecke's avatar
Martin Reinecke committed
115
            w_0_x, 1, (2,), False, w_0_res],
116
        [RGSpace((4, 4), harmonic=True),
Martin Reinecke's avatar
Martin Reinecke committed
117
            w_0_x.copy(), 1, (2,), True, w_0_res],
118
119
120
121
122
        ]


class PowerSpaceInterfaceTest(unittest.TestCase):
    @expand([
Theo Steininger's avatar
Theo Steininger committed
123
        ['harmonic_partner', Space],
Theo Steininger's avatar
Theo Steininger committed
124
        ['config', dict],
125
126
127
128
129
130
131
132
133
134
135
        ['pindex', distributed_data_object],
        ['kindex', np.ndarray],
        ['rho', np.ndarray],
        ['pundex', np.ndarray],
        ['k_array', distributed_data_object],
        ])
    def test_property_ret_type(self, attribute, expected_type):
        r = RGSpace((4, 4), harmonic=True)
        p = PowerSpace(r)
        assert_(isinstance(getattr(p, attribute), expected_type))

Martin Reinecke's avatar
Martin Reinecke committed
136

137
class PowerSpaceConsistencyCheck(unittest.TestCase):
138
    @expand(CONSISTENCY_CONFIGS)
139
    def test_pipundexInversion(self, harmonic_partner, distribution_strategy,
140
141
142
143
144
145
146
147
                               binbounds, nbin, logarithmic):
        if distribution_strategy == "fftw":
            if not hasattr(gdi.get('fftw'), 'FFTW_MPI'):
                raise SkipTest
        p = PowerSpace(harmonic_partner=harmonic_partner,
                       distribution_strategy=distribution_strategy,
                       logarithmic=logarithmic, nbin=nbin,
                       binbounds=binbounds)
148
149
        assert_equal(p.pindex.flatten().get_full_data()[p.pundex],
                     np.arange(p.dim),
150
                     err_msg='pundex is not right-inverse of pindex!')
Martin Reinecke's avatar
Martin Reinecke committed
151

152
    @expand(CONSISTENCY_CONFIGS)
Martin Reinecke's avatar
Martin Reinecke committed
153
154
155
    def test_rhopindexConsistency(self, harmonic_partner,
                                  distribution_strategy, binbounds, nbin,
                                  logarithmic):
Theo Steininger's avatar
Theo Steininger committed
156
157
158
        if distribution_strategy == "fftw":
            if not hasattr(gdi.get('fftw'), 'FFTW_MPI'):
                raise SkipTest
Martin Reinecke's avatar
Martin Reinecke committed
159
        p = PowerSpace(harmonic_partner=harmonic_partner,
160
161
162
                           distribution_strategy=distribution_strategy,
                           logarithmic=logarithmic, nbin=nbin,
                           binbounds=binbounds)
163
164
        assert_equal(p.pindex.flatten()[p.pundex],np.arange(p.dim),
            err_msg='pundex is not right-inverse of pindex!')
Martin Reinecke's avatar
Martin Reinecke committed
165

166
167
        assert_equal(p.pindex.flatten().bincount(), p.rho,
            err_msg='rho is not equal to pindex degeneracy')
Martin Reinecke's avatar
Martin Reinecke committed
168

169
class PowerSpaceFunctionalityTest(unittest.TestCase):
Martin Reinecke's avatar
Martin Reinecke committed
170
    @expand(CONSTRUCTOR_CONFIGS)
Theo Steininger's avatar
Theo Steininger committed
171
    def test_constructor(self, harmonic_partner, distribution_strategy,
Theo Steininger's avatar
Theo Steininger committed
172
                         logarithmic, nbin, binbounds, expected):
Theo Steininger's avatar
Theo Steininger committed
173
174
175
        if distribution_strategy == "fftw":
            if not hasattr(gdi.get('fftw'), 'FFTW_MPI'):
                raise SkipTest
Martin Reinecke's avatar
Martin Reinecke committed
176
            raise SkipTest
177
178
        if 'error' in expected:
            with assert_raises(expected['error']):
Theo Steininger's avatar
Theo Steininger committed
179
                PowerSpace(harmonic_partner=harmonic_partner,
180
                           distribution_strategy=distribution_strategy,
Theo Steininger's avatar
Theo Steininger committed
181
182
                           logarithmic=logarithmic, nbin=nbin,
                           binbounds=binbounds)
183
        else:
Theo Steininger's avatar
Theo Steininger committed
184
            p = PowerSpace(harmonic_partner=harmonic_partner,
185
                           distribution_strategy=distribution_strategy,
Theo Steininger's avatar
Theo Steininger committed
186
187
                           logarithmic=logarithmic, nbin=nbin,
                           binbounds=binbounds)
Martin Reinecke's avatar
Martin Reinecke committed
188
            for key, value in expected.items():
189
190
191
192
193
194
                if isinstance(value, np.ndarray):
                    assert_almost_equal(getattr(p, key), value)
                else:
                    assert_equal(getattr(p, key), value)

    @expand(get_distance_array_configs())
Theo Steininger's avatar
Theo Steininger committed
195
196
    def test_distance_array(self, harmonic_partner, expected):
        p = PowerSpace(harmonic_partner=harmonic_partner)
197
198
199
        assert_almost_equal(p.get_distance_array('not'), expected)

    @expand(get_weight_configs())
Theo Steininger's avatar
Theo Steininger committed
200
    def test_weight(self, harmonic_partner, x, power, axes,
201
                    inplace, expected):
Theo Steininger's avatar
Theo Steininger committed
202
        p = PowerSpace(harmonic_partner=harmonic_partner)
203
204
205
206
        res = p.weight(x, power, axes, inplace)
        assert_almost_equal(res, expected)
        if inplace:
            assert_(x is res)