{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Axes box aspect\n\nThis demo shows how to set the aspect of an Axes box directly via\n`~.Axes.set_box_aspect`. The box aspect is the ratio between Axes height\nand Axes width in physical units, independent of the data limits.\nThis is useful to e.g. produce a square plot, independent of the data it\ncontains, or to have a usual plot with the same axes dimensions next to\nan image plot with fixed (data-)aspect.\n\nThe following lists a few use cases for `~.Axes.set_box_aspect`.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## A square Axes, independent of data\n\nProduce a square Axes, no matter what the data limits are.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\nimport numpy as np\n\nfig1, ax = plt.subplots()\n\nax.set_xlim(300, 400)\nax.set_box_aspect(1)\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Shared square Axes\n\nProduce shared subplots that are squared in size.\n\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig2, (ax, ax2) = plt.subplots(ncols=2, sharey=True)\n\nax.plot([1, 5], [0, 10])\nax2.plot([100, 500], [10, 15])\n\nax.set_box_aspect(1)\nax2.set_box_aspect(1)\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Square twin Axes\n\nProduce a square Axes, with a twin Axes. The twinned Axes takes over the\nbox aspect of the parent.\n\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig3, ax = plt.subplots()\n\nax2 = ax.twinx()\n\nax.plot([0, 10])\nax2.plot([12, 10])\n\nax.set_box_aspect(1)\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Normal plot next to image\n\nWhen creating an image plot with fixed data aspect and the default\n``adjustable=\"box\"`` next to a normal plot, the Axes would be unequal in\nheight. `~.Axes.set_box_aspect` provides an easy solution to that by allowing\nto have the normal plot's Axes use the images dimensions as box aspect.\n\nThis example also shows that *constrained layout* interplays nicely with\na fixed box aspect.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig4, (ax, ax2) = plt.subplots(ncols=2, layout=\"constrained\")\n\nnp.random.seed(19680801)  # Fixing random state for reproducibility\nim = np.random.rand(16, 27)\nax.imshow(im)\n\nax2.plot([23, 45])\nax2.set_box_aspect(im.shape[0]/im.shape[1])\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Square joint/marginal plot\n\nIt may be desirable to show marginal distributions next to a plot of joint\ndata. The following creates a square plot with the box aspect of the\nmarginal Axes being equal to the width- and height-ratios of the gridspec.\nThis ensures that all Axes align perfectly, independent on the size of the\nfigure.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig5, axs = plt.subplots(2, 2, sharex=\"col\", sharey=\"row\",\n                         gridspec_kw=dict(height_ratios=[1, 3],\n                                          width_ratios=[3, 1]))\naxs[0, 1].set_visible(False)\naxs[0, 0].set_box_aspect(1/3)\naxs[1, 0].set_box_aspect(1)\naxs[1, 1].set_box_aspect(3/1)\n\nnp.random.seed(19680801)  # Fixing random state for reproducibility\nx, y = np.random.randn(2, 400) * [[.5], [180]]\naxs[1, 0].scatter(x, y)\naxs[0, 0].hist(x)\naxs[1, 1].hist(y, orientation=\"horizontal\")\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Set data aspect with box aspect\n\nWhen setting the box aspect, one may still set the data aspect as well.\nHere we create an Axes with a box twice as long as it is tall and use\nan \"equal\" data aspect for its contents, i.e. the circle actually\nstays circular.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig6, ax = plt.subplots()\n\nax.add_patch(plt.Circle((5, 3), 1))\nax.set_aspect(\"equal\", adjustable=\"datalim\")\nax.set_box_aspect(0.5)\nax.autoscale()\n\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Box aspect for many subplots\n\nIt is possible to pass the box aspect to an Axes at initialization. The\nfollowing creates a 2 by 3 subplot grid with all square Axes.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig7, axs = plt.subplots(2, 3, subplot_kw=dict(box_aspect=1),\n                         sharex=True, sharey=True, layout=\"constrained\")\n\nfor i, ax in enumerate(axs.flat):\n    ax.scatter(i % 3, -((i // 3) - 0.5)*200, c=[plt.colormaps[\"hsv\"](i / 6)], s=300)\nplt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. 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.set_box_aspect`\n\n.. tags::\n\n   component: axes\n   styling: size\n   level: beginner\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
}