
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "gallery/subplots_axes_and_figures/secondary_axis.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        Click :ref:`here <sphx_glr_download_gallery_subplots_axes_and_figures_secondary_axis.py>`
        to download the full example code

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_gallery_subplots_axes_and_figures_secondary_axis.py:


==============
Secondary Axis
==============

Sometimes we want a secondary axis on a plot, for instance to convert
radians to degrees on the same plot.  We can do this by making a child
axes with only one axis visible via `.axes.Axes.secondary_xaxis` and
`.axes.Axes.secondary_yaxis`.  This secondary axis can have a different scale
than the main axis by providing both a forward and an inverse conversion
function in a tuple to the ``functions`` kwarg:

.. GENERATED FROM PYTHON SOURCE LINES 13-41

.. code-block:: default


    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    import matplotlib.dates as mdates
    from matplotlib.ticker import AutoMinorLocator

    fig, ax = plt.subplots(constrained_layout=True)
    x = np.arange(0, 360, 1)
    y = np.sin(2 * x * np.pi / 180)
    ax.plot(x, y)
    ax.set_xlabel('angle [degrees]')
    ax.set_ylabel('signal')
    ax.set_title('Sine wave')


    def deg2rad(x):
        return x * np.pi / 180


    def rad2deg(x):
        return x * 180 / np.pi


    secax = ax.secondary_xaxis('top', functions=(deg2rad, rad2deg))
    secax.set_xlabel('angle [rad]')
    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_001.png
    :alt: Sine wave
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 42-49

Here is the case of converting from wavenumber to wavelength in a
log-log scale.

.. note ::

  In this case, the xscale of the parent is logarithmic, so the child is
  made logarithmic as well.

.. GENERATED FROM PYTHON SOURCE LINES 49-72

.. code-block:: default


    fig, ax = plt.subplots(constrained_layout=True)
    x = np.arange(0.02, 1, 0.02)
    np.random.seed(19680801)
    y = np.random.randn(len(x)) ** 2
    ax.loglog(x, y)
    ax.set_xlabel('f [Hz]')
    ax.set_ylabel('PSD')
    ax.set_title('Random spectrum')


    def forward(x):
        return 1 / x


    def inverse(x):
        return 1 / x


    secax = ax.secondary_xaxis('top', functions=(forward, inverse))
    secax.set_xlabel('period [s]')
    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_002.png
    :alt: Random spectrum
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 73-77

Sometime we want to relate the axes in a transform that is ad-hoc from
the data, and is derived empirically.  In that case we can set the
forward and inverse transforms functions to be linear interpolations from the
one data set to the other.

.. GENERATED FROM PYTHON SOURCE LINES 77-107

.. code-block:: default


    fig, ax = plt.subplots(constrained_layout=True)
    xdata = np.arange(1, 11, 0.4)
    ydata = np.random.randn(len(xdata))
    ax.plot(xdata, ydata, label='Plotted data')

    xold = np.arange(0, 11, 0.2)
    # fake data set relating x coordinate to another data-derived coordinate.
    # xnew must be monotonic, so we sort...
    xnew = np.sort(10 * np.exp(-xold / 4) + np.random.randn(len(xold)) / 3)

    ax.plot(xold[3:], xnew[3:], label='Transform data')
    ax.set_xlabel('X [m]')
    ax.legend()


    def forward(x):
        return np.interp(x, xold, xnew)


    def inverse(x):
        return np.interp(x, xnew, xold)


    secax = ax.secondary_xaxis('top', functions=(forward, inverse))
    secax.xaxis.set_minor_locator(AutoMinorLocator())
    secax.set_xlabel('$X_{other}$')

    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_003.png
    :alt: secondary axis
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 108-112

A final example translates np.datetime64 to yearday on the x axis and
from Celsius to Fahrenheit on the y axis.  Note the addition of a
third y axis, and that it can be placed using a float for the
location argument

.. GENERATED FROM PYTHON SOURCE LINES 112-168

.. code-block:: default


    dates = [datetime.datetime(2018, 1, 1) + datetime.timedelta(hours=k * 6)
             for k in range(240)]
    temperature = np.random.randn(len(dates)) * 4 + 6.7
    fig, ax = plt.subplots(constrained_layout=True)

    ax.plot(dates, temperature)
    ax.set_ylabel(r'$T\ [^oC]$')
    plt.xticks(rotation=70)


    def date2yday(x):
        """Convert matplotlib datenum to days since 2018-01-01."""
        y = x - mdates.date2num(datetime.datetime(2018, 1, 1))
        return y


    def yday2date(x):
        """Return a matplotlib datenum for *x* days after 2018-01-01."""
        y = x + mdates.date2num(datetime.datetime(2018, 1, 1))
        return y


    secax_x = ax.secondary_xaxis('top', functions=(date2yday, yday2date))
    secax_x.set_xlabel('yday [2018]')


    def celsius_to_fahrenheit(x):
        return x * 1.8 + 32


    def fahrenheit_to_celsius(x):
        return (x - 32) / 1.8


    secax_y = ax.secondary_yaxis(
        'right', functions=(celsius_to_fahrenheit, fahrenheit_to_celsius))
    secax_y.set_ylabel(r'$T\ [^oF]$')


    def celsius_to_anomaly(x):
        return (x - np.mean(temperature))


    def anomaly_to_celsius(x):
        return (x + np.mean(temperature))


    # use of a float for the position:
    secax_y2 = ax.secondary_yaxis(
        1.2, functions=(celsius_to_anomaly, anomaly_to_celsius))
    secax_y2.set_ylabel(r'$T - \overline{T}\ [^oC]$')


    plt.show()




.. image:: /gallery/subplots_axes_and_figures/images/sphx_glr_secondary_axis_004.png
    :alt: secondary axis
    :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 169-175

------------

References
""""""""""

The use of the following functions and methods is shown in this example:

.. GENERATED FROM PYTHON SOURCE LINES 176-181

.. code-block:: default


    import matplotlib

    matplotlib.axes.Axes.secondary_xaxis
    matplotlib.axes.Axes.secondary_yaxis




.. rst-class:: sphx-glr-script-out

 Out:

 .. code-block:: none


    <function Axes.secondary_yaxis at 0x7f73be8ef4c0>




.. rst-class:: sphx-glr-timing

   **Total running time of the script:** ( 0 minutes  5.693 seconds)


.. _sphx_glr_download_gallery_subplots_axes_and_figures_secondary_axis.py:


.. only :: html

 .. container:: sphx-glr-footer
    :class: sphx-glr-footer-example



  .. container:: sphx-glr-download sphx-glr-download-python

     :download:`Download Python source code: secondary_axis.py <secondary_axis.py>`



  .. container:: sphx-glr-download sphx-glr-download-jupyter

     :download:`Download Jupyter notebook: secondary_axis.ipynb <secondary_axis.ipynb>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    Keywords: matplotlib code example, codex, python plot, pyplot
    `Gallery generated by Sphinx-Gallery
    <https://sphinx-gallery.readthedocs.io>`_
