Skip to content

Commit

Permalink
Merge pull request #12574 from tylerjereddy/treddy_152_prep
Browse files Browse the repository at this point in the history
MAINT: backports for SciPy 1.5.2
  • Loading branch information
rgommers committed Jul 18, 2020
2 parents 4251f4a + a06490f commit b08aecf
Show file tree
Hide file tree
Showing 30 changed files with 548 additions and 193 deletions.
2 changes: 1 addition & 1 deletion doc/Makefile
Expand Up @@ -101,7 +101,7 @@ upload:
# SSH must be correctly configured for this to work.
# Assumes that ``make dist`` was already run
# Example usage: ``make upload USERNAME=rgommers RELEASE=0.17.0``
ssh $(USERNAME)@new.scipy.org mkdir $(UPLOAD_DIR)
ssh $(USERNAME)@new.scipy.org mkdir -p $(UPLOAD_DIR)
scp build/dist.tar.gz $(USERNAME)@new.scipy.org:$(UPLOAD_DIR)
ssh $(USERNAME)@new.scipy.org tar xvC $(UPLOAD_DIR) \
-zf $(UPLOAD_DIR)/dist.tar.gz
Expand Down
54 changes: 54 additions & 0 deletions doc/release/1.5.2-notes.rst
Expand Up @@ -10,9 +10,63 @@ compared to 1.5.1.
Authors
=======

* Peter Bell
* Tobias Biester +
* Evgeni Burovski
* Ralf Gommers
* Sturla Molden
* Andrew Nelson
* ofirr +
* Sambit Panda
* Ilhan Polat
* Tyler Reddy
* Atsushi Sakai
* Pauli Virtanen

A total of 12 people contributed to this release.
People with a "+" by their names contributed a patch for the first time.
This list of names is automatically generated, and may not be fully complete.


Issues closed for 1.5.2
-----------------------

* `#3847 <https://github.com/scipy/scipy/issues/3847>`__: Crash of interpolate.splprep(task=-1)
* `#7395 <https://github.com/scipy/scipy/issues/7395>`__: splprep segfaults if fixed knots are specified
* `#10761 <https://github.com/scipy/scipy/issues/10761>`__: scipy.signal.convolve2d produces incorrect values for large arrays
* `#11971 <https://github.com/scipy/scipy/issues/11971>`__: DOC: search in devdocs returns wrong link
* `#12155 <https://github.com/scipy/scipy/issues/12155>`__: BUG: Fix permutation of distance matrices in scipy.stats.multiscale_graphcorr
* `#12203 <https://github.com/scipy/scipy/issues/12203>`__: Unable to install on PyPy 7.3.1 (Python 3.6.9)
* `#12316 <https://github.com/scipy/scipy/issues/12316>`__: negative scipy.spatial.distance.correlation
* `#12422 <https://github.com/scipy/scipy/issues/12422>`__: BUG: slsqp: ValueError: failed to initialize intent(inout) array...
* `#12428 <https://github.com/scipy/scipy/issues/12428>`__: stats.truncnorm.rvs() never returns a scalar in 1.5
* `#12441 <https://github.com/scipy/scipy/issues/12441>`__: eigvalsh inconsistent eigvals= subset_by_index=
* `#12445 <https://github.com/scipy/scipy/issues/12445>`__: DOC: scipy.linalg.eigh
* `#12449 <https://github.com/scipy/scipy/issues/12449>`__: Warnings are not filtered in csr_matrix.sum()
* `#12469 <https://github.com/scipy/scipy/issues/12469>`__: SciPy 1.9 exception in LSQSphereBivariateSpline
* `#12487 <https://github.com/scipy/scipy/issues/12487>`__: BUG: optimize: incorrect result from approx_fprime
* `#12493 <https://github.com/scipy/scipy/issues/12493>`__: CI: GitHub Actions for maintenance branches
* `#12533 <https://github.com/scipy/scipy/issues/12533>`__: eigh gives incorrect results

Pull requests for 1.5.2
-----------------------

