1 Hello Python

Lets start with xkcd

From xkcd

From xkcd

Some Tips

Remember as little as possible! Instead have a few good websites (or notes) that you can access easily.

Don’t try to remember syntax. Instead try to understand how the syntax is structured (e.g. Python uses tab indentation to).

Experiment! Experiment! Experiment! Playing with the code does not cost anything. So, be curious. Go with your intuition and try things out. Things won’t work so well at the start but it will get better.

Keyboard Shortcuts makes life easy and efficient. Learn as many as you can.

Don’t work alone Learning is more fun and faster if you discuss and clarify things with a colleague.

Just learn what you need When starting programming it is better to learn the basics and just what you need to solve your problem.

Copy and edit others’ code This is the fastest way to get started. After some practice you will become more independent.

Python

What is Python?

Python is a free, high-level(i.e. more English like), highly readable programming language.

Python is an interpreted language. The latest version of the interpreter is Python 3.

There are several ways to install the Python interpreter. One of the best (and easiest) is with the Anaconda distribution.

Python instructions (code) is usually saved in a file with the extension .py and then ‘passed’ onto the Python interpreter. However, if you use the (powerful and versatile) , the file will be saved with a .ipynb extension.

Conventions

Python code is shown in a grey box like this:

print('Code is shown in a box like this')

Installing Python with Anaconda

Step 1. Visit the download page at Anaconda.
Step 2. Download and install the 64-bit Python 3 distribution suitable for your operating system.
(Windows users should run Anaconda as Administrator)

Jupyter Notebooks

There are many ways to issue commands to the Python interpreter. A is one very easy environment to write Python(or R or Julia) code.

files have the extension .ipynb

allows you to combine Markdown and Python in the same document.

have two types of cells: Markdown cells or Code cells. Both type of cells are ‘run’ by pressing SHIFT + ENTER.

Take a look at this site for some cool tricks and optimisations for these notebooks.

Colab

Colab is a (free) platform for coding in Python (and some other languages). Colab offers an environment (almost) identical to .

Some advantages of using Colab are: - Colab will allow us to use Python without having to install it on our computers. - Colab will enable us to share our code with others (just like any other Google document) - Colab does all the processing on their servers. So, it won’t tax your computer(Of course you pay the price of computations being slightly slower).

Let’s see what Colab can do by watching their introductory video.

Markdown

Markdown is a simple, but powerful language for ‘word processing’. Markdown is not only succinct and efficient but (like \(\LaTeX\)) tries to separate content from style. So, you will have less distractions and can focus on producing the content.

You can convert the content of Markdown (.md) files directly into PDF or HTML formats1. Markdown is also used in the Jupyter notebooks.

Markdown has different ‘flavours’ that have slightly different features. You can read more about it at the Wikipedia page.

Software/Platforms for Markdown

OS Example Software
iOS Werdsmith
OS X MacDown
Windows WriteMonkey
Cross platform Typora
Web based StackEdit
Dillinger
Madoko
Markdown & LaTeX Editor

A Quick Intro

2 A Simple Start

Example 1

Result

Code

  • You can have only a scatter (without error bars) by using scatter (which is commented below).
  • fmt is short for ‘format string’. This decides the shape of the data point.
  • The $…$ allows us to use (a limited set of) LaTeX commands!
from matplotlib import pyplot as plt
     
     # Some data for plotting
     x = [0, 1, 2, 3, 4, 5]
     y_1 = [0, 2, 4, 6, 8, 10]
     y_2 = [0, 4, 8, 12, 16, 20]
     err = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
     
     # Lets start plotting
     fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(5, 5))
     ax.plot(x, y_1, color='red', linestyle='dashed', label='$Y_1$ values')
     ax.errorbar(x, y_2, yerr=err, xerr=.25, color='black', fmt='o', label='$Y_2$ values')
     # ax.scatter(x, y_2, color='blue', label='$Y_2$ values')
     
     ax.set_xlabel('x-values')
     ax.set_ylabel('y-values')
     ax.set_title('X vs Y')
     ax.grid(alpha=.25)
     ax.legend(loc='upper left')
     
     plt.savefig('simple-01.png', dpi=150)
     plt.show()

