{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Including upper and lower limits in error bars\n\nIn matplotlib, errors bars can have \"limits\". Applying limits to the\nerror bars essentially makes the error unidirectional. Because of that,\nupper and lower limits can be applied in both the y- and x-directions\nvia the ``uplims``, ``lolims``, ``xuplims``, and ``xlolims`` parameters,\nrespectively. These parameters can be scalar or boolean arrays.\n\nFor example, if ``xlolims`` is ``True``, the x-error bars will only\nextend from the data towards increasing values. If ``uplims`` is an\narray filled with ``False`` except for the 4th and 7th values, all of the\ny-error bars will be bidirectional, except the 4th and 7th bars, which\nwill extend from the data towards decreasing y-values.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\nimport numpy as np\n\n# example data\nx = np.array([0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0])\ny = np.exp(-x)\nxerr = 0.1\nyerr = 0.2\n\n# lower & upper limits of the error\nlolims = np.array([0, 0, 1, 0, 1, 0, 0, 0, 1, 0], dtype=bool)\nuplims = np.array([0, 1, 0, 0, 0, 1, 0, 0, 0, 1], dtype=bool)\nls = 'dotted'\n\nfig, ax = plt.subplots(figsize=(7, 4))\n\n# standard error bars\nax.errorbar(x, y, xerr=xerr, yerr=yerr, linestyle=ls)\n\n# including upper limits\nax.errorbar(x, y + 0.5, xerr=xerr, yerr=yerr, uplims=uplims,\n            linestyle=ls)\n\n# including lower limits\nax.errorbar(x, y + 1.0, xerr=xerr, yerr=yerr, lolims=lolims,\n            linestyle=ls)\n\n# including upper and lower limits\nax.errorbar(x, y + 1.5, xerr=xerr, yerr=yerr,\n            lolims=lolims, uplims=uplims,\n            marker='o', markersize=8,\n            linestyle=ls)\n\n# Plot a series with lower and upper limits in both x & y\n# constant x-error with varying y-error\nxerr = 0.2\nyerr = np.full_like(x, 0.2)\nyerr[[3, 6]] = 0.3\n\n# mock up some limits by modifying previous data\nxlolims = lolims\nxuplims = uplims\nlolims = np.zeros_like(x)\nuplims = np.zeros_like(x)\nlolims[[6]] = True  # only limited at this index\nuplims[[3]] = True  # only limited at this index\n\n# do the plotting\nax.errorbar(x, y + 2.1, xerr=xerr, yerr=yerr,\n            xlolims=xlolims, xuplims=xuplims,\n            uplims=uplims, lolims=lolims,\n            marker='o', markersize=8,\n            linestyle='none')\n\n# tidy up the figure\nax.set_xlim(0, 5.5)\nax.set_title('Errorbar upper and lower limits')\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. tags:: plot-type: errorbar, domain: statistics\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.errorbar` / `matplotlib.pyplot.errorbar`\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
}