<jupyter_start><jupyter_text>Plotting in the scientific python ecosystemThere are a large number of plotting libraries available, but unfortunately the most commonly used, featureful, well maintained etc. is a bit low-level. Due to its ubiquity we will however focus on that one here. Namely, matplotlib. Matplotlib basicsThe basic matplotlib API is similar to MATLAB. Matplotlib also has an object-oriented interface. The different is basically that the MATLAB style interface stores some things between functions calls (hidden state, global variables) whereas with the OO interface you get back objects which you call methods on. Usually the MATLAB-style interface is sufficient.<jupyter_code>%matplotlib inline

import numpy as np
import matplotlib.pyplot as plt


x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.0)

y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)

plt.subplot(2, 1, 1)
plt.plot(x1, y1, 'o-')
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')

plt.subplot(2, 1, 2)
plt.plot(x2, y2, '.-')
plt.xlabel('time (s)')
plt.ylabel('Undamped')

plt.show()

import numpy as np
import matplotlib.pyplot as plt


x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.)

y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)

fig = plt.figure()
ax = fig.add_subplot(211)
ax.plot(x1, y1, 'o-')
ax.set_title('A tale of 2 subplots, OO style')
ax.set_ylabel('Damped oscillation')

ax = fig.add_subplot(212)
ax.plot(x2, y2, '.-')
ax.set_xlabel('time (s)')
ax.set_ylabel('Undamped')

plt.show()<jupyter_output><empty_output><jupyter_text>Pseudocolor plotsA pseudocolor plot is a plot where you want to convert a scalar value in some range into a color value. This means that you must map the range of values into a *colormap*. Things to think about when selecting a colormap:- The map should be perceptually uniform. From https://bids.github.io/colormap/ : A "perceptually uniform" colormap is one for which the "perceptual deltas" plot makes a simple horizontal line. (This is essentially the derivative of the colormap in perceptual space with respect to the data. We want our colormap to have the property that if your data goes from 0.1 to 0.2, this should create about the same perceptual change as if your data goes from 0.8 to 0.9. For color geeks: we're using CAM02-UCS as our model of perceptual distance.)- It should look good when rendered in gray-scale, e.g. if someone prints the picture on a black-and-white printer. Or sometimes per-page costs in journals are lowers if everything is BW.- It should make sense to people with the most common type of color blindness (red-green). In practice this means the color maps shouldn't use both green and red colors, so that they are not confused.**Bad news**: The commonly used rainbow (or "jet" as it's often called) is very bad when comparing against these criteria! NEVER USE IT! It was the default in matplotlib <= 1.5, and in MATLAB for a long time.**Good news**: Matplotlib >= 2.0 has sane defaults here! See https://matplotlib.org/users/dflt_style_changes.html . In particular, compare https://bids.github.io/colormap/images/screenshots/jet.png (matplotlib = 2.0 default colormap). As an aside, the 2.0 default colormap ("viridis") is similar to the default colormap in current versions of MATLAB ("parula").One case where you should NOT use parula is if your data has some "natural" zero point. In that case it's better to use a "cool-warm" style colormaps, see "Diverging Colormaps" at https://matplotlib.org/examples/color/colormaps_reference.html.<jupyter_code>%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

N = M = 200
X, Y = np.ogrid[0:20:N*1j, 0:20:M*1j]
data = np.sin(np.pi * X*2 / 20) * np.cos(np.pi * Y*2 / 20)

fig, (ax2, ax1) = plt.subplots(1, 2, figsize=(7, 3))
im = ax1.imshow(data, extent=[0, 200, 0, 200])
ax1.set_title("v2.0: 'viridis'")
fig.colorbar(im, ax=ax1, shrink=0.8)

im2 = ax2.imshow(data, extent=[0, 200, 0, 200], cmap='jet')
fig.colorbar(im2, ax=ax2, shrink=0.8)
ax2.set_title("classic: 'jet'")

