Commit 04f898f4 authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

Merge branch 'enh/virtual_mini_pytreat_intro_purple_monkey_dishwasher' into 'master'

virtual mini pytreat intro

See merge request fsl/pytreat-practicals-2020!23
parents c131e3e7 d1bb3f45
% The purpose of this comment is purely
% to make life difficult for you. Sorry
% about that. I'm not really sorry.
128.3 100.8 67.2 120.1 150.2 53.0 64.2 139.3 46.7 118.1 125.8 153.1 83.2 115.9 3.4 126.3 92.2 104.7 131.2 29.3
89.3 118.8 119.2 80.1 121.2 35.0 66.2 153.3 43.7 102.1 147.8 160.1 94.2 140.9 70.4 124.3 124.2 93.7 100.2 32.3
91.3 146.8 137.2 129.1 157.2 -22.0 75.2 90.3 33.7 86.1 74.8 90.1 114.2 81.9 72.4 135.3 85.2 102.7 58.2 55.3
75.3 87.8 84.2 112.1 131.2 57.0 150.2 73.3 41.7 110.1 78.8 102.1 116.2 134.9 34.4 74.3 150.2 52.7 89.2 21.3
79.3 83.8 78.2 103.1 96.2 26.0 151.2 122.3 46.7 113.1 143.8 80.1 61.2 136.9 8.4 94.3 76.2 123.7 150.2 10.3
93.3 157.8 154.2 79.1 155.2 8.0 63.2 120.3 12.7 130.1 105.8 111.1 66.2 99.9 54.4 120.3 113.2 128.7 110.2 46.3
111.3 126.8 65.2 90.1 101.2 36.0 116.2 139.3 36.7 91.1 88.8 94.1 90.2 92.9 -0.6 46.3 80.2 105.7 88.2 -11.7
149.3 119.8 134.2 124.1 89.2 21.0 133.2 113.3 28.7 139.1 136.8 82.1 141.2 90.9 11.4 97.3 109.2 137.7 120.2 32.3
141.3 149.8 115.2 115.1 105.2 51.0 77.2 130.3 -4.3 124.1 141.8 162.1 95.2 130.9 -10.6 114.3 132.2 134.7 79.2 69.3
141.3 77.8 135.2 167.1 103.2 55.0 153.2 68.3 33.7 136.1 125.8 85.1 148.2 114.9 76.4 57.3 147.2 125.7 153.2 45.3
13,7,3,18,15,3,12,11,9,9
13,1,7,17,16,13,18,9,18,6
9,19,16,3,18,3,19,12,9,6
2,11,6,12,2,11,15,9,3,9
2,12,1,7,4,3,6,6,2,4
10,8,14,1,17,19,8,19,2,9
18,14,2,11,17,14,6,16,14,18
6,8,13,16,11,17,16,5,16,15
6,5,4,18,6,14,19,8,4,15
15,17,12,10,17,12,5,9,18,6
Congratulations, you have read your first file from Python!
1 3
14 3
4 7
12 5
15 5
14 4
15 19
7 17
7 15
16 3
15 14
17 9
7 8
4 5
15 4
11 5
17 10
3 19
14 4
18 3
%% Cell type:markdown id: tags:
# Welcome to the WIN Virtual Mini PyTreat 2020!
This notebook is available at:
https://git.fmrib.ox.ac.uk/fsl/pytreat-practicals-2020/-/tree/master/talks%2Fvirtual_intro/intro.ipynb
If you have FSL installed and you'd like to follow along *interactively*,
follow the instructions for attendees in the `README.md` file of the above
repository, and then open the `talks/virtual_intro/intro.ipynb` notebook.
# Contents
* [Introduction](#introduction)
* [Python in a nutshell](#python-in-a-nutshell)
* [Different ways of running Python](#different-ways-of-running-python)
* [Variables and basic types](#variables-and-basic-types)
* [Integer and floating point scalars](#integer-and-floating-point-scalars)
* [Strings](#strings)
* [Lists and tuples](#lists-and-tuples)
* [Dictionaries](#dictionaries)
* [A note on mutablility](#a-note-on-mutablility)
* [Flow control](#flow-control)
* [List comprehensions](#list-comprehensions)
* [Reading and writing text files](#reading-and-writing-text-files)
* [Example: processing lesion counts](#example-processing-lesion-counts)
* [Functions](#functions)
* [Working with `numpy`](#working-with-numpy)
* [The Python list versus the `numpy` array](#the-python-list-versus-the-numpy-array)
* [Creating arrays](#creating-arrays)
* [Example: reading arrays from text files](#example-reading-arrays-from-text-files)
<a class="anchor" id="introduction"></a>
# Introduction
This talk is an attempt to give a whirlwind overview of the Python programming
language. It is assumed that you have experience with another programming
language (e.g. MATLAB).
This talk is presented as an interactive [Jupyter
Notebook](https://jupyter.org/) - you can run all of the code on your own
machine - click on a code block, and press **SHIFT+ENTER**. You can also "run"
the text sections, so you can just move down the document by pressing
**SHIFT+ENTER**.
It is also possible to *change* the contents of each code block (these pages
are completely interactive) so do experiment with the code you see and try
some variations!
You can get help on any Python object, function, or method by putting a `?`
before or after the thing you want help on:
%% Cell type:code id: tags:
```
a = 'hello!'
?a.upper
```
%% Cell type:markdown id: tags:
And you can explore the available methods on a Python object by using the
**TAB** key:
%% Cell type:code id: tags:
```
# Put the cursor after the dot, and press the TAB key...
a.
```
%% Cell type:markdown id: tags:
<a class="anchor" id="python-in-a-nutshell"></a>
## Python in a nutshell
**Pros**
* _Flexible_ Feel free to use functions, classes, objects, modules and
packages. Or don't - it's up to you!
* _Fast_ If you do things right (in other words, if you use `numpy`)
* _Dynamically typed_ No need to declare your variables, or specify their
types.
* _Intuitive syntax_ How do I run some code for each of the elements in my
list?
%% Cell type:code id: tags:
```
mylist = [1, 2, 3, 4, 5]
for element in mylist:
print(element)
```
%% Cell type:markdown id: tags:
**Cons**
* _Dynamically typed_ Easier to make mistakes, harder to catch them
* _No compiler_ See above
* _Slow_ if you don't do things the right way
* _Python 2 is not the same as Python 3_ But there's an easy solution: Forget
that Python 2 exists.
* _Hard to manage different versions of python_ But we have a solution for
you: `fslpython`.
Python is a widely used language, so you can get lots of help through google
and [stackoverflow](https://stackoverflow.com). But make sure that the
information you find is for **Python 3**, and **not** for **Python 2**!
Python 2 is obsolete, but is still used by many organisations, so you will
inevitably come across many Python 2 resources.
The differences between Python 2 and 3 are small, but important. The most
visible difference is in the `print` function: in Python 3, we write
`print('hello!')`, but in Python 2, we would write `print 'hello!'`.
FSL 5.0.10 and newer comes with its own version of Python, bundled with nearly
all of the scientific libraries that you are likely to need.
So if you use `fslpython` for all of your development, you can be sure that it
will work in FSL!
<a class="anchor" id="different-ways-of-running-python"></a>
## Different ways of running Python
Many of the Pytreat talks and practicals are presented as *Jupyter notebooks*,
which is a way of running python code in a web browser.
Jupyter notebooks are good for presentations and practicals, and some people
find them very useful for exploratory data analysis. But they're not the only
way of running Python code.
**Run Python from a file**
This works just like it does in MATLAB:
1. Put your code in a `.py` file (e.g. `mycode.py`).
2. Run `fslpython mycode.py` in a terminal.
3. ??
4. Profit.
**Run python in an interpreter**
Python is an [*interpreted
language*](https://en.wikipedia.org/wiki/Interpreted_language), like MATLAB.
So you can either write your code into a file, and then run that file, or you
can type code directly into a Python interpreter.
Python has a standard interpreter built-in - run `fslpython` in a terminal,
and see what happens (use CTRL+D to exit).
**But** there is another interpreter called [IPython](https://ipython.org/)
which is vastly superior to the standard Python interpreter. Use IPython
instead! It is already installed in `fslpython`, so if you want to do some
interactive work, you can use `fslipython` in a terminal.
<a class="anchor" id="variables-and-basic-types"></a>
# Variables and basic types
There are many different types of values in Python. Python *variables* do not
have a type though - a variable can refer to values of any type, and a
variable can be updated to refer to different values (of different
types). This is just like how things work in MATLAB.
<a class="anchor" id="integer-and-floating-point-scalars"></a>
## Integer and floating point scalars
%% Cell type:code id: tags:
```
a = 7
b = 1 / 3
c = a + b
print('a: ', a)
print('b: ', b)
print('c: ', c)
print('b: {:0.4f}'.format(b))
print('a + b:', a + b)
```
%% Cell type:markdown id: tags:
<a class="anchor" id="strings)"></a>
## Strings
%% Cell type:code id: tags:
```
a = 'Hello'
b = "Kitty"
c = '''
Magic
multi-line
strings!
'''
print(a, b)
print(a + b)
print('{}, {}!'.format(a, b))
print(c)
```
%% Cell type:markdown id: tags:
String objects have a number of useful methods:
%% Cell type:code id: tags:
```
s = 'This is a Test String'
print(s.upper())
print(s.lower())
```
%% Cell type:markdown id: tags:
Another useful method is:
%% Cell type:code id: tags:
```
s = 'This is a Test String'
s2 = s.replace('Test', 'Better')
print(s2)
```
%% Cell type:markdown id: tags:
Two common and convenient string methods are `strip()` and `split()`. The
first will remove any whitespace at the beginning and end of a string:
%% Cell type:code id: tags:
```
s2 = ' A very spacy string '
print('*' + s2 + '*')
print('*' + s2.strip() + '*')
```
%% Cell type:markdown id: tags:
With `split()` we can tokenize a string (to turn it into a list of strings)
like this:
%% Cell type:code id: tags:
```
print(s.split())
print(s2.split())
```
%% Cell type:markdown id: tags:
We can also use the `join` method to re-construct a new string. Imagine that
we need to reformat some data from being comma-separated to being
space-separated:
%% Cell type:code id: tags:
```
data = ' 1,2,3,4,5,6,7 '
```
%% Cell type:markdown id: tags:
`strip`, `split` and `join` makes this job trivial:
%% Cell type:code id: tags:
```
print('Original: {}'.format(data))
print('Strip, split, and join: {}'.format(' '.join(data.strip().split(','))))
```
%% Cell type:markdown id: tags:
<a class="anchor" id="lists-and-tuples"></a>
## Lists and tuples
Both tuples and lists are built-in Python types and are like cell-arrays in
MATLAB. For numerical vectors and arrays it is much better to use *numpy*
arrays, which are covered later.
Tuples are defined using round brackets and lists are defined using square
brackets. For example:
%% Cell type:code id: tags:
```
t = (3, 7.6, 'str')
l = [1, 'mj', -5.4]
print(t)
print(l)
t2 = (t, l)
l2 = [t, l]
print('t2 is: ', t2)
print('l3 is: ', l2)
print(len(t2))
print(len(l2))
```
%% Cell type:markdown id: tags:
The key difference between lists and tuples is that tuples are *immutable*
(once created, they cannot be changed), whereas lists are *mutable*:
%% Cell type:code id: tags:
```
a = [10, 20, 30]
a[2] = 999
print(a)
```
%% Cell type:markdown id: tags:
Square brackets are used to index tuples, lists, strings, dictionaries, etc.
For example:
%% Cell type:code id: tags:
```
d = [10, 20, 30]
print(d[1])
```
%% Cell type:markdown id: tags:
> **MATLAB pitfall:** Python uses zero-based indexing, unlike MATLAB, where
> indices start from 1.
%% Cell type:code id: tags:
```
a = [10, 20, 30, 40, 50, 60]
print(a[0])
print(a[2])
```
%% Cell type:markdown id: tags:
A range of values for the indices can be specified to extract values from a
list or tuple using the `:` character. For example:
%% Cell type:code id: tags:
```
print(a[0:3])
```
%% Cell type:markdown id: tags:
> **MATLAB pitfall:** Note that Python's slicing syntax is different from
> MATLAB in that the second number is *exclusive*, i.e. `a[0:3]` gives us the
> elements of `a` at positions `0`, `1` and `2` , but *not* at position `3`.
When slicing a list or tuple, you can leave the start and end values out -
when you do this, Python will assume that you want to start slicing from the
beginning or the end of the list. For example:
%% Cell type:code id: tags:
```
print(a[:3])
print(a[1:])
print(a[:])
print(a[:-1])
```
%% Cell type:markdown id: tags:
You can also change the step size, which is specified by the third value (not
the second one, as in MATLAB). For example:
%% Cell type:code id: tags:
```
print(a[0:4:2])
print(a[::2])
print(a[::-1])
```
%% Cell type:markdown id: tags:
Some methods are available on `list` objects for adding and removing items:
%% Cell type:code id: tags:
```
print(d)
d.append(40)
print(d)
d.extend([50, 60])
print(d)
d = d + [70, 80]
print(d)
d.remove(20)
print(d)
d.pop(0)
print(d)
```
%% Cell type:markdown id: tags:
What will `d.append([50,60])` do, and how is it different from
`d.extend([50,60])`?
%% Cell type:code id: tags:
```
d.append([50, 60])
print(d)
```
%% Cell type:markdown id: tags:
<a class="anchor" id="dictionaries"></a>
## Dictionaries
Dictionaries (or *dicts*) can be used to store key-value pairs. Almost
anything can used as a key, and anything can be stored as a value; it is
common to use strings as keys:
%% Cell type:code id: tags:
```
e = {'a' : 10, 'b': 20}
print(len(e))
print(e.keys())
print(e.values())
print(e['a'])
```
%% Cell type:markdown id: tags:
Like lists (and unlike tuples), dicts are mutable, and have a number of
methods for manipulating them:
%% Cell type:code id: tags:
```
e['c'] = 30
e.pop('a')
e.update({'a' : 100, 'd' : 400})
print(e)
e.clear()
print(e)
```
%% Cell type:markdown id: tags:
<a class="anchor" id="a-note-on-mutability"></a>
## A note on mutablility
Python variables can refer to values which are either mutable, or
immutable. Examples of immutable values are strings, tuples, and integer and
floating point scalars. Examples of mutable values are lists, dicts, and most
user-defined types.
When you pass an immutable value around (e.g. into a function, or to another
variable), it works the same as if you were to copy the value and pass in the
copy - the original value is not changed:
%% Cell type:code id: tags:
```
a = 'abcde'
b = a
b = b.upper()
print('a:', a)
print('b:', b)
```
%% Cell type:markdown id: tags:
In contrast, when you pass a mutable value around, you are passing a
*reference* to that value - there is only ever one value in existence, but
multiple variables refer to it. You can manipulate the value through any of
the variables that refer to it:
%% Cell type:code id: tags:
```
a = [1, 2, 3, 4, 5]
b = a
a[3] = 999
b.append(6)
print('a', a)
print('b', b)
```
%% Cell type:markdown id: tags:
<a class="anchor" id="flow-control"></a>
# Flow control
Python also has a boolean type which can be either `True` or `False`. Most
Python types can be implicitly converted into booleans when used in a
conditional expression.
Relevant boolean and comparison operators include: `not`, `and`, `or`, `==`
and `!=`
For example:
%% Cell type:code id: tags:
```
a = True
b = False
print('Not a is:', not a)
print('a or b is:', a or b)
print('a and b is:', a and b)
print('Not 1 is:', not 1)
print('Not 0 is:', not 0)
print('Not {} is:', not {})
print('{}==0 is:', {}==0)
```
%% Cell type:markdown id: tags:
There is also the `in` test for strings, lists, etc:
%% Cell type:code id: tags:
```
print('the' in 'a number of words')
print('of' in 'a number of words')
print(3 in [1, 2, 3, 4])
```
%% Cell type:markdown id: tags:
We can use boolean values in `if`-`else` conditional expressions:
%% Cell type:code id: tags:
```
a = [1, 2, 3, 4]
val = 3
if val in a:
print('Found {}!'.format(val))
else: