{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Histograms\n\nHow to plot histograms with Matplotlib.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib import colors\nfrom matplotlib.ticker import PercentFormatter\n\n# Create a random number generator with a fixed seed for reproducibility\nrng = np.random.default_rng(19680801)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Generate data and plot a simple histogram\n\nTo generate a 1D histogram we only need a single vector of numbers. For a 2D\nhistogram we'll need a second vector. We'll generate both below, and show\nthe histogram for each vector.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "N_points = 100000\nn_bins = 20\n\n# Generate two normal distributions\ndist1 = rng.standard_normal(N_points)\ndist2 = 0.4 * rng.standard_normal(N_points) + 5\n\nfig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True)\n\n# We can set the number of bins with the *bins* keyword argument.\naxs[0].hist(dist1, bins=n_bins)\naxs[1].hist(dist2, bins=n_bins)\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Updating histogram colors\n\nThe histogram method returns (among other things) a ``patches`` object. This\ngives us access to the properties of the objects drawn. Using this, we can\nedit the histogram to our liking. Let's change the color of each bar\nbased on its y value.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig, axs = plt.subplots(1, 2, tight_layout=True)\n\n# N is the count in each bin, bins is the lower-limit of the bin\nN, bins, patches = axs[0].hist(dist1, bins=n_bins)\n\n# We'll color code by height, but you could use any scalar\nfracs = N / N.max()\n\n# we need to normalize the data to 0..1 for the full range of the colormap\nnorm = colors.Normalize(fracs.min(), fracs.max())\n\n# Now, we'll loop through our objects and set the color of each accordingly\nfor thisfrac, thispatch in zip(fracs, patches):\n    color = plt.colormaps[\"viridis\"](norm(thisfrac))\n    thispatch.set_facecolor(color)\n\n# We can also normalize our inputs by the total number of counts\naxs[1].hist(dist1, bins=n_bins, density=True)\n\n# Now we format the y-axis to display percentage\naxs[1].yaxis.set_major_formatter(PercentFormatter(xmax=1))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Plot a 2D histogram\n\nTo plot a 2D histogram, one only needs two vectors of the same length,\ncorresponding to each axis of the histogram.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig, ax = plt.subplots(tight_layout=True)\nhist = ax.hist2d(dist1, dist2)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Customizing your histogram\n\nCustomizing a 2D histogram is similar to the 1D case, you can control\nvisual components such as the bin size or color normalization.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig, axs = plt.subplots(3, 1, figsize=(5, 15), sharex=True, sharey=True,\n                        tight_layout=True)\n\n# We can increase the number of bins on each axis\naxs[0].hist2d(dist1, dist2, bins=40)\n\n# As well as define normalization of the colors\naxs[1].hist2d(dist1, dist2, bins=40, norm=colors.LogNorm())\n\n# We can also define custom numbers of bins for each axis\naxs[2].hist2d(dist1, dist2, bins=(80, 10), norm=colors.LogNorm())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. tags::\n\n   plot-type: histogram,\n   plot-type: histogram2d\n   domain: statistics\n   styling: color,\n   component: normalization\n   component: patch\n\n.. admonition:: References\n\n   The use of the following functions, methods, classes and modules is shown\n   in this example:\n\n   - `matplotlib.axes.Axes.hist` / `matplotlib.pyplot.hist`\n   - `matplotlib.pyplot.hist2d`\n   - `matplotlib.ticker.PercentFormatter`\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
}