{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<figure>\n",
    "  <IMG SRC=\"https://raw.githubusercontent.com/mbakker7/exploratory_computing_with_python/master/tudelft_logo.png\" WIDTH=250 ALIGN=\"right\">\n",
    "</figure>\n",
    "\n",
    "# Exploratory Computing with Python\n",
    "*Developed by Mark Bakker*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Notebook 2: Arrays and basic `if`-statements\n",
    "###One dimensional arrays\n",
    "In this notebook, we will do math on arrays using functions of the `numpy` package. A nice overview of `numpy` functionality can be found [here](http://wiki.scipy.org/Tentative_NumPy_Tutorial). We will also make plots. So we start by importing the plotting part of the `matplotlib` package and call it `plt` and we import the `numpy` package and call it `np`. We also tell IPython to put all graphs inline. We will add these three lines at the top of all upcoming notebooks as we will always be using `numpy` and `matplotlib`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are many ways to create arrays. For example, you can enter the individual elements of an array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "np.array([1, 7, 2, 12])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the `array` function takes one sequence of points between square brackets. \n",
    "Another function to create an array is `ones(shape)`, which creates an array of the specified `shape` filled with the value 1. \n",
    "There is an analogous function `zeros(shape)` to create an array willed with the value 0 (which can also be achieved with `0 * ones(shape)`). Next to the already mentioned `linspace` function there is the `arange(start,end,step)` \n",
    "function, which creates an array starting at `start`, taking steps equal to `step` and stopping before it reaches `end`. If you don't specify the `step`, \n",
    "it is set equal to 1. If you only specify one input value, it returns a sequence starting at 0 and incrementing by 1 until the specified value is reached (but again, it stops before it reaches that value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "print np.arange(1, 7) # Takes defauls steps of 1 and doesn't include 7\n",
    "print np.arange(5) # Starts at 0 end ends at 4, giving 5 numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Recall that comments in Python are preceded by a `#`. \n",
    "Arrays have a dimension. So far we have only used one-dimensional arrays. \n",
    "Hence the dimension is 1. \n",
    "For one-dimensional arrays, you can also compute the length (which is part of Python and not `numpy`), which returns the number of values in the array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.array([1, 7, 2, 12])\n",
    "print 'number of dimensions of x:', np.ndim(x)\n",
    "print 'length of x:',len(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The individual elements of an array can be accessed with their index. Indices start at 0. \n",
    "This may require a bit of getting used to. It means that the first value in the array has index 0. The index of an array is specified using square brackets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.arange(20, 30)\n",
    "print x\n",
    "print x[0]\n",
    "print x[5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A range of indices may be specified using the colon syntax:\n",
    "`x[start:end_before]` or `x[start:end_before:step]`. If the `start` or `end_before` isn't specified, 0 will be used. If the step isn't specified, 1 will be used. You can also start at the end and count back. Generally, the index of the end is not known. You can find out how long the array is and access the last value by typing `x[len(x)-1]` but it would be inconvenient to have to type `len(arrayname)` all the time. Luckily, there is a shortcut: `x[-1]` is the last value in the array. This all requires practice. Make sure you understand the following examples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.arange(20, 30)\n",
    "print x\n",
    "print x[0:5]\n",
    "print x[:5] # same as previous one\n",
    "print x[3:7]\n",
    "print x[2:9:2] # step is 2\n",
    "print x[-1:4:-2] # starts at last one and stops before reaching index 4 with step -2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can assign one value to a range of an array by specifying a range of indices, \n",
    "or you can assign an array to a range of another array, as long as the ranges have equal length. In the second example below, the first 5 values of `x` (specified as `x[0:5]`) are given the values `[40,42,44,46,48]`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = 20 * np.ones(10)\n",
    "print x\n",
    "x[0:5] = 40\n",
    "print x\n",
    "x[0:5] = np.arange(40, 50, 2)\n",
    "print x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the example below, it is meant to give the last 5 values of `x` the values [50,52,54,56,58], but there are some errors in the code. Remove the comment markers and run the code to see the error message. Then fix the code and run it again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#x = np.ones(10)\n",
    "#x[5:] = np.arange(50, 62, 1)\n",
    "#print x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Exercise 1, <a name=\"back1\"></a> Arrays and indices\n",
    "Create an array of zeros with length 20. Change the first 5 values to 10. Change the next 10 values to a sequence starting at 12 and increasig with steps of 2 to 30 - do this with one command. Set the final 5 values to 30. Plot the value of the array on the y-axis vs. the index of the array on the x-axis. Draw vertical dashed lines at x=4 and x=14 (i.e, the section between the dashed lines is where the line increases from 10 to 30). Set the minimum and maximum values of the y-axis to 8 and 32 using the `ylim` command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex1answer\">Answer for Exercise 1</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Arrays, Lists, and Tuples\n",
    "A one-dimensional array is a sequence of values that you can do math on. Next to the array, Python has several other data types that can store a sequence of values. The first one is called a `list` and is entered between square brackets. The second one is a tuple (you are right, strange name), and it is entered with parentheses. The difference is that you can change the values of a list after you create them, and you can not do that with a tuple. Other than that, for now you just need to remember that they exist, and that you *cannot* do math with either lists or tuples. When you do `2 * alist` where `alist` is a list, you don't multiply all values in `alist` with the number 2. What happens is that you create a new list that contains `alist` twice (so it adds them back to back). The same holds for tuples. That can be very useful, but not when your intent is to multiply all values by 2. In the example below, the first value in a list is modified. Try to modify one of the values in `btuple` below and you will see that you get an error message:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "alist = [1, 2, 3]\n",
    "print 'alist', alist\n",
    "btuple = (10, 20, 30)\n",
    "print 'btuple', btuple\n",
    "alist[0] = 7  # Since alist is a list, you can change values \n",
    "print 'modified alist', alist\n",
    "#btuple[0] = 100  # Will give an error\n",
    "#print 2*alist"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lists and tuples are versatile data types in Python. We already used lists without knowing it when we created our first array with the command `array([1,7,2,12])`. What we did is we gave the `array` function one input argument: the list `[1,7,2,12]`, and the `array` function returned a one-dimensional array with those values. Lists and tuples can consist of a sequences of pretty much anything, not just numbers. In the example given below, `alist` contains 5 *things*: the integer 1, the float 20, the word `python`, an array with the values 1,2,3, and finally, the function `len`. The latter means that `alist[4]` is actually the function `len`. That function can be called to determine the length of an array as shown below. The latter may be a bit confusing, but it is cool behavior if you take the time to think about it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "alist = [1, 20.0, 'python', np.array([1,2,3]), len]\n",
    "print alist\n",
    "print alist[0]\n",
    "print alist[2]\n",
    "print alist[4](alist[3])  # same as len( np.array([1,2,3]) )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Two-dimensional arrays\n",
    "Arrays may have arbitrary dimensions (as long as they fit in your computer's memory). We will make frequent use of two-dimensional arrays. They can be created with any of the aforementioned functions by specifying the number of rows and columns of the array. Note that the number of rows and columns must be a tuple (so they need to be between parentheses), as the functions expect only one input argument, which may be either one number or a tuple of multiple numbers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.ones((3, 4)) # An array with 3 rows and 4 columns\n",
    "print x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Arrays may also be defined by specifying all the values in the array. The `array` function gets passed one list consisting of separate lists for each row of the array. In the example below the rows are entered on different lines. That may make it easier to enter the array, but it is note required. You can change the size of an array to any shape using the `reshape` function as long as the total number of entries doesn't change. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.array([[4, 2, 3, 2],\n",
    "              [2, 4, 3, 1],\n",
    "              [0, 4, 1, 3]])\n",
    "print x\n",
    "print np.reshape(x, (6, 2))  # 6 rows, 2 columns\n",
    "print np.reshape(x, (1, 12))  # 1 row, 12 columns"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The index of a two-dimensional array is specified with two values, first the row index, then the column index."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.zeros((3, 8))\n",
    "x[0,0] = 100\n",
    "x[1,4:] = 200  # Row with index 1, columns starting with 4 to the end\n",
    "x[2,-1:4:-1] = 400  # Row with index 2, columns counting back from the end and stop before reaching index 4\n",
    "print x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Arrays are not matrices\n",
    "Now that we talk about the rows and columns of an array, the math-oriented reader may think that arrays are matrices, or that one-dimensional arrays are vectors. It is crucial to understand that *arrays are not vectors or matrices*. The multiplication and division of two arrays is term by term"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a = np.arange(4, 20, 4)\n",
    "b = np.array([2, 2, 4, 4])\n",
    "print 'array a:', a\n",
    "print 'array b:', b\n",
    "print 'a * b  :', a * b  # term by term multiplication\n",
    "print 'a / b  :', a / b  # term by term division"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that, just like for scalars, integer division gives integers (in Python 2.X). If that is not what you want (and it rarely is), make sure that at least one of the arrays is of type float by putting at least one floating point number in the array. Python figures out what data type to assign to the array (called `dtype` for short). You can ask for the `dtype` of an array, or you can specify it as a keyword argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a = np.arange(4)\n",
    "b = np.array([2, 2, 4, 4])\n",
    "print 'array a, dtype: ', a, a.dtype\n",
    "print 'array b, dtype: ', b, b.dtype\n",
    "print 'a / b  :', a / b  # interger divistion\n",
    "a = np.arange(4.)  # make array a of type float, same as np.arange(4,dtype='float')\n",
    "print 'array a, dtype: ', a, a.dtype\n",
    "print 'a / b  :', a / b  # float division !"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Exercise 2, <a name=\"back2\"></a> Two-dimensional array indices\n",
    "For the array `x` shown below, write code to print: \n",
    "\n",
    "* the first row of `x`\n",
    "* the first column of `x`\n",
    "* the third row of `x`\n",
    "* the last two columns of `x`\n",
    "* the four values in the upper right hand corner of `x`\n",
    "* the four values at the center of `x`\n",
    "\n",
    "`x = np.array([[4, 2, 3, 2],\n",
    "              [2, 4, 3, 1],\n",
    "              [2, 4, 1, 3],\n",
    "              [4, 1, 2, 3]])`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex2answer\">Answer for Exercise 2</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Visualizing two-dimensional arrays\n",
    "Two-dimensonal arrays can be visualized with the `plt.matshow` function. In the example below, the array is very small (only 4 by 4), but it illustrates the general principle. A colorbar is added as a legend showing that the value 1 corresponds to dark blue and the value 4 corresponds to dark red. The ticks in the colorbar are specified to be 1, 2, 3, and 4. Note that the first row of the matrix (with index 0), is plotted at the top, which corresponds to the location of the first row in the matrix."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.array([[8, 4, 6, 2],\n",
    "              [4, 8, 6, 2],\n",
    "              [4, 8, 2, 6],\n",
    "              [8, 2, 4, 6]])\n",
    "plt.matshow(x)\n",
    "plt.colorbar(ticks=[2, 4, 6, 8])\n",
    "print x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The colors that are used are the default color map (it is called `jet`), which maps the highest value to red, the lowest value to blue and the numbers in between varying between green and yellow. If you want other colors, you can choose one of the other color maps. To find out all the available color maps, go [here](href=\"http://matplotlib.org/examples/color/colormaps_reference.html). To change the color map, you need to import the `cm` part of the matplotlib package, which contains all the color maps. After you have imported the color map package (which we call `cm` below), you can specify any of the available color maps with the `cmap` keyword. Try a few."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import matplotlib.cm as cm\n",
    "plt.matshow(x, cmap=cm.rainbow)\n",
    "plt.colorbar(ticks=np.arange(2, 9, 2));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Exercise 3, <a name=\"back3\"></a> Create and visualize an array\n",
    "Create an array of size 10 by 10. The upper left-hand quadrant of the array should get the value 4, the upper right-hand quadrant the value 3, the lower right-hand quadrant the value 2 and the lower left-hand quadrant the value 1. First create an array of 10 by 10 using the `zeros` command, then fill each quadrant by specifying the correct index ranges. Note that the first index is the row number. The second index runs from left to right. Visualize the array using `matshow`. It should give a red, yellow, light blue and dark blue box (clock-wise starting from upper left) when you use the default `jet` colormap."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex3answer\">Answer for Exercise 3</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4, <a name=\"back4\"></a> Create and visualize a slightly fancier array\n",
    "Consider the image shown below, which roughly shows the letters TU. You are asked to create an array that represents the same TU. First create a zeros array of 11 rows and 17 columns. Give the background value 0, the letter T value -1, and the letter U value +1. <a name=\"back4\"></a>\n",
    "\n",
    "<img src= \"https://raw.githubusercontent.com/mbakker7/exploratory_computing_with_python/master/notebook2/tufig.png\" width=\"500px\" />"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex4answer\">Answer to Exercise 4</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Basic `if` statements\n",
    "An `if` statement lets you perform a task only when the outcome of the `if` statement is true. For example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "avalue = 4\n",
    "print avalue\n",
    "if avalue < 6:\n",
    "    print 'changing avalue in first if statement'\n",
    "    avalue = avalue + 2\n",
    "print avalue\n",
    "if avalue > 20:\n",
    "    print 'changing a in second if statement'\n",
    "    avalue = 200\n",
    "print avalue  # avalue hasn't changed as avalue is not larger than 20"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice the syntax of the `if` statement. It starts with `if` followed by a statement that is either `True` or `False` and then a colon. After the colon, you need to indent and the entire indented code block (in this case 2 lines of code) is executed if the statement is `True`. Otherwise it is not executed. The following comparisons can be made. Make sure you understand them all."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a = 4\n",
    "print a < 4\n",
    "print a <= 4 # a is smaller than or equal to 4\n",
    "print a == 4 # a is equal to 4. Note that there are 2 equal signs\n",
    "print a >= 4 \n",
    "print a >  4\n",
    "print a != 4 # a is not equal to 4"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is important to understand the difference between one equal sign like `a = 4` and two equal signs like `a == 4`. One equal sign means assignment. Whatever is on the right side of the equal sign is assigned to what is on the left side of the equal sign. Two equal signs is a comparison and results in either `True` (when the left and right sides are equal) or `False`. A variable that can either be `True` or `False` is called a *boolean* variable. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "print 4 == 4\n",
    "a = 4 == 5\n",
    "print a\n",
    "print type(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Comparisons can also be used for arrays. For example let's create an array and find out what values of the array are below 3:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "data = np.arange(5)\n",
    "print data\n",
    "print data < 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The statement `a < 3` returns an array of type `boolean` that has the same length as the array `data` and for each item in the array it is either `True` or `False`. The cool thing is that this array of `True` and `False` values can be used to specify the indices of an array:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a = np.arange(5)\n",
    "b = np.array([ True, True, True, False, False ])\n",
    "print a[b]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When the indices of an array are specified with a boolean array, only the values of the array where the boolean array is `True` are selected. This is a very powerful feature. For example, all values of an array that are less than, for example, 3 may be obtained by specifying a comparison as the indices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a = np.arange(5)\n",
    "print 'the total array: ',a\n",
    "print 'values less than 3: ', a[a < 3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we want to replace all values that are less than 3 by, for example, the value 10, use the following short syntax:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "a = np.arange(5)\n",
    "print a\n",
    "a[a < 3] = 10\n",
    "print a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Exercise 5, <a name=\"back5\"></a> Replace high and low in an array\n",
    "Create an array for variable $x$ consisting of 100 points from 0 to 20. Compute $y=\\sin(x)$ and plot $y$ vs. $x$ with a blue line. Next, replace all values of $y$ that are larger than 0.5 by 0.5, and all values that are smaller than $-$0.75 by $-$0.75 and plot $x$ vs. $y$ using a red line on the same graph. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex5answer\">Answer to Exercise 5</a>\n",
    "\n",
    "###Exercise 6, <a name=\"back6\"></a> Change marker color based on data value\n",
    "Create an array for variable x consisting of 100 points from 0 to 20 and compute $y=\\sin(x)$. Plot a blue dot for every $y$ that is larger than zero, and a red dot otherwise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex6answer\">Answer to Exercise 6</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Select indices based on multiple conditions\n",
    "Multiple conditions can be given as well. When two conditions both have to be true, use the `&` symbol. When at least one of the conditions needs to be true, use the '|' symbol (that is the vertical bar). For example, let's plot blue markers when $y>0.7$ or $y<-0.5$ (using one plot statement), and a red marker when $-0.5\\le y\\le 0.7$. When there are multiple conditions, they need to be between parenteses. Note that in the example below, $x$ varies from 0 to 6$\\pi$ (`pi` is part of `numpy`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.linspace(0, 6 * np.pi, 50)\n",
    "y = np.sin(x)\n",
    "plt.plot(x[(y > 0.7) | (y < -0.5)], y[(y > 0.7) | (y < -0.5)], 'bo' )\n",
    "plt.plot(x[(y > -0.5) & (y < 0.7)], y[(y > -0.5) & (y < 0.7)], 'ro' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Exercise 7, <a name=\"back7\"></a> Multiple conditions \n",
    "The file `xypoints.dat` contains 1000 randomly chosen $x,y$ locations of points; both $x$ and $y$ vary between -10 and 10. Load the data using `loadtxt`, and store the first row of the array in an array called `x` and the second row in an array called `y`. First, plot a red dot for all points. On the same graph, plot a blue dot for all $x,y$ points where $x<-2$ and $-5\\le y \\le 0$. Finally, plot a green dot for any point that lies in the circle witch center $(x_c,y_c)=(5,0)$ and with radius $R=5$. Hint: it may be useful to compute a new array for the radial distance $r$ between any point and the center of the circle using the formula $r=\\sqrt{(x-x_c)^2+(y-y_c)^2}$. Use the `plt.axis('image')` command to make sure the scales along the two axes are equal and the circular area looks like a circle."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#ex7answer\">Answer to Exercise 7</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###Answers to the exercises"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a name=\"ex1answer\">Answer to Exercise 1</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.zeros(20)\n",
    "x[:5] = 10\n",
    "x[5:15] = np.arange(12, 31, 2)\n",
    "x[15:] = 30\n",
    "plt.plot(x)\n",
    "plt.plot([4, 4], [8, 32],'k--')\n",
    "plt.plot([14, 14], [8, 32],'k--')\n",
    "plt.ylim(8, 32)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back1\">Back to Exercise 1</a>\n",
    "\n",
    "<a name=\"ex2answer\">Answer to Exercise 2</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.array([[4, 2, 3, 2],\n",
    "              [2, 4, 3, 1],\n",
    "              [2, 4, 1, 3],\n",
    "              [4, 1, 2, 3]])\n",
    "print 'the first row of x'\n",
    "print x[0]\n",
    "print 'the first column of x'\n",
    "print x[:, 0]\n",
    "print 'the third row of x'\n",
    "print x[2]\n",
    "print 'the last two columns of x'\n",
    "print x[:, -2:]\n",
    "print 'the four values in the upper right hand corner'\n",
    "print x[:2, 2:]\n",
    "print 'the four values at the center of x'\n",
    "print x[1:3, 1:3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back2\">Back to Exercise 2</a>\n",
    "\n",
    "<a name=\"ex3answer\">Answer to Exercise 3</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.zeros((10, 10))\n",
    "x[:5, :5] = 4\n",
    "x[:5, 5:] = 3\n",
    "x[5:, 5:] = 2\n",
    "x[5:, :5] = 1\n",
    "print x\n",
    "plt.matshow(x)\n",
    "plt.colorbar(ticks=[1, 2, 3, 4]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back3\">Back to Exercise 3</a>\n",
    "\n",
    "<a name=\"ex4answer\">Answer to Exercise 4</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.zeros((11, 17))\n",
    "x[2:4, 1:7] = -1\n",
    "x[2:9, 3:5] = -1\n",
    "x[2:9, 8:10] = 1\n",
    "x[2:9, 13:15] = 1\n",
    "x[7:9, 10:13] = 1\n",
    "print x\n",
    "plt.matshow(x, interpolation='nearest');\n",
    "plt.yticks(range(11, -1, -1))\n",
    "plt.xticks(range(0, 17));\n",
    "plt.ylim(10.5, -0.5)\n",
    "plt.xlim(-0.5, 16.5);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back4\">Back to Exercise 4</a>\n",
    "\n",
    "<a name=\"ex5answer\">Answer to Exercise 5</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.linspace(0, 20, 100)\n",
    "y = np.sin(x)\n",
    "plt.plot(x, y, 'b')\n",
    "y[y > 0.5] = 0.5\n",
    "y[y < -0.75] = -0.75\n",
    "plt.plot(x,y,'r')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back5\">Back to Exercise 5</a>\n",
    "\n",
    "<a name=\"ex6answer\">Answer to Exercise 6</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x = np.linspace(0, 6 * np.pi, 50)\n",
    "y = np.sin(x)\n",
    "plt.plot(x[y > 0], y[y > 0], 'bo' )\n",
    "plt.plot(x[y <= 0], y[y <= 0], 'ro' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back6\">Back to Exercise 6</a>\n",
    "\n",
    "<a name=\"ex6answer\">Answer to Exercise 7</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "x,y = np.loadtxt('xypoints.dat')\n",
    "plt.plot(x, y, 'ro')\n",
    "plt.plot(x[(x < -2) & (y >= -5) & (y < 0) ], y[(x < -2) & (y >= -5) & (y < 0) ], 'bo')\n",
    "r = np.sqrt((x - 5) ** 2 + y ** 2)\n",
    "plt.plot(x[r < 5], y[r < 5],'go')\n",
    "plt.axis('image');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"#back7\">Back to Exercise 7</a>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.1+"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}