Commit 6a0643c8 authored by Greg Wilson's avatar Greg Wilson
Browse files

Switching to page.root for references

parent 9a0adc61
......@@ -52,6 +52,8 @@ collections:
# Set the default layout for things in the episodes collection.
defaults:
- values:
root: ..
- scope:
path: ""
type: episodes
......
......@@ -33,11 +33,11 @@ Words are useful,
but what's more useful are the sentences and stories we build with them.
Similarly,
while a lot of powerful, general tools are built into languages like Python,
specialized tools built up from these basic units live in [libraries]({{ site.github.url }}/reference/#library)
specialized tools built up from these basic units live in [libraries]({{ page.root }}/reference/#library)
that can be called upon when needed.
In order to load our inflammation data,
we need to access ([import]({{ site.github.url }}/reference/#import) in Python terminology)
we need to access ([import]({{ page.root }}/reference/#import) in Python terminology)
a library called [NumPy](http://docs.scipy.org/doc/numpy/ "NumPy Documentation").
In general you should use this library if you want to do fancy things with numbers,
especially if you have matrices or arrays.
......@@ -70,15 +70,15 @@ array([[ 0., 0., 1., ..., 3., 0., 0.],
~~~
{: .output}
The expression `numpy.loadtxt(...)` is a [function call]({{ site.github.url }}/reference/#function-call)
that asks Python to run the [function]({{ site.github.url }}/reference/#function) `loadtxt` which belongs to the `numpy` library.
This [dotted notation]({{ site.github.url }}/reference/#dotted-notation) is used everywhere in Python
The expression `numpy.loadtxt(...)` is a [function call]({{ page.root }}/reference/#function-call)
that asks Python to run the [function]({{ page.root }}/reference/#function) `loadtxt` which belongs to the `numpy` library.
This [dotted notation]({{ page.root }}/reference/#dotted-notation) is used everywhere in Python
to refer to the parts of things as `thing.component`.
`numpy.loadtxt` has two [parameters]({{ site.github.url }}/reference/#parameter):
`numpy.loadtxt` has two [parameters]({{ page.root }}/reference/#parameter):
the name of the file we want to read,
and the [delimiter]({{ site.github.url }}/reference/#delimiter) that separates values on a line.
These both need to be character strings (or [strings]({{ site.github.url }}/reference/#string) for short),
and the [delimiter]({{ page.root }}/reference/#delimiter) that separates values on a line.
These both need to be character strings (or [strings]({{ page.root }}/reference/#string) for short),
so we put them in quotes.
When we are finished typing and press Shift+Enter,
......@@ -97,10 +97,10 @@ when there's nothing interesting after the decimal point.
Our call to `numpy.loadtxt` read our file,
but didn't save the data in memory.
To do that,
we need to [assign]({{ site.github.url }}/reference/#assignment) the array to a [variable]({{ site.github.url }}/reference/#variable).
we need to [assign]({{ page.root }}/reference/#assignment) the array to a [variable]({{ page.root }}/reference/#variable).
A variable is just a name for a value,
such as `x`, `current_temperature`, or `subject_id`.
Python's variables must begin with a letter and are [case sensitive]({{ site.github.url }}/reference/#case-sensitive).
Python's variables must begin with a letter and are [case sensitive]({{ page.root }}/reference/#case-sensitive).
We can create a new variable by assigning a value to it using `=`.
As an illustration,
let's step back and instead of considering a table of data,
......@@ -246,7 +246,7 @@ print(data)
Now that our data is in memory,
we can start doing things with it.
First,
let's ask what [type]({{ site.github.url }}/reference/#type) of thing `data` refers to:
let's ask what [type]({{ page.root }}/reference/#type) of thing `data` refers to:
~~~
print(type(data))
......@@ -283,10 +283,10 @@ are their daily inflammation measurements.
> {: .output}
>
> This tells us that the NumPy array's elements are
> [floating-point numbers]({{ site.github.url }}/reference/#floating-point number).
> [floating-point numbers]({{ page.root }}/reference/#floating-point number).
{: .callout}
We can see what the array's [shape]({{ site.github.url }}/reference/#shape) is like this:
We can see what the array's [shape]({{ page.root }}/reference/#shape) is like this:
~~~
print(data.shape)
......@@ -300,7 +300,7 @@ print(data.shape)
This tells us that `data` has 60 rows and 40 columns. When we created the
variable `data` to store our arthritis data, we didn't just create the array, we also
created information about the array, called [members]({{ site.github.url }}/reference/#member) or
created information about the array, called [members]({{ page.root }}/reference/#member) or
attributes. This extra information describes `data` in
the same way an adjective describes a noun.
`data.shape` is an attribute of `data` which describes the dimensions of `data`.
......@@ -309,7 +309,7 @@ that we use for the functions in libraries
because they have the same part-and-whole relationship.
If we want to get a single number from the array,
we must provide an [index]({{ site.github.url }}/reference/#index) in square brackets,
we must provide an [index]({{ page.root }}/reference/#index) in square brackets,
just as we do in math:
~~~
......@@ -378,7 +378,7 @@ print(data[0:4, 0:10])
~~~
{: .output}
The [slice]({{ site.github.url }}/reference/#slice) `0:4` means,
The [slice]({{ page.root }}/reference/#slice) `0:4` means,
"Start at index 0 and go up to, but not including, index 4."
Again,
the up-to-but-not-including takes a bit of getting used to,
......@@ -503,8 +503,8 @@ print(numpy.mean(data))
~~~
{: .output}
`mean` is a [function]({{ site.github.url }}/reference/#function) that takes
an array as an [argument]({{ site.github.url }}/reference/#argument).
`mean` is a [function]({{ page.root }}/reference/#function) that takes
an array as an [argument]({{ page.root }}/reference/#argument).
If variables are nouns, functions are verbs:
they do things with variables.
......@@ -582,7 +582,7 @@ maximum inflammation for patient 0: 18.0
{: .output}
Everything in a line of code following the '#' symbol is a
[comment]({{ site.github.url }}/reference/#comment) that is ignored by the computer.
[comment]({{ page.root }}/reference/#comment) that is ignored by the computer.
Comments allow programmers to leave explanatory notes for other
programmers or their future selves.
......@@ -751,7 +751,7 @@ You can group similar plots in a single figure using subplots.
This script below uses a number of new commands. The function `matplotlib.pyplot.figure()`
creates a space into which we will place all of our plots. The parameter `figsize`
tells Python how big to make this space. Each subplot is placed into the figure using
its `add_subplot` [method]({{ site.github.url }}/reference/#method). The `add_subplot` method takes 3 parameters. The first denotes
its `add_subplot` [method]({{ page.root }}/reference/#method). The `add_subplot` method takes 3 parameters. The first denotes
how many total rows of subplots there are, the second parameter refers to the
total number of subplot columns, and the final parameter denotes which subplot
your variable is referencing (left-to-right, top-to-bottom). Each subplot is stored in a
......@@ -788,7 +788,7 @@ matplotlib.pyplot.show()
![The Previous Plots as Subplots](../fig/01-numpy_80_0.png)
The [call]({{ site.github.url }}/reference/#function-call) to `loadtxt` reads our data,
The [call]({{ page.root }}/reference/#function-call) to `loadtxt` reads our data,
and the rest of the program tells the plotting library
how large we want the figure to be,
that we're creating three subplots,
......@@ -842,7 +842,7 @@ the graphs will actually be squeezed together more closely.)
> ## Slicing Strings
>
> A section of an array is called a [slice]({{ site.github.url }}/reference/#slice).
> A section of an array is called a [slice]({{ page.root }}/reference/#slice).
> We can take slices of character strings as well:
>
> ~~~
......@@ -893,7 +893,7 @@ the graphs will actually be squeezed together more closely.)
> ## Thin Slices
>
> The expression `element[3:3]` produces an [empty string]({{ site.github.url }}/reference/#empty-string),
> The expression `element[3:3]` produces an [empty string]({{ page.root }}/reference/#empty-string),
> i.e., a string that contains no characters.
> If `data` holds our array of patient data,
> what does `data[3:3, 4:4]` produce?
......
......@@ -132,7 +132,7 @@ n
~~~
{: .output}
The improved version uses a [for loop]({{ site.github.url }}/reference/#for-loop)
The improved version uses a [for loop]({{ page.root }}/reference/#for-loop)
to repeat an operation---in this case, printing---once for each thing in a collection.
The general form of a loop is:
......@@ -149,7 +149,7 @@ Using the oxygen example above, the loop might look like this:
where each character (`char`) in the variable `word` is looped through and printed one character after another.
The numbers in the diagram denote which loop cycle the character was printed in (1 being the first loop, and 6 being the final loop).
We can call the [loop variable]({{ site.github.url }}/reference/#loop-variable) anything we like,
We can call the [loop variable]({{ page.root }}/reference/#loop-variable) anything we like,
but there must be a colon at the end of the line starting the loop,
and we must indent anything we want to run inside the loop. Unlike many other languages, there is no
command to signify the end of the loop body (e.g. end for); what is indented after the for statement belongs to the loop.
......
......@@ -103,8 +103,8 @@ does not.
> ## Ch-Ch-Ch-Changes
>
> Data which can be modified in place is called [mutable]({{ site.github.url }}/reference/#mutable),
> while data which cannot be modified is called [immutable]({{ site.github.url }}/reference/#immutable).
> Data which can be modified in place is called [mutable]({{ page.root }}/reference/#mutable),
> while data which cannot be modified is called [immutable]({{ page.root }}/reference/#immutable).
> Strings and numbers are immutable. This does not mean that variables with string or number values are constants,
> but when we want to change the value of a string or number variable, we can only replace the old value
> with a completely new value.
......
......@@ -304,7 +304,7 @@ freeing us from having to manually examine every plot for features we've seen be
> ## In-Place Operators
>
> Python (and most other languages in the C family) provides [in-place operators]({{ site.github.url }}/reference/#in-place-operators)
> Python (and most other languages in the C family) provides [in-place operators]({{ page.root }}/reference/#in-place-operators)
> that work like this:
>
> ~~~
......
......@@ -57,7 +57,7 @@ regenerate the above figure --->
The function definition opens with the keyword `def` followed by the
name of the function and a parenthesized list of parameter names. The
[body]({{ site.github.url }}/reference/#function-body) of the function --- the
[body]({{ page.root }}/reference/#function-body) of the function --- the
statements that are executed when it runs --- is indented below the
definition line.
......@@ -65,7 +65,7 @@ When we call the function,
the values we pass to it are assigned to those variables
so that we can use them inside the function.
Inside the function,
we use a [return statement]({{ site.github.url }}/reference/#return-statement) to send a result back to whoever asked for it.
we use a [return statement]({{ page.root }}/reference/#return-statement) to send a result back to whoever asked for it.
Let's try running our function.
Calling our own function is no different from calling any other function:
......@@ -199,7 +199,7 @@ What about converting Fahrenheit to Celsius?
We could write out the formula,
but we don't need to.
Instead,
we can [compose]({{ site.github.url }}/reference/#compose) the two functions we have already created:
we can [compose]({{ page.root }}/reference/#compose) the two functions we have already created:
~~~
def fahr_to_celsius(temp_f):
......@@ -391,10 +391,10 @@ the difference is very small.
It's still possible that our function is wrong,
but it seems unlikely enough that we should probably get back to doing our analysis.
We have one more task first, though:
we should write some [documentation]({{ site.github.url }}/reference/#documentation) for our function
we should write some [documentation]({{ page.root }}/reference/#documentation) for our function
to remind ourselves later what it's for and how to use it.
The usual way to put documentation in software is to add [comments]({{ site.github.url }}/reference/#comment) like this:
The usual way to put documentation in software is to add [comments]({{ page.root }}/reference/#comment) like this:
~~~
# center(data, desired): return a new array containing the original data centered around the desired value.
......@@ -429,7 +429,7 @@ center(data, desired)
~~~
{: .output}
A string like this is called a [docstring]({{ site.github.url }}/reference/#docstring).
A string like this is called a [docstring]({{ page.root }}/reference/#docstring).
We don't need to use triple quotes when we write one,
but if we do,
we can break the string across multiple lines:
......@@ -530,7 +530,7 @@ print(center(test_data, 3))
{: .output}
But we can also now call it with just one parameter,
in which case `desired` is automatically assigned the [default value]({{ site.github.url }}/reference/#default-value) of 0.0:
in which case `desired` is automatically assigned the [default value]({{ page.root }}/reference/#default-value) of 0.0:
~~~
more_data = 5 + numpy.zeros((2, 2))
......
......@@ -28,7 +28,7 @@ Once you know *why* you get certain types of errors,
they become much easier to fix.
Errors in Python have a very specific form,
called a [traceback]({{ site.github.url }}/reference/#traceback).
called a [traceback]({{ page.root }}/reference/#traceback).
Let's examine one:
~~~
......@@ -65,7 +65,7 @@ In this case:
The last level is the actual place where the error occurred.
The other level(s) show what function the program executed to get to the next level down.
So, in this case, the program first performed a [function call]({{ site.github.url }}/reference/#function-call) to the function `favorite_ice_cream`.
So, in this case, the program first performed a [function call]({{ page.root }}/reference/#function-call) to the function `favorite_ice_cream`.
Inside this function,
the program encountered an error on Line 7, when it tried to run the code `print(ice_creams[3])`.
......@@ -107,7 +107,7 @@ hopefully the custom error message is informative enough to help you figure out
When you forget a colon at the end of a line,
accidentally add one space too many when indenting under an `if` statement,
or forget a parenthesis,
you will encounter a [syntax error]({{ site.github.url }}/reference/#syntax-error).
you will encounter a [syntax error]({{ page.root }}/reference/#syntax-error).
This means that Python couldn't figure out how to read your program.
This is similar to forgetting punctuation in English:
for example,
......@@ -172,7 +172,7 @@ it *always* means that there is a problem with how your code is indented.
> A quick note on indentation errors:
> they can sometimes be insidious,
> especially if you are mixing spaces and tabs.
> Because they are both [whitespace]({{ site.github.url }}/reference/#whitespace),
> Because they are both [whitespace]({{ page.root }}/reference/#whitespace),
> it is difficult to visually tell the difference.
> The Jupyter notebook actually gives us a bit of a hint,
> but not all Python editors will do that.
......@@ -231,7 +231,7 @@ That's harder question to answer,
because it depends on what your code is supposed to do.
However,
there are a few very common reasons why you might have an undefined variable.
The first is that you meant to use a [string]({{ site.github.url }}/reference/#string), but forgot to put quotes around it:
The first is that you meant to use a [string]({{ page.root }}/reference/#string), but forgot to put quotes around it:
~~~
print(hello)
......@@ -274,7 +274,7 @@ NameError: name 'count' is not defined
Finally, the third possibility is that you made a typo when you were writing your code.
Let's say we fixed the error above by adding the line `Count = 0` before the for loop.
Frustratingly, this actually does not fix the error.
Remember that variables are [case-sensitive]({{ site.github.url }}/reference/#case-sensitive),
Remember that variables are [case-sensitive]({{ page.root }}/reference/#case-sensitive),
so the variable `count` is different from `Count`. We still get the same error, because we still have not defined `count`:
~~~
......
......@@ -48,8 +48,8 @@ is much greater than the time that measuring takes.
The first step toward getting the right answers from our programs
is to assume that mistakes *will* happen
and to guard against them.
This is called [defensive programming]({{ site.github.url }}/reference/#defensive-programming),
and the most common way to do it is to add [assertions]({{ site.github.url }}/reference/#assertion) to our code
This is called [defensive programming]({{ page.root }}/reference/#defensive-programming),
and the most common way to do it is to add [assertions]({{ page.root }}/reference/#assertion) to our code
so that it checks itself as it runs.
An assertion is simply a statement that something must be true at a certain point in a program.
When Python sees one,
......@@ -92,14 +92,14 @@ are there to check that the other 80-90% are working correctly.
Broadly speaking,
assertions fall into three categories:
* A [precondition]({{ site.github.url }}/reference/#precondition) is something that must be true at the start of a function in order for it to work correctly.
* A [precondition]({{ page.root }}/reference/#precondition) is something that must be true at the start of a function in order for it to work correctly.
* A [postcondition]({{ site.github.url }}/reference/#postcondition) is something that the function guarantees is true when it finishes.
* A [postcondition]({{ page.root }}/reference/#postcondition) is something that the function guarantees is true when it finishes.
* An [invariant]({{ site.github.url }}/reference/#invariant) is something that is always true at a particular point inside a piece of code.
* An [invariant]({{ page.root }}/reference/#invariant) is something that is always true at a particular point inside a piece of code.
For example,
suppose we are representing rectangles using a [tuple]({{ site.github.url }}/reference/#tuple) of four coordinates `(x0, y0, x1, y1)`,
suppose we are representing rectangles using a [tuple]({{ page.root }}/reference/#tuple) of four coordinates `(x0, y0, x1, y1)`,
representing the lower left and upper right corners of the rectangle.
In order to do some calculations,
we need to normalize the rectangle so that the lower left corner is at the origin
......@@ -244,7 +244,7 @@ If you made a mistake in a piece of code,
the odds are good that you have made other mistakes nearby,
or will make the same mistake (or a related one)
the next time you change it.
Writing assertions to check that you haven't [regressed]({{ site.github.url }}/reference/#regression)
Writing assertions to check that you haven't [regressed]({{ page.root }}/reference/#regression)
(i.e., haven't re-introduced an old problem)
can save a lot of time in the long run,
and helps to warn people who are reading the code
......@@ -279,7 +279,7 @@ there's a better way:
3. If `range_overlap` produces any wrong answers, fix it and re-run the test functions.
Writing the tests *before* writing the function they exercise
is called [test-driven development]({{ site.github.url }}/reference/#test-driven-development) (TDD).
is called [test-driven development]({{ page.root }}/reference/#test-driven-development) (TDD).
Its advocates believe it produces better code faster because:
1. If people write tests after writing the thing to be tested,
......
......@@ -65,7 +65,7 @@ scientists tend to do the following:
our first test should hold temperature, precipitation, and other factors constant.
3. *Compare to an oracle.*
A [test oracle]({{ site.github.url }}/reference/#test-oracle) is something whose results are trusted,
A [test oracle]({{ page.root }}/reference/#test-oracle) is something whose results are trusted,
such as experimental data, an older program, or a human expert.
We use to test oracles to determine if our new program produces the correct results.
If we have a test oracle,
......@@ -88,7 +88,7 @@ scientists tend to do the following:
Data analysts frequently use simple visualizations to check both
the science they're doing
and the correctness of their code
(just as we did in the [opening lesson]({{ site.github.url }}/01-numpy/) of this tutorial).
(just as we did in the [opening lesson]({{ page.root }}/01-numpy/) of this tutorial).
This should only be used for debugging as a last resort,
though,
since it's very hard to compare two visualizations automatically.
......
......@@ -63,7 +63,7 @@ $ python code/readings_04.py --max data/inflammation-*.csv
Our scripts should do the following:
1. If no filename is given on the command line, read data from [standard input]({{ site.github.url }}/reference/#standard-input).
1. If no filename is given on the command line, read data from [standard input]({{ page.root }}/reference/#standard-input).
2. If one or more filenames are given, read data from them and report statistics for each file separately.
3. Use the `--min`, `--mean`, or `--max` flag to determine what statistic to print.
......@@ -488,7 +488,7 @@ but there are several things wrong with it:
command-line, one for the **flag** and one for the **filename**, but only
one, the program will not throw an exception but will run. It assumes that the file
list is empty, as `sys.argv[1]` will be considered the `action`, even if it
is a filename. [Silent failures]({{ site.github.url }}/reference/#silence-failure) like this
is a filename. [Silent failures]({{ page.root }}/reference/#silence-failure) like this
are always hard to debug.
3. The program should check if the submitted `action` is one of the three recognized flags.
......@@ -718,7 +718,7 @@ the program now does everything we set out to do.
> ## Finding Particular Files
>
> Using the `glob` module introduced [earlier]({{ site.github.url }}/04-files/),
> Using the `glob` module introduced [earlier]({{ page.root }}/04-files/),
> write a simple version of `ls` that shows files in the current directory with a particular suffix.
> A call to this script should look like this:
>
......
......@@ -38,7 +38,7 @@ The diagram below shows what memory looks like after the first line has been exe
When we call `fahr_to_celsius`,
Python *doesn't* create the variable `temp` right away.
Instead,
it creates something called a [stack frame]({{ site.github.url }}/reference/#stack-frame)
it creates something called a [stack frame]({{ page.root }}/reference/#stack-frame)
to keep track of the variables defined by `fahr_to_kelvin`.
Initially,
this stack frame only holds the value of `temp`:
......@@ -152,7 +152,7 @@ but we don't want to have to read every line of NumPy to see what variable names
before calling any of those functions,
just in case they change the values of our variables.
The big idea here is [encapsulation]({{ site.github.url }}/reference/#encapsulation),
The big idea here is [encapsulation]({{ page.root }}/reference/#encapsulation),
and it's the key to writing correct, comprehensible programs.
A function's job is to turn several operations into one
so that we can think about a single function call
......@@ -222,9 +222,9 @@ grid lines on: True
The obvious thing to do with a grid like this is color in its cells,
but in order to do that,
we need to know how computers represent color.
The most common schemes are [RGB]({{ site.github.url }}/reference/#rgb),
The most common schemes are [RGB]({{ page.root }}/reference/#rgb),
which is short for "red, green, blue".
RGB is an [additive color model]({{ site.github.url }}/reference/#additive-color-model):
RGB is an [additive color model]({{ page.root }}/reference/#additive-color-model):
every shade is some combination of red, green, and blue intensities.
We can think of these three values as being the axes in a cube:
......@@ -233,7 +233,7 @@ We can think of these three values as being the axes in a cube:
An RGB color is an example of a multi-part value:
like a Cartesian coordinate,
it is one thing with several parts.
We can represent such a value in Python using a [tuple]({{ site.github.url }}/reference/#tuple),
We can represent such a value in Python using a [tuple]({{ page.root }}/reference/#tuple),
which we write using parentheses instead of the square brackets used for a list:
~~~
......@@ -266,7 +266,7 @@ first element of color is: 10
Unlike lists and arrays,
though,
tuples cannot be changed after they are created --- in technical terms,
they are [immutable]({{ site.github.url }}/reference/#immutable):
they are [immutable]({{ page.root }}/reference/#immutable):
~~~
color[0] = 40
......
......@@ -89,7 +89,7 @@ which are covered in the lesson on the shell.
* NumPy methods.
We used to use NumPy array methods in the first [NumPy topic]({{ site.github.url }}/01-numpy/).
We used to use NumPy array methods in the first [NumPy topic]({{ page.root }}/01-numpy/).
We switched these methods to the equivalent functions because a majority
of instructors supported the change; see
[PR #244](https://github.com/swcarpentry/python-novice-inflammation/pull/244)
......
---
layout: lesson
root: .
---
The best way to learn how to program is to do something useful,
......@@ -22,7 +23,7 @@ and to use that language *well*.
We are studying inflammation in patients who have been given a new treatment for arthritis,
and need to analyze the first dozen data sets of their daily inflammation.
The data sets are stored in [comma-separated values]({{ site.github.url }}/reference/#comma-separated-values) (CSV) format:
The data sets are stored in [comma-separated values]({{ page.root }}/reference/#comma-separated-values) (CSV) format:
each row holds information for a single patient,
and the columns represent successive days.
The first few rows of our first file look like this:
......
......@@ -36,4 +36,4 @@ $ python
~~~
{: .source}
[zipfile]: {{ site.github.url }}/data/python-novice-inflammation-data.zip
[zipfile]: {{ page.root }}/data/python-novice-inflammation-data.zip
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment