Skip to content

Commit

Permalink
Removed the depreciated ExpressionTree class and associated tests.
Browse files Browse the repository at this point in the history
Removed deprecated models `MexicanHat1D` and `MexicanHat2D`.

Removed deprecated code in `~astropy/modeling/core.py`.

Removed deprecation filtering from tests.

Fixed codestyle error.

Added changelog entry.

Updated changelog entry.
  • Loading branch information
WilliamJamieson committed Jul 29, 2021
1 parent a8a4b58 commit d65d668
Show file tree
Hide file tree
Showing 8 changed files with 14 additions and 463 deletions.
52 changes: 2 additions & 50 deletions astropy/modeling/core.py
Expand Up @@ -20,7 +20,6 @@
import functools
import operator
import types
import warnings

from collections import defaultdict, deque
from inspect import signature
Expand All @@ -35,7 +34,6 @@
from astropy.utils import (sharedmethod, find_current_module,
check_broadcast, IncompatibleShapeError, isiterable)
from astropy.utils.codegen import make_function_with_signature
from astropy.utils.exceptions import AstropyDeprecationWarning
from astropy.nddata.utils import add_array, extract_array
from .utils import (combine_labels, make_binary_operator_eval,
get_inputs_and_params, _BoundingBox, _combine_equivalency_dict,
Expand Down Expand Up @@ -719,19 +717,6 @@ def __init__(self, *args, meta=None, name=None, **kwargs):
self._initialize_slices()
self._initialize_unit_support()

# Raise DeprecationWarning on classes with class attributes
# ``inputs`` and ``outputs``.
self._inputs_deprecation()

def _inputs_deprecation(self):
if hasattr(self.__class__, 'inputs') and isinstance(self.__class__.inputs, tuple):
warnings.warn(
f"""Class {self.__class__.__name__} defines class attributes ``inputs``.
This has been deprecated in v4.0 and support will be removed in v4.1.
Starting with v4.0 classes must define a class attribute ``n_inputs``.
Please consult the documentation for details.
""", AstropyDeprecationWarning)

def _default_inputs_outputs(self):
if self.n_inputs == 1 and self.n_outputs == 1:
self._inputs = ("x",)
Expand Down Expand Up @@ -2519,7 +2504,7 @@ class CompoundModel(Model):
to combine models is through the model operators.
'''

def __init__(self, op, left, right, name=None, inverse=None):
def __init__(self, op, left, right, name=None):
self.__dict__['_param_names'] = None
self._n_submodels = None
self.op = op
Expand All @@ -2533,14 +2518,6 @@ def __init__(self, op, left, right, name=None, inverse=None):
self._parameters_ = None
self._param_metrics = None

if inverse:
warnings.warn(
"The 'inverse' argument is deprecated. Instead, set the inverse "
"property after CompoundModel is initialized.",
AstropyDeprecationWarning
)
self.inverse = inverse

if op != 'fix_inputs' and len(left) != len(right):
raise ValueError(
'Both operands must have equal values for n_models')
Expand Down Expand Up @@ -2785,24 +2762,6 @@ def submodel_names(self):
newnames.append(item)
return tuple(newnames)

def both_inverses_exist(self):
'''
if both members of this compound model have inverses return True
'''
warnings.warn(
"CompoundModel.both_inverses_exist is deprecated. "
"Use has_inverse instead.",
AstropyDeprecationWarning
)

try:
linv = self.left.inverse
rinv = self.right.inverse
except NotImplementedError:
return False

return True

def __call__(self, *args, **kw):
# Turn any keyword arguments into positional arguments.
args, kw = self._get_renamed_inputs_as_positional(*args, **kw)
Expand Down Expand Up @@ -3618,7 +3577,7 @@ def fix_inputs(modelinstance, values):
return CompoundModel('fix_inputs', modelinstance, values)


def custom_model(*args, fit_deriv=None, **kwargs):
def custom_model(*args, fit_deriv=None):
"""
Create a model from a user defined function. The inputs and parameters of
the model will be inferred from the arguments of the function.
Expand Down Expand Up @@ -3689,13 +3648,6 @@ def custom_model(*args, fit_deriv=None, **kwargs):
0.3333333333333333
"""

if kwargs:
warnings.warn(
"Function received unexpected arguments ({}) these "
"are ignored but will raise an Exception in the "
"future.".format(list(kwargs)),
AstropyDeprecationWarning)

if len(args) == 1 and callable(args[0]):
return _custom_model_wrapper(args[0], fit_deriv=fit_deriv)
elif not args:
Expand Down
11 changes: 0 additions & 11 deletions astropy/modeling/functional_models.py
Expand Up @@ -6,7 +6,6 @@

from astropy import units as u
from astropy.units import Quantity, UnitsError
from astropy.utils.decorators import deprecated
from .core import (Fittable1DModel, Fittable2DModel)

from .parameters import Parameter, InputParameterError
Expand Down Expand Up @@ -2833,13 +2832,3 @@ def input_units(self):
def _parameter_units_for_data_units(self, inputs_unit, outputs_unit):
return {'tau': inputs_unit[self.inputs[0]],
'amplitude': outputs_unit[self.outputs[0]]}


@deprecated('4.0', alternative='RickerWavelet1D')
class MexicanHat1D(RickerWavelet1D):
""" Deprecated."""


@deprecated('4.0', alternative='RickerWavelet2D')
class MexicanHat2D(RickerWavelet2D):
""" Deprecated."""
3 changes: 0 additions & 3 deletions astropy/modeling/models.py
Expand Up @@ -17,9 +17,6 @@
from .tabular import *
from . import math_functions as math

# Deprecated models that are not defined in __all__
from .functional_models import MexicanHat1D, MexicanHat2D


# Attach a docstring explaining constraints to all models which support them.
# Note: add new models to this list
Expand Down
15 changes: 1 addition & 14 deletions astropy/modeling/tests/test_functional_models.py
Expand Up @@ -8,7 +8,7 @@
from astropy.modeling import models, InputParameterError
from astropy.coordinates import Angle
from astropy.modeling import fitting
from astropy.utils.exceptions import AstropyDeprecationWarning, AstropyUserWarning
from astropy.utils.exceptions import AstropyUserWarning
from astropy.utils.compat.optional_deps import HAS_SCIPY # noqa


Expand Down Expand Up @@ -346,16 +346,3 @@ def test_ExponentialAndLogarithmic1D_fit():
log_model = models.Logarithmic1D(amplitude=1, tau=1)
assert_allclose(xarr, em_model.inverse(em_model(xarr)))
assert_allclose(xarr, log_model.inverse(log_model(xarr)))


def test_deprecated_hat_kernel():

# 'MexicanHat' was deprecated as a name for the models which are now
# 'RickerWavelet'. This test ensures that the models are correctly
# deprecated.

with pytest.warns(AstropyDeprecationWarning):
models.MexicanHat1D()

with pytest.warns(AstropyDeprecationWarning):
models.MexicanHat2D()
6 changes: 1 addition & 5 deletions astropy/modeling/tests/test_quantities_model.py
Expand Up @@ -6,7 +6,6 @@

from astropy import units as u
from astropy.tests.helper import assert_quantity_allclose
from astropy.utils.exceptions import AstropyDeprecationWarning

from astropy.modeling.models import Mapping, Pix2Sky_TAN, Gaussian1D
from astropy.modeling import models
Expand Down Expand Up @@ -115,10 +114,7 @@ def _allmodels():
model = getattr(models, name)
if type(model) is _ModelMeta:
try:
with warnings.catch_warnings():
# Ignore deprecation warnings from BlackBody1D and MexicanHat
warnings.simplefilter('ignore', category=AstropyDeprecationWarning)
m = model()
m = model()
except Exception:
pass
allmodels.append(m)
Expand Down
100 changes: 0 additions & 100 deletions astropy/modeling/tests/test_utils.py
@@ -1,110 +1,10 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
# pylint: disable=invalid-name
import operator

import numpy as np
import pytest

from astropy.utils.exceptions import AstropyDeprecationWarning
from astropy.modeling.utils import ExpressionTree as ET, ellipse_extent
from astropy.modeling.models import Ellipse2D

from astropy.modeling.utils import _SpecialOperatorsDict


def test_traverse_postorder_duplicate_subtrees():
"""
Regression test for a bug in `ExpressionTree.traverse_postorder`
where given an expression like ``(1 + 2) + (1 + 2)`` where the two proper
subtrees are actually the same object.
"""
with pytest.warns(AstropyDeprecationWarning):
subtree = ET('+', ET(1), ET(2))
tree = ET('+', subtree, subtree)
traversal = [n.value for n in tree.traverse_postorder()]
assert traversal == [1, 2, '+', 1, 2, '+', '+']


def test_tree_evaluate_subexpression():
"""Test evaluating a subexpression from an expression tree."""

operators = {'+': operator.add, '-': operator.sub, '*': operator.mul,
'/': operator.truediv, '**': operator.pow}
# The full expression represented by this tree is:
# 1.0 + 2 - 3 * 4 / 5 ** 6 (= 2.999232 if you must know)
with pytest.warns(AstropyDeprecationWarning):
tree = ET('+', ET(1.0), ET('-', ET(2.0),
ET('*', ET(3.0), ET('/', ET(4.0),
ET('**', ET(5.0), ET(6.0))))))

def test_slice(start, stop, expected):
assert np.allclose(tree.evaluate(operators, start=start, stop=stop),
expected)

assert tree.evaluate(operators) == (1.0 + 2.0 - 3.0 * 4.0 / 5.0 ** 6.0)
test_slice(0, 5, (1.0 + 2.0 - 3.0 * 4.0 / 5.0))
test_slice(0, 4, (1.0 + 2.0 - 3.0 * 4.0))
test_slice(0, 3, (1.0 + 2.0 - 3.0))
test_slice(0, 2, (1.0 + 2.0))
test_slice(0, 1, 1.0)

test_slice(1, 6, (2.0 - 3.0 * 4.0 / 5.0 ** 6.0))
test_slice(1, 5, (2.0 - 3.0 * 4.0 / 5.0))
test_slice(1, 4, (2.0 - 3.0 * 4.0))
test_slice(1, 3, (2.0 - 3.0))
test_slice(1, 2, 2.0)

test_slice(2, 6, (3.0 * 4.0 / 5.0 ** 6.0))
test_slice(2, 5, (3.0 * 4.0 / 5.0))
test_slice(2, 4, (3.0 * 4.0))
test_slice(2, 3, 3.0)

test_slice(3, 6, (4.0 / 5.0 ** 6.0))
test_slice(3, 5, (4.0 / 5.0))
test_slice(3, 4, 4.0)

test_slice(4, 6, (5.0 ** 6.0))
test_slice(4, 5, 5.0)

test_slice(5, 6, 6.0)


def test_ellipse_extent():
# Test this properly bounds the ellipse

imshape = (100, 100)
coords = y, x = np.indices(imshape)

amplitude = 1
x0 = 50
y0 = 50
a = 30
b = 10
theta = np.pi / 4

model = Ellipse2D(amplitude, x0, y0, a, b, theta)

dx, dy = ellipse_extent(a, b, theta)

limits = ((y0 - dy, y0 + dy), (x0 - dx, x0 + dx))

model.bounding_box = limits

actual = model.render(coords=coords)

expected = model(x, y)

# Check that the full ellipse is captured
np.testing.assert_allclose(expected, actual, atol=0, rtol=1)

# Check the bounding_box isn't too large
limits = np.array(limits).flatten()
for i in [0, 1]:
s = actual.sum(axis=i)
diff = np.abs(limits[2 * i] - np.where(s > 0)[0][0])
assert diff < 1


def test__SpecialOperatorsDict__set_value():
key = 'test'
val = 'value'
Expand Down

0 comments on commit d65d668

Please sign in to comment.