1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
# Licensed under a 3-clause BSD style license - see LICENSE.rst
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import itertools
import numpy as np
from numpy.testing import assert_allclose
from ...tests.helper import pytest
from ..utils import discretize_model
from ...modeling.functional_models import (
Gaussian1D, Box1D, MexicanHat1D, Gaussian2D, Box2D, MexicanHat2D)
from ...modeling.tests.example_models import models_1D, models_2D
from ...modeling.tests.test_models import create_model
try:
import scipy # pylint: disable=W0611
HAS_SCIPY = True
except ImportError:
HAS_SCIPY = False
modes = ['center', 'linear_interp', 'oversample']
test_models_1D = [Gaussian1D, Box1D, MexicanHat1D]
test_models_2D = [Gaussian2D, Box2D, MexicanHat2D]
@pytest.mark.parametrize(('model_class', 'mode'), list(itertools.product(test_models_1D, modes)))
def test_pixel_sum_1D(model_class, mode):
"""
Test if the sum of all pixels corresponds nearly to the integral.
"""
if model_class == Box1D and mode == "center":
pytest.skip("Non integrating mode. Skip integral test.")
parameters = models_1D[model_class]
model = create_model(model_class, parameters)
values = discretize_model(model, models_1D[model_class]['x_lim'], mode=mode)
assert_allclose(values.sum(), models_1D[model_class]['integral'], atol=0.0001)
@pytest.mark.parametrize('mode', modes)
def test_gaussian_eval_1D(mode):
"""
Discretize Gaussian with different modes and check
if result is at least similar to Gaussian1D.eval().
"""
model = Gaussian1D(1, 0, 20)
x = np.arange(-100, 101)
values = model(x)
disc_values = discretize_model(model, (-100, 101), mode=mode)
assert_allclose(values, disc_values, atol=0.001)
@pytest.mark.parametrize(('model_class', 'mode'), list(itertools.product(test_models_2D, modes)))
def test_pixel_sum_2D(model_class, mode):
"""
Test if the sum of all pixels corresponds nearly to the integral.
"""
if model_class == Box2D and mode == "center":
pytest.skip("Non integrating mode. Skip integral test.")
parameters = models_2D[model_class]
model = create_model(model_class, parameters)
values = discretize_model(model, models_2D[model_class]['x_lim'],
models_2D[model_class]['y_lim'], mode=mode)
assert_allclose(values.sum(), models_2D[model_class]['integral'], atol=0.0001)
@pytest.mark.parametrize('mode', modes)
def test_gaussian_eval_2D(mode):
"""
Discretize Gaussian with different modes and check
if result is at least similar to Gaussian1D.eval()
"""
model = Gaussian2D(1, 0, 0, 20, 20)
x = np.arange(-100, 101)
y = np.arange(-100, 101)
x, y = np.meshgrid(x, y)
values = model(x, y)
disc_values = discretize_model(model, (-100, 101), (-100, 101), mode=mode)
assert_allclose(values, disc_values, atol=0.001)
@pytest.mark.skipif('not HAS_SCIPY')
def test_subpixel_gauss_1D():
"""
Test subpixel accuracy of the oversample mode with gaussian 1D model.
"""
gauss_1D = Gaussian1D(1, 0, 0.1)
values = discretize_model(gauss_1D, (-1, 2), mode='integrate', factor=100)
assert_allclose(values.sum(), np.sqrt(2 * np.pi) * 0.1, atol=0.00001)
@pytest.mark.skipif('not HAS_SCIPY')
def test_subpixel_gauss_2D():
"""
Test subpixel accuracy of the oversample mode with gaussian 2D model.
"""
gauss_2D = Gaussian2D(1, 0, 0, 0.1, 0.1)
values = discretize_model(gauss_2D, (-1, 2), (-1, 2), mode='integrate', factor=100)
assert_allclose(values.sum(), 2 * np.pi * 0.01, atol=0.00001)
def test_discretize_callable_1d():
"""
Test discretize when a 1d function is passed.
"""
def f(x):
return x ** 2
y = discretize_model(f, (-5, 6))
assert_allclose(y, np.arange(-5, 6) ** 2)
def test_discretize_callable_2d():
"""
Test discretize when a 2d function is passed.
"""
def f(x, y):
return x ** 2 + y ** 2
actual = discretize_model(f, (-5, 6), (-5, 6))
y, x = (np.indices((11, 11)) - 5)
desired = x ** 2 + y ** 2
assert_allclose(actual, desired)
def test_type_exception():
"""
Test type exception.
"""
with pytest.raises(TypeError) as exc:
discretize_model(float(0), (-10, 11))
assert exc.value.args[0] == 'Model must be callable.'
def test_dim_exception_1d():
"""
Test dimension exception 1d.
"""
def f(x):
return x ** 2
with pytest.raises(ValueError) as exc:
discretize_model(f, (-10, 11), (-10, 11))
assert exc.value.args[0] == "y range specified, but model is only 1-d."
def test_dim_exception_2d():
"""
Test dimension exception 2d.
"""
def f(x, y):
return x ** 2 + y ** 2
with pytest.raises(ValueError) as exc:
discretize_model(f, (-10, 11))
assert exc.value.args[0] == "y range not specified, but model is 2-d"
def test_float_x_range_exception():
def f(x, y):
return x ** 2 + y ** 2
with pytest.raises(ValueError) as exc:
discretize_model(f, (-10.002, 11.23))
assert exc.value.args[0] == ("The difference between the upper an lower"
" limit of 'x_range' must be a whole number.")
def test_float_y_range_exception():
def f(x, y):
return x ** 2 + y ** 2
with pytest.raises(ValueError) as exc:
discretize_model(f, (-10, 11), (-10.002, 11.23))
assert exc.value.args[0] == ("The difference between the upper an lower"
" limit of 'y_range' must be a whole number.")
|