{
    "nbformat": 4,
    "nbformat_minor": 5,
    "metadata": {
        "kernelspec": {
            "display_name": "Python",
            "language": "python",
            "name": "python"
        },
        "language_info": {
            "name": "python"
        }
    },
    "cells": [
        {
            "id": "82956ed9",
            "cell_type": "markdown",
            "source": "<div class='alert alert-warning'>\n\nSciPy's interactive examples with Jupyterlite are experimental and may not always work as expected. Execution of cells containing imports may result in large downloads (up to 60MB of content for the first import from SciPy). Load times when importing from SciPy may take roughly 10-20 seconds. If you notice any problems, feel free to open an [issue](https://github.com/scipy/scipy/issues/new/choose).\n\n</div>",
            "metadata": {}
        },
        {
            "id": "207a002a",
            "cell_type": "markdown",
            "source": "Translating the recursive definition of B-splines into Python code, we have:\n",
            "metadata": {}
        },
        {
            "id": "ef41df5b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "def B(x, k, i, t):\n   if k == 0:\n      return 1.0 if t[i] <= x < t[i+1] else 0.0\n   if t[i+k] == t[i]:\n      c1 = 0.0\n   else:\n      c1 = (x - t[i])/(t[i+k] - t[i]) * B(x, k-1, i, t)\n   if t[i+k+1] == t[i+1]:\n      c2 = 0.0\n   else:\n      c2 = (t[i+k+1] - x)/(t[i+k+1] - t[i+1]) * B(x, k-1, i+1, t)\n   return c1 + c2",
            "outputs": []
        },
        {
            "id": "c189af51",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "def bspline(x, t, c, k):\n   n = len(t) - k - 1\n   assert (n >= k+1) and (len(c) >= n)\n   return sum(c[i] * B(x, k, i, t) for i in range(n))",
            "outputs": []
        },
        {
            "id": "4e3ecba9",
            "cell_type": "markdown",
            "source": "Note that this is an inefficient (if straightforward) way to\nevaluate B-splines --- this spline class does it in an equivalent,\nbut much more efficient way.\n\nHere we construct a quadratic spline function on the base interval\n``2 <= x <= 4`` and compare with the naive way of evaluating the spline:\n",
            "metadata": {}
        },
        {
            "id": "b29f1838",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "from scipy.interpolate import BSpline\nk = 2\nt = [0, 1, 2, 3, 4, 5, 6]\nc = [-1, 2, 0, -1]\nspl = BSpline(t, c, k)\nspl(2.5)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array(1.375)"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "62bfe149",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "bspline(2.5, t, c, k)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "1.375"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "c3001b1a",
            "cell_type": "markdown",
            "source": "Note that outside of the base interval results differ. This is because\n`BSpline` extrapolates the first and last polynomial pieces of B-spline\nfunctions active on the base interval.\n",
            "metadata": {}
        },
        {
            "id": "6dcc9622",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "import matplotlib.pyplot as plt\nimport numpy as np\nfig, ax = plt.subplots()\nxx = np.linspace(1.5, 4.5, 50)\nax.plot(xx, [bspline(x, t, c ,k) for x in xx], 'r-', lw=3, label='naive')\nax.plot(xx, spl(xx), 'b-', lw=4, alpha=0.7, label='BSpline')\nax.grid(True)\nax.legend(loc='best')\nplt.show()",
            "outputs": []
        }
    ]
}