diff --git a/ch00git/01Intro.ipynb.py b/ch00git/01Intro.ipynb.py
index 337faa62..0e1dcdff 100644
--- a/ch00git/01Intro.ipynb.py
+++ b/ch00git/01Intro.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Introduction
+# # Introduction
# %% [markdown]
-# ### What's version control?
+# ## What's version control?
#
# Version control is a tool for __managing changes__ to a set of files.
#
@@ -28,7 +28,7 @@
# - ...
# %% [markdown]
-# ### Why use version control?
+# ## Why use version control?
#
# - Better kind of __backup__.
# - Review __history__ ("When did I introduce this bug?").
@@ -43,14 +43,14 @@
# - "How can I submit a change to someone else's code?"
# - "How can I merge my work with Sue's?"
#
-# ### Git != GitHub
+# ## Git != GitHub
#
# - __Git__: version control system tool to manage source code history.
#
# - __GitHub__: hosting service for Git repositories.
# %% [markdown]
-# ### How do we use version control?
+# ## How do we use version control?
#
# Do some programming, then commit our work:
#
@@ -65,7 +65,7 @@
# Mistake is undone.
# %% [markdown]
-# ### What is version control? (Team version)
+# ## What is version control? (Team version)
#
# Graham | Eric
# ------------------ |------
@@ -82,7 +82,7 @@
# `my_vcs commit` | ...
# %% [markdown]
-# ### Scope
+# ## Scope
#
# This course will use the `git` version control system, but much of what you learn will be valid with other version control
# tools you may encounter, including subversion (`svn`) and mercurial (`hg`).
@@ -91,28 +91,28 @@
# ## Practising with Git
# %% [markdown]
-# ### Example Exercise
+# ## Example Exercise
#
# In this course, we will use, as an example, the development of a few text files containing a description of a topic of your choice.
#
# This could be your research, a hobby, or something else. In the end, we will show you how to display the content of these files as a very simple website.
# %% [markdown]
-# ### Programming and documents
+# ## Programming and documents
#
# The purpose of this exercise is to learn how to use Git to manage program code you write, not simple text website content, but we'll just use these text files instead of code for now, so as not to confuse matters with trying to learn version control while thinking about programming too.
#
# In later parts of the course, you will use the version control tools you learn today with actual Python code.
# %% [markdown]
-# ### Markdown
+# ## Markdown
#
# The text files we create will use a simple "wiki" markup style called [markdown](http://daringfireball.net/projects/markdown/basics) to show formatting. This is the convention used in this file, too.
#
# You can view the content of this file in the way Markdown renders it by looking on the [web](https://github.com/UCL/ucl_software_carpentry/blob/master/git/git_instructions.md), and compare the [raw text](https://raw.github.com/UCL/ucl_software_carpentry/master/git/git_instructions.md).
# %% [markdown]
-# ### Displaying Text in this Tutorial
+# ## Displaying Text in this Tutorial
#
# This tutorial is based on use of the Git command line. So you'll be typing commands in the shell.
@@ -145,7 +145,7 @@
# On either Windows, Mac or Linux, we recommend [VS Code](https://code.visualstudio.com/).
# %% [markdown]
-# ### Setting up somewhere to work
+# ## Setting up somewhere to work
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# rm -rf learning_git/git_example # Just in case it's left over from a previous class; you won't need this
@@ -173,7 +173,7 @@
# %% [markdown]
# ## Solo work
#
-# ### Configuring Git with your name and email
+# ## Configuring Git with your name and email
#
# First, we should configure Git to know our name and email address:
@@ -191,7 +191,7 @@
# Historically, the default branch was named `master`. Nowadays, the community and most of the hosting sites have changed the default ([read about this change in GitHub](https://github.com/github/renaming/) and [Gitlab](https://about.gitlab.com/blog/2021/03/10/new-git-default-branch-name/).
# %% [markdown]
-# ### Initialising the repository
+# ## Initialising the repository
#
# Now, we will tell Git to track the content of this folder as a git "repository".
diff --git a/ch00git/02Solo.ipynb.py b/ch00git/02Solo.ipynb.py
index a0bec1f7..fe92f530 100644
--- a/ch00git/02Solo.ipynb.py
+++ b/ch00git/02Solo.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Solo work with Git
+# # Solo work with Git
# %% [markdown]
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
@@ -31,7 +31,7 @@
working_dir
# %% [markdown]
-# ### A first example file
+# ## A first example file
#
# So let's create an example file, and see how to start to manage a history of changes to it.
@@ -50,7 +50,7 @@
# cat index.md
# %% [markdown]
-# ### Telling Git about the File
+# ## Telling Git about the File
#
# So, let's tell Git that `index.md` is a file which is important, and we would like to keep track of its history:
@@ -60,7 +60,7 @@
# %% [markdown]
# Don't forget: Any files in repositories which you want to "track" need to be added with `git add` after you create them.
#
-# ### Our first commit
+# ## Our first commit
#
# Now, we need to tell Git to record the first version of this file in the history of changes:
@@ -73,7 +73,7 @@
# There's a lot of output there you can ignore for now.
# %% [markdown]
-# ### Configuring Git with your editor
+# ## Configuring Git with your editor
#
# If you don't type in the log message directly with -m "Some message", then an editor will pop up, to allow you
# to edit your message on the fly.
@@ -102,7 +102,7 @@
# I'm going to be using `nano` as my editor, but you can use whatever editor you prefer. Find how to setup your favourite editor in [the setup chapter of Software Carpentry's Git lesson](https://swcarpentry.github.io/git-novice/02-setup.html).
# %% [markdown]
-# ### Git log
+# ## Git log
#
# Git now has one change in its history:
@@ -113,7 +113,7 @@
# You can see the commit message, author, and date...
# %% [markdown]
-# ### Hash Codes
+# ## Hash Codes
#
# The commit "hash code", e.g.
#
@@ -124,7 +124,7 @@
# (This is a really long code, but whenever you need to use it, you can just use the first few characters, however many characters is long enough to make it unique, `c438` for example. )
# %% [markdown]
-# ### Nothing to see here
+# ## Nothing to see here
#
# Note that git will now tell us that our "working directory" is up-to-date with the repository: there are no changes to the files that aren't recorded in the repository history:
@@ -150,7 +150,7 @@
# cat index.md
# %% [markdown]
-# ### Unstaged changes
+# ## Unstaged changes
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# git status
@@ -174,7 +174,7 @@
# Deleted lines are prefixed with a minus, added lines prefixed with a plus.
# %% [markdown]
-# ### Staging a file to be included in the next commit
+# ## Staging a file to be included in the next commit
#
# To include the file in the next commit, we have a few choices. This is one of the things to be careful of with git: there are lots of ways to do similar things, and it can be hard to keep track of them all.
@@ -187,14 +187,14 @@
# Note that `git add` is the command we use to introduce git to a new file, but also the command we use to "stage" a file to be included in the next commit.
# %% [markdown]
-# ### The staging area
+# ## The staging area
#
# The "staging area" or "index" is the git jargon for the place which contains the list of changes which will be included in the next commit.
#
# You can include specific changes to specific files with `git add`, commit them, add some more files, and commit them. (You can even add specific changes within a file to be included in the index.)
# %% [markdown]
-# ### Message Sequence Charts
+# ## Message Sequence Charts
# %% [markdown]
# In order to illustrate the behaviour of Git, it will be useful to be able to generate figures in Python
@@ -237,7 +237,7 @@ def wsd(code):
wsd("Sender->Recipient: Hello\n Recipient->Sender: Message received OK")
# %% [markdown]
-# ### The Levels of Git
+# ## The Levels of Git
# %% [markdown]
# Let's make ourselves a sequence chart to show the different aspects of Git we've seen so far:
@@ -251,7 +251,7 @@ def wsd(code):
wsd(message)
# %% [markdown]
-# ### Review of status
+# ## Review of status
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# git status
@@ -266,7 +266,7 @@ def wsd(code):
# Great, we now have a file which contains a mistake.
# %% [markdown]
-# ### Carry on regardless
+# ## Carry on regardless
#
# In a while, we'll use Git to roll back to the last correct version: this is one of the main reasons we wanted to use version control, after all! But for now, let's do just as we would if we were writing code, not notice our mistake and keep working...
@@ -289,7 +289,7 @@ def wsd(code):
# cat index.md
# %% [markdown]
-# ### Review of changes
+# ## Review of changes
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# git log | head
@@ -301,7 +301,7 @@ def wsd(code):
# git log --oneline
# %% [markdown]
-# ### Git Solo Workflow
+# ## Git Solo Workflow
# %% [markdown]
# We can make a diagram that summarises the above story:
diff --git a/ch00git/03Mistakes.ipynb.py b/ch00git/03Mistakes.ipynb.py
index 59821275..0932578b 100644
--- a/ch00git/03Mistakes.ipynb.py
+++ b/ch00git/03Mistakes.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Fixing mistakes
+# # Fixing mistakes
# %% [markdown]
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
@@ -31,7 +31,7 @@
working_dir
# %% [markdown]
-# ### Referring to changes with HEAD and ^
+# ## Referring to changes with HEAD and ^
#
# The commit we want to revert to is the one before the latest.
#
@@ -40,7 +40,7 @@
# We could use the hash code (e.g. 73fbeaf) to reference this, but you can also refer to the commit before the `HEAD` as `HEAD^`, the one before that as `HEAD^^`, the one before that as `HEAD~3`.
# %% [markdown]
-# ### Reverting
+# ## Reverting
#
# Ok, so now we'd like to undo the nasty commit with the lie about Mount Fictional.
@@ -51,7 +51,7 @@
# An editor may pop up, with some default text which you can accept and save.
# %% [markdown]
-# ### Conflicted reverts
+# ## Conflicted reverts
#
# You may, depending on the changes you've tried to make, get an error message here.
#
@@ -60,7 +60,7 @@
# If that happens, you need to manually edit the file to fix the problem. Skip ahead to the section on resolving conflicts, or ask a demonstrator to help.
# %% [markdown]
-# ### Review of changes
+# ## Review of changes
#
# The file should now contain the change to the title, but not the extra line with the lie. Note the log:
@@ -68,7 +68,7 @@
# git log --date=short
# %% [markdown]
-# ### Antipatch
+# ## Antipatch
#
# Notice how the mistake has stayed in the history.
#
@@ -76,12 +76,12 @@
# This is nice: you have a record of the full story, including the mistake and its correction.
# %% [markdown]
-# ### Rewriting history
+# ## Rewriting history
#
# It is possible, in git, to remove the most recent change altogether, "rewriting history". Let's make another bad change, and see how to do this.
# %% [markdown]
-# ### A new lie
+# ## A new lie
# %% jupyter={"outputs_hidden": false}
# %%writefile index.md
@@ -106,7 +106,7 @@
# git log --date=short
# %% [markdown]
-# ### Using reset to rewrite history
+# ## Using reset to rewrite history
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# git reset HEAD^
@@ -115,12 +115,12 @@
# git log --date=short
# %% [markdown]
-# ### Covering your tracks
+# ## Covering your tracks
#
# The silly spelling *is no longer in the log*. This approach to fixing mistakes, "rewriting history" with `reset`, instead of adding an antipatch with `revert`, is dangerous, and we don't recommend it. But you may want to do it for small silly mistakes, such as to correct a commit message.
# %% [markdown]
-# ### Resetting the working area
+# ## Resetting the working area
#
# When `git reset` removes commits, it leaves your working directory unchanged -- so you can keep the work in the bad change if you want.
diff --git a/ch00git/04Publishing.ipynb.py b/ch00git/04Publishing.ipynb.py
index fe302500..989a94ce 100644
--- a/ch00git/04Publishing.ipynb.py
+++ b/ch00git/04Publishing.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Publishing
+# # Publishing
# %% [markdown]
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
@@ -31,7 +31,7 @@
working_dir
# %% [markdown]
-# ### Sharing your work
+# ## Sharing your work
# %% [markdown]
# So far, all our work has been on our own computer. But a big part of the point of version control is keeping your work safe, on remote servers. Another part is making it easy to share your work with the world In this example, we'll be using the "GitHub" cloud repository to store and publish our work.
@@ -39,14 +39,14 @@
# If you have not done so already, you should create an account on [GitHub](https://github.com/): go to [GitHub's website](https://github.com/), fill in a username and password, and click on "sign up for GitHub".
# %% [markdown]
-# ### Creating a repository
+# ## Creating a repository
#
# Ok, let's create a repository to store our work. Hit "[new repository](https://github.com/new)" on the right of the github home screen.
#
# Fill in a short name, and a description. Choose a "public" repository. Don't choose to initialize the repository with a README. That will create a repository with content and we only want a placeholder where to upload what we've created locally.
# %% [markdown]
-# ### Paying for GitHub
+# ## Paying for GitHub
#
# For this course, you should use public repositories in your personal account for your example work: it's good to share! GitHub is free for open source, but in general, charges a fee if you want to keep your work private.
#
@@ -57,7 +57,7 @@
# UCL pays for private GitHub repositories for UCL research groups: you can find the service details on the [Advanced Research Computing Centre's website](https://www.ucl.ac.uk/advanced-research-computing/expertise/research-software-development/research-software-development-tools/support-ucl-2).
# %% [markdown]
-# ### Adding a new remote to your repository
+# ## Adding a new remote to your repository
#
# Instructions will appear, once you've created the repository, as to how to add this new "remote" server to your repository, in the lower box on the screen. Mine say:
@@ -69,7 +69,7 @@
# #You should copy the instructions from YOUR repository.
# %% [markdown]
-# ### Remotes
+# ## Remotes
#
# The first command sets up the server as a new `remote`, called `origin`.
#
@@ -97,7 +97,7 @@
wsd(message)
# %% [markdown]
-# ### Playing with GitHub
+# ## Playing with GitHub
#
# Take a few moments to click around and work your way through the GitHub interface. Try clicking on 'index.md' to see the content of the file: notice how the markdown renders prettily.
#
@@ -107,7 +107,7 @@
# ## Working with multiple files
# %% [markdown]
-# ### Some new content
+# ## Some new content
#
# So far, we've only worked with one file. Let's add another:
@@ -127,7 +127,7 @@
# cat lakeland.md
# %% [markdown]
-# ### Git will not by default commit your new file
+# ## Git will not by default commit your new file
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} magic_args="--no-raise-error" language="bash"
# git commit -m "Try to add Lakeland"
@@ -136,7 +136,7 @@
# This didn't do anything, because we've not told git to track the new file yet.
# %% [markdown]
-# ### Tell git about the new file
+# ## Tell git about the new file
# %% attributes={"classes": [" Bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# git add lakeland.md
diff --git a/ch00git/05Collaboration.ipynb.py b/ch00git/05Collaboration.ipynb.py
index 224c9ecf..0f5a07d9 100644
--- a/ch00git/05Collaboration.ipynb.py
+++ b/ch00git/05Collaboration.ipynb.py
@@ -12,14 +12,14 @@
# ---
# %% [markdown]
-# ## Collaboration
+# # Collaboration
# %% [markdown]
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
# thread/process restriction), and the cells below might error out on the browser
# (jupyterlite) version of this notebook
#
-# ### Form a team
+# ## Form a team
# %% [markdown]
# Now we're going to get to the most important question of all with Git and GitHub: working with others.
@@ -27,7 +27,7 @@
# Organise into pairs. You're going to be working on the website of one of the two of you, together, so decide who is going to be the leader, and who the collaborator.
# %% [markdown]
-# ### Giving permission
+# ## Giving permission
#
# The leader needs to let the collaborator have the right to make changes to his code.
#
@@ -36,7 +36,7 @@
# Add the user name of your collaborator to the box. They now have the right to push to your repository.
# %% [markdown]
-# ### Obtaining a colleague's code
+# ## Obtaining a colleague's code
#
# Next, the collaborator needs to get a copy of the leader's code. For this example notebook,
# I'm going to be collaborating with myself, swapping between my two repositories.
@@ -78,7 +78,7 @@
# cat lakeland.md
# %% [markdown]
-# ### Nonconflicting changes
+# ## Nonconflicting changes
#
# Now, both of you should make some changes. To start with, make changes to *different* files. This will mean your work doesn't "conflict". Later, we'll see how to deal with changes to a shared file.
@@ -135,7 +135,7 @@
# git push
# %% [markdown]
-# ### Rejected push
+# ## Rejected push
# %% [markdown]
# The other should then push, but should receive an error message:
@@ -154,7 +154,7 @@
# git pull
# %% [markdown]
-# ### Merge commits
+# ## Merge commits
#
# A window may pop up with a suggested default commit message. This commit is special: it is a *merge* commit. It is a commit which combines your collaborator's work with your own.
@@ -177,7 +177,7 @@
# ls
# %% [markdown]
-# ### Nonconflicted commits to the same file
+# ## Nonconflicted commits to the same file
#
# Go through the whole process again, but this time, both of you should make changes to a single file, but make sure that you don't touch the same *line*. Again, the merge should work as before:
@@ -290,7 +290,7 @@
wsd(message)
# %% [markdown]
-# ### Conflicting commits
+# ## Conflicting commits
#
# Finally, go through the process again, but this time, make changes which touch the same line.
@@ -334,7 +334,7 @@
# git pull
# %% [markdown]
-# ### Resolving conflicts
+# ## Resolving conflicts
#
# Git couldn't work out how to merge the two different sets of changes.
#
@@ -360,7 +360,7 @@
* Fan y Big
# %% [markdown]
-# ### Commit the resolved file
+# ## Commit the resolved file
#
# Now commit the merged result:
@@ -384,7 +384,7 @@
# git log --oneline --graph
# %% [markdown]
-# ### Distributed VCS in teams with conflicts
+# ## Distributed VCS in teams with conflicts
# %% jupyter={"outputs_hidden": false}
message="""
@@ -430,7 +430,7 @@
wsd(message)
# %% [markdown]
-# ### The Levels of Git
+# ## The Levels of Git
# %% jupyter={"outputs_hidden": false}
message="""
@@ -451,7 +451,7 @@
# %% [markdown]
# ## Editing directly on GitHub
#
-# ### Editing directly on GitHub
+# ## Editing directly on GitHub
#
# Note that you can also make changes in the GitHub website itself. Visit one of your files, and hit "edit".
#
@@ -465,7 +465,7 @@
# %% [markdown]
# ## Social Coding
#
-# ### GitHub as a social network
+# ## GitHub as a social network
#
# In addition to being a repository for code, and a way to publish code, GitHub is a social network.
#
diff --git a/ch00git/06ForkAndPull.ipynb.py b/ch00git/06ForkAndPull.ipynb.py
index 4af89b75..b6d1024d 100644
--- a/ch00git/06ForkAndPull.ipynb.py
+++ b/ch00git/06ForkAndPull.ipynb.py
@@ -12,9 +12,9 @@
# ---
# %% [markdown]
-# ## Fork and Pull
+# # Fork and Pull
#
-# ### Different ways of collaborating
+# ## Different ways of collaborating
#
# We have just seen how we can work with others on GitHub: we add them as collaborators on our repositories and give them permissions to push changes.
#
@@ -31,7 +31,7 @@
# The right way to do this is __forking Numpy's repository__.
# %% [markdown]
-# ### Forking a repository on GitHub
+# ## Forking a repository on GitHub
#
# By forking a repository, all you do is make a copy of it in your GitHub account, where you will have write permissions as well.
#
@@ -40,7 +40,7 @@
# Once you are happy with with the changes, GitHub also offers you a way to notify Numpy's developers of this changes so that they can include them in the official Numpy repository via starting a __Pull Request__.
# %% [markdown]
-# ### Pull Request
+# ## Pull Request
#
# You can create a Pull Request and select those changes that you think can be useful for fixing Numpy's bug.
#
@@ -49,7 +49,7 @@
# Once Numpy's developers are happy with your changes, they'll accept your Pull Request and merge the changes into their original repository, for everyone to use.
# %% [markdown]
-# ### Practical example - Team up!
+# ## Practical example - Team up!
#
# We will be working in the same repository with one of you being the leader and the other being the collaborator.
#
@@ -161,7 +161,7 @@
# Fork and Pull Request done!
# %% [markdown]
-# ### Some Considerations
+# ## Some Considerations
#
# * Fork and Pull Request are things happening only on the repository's server side (GitHub in our case). Consequently, you can't do things like `git fork` or `git pull-request` from the local copy of a repository.
#
diff --git a/ch00git/10Branches.ipynb.py b/ch00git/10Branches.ipynb.py
index b5604873..84025ce5 100644
--- a/ch00git/10Branches.ipynb.py
+++ b/ch00git/10Branches.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Branches
+# # Branches
#
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
# thread/process restriction), and the cells below might error out on the browser
@@ -68,7 +68,7 @@
# cat Wales.md
# %% [markdown]
-# ### Publishing branches
+# ## Publishing branches
#
# To let the server know there's a new branch use:
@@ -99,7 +99,7 @@
# git branch -vv
# %% [markdown]
-# ### Find out what is on a branch
+# ## Find out what is on a branch
#
# In addition to using `git diff` to compare to the state of a branch,
# you can use `git log` to look at lists of commits which are in a branch
@@ -157,7 +157,7 @@
# Three dots means "everything which is not a common ancestor" of the two commits, i.e. the differences between them.
# %% [markdown]
-# ### Merging branches
+# ## Merging branches
# %% [markdown]
# We can merge branches, and just as we would pull in remote changes, there may or may not be conflicts.
@@ -170,7 +170,7 @@
# git log --graph --oneline HEAD~3..HEAD
# %% [markdown]
-# ### Cleaning up after a branch
+# ## Cleaning up after a branch
# %% jupyter={"outputs_hidden": false} language="bash"
# git branch
@@ -193,7 +193,7 @@
# git branch --remote
# %% [markdown]
-# ### A good branch strategy
+# ## A good branch strategy
#
# * A `develop` or `main` branch: for general new code - (the cutting edge version of your software)
# * `feature` branches: for specific new ideas. Normally branched out from `main`.
@@ -202,7 +202,7 @@
# * A `production` branch: code used for active work. Normally it's the same than the latest release.
# %% [markdown]
-# ### Grab changes from a branch
+# ## Grab changes from a branch
#
# Make some changes on one branch, switch back to another, and use:
diff --git a/ch00git/11Miscellany.ipynb.py b/ch00git/11Miscellany.ipynb.py
index 8805c68e..47ebdde6 100644
--- a/ch00git/11Miscellany.ipynb.py
+++ b/ch00git/11Miscellany.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Git Stash
+# # Git Stash
# %% [markdown]
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
@@ -161,7 +161,7 @@
# %% [markdown]
# ## Hunks
#
-# ### Git Hunks
+# ## Git Hunks
#
# A "Hunk" is one git change. This changeset has three hunks:
@@ -185,7 +185,7 @@
# ```
# %% [markdown]
-# ### Interactive add
+# ## Interactive add
#
# `git add` and `git reset` can be used to stage/unstage a whole file,
# but you can use interactive mode to stage by hunk, choosing
@@ -206,7 +206,7 @@
# %% [markdown]
# ## GitHub pages
#
-# ### Yaml Frontmatter
+# ## Yaml Frontmatter
#
# GitHub will publish repositories containing markdown as web pages, automatically.
#
@@ -236,7 +236,7 @@
# git commit -m "Add github pages YAML frontmatter"
# %% [markdown]
-# ### The gh-pages branch
+# ## The gh-pages branch
#
# GitHub creates github pages when you use a special named branch.
#
@@ -258,7 +258,7 @@
# http://UCL.github.io/github-example/
# %% [markdown]
-# ### UCL layout for GitHub pages
+# ## UCL layout for GitHub pages
#
# You can use GitHub pages to make HTML layouts, here's an [example of how to do it](http://github.com/UCL/ucl-github-pages-example),
# and [how it looks](http://github-pages.ucl.ac.uk/ucl-github-pages-example). We won't go into the detail of this now,
diff --git a/ch00git/12Remotes.ipynb.py b/ch00git/12Remotes.ipynb.py
index ce3f2b9d..8f621186 100644
--- a/ch00git/12Remotes.ipynb.py
+++ b/ch00git/12Remotes.ipynb.py
@@ -12,13 +12,13 @@
# ---
# %% [markdown]
-# ## Working with multiple remotes
+# # Working with multiple remotes
#
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
# thread/process restriction), and the cells below might error out on the browser
# (jupyterlite) version of this notebook
#
-# ### Distributed versus centralised
+# ## Distributed versus centralised
#
# Older version control systems (cvs, svn) were "centralised"; the history was kept only on a server,
# and all commits required an internet.
@@ -66,7 +66,7 @@
# git push -uf arc main
# %% [markdown]
-# ### Referencing remotes
+# ## Referencing remotes
#
# You can always refer to commits on a remote like this:
@@ -91,7 +91,7 @@
# %% [markdown]
# ## Hosting Servers
#
-# ### Hosting a local server
+# ## Hosting a local server
#
# * Any repository can be a remote for pulls
# * Can pull/push over shared folders or ssh
@@ -123,7 +123,7 @@
# If you have a colleague on a shared file system, you can use this approach to collaborate through that file system.
# %% [markdown]
-# ### Home-made SSH servers
+# ## Home-made SSH servers
#
# Classroom exercise: Try creating a server for yourself using a machine you can SSH to:
diff --git a/ch00git/13Rebase.ipynb.py b/ch00git/13Rebase.ipynb.py
index 7b38c82a..75e3506a 100644
--- a/ch00git/13Rebase.ipynb.py
+++ b/ch00git/13Rebase.ipynb.py
@@ -12,9 +12,9 @@
# ---
# %% [markdown]
-# ## Rebasing
+# # Rebasing
#
-# ### Rebase vs merge
+# ## Rebase vs merge
#
# A git *merge* is only one of two ways to get someone else's work into yours.
# The other is called a rebase.
@@ -26,7 +26,7 @@
#
# Git will invent some new revisions, and the result will be a repository with an apparently linear history. This can be useful if you want a cleaner, non-branching history, but it has the risk of creating inconsistencies, since you are, in a way, "rewriting" history.
#
-# ### An example rebase
+# ## An example rebase
#
# We've built a [repository to help visualise the difference between a merge and a rebase](https://github.com/UCL-ARC-RSEing-with-Python/wocky_rebase/blob/main/wocky.md).
@@ -137,7 +137,7 @@
# ```
# %% [markdown]
-# ### Fast Forwards
+# ## Fast Forwards
#
# If we want to continue with the translation, and now want to merge the rebased branch into the carollian branch,
# we get:
@@ -157,7 +157,7 @@
#
# The main branch was already **rebased on** the carollian branch, so this merge was just a question of updating *metadata* (moving the label for the carollian branch so that it points to the same commit main does): a "fast forward".
#
-# ### Rebasing pros and cons
+# ## Rebasing pros and cons
#
# Some people like the clean, apparently linear history that rebase provides.
#
@@ -187,7 +187,7 @@
# ```
# %% [markdown]
-# ### Using rebase to squash
+# ## Using rebase to squash
# %% [markdown] attributes={"classes": [" bash"], "id": ""}
# If we type
diff --git a/ch00git/14Bisect.ipynb.py b/ch00git/14Bisect.ipynb.py
index bace9a06..d99a9d9f 100644
--- a/ch00git/14Bisect.ipynb.py
+++ b/ch00git/14Bisect.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Debugging With Git Bisect
+# # Debugging With Git Bisect
#
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
# thread/process restriction), and the cells below might error out on the browser
@@ -27,7 +27,7 @@
# to find out which commit caused a bug.
# %% [markdown]
-# ### An example repository
+# ## An example repository
#
# In a nice open source example, I found an arbitrary exemplar on github
@@ -62,7 +62,7 @@
# python squares.py 2 # Error message
# %% [markdown]
-# ### Bisecting manually
+# ## Bisecting manually
# %% attributes={"classes": [" bash"], "id": ""} jupyter={"outputs_hidden": false} language="bash"
# git bisect start
@@ -74,7 +74,7 @@
# Bisect needs one known good and one known bad commit to get started
# %% [markdown]
-# ### Solving Manually
+# ## Solving Manually
# %% [markdown] attributes={"classes": [" bash"], "id": ""}
# ``` bash
@@ -130,7 +130,7 @@
# ```
# %% [markdown]
-# ### Solving automatically
+# ## Solving automatically
#
# If we have an appropriate unit test, we can do all this automatically:
#
diff --git a/ch01python/010exemplar.ipynb.py b/ch01python/010exemplar.ipynb.py
index 2a1c6246..c4fc67d4 100644
--- a/ch01python/010exemplar.ipynb.py
+++ b/ch01python/010exemplar.ipynb.py
@@ -43,12 +43,7 @@
# By combining them we can feel really powerful but doing minimum work ourselves. The python syntax to import someone else's library is "import".
# %%
-# sending requests to the web is not fully supported on jupyterlite yet, and the
-# cells below might error out on the browser (jupyterlite) version of this notebook
-
-# install geopy if it is not already installed
-%pip install geopy
-
+%pip install -q geopy # install geopy if not already installed
import geopy # A python library for investigating geographic information.
# https://pypi.org/project/geopy/
diff --git a/ch02data/110Capstone.ipynb.py b/ch02data/110Capstone.ipynb.py
index 6f175034..fbe90f1f 100644
--- a/ch02data/110Capstone.ipynb.py
+++ b/ch02data/110Capstone.ipynb.py
@@ -35,7 +35,7 @@
# cells below might error out on the browser (jupyterlite) version of this notebook
# install geopy if it is not already installed
-%pip install geopy
+%pip install -q geopy
import numpy as np
import geopy
diff --git a/ch03tests/01testingbasics.ipynb.py b/ch03tests/01testingbasics.ipynb.py
index 60a554f2..0bf5c30f 100644
--- a/ch03tests/01testingbasics.ipynb.py
+++ b/ch03tests/01testingbasics.ipynb.py
@@ -14,9 +14,6 @@
# %% [markdown]
# # Testing
-# %% [markdown]
-# ## Introduction
-
# %% [markdown]
# When programming, it is very important to know that the code we have written does what it was intended. Unfortunately, this step is often skipped in scientific programming, especially when developing code for our own personal work.
#
@@ -25,7 +22,7 @@
# In this chapter, we will mostly look at how to write **unit tests**, which check the behaviour of small parts of our code. We will work with a particular framework for Python code, but the principles we discuss are general. We will also look at how to use a debugger to locate problems in our code, and services that simplify the automated running of tests.
# %% [markdown]
-# ### A few reasons not to do testing
+# ## A few reasons not to do testing
# %% [markdown]
# Sensibility | Sense
@@ -38,7 +35,7 @@
# **Will do it later** | *See above*
# %% [markdown]
-# ### A few reasons to do testing
+# ## A few reasons to do testing
#
# * **laziness**: testing saves time
# * **peace of mind**: tests (should) ensure code is correct
@@ -49,7 +46,7 @@
# * **ease of modification**: since results can be tested
# %% [markdown]
-# ### Not a panacea
+# ## Not a panacea
#
# > Trying to improve the quality of software by doing more testing is like trying to lose weight by
# > weighing yourself more often.
@@ -64,7 +61,7 @@
# If the test cases do not cover the bugs, things can go horribly wrong - an example for this is [Therac-25](https://en.wikipedia.org/wiki/Therac-25).
# %% [markdown]
-# ### Tests at different scales
+# ## Tests at different scales
#
# Level of test |Area covered by test
# -------------------------- |----------------------
@@ -83,7 +80,7 @@
#
# %% [markdown]
-# ### Legacy code hardening
+# ## Legacy code hardening
#
# * Very difficult to create unit-tests for existing code
# * Instead we make a **regression test**
@@ -100,7 +97,7 @@
# * Checks code is a similarly wrong on day N as day 0
# %% [markdown]
-# ### Testing vocabulary
+# ## Testing vocabulary
#
# * **fixture**: input data
# * **action**: function that is being tested
@@ -109,7 +106,7 @@
# * **coverage**: proportion of all possible paths in the code that the tests take
# %% [markdown]
-# ### Branch coverage:
+# ## Branch coverage:
# %% [markdown] attributes={"classes": [" python"], "id": ""}
# ```python
diff --git a/ch03tests/02SaskatchewanFields.ipynb.py b/ch03tests/02SaskatchewanFields.ipynb.py
index 7a278669..921871c5 100644
--- a/ch03tests/02SaskatchewanFields.ipynb.py
+++ b/ch03tests/02SaskatchewanFields.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## How to Test
+# # How to Test
# %% [markdown]
-# ### Equivalence partitioning
+# ## Equivalence partitioning
# %% [markdown]
# Think hard about the different cases the code will run under: this is science, not coding!
@@ -115,7 +115,7 @@ def vertices(left, bottom, right, top):
# %% [markdown]
-# ### Using our tests
+# ## Using our tests
# %% [markdown]
# OK, so how might our tests be useful?
@@ -219,7 +219,7 @@ def overlap(field1, field2):
# Note, we reran our other tests, to check our fix didn't break something else. (We call that "fallout")
# %% [markdown]
-# ### Boundary cases
+# ## Boundary cases
# %% [markdown]
# "Boundary cases" are an important area to test:
@@ -239,7 +239,7 @@ def overlap(field1, field2):
# * What happens when a matrix/data-frame reaches one row, or one column?
# %% [markdown]
-# ### Positive *and* negative tests
+# ## Positive *and* negative tests
#
# * **Positive tests**: code should give correct answer with various inputs
# * **Negative tests**: code should crash as expected given invalid inputs, rather than lying
@@ -251,7 +251,7 @@ def overlap(field1, field2):
# Testing should ensure that explicit failures do indeed happen.
# %% [markdown]
-# ### Raising exceptions
+# ## Raising exceptions
# %% [markdown]
# In Python, we can signal an error state by raising an error:
diff --git a/ch03tests/03pytest.ipynb.py b/ch03tests/03pytest.ipynb.py
index 72823ac1..b0e6cd6d 100644
--- a/ch03tests/03pytest.ipynb.py
+++ b/ch03tests/03pytest.ipynb.py
@@ -12,13 +12,13 @@
# ---
# %% [markdown]
-# ## Testing frameworks
+# # Testing frameworks
#
# **NOTE:** using bash/git commands is not fully supported on jupyterlite yet (due to single
# thread/process restriction), and the cells below might error out on the browser
# (jupyterlite) version of this notebook
#
-# ### Why use testing frameworks?
+# ## Why use testing frameworks?
# %% [markdown]
# Frameworks should simplify our lives:
@@ -35,7 +35,7 @@
# * Additional goodies, such as code coverage
# %% [markdown]
-# ### Common testing frameworks
+# ## Common testing frameworks
# %% [markdown]
# * Language agnostic: [CTest](http://www.cmake.org/cmake/help/v2.8.12/ctest.html)
@@ -73,7 +73,7 @@
# * [pfunit](http://sourceforge.net/projects/pfunit/)(works with MPI)
# %% [markdown]
-# ### pytest framework: usage
+# ## pytest framework: usage
#
# [pytest](https://docs.pytest.org/en/latest/) is a recommended python testing framework.
@@ -161,7 +161,7 @@ def test_no_overlap():
# %% [markdown]
# ## Testing with floating points
#
-# ### Floating points are not reals
+# ## Floating points are not reals
#
#
# Floating points are inaccurate representations of real numbers:
@@ -189,7 +189,7 @@ def test_no_overlap():
# The result should be `2e-8`.
# %% [markdown]
-# ### Comparing floating points
+# ## Comparing floating points
#
# Use the "approx", for a default of a relative tolerance of $10^{-6}$
@@ -208,7 +208,7 @@ def test_no_overlap():
# Choosing tolerances is a big area of [debate](https://software-carpentry.org/blog/2014/10/why-we-dont-teach-testing.html).
# %% [markdown]
-# ### Comparing vectors of floating points
+# ## Comparing vectors of floating points
#
# Numerical vectors are best represented using [numpy](http://www.numpy.org/).
diff --git a/ch03tests/04EnergyExample.ipynb.py b/ch03tests/04EnergyExample.ipynb.py
index d1de4afc..3e3bc3b3 100644
--- a/ch03tests/04EnergyExample.ipynb.py
+++ b/ch03tests/04EnergyExample.ipynb.py
@@ -12,9 +12,9 @@
# ---
# %% [markdown]
-# ## Classroom exercise: energy calculation
+# # Classroom exercise: energy calculation
#
-# ### Diffusion model in 1D
+# ## Diffusion model in 1D
#
# Description: A one-dimensional diffusion model. (Could be a gas of particles, or a bunch of crowded people in a corridor, or animals in a valley habitat...)
#
@@ -46,7 +46,7 @@
# total energy.
# %% [markdown]
-# ### Starting point
+# ## Starting point
#
# Create a Python module:
@@ -96,7 +96,7 @@ def test_energy():
# Now, write your code (in `model.py`), and tests (in `test_model.py`), testing as you do.
# %% [markdown]
-# ### Solution
+# ## Solution
#
# Don't look until after you've tried!
@@ -199,7 +199,7 @@ def test_derivative_no_self_energy():
# pytest
# %% [markdown]
-# ### Coverage
+# ## Coverage
#
# With py.test, you can use the ["pytest-cov" plugin](https://github.com/pytest-dev/pytest-cov) to measure test coverage
diff --git a/ch03tests/05Mocks.ipynb.py b/ch03tests/05Mocks.ipynb.py
index b77058f2..0a625127 100644
--- a/ch03tests/05Mocks.ipynb.py
+++ b/ch03tests/05Mocks.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Mocking
+# # Mocking
# %% [markdown]
-# ### Definition
+# ## Definition
#
# **Mock**: *verb*,
#
@@ -30,14 +30,14 @@
# - Replace a real object with a pretend object, which records how it is called, and can assert if it is called wrong
# %% [markdown]
-# ### Mocking frameworks
+# ## Mocking frameworks
#
# * C: [CMocka](http://www.cmocka.org/)
# * C++: [googletest](https://github.com/google/googletest)
# * Python: [unittest.mock](http://docs.python.org/3/library/unittest.mock)
# %% [markdown]
-# ### Recording calls with mock
+# ## Recording calls with mock
#
# Mock objects record the calls made to them:
@@ -80,7 +80,7 @@
function()
# %% [markdown]
-# ### Using mocks to model test resources
+# ## Using mocks to model test resources
# %% [markdown]
# Often we want to write tests for code which interacts with remote resources. (E.g. databases, the internet, or data files.)
@@ -163,7 +163,7 @@ def test_build_default_params():
# passing "by accident", run the tests, then change it back!
# %% [markdown]
-# ### Testing functions that call other functions
+# ## Testing functions that call other functions
#
#
diff --git a/ch03tests/06Debugger.ipynb.py b/ch03tests/06Debugger.ipynb.py
index b591616c..384cd33f 100644
--- a/ch03tests/06Debugger.ipynb.py
+++ b/ch03tests/06Debugger.ipynb.py
@@ -12,9 +12,9 @@
# ---
# %% [markdown]
-# ## Using a debugger
+# # Using a debugger
#
-# ### Stepping through the code
+# ## Stepping through the code
#
# Debuggers are programs that can be used to test other programs. They allow programmers to suspend execution of the target program and inspect variables at that point.
#
@@ -32,7 +32,7 @@
# [browser](http://stat.ethz.ch/R-manual/R-devel/library/base/html/browser.html).
# %% [markdown]
-# ### Using the python debugger
+# ## Using the python debugger
# %% [markdown]
# Unfortunately this doesn't work nicely in the notebook. But from the command line, you can run a python program with:
@@ -43,7 +43,7 @@
# ```
# %% [markdown]
-# ### Basic navigation:
+# ## Basic navigation:
#
# Basic command to navigate the code and the python debugger:
#
@@ -59,7 +59,7 @@
# The python debugger is **a python shell**: it can print and compute values, and even change the values
# of the variables at that point in the program.
#
-# ### Breakpoints
+# ## Breakpoints
#
# Break points tell debugger where and when to stop
# We say
@@ -89,7 +89,7 @@
# Alternatively, break-points can be set on files: `b file.py:20` will stop on line 20 of `file.py`.
# %% [markdown]
-# ### Post-mortem
+# ## Post-mortem
#
# Debugging when something goes wrong:
#
diff --git a/ch03tests/07CI.ipynb.py b/ch03tests/07CI.ipynb.py
index 388cf869..aa1a7f37 100644
--- a/ch03tests/07CI.ipynb.py
+++ b/ch03tests/07CI.ipynb.py
@@ -12,11 +12,11 @@
# ---
# %% [markdown]
-# ## Continuous Integration
+# # Continuous Integration
#
# Continuous integration (CI) is a software development practice that involves integrating new code to a shared repository regularly (typically at least once a day). The integrated changes are then automatically checked by the CI system on test servers, which allows to detect problems early.
#
-# ### Test servers
+# ## Test servers
#
# The test servers of the CI system might be configured to:
#
@@ -29,7 +29,7 @@
# When configuring a CI system, it's important to weigh up the usefulness of the test settings you cover against the energy consumption that will incur from running the tests frequently. For example, you might want to set up the CI system to run a more extensive suite of tests when a PR to the `main` branch is opened, and only run a small number of important tests at every commit. You could also decide that you don't need to test your code for all Python versions, but only for an old version and a recent one.
# %% [markdown]
-# ### Memory and profiling
+# ## Memory and profiling
#
# For compiled languages (C, C++, Fortran):
# * Checking for memory leaks with [valgrind](http://valgrind.org/):
diff --git a/ch03tests/08DiffusionExample.ipynb.py b/ch03tests/08DiffusionExample.ipynb.py
index 5dda3f8f..5626bc64 100644
--- a/ch03tests/08DiffusionExample.ipynb.py
+++ b/ch03tests/08DiffusionExample.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Recap example: Monte-Carlo
+# # Recap example: Monte-Carlo
# %% [markdown]
-# ### Problem: Implement and test a simple Monte-Carlo algorithm
+# ## Problem: Implement and test a simple Monte-Carlo algorithm
#
# Given an input function (energy) and starting point (density) and a temperature $T$:
#
@@ -37,7 +37,7 @@
# * Use [matplotlib](http://matplotlib.org/) to plot density at each iteration, and make an animation
# %% [markdown]
-# ### Solution
+# ## Solution
# %% [markdown]
# We need to break our problem down into pieces:
diff --git a/ch04packaging/010Libraries.ipynb.py b/ch04packaging/001Libraries.ipynb.py
similarity index 94%
rename from ch04packaging/010Libraries.ipynb.py
rename to ch04packaging/001Libraries.ipynb.py
index 1aff6e8f..817c837d 100644
--- a/ch04packaging/010Libraries.ipynb.py
+++ b/ch04packaging/001Libraries.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Libraries
+# # Libraries
# %% [markdown]
-# ### Libraries are awesome
+# ## Libraries are awesome
# %% [markdown]
#
@@ -35,7 +35,7 @@
# The chances are any algorithm you might want to use has already been programmed better by someone else.
# %% [markdown]
-# ### Drawbacks of libraries.
+# ## Drawbacks of libraries.
# %% [markdown]
#
@@ -50,7 +50,7 @@
#
# %% [markdown]
-# ### Contribute, don't duplicate
+# ## Contribute, don't duplicate
# %% [markdown]
#
@@ -60,7 +60,7 @@
#
# %% [markdown]
-# ### How to choose a library
+# ## How to choose a library
# %% [markdown]
#
@@ -86,7 +86,7 @@
#
# %% [markdown]
-# ### Sensible Version Numbering
+# ## Sensible Version Numbering
# %% [markdown]
#
@@ -102,7 +102,7 @@
#
# %% [markdown]
-# ### The Python Standard Library
+# ## The Python Standard Library
# %% [markdown]
#
@@ -114,7 +114,7 @@
#
# %% [markdown]
-# ### The Python Package Index
+# ## The Python Package Index
# %% [markdown]
#
diff --git a/ch04packaging/01Installation.ipynb.py b/ch04packaging/01Installation.ipynb.py
index 99ef7716..1fa269d9 100644
--- a/ch04packaging/01Installation.ipynb.py
+++ b/ch04packaging/01Installation.ipynb.py
@@ -69,7 +69,7 @@
# cells below might error out on the browser (jupyterlite) version of this notebook
# install geopy if it is not already installed
-%pip install geopy
+%pip install -q geopy
import geopy
geocoder = geopy.geocoders.Nominatim(user_agent="mphy0021")
diff --git a/ch04packaging/025TextFiles.ipynb.py b/ch04packaging/025TextFiles.ipynb.py
index 472fcac0..745f896e 100644
--- a/ch04packaging/025TextFiles.ipynb.py
+++ b/ch04packaging/025TextFiles.ipynb.py
@@ -12,14 +12,14 @@
# ---
# %% [markdown]
-# ## Python not in the Notebook
+# # Python not in the Notebook
# %% [markdown]
# We will often want to save our Python classes, for use in multiple Notebooks.
# We can do this by writing text files with a .py extension, and then `importing` them.
# %% [markdown]
-# ### Writing Python in Text Files
+# ## Writing Python in Text Files
# %% [markdown]
# You can use a text editor like [VS Code](https://code.visualstudio.com/) or [Spyder](https://www.spyder-ide.org/). If you create your own Python files ending in `.py`, then you can import them with `import` just like external libraries.
@@ -164,7 +164,7 @@ def valid(self):
# In this case we are making it easier to import `Maze` as we are making it available one level above.
# %% [markdown]
-# ### Loading Our Package
+# ## Loading Our Package
# %% [markdown]
# We just wrote the files, there is no "Maze" class in this notebook yet:
@@ -206,7 +206,7 @@ def valid(self):
# on the fly when your `.py` files change. They may appear inside the `__pycache__` directory.
# %% [markdown]
-# ### The Python Path
+# ## The Python Path
# %% [markdown]
# We want to `import` these from notebooks elsewhere on our computer:
diff --git a/ch04packaging/02Argparse.ipynb.py b/ch04packaging/02Argparse.ipynb.py
index be1061a6..24d132dd 100644
--- a/ch04packaging/02Argparse.ipynb.py
+++ b/ch04packaging/02Argparse.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Argparse
+# # Argparse
# %% [markdown]
# This is the standard library for building programs with a command-line interface. Here we show a short introduction to it, but we recommend to read the [official tutorial](https://docs.python.org/3/howto/argparse.html).
diff --git a/ch04packaging/03Packaging.ipynb.py b/ch04packaging/03Packaging.ipynb.py
index 518a4e2b..c6119d74 100644
--- a/ch04packaging/03Packaging.ipynb.py
+++ b/ch04packaging/03Packaging.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Packaging
+# # Packaging
# %% [markdown]
#
@@ -39,7 +39,7 @@
#
# %% [markdown]
-# ### Distribution tools
+# ## Distribution tools
# %% [markdown]
# Distribution tools allow one to obtain a working copy of someone else's package.
@@ -75,7 +75,7 @@
#
# %% [markdown]
-# ### Laying out a project
+# ## Laying out a project
# %% [markdown]
#
@@ -119,7 +119,7 @@
# %autoreload 2
# %% [markdown]
-# ### Using pyproject.toml
+# ## Using pyproject.toml
# %% [markdown]
# Since June 2020, python's recommendation for creating a package is to specify package information in a `pyproject.toml` file.
@@ -222,7 +222,7 @@ def greet(personal, family, title="", polite=False):
# %% [markdown]
-# ### Convert the script to a module
+# ## Convert the script to a module
# %% [markdown]
#
@@ -276,7 +276,7 @@ def greet(personal, family, title="", polite=False):
# this on [the next section](./04documentation.html) ([notebook version](./04documentation.ipynb)).
# %% [markdown]
-# ### Write an executable script
+# ## Write an executable script
# %% [markdown]
#
@@ -369,7 +369,7 @@ def process():
# greet Terry Gilliam --title Cartoonist
# %% [markdown]
-# ### Specify dependencies
+# ## Specify dependencies
# %% [markdown]
# Let's give some life to our output using ascii art
@@ -440,7 +440,7 @@ def process():
# greet Terry Gilliam
# %% [markdown]
-# ### Installing from GitHub
+# ## Installing from GitHub
# %% [markdown]
#
@@ -469,7 +469,7 @@ def process():
#
# %% [markdown]
-# ### Write a readme file
+# ## Write a readme file
# %% [markdown]
# The readme file might look like this:
@@ -499,7 +499,7 @@ def process():
```
# %% [markdown]
-# ### Write a license file
+# ## Write a license file
# %% [markdown]
# We will discus more about [licensing in a later section](https://github-pages.ucl.ac.uk/rsd-engineeringcourse/ch04packaging/07Licensing.html). For now let's assume we want to release this package into the public domain:
@@ -512,7 +512,7 @@ def process():
This "greetings" example package is granted into the public domain.
# %% [markdown]
-# ### Write a citation file
+# ## Write a citation file
# %% [markdown]
# A citation file will inform our users how we would like to be cited when refering to our software:
@@ -530,7 +530,7 @@ def process():
# %% [markdown]
-# ### Write some unit tests
+# ## Write some unit tests
# %% [markdown]
# We can now write some tests to our library.
@@ -684,7 +684,7 @@ def test_greeter(fixture):
# %% [markdown]
-# ### Developer Install
+# ## Developer Install
# %% [markdown]
#
@@ -712,7 +712,7 @@ def test_greeter(fixture):
# ```
# %% [markdown]
-# ### Distributing compiled code
+# ## Distributing compiled code
# %% [markdown]
#
diff --git a/ch04packaging/04documentation.ipynb.py b/ch04packaging/04documentation.ipynb.py
index a57283d9..4e206aea 100644
--- a/ch04packaging/04documentation.ipynb.py
+++ b/ch04packaging/04documentation.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Documentation
+# # Documentation
# %% [markdown]
-# ### Documentation is hard
+# ## Documentation is hard
# %% [markdown]
#
@@ -26,7 +26,7 @@
#
# %% [markdown]
-# ### Prefer readable code with tests and vignettes
+# ## Prefer readable code with tests and vignettes
# %% [markdown]
#
@@ -39,7 +39,7 @@
#
# %% [markdown]
-# ### Comment-based Documentation tools
+# ## Comment-based Documentation tools
# %% [markdown]
#
@@ -69,7 +69,7 @@
# ## Example of using Sphinx
# %% [markdown]
-# ### Write some docstrings
+# ## Write some docstrings
# %% [markdown]
# We're going to document our "greeter" example from the previous section using docstrings with Sphinx.
@@ -108,7 +108,7 @@
# ```
# %% [markdown]
-# ### Set up Sphinx
+# ## Set up Sphinx
# %% [markdown]
# Install Sphinx using the [appropiate instructions](https://www.sphinx-doc.org/en/master/usage/installation.html) for your system following the documentation online.
@@ -238,7 +238,7 @@
]
# %% [markdown]
-# ### Define the root documentation page
+# ## Define the root documentation page
# %% [markdown]
#
@@ -263,7 +263,7 @@
# %% [markdown]
-# ### Run sphinx
+# ## Run sphinx
# %% [markdown]
#
@@ -275,7 +275,7 @@
# sphinx-build . doc
# %% [markdown]
-# ### Sphinx output
+# ## Sphinx output
# %% [markdown]
# Sphinx's output is [html](./greetings/doc/index.html). We just created a simple single function's documentation, but Sphinx will create
diff --git a/ch04packaging/05Process.ipynb.py b/ch04packaging/05Process.ipynb.py
index 8f92232d..ff9b337a 100644
--- a/ch04packaging/05Process.ipynb.py
+++ b/ch04packaging/05Process.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Software Project Management
+# # Software Project Management
# %% [markdown]
-# ### Software Engineering Stages
+# ## Software Engineering Stages
# %% [markdown]
#
@@ -27,7 +27,7 @@
#
# %% [markdown]
-# ### Requirements Engineering
+# ## Requirements Engineering
# %% [markdown]
#
@@ -44,7 +44,7 @@
#
# %% [markdown]
-# ### Functional and architectural design
+# ## Functional and architectural design
# %% [markdown]
#
@@ -55,7 +55,7 @@
#
# %% [markdown]
-# ### Waterfall
+# ## Waterfall
# %% [markdown]
#
@@ -65,7 +65,7 @@
#
# %% [markdown]
-# ### Why Waterfall?
+# ## Why Waterfall?
# %% [markdown]
#
@@ -75,7 +75,7 @@
#
# %% [markdown]
-# ### Problems with Waterfall
+# ## Problems with Waterfall
# %% [markdown]
#
@@ -90,7 +90,7 @@
#
# %% [markdown]
-# ### Software is not made of bricks
+# ## Software is not made of bricks
# %% [markdown]
#
@@ -122,7 +122,7 @@
# -- Prof. [Anthony Finkelstein](http://www0.cs.ucl.ac.uk/staff/A.Finkelstein/), UCL Dean of Engineering, and Professor of Software Systems Engineering
# %% [markdown]
-# ### The Agile Manifesto
+# ## The Agile Manifesto
# %% [markdown]
#
@@ -144,7 +144,7 @@
#
# %% [markdown]
-# ### Agile is not absence of process
+# ## Agile is not absence of process
# %% [markdown]
#
@@ -158,7 +158,7 @@
#
# %% [markdown]
-# ### Elements of an Agile Process
+# ## Elements of an Agile Process
# %% [markdown]
#
@@ -169,7 +169,7 @@
#
# %% [markdown]
-# ### Ongoing Design
+# ## Ongoing Design
# %% [markdown]
#
@@ -186,7 +186,7 @@
#
# %% [markdown]
-# ### Iterative Development
+# ## Iterative Development
# %% [markdown]
#
@@ -200,7 +200,7 @@
#
# %% [markdown]
-# ### Continuous Delivery
+# ## Continuous Delivery
# %% [markdown]
#
@@ -210,7 +210,7 @@
#
# %% [markdown]
-# ### Self-organising teams
+# ## Self-organising teams
# %% [markdown]
#
@@ -222,7 +222,7 @@
#
# %% [markdown]
-# ### Agile in Research
+# ## Agile in Research
# %% [markdown]
#
@@ -236,7 +236,7 @@
#
# %% [markdown]
-# ### Conclusion
+# ## Conclusion
# %% [markdown]
#
diff --git a/ch04packaging/06Issues.ipynb.py b/ch04packaging/06Issues.ipynb.py
index 15469da7..f115f3dd 100644
--- a/ch04packaging/06Issues.ipynb.py
+++ b/ch04packaging/06Issues.ipynb.py
@@ -12,17 +12,17 @@
# ---
# %% [markdown]
-# ## Managing software issues
+# # Managing software issues
# %% [markdown]
-# ### Issues
+# ## Issues
#
# Code has *bugs*. It also has *features*, things it should do.
#
# A good project has an organised way of managing these. Generally you should use an issue tracker.
# %% [markdown]
-# ### Some Issue Trackers
+# ## Some Issue Trackers
#
# There are lots of good issue trackers.
#
@@ -33,7 +33,7 @@
# Commercial solutions include [Jira](https://www.atlassian.com/software/jira).
# %% [markdown]
-# ### Anatomy of an issue
+# ## Anatomy of an issue
#
# * Reporter
# * Description
@@ -44,7 +44,7 @@
# * Severity
# %% [markdown]
-# ### Reporting a Bug
+# ## Reporting a Bug
#
# The description should make the bug reproducible:
#
@@ -54,13 +54,13 @@
# If possible, submit a minimal reproducing code fragment - look at this detailed answer about [how to create a minimal example for $LaTeX$](https://tex.meta.stackexchange.com/a/3225/10934).
# %% [markdown]
-# ### Owning an issue
+# ## Owning an issue
#
# * Whoever the issue is assigned to works next.
# * If an issue needs someone else's work, assign it to them.
# %% [markdown]
-# ### Status
+# ## Status
#
# * Submitted
# * Accepted
@@ -68,7 +68,7 @@
# * Blocked
# %% [markdown]
-# ### Resolutions
+# ## Resolutions
#
# * Resolved
# * Will Not Fix
@@ -76,7 +76,7 @@
# * Not a bug (working as intended)
# %% [markdown]
-# ### Bug triage
+# ## Bug triage
#
# Some organisations use a severity matrix based on:
#
@@ -84,13 +84,13 @@
# * Frequency [All users, most users, some users...]
# %% [markdown]
-# ### The backlog
+# ## The backlog
#
# The list of all the bugs that need to be fixed or
# features that have been requested is called the "backlog".
# %% [markdown]
-# ### Development cycles
+# ## Development cycles
#
# Development goes in *cycles*.
#
@@ -103,7 +103,7 @@
# * Move these issues from the Backlog into the current cycle. (Aka Sprint)
# %% [markdown]
-# ### GitHub issues
+# ## GitHub issues
#
# GitHub doesn't have separate fields for status, component, severity etc.
# Instead, it just has labels, which you can create and delete.
diff --git a/ch04packaging/07Licensing.ipynb.py b/ch04packaging/07Licensing.ipynb.py
index 8374c266..8967e7e7 100644
--- a/ch04packaging/07Licensing.ipynb.py
+++ b/ch04packaging/07Licensing.ipynb.py
@@ -12,15 +12,15 @@
# ---
# %% [markdown]
-# ## Software Licensing
+# # Software Licensing
# %% [markdown]
-# ### Reuse
+# ## Reuse
#
# This course is distributed under the [Creative Commons By Attribution license](https://creativecommons.org/licenses/by/3.0/), which means you can modify and reuse the materials, so long as you credit [UCL Research IT Services](https://www.ucl.ac.uk/research-it-services/).
# %% [markdown]
-# ### Disclaimer
+# ## Disclaimer
#
# Here we attempt to give some basic advice on choosing a licence for your software. But:
#
@@ -33,7 +33,7 @@
# Your department, or UCL, may have policies about applying licences to code you create while a UCL employee or student. This training doesn't address this issue, and does not represent UCL policy -- seek advice from your supervisor or manager if concerned.
# %% [markdown]
-# ### Choose a licence
+# ## Choose a licence
#
# It is important to choose a licence and to create a *license file* to tell people what it is.
#
@@ -43,7 +43,7 @@
# Your licence file should typically be called LICENSE.txt or similar. GitHub will offer to create a licence file automatically when you create a new repository.
# %% [markdown]
-# ### Open source doesn't stop you making money
+# ## Open source doesn't stop you making money
#
# A common misconception about open source software is the thought that
# open source means you can't make any money. This is *wrong*.
@@ -57,7 +57,7 @@
# * Server software, which open source client software interacts with. For example: [GitHub API clients](https://github.com/octokit/octokit.rb).
# %% [markdown]
-# ### Plagiarism vs promotion
+# ## Plagiarism vs promotion
#
# Many researchers worry about people stealing their work if they open source their code. But often the biggest problem is not theft, but the fact no one is aware of your work.
#
@@ -67,7 +67,7 @@
# anonymity or theft.
# %% [markdown]
-# ### Your code *is* good enough
+# ## Your code *is* good enough
#
# New coders worry that they'll be laughed at if they put their code online. Don't worry. Everyone, including people who've been coding for decades,
# writes shoddy code that is full of bugs.
@@ -79,7 +79,7 @@
# Find a buddy, and get them to comment on it.
# %% [markdown]
-# ### Worry about licence compatibility and proliferation
+# ## Worry about licence compatibility and proliferation
#
# Not all open source code can be used in all projects. Some licences are legally incompatible.
#
@@ -94,7 +94,7 @@
# using the [opensource.org proliferation report](http://opensource.org/proliferation-report).
# %% [markdown]
-# ### Academic licence proliferation
+# ## Academic licence proliferation
#
# Academics often write their own licence terms for their software.
#
@@ -116,14 +116,14 @@
# future software ecosystem. Also, *Unless you are a lawyer, you cannot do this safely!*
# %% [markdown]
-# ### Licences for code, content, and data.
+# ## Licences for code, content, and data.
#
# Licences designed for code should not be used to license data or prose.
#
# Don't use Creative Commons for software, or GPL for a book.
# %% [markdown]
-# ### Licensing issues
+# ## Licensing issues
#
# * Permissive vs share-alike
# * Non-commercial and academic Use Only
@@ -131,7 +131,7 @@
# * Use as a web service
# %% [markdown]
-# ### Permissive vs share-alike
+# ## Permissive vs share-alike
#
# Some licences require all derived software to be licensed under terms that are similarly free.
# Such licences are called "Share Alike" or "Copyleft".
@@ -149,7 +149,7 @@
# If you want to use code that has a copyleft licence, you'll have to release your code under such a licence.
# %% [markdown]
-# ### Academic use only
+# ## Academic use only
#
# Some researchers want to make their code free for 'academic use only'.
# None of the standard licences state this, and this is a reason why academic bespoke licences proliferate.
@@ -164,7 +164,7 @@
# but offer the code under more permissive terms, allowing for commercial use, for a fee.
# %% [markdown]
-# ### Patents
+# ## Patents
#
# Intellectual property law distinguishes copyright from patents.
# This is a complex field, which I am far from qualified to teach!
@@ -174,7 +174,7 @@
# can't then go off and patent their contribution, some licences, such as the Apache licence, protect you from this.
# %% [markdown]
-# ### Use as a web service
+# ## Use as a web service
#
# If I take copyleft code, and use it to host a web service, I have not sold the software.
#
@@ -182,7 +182,7 @@
# This "loophole" in the GPL is closed by the AGPL ("Affero GPL")
# %% [markdown]
-# ### Library linking
+# ## Library linking
#
# If I use your code just as a library, without modifying it or including it directly in my own code,
# does the copyleft term of the GPL apply?
@@ -192,7 +192,7 @@
# If you don't want it to, use the LGPL. ("Lesser GPL"). This has an exception for linking libraries.
# %% [markdown]
-# ### Citing software
+# ## Citing software
#
# Almost all software licences require people to credit you for what they used ("attribution").
#
@@ -218,7 +218,7 @@
# }
# %% [markdown]
-# ### Referencing the licence in every file
+# ## Referencing the licence in every file
#
# Some licences require that you include licence information in every file.
# Others do not.
@@ -236,13 +236,13 @@
# [opensource.org](http://opensource.org/) for details of how to apply it to your software. For example, for the [GPL](http://opensource.org/licenses/GPL-3.0#howto).
# %% [markdown]
-# ### Choose a licence
+# ## Choose a licence
#
# See [GitHub's advice on how to choose a licence](http://choosealicense.com/) or [European Commision's Joinup Licensing Assistant](https://joinup.ec.europa.eu/collection/eupl/solution/joinup-licensing-assistant/jla-find-and-compare-software-licenses).
# Further, [REUSE Software](https://reuse.software) makes checking what license a file is licensed under easy by defining a machine-readable format for license files.
# %% [markdown]
-# ### Open source does not equal free maintenance
+# ## Open source does not equal free maintenance
#
# One common misunderstanding of open source software is that you'll automatically get loads of contributors from around the internets.
# This is wrong. Most open source projects get no commits from anyone else.
diff --git a/ch05construction/01introduction.ipynb.py b/ch05construction/01introduction.ipynb.py
index 706ef950..2df5055a 100644
--- a/ch05construction/01introduction.ipynb.py
+++ b/ch05construction/01introduction.ipynb.py
@@ -14,9 +14,6 @@
# %% [markdown]
# # Construction
-# %% [markdown]
-# ## Construction
-
# %% [markdown]
#
# Software *design* gets a lot of press (Object orientation, UML, design patterns).
@@ -25,7 +22,7 @@
#
# %% [markdown]
-# ### Construction vs Design
+# ## Construction vs Design
# %% [markdown]
#
@@ -39,7 +36,7 @@
#
# %% [markdown]
-# ### Low-level design decisions
+# ## Low-level design decisions
# %% [markdown]
#
@@ -51,7 +48,7 @@
#
# %% [markdown]
-# ### Algorithms and structures
+# ## Algorithms and structures
# %% [markdown]
#
@@ -65,7 +62,7 @@
#
# %% [markdown]
-# ### Architectural design
+# ## Architectural design
# %% [markdown]
#
@@ -80,7 +77,7 @@
#
# %% [markdown]
-# ### Construction
+# ## Construction
# %% [markdown]
#
@@ -89,7 +86,7 @@
#
# %% [markdown]
-# ### Literate programming
+# ## Literate programming
# %% [markdown]
#
@@ -108,7 +105,7 @@
#
# %% [markdown]
-# ### Programming for humans
+# ## Programming for humans
# %% [markdown]
#
@@ -124,7 +121,7 @@
#
# %% [markdown]
-# ### Setup
+# ## Setup
# %% [markdown]
# This notebook is based on a number of fragments of code, with an implicit context.
diff --git a/ch05construction/02conventions.ipynb.py b/ch05construction/02conventions.ipynb.py
index 9816140a..dae3966e 100644
--- a/ch05construction/02conventions.ipynb.py
+++ b/ch05construction/02conventions.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Coding Conventions
+# # Coding Conventions
#
# Let's import a few variables from context.py that will be used in the following lesson.
@@ -30,7 +30,7 @@
)
# %% [markdown]
-# ### One code, many layouts:
+# ## One code, many layouts:
#
# Consider the following fragment of python:
#
@@ -67,7 +67,7 @@ def add_to_reaction(a_name,
#
# %% [markdown]
-# ### So many choices
+# ## So many choices
# %% [markdown]
#
@@ -77,7 +77,7 @@ def add_to_reaction(a_name,
#
# %% [markdown]
-# ### Layout
+# ## Layout
# %%
reaction = {
@@ -109,7 +109,7 @@ def add_to_reaction(a_name,
# %% [markdown]
-# ### Layout choices
+# ## Layout choices
# %% [markdown]
#
@@ -121,7 +121,7 @@ def add_to_reaction(a_name,
# Inconsistency will produce a mess in your code! Some choices will make your code harder to read, whereas others may affect the code. For example, if you copy/paste code with tabs in a place that's using spaces, they may appear OK in your screen but it will fail when running it.
# %% [markdown]
-# ### Naming Conventions
+# ## Naming Conventions
# %% [markdown]
# [Camel case](https://en.wikipedia.org/wiki/Camel_case) is used in the following example, where class name is in UpperCamel, functions in lowerCamel and underscore_separation for variables names. This convention is used broadly in the python community.
@@ -142,7 +142,7 @@ def method_name(a_variable):
# %% [markdown]
-# ### Hungarian Notation
+# ## Hungarian Notation
# %% [markdown]
#
@@ -163,7 +163,7 @@ def method_name(a_variable):
number = float(entry) + offset
# %% [markdown]
-# ### Newlines
+# ## Newlines
# %% [markdown]
#
@@ -174,7 +174,7 @@ def method_name(a_variable):
#
# %% [markdown]
-# ### Syntax Choices
+# ## Syntax Choices
# %% [markdown]
# The following two snippets do the same, but the second is separated into more steps, making it more readable.
@@ -195,7 +195,7 @@ def method_name(a_variable):
# What about operator precedence? Being explicit helps to remind yourself what you are doing.
# %% [markdown]
-# ### Syntax choices
+# ## Syntax choices
# %% [markdown]
#
@@ -205,7 +205,7 @@ def method_name(a_variable):
#
# %% [markdown]
-# ### Coding Conventions
+# ## Coding Conventions
# %% [markdown]
#
@@ -220,7 +220,7 @@ def method_name(a_variable):
#
# %% [markdown]
-# ### Lint
+# ## Lint
# %% [markdown]
#
diff --git a/ch05construction/03comments.ipynb.py b/ch05construction/03comments.ipynb.py
index 82d8e879..4e7b29b9 100644
--- a/ch05construction/03comments.ipynb.py
+++ b/ch05construction/03comments.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Comments
+# # Comments
# %% [markdown]
# Let's import first the context for this chapter.
@@ -21,7 +21,7 @@
from context import *
# %% [markdown]
-# ### Why comment?
+# ## Why comment?
# %% [markdown]
#
@@ -32,7 +32,7 @@
#
# %% [markdown]
-# ### Bad Comments
+# ## Bad Comments
# %% [markdown]
#
@@ -42,7 +42,7 @@
#
# %% [markdown]
-# ### Comments which are obvious
+# ## Comments which are obvious
# %%
counter = counter + 1 # Increment the counter
@@ -50,7 +50,7 @@
pass
# %% [markdown]
-# ### Comments which could be replaced by better style
+# ## Comments which could be replaced by better style
# %% [markdown]
# The following piece of code could be a part of a game to move a turtle in a certain direction, with a particular angular velocity and step size.
@@ -86,7 +86,7 @@ def move(self):
#
# %% [markdown]
-# ### Comments vs expressive code
+# ## Comments vs expressive code
# %% [markdown]
#
@@ -99,7 +99,7 @@ def move(self):
#
# %% [markdown]
-# ### Comments which belong in an issue tracker
+# ## Comments which belong in an issue tracker
# %%
x.clear() # Code crashes here sometimes
@@ -131,7 +131,7 @@ class Agent(object):
#
# %% [markdown]
-# ### Comments which only make sense to the author today
+# ## Comments which only make sense to the author today
# %%
agent.turn() # Turtle Power!
@@ -140,14 +140,14 @@ class Agent(object):
# %% [markdown]
-# ### Comments which are unpublishable
+# ## Comments which are unpublishable
# %%
# Stupid supervisor made me write this code
# So I did it while very very drunk.
# %% [markdown]
-# ### Good commenting: pedagogical comments
+# ## Good commenting: pedagogical comments
# %% [markdown]
#
@@ -174,7 +174,7 @@ def try_me_twice():
# %% [markdown]
-# ### Good commenting: reasons and definitions
+# ## Good commenting: reasons and definitions
# %% [markdown]
#
diff --git a/ch05construction/05refactoring.ipynb.py b/ch05construction/05refactoring.ipynb.py
index 2e6b7622..051dda20 100644
--- a/ch05construction/05refactoring.ipynb.py
+++ b/ch05construction/05refactoring.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Refactoring
+# # Refactoring
# %% [markdown]
# Let's import first the context for this chapter.
@@ -26,7 +26,7 @@
# Instead of doing so, we could use a more robust approach to go from nasty ugly code to clean code in a safer way.
# %% [markdown]
-# ### Refactoring
+# ## Refactoring
# %% [markdown]
#
@@ -39,7 +39,7 @@
#
# %% [markdown]
-# ### A word from the Master
+# ## A word from the Master
# %% [markdown]
#
@@ -54,7 +54,7 @@
#
# %% [markdown]
-# ### List of known refactorings
+# ## List of known refactorings
# %% [markdown]
#
@@ -64,7 +64,7 @@
#
# %% [markdown]
-# ### Replace magic numbers with constants
+# ## Replace magic numbers with constants
# %% [markdown]
#
@@ -106,7 +106,7 @@
#
# %% [markdown]
-# ### Replace repeated code with a function
+# ## Replace repeated code with a function
# %% [markdown]
#
@@ -152,7 +152,7 @@ def can_see(source, target):
#
# %% [markdown]
-# ### Change of variable name
+# ## Change of variable name
# %% [markdown]
#
@@ -183,7 +183,7 @@ def can_see(source, target):
transcribe(gene)
# %% [markdown]
-# ### Separate a complex expression into a local variable
+# ## Separate a complex expression into a local variable
# %% [markdown]
#
@@ -211,7 +211,7 @@ def can_see(source, target):
do_something()
# %% [markdown]
-# ### Replace loop with iterator
+# ## Replace loop with iterator
# %% [markdown]
#
@@ -242,7 +242,7 @@ def can_see(source, target):
sum += value
# %% [markdown]
-# ### Replace hand-written code with library code
+# ## Replace hand-written code with library code
# %% [markdown]
#
@@ -279,7 +279,7 @@ def can_see(source, target):
#
# %% [markdown]
-# ### Replace set of arrays with array of structures
+# ## Replace set of arrays with array of structures
# %% [markdown]
#
@@ -318,7 +318,7 @@ def can_see(source, target):
#
# %% [markdown]
-# ### Replace constants with a configuration file
+# ## Replace constants with a configuration file
# %% [markdown]
#
@@ -373,7 +373,7 @@ def can_see(source, target):
#
# %% [markdown]
-# ### Replace global variables with function arguments
+# ## Replace global variables with function arguments
# %% [markdown]
#
@@ -413,7 +413,7 @@ def can_see(self, target, viewport):
# %% [markdown]
-# ### Merge neighbouring loops
+# ## Merge neighbouring loops
# %% [markdown]
#
@@ -448,7 +448,7 @@ def can_see(self, target, viewport):
# Though there may be a case where all the nests need to be built before the birds can start laying eggs.
# %% [markdown]
-# ### Break a large function into smaller units
+# ## Break a large function into smaller units
# %% [markdown]
#
@@ -494,7 +494,7 @@ def predate(predator, prey):
# %% [markdown]
-# ### Separate code concepts into files or modules
+# ## Separate code concepts into files or modules
# %% [markdown]
#
@@ -539,7 +539,7 @@ def __init__():
self.child = One()
# %% [markdown]
-# ### Refactoring is a safe way to improve code
+# ## Refactoring is a safe way to improve code
# %% [markdown]
#
@@ -552,7 +552,7 @@ def __init__():
#
# %% [markdown]
-# ### Tests and Refactoring
+# ## Tests and Refactoring
# %% [markdown]
#
@@ -567,7 +567,7 @@ def __init__():
#
# %% [markdown]
-# ### Refactoring Summary
+# ## Refactoring Summary
# %% [markdown]
#
diff --git a/ch05construction/08objects.ipynb.py b/ch05construction/08objects.ipynb.py
index de598607..200d37b2 100644
--- a/ch05construction/08objects.ipynb.py
+++ b/ch05construction/08objects.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Class design
+# # Class design
# %% [markdown]
#
@@ -58,7 +58,7 @@ def move(self, delta_t):
# ```
# %% [markdown]
-# ### UML
+# ## UML
# %% [markdown]
#
@@ -70,7 +70,7 @@ def move(self, delta_t):
#
# %% [markdown]
-# ### YUML
+# ## YUML
# %% [markdown]
# We can see a YUML model for a Particle class with `position` and `velocity` data and a `move()` method using
@@ -102,7 +102,7 @@ def yuml(model):
# The representation of the `Particle` class defined above in UML is done with a box with three sections. The name of the class goes on the top, then the name of the member variables in the middle, and the name of the methods on the bottom. We will see later why this is useful.
# %% [markdown]
-# ### Information Hiding
+# ## Information Hiding
# %% [markdown]
#
@@ -159,7 +159,7 @@ def called_inside(self):
# %% [markdown]
-# ### Property accessors
+# ## Property accessors
# %% [markdown]
#
@@ -256,7 +256,7 @@ def get_married(self, to):
# In database design, this is called [Normalisation](https://en.wikipedia.org/wiki/Database_normalization).
# %% [markdown]
-# #### UML for private/public
+# ### UML for private/public
# %% [markdown]
# We prepend a `+`/`-` on public/private member variables and methods:
@@ -266,7 +266,7 @@ def get_married(self, to):
# %% [markdown]
-# ### Class Members
+# ## Class Members
# %% [markdown]
#
@@ -300,7 +300,7 @@ def howMany(cls):
# ## Inheritance and Polymorphism
# %% [markdown]
-# ### Object-based vs Object-Oriented
+# ## Object-based vs Object-Oriented
# %% [markdown]
#
@@ -312,7 +312,7 @@ def howMany(cls):
#
# %% [markdown]
-# ### Inheritance
+# ## Inheritance
# %% [markdown]
#
@@ -321,7 +321,7 @@ def howMany(cls):
#
# %% [markdown]
-# ### Ontology and inheritance
+# ## Ontology and inheritance
# %% [markdown]
#
@@ -335,7 +335,7 @@ def howMany(cls):
#
# %% [markdown]
-# ### Inheritance in python
+# ## Inheritance in python
# %% [markdown]
#
@@ -366,7 +366,7 @@ def flew(self):
# %% [markdown]
-# ### Inheritance terminology
+# ## Inheritance terminology
# %% [markdown]
# Here are two equivalents definition, one coming from C++ and another from Java:
@@ -384,7 +384,7 @@ def flew(self):
#
# %% [markdown]
-# ### Inheritance and constructors
+# ## Inheritance and constructors
# %% [markdown]
# To use implicitly constructors from a *superclass*, we can use `super` as shown below.
@@ -404,7 +404,7 @@ def __init__(self, age, name):
# Read [Raymond Hettinger](https://twitter.com/raymondh)'s [article about `super`](https://rhettinger.wordpress.com/2011/05/26/super-considered-super/) to see various real examples.
# %% [markdown]
-# ### Inheritance UML diagrams
+# ## Inheritance UML diagrams
# %% [markdown]
# UML shows inheritance with an open triangular arrow pointing from subclass to superclass.
@@ -413,7 +413,7 @@ def __init__(self, age, name):
yuml("[Animal]^-[Bird],[Bird]^-[Eagle],[Bird]^-[Starling]%")
# %% [markdown]
-# ### Aggregation vs Inheritance
+# ## Aggregation vs Inheritance
# %% [markdown]
#
@@ -424,7 +424,7 @@ def __init__(self, age, name):
#
# %% [markdown]
-# #### Aggregation in UML
+# ### Aggregation in UML
# %% [markdown]
# The Boids situation can be represented thus:
@@ -440,7 +440,7 @@ def __init__(self, age, name):
# The asterisk represents cardinality, a model may contain multiple Boids. This is a [one to many relationship](https://en.wikipedia.org/wiki/One-to-many_(data_model)). [Many to many relationship](https://en.wikipedia.org/wiki/Many-to-many_(data_model)) is shown with `*` on both sides.
# %% [markdown]
-# #### Refactoring to inheritance
+# ### Refactoring to inheritance
# %% [markdown]
#
@@ -495,7 +495,7 @@ def __init__(self, age, owner):
# %% [markdown]
-# ### Polymorphism
+# ## Polymorphism
# %%
class Dog:
@@ -531,7 +531,7 @@ def noise(self):
#
# %% [markdown]
-# ### Polymorphism and Inheritance
+# ## Polymorphism and Inheritance
# %% [markdown]
#
@@ -567,7 +567,7 @@ class Poodle(Dog):
# %% [markdown]
-# ### Undefined Functions and Polymorphism
+# ## Undefined Functions and Polymorphism
# %% [markdown]
#
@@ -591,7 +591,7 @@ class Worm(Animal):
# %% [markdown]
-# ### Refactoring to Polymorphism
+# ## Refactoring to Polymorphism
# %% [markdown]
#
@@ -620,7 +620,7 @@ def noise(self):
# which is better replaced by the code above.
# %% [markdown]
-# ### Interfaces and concepts
+# ## Interfaces and concepts
# %% [markdown]
#
@@ -634,7 +634,7 @@ def noise(self):
#
# %% [markdown]
-# ### Interfaces in UML
+# ## Interfaces in UML
# %% [markdown]
# Interfaces implementation (a common ancestor that doesn't do anything but defines methods to share) in UML is indicated thus:
@@ -643,7 +643,7 @@ def noise(self):
yuml("[<
>]^-.-[Dog]")
# %% [markdown]
-# ### Further UML
+# ## Further UML
# %% [markdown]
#
diff --git a/ch05construction/09patterns.ipynb.py b/ch05construction/09patterns.ipynb.py
index f61ebc42..1e4b1ae7 100644
--- a/ch05construction/09patterns.ipynb.py
+++ b/ch05construction/09patterns.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Patterns
+# # Patterns
# %% [markdown]
-# ### Class Complexity
+# ## Class Complexity
#
#
# We've seen that using object orientation can produce quite complex class structures, with classes owning each other, instantiating each other,
@@ -28,7 +28,7 @@
# > - To reuse functionality: should I use inheritance, or add class variable which it is delegated to?
# %% [markdown]
-# #### Inheritance vs composition
+# ### Inheritance vs composition
#
# The last point is known as `is-a` vs `has-a` or inheritance vs composition.
#
@@ -61,7 +61,7 @@
# We've linked to an article which carries out a deep dive on this topic in the [other resources section](#Other-resources)
# %% [markdown]
-# ### Design Patterns
+# ## Design Patterns
# %% [markdown]
#
@@ -74,7 +74,7 @@
#
# %% [markdown]
-# ### Reading a pattern
+# ## Reading a pattern
# %% [markdown]
#
@@ -93,7 +93,7 @@
#
# %% [markdown]
-# ### Introducing Some Patterns
+# ## Introducing Some Patterns
# %% [markdown]
#
@@ -111,7 +111,7 @@
# check out another explanation from the [other resources section](#Other-resources)
# %% [markdown]
-# ### Supporting code
+# ## Supporting code
# %% pycharm={"name": "#%%\n"}
# %matplotlib inline
@@ -136,7 +136,7 @@ def yuml(model):
#
# %% [markdown]
-# ### Strategy pattern example: sunspots
+# ## Strategy pattern example: sunspots
# %% pycharm={"name": "#%%\n"}
import csv
@@ -181,7 +181,7 @@ def load_sunspots():
# %% [markdown]
-# ### Sunspot cycle has periodicity
+# ## Sunspot cycle has periodicity
# %% pycharm={"name": "#%%\n"}
# Use Fast Fourier Transform
@@ -197,7 +197,7 @@ def load_sunspots():
# %% [markdown]
-# ### Years are not constant length
+# ## Years are not constant length
# %% [markdown]
# After we've started out analysis we realise there's a potential problem with this analysis:
@@ -217,7 +217,7 @@ def load_sunspots():
# by quadrature to find the mean frequency, or choosing the largest single value.
# %% [markdown]
-# ### Number of child-classes can increase quickly
+# ## Number of child-classes can increase quickly
# %% [markdown]
# We could implement a base class for our common code between the different approaches,
@@ -393,7 +393,7 @@ def transform(self, series):
# * A class wants its subclasses to specify the objects it creates
# %% [markdown]
-# ### Factory UML
+# ## Factory UML
#
# %% pycharm={"name": "#%%\n"}
@@ -405,7 +405,7 @@ def transform(self, series):
# This is all very abstract, so let's get a clearer idea of what that means with an example.
# %% [markdown]
-# ### Initial Example
+# ## Initial Example
# %% [markdown]
# We have created code that can analyse imaging data from different types of instrument.
@@ -471,7 +471,7 @@ def _get_colour_image(self, normalised_data):
return normalised_data
# %% [markdown]
-# ### Implemented classes
+# ## Implemented classes
#
# Here are four example child classes that have implemented their own internal methods for normalising
# the image data and creating a coloured image. We can use these in exactly the same way as our
@@ -666,7 +666,7 @@ def read_image(self, path):
# %% [markdown]
-# ### Builder example
+# ## Builder example
# %% [markdown]
# Imagine that we have a large model with many parameters that we want to run.
@@ -686,7 +686,7 @@ def __init__(self, xsize, ysize,
# %% [markdown]
-# #### Builder preferred to complex constructor
+# ### Builder preferred to complex constructor
# %% [markdown]
# However, long constructors easily become very complicated.
@@ -743,7 +743,7 @@ def validate(self):
#
# %% [markdown]
-# ### Using a builder
+# ## Using a builder
# %% pycharm={"name": "#%%\n"}
builder = ModelBuilder()
@@ -757,7 +757,7 @@ def validate(self):
model.simulate()
# %% [markdown]
-# ### Avoid staged construction without a builder.
+# ## Avoid staged construction without a builder.
# %% [markdown]
#
@@ -779,7 +779,7 @@ def validate(self):
#
# %% [markdown]
-# ### Other resources
+# ## Other resources
#
# There are a lot of design patterns and one explanation might not work well for all people so here are some extra
# sources of information about them. Spending some time to understand them can pay off in the future so you don't
diff --git a/ch05construction/10boids.ipynb.py b/ch05construction/10boids.ipynb.py
index 4a747ded..dee5d154 100644
--- a/ch05construction/10boids.ipynb.py
+++ b/ch05construction/10boids.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## Exercise: Refactoring The Bad Boids
+# # Exercise: Refactoring The Bad Boids
# %% [markdown]
-# ### Bad_Boids
+# ## Bad_Boids
# %% [markdown]
#
@@ -113,7 +113,7 @@ def animate(frame):
HTML(anim.to_jshtml())
# %% [markdown]
-# ### Your Task
+# ## Your Task
# %% [markdown]
#
@@ -121,7 +121,7 @@ def animate(frame):
#
# %% [markdown]
-# ### A regression test
+# ## A regression test
# %% [markdown]
#
@@ -147,7 +147,7 @@ def animate(frame):
# ```
# %% [markdown]
-# ### Invoking the test
+# ## Invoking the test
# %% [markdown]
#
@@ -171,7 +171,7 @@ def animate(frame):
# ```
# %% [markdown]
-# ### Make the regression test fail
+# ## Make the regression test fail
# %% [markdown]
# Check the tests pass:
@@ -192,7 +192,7 @@ def animate(frame):
# ```
# %% [markdown]
-# ### Start Refactoring
+# ## Start Refactoring
# %% [markdown]
#
diff --git a/ch07dry/020Functional.ipynb.py b/ch07dry/020Functional.ipynb.py
index 072592e6..96e20277 100644
--- a/ch07dry/020Functional.ipynb.py
+++ b/ch07dry/020Functional.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Functional programming
+# # Functional programming
# %% [markdown]
# We have previously seen the object-oriented style of programming, and how to organise our code according to it using objects, classes and inheritance. While widely-adopted and very useful, this is not the only way of writing code. The [*functional paradigm*](https://en.wikipedia.org/wiki/Functional_programming), as the name suggests, emphasises functions as building blocks of programs.
@@ -23,7 +23,7 @@
# However, being aware of different paradigms and styles gives you access to more techniques that you can use to write, structure and reason about your code.
# %% [markdown]
-# ### Functions within functions
+# ## Functions within functions
# %% [markdown]
# Programs are composed of functions: they take data in (which we call
@@ -211,7 +211,7 @@ def _adder(a):
# This may seem like an overly complicated process - and, in some cases, it is! However, this pattern of functions that return functions (or even take them as arguments!) can be very useful. In fact, it is the basis of decorators, a Python feature that we will discuss more [in this chapter](./025Iterators.html#Decorators) [[notebook](./025Iterators.ipynb#Decorators)].
# %% [markdown]
-# ### Closures
+# ## Closures
# %% [markdown]
# You may have noticed something a bit weird:
@@ -247,7 +247,7 @@ def greet():
greet()
# %% [markdown]
-# ### Map and Reduce
+# ## Map and Reduce
# %% [markdown]
# We often want to apply a function to each variable in an array, to return a new array. We can do this with a list comprehension:
@@ -401,7 +401,7 @@ def my_max(data):
#
# %% [markdown]
-# ### Lambda Functions
+# ## Lambda Functions
# %% [markdown]
#
@@ -492,7 +492,7 @@ def my_max(data):
my_max([2, 5, 10, -11, -5])
# %% [markdown]
-# ### Using functional programming for numerical methods
+# ## Using functional programming for numerical methods
# %% [markdown]
#
diff --git a/ch07dry/025Iterators.ipynb.py b/ch07dry/025Iterators.ipynb.py
index 23b57a8a..26d7fae7 100644
--- a/ch07dry/025Iterators.ipynb.py
+++ b/ch07dry/025Iterators.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Iterators and Generators
+# # Iterators and Generators
# %% [markdown]
# In Python, anything which can be iterated over is called an iterable:
@@ -41,7 +41,7 @@
# how they work, when to use them, how to create our own.
# %% [markdown]
-# ### Iterators
+# ## Iterators
# %% [markdown]
# Consider the basic python `range` function:
@@ -108,7 +108,7 @@
# %% [markdown]
-# ### Defining Our Own Iterable
+# ## Defining Our Own Iterable
# %% [markdown]
# When we write `next(a)`, under the hood Python tries to call the `__next__()` method of `a`. Similarly, `iter(a)` calls `a.__iter__()`.
@@ -169,7 +169,7 @@ def __next__(self):
sum(fib_iterator(1000))
# %% [markdown]
-# ### A shortcut to iterables: the `__iter__` method
+# ## A shortcut to iterables: the `__iter__` method
# %% [markdown]
# In fact, we don't always have to define both `__iter__` and `__next__`!
@@ -222,7 +222,7 @@ def show(self):
# an iterator.
# %% [markdown]
-# ### Generators
+# ## Generators
# %% [markdown]
# There's a fair amount of "boiler-plate" in the above class-based definition of
@@ -305,7 +305,7 @@ def yield_fibs(limit, seed1=1, seed2=1):
# Iterables and generators can be used to achieve complex behaviour, especially when combined with functional programming. In fact, Python itself contains some very useful language features that make use of these practices: context managers and decorators. We have already seen these in this class, but here we discuss them in more detail.
# %% [markdown]
-# ### Context managers
+# ## Context managers
# %% [markdown]
# [We have seen before](../ch02data/060files.html#Closing-files) [[notebook](../ch02data/060files.ipynb#Closing-files)] that, instead of separately `open`ing and `close`ing a file, we can have
@@ -377,7 +377,7 @@ def verbose_context(name):
#
# %% [markdown]
-# ### Decorators
+# ## Decorators
# %% [markdown]
#
@@ -442,7 +442,7 @@ def hello(name):
# The remainder of this page contains an example of the flexibility of the features discussed above. Specifically, it shows how generators and context managers can be combined to create a testing framework like the one previously seen in the course.
# %% [markdown]
-# ### Test generators
+# ## Test generators
#
#
# A few weeks ago we saw a test which loaded its test cases from a YAML file and
@@ -476,7 +476,7 @@ def test_greeter():
# Each time a function beginning with `test_` does a `yield` it results in another test.
# %% [markdown]
-# ### Negative test contexts managers
+# ## Negative test contexts managers
# %% [markdown]
# We have seen this:
@@ -512,7 +512,7 @@ def reimplement_raises(exception):
x.foo()
# %% [markdown]
-# ### Negative test decorators
+# ## Negative test decorators
# %% [markdown]
# Some frameworks, like `nose`, also implement a very nice negative test decorator, which lets us marks tests that we know should produce an exception:
diff --git a/ch07dry/040Exceptions.ipynb.py b/ch07dry/040Exceptions.ipynb.py
index 48ce7e3c..68c728d8 100644
--- a/ch07dry/040Exceptions.ipynb.py
+++ b/ch07dry/040Exceptions.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Exceptions
+# # Exceptions
# %% [markdown]
#
@@ -53,7 +53,7 @@
# %% [markdown]
-# ### Create your own Exception
+# ## Create your own Exception
# %% [markdown]
# When we were looking at testing, we saw that it is important for code to crash with a meaningful exception type when something is wrong.
@@ -136,7 +136,7 @@ def __str__(self):
# Therefore, we should be specific and catch only the type of error we want.
# %% [markdown]
-# ### Managing multiple exceptions
+# ## Managing multiple exceptions
# %% [markdown]
# Let's create two credential files to read
@@ -288,7 +288,7 @@ def f1(x):
f1(3)
# %% [markdown]
-# ### Design with Exceptions
+# ## Design with Exceptions
# %% [markdown]
#
diff --git a/ch07dry/050OperatorsExample.ipynb.py b/ch07dry/050OperatorsExample.ipynb.py
index fee0fc04..9ffbe426 100644
--- a/ch07dry/050OperatorsExample.ipynb.py
+++ b/ch07dry/050OperatorsExample.ipynb.py
@@ -18,7 +18,7 @@
# Warning: Advanced Topic!
# %% [markdown]
-# ### Setup for this notebook
+# ## Setup for this notebook
# %% [markdown]
# We need to use a metaprogramming trick to make this teaching notebook work.
@@ -40,7 +40,7 @@ def decorator(extending_class):
# %% [markdown]
-# ### Operator overloading
+# ## Operator overloading
# %% [markdown]
#
diff --git a/ch07dry/060Metaprogramming.ipynb.py b/ch07dry/060Metaprogramming.ipynb.py
index 6d3bfece..c1dba0b5 100644
--- a/ch07dry/060Metaprogramming.ipynb.py
+++ b/ch07dry/060Metaprogramming.ipynb.py
@@ -12,13 +12,13 @@
# ---
# %% [markdown]
-# ## Metaprogramming
+# # Metaprogramming
# %% [markdown]
# Warning: Advanced topic!
# %% [markdown]
-# ### Metaprogramming globals
+# ## Metaprogramming globals
# %% [markdown]
#
@@ -179,7 +179,7 @@ def buy(self):
#
# %% [markdown]
-# ### Metaprogramming class attributes
+# ## Metaprogramming class attributes
# %% [markdown]
# We can metaprogram the attributes of a **module** using the globals() function.
@@ -286,7 +286,7 @@ def broken_birth_year(b_instance):
# %% [markdown]
-# ### Metaprogramming function locals
+# ## Metaprogramming function locals
# %% [markdown]
# We can access the attribute dictionary for the local namespace inside a
@@ -313,7 +313,7 @@ def __init__(self, name, age, job, children_count):
# %% [markdown]
-# ### Metaprogramming warning!
+# ## Metaprogramming warning!
# %% [markdown]
#
diff --git a/ch08performance/020numpy.ipynb.py b/ch08performance/020numpy.ipynb.py
index 91da6a29..a9ed89c2 100644
--- a/ch08performance/020numpy.ipynb.py
+++ b/ch08performance/020numpy.ipynb.py
@@ -12,10 +12,10 @@
# ---
# %% [markdown]
-# ## NumPy for Performance
+# # NumPy for Performance
# %% [markdown]
-# ### NumPy constructors
+# ## NumPy constructors
# %% [markdown]
# We saw previously that NumPy's core type is the `ndarray`, or N-Dimensional Array:
@@ -84,7 +84,7 @@
print(values)
# %% [markdown]
-# ### Arraywise Algorithms
+# ## Arraywise Algorithms
# %% [markdown]
# We can use this to apply the mandelbrot algorithm to whole *ARRAYS*
@@ -239,7 +239,7 @@ def mandel_numpy(position, limit=50):
# Note that we didn't compare two arrays to get our logical array, but an array to a scalar integer -- this was broadcasting again.
# %% [markdown]
-# ### More Mandelbrot
+# ## More Mandelbrot
# %% [markdown]
# Of course, we didn't calculate the number-of-iterations-to-diverge, just whether the point was in the set.
@@ -306,7 +306,7 @@ def mandel5(position, limit=50):
# Probably not worth the time I spent thinking about it!
# %% [markdown]
-# ### NumPy Testing
+# ## NumPy Testing
# %% [markdown]
# Now, let's look at calculating those residuals, the differences between the different datasets.
@@ -370,7 +370,7 @@ def mandel5(position, limit=50):
# %% [markdown]
-# ### Arraywise operations are fast
+# ## Arraywise operations are fast
# %% [markdown]
# Note that we might worry that we carry on calculating the mandelbrot values for points that have already diverged.
@@ -414,7 +414,7 @@ def mandel6(position, limit=50):
# Complicating your logic to avoid calculations sometimes therefore slows you down. The only way to know is to **measure**
# %% [markdown]
-# ### Indexing with arrays
+# ## Indexing with arrays
# %% [markdown]
# We've been using Boolean arrays a lot to get access to some elements of an array. We can also do this with integers:
diff --git a/ch08performance/040cython.ipynb.py b/ch08performance/040cython.ipynb.py
index 2cd5411a..94158d60 100644
--- a/ch08performance/040cython.ipynb.py
+++ b/ch08performance/040cython.ipynb.py
@@ -12,11 +12,11 @@
# ---
# %% [markdown]
-# ## Cython
+# # Cython
# Cython can be viewed as an extension of Python where variables and functions are annotated with extra information, in particular types. The resulting Cython source code will be compiled into optimized C or C++ code, and thereby yielding substantial speed-up of slow Python code. In other words, Cython provides a way of writing Python with comparable performance to that of C/C++.
# %% [markdown]
-# ### Start Coding in Cython
+# ## Start Coding in Cython
# %% [markdown]
# Cython code must, unlike Python, be compiled. This happens in the following stages:
@@ -92,7 +92,7 @@ def mandel(position, limit=50):
# We have improved the performance of a factor of 1.5 by just using the Cython compiler, **without changing the code**!
# %% [markdown]
-# ### Cython with C Types
+# ## Cython with C Types
# But we can do better by telling Cython what C data type we would use in the code. Note we're not actually writing C, we're writing Python with C types.
# %% [markdown]
@@ -144,7 +144,7 @@ def mandel(position, limit=50):
# %timeit a = call_typed_mandel_cython(complex(0, 0))
# %% [markdown]
-# ### Cython with numpy ndarray
+# ## Cython with numpy ndarray
# You can use NumPy from Cython exactly the same as in regular Python, but by doing so you are losing potentially high speedups because Cython has support for fast access to NumPy arrays.
# %%
@@ -203,7 +203,7 @@ def mandel(position, limit=50):
# %timeit numpy_cython_2(values) # vectorize
# %% [markdown]
-# ### Calling C functions from Cython
+# ## Calling C functions from Cython
#
# **Example: compare `sin()` from Python and C library**
diff --git a/ch08performance/050scaling.ipynb.py b/ch08performance/050scaling.ipynb.py
index 4b84c9a0..ee1b7246 100644
--- a/ch08performance/050scaling.ipynb.py
+++ b/ch08performance/050scaling.ipynb.py
@@ -12,7 +12,7 @@
# ---
# %% [markdown]
-# ## Scaling for containers and algorithms
+# # Scaling for containers and algorithms
# %% [markdown]
# We've seen that NumPy arrays are really useful. Why wouldn't we always want to use them for data which is all the same type?
@@ -181,7 +181,7 @@ def totime():
# 
# %% [markdown]
-# ### Dictionary performance
+# ## Dictionary performance
# %% [markdown]
# For another example, let's consider the performance of a dictionary versus a couple of other ways in which we could implement an associative array.