diff --git a/TODO.txt b/TODO.txt index bbf248be..16a3f85f 100644 --- a/TODO.txt +++ b/TODO.txt @@ -3,6 +3,7 @@ Version 0.11 * Remove deprecated `reverse_map` parameter of `skimage.transform.warp` * Change depecrated `enforce_connectivity=False`on skimage.segmentation.slic and set it to True as default +* Remove deprecated `skimage.measure.fit.BaseModel._params` attribute Version 0.10 ------------ diff --git a/skimage/measure/fit.py b/skimage/measure/fit.py index e16cd218..ce0faf10 100644 --- a/skimage/measure/fit.py +++ b/skimage/measure/fit.py @@ -1,4 +1,5 @@ import math +import warnings import numpy as np from scipy import optimize @@ -11,7 +12,14 @@ def _check_data_dim(data, dim): class BaseModel(object): def __init__(self): - self._params = None + # keep _params for backwards compatibility + self.params_ = None + + @property + def _params(self): + warnings.warn('`_params` attribute is deprecated, ' + 'use `params_` instead.') + return self.params_ class LineModel(BaseModel): @@ -30,7 +38,7 @@ class LineModel(BaseModel): min{ sum((dist - x_i * cos(theta) + y_i * sin(theta))**2) } - The ``_params`` attribute contains the parameters in the following order:: + The ``params_`` attribute contains the parameters in the following order:: dist, theta @@ -68,7 +76,7 @@ class LineModel(BaseModel): # line always passes through mean dist = X0[0] * math.cos(theta) + X0[1] * math.sin(theta) - self._params = (dist, theta) + self.params_ = (dist, theta) def residuals(self, data): """Determine residuals of data to model. @@ -89,7 +97,7 @@ class LineModel(BaseModel): _check_data_dim(data, dim=2) - dist, theta = self._params + dist, theta = self.params_ x = data[:, 0] y = data[:, 1] @@ -114,7 +122,7 @@ class LineModel(BaseModel): """ if params is None: - params = self._params + params = self.params_ dist, theta = params return (dist - y * math.sin(theta)) / math.cos(theta) @@ -136,7 +144,7 @@ class LineModel(BaseModel): """ if params is None: - params = self._params + params = self.params_ dist, theta = params return (dist - x * math.cos(theta)) / math.sin(theta) @@ -154,7 +162,7 @@ class CircleModel(BaseModel): min{ sum((r - sqrt((x_i - xc)**2 + (y_i - yc)**2))**2) } - The ``_params`` attribute contains the parameters in the following order:: + The ``params_`` attribute contains the parameters in the following order:: xc, yc, r @@ -203,7 +211,7 @@ class CircleModel(BaseModel): params0 = (xc0, yc0, r0) params, _ = optimize.leastsq(fun, params0, Dfun=Dfun, col_deriv=True) - self._params = params + self.params_ = params def residuals(self, data): """Determine residuals of data to model. @@ -224,7 +232,7 @@ class CircleModel(BaseModel): _check_data_dim(data, dim=2) - xc, yc, r = self._params + xc, yc, r = self.params_ x = data[:, 0] y = data[:, 1] @@ -249,7 +257,7 @@ class CircleModel(BaseModel): """ if params is None: - params = self._params + params = self.params_ xc, yc, r = params x = xc + r * np.cos(t) @@ -279,7 +287,7 @@ class EllipseModel(BaseModel): Thus you have ``2 * N`` equations (x_i, y_i) for ``N + 5`` unknowns (t_i, xc, yc, a, b, theta), which gives you an effective redundancy of ``N - 5``. - The ``_params`` attribute contains the parameters in the following order:: + The ``params_`` attribute contains the parameters in the following order:: xc, yc, a, b, theta @@ -353,7 +361,7 @@ class EllipseModel(BaseModel): params, _ = optimize.leastsq(fun, params0, Dfun=Dfun, col_deriv=True) - self._params = params[:5] + self.params_ = params[:5] def residuals(self, data): """Determine residuals of data to model. @@ -374,7 +382,7 @@ class EllipseModel(BaseModel): _check_data_dim(data, dim=2) - xc, yc, a, b, theta = self._params + xc, yc, a, b, theta = self.params_ ctheta = math.cos(theta) stheta = math.sin(theta) @@ -436,7 +444,7 @@ class EllipseModel(BaseModel): """ if params is None: - params = self._params + params = self.params_ xc, yc, a, b, theta = params ct = np.cos(t) @@ -550,7 +558,7 @@ def ransac(data, model_class, min_samples, residual_threshold, >>> model = EllipseModel() >>> model.estimate(data) - >>> model._params # doctest: +SKIP + >>> model.params_ # doctest: +SKIP array([ -3.30354146e+03, -2.87791160e+03, 5.59062118e+03, 7.84365066e+00, 7.19203152e-01]) @@ -558,7 +566,7 @@ def ransac(data, model_class, min_samples, residual_threshold, Estimate ellipse model using RANSAC: >>> ransac_model, inliers = ransac(data, EllipseModel, 5, 3, max_trials=50) - >>> ransac_model._params + >>> ransac_model.params_ array([ 20.12762373, 29.73563063, 4.81499637, 10.4743584 , 0.05217117]) >>> inliers array([False, False, False, False, True, True, True, True, True, diff --git a/skimage/measure/tests/test_fit.py b/skimage/measure/tests/test_fit.py index 253ac0ea..6d191a19 100644 --- a/skimage/measure/tests/test_fit.py +++ b/skimage/measure/tests/test_fit.py @@ -10,7 +10,7 @@ def test_line_model_invalid_input(): def test_line_model_predict(): model = LineModel() - model._params = (10, 1) + model.params_ = (10, 1) x = np.arange(-10, 10) y = model.predict_y(x) assert_almost_equal(x, model.predict_x(y)) @@ -19,7 +19,7 @@ def test_line_model_predict(): def test_line_model_estimate(): # generate original data without noise model0 = LineModel() - model0._params = (10, 1) + model0.params_ = (10, 1) x0 = np.arange(-100, 100) y0 = model0.predict_y(x0) data0 = np.column_stack([x0, y0]) @@ -33,16 +33,16 @@ def test_line_model_estimate(): model_est.estimate(data) # test whether estimated parameters almost equal original parameters - assert_almost_equal(model0._params, model_est._params, 1) + assert_almost_equal(model0.params_, model_est.params_, 1) def test_line_model_residuals(): model = LineModel() - model._params = (0, 0) + model.params_ = (0, 0) assert_equal(abs(model.residuals(np.array([[0, 0]]))), 0) assert_equal(abs(model.residuals(np.array([[0, 10]]))), 0) assert_equal(abs(model.residuals(np.array([[10, 0]]))), 10) - model._params = (5, np.pi / 4) + model.params_ = (5, np.pi / 4) assert_equal(abs(model.residuals(np.array([[0, 0]]))), 5) assert_almost_equal(abs(model.residuals(np.array([[np.sqrt(50), 0]]))), 0) @@ -59,7 +59,7 @@ def test_circle_model_invalid_input(): def test_circle_model_predict(): model = CircleModel() r = 5 - model._params = (0, 0, r) + model.params_ = (0, 0, r) t = np.arange(0, 2 * np.pi, np.pi / 2) xy = np.array(((5, 0), (0, 5), (-5, 0), (0, -5))) @@ -69,7 +69,7 @@ def test_circle_model_predict(): def test_circle_model_estimate(): # generate original data without noise model0 = CircleModel() - model0._params = (10, 12, 3) + model0.params_ = (10, 12, 3) t = np.linspace(0, 2 * np.pi, 1000) data0 = model0.predict_xy(t) @@ -82,12 +82,12 @@ def test_circle_model_estimate(): model_est.estimate(data) # test whether estimated parameters almost equal original parameters - assert_almost_equal(model0._params, model_est._params, 1) + assert_almost_equal(model0.params_, model_est.params_, 1) def test_circle_model_residuals(): model = CircleModel() - model._params = (0, 0, 5) + model.params_ = (0, 0, 5) assert_almost_equal(abs(model.residuals(np.array([[5, 0]]))), 0) assert_almost_equal(abs(model.residuals(np.array([[6, 6]]))), np.sqrt(2 * 6**2) - 5) @@ -101,7 +101,7 @@ def test_ellipse_model_invalid_input(): def test_ellipse_model_predict(): model = EllipseModel() r = 5 - model._params = (0, 0, 5, 10, 0) + model.params_ = (0, 0, 5, 10, 0) t = np.arange(0, 2 * np.pi, np.pi / 2) xy = np.array(((5, 0), (0, 10), (-5, 0), (0, -10))) @@ -111,7 +111,7 @@ def test_ellipse_model_predict(): def test_ellipse_model_estimate(): # generate original data without noise model0 = EllipseModel() - model0._params = (10, 20, 15, 25, 0) + model0.params_ = (10, 20, 15, 25, 0) t = np.linspace(0, 2 * np.pi, 100) data0 = model0.predict_xy(t) @@ -124,13 +124,13 @@ def test_ellipse_model_estimate(): model_est.estimate(data) # test whether estimated parameters almost equal original parameters - assert_almost_equal(model0._params, model_est._params, 0) + assert_almost_equal(model0.params_, model_est.params_, 0) def test_ellipse_model_residuals(): model = EllipseModel() # vertical line through origin - model._params = (0, 0, 10, 5, 0) + model.params_ = (0, 0, 10, 5, 0) assert_almost_equal(abs(model.residuals(np.array([[10, 0]]))), 0) assert_almost_equal(abs(model.residuals(np.array([[0, 5]]))), 0) assert_almost_equal(abs(model.residuals(np.array([[0, 10]]))), 5) @@ -141,7 +141,7 @@ def test_ransac_shape(): # generate original data without noise model0 = CircleModel() - model0._params = (10, 12, 3) + model0.params_ = (10, 12, 3) t = np.linspace(0, 2 * np.pi, 1000) data0 = model0.predict_xy(t) @@ -155,7 +155,7 @@ def test_ransac_shape(): model_est, inliers = ransac(data0, CircleModel, 3, 5) # test whether estimated parameters equal original parameters - assert_equal(model0._params, model_est._params) + assert_equal(model0.params_, model_est.params_) for outlier in outliers: assert outlier not in inliers @@ -204,5 +204,13 @@ def test_ransac_is_model_valid(): assert_equal(inliers, None) +def test_deprecated_params_attribute(): + model = LineModel() + model.params_ = (10, 1) + x = np.arange(-10, 10) + y = model.predict_y(x) + assert_equal(model.params_, model._params) + + if __name__ == "__main__": np.testing.run_module_suite()