Exercise 1

Problem

  1. Reproduce the plot of Example 1 in Colab by copying and pasting the code.
  2. Comment the errorbar plot to and uncomment the scatter plot.
  3. Change the following properties of the plot.
    1. Change colour of the line to green.
    2. Change the title to ‘X vs. Y and 2Y
  4. Change the colour of the grid to blue.
  5. Change the format of the saved figure to PDF.
  6. Download the saved plot into your computer.

Please spend not more that 5 minutes on this exercise.

A Solution

from matplotlib import pyplot as plt
     
     # Some data for plotting
     x = [0, 1, 2, 3, 4, 5]
     y_1 = [0, 2, 4, 6, 8, 10]
     y_2 = [0, 4, 8, 12, 16, 20]
     err = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
     
     # Lets start plotting
     fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(5, 5))
     ax.plot(x, y_1, color='green', linestyle='dashed', label='$Y_1$ values')
     ax.scatter(x, y_2, color='blue', label='$Y_2$ values')
     
     ax.set_xlabel('x-values')
     ax.set_ylabel('y-values')
     ax.set_title('X vs Y and 2Y')
     ax.grid(alpha=.25, color='blue')
     ax.legend(loc='upper left')
     
     plt.savefig('simple-01_ex-01.png', dpi=150)
     plt.show()

Result

Example 2

Result

Code

import numpy as np
     from matplotlib import pyplot as plt
     
     x = np.linspace(-np.pi, np.pi, num=100, endpoint=True)
     cos_x = np.cos(x)
     sin_x = np.sin(x)
     
     fig, axes = plt.subplots()
     axes.plot(x, sin_x, label='sin x')
     axes.plot(x, cos_x, label='cos x')
     
     axes.fill_between(x, cos_x, sin_x, where=cos_x > sin_x,
                       color='orange', alpha=.125, label='cos x > sin x')
     
     axes.fill_between(x, cos_x, sin_x, where=cos_x < sin_x,
                       color='b', alpha=.075, label='cos x < sin x')
     
     axes.set_xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi]),
     axes.set_xticklabels([r'$-\pi$', r'$-\pi/2$', r'$0$', r'$+\pi/2$', r'$+\pi$'])
     
     axes.legend()
     axes.grid(axis='x', alpha=.5)
     
     plt.savefig('simple-02.png', dpi=150)
     plt.show()

Anatomy