* `#12156 <https://github.com/scipy/scipy/pull/12156>`__: BUG: Fix permutation of distance matrices in scipy.stats.multiscale_graphcorr
* `#12238 <https://github.com/scipy/scipy/pull/12238>`__: BUG: Use 64-bit indexing in convolve2d to avoid overflow
* `#12256 <https://github.com/scipy/scipy/pull/12256>`__: BLD: Build lsap as a single extension instead of extension +...
* `#12320 <https://github.com/scipy/scipy/pull/12320>`__: BUG: spatial: avoid returning negative correlation distance
* `#12383 <https://github.com/scipy/scipy/pull/12383>`__: ENH: Make cKDTree.tree more efficient
* `#12392 <https://github.com/scipy/scipy/pull/12392>`__: DOC: update scipy-sphinx-theme
* `#12430 <https://github.com/scipy/scipy/pull/12430>`__: BUG: truncnorm and geninvgauss never return scalars from rvs
* `#12437 <https://github.com/scipy/scipy/pull/12437>`__: BUG: optimize: cast bounds to floats in new_bounds_to_old/old_bounds_to_new
* `#12442 <https://github.com/scipy/scipy/pull/12442>`__: MAINT:linalg: Fix for input args of eigvalsh
* `#12461 <https://github.com/scipy/scipy/pull/12461>`__: MAINT: sparse: write matrix/asmatrix wrappers without warning...
* `#12478 <https://github.com/scipy/scipy/pull/12478>`__: BUG: fix array_like input defects and add tests for all functions...
* `#12488 <https://github.com/scipy/scipy/pull/12488>`__: BUG: fix approx_derivative step size. Closes #12487
* `#12500 <https://github.com/scipy/scipy/pull/12500>`__: CI: actions branch trigger fix
* `#12501 <https://github.com/scipy/scipy/pull/12501>`__: CI: actions branch trigger fix
* `#12504 <https://github.com/scipy/scipy/pull/12504>`__: BUG: cKDTreeNode use after free
* `#12529 <https://github.com/scipy/scipy/pull/12529>`__: MAINT: allow graceful docs re-upload
* `#12538 <https://github.com/scipy/scipy/pull/12538>`__: BUG:linalg: eigh type parameter handling corrected
* `#12560 <https://github.com/scipy/scipy/pull/12560>`__: MAINT: truncnorm.rvs compatibility for \`Generator\`
* `#12562 <https://github.com/scipy/scipy/pull/12562>`__: redo gh-12188: fix segfaults in splprep with fixed knots
2 changes: 1 addition & 1 deletion scipy/_build_utils/compiler_helper.py
Expand Up @@ -100,6 +100,6 @@ def set_cxx_flags_clib_hook(build_clib, build_info):
new_args.append(min_macos_flag)
new_link_args.append(min_macos_flag)

