diff --git a/getting_started/07_jupyter.ipynb b/getting_started/07_jupyter.ipynb
index 6d743be8f5f8c69db2ba2dc12a8e315e3dc13f10..bed1e2d09b1e6fbe9baeaf5413c785905821f70b 100644
--- a/getting_started/07_jupyter.ipynb
+++ b/getting_started/07_jupyter.ipynb
@@ -91,7 +91,7 @@
    "source": [
     "r = !fslstats ${FSLDIR}/data/standard/FMRIB58_FA_1mm.nii.gz -r\n",
     "r_lower, r_upper = [float(element) for element in r[0].split()]\n",
-    "print('Bounds are ({:.0f}, {:.0f})'.format(r_lower, r_upper))"
+    "print('Bounds are ({:d}, {:d})'.format(r_lower, r_upper"
    ]
   },
   {
@@ -174,10 +174,6 @@
    "source": [
     "import numpy as np\n",
     "def total(a_list):\n",
-    "    \"\"\"Calculate the total of a list.\n",
-    "\n",
-    "    This is a very naive (not recommended) and bugged implementation\n",
-    "    \"\"\"\n",
     "    # create local copy befor changing the input\n",
     "    local_list = list(a_list)\n",
     "    total = 0.\n",
@@ -348,7 +344,7 @@
     "\n",
     "## Exporting code from the Ipython terminal\n",
     "You can access the full history of your session using `%history`.\n",
-    "To save the history to a file use `%history -f <filename>`.\n",
+    "To save the history to a file use `%history -f <filename>`\n",
     "You will probably have to clean a lot of erroneous commands you typed from that file before you are able to run it as a script."
    ]
   }
diff --git a/getting_started/07_jupyter.md b/getting_started/07_jupyter.md
index 9924b38fad0c17c98e38062a0fe6d0a3a7e7dffa..990f4fea79edb6c3ac6cdbd27c3091956b0ec644 100644
--- a/getting_started/07_jupyter.md
+++ b/getting_started/07_jupyter.md
@@ -25,6 +25,11 @@ import string
 string.capwords?
 ```
 
+This also works for any of the magic commands discussed below
+```
+%run?
+```
+
 Alternatively you can put two questions marks to get the complete code for the method or object class
 ```
 import string
@@ -50,6 +55,18 @@ print('Bounds are ({:.0f}, {:.0f})'.format(r_lower, r_upper))
 
 ---
 
+## Running python scripts
+We could run a python script as a shell command above. However, it will often be more convenient to use `%run` instead.
+> ```
+> %run <python script> <arguments...>
+> ```
+Arguments are provided in exactly the same way as if you called `python` in the shell. The main advantages are:
+- Any top-level variables will be made available to you after the script finishes
+- All the debugging/timing/profiling tools discussed below will be available to you
+A common workflow, when writing a python script is to have an Ipython terminal open next to your text editor and regularly use %run to test the script
+
+---
+
 ## Running other programming languages
 In the notebook you can include a whole code block using another language by using `%%<language>` (for many languages you will have to install a toolkit first, just google your favorite language besides python)
 ```
@@ -61,7 +78,7 @@ done
 
 ---
 
-## Timing code
+## Timing/profiling code
 We can time a line of code with `%time` or a whole code block using `%%time`.
 To get the time needed to calculate the sine of a million random numbers:
 ```
@@ -77,6 +94,13 @@ numbers = np.random.rand(10)
 %timeit np.sin(numbers)  # this will take a few seconds to run
 ```
 
+Finally, if you want to figure out what part of the code is actually slowing you down you can use `%prun`, which gives you an overview of how long the interpreter spent in each method:
+```
+import nibabel as nib
+import os.path as op
+%prun nib.load(op.expandvars('${FSLDIR}/data/standard/FMRIB58_FA_1mm.nii.gz'))
+```
+
 ---
 
 ## Debugging
@@ -170,7 +194,7 @@ print('sin(3) is ', np.sin(3))
 
 We can now run this script
 ```
-!python script_from_notebook.py
+%run script_from_notebook.py
 ```
 
 ---