Exercises: Modularisation

Use this notebook for the practical tasks.

Before starting, ensure plot_example.py is open side-by-side with this notebook.

Setup

Important when editing modules

If you change plot_example.py while this notebook is open, you must refresh what the notebook sees.

importlib is a standard Python library module for working with imports programmatically.

importlib.reload(module_name) tells Python to re-read that module file from disk and replace the in-memory version.

You can either restart and run all cells, or reload the module in-place:

import importlib
import plot_example
importlib.reload(plot_example)

Use reload whenever you edit functions in plot_example.py and want those edits to be used immediately in this notebook session.


Exercise 1

Learning goal: implement a missing function in a module and call it from a notebook.

In plot_example.py, find the plot_uncert() function stub (currently with pass).

Use this code inside plot_uncert():

# Define upper and lower bounds of shading using the error term
y_low = y - yerr
y_high = y + yerr

# Plot the line and the shading around it
ax.plot(x, y)
ax.fill_between(x, y1=y_low, y2=y_high, alpha=0.3, label=label)

ax.legend()

Steps 1) Update plot_example.py with this implementation.

  1. Save the module, then import and run the test plot below.

  2. If your edits do not appear, run importlib.reload(plot_example) before testing.

Success check: your figure should show a line with a shaded uncertainty region around it.


Exercise 2

Learning goal: identify reusable vs dataset-specific code and wrap reusable parts in a function.

Steps 1) Recreate the matplotlib stackplot demo in the cell below: https://matplotlib.org/stable/gallery/lines_bars_and_markers/stackplot_demo.html

Consider which parts are generic and which are specific to one dataset.

  1. In plot_example.py, use the provided plot_population_stacked() stub (or create your own more generic function).
  2. Import your function and test it in this notebook.

Success check: your function plots a stackplot from inputs, rather than hard-coded values.

Questions - How could this function be improved? - How could it be made generic enough for any stackplot, not just year vs population? - Could the input structure be improved beyond a dictionary of lists?


Exercise 3

Learning goal: understand notebook module caching and verify that reload applies code edits.

Steps 1) In plot_example.py, modify time_scatter() so it accepts an optional marker argument (default '+') and uses that marker in ax.scatter(...). 2) Save plot_example.py, then reload the module in this notebook and test two different markers. 3) Briefly note what happened before and after reloading.

Success check: your plot displays different marker styles, and your notes explain why reload was needed.

Write 2-3 sentences: Why is reloading needed in notebooks when a module file changes?


Exercise 4

Learning goal: improve function robustness with validation and configurable parameters.

Steps 1) Update plot_population_stacked() so it checks that every population series has the same length as year. 2) If a mismatch is found, raise a ValueError with a clear message. 3) Add optional inputs legend_loc='upper left' and alpha=0.85, then use them in the plot. 4) Demonstrate one valid call and one invalid call (inside try/except) below.

Success check: the valid example plots correctly, and the invalid example raises your custom error message.

Exercise 5

Now you can create your own modularised plotting function. The problem you want to solve is to take input data in x and y sequences and construct a funciton that plots the data together with an arbitrary polynomial fit of specified degree. You can use numpy.polyfit() to compute the polynomial coefficients and numpy.polyval() to create a polynomial function that can be evaluated at any x value.

Steps

  1. Write the function in the notebook first, and experiment a bit
  2. Move the function to plot_example.py and test it in this notebook.
  3. Make sure that you have added suitable error handling to your function, and test that it works by calling the function with wrong inputs.
  4. Make sure that you have added a docstring to your function, and test that it is informative and clear by calling help(your_function_name).

Success check Test the function with some synthetic data.

Then test it again with a real dataset, by taking the UK time series from the Energy per person dataset from Our World in Data here below.

Solution: Plot with polynomial fit

Here’s the complete function with docstring, validation, and error handling:

Test 1: Synthetic data (with error handling)

Test 2: Error handling

Test 3: Real-world UK energy data