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

    Click :ref:`here <sphx_glr_download_gallery_lines_bars_and_markers_timeline.py>` to download the full example code
.. rst-class:: sphx-glr-example-title

.. _sphx_glr_gallery_lines_bars_and_markers_timeline.py:


===============================================
Creating a timeline with lines, dates, and text
===============================================

How to create a simple timeline using Matplotlib release dates.

Timelines can be created with a collection of dates and text. In this example,
we show how to create a simple timeline using the dates for recent releases
of Matplotlib. First, we'll pull the data from GitHub.


.. code-block:: python


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

    try:
        # Try to fetch a list of Matplotlib releases and their dates
        # from https://api.github.com/repos/matplotlib/matplotlib/releases
        import urllib.request
        import json

        url = 'https://api.github.com/repos/matplotlib/matplotlib/releases'
        url += '?per_page=100'
        data = json.loads(urllib.request.urlopen(url, timeout=.4).read().decode())

        dates = []
        names = []
        for item in data:
            if 'rc' not in item['tag_name'] and 'b' not in item['tag_name']:
                dates.append(item['published_at'].split("T")[0])
                names.append(item['tag_name'])
        # Convert date strings (e.g. 2014-10-18) to datetime
        dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates]

    except Exception:
        # In case the above fails, e.g. because of missing internet connection
        # use the following lists as fallback.
        names = ['v2.2.4', 'v3.0.3', 'v3.0.2', 'v3.0.1', 'v3.0.0', 'v2.2.3',
                 'v2.2.2', 'v2.2.1', 'v2.2.0', 'v2.1.2', 'v2.1.1', 'v2.1.0',
                 'v2.0.2', 'v2.0.1', 'v2.0.0', 'v1.5.3', 'v1.5.2', 'v1.5.1',
                 'v1.5.0', 'v1.4.3', 'v1.4.2', 'v1.4.1', 'v1.4.0']

        dates = ['2019-02-26', '2019-02-26', '2018-11-10', '2018-11-10',
                 '2018-09-18', '2018-08-10', '2018-03-17', '2018-03-16',
                 '2018-03-06', '2018-01-18', '2017-12-10', '2017-10-07',
                 '2017-05-10', '2017-05-02', '2017-01-17', '2016-09-09',
                 '2016-07-03', '2016-01-10', '2015-10-29', '2015-02-16',
                 '2014-10-26', '2014-10-18', '2014-08-26']

        # Convert date strings (e.g. 2014-10-18) to datetime
        dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates]







Next, we'll create a `~.Axes.stem` plot with some variation in levels as to
distinguish even close-by events. In contrast to a usual stem plot, we will
shift the markers to the baseline for visual emphasis on the one-dimensional
nature of the time line.
For each event, we add a text label via `~.Axes.annotate`, which is offset
in units of points from the tip of the event line.

Note that Matplotlib will automatically plot datetime inputs.



.. code-block:: python



    # Choose some nice levels
    levels = np.tile([-5, 5, -3, 3, -1, 1],
                     int(np.ceil(len(dates)/6)))[:len(dates)]

    # Create figure and plot a stem plot with the date
    fig, ax = plt.subplots(figsize=(8.8, 4), constrained_layout=True)
    ax.set(title="Matplotlib release dates")

    markerline, stemline, baseline = ax.stem(dates, levels,
                                             linefmt="C3-", basefmt="k-",
                                             use_line_collection=True)

    plt.setp(markerline, mec="k", mfc="w", zorder=3)

    # Shift the markers to the baseline by replacing the y-data by zeros.
    markerline.set_ydata(np.zeros(len(dates)))

    # annotate lines
    vert = np.array(['top', 'bottom'])[(levels > 0).astype(int)]
    for d, l, r, va in zip(dates, levels, names, vert):
        ax.annotate(r, xy=(d, l), xytext=(-3, np.sign(l)*3),
                    textcoords="offset points", va=va, ha="right")

    # format xaxis with 4 month intervals
    ax.get_xaxis().set_major_locator(mdates.MonthLocator(interval=4))
    ax.get_xaxis().set_major_formatter(mdates.DateFormatter("%b %Y"))
    plt.setp(ax.get_xticklabels(), rotation=30, ha="right")

    # remove y axis and spines
    ax.get_yaxis().set_visible(False)
    for spine in ["left", "top", "right"]:
        ax.spines[spine].set_visible(False)

    ax.margins(y=0.1)
    plt.show()





.. image:: /gallery/lines_bars_and_markers/images/sphx_glr_timeline_001.png
    :class: sphx-glr-single-img




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

References
""""""""""

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



.. code-block:: python


    import matplotlib
    matplotlib.axes.Axes.stem
    matplotlib.axes.Axes.annotate
    matplotlib.axis.Axis.set_major_locator
    matplotlib.axis.Axis.set_major_formatter
    matplotlib.dates.MonthLocator
    matplotlib.dates.DateFormatter







.. _sphx_glr_download_gallery_lines_bars_and_markers_timeline.py:


.. only :: html

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



  .. container:: sphx-glr-download

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



  .. container:: sphx-glr-download

     :download:`Download Jupyter notebook: timeline.ipynb <timeline.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>`_
