Skip to content

Commit

Permalink
Merge pull request #12 from espdev/drop-py35
Browse files Browse the repository at this point in the history
v0.9.0

* Drop support of Python 3.5
* `weights`, `smooth` and `axis` arguments in `csaps` function are keyword-only now
* `UnivariateCubicSmoothingSpline` and `MultivariateCubicSmoothingSpline` classes are deprecated and will be removed in 1.0.0 version. Use `CubicSmoothingSpline` instead.
  • Loading branch information
espdev authored Jan 21, 2020
2 parents 40e6179 + 766735f commit b9189f3
Show file tree
Hide file tree
Showing 18 changed files with 148 additions and 90 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ language: python

matrix:
include:
- python: "3.5"
env: TOXENV=py35-pytest
- python: "3.6"
env: TOXENV=py36-pytest
- python: "3.7"
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v0.9.0

* Drop support of Python 3.5
* `weights`, `smooth` and `axis` arguments in `csaps` function are keyword-only now
* `UnivariateCubicSmoothingSpline` and `MultivariateCubicSmoothingSpline` classes are deprecated
and will be removed in 1.0.0 version. Use `CubicSmoothingSpline` instead.

## v0.8.0

* Add `csaps` function that can be used as the main API
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

## Installation

Python 3.5 or above is supported.
Python 3.6 or above is supported.

