{
    "nbformat": 4,
    "nbformat_minor": 5,
    "metadata": {
        "kernelspec": {
            "display_name": "Python",
            "language": "python",
            "name": "python"
        },
        "language_info": {
            "name": "python"
        }
    },
    "cells": [
        {
            "id": "1ba6f8de",
            "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": "81b84e03",
            "cell_type": "markdown",
            "source": "To demonstrate this function's usage we use a signal `x` supplied with\nSciPy (see `scipy.datasets.electrocardiogram`). Let's find all peaks (local\nmaxima) in `x` whose amplitude lies above 0.\n",
            "metadata": {}
        },
        {
            "id": "755b5999",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom scipy.datasets import electrocardiogram\nfrom scipy.signal import find_peaks\nx = electrocardiogram()[2000:4000]\npeaks, _ = find_peaks(x, height=0)\nplt.plot(x)\nplt.plot(peaks, x[peaks], \"x\")\nplt.plot(np.zeros_like(x), \"--\", color=\"gray\")\nplt.show()",
            "outputs": []
        },
        {
            "id": "ceaa80d2",
            "cell_type": "markdown",
            "source": "We can select peaks below 0 with ``height=(None, 0)`` or use arrays matching\n`x` in size to reflect a changing condition for different parts of the\nsignal.\n",
            "metadata": {}
        },
        {
            "id": "c2cb325e",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "border = np.sin(np.linspace(0, 3 * np.pi, x.size))\npeaks, _ = find_peaks(x, height=(-border, border))\nplt.plot(x)\nplt.plot(-border, \"--\", color=\"gray\")\nplt.plot(border, \":\", color=\"gray\")\nplt.plot(peaks, x[peaks], \"x\")\nplt.show()",
            "outputs": []
        },
        {
            "id": "b36063e7",
            "cell_type": "markdown",
            "source": "Another useful condition for periodic signals can be given with the\n`distance` argument. In this case, we can easily select the positions of\nQRS complexes within the electrocardiogram (ECG) by demanding a distance of\nat least 150 samples.\n",
            "metadata": {}
        },
        {
            "id": "866fb82f",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "peaks, _ = find_peaks(x, distance=150)\nnp.diff(peaks)",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "array([186, 180, 177, 171, 177, 169, 167, 164, 158, 162, 172])"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "3b8afb41",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "plt.plot(x)\nplt.plot(peaks, x[peaks], \"x\")\nplt.show()",
            "outputs": []
        },
        {
            "id": "4549d7c3",
            "cell_type": "markdown",
            "source": "Especially for noisy signals peaks can be easily grouped by their\nprominence (see `peak_prominences`). E.g., we can select all peaks except\nfor the mentioned QRS complexes by limiting the allowed prominence to 0.6.\n",
            "metadata": {}
        },
        {
            "id": "1da49f3b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "peaks, properties = find_peaks(x, prominence=(None, 0.6))\nproperties[\"prominences\"].max()",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "0.5049999999999999"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "4e58537b",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "plt.plot(x)\nplt.plot(peaks, x[peaks], \"x\")\nplt.show()",
            "outputs": []
        },
        {
            "id": "89f1f9d8",
            "cell_type": "markdown",
            "source": "And, finally, let's examine a different section of the ECG which contains\nbeat forms of different shape. To select only the atypical heart beats, we\ncombine two conditions: a minimal prominence of 1 and width of at least 20\nsamples.\n",
            "metadata": {}
        },
        {
            "id": "2bc3505f",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "x = electrocardiogram()[17000:18000]\npeaks, properties = find_peaks(x, prominence=1, width=20)\nproperties[\"prominences\"], properties[\"widths\"]",
            "outputs": [
                {
                    "output_type": "execute_result",
                    "metadata": {},
                    "data": {
                        "text/plain": "(array([1.495, 2.3  ]), array([36.93773946, 39.32723577]))"
                    },
                    "execution_count": null
                }
            ]
        },
        {
            "id": "cbdd9d7c",
            "cell_type": "code",
            "metadata": {},
            "execution_count": null,
            "source": "plt.plot(x)\nplt.plot(peaks, x[peaks], \"x\")\nplt.vlines(x=peaks, ymin=x[peaks] - properties[\"prominences\"],\n           ymax = x[peaks], color = \"C1\")\nplt.hlines(y=properties[\"width_heights\"], xmin=properties[\"left_ips\"],\n           xmax=properties[\"right_ips\"], color = \"C1\")\nplt.show()",
            "outputs": []
        }
    ]
}