Skip to content

Commit 3b43ba4

Browse files
committed
Fixed #2274
1 parent 72ca1bb commit 3b43ba4

3 files changed

Lines changed: 79 additions & 15 deletions

File tree

‎CHANGES.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,8 @@ Bug Fixes
366366
- ``astropy.constants``
367367

368368
- ``astropy.convolution``
369+
370+
- ``astropy.convolution.discretize_model`` now handles arbitrary callables correctly [#2274].
369371

370372
- ``astropy.coordinates``
371373

‎astropy/convolution/tests/test_discretize.py‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,52 @@ def test_subpixel_gauss_2D():
104104
gauss_2D = Gaussian2D(1, 0, 0, 0.1, 0.1)
105105
values = discretize_model(gauss_2D, (-1, 2), (-1, 2), mode='integrate', factor=100)
106106
assert_allclose(values.sum(), 2 * np.pi * 0.01, atol=0.00001)
107+
108+
def test_discretize_callable_1d():
109+
"""
110+
Test discretize when a 1d function is passed.
111+
"""
112+
def f(x):
113+
return x ** 2
114+
y = discretize_model(f, (-5, 6))
115+
assert_allclose(y, np.arange(-5, 6) ** 2)
116+
117+
def test_discretize_callable_2d():
118+
"""
119+
Test discretize when a 2d function is passed.
120+
"""
121+
def f(x, y):
122+
return x ** 2 + y ** 2
123+
actual = discretize_model(f, (-5, 6), (-5, 6))
124+
y, x = (np.indices((11, 11)) - 5)
125+
desired = x ** 2 + y ** 2
126+
assert_allclose(actual, desired)
127+
128+
def test_type_exception():
129+
"""
130+
Test type exception.
131+
"""
132+
with pytest.raises(TypeError) as exc:
133+
discretize_model(float(0), (-10, 11))
134+
assert exc.value.args[0] == 'Model must be callable.'
135+
136+
def test_dim_exception_1d():
137+
"""
138+
Test dimension exception 1d.
139+
"""
140+
def f(x):
141+
return x ** 2
142+
with pytest.raises(ValueError) as exc:
143+
discretize_model(f, (-10, 11), (-10, 11))
144+
assert exc.value.args[0] == "y range specified, but model is only 1-d."
145+
146+
def test_dim_exception_2d():
147+
"""
148+
Test dimension exception 2d.
149+
"""
150+
def f(x, y):
151+
return x ** 2 + y ** 2
152+
with pytest.raises(ValueError) as exc:
153+
discretize_model(f, (-10, 11))
154+
assert exc.value.args[0] == "y range not specified, but model is 2-d"
155+

‎astropy/convolution/utils.py‎

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
import numpy as np
66

7-
from ..modeling.core import Fittable1DModel, Fittable2DModel
8-
7+
from ..modeling.core import FittableModel, custom_model
98

109
__all__ = ['discretize_model']
1110

@@ -74,12 +73,16 @@ def add_kernel_arrays_2D(array_1, array_2):
7473

7574
def discretize_model(model, x_range, y_range=None, mode='center', factor=10):
7675
"""
77-
Function to evaluate analytical models on a grid.
76+
Function to evaluate analytical model functions on a grid.
77+
78+
So far the function can only deal with pixel coordinates.
7879
7980
Parameters
8081
----------
81-
model : `~astropy.modeling.FittableModel`
82-
Model to be evaluated.
82+
model : `~astropy.modeling.FittableModel` or callable.
83+
Analytic model function to be discretized. Callables, which are not an
84+
instances of `~astropy.modeling.FittableModel` are passed to
85+
`~astropy.modeling.custom_model` and then evaluated.
8386
x_range : tuple
8487
x range in which the model is evaluated.
8588
y_range : tuple, optional
@@ -135,27 +138,37 @@ def discretize_model(model, x_range, y_range=None, mode='center', factor=10):
135138
136139
137140
"""
138-
if isinstance(model, Fittable2DModel) and y_range is None:
139-
raise Exception("Please specify y range.")
141+
if not callable(model):
142+
raise TypeError('Model must be callable.')
143+
if not isinstance(model, FittableModel):
144+
model = custom_model(model)()
145+
ndim = model.n_inputs
146+
if ndim > 2:
147+
raise ValueError('discretize_model only supports 1-d and 2-d models.')
148+
149+
if ndim == 2 and y_range is None:
150+
raise ValueError("y range not specified, but model is 2-d")
151+
if ndim == 1 and y_range is not None:
152+
raise ValueError("y range specified, but model is only 1-d.")
140153
if mode == "center":
141-
if isinstance(model, Fittable1DModel):
154+
if ndim == 1:
142155
return discretize_center_1D(model, x_range)
143-
if isinstance(model, Fittable2DModel):
156+
elif ndim == 2:
144157
return discretize_center_2D(model, x_range, y_range)
145158
elif mode == "linear_interp":
146-
if isinstance(model, Fittable1DModel):
159+
if ndim == 1:
147160
return discretize_linear_1D(model, x_range)
148-
if isinstance(model, Fittable2DModel):
161+
if ndim == 2:
149162
return discretize_bilinear_2D(model, x_range, y_range)
150163
elif mode == "oversample":
151-
if isinstance(model, Fittable1DModel):
164+
if ndim == 1:
152165
return discretize_oversample_1D(model, x_range, factor)
153-
if isinstance(model, Fittable2DModel):
166+
if ndim == 2:
154167
return discretize_oversample_2D(model, x_range, y_range, factor)
155168
elif mode == "integrate":
156-
if isinstance(model, Fittable1DModel):
169+
if ndim == 1:
157170
return discretize_integrate_1D(model, x_range)
158-
if isinstance(model, Fittable2DModel):
171+
if ndim == 2:
159172
return discretize_integrate_2D(model, x_range, y_range)
160173
else:
161174
raise DiscretizationError('Invalid mode.')

0 commit comments

Comments
 (0)