{ "metadata": { "name": "", "signature": "sha256:12d4acf3c70609d4d2ed07213dda59c435e57e83abea602293e44e931eb25512" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Welcome to IPython Notebook!\n", "======================================================\n", "\n", "This is a brief introduction to Python and the IPython Notebook. We will be around to help you with any questions you may have. If you are familiar with programming you will still want to skim this document for how to use IPython Notebook and how Python is different than what you already know.\n", "\n", "First we will start with some IPython Notebook features. IPython stands for Interactive Python. The notebook part of it is a web-based interactive computational environment where you can combine code execution, text, mathematics, plots and rich media into a single document.\n", "\n", "The notebook is split into different \"cells\". Each cell contains one kind of content, such as code, text, formulas for display, ... This allows you to write your thoughts inbetween sections of code. This text here is a cell; double-clicking it will allow you to edit it.\n", "\n", "Code cells can be run on there own, but will remember all the results from the previously run cell. As you go through this tutorial you should try to modify the contents of the cell to explore the features of Python - making sure you understand every line. You can run the same cell over and over again, or you can add new cells using the menu above.\n", "\n", "*Note*: Python is similar to MATLAB. If you are used to MATLAB I recommend checking out http://www.scipy.org/NumPy_for_Matlab_Users which will tell you all of the important differences. Biggest thing to remember is that arrays / matrices are 0-based, not 1-based.\n", "\n", "*Note 2*: If you wish to setup Python on your own computer, please talk to us." ] }, { "cell_type": "code", "collapsed": false, "input": [ "# This is a code cell that sets some defaults for us, focus this cell and type Shift+Enter\n", "from __future__ import division, print_function # makes the division operator and print function work as you would expect" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Basics\n", "------\n", "First, any text after a `#` symbol is a comment and is ignored by Python. You should be in the practice of commenting your code thoroughly so that someone else will know what it is doing and so you will know in a couple months when you go back and look at it (you think you'll remember but you won't).\n", "\n", "In Notebook you could add it as a text cell, but you will still want comments to be within your code.\n", "\n", "In the Notebook there are shortcut keys for executing cells:\n", "\n", "* `Shift + Enter` to run the current cell and move to the next one\n", "* `Ctrl + Enter` to run the current cell in-place\n", "\n", "You can use the toolbar and menus at the top to do this and much more, like insert cells.\n", "\n", "Simple math is pretty straight forward:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Note: print() is a function that writes to the screen what it was given\n", "# In Notebooks the last thing in a cell will automatically print out if it did not have = in it (we will learn about = in a bit)\n", "print(2 + 2) # prints 4\n", "print((50-5*6)/4) # prints 5\n", "print(3**3) # prints 27 (3^3, 3 to the third power)\n", "print(7 / 2) # prints 3.5\n", "print(abs(-5)) # prints 5\n", "print(round(5.53)) # prints 6\n", "round(5.53, 1) # outputs 5.5" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At any time if you want to know what a function does you can add `?` after the function name and run the cell. It opens a new window with the help. Click the 'x' in the top-right of the new window to close it.\n", "\n", "Note: in normal Python you would have to do `help(round)`" ] }, { "cell_type": "code", "collapsed": false, "input": [ "round?" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You will also notice that while typing in a code cell you pause after `round(` it will give you the help information. Try it by adding a new cell block below!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Also, IPython Notebook will 'autocomplete' things for you when you press tab. Typing `rou` and pressing tab will give you a list of options. This can save you from typing long names! Try it in a new cell block below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can create variables to hold values:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = 2 + 2 # assigns 4 to the variable x\n", "y = x * 3 # assigns 12 to the variable y\n", "y / 2 # prints 6" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Notebooks, when you run a cell that defines variables they will stick around for all subsequent cells you run. You could add a cell here and use the values of `x` and `y`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__TODO__: Insert a new cell and output what x to the power of y is" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists\n", "-----\n", "Lists are many variables rolled into one that have a specific order. Lists in Python are quite powerful and versatile.\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list = [5, 0, 2, 6] # a list of a few numbers\n", "str_list = ['Hello','World', # a list of strings, can be across many lines\n", " 'How','Are','You?'] # however the other lines must be indented\n", "\n", "print(len(num_list)) # prints 4, the number of items in the list\n", "print(min(num_list)) # prints 0, the minimum in the list\n", "print(max(str_list)) # prints You?, the maximum of the list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists support `+` and `*` for concatenation and repetition respectively" ] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list+str_list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list*2" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python lists are zero-based (unlike Matlab which is one-based). This means that the first item in a list has the index `0`. You can retrieve and modify items by index:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = num_list[1] # x is 0, the second element of num_list\n", "x # Put this here by itself so Notebook will show us the value" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list[2] = 99\n", "num_list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To add and remove elements from a list use `append` and `del`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list.append(200) # num_list is now [5, 0 99, 6, 200]\n", "del num_list[1] # num_list is now [5, 99, 6, 200]\n", "num_list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python lists support 'slices' which are portions of a list" ] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list[1:3] # The second through third values in the list\n", "# Note: the range includes the first number and goes up to the second number but does not include it" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each side of the slice is optional and if not included means go to the end:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(num_list[1:]) # from the second element to the end\n", "print(num_list[:3]) # from the start to the third element\n", "print(num_list[:]) # the entire list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Negative slice values mean from the end" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(num_list[:-1]) # from the start to the second to last element\n", "print(num_list[1:-1]) # from the second to the second to last element\n", "print(num_list[-1:]) # from the second to last element to the end" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ " And even more advanced with a third value for an increment:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "num_list[::2] # every other element" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Slices can be be replaced and deleted:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "str_list[1:2] = num_list # str_list is now ['Hello',5,99,6,200,'How','Are','You?']\n", "del str_list[1:5] # str_list is now ['Hello','How','Are','You?']\n", "str_list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lists support many useful functions including `sort()` and `reverse()`. See http://docs.python.org/library/stdtypes.html#mutable-sequence-types for more information.\n", "\n", "Another powerful feature of Python lists is list comprehensions, but they are a bit complicated. If you want to learn more, see: \n", "http://docs.python.org/tutorial/datastructures.html#list-comprehensions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Tuples\n", "------\n", "\n", "Tuples are similar to lists but a little less powerful. Instead of using `[]` tuples use `()` when being created. Tuples are fixed in length and cannot be changed. They are most useful for things like coordinates (e.g `(x, y)`), having functions return more than one value, and read-only lists. Below are some examples. Lists and tuples can be coverted to each other: `tuple(aList)` and `list(aTuple)`" ] }, { "cell_type": "code", "collapsed": false, "input": [ "coord = (4, 5) # packs a tuple\n", "coord = 4, 5 # same as above\n", "x, y = coord # unpacks a tuple\n", "x = coord[0] # they support many of the list features\n", "coords = [ (1, 2), (3, 4), (4, 5) ] # a list of tuples\n", "x, y = coords[2] # x is 4, y is 5" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Strings\n", "-------\n", "\n", "A string is a piece of text enclosed in either single or doule quotes:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(\"Hello World\")\n", "'It is a beautiful day'" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Strings are very similar to lists, and support many of the same things (like `len`, `min`, `max`, and slices).\n", "\n", "You can concatenate strings to each other:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "\"How \" + \"are you?\"" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can convert numbers to a string:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "str(2+2) # Try: str(x) using the value of x from the first section" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can even concatenate numbers to a string by first converting:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "\"2 + 2 equals: \"+str(2+2)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are an incredible number of built-in functions for working with strings. For more information see http://docs.python.org/library/stdtypes.html#string-methods\n", "\n", "Strings also provide a very rich formatting syntax, however it is a bit much for this guide. For more information see http://docs.python.org/library/string.html#format-specification-mini-language" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__TODO__: Insert a cell and output the string \"x is :\" followed by the value of x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Booleans\n", "--------\n", "\n", "Booleans are values that are either `True` or `False`. They are typically used in conditional tests (which we will get to in the next section). When using a value as a boolean, any of the following are considered `False`:\n", "\n", " False, 0, \"\", [], (), None\n", "\n", "Everything else is `True`.\n", "\n", "__Try__: adding `print()` functions or extra cells to see the outputs below, currently nothing below is output." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The basic boolean operations are `not`, `and`, and `or`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "t = True\n", "f = not t # False (not switches True to False and False to True)\n", "b = t and t # True (and is True only if both are True)\n", "b = t and f # False (and is False if either is False)\n", "b = f and f # False\n", "b = t or t # True (or is True if either is True)\n", "b = t or f # True\n", "b = f or f # False" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also make booleans by comparisons:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = 5\n", "b = x > 4 # True (greater than)\n", "b = x >= 4 # True (greater than or equal to)\n", "b = x < 4 # False (less than)\n", "b = x <= 4 # False (less than or equal to)\n", "b = x == 4 # False (equals)\n", "b = x != 4 # True (not equals), can also be written 5 <> 4\n", "b = 4 < x < 6 # True, same as 4 < x and x < 6" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comparisons work for strings as well, but be careful since by default uppercase letters come before lowercase letters" ] }, { "cell_type": "code", "collapsed": false, "input": [ "b = \"aardvark\" < \"zebra\" # True\n", "b = \"aardvark\" < \"Zebra\" # False\n", "b = \"Yes\" == 'Yes' # True" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are special comparisons for lists (also work for strings and tuples):" ] }, { "cell_type": "code", "collapsed": false, "input": [ "l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "b = x in l # True (the list contains 5)\n", "b = x not in l # False" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Conditionals (`if` statements)\n", "------------------------------\n", "\n", "We are finally getting to the interesting stuff. If statements let you run a chunk of code if and only if something is True. First lets set some variables to known values:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "x, y = 5, 10" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then, lets check if x is positive:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if x > 0:\n", " print(\"x is positive\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This will only print \"x is positive\" if x is positive. __Try__ changing the value of x.\n", "\n", "Your value of x could come from many places, maybe a file, maybe from the user, maybe from some really complicated calculations.\n", "\n", "You can also compare two variables to each other:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if x > y:\n", " print(\"x is greater than y\")\n", "else:\n", " print(\"x is less than or equal to y\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We added an `else` there which runs in case the `if` statement was `False`.\n", "\n", "You can chain multiple `if`s together using `elif` which stands for 'else if'" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if x > 0:\n", " print(\"x is positive\")\n", "elif x < 0:\n", " print(\"x is negative\")\n", "else: # at this point x cannot be positive or negative\n", " print(\"x is 0\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indentation is very important in Python. Here is an example to help explain indentation importance:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if x > 0:\n", " print(\"x is positive\")\n", "elif x < 0:\n", " # this group has two lines, both have the same indentation\n", " x = -x\n", " print(\"x was negative, but now is positive\")\n", " # this group is done so the next line is un-indented\n", "else:\n", " print(\"x is 0\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another more complicated example:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if x > 0:\n", " print(\"x is positive\")\n", " if x > y:\n", " # if statements can be inside if statements, you just need to indent again\n", " print(\"x is above y\")\n", " else: # this else is paired with \"if (x > y):\" because of its indentation\n", " print(\"x is at most y\")\n", " print(\"wasn't that interesting?\")\n", "else: # this else is paired with \"if (x > 0):\" because of its indentation\n", " print(\"x is not positive\")" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`while` Loops\n", "-------------\n", "\n", "So now that we have conditional statements down, lets add on loops. The simplest loop is a while loop. Below is an example. Do you recongnize the pattern of numbers? The while loop will repeatedly run the code inside it until its conditional statement is False." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a, b = 0, 1\n", "while b < 20:\n", " print(b)\n", " a, b = b, a+b" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__TODO__: What happends when you change the conditional to `b < 2000`?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`for` Loops\n", "-----------\n", "\n", "The truth is that you probably won't use while loops too much because their big brother the \"for loop\" is much more convient." ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = ['cat', 'window', 'defenestrate']\n", "for x in a: # for loops can take any 'iterable' object\n", " print(x, len(x))\n", "\n", "for letter in a[0]:\n", " print(letter)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you need to cover a range of values, then you use the conveniently named `range()` function:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "for index in range(len(a)): # Goes from index = 0 to len(a)-1 (so 0, 1, 2 in this case)\n", " print(index, a[index])\n", "\n", "# This particular example can also be done with 'enumerate'\n", "for index, value in enumerate(a):\n", " print(index, value)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`range()` creates a list of numbers based on what you give it. You can also make it not start at zero, skip numbers, and go downwards:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(range(5))\n", "print(range(5, 10))\n", "print(range(0, 10, 3))\n", "print(range(-10, -100, -30))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Basically `range(start, end, step)` with `start` and `step` being optional" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions\n", "---------\n", "\n", "If you find yourself writing the same lines of code over and over, or if you just need to organize your code (always a good thing), you can create functions. Functions are mini-programs that take a set of inputs and give an optional set of outputs. Here is a basic example:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def minimum(a, b): # define a function called 'minimum' that takes two inputs: 'a' and 'b'\n", " if a < b:\n", " return a # the return keyword gives the outputs\n", " else:\n", " return b" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above function finds the minimum of two values. You can use it like so:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "minimum(5, 10)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: like variables, once you run a cell that defines a function it is available for all other cells you run\n", "\n", "Since the `return` keyword immediately stops the function, the `minimum` function could be simplified to:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def minimum(a, b):\n", " if a < b:\n", " return a\n", " return b" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also return more than one value. The function below returns both the minumum and maximum value." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def min_max(a, b):\n", " if a < b:\n", " return a, b\n", " return b, a" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "min_max(10, 5)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note: this was just a simple example and for minimum and maximum you would use the built-in `min()` and `max()` functions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Errors\n", "------\n", "\n", "It is invetible that you will run into errors in your code so you need to understand the common errors, what they mean, and how to work on fixing them.\n", "\n", "Probably the most common error is a `SyntaxError`. This basically means that you tried to run a program that doesn't follow the rules of the Python language. Try executing the cell below and you will get a syntax error (the list must end with `]` instead of `)`)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "x = [5, 6, 7)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The little `^` indicates where the problem is. The file is a random name because we are in a Notebook.\n", "\n", "Sometimes a syntax error on a previous line causes Python to complain on a future line so make sure to check the line before if you can't find a problem with the given line.\n", "\n", "A special type of the `SyntaxError` is the `IndentationError` meaning Python expected an indentation and you didn't indent, for an example run the following cell:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "if x > 5:\n", "print('This line should be indented')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other errors give a \"traceback\" where it tells you all the functions being called with the second to last being the line that caused the error at the and the last line being a description of the problem. For example, the following cell will do a division by zero (which is undefined)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def divZero(x):\n", " return x / 0\n", "divZero(5)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Other Common Errors**\n", "\n", "`NameError: name 'spam' is not defined` - You tried to use a variable named \"spam\" but it does not exist yet.\n", "\n", "`IndexError: list index out of range` - You tried to access an element in a list or array that is `>=len(list)`, for example:\n", " \n", " x = [1, 2, 3]\n", " x[5] # generates error\n", "\n", "`TypeError: cannot concatenate 'str' and 'int' objects` - You tried to \"add\" a string and a number like so: `\"hello\" + 5`, to do this properly you must do `\"hello\" + str(5)`\n", "\n", "`TypeError: divZero() takes exactly 1 argument (0 given)` - You called a function with the wrong number of inputs. This is the error you would get if you ran `divZero()`.\n", "\n", "`ImportError: No module named foo` - You tried to import the module named foo but it doesn't exist. Either you typed the name wrong or you haven't properly installed the module.\n", "\n", "`IOError: [Errno 2] No such file or directory: 'x.txt'` - All `IOErrors` deal with problems with files. In this case we tried to open the file 'x.txt' which doesn't exist.\n", "\n", "`AttributeError: 'list' object has no attribute 'bar'` - You tried to access an property or function of an object that doesn't exist. For example:\n", "\n", " x = [1, 2, 3]\n", " x.foo() # Since lists have no foo function, this causes an error.\n", "\n", "`ValueError: list.remove(x): x not in list` - A `ValueError` means that a function received an unexpected value. For example:\n", "\n", " x = [1, 2, 3]\n", " x.remove(6) # Since there is no \"6\" in the list it causes an error.\n", "\n", "There are many other errors, but these are the most common ones. Hopefully you won't see them too often, and never see the less common ones." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***********************************\n", "Exercise: Fibonacci Series Function\n", "-----------------------------------\n", "\n", "To see that you understand the basics, write a function that computes the Fibonacci series up to a given value. It should store every value in a list and return that list (__not print anything directly__).\n", "\n", "Tip: the example `while` loops printed the Fibonacci series, so you have the algorithm." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def fib(max_value):\n", " l = []\n", " # TODO: fill in the list 'l' with the Fibonacci values up to and including max_value then return the list" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "fib(20) # should output [1, 1, 2, 3, 5, 8, 13]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "fib(2000) # should output [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*****" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Advanced\n", "--------\n", "\n", "There are tons of other advanced things that are built into Python. Ask us and we may be able to help you use them. Here is a brief list of things you may use:\n", "\n", " * [dictionaries / associative arrays](https://docs.python.org/2/tutorial/datastructures.html#dictionaries)\n", " * [list comprehensions](https://docs.python.org/2/tutorial/datastructures.html#list-comprehensions)\n", " * [classes](https://docs.python.org/2/tutorial/classes.html) and [modules](https://docs.python.org/2/tutorial/modules.html)\n", " * [complex numbers](https://docs.python.org/2/library/stdtypes.html#typesnumeric)\n", " * [lambda functions](https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions)\n", " * [sets](https://docs.python.org/2/tutorial/datastructures.html#sets), [queues](https://docs.python.org/2/library/collections.html#collections.deque), and [stacks](https://docs.python.org/2/tutorial/datastructures.html#using-lists-as-stacks)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**************************\n", "NumPy / SciPy / matplotlib\n", "==========================\n", "\n", "Now we get to the really interesting stuff. NumPy and SciPy provide advanced math and scientific functions for Python. They provide nearly all of the functionality of MATLAB for Python (see http://www.scipy.org/NumPy_for_Matlab_Users for differences). In fact, internally they use many of the same libraries!\n", "\n", "NumPy and SciPy are fully documented online at http://docs.scipy.org/doc/numpy/reference/ and http://docs.scipy.org/doc/scipy/reference/ respectively along with inside the code (using `fft?` or `fft(` and waiting a second). The help includes examples. Try it out!\n", "\n", "Note: NumPy is actually a subset of SciPy, so everything in NumPy is also in SciPy\n", "\n", "matplotlib is the plotting module for Python and we will get to it in a few sections.\n", "\n", "The NumPy and SciPy modules (a.k.a. libraries) needs to imported to be used. Since NumPy, SciPy and matplotlib are so often used together, there is a special import called \"pylab\" for it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from pylab import * # import numpy, scipy and matplotlib" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Arrays\n", "------\n", "\n", "So you know how we learned about lists? Well it turns out that for the most part you want to use a NumPy array and not a list. They are much faster for many things and when used with NumPy the benefits are amazing. The good news is that they act almost the same as the normal Python lists.\n", "\n", "Some simple 1-dimensional array examples:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a1 = array([1, 2, 3, 4])\n", "a2 = array([4, 3, 2, 1])\n", "a3 = a1 + a2 # add array element-wise (normal Python lists would concatenate)\n", "print(a3) # prints [5, 5, 5, 5]\n", "print(a1[0]) # prints [1]\n", "print(a2[1:3]) # prints [3, 2] (all the other slice operations work as well)\n", "a4 = a1 * a2 # multiply arrays element-wise\n", "a5 = sin(a1) # takes sin of all elements\n", "a6 = log(a2) # takes natrual log of all elements\n", "a7 = exp(a6) # computes e^(x) for each x in the array\n", "a8 = 10**a1 # computes 10^(x) for each x in the array\n", "py_list = a4.tolist() # converts to a Python list\n", "a4_dup = array(py_list) # converts to a NumPy array" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are many more available functions, commonly used ones are:\n", "\n", "[`sum`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html),\n", "[`mean`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.mean.html),\n", "[`std`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.std.html),\n", "[`cumsum`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.cumsum.html),\n", "[`append`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.append.html),\n", "[`concatenate`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.concatenate.html),\n", "[`amin`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.amin.html),\n", "[`amax`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.amax.html),\n", "[`argmin`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.argmin.html),\n", "[`argmax`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.argmax.html),\n", "[`histogram`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html),\n", "[`round`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.round.html),\n", "[`sign`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.sign.html),\n", "[`unique`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.unique.html)\n", "\n", "For a complete list with examples see: http://www.scipy.org/Numpy_Example_List_With_Doc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "More ways to make a 1-D array:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "r = arange(0, 50, 1) # from 0 to 49, in steps of 1, like Python range but with real-valued SciPy arrays\n", "l = linspace(0, 50, 10000) # 10000 element array from 0 to 50 (inclusive)\n", "z = zeros(50) # an array of 50 zeros\n", "o = ones(50) # an array of 50 ones\n", "p = pi*ones(50) # an array of 50 pis" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrices\n", "--------\n", "\n", "NumPy arrays can also be multi-dimensional (2-dimensional arrays are commonly called matrices). In most cases 1-D and 2-D arrays are treated the same, and everything that works on a 1-D array will work on a 2-D array." ] }, { "cell_type": "code", "collapsed": false, "input": [ "m1 = array([[1, 2, 3, 4], # 3 rows and 4 columns\n", " [4, 3, 2, 1],\n", " a3 ])\n", "m2 = zeros((4, 5)) # 4 rows and 5 columns of zeros - note the double parathesis, these are critical" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get the shape:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(m2.shape) # prints (4, 5)\n", "nrows, ncols = m2.shape\n", "nrows # outputs 4, the number of rows" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To access elements in a matrix:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "m2[3,0] = 5 # Changes fourth row and first column to 5, same as m2[3][0]\n", "print(m1[1,:]) # Prints the entire second row (same as m1[1])\n", "print(m1[:,2]) # Prints the entire third column\n", "# The other slice operations work as well:\n", "m1[1:3,1:3] # Outputs: [[3 2] # second row, second and third columns\n", " # [5 5]] # third row, second and third columns" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Matrices support `+`, `*`, `**` (power), `sin`, `log`, ... the same way that arrays do (element-wise operations, no need for `.*` or `./` like in MATLAB).\n", "\n", "They also support some matrix-only operations:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "t = transpose(m2) # switch rows and columns in the array / matrix\n", "t = m2.T # same as above\n", "m = m1.dot(m2) # dot product (like * in MATLAB)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some common matrix functions to look into are [`reshape`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html) and [`histogram2d`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram2d.html).\n", "\n", "Note: SciPy/NumPy actually has something called [`matrix`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.matrix.html) as well, which acts like MATLAB matrices where `*` is the matrix multiplication (it is designed for linear algebra)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finding\n", "-------\n", "\n", "SciPy arrays can easily be searched. You can use the comparison operators we learned before to get an `array` / `matrix` of `True` / `False` values for each element like so:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a = array([-1, 0, 5, -5, 7])\n", "b = array([-2, 4, -1, 0, 8])\n", "print(a > 0) # prints [False False True False True]\n", "print(b > a) # prints [False True False True True]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check if any or all are `True`:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "print(\"Are any negative? \"+str(any(a < 0)))\n", "print(\"Are all negative? \"+str(all(a < 0)))" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you need the indices, you can use the `where()` function:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "where(a >= 0)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get the values you can use the comparison or the result of `where()` as an index:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "a[a >= 0] # equivilent to a[where(a >= 0)]" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using these techniques we can find spike times in voltage data (at the moment we don't have any data, so this won't work, so just make a note of it):" ] }, { "cell_type": "code", "collapsed": false, "input": [ "threshold = 0 # the spike threshold\n", "time = ... # when we sampled voltage\n", "voltage = ... # what the voltage was\n", "spikes = time[logical_and(voltage[:-1] < threshold, voltage[1:] >= threshold)] # find all time points when previous voltage was below threshold and next voltage was above threshold" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Files\n", "-----\n", "\n", "You will need to be able to get your data into Python to make use of it. Arrays can easily be read from and saved to files." ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Save array:\n", "save('test.npy', m2) # binary format (smallest) but can only be read by numpy\n", "savetxt('test.txt', m2) # text format (easiest to read as text)\n", "savetxt('test.csv', m2, delimiter=',') # comma-seperated values format (easily usable by Excel)" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "# Load array\n", "m3 = load('test.npy')\n", "m3 = genfromtxt('test.txt')\n", "m3 = genfromtxt('test.csv', delimiter=',')" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also save many arrays / matrices into a single compressed file using [`savez`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.savez.html). Those files should have the extension 'npz'.\n", "\n", "Can also use [`io.loadmat`](http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.io.loadmat.html) and [`io.savemat`](http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.io.savemat.html) to read and write MAT files from MATLAB." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Data from the PowerLab/MacLab recording software puts multiple traces or 'sweeps' in a single text file. We have created a function that splits these apart for you. You must download the \"bootcamp.py\" file and put it in the same directory as your iPython notebooks." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from bootcamp import split_sweeps, combine_sweeps\n", "trace_data = genfromtxt('trace.txt') # assuming you have a 'trace.txt' file\n", "sweeps = split_sweeps(trace_data) # assuming you have this function added\n", "# Now `sweeps` is a cell array of the different sweeps, for example:\n", "time = sweeps[0][:,0]\n", "voltage1 = sweeps[0][:,1]\n", "#voltage2 = sweeps[0][:,2] # assuming you had two recordings going on" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have also provided `combine_sweeps` which allows you to combine multiple sweeps into a single sweep (with the times adjusted as necessary). Use it like: `big_sweep = combine_sweeps(sweeps[1:3])`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotting\n", "--------\n", "\n", "You can also make beautiful plots with Python. Within IPython Notebook they show up right in the notebook!" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# First, some code to make plots look a little better in Notebook - just run it and continue\n", "rcParams['figure.figsize'] = (8.0, 5.0)\n", "rcParams['font.size'] = 14\n", "rcParams['savefig.dpi'] = 72" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "code", "collapsed": false, "input": [ "# First we create data for a sin wave, just to have something to show\n", "x = linspace(-2*pi, 2*pi, 5000) # create a list of numbers\n", "y = sin(x) # calculate the sin for each point\n", "\n", "# Now plot it\n", "figure() # creates a new figure to plot in\n", "title('sin curve') # add a title\n", "xlabel('X') # add an x label\n", "ylabel('$\\\\sin(x)$') # add a y label (use can use \"latex\" here when you put $...$)\n", "plot(x, y) # plot x vs y\n", "# In regular Python you would need a show() command to show the plot." ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are an incredible number of options for plotting your data just the way you want, and you can have multiple plots at the same time." ] }, { "cell_type": "code", "collapsed": false, "input": [ "y2 = cos(x) # calculate the cos for each point\n", "figure()\n", "title('sine and cosine curves')\n", "xlabel('X values')\n", "ylabel('Y values')\n", "plot(x, y, color='red', linestyle='-.', label='$\\\\sin(x)$') # shorthand is plot(x, y, 'r-.', label='$\\\\sin(x)$')\n", "plot(x, y2, color='green', linestyle='--', label='$\\\\cos(x)$') # shorthand is plot(x, y2, 'g--', label='$\\\\cos(x)$')\n", "legend(loc='upper right') # uses the 'label' string for each" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For a complete list of options see http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot\n", "\n", "You can also do 2D plots:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Generate some 'interesting' data (just ignore this part)\n", "from matplotlib.mlab import bivariate_normal\n", "x, y = arange(-3.0, 3.0, 0.025), arange(-2.0, 2.0, 0.025)\n", "X, Y = meshgrid(x, y)\n", "Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)\n", "Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1.0, 1.0)\n", "Z = 10.0 * (Z2 - Z1)\n", "\n", "# Contour plot\n", "figure()\n", "title('Contour Plot')\n", "contour(X, Y, Z)\n", "colorbar() # adds a color bar to the image\n", "\n", "\n", "# Image plot\n", "figure()\n", "title('Image Plot')\n", "imshow(Z, extent=[amin(X), amax(X), amin(Y), amax(Y)], aspect='auto', origin='lower')\n", "colorbar()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other plot types that may be useful:\n", "\n", " * line plot: `errorbar`, `fill`, `fill_betweenx`\n", " * box plots: `bar`, `barh`, `hist`, `boxplot`\n", " * vector field: `quiver`, `barbs`\n", " * 2D plots: `contourf`\n", " * spectral: `specgram`, `psd`, `csd`\n", " * other: `polar`, `scatter`, `acorr`, `xcorr`\n", "\n", "Other functions to perfect the figure:\n", "\n", " * `annotate`, `subtitle`, `clim` (color scale limits)\n", " * `axis`, `twinx`/`twiny` (create second axis), `xscale`/`yscale` (set log scale)\n", "\n", "See the matplotlib homepage for complete documentation and tons of examples: http://matplotlib.sourceforge.net/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3D Plotting\n", "-----------\n", "Matplotlib has 3D plotting built-in, but it takes just a little work to use it" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# First you need to import the 3D library:\n", "import mpl_toolkits.mplot3d" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then you have to set the axes to 3D projections.\n", "If not using subplots create the figure like this:\n", "\n", " figure().gca(projection='3d')\n", "\n", "Otherwise create the subplot like this:\n", "\n", " gcf().add_subplot(1, 2, 1, projection='3d')" ] }, { "cell_type": "code", "collapsed": false, "input": [ "# Generate some interesting data\n", "n_mer, n_long = 6, 11\n", "phi = sp.arange(0.0, 2*sp.pi + 0.0005*sp.pi, sp.pi/1000.0)\n", "mu = phi*n_mer\n", "x = sp.cos(mu)*(1+sp.cos(n_long*mu/n_mer)*0.5)\n", "y = sp.sin(mu)*(1+sp.cos(n_long*mu/n_mer)*0.5)\n", "z = sp.sin(n_long*mu/n_mer)*0.5\n", "\n", "# Plot the 3D Data\n", "plt.figure().gca(projection='3d')\n", "plt.plot(x, y, z)\n", "plt.show()\n", "\n", "# There are a ton more plotting types and options that you can use is. See:\n", "# http://matplotlib.sourceforge.net/mpl_toolkits/mplot3d/tutorial.html" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Solving Diff Eqs\n", "----------------\n", "SciPy has an ordinary differential equation solver that we will use for many problems in this class." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from scipy.integrate import odeint # alias the ODE integration function\n", "\n", "# We will integrate this system of differential equations:\n", "# du/dt = v\n", "# dv/dt = -u\n", "def step(n, t):\n", " # Calculate a single step of the integration\n", " # n are the variables\n", " # t is the current time\n", " \n", " u, v = n # n must be 'unpacked'\n", " \n", " # Compute the integration step\n", " dudt = v\n", " dvdt = -u\n", " \n", " return dudt, dvdt # return these values\n", "\n", "# Time runs from 0 to 10 in 0.1 increments\n", "t = arange(0.0, 10, 0.1)\n", "\n", "# Using the function named 'step' and starting from the initial conditions\n", "# u=0.0 and v=1.0 integrate over time\n", "n = odeint(step, [0.0, 1.0], t)\n", "\n", "u = n[:, 0] # Column zero is u values for all times in t\n", "v = n[:, 1] # Column one is v values for all times in t\n", "\n", "# Plot the u values as a function of time\n", "figure()\n", "title(\"du/dt = v, dv/dt = -u\")\n", "plot(t, u, label=\"u\")\n", "legend(loc=\"upper right\")\n", "show()" ], "language": "python", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exercises\n", "=========\n", "Run the code that solves a simple ODE, look at the graph, and understand what is going on. Then change the function to compute the following system of equations:\n", "\n", " $$du/dt = v-0.1u$$\n", " $$dv/dt = -u-0.1v$$\n", "\n", "Also, plot both u and v over time in the same graph instead of just u.\n", "\n", "Now that you have the hang of solving differential equations, recreate the Lorenz Attractor (look it up on Wikipedia). Plot the result using a 3D plot." ] } ], "metadata": {} } ] }