From a1c97f14d14a0de970403e5e679731592921022e Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <MichielCottaar@gmail.com> Date: Thu, 15 Feb 2018 12:41:41 +0000 Subject: [PATCH] Implemented MJ's comments --- getting_started/02_text_io.ipynb | 10 ++--- getting_started/02_text_io.md | 10 ++--- getting_started/07_jupyter.ipynb | 66 +++++++++++++++++++++++++++++--- getting_started/07_jupyter.md | 7 +++- 4 files changed, 75 insertions(+), 18 deletions(-) diff --git a/getting_started/02_text_io.ipynb b/getting_started/02_text_io.ipynb index d329bea..a6333b9 100644 --- a/getting_started/02_text_io.ipynb +++ b/getting_started/02_text_io.ipynb @@ -110,7 +110,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "> Any lines starting with `!` will be interpreted as shell commands by ipython. It is great when playing around in the ipython notebook or in the ipython terminal, however it is an ipython-only feature and hence is not available when writing python scripts. How to call shell commands from python will be discusses in the `scripts` practical.\n", + "> Any lines starting with `!` will be interpreted as shell commands by ipython. It is great when playing around in the ipython notebook or in the ipython terminal, however it is an ipython-only feature and hence is not available when writing python scripts. How to call shell commands from python will be discussed in the `scripts` practical.\n", "\n", "If we want to add to the existing file we can open it in the append mode:" ] @@ -375,8 +375,8 @@ "outputs": [], "source": [ "from datetime import datetime\n", - "print(str(datetime.now())\n", - "print(repr(datetime.now())" + "print('str(): ', str(datetime.now()))\n", + "print('repr(): ', repr(datetime.now()))" ] }, { @@ -492,7 +492,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that the variable `:` delimiter separates the variable identifies on the left from the formatting rules on the right.\n", + "Note that the variable `:` delimiter separates the variable identifiers on the left from the formatting rules on the right.\n", "\n", "Finally the new, fancy formatted string literals (only available in python 3.6+).\n", "This new format is very similar to the recommended style, except that all placeholders are automatically evaluated in the local environment at the time the template is defined.\n", @@ -596,7 +596,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "> We use the syntax `[<expr> for <element> in <sequence>]` here which applies the `expr` to each `element` in the `sequence` and returns the resulting list. This is a convenient form in python to create a new list from the old one.\n", + "> We use the syntax `[<expr> for <element> in <sequence>]` here which applies the `expr` to each `element` in the `sequence` and returns the resulting list. This is a list comprehension - a convenient form in python to create a new list from the old one.\n", "\n", "<a class=\"anchor\" id=\"converting-strings-to-numbers\"></a>\n", "### Converting strings to numbers\n", diff --git a/getting_started/02_text_io.md b/getting_started/02_text_io.md index da04b17..efc40b9 100644 --- a/getting_started/02_text_io.md +++ b/getting_started/02_text_io.md @@ -52,7 +52,7 @@ Note that no new line characters get added automatically. We can investigate the ``` !cat 02_text_io/my_file ``` -> Any lines starting with `!` will be interpreted as shell commands by ipython. It is great when playing around in the ipython notebook or in the ipython terminal, however it is an ipython-only feature and hence is not available when writing python scripts. How to call shell commands from python will be discusses in the `scripts` practical. +> Any lines starting with `!` will be interpreted as shell commands by ipython. It is great when playing around in the ipython notebook or in the ipython terminal, however it is an ipython-only feature and hence is not available when writing python scripts. How to call shell commands from python will be discussed in the `scripts` practical. If we want to add to the existing file we can open it in the append mode: ``` @@ -166,8 +166,8 @@ The `datetime` module contains various classes and functions to work with dates Here we will look at the alternative string representations of the `datetime` object itself: ``` from datetime import datetime -print(str(datetime.now()) -print(repr(datetime.now()) +print('str(): ', str(datetime.now())) +print('repr(): ', repr(datetime.now())) ``` Note that the result from `str()` is human-readable as a date, while the result from `repr()` is more useful if you wanted to recreate the `datetime` object. @@ -222,7 +222,7 @@ b = 1 / 3 print('{:.3f} = {} + {:.3f}'.format(a + b, a, b)) print('{total:.3f} = {a} + {b:.3f}'.format(a=a, b=b, total=a+b)) ``` -Note that the variable `:` delimiter separates the variable identifies on the left from the formatting rules on the right. +Note that the variable `:` delimiter separates the variable identifiers on the left from the formatting rules on the right. Finally the new, fancy formatted string literals (only available in python 3.6+). This new format is very similar to the recommended style, except that all placeholders are automatically evaluated in the local environment at the time the template is defined. @@ -269,7 +269,7 @@ print(list_with_whitespace) list_without_whitespace = [individual_string.strip() for individual_string in list_with_whitespace] print(list_without_whitespace) ``` -> We use the syntax `[<expr> for <element> in <sequence>]` here which applies the `expr` to each `element` in the `sequence` and returns the resulting list. This is a convenient form in python to create a new list from the old one. +> We use the syntax `[<expr> for <element> in <sequence>]` here which applies the `expr` to each `element` in the `sequence` and returns the resulting list. This is a list comprehension - a convenient form in python to create a new list from the old one. <a class="anchor" id="converting-strings-to-numbers"></a> ### Converting strings to numbers diff --git a/getting_started/07_jupyter.ipynb b/getting_started/07_jupyter.ipynb index bed1e2d..d80ba60 100644 --- a/getting_started/07_jupyter.ipynb +++ b/getting_started/07_jupyter.ipynb @@ -38,6 +38,22 @@ "string.capwords?" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This also works for any of the magic commands discussed below" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%run?" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -91,13 +107,25 @@ "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 ({:d}, {:d})'.format(r_lower, r_upper" + "print('Bounds are ({:.0f}, {:.0f})'.format(r_lower, r_upper))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "---\n", + "\n", + "## Running python scripts\n", + "We could run a python script as a shell command above. However, it will often be more convenient to use `%run` instead.\n", + "> ```\n", + "> %run <python script> <arguments...>\n", + "> ```\n", + "Arguments are provided in exactly the same way as if you called `python` in the shell. The main advantages are:\n", + "- Any top-level variables will be made available to you after the script finishes\n", + "- All the debugging/timing/profiling tools discussed below will be available to you\n", + "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\n", + "\n", "---\n", "\n", "## Running other programming languages\n", @@ -122,7 +150,7 @@ "source": [ "---\n", "\n", - "## Timing code\n", + "## Timing/profiling code\n", "We can time a line of code with `%time` or a whole code block using `%%time`.\n", "To get the time needed to calculate the sine of a million random numbers:" ] @@ -156,6 +184,24 @@ "%timeit np.sin(numbers) # this will take a few seconds to run" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import nibabel as nib\n", + "import os.path as op\n", + "%prun nib.load(op.expandvars('${FSLDIR}/data/standard/FMRIB58_FA_1mm.nii.gz'))" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -174,6 +220,10 @@ "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", @@ -208,7 +258,7 @@ "\n", "> WARNING: you need to quit the debugger before any further commands will run (type `q` into the prompt)!\n", "\n", - "If you always want to enter the debugger when an error is raised you can call `%pdb on` at any time (call `%pdf off` to rever this)\n", + "If you always want to enter the debugger when an error is raised you can call `%pdb on` at any time (call `%pdf off` to reverse this)\n", "\n", "---\n", "\n", @@ -233,7 +283,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "> Keep in mind that as soon as you have started plotting you can no longer change your backend without restarting python.\n", + "> Keep in mind that as soon as you have started plotting you can no longer change your backend without exiting the python interpreter and restarting `python` (note that in the jupyter notebook you can just press `Restart` in the `Kernel` menu).\n", "\n", "To do the equivalent in a python script would look like\n", "> ```\n", @@ -264,6 +314,7 @@ "> mpl.use(<backend>)\n", "> from matplotlib.pylab import *\n", "> ```\n", + "> The last line imports everything from the matplotlib.pylab module into the namespace.\n", "\n", "I start most of my notebooks or terminals with the `%pylab` command, because afterwards I can just do stuff like:" ] @@ -283,6 +334,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "The main disadvantage is that it will not be obvious to the naive reader of this code, whether functions like `linspace`, `sin`, or `plot` are originate from numpy, matplotlib, or are built-in.\n", + "This is why we dont recommend `from <module> import *` statements in any longer code or code you intend to share.\n", + "\n", "---\n", "\n", "## Exporting code from the Jupyter notebook\n", @@ -333,7 +387,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python script_from_notebook.py" + "%run script_from_notebook.py" ] }, { @@ -344,7 +398,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 990f4fe..d5e9de6 100644 --- a/getting_started/07_jupyter.md +++ b/getting_started/07_jupyter.md @@ -130,7 +130,7 @@ Try to check the value of `a_list` and `local_list` from within the debugger. > WARNING: you need to quit the debugger before any further commands will run (type `q` into the prompt)! -If you always want to enter the debugger when an error is raised you can call `%pdb on` at any time (call `%pdf off` to rever this) +If you always want to enter the debugger when an error is raised you can call `%pdb on` at any time (call `%pdf off` to reverse this) --- @@ -143,7 +143,7 @@ When failing to provide a backend it will simply use the default (which is usual ``` %matplotlib nbagg ``` -> Keep in mind that as soon as you have started plotting you can no longer change your backend without restarting python. +> Keep in mind that as soon as you have started plotting you can no longer change your backend without exiting the python interpreter and restarting `python` (note that in the jupyter notebook you can just press `Restart` in the `Kernel` menu). To do the equivalent in a python script would look like > ``` @@ -163,6 +163,7 @@ This is equivalent in python code to: > mpl.use(<backend>) > from matplotlib.pylab import * > ``` +> The last line imports everything from the matplotlib.pylab module into the namespace. I start most of my notebooks or terminals with the `%pylab` command, because afterwards I can just do stuff like: ``` @@ -170,6 +171,8 @@ x = linspace(0, pi, 301) y = sin(x) plot(x, y, 'r-') ``` +The main disadvantage is that it will not be obvious to the naive reader of this code, whether functions like `linspace`, `sin`, or `plot` are originate from numpy, matplotlib, or are built-in. +This is why we dont recommend `from <module> import *` statements in any longer code or code you intend to share. --- -- GitLab