```
pip install -U csaps
Expand Down
2 changes: 2 additions & 0 deletions csaps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
)
from csaps._sspumv import (
SplinePPForm,
CubicSmoothingSpline,
UnivariateCubicSmoothingSpline,
MultivariateCubicSmoothingSpline,
)
Expand All @@ -38,6 +39,7 @@
'ISmoothingSpline',
'SplinePPForm',
'NdGridSplinePPForm',
'CubicSmoothingSpline',
'UnivariateCubicSmoothingSpline',
'MultivariateCubicSmoothingSpline',
'NdGridCubicSmoothingSpline',
Expand Down
20 changes: 9 additions & 11 deletions csaps/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import numpy as np

from csaps._types import TData, TProps, TSmooth, TXi, TSpline
from ._types import TData, TProps, TSmooth, TXi, TSpline


class SplinePPFormBase(abc.ABC, ty.Generic[TData, TProps]):
Expand Down Expand Up @@ -87,17 +87,15 @@ def evaluate(self, xi: TData) -> np.ndarray:
Interpolated/smoothed data
"""

def __repr__(self):
def __repr__(self): # pragma: no cover
return (
'{}\n'
' breaks: {}\n'
' coeffs: {} shape\n'
' pieces: {}\n'
' order: {}\n'
' ndim: {}\n'
).format(
type(self).__name__, self.breaks, self.coeffs.shape,
self.pieces, self.order, self.ndim)
f'{type(self).__name__}\n'
f' breaks: {self.breaks}\n'
f' coeffs: {self.coeffs.shape} shape\n'
f' pieces: {self.pieces}\n'
f' order: {self.order}\n'
f' ndim: {self.ndim}\n'
)


class ISmoothingSpline(abc.ABC, ty.Generic[TSpline, TSmooth, TXi]):
Expand Down
8 changes: 4 additions & 4 deletions csaps/_utils.py → csaps/_reshape.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ def to_2d(arr: np.ndarray, axis: int) -> np.ndarray:
arr = np.asarray(arr)
axis = arr.ndim + axis if axis < 0 else axis

if axis >= arr.ndim:
raise ValueError('axis {} is out of array axes {}'.format(axis, arr.ndim))
if axis >= arr.ndim: # pragma: no cover
raise ValueError(f'axis {axis} is out of array axes {arr.ndim}')

tr_axes = list(range(arr.ndim))
tr_axes.pop(axis)
Expand Down Expand Up @@ -135,8 +135,8 @@ def from_2d(arr: np.ndarray, shape: ty.Sequence[int], axis: int) -> np.ndarray:
ndim = len(shape)
axis = ndim + axis if axis < 0 else axis

if axis >= ndim:
raise ValueError('axis {} is out of N-D array axes {}'.format(axis, ndim))
if axis >= ndim: # pragma: no cover
raise ValueError(f'axis {axis} is out of N-D array axes {ndim}')

new_shape = list(shape)
new_shape.pop(axis)
Expand Down
30 changes: 18 additions & 12 deletions csaps/_shortcut.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

import numpy as np

from csaps._base import ISmoothingSpline
from csaps._sspumv import UnivariateCubicSmoothingSpline
from csaps._sspndg import ndgrid_prepare_data_sites, NdGridCubicSmoothingSpline
from csaps._types import (
from ._base import ISmoothingSpline
from ._sspumv import CubicSmoothingSpline
from ._sspndg import ndgrid_prepare_data_sites, NdGridCubicSmoothingSpline
from ._types import (
UnivariateDataType,
UnivariateVectorizedDataType,
NdGridDataType,
Expand All @@ -25,11 +25,16 @@
_WeightsDataType = Optional[Union[UnivariateDataType, NdGridDataType]]
_SmoothDataType = Optional[Union[float, Sequence[Optional[float]]]]

AutoSmoothingResult = NamedTuple('AutoSmoothingResult', [
('values', _YDataType),
('smooth', _SmoothDataType),
])
"""The result for auto smoothing for `csaps` function"""

class AutoSmoothingResult(NamedTuple):
"""The result for auto smoothing for `csaps` function"""

values: _YDataType
"""Smoothed data values"""

smooth: _SmoothDataType
"""The calculated smoothing parameter"""


_ReturnType = Union[
_YDataType,
Expand All @@ -41,6 +46,7 @@
def csaps(xdata: _XDataType,
ydata: _YDataType,
xidata: _XiDataType = None,
*,
weights: _WeightsDataType = None,
smooth: _SmoothDataType = None,
axis: Optional[int] = None) -> _ReturnType:
Expand Down Expand Up @@ -105,7 +111,7 @@ def csaps(xdata: _XDataType,
ssp_obj : ISmoothingSpline
Smoothing spline object if ``xidata`` was not set:
- :class:`UnivariateCubicSmoothingSpline` instance for univariate/multivariate data
- :class:`CubicSmoothingSpline` instance for univariate/multivariate data
- :class:`NdGridCubicSmoothingSpline` instance for nd-gridded data
Examples
Expand Down Expand Up @@ -134,7 +140,7 @@ def csaps(xdata: _XDataType,
See Also
--------
UnivariateCubicSmoothingSpline
CubicSmoothingSpline
NdGridCubicSmoothingSpline
"""
Expand All @@ -151,7 +157,7 @@ def csaps(xdata: _XDataType,

if umv:
axis = -1 if axis is None else axis
sp = UnivariateCubicSmoothingSpline(xdata, ydata, weights, smooth, axis)
sp = CubicSmoothingSpline(xdata, ydata, weights, smooth, axis)
else:
sp = NdGridCubicSmoothingSpline(xdata, ydata, weights, smooth)

Expand Down
38 changes: 16 additions & 22 deletions csaps/_sspndg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,23 @@

import numpy as np

from csaps._base import SplinePPFormBase, ISmoothingSpline
from csaps._types import UnivariateDataType, NdGridDataType
from csaps._sspumv import SplinePPForm, UnivariateCubicSmoothingSpline
from ._base import SplinePPFormBase, ISmoothingSpline
from ._types import UnivariateDataType, NdGridDataType
from ._sspumv import SplinePPForm, CubicSmoothingSpline


def ndgrid_prepare_data_sites(data, name) -> ty.Tuple[np.ndarray, ...]:
if not isinstance(data, c_abc.Sequence):
raise TypeError("'{}' must be a sequence of the vectors.".format(name))
raise TypeError(f"'{name}' must be a sequence of the vectors.")

data = list(data)

for i, di in enumerate(data):
di = np.array(di, dtype=np.float64)
if di.ndim > 1:
raise ValueError("All '{}' elements must be a vector.".format(name))
raise ValueError(f"All '{name}' elements must be a vector.")
if di.size < 2:
raise ValueError(
"'{}' must contain at least 2 data points.".format(name))
raise ValueError(f"'{name}' must contain at least 2 data points.")
data[i] = di

return tuple(data)
Expand Down Expand Up @@ -165,28 +164,24 @@ def _prepare_data(cls, xdata, ydata, weights, smooth):
data_ndim = len(xdata)

if ydata.ndim != data_ndim:
raise ValueError(
'ydata must have dimension {} according to xdata'.format(data_ndim))
raise ValueError(f'ydata must have dimension {data_ndim} according to xdata')

for yd, xs in zip(ydata.shape, map(len, xdata)):
if yd != xs:
raise ValueError(
'ydata ({}) and xdata ({}) dimension size mismatch'.format(yd, xs))
raise ValueError(f'ydata ({yd}) and xdata ({xs}) dimension size mismatch')

if not weights:
weights = [None] * data_ndim
else:
weights = ndgrid_prepare_data_sites(weights, 'weights')

if len(weights) != data_ndim:
raise ValueError(
'weights ({}) and xdata ({}) dimensions mismatch'.format(len(weights), data_ndim))
raise ValueError(f'weights ({len(weights)}) and xdata ({data_ndim}) dimensions mismatch')

for w, x in zip(weights, xdata):
if w is not None:
if w.size != x.size:
raise ValueError(
'weights ({}) and xdata ({}) dimension size mismatch'.format(w, x))
raise ValueError(f'weights ({w}) and xdata ({x}) dimension size mismatch')

if not smooth:
smooth = [None] * data_ndim
Expand All @@ -198,8 +193,8 @@ def _prepare_data(cls, xdata, ydata, weights, smooth):

if len(smooth) != data_ndim:
raise ValueError(
'Number of smoothing parameter values must be equal '
'number of dimensions ({})'.format(data_ndim))
f'Number of smoothing parameter values must '
f'be equal number of dimensions ({data_ndim})')

return xdata, ydata, weights, smooth

Expand All @@ -208,9 +203,8 @@ def __call__(self, xi: NdGridDataType) -> np.ndarray:
"""
xi = ndgrid_prepare_data_sites(xi, 'xi')

if len(xi) != self._ndim:
raise ValueError(
'xi ({}) and xdata ({}) dimensions mismatch'.format(len(xi), self._ndim))
if len(xi) != self._ndim: # pragma: no cover
raise ValueError(f'xi ({len(xi)}) and xdata ({self._ndim}) dimensions mismatch')

return self._spline.evaluate(xi)

Expand All @@ -224,8 +218,8 @@ def _make_spline(self, smooth: ty.List[ty.Optional[float]]) -> ty.Tuple[NdGridSp
shape_i = (np.prod(sizey[:-1]), sizey[-1])
ydata_i = ydata.reshape(shape_i, order='F')

s = UnivariateCubicSmoothingSpline(
self._xdata[i], ydata_i, self._weights[i], smooth[i])
s = CubicSmoothingSpline(
self._xdata[i], ydata_i, weights=self._weights[i], smooth=smooth[i])

_smooth.append(s.smooth)
sizey[-1] = s.spline.pieces * s.spline.order
Expand Down
Loading

0 comments on commit b9189f3

Please sign in to comment.