The various parts of a `matplotlib` figure. (From [matplotlib.org](https://matplotlib.org/))

The various parts of a matplotlib figure. (From matplotlib.org)

Note

  • matplotlib allows several syntaxes. One is referred to as the pyplot API. It is simple but can be limited.
  • The version we are using is referred to as the object-oriented API.
    It is slightly complicated but offers more flexibility and versatility than the pyplot API.
  • Just for comparison, here is the code using pyplot API format
from matplotlib import pyplot as plt
     
     # Some data for plotting
     x = [0, 1, 2, 3, 4, 5]
     y_1 = [0, 2, 4, 6, 8, 10]
     y_2 = [0, 4, 8, 12, 16, 20]
     err = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
     
     # Lets start plotting
     plt.figure(figsize=(5, 5))
     plt.plot(x, y_1, color='red', linestyle='dashed', label='$Y_1$ values')
     plt.errorbar(x, y_2, yerr=err, color='black', fmt='o', label='$Y_2$ values')
     
     plt.xlabel('x-values')
     plt.ylabel('y-values')
     plt.title('X vs Y')
     plt.grid(alpha=.25)
     plt.legend(loc='upper left')
     plt.show()

3 Styles

Matplotlib

Example

  • matplotlib comes with several predefined styles that we can apply with just a single line!
    plt.style.use('<NAME OF STYLE>')
  • Click on the ‘All Styles’ tab for all the other possible styles.
  • There is also a xkcd (xkcd.com) style! (This is activated/deactiavted by plt.xkcd(True/False).

Code

  • Note the use of the ‘bmh’ style. Uncomment the style you want to use.
from matplotlib import pyplot as plt
     
     # plt.style.use('default')
     plt.style.use('bmh')
     # plt.style.use('ggplot')
     # plt.style.use('grayscale')
     # plt.style.use('fivethirtyeight')
     # plt.xkcd()
     
     # Some data for plotting
     x = [0, 1, 2, 3, 4, 5]
     y_1 = [0, 2, 4, 6, 8, 10]
     y_2 = [0, 4, 8, 12, 16, 20]
     err = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
     
     # Lets start plotting
     fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(5, 5))
     ax.plot(x, y_1, label='$Y_1$ values')
     ax.errorbar(x, y_2, yerr=err, fmt='o', label='$Y_2$ values')
     
     ax.set_xlabel('x-values')
     ax.set_ylabel('y-values')
     ax.set_title('X vs Y')
     ax.grid(alpha=.25)
     ax.legend(loc='upper left')
     
     plt.savefig('simple-01_styled.png', dpi=150)
     plt.show()

All Styles

Seaborn

Example

  • Seaborn is a Python package that is built on top of matplotlib and allows us to do useful things with less code. The Seaborn functions are often more friendlier than juts using matplotlib.

  • Even if you do not use the functions of Seaborn you can still make your plots look nicer just by calling Seaborn!

  • Seaborn allows to adjust the styles of your plot (out of the box) in two convenient ways.

    1. Changing the style using set_theme()
    2. Specifying the context (i.e. paper, talk or poster ) using set_context()

Please visit this Seaborn help page for more information.

Code

  • Note the use of the Seaborn style and context.
from matplotlib import pyplot as plt
     import seaborn as sns
     
     # Please refer to http://seaborn.pydata.org/tutorial/aesthetics.html for
     sns.set_theme()                     # Set default Seaborn parameters
     sns.set_style('darkgrid')           # Options: darkgrid, whitegrid, dark, white, and ticks
     sns.set_context(context='talk')     # Options: paper, notebook, talk, and poster
     
     # Some data for plotting
     x = [0, 1, 2, 3, 4, 5]
     y_1 = [0, 2, 4, 6, 8, 10]
     y_2 = [0, 4, 8, 12, 16, 20]
     err = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
     
     # Lets start plotting
     fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(5, 5))
     ax.plot(x, y_1, label='$Y_1$ values')
     ax.errorbar(x, y_2, yerr=err, fmt='o', label='$Y_2$ values')
     
     ax.set_ylabel('y-values')
     ax.set_title('X vs Y')
     ax.legend(loc='upper left')
     
     plt.tight_layout()
     plt.savefig('simple-01_styled-with-sns.png', dpi=150)
     plt.show()

4 Multiple Plots

Example 1 : Columns

Result

Code

import numpy as np
     from matplotlib import pyplot as plt
     
     x = np.linspace(-np.pi, np.pi, num=100, endpoint=True)
     cos_x = np.cos(x)
     sin_x = np.sin(x)
     
     fig, axes = plt.subplots(ncols=1, nrows=2, figsize=(8, 5), sharex=True)
     
     axes[0].plot(x, sin_x, label='sin x')
     axes[0].fill_between(x, sin_x, 0, alpha=.125)
     
     axes[1].plot(x, cos_x, label='cos x', color='green')
     axes[1].fill_between(x, cos_x, 0, color='green', alpha=.125)
     
     axes[1].set_xlabel('x values')
     
     for ax in axes.flat:
         ax.legend(loc='upper left', frameon=False)
         ax.grid(axis='x', alpha=.5)
     
     plt.tight_layout()
     plt.savefig('multi-plots-01.png')
     plt.show()

Example 2: Grid

Result

Code

from matplotlib import pyplot as plt
     import numpy as np
     
     #--------- Generate cosine and sine values --------#
     x = np.linspace(-np.pi, np.pi, num=100, endpoint=True)
     cos_x = np.cos(x)
     sin_x = np.sin(x)
     fun_cos_x = np.exp(-x)*np.cos(5*x)
     fun_sin_x = np.exp(-x)*np.sin(5*x)
     
     #------------------ Plot the data -----------------#
     fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 8), sharex='col', sharey='row')
     
     # Plot 0,0 : Cosines
     axes[0, 0].plot(x, cos_x, color='r', label='cos x')
     axes[0, 0].plot(x, cos_x**2, color='grey', linestyle='--', label='cos$^2$ x')
     axes[0, 0].set_title('Cosine x & Cosine$^2$ x')
     axes[0, 0].set_xlim(-np.pi, np.pi)
     axes[0, 0].legend(loc='lower center', frameon=False)
     
     # Plot 0,1 : Sine
     axes[0, 1].plot(x, sin_x, color='g', label='sin x')
     axes[0, 1].plot(x, sin_x**2, color='grey', linestyle='--', label='sin$^2$ x')
     axes[0, 1].set_title('Sin x & Sin$^2$ x')
     axes[0, 1].set_ylim(-1.25, 1.25)
     axes[0, 1].legend(loc='lower right', frameon=False)
     
     # Plot 1,0 : Function with Cosine
     axes[1, 0].plot(x, fun_cos_x, color='r')
     axes[1, 0].fill_between(x, fun_cos_x, 0, color='r', alpha=.125)
     axes[1, 0].set_title('Function with Cosine')
     axes[1, 0].set_xlim(-np.pi, np.pi)
     
     # Plot 0,1 : Function with Sine
     axes[1, 1].plot(x, fun_sin_x, color='g')
     axes[1, 1].fill_between(x, fun_sin_x, 0, color='g', alpha=.125)
     axes[1, 1].set_title('Function with Sine')
     axes[1, 1].set_xlim(-np.pi, np.pi)
     
     
     axes[1, 0].set_xlabel('Angle (radians)')
     axes[1, 1].set_xlabel('Angle (radians)')
     
     axes[0, 0].set_ylim(-1, 1)
     axes[0, 1].set_ylim(-1, 1)
     
     axes[1, 0].set_ylim(-20, 15)
     axes[1, 1].set_ylim(-20, 15)
     
     for a in axes.flat:            # 'flat', 'opens' the 2D list into a simple 1D list
         a.grid(alpha=.5)
         a.set_xlim(-np.pi, np.pi)
     
     plt.tight_layout()
     plt.savefig('multi-plots-02.png')
     plt.show()