fig.tight_layout()<jupyter_output><empty_output><jupyter_text>Publication-quality plots with matplotlibWhen doing plots for including in a publication, the low-level nature of matplotlib turns out to be an advantage, as you can (with some considerable amount of work!) modify the plots to look exactly like you want. Things to look out for- Using the same font for labels etc. as in the document text.- Fonts should be roughly the same size (or at least, not disproprotionately smaller/larger) as the document text.- Save your graphs in a vector graphics format such as PDF, not as a bitmap (PNG, JPEG).- Often in a publication with double columns per page, the graphs are relatively small, thus you need to make fonts, axis, tick marks etc. thicker to be legible.- If possible, graphs should be legible also when printed BW. You can set many of these by changing the `rc` parameters, or by editing the `~/.config/matplotlib/matplotlibrc` config file. For instance, [Aalto University style guidelines](https://wiki.aalto.fi/display/aaltolatex/Home)  says that dissertations written in LaTeX should use the "New Century Schoolbook" font. In that case you might want to use the LaTeX `fouriernc` package to get math fonts matching the text font. E.g. `matplotlibrc` for an Aalto dissertation written in LaTeX could have something like```font.family        : seriffont.serif         : New Century Schoolbook, Century Schoolbook, TeXGyreSchola, TeX Gyre Schola, Century Schoolbook L, Times, Times New Roman, Liberation Serif, Palatino, Bookman, Computer Modern Romanfont.sans-serif    : Helvetica, Arial, TeXGyreHeros, Liberation Sans, Avant Garde, Computer Modern Sans seriffont.cursive       : Zapf Chancery, TeXGyreChorusfont.monospace     : Courier, Liberation Mono, TeXGyreCursor, Computer Modern Typewriterps.usedistiller    : xpdfps.papersize       : a4text.usetex        : truetext.latex.unicode : truetext.latex.preamble : \usepackage{fouriernc}```See a long list of rc params at https://matplotlib.org/users/customizing.html.Note that for normal day-to-day usage you DON'T want to set usetex to true, it's very slow compared to the native rendering!Lets test fancy latex graphs:<jupyter_code>import matplotlib as mpl
mpl.rcdefaults()
mpl.rcParams['text.usetex'] = True
mpl.rcParams['text.latex.unicode'] = True
mpl.rcParams['ps.usedistiller'] = 'xpdf'
mpl.rcParams['ps.papersize'] = 'a4'
import numpy as np
import matplotlib.pyplot as plt

#mpl.rcdefaults()
x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.)

y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)

fig = plt.figure()
ax = fig.add_subplot(211)
ax.plot(x1, y1, 'o-')
ax.set_title(r'A tale of 2 subplots, OO style: $\frac{\pi}{2} \int_0^{2\pi} x^2  \mathrm{d}x$')
ax.set_ylabel('Damped oscillation')

ax = fig.add_subplot(212)
ax.plot(x2, y2, '.-')
ax.set_xlabel('time (s)')
ax.set_ylabel('Undamped')

plt.show()<jupyter_output><empty_output><jupyter_text>**Exercise**: Try to recreate the graph below:![graph](img/sin.svg)  SeabornFor statistical plotting, in particular, there exists a project called [Seaborn](https://seaborn.pydata.org/), which is built on top of matploblib, but adds plots often used in statistical data analysis.<jupyter_code>mpl.rcdefaults() # Seaborn doesn't like usetex=True?

import seaborn as sns
sns.set()

# Load the example tips dataset
iris = sns.load_dataset("iris")

# Plot tip as a function of toal bill across days
g = sns.lmplot(x="sepal_length", y="sepal_width", hue="species",
               truncate=True, size=5, data=iris)

# Use more informative axis labels than are provided by default
g.set_axis_labels("Sepal length (mm)", "Sepal width (mm)")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10640761708697889, 'fraction_numerical': 0.020586721564590838, 'mean_word_length': 4.6041816870944485, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 18, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '599889', 'license': 'CC0-1.0', 'n_tokens_mistral': 2695, 'n_tokens_neox': 2551, 'n_words': 969, 'path': 'python/09_Matplotlib.ipynb', 'repo_name': 'AaltoScienceIT/python-r-data-analysis-course', 'size': '7772'}