{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# ``floating_axes`` features\n\nDemonstration of features of the :mod:`.floating_axes` module:\n\n* Using `~.axes.Axes.scatter` and `~.axes.Axes.bar` with changing the shape of\n  the plot.\n* Using `~.floating_axes.GridHelperCurveLinear` to rotate the plot and set the\n  plot boundary.\n* Using `~.Figure.add_subplot` to create a subplot using the return value from\n  `~.floating_axes.GridHelperCurveLinear`.\n* Making a sector plot by adding more features to\n  `~.floating_axes.GridHelperCurveLinear`.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib.projections import PolarAxes\nfrom matplotlib.transforms import Affine2D\nimport mpl_toolkits.axisartist.angle_helper as angle_helper\nimport mpl_toolkits.axisartist.floating_axes as floating_axes\nfrom mpl_toolkits.axisartist.grid_finder import DictFormatter, FixedLocator, MaxNLocator\n\n# Fixing random state for reproducibility\nnp.random.seed(19680801)\n\n\ndef setup_axes1(fig, rect):\n    \"\"\"\n    A simple one.\n    \"\"\"\n    tr = Affine2D().scale(2, 1).rotate_deg(30)\n\n    grid_helper = floating_axes.GridHelperCurveLinear(\n        tr, extremes=(-0.5, 3.5, 0, 4),\n        grid_locator1=MaxNLocator(nbins=4),\n        grid_locator2=MaxNLocator(nbins=4))\n\n    ax1 = fig.add_subplot(\n        rect, axes_class=floating_axes.FloatingAxes, grid_helper=grid_helper)\n    ax1.grid()\n\n    aux_ax = ax1.get_aux_axes(tr)\n\n    return ax1, aux_ax\n\n\ndef setup_axes2(fig, rect):\n    \"\"\"\n    With custom locator and formatter.\n    Note that the extreme values are swapped.\n    \"\"\"\n    tr = PolarAxes.PolarTransform()\n\n    pi = np.pi\n    angle_ticks = {\n        0: r\"$0$\",\n        pi/4: r\"$\\frac{1}{4}\\pi$\",\n        pi/2: r\"$\\frac{1}{2}\\pi$\",\n    }\n    grid_helper = floating_axes.GridHelperCurveLinear(\n        tr, extremes=(.5*pi, 0, 2, 1),\n        grid_locator1=FixedLocator([*angle_ticks]),\n        tick_formatter1=DictFormatter(angle_ticks),\n        grid_locator2=MaxNLocator(2),\n        tick_formatter2=None,\n    )\n    ax1 = fig.add_subplot(\n        rect, axes_class=floating_axes.FloatingAxes, grid_helper=grid_helper)\n    ax1.grid()\n\n    # create a parasite Axes whose transData in RA, cz\n    aux_ax = ax1.get_aux_axes(tr)\n\n    aux_ax.patch = ax1.patch  # for aux_ax to have a clip path as in ax\n    ax1.patch.zorder = 0.9  # but this has a side effect that the patch is\n    # drawn twice, and possibly over some other\n    # artists. So, we decrease the zorder a bit to\n    # prevent this.\n\n    return ax1, aux_ax\n\n\ndef setup_axes3(fig, rect):\n    \"\"\"\n    Sometimes, things like axis_direction need to be adjusted.\n    \"\"\"\n\n    tr_rotate = Affine2D().translate(-95, 0)  # rotate a bit for better orientation\n    tr_scale = Affine2D().scale(np.pi/180., 1.)  # scale degree to radians\n    tr = tr_rotate + tr_scale + PolarAxes.PolarTransform()\n\n    # Specify theta limits in degrees\n    ra0, ra1 = 8.*15, 14.*15\n    # Specify radial limits\n    cz0, cz1 = 0, 14000\n\n    grid_helper = floating_axes.GridHelperCurveLinear(\n        tr, extremes=(ra0, ra1, cz0, cz1),\n        grid_locator1=angle_helper.LocatorHMS(4),\n        tick_formatter1=angle_helper.FormatterHMS(),\n        grid_locator2=MaxNLocator(3),\n        tick_formatter2=None,\n    )\n    ax1 = fig.add_subplot(\n        rect, axes_class=floating_axes.FloatingAxes, grid_helper=grid_helper)\n\n    # adjust axis\n    ax1.axis[\"left\"].set_axis_direction(\"bottom\")\n    ax1.axis[\"right\"].set_axis_direction(\"top\")\n\n    ax1.axis[\"bottom\"].set_visible(False)\n    ax1.axis[\"top\"].set_axis_direction(\"bottom\")\n    ax1.axis[\"top\"].toggle(ticklabels=True, label=True)\n    ax1.axis[\"top\"].major_ticklabels.set_axis_direction(\"top\")\n    ax1.axis[\"top\"].label.set_axis_direction(\"top\")\n\n    ax1.axis[\"left\"].label.set_text(r\"cz [km$^{-1}$]\")\n    ax1.axis[\"top\"].label.set_text(r\"$\\alpha_{1950}$\")\n    ax1.grid()\n\n    # create a parasite Axes whose transData in RA, cz\n    aux_ax = ax1.get_aux_axes(tr)\n\n    aux_ax.patch = ax1.patch  # for aux_ax to have a clip path as in ax\n    ax1.patch.zorder = 0.9  # but this has a side effect that the patch is\n    # drawn twice, and possibly over some other\n    # artists. So, we decrease the zorder a bit to\n    # prevent this.\n\n    return ax1, aux_ax"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig = plt.figure(figsize=(8, 4))\nfig.subplots_adjust(wspace=0.3, left=0.05, right=0.95)\n\nax1, aux_ax1 = setup_axes1(fig, 131)\naux_ax1.bar([0, 1, 2, 3], [3, 2, 1, 3])\n\nax2, aux_ax2 = setup_axes2(fig, 132)\ntheta = np.random.rand(10)*.5*np.pi\nradius = np.random.rand(10) + 1.\naux_ax2.scatter(theta, radius)\n\nax3, aux_ax3 = setup_axes3(fig, 133)\n\ntheta = (8 + np.random.rand(10)*(14 - 8))*15.  # in degrees\nradius = np.random.rand(10)*14000.\naux_ax3.scatter(theta, radius)\n\nplt.show()"
      ]
    }
  ],
  "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
}