Example 3: Two Axes

Result

Code

from matplotlib import pyplot as plt
     import numpy as np
     
     # --------- Generate cosine and sine values --------#
     x = np.linspace(-np.pi, np.pi, num=200, endpoint=True)
     cos_x = np.cos(x)
     fun_cos_x = np.exp(-x)*np.cos(5*x)
     
     # ------------------ Plot the data -----------------#
     fig, axes = plt.subplots(figsize=(10, 5))
     
     axes.plot(x, cos_x, label='$\\cos x$', color='black', linestyle='--')
     axes.fill_between(x, cos_x, -1, alpha=.05)
     
     axes.set_xlim(-np.pi, np.pi)
     axes.set_ylim(-1, 1)
     axes.set_xlabel('Angle (radians)')
     axes.set_ylabel('$\cos (x)$', rotation=0, ha='right')
     axes.grid(alpha=.5)
     axes.legend(loc=(.825, .9), frameon=False)
     
     # Create a twin axix that shares the x-axis
     ax_twin = axes.twinx()
     ax_twin.plot(x, fun_cos_x, label='$e^{-x}\\cos (5x)$')
     ax_twin.set_ylim(-20, 15)
     ax_twin.set_ylabel('$e^{-x}\\cos (5x)$', rotation=0, ha='left')
     ax_twin.fill_between(x, fun_cos_x, -20, alpha=.1)
     ax_twin.legend(loc=(.825, .825), frameon=False)
     
     plt.tight_layout()
     plt.savefig('multi-plots-03.png')
     plt.show()

Exercise 2

Problem

Recast the plot from Example 1 so that the plots are in a single row, with a shared y axis.

