{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Introduction to programming for Geoscientists with Python\n", "### [Gerard Gorman](http://www.imperial.ac.uk/people/g.gorman)\n", "\n", "# Lecture 1: Computing with formulas" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "source": [ "## Learning objectives:\n", "\n", "* You will understand that Python will help you defy gravity.\n", "* You will know how to execute Python statements from within Jupyter.\n", "* Learn what a program variable is and how to express a mathematical expression in code.\n", "* Print program outputs.\n", "* Access mathematical functions from a Python module." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "slideshow": { "slide_type": "slide" } }, "outputs": [], "source": [ "import antigravity" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "![import antigravity](https://imgs.xkcd.com/comics/python.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Programming a mathematical formula\n", "\n", "Here is a formula for the position of a ball in vertical motion, starting at ground level (i.e. $y=0$) at time $t=0$:\n", " $$ y(t) = v_0t- \\frac{1}{2}gt^2 $$\n", "\n", "where:\n", "\n", "* $y$ is the height (position) as a function of time $t$\n", "* $v_0$ is the initial velocity (at $t=0$)\n", "* $g$ is the acceleration due to gravity\n", "\n", "The computational task is: given $v_0$, $g$ and $t$, compute the value $y$. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How do we program this task?** A program is a sequence of instructions given to the computer. However, while a programming language is much **simpler** than a natural language, it is more **pedantic**. Programs must have correct syntax, i.e., correct use of the computer language grammar rules, and no misprints.\n", "\n", "So let's execute a Python statement based on this example. Evaluate $y(t) = v_0t- \\frac{1}{2}gt^2$ for $v_0=5$, $g=9.81$ and $t=0.6$. If you were doing this on paper you would probably write something like this: $$ y = 5\\cdot 0.6 - {1\\over2}\\cdot 9.81 \\cdot 0.6^2.$$ Happily, writing this in Python is very similar:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.2342\n" ] } ], "source": [ "print(5*0.6 - 0.5*9.81*0.6**2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Go ahead and mess with the code above to see what happens when you change values and rerun. To see what I mean about programming being pedantic, see what happens if you replace `**` with `^`:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "TypeError", "evalue": "unsupported operand type(s) for ^: 'float' and 'int'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m0.6\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m0.5\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m9.81\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m0.6\u001b[0m\u001b[0;34m^\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for ^: 'float' and 'int'" ] } ], "source": [ "print(5*0.6 - 0.5*9.81*0.6^2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "or `write` rather than `print`:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'write' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m0.6\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m0.5\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m9.81\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m0.6\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'write' is not defined" ] } ], "source": [ "write(5*0.6 - 0.5*9.81*0.6**2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "While a human might still understand these statements, they do not mean anything to the Python interpreter. Rather than throwing your hands up in the air whenever you get an error message like the above (you are going to see many during the course of these lectures!!!) train yourself to read the message patiently to get an idea what it is complaining about and re-read your code from the perspective of the pedantic Python interpreter.\n", "\n", "Error messages can look bewildering (frustrating etc.) at first, but it gets much **easier with practise**." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Storing numbers in variables\n", "From mathematics you are already familiar with variables (e.g. $v_0=5,\\quad g=9.81,\\quad t=0.6,\\quad y = v_0t -{1\\over2}gt^2$) and you already know how important they are for working out complicated problems. Similarly, you can use variables in a program to make it easier to read and understand." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.2342\n" ] } ], "source": [ "v0 = 5\n", "g = 9.81\n", "t = 0.6\n", "y = v0*t - 0.5*g*t**2\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This program spans several lines of text and uses variables, otherwise the program performs the same calculations and gives the same output as the previous program.\n", "\n", "In mathematics we usually use one letter for a variable, resorting to using the Greek alphabet and other characters for more clarity. The main reason for this is to avoid becoming exhausted from writing when working out long expressions or derivations. However, when programming you should use more descriptive names for variable names. This might not seem like an important consideration for the trivial example here but it becomes increasingly important as the program gets more complicated and if someone else has to read your code." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Good variable names make a program easier to understand!\n", "\n", "Permitted variable names include:\n", "\n", "* One-letter symbols.\n", "* Words or abbreviation of words.\n", "* Variable names can contain a-z, A-Z, underscore (\"'_'\") and digits 0-9, **but** the name cannot start with a digit.\n", "\n", "Variable names are case-sensitive (i.e. \"'a'\" is different from \"'A'\"). Let's rewrite the previous example using more descriptive variable names:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.2342\n" ] } ], "source": [ "initial_velocity = 5\n", "acceleration_of_gravity = 9.81\n", "TIME = 0.6\n", "VerticalPositionOfBall = initial_velocity*TIME - 0.5*acceleration_of_gravity*TIME**2\n", "print(VerticalPositionOfBall)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Certain words have a **special meaning** in Python and **cannot be used as variable names**. These are: *and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, with, while,* and *yield*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Adding comments to code\n", "\n", "Not everything written in a computer program is intended for execution. In Python anything on a line after the '#' character is ignored and is known as a **comment**. You can write whatever you want in a comment. Comments are intended to be used to explain what a snippet of code is intended for. It might for example explain the objective or provide a reference to the data or algorithm used. This is both useful for you when you have to understand your code at some later stage, and indeed for whoever has to read and understand your code later." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.2342\n" ] } ], "source": [ "# Program for computing the height of a ball in vertical motion.\n", "v0 = 5 # Set initial velocity in m/s.\n", "g = 9.81 # Set acceleration due to gravity in m/s^2.\n", "t = 0.6 # Time at which we want to know the height of the ball in seconds.\n", "y = v0*t - 0.5*g*t**2 # Calculate the vertical position\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 1.1: Convert from meters to British length units\n", "Make a program where you set a length given in meters and then compute and write out the corresponding length measured in inches, in feet, in yards, and in miles. Use the fact that one inch is 2.54 cm, one foot is 12 inches, one yard is 3 feet, and one British mile is 1760 yards. As a verification, a length of 640 meters corresponds to 25196.85 inches, 2099.74 feet, 699.91 yards, or 0.3977 miles." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Formatted printing style\n", "Often we want to print out results using a combination of text and numbers, e.g. \"'At t=0.6 s, y is 1.23 m'\". Particularly when printing out floating point numbers we should **never** quote numbers to a higher accuracy than they were measured. Python provides a *printf formatting* syntax exactly for this purpose. We can see in the following example that the *slot* `%g` was used to express the floating point number with the minimum number of significant figures, and the *slot* `%.2f` specified that only two digits are printed out after the decimal point." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "At t=0.6 s, y is 1.23 m.\n" ] } ], "source": [ "print(\"At t=%g s, y is %.2f m.\" % (t, y))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Notice in this example how the values in the tuple `(t, y)` are inserted into the *slots*." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Sometimes we want a multi-line output. This is achieved using a triple quotation (*i.e.* `\"\"\"`):" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "At t=0.600000 s, a ball with\n", "initial velocity v0=5.000E+00 m/s\n", "is located at the height 1.23 m.\n", "\n" ] } ], "source": [ "print(\"\"\"At t=%f s, a ball with\n", "initial velocity v0=%.3E m/s\n", "is located at the height %.2f m.\n", "\"\"\" % (t, v0, y))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 1.2: Compute the air resistance on a football\n", "The drag force, due to air resistance, on an object can be expressed as\n", "$$F_d = \\frac{1}{2}C_D\\rho AV^2$$\n", "where $\\rho$ is the density of the air, $V$ is the velocity of the object, $A$ is the cross-sectional area (normal to the velocity direction), and $C_D$ is the drag coefficient, which depends heavily on the shape of the object and the roughness of the surface.

\n", "The gravity force on an object with mass $m$ is $F_g = mg$, where $g = 9.81ms^{−2}$.

\n", "Write a program that computes the drag force and the gravity force on an object. Write out the forces with one decimal in units of Newton ($N = kgm/s^2$). Also print the ratio of the drag force and the gravity force. Define $C_D$, $\\rho$, $A$, $V$, $m$, $g$, $F_d$, and $F_g$ as variables, and put a comment with the corresponding unit.

" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "As a computational example, you can initialize all variables with values relevant for a football kick. The density of air is $\\rho = 1.2 kg m^{−3}$. For any ball, we have obviously that $A = \\pi a^2$, where $a$ is the radius of the ball, which can be taken as $11cm$ for a football. The mass of the ball is $0.43kg$. $C_D$ can be taken as $0.2$.

\n", "Use the program to calculate the forces on the ball for a hard kick, $V = 120km/h$ and for a soft kick, $V = 10km/h$ (it is easy to make the mistake of mixing inconsistent units, so make sure you compute with V expressed in m/s). Make sure you use the *printf* formatting style introduced above." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## How are arithmetic expressions evaluated?\n", "Consider the random mathematical expression, ${5\\over9} + 2a^4/2$, implemented in Python as `5.0/9 + 2*a**4/2`.\n", "\n", "The rules for evaluating the expression are the same as in mathematics: proceed term by term (additions/subtractions) from the left, compute powers first, then multiplication and division. Therefore in this example the order of evaluation will be:\n", "\n", "1. `r1 = 5.0/9`\n", "2. `r2 = a**4`\n", "3. `r3 = 2*r2`\n", "4. `r4 = r3/2`\n", "5. `r5 = r1 + r4`\n", "\n", "Use parenthesis to override these default rules. Indeed, many programmers use parenthesis for greater clarity." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 1.3: Compute the growth of money in a bank\n", "Let *p* be a bank's interest rate in percent per year. An initial amount *A* has then grown to $$A\\left(1+\\frac{p}{100}\\right)^n$$ after *n* years. Write a program for computing how much money 1000 euros have grown to after three years with a 5% interest rate." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Standard mathematical functions\n", "What if we need to compute $\\sin x$, $\\cos x$, $\\ln x$, etc. in a program? Such functions are available in Python's *math module*. In fact there is a vast universe of functionality for Python available in modules. We just *import* in whatever we need for the task at hand.\n", "\n", "In this example we compute $\\sqrt{2}$ using the *sqrt* function in the *math* module:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.4142135623730951\n" ] } ], "source": [ "import math\n", "r = math.sqrt(2)\n", "print(r)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "or:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.4142135623730951\n" ] } ], "source": [ "from math import sqrt\n", "r = sqrt(2)\n", "print(r)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "or:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.4142135623730951\n" ] } ], "source": [ "from math import * # import everything in math\n", "r = sqrt(2)\n", "print(r)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Another example:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0670178174513938\n" ] } ], "source": [ "from math import sin, cos, log\n", "x = 1.2\n", "print(sin(x)*cos(x) + 4*log(x)) # log is ln (base e)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 1.4: Evaluate a Gaussian function\n", "The bell-shaped Gaussian function,\n", "$$f(x)=\\frac{1}{\\sqrt{2\\pi}s}\\exp\\left(-\\frac{1}{2} \\left(\\frac{x-m}{s}\\right)^2\\right)$$\n", "is one of the most widely used functions in science and technology. The parameters $m$ and $s$ are real numbers, where $s$ must be greater than zero. Write a program for evaluating this function when $m = 0$, $s = 2$, and $x = 1$. Verify the program's result by comparing with hand calculations on a calculator." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 1.5: Find errors in the coding of a formula\n", "Given a quadratic equation,\n", "$$ax^2 + bx + c = 0,$$\n", "$$x1 = \\frac{−b + \\sqrt{b^2 −4ac}}{2a},$$ and\n", "$$x2 = \\frac{−b − \\sqrt{b^2 −4ac}}{2a}.$$\n", "Why does the following program not work correctly?" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "ename": "ValueError", "evalue": "math domain error", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m;\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m;\u001b[0m \u001b[0mc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mmath\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msqrt\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mq\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msqrt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mb\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0mx1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mb\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mq\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mx2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mb\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mq\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: math domain error" ] } ], "source": [ "a = 2; b = 1; c = 2\n", "from math import sqrt\n", "q = sqrt(b*b - 4*a*c)\n", "x1 = (-b + q)/2*a\n", "x2 = (-b - q)/2*a\n", "print(x1, x2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Slideshow", "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.6.2" } }, "nbformat": 4, "nbformat_minor": 1 }