test_nft.py 3.03 KB
Newer Older
Philipp Arras's avatar
Philipp Arras committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 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) 2019 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.

import numpy as np
import pytest
Philipp Arras's avatar
Philipp Arras committed
20
from numpy.testing import assert_
Philipp Arras's avatar
Philipp Arras committed
21

Martin Reinecke's avatar
Martin Reinecke committed
22
import nifty7 as ift
23
from ..common import setup_function, teardown_function
Philipp Arras's avatar
Philipp Arras committed
24
25
26

pmp = pytest.mark.parametrize

Martin Reinecke's avatar
Martin Reinecke committed
27

Martin Reinecke's avatar
Martin Reinecke committed
28
def _l2error(a, b):
Martin Reinecke's avatar
fixes    
Martin Reinecke committed
29
    return np.sqrt(np.sum(np.abs(a-b)**2)/np.sum(np.abs(a)**2))
Philipp Arras's avatar
Philipp Arras committed
30

Martin Reinecke's avatar
fixes    
Martin Reinecke committed
31

Martin Reinecke's avatar
Martin Reinecke committed
32
@pmp('eps', [1e-2, 1e-4, 1e-7, 1e-10, 1e-11, 1e-12, 2e-13])
Philipp Arras's avatar
Philipp Arras committed
33
34
35
@pmp('nu', [12, 128])
@pmp('nv', [4, 12, 128])
@pmp('N', [1, 10, 100])
36
def test_gridding(nu, nv, N, eps):
Martin Reinecke's avatar
Martin Reinecke committed
37
38
39
    uv = ift.random.current_rng().random((N, 2)) - 0.5
    vis = (ift.random.current_rng().standard_normal(N)
           + 1j*ift.random.current_rng().standard_normal(N))
Philipp Arras's avatar
Philipp Arras committed
40

41
42
43
    if N > 2:
        uv[-1] = 0
        uv[-2] = 1e-5
Philipp Arras's avatar
Philipp Arras committed
44
    # Nifty
45
46
    dom = ift.RGSpace((nu, nv), distances=(0.2, 1.12))
    dstx, dsty = dom.distances
Martin Reinecke's avatar
Martin Reinecke committed
47
48
    uv[:, 0] = uv[:, 0]/dstx
    uv[:, 1] = uv[:, 1]/dsty
Martin Reinecke's avatar
Martin Reinecke committed
49
    Op = ift.Gridder(dom, uv=uv, eps=eps)
Martin Reinecke's avatar
Martin Reinecke committed
50
    vis2 = ift.makeField(ift.UnstructuredDomain(vis.shape), vis)
Philipp Arras's avatar
Philipp Arras committed
51

Martin Reinecke's avatar
stage 3    
Martin Reinecke committed
52
    pynu = Op(vis2).val
Philipp Arras's avatar
Philipp Arras committed
53
54
55
56
57
    # DFT
    x, y = np.meshgrid(
        *[-ss/2 + np.arange(ss) for ss in [nu, nv]], indexing='ij')
    dft = pynu*0.
    for i in range(N):
Martin Reinecke's avatar
Martin Reinecke committed
58
59
        dft += (
            vis[i]*np.exp(2j*np.pi*(x*uv[i, 0]*dstx + y*uv[i, 1]*dsty))).real
Martin Reinecke's avatar
Martin Reinecke committed
60
    assert_(_l2error(dft, pynu) < eps)
Philipp Arras's avatar
Philipp Arras committed
61
62


Martin Reinecke's avatar
Martin Reinecke committed
63
64
65
66
67
68
69
70
71
72
73
def test_cartesian():
    nx, ny = 2, 6
    dstx, dsty = 0.3, 0.2
    dom = ift.RGSpace((nx, ny), (dstx, dsty))

    kx = np.fft.fftfreq(nx, dstx)
    ky = np.fft.fftfreq(ny, dsty)
    uu, vv = np.meshgrid(kx, ky)
    tmp = np.vstack([uu[None, :], vv[None, :]])
    uv = np.transpose(tmp, (2, 1, 0)).reshape(-1, 2)

Martin Reinecke's avatar
Martin Reinecke committed
74
    op = ift.Gridder(dom, uv=uv).adjoint
Martin Reinecke's avatar
Martin Reinecke committed
75

76
    fld = ift.from_random(dom, 'normal')
Martin Reinecke's avatar
stage 3    
Martin Reinecke committed
77
    arr = fld.val
Martin Reinecke's avatar
Martin Reinecke committed
78

Martin Reinecke's avatar
Martin Reinecke committed
79
    fld2 = ift.makeField(dom, np.roll(arr, (nx//2, ny//2), axis=(0, 1)))
Martin Reinecke's avatar
stage 3    
Martin Reinecke committed
80
    res = op(fld2).val.reshape(nx, ny)
Martin Reinecke's avatar
Martin Reinecke committed
81
82

    fft = ift.FFTOperator(dom.get_default_codomain(), target=dom).adjoint
Martin Reinecke's avatar
Martin Reinecke committed
83
    vol = ift.full(dom, 1.).s_integrate()
Martin Reinecke's avatar
stage 3    
Martin Reinecke committed
84
    res1 = fft(fld).val
Martin Reinecke's avatar
Martin Reinecke committed
85

Martin Reinecke's avatar
Martin Reinecke committed
86
    np.testing.assert_allclose(res, res1*vol)
Martin Reinecke's avatar
Martin Reinecke committed
87
88


Martin Reinecke's avatar
Martin Reinecke committed
89
@pmp('eps', [1e-2, 1e-6, 2e-13])
Philipp Arras's avatar
Philipp Arras committed
90
91
92
@pmp('nu', [12, 128])
@pmp('nv', [4, 12, 128])
@pmp('N', [1, 10, 100])
93
def test_build(nu, nv, N, eps):
Philipp Arras's avatar
Philipp Arras committed
94
    dom = ift.RGSpace([nu, nv])
Martin Reinecke's avatar
Martin Reinecke committed
95
    uv = ift.random.current_rng().random((N, 2)) - 0.5
Martin Reinecke's avatar
Martin Reinecke committed
96
    RF = ift.Gridder(dom, uv=uv, eps=eps)
Philipp Arras's avatar
Philipp Arras committed
97
98

    # Consistency checks
99
100
    flt = np.float64
    cmplx = np.complex128
Philipp Arras's avatar
Philipp Arras committed
101
    ift.extra.check_linear_operator(RF, cmplx, flt, only_r_linear=True)