Please spend not more that 10 minutes on this exercise.

A Solution

import numpy as np
     from matplotlib import pyplot as plt
     
     x = np.linspace(-np.pi, np.pi, num=100, endpoint=True)
     cos_x = np.cos(x)
     sin_x = np.sin(x)
     
     fig, axes = plt.subplots(ncols=2, nrows=1, figsize=(20, 5), sharey=True)
     
     axes[0].plot(x, sin_x, label='sin x')
     axes[0].fill_between(x, sin_x, 0, alpha=.125)
     
     axes[1].plot(x, cos_x, label='cos x', color='green')
     axes[1].fill_between(x, cos_x, 0, color='green', alpha=.125)
     
     for ax in axes.flat:
         ax.legend(loc='upper left')
         ax.grid(axis='x', alpha=.5)
         ax.set_xlabel('x values')
     
     plt.tight_layout()
     plt.savefig('multi-plots-01_ex.png')
     plt.show()

Result

Exercise 3

Problem

Please work on this in your own time at home!

The Lennard-Jones potential is a simple model for the interaction between two atoms as a function of their distance, \(r\). The potential (\(U\)) , inter-atomic force (\(F\)), depth (\(\epsilon\)) and position (\(r_0\)) of the well are given by:

\[ \begin{align*} U(r) &=\dfrac{B}{ r^{12}} − \dfrac{A}{r^{6}}\\[1em] F(r) =−\dfrac{dU}{dr} &= \dfrac{12 B}{ r^{13}} − \dfrac{6 A}{r^{7}}\\[1em] \epsilon &= -\dfrac{A^2}{4B}\\[1em] r_0 &= \left(\dfrac{2B}{A}\right)^{1/6}\\[1em] \end{align*} \]

\(A\) and \(B\) are positive constants.

For small displacements from the equilibrium inter-atomic separation (where \(F = 0\)), the potential may be approximated to the harmonic oscillator function \(V\) given by:

\[ \begin{align} V(r) &= \dfrac{1}{2}k(r-r_0)^2+ \epsilon \\[1em] \text {where}\quad k &= \left|\dfrac{d^2U}{dr^2}\right|_{r_0}= \dfrac{156 B}{ {r_0}^{14}} − \dfrac{42 A}{{r_0}^{8}} \end{align} \]

  1. Plot \(U(r)\) and \(V(r)\) for Argon atoms where \(A = 1.024 \times 10^{−23}\) J nm\(^6\) and \(B = 1.582 \times 10^{−26}\) J nm\(^{12}\).
    • Life is easier if you divide A and B by Boltzmann’s constant, \(1.381\times 10^{−23}\) JK\(^{−1}\) so as to measure \(U(r)\) in units of K.
    • Your plot should show the “interesting” part of this curve, which tends rapidly to very large values at small \(r\).
      (Hint: Start with [0.2,0.6]).
  2. On a second y-axis on the same figure, plot the inter-atomic force \(F\).

A Solution