dict_append(build_info, extra_compile_args=new_args,
dict_append(build_info, extra_compiler_args=new_args,
extra_link_args=new_link_args)

18 changes: 14 additions & 4 deletions scipy/interpolate/fitpack2.py
Expand Up @@ -1424,13 +1424,17 @@ class SmoothSphereBivariateSpline(SphereBivariateSpline):

def __init__(self, theta, phi, r, w=None, s=0., eps=1E-16):

theta, phi, r = np.asarray(theta), np.asarray(phi), np.asarray(r)

# input validation
if not ((0.0 <= theta).all() and (theta <= np.pi).all()):
raise ValueError('theta should be between [0, pi]')
if not ((0.0 <= phi).all() and (phi <= 2.0 * np.pi).all()):
raise ValueError('phi should be between [0, 2pi]')
if w is not None and not (w >= 0.0).all():
raise ValueError('w should be positive')
if w is not None:
w = np.asarray(w)
if not (w >= 0.0).all():
raise ValueError('w should be positive')
if not s >= 0.0:
raise ValueError('s should be positive')
if not 0.0 < eps < 1.0:
Expand Down Expand Up @@ -1538,6 +1542,9 @@ class LSQSphereBivariateSpline(SphereBivariateSpline):

def __init__(self, theta, phi, r, tt, tp, w=None, eps=1E-16):

theta, phi, r = np.asarray(theta), np.asarray(phi), np.asarray(r)
tt, tp = np.asarray(tt), np.asarray(tp)

if not ((0.0 <= theta).all() and (theta <= np.pi).all()):
raise ValueError('theta should be between [0, pi]')
if not ((0.0 <= phi).all() and (phi <= 2*np.pi).all()):
Expand All @@ -1546,8 +1553,10 @@ def __init__(self, theta, phi, r, tt, tp, w=None, eps=1E-16):
raise ValueError('tt should be between (0, pi)')
if not ((0.0 < tp).all() and (tp < 2*np.pi).all()):
raise ValueError('tp should be between (0, 2pi)')
if w is not None and not (w >= 0.0).all():
raise ValueError('w should be positive')
if w is not None:
w = np.asarray(w)
if not (w >= 0.0).all():
raise ValueError('w should be positive')
if not 0.0 < eps < 1.0:
raise ValueError('eps should be between (0, 1)')

Expand Down Expand Up @@ -1763,6 +1772,7 @@ def __init__(self, u, v, r, s=0., pole_continuity=False, pole_values=None,
ider[1], ider[3] = pole_flat

u, v = np.ravel(u), np.ravel(v)
r = np.asarray(r)

if not ((0.0 <= u).all() and (u <= np.pi).all()):
raise ValueError('u should be between [0, pi]')
Expand Down
2 changes: 1 addition & 1 deletion scipy/interpolate/src/_fitpackmodule.c
Expand Up @@ -499,7 +499,7 @@ fitpack_parcur(PyObject *dummy, PyObject *args)
if (ap_t == NULL || ap_c == NULL) {
goto fail;
}
if (iopt == 0|| n > no) {
if (iopt != 1|| n > no) {
Py_XDECREF(ap_wrk);
ap_wrk = NULL;
Py_XDECREF(ap_iwrk);
Expand Down
13 changes: 13 additions & 0 deletions scipy/interpolate/tests/test_fitpack.py
Expand Up @@ -459,6 +459,19 @@ def test_splev_der_k():
assert_allclose(splev(x, (t, c, k), k), splev(x, tck2))


def test_splprep_segfault():
# regression test for gh-3847: splprep segfaults if knots are specified
# for task=-1
t = np.arange(0, 1.1, 0.1)
x = np.sin(2*np.pi*t)
y = np.cos(2*np.pi*t)
tck, u = interpolate.splprep([x, y], s=0)
unew = np.arange(0, 1.01, 0.01)

uknots = tck[0] # using the knots from the previous fitting
tck, u = interpolate.splprep([x, y], task=-1, t=uknots) # here is the crash


def test_bisplev_integer_overflow():
np.random.seed(1)

Expand Down
116 changes: 116 additions & 0 deletions scipy/interpolate/tests/test_fitpack2.py
Expand Up @@ -309,6 +309,21 @@ def test_invalid_input_for_lsq_univariate_spline(self):
LSQUnivariateSpline(x_values, y_values, t_values, k=6)
assert "k should be 1 <= k <= 5" in str(info.value)

def test_array_like_input(self):
x_values = np.array([1, 2, 4, 6, 8.5])
y_values = np.array([0.5, 0.8, 1.3, 2.5, 2.8])
w_values = np.array([1.0, 1.0, 1.0, 1.0, 1.0])
bbox = np.array([-100, 100])
# np.array input
spl1 = UnivariateSpline(x=x_values, y=y_values, w=w_values,
bbox=bbox)
# list input
spl2 = UnivariateSpline(x=x_values.tolist(), y=y_values.tolist(),
w=w_values.tolist(), bbox=bbox.tolist())

assert_allclose(spl1([0.1, 0.5, 0.9, 0.99]),
spl2([0.1, 0.5, 0.9, 0.99]))


class TestLSQBivariateSpline(object):
# NOTE: The systems in this test class are rank-deficient
Expand Down Expand Up @@ -430,6 +445,27 @@ def test_invalid_input(self):
LSQBivariateSpline(x, y, z, tx, ty, eps=1.0)
assert "eps should be between (0, 1)" in str(exc_info.value)

def test_array_like_input(self):
s = 0.1
tx = np.array([1 + s, 3 - s])
ty = np.array([1 + s, 3 - s])
x = np.linspace(1.0, 10.0)
y = np.linspace(1.0, 10.0)
z = np.linspace(1.0, 10.0)
w = np.linspace(1.0, 10.0)
bbox = np.array([1.0, 10.0, 1.0, 10.0])

with suppress_warnings() as sup:
r = sup.record(UserWarning, "\nThe coefficients of the spline")
# np.array input
spl1 = LSQBivariateSpline(x, y, z, tx, ty, w=w, bbox=bbox)
# list input
spl2 = LSQBivariateSpline(x.tolist(), y.tolist(), z.tolist(),
tx.tolist(), ty.tolist(), w=w.tolist(),
bbox=bbox)
assert_allclose(spl1(2.0, 2.0), spl2(2.0, 2.0))
assert_equal(len(r), 2)


class TestSmoothBivariateSpline(object):
def test_linear_constant(self):
Expand Down Expand Up @@ -538,6 +574,20 @@ def test_invalid_input(self):
SmoothBivariateSpline(x, y, z, eps=1.0)
assert "eps should be between (0, 1)" in str(exc_info.value)

def test_array_like_input(self):
x = np.array([1, 1, 1, 2, 2, 2, 3, 3, 3])
y = np.array([1, 2, 3, 1, 2, 3, 1, 2, 3])
z = np.array([3, 3, 3, 3, 3, 3, 3, 3, 3])
w = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1])
bbox = np.array([1.0, 3.0, 1.0, 3.0])
# np.array input
spl1 = SmoothBivariateSpline(x, y, z, w=w, bbox=bbox, kx=1, ky=1)
# list input
spl2 = SmoothBivariateSpline(x.tolist(), y.tolist(), z.tolist(),
bbox=bbox.tolist(), w=w.tolist(),
kx=1, ky=1)
assert_allclose(spl1(0.1, 0.5), spl2(0.1, 0.5))


class TestLSQSphereBivariateSpline(object):
def setup_method(self):
Expand Down Expand Up @@ -651,6 +701,30 @@ def test_invalid_input(self):
knotst, knotsp, eps=1.0)
assert "eps should be between (0, 1)" in str(exc_info.value)

def test_array_like_input(self):
ntheta, nphi = 70, 90
theta = linspace(0.5 / (ntheta - 1), 1 - 0.5 / (ntheta - 1),
ntheta) * pi
phi = linspace(0.5 / (nphi - 1), 1 - 0.5 / (nphi - 1),
nphi) * 2. * pi
lats, lons = meshgrid(theta, phi)
data = ones((theta.shape[0], phi.shape[0]))
# define knots and extract data values at the knots
knotst = theta[::5]
knotsp = phi[::5]
w = ones((lats.ravel().shape[0]))

# np.array input
spl1 = LSQSphereBivariateSpline(lats.ravel(), lons.ravel(),
data.T.ravel(), knotst, knotsp, w=w)
# list input
spl2 = LSQSphereBivariateSpline(lats.ravel().tolist(),
lons.ravel().tolist(),
data.T.ravel().tolist(),
knotst.tolist(),
knotsp.tolist(), w=w.tolist())
assert_array_almost_equal(spl1(1.0, 1.0), spl2(1.0, 1.0))


class TestSmoothSphereBivariateSpline(object):
def setup_method(self):
Expand Down Expand Up @@ -720,6 +794,22 @@ def test_invalid_input(self):
SmoothSphereBivariateSpline(theta, phi, r, eps=1.0)
assert "eps should be between (0, 1)" in str(exc_info.value)

def test_array_like_input(self):
theta = np.array([.25 * pi, .25 * pi, .25 * pi, .5 * pi, .5 * pi,
.5 * pi, .75 * pi, .75 * pi, .75 * pi])
phi = np.array([.5 * pi, pi, 1.5 * pi, .5 * pi, pi, 1.5 * pi, .5 * pi,
pi, 1.5 * pi])
r = np.array([3, 3, 3, 3, 3, 3, 3, 3, 3])
w = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])

