Repository: scipy/scipy
File: scipy/interpolate/tests/test_bsplines.py (Python)

Code before:
        y = np.sin(x) + np.cos(x)

        spl_0 = make_splrep(x, y, k=k, s=0, bc_type=self.bc_type)
        spl_1 = make_splrep(x, y, k=k, s=1, bc_type=self.bc_type)

        assert spl_0.c.ndim == 1
        assert spl_1.c.ndim == 1

        assert spl_0.t.shape[0] == n + 2 * k

    def test_periodic_with_periodic_data(self, xp):
        N = 10
        a, b = 0, 2*xp.pi
        x = xp.linspace(a, b, N + 1, dtype=xp.float64)    # nodes

        y = xp.cos(x)
        spl = make_splrep(x, y, s=1e-8, bc_type=self.bc_type)
        xp_assert_close(spl(x), y, atol=1e-5, rtol=1e-4)

        y = xp.sin(x) + xp.cos(x)
        spl = make_splrep(x, y, s=1e-12, bc_type=self.bc_type)
        xp_assert_close(spl(x), y, atol=1e-5, rtol=1e-6)

        y = 5*xp.sin(x) + xp.cos(x)*3
        spl = make_splrep(x, y, s=1e-8, bc_type=self.bc_type)
        xp_assert_close(spl(x), y, atol=1e-5, rtol=1e-4)

    def test_periodic_with_non_periodic_data(self):
        N = 10
        a, b = 0, 2*np.pi
        x = np.linspace(a, b, N + 1)    # nodes

        y = np.exp(x)
        with assert_raises(ValueError):
            make_splrep(x, y, s=1e-8, bc_type=self.bc_type)

    @pytest.mark.parametrize("s", [0, 1e-50])
    def test_make_splrep_periodic_m_eq_2_k_eq_1(self, s):
        # Two data points (m = 2)
        x = np.array([0.0, 1.0])
        y = np.array([5.0, 5.0])  # constant function
        w = np.array([1.0, 1.0]) if s > 0 else None

        # Degree 1 periodic spline
        spl = make_splrep(x, y, w=w, k=1, bc_type="periodic", s=s)
        tck = splrep(x, y, w=w, k=1, per=1, s=s)

        if s > 0:
            xp_assert_close(spl.t, tck[0])
        xp_assert_close(np.r_[spl.c, [0]*(spl.k+1)],
                        tck[1])

Review comment (suggestion):
this change caught my eye as well--since `splev` is marked legacy in the docs, it makes sense that we switch to the recommended direct `__call__` approach, but the reason for the change was not obvious without checking that.

Code after:
        y = np.sin(x) + np.cos(x)

        spl_0 = make_splrep(x, y, k=k, s=0, bc_type=self.bc_type)
        spl_1 = make_splrep(x, y, k=k, s=1, bc_type=self.bc_type)

        assert spl_0.c.ndim == 1
        assert spl_1.c.ndim == 1

        assert spl_0.t.shape[0] == n + 2 * k

    def test_periodic_with_periodic_data(self, xp):
        N = 10
        a, b = 0, 2*xp.pi
        x = xp.linspace(a, b, N + 1, dtype=xp.float64)    # nodes

        y = xp.cos(x)
        spl = make_splrep(x, y, s=1e-8, bc_type=self.bc_type)
        xp_assert_close(splev(x, spl), y, atol=1e-5, rtol=1e-4)

        y = xp.sin(x) + xp.cos(x)
        spl = make_splrep(x, y, s=1e-12, bc_type=self.bc_type)
        xp_assert_close(splev(x, spl), y, atol=1e-5, rtol=1e-6)

        y = 5*xp.sin(x) + xp.cos(x)*3
        spl = make_splrep(x, y, s=1e-8, bc_type=self.bc_type)
        xp_assert_close(splev(x, spl), y, atol=1e-5, rtol=1e-4)

    def test_periodic_with_non_periodic_data(self):
        N = 10
        a, b = 0, 2*np.pi
        x = np.linspace(a, b, N + 1)    # nodes

        y = np.exp(x)
        with assert_raises(ValueError):
            make_splrep(x, y, s=1e-8, bc_type=self.bc_type)

    @pytest.mark.parametrize("s", [0, 1e-50])
    def test_make_splrep_periodic_m_eq_2_k_eq_1(self, s):
        # Two data points (m = 2)
        x = np.array([0.0, 1.0])
        y = np.array([5.0, 5.0])  # constant function
        w = np.array([1.0, 1.0]) if s > 0 else None

        # Degree 1 periodic spline
        spl = make_splrep(x, y, w=w, k=1, bc_type="periodic", s=s)
        tck = splrep(x, y, w=w, k=1, per=1, s=s)

        if s > 0:
            xp_assert_close(spl.t, tck[0])
        xp_assert_close(np.r_[spl.c, [0]*(spl.k+1)],
                        tck[1])