from matplotlib import pyplot as plt
     import numpy as np
     
     my_colors = {'force': '#1b9e77', 'potential': '#d95f02', 'harmonic': '#7570b3'}
     
     # ------------------------------ Values for plotting ------------------------
     n = 1000                    # Number of points
     r_min, r_max = .3275, .8    # Plotting range
     # -------------------------- Constants for the potential --------------------
     A = 1.024E-23                     # J nm^6
     B = 1.582E-26                     # J nm^12
     
     A = A/1.381E-23                   # K nm^6
     B = B/1.381E-23                   # K nm^12
     
     r0 = (2.*B/A)**(1.0/6.0)
     eps = -1./4.*A**2./B              # Epsilon
     
     # ------------------------------- Data for plotting -------------------------
     r = np.linspace(r_min, r_max, n)               # Generate r values for plotting
     potential = B/r**12 - A/r**6                   # Calculate potential
     force = 12*B/r**13 - 6*A/r**7                  # Calculate force
     
     r_2 = np.linspace(r0 - .065, r0 + .065, n)               # Generate r values for plotting
     k = 156.*B/r0**14. - 42.*A/r0**8
     v = 1./2.*k*(r_2-r0)**2 + eps                    # Harmonic approximation
     
     # -------------------------------- Start plotting ---------------------------
     fig, axes = plt.subplots(figsize=(10, 8))
     
     axes.plot(r, potential, label='Potential $U(r)$', color=my_colors['potential'], linestyle='-')
     axes.plot(r_2, v, linestyle='--', color=my_colors['harmonic'], label='Harmonic $V(r)$')
     axes.grid(True, axis='both', alpha=.5)
     
     axes.text(0.565, -135, "Lennard-Jones Potential\nwith Harmonic Approximation",
               fontsize=16, horizontalalignment='left')
     axes.set_xlabel('Interatomic separtion (nm)')
     axes.set_ylabel('Potential(K)')
     axes.set_ylim(-150, 150)
     axes.set_xlim(.3, .8)
     axes.legend(loc='upper right', frameon=False)
     
     # Plot force
     ax_twin = axes.twinx()                          # Get a new y-axis for the force
     ax_twin.plot(r, force, label='Force', color=my_colors['force'], linestyle='-')
     ax_twin.set_ylabel('Force (N)')
     ax_twin.legend(loc=(.8, .8625), frameon=False)
     ax_twin.set_ylim(-900, 900)
     ax_twin.set_xlim(.3, .8)
     
     plt.savefig('plot-lj.png', dpi=150)
     plt.show()

Result

5 Plotting Data

Example 1

Result

Task

The files Spectrum 01 contain data from a diffraction experiment of an atomic Hydrogen lamp. The data is in the form of two columns. The first is the measured angle (in radians) and the second the measured intensity of the light (in an arbitrary unit). We expect to see the lines for red (656.3 nm) and green (434.0 nm) at angles \(\pm .473\) \(\pm0.306\) respectively.

Plot this data and indicate the position of the red and green lines.

Code

import numpy as np
     from matplotlib import pyplot as plt
     
     data = np.loadtxt('spectrum-01.txt', skiprows=2)
     angle = data[:, 0]
     intensity = data[:, 1]
     
     fig, axes = plt.subplots(figsize=(8.09, 5))
     axes.plot(angle, intensity, color='black')
     axes.fill_between(x=angle, y1=intensity, y2=0, color='k', alpha=.25)
     axes.grid(alpha=.25)
     
     axes.set_xlabel('Angle (radians)')
     axes.set_ylabel('Intensity (%)')
     axes.set_title('Source 1')
     
     ang, wavelength = 0.473, 656.3
     axes.vlines([-ang, ang], 0, 70, linestyle='--',
                 alpha=.5, color=(.5, 0, 0), label=f'{wavelength} nm')
     
     ang, wavelength = 0.306, 434.0
     axes.vlines([-ang, ang], 0, 70, linestyle='--',
                 alpha=.5, color=(0, .5, 0), label=f'{wavelength} nm')
     
     axes.legend()
     plt.savefig('data-01.png', dpi=150)
     plt.show()

Exercise 4

Problem

The sites shown below shares CO\(_2\) and temperature data from ice core measurement in Lake Vostok. Plot these to see if there is any correlation between temperature and CO\(_2\) levels.

Link
Temperature https://cdiac.ess-dive.lbl.gov/ftp/trends/temp/vostok/vostok.1999.temp.dat
CO\(_2\) https://cdiac.ess-dive.lbl.gov/ftp/trends/co2/vostok.icecore.co2

Note: - You can read the data directly by giving the url. - Remember to skiprows.

A Solution