# np.array input
spl1 = SmoothSphereBivariateSpline(theta, phi, r, w=w, s=1E10)

# list input
spl2 = SmoothSphereBivariateSpline(theta.tolist(), phi.tolist(),
r.tolist(), w=w.tolist(), s=1E10)
assert_array_almost_equal(spl1(1.0, 1.0), spl2(1.0, 1.0))


class TestRectBivariateSpline(object):
def test_defaults(self):
Expand Down Expand Up @@ -825,6 +915,18 @@ def test_invalid_input(self):
RectBivariateSpline(x, y, z, s=-1.0)
assert "s should be s >= 0.0" in str(info.value)

def test_array_like_input(self):
x = array([1, 2, 3, 4, 5])
y = array([1, 2, 3, 4, 5])
z = array([[1, 2, 1, 2, 1], [1, 2, 1, 2, 1], [1, 2, 3, 2, 1],
[1, 2, 2, 2, 1], [1, 2, 1, 2, 1]])
bbox = array([1, 5, 1, 5])

spl1 = RectBivariateSpline(x, y, z, bbox=bbox)
spl2 = RectBivariateSpline(x.tolist(), y.tolist(), z.tolist(),
bbox=bbox.tolist())
assert_array_almost_equal(spl1(1.0, 1.0), spl2(1.0, 1.0))


