{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Animated histogram\n\nUse histogram's `.BarContainer` to draw a bunch of rectangles for an animated\nhistogram.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import functools\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nimport matplotlib.animation as animation\n\n# Setting up a random number generator with a fixed state for reproducibility.\nrng = np.random.default_rng(seed=19680801)\n# Fixing bin edges.\nHIST_BINS = np.linspace(-4, 4, 100)\n\n# Histogram our data with numpy.\ndata = rng.standard_normal(1000)\nn, _ = np.histogram(data, HIST_BINS)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "To animate the histogram, we need an ``animate`` function, which generates\na random set of numbers and updates the heights of rectangles. The ``animate``\nfunction updates the `.Rectangle` patches on an instance of `.BarContainer`.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def animate(frame_number, bar_container):\n    # Simulate new data coming in.\n    data = rng.standard_normal(1000)\n    n, _ = np.histogram(data, HIST_BINS)\n    for count, rect in zip(n, bar_container.patches):\n        rect.set_height(count)\n\n    return bar_container.patches"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Using :func:`~matplotlib.pyplot.hist` allows us to get an instance of\n`.BarContainer`, which is a collection of `.Rectangle` instances.  Since\n`.FuncAnimation` will only pass the frame number parameter to the animation\nfunction, we use `functools.partial` to fix the ``bar_container`` parameter.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Output generated via `matplotlib.animation.Animation.to_jshtml`.\n\nfig, ax = plt.subplots()\n_, _, bar_container = ax.hist(data, HIST_BINS, lw=1,\n                              ec=\"yellow\", fc=\"green\", alpha=0.5)\nax.set_ylim(top=55)  # set safe limit to ensure that all data is visible.\n\nanim = functools.partial(animate, bar_container=bar_container)\nani = animation.FuncAnimation(fig, anim, 50, repeat=False, blit=True)\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. tags:: plot-type: histogram, component: animation\n\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}