import numpy as np
     from matplotlib import pyplot as plt
     
     plt.style.use('ggplot')
     
     src = 'https://cdiac.ess-dive.lbl.gov/ftp/trends/temp/vostok/vostok.1999.temp.dat'
     t_data = np.loadtxt(src, skiprows=59)
     t_age = t_data[:, 1]
     t_temperature = t_data[:, 3]
     
     src = 'https://cdiac.ess-dive.lbl.gov/ftp/trends/co2/vostok.icecore.co2'
     co2_data = np.loadtxt(src, skiprows=20)
     co2_age = co2_data[:, 1]
     co2_concentration = co2_data[:, 3]
     
     # Lets start plotting
     fig, (co2_ax, t_ax) = plt.subplots(nrows=2, ncols=1, sharex=True, figsize=(10, 4))
     
     co2_ax.plot(co2_age/1000, co2_concentration)
     t_ax.plot(t_age/1000, t_temperature, color='#0077BB')
     
     co2_ax.set_ylabel('CO$_2$ Concentration')
     t_ax.set_ylabel('Temperature (C)')
     t_ax.set_xlabel('Millennia before present')
     
     for ax in [co2_ax, t_ax]:
         ax.grid(alpha=.35)
         ax.set_xlim(0, 430)
     
     plt.suptitle('Vostok Ice Core Data for global CO$_2$ and Temperatures')
     fig.tight_layout(rect=[0, 0.03, 1, 0.95])
     plt.savefig('data-ex.png', dpi=150)
     plt.show()

Result

6 Core Visualisation Concepts

“The greatest value of a picture is when it forces us to notice what we never expected to see”.

—John W. Tukey, Exploratory Data Analysis

Here are a few visualisation fundamentals that you should think about. These are based in the idea presented by Alberto Cairo. “The Truthful Art: Data, Charts, and Maps for Communication”.

Desirable Charactericts of a Good Plot

  1. Truthful
  2. Functional
    • Must a clear objective or message/story that it is trying to convey to the audience.
    • Don’t use exploratory plot for explanatory presentations.
  3. Beautiful
    • Because pretty things put us in a good mood making it easier to think about the message
  4. Inspiring
    • “The purpose of visualization is insight, not pictures,”
    • Ideally lead to an ‘a-ha’ moment.

Some Practical Considerations

Types of Charts

Pre-attentive Attributes

  • Our brains have been fine tuned by evolution

    • Be aware of pre-attentive attributes.
    • Be mindful when you use colour.
  • Our minds are capacity limited: the more unnecessary stuff you add, the less we will pick up.

    • Do not be afraid of white space.
    • Maximise information density and remove clutter.
    • Make it easy; do not make your audience jump over mental obstacles (e.g. slanted text).

7 Resources

Matplotlib Documentation

Tips on using Colour

Guidelines

Following are some ‘rules’ for the sensible use of colour. They have been extracted from this article by Stephen Few.

  1. If you want different objects of the same color in a table or graph to look the same, make sure that the background—the color that surrounds them—is consistent.

  2. If you want objects in a table or graph to be easily seen, use a background color that contrasts suffi ciently with the object.

  3. Use color only when needed to serve a particular communication goal.

  4. Use different colors only when they correspond to differences of meaning in the data.

  5. Use soft, natural colors to display most information and bright and/or dark colors to highlight information that requires greater attention.

  6. When using color to encode a sequential range of quantitative values, stick with a single hue (or a small set of closely related hues) and vary intensity from pale colors for low values to increasingly darker and brighter colors for high values.

  7. Non-data components of tables and graphs should be displayed just visibly enough to perform their role, but no more so, for excessive salience could cause them to distract attention from the data.

  8. To guarantee that most people who are colorblind can distinguish groups of data that are color coded, avoid using a combination of red and green in the same display.

  9. Avoid using visual effects in graphs.

ColorBrewer

Original website: colorbrewer2.org.
Also see: Every ColorBrewer Scale

Other Tools

These are alternative tools to pick a suitable colour pallette.

Books & Articles

Author Link Comments
Fundamentals of Data Visualization Claus O. Wilke Link – Highly recommended
– Written for scientists
The Truthful Art: Data, Charts, and Maps for Communication Alberto Cairo – Highly recommended
– Has a bias towards journalism.
Storytelling with Data: A Data Visualization Guide for Business Professionals Nussbaumer KnaflicModern – Easy read
– Not for science but has useful ideas
Scientific Computing for Chemists Charles J. Weiss Link – Highly recommended

  1. Using pandoc offers even more possibilities.↩︎