Programming and Scientific Computing in Python For Aerospace Engineers - J Hoekstra (TU Delft)
Programming and Scientific Computing in Python For Aerospace Engineers - J Hoekstra (TU Delft)
Programming and Scientific Computing in Python For Aerospace Engineers - J Hoekstra (TU Delft)
40
35
30
25
20
15
10
5
0 10 20 30 40 50 60 70
if language==python:
programming = fun
2
Table of Contents
1. Getting started ......................................................................................................................... 8
1.1 What is programming? .......................................................................................................... 8
1.2 What is Python? .................................................................................................................... 9
1.3 Installing Python ................................................................................................................. 10
1.3.1 Using a packaged version of Python ............................................................................ 11
1.3.2 Customized installation of separate packages (Windows/Mac/Linux)........................ 13
1.3.3 Documentation ............................................................................................................. 13
1.3.4 Optional tools ............................................................................................................... 14
1.3.5 Configuring and using Python ..................................................................................... 14
1.3.6 Spyder: a more advanced IDE ..................................................................................... 16
1.4 Examples and exploration of the language ......................................................................... 17
1.4.1 Temperature conversion: (PRINT, INPUT statement, variables) ................................ 17
1.5.2 Example: a,b,c formula solver (IF statement, Math functions) ................................... 20
1.5.3 Example: using lists and a for-loop ............................................................................. 22
1.5.4 While loops .................................................................................................................. 27
1.5.5 More modules .............................................................................................................. 28
1.5.6 Finding your way around: many ways in which you can get help .............................. 29
2. Python syntax: Variables and functions ................................................................................ 33
2.1 Assignment and implicit type declaration........................................................................... 33
2.2 Floats ................................................................................................................................... 33
2.3 Integers ................................................................................................................................ 34
2.4 Strings ................................................................................................................................. 35
2.5 Logicals/Booleans ............................................................................................................... 37
2.6 Lists ..................................................................................................................................... 38
2.6.1 What are lists? .............................................................................................................. 38
2.6.2 Indexing and slicing ..................................................................................................... 39
2.6.3*** Lists are Mutable: risks with multiple dimensions list creation ............................ 40
2.6.4 List methods ................................................................................................................. 43
2.7 Some useful standard built-in functions ............................................................................. 44
3. Python syntax: Statements .................................................................................................... 45
3.1 Assignment ......................................................................................................................... 45
3.2 Input function ...................................................................................................................... 46
3.3 Print statement .................................................................................................................... 47
3.4 If-statement ......................................................................................................................... 48
3.5 For-loop............................................................................................................................... 49
3
3.6 WHILE-loop ....................................................................................................................... 50
3.7 Loop controls: Break and Continue .................................................................................... 51
4. Making your code reusable and readable.............................................................................. 52
5. Using modules like the math module.................................................................................... 55
5.1 How to use math functions ................................................................................................. 55
5.2 List of math module functions and constants ..................................................................... 57
5.3 The module random ............................................................................................................ 58
5.4 Explore other modules ........................................................................................................ 58
6. Defining your own functions and modules ........................................................................... 59
6.1 Def statement: define a function ......................................................................................... 59
6.2 Multiple outputs .................................................................................................................. 60
6.3 Function with no outputs .................................................................................................... 60
6.4 Using one variable in definition as input and output is not possible .................................. 61
6.5 Using functions defined in other modules: managing a project ......................................... 62
7. Using logicals, example algorithm: Bubblesort .................................................................... 63
8. File input/output and String handling ................................................................................... 66
8.1 Opening and closing of files ............................................................................................... 66
8.2 Reading from a text file ...................................................................................................... 66
8.3 Writing to files .................................................................................................................... 67
8.4 Reading a formatted data file .............................................................................................. 68
8.5 List of some useful string methods/functions ..................................................................... 70
8.6 Genfromtxt: a tool in Numpy to read data from text files in one line ................................ 71
9. Matplotlib: Plotting in Python .............................................................................................. 73
9.1 Example: plotting sine and cosine graph ............................................................................ 73
9.2 More plots in one window and scaling: subplot and axis .............................................. 75
9.3 Interactive plots ................................................................................................................... 77
9.3 3D and contour plots ........................................................................................................... 78
9.4 Overview of essential matplotlib.pyplot functions ............................................................. 80
10. Numerical integration ........................................................................................................ 81
10.1 Falling ball example .......................................................................................................... 81
10.2 Two-dimensions and the atan2(y,x) function ................................................................... 82
10.3 Program structure of numerical integration and simulation ............................................. 83
4
11. Numpy and Scipy : Scientific Computing with Arrays and Matrices .............................. 84
11.1 Numpy, Scipy ................................................................................................................... 84
11.2 Arrays ................................................................................................................................ 85
11.3 Speeding it up: vectorizing your software with numpy .................................................... 87
11.4 Matrices and Linear algebra functions .............................................................................. 90
11.5 Scipy: a toolbox for scientists and engineers .................................................................... 93
11.6 Scipy example: Polynomial fit on noisy data ................................................................... 94
11.7 iPy Notebook .................................................................................................................... 97
12. Tuples, classes, dictionaries and sets ................................................................................. 98
12.1 New types.......................................................................................................................... 98
12.2 Tuples ................................................................................................................................ 99
12.3 Classes and methods (object oriented programming) ..................................................... 100
12.4 Dictionaries & Sets ..................................................................................................... 102
13. Pygame: animation, visualization and controls ............................................................... 103
13.1 Pygame module ............................................................................................................... 103
13.2 Setting up a window........................................................................................................ 104
13.3 Surfaces and Rectangles ................................................................................................. 105
13.4 Bitmaps and images ........................................................................................................ 107
13.5 Drawing shapes and lines................................................................................................ 108
13.6 When our drawing is ready: pygame.display.flip() ........................................................ 109
13.7 Timing and the game-loop .............................................................................................. 109
13.8 Input: keyboard, mouse and events ................................................................................. 112
13.9 Overview of basic pygame functions .............................................................................. 114
14. Distributing your Python programs using Py2exe ........................................................... 115
14.1 Making an .exe of your program..................................................................................... 115
14.2 Making a setup program with e.g. Inno Setup ................................................................ 118
15. Go exploring: Some pointers for applications of Python beyond this course................. 119
15.1 Alternatives to pygame for 2D graphics ......................................................................... 119
15.1.1 Tkinter canvas (included in Python) ........................................................................ 119
15.1.2 Pycairo ( http://cairographics.org/pycairo/) ............................................................. 119
15.1.3 Using Python Console in GIMP .............................................................................. 120
15.2 Animated 3D graphics .................................................................................................... 121
15.2.1 VPython: easy 3D graphics ...................................................................................... 121
15.2.2 Panda3D ................................................................................................................... 121
5
15.2.3 Open GL programming ............................................................................................ 122
15.2.3 Blender (www.blender.org) ..................................................................................... 123
15.2.4 Physics Engine: PyODE (http://pyode.sourceforge.net/)......................................... 123
15.3 User interfaces: windows dialog boxes, pull-down menus, etc. ..................................... 124
15.3.1 Tkinter ...................................................................................................................... 124
15.3.2 PyQt ......................................................................................................................... 126
15.3.4 wxPython ................................................................................................................. 127
15.3.5 GLUT ....................................................................................................................... 127
15.3.6 Glade Designer for Gnome ...................................................................................... 127
15.4 Interfacing with Excel sheets .......................................................................................... 129
15.5 Interfacing with hardware ......................................................................................... 130
15.5.1 Velleman k8055 example ........................................................................................ 130
15.5.2 Raspberry Pi ............................................................................................................. 131
15.5.3 MicroPython ............................................................................................................ 132
16. Exception Handling in Python ......................................................................................... 133
Appendix A Overview of basic Python statements .................................................................... 137
Appendix B Overview of functions and special operators ......................................................... 138
6
Preface
This reader was developed for, and during the pilot of, the Programming course in the first year
of the BSc program Aerospace Engineering at the Delft University of Technology in 2012. It is
still a living document and will be expanded and adapted (and debugged) for another year.
The goal of the Python programming course is to enable the student to:
- write a program for scientific computing
- develop models
- analyze behavior of the models using e.g. plots
- visualize models by animating graphics
The course assumes some mathematical skills, but no programming experience at the start.
This document is provided as a reference for the elaboration of the assignments. The reader is
encouraged to read through the relevant chapters applicable to a particular problem. For later
reference, many tables as well as some appendices with quick reference guides, have been
included. These encompass the most often used functions and methods. For a complete overview,
there is the excellent documentation as provided with Python in the IDLE Help menu, as well as
the downloadable and on-line documentation for the Python modules Numpy, Scipy, Matplotlib
and Pygame.
Also, the set-up of the present course is to show the appeal of programming. Having this
powerful tool at hand allows the reader to use the computer as a mathematical slave. And by
making models one basically has the universe in a sandbox at ones disposal: Any complex
problem can be programmed and displayed, from molecular behavior to the motion in a complex
gravity field in space.
An important ingredient at the beginning of the course is the ability to solve mathematical
puzzles and numerical problems. As an addition to the basic Python modules, the Pygame
module has been included in this reader. This allows, next to the simulation of a physical
problem, a real-time visualization and some control for the user, which also adds some fun for
the beginning and struggling programmer.
Next to the mathematical puzzles, challenges (like Project Euler and the Python challenge) and
games, there is a programming contest included in the last module of the course for which there
is a prize for the winners. Often students surprise me with their skills and creativity in such a
contest by submitting impressive simulations and games.
Many thanks to the students and teaching assistants, who contributed greatly to this reader. Their
questions, input and feedback formed the foundation for this reader. Also many thanks to the
student assistants for their help in debugging the reader.
7
1. Getting started
This also means that learning to program is very different from the learning you do in most other
courses. In the beginning, there is a very steep learning curve, but once you have taken this first
big step, it will become much easier and basically a lot of fun. But how and when you take that
first hurdle is very personal. Of course, you need to achieve the right rate of success over failure,
something you can achieve by testing small parts during the development. For me, there arent
many things that give me more pleasure than to see my program (finally) work. The instant,
often visual, feedback makes it a very rewarding activity.
And even though at some stage you will also see the right solution method in a flash, at the same
time your program will almost certainly not work the first time you run it. A lot of time is spent
understanding why it will not work and fixing this. Therefore some people call the art of
programming: solving puzzles created by your own stupidity!
8
Another way to design and represent algorithms is using simplified natural language. Lets take
as an example the algorithm to find the maximum value of four numbers. We can detail this
algorithm as a number of steps:
Going through these steps, the result will always be that the maximum value of the four numbers
is shown on the screen. This kind of description in natural language is called pseudo-code.
This pseudo-code is already very close to how Python looks, as this was one the goals of Python:
it should read just as clear as pseudo-code. But before we can look at some real Python code, we
need to know what Python is and how you can install it. After that, we will have a look at some
simple programs in Python, which you can try out in your freshly installed Python environment.
Guido van Rossum was employed by Google for years, as this is one of the many companies that
use Python. He is currently working for another user of Python: Dropbox. He still is the
moderator of the language, or as he is called by the Python community: the benevolent dictator
for life.
A practical advantage of Python is that it is free, and so are all add-ons, which have been
developed by the large (academic) Python community. Some have become standards of their
own, such as the combination Numpy/Scipy/Matplotlib. These scientific libraries(or modules), in
syntax(grammar) heavily inspired by the software package MATLAB, are now the standard
libraries for scientific computing in Python.
9
There are two current versions: Python 2 and Python 3.(There is also a second and a third
number indicating the exact version, but these as less relevant as they are downwards compatible
with the other 2.x and 3.x versions. At the time of writing the newest versions were 2.7.3 and
3.2.3) Up to Python 3 all versions were downwards compatible. So all past programs and
libraries will still work in a newer Python 2.x versions. However, at some point, Guido van
Rossum wanted to correct some issues, which could only be done by breaking the downward
compatibility. This started the development of Python 3.0. However, luckily for the Python
community, Python 2.x is also still maintained and updated. The majority of the community is
still using Python 2. The parallel path offers a gradual, optional transition. Whether Python 3 will
actually become the standard is yet unknown. An example of a difference between the two
versions is the syntax of the PRINT-statement, which shows a text or a number on the screen
during runtime of the program:
(Another major difference applies to integer division, but we need to know more about data
types to understand that)
Since still many more modules are available for Python 2.x than for Python 3.x, we use Python
2.x. In this reader and the course, we use Python 2.7 (but any 2.5+ version will work).
The libraries that we use: Numpy/Scipy/Matplotlib and Pygame are available for both Python 2.x
and Python 3.x for both the 32-bit version(most used) as well as for the 64-bit version (for
Windows, for Apple there is only a 32-bits version of Pygame). For the 32-bit Python 2.x the
amount of modules available is the largest, so this is the version 95% of the community uses and
so will we in this course.
At times Python is called a script language. A Python source is interpreted when you run the
program. This is very user-friendly: there is no need to compile or link files before you can run it.
The cost is, often, some execution speed. In a way, some (milli)seconds of runtime are traded for
short development times, which saves days or weeks. Note that Python libraries like Numpy and
Scipy use very fast low-level modules, resulting in extremely fast execution times for scientific
computing. It beats MATLAB, Fortran and C++ in many instances for these tasks. The same
goes for Pygame graphics library, as this is a layer over the very fast SDL library used in many
games already.
Using an interpreter instead of a compiler, means you need to have Python installed on the
computer where you run the Python program. But fortunately there is an add-on, called Py2exe,
which avoids this by creating executables, which are self-contained applications. Creating
executables is called compiling. These programs can be executed on any computer without
having installed Python. How this should be done, is covered by a separate chapter of the reader,
called Distributing your Python program. Using the Inno Setup tool, one can integrate data
stored in a program into one setup executable file, which is also covered in this chapter.
10
There are two ways to install Python with the libraries we need:
1. Download a package: a distribution of Python from Python(x,y) or Enthought, which
contains all libraries we need (and many more) except Pygame
2. Or do a custom install: Download the components independently (resulting in a smaller,
tailored installation)
There are two common distributions of Python+add-ons: Enthought (free for universities) and
Python(x,y) (free for all).
Python(x,y) (Windows/Linux)
Python(x,y) is recommended for this course for Windows and Linux Users. Go to:
http://www.pythonxy.org
Then go to Downloads and download the version for your operating system (Windows/Linux).
When you have installed this without pygame, you can also download and install the Pygame
module for Python 2.7 (32 bits) separately. We use this for 2D animated graphics as well as
keyboard/mouse input.
http://pygame.org/download.shtml
Current version of Pygame at the writing of this document is 1.9.1. Select the correct version for
your OS and your Python version.
11
Figure 1.2: A full content of Python(x,y).
Optional libraries/editors which will be referenced in the course are: Spyder, Py2exe. They are
already included in the Python(x,y) distribution.
Enthought/Canopy(Windows/Mac/Linux/Sun)
The Enthought full distribution is available for Windows, Mac, Linux and Sun Solaris. It is free
for universities. Therefore use your university e-mail address when downloading this. There is
also a lightweight distribution, which is free for all and which contains the essential libraries
(Numpy/Scipy/Matplotlib) for this course except, again, Pygame. Go to :
http://www.enthought.com/
Download Enthought version 7.2 which contains Python 2.7. Then add pygame:
http://pygame.org/download.shtml
Current version of Pygame at the writing of this document is 1.9.1. Select the correct version for
your OS and Python version.
There is also a distribution for Apple (& Windows that is called Anaconda, but this will install
64-bit versions on 64-bit machines. The problem is that there is no 64-bit version of Pygame.
12
1.3.2 Customized installation of separate packages (Windows/Mac/Linux)
If you do not want to use these large distributions, there is always the option to install Python
and the modules yourself. Do this in the following order:
http://python.org/download/
For scientific computing, now download Numpy+Scipy for Python 2.7 from:
http://www.scipy.org/Download
For 2D moving graphics, keyboard and mouse input, now download pygame from:
http://pygame.org/download.shtml
This completes the set-up you need for this course. To start Python select IDLE from the
Python folder in the Start Menu. Or even better: create a Shortcut to this on your desktop, set the
working directory to the folder where you want to keep your Python programs.
1.3.3 Documentation
IDLE has an option to Configure IDLE and add items to the Help menu. Here a link to a file or a
URL can be added as an item in the Help pull down menu.
For Scipy and Numpy, downloading the .CHM files (chum-files) of the reference guides onto
your hard disk and linking to these files is recommended. They are available for download at:
http://docs.scipy.org/doc/
http://matplotlib.sourceforge.net/contents.html
Also check out the Gallery for examples but most important: with the accompanying source code
for plotting with Matplotlib:
http://matplotlib.sourceforge.net/gallery.html
13
http://www.pygame.org/docs/
Another useful help option is entering python in the Google search window followed by what
you want to do. Since there is a large Python user community, you will easily find answers to
your questions as well as example source codes.
If you did the customized installation and you want to use Spyder, you first need to download
PyQt from riverbanks (when you have the Enthought distribution, you already have this):
http://www.riverbankcomputing.co.uk/news
http://code.google.com/p/spyderlib/
Py2exe can be installed separately and is already included in Python(x,y) . How to install and use
this is covered in the chapter on distributing your Python programs.
14
In the IDLE window, named Python Shell, select File>New Window to create a window in
which you can edit your first program. You will see that this window has a different pull-down
menu. It contains Run, indicating this is a Program window, still called Untitled at first. Enter
the following lines in this window:
(if you would have chosen to use Python 3.x, you should add brackets around the texts and find
another reader on the web, since we will use Python 2.x syntax in all our examples).
Now select Run>Run Module. You will get a dialog box telling you that you have to Save it
and then asking whether it is Ok to Save this, so you click Ok. Then you enter a name for your
program like hello.py and save the file. The extension .py is important for Python, the name is
only important for you. Then you will see the text being printed by the program which runs in
the Python Shell window.
After File>New Window, IDLE shows an editor window (right) next to the Shell window(left)
15
1.3.6 Spyder: a more advanced IDE
Though IDLE is a very useful IDE (Interactive Development Environment), there are some
limitations:
- With large projects and many files it can become cumbersome to switch between
different files
- Debugging facilities are limited
For this reason often another IDE is used for larger projects. There are many on the web. For
scientific purposes the most popular one is Spyder. This comes with python(x,y) and many other
distributions. An example of a screenshot of Spyder with some explanation is given below:
Spyder screenshot
Other features include inspecting data arrays, plotting them and many other advanced debugging
tools.
Make sure to change the settings of file in the dialog box which will pop up the first time you run
the file to allow interaction with the Shell. Then you have similar features to which IDLE allows:
checking your variables in the shell after running your program or simply to testing a few lines
of code.
My advice would be to first keep it simple and use IDLE for the basics. Use the print statement
and the shell (to inspect variables) as debugger and occasionally www.pythontutor.com. Then
later, for larger or more complex problems switch to Spyder.
16
1.4 Examples and exploration of the language
1.4.1 Temperature conversion: (PRINT, INPUT statement, variables)
In the IDLE window, named Python Shell, select File>New Window to create a window in
which you can edit your program. You will see that this window has a different pull-down menu.
It contains Run, indicating this is a Program window, still called Untitled at first.
Enter the following lines in this window and follow the example literally. If you type 5 (so leave
out the decimal point) instead of 5.0 the program might not work.
(If you want to make it a bit more interesting, and harder for yourself, you could make a
variation on this program. In much the same fashion, you could try to make a saving/debt
interest calculator where you enter start amount, interest rate in percentage and number of years.
To raise x to the power y, you use x**y)
Now select Run>Run Module. Depending on your settings, you might get a dialog box telling
you that you have to Save it and then asking whether it is Ok to Save this, so you click Ok. Then
you enter a name for your program like temperature.py and save the file. The extension .py is
important for Python, the name is only important for you. Then you will see the text being
printed by the program, which runs in the window named Python Shell:
17
Now let us have a closer look at this program. It is important to remember that the computer will
step through the program line by line. So the first line says:
The computer sees a print statement, which means it will have to output anything that comes
after this statement (separated by commas) to the screen. In this case it is a string of characters,
marked by a at the beginning and the end. Such a string of characters is called a text string or
just string. So it put this on the screen. The computer will also automatically add a newline
character to jump to the next line for any next print statement (unless you end with a comma to
indicate you want to continue on the same line!).
Then this line is done, so we can go to the next one, which is slightly more complicated:
This line is a so called assignment statement, indicated by the = symbol. In general, it has the
following structure:
variablename = expression
In our example it tells the computer that in the computers memory a variable has to be created
with the name tempf.
To be able to do this, the computer first evaluates the expression on the other side of the = sign
to see what the type of this variable has to be. It could for example be a floating point value
(float type) or a round number (integer type), a serie of characters (string) or a switch (boolean
or logical). It then reserves the required amount of bytes, stores the type and the name. If the
name already exists, then this old value and type are first to avoid problems later on.
18
The computer evaluates the expression. The outcome is stored in memory and can be used later
in other expressions by using the variable name. To do this, the computer maintains a table in its
memory with the value of a variable, its name and its type.
a = 2
For numbers there are two types: integers and floats. Integers are whole numbers, used to count
something or as an index in a table. Floats are numbers with a floating point and can be any
value. Python looks at the expression to determine the type:
Now let us have a look at the expression, This is not a simple one. The expression in our
example has the following structure:
functionname ( argument )
Python knows this is a function because of the brackets. In this case, the name of the function is
which is used is input( ), one of the standard functions included in the Python language. (Later
we will also use functions which we have defined ourselves!)
Most functions do some calculations and yield a value. Example of these functions are abs(x)
for the absolute value (modulus) of x or int(x) which will truncates the float x to returns an
integer type. The int( ) function is one of the type conversion functions:
But some functions are complete little programs in itself. The input-functions for example does
more: it can be called with one argument, which will be printed on the screen, before the user is
prompted to enter a value. When the user presses enter, the value is read, the type is determined
19
and this is returned as the result by the input function. So in our case, the text Enter
temperature in degrees Fahrenheit: is printed and the user enters something
(hopefully a number) and this is then stored as an integer or floating point number in a memory
location. We call this variable tempf.
The next line is again an assignment statement as the computer sees from the equal sign =:
tempc = (tempf-32.0)*5.0/9.0
Here a variable with the name tempc is created. The value is deduced from the result of the
expression. Because the numbers in the expression on the left side of the equal sign are spelled
like 5.0 and 32.0, the computer sees we have to use floating point calculations. We could
also have left out the zero as long as we use the decimal point, so 5./9. would have been
sufficient to indicate we want to use floating point values.
If we would leave them out, the result might be an integer value, which means that every
intermediate value is truncated (so cut off behind the decimal point) which would mean the result
of the expression would be zero, as 5/9 would yield zero as result in integer arithmetic!
When this expression has been evaluated, a variable of the right type (float) has been created and
named tempf, the computer can continue with the next line:
This line prints four things: a variable value, a text string, an expression which needs to be
evaluated and another text string, which are all printed on the same line with each comma a
space character is automatically inserted as well. The int function means the result will be
truncated (cut off behind the decimal point). Better would have been to use:
int(round(tempc))
What do you think the difference would have been? (check section 2.8).
Try running the program a few times. See what happens if you enter your name instead of a
value.
import math
20
b = input("Enter the value of b:")
c = input("Enter the value of c:")
D = b**2 - 4.*a*c
Run this program and you will see the effect. Some notes about this program:
- note how ** is used to indicate the power function. So 5**2 will yield 25. (Using 5*5 is
faster by the way.)
- the program uses a function called sqrt() This is the square root function. This function is
not a standard Python function. It is part of the math module, supplied with Python.
Therefore the math module needs to be imported at the beginning of the program. The
text math.sqrt() tells Python that the sqrt() function can be found in the imported math
module
- After you have run the program, you can type D in the shell to see the value of the
discriminant. All variables can be checked this way.
Also, note the difference between text input and output. The line print is a statement, while
input is used as a function returning a value, which is then stored in a variable. The argument
of input-function is between the brackets: its a prompt text, which will be shown to the user
before he enters his input.
There is one problem with our program. Many times it will stop with an error because the
discriminant D is negative, resulting in an error with the square root function.
To solve this, let us try adding some logic to the program, see below. Adapt your program to
match this precisely, note the margin jumps (use TAB-key) in the IF statement, which is called
indentation.
D = b**2 - 4.*a*c
if D<0:
21
print "This equation has no solutions."
else:
x1 = (-b - sqrt(D)) / (2.*a)
x2 = (-b + sqrt(D)) / (2.*a)
Now the program first checks whether D is negative. If so, it will tell you that there are no
solutions.
- Note the structure and syntax(=grammar) of the if-else statement. A colon ( : ) indicates a
block of code will be given, so it acts as a then. The block is marked by the indented
part of the code,.
- When it jumps back to the margin of the beginning to indicate the end of this block of
code, an else follows, again with a colon and an indented block of code.
- It also uses a different way to import the sqrt function from the math module. Note the
difference in syntax in both the line with the import statement as well as the line where
the sqrt function is used.
Assignment 1.1:
Adapt the program so that it calculates the hypotenuse c of a rectangular triangle for
rectangular sides a and b as entered by the user, using Pythagoras formula.
Assignment 1.2:
Now adapt the program so that it determines the maximum value of given numbers a,b,c and d.
Use the algorithm described before. Translate this into Python code using the example above
and run it
Assignment 1.3***:
Change the program in a way that it solves a third order polynomials written as:
x 3 + ax 2 + bx + c = 0
The user enters the values of a, b and c. And the program prints the solutions for x. Find the
required formulas by searching for formulas to solve polynomial functions nth degree.
range(10)
range(1,11)
22
range(2,22,2)
range(5,1,-1)
What do you notice? If you do not see its logic, try a few values yourself. Some things you
probably have noticed:
This result is in fact a new variable type: a list . You can regard this as a table:
a = [ 7, 3, -1, 3]
Indexing of the list starts with zero, so a[0] will return in the first value (7) and a[3] the last one
(3).
For the next example code we will use the website http://www.pythontutor.com . Go to this site
and on the start page cick Start using.., clear the source edit window and enter this program in
the window (also mind the layout (use tab to move the margin right!)
a = 9
for i in range(1,11):
x = i*a
print i,"x", a,"=",x
print
print "Ready."
Now click Visualize execution and then click Forward a few times to see what happens. On
the right side of the edit window you can see what happens in the memory of the computer. Next,
you see the output window, with the text the user of the program will see:
23
Can you explain what the computer does? Why he jumps back? How he knows which part of the
code to repeat and which not? Do you notice what happens to the value of i when it jumps back
to the for-statement? What happens when i is equal to 10?
This is called a for-loop: i is assigned the first value of the list (in this case the list made by the
range function) and after it has completed the indented block of code, it jumps back and assigns
the next value of the list until it has reached the end of the list. If there are no more value for i, so
after the last value it continues the code and does not jump back, the variable i now has the final
value (10, because 11 is not included in the list generated by the range-function. See also the
program below, what will this program do? Which integer do you think the len() function returns?
sqrt(D)
len(a)
range(1,11)
You can see that Python knows whether something is a list or a function based on the type of
brackets used!
24
Ttab = [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]
Htab = [0.06,42.1, 84.0, 125.8,167.5,209.3,251.2,293.0, 335.0, 377.0,419.1]
for i in range(n-1):
if T >= Ttab[i] and T < Ttab[i+1]:
print "H is between",Htab[i],"and",Htab[i+1]
Note the two indentations: one for the for-loop, the next for the if statement.
A unique feature of Python is that the same list can store different types of variables:
b = [2, Hello there!, 3.141565 , 2, 10.0, True]
This assignment of b is a valid list, and it consists of a mix of variable types: floats, integers, a
string and a Boolean(logical)
And the result is basically a two dimensional table, as we can see by showing some values of this
table in the Python shell (first type the assignment statement above):
>>>c[0]
[ 2, 3, -1 ]
>>>c[2][0]
The second c[2][0] basically means, from left to right: the third element of c (which is a list)and
then the first element of that list.
Through with this format it is easy to select a row, but selecting a column is only possible with a
for loop. Below there are two ways to go through a two dimensional list to pick a column, What
would be advantages of each method?
The first method is to have an integer run through a list of integers (so whole numbers) as
generated by the range function: [0,1,..len(people)-1] Remember the end value given in the
range function will not be included in the range functions resulting list. These are exactly the
indices for the list as this also starts with 0 and ends with its length minus one.
25
["Piet", 20, "Leiden"], \
["Kees", 19, "Amsterdam"], \
["Klaas",34, "Utrecht"], \
["Victor",22,"Leeuwarden"] ]
iname = 0
iage = 1
icity = 2
for i in range(len(people)):
print people[i][iname],"is",people[i][iage],"years old."
The above way will work in most other programming languages as well. A unique feature of python is
that a list of any type can be used as the counter (or as we call it: iterator) in the loop. The variable person
will get each value from the list people. As people is a list of lists, person will first be the first element
from people: ["Jan", 18, "Delft". Then, when the block of code that is in the loop has been
executed with this value for person, the next value of people will be used: ["Piet", 20,
"Leiden"] and so on, for as long as the list people lasts:
# Database: see how one statement can cover more program lines
# (within a list definition, without the backslash is also ok)
iname = 0
iage = 1
icity = 2
Lists are often created by appending values at the end of the list, using the append function,
which comes with the list-type and has a special syntax (varname.function), similar to how we
use functions from a module, which we will later see more often. Such a function, which is
called by a dot after the variable name is called a method, in this case of the list object (i.e. the
list type).
debt = []
rate = 1.03
26
x = 30000.
for i in range(30):
debt.append(x)
x = x*rate
print debt
Now try to change the line with the append function in:
debt.append([i,x])
and see what the effect is (and what the debt is after 30 years of only 3% interest!). Could you
think of a way to make the output look better, using a for-loop, list-indices, the e.g. the round( )
function (see section 2.8)?
x = 0.
while x+5>x*x:
print x
x = x+1
Or see how this while-loop finds the right spot in a table to interpolate:
# Enthalpy of water at 1 atmosphere
Ttab = [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]
Htab = [0.06,42.1, 84.0, 125.8,167.5,209.3,251.2,293.0, 335.0, 377.0,419.1]
i = 0
while T>Ttab[i+1] and i+1<n-1:
i = i + 1
f = (T-Ttab[i])/(Ttab[i+1]-Ttab[i])
27
Hip = (1.-f)*Htab[i] + f*Htab[i+1]
Python comes with many handy features built-in as modules. To be able to access these from
your program, simply put an import statement at the beginning. Then in your program simply
type the module name followed by a period and the function name. In this way you can access all
functions inside this module. Some examples are given in this section.
Type in the shell help(time) or help(time.localtime) and try to see what happens
in the program below. It uses the time module to get current local time and date as integers
(whole numbers).
import time
28
hour = t[3]
mins = t[4]
secs = t[5]
date = t[2]
month = t[1]
year = t[0]
hour = t.tm_hour
mins = t.tm_min
secs = t.tm_sec
date = t.tm_mday
month = t.tm_mon
year = t.tm_year
Or the random number generator from the moduel named random (in the shell type
help("random.random") and help("random.randint") to get more information:
import random
die = random.randint(1,6)
print die
1.5.6 Finding your way around: many ways in which you can get help
There are many ways to get help. For instance if you need help on the range function, in the
Python shell, you can type:
help(range)
Which calls the help-function and uses the string to find appropriate help-information. Similarly
to find methods of the list or string type, use:
help(list)
You can also use help interactively by typing help(), without arguments, and then type the
keywords to get help, e.g. to see which modules are currently installed.
29
>>>help()
help>math
And you will see an overview of all methods in the math module. There are some limitations to
this help. When you will type append, you will not get any results because this is not a separate
function but a part of the list object, so you should have typed
>>> help("list.append")
Help on method_descriptor in list:
list.append = append(...)
L.append(object) -- append object to end
>>>
>>> help()
Welcome to Python 2.7! This is the online help utility.
..
help> list.append
Help on method_descriptor in list:
list.append = append(...)
L.append(object) -- append object to end
help>
30
31
Using the huge Python community
Python has a very large user community: conservative estimates say there are 3 to 5 million
Python users and its growing fast as MIT, Stanford and many others use Python in their courses
and exercises. It is also the most popular language among PhDs and IEEE calls it the standard for
scientific computing.
So simply Googling a question (or error message) with the keyword Python (or later Numpy) in
front of it as an extra search term will quickly bring you to a page with an example or an answer.
For basic questions this might bring you to the same documentation as in the Help-menu which
is at http://docs.python.org . You will also see that www.stackoverflow.com is a site, which will
often pop-up, and where most questions you might have, have already been posed and answered:
(Which shows that next to append there apparently is another method called extend which works
with a list as an argument and apparently appends each element to the list.)
In general, thanks to the interactive Python Shell window, simply trying statements or program
lines in the Python shell is a way to try what works as you intended. Or to check the value of
variables after your still incomplete program has run.
To find bugs in your program, for small programs http://www.pythontutor.com can be helpful to
what is going on inside the computer when your program runs. And of course using the print
statement to see what a variable is, or where the computer gets stuck in your program, is always
the first thing to try.
Be prepared that in the beginning the level of frustration might be high, but so is the reward
when your program runs. And when you get experience, you will see how fast you can make
working programs, not because you wont create bugs, but because you will immediately
recognize what went wrong. The nice thing of software is that it can always be fixed, so trial
and error is an accepted way to develop programs. So do not be afraid to try things and play
around with Python to get acquainted with the way it works.
In appendix A and appendix B a short overview of the Python statements and mpst important
functions is given. In section 5.2 an overview of the math-functions is given. Having a copy of
these pages at hand may be handy when starting Python. It will provide the keywords for you to
look into the help-functions of Google searches.
Although we already touched upon most basic elements of the Python language, we have not
seen all statements and types yet, so first go through the next chapters (discover the very useful
while-loop, the string type and its methods and the Boolean/logical and slicing of strings and lists
etc.). Just glance over these chapters to get the essence and then start making simple programs
and study the paragraphs in more details when you (think you) need them. Programming has a
steep learning curve at the beginning, so good luck with making it through this first phase. Once
you have passed this, things will be a lot easier and more rewarding. Good luck!
32
2. Python syntax: Variables and functions
In this chapter we describe the building blocks which you need to write a program. First we have
a look at variables. A variable is used to store data. But there are different types of data: numbers
or bits of text for instance. There are also different data types of numbers And of course there are
more data types than just text and numbers, like switches (called booleans or logicals) and
tables(lists). The type of variable is defined by the assignment statement, the programming line
giving the variable its name, type and value. Therefore we first concentrate the assignment
statement and then the different data types are discussed.
variablename = expression
Example assignments of the four main types (which will be discussed in details in the following
sections):
Integers:
i = 200
a = -5
Floats:
in = 2.54
ft = .3048
spd = 4.
alt = 1e5
Logicals:
swfound = True
prime = False
Strings:
name = Jane
txt = Hello world.
s = abc
2.2 Floats
Floats, commonly referred to as floating point variables, are used for real numbers. These are the
numbers as you know them from your calculator. Operations are similar to what you use on a
calculator. For power you use the asterisk twice, so xy is achieved by x**y.
33
One special rule with floats in programming is that you never test for equality. Never use the
condition when x is equal to y with floats, because a minute difference in how the float is
stored can result an inaccuracy, making this condition False when you expected otherwise. This
may not be visible when you print it, but still causing two variables to be different according to
the computer while you expected them to be the same. For example: adding 0.1 several times and
then checking whether it is equal to 10.0 might fail because the actual result is approximated by
the computer as 9.99999999 when it passes the 10. So always test for smaller than (<) or larger
than (>). You can also use smaller or equal to (<=) and larger or equal to (<=).
2.3 Integers
Integers are variables used for whole numbers. They are used for example as counters, loop
variables and indices in lists and strings. They work similar to floats but division results will be
floored. This means that integers are always rounded off to the lower whole number (so
truncated or cut off). For example:
a = 4
b = 5
c = a/b
print c
This will print zero in the screen and not 0.8. This is the source of many bugs: variable become
integer by accident (the programmer forgets to add the decimal point), and strange result come
out of th expressions because some intermediate value is rounded off to zero. So never forget the
decimal point or using the float(0 conversion function when necessary!
A very useful operator with integers is the % operator. This is called the modulo function.
You could also call it the remainder because it gives only remainder of a division. For example:
27%4 = 3
4%5 = 4
32%10 = 2
128%100 = 28
You can convert integers to floats and vice versa (since they are both numbers) with the
functions int( ) and float( ):
a = float(i)
j = int(b) # Cut of behind decimal point
k = int(round(x)) # Rounded off to nearest whole number
The int( ) function will cut off anything behind the decimal point, so int(b) will give the
largest integer not greater than b . These functions int( ) and float( ) can also take
34
strings (variables containing text) as an argument, so you can also use them to convert text to a
number like this:
txt = 100
i = int(txt)
a = float(txt)
2.4 Strings
Strings are variables used to store text. They contain a string of characters (and often work
similar to a list of characters). These are defined by a text surrounded by quotes. These quotes
can be single quotes or double quotes as long as you use the same character to start and end the
string. It also means you can use the other type of quote-symbol inside the text. A useful operator
on strings is the + which glues them together, This is very useful e.g in functions which expect
one string variable (like the input function).
Example assignments:
txt = abc
s =
name = Jacco+ M. +Hoekstra (so the + concatenates strings)
words = def ghi
a = input(Give value at row+str(i))
Using indices in square brackets [ ] allows you to take out parts of a string. This is called slicing.
You cannot change a part of string but you can concatenate substrings to form a new string. This
can be used to achieve the same thing:
c = hello world
c[0] is then h (indices start with zero)
c[1:4] is then ell (so when 4 is end, it means until and not including 4)
c[:4] is then hell
c[4:1:-1] is then oll so from index 4 until 1 with step -1
c[::2] is then hlowrd
c[-1] will return last character d
c[-2] will give one but last character l
c = c[:3]+c[-1] will change c into hel+d=held
the string variable also has functions built-in, the so-called string methods. See some examples
below (more on this in chapter 8).
35
a = c.lower() returns copy of the string but then in lower case
a = c.strip() returns copy of the string with leading and trailing spaces removed
sw = c.isalpha()returns True if all characters are alphabetic
sw = c.isdigit()returns True if all characters are digits
i = c.index(b) returns index for substring in this case b
For more methods see chapter 8 or 5.6.1 of the Python supplied reference documentation in the
Help file.
36
2.5 Logicals/Booleans
Logicals or Booleans are two names for the variable type in which we store conditions. You can
see them as switches inside your program. Conditions can be either True or False, so these
are the only two possible values of a logical. Mind the capitals at the beginning of True and
False when you use these words: Python is case sensitive. Examples of assignments are given
below:
found = False
prime = True
swlow = a<b
outside = a>=b
swfound = a==b
notfound = a!=b ( != means: not equal to)
notfound = a<>b ( <> also means: not equal to, but is old notation)
outside = x<xmin or x>xmax or y<ymin or y>ymax
inside = not outside
out = outside and (abs(vx)>vmax or abs(vy)>vmax)
inbetween = 6. < x <= 10.
Conditions are a special kind of expressions used in statements like if and while to control the
flow of the execution of the program. In the above statements, often brackets are used to indicate
it is a logical expression.
To test whether two variables are the same, you have to use two equal signs. Two equal signs
will check the condition and one equal sign assigns an expression to a variable name. For is not
equal to both != as well as <> can be used, but != is preferred. With combined conditions
with many and, or and not statements use brackets to avoid confusion:
if inside:
print (x,y) is inside rectangle
Note that if inside basically means: if inside==True and similarly while not
found means while found==False .
37
2.6 Lists
2.6.1 What are lists?
Lists are not really an independent type but a way to group variables together. This allows you to
repeat something for all elements of a list by using an index or by iterating through the list with
the for-statement. This could be an operation, a search or a sorting action. Often it is useful to
have a series of variables. Look at it as a table. An element of a list could be of any type, it can
be an integer, float, logical, string or even a list! Special for Python is that you can even use
different types in one list; in most programming languages this would not be possible. Both to
define a list, as well as to specify an index, square brackets are used as in strings.
This would make the variable a a list of floats, b a list of integers, c a list of strings. A list of
lists as defined in d is basically a way to create a two-dimensional list. Finally e is an empty list.
Accessing elements from the list is done as indicated below. Another way to make a list of
numbers is using the range function. The range function can contain one two or even three
arguments:
range(stop)
range(start,stop)
range(start,stop,step)
In all these cases start is the start value (included), stop is the value for which the block is not
executed because for will stop when this value is reached. So it is an inclusive start but
excludes stop. Another option is to enter a third argument, which is then is the step. The default
start is 0, the default step is 1. Note that range( ) only works with integers:
38
2.6.2 Indexing and slicing
lst = [1,2,3,4,5,6,7,8,9,10]
If we now print elements we can use the indices in many ways. Using one index, indicating a
single element:
Here it can be seen that indices start at 0, just as with strings. And similar to strings, the function
len( ) will give the length of a list and thus the not to reach maximum for the list. Slicing lists
with indices also works just as for strings, with three possible arguments: start, stop and step.
Only one index refers to one single element. Two arguments separated by a colon refer to start
and stop. A third can be used as step. If you look at the lists that were made in the previous
paragraph about lists you can see that:
Another way is to use the del (delete command) and/or functions which are a part of the list
class. You call these functions by variablename.functionname( ) so a period between
variablename and functionname. Some examples:
39
del a[-1] removes the last element of list named a
a = a[:3]+a[4:] will remove the 4rd element of the list named a
Slicing
The last example line uses the slicing notation (which can also be used on strings!). Slicing, or
cutting out parts of a list is done with the colon. The notation is similar to the range arguments:
start:stop and optionally a step can be added as third: start:stop:step. If no value is enter as start,
the default value is zero. If no value is added as end the default value is the last. De default step
is 1. Negative values can be used to point to the end (-1 = last element, -2 is one but last etc.).
lst = [1,2,3,4,5,6,7,8,9,10]
2.6.3*** Lists are Mutable: risks with multiple dimensions list creation
You can quickly build a one dimensional list with 5 elements like this:
>>> a=5*[0]
>>> a
[0, 0, 0, 0, 0]
>>> a[1]=1
>>> a
[0, 1, 0, 0, 0]
>>>
Warning: This only works with one dimensional arrays, see what happens when you try it with
lists of lists, so two dimensional lists:
>>> a=3*[3*[0]]
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][1]=1
>>> a
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
40
>>>
So we only change the second element of the first row, but surprisingly all rows (all lists) have
their second element changed into 1!
In general you could say, simply avoid this. But for the people who really want to know what is
going on: In www.python.tutor.com we can see the difference. Imagine we will run the following
code:
a = 3*[0]
b = 3*[a]
c = 3*a
d = 3*[3*[0]]
When using one dimensional lists with the star-sign (so for example *a or *[0]), it will be an
expression, evaluated and taken as a value and hence create a new list. Examples of this are how
the list a and d are created. But normally in Python a list is seen as an object, which means it will
just be copied by reference (a pointer to the same object, to the same memory location) will be
used. This causes the at first sight strange behavior.
To avoid this confusion (and ignore this difference), it is better to build a two dimensional array
with append in a for-loop:
a=[]
for i in range(3):
a.append(3*[0])
a[0][1] = 1
41
print a
a=[]
b=[0,0,0]
for i in range(3):
a.append(b)
a[0][1] = 1
print a
This only slightly different code will result in the problematic output again:
[[0, 1, 0], [0, 1, 0], [0, 1, 0]]
So 3*[0] is an expression, just like integer variables and float variables. But because b is a list-
object and passed on by reference to the memory location.
In general, using append with non-list arguments is a safe method. This is because most variable
types (floats, integers, strings) are passed on as value. They are called immutable. Expressions
are also passed on as a value. List objects (like most objects) are called mutable and will be
passed on as a reference to a memory location and hence can be changed by the function that is
called.
Here are two ways to quickly create a two-dimensional list without the risk of creating pointers
to the same list:
First create a one dimensional list, then replace each element by a list:
a=3*[0]
for i in range(3):
a[i]=3*[0]
a[0][1] = 1
print a
Or with nested loops, create a fresh, new list (as a row) and then append this:
a=[]
for i in range(3):
row = []
for j in range(3):
row.append(0)
a.append(row)
a[0][1] = 1
print a
42
Both will give this output, indicating that a indeed consists of three independent lists:
So creating the variable row or he list a lement a[i] every time anew, is the safest way to avoid
all appended lists pointing to the same memory location. If you are not sure, test a simple
example in the above way: change one element and see the effect by printing the list. Or use
www.pythontutor.com to see what is going on in the computers memory.
An advantage of lists are the methods that come with it. These are functions which you call with
a period after the variable name (just like append). An example is the sort function:
>>> a=[2,10,1,0,8,7]
>>> a.sort()
>>> a
[0, 1, 2, 7, 8, 10]
As we can see the function sort() (recognizable as a function because of the brackets) sorts the
list a. This is special function in that is changes the actual source list instead of creating a sorted
copy. Most methods will give the result of the function and leave the original intact. Example are
the method index and count. Index will give the index of the first occurrence of the value. Count
will give the total number of occurrences:
>>> a = [3,1,8,0,1,7]
>>> a.count(1)
2
>>> a.index(1)
1
>>> a.index(9)
How would you make a program which will the index of the first occurrence but also avoids the
error message if it is not found by simply printing -1?
43
2.7 Some useful standard built-in functions
As we have already seen in the examples, Python has a number of built-in function which you
can use in the right side of assignment statement on any expression using values and variables:
44
3. Python syntax: Statements
3.1 Assignment
In this chapter we discuss the basic Python statements: commands that you use in a program
which often do something with the data. A one page summary of the basic python statements can
be found in Appendix A. We already discussed the assignment statement at the beginning of the
previous chapter. The assignment statement is one of the most simple statements in Python:
variablename = expression
In this statement the expression on the right hand side is evaluated and the stored in the variable
with the name as given left of the equal sign. The expression determines the type and value of
the variable and the left side, the variablename, the name.
It is possible to overwrite a variable, even when it is used in the expression on the right side. This
is because the computer first evaluates the expression and only then stores the result in the
variable, overwriting anything that was previously stored in that variable.
Some examples of how you can use the assignment are given below:
Here it should be noted that a statement as i=i+1 may seem mathematically incorrect, but in
programming this means that the new value of i becomes the old value of i+1. So = means will
become instead of is equal to (for which we use == in Python, for example when we test a
condition in an if-statement).
45
3.2 Input function
With the function input( ) the user can be asked to input values during runtime of the
program. Input is not really a statement, but as a function in an assignment line. It returns the
value as given by the user during runtime. As argument in, it takes one string, which is used as
the prompt by the function: it will print this text just before the user can give the input. Some
examples:
a = input(Give a:)
nloop = input(Give the maximum number of tries:)
The input function will check which type is entered. To prevent users from having to enter
quotes when entering a string, a special input function, called raw_input( ) can be used for
entering text this way into strings. Raw_input( ) leaves out the type-check by Python and returns
simply the text exactly as entered by the user during runtime, and stores it as a string:
This example code will result in two strings named player1 and player2, which contain the
text as entered by the user. Also, raw_input does not give an error when nothing is entered,
contrary to input( ). So it can also be used as a pause statement, as in the third example. The
variable dummy will then contain an empty string when the user presses enter.
There is a risk of using just the input function because the user determines the type of the
variable. For instance, when he omits a decimal point a variable may inadvertently become an
integer or the other way around. To avoid this, you will often see:
Python 2.x:
input(prompt) => use for integer, float, etc. type determined by user
raw_input(prompt) => use for string, so to enter text
Python 3.x:
input(prompt) => always returns a string
46
Nevertheless, it is considered good practice to use a conversion function with input, also in
Python 2.
The command line print generates text output in the console. It can print texts, variables and
expressions. To print several things on one line use a comma to separate them. A space will be
inserted automatically between the arguments. When there is a comma at the end of the program
line with the print statement, the next print statement in the program will continue on the same
line. A plain print-statement prints an empty line (or a newline character to be exact). Some
examples:
Three ways, which will result in the same output, it will print Hello world on one line:
print Hello world
print Hello,world
print Hello,
print world
The print statement can print one or more texts, variables expressions, outcome of functions.
Basically anything can be printed. Apart from generating output for the user, print is also very
useful when trying to find bugs in your program. Every experienced programmer puts in a print
statement after each ten lines of code to check if everything works as intended. These are then
later deleted or commented out with the hash sign.
In Python 3, PRINT has been changed into a function, this means the syntax becomes different:
47
3.4 If-statement
The if statement has the following syntax:
if condition :
statement 1
statement 2
statement 3
In this example above, only if the condition is True, the statements statement 1 and statement 2
are executed. If the condition is False it will automatically jump to statement 3 without executing
statement 1 and statement 2. The conditional lines of code are marked by indenting the margin
after the colon, this is called a block. So in Python a block is marked by using the same margin,
the same indentation. One indentation step is set to four spaces by default in IDLE but any
number of spaces will do, as long as one block has the same indentation.
Because statement 3 starts at the beginning of the line again, so un-indented, Python knows that
this is the end of the conditional block. One of the statements inside the if-statement could be
another if-statement, which would mean that another set of conditional statement would be
indented one more time (nested if-loops).
Optionally the if-statement can be expanded with an else-branch or one or more else-ifs which
are spelled as elif in Python. As many elif-branches can be added as necessary. Only one
else can be added, always at the end of the if branche(s).
An example:
if x<xmin:
x = xmin
vx=-vx
print Ball left via left side of screen.
elif x>xmax:
x = xmax
vx = -vx
print Ball left via right side of screen.
else:
print Ball still on screen.
x = x + vx*dt
In this example the condition x>xmax is only checked if x<xmin is False. Which probably is
not a problem in this case. In the above example the assignment statement to update the variable
x is always executed because it is not indented.
48
3.5 For-loop
The for loop is a very convenient loop, especially when it is used in combination with the
range()function. For example:
for i in range(10):
print i
print Ready.
If you try this code, you will see that it prints the numbers 0 to 9. The range(10) function results
in a list: [0,1,2,3,4,5,6,7,8,9] through which the variable i is iterated. This means: The indented
block of code (one statement in this case) is executed ten times, once for each value of i.
Another example:
total = 0
for i in range(1,11):
print i
total = total + i*i
print total
In this example, a variable total is initialized as zero just before the loop. But then in every
execution of the loop i*i is added to total. Since i runs from 1 until but, not including, 11
here, the result is that total will be equal to 1*1 + 2*2 +3*3+ + 9*9 + 10*10 .
Instead of using range( ) to generate a list with integers, any list can be used:
names = [Anna,Betty,Catherina,Zoe,Morgan]
for name in names:
print name
If you need to loop floats e.g. from 0. to 10. with step of .1, you can also use the following
construction. This example will print these values:
for i in range(101):
x= i*0.1
print x
When setting up loops (while or for), use print statements first (e.g. with a small number of
iterations) to see whether your loop does what you intend it to do.
Tip
Try using xrange() instead of range() for very large numbers. It will have the same effect as
range(), but it avoids making a long list, while still returning the same numbers but now an an
iterator function. This saves memory (and increases the speed) when using a for-loop.
49
3.6 WHILE-loop
A more versatile loop is the while-loop. It is a sort of a combination between an if- and for-loop.
A block of statement is executed for as long as a given condition is True. The block is repeated
until the condition becomes False. The syntax is:
while condition:
statement 1
statement 2
statement 3
Some examples:
Another example:
import math
found = False
if n%i==0:
found = True
i = i+1
if found:
print n,is divisible by,i
else:
print No factors of,n,found.
50
3.7 Loop controls: Break and Continue
It is possible to make exceptions to the normal execution of the for- or while-loop. Two
statements can do this: break and continue.
The command line break will break out of the current loop and continue with the next
statement after the loop. The command line continue will also skip the remainder of the block
of code in the loop, but in contrast to the break command, it will return to the beginning of the
loop (in a for-loop it will thus return to the beginning of the loop, taking the next value of the
iterator).
while True:
if keypressed == ESCkey:
break
for i in range(100):
if i%4==0:
continue
Note that continue and break can be used in both loop-types: so both can be used in for and
while loops.
Using these two commands on a regular basis is considered to be a bad programming habit, as a
clever definition of the loop can avoid these unpleasant disruption of the flow of the program.
Also, take into account that an if-then statement could also do the job. The break and continue
statements however, make the code more readable since less indentations are required compared
to the if-then statements.
continue means skip the rest of the code in the block inside the loop and go to the line with
the while or for statement. So in case of a for-loop the next value of the list will be
used.
break means jump out of the loop and proceed with the code after the loop
Programming language purists do not like these commands as they disrupt the flow of a program
and can be used to create real spaghetti-code, so only use them when there is no other neater
way to achieve the same goal, e.g. to avoid too many indentations in the margin.
51
4. Making your code reusable and readable
When writing a piece of code it is important to make sure your code looks understandable to the
outsider or to yourself when you look at the code in one year from now. You do not want to
write code that you can only use once, so get used to this and do it all the time. Some suggestions:
- At the top of your script, write a small summary explaining the function of your code
using comment lines. Also add your name and the date of editing.
- Use empty lines to create paragraphs indicating which parts belong together. Also
use spaces in your line, they have no effect during runtime but can increase the
readability
- Also use a comment line just before such a piece of code indicating in plain language
what the meaning of the code is. Comments can be inserted when you start the line with
a hash-character: #. The hash-sign can also be used to add comments at the end of the
line (such as units of variables). An example:
If you have a line which becomes very long, continue on the next line. Often Python will
understand it because you are in the middle of a list or function call, but otherwise you may end
the line with a backslash as a continuation character. Then Python will know that the next line
needs to be added behind this line before it executes the command.
Tip: Since it is often not very motivating to add comments afterwards, you can also do it in the
other way around: When you have to design an algorithm, you first have to decompose the
problem into smaller steps. Use comment lines to break your problem down in smaller steps and
write in natural language what each step should do. Then all you have to do is fill in the gaps
between the comment lines with the actual code and you have developed and commented your
source code at the same time.
An example of the same code, both badly and well formatted, is given on the next page:
52
:
In this case the function is extremely simple, but imagine a more complex function: You would
never be able to understand it or use it again a few months or years later, when coded in the
format of the first example. When you make a habit of doing this while you code, it not an extra
effort and it even saves you the effort of memorizing which part does what and what the
variables mean during the debugging.
53
The small summary at the beginning of your code is called the header of a source file. A very
good habit is to add this header at the beginning of each Python file. In this you can quickly
describe the purpose of the program or the inputs and output of a function for potential users. For
this you often want to use multiple lines with comments. You could of course do that using the
hash sign:
#
# Main module of BlueSky Open ATM Simulator
#
# Start this module to start the program
#
# Created by : Jacco M. Hoekstra (TU Delft)
# Date : September 2013
#
# Modification :
# By :
# Date :
#
But another way to add multiple line comments is the triple quote:
"""
Main module of BlueSky Open ATM Simulator
Modification :
By :
Date :
"""
Using this format will also make sure that python recognizes this as documentation for the
function and will return it if the help function is called for your function. This is called the
docstring. See below for an example:
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)
"""
if imag == 0.0 and real == 0.0: return complex_zero
(Also note how default values are given to the arguments when this function is defined).
54
5. Using modules like the math module
As we already saw in the first chapter, Python mathematical functions are defined in a math
module which is one of the many modules that comes with Python. The math module contains:
math functions e.g.: sqrt() (=square root) sin() (=sine of an angle in radians), asin()
(=arcsine or inverse sine, returns the angle again in radians),
angle unit conversion functions: degrees(0 and radians()
constants like pi and e.
If you use a function that has been defined in a module you first have to input that module once
at the beginning of the python script file in which you use the functions. This is done by typing:
import math
When we want to use a function from this module, we type the name of the module, math in this
case, in front of the name of the function followed by a period (.) followed by the name of the
function. For example:
The math module also contains the constants pi and e. These are used in the same way as the
functions, with the module name in front of the constants name:
bdeg = b/math.pi*180.0
y = math.e**x
Note that with logarithmic functions log(x) means ln(x), so base e and not base 10! To use a
logarithmic function with base 10, use the function log(x,10.) or the special function log10(x) .
As it may be cumbersome to type math. before these very common functions there are ways to
import the names from the module into the namespace of the module. This means you dont have
to put math. in front of the function names every time but you can use the function names as if
they were defined inside your module. There are two ways to do this. Look at the examples
below.
Method 1 to avoid this is directly importing selected functions from the module math:
alpha = asin(BC/AC)
bdeg = b/pi*180.0
55
or easier, just import all functions from the math module with the star:
alpha = asin(BC/AC)
bdeg = b/pi*180.0
In the first example the names are explicitly imported. This has two advantages: the reader of the
source can tell from which module which function was imported. This is important if you use
more than one module. Secondly, you prevent problems, which might arise if you use a variable
name which happens to be the same as some function somewhere in the imported module.
Still, if there is any module where you could use the star-import method, it would be the math
module, since the names in there are well-known. In many other languages, these math functions
are also reserved names and part of the so-called namespace of the language.
A nice feature of the from import way of importing functions is the option to rename
functions:
x = wortel(9)
(This example will result in x being a float with value 3.0 as the sqrt() function converts the type
to a float. )
On the next pages an overview is given of the main functions in math. There are a few extra in
the actual module; e.g. those functions show how numbers are represented on a binary scale. If
youre interested in these, use help(math) in the shell or look up math module in the Python
Docs via the IDLE Help menu.
56
5.2 List of math module functions and constants
Constants
math.pi The mathematical constant pi (= 3.1415926535897931)
math.e The mathematical constant e (= 2.7182818284590451)
Trigonometric functions
math.sin(x) Return the sine of x radians.
math.cos(x) Cosine of x radians.
math.tan(x) Return the tangent of x radians.
math.acos(x) Arc cosine of x (i.e. the inverse cosine), resulting angle is in radians
math.asin(x) Arc sine of x (i.e. the inverse sine), resulting angle is in radians
math.atan(x) Arc tangent of x (i.e. the inverse tangent), resulting angle is in radians.
math.atan2(y, x) Same as atan(y / x), in radians but now the result is between -pi and pi. The
vector in the plane from the origin to point (x, y) makes this angle with the positive X
axis. The point of atan2() is that the signs of both inputs are known to it, so it can
compute the correct quadrant for the angle.
math.hypot(x, y) The Euclidean norm, sqrt(x*x + y*y). This is the length of the vector from the
origin to point (x, y).
Hyperbolic functions
57
Number functions
math.ceil(x) Ceiling of x as a float, the smallest integer value greater than or equal to x.
math.copysign(x, y) Returns x with the sign of y ( so abs(x)*y/abs(y) )
math.factorial(n) n! or the factorial of n (in Dutch: faculteit n)
math.floor(x) Floor of x as a float, the largest integer value less than or equal to x.
math.fmod(x, y) Modulo fmod(x,y), returns x - n*y for some integer n such that the result has
the same sign as x and magnitude less than abs(y).This function fmod() is
generally preferred when working with floats, while Pythons x%y is preferred when
working with integers.
math.fsum(iterable) More accurate summing for floats than sum( )
math.modf(x) The fractional and integer parts of x. Both float results carry the sign of x.
math.trunc(x) Return the Real value x truncated to an Integer (usually a long integer)
Another often used module is a module which generates (seemingly) random numbers. This can
be used for random initial conditions, dice or noise etc.
To find more information on the functions in this module, go to Python docs in the Help pull
down menu in IDLE, we type random in the Search window.
Clicking on the first result brings us to chapter 10.6 Pseudo random generator. This section
discusses the functions inside the random module.
After a lot of complex information (which we skip) we also see some useful functions:
random.random() Return the next random floating point number in the range
[0.0, 1.0)
To see which other modules are installed, you can type help(modules) in the Shell, but with
Python(x,y) installed this quickly becomes too much (and takes too long). More info on specific
modules supplied with Python can be found in the Python documentation. For instance check out
the simple modules like os, sys and time, or more advanced like urllib or Tkinter! Youll find a
treasure box of goodies. This is what is meant with Python comes with batteries installed.
58
6. Defining your own functions and modules
Using and making functions can make programming and debugging a lot easier. This is because
it will make your main code shorter. It is also very useful when using the same calculation
multiple times or to use the preprogrammed calculations.
With Python you can define your own functions and in this way basically extend the language
with your own commands. The statement def is used to define a function. The syntax of this
statement is as follows:
def functionname(arg1,arg2,arg3) :
statement1
statement2
statement3
return resultvalue
Examples:
def fibo(n):
while serie[-1]<=n:
x = serie[-2]+serie[-1]
serie.append(x)
del s[-1]
return serie
Functions can be complete programs or simple one-liners. Another example with a very short
function:
def f(x):
return x*sin(x)
Be aware that the def statement does not yet execute the function, it merely defines it. The code
inside the function will only be executed when you call the function, after it has been defined
59
with def. So always call it, could be done manually from the interpreter to check the syntax and
working of your newly defined function.
As you have seen in the formatting example, you can output several different values from your
function. You can do this as a list, defined with the square brackets or a s tuple (a constant list )
with the round brackets or a tuple by leaving out the brackets.
When you call the function you can store the result in a list/tuple or in different variables. The
latter is done in the example below, which explains how to output more than one value of a
function.
60
6.4 Using one variable in definition as input and output is not possible
In some languages, a function can do something to the input variable without returning a value.
This is not the case with the standard data types in Python, except for the list type.
In Python most data types are immutable, which means they are passed on as a value of the
object is used in the function but since there is no reference to the memory location of the
original variable in the calling module will not be changed by anything the function does. See the
example below. Most types of variables (floats, integers, strings, booleans) are immutable
because they are passed on by value. Others (lists) are passed on as reference to a memory
location, then tey would change with the function increase. These are called mutable variables.
Mind you, this use of one variable as input and output at the same time in the definition of a
function is considered very bad programming practice anyway in the procedural programming
style in the languages where this is possible. Yet at the same time, it is common practice in
object oriented programming, also in Python! It would then be called a method of the variable a
and called as: a.increaseit()
61
6.5 Using functions defined in other modules: managing a project
As you have already seen with the math functions in the previous chapter, they are defined in a
separate file(module) math.py and to use them, you first need to import this module.
You can also use this principle of defining functions in different files for large programs where
you want to keep an oversight by storing different sets of functions in different files, or as we say
in Python: in different modules. In this case the module file needs to be in the same folder so
Python can find it.
Suppose you have defined a function fibo in the file series.py , and now you want to use in
your own program test.py . Then you need to import your module series. We usually do
this at the beginning of the source, since you need to do this only once. Because once the
function is defined, you can use it as many times as you want. There are now many ways in
which you can import and call this function:
Method 1:
import series
s = series.fibo(10)
Method 2:
from series import fibo
s = fibo(10)
Method 3:
from series import fibo as fibonacci
s = fibonacci(10)
Method 4 which I would discourage: you do not know which other names now suddenly have a
special meaning, it also makes it harder to trace where functions are defined (I only use this with
math and sometimes with Numpy for the math functions:
On the internet you can find many 3rd party modules which extend the functionality of Python to
do a range of things. Once they are installed it is hence very easy to use them: just add an import
call at the beginning of your script and all functions inside that module are available to you.
62
7. Using logicals, example algorithm: Bubblesort
In this chapter to apply the logic and the loops weve described so far, we will have a look at the
Bubblesort example. The first task is to generate a program that generates 50 random numbers
under 100.
Here randint, see the chapter on the random module, can be used to make an unsorted list:
for i in range(50):
numbers.append(randint(1,100))
This prints an unsorted array of 50 random numbers under 100. Now we will sort it with the
famous Bubblesort algorithm:
If we want to add this then we have to add the code on the following page:
63
# Make sure we enter while loop first time
swapped = True
while swapped:
for i in range(len(numbers)-1):
if numbers[i]>numbers[i+1]:
a =numbers[i]
numbers[i] = numbers[i+1]
numbers[i+1] = a
swapped = True
# Loop end when swapped is False and no swaps were performed anymore
print
print "After sort:"
print numbers
First we check whether these elements are in the wrong order. When they are the same we should
not swap them (it would keep doing this forever then). If wrong, we save the value of numbers[i]
in the variable a, then we overwrite this with the value of numbers[i+1]. And then we use our
saved value in a to put in numbers[i+1] resulting in a swap of places.
For this to work we need to let i run from 0 till the last place minus 1. Otherwise the
numbers[i+1] will result in an error. So the for-loop reads:
for i in range(len(numbers)-1):
Now all we need to do is add some logic to detect whether we are done. We can use a logical
swap to detect any swapping. For this we first set it to False outside the for-loop and as soon as
we swap two variables we set it to True.
64
Then we add a while loop around this which will keep repeating our for-loop until swap remains
False and hence no swap was performed. To make sure we enter the while loop the first time, we
have to set it to True outside the while loop.
This is the order in which this program was made: from the inside out. First putting in
elementary operations and then using a logical to add some logic.
The end result is an already complex looking construction. Look at the three indent levels: while
for and if are inside each other or nested as we call this in programming.
65
8. File input/output and String handling
As soon as your done with the file, you need to release it again with the close statement.:
f.close()
g.close()
h.close()
This will not only release the file for use by other programs but also empty any read/write
buffers which may be in use and whose content might get lost if the program ends abruptly
without closing (and releasing) the files.
You can use the file handle variable in a while-statement when reading files:
The easiest is to store it in a list of lines directly and use this list in the for-loop:
# Read a file
f = open(test.dat,r) # Open file for reading
lines = f.readlines()
f.close()
for s in lines:
. Do something with the string variable s
Because the file object will return False when the end of the file is reached. This is an example of
how you can read lines from a text file using this feature:
# Read a file
f = open(test.dat,r) # Open file for reading
while f:
66
line = f.readline()
f.close()
# Read a file
f = open(test.dat,r) # Open file for reading
f.close()
for i in range(len(xtab)):
line = str(xtab[i])+,+str(ytab[i])+\n
f.write(line)
f.close()
Note the newline character at the end of the line: \n .(You can also use the DOS newline
characters: +chr(13)+chr(10) = CR LF = Carriage return + Line Feed).
Similarly as with readline() and readlines(), there is here also a writelines(), which will write a
complete list of strings to a file. See the example below:
f = open("bigbang.dat","w")
f.writelines(a)
f.close()
67
8.4 Reading a formatted data file
Often text files are formatted in a way which inhibits a straight read into a float or integer
variable. Extra comment lines, text on the same line are very useful when a human reads the file,
but often a burden when you have to read it with a computer program.
Suppose we want the program to read this file and store the result in a two-dimensional list with
strings for the label and floats for the value per variable. So in this example, the text file should
result in the following list:
[['alpha', 5.2240000000000002],
['beta', -0.0112],
['gamma', -2.7759999999999998]]
- The program should recognize comment lines because these start with a C-character.
- When no value is provided (as in the example with theta), it should also not appear in the list.
- Empty lines should have no effect, similarly whitespaces in the lines should not be critical
(see gamma in example)
As a first step, we read the lines into a list of strings (see previous chapter):
# Read a file
f = open(test.dat,r) # Open file for reading
lines = f.readlines()
f.close()
Now we have to process these strings. And then find the labels, strip the superfluous characters
and lines and read the values in the list. This is achieved by the following program, which well
discuss briefly below.
68
# Check every line in the list lines
for line in lines:
The for-loop makes sure the indented block of code will be executed for every string in the list
variable lines.
To prevent that any further checks will not work because a lower case c is used or somebody
starts every name with a capital character, we change the whole line to lower case with the string
method lower. Since it is not a general function but a method of the string type, we use the
variablename.methodname(arguments if any) notation. Similar to the append method with
lists.
Before we read the data two things are done: it is checked whether it is not an empty line or
comment line and then the line is split up and cut using a combination of the split-method, the
find-method and slicing.
There is a long list of string methods which can be handy. A selection is shown on the following
page.
69
8.5 List of some useful string methods/functions
A complete list, as well as more detail per function, can be found in the Python Docs in the
chapter on built-in types (6.6.1) or by typing help(string) in the shell window.
These are methods, which are functions that are part of the type string. This means they are
called in a special way: by using the name of the string input variable instead of str, so followed
by a period and then the name of the function. As the string is an immutable type, so passed only
by its value, these functions return something as output: e.g. an altered copy of the string, an
integer value or a logical.
str.replace(old,new) Return copy of str with all occurrences of substring old replaced by new
str.join(lst) Return one string, with the strings from the list, separated by the character
in str
str.split(sep) Returns a list of strings: the words in str as separated by sep substring
str.splitlines( ) Returns a list of strings: str is split using the newline character
str.join(lst[,sep]) Returns a string with words in lst concatenated (with optional separator)
str.strip(ch ) Remove character ch from begin and end of str, default ch is a space. See
also rstrip( ) and lstrip( ) for stripping only one side of str
str.expandtabs(n) Replace tab-character by n spaces. If n is not provided 8 spaces are used.
str.lower( ) Returns copy of string str with all alphabetic characters in lower case
str.upper( ) Returns copy of string str with all alphabetic characters in upper case
str.title( ) Returns Copy Of String str But Then In Title Case, Like This
str.capitalize( ) Returns copy of string str with the first character capitalized
str.islower( ) Returns True if all characters in the string str are lower case
str.isupper( ) Returns True if all characters in the string str are upper case
str.istitle( ) Returns True If The String str Is In Title Case, Like This
str.isalpha( ) Returns True if all characters in the string str are alphabetic characters
70
str.isdigit( ) Returns True if all characters in the string str are digits
str.isalnum( ) Returns True if all characters in the string str are digits or alphabetic
str.isspace( ) Returns True if all characters in the string str are whitespace
8.6 Genfromtxt: a tool in Numpy to read data from text files in one line
To use genfromtxt(), the Numpy module has to be imported (by the way, it is also included in
Scipy):
import numpy as np
table = np.genfromtxt(test.dat,delimiter=,,comments=#)
x = table[:,0] # x in first column
y1 = table[:,1] # y1 in 2nd column
y2 = table[:,2] # y2 in third column
Here we see that the different columns of the two-dimensional array table are copied in
independent one-dimensionnal arrays x, y1 and y2.
Loads data from a text file, with missing values handled as specified. Above the default values
for the keywords are shown.
Each line past the first skiprows line is split at the delimiter character, and characters following
the comments character are discarded.
71
comments : str, optional
The character used to indicate the start of a comment. All the characters occurring on a line after a
comment are discarded
72
9. Matplotlib: Plotting in Python
9.1 Example: plotting sine and cosine graph
Making graphs in Python is very easy with the matplotlib module. A large range of types of
plots can be made on screen and saved in several high-quality formats (like .eps) to be used in
reports etc.
Try the example program below (or download plotsincos.py from blackboard). The header is the
standard way to import both matplotlib and matplotlib.pyplot. It uses import module as
newname , to create shorter names, which make it easier to use the modules.
Pyplot is a module inside a module and imported as plt in the code below. Then it uses a for-
loop to generate different values for x and with this, two y-values using sine and cosine are
calculated. Append each value to the list variables xtab, y1tab and y2tab and then plot these in
the same figure. This figure will only become visible when a call to plt.show() is made. This
starts a separate program with the plot and waits until the user has closed this window.
73
If you run this program, you will see the following window appear as a result of plt.show():
Now try some of the buttons below the graph. From left to right these are:
- Home button: brings you back to default figure as shown in the beginning
- Back button: return to previous plot when youve panned or zoomed
- Next button: opposite of back
- Pan button: move the plotting window coordinates
- Zoom: Select a zoom window
- Adjust subplot: Adjust (sub)plot parameters with sliders
- Save: Select a file format and filename to save the plot as currently set up in the window
More options are available if we define a figure and a subplot. We can then use the methods
provided in these types:
sc.plot(xtab,y1tab)
sc.plot(xtab,y2tab)
sc.set_title('Now a title can be added to a figure')
The variable fig can now also be used to add different subplots next to each other in one figure.
We define one subplot here which we call sc (sine-cosine) and then use methods provided with
the plot to both plot as well as add a title. Similarly functions for legends and labels are available.
http://matplotlib.sourceforge.net/gallery.html
In this gallery, click on a figure and then select source code to see how the figure is made.
Ignore all the complex stuff where they generate the data and check for useful Matplotlib
74
methods in a figure or a subplot to enhance the way your graphs look. Also the different types of
graphs like bar charts are illustrated.
Try yourself: Make a plot of the two functions f(x) = sin x and g(x) = ex 2 for x = [0, ] Find
the coordinates of the point where sin x = ex 2 using the zoom-function of the plot window.
9.2 More plots in one window and scaling: subplot and axis
Instead of several lines in one plot, you can also include more than one figure in one plot
window with the subplot function. In the example below, we want to show the standard
goniometric functions sine, cosine and tangent in the top row and the hyperbolic functions in the
bottom row. This is done by including the command subplot. For example the first subplot-
command:
plt.subplot(231)
The number 231 is used in an unusual way, it should be read as 2-3-1 and stands for: make 2
rows of 3 graphs and start with subplot number 1. Until the next subplot command, all function
calls will now affect this subplot. The numbering of the plots is in this case 1 to 3 for the plots in
the first row and 4 to 6 for the three plots in the bottom row.
Note that since the tangent had vertical asymptotes, it will yield a useless high range on the y-
scale. To control the range of the axes from within our program for the third subplot, we use the
command:
plt.axis([-2.*pi,2.*pi,-5.,5.])
This will set the x-axis at a range of [-2, 2] and the y-axis at [-5,5]. This shows the shape of the
tangent in a more sensible way.
# Generate data
x = np.linspace(-2.*pi,2.*pi,1000)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)
z1 = np.sinh(x)
z2 = np.cosh(x)
z3 = np.tanh(x)
plt.subplot(231)
plt.plot(x,y1)
plt.title('sin')
75
plt.subplot(232)
plt.plot(x,y2)
plt.title('cos')
plt.subplot(233)
plt.plot(x,y3)
plt.axis([-2.*pi,2.*pi,-5.,5.]) # setting scale:xmin,xmax,ymin,ymax
plt.title('tan')
plt.subplot(234)
plt.plot(x,z1)
plt.title('sinh')
plt.subplot(235)
plt.plot(x,z2)
plt.title('cosh')
plt.subplot(236)
plt.plot(x,z3)
plt.title('tanh')
plt.show()
You can also see that in the plot the asymptotes are just nearly vertical jumps in the data. You
could draw the tangent graph in such a way that it will not connect these points. You can even
add drawing the asymptotes with red dashed lines when you know where they are. How would
you do this? Check out the examples and the Matplotlib reference documentation for this.
(Another way might be to draw an independent line in graph for each period!)
76
9.3 Interactive plots
Sometimes you do not want to wait till your program is ready, but you would like to see the data
already when it is being generated. For this you can use the interactive plot feature. By default
this is switched off, but you can switch it on and off using the matplotlib.pyplot.ion() and
matplotlib.pyplot.ioff() commands. See for example the program below:
for i in range(100):
x = float(i)/10.
plt.plot(x,sin(x),"ro") # plot each point as a red dot
plt.draw() # Show result
Which will show data as it is being generated and adjust axes on the fly when necessary:
77
9.3 3D and contour plots
When you need to plot a function of two variables, for example z = f(x,y) , anpother type of
graph may be needed. In that case there are two common ways to do this. Using colours
indicating the z values per point x,y or using a 3D plot where the height indicates the value z.
Both methods are explained in the following example codes.
Both examples, plot the function z=f(x,y) . For this they use a 2-dimensional array with a grid,
generated with a function called meshgrid, to generate the values at an equal distance. You
could convert these examples of source code to a function which plots your own data or your
own function. You should then only change the data X,Y and Z. To do this in a neat way, you
could convert these examples to a function where the X,Y and Z are input arguments to that
function.
The resulting figure is shown next to the source. In the 3D plot you can move around the plot to
change the viewing angle before saving it to an image file. Both plots also use a colour map cm.
78
And for the colour- and contour plot we can use the following example code:
79
9.4 Overview of essential matplotlib.pyplot functions
It is assumed you have imported matplotlib.pyplot as plt, so the pyplot commands are preceded
by a plt.
plt.bar(x,y) Bar plot, x = hor. place (e.g. arange(5), y , where y is alist/array with 5
values)
plt.show( ) Show graph in interactive window (put this as the end of your plot
commands or you will not see anything)
plt.axis([xmin, xmax, ymin, ymax]) Set range of axes, uses a list (or tuple) with the values
plt.legend( loc=locstr) Add legend, uses a list of strings: str1 is text for 1st line etc. Location of
box with legend can be specified with this string:
plt.subplot(231) Specify number of rows (2), number of columns(3) and finally set the
figure number for next pyplot commands (1st figure in this example)
plt.axvline(x=1) Draw a vertical line. You can also limit the length with the ymin and ymax
keywords: plt.axvline(x=1,ymin=0.,ymax=2.,color=r)
plt.axhline(y=2) Draw a horizontal line. You can also limit the length with the xmin and
xmax keywords: plt.axhline(y=2,xmin=-1.,ymax=1.,color=r)
80
10. Numerical integration
10.1 Falling ball example
The example assignment below describes a technique called numerical integration: for every
time step, the change of a variable is first calculated and then used to change the value of that
variable. It is called numerical integration because you move from the second derivative of place
to time (the acceleration) to the first derivative of place to time (the speed) and then the
derivative to the place itself (in this case the altitude). So those two steps integrate with respect
to time.
In complex examples many forces can act on a mass, but you can often calculate these for a
given situation. And with this technique, if the forces can be calculated for a situation, we can
calculate the acceleration and then integrate this to get the time history of speed and place. In this
way we can simulate the physics and solve problems, which we cannot solve analytically.
While y remains larger than zero (until the mass hits the ground), repeat the next
iterations:
t = t + dt
F=m g
a = - F/m
vy = vy + adt
y = y + vydt
During each step, append the value t to a table for the time and append the value of y to a
table with the value of y. After all iterations, when the mass has reached the ground, plot
the value of the height y against the time t, using these tables.
c) Compare the two different datasets in one plot to see the effect of the drag. Try
different values for starting altitude and CD.
81
10.2 Two-dimensions and the atan2(y,x) function
Our example of the falling ball has only one dimension, but this can easily be expanded. Imagine
a horizontal speed is added:
x = x + vx*dt
But when drag is then added things get more complicated in two dimensions.
The drag can be calculated in the direction opposite of the speed, but then it needs to be
composed in two directions. One way to do this is by calculating the length of the force and then
decompose it into two directions.
Often it is handy to switch between polar coordinates for the positions and to orthogonal
coordinates to get the forces. This we can use for calculating acceleration, speed and
displacement in both x- and y-direction. For this there is a very convenient, special arctan-
function called atan2(y,x). Look at the example below:
V = sqrt(vx*vx+vy*vy)
D = cd*0.5*rho*V*V*S
angle = atan2(-vy,-vx)
Dx = D*cos(angle)
Dy = D*sin(angle)
Here we see that first the length of the speed vector is calculated. This is then used to calculate
the length of the drag force. Then the angle is calculated using a special arctan-function atan2. If
the normal atan function would have been used, there will be no different outcome for vy/-vx
and vy/vx even thought the two vectors point in opposite direction. This is caused by the fact
that the tangent, being the quotient of sine and cosine, has a period of only and not 2.
To be able to move from Cartesian coordinates (x,y) to polar coordinates (r,) without an extra
if-statement for checking the sign of x and y, atan2 can be used as in the example. It will result
the correct angle for the (y,x) (vy,vx) or (dy,dx). Since the tangent is sine/cos, hence y/x the y-
coordinate is given first. So with this function =atan2(y,x) it works for all quadrants!
82
10.3 Program structure of numerical integration and simulation
Use this structure as a template for all your simulations: add the descriptions in the block as
comment lines and then fill these in with real code between the comment lines.
83
11. Numpy and Scipy :
Scientific Computing with Arrays and Matrices
Python with Numpy and Scipy are more capable than Matlab. Python is better in handling strings,
reading files, working with very large projects and with large datasets. Python can also be used
in an object oriented programming way. Both Spyder and the iPy Notebook provide a very user-
friendly environment for scientists. A more general difference are the extra possibilities, which
are provided by a full-featured general purpose programming language like Python. And, often
more importantly, MATLAB is very expensive and many applications require extra toolboxes,
which are in turn also very expensive. This also hinders sharing tools as well as quickly using
source code from the internet community: often you can only use the downloaded bits after
purchasing the required toolboxes.
With Numpy and Scipy, Python has surpassed MATLAB in terms of functionality. The modules
are available for free (as are all Python modules). They are developed, maintained, expanded and
used by a large academic community, mainly in the US and Europe.
Numpy forms the foundation for Scipy, Matplotlib and many other modules: it provides the
array- and matrix-types as well as linear algebra functions as extension to Python. Scipy adds a
whole range of sometimes very dedicated scientific computing and engineering functions.
Thanks to Numpy and Scipy, Python has become the default language of choice for scientific
computing, according to IEEE and many others. Lets explore the capabilities of these modules,
even though we can only scratch the surface in this course.
To use these modules, they need to be imported. It has become standard practice to rename them
when importing them. Numpy becomes np and Scipy becomes sp. This means we will often
see the following header in our scientific applications. In this course, we assume you have
imported the modules as follows:
import numpy as np
import scipy as sp
import matplotlib as mplt
import matplotlib.pyplot as plt
In the Numpy and Scipy documentation it is often even assumed that you have imported
everything using from numpy import * So do not forget to type np. before the
Numpy functions and sp. before the Scipy functions, even though you dont see this in the
Numpy and Scipy documentation. Most Numpy functions can also be used as if they were a part
of Scipy, wo with the sp. prefix.
84
This would also be good time to add a link to the Help chm-files containing the Numpy and
Scipy reference to your IDLE Help menu, if you have not already done so. Go to
Options>Configure IDLE, click on the General-sheet on the top right. Then click Add in the
lower part of the window to add the menu item and the link to these files.
11.2 Arrays
So far we have seen lists and even lists of lists. When we used lists as tables we often kept
separate columns in separate one-dimensional lists, so we could select them individually (like
xtab, ytab in the previous chapter). And if we used a two dimensional table, we could add small
lists of two elements to the lists like this:
for i in range(1000):
x = x + vx*dt
y = y + vy*dt
postab.append([x,y])
But how can we now select only the first column? Unfortunately, postab[:][0] does not give this
result. This indicates, as well as many other examples, that two dimensional lists are, as a
variable type, despite their versatility, are not always the most suitable type for scientific
computing and working with large tables in a fast and user-friendly way.
The module Numpy has an advanced list-type which solves this: the array .This type forms the
foundations for Numpy and Scipy. With this type you can do computations with entire tables, as
easy as if they are one scalar variable.
85
The indexing also has a different syntax although both use the square brackets:
np.arange(start,stop,step) Define an array with floats evenly spaced with step (stop not
included), difference with range function: it works with floats and result is
a numpy array, Example:
arrange(0.,0.6,0.1) will result in [0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
np.linspace(start,end,nelem) Define an array ranging from start to, and including, end with
nelem elements, results in a Numpy array, example:
np.linspace(1,3,) will result in [1.0, 1.5, 2.0, 2.5, 3.0]
Next to being able to use two indices separated by a comma instead of many pairs of square
brackets, there is another useful feature of an array: it is easy to select columns or other parts of
the array:
Numpy arrays can be multiplied by each other or a scalar and used in functions from Numpy (np)
like np.sin( ), np.exp(), np.sqrt( ) etc. All functions and operators, work on an element-by-
element basis with arrays.
A drawback of arrays is the slower append function. Note the difference in append of lists:
import numpy as np
# List append
xtab.append(x)
86
The effect is more than a different syntax. The numpy.append function makes a copy of the array
with the value appended to it. In this case because xtab is also before the assignment it
overwrites the original, so the end effect is the same. The real penalty however is the decrease in
execution speed. With large quantities of data, making a copy takes extra time which can slow
down your code immensely. There are two better alternatives, which you sometimes can use:
1. When you know the size, it is better to generate an array of the right size with
numpy.zeros(shape) e.g. numpy.zeros(10) or numpy.zeros((4,4)) or a scalar times
np.ones(shape) if you need a specific default value.
2. You can use the list-type to append first and then, when it is complete, convert the list to
an array.
The example below also times the execution time of both ways.
for i in range(n):
Vtab.append(100.+250.*rnd())
hdgtab.append(360.*rnd())
vetab = []
vntab = []
t0 = clock()
for i in range(n):
vntab.append(Vtab[i]*cos(radians(hdgtab[i])))
vetab.append(Vtab[i]*sin(radians(hdgtab[i])))
dtlst = clock()-t0
print "Lists took",dtlst,"seconds"
87
# Convert to arrays
Vtab = np.array(Vtab)
hdgtab = np.array(hdgtab)
The result show that with10000 elements the numpy method is about 11 times faster than the list
method! And also the numpy code looks cleaner. If we oly do it the numpy way, the program can
even cleaned up to look like this (without the timing):
n = 10000
Vtab = 100.+250.*rand(n)
hdgtab = 360.*rand(n)
vntab = Vtab*cos(radians(hdgtab))
vetab = Vtab*sin(radians(hdgtab))
The difference between the two approaches is that when you apply a function or an operator on
the complete array, or the complete vector, the looping over the elements is handled by low-level
code inside numpy. The reason this is faster is twofold:
- the loop takes place in the fast, compiled low-level code of numpy
- list elements can have different types, while all array elements always have the same type, this
saves the computer from checking the type for each element and this saves execution time
Changing the code from treating each element to a complete array (or vector) at once, is called
vectorizing your code. In general, it is a good rule of thumb that when you can vectorize your
code, you should. Sometimes lists are easier or the lists are not that large that it is needed. But for
large quantities of data with the same type, vectorizing is nearly always a good idea.
Using two-dimensional arrays and the transpose function, vectorizing can be really powerful for
geometrical calculations, see the example below:
import numpy as np
88
# Make two dimensional
x = x.reshape((n,1))
y = y.reshape((n,1))
dist = np.sqrt(dx*dx+dy*dy)
del dx,dy # Free up memory
x.T means x will be transposed (so rows become columns and the other way around. So in this case x.T is:
>>> x.T
array([[12, 2, 35, 11]])
Note that this is still a two dimensional array, but with one row ( double square brackets).
As you can see in the ouput x-x.T results in matrix in which dx[0,1] gives x[0]-x[1].
The downside of using vectors this way with a lot of data is that all intermediate answers also become
vectors. With large quaitites of data, you can easily consume a lot of memory this way. In that sense,
vectorizing sometimes means exchanging speed for memory usage. A good way to avoid running out of
memory is therefore delete arrays used for intermediate results. But together with some linear algebra,
you can speed things up enormously.
89
11.5 Matrices and Linear algebra functions
Another very useful type is the matrix. The matrix is a type used within linear algebra. Why don't
we use the array type for this? One important reason is that some rules are different when
working with entire tables or with matrices.
For instance: A*B will result in entirely different things depending on what type you use. If A
and B are arrays, we will get an array where each element is the product of the same elements of
A and B. This is called element-by-element multiplication and is what you would expect if you
are talking about a table with densities and temperatures for example.
With matrices in linear algebra, we don't want that kind of multiplication, we want a matrix
multiplication. This also poses different restrictions to the dimensions. The resulting matrix is a
matrix-product of the two given matrices.
There is a special function to do element-by-element multiplication with matrices and there also
is a special function to do matrix-multiplication with arrays, but the default * operator uses the
most applicable for arrays and matrices as explained above.
So in short: use arrays for tables, like time histories or other scientific computing problems with
tables. And use the matrix-type for matrices in linear algebra problems or simulation models
with matrices. An example of how to define and use matrices is given below:
import numpy as np
B = A.I
print B
C=A*B
print C
Running this example will first print the matrix A (as a matrix), then a 9, (1=second row, 2=third
column). Then it prints the inverse of A, called B here. And finally it should print the identity-
matrix to check the inverse calculation.
Note that we use square brackets for indices and 0 as starting index as in Python. But also note
how we use a comma instead of two separate pairs of square brackets. Slicing with matrices (and
arrays) is much more user friendly and works as you would expect. So A[:,2] will give the last
column, try for instance:
print A[:,2]
90
There are many ways to define a matrix. The np.matrix() or mat function accepts lists,
arrays and strings as input as in the example above. Using a string with a space between the
numbers and a semi-colon between the rows is often the easiest way to define a matrix as in:
A = np.mat("2 -2 0;1 5 9; 4 2 -5")
For some more examples on how to use a matrix, see the following source code. Also note how
Scipy also supports all types of Numpy. (So here we use sp instead of np!)
91
This illustrates some of the functions Numpy provides for matrices: inverse, determinant and
solve.
np.matrix( ), np.mat( ) Creates a matrix , argument can be a string like (1 2;3 4) or a list,
or an array (operators now work with entire matrices)
matrix.I Invert matrix
np.linalg.det(matrix) Calculates the determinant of a matrix
It is possible to use two-dimensional arrays as vectors and matrices. To use the dot product, it is
then required to use the numpy.dot() function.
import numpy as np
A = np.array([[2,-2,0],[1,5,9],[4,2,-5]])
print A
print A[1,2] # row,column as in lin algebra but index starts
# with 0!
B = np.linalg.inv(A)
print B
Or to solve an equation Ax = b:
import numpy as np
A = np.array([[1,0,3],[-2,-1,0],[1,1,2]])
b = np.array([[1],[-1],[2]])
AI = np.linalg.inv(A)
x = np.dot(AI,b)
print x
x = np.linalg.solve(A,b)
print x
Note: Unfortunately, lately the Numpy community has been very critical about this matrix type,
which is regarded as an unwanted dialect of the array type. Using two-dimensional arrays for
matrices means using np.dot(A,B) or A.dot(B) for multiplication and np.linalg.inv(A) for
inverse, you can achieve the same as with the matrix type (but less elegant). This may mean the
matrix type will be phased out of Numpy.
92
11.6 Scipy: a toolbox for scientists and engineers
Numpy forms the foundation of Scipy. It is the basis of the array types and the basic functions
such as linear algebra Building on this foundation, there are already a large number of functions
available in the modules in numpy. See the list below for an overview of what is inside numpy:
But while Numpy has some useful functions for many applications and even some advanced
functions like Fourier transforms (frequency analysis of signals), Scipy contains many more
advanced functions, like curve fitting, optimization methods, frequency analysis, statistics:
93
On the internet, many more modules, which use Scipy and Numpy can be found. For nearly all
fields of science and engineering, modules with many tools are available for free.
In comparison, for a comparable package like MATLAB, often expensive toolboxes are required
to use something, which you downloaded from the internet. These toolboxes easily cost
thousands of euros, making it a costly decision to try a toolbox. This is, next to the higher
versatility and better syntax, one of the reasons why Python+Scipy nowadays is being used
instead of MATLAB. IEEE has already called Python+Numpy+Scipy the standard for data
analysis. MATLAB will probably become obsolete in the future as it is both more limited and
more expensive.
The Python community has the highest amount of PhDs resulting in high quality toolboxes being
expanded continuously and growing very fast. For aeronautics, we could still build a better
toolbox than the sparse examples which are available.
C
C Output theta in radians to block response of elevator
C Elevator = 0.2 radians between 1 and 2 seconds
C Boeing 737
C timestamp in seconds
C
0.0 = -0.00122299949023
0.1 = -0.0148544598502
0.2 = -0.00128081998763
0.3 = -0.00912089119957
19.7 = 0.0375150505001
19.8 = 0.0133852241026
19.9 = 0.0195944297302
When we plot this data we get this figure, showing a very noisy signal:
94
In this plot we can see the original signal, to get this line we can try a polynomial fit, to get a
signal more close to the original signal. Note how in this program we use the function
genfromtxt() from Numpy/Scipy to read the data into a two-dimensional array with one
program line! Then we select the two columns.
To fit the data we use the function polyfit, which return the polynomial coefficients, in this case
set to a 10th order polynomial. The result is then written to a file.
import scipy as sp
import matplotlib.pyplot as plt
# Plot
plt.plot(xtab,ysmooth)
plt.plot(xtab,ytab,"r+")
plt.show()
# Write to file
g = open("filtered.log","w")
g.write("C\n")
g.write("C Data smoothed by fitting a 10th order polynomial\n")
g.write("C\n")
95
for i in range(len(xtab)):
line = str(xtab[i])+" = "+str(ysmooth[i])+"\n"
g.write(line)
print line
g.close()
The resulting plot shows both the power and limitation of polynomial fitting:
The curve is indeed a smooth polynomial. The disadvantage is that there are limitations to how a
polynomial can fit the data points. Even when a higher order is chosen (10th order seems to be
working for a smooth curve with 8 local minima/maxima) it does not give a useful result outside
the interval. So while it is very useful for interpolation, it should never be used for extrapolation.
More advanced methods take into account a certain assumed relation of which the parameters
will then be estimated. The least squares method, which minimizes the square of the error, can be
used for this and is available by Scipy.
96
11.7 iPy Notebook
With Python(x,y) comes iPy notebook. (You can find it hidden in the Start menu Python(x,y) >
Command prompts > IPython Notebook Server
The iPy Notebook is very convenient user interface for Scientific Computing tasks. It allows you
to edit snippets of Python/Numpy code (Cells) which you run but also can still edit later. You
can access all variables between cells, as if you are in one program, but you can also see the
output (including plots) in between the code. The result is a blend of a graphical calculator,
Python and a spreadsheet program like Excel. You can run an individual cell or all cells and see
how the output changes. You can also add cells with raw text to create a living document. Each
notebook page can be saved (downloaded as it is called in this client-serve set-up) as either
a .py Python file or a .pyndb Python notebook file. The Notebook page is both a scratchpad as
well as a publication.
An example of how this looks is shown below. As you can see all functions from math, numpy
scipy and matplotlib.pyplot have already been imported:
97
12. Tuples, classes, dictionaries and sets
12.1 New types
Before we continue with Pygame there are two concepts of Python you need to know: Tuples
and classes. For classes you only need to know how to use them for now. But a simple example
how they are defined helps understanding the principle. In chapter 1 we have seen the list type,
which we use regularly in simulations to make tables. For instance like this:
# Create tables
ttab = []
ytab = []
# Initialize
y = 100.0
vy =0.0
t = 0.0
dt = 0.01
# Run simulation
while y>0.:
t = t + dt
vy = vy g*dt
y = y + vy*dt
ytab.append(y)
ttab.append(t)
# Plot y
plt.plot(ttab,ytab)
plt.show()
Here we note two things: an empty list is created and later elements are added. These elements
could be changed later. We could set ytab[i] to a certain value. But what is also notable is the
fact that we call the append function (or method) with the variable:
variablename.append(value)
We have seen a similar syntax with strings: varname.sort() or varname.upper(). The reason
for this is that lists and strings are actually so-called classes: a sort of specific variable type with
data and functions as a part of its definition.
This syntax is often seen when using modules. Since one of the powers of Python is the number
of modules included and freely available on the internet, this deserves some extra attention in the
final paragraph on classes.
98
12.2 Tuples
Lists have been discussed in chapter 2 and in the previous chapter on Numpy we have already
seen a new type of lists called arrays, as used by Numpy. In fact, the list-type is the most simple
and versatile form of an array- or list-type of variable. It can contain different types and each
element can be treated as an independent variable. But there are many more list-like types, one is
the so-called tuple.
A tuple is a list but it is immutable (just like strings). This means it cannot be changed once it is
created. The variable can be overwritten by a new tuple, but individual element cannot be
assigned a different value, nor can elements be added or removed. This is the only difference
between lists and arrays. To distinguish between lists and tuples we use the round (normal)
brackets to define a tuple. It is also possible to leave the brackets a way, this also indicates you
want to create a tuple. So two valid ways to create a tuple are:
origin = (0,0)
pos = 3,4
If you call a function with a tuple, you always need the round brackets, see the line with d2
below:
d1 = dist(origin,pos)
d2 = dist((3,4),(-3,6))
If you would leave the brackets away in the second line, Python would think you call the
function dist with four arguments.
Tuples can, just like lists, and unlike Numpy arrays, contain a mix of different types such as
integers and floats etc..
It seems like a tuple is a list with a limitation, so what are they used for? Tuples can be seen as
multi-dimensional values. So for instance if you want to specify an RGB-colour by its red-green-
blue components you could use the following assignment to defines these colours for later calls
to a graphical library:
black = (0,0,0)
white = (255,255,255)
brightred = (255,0,0)
red = (127,0,0)
cyan = (0,255,255)
Weve also already seen that maptlotlib.pyplot.legend() used a tuple for the legend text,
Although this legend() function can also be called with a list. In the next chapter about Pygame,
tuples are used for colors and positions.
There are many more list-like types. In most cases the list type will work for you. But sometimes
a special list-like type can be convenient. If youre curious, check the Python documentation on
sets and dictionaries.
99
12.3 Classes and methods (object oriented programming)
In Python, next to function definitions, you can also define you own variables types and
associated functions. This is what classes are. Imagine we could design a new type of variable
called Pos, short for position. We want it to hold an x- and y-coordinate and we want to be able
to do vector-wise addition. Also a length function will give is the length of a two-dimension
position vector. Then we would be able to write a program like below:
posa = Pos(3,4)
posb = Pos(-1,5)
distvector = posa.sub(posb)
dist = distvector.length()
To be able to do this we need to tell Python what our type of variable, our class, is and what the
functions should do. This is done by defining a new so-called class Pos:
class Pos:
def __init__(self, xcoord, ycoord):
self.x = xcoord
self.y = ycoord
return
def sub(self,pos2):
rx = self.x - pos2.x
ry = self.y - pos2.y
newp = Pos(rx,ry)
return newp
def length(self):
return sqrt(self.x*self.x+self.y*self.y)
After the header a number of methods are defined. They use the same syntax as the definition of
a function. So a method is a special type of function connected to the class Pos. It is therefore
also called by the syntax varname.methodname(arguments).
Note that a special function __init__ is defined first: the so-called constructor. It is called
automatically upon creation of a new instance of the class (like for posa and posb in the
example). This definition of __init__ tells Python how this type can be created and what to do
with the arguments that may also be given. In this case, they are simply stored as members x and
y. So we note there are two variables stored in a Pos-type of variable: x and y. These are called
members of the class Pos.
An example of how to use this class (we assume we have saved the above code in the file named
CPos.py):
a = Pos(2,3)
b = Pos(1,2)
100
c = a.sub(b)
print c.x,c.y
print c.length()
You can build your complete program around classes. By first defining your classes including
members and methods, and building classes consisting of classes on top of each other your final
program could be very short. This can be done by just calling the highest level of classes like:
sim = Sim()
running = sim.start(0.,0.,0.)
while running:
sim.update(running)
Object oriented programming is beyond the scope of this reader. You do not need to know how
to define your own classes. You have already been using classes when calling string methods or
list methods. For this course, it is only important that you know that the concept exists and why
you sometime call methods or access members. It also explains this strange syntax of
variablename-period-method(arguments) like list.append(x).
It is important for you to know how to use the classes and how to call methods inside a class.
Especially in Pygame we see two new types of variables used a lot: a surface and a rectangle.
These are classes. One designed to hold a bitmap, the other to hold a position and a size of any
rectangle. In the rectangle class not only methods are used but also members, (like top, width,
height) can be assigned a value. This will be shown in examples in the Pygame chapter. Even
though the concept of classes and object-oriented programming may be difficult, using modules
with classes is surprisingly easy and user-friendly, as we have already seen with lists and strings
and we will also see in the Pygame chapter.
101
12.4 Dictionaries & Sets
Dictionaries
Two special types of lists can be handy. Dictionaries are list where you do no use an index but a
key to look up a value.
An example of a dictionary:
Sets
Sets are lists used for unordered collections of unique elements. It is used to check membership
of a collection, overlaps of collections, etc.
It is defined similarly to a list (square brackets) with the function set. Example of the use of sets:
>>> a = set([3,1,34,65,2,2,1])
>>> a
set([1, 34, 3, 2, 65])
>>> if 2 in a:
print 'yes'
yes
>>> 2 in a
True
>>> b = set([1,6,7,10,2,3,7])
>>> a|b # which elements are in a or b?
set([1, 34, 3, 6, 65, 10, 7, 2])
>>> a&b # which elements are in a and b?
set([1, 2, 3])
>>>
102
13. Pygame: animation, visualization and controls
13.1 Pygame module
The Pygame module contains a set of user-friendly modules for building arcade-like games in
Python. But because it has several drawing routines as well as key controls, it is also a very
convenient library to make any 2D graphics, especially moving graphics with some key controls.
Therefore it has also become the default graphics library. It is often used for other purposes than
games, like animation, visualization of simulation and all other non-moving drawings which
need something more versatile than Matplotlib, which produces graphs but is not a grapchis
library. Also key and mouse controls are part of Pygame and can be added to pan, zoom or
control a simulation.
In this chapter we will explore different modules inside Pygame like display, event, key, mouse,
image, transform and draw, as well as the new types (classes to be exact): surface and rect. There
are many more modules inside Pygame for you to explore like, music, joystick, etc. but these
will not be discussed here. Next to Pygame, some basics of setting up a game or simulation will
be discussed such as the game-loop and timing issues.
Just as with Numpy and Matplotlib, Pygame is a third party add-on. So before you can use
Pygame, you need to add the import line. Also you should add two calls to Pygame at the
beginning and end of your program for initialization and cleaning up, resulting in the following
three mandatory lines:
import pygame
pygame.init()
.
.
(your program will be in between these calls)
.
.
pygame.quit()
The init-call has no immediate visible effect, but it is required to avoid having to initialize each
module of Pygame independently. So calling pygame.display.init, pygame.key.init is
not necessary when you include this one call.
pygame.quit() will have a visible effect: it will close any Pygame windows still open. If
during the development your program crashes due to an error and the Pygame window is still
open, type pygame.quit() in the shell to close it. (or pg.quit() if you used import
pygame as pg)
Pygame has a very good online reference manual at http://pygame.org/docs . In the top section of
this page, you see the name of each module inside Pygame. Click on these names to get a list of
functions in that module, a click on the function names in this list to get a full description.
103
13.2 Setting up a window
Before we draw anything, we need a window to draw in. The way to do this is using a function in
the display module, which is called pygame.display.set_mode(). The various possibilities
of this function are explained in the documentation of Pygame. To get an impression, here is an
example call which creates a window of 600 pixels wide and 500 pixels high:
reso = (600,500)
screen = pygame.display.set_mode(reso)
Or in a similar way (mind the double brackets, the resolution is a so-called tuple, see section
12.2):
screen = pygame.display.set_mode((600,500))
In computer graphics, a coordinate system different from mathematics is used, mainly for
historical reasons. The top left corner is the origin and the y-coordinate runs from zero in the top
to the bottom, so in our example y=500 pixels indicates the bottom line. X-coordinates are from
left to right. This stems from the text terminal which had line zero and column zero in the top left.
So the window, which we just created, has the following coordinate system:
In the computer graphics world things get really complicated in three dimensions. The axis of the
graphics coordinate the Z-axis points positive to the viewer, in effect creating a left-handed (!)
axes reference system, where cross products and other functions work just the other way around.
104
So screen coordinates work in a non-standard way and are also always integers. For these two
reasons, it is standard procedure to define your own so-called world coordinates 9with a right-
handed reference frame), which you use for your model. And when necessary you convert them
to screen coordinates, normally just before we need to plot, draw or blit. It also allows us to
change the window size later (e.g. to full screen), without changing our model. An example of a
simple 2D world coordinate system is:
In this case we can calculate with any position in floats, use numerical integration in floats and
then convert our float world coordinates to the integer screen coordinates just before plotting
with the following lines of code. In the example below the world coordinates are (x,y) and are
converted to screen coordinates (xs,ys):
xmax = 600
ymax = 500
reso = (xmax,ymax)
screen = pygame.display.set_mode(reso)
.
..
x = x + vx*dt
y = y + vy*dt
xs = int(x/1.67*xmax)
ys = ymax-int(y*ymax)
105
surface. A surface can also have a transparent background so that when you paste it over another
surface some pixels will remain the color of the original surface.
All in all, it is a very versatile type allowing you to manipulate or transform (scale move,
copy/paste, rotate) bitmaps.
When you paste a surface onto another, this is called blitting in the computer graphics world. It
stems from the block of bits of the video memory which is transferred with one call to a blit
function. Before we can do this we also need to specify where we want this rectangular image to
be pasted.
When we have loaded an image from the disk, we need to know how large it is and where we
should be able to position it onto another surface later. This is where the rectangle class comes in.
A rectangle is not the actual surface but it contains some parameters: the size and position of a
surface. It has several members, which we can assign values to. The neat thing is that we do not
need to worry about the bookkeeping: when you change one value, the other ones will be
changed automatically when needed. One simple example is given below. To clear the screen,
we draw a black rectangle. For this we need to specify the position and scale first. If we get the
rectangle from a surface to measure the size, the position is by default set to (0,0) for the top left
corner. To do this, we use the method get_rect in the Surface class (see the section on Surface
in the Pygame documentation for a full description of the methods of surface).
black =(0,0,0)
scrrect = screen.get_rect()
pygame.draw.rect(screen,black,scrrect)
A Rect has the following members, which you can read or assign a value to:
Center is a tuple equal to (centerx,centery). The user can choose to position the rectangle using
any combination of these members.
Another example where the Rect class is used is given below, where an image is loaded from a
file on the hard disk. Generally, we do this loading from a file only once at the beginning of our
program, because accessing the hard disk has a huge execution speed penalty. The example
shows how to use the rectangle: first we get the size from the surface object and then we position
it and use it to blit the surface on the screen surface.
ship = pygame.image.load(rocket.gif)
shiprect = ship.get_rect()
..
..
while running:
shipx = shipx + vx*dt
106
shipy = shipy + vy*dt
shiprect.centerx = shipx
shiprect.centery = shipy
screen.blit(ship,shiprect)
In the code we can see how the rectangle is used to position the bitmap, which was read from
rocket.gif, on the screen. The same call can be used with a tuple containing the coordinates of the
top-left corner of the surface. As visible in the syntax, blit is a method from the Surface class,
hence it is called as a method, so with a period behind the destination surface (=variable named
screen in our example).
scr = pygame.display.set_mode((500,500))
ship = pygame.image.load(lander.gif)
shiprect = ship.get_rect()
shiprect.center = (xs,ys)
scr.blit(ship,shiprect)
As said before, it is important, to load the bitmaps before the actual game loop. Accessing files,
to load an image, in general takes a lot of time. This means it might cause hick-ups or delays in
your program, if you do this during the loop.
Sometimes bitmaps do need some editing before they can be used. When blitting images on a
surface a transparent background is often required. This can be edited with a painting program
such as Paint.net, Gimp, Paint Shop, Corel Draw or Photo shop and deleting the background so it
becomes the transparent colour. Save the file in the GIF format (or PNG) as these formats allow
transparent backgrounds. Also use these programs to change colors, size or perform rotations.
If you need one bitmap in a lot of different orientations, editing it with a paint program can be
cumbersome. These operations can also be done much easier with pygame in your program. This
can be done using the transform module which allows you to manipulate bitmaps/surfaces. Some
examples of functions available in pygame.transform:
107
pygame.transform.rotozoom(surface, angle, scale)- filtered scale and rotation, angle
float in degrees, scale factor also float, returns new surface
pygame.transform.scale2x(surface) - specialized image doubler, returns new surface
pygame.transform.smoothscale(surface,(newwidth,newheight)) - scale a surface to an
arbitrary size smoothly, returns new surface
Be aware that you do not scale or rotate inside the game loop unless it is absolutely necessary. In
most cases it pays off to generate different surfaces for all possible orientations beforehand, store
them in a list and just use the appropriate one during the game loop by setting the index with the
angle rounded off to 45, 20 or 5 degrees. The same goes for scaling. Transforming bitmaps is
rather computational intensive and in general it is the goal to do any time consuming operation as
much as possible before the actual running of the game loop.
The coordinate system used is explained in the section on setting up your screen. It runs from
(0,0) in the top left corner to the maximum x and y in the bottom right. All sizes and positions
are integers.
Colours are specified with a tuple (red,green,blue), three numbers each ranging from 0 255 to
indicate the amount of each colour channel present in the mixed color. For readability it helps to
define a few colours at the beginning of your program and use these in the calls:
black = (0,0,0)
cyan = (0,255,255)
white = (255,255,255)
background = (0,0,63)
foreground = white
108
normal bitmapped shapes. One disadvantage of this is that it takes more time and memory: the
shape is first drawn in a higher resolution and then anti-aliased. Another disadvantage is that
you later on cannot select the pixels which are part and not a part of the shape. It depends on
your application whether you want to use anti-aliasing.
Animation consists of nothing else then redrawing every frame over and over in a simulation or
game. To avoid flickering images when the screen is cleared for the next drawing, this is first
done in a part of the video memory which is not visible. There we clear the screen, and either
with drawing (rectangles, circles and lines) or blitting the next image is created. Once it is
finished, we can show it on the screen. This also means we will not see anything until we copy
this video memory to the screen. This is done with the following call, to be used at end of all
your draw and blit calls in the loop.
pygame.display.flip()
If you have used the default settings when creating the window with
pygame.display.set_mode(), a call to flip updates the window with the video memory.
When you use the option double buffering, you have two areas of video memory, so two surfaces
which will be used simultaneously: one will be shown on screen, the other you can draw on.
Once youre done drawing the frame, you swap the function of both surfaces. The advantage is
that you do not need to start with an empty frame then, but can use the one-but-last frame as a
start. In practice, to take advantage of this you might need a lot of bookkeeping but it might
result in a higher execution speed.
Using the full-screen option is often only done when the game or simulation is ready, debugged
and tested, since debugging is severely hampered by a crashing full screen application!
import pygame
pygame.init()
reso = (600,500)
screen = pygame.display.set_mode(reso)
scrrect = screen.get_rect()
black =(0,0,0)
ship = pygame.image.load("rocket.jpg")
shiprect = ship.get_rect()
shiprect.centerx = 250
for y in range(500,-100,-2):
shiprect.centery = y
pygame.draw.rect(screen,black,scrrect)
109
screen.blit(ship,shiprect)
pygame.display.flip()
pygame.quit()
Now when we run this, it could turn out that our ship moves too fast or too slow. To fix this, we
will then adjust the third argument of the range function in the for-loop, currently set to -2.
However, on another computer the speed would again be different. Also, when another
application in the background needs the CPU for a short period, our rocket will hamper before
continuing. This is because we have no control over the real speed of the rocket. For this we
need more than controlling the position, we need to control the timing in our game as well. Or at
least measure it and calculate the elapsed time (time step) since we last drew our ship, so that we
can calculate the required new position with the speed and right time step based on the elapsed
time since the last frame.
There are two principles we can use to make sure our simulated time runs in accordance with the
real time:
import pygame
# initialize clock
pygame.init()
tsim = 0.0
tstart = 0.001*pygame.time.get_ticks()
dt = 0.1
running = True
while running:
trun = 0.001*pygame.time.get_ticks() tstart
if trun+dt >= tsim:
tsim = tsim + dt
vx = vx+ax*dt
vy = vy+ay*dt
x = x + vx*dt
y = y + vy*dt
The advantage of this method is that you know what the time step is. This also allows for more
advanced numerical integration methods and guarantees the stability of your simulation. When
using a variable time step (Method II) there is a risk of getting a too large time step, which can
result in overshoots and even a runaway of your simulation. The disadvantage of this method,
that it requires a time step, which is large enough to make sure the simulation can always keep
up with the real time. If you make this time step too small, the simulation may lag behind or run
at a variable speed, resulting in quirky speeds and movements
110
Method II: Variable time step
In this case we simply measure the time elapsed since the last time we update the simulation.
This difference is our time step dt, which we then use to update everything including the time. It
looks much simpler, and when the computer is fast enough it will also use this for higher update
frequencies. The downside is that the reverse is also true: if the computer is too slow or
occasionally too slow, the simulation might cause problems because of a very large dt. It is
possible to safeguard this and catch up later, but then the code gets more complex than we want
to use for now. (It becomes basically a mix of the two methods.)
This is how the code looks in Python when using the method of the variable time step. The
variable t0 here keeps the previous time when everything was updated.
import pygame
# initialize clock
pygame.init()
t0 = 0.001*pygame.time.get_ticks()
.
.
maxdt = 0.5 # time step limit to avoid jumps
running = True
while running:
t = 0.001*pygame.time.get_ticks()
dt = min(t-t0,maxdt) # set maximum limit to dt
if dt>0.:
t0 = t
vx = vx+ax*dt
vy = vy+ay*dt
x = x + vx*dt
y = y + vy*dt
One of these two mechanisms forms the basis of our loop which is executed while running. This
is generally called the game-loop. In principles it runs indefinitely until a quit event is triggered.
This quit event can be multiple things:
In our example so far, just setting running to False will make sure the loop ends:
running = True
while running:
.....
.....
if y<0.:
running = False
.....
Another way to achieve this, is using the break command (which I personally see as less elegant):
111
while True:
.....
.....
if y<0.:
break
.....
Before the game loop our model is initialized, graphics are loaded and set-up and our simulation
is initialized.
We have seen how to control time, how to numerically integrate and how to draw a frame. But
we still need to know how to process input from keyboard and/or mouse.
pygame.event.pump()
keys = pygame.key.get_pressed()
The first line is required because of the way windows handles events, like keys being pressed.
The second line collects all key states in a long list of logicals. Each key has a fixed position in
this list of logicals. When this logical is True, the key is currently held down and when the key is
not pressed, the logical is False.
So imagine we want to check for the Escape key, how do we know which logical to check?
Pygame has a list of variables (integers) with indices for every key (check
http://pygame.org/docs/ref/key.html ) that you can use. For example to check the Escape key we
use (after the storing the logical in our variable keys with the above call):
if keys[pygame.K_ESCAPE]:
running = False
112
Some examples for other indices we can use (always with pygame. in front of this name if
youve use import pygame):
Similarly we can get the state of the mouse buttons with pygame.mouse.get_pressed(),
which returns three logicals for the three mouse buttons. The function
pygame.mouse.get_pos() returns the current position of the mouse.
Both keys- and mouse-functions only will return the useful values if your pygame-window is
running in the foreground (or in windows speak: has focus).
Another more advanced way to handle the mouse is to use the windows event handler. For
instance for the quit-event (somebody tries to close the window, e.g. by clicking on the red
button). An example of how this event handling could be used is given in the code below:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
elif event.type == pygame.MOUSEBUTTONUP:
Most of the times the event handling is not required, but as a minimum handling the quit event is
considered good practice: it allows the user to close the window.
Note: it is important to always include the event pump. If not the Pygame window will say Not
repondings as the windows OS events will not be processed.
113
13.9 Overview of basic pygame functions
import pygame Below it is assumed, you have imported Pygame simply as pygame
pygame.display.flip() Update the screen with the video memory (so display screen surface)
surface.get_rect() get the size of a surface in a rectangle (top and left will be zero)
surface.blit(sourcesurface,rect) Pastes the source surface on the surface at the position specified
in rectangle rect
pygame.event.pump() Flush event queue (to avoid hanging app, and to poll keyboard)
var = pygame.key.get_pressed( ) Poll the keyboard: logical array for all keys, True if pressed
if var[pygame.K_ESCAPE] : How to test for Escape key: test the logical array with the
right index (see documentation for other key indices)
More information on these and many other pygame functions can be found in the on-line
reference guide:
http://pygame.org/docs
114
14. Distributing your Python programs using Py2exe
The game has two python files: mazeman.py and toolsmaze.py, the latter of which all functions
are imported in mazeman.py (with the star-import). The are three subfolders with data files
named bitmaps, sounds and choose-your-maze. The program uses fonts to display the score text
on the top line. The main module, with which the program is started, is called mazeman.py.
Install py2exe
Py2exe comes with python(x,y) but if you dont have it, first install the correct version of Py2exe
for your OS, if you havent already done so. I used version 0.6.9:
http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/
First I also tried the pygame2exe script provided at pygame.org, but this kept giving me errors
and I also did not fully understand what it was trying to do. In the end it turned out, I did not
need all these bells and whistles, as long as I was willing to add my data files (bitmaps etc.) and
some DLL-files manually later, as we will see.
Then we make our own python script called setup.py in the same folder of our Python game. It
contains only the following few lines:
115
You can change the word console into window if youre not using the console window (so
you don't use print, input() or raw_input(). In the final line, we only mention mazeman.py and
not toolsmaze.py, since this is the main module. Py2exe will read the import-statements in there
and then automatically also add toolsmaze.py, as well as Pygame and Tkinter (and os and sys
and any other modules we use)
We need to run this script outside IDLE. For this we use the following file, a so-called batch file
(extension .bat), which we call runsetup.bat (make textfile with Notepad, which you rename to
runsetup.bat ):
This batch file starts our setup.py script (change the python folder name to match your version so
c:\python27\python if you have version 2.7).
The pause command at the end ensures, we have the time to read potential error messages if it
crashes, before the console window closes again. If there are fatal errors, we need to fix those
errors, sometimes leading to tidying up your code a bit.
If it runs successfully, it will create a subfolder called dist containing your program
(mazeman.exe in our example) and a lot of other files needed by the executable. Still we also
need to add some files manually before were ready.
Next we need to add some very important DLLs, which are probably already somewhere on your
computer as any program made with Visual C++ needs them as well. Search your hard disk for
the file named: MSVCR90.dll Then in the search window with the results, hover over the files
with your mouse to see the exact version.
For Python 2.6 you need version version 9.0.21022.8. If you do not have it, download it here:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=29
Open the folder where the correct version is located (in right mouse button menu when you click
on the file) and copy (not move or cut!!!) three DLLs from this directory to your dist subfolder:
116
msvcm90.dll
msvcp90.dll
msvcr90.dll
C:\Python26\Lib\site-packages\pygame
Py2exe should have copied the relevant DLLs, but regularly misses out on a few (often the Font
ones). So from this directory we copy (again be careful not to delete or move them) all DLLs (so
sort by type and select all of type Application Extension) to your dist folder. We do the same
with the font file: freesansbold.ttf.
In short we copy these files from the pygame folder to our dist subfolder:
*.dll
*.ttf
To see whether our program needs any additional files, it may be useful to start our program
mazeman.exe with a batch files with a pause command, so we can read warnings and error
messages in the console. Lets call this runme.bat for example (in the dist folder as well) .
Create it with notepad or idle):
mazeman.exe
pause
Then run it to test it and see if you need to add any other files. Sometimes you may need other
DLLs from third party module you use. You can find these folders in your Python directory (in
C:\Python26\Lib\site-packages\), and basically do the same as we did above for
pygame.
When your .exe pygame program crashes, even though it did not when executed in IDLE
Without IDLE, there is less protection against memory leakage and lost handles. When I
experienced problems with crashing Pygame executables it was always due to one thing: the font
library. When you have created a font object, you also need to delete it before you go on with the
next text. So make sure you always delete variables created with pygame.font after youve used
them. The font object in Pygame is very sensitive, but apparently Python handles this for you
when you run it in the shell, so you will only get into trouble when you have made your
executable.
117
14.2 Making a setup program with e.g. Inno Setup
There are more fancy ways to distribute your program and create an installer, which will do these
same things for you and create an executable for installation. Just download such a program e.g.
from download.com. Some are free like NSIS or Inno Setup (last one is recommended).
With Inno Setup, you need to select the dist folder as root and add this (with all files and
subfolders). Also you need to indicate which executable is the program to start and perhaps
allows an entry in the Start menu. Inno set-up then compiles everything into one neat setup
program as a executable e.g. setupmazeman.exe. This is often quite large. Many mail programs
or mail servers will prevent sending executables, because thats the way viruses are distributed.
So to mail it, you may need to convert this one file to a compressed folder/ archive (ZIP or ARJ
extension).
118
15. Go exploring: Some pointers for applications of
Python beyond this course
15.1 Alternatives to pygame for 2D graphics
15.1.1 Tkinter canvas (included in Python)
Tkinter is primarily meant to design dialog boxes, but also has the so-called canvas object to
draw something. See an example below which demonstrates its ease of use:
from Tkinter import *
master = Tk()
w = Canvas(master, width=200, height=100)
w.pack()
w.create_line(0, 0, 200, 100)
w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
w.create_rectangle(50, 25, 150, 75, fill="blue")
mainloop()
Alternatively, even LOGO like graphics have been included in Python using the turtle module.
Not te be used for serious applications but its really a lot of fun, like a nice, spirograph-like toy
and also a very good way to teach younger people how to program!
from turtle import *
for i in range(200):
forward(i)
right(90.5)
done()
For other option to draw in 2D, see also the windows GUI section, because both PyQT and
wxPython have graphics functions included for 2D graphics. This library was discovered and
recommended by Fons de Leeuw, a student who used this to visualize acceleration data in his
paragliding footage using flight instruments. He found it to produce better images, mainly due to
the anti-aliasing which creates smoother drawing. Because of the vector format, the output
quality is also better for e.g. printing.
119
15.1.3 Using Python Console in GIMP
Not really a graphics library, but the free, open source photoshop program GIMP, has a Python
console built-in, which allows you to do batch operations in GIMP. You can find it in the pull
down menu Filters > Python FU. To get an impression of the code an example is given
below:
g = gimp.pdb
images = gimp.image_list()
my_image = images[0]
layers = my_image.layers
w = g.gimp_image_width(my_image)
h = g.gimp_image_height(my_image)
print "Image Resolution: w=%d,h=%d"%(w,h)
new_layer = g.gimp_layer_new( my_image, w, h, \
RGBA_IMAGE, "LeopardLayer", 100, NORMAL_MODE)
my_image.add_layer( new_layer )
g.gimp_context_set_pattern("Leopard")
g.gimp_edit_fill(new_layer, PATTERN_FILL)
g.gimp_layer_set_opacity(new_layer, 20)
g.gimp_layer_set_mode(new_layer, SCREEN_MODE)
120
15.2 Animated 3D graphics
Next to dominating the world of scientific computing and web development, Python is also very
large in the professional computer graphics world. Therefore there are many modules to edity
images, movies, 3D scenes and sound files.
These two lines will result in the window on the right side to be shown:
Objects can be added a simple way (see the axes below to understand the positioning):
15.2.2 Panda3D
Panda 3D is a very complete 3D graphics and game engine developed orginally and hosted by
Carnegie Mellon. This includes very advanced graphics functions. It is compatible with the
PyODE physics engine. Check out their website for some impressive demos: www.panda3d.org
and for documentation and download. Panda3D is Open Source and free for any purpose.
121
15.2.3 Open GL programming
OpenGL has been the standard for 3D graphics for a long time and is at the lowest layer of most
other 3D packages. For the Microsoft gamers: it is a sort of cross-platform DirectX. You can
then directly conrol the hardware of OpenGl compatible graphics cards. Only to be used by the
more daring, demanding and experienced programmer, it provides the possibility to call OpenGL
directly from Python with the PyOpenGL module. PyOpenGL is compatible with Pygame: so
you can use it in a pygame window (and it often is).
PyOpenGL is very fast and interoperable with a large number of external GUI libraries for
Python including wxPython, PyGTK, and Qt. It can also use the GLUT library to provide basic
windowing and user interface mechanisms (pulldown
menus).
http://www.willmcgugan.com/blog/tech/2007/6/4/opengl
-sample-code-for-pygame/
Student Jan Harms has explored this option and used it successfully to make a 3D solar system
visualization as well as a 3D asteroids game. Even though he had some prior experience with
OpenGL he still found it to be quite hard, but also very powerful.
122
15.2.3 Blender (www.blender.org)
No matter which 3D library you use, you will need to create 3D objects with complex shapes,
surfaces and textures. For this most Python programmers (and many others) use the freeware
program Blender. Blender a a very advanced, yet easy to use, 3D content creation suite. You can
import objects made in Blender in Python in OpenGL. Even without Python, Blender can make
interactive animations. Make sure to visit the website to check out the beautiful gallery. Blender
is used a lot by professionals in the Computer graphics world (for commercials, movies and
games). Also check out Youtube for some impressive Blender examples. Blender also has a
powerful game engine.
To add even more realism, you can also use the PyODE physics engine as your development
environment. It provides a physics simulation of an extremely rich physical environment. It takes
care of realistic mechanics and dynamics of your scenery including gravity, friction, inertia,
collisions, etc.. PyODE can be used for simulation, visualisation or gaming. Relatively easy to
use, but realize that the closer you get to reality with your simulation, the more complex your
123
model and your program will become: youll need to set a lot of parameters, although many
defaults are supplied. To get an impression of what it can do check put youtube videos like
ragdoll demo python ODE.
15.3.1 Tkinter
Already provided with Python, builds on Tcl/Tk library. The TkInter module is an easy way to
use the standard window dialog boxes, e.g. the File Open dialog box (named:
tkFileDialog.askopenfilename ) in the example below:
import os,sys
from Tkinter import *
import tkFileDialog
Other standard dialog boxes with their tk name which you can use, like the above example, are:
124
Even though the Python source will look the same,
the OS determines the actual look of these standard dialogboxes
Some documentation can be found in Python Reference, but more can be found in the pdf file at
http://www.pythonware.com/media/data/an-introduction-to-tkinter.pdf. It contains basic
functions to build dialog boxes with many controls as well as the handle to call most standard
windows dialogs. Easy to use but requires hand-coding and is rather basic in terms of graphics.
Still, the IDLE shell and editor you are using, were made in Tkinter. Tcl/Tk has a long-standing
record in the Unix world from times far
before Python even existed.
125
# Set up window
app = Tk()
app.title('Rekenmachine')
app.grid()
app.resizable(False,False)
# TUDelft logo
image = PhotoImage(file='tud.gif')
label2 = Label(app, image = image)
label2.grid(column=0,row=2,columnspan=8,pady=8)
app.configure(background='white')
15.3.2 PyQt
Qt from Riverbank Computing (: http://www.riverbankcomputing.co.uk/software/pyqt/intro)
provides an environment similar to Tkinter. Comes with many extras, like a QtDesigner,
allowing you to graphically draw the dialog boxes. The Spyder editor and IDE were built using
PyQt. Builds on Nokia's Qt application framework and runs on all platforms supported by Qt
including Windows, MacOS/X and Linux. As a result of using QtDesigner the code is
autogenerated and looks less nice. The programming effrot then comes down to connecting the
right functions to hooks provided by the automatically generated code.
126
15.3.4 wxPython
Can be found at http://wxpython.org/ Also one of the classics in the Python community,
wxPython is fully Open Source, cross-platform (Windows/Linux/Mac OS). I would say its
something in between Tkinter and PyQt in terms of funtionality.
To given an impression of the code, a simple Hello world example is given below. It shows a
window called Hello world and catches the Close event when the user closes the window to ask
for a verification with an OK/Cancel Messagebox.
import wx
class Frame(wx.Frame):
def __init__(self, title):
wx.Frame.__init__(self, None, title=title, size=(350,200))
self.Bind(wx.EVT_CLOSE, self.OnClose)
app = wx.App(redirect=True)
top = Frame("Hello World")
top.Show()
app.MainLoop()
15.3.5 GLUT
GLUT, which is a part of OpenGL, is the good old user interface system used by all Open GL
fans. Robust, does the job on all platforms, but not always very easy to use.
127
PyGTK is not included in python(x,y) but can be downloaded from www.pygtk.org . The Glade
program can be found at: http://glade.gnome.org/
As with all of these editor, it results in a mix of generated code (XML data in this case, read by
the PyGTK module) and e.g. Python code you edit yourself. You connect buttons or fields to
functions for which you can add the source to add functionality:
The GUI of the Open Source Photoshop program GIMP has been made with the GTK-library.
128
15.4 Interfacing with Excel sheets
As we use MS Office Excel a lot, it is sometimes useful to use their worksheet format from
within our Python programs. The easiest way is of course to generate Tab-delimited or comma-
delimited data, which can work in both ways. But there are more advanced ways to work directly
in Excel spreadsheets using two modules:
A very straightforward way to read from and write to excel files is Openpyxl, see the following
link:
http://pythonhosted.org/openpyxl/
An example of the resulting source code if you use this module from the tutorial:
wb = Workbook()
ws = wb.active
wb = load_workbook(filename = r'empty_book.xlsx')
sheet_ranges = wb['range names']
129
Pyexcelerator
Pyexcelerator is an alternative to xlrd, and xlwt. This module can be found at:
http://sourceforge.net/projects/pyexcelerator/ where you can also find docs and examples. The
zip file with which you download the moduel contains many examples for you to borrow from.
To let the computer communicate with the external world you might want connect it to several
switches, sensors or analog inputs and outputs. A popular interace board for this, is the Velleman
K8055 kit. Student Bastian Telgen has discovered how easy it is to use this with Python and used
this at the Lowland festival for Lowlabs.
Each Velleman K8055 board has 5 digital (on/off) input channels and 8 digitale output channels.
There are also two analog input channels and two analog output channels, which all have a 8-bit
resolution (so yield a value from 0-255).
A Python interface can be downloaded from the Velleman website: www.velleman.eu. See the
example below on how easy it us to use this card from Python. You install the pyk8055 module
and connect it to the USB port. You can then run a program like:
130
15.5.2 Raspberry Pi
The Raspberry Pi (http://www.raspberrypi.org/ ) is a very basic (but complete), low cost, very
small (credit card size) Linux computer which comes with Python installed and it also runs
pygame. For around 50 euros you have a complete computer with the basic accessories like
power supply, OS on SD-card, etc.. You can connect it to any screen via HDMI. It is used for
many purposes like programming/gaming console, mobile webcam, robotics, education projects,
twitter and other desktop applications. Some specifications:
131
And so does Pygame!
15.5.3 MicroPython
A relatively new initiative (from MIT) is called MicroPython. This is a special version of Python
for a microcontroller. The Micro Python board is shown below.
By simply copying the text files with your Python code from your PC onto the microboard, you
can run the programs. To get an impression of the code, some examples from the website are
given below:
Controlling LEDs:
132
Showing something on LCD screen:
Still, it can sometimes be a very useful feature, so we show a few examples here of how to use
try and except.
The first example of an a,b,c formula solver for second order polynomial could check for a
negative D by simply catching the error of a negative square root:
import math
133
print "To solve ax2 + bx + c = 0 ,"
D = b**2 - 4.*a*c
try:
x1 = (-b - math.sqrt(D)) / (2.*a)
x2 = (-b + math.sqrt(D)) / (2.*a)
print "x1 =",x1
print "x2 =",x2
except:
print "This equation has no solutions."
To make it even more advanced: it is possible to check which error was caught:
import math
D = b**2 - 4.*a*c
try:
x1 = (-b - math.sqrt(D)) / (2.*a)
x2 = (-b + math.sqrt(D)) / (2.*a)
print "x1 =",x1
print "x2 =",x2
except ZeroDivisionError:
print "this is a first order equation: a=0"
x = -c/b
print "Solution x =",x
except:
print "This equation has no solutions."
Just like other flow control statements, try statements can be nested:
try:
x1 = (-b - math.sqrt(D)) / (2.*a)
x2 = (-b + math.sqrt(D)) / (2.*a)
print "x1 =",x1
print "x2 =",x2
except ZeroDivisionError:
print "this is a first order equation: a=0"
134
try:
x= -c/b
print "Solution x =",x
except:
print "No x found."
except:
print "This equation has no solutions."
Examples of types of errors you can catch (the names speak for themselves):
When an error occurs, the name of error is always given in the shell. A complete list can also be found in
the Python (documentation provided with Python) under the header Exceptions.
135
136
Appendix A Overview of basic Python statements
print prints output to console
del a delete variable named a (can also be an element of a list: del tab[2] )
File input/output
137
Appendix B Overview of functions and special operators
i%k modulo operator, remainder of i divided by k e.g. 34%10 is 4
x**y power operator: xy for integers and floats, so 2**3 is 8 while 2.0**-1.0 is 0.5
range(stop) produces an iterable list [0,1..stop-1] so until but not incl. stop
range(start,stop) same but now starting with start (included) i.s.o. default zero
range(start,stop,step) same but now with step step instead of default 1
random.random()returns random number (float) between 0.0 and 1.0 (from module random)
random.randint(a,b) returns random integer with minimum a and maximum b (limits included)
time.clock() returns clock time as float in seconds (starts at zero the 1st time it is called)
time.time() returns time tuple with integers: [year, month, date, hour, minute, seconds,
weekday, yearday, daylightsavingtimeswitch]
138
139