class TestRectSphereBivariateSpline(object):
def test_defaults(self):
Expand Down Expand Up @@ -925,6 +1027,20 @@ def test_invalid_input(self):
RectSphereBivariateSpline(lats, lons, data, s=-1)
assert "s should be positive" in str(exc_info.value)

def test_array_like_input(self):
y = linspace(0.01, 2 * pi - 0.01, 7)
x = linspace(0.01, pi - 0.01, 7)
z = array([[1, 2, 1, 2, 1, 2, 1], [1, 2, 1, 2, 1, 2, 1],
[1, 2, 3, 2, 1, 2, 1],
[1, 2, 2, 2, 1, 2, 1], [1, 2, 1, 2, 1, 2, 1],
[1, 2, 2, 2, 1, 2, 1],
[1, 2, 1, 2, 1, 2, 1]])
# np.array input
spl1 = RectSphereBivariateSpline(x, y, z)
# list input
spl2 = RectSphereBivariateSpline(x.tolist(), y.tolist(), z.tolist())
assert_array_almost_equal(spl1(x, y), spl2(x, y))


def _numdiff_2d(func, x, y, dx=0, dy=0, eps=1e-8):
if dx == 0 and dy == 0:
Expand Down
15 changes: 9 additions & 6 deletions scipy/linalg/decomp.py
Expand Up @@ -293,7 +293,7 @@ def eigh(a, b=None, lower=True, eigvals_only=False, overwrite_a=False,
If omitted, identity matrix is assumed.
lower : bool, optional
Whether the pertinent array data is taken from the lower or upper
triangle of `a`. (Default: lower)
triangle of ``a`` and, if applicable, ``b``. (Default: lower)
eigvals_only : bool, optional
Whether to calculate only eigenvalues and no eigenvectors.
(Default: both are calculated)
Expand Down Expand Up @@ -460,8 +460,11 @@ def eigh(a, b=None, lower=True, eigvals_only=False, overwrite_a=False,
raise ValueError("wrong b dimensions {}, should "
"be {}".format(b1.shape, a1.shape))

if type not in [1, 2, 3]:
raise ValueError('"type" keyword only accepts 1, 2, and 3.')

cplx = True if iscomplexobj(b1) else (cplx or False)
drv_args.update({'overwrite_b': overwrite_b})
drv_args.update({'overwrite_b': overwrite_b, 'itype': type})

# backwards-compatibility handling
subset_by_index = subset_by_index if (eigvals is None) else eigvals
Expand Down Expand Up @@ -905,7 +908,7 @@ def eigvalsh(a, b=None, lower=True, overwrite_a=False,
If omitted, identity matrix is assumed.
lower : bool, optional
Whether the pertinent array data is taken from the lower or upper
triangle of `a`. (Default: lower)
triangle of ``a`` and, if applicable, ``b``. (Default: lower)
eigvals_only : bool, optional
Whether to calculate only eigenvalues and no eigenvectors.
(Default: both are calculated)
Expand Down Expand Up @@ -1006,9 +1009,9 @@ def eigvalsh(a, b=None, lower=True, overwrite_a=False,
"""
return eigh(a, b=b, lower=lower, eigvals_only=True,
overwrite_a=overwrite_a, overwrite_b=overwrite_b,
turbo=turbo, eigvals=None, type=type,
check_finite=check_finite, subset_by_index=eigvals,
subset_by_value=None, driver=None)
turbo=turbo, eigvals=eigvals, type=type,
check_finite=check_finite, subset_by_index=subset_by_index,
subset_by_value=subset_by_value, driver=driver)


def eigvals_banded(a_band, lower=False, overwrite_a_band=False,
Expand Down

0 comments on commit b08aecf

Please sign in to comment.