.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/lines_bars_and_markers/timeline.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. meta:: :keywords: codex .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_lines_bars_and_markers_timeline.py: ==================================== 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. .. GENERATED FROM PYTHON SOURCE LINES 12-55 .. code-block:: Python from datetime import datetime import matplotlib.pyplot as plt import numpy as np import matplotlib.dates as mdates try: # Try to fetch a list of Matplotlib releases and their dates # from https://api.github.com/repos/matplotlib/matplotlib/releases import json import urllib.request url = 'https://api.github.com/repos/matplotlib/matplotlib/releases' url += '?per_page=100' data = json.loads(urllib.request.urlopen(url, timeout=1).read().decode()) dates = [] releases = [] 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]) releases.append(item['tag_name'].lstrip("v")) except Exception: # In case the above fails, e.g. because of missing internet connection # use the following lists as fallback. releases = ['2.2.4', '3.0.3', '3.0.2', '3.0.1', '3.0.0', '2.2.3', '2.2.2', '2.2.1', '2.2.0', '2.1.2', '2.1.1', '2.1.0', '2.0.2', '2.0.1', '2.0.0', '1.5.3', '1.5.2', '1.5.1', '1.5.0', '1.4.3', '1.4.2', '1.4.1', '1.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'] dates = [datetime.strptime(d, "%Y-%m-%d") for d in dates] # Convert strs to dates. releases = [tuple(release.split('.')) for release in releases] # Split by component. dates, releases = zip(*sorted(zip(dates, releases))) # Sort by increasing date. .. GENERATED FROM PYTHON SOURCE LINES 56-64 Next, we'll create a stem plot with some variation in levels as to distinguish even close-by events. We add markers on the baseline for visual emphasis on the one-dimensional nature of the timeline. 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. .. GENERATED FROM PYTHON SOURCE LINES 64-118 .. code-block:: Python # Choose some nice levels: alternate meso releases between top and bottom, and # progressively shorten the stems for micro releases. levels = [] macro_meso_releases = sorted({release[:2] for release in releases}) for release in releases: macro_meso = release[:2] micro = int(release[2]) h = 1 + 0.8 * (5 - micro) level = h if macro_meso_releases.index(macro_meso) % 2 == 0 else -h levels.append(level) def is_feature(release): """Return whether a version (split into components) is a feature release.""" return release[-1] == '0' # The figure and the axes. fig, ax = plt.subplots(figsize=(8.8, 4), layout="constrained") ax.set(title="Matplotlib release dates") # The vertical stems. ax.vlines(dates, 0, levels, color=[("tab:red", 1 if is_feature(release) else .5) for release in releases]) # The baseline. ax.axhline(0, c="black") # The markers on the baseline. meso_dates = [date for date, release in zip(dates, releases) if is_feature(release)] micro_dates = [date for date, release in zip(dates, releases) if not is_feature(release)] ax.plot(micro_dates, np.zeros_like(micro_dates), "ko", mfc="white") ax.plot(meso_dates, np.zeros_like(meso_dates), "ko", mfc="tab:red") # Annotate the lines. for date, level, release in zip(dates, levels, releases): version_str = '.'.join(release) ax.annotate(version_str, xy=(date, level), xytext=(-3, np.sign(level)*3), textcoords="offset points", verticalalignment="bottom" if level > 0 else "top", weight="bold" if is_feature(release) else "normal", bbox=dict(boxstyle='square', pad=0, lw=0, fc=(1, 1, 1, 0.7))) ax.xaxis.set(major_locator=mdates.YearLocator(), major_formatter=mdates.DateFormatter("%Y")) # Remove the y-axis and some spines. ax.yaxis.set_visible(False) ax.spines[["left", "top", "right"]].set_visible(False) ax.margins(y=0.1) plt.show() .. image-sg:: /gallery/lines_bars_and_markers/images/sphx_glr_timeline_001.png :alt: Matplotlib release dates :srcset: /gallery/lines_bars_and_markers/images/sphx_glr_timeline_001.png, /gallery/lines_bars_and_markers/images/sphx_glr_timeline_001_2_00x.png 2.00x :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 119-136 .. admonition:: References The use of the following functions, methods, classes and modules is shown in this example: - `matplotlib.axes.Axes.annotate` - `matplotlib.axes.Axes.vlines` - `matplotlib.axis.Axis.set_major_locator` - `matplotlib.axis.Axis.set_major_formatter` - `matplotlib.dates.MonthLocator` - `matplotlib.dates.DateFormatter` .. tags:: component: annotate plot-type: line level: intermediate .. _sphx_glr_download_gallery_lines_bars_and_markers_timeline.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: timeline.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: timeline.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: timeline.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_