{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python Tutorial" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are using **Jupyter Notebook** as an interface for Python programming. This html page is converted from a Notebook; you can download the source file by clicking the download button on the upper right corner and choose the .ipynb format. If you are reading this inside the notebook, you may modify and play with the commands." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Notebook editor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Jupyter Notebook contains three types of cells: Code, Markdown, and Raw. You can add a cell and change its type by choosing from the menu bar on top." ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "This is a `Markdown` cell (see basic Markdown syntax [here](https://www.markdownguide.org/basic-syntax/)). Double click to edit its content, then press \"Shift+Enter\" to display it.\n", "\n", "Below is a `Code` cell. Press \"Shift+Enter\" to execute the codes inside the cell." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!\n" ] } ], "source": [ "print(\"Hello World!\") # everything after the `#` sign is comment" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can format the string by passing it as a variable." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World! from Python\n" ] } ], "source": [ "s = \"Hello World!\" # assign string to variable s\n", "print(f'{s} from Python') # s will be replaced by its value" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Variable types and operations" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python variables are \"pointers\"; we can assign any data type to a variable without having to define the type." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "x = 17 # x is an integer\n", "y = 2.3 # y is a floating number\n", "z = 'hello' # z is a string\n", "l = [1, 2, 3] # l is a list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some basic operations on these variables are as follows." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "17 / 2 = 8.5\n", "17 // 2 = 8\n", "17 % 2 = 1\n" ] } ], "source": [ "print(f'{x} / 2 = {x/2}') # single slash division will convert integers to float\n", "print(f'{x} // 2 = {x//2}') # double slash gives integer division, i.e. quotient\n", "print(f'{x} % 2 = {x%2}') # percentage sign gives remainder of integer division" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x != 20 # unequal to" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(x > 20) or (x == 17) # logical operators: and, or" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "list [1, 2, 3, 4] has length 4.\n" ] } ], "source": [ "l.append(4) # add item to list\n", "n = len(l) # get length of list\n", "print(f'list {l} has length {n}.')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "a = l[0] # retrieve element of list\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that Python **indices start from 0**." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l * 3 # one can multiply list by number" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 1, 2, 3, 4]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l + l # or add two lists" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'hello world. hello world. hello world. hello world. hello world. '" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(z + \" world. \") * 5 # string is treated like a list of characters" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['h', 'e', 'l', 'l', 'o']" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Control flow" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Basic controls include `if` and `for` statements. Notice that Python uses **indentation** to group code blocks." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7 is positive\n" ] } ], "source": [ "x = 7\n", "if x == False: # 0 equals False, otherwise True\n", " print(f'{x} is zero')\n", "elif x > 0:\n", " print(f'{x} is positive')\n", "elif x in l: # check if an element is in a list\n", " print(f'{x} belongs to {l}')\n", "else:\n", " print(f'{x} not found.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is a `for` loop. A `while` loop would be similar." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World #0\n", "Hello World #1\n", "Hello World #2\n", "Hello World #3\n", "Hello World #4\n", "Hello World #5\n", "Hello World #6\n", "The `for` loop has ended.\n" ] } ], "source": [ "n = 10 # number of iterations in the `for` loop below\n", "for i in range(n): # range() is a built-in function that returns an iterator\n", " print(f\"Hello World #{i}\") # in each iteration i will take on a new value incremented by 1\n", " if i > 5:\n", " break # break out of loop, jumping to codes below this `for` block\n", " else:\n", " continue # skip to next iteration, ignoring anything below this `if` block\n", " print(\"This line will not be printed.\") # this line will be skipped because of the line above\n", "else: # this `else` is paired with the `for` statement\n", " print('Finished printing the full list.') # this will be executed if the `for` loop completes normally\n", "print('The `for` loop has ended.') # this will always be executed as it is outside the `for` loop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You are welcome to change the number `n` in the above code and see what happens. Try to understand why the output looks the way it is." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python allows you to loop over elements of any list, which are not necessarily integers. Note that the elements of a Python list do not even have to be of the same variable type." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7 \n", "2.3 \n", "hello \n" ] } ], "source": [ "mixed = [x, y, z] # these variables as defined above are of different types\n", "for e in mixed: # for each element `e` in the list `mixed`\n", " print(e, type(e)) # the function `type` returns the variable type" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above `for` loop is equivalent to one using an index:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7 \n", "2.3 \n", "hello \n" ] } ], "source": [ "for i in range(len(mixed)):\n", " e = mixed[i]\n", " print(e, type(e))" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "```{admonition} Exercise\n", ":class: tip\n", "\n", "**Find prime numbers:** \n", "Let us use the basic operations we learned so far to carry out a simple task: finding all prime numbers below 100.\n", "```" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "````{admonition} Solution\n", ":class: note, dropdown\n", "\n", "By definition, a prime number cannot be divided by any smaller numbers. Therefore, for a given number $n$, we can check if it is a prime by trying to divide it with all numbers smaller than it. As soon as we find one smaller number that divides $n$, we will know that $n$ is not a prime. We will then throw it out and check the next number $n+1$. But if no smaller number divides $n$, then we know that $n$ is prime and will store it in our list of primes. This line of reasoning can be translated into code as follows.\n", "\n", "```{code-block}\n", "prime_list = [] # create an empty list to store primes\n", "for n in range(1,100): # check every n in the range 1 to 99 (note that 100 is excluded!)\n", " for m in range(2,n): # check every m smaller than n\n", " # print(n, m, n%m) # uncomment this line to see what is going on through the loops\n", " if n%m == 0: # the % operator calculates the remainder from integer division; check if remainder is 0\n", " break # end the `for` loop because there is no need to check other m\n", " else: # this is executed only if we did not `break` from the loop, which means no m divides n\n", " prime_list.append(n) # add n to our list of primes\n", "print(prime_list)\n", "```\n", "\n", "Can you find ways to improve this algorithm?\n", "````" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions and Classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To make codes modular, we can define a block of codes as a *function*, or *class* to be more stylish, so that we can reuse it later." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Defining functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A *function* takes certain inputs, does certain operations, and returns certain outputs. Defining functions in Python is very similar to that in other languages, except for the convenience that we do not have to explicitly state the variable types of inputs or outputs." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As an example, let us define a function that calculates the first $N$ Fibonacci numbers. By definition, these numbers are generated by the recursive relation\n", "\\begin{equation*}\n", "F_{n+1} = F_{n} + F_{n-1}\n", "\\end{equation*}\n", "starting from $F_0 = 0$ and $F_1 = 1$. To get the $N$-th Fibonacci number, we need to iterate the recursion $N-1$ times." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def fibonacci(N): # here `fibonacci` is the function name, `N` is the input (need not specify data type)\n", " \"\"\"\n", " generate the first N Fibonacci numbers.\n", " input:\n", " N: integer expected, number of Fibonacci numbers to calculate.\n", " output:\n", " fibo_list: a list of Fibonacci numbers.\n", " \"\"\"\n", " fibo_list = [0, 1] # list to store Fibonacci numbers\n", " a, b = 0, 1 # assign values of a, b as a pair (Python \"tuple\")\n", " while len(fibo_list) < N: # use `while` loop to ensure that we get N numbers\n", " a, b = b, a+b # carry out recursion by reassigning the value of a with b and b with a+b\n", " fibo_list.append(b) # store the next Fibonacci number\n", " return fibo_list[:N] # return list as output (need not specify data type)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice how we assigned values of a, b simultaneously, using Python *tuple*. A tuple is an ordered set, e.g., `(1, 2, 3)`, where the parenthesis is optional. The elements of the tuple on the right hand side, `(b, a+b)`, are evaluated simultaneously and then assigned to the left hand side. Had we not used tuple, this step would have required another auxiliary variable, e.g., `c = a + b; a = b; b = c`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us test our function by executing it with an *argument*, say $N = 10$." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fibonacci(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Python classes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As an object-oriented programming language, an important strength of Python lies in the use of class objects. A *class* is like a user-defined variable type that has its own attributes and methods." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can define a class as follows." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "class Fibonacci: # here `Fibonacci` is the class name\n", " \"\"\"\n", " generate Fibonacci numbers.\n", " \"\"\"\n", " \n", " def __init__(self): # there is at least one input that is `self`\n", " \"\"\"\n", " initialize the class object by defining internal variables.\n", " \"\"\"\n", " self.a = 0 # current value of lower number\n", " self.b = 1 # current value of higher number\n", " self.fibo_list = [0, 1] # list to store calculated numbers\n", " \n", " def next_num(self): # define an internal function (a \"method\" of the class object)\n", " \"\"\"\n", " calculate the next number.\n", " output:\n", " b: int, next Fibonacci number.\n", " \"\"\"\n", " self.a, self.b = self.b, self.a + self.b\n", " self.fibo_list.append(self.b)\n", " return self.b\n", " \n", " def find(self, N): # functions can have other inputs besides `self`\n", " \"\"\"\n", " find the first N numbers.\n", " input:\n", " N: int, number of Fibonacci numbers to find.\n", " output:\n", " fibo_list: the list of first N Fibonacci numbers.\n", " \"\"\"\n", " while len(self.fibo_list) < N: # if not enough numbers are already calculated\n", " self.next_num() # call the class's own method to calculate the next number\n", " return self.fibo_list[:N] # return the first N numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let us create an **instance** of the class and test its method." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fibo1 = Fibonacci()\n", "fibo1.find(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So far it works just like the function we defined above. The advantage of defining it as a *class* instead of a *function* is that, while a function will be \"forgotten\" after use, an *instance* of the class will continue to exist as an object (like a variable), which can be called later. For example, if we now want to calculate more Fibonacci numbers, we can simply call the class object again." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "55" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fibo1.next_num()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fibo1.find(15)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These numbers are saved internally inside the class object `fibo1`. When we calculate more numbers, we do not have to repeat our calculations before, and can simply continue to calculate new numbers. This is unlike the function `fibonacci()` defined above, for which we always have to start over from the beginning. For example, our class object may have already calculated and stored more numbers than we need, so it would simply return the stored numbers." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]\n" ] } ], "source": [ "print(fibo1.fibo_list) # this is the current list of numbers already calculated and stored" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 1, 2, 3]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fibo1.find(5) # it will return the first few stored numbers without having to recalculate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{admonition} Exercise\n", ":class: tip\n", "\n", "**Write a class for finding prime numbers:** \n", "We have already been able to find the prime numbers using `for` loops. Now let us package our codes into a class, so that it stores those numbers and can calculate new ones if needed.\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "````{admonition} Solution\n", ":class: note, dropdown\n", "\n", "Here is the code:\n", "```{code-block}\n", "class Prime:\n", " \"\"\"\n", " find prime numbers.\n", " \"\"\"\n", " \n", " def __init__(self):\n", " \"\"\"\n", " initialize the class object by defining internal variables.\n", " \"\"\"\n", " self.n = 1 # current number that has been checked\n", " self.prime_list = [1] # list to store prime numbers\n", " \n", " def next_num(self):\n", " \"\"\"\n", " calculate the next prime number.\n", " output:\n", " n: int, next prime number.\n", " \"\"\"\n", " while True: # not the best practice... consider putting an upper bound\n", " self.n = self.n + 1 # check next number\n", " for m in self.prime_list[1:]: # only need to check existing prime numbers >= 2\n", " if self.n % m == 0:\n", " break\n", " else:\n", " self.prime_list.append(self.n)\n", " return self.n # the `return` statement automatically terminates the loop\n", " \n", " def find(self, N): # functions can have other inputs besides `self`\n", " \"\"\"\n", " find the first N prime numbers.\n", " input:\n", " N: int, number of prime numbers to find.\n", " output:\n", " prime_list: the list of first N prime numbers.\n", " \"\"\"\n", " while len(self.prime_list) < N: # if not enough numbers are already calculated\n", " self.next_num() # call the class's own method to calculate the next number\n", " return self.prime_list[:N] # return the first N numbers\n", "```\n", "\n", "To test the class, try:\n", "```{code-block}\n", "prime1 = Prime()\n", "prime1.find(10)\n", "```\n", "````" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Importing Modules" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One power of Python comes from being able to import external packages (or \"modules\") that offer special functionalities. We will rely a lot on the package `NumPy` for numerical computation and `MatPlotLib` for making plots." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### NumPy for numerical computation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To use a module, first import it." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.21.5\n" ] } ], "source": [ "import numpy as np # use `np` as a shorthand for `numpy`\n", "print(np.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `numpy` module provides various functions that deal with arrays (matrices), using syntax very similar to *MatLab*." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0. 0. 0. 0.]\n" ] } ], "source": [ "a = np.zeros(5) # create a zero array, can be used to initialize an array\n", "print(a) # note that the default data type is float" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0 1 2 3 4 5 6 7 8 9]\n", "sum = 45\n" ] } ], "source": [ "b = np.arange(10) # numpy version of `range()` (which is an array instead of an iterator)\n", "print(b) # these are integers by default, like in `range()`\n", "s = np.sum(b) # calculate the sum of the whole array\n", "print(f'sum = {s}')" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 1 1 1 1]\n", " [1 1 1 1 1]\n", " [1 1 1 1 1]\n", " [1 1 1 1 1]\n", " [1 1 1 1 1]]\n", "c . a = [0. 0. 0. 0. 0.]\n" ] } ], "source": [ "c = np.ones((5,5), dtype=int) # create a (5x5) 2d-array with all ones, specifying data type as integer\n", "print(c)\n", "d = np.dot(c, a) # dot product, `c` is automatically treated as float because `a` is float\n", "print(f'c . a = {d}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The advantage of using arrays is that you can do operations \"in parallel\", i.e., on all elements in the array \"simultaneously\", which is *much faster* than using a `for` loop. Note that NumPy is able to \"broadcast\" over arrays of different shapes. The rules are intuitive between numbers and arrays, but can be confusing for multi-dimensional arrays." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "10 - b # the first number (\"0d\" array) will be broadcasted" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access elements of an array using indices (starting **from 0**), just like for Python lists." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([3, 4, 5])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b[3:6] # index 3 is really the \"fourth\" element and, again, last index is not included" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can convert a Python list to a NumPy array." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1. 2. 3.]\n", " [4. 5. 6.]\n", " [7. 8. 9.]]\n" ] } ], "source": [ "e = np.array([[1, 2, 3],\n", " [4, 5, 6],\n", " [7, 8, 9]], dtype=float) # specify data type if necessary\n", "print(e)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[4., 5.],\n", " [7., 8.]])" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "e[1:3,0:2] # 2d indices, first axis is row, second is column" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Random numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A useful submodule of NumPy is `random`, which allows us to generate random numbers and use them in many ways." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.03188996 0.08789285 0.92091998]\n" ] } ], "source": [ "r = np.random.rand(3) # create 3 random numbers uniformly distributed between 0 and 1\n", "print(r)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0.76617361 0.74984009]\n", " [ 0.47185396 -0.13183161]\n", " [ 1.00402612 -0.54519687]]\n" ] } ], "source": [ "rn = np.random.randn(3,2) # create a (3x2) array of random numbers with standard Gaussian distribution\n", "print(rn)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### MatPlotLib for making plots" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `matplotlib` module provides functions for making various types of plots, with similar syntax to *MatLab* (but better-looking plots IMO). In most cases we only need the basic `pyplot` submodule." ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us plot a function as a curve." ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "x_array = np.arange(0, 10, 0.1) # 1d-array from 0 to 10 (excluded) with equal increments 0.1\n", "y_array = np.sin(x_array) # numpy functions work element-wise on arrays\n", "\n", "plt.figure() # create an empty figure\n", "plt.plot(x_array, y_array) # plot curve\n", "plt.xlabel('x') # make x label\n", "plt.ylabel('y') # make y label\n", "plt.title(r'$y(x) = \\sin (x)$') # 'raw' string has latex support\n", "plt.show() # show figure" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.7.4" } }, "nbformat": 4, "nbformat_minor": 4 }