Introduction to Computing at SIO: Notes for Fall class, 2012

Peter Shearer Scripps Institution of Oceanography University of California, San Diego November 30, 2012


1 Introduction 1.1 Scientific Computing at SIO . . . . . . . 1.1.1 Hardware . . . . . . . . . . . . . 1.1.2 Software . . . . . . . . . . . . . . 1.2 Why you should learn a “real” language 1.3 Learning to program . . . . . . . . . . . 1.4 FORTRAN vs. C . . . . . . . . . . . . . 1.5 Python . . . . . . . . . . . . . . . . . . 2 UNIX introduction 2.1 Getting started . . . . . . . . . . . . . . 2.2 Basic commands . . . . . . . . . . . . . 2.3 Files and editing . . . . . . . . . . . . . 2.4 Basic commands, continued . . . . . . . 2.4.1 Wildcards . . . . . . . . . . . . . 2.4.2 The .login and .cshrc files . . . . 2.5 Scripts . . . . . . . . . . . . . . . . . . . 2.6 File transfer and compression . . . . . . 2.6.1 FTP command . . . . . . . . . . 2.6.2 File compression . . . . . . . . . 2.6.3 Using the tar command . . . . . 2.6.4 Remote logins and job control . . 2.7 Miscellaneous commands . . . . . . . . . 2.7.1 Common sense . . . . . . . . . . 2.8 Advanced UNIX . . . . . . . . . . . . . 2.8.1 Some sed and awk examples . . . 2.9 Example of UNIX script to process data 2.10 Common UNIX command summary . . 1 2 2 3 4 4 5 6 9 9 11 14 15 17 17 19 21 22 23 24 25 26 29 29 31 31 34 37 37 51 52 52 53 54 55 56

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . .

3 Generic Mapping Tools 3.1 Installation of Fink, GMT other useful tools . . . . . . . . . . . . . . 4 Fortran 4.1 Fortran history . . . . . . . . . . . . . 4.2 Texts and manuals . . . . . . . . . . . 4.3 Compiling and running F90 programs 4.3.1 The first program explained . . 4.3.2 How to multiply two integers . 4.4 An important historical digression . . iii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iv 4.5

CONTENTS 4.4.1 Alternate coding options . . . . . . . . . . . . . . . . . . Making a formatted trig table using a do loop . . . . . . . . . . 4.5.1 Fortran mathematical functions . . . . . . . . . . . . . . 4.5.2 Possible integer vs. real problems . . . . . . . . . . . . . 4.5.3 More about formats . . . . . . . . . . . . . . . . . . . . Input using the keyboard . . . . . . . . . . . . . . . . . . . . . If statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.7.1 If, then, else constructs . . . . . . . . . . . . . . . . . . Greatest common factor example . . . . . . . . . . . . . . . . . User defined functions and subroutines . . . . . . . . . . . . . . 4.9.1 Subroutines . . . . . . . . . . . . . . . . . . . . . . . . . 4.9.2 Linking to subroutines during compilation . . . . . . . . Internal procedures . . . . . . . . . . . . . . . . . . . . . . . . . Extended precision . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.1 Integer sizes . . . . . . . . . . . . . . . . . . . . . . . . . Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.12.1 Checking for problems with the -fcheck=bounds option 4.12.2 More about random numbers . . . . . . . . . . . . . . . 4.12.3 Arrays as subroutine arguments . . . . . . . . . . . . . . Character strings . . . . . . . . . . . . . . . . . . . . . . . . . . I/O with files . . . . . . . . . . . . . . . . . . . . . . . . . . . . More about multi-dimensional arrays . . . . . . . . . . . . . . . 4.15.1 Arrays of strings . . . . . . . . . . . . . . . . . . . . . . A more complex example of data processing . . . . . . . . . . . Example sorting routine from Numerical Recipes . . . . . . . . Example of saving values in a subroutine . . . . . . . . . . . . . Complex numbers . . . . . . . . . . . . . . . . . . . . . . . . . Array operations in F90 . . . . . . . . . . . . . . . . . . . . . . Allocatable arrays . . . . . . . . . . . . . . . . . . . . . . . . . Structures in F90 . . . . . . . . . . . . . . . . . . . . . . . . . . Writing fast programs . . . . . . . . . . . . . . . . . . . . . . . 4.23.1 The -O option . . . . . . . . . . . . . . . . . . . . . . . Fast I/O in Fortran . . . . . . . . . . . . . . . . . . . . . . . . . 4.24.1 Ascii versus binary files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . fractals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 58 61 61 62 63 65 66 68 69 71 73 75 77 80 81 86 88 89 90 93 97 100 100 105 107 111 113 116 117 119 121 122 124 127 127 133 137 137 140 143 143 144 145 147 148 148 150 150

4.6 4.7 4.8 4.9 4.10 4.11 4.12

4.13 4.14 4.15 4.16 4.17 4.18 4.19 4.20 4.21 4.22 4.23 4.24

5 Fun programs 5.1 Tic-tac-toe . . . . . . . . . . . . . . 5.2 Fractals . . . . . . . . . . . . . . . . 5.2.1 Plotting using MatLab . . . . 5.2.2 Plotting using Python . . . . 5.2.3 Good targets and more about 6 Lisa’s Python Notes 6.1 Introducing Python . . . . . . . . 6.2 An Interactive Python session . . 6.3 A first look at NumPy . . . . . . 6.4 Variable types . . . . . . . . . . . 6.5 Data Structures . . . . . . . . . . 6.5.1 Lists . . . . . . . . . . . . 6.5.2 More about strings . . . . 6.5.3 Data structures as objects . . . . . . . . . . . . . . . .

CONTENTS 6.5.4 Tuples . . . . . . . . . . . . . . . . . . . 6.5.5 Dictionaries! . . . . . . . . . . . . . . . 6.5.6 N-dimensional arrays . . . . . . . . . . . Python Scripts . . . . . . . . . . . . . . . . . . A first look at code blocks . . . . . . . . . . . . 6.7.1 The for loop . . . . . . . . . . . . . . . 6.7.2 If and while blocks . . . . . . . . . . . . 6.7.3 Code blocks in interactive Python . . . File I/O in Python . . . . . . . . . . . . . . . . 6.8.1 Reading data in . . . . . . . . . . . . . 6.8.2 Command line switches . . . . . . . . . 6.8.3 Writing data out . . . . . . . . . . . . . Functions . . . . . . . . . . . . . . . . . . . . . 6.9.1 Line by line analysis . . . . . . . . . . . 6.9.2 Main program as function . . . . . . . . 6.9.3 Scope of variables . . . . . . . . . . . . Combining F90 code with Python . . . . . . . . 6.10.1 Brute force f2py method: . . . . . . . . 6.10.2 Signature files . . . . . . . . . . . . . . . 6.10.3 F90 Surgery . . . . . . . . . . . . . . . . 6.10.4 A few more things you need to know: . Classes . . . . . . . . . . . . . . . . . . . . . . . Matplotlib . . . . . . . . . . . . . . . . . . . . . 6.12.1 A first plot . . . . . . . . . . . . . . . . 6.12.2 Multiple figures and more customization 6.12.3 Adding text . . . . . . . . . . . . . . . . 6.12.4 Histograms . . . . . . . . . . . . . . . . 6.12.5 Pie Charts . . . . . . . . . . . . . . . . 6.12.6 Basemap . . . . . . . . . . . . . . . . . 6.12.7 Contour plots . . . . . . . . . . . . . . . Deeper into NumPy and Scipy . . . . . . . . . 6.13.1 More on slicing with arrays . . . . . . . 6.13.2 Looping through arrays . . . . . . . . . 6.13.3 Random Numbers . . . . . . . . . . . . 6.13.4 Normal Distribution . . . . . . . . . . . 6.13.5 Statistics in Python . . . . . . . . . . . Graphical User Interfaces - GUIs . . . . . . . . 6.14.1 Interacting with plots . . . . . . . . . . 6.14.2 Event Handling in matplotlib . . . . . . 3D plotting with Python . . . . . . . . . . . . . 6.15.1 Geoscience applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

v 150 151 151 154 156 158 160 162 162 162 165 166 168 169 170 172 173 174 176 178 178 179 181 181 185 186 188 191 192 193 195 197 198 198 200 200 202 207 214 220 225 233 234 235 236 236 237 239 239 240

6.6 6.7




6.11 6.12


6.14 6.15

7 Peter’s Python Notes 7.1 How to multiply two integers . . . . . . . 7.1.1 Declaring variables . . . . . . . . . 7.1.2 Alternate coding options . . . . . . 7.2 Numpy . . . . . . . . . . . . . . . . . . . . 7.3 Making a trig table using a ‘for’ statement 7.3.1 Numpy mathematical functions . . 7.3.2 Possible integer/real problems . . . 7.4 More about Python for loops . . . . . . .

. . . . . . . . . . . . . . . 7. . 8. 8. . . . . .7 7. . . . . . . . .12 7. . . .2 Using functions in separate files . . . . . . . . . .3. . . . . . 279 . . . . . . . . . . . . . . . . . . . . . . Using tuples and lists . . . . . . . .vi 7. . . . . . . . . . .6 7. . . . . . . .2 Example with equations . . I/O with files . . . . . . . .1 A simple example . . . . . . . .1 PSPLOT Fortran subroutines . . . . . . . . . . . . . . . . .14 7. .1 More about formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9. . . . . . . . . . . . . . 8. . . . . .13 7. . . . . . . . . . . 8. . . . . . .10 7. .5 7. Plotting with Python . . . . . . . . . . . . . . . . . . . . . 8. . . . . . . . . . . . . . . . . .14.9. . . . . . . . . . . . . . . . . . . . . .1 Font size . Character strings . . . . . . . . . . . . . . . . .9 7. . . . . . . . . . . . . . . .4. .1 Python keywords . . . . . . . . . . . . . . . . . . . User defined functions . . . . . . . . . . . . else constructs . . . . . . . . . . . . . . . . . . 9 Postscript plotting 275 9. 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . If. . . . . elif. . . . . . . . . . . . . . . . .11 7. . . . .3. . . . . . . . . . . .2 Font attributes . . 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Example of computing least-squares line . . . . . . . . . . . . . . . 7. . . . . . . . .3 Line spacing . . . . . . .3 Changing the default parameters 8. . . . . .5 Want to know more? . . . . . . . . . . CONTENTS . . .8 7. . . . . . . . . . . . . . . . Arrays . .4 Including graphics . . . . . . . . . . . . . . . . . . . . . . . . . . Greatest common factor example . .3. . . . . . . . . Input using keyboard . If statements . . . . . . 241 241 242 245 246 247 249 250 251 253 254 257 257 260 265 266 267 269 269 269 270 271 273 8 LaTeX 8. . . . . . . . . . . . . . . . . . . .

The perspective is largely that of the Geoscience program at SIO.Chapter 1 Introduction This course is intended to help incoming students get up to speed on the various computing tools that will help them with their research and some of the homework assignments for other classes. All students should have access to a Mac and an account on the IGPP Mac network. but we hope that the course is general enough to be useful for other students as well. you probably don’t need to take this class (although you may find Python and some of the other material and the geoscience examples of interest). If you are using your own Mac. Please let me know if you do not already have an account.1. you will need to install the following: • Fink • gfortran • GMT (from fink) • XCode • Python • TexShop • TextWrangler There are download instructions on the class website. 1 . The planned class schedule is listed in Table 1. If you are already experienced in C or Fortran. GMT and other topics. We will spend a few classes on UNIX. but the bulk of the class will be an introduction to the Fortran90 and Python programming languages.

Sun.sladen..2 CHAPTER 1. these boundaries are now blurred because many PCs run Linex1 (an open source form of UNIX) and Apple has adopted UNIX for their operating system (starting with OS X). etc. UNIX Workstations (e.1: Class Schedule Wednesday Friday 09/28 – 10/03 – UNIX 10/05 – 10/10 – F90 10/12 – 10/17 – F90 10/19 – 10/24 – F90 10/26 – 10/31 – no class 11/02 – 11/07 – F90 11/09 – 11/14 – F90 11/16 – 11/21 – F90 11/23 – 11/28 – Python 11/30 – 12/05 – AGU week 12/07 – Monday 10/01 10/08 10/15 10/22 10/29 11/05 11/12 11/19 11/26 12/03 12/10 – – – – – – – – – – – UNIX GMT F90 F90 F90 F90 UC holiday F90 Python AGU week TTT playoff Intro UNIX F90 F90 F90 no class F90 F90 no class (Thanksgiving) Python AGU week 1. Macs) (a) (b) (c) (d) Word Processing Graphics Presentations (talks and posters) (some programming) However. 1 Linex is pronounced similar to “linen” (see http://www.1. INTRODUCTION Table 1.1 1. PCs (Windows machines. Silicon Graphics. computer hardware used at SIO was of two main types: 1. This permits these machines to be used for both serious scientific computations and word processing and more traditional PC activities.g.) (a) (b) (c) (d) Scientific programming Data storage General research (some word . HP.1 Scientific Computing at SIO Hardware Before 2004 or so. graphics) 2.paul.

Lisa Tauxe likes it) (f) MatLab (widely used but commercial product. preparing posters) (e) PhotoShop (f) Mathematica (g) etc. but our aim is to replace it with Python) (g) HTML for web sites (most people now don’t program in raw html. For example. Commercial Programs (a) MS Word for word processing (b) MS Powerpoint or Apple Keynote for presentations (c) *TeX/LaTex (no single vendor. 1.1. most geophysics departments had networks of Sun workstations. Programming (a) (b) (c) (d) *FORTRAN (most IGPP faculty use this.1. 1. best option for papers & thesis) (d) Adobe Illustrator (for graphics. Community Programs (a) (b) (c) (d) Bob Parker programs (plotxy. but often not fast enough for serious computing) (e) *Python (lots of buzz. SCIENTIFIC COMPUTING AT SIO 3 Ten to twenty years ago. such as DreamWeaver) 2. has portability advantages. contour) *GMT for mapping (UNIX based) SAC for seismic analysis etc. previously presented in this class. At IGPP we now use Macs for everything except for certain specialized or high-performance computers maintained by individual PIs. David Sandwell’s group maintains some Suns because some of their processing software runs only on that platform.2 Software Here is a list of programming languages and software used at IGPP (Items with * will be discussed in this class). different implementations available. large library of existing code) C (more widely taught and used by computer scientists) C++ (extended version of C) Java (used a lot for web programming. but use web designer software. color. files are compatible. Today these have largely been replaced with networks of cheap PCs running Linux or with Apple machines. .1.

INTRODUCTION 1. There is simply too much material and it seems overwhelming. Matlab is a commercial product that does not have the long-term stability of other languages. you will likely be handicapped in your research at some point if you don’t learn FORTRAN or C. Your research may involve processing data using a FORTRAN or C program. you will be in a more competitive position to get a job after you graduate if you have real programming experience. begin by writing the simplest possible program and get it to work. Often this means that a simple FORTRAN or C program can be written that will perform a task far more cleanly and efficiently than Matlab. including large libraries of existing code that are freely shared among researchers.3 Learning to program Learning to program can be intimidating. This will come with experience. you may drive your colleagues crazy by continually requesting that the original authors of the program make changes to accommodate your wishes. While it is possible to get by for most class assignments by using Matlab. Part of learning to write more complicated programs is to figure out ways to logically divide the problem into smaller pieces. . You may resort to elaborate kludges to get the program to do what you want. the two main scientific programming languages in use today. You only really learn when you get your own programs to work. Worse.2 Why you should learn a “real” language Many students arrive at SIO without much experience in FORTRAN or C. In addition. DO NOT DO THIS! Instead. even if a complicated Matlab script can be kludged together to do the same thing. when a simple modification to the code would be much easier.4 CHAPTER 1. The worst thing to do is to buy a book on the language and try to read it. Then read just enough to add a single additional feature to your program and get that to work. particularly if you have not previous experience. you will not be able to modify it to do anything other than what it can already do. Finally. This will make it difficult to do anything original in your research. If you do not understand the program. Matlab is very convenient for quick results but has limited flexibility. There is no need to learn everything that the language will do all at once. so the idea is to write lots of little programs that do various things and only gradually add in new concepts. 1.

FORTRAN VS. I decided to bite the bullet and learn enough C to teach this class. (Having said that. C 5 The final project in this class will be to write a program that plays tic-tac-toe.4 FORTRAN vs.1. I probably only know about 20 UNIX commands. But we will divide it into smaller parts for separate assignments over the weeks. After talking to some people who know both FORTRAN and C. Here is my summary of the advantages and disadvantages of either choice: • FORTRAN – Advantages ∗ ∗ ∗ ∗ Large amount of existing code Preferred language of most SIO faculty (most faculty are old) Complex numbers are built in Choice of single or double precision math functions – Disadvantages ∗ Column sensitive format in older versions ∗ Dead language in computer science departments • C – Advantages ∗ Large amount of existing code . C Some years ago when I (Peter) first started teaching programming in this class. and only put all the pieces together for the final program at the end. Like most SIO faculty of my generation or older. Few of us except professional programmers learn them all. This was motivated in part by the fact that C is now one of the standard languages taught in computer science departments. it wouldn’t hurt for me to learn more and I’m going to look over some of Duncan Agnew’s notes from the 2009 class to find some new tricks) 1. however.4. This is a daunting task if one tries to write it all at once. I had to decide whether to teach C or Fortran. But it’s been enough for me to get by and to do the science that I want to do. Also. A real computer nerd would find pathetic some of the ways that I do things. But we do not need to write professional programs—we only need to learn to write practical programs that serve our own needs. For example. be aware the most languages have far more features than you actually need. I was experienced in FORTRAN but had little exposure to C. many of our incoming students have C experience but few have Fortran experience.

6 ∗ ∗ ∗ ∗ CHAPTER 1. However.. Python was started in 1989 by Guido van Rossum from the Netherlands.g.. I concluded that C is not a very user friendly language for those without programming experience. both languages are equally fast.. The name Python comes from the old Monty Python TV series and Monty Python references are common in example code. some younger faculty Free format. It is very flexible and combines many of the advantages of traditional programming languages (e. there are fixes for both languages that permit them to assume the advantages of the other language. For this reason. not column sensitive More efficient I/O Easier to use pointers – Disadvantages ∗ Less user-friendly than FORTRAN (I think so. UNIX shell scripts). So I switched to Fortran90.g. we are introducing it after the F90 part of the class. For example. but others may debate this) ∗ Fewer built in math functions (but easy to fix) ∗ No standard complex numbers (but easy to fix) ∗ Easier to use pointers With reasonable compilers. C and Fortran) with object-oriented languages (e. An interesting feature is that indentation is required in the block delimiters used in if statements and do/for loops. Indeed it has so many features that it can be daunting for beginning programmers. The idea is to enforce good programming style. INTRODUCTION Preferred language of incoming students. you can use pointers in FORTRAN90 and you can define an add-on set of functions to do complex arithmetic in C.g. that combines the advantages of Fortran and C into a more user-friendly package. Python is free and runs on almost all computers. 1. an improved version of Fortran77. Java) and with scripting languages (e. . after learning enough C to teach the class. Ultimately. who has been been given the name Benevolent Dictator for Life (BDFL) by the Python community. It also has more integrated graphics options in its standard library than C or Fortran (which require use of non-standard plotting packages).5 Python Python is an up-and-coming new programming language that is gaining popularity.

However. Munk Lab. This provides a way to combine the speed of Fortran with the graphical capabilities of it is possible to call C or Fortran subroutines from within Python and we will learn how to do this.ucsd. Peter . x42260. PYTHON 7 Python is a dynamic programming language. which is not compiled before it is run (C and Fortran programs are first compiled). which can be a disadvantage for serious data processing and number crunching.5. pshearer@ucsd.1. Dynamic languages generally run much slower than compiled languages. Other examples of dynamic languages include BASIC and Matlab. IGPP Class web site: http://mahi.


which in normally in Applications/Utilities. Some of us still work some on the Suns.Chapter 2 UNIX introduction You will very likely do your scientific computing in a UNIX environment.1 Getting started To use UNIX on the Macs. and then Terminal to create the UNIX text window that you will use. (X11 also has a text window but its scroll bar is not as nice as the one in the Terminal application). In many cases you will need to have X11 (called XQuartz in the newest Mac OS) also running in order to display graphics. you will need to bring up a regular text-based window rather than the standard Mac windows. X11 (XQuartz) can be downloaded for free from Apple if you do not already have it installed on your machine. that will run on most PCs. However it is possible that your Mac is running something called “bash”. There is also a free version of UNIX. which many people think is better than csh. called LINUX (pronounced lynn exs). A note about UNIX shells: UNIX comes in different flavors. etc. which use Solaris (also UNIX). We will assume in these notes that you are entering UNIX commands within such a window. UNIX is by far the most common operating system for the workstations that dominate today’s scientific computing. which is an Apple version of UNIX. There are many different versions of UNIX. This can be done by running the “Terminal” program. The default C-shells for Macs changed from tcsh to bash 9 . 2. We are going to assume that you are running what is called the C shell (“csh” or “tcsh”). Thus I recommend that you always run X11 first. In this class we will be using OS X on the Macs.

Do not choose a common word that can easily be guessed by outside hackers. you should make sure your Mac is running tcsh (if you think bash is better. I have learned only enough to get by and could benefit from learning run the Terminal program and select “Preferences” from the pull-down menu under “Terminal” at the top of the screen. UNIX INTRODUCTION between Jaguar and Panther (OS X 10. To change your password on more traditional UNIX machines.3). check out: http://www. although no damage has been done.macdevcenter. or if you later want to change your password. So there are a lot of security features. than you probably are more of a UNIX expert than me and don’t need to be taking this part of the course anyway!). type printenv within your UNIX shell and it will tell you lots of interesting things. The NetOps people here are very concerned about security issues and IGPP computers have been “attacked” several times already. However because these notes are based on csh. If not. probably there are several of you here that know much more than I do. use the command: passwd You should choose a password with numbers or special characters as well as letters.10 CHAPTER 2. . on the Macs. including what your SHELL is. The UNIX operating system was originally designed to run on mainframe computers where security was a big issue. You will be assigned a login name and password.html I am by no means an expert on UNIX. just look at the top of the Terminal window and it will say. To set things up so that you are always in tcsh. Alternatively.2 to 10. You don’t want users to be able to delete other user’s files or do other nasty things. This normally happens automatically upon your first login. The first of these is the login and the password. Then just close the “Terminal Preferences” box and restart Terminal. To find out what you are running. To learn more about UNIX shells on the Macs. Select “Execute this command (specify complete path)” and enter /bin/tcsh in the little box. The first thing that you should do after you login is change your password so that only you know what it is. go to System Preferences and click on Accounts. So I’m just going to outline the basics here for the benefit of those students who have not been exposed much to UNIX.

” In my case. For example.2. You will find it convenient to put this in your . this looks like: shearer@katmai 5> because my laptop (my primary computer) is called katmai. You could type “man pwd” and you would get a description of the pwd command.cshrc file (see below). The notes that follow were written when I used a now defunct Sun computer named rock and so have rock as the standard prompt. m your machine name.2. BASIC COMMANDS 11 Do not write your password down (like on a note next to your computer!) where it can be found. 2. enter set prompt = "%n@%m %h> " where n will give your username. Of course all this makes it very hard to remember your password if you don’t use the computer very often.. You can easily give them access to read your files without giving them the password. Let us assume that you have successfully logged on. this will give: rock> pwd /net/rock/shearer This shows that I am located in my home directory (named shearer) on rock.2 Basic commands To find out where you are. and h the line number.. You can list the contents of your current directory with the “ls” command: rock> ls (I’m not showing you the output because it’s too messy in my case!) UNIX has an online set of manuals that may be accessed with the “man” command. If you want to have one like mine. One annoying aspect . Do not tell other students your password. suppose you forgot what “pwd” does. In my case. enter “pwd” which stands for “Print Working Directory. UNIX uses a directory tree structure. similar to the “folders” used by PCs but without all the fancy icons. Your will now be located in your home directory. Your default prompt is likely to be different from this. Normally you will have a cursor prompt that tells you what machine you are running on..

you will then get the next page of output. one solution is to use the name “junk” as a temporary place to store output. For example. enter “b” at the colon prompt. If you enter the space bar. you only ever have one “scratch” file in your directory at one time. UNIX INTRODUCTION of standard UNIX is that the man command output uses a form of the VI editor rather than the normal window output. If you already have a file named junk. But you can’t scroll backwards using the window scroll arrows. This file will not appear if you just enter “ls”.pwd.cshrc” (see below). If you want to find out how big they are or when they were last modified. If you don’t want to worry about deleting them. hit the ‘q’ key (for quit) at any point. you will likely see how kinds of weird control characters that are used to format the screen output. then use “ls -l” where the “l” stands for the long output option. use the ‘cat’ command: cat man.pwd using a text editor.pwd The output will now be directed into a file named “man.whatever” if you do this a lot. Note that if you try to look at man. In your home directory. The advantage in this case is that you can use the scroll bar. To make it appear. . When you get to the final page. This way. enter: man pwd > man. you will see END at the bottom. if you access to the web. To look at man. you risk cluttering up your directory with lots of files named “man. is to simply Google ‘unix man pwd’ to bring up the man pages. To go backwards. which permits scrolling up and down in the window. “ls” simply lists the file names in your directory. you will have a very important file called “.pwd” rather than to the screen. Of course. If you find this too annoying to deal with. To leave the man pages and return to the normal terminal. nicely formatted! There usually are options to UNIX commands that can make them more useful for what you want. etc. it will just overwrite the old file. you can always save the man pages to another file. enter “ls -a” where the “a” stands for the “all file” option.12 CHAPTER 2. When you enter “man pwd” you will get a page of output on the screen with a colon (:) at the bottom. To do this.pwd The ‘cat’ command prints a text file to the screen. Another approach.

BASIC COMMANDS To change your directory.. one can go to one’s home directory by entering cd You can also go directly to subdirectories by entering: cd ~/dir1/dir2 This will get you to directory dir2. Or you can give the full path name for dirname. cd /net/rock/shearer will get me to my home directory no matter where I am on the system. in front of the directory names.2. Some people put . use: cd dirname 13 This will move you to the directory dirname. You can go back up and then down again into a different directory by entering: cd ../dir2 To create a new directory. Alternatively. which has the advantage of grouping them together when “ls” is entered. use the “make directory” command: mkdir dir1 It is often convenient to use a different naming convention for your directories in order to distinguish them from your files. Naturally this does the same thing as cd cd dir1 cd dir2 You can go back up one level by entering cd .e. since UNIX lists things in alphabetical .dir after their directories. located in dir1 in your home directory. This directory name must be in your current directory.2. For awhile I put d. i.

This makes them more visible. but has the disadvantage of slowing down typing their names (yes. I have been using all capital letters for the directory names. Be sure to set the format (under Preferences) to Plain text and not Rich text. One standard UNIX editor is called vi and is still used by some of the old time programmers at IGPP who will insist that it is remains the best editor. Editors on the Mac include: • TextEdit – You can find this in the applications folder. You can do things. • nedit – This is supposed to run on all platforms and has more features than textedit.3 Files and editing Files can be simple ascii (text) files or they can be binary files. If you know vi or decide that you want to learn it—more power to you. vi is not mouse or window friendly and is not favored by most students today. often the executable versions of computer programs. which will put in control characters that will screw things up. . I like this so much that I have set this up as my default “ls” command by putting an alias into my . Most recently. you can use the “ls -F” command: ls -F This will add a / suffix to directory names and a * prefix to excutable file names. that most editors can’t do. If you don’t want to use special names for directories or if you find yourself in somebody else’s directory where they don’t do this. You will not lose any points around here. If you know all of its tricks it can be an extremely powerful editor. like cut and paste columns of numbers. However. UNIX INTRODUCTION order. UNIX is case sensitive!). It also has the advantage of running on any terminal so if you log in from home you can still edit files. It can do just about anything but may be somewhat harder to learn at first than simpler editors.14 CHAPTER 2. I have forgotten most of the vi that I once knew (I used it to do my thesis back in the late Cretaceous).cshrc file (more about this later). 2. • emacs – this is a very powerful editor that is used by computing professionals.

the computer will ask you first if you want to overwrite this file.type. BASIC for a Postscript file figure1. use the ‘mv’ (move) command: mv filename1 filename2 If filename2 already exists. WARNING: Do not use the dash character (-) in file names. When used with wildcards (see below) this will make it easy to list all files of a particular type.c for C program source code testprog. this may cause all kinds of problems for you.f for Fortran77 program source code testprog. CONTINUED • Xcode – special editor designed for editing programming code 15 You can use any of these editors to create a new file or edit an existing file. Unix file names are case sensitive.4 Basic commands.gif for a GIF file You may wish to create your own naming convention to keep track of your files. or to separate the words. the type of file is often indicated by . By convention.m for a MatLab script testprog. mv can also be used to move files between directories: . use the “-i” option: mv -i filename1 filename2 Now if filename2 already exists. NEVER USE BLANKS IN FILE OR DIRECTORY NAMES!!! (I know this is common on Macs and PCs but you will eventually have big problems reading these files with your programs) 2. continued If you want to remove a file use the ‘rm’ command: rm filename If you want to change the name of a file.f90 for Fortran90 source code testprog. for example: testprog.2. To guard against this.o for an object file figure1. Use .4. this will have the possibly undesired consequent of deleting the original filename2.

UNIX INTRODUCTION will move filename into directory dirname (assuming dirname already exists!) where it will have the same name. use the “rmdir” command: rmdir dirname The directory must first be empty for this to work. Note that this does the same thing as mv filename dirname/filename For convenience. The copy command works in a similar way: cp filename1 filename2 makes a copy of filename1 called filename2.16 mv filename dirname CHAPTER 2. Many people so prefer the -i option for mv and cp that they make it the default option by defining an alias in their .cshrc file (see below) so that mv and cp become “mv -i” and “cp -i”. To remove a directory. To recursively remove a directory and its contents use: rm -r dirname Use this with extreme caution to avoid accidentally deleting more than you intended! . You can copy files to different directories in the same way as the mv command works. I recommend that you do this—it is likely to save you some grief in the future. then the name of filename will be changed to dirname. cp -i filename1 filename2 will first ask if you really want to do this if filename2 already exists. you can leave off the /filename if the file is to keep the same name. if dirname does not exist as a directory. A note of caution: In this shortened version.

For example. For example. however.2.login and .f You could move all of these programs in a subdirectory called source. that you are careless when you type this and enter instead: rm * % This will delete everything in your current directory! So always look carefully at what you have typed before hitting the return key when you are deleting files using wildcards.4.cshrc files In your home directory.login and . Simply enter: ls *.1 Wildcards UNIX commands become much more powerful when they are used with the wildcard character * which can take on any ascii string.f the suffix used to identify Fortran source code. you can have a files called . but you can modify them to do what you want.f source.4. CONTINUED 17 2. For example.cshrc file for the mv and cp commands so that you don’t accidentally overwrite files: . suppose you wanted to delete all files in your current directory that end in %. enter: rm *% Suppose. You may have default .dir by entering: mv *. 2. be very careful when using * with the rm command. BASIC COMMANDS.dir You might have a bunch of plot files called mypost1.login and .cshrc that are executed whenever you login. you can put aliases in your . etc.cshrc files set up by the NetOps people when you first logon.2 The . which some text editors use to store the original version of edited files. suppose you wanted to list all files ending with . To do this. mypost2. You could delete all of these at once by entering: rm mypost* For obvious reasons.4. These files are used to define and customize your environment.

i. This lists all the directories that the computer should look in when you try to run a program.e. if you have a program called compspec.) This has the advantage that you can run programs in the current directory simply by typing their name.g.18 alias cp ’cp -i’ alias mv ’mv -i’ CHAPTER 2. you must type ‘. However. This means that to execute compspec within the current directory. ls). if you type “matlab” the computer needs to know where to look to find the matlab program. For example.login file). NetOps has now convinced me that this is a security risk because bad people could put malevolent programs into your directories./compspec’ on the command line (which really is not that much more work). with the same name as common UNIX commands (e.cshrc file (or your . But you will have to do this separately for each window that you have open..cshrc files if you have trouble with yours. I recommended that students include the current directory in their path. then you don’t have the right directories listed in your . You can always look at other people’s . If you get a “Command not found” message. Alternatively you can enter: source . which would be executed when you innocently typed them.. UNIX INTRODUCTION One of the most important things in the . they won’t take place until your next login. set path=($path .cshrc to make the changes immediately. i. .cshrc file under “set path” Here are example set path commands: set set set set set set set set path=($path path=($path path=($path path=($path path=($path path=($path path=($path path=($path /usr/X11R6/bin ) /sw/bin ) /sw/sbin ) /sw/igpp/bin ) /Applications ) /Applications/Utilities ) /Applications/MATLAB6p5p1/bin) /Developer/Applications ) In the past.cshrc file is the “set path” command. If you make any changes to your .e. you can run it by typing ‘compspec’ on the command line..

ps nplot = 415 shearer@katmai 17> After running this program. for M0 scale) 0.mapfocal’ that looks like this: . they seem to work ..08 !circle radius for beach balls (neg for mom scale. This is tedious if you have to type in everything again. line thickness for conts 0./mapfocal << MAPFOCAL globalcmtmap.08 looks nice) 1 !1=complete plot or 2=outline for test MAPFOCAL This is just an ascii file that you write with your favorite text editor. For example. Often people will use ‘!’ instead of ‘MAPFOCAL’ in scripts like this. suppose you have a program called mapfocal that asks you a bunch of questions like this: shearer@katmai 16> .2. 0./mapfocal reading cmt file. This is an easy way to keep track of the input and output parameters and to make changes without having to enter everything in again.93 1 !fill level..5 Scripts One of the most powerful ways to use UNIX is to write scripts to run your programs. Instead you can write a script to run the program called ‘do.93 1 Enter line thickness for plate boundaries 5 Enter line thickness for beachballs 1 Enter minimum magnitude 0 Enter circle radius for beach balls (neg. nev = 24584 Enter output file name globalcmtmap. line thickness for continents 5 !line thickness for plate boundaries 1 !line thickness for beach balls 0 !mininum magnitude Enter fill level. you decide that you would like to change the continent line thickness to 2.08 (1) complete plot or (2) outline for test 1 Creating psplot postscript file : globalcmtmap. SCRIPTS 19 2.

mapfocal* The ‘-rw-r–r–’ shows what the permissions are for the file.mapfocal -rw-r--r-1 shearer 669 421 Sep 30 09:20 do.mapfocal You may get a message which says: do. Columns 2-4 (rw-) are your permissions as owner of the file. use the ‘chmod’ command: chmod 755 do.g. UNIX INTRODUCTION in the same way.20 CHAPTER 2.mapfocal For more details see the chmod manual. set chmod 700 do.. as long as they are not allowed to make changes. If you don’t want anyone else to be able to see your file. !min. the w means write permission and x means execute permission. To see what the permissions are. To run the script. This is probably the most common set of permissions you will want to set. . use the ‘ls -l’ command: shearer@katmai 18> ls -l do. Columns 5-7 and 8-10 give the permissions for your group and all others. The r means read permission. (Can anyone tell me if one convention has any advantages over the other?) The comments following the numbered input (e.max quake magnitude) are convenient if the program that you are running is robust enough to ignore additional characters on line that follow the numbers that are actually input into the program.mapfocal This will give you rwx permission of file do.mapquake and will give everyone else rx permission but not w permission. simply enter: ./do. respectively. In this case our problem is that we have ‘rw-’ instead of ‘rwx’ To fix this.mapfocal: Permission denied This means that you don’t have execute permission on this file. assuming you are OK with others looking at your code.

1 1 ! !fill level. Notice that in this case I have added helpful comments to the numerical input lines. An old fashioned method of file transfer is the ftp (file transfer protocol) in this example) because it will consider them part of the name./mapfocal << ! globalcmtmap1.2. however. 0.93 1 5 1 0 0. line thickness for continents !line thickness for plate boundaries !line thickness for beach balls !mininum magnitude !circle radius for beach balls (neg for mom scale. add comments to the character inputs (e.g. There are various ways to do this. you can make two different plots from the same script. or by directly mounting the disk of the other computer. 0. You usually cannot.08 looks nice) !1=complete plot or 2=outline for test In this case.93 2 5 1 0 1. FILE TRANSFER AND COMPRESSION 21 The do. which is still used quite a bit./mapfocal << ! globalcmtmap2. . Today often files can simply be accessed via the web through a web browser.08 1 ! .ps 0. 2. line thickness for continents !line thickness for plate boundaries !line thickness for beach balls !mininum magnitude !circle radius for beach balls (neg for mom scale. I’m not so sure about C).mapfocal script will run the mapfocal program and enter all of the required inputs. Now it’s easy to keep track of the inputs and to make changes without having to re-enter everything. You can do this with most programs and it will not affect the input (at least for FORTRAN.6.6 File transfer and compression You often will want to get files from another computer. You can also put scripts together to run the program many times: .. 0.08 looks nice) !1=complete plot or 2=outline for test !fill level.

You simply enter: ftp othercomputer where ‘othercomputer’ is the name (or IP address) of the other computer. you will get a ftp prompt. Of course. UNIX INTRODUCTION 2.6. you may want to use the secure copy command: scp filename *. including ascii./TRANSFER will copy filename and all files ending with .ucsd. use the command ‘mget *’ and you will be prompted for each file name. you should enter type binary at the FTP prompt before getting the files. you can turn off the interactive mode by entering ftp -i othercomputer when you first invoke ftp.ucsd. If you have just a few files to (after first prompting .ps shearer@rock. If you don’t want to be prompted. Finally use ‘get’ to bring the desired file to your own computer and then ‘quit’ to exit ftp. If the remote computer objects to regular ftp for security reasons. Once within ftp. If you are getting binary files (rather than simple text files). When you are asked to login. Because ‘type binary’ will work with all types of files.22 CHAPTER 2. just enter ‘anonymous’ and then your e-mail address as a password. you might try the ‘sftp’ which is the secure ftp command. For many public sites and data centers this is done with anonymous from the current directory to the TRANSFER directory in shearer’s account on rock. The default for the Suns is ‘type ascii’ which does not work with binary files. if you have login permission on the other computer then you can ftp to the machine even if it is not set up for anonymous ftp. it is a good practice to always enter ‘type binary’ as soon as you enter If you want to get all of the files in the directory. You then can use the ‘cd’ command to get to the directory that you want and ‘ls’ to see the file names on the remote computer.1 FTP command One classic method of UNIX file transfer is the ftp command.

/TRANSFER Note that one can also copy files from the remote computer to the current directory..e. i.ucsd.2 File compression Often the files that you retrieve will be compressed.e. To get back to the original file.6. use uncompress: uncompress filename You can compress a whole bunch of files by using wildcards: compress *.edu:/net/moray2/scratch/dirname dirname\_local In this case the remote directory was on the /net/moray2 disk. scp -r shearer@rock.gz with the reverse operation: . This is useful to save disk space when you will not be using the file for awhile. scp -r dirname shearer@rock. If you want to copy a directory. you need to use the -r (recursive) option. An alternative compression method (not standard UNIX but usually available) is invoked with the gzip command: gzip filename This changes the name to filename. 2. FILE TRANSFER AND COMPRESSION 23 for the password).ps will compress all of your Postscript suffix convention for these’ as you would Files are compressed using the UNIX ‘compress’ command: compress filename This will change the name to filename. assuming you use the .6. notice how we specified the complete path name. i.Z which tells you that it is compressed. These can be uncompressed with ‘uncompress *.

/archive. I often do this when I want to get some disk space but am too nervous to delete the files and too lazy to write them to a backup tape. 2. onto tape. If you are within the directory containing the files that you wish to save. The arguments are as follows: -c -v -f .24 gunzip filename CHAPTER 2.) in . For even more efficiency you may wish to compress the tar file first. etc. You may find it useful to use compression yourself by compressing files that you do not use very often in order to save space. The tar command was originally written largely to write and retrieve backups./ to put in next level up) tar every file in current directory Alternatively you can save the entire directory and its contents from the level above the directory: tar -cvf programs. etc. The files can be retrieved as follows: tar -xvf archive.Z files (but the uncompress command will not decompress ./archive. then enter: tar -cvf .tar This will put all of the files in the archive into the current directory.6.tar . UNIX INTRODUCTION The gunzip command will also decompress .. ... in which case the file name (e.tar programs./archive.tar.gz files).3 Using the tar command Often you may want to save or retrieve an entire directory of files. This is most easily done using the ‘tar’ command.. Note: On Macs. programs. most compressed file formats can be uncompressed by simply double-clicking on them.tar .dir The tar file can then be FTPed to another machine. create tar archive verify by printing file names to screen output file name will follow name for tar file (.g..

e. as they still have a few old tape readers. You still may be unpopular.bigjob is the script that runs your program. The “nice” command lowers the priority of your job so that it will not interfere with others using the machine. have more memory.bigjob where do. nice +15 do. As a word of caution. it you use a lot of memory on the machine. 2.4 Remote logins and job control Often you will want to run on a different machine than the one that you are sitting at. you can specify a number. To find out what jobs are running on your machine. To do this enter: ssh machinename and you can login and run remotely on this machine. be connected to a tape drive.g. Today hardly anyone uses tape drives because large capacity hard drives have gotten so cheap. most people don’t like to have other people run jobs on their ‘personal’ machines (the ones in their offices) without permission.bigjob will run do. you might check with NetOps to see if they can read it. Niceness levels range from 1 (highest) to 19 (lowest). The Exabyte and DAT tape drives we used to have in the barnyard have been retired. Of course this will slow the machine down for anyone else using it so use some courtesy in doing this. One way to do this is to start your job with the ‘nice’ command: nice do. To set the niceness to a specific value. however. FILE TRANSFER AND COMPRESSION 25 the above examples is replaced with the name for the tape device.6.6. even if the jobs are set to run at large niceness values..bigjob at niceness 15. etc. The default for the nice command is niceness 4 or 10 (depending upon which UNIX shell you are running). If your advisor hands you an old data tape.2. The other machine may be faster. you can use the ‘top’ command to list the most active jobs: top .

2. together will the username. e.). enter history for history and it will list your last 30 commands. u to see only one user. enter ! followed by line number in the ‘h’ list or simply the first few letters of the command. You can stop (kill) jobs from within the top program. The Process ID (PID) is listed. rock> renice +15 1132 where 1132 is the PID number (get from top program).. You can renice more than once. Want to see how many lines and words are in a text file? Use the word count (‘wc’) command: . but only to raise the niceness level— you can never lower the niceless level once it is set. the niceness.g. To repeat the very last command. or at the command line using the “kill” command (see below). UNIX INTRODUCTION This will take over your window and update the results continuously until you enter q for quit. if you know the job number you can change the niceness at the command level. top is interactive and you can input various commands (? for help. To repeat a past command. the faction of the CPU being used and other useful information. To see them. If you did not originally use nice when you started a job you can ‘renice’ the job from within top by entering ‘r’ Alternatively. enter !! Want to see what the beginning or end of a file looks like? Use the head or tail command: head filename tail filename ---lists the first 10 lines of the file ---lists the last 10 lines of the file To see a file one page at a time. use the ‘more’ command: more filename and then hit the space bar to advance one page at a time.7 Miscellaneous commands Unix keeps track of your previous commands.26 CHAPTER 2. etc.

most computers now have built in search programs (e. -name ’map*’ -print This will find all files that begin with ‘map’ and print them on your screen. The following options are used in this example: +4 -n -b -r skip first 4 fields (leave out to use beginning of line) numerical order (default is alphabetical order) ignore leading blanks reverse order (leave out for standard order) NOTE: The +4 option no longer seems to work. -name filename -print This will look in the current directory (that’s what the . i. Instead you set the field number (normally the column number) using the -k option. MISCELLANEOUS COMMANDS wc filename 27 This will list the number of lines. What if you only know some of the characters of the file? You can use a wildcard: find .2.7.e. is for) and below for the file named ‘filename’ and then print where it is. Mac Spotlight) to locate files. Example: sort +4 -n -b -r file1 -o file2 This sorts file1 and outputs the results to file2. sort -k 5 -n -b -r file1 -o file2 . which may be more useful in many cases.. Of course. in which case it will run faster to use the -l option for line: wc -l filename Lose track of where a file is? You can use the ‘find’ command: find . One of these is the ‘sort’ command to sort files in alphabetical or numerical order. Unix has many powerful utility programs. Note that you MUST enclose ’map*’ in apostrophes for this to work. Often I just want to know the number of lines. and bytes in the file.g. words.

UNIX INTRODUCTION should do the same thing as +4. Use the -b option for the British spelling if you are submitting a paper to Nature. Just go to the disk that you are interested in and retry ‘df’ if it does not appear the first which is an abbreviation for the old ghostview program. This command is a useful feature if you use regular unix mail and create your outgoing messages with a text editor. (NOTE: spell does not seem to work on the Macs!) To reformat a text file to a uniform maximum line length of 72 characters.e.. It is a good idea to go through your directories once a month or so to delete unnecessary files and/or compress large files that you don’t use very often. To preview a postscript file on the screen use: gv filename. . To find out how much disk space is available use df (disk free): df This will not list all the disks on the system unless they have been mounted. Line feeds within a paragraph are removed and added as necessary to make the lines of approximately equal length. the best command is du -ks * This will list the disk usage of each of your subdirectories. To check for misspelled words in a file. It is helpful when you want to change a line in the middle of a paragraph because you don’t have to redo all the following lines in order to make things look nice. To see how much space you are using. i. use: fmt file1 > file2 This assumes that blank lines separate paragraphs.28 CHAPTER 2. use: spell filename This will list all words not found in a dictionary (which one?). skip 4 columns and sort on the 5th column.

However. but you never know. grep -v dziewonski filename This will print every line from file filename that does NOT contain the string Dziewonski. 2. on UCSD computers. you could get your advisor into trouble!). grep. etc. awk. you may really want just the file names of the files that contain the string dziewonski.1 Common sense This should go without saying. sed. ADVANCED UNIX 29 2. You can go pretty far with only 20 commands or so. grep dziewonski * This lists lines containing dziewonski from ALL files within your current directory..7. Even deleted e-mail is usually still on the computer system somewhere. grep dziewonski filename > dz. Attempts at sarcasm and irony usually misfire in e-mails. You should not consider e-mail to be completely private.lines This works as above except the lines containing dziewonski are written to the file dz.8 Advanced UNIX This writeup so far contains pretty much all I’ve ever done with UNIX. in which case the following command will work better: . Here are some examples: grep dziewonski filename This will print every line from file filename that contains the string Dziewonski. If you really want to be a UNIX guru.2. Do not download pornography. etc. try reading up on pipes. Then you will be able to write custom scripts to do all kinds of neat things.lines rather than printed to the screen. Be very careful when you reply to messages sent to a group of people that you do not send your message to everyone on the list (unless that is your intention). hate literature. You may get into BIG trouble (worse. often on daily and weekly backup tapes. However there are much more powerful things you can do. It’s best to err on the side of professionalism in your communications with your colleagues.8.

UNIX INTRODUCTION This lists the file names of the files that contain the string dziewonski grep ezxplot ‘find . . This is useful if you have made some changes to a file but cannot remember exactly what they are. kill PID This kills a job with process ID number PID (obtained from the tops or ps command). use the -9 option: kill -9 PID You can compare two files using the diff command: diff file1 file2 This lists all differences between file1 and file2. Note that the find command must be enclosed with backward apostrophes. into the input of the second command. For stubborn jobs. grep. the vertical line is a ‘pipe’ that directs the output of the first command. that the program was compiled with a Makefile that would contain ezxplot because this is necessary to make the program work. This is useful for runaway jobs. not regular apostrophes. ps -eaf | grep shearer > junk As above. In this case.30 grep -l dziewonski * CHAPTER 2. The grep command searches for ezxplot in a list of file names returned by the find command. however. ps -eaf This lists all processes that are running on your machine ps -eaf | grep shearer This lists all of the processes that contain the string shearer in the output lines of ps. ps. -name Makefile -print‘ This is one that recently saved me when I could not find a program that I knew I had written. but I did not know its name or which directory it was in. but writes the output into file junk rather than to the screen. I knew.

8. the last part prints the remainder of the line. swapping the contents of columns 11-20 and columns 31-40.11.proc.31.41. Note that "^" means start of line cat file1 | awk ’{print $5.10) substr($0. cat file1 | sed ’s/^/Paul says /’ > file2 Insert the prefix "Paul says " at the beginning of each line. cat file1 | awk ’{print substr($0. substituting "Paul" for the first "Peter" on each line. substr takes a chunk of it. cat file1 | sed ’s/Peter/Paul/g’ > file2 Copy file1 to file2.20)}’ > file2 Start the beginning of each line with "Columns 11 to 20 are " and then list the contents of those columns in the input file.10) substr($0. Variations on the last few examples can be used to reformat ascii data files. in that order.10) substr($0.1 Some sed and awk examples cat file1 | sed ’s/Peter/Paul/’ > file2 Copy file1 to file2.2.length($0)-40)}’ > file2 This copies file1 to file2. substituting "Paul" for the every "Peter" on each line (note the "g" flag for global substitution). etc.11.1. EXAMPLE OF UNIX SCRIPT TO PROCESS DATA 31 2.9 Example of UNIX script to process data By combining UNIX commands into a script.$3.dir rock> ls data1 data2 data3 We have written a program to process the data in these files and write new data files which we might want to call data1. and 1 to file2. 2.9. including those that do not have spaces between fields. cat file1 | awk ’{print "Columns 11 to 20 are " substr($0. omitting the 2nd and 4th columns. $0 is the line. The program is called procdata .21. Consider a simple example where we have a number of data files contained in a data directory: rock> cd data. cat file1 | awk ’{print $2. $1*(-10)}’ > file2 Switch columns 1 and 2 and multiply original 1st column numbers by -10. it is possible to create very powerful tools for processing data. 3.10) substr($0. this copies columns 5.$1}’ > file2 Assuming file1 has 5 columns of figures.

log \rm data. using the command file do.dir > filelist cd data./procdata Enter input file name data1 Enter output file name data1.proc Enter multiplier factor 3 rock> To process all of the files in the directory. Another approach is to write a UNIX script to run the program for all of the files in the directory. clearly this would get very tedious if we had lots of files to process.dir # Note the "backwards" apostrophes in next line. which looks like this: #! /bin/csh \rm procdata. We could modify the program to accept a list of file names. If the program is one level up from the data directory. However. \rm filelist .. manually entering the file names.proc ls data. a multiplier factor to scale the data. in this simple example..32 CHAPTER 2. regular ones won’t work! foreach filename (‘cat .. UNIX INTRODUCTION and prompts the user for an input file name and an output file name.proc.proc 2 ! end cd . Here is one way to do this.log << ! $filename $filename./procdata. we could run the program for each file./filelist‘) echo "processing file:" $filename ..dir/*. but perhaps it is a complicated program that someone else wrote that we don’t want to mess with. and../procdata >>! . then: rock> .

cshrc file (set noclobber prevents overwriting an existing file with > or writing to a nonexistent file with >>. we use ‘backslash rm’ instead of ‘rm’ so that any aliases that might require interactive verification of the deletions are not performed. Note that >! also overrides the noclobber setting). we remove any existing processed files in the data.dir directory. using a wildcard and assuming that the file names end in . EXAMPLE OF UNIX SCRIPT TO PROCESS DATA 33 This is designed to be located in the same directory as the program. This loop is terminated by the ‘end’ command later in the script. The power of this script is that it can be run on a directory containing thousands of files. lines) are directed to a file called procdata. We use >> ! rather than >> in case ‘set noclobber’ is contained in our . we really did not need to generate the file filelist because we eventually deleted it. etc. Note that within the script.proc Next. The screen output from the program (all of the ‘Enter input file name’. the latter case being our situation. The procdata program is terminated within the script with the ! symbol.2. just as easily as for a smaller number of files. we could have written the script as: #! /bin/csh . Following the ‘end’ statement that completes the loop over the files. We use the echo command to output to the screen each file that is being processed.dir where we loop over the filenames contained in filelist. In this example. using the ‘foreach’ command. Next.. as it is no longer needed. Otherwise the computer might prompt us to see if we really want to delete the files and the script would not be prepared to handle this.dir into the file filelist Then we go into data. Thus. one level up from the data directory. The backward apostrophes indicate that a UNIX command is to be executed.log so the first thing we do is remove any old version of this file. we write a list of the data file names within data.9. if it exists../) and direct the normal screen output to the logfile./filelist‘ (be sure to use backward apostrophes!) will return one line of filelist at a time and assign it to the filename variable. The ‘cat . Within the ‘foreach’ loop we refer to the contents of the filename variable as $filename. We then run the procdata program (one level up so we need the .. we go back to the directory containing the program and delete filelist.

proc CHAPTER 2.log << ! $filename $filename. ~/dirname ~otheruser . i. but most of us just pick up stuff as we need it. 2.. Your work will be better documented and it will be much easier for you (and others) to reproduce your work. There are lots of books on UNIX that one can consult for this purpose (but who has time to read them?). then you are wasting your time. regular ones won’t work! foreach filename (‘ls‘) echo "processing file:" $filename . UNIX INTRODUCTION Note the backwards apostrophes in the next line..10 Common UNIX command summary print filename on your screen change directory to dirname go back up one level go to home directory go to directory dirname in home directory go to home directory of otheruser cat filename cd cd cd cd cd dirname .e..dir \rm *. In this case the wildcard * will assume the name of all of the files within the current directory. Spend some of that time learning how to write a UNIX script and you will be far better off in the long run../procdata >>! ./procdata..proc 2 ! end cd .34 \rm procdata. foreach filename (*) will also work. Alternatively.log cd data. the ‘ls‘ could be written as *. We won’t have time in this class to go into the details of all of the different things one can do in scripts like this. The main point that I want to get across is that if you are spending lots of time running programs manually.

f src pwd rm filename rmdir dirname wc filename wc -l filename make directory dirname change name of file1 to file2 change name of f1 to f2 but ask before overwriting existing f2 move all files ending in ’.10. directories by adding slash to their name all files with ending with ".f list list list flag list mkdir dirname mv file1 file2 mv -i f1 f2 mv *.f" 35 lpr -P silo filename ls ls ls ls ls -l -a -F *.2. COMMON UNIX COMMAND SUMMARY cp file1 file2 cp -i f1 f2 df du -ks * copy file1 to file2 copy f1 to f2 but ask before overwriting f2 list disk space on the different disks list disk usage for files/dirs in current directory send filename to printer silo files in directory all files including those starting with .f’ into existing directory src print working directory remove filename remove directory dirname (directory must be empty) count words in file count lines in file .


31. In the following are some instructions to help you through the installation process. Note that with all these scripts. GMT other useful tools Download the Fink source code for your operating system via this link: http://www.finkproject. there are a LOT of other programs available to you for free and keeping everything up to date is pretty easy.Chapter 3 Generic Mapping Tools Generic Mapping Tools. ∼/Downloads/fink-0. %cd ~/Downloads/fink-0.php Double click on the tar file that you just downloaded if it hasn’t been unpacked automatically.31.3 Start the installation operation with the supplied bootstrap script. 3. it is a The best way is to use a utility called “Fink”. 2011. % . If you haven’t yet installed GMT. The latest update (Version 4. frequently referred to as GMT.1 Installation of Fink. just select the default options by hitting the return key.7) was released on July 15. which itself must be installed and is also a pain.3). I’m not going to lie.5. is a set of UNIX tools for making map and plots written by Paul Wessel and Walter Smith. Open a terminal window and change directories into this folder (in the test case I just did. This software is in the public domain and is still maintained by Wessel and Smith./bootstrap Now do the following: 37 . The good news is that once you have installed Fink.

try fink list.2_high/share/coast/*. so install it and some other related packages using Fink: % fink install gmt % fink install gmt-coast % fink install gmt-doc The high resolution GMT coastlines may not be the most up to date in the most recent version.tar.2_coast/share/coast/*. If you want a complete list of packages.cdf /sw/share/gmt/coast % sudo cp and download the following high resolution coastline archives: GSHHS2.0. Now in Terminal run the following commands (please note that the version number of your downloaded packages may be newer than in the commands below and may need to be modified): % cd ~/Downloads % sudo cp GSHHS2. go to ftp://ftp.hawaii.cdf /sw/share/gmt/coast You should also install ps2eps (PostScript to Encapsulated PostScript).2_coast.cdf /sw/share/gmt/coast % sudo cp GSHHS2.bz2 In the Finder go to the download folder and double click on each of the three archives.2_full/share/coast/*. GENERIC MAPPING TOOLS % /sw/bin/pathsetup.38 CHAPTER 3.tar.0.bz2 GSHHS2. They will be unpacked as folders.bz2 GSHHS2.2_high. If # this sets up your path (if it wasn’t already) % fink selfupdate-rsync # this updates your fink distribution % fink index -f # this makes an index % fink scanpackages # this figures out what packages are available.eps to image files like .0. We are after GMT now. gv (Ghostview) and ImageMagick (which includes the conver program to convert .2_full.0.png): % fink install ps2eps % fink install gv % fink install imagemagick .

and a number of examples. Once you have learned a little bit about how to use GMT. The output of the program is directed to the Postscript file map. INSTALLATION OF FINK. You will ALWAYS want to run GMT as a UNIX script (see Chapter 2).hawaii. Some other sites that may be helpful are: file. GMT is not very “user friendly”.edu/” that contains a GMT tutorial.1. are invoked with a dash and a letter on the same line (e.rice. but . You can access these at the UNIX command level by simply entering: man pscoast or even just pscoast. etc. Note that we use >! instead of > to avoid getting an error message if map. Use that as a starting point. invokes the C-shell environment.eps The first line.gatech.soest. Presumably in some cases it may make a difference.). #!/bin/csh.ruf. Here is one called do. Next we encounter pscoast which is the GMT program that draws coastlines. let’s take it out for a spin. but it is probably safest to always go into the C-shell because all of the example GMT scripts do this. If you are unfamiliar with some of the features of the UNIX environment like piping∼ben/ already exists. We begin with an example using the tool pscoast. in UNIX style. -P. etc. There is a GMT website at “http://gmt. GMT OTHER USEFUL TOOLS 39 Now that you have installed GMT. However. -JQ180/6i -B60g30 -P -Dc -G200 >! map. The script will run without this. it is extremely powerful in the number of things that it can do and the time spent learning how it works will not be wasted as you will become familiar with many useful UNIX tools. you will overwrite any existing gv map. But be warned.. The best strategy for figuring things out is to look through the examples and find something close to what you want. it’s helpful to use the help documents as your primary reference.html (useful links to things to plot). This program has a lot of options that.gmt1: #!/bin/csh pscoast -R0/360/-90/90 ps2eps -f -g -l map.3. you may find it fairly intimidating at GMT/ (tutorial) http://www. -Dc. GMT is capable of producing very nice maps and plots and is pretty much the industry standard for Earth Science map making.

Note that we could have written this with a space between the “R” and the zero (”0”) immediately following. The default is (l)ow resolution. The available options are: (f)ull. But for now. so generally should only be used for extreme close ups. simply type the command name alone. (i)ntermediate. GENERIC MAPPING TOOLS To get a full list of options. lat2=90). -Dc Sets the resolution of the coastline to “c” for crude. It takes more time to generate the plot. (h)igh. Most people leave this space out to more easily separate the different commands. too. and latitude (lat1=90. lon2=360). -JQ180/6i This specifies the map projection to be cylindrical equidistant (a simple linear scaling of lat/lon). Note that the full resolution files require over 55Mb of data and provide great detail. A very large number of different map projections are available! -B60g30 This sets the labeled lat/lon lines to 60 degree intervals and the unlabeled lines to 30 degree intervals -P Specifies “portrait” mode so that the plot is not rotated by 90 degrees as in “landscape” mode (default). For larger maps or closeups. This is all that is required for a small map of the whole globe. . the plot width is set to 6 inches (the “i” means inches). (l)ow and (c)rude. The center meridian is set to 180 degrees. higher resolution will be required.40 CHAPTER 3. let us examine the arguments in our example: -R0/360/-90/90 This sets the map limits of longitude (lon1=0.

These are ps2eps and gv.gmt1. These nonintuitive units are a Postscript convention! Finally. GMT OTHER USEFUL TOOLS -G200 41 Specifies the grayshade level for the continent shading from 0 (black) to 255 (white). which is poster size. GMT will truncate it. The first problem can be fixed by setting the page size to “Letter” using the command gmtset PAPER MEDIA Letter. you should get a popup window that looks like this: If you open the file in PageView. But. If you want to be always safe from that problem. y=1inch. a handy quick look program for EPS files. set the media type to ArchE.1.2 inches from the left edge and 4 inches from the bottom. The former converts the postscript file format to and encapsulated postscript (EPS) format and the second calls ghostview. .3. there are two more commands that let us view the plot without any fancy store bought applications. if you generate a plot that is bigger than that. you will notice that there is a lot of white space around the plot and it is not centered on the page. The second problem is because the default position for the lower left corner is at x=1inch. We can change this by specifying the x and y positions directly: -X1. INSTALLATION OF FINK. After running the script do.2i -Y4i This sets the lower left corner to 1.

green and blue are numbers between 0 and 255. In this way we can avoid making our lines too long.2i -Y4i \ -G0/255/0 >! map. you may decide we want the continents to be a hideous green color and can choose the -Gred/green/blue option where red. but doesn’t draw the grid You may prefer a smaller font. GENERIC MAPPING TOOLS You may also decide that we don’t want grid lines drawn on the plot so we remove the “g30” from the -B command: -B60 This puts a label on the latitudes and longitudes every 60◦ .42 CHAPTER 3. This script produces something like this (is the green hideous enough for you?): 0˚ 60˚ 120˚ 180˚ 240˚ 300˚ 0˚ -JQ180/6i -B60 -P -X1. The resulting script (do.eps Note that we used a backslash to indicate that the line continues to the next line.gmt2) is: #!/bin/csh gmtset PAPER_MEDIA Letter gmtset ANOT_FONT_SIZE 10 pscoast -R0/360/-90/90 -Dc ps2eps -f -g -l map. We can do this with a different program which we run before calling pscoast: gmtset ANOT_FONT_SIZE 10 gv 60˚ 60˚ 0˚ 0˚ −60˚ −60˚ 0˚ 60˚ 120˚ 180˚ 240˚ 300˚ 0˚ . gv map. The arguments of psxy are as follows: -O Indicates that this is a overlay onto an existing Postscript file to avoid the initializations at the beginning of the file. Next.06i -B60 -P -Dc -G200 \ >> map. GMT OTHER USEFUL TOOLS 43 Next.1.eps The first part of the script is the same as before.11890 678 ABKT 116 ADK 706 AFI 51.90930 -171.77730 Here is a script (do. don’t put a “showpage” at the end of the file) so that more can be added to the file. INSTALLATION OF FINK..02920 42. -R Sets the plot boundaries (defaults to those set by pscoast) .49400 1645 AAK -G0 -: station. we use psxy to read and plot the x-y points from file station. except that the -K is necessary to tell GMT to keep the Postscript file open (i.gmt3) that will plot these points on our map: #!/bin/csh gmtset ANOT_FONT_SIZE 10 pscoast -R0/360/-90/90 psxy -O -R -JQ180/6i -JQ180/6i -X1.list and its first five lines are: 9.2i -Y4i -K >! file.list ps2eps -f -g -l map. Note that > or >! would not work here because it would overwrite the file instead of adding to it.76560 2442 AAE 74. The file is called station. We use >> to append the output onto the end of the map.88370 -176.93040 38. suppose you have a file containing the coordinates of some seismic stations which we wish to plot on this map.e.63900 37.68440 -13.

gmt4: . 0˚ 60˚ 120˚ 180˚ 240˚ 300˚ 0˚ 60˚ 60˚ 0˚ 0˚ −60˚ −60˚ 0˚ 60˚ 120˚ 180˚ 240˚ 300˚ 0˚ Now let’s try a different map projection.06i Plots xy points as (t)riangles of 0. This will fill in the triangles. (s)quare.06 inch width. Note that the program automatically converts the longitude convention of the data points (-180 to 180) to the longitude convention of the map (0 to 360). For seismology this option is very useful because coordinates are usually given as lat. -: This tells the program that the data are to be read as y-x pairs. in our case. lon rather than the other way around. this should work without the 180/6i but I did not find this to be true). This is a nice feature of GMT. (x)cross. -G0 Set fill parameter to 0 (black). or (long. The default is x-y. In the case of the vector. Other options are (c)ircle. the direction and length are also read from the file (see manual). and add a title in a script called do.44 -JQ180/6i CHAPTER 3. (i)nverted triangle. GENERIC MAPPING TOOLS Sets the map projection (according to the manual. and (v)ector. (d)iamond. plot the points in red.

ps -G255/0/0 -: station."IRIS FARM stations": \ >> map.2i -Y4i -K >! map."IRIS FARM stations": The 0 results in no grid lines or labels The title is set off with :.3.lon2.lat2 to S.list 45 The changed commands are as follows: -JH0/6i Invokes the equal-area Hammer projection with 6 inch width -Bg0:. green=0. This can be changed using the gmtset HEADER FONT SIZE command (see below).ps -G150 Changes are: gmtset HEADER_FONT_SIZE 20 Set font size for title to 20 -R-121/-114/32/37 Set lon1. Next.06i -JH0/6i -Bg0:."IRIS FARM stations": \ -Di -I1 -I2 -I3 -N1 -N2 -G255/200/200 -X1. INSTALLATION OF FINK. the title is way too big.gmt5: #!/bin/csh gmtset HEADER_FONT_SIZE 20 gmtset ANOT_FONT_SIZE 10 pscoast -R-121/-114/32/37 -P psxy -O -R -JM6i -B1g1:.lat1.2i -Y4i -K >! map. let’s look at a closeup of these stations in southern California with the script do.06i -G0 -: -JM -St0. GMT OTHER USEFUL TOOLS #!/bin/csh gmtset ANOT_FONT_SIZE 10 pscoast -R-180/180/-90/90 -P psxy -O -R -Dc -JH -St0. California . blue=0 To my taste.1.list >> map.” and “: (weird!) -G255/0/0 Define the fill for the xy plot as red=255.

46 -JM6i CHAPTER 3. GENERIC MAPPING TOOLS Use Mercator projection. blue=200 ."IRIS FARM stations": Label and draw grid lines every 1 degree Use same title -I1 Plot permanent major rives -I2 Plot additional major rivers -I3 Plot additional rivers -N1 Plot national boundaries -N2 Plot state boundaries within the Americas -G255/200/200 Fill land areas with red=255. green=200. width = 6 inches -B1g1:.a ghastly shade of pink: .

8398 32.5496 32.9498 -115.0000 99.3.9295 .8936 32.9849 -115.0000 -115.0000 99.0000 -115.8890 370. GMT OTHER USEFUL TOOLS 47 IRIS FARM stations 239˚ 37˚ 240˚ 241˚ 242˚ 243˚ 244˚ 245˚ 246˚ 37˚ 36˚ 36˚ 35˚ 35˚ 34˚ 34˚ 33˚ 33˚ 32˚ 239˚ 240˚ 241˚ 242˚ 243˚ 244˚ 245˚ 246˚ 32˚ Next.9142 -115. For this.flts that has the following format: 370. INSTALLATION OF FINK.8729 32.1.9655 -115.5276 32.5358 32. we use a file called calif.9410 -115.9916 -115. let’s add lines that show the traces of mapped faults in southern California.9218 32.9745 -115.8216 32.7983 32.9096 32.9312 -115.5419 32.9029 -115.

15i -G0/0/255 -: station."IRIS FARM stations": \ -Di -I1 -I2 -I3 -N1 -N2 -G255/200/200 -X1.9228 370. -W8/255/0/0 .0000 99.2i -Y4i -K >! map.99) is used to separate the different faults because 370 is off the map (only goes to 360!).0000 -115.48 -115. GENERIC MAPPING TOOLS The faults are defined as (lon.9973 Changes are: -B1:.flts -K >> map.8205 33. A value of ( In this command.7796 32. we can use the psxy command a second time in the script -M’370’ -W8/255/0/0 calif. we use the -M option to flag the segment boundaries -M’370’ lines starting with ’370’ mark segment -St0.0015 -115.99) points. CHAPTER 3.gmt6: #!/bin/csh gmtset HEADER_FONT_SIZE 20 gmtset ANOT_FONT_SIZE 10 pscoast -R-121/-114/32/37 -P psxy -O psxy -O -R -R -JM -JM -JM6i -B1:.flts -K >> map.0127 -115.list >> map."IRIS FARM stations": We removed the g0 so we don’t plot grid lines which might get confused with the faults We plot the faults using: psxy -O -R -JM -M’370’ -W8/255/0/0 calif.8017 33.8391 pairs.0069 -115.7892 32. Without this command the plot would look like a mess because lines would be drawn to the (370. To plot these faults on our map of the southern California stations.

15 inches high -G0/0/255 plot with red=0.15i plot triangles 0. blue=0 Note that we do not need the -: option because the points are already given as ( results in the plot: IRIS FARM stations 239˚ 37˚ 240˚ 241˚ 242˚ 243˚ 244˚ 245˚ 246˚ 37˚ 36˚ 36˚ 35˚ 35˚ 34˚ 34˚ 33˚ 33˚ 32˚ 239˚ 240˚ 241˚ 242˚ 243˚ 244˚ 245˚ 246˚ 32˚ (Are there really no faults in eastern southern California?) ASSIGNMENT GMT1 . GMT OTHER USEFUL TOOLS 49 This draws the line with linewidth=8 (thicker than normal) and color red=255. (***THIS IS KEY TO GETTING GMT SCRIPTS TO WORK PROPERLY!!! CHECK THIS FIRST WHEN YOU HAVE PROBLEMS. green=0. We change the symbol size and the color: -St0. green=0. INSTALLATION OF FINK.1.3. We plot the stations last so that they will go on top of the faults.***) The script do. -O is needed on every command except the first. blue=255 Note that -K is needed on every command except the last.

2in) red Turn in the script and the . . Look up how to annotate the point with text (HINT: pstext and label the star with the name of the place you were born. Write a script that plots your birthplace as a big (.eps file produced by it (via e-mail to ltauxe@ucsd. GENERIC MAPPING TOOLS Install Fink and GMT if you haven’t already. national and state boundaries. Draw all rivers. Make a title in 20pt font with your name.50 CHAPTER 3. Use an orthographic projection with the star at lon0/lat0.

C has emerged as a competitor and seems to now be much more widely taught to students. 2. You will communicate and exchange software more readily with most IGPP faculty. some cranky advice: It is important to become familiar with at least one major programming language.Chapter 4 Fortran Why learn Fortran? The answer for geophysics students at SIO is obvious—most IGPP faculty program in Fortran. Matlab and other application programs are not. There is a huge library of existing Fortran subroutines to perform various algorithms. Why learn Fortran if you already know C? Several reasons come to mind: 1. Fortran was the language of choice for scientific programming. 4. Recently. For many years. It’s fun! Finally. both at IGPP and in the wider scientific community. let me make a broader pitch for its usefulness. 3. In the long run. Fortran and C are such languages. Complex numbers and double precision are included. who are generally proficient in Fortran but rather challenged in C. perhaps because it is favored by computer science departments (who worry more about writing compilers than how to handle complex numbers). you will be one of those annoying people that is forever asking others to write or modify programs for you. However. you will handicap your ability to do science if you do not take the time to gain experience with a real programming language. In the worst case. 51 .

major revision Fortran 95 (released in ?). Press. To make sure you have it in your path. minor revision Wikipedia also lists Fortran 2003 and 2008. which can be downloaded free for the Macs. Important versions include: Fortran IV (released in 1972) Fortran 77 (released in 1980). It is updated and ”improved” by some committee of computer sciences every ten years or so. There is an updated version that I have not seen for $53.2 Texts and manuals This class will be a tutorial on Fortran90 and will not be comprehensive. resulting in a more modern approach that necessitated some slight incompatibilities with older Fortran. In class. 1999). You may want to check around to see which book you like best. It’s only $47. Fortran90 departed from the column sensitive format of older Fortran. Oxford Univ. Thus. but the more modern usage is to only capitalize the first letter. but will describe the differences with Fortran77 when they are important because you are likely to need to work with existing Fortran77 code at some point. FORTRAN 4. we will use gfortran. Most versions are designed to be fully backward compatible with previous versions. I will try to teach this class entirely in Fortran90. Originally it was spelled in all caps as FORTRAN. which I don’t know anything about. I just checked on Amazon and there are 4 or 5 books out there. One that I have used and recommend is: Fortran 90/95 Explained (Metcalf and Ker Reid.cshrc file: alias f90 ’gfortran’ . 4. However. Fortran is one of the oldest computer programming languages and was begun in 1954 by IBM programmers led by John Backus (no relation to George). which has some favorable reviews. I recommend that you buy a textbook that will be serve as a more complete reference. major revision Fortran 90 (released in 1991). enter: ‘which gfortran’ and you should get something like /usr/local/gfortran/bin/gfortran I recommend that you add the following to your . I would not recommend using these at this point in time.1 Fortran history The name Fortran is derived from IBS Mathematical FORmula TRANslation System.52 CHAPTER 4.

f90” for the executable) which can then be run simply by entering . Before the program can be run. COMPILING AND RUNNING F90 PROGRAMS 53 This will allow you to just type f90 instead of gfortran when you want to compile programs.4.f90 -o printmess’ and get the following response: rock% f90 printmess. This creates an executable version of the program called ‘printmess’ (you should ALWAYS use name of the program without the ”.f90 -o printmess rock% No news is good news! If there was a syntax or other error detected during the compilation.f rather than . we need to type . ./printmess test message rock% Note the because . "test message" end program printmess To compile this program from my computer (rock in this case).f90.f90) program printmess print *. suppose you have a program called printmess. creating the executable file that you use to actually run the program. be sure to use the appropriate suffix so that both you and the compiler know which version to use. 4./printmess and not just printmess.f’. For example./printmess: rock% . we would get an error message at this point.f90 with contents: ! simple Fortran90 test program (printmess. It is in fact possible to set things up so that your F90 programs end in .3. it must be compiled using the Fortran90 compiler on your computer. is not in our path. Because of the slight incompatibilities between the versions. The examples that follow assume that you have done this. I do not recommend this because there is so much existing code around in Fortran77 that confusion is likely to result if you do not explicitly identify your code as F90.f90’. Programs in older versions of Fortran end in simply ‘. I enter ‘f90 printmess.3 Compiling and running F90 programs Fortran90 programs are written as ascii files that end in ‘. This is called the source code.

f90 -o printmess’ Thus. FORTRAN If you are like me. You can put in as many blank lines as you want and they will be ignored by the compiler. e.54 CHAPTER 4. There is no need (as in many languages) to terminate the comment with another flag. I recommend that you create a Makefile (yes.f90 gfortran $< -o $* The tricky part of this is that the space before the gfortran MUST be entered as a tab. It is why they generally run much faster than uncompiled languages like BASIC or Matlab or Python scripts. Makefiles are very useful to keep track of compiler options and to bind with subroutines. The next line is blank. We can also use ! to add an inline comment following a statement. now let’s examine our simple F90 test program again: ! simple Fortran90 test program (printmess.. then you can just enter: make printmess in order to compile the program.g. "test message" !print message on screen would be a valid line. . not as a series of spaces. "test message" end program printmess The first line is a comment line. The end of the line terminates the comment. Blank lines provide a good way to improve the readability of longer programs by breaking them up into coherent blocks of code.3. Once you have set up this Makefile. print *. Include in the Makefile the following lines: %: %. Anything following an exclamation mark (!) is a comment. (more about this later). you will quickly tire of typing in the line ‘f90 printmess.f90) program printmess print *. the first character MUST be capitalized) in the same directory as the program. The difference between source code and excutables is fundamental to languages like FORTRAN and C. 4.1 The first program explained OK.

c end program multint The program uses three variables. The remaining characters can be any combination of letters. This line is optional but is considered good programming style. b and c. ASSIGNMENT F1 Write a F90 program to print your favorite pithy phrase. we want them to be integers so we define them using a ‘type statement’ . Variable names can be from 1 to 31 characters long. but is considered good programming practice. The name printmess is not used by the program at all. in this case by three spaces: print *. Variables in Fortran can be of many types.4. b. integer. The desired output is enclosed in quotes (apostrophes would also work). "test message" print * will output to the screen. "Product = ". The ‘program printmess’ is optional. including real (floating point). In our case. complex. all F90 programs must terminate with an ‘end’ statement. the letters a. COMPILING AND RUNNING F90 PROGRAMS 55 The next line is used to name the program. and underscores ( ). "test message" end but are helpful for longer programs (hundreds to thousands of lines of code) where the label following the ‘end’ would remind a reader of which program is actually ending. which would work just as well if were written as: print *. These style points don’t matter much for a short program like this. Finally. c !declare variables a = 2 b = 3 c = a * b print *. numbers.3. 4. Good style also suggests that lines in the body of the program are indented. The first character must be a letter.3. character and logical.2 How to multiply two integers Here is a simple F90 program to multiply 2 and 3: program multint integer :: a. double precision.

175494e-38 to 3. these are 4byte integers that can range from -2. all others are assumed to be real. A prominent example of this type of Fortran programming may be found in the first edition (1986) of Numerical Recipes (but by the time of the second edition in 1992. this convention still works under F90 but is discouraged.483. Often they only declare variables when the rule is broken. older Fortran programs adopt this convention.483.647. for example when it is desired that the variable ‘year’ be an integer. b.4 An important historical digression It is not required that variables be declared in Fortran.56 integer :: a. get it?) are assumed to be integers. Addition is +. c in which case they would be floating point (real) variables. Alternatively. if not most. For the Sun F90 compiler. If they are not declared. and division is /. the authors had been shamed into declaring all variables). Variable names beginning with i through n (INteger. another Fortran advantage over standard C. they could have been defined as real numbers: real :: a. c !declare variables CHAPTER 4.147.648 to 2. In Fortran. for example implicit real (a-z) .147. b. "Product = ". An ‘implicit’ statement can be used to modify the default rules. subtraction is -.402823e+38) The lines that follow are pretty self explanatory: a = 2 b = 3 c = a * b print *. depending upon their first letter. c Note that * is used to indicate multiplication as is true in almost all programming languages. Such undeclared variables are said to be declared implicitly based upon their first letter. real numbers range from 1. 4. then the compiler assigns them as integer or real. For the Sun compiler. a to the power of b is written as a**b where a and b can both be real. Many. FORTRAN Older Fortran programs do not include the :: in these statements.

modifications such as this will only lead to more confusing code.4. The value 111. I must concede. however. However. we will declare all variables for the programs in this class and I will dock you points if you fail to do so in assignments.delta1)*kmdeg but you have not declared kmdeg explicitly. I will admit that. On the other hand. Because the letter k is between i and n. I do not always follow this practice. the compiler will flag scalc1 as an undeclared variable and you can fix it before it causes any more trouble. The program will run and assign zero to the otherwise unused variable scalc1 and you will get wrong answers. wrong (the worst kind of program bug to have).19 will be truncated to 111 and you will get values for dist that are slightly.4.19 dist = (delta2 . . To save you from these embarrassments and to encourage good programming habits. if you use ‘implicit none’ and declare your variables. the program will declare kmdeg as an integer. Example 2: Suppose you have the following lines in your code: kmdeg = 111. as a long time Fortran programmer. Modern programming practice is to explicitly declare ALL variables and to have the compiler warn us when variables are not declared. but not obviously. Example 1: Suppose you should have the following line in your program: x2 = a1 + a2*sin(theta)*scale1/scale2 but you accidentally type: x2 = a1 + a2*sin(theta)*scalc1/scale2 If you don’t follow the practice of declaring all of your variables. then the error will not be detected during compilation. AN IMPORTANT HISTORICAL DIGRESSION 57 will make all undeclared variables real. that it is a good idea and is likely to save more time in the long run (by eliminating program bugs that are often caused by undeclared variables) than is lost while writing the program. This can be done by including the statement implicit none at the beginning of every Fortran program.

I suggest that you never use semicolons in this way.37 print *. 4. Here is an example program that generates a table of trig functions: . only OK in F90).4. c !declare variables c = a * b. 4. In FORTRAN this is done with the ‘do loop’. notice that variables can be assigned values when they are declared (OK in F90.90 !distance in meters powell_long = 8.58 ASSIGNMENT F2 CHAPTER 4. What happens when you run the program? Why? ASSIGNMENT F3 Cut and paste the following defective program onto your computer: program longjump beamon_long = 8. "Product = ". The variable assigning option is a reasonable convenience. but the multiple command option is certainly misused in this case because it makes the code much harder to read.1 Alternate coding options There are always lots of ways to write the same program.f90 code: program multint2 implicit none integer :: a=2. Then explain why it gives the wrong answer. Both of these changes make the code more similar to C. this is most naturally implemented with the ‘for’ statement. Unless you have a really good reason to put more than one command on a line (saving space is NOT a good reason!).dif_inch. c end program multint2 First.95 dif_inch = (powell_long . Second. In C. c statement.beamon_1ong) * 39."Powell jumped ". don’t try this in F77). Here is another way to write the multint. FORTRAN Copy the program multint but leave out the integer :: a." inches more than Beamon" end program longjump Compile and run the program.5 Making a formatted trig table using a do loop Any reasonable programming language must provide a way to loop over a series of values for a variable. print *. b=3. b. notice that more than one command can be included on a line if the commands are separated by a semicolon (again.

This is not recommended and roundoff peculiarities mean that the do loop would need to be written in the form: do theta = 0. degrad degrad = 180. 1.1x. To make the output look nice.. after converting from degrees to radians by dividing by degrad (anybody see how we could make the program slightly more efficient?).1x.4.g.. following the definitions of the variables as real. 1.1415927 do itheta = 0.0 as the ending value to avoid the possibility that roundoff error might cause the desired ending value (computed by successively adding 1.f6. incremented by 1 each time.1. The 1 is actually optional as it is the default increment. 89./3. stheta. 89.1.0 !****WON’T WORK IN F95! Note that we use 89.f7.4. Thus.0. until theta is greater than 89. 1 This begins the do loop which must eventually be closed with the enddo statement. 89. stheta. Notice that we use an integer for the do loop. we assign degrad to 180/pi so that we can easily make this conversion.. do itheta = 0. ctheta. we indent the inside of the loop. 2. Thus theta will assume the values (0. 88.. This is a loop over values of theta from a starting value of 0.f6. I have a lot of old code of this form. MAKING A FORMATTED TRIG TABLE USING A DO LOOP 59 program trigtable implicit none integer :: itheta real :: theta. we do not use . theta. ctheta.4)". ttheta.4.1x. but I’m going to slowly try to get rid of it. F77) permitted the use of real variables in do loops.1 rather than 89. . Older versions of Fortran (e. Inside the do loop we first convert from the integer theta to the real theta using: theta = real(theta) We then compute the cosine..5. ttheta enddo end program trigtable Fortran (like C and Matlab) uses radians (not degrees) as the arguments of the trig functions.0 to theta) to slightly exceed 89 and thus be excluded from the loop. 1 theta = real(theta) ctheta = cos(theta/degrad) stheta = sin(theta/degrad) ttheta = tan(theta/degrad) print "(f5. For clarity. sine and tangent of theta. 89) inside the loop.

4. An alternative way to write this: print "( f5.1x.f6. theta. . The numbers will be right justified.4)". writing f7. 2f7.4).4. e. this will add an additional space to the left of each number. stheta. f8. Older Fortran programs usually put the format specifier into a separate numbered line.4.4) 117 This convention is still allowed in F90 but should not be used unless you want to use the format statement more than once. Because the numbers are right justified.e. print 117. f8.g. Aligning things this neatly is probably more trouble than it’s worth. ctheta. ctheta. f8. ttheta Here we have used the continuation character & to split the statement into two lines. but it certainly makes the code easier to understand.1.4.f7. i. & theta.1. with leading blanks used as necessary. with 1 digit to the right of the decimal place.1.e. we explicitly specify the output format using a format specification: print "(f5.4)". ttheta CHAPTER 4.1 specifies that theta will be output as a real number into 5 total spaces. ctheta. Similarly. theta.1.4)". f7.4. stheta.. ttheta format (f5. ctheta.4. ctheta. ttheta since Fortran allows this syntax. ttheta where f5. stheta. f7. FORTRAN which would space the numbers irregularly among the columns. stheta. Notice that we have removed the need for the 1x between formats by adding an additional column to the appropriate formats (i.1x.1x. f6. Often programmers will write this more compactly as: print "(f5. Blanks are ignored so we can space things out neatly to line up the variables with their formats. Notice that in this case the f7.f6. 2f7.4 appears twice in a row. theta.4 rather than f6. theta. The 1x specifies that one blank character will be output between each of the numbers. Instead.60 print *.4 specifies that ctheta is output into spaces with 4 digits to the right of the decimal place. stheta..

An alternative way in F90 to use the same format specification more than once is to define it as a character variable.4. Here is a complete list of math functions: acos(x) asin(x) atan(x) atan2(y.1. theta2. it can come before.4. 2f7. ctheta1.. ctheta2. Note that the format line need not immediately follow the print line(s). theta2. 2f7.5.5.e. note that the trigtable program uses: .4)" print fmt.5. ctheta2.1 Fortran mathematical functions We used the Fortran sine. real problems As an aside. theta1. It is best not to refer to it as a line number (the old usage) because it normally has nothing to do with the line numbers and the labels need not be sequential (more about this later). ttheta2 but we are getting ahead of ourselves because we have not yet shown how to use character variables. stheta2. character (len = 30) :: fmt fmt = "(f5. stheta2. ctheta1.x) cos(x) cosh(x) exp(x) log(x) log10(x) sin(x) sinh(x) sqrt(x) tan(x) tanh(x) arccosine arcsine arctangent arctangent of y/x in correct quadrant (***very useful!) cosine hyperbolic cosine exponential natural logarithm base 10 log sine hyperbolic sine square root tangent hyperbolic tangent 4. MAKING A FORMATTED TRIG TABLE USING A DO LOOP print 117.2 Possible integer vs. ttheta1 print 117. Many older programs put all of the format statements at the end of the code.4. cosine and tangent function in the trigtable program. i. f8. stheta1. stheta1. f8. 4. ttheta2 format (f5.1.4) 61 117 117 is termed a line label and must consist of digits. theta1. ttheta1 print fmt.

62 degrad = 180./3.1415927 rather than simply degrad = 180/3.1415927


The reason is to make completely sure that the program will compute a real quotient and not an integer quotient. In fact, this caution is not needed in this case, as the following program demonstrates: program testfrac implicit none real c c = 2/3 print *,’2/3 = ’, c c = 2/3. print *,’2/3. = ’, c c = 2./3 print *,’2./3 = ’, c c = 2./3. print *,’2./3. = ’, c end program testfrac Running the program yields: 2/3 = 0.0E+0 2/3. = 0.6666667 2./3 = 0.6666667 2./3. = 0.6666667 As long as one part of the fraction is real, the program will compute a real quotient. It is only when both numbers are written as integers that the result is truncated. However, I have gotten into the habit of always including the decimal point in real expressions to avoid someday accidentally writing something like: a = sin(phi/degrad) + (2/3) * cos(theta/degrad)**2 which will definitely produce the wrong answer!


More about formats

There are many different formats that can specified. Here are some common examples:

4.6. INPUT USING THE KEYBOARD i5 = i5.4 = f8.3 = e12.4 = integer, 5 spaces, right justified as above but pad with zeros to 4 spaces (88 becomes 0088) real, 8 spaces, 3 to right of decimal place real output with exponent, 4 places to right of decimal e.g., b-0.2342E+02 where "b" is blank (useful for big or small numbers or when you are not sure what size they will be and want to be sure you have enough room to output them) (cranky aside: why always start with "0." which wastes a space? -2.342E+01 would be more compact)


If a number does not fit into the allocated spaces, it will appear as a series of asterisks (*****) a8 2x tn tln trn / = = = = = = character output, 8 spaces, right justified (if the length of the string is greater than 8, then the leftmost 8 characters will appear) output two blanks tab to position n tab left n spaces tab right n spaces (tr2 is the same as 2x) start a new line

ASSIGNMENT F4 Write a F90 program to print a table of x, sinh(x), and cosh(x) (the hyperbolic sine and cosine, these are built-in functions in Fortran) for values of x ranging from 0.0 to 6.0 at increments of 0.5 (use these x values directly in sinh(x) and cosh(x), do not convert them to radians). Use a suitable format to make nicely aligned columns of numbers.


Input using the keyboard

So far all of our example programs have run without prompting the user for any information. To expand our abilities, let’s learn how to input data from the keyboard. In most programs, we will want to first prompt the user to input the data, so here is an example of how to input two numbers: print *, "Enter two integers" read *, a, b Pretty easy, isn’t it? (Compare this section with the corresponding input section in the C or Python notes and you will see why I think Fortran is more user friendly than C or Python)


CHAPTER 4. FORTRAN Here is an example of a complete program that multiplies two numbers:

program usermult implicit none integer :: a, b, c print *, "Enter two integers" read *, a, b c = a * b print *, "Product = ", c end program usermult Running this program, we have: rock% usermult Enter two integers 2 5 Product = 10 The program will also accept the input on two lines: rock% usermult Enter two integers 2 5 Product = 10 Often in cases like this I will forget that I’m supposed to input more than one number. When the program just sits there, I then realize that I need to input more numbers (or I wonder why it’s taking so long to finish!). What happens if we make a mistake and try entering a real number? Let’s check: rock% usermult Enter two integers 3.1 15 ****** FORTRAN RUN-TIME SYSTEM ****** Error 1083: unexpected character in integer value Location: the READ statement at line 4 of "usermult.f90" Unit: * File: standard input Input: 3.1 ^ Abort rock% This is what happens on my old Sun computer, but most Fortran compilers will produce a similar message. The error message in this case is quite informative and



tells us exactly what the problem is. This is better than performing the computation and returning the wrong answer (the default in C for this example unless you are quite careful).


If statements

Next, let’s modify this program so that it will allow the user to continue entering numbers until he/she wants to stop: program usermult2 implicit none integer :: a, b, c do print *, "Enter two integers (zeros to stop)" read *, a, b if (a == 0 .and. b == 0) exit c = a * b print *, "Product = ", c enddo end program usermult2 Here the do loop has no arguments and the block of code inside the do loop will be repeatedly executed until an ‘exit’ command is executed. ‘Exit’ (a new feature in F90) means to leave the do loop entirely and go to the next line after the ‘enddo’ statement. As in our previous example, we indent the block inside the do loop to make the code easier to read. The program will allow the user to continuing entering numbers to be multiplied. When the user wishes to stop the program (in a more elegant way than hitting CNTRL-C), he/she enters zeros for both arguments. The if statement checks for this and exits the do loop in this case: if (a == 0 .and. b == 0) exit A list of the relational (comparison) operators in different languages is as follows: FORTRAN 77 90 .eq. .ne. .lt. .le. .gt. == /= < <= > C == != < <= > PYTHON == != < <= > MATLAB == ~= < <= > meaning equals does not equal less than less than or equal to greater than

66 .ge. .and. .or. .not. >= .and. .or. .not. >= && || ! >= and or not >= & | ~

CHAPTER 4. FORTRAN greater than or equal to and or not

The F77 syntax will still work under F90 and you are likely to see this in many of the older programs, e.g., if (a .eq. 0 .and. b .eq. 0) exit will also work. These operators can be combined to make complex tests, e.g., if ( (a > b .and. c <= 0) .or. d == 0) z = a There is, of course, an order of operations for these things which I can’t remember very well. Look it up in a book if you are unsure or, better, just put in enough parenthesis to make it completely clear to anyone reading your code. One nice aspect of Fortran compared to C is that if you make a mistake and type, for example, if (a = 0) exit you will get an error message during compilation. In C this is a valid statement with a completely different meaning than is intended!


If, then, else constructs

In the above example, a single statement is executed when the if condition is true. A more versatile form is as follows: if (logical expression) then (block of code) else if (logical expression) then (block of code) else if (logical expression) then (block of code) . . else (block of code) end if

the program stops. In contrast. As many ‘else if’ statements as required can be used. ’sqrt = ’. Using the quadratic formula. b. ’Enter positive real number (0 to stop)’ read *.’This number is negative!’ cycle else if (a == 0) then exit else b = sqrt(a) print *. Stop the program if the users enters zeros for all three values. c=-3 should return -3 and 1). ASSIGNMENT F5 Write a program to repeatedly ask the user for the constants a. have the program identify and compute any real roots. If the user enters zero. a if (a < 0) then print *. . IF STATEMENTS 67 The blocks of code can contain many lines if desired. The final ‘else’ will be executed if none of the preceding if statements is true. The final ‘else’ is optional.7. one block of code will be executed (once one of the ‘if’ tests is satisfied. Here is a demonstration program that repeatedly prompt the user for a positive real number. Output the number of real roots and their values. b end if end do end program usersqrt Notice the use of the ‘cycle’ command (also new in F90).4. it does not check the others). At most. The ‘cycle’ and ‘exit’ commands permit code to be written that is free of the ‘go to’ statements that would likely have been present in a F77 version of this program (‘go to’ statements are considered mortal sins by the programming style police). HINT: Test your program for some simple examples to make sure it is working correctly (a=1. ask the user to try again. the ‘exit’ command exits the do loop entirely. program usersqrt implicit none real :: a. If it is negative. which directs the program to the next iteration of the do loop. b=2. it computes and displays the square root using the sqrt() function. and c in the quadratic equation a*x**2+b*x+c=0. If it is positive. b do print *.

min and max can have more than 2 arguments if desired.b) computes the minimum of a and b using the intrinsic Fortran ‘min’ function.i) has the sign of a. mod(b.i) computes the remainder of a divided by i (this is called the modulus).f90 to compute the least common multiple of two integers. b. then a is evenly divisible by i. FORTRAN 4. If mod(a. imax do print *.and. i) == 0) imax=i end do print *. imax end if enddo end program gcf This is not a particularly efficient algorithm. but it runs plenty fast for small numbers. then mod(a. 2. min(a. min(a. If non-zero. Naturally there is also a ‘max’ function. "Greatest common factor = ". b) real(a) int(a) nint(a) ceiling(a) floor(a) absolute value abs(a) with sign of b conversion to real (F77 float(a) still works) conversion to integer nearest integer least integer greater than or equal to number greatest integer less than or equal to number ASSIGNMENT F6 Modify gfc. b == 0) then exit else do i = 1. There are some new things here: 1. b if (a == 0 .68 CHAPTER 4. . Here are some more useful Fortran functions: abs(a) sign(a. a. i) == 0 . mod(a.and.8 Greatest common factor example Here is an example program that uses some of the concepts that we have just learned: ! compute the greatest common factor of two integers program gcf implicit none integer :: a.i) is zero. i. ’Enter two integers (zeros to stop)’ read *. b) if (mod(a.

They are passed to the function in the statement: gcf = getgcf(a. ’Enter two integers (zeros to stop)’ read *. The variables a and b in the main program are the function arguments.i) == 0 . It is easier to use parts of the program in a different program. gcf end if enddo end program gcf2 integer function getgcf(x. You can test these pieces individually to see if they work before trying to get the complete program to work. b. a. i.i) == 0) getgcf = i end do end function getgcf We now perform the gcf calculation in the function getgcf. Your code is more modular and easier to understand. b) . gcf integer.and. 3. This provides several advantages: 1. 2. external :: getgcf do print *. "Greatest common factor = ". b if (a == 0 .b) print *. y. it is a good strategy to break the problem down into smaller pieces by defining functions or subroutines to perform smaller tasks.4.9 User defined functions and subroutines As the length and complexity of a computer program grows. USER DEFINED FUNCTIONS AND SUBROUTINES 69 4. To illustrate how to define your own function. mod(y.and. z do i = 1. here again is the greatest common factor program: program gcf2 implicit none integer :: a.y) if (mod(x. min(x.9. b == 0) then exit else gcf = getgcf(a. y) implicit none integer :: x.

however. y) result(z) implicit none integer :: x. To do this. i) == 0 . external :: getgcf This is the preferred F90 syntax. y. z do i = 1. i) == 0) z = i end do end function getgcf The result(z) indicates that the result will be passed back to the calling program as the variable z.) with the variables in the main program. FORTRAN integer function getgcf(x. Notice that we must declare getgcf in the calling program: integer. min(x. Note. mod(y. ASSIGNMENT F7 Modify your program from F6 to compute the least-common multiple as a userdefined function. i. etc. In some cases involving recursive functions (a more complicated topic that we may cover later). These arguments must match in number and type (real vs. . gcf in the calling program will assume the value of z in the function. we can use the optional ‘result’ specifier in the subroutine name: function getgcf(x. y) The variables x and y in the function will assume the values passed to the function by the main program. it may desirable to have the value returned to the main program be specified by a different variable name. Thus. although the following will also work: integer :: getgcf The name of the function is by default the value that will be passed back to the main program. y) if (mod(x. integer.and.70 The function getgcf definition begins with: CHAPTER 4. that they do not need to have the same names.

flon2. a subroutine to compute the distance and azimuth between any two points on the Earth’s surface: program userdist implicit none real lat1.ctheta2. . lon’ read *.del.theta1.9. & sang.azi.4. ’Enter 1st point lat.flon1. lat2.and.1 Subroutines Functions are limited in their usefulness because they are designed to pass only one value back to the calling program.saz.flat2.cang. ! subroutine SPH_AZI(flat1. lon1. azi = ’. flon1 == flon2) . which allows unlimited numbers of values to be passed to and from the calling program. azi) implicit none real :: flat1. A more general construct is the Fortran subroutine. lat1. lon1 print *. Here is our first geophysically useful example.theta2.and. del. lon’ read *. del. & phi1. & (flat1 == 90. ! For greater accuracy.) .or. azi) print *.stheta1. & (flat1 == -90. ’Enter 2nd point lat. flat2 == -90.raddeg. azi end do end program userdist ! SPH_AZI computes distance and azimuth between two points on sphere ! ! Inputs: flat1 = latitude of first point (degrees) ! flon2 = longitude of first point (degrees) ! flat2 = latitude of second point (degrees) ! flon2 = longitude of second point (degrees) ! Returns: del = angular separation between points (degrees) ! azi = azimuth at 1st point to 2nd point.lon on Earth ! ! (2) This routine is inaccurate for del less than about if ( (flat1 == flat2 . . del. lat2. lat2.ctheta1.and. lon2 call SPH_AZI(lat1.phi2. USER DEFINED FUNCTIONS AND SUBROUTINES 71 4.or. use double precision or perform a separate ! calculation for close ranges using Cartesian geometry.9. . lon1.5 degrees.’del.) ! ! Notes: ! ! (1) applies to geocentric not geographic lat.pi. flat2. flon1.ang. del. from N (deg. lon2.caz.) ) then del=0. flon2. flat2 == 90. lon2. azi do print *.

the other automatically changes as well. or someone else. theta1=(90. lon2. Clarity is important—I have seen versions of this routine that do not make clear whether . This may seem like overkill. as well as some of the limitations of the routine. Fortran is not case-sensitive so sph azi and SPH AZI have the same meaning. but documenting your subroutines as completely as possible is likely to save you considerable time later if you ever want to use the routine again.-flat1)*raddeg theta2=(90. However.caz) azi=az/raddeg if (azi.141592654 raddeg=pi/180. note that if flat1. then the corresponding variable would also be changed in the main program as well. the lat/lon values are passed to the subroutine while del and azi are passed back to the main program. lat1 in the main program and flat1 in the subroutine point to the same memory location. The subroutine is well-documented in this case. were changed in the subroutine. can use it correctly without having to study the code itself. return end if pi=3. end subroutine SPH_AZI The subroutine is called with the statement: call SPH_AZI(lat1.. If one is changed. FORTRAN azi=0.-flat2)*raddeg phi1=flon1*raddeg phi2=flon2*raddeg stheta1=sin(theta1) stheta2=sin(theta2) ctheta1=cos(theta1) ctheta2=cos(theta2) cang=stheta1*stheta2*cos(phi2-phi1)+ctheta1*ctheta2 ang=acos(cang) del=ang/raddeg sang=sqrt(1.72 CHAPTER 4.) azi=azi+360.-cang*cang) caz=(ctheta2-ctheta1*cang)/(sang*stheta1) saz=-stheta2*sin(phi1-phi2)/sang az=atan2(saz. It is good to document the routine well enough that you. I like to put subroutine names in all caps so they are more visible.0. lat2. azi) In this case. Note that sph azi does not have to be declared in the main program. lon1. explaining exactly what is going into the subroutine and what is going out. del.

flon2. given its radius. Listing the limits of the subroutine may help prevent future misuse of the routine.flat1. For example. E-mail me the source code in a single file containing both the main program and the subroutine.azi) print *.flat2.flat2.flon1.del. it need not be listed along with the source code of the main program.2 Linking to subroutines during compilation A powerful aspect of subroutines is that one can link to compiled versions of existing subroutines without having to recompile them. azi = ’. ASSIGNMENT F8 Write a single subroutine that computes the volume. in this example it may prevent the naive user from assuming that the distance returned is accurate when used with geographic latitude and longitude on the Earth. or vice versa. This means that you only have to maintain one version of a subroutine. 4. such as when the two points have the same coordinates.f Our main program could simply consist of: program userdist2 implicit none real flat1.flon2.’Enter 1st point lat. Allow the user to terminate the program by entering zero for the radius. surface area.9.flon2 call SPH_AZI(flat1. USER DEFINED FUNCTIONS AND SUBROUTINES 73 the azimuth is measured at the first point to the second point.lon’ read *.4.’Enter 2nd point lat.9.’del. The routine is also designed to be robust with respect to pathological inputs. del.flat2.azi do print *. we need to indicate where the SPH AZI subroutine can be found. the SPH AZI subroutine is also part of a F77 package of spherical geometry subroutines contained in: ~shearer/PROG/SUBS/sphere_subs. We want to link with what is called an ‘object file’ for the .flon1 print *.lon’ read *.del.flon1. azi end do end program userdist2 When we compile this program. together with a main program that inputs different values for the radius from the keyboard and prints the results. and circumference of a sphere.



subroutines. Object files end in .o and there is a sphere subs f90.o file in the same directory ( shearer/PROG/SUBS) as the source file sphere subs.f. You must link with object files that have been compiled using the same Fortran compiler as you use for the main program. When I switched to using gfortran from g77 a year or two ago, I had to recompile my subroutines in order for them to link properly with gfortran compiled code. I still occasionally run into this problem when I link to a subroutine I have not used in awhile. To create a F90 object file, enter, for example: gfortran -c someprogram.f90 -o someprogram.o You can also create a F90 object file from F77 source code: gfortran -c anotherprogram.f -o anotherprogram.o This will work on native F77 code that includes non-F90 compatible features (e.g., comment lines starting with C), because the F90 compiler sees that the source file ends in .f rather than .f90. To compile userdist2 and link to sphere subs.o, we enter: gfortran userdist2.f90 /home/shearer/PROG/SUBS/sphere_subs.o -o userdist2 This quickly becomes cumbersome to write so you will find it convenient to set up a Makefile to keep track of all this for you. Here is part of a Makefile that does this for this program: OBJS1= /home/shearer/PROG/SUBS/sphere_subs_f90.o

userdist2: Makefile userdist2.f90 $(OBJS1) gfortran userdist2.f90 $(OBJS1) -o userdist2 Note that you MUST use a tab to generate the spaces before ’gfortran’ for the Makefile to work correctly! This is a leading source of confusion for novice Makefile users. You can list the full path names for any number of subroutine object files in this way. To compile the program, simply enter: make userdist2



Study the SPH MID subroutine contained in sphere subs.f (in ∼shearer/PROG/SUBS). Write a program that uses this subroutine to compute the midpoint between two (lat,lon) points input by the user. Print out the latitude and longitude of this point. Do not attempt to copy the SPH MID source code, just link to the sphere subs f90.o object file. Make sure that the argument list for SPH MID in your program matches the subroutine arguments. E-mail me the source code and also tell me where the working executable version of the program is located. Be sure to give me execute permission so that I can try running your program. (Remember: ‘ls -l’ shows the current permissions, ‘chmod’ is how you change the permissions, ‘man chmod’ will explain this.) If you are at sea (!), then you may have to copy the sphere subs.f routines to your local machine. You can make an object file from them using gfortran -c sphere subs.f -o sphere subs.o


Internal procedures

The functions and subroutines that we discussed above are called ‘external’ because are located outside of the main program. With external procedures all of the values that are to passed into and out of the procedure must be part of the argument list. All other variables are local to the procedure or to the main program, even if they have the same name as a variable in a different procedure. External procedures are the only kind of procedure allowed in F77 and are what you will find in books like Numerical Recipes or in the subroutine libraries maintained by various scientists at SIO. Their great advantage is their portability—everything you need to know about what they do is contained in their argument list. However, in some cases it may be more convenient to use an ‘internal’ subroutine or function, a method that is new to F90. Internal procedures are listed immediately BEFORE the end statement in the main program. All variable names are shared within internal procedures; thus argument lists are not necessarily required for them to work. Here is an example adapted from the Brainard text that illustrates how internal subroutines work: program sort3 implicit none real :: a1, a2, a3

76 call read_numbers call sort_numbers call print_numbers contains subroutine read_numbers print *,’Enter three numbers’ read *, a1, a2, a3 end subroutine read_numbers subroutine sort_numbers if (a1 > a2) call swap(a1,a2) if (a1 > a3) call swap(a1,a3) if (a2 > a3) call swap(a2,a3) end subroutine sort_numbers subroutine print_numbers print *,’The sorted numbers are: ’ print *, a1, a2, a3 end subroutine print_numbers subroutine swap(x,y) real :: x, y, temp temp = x x = y y = temp end subroutine swap end program sort3


Internal procedures are listed following a ‘contains’ statement and before the end statement for the main program. Variables already declared in the main program need not be declared in the internal procedure. Arguments are optional; they are used here in the swap routine to permit it to be used for different pairs from a1, a2 and a3. Note that the procedures are not nested (e.g., one might have tried to put swap internal to sort numbers); internal procedures may not contain other internal procedures. Note also that variables declared within a subroutine are purely local to the subroutine. For example, the value for temp (in swap) is not available in the main program. Even if temp were declared in the main program, its value will not correspond to the value of temp in the swap subroutine (try it!). The use of internal subroutines is rather pointless in this case because the code would probably be clearer without them. However, for longer programs they may well be useful for making the code more structured. If you write a program and



notice that you are using the same block of code over and over again, this would a situation where using a subroutine would make sense. The advantage of an internal subroutine is that you don’t have to match the argument lists and declare all of the variables. External subroutines can become cumbersome when they involve a large number of variables. Often common blocks are used to avoid long argument lists in this case (more about this later). In many case, internal subroutines may provide a neater way to handle this situation.


Extended precision

By default, Fortran stores real variables using 4 bytes, providing a precision of about 6 to 7 significant figures over a range from (on the Suns) 1.175494e-38 to 3.402823e+38. If this is insufficient precision, then variables can be defined in double precision. In F77, this was done by declaring them as ‘double precision’ or ‘real*8’ variables. This syntax will still work, although F90 has introduced a new concept— the ‘kind’ specifier for variables. All of these methods are demonstrated in this program: program testdouble implicit none character (len = 30) :: fmt = "(a5,f44.40)" real a4 real*8 a8 double precision aa real (kind=4) :: k4 real (kind=8) :: k8 real (kind=16) :: k16 !only include if using 64-bit machine + compiler a4 = 8.9 print fmt, ’a4 = ’, a4 a8 = 8.9d0 print fmt, ’a8 = ’, a8 aa = 8.9d0 print fmt, ’aa = ’, aa k4 = 8.9 print fmt, ’k4 = ’, k4 k8 = 8.9_8 print fmt, ’k8 = ’, k8 k16 = 8.9_16 !only include if using 64-bit machine + compiler

78 print fmt, ’k16= ’, k16 end program testdouble

CHAPTER 4. FORTRAN !only include if using 64-bit machine + compiler

which produced the following output on my old Sun computer: a4 = a8 = aa = k4 = k8 = k16= 8.8999996185302734375000000000000000000000 8.9000000000000003552713678800500929355621 8.9000000000000003552713678800500929355621 8.8999996185302734375000000000000000000000 8.9000000000000003552713678800500929355621 8.900000000000000000000000000000000308148

and which produces the following output on my Mac running 32-bit gfortran: a4 a8 aa k4 k8 = = = = = 8.8999996185302734375000000000000000000000 8.9000000000000003552714000000000000000000 8.9000000000000003552714000000000000000000 8.8999996185302734375000000000000000000000 8.9000000000000003552714000000000000000000

after I comment out the k16 lines. Note that a4 and k4 are regular real*4 variables and approximate 8.9 as 8.999996. Much greater precision is obtained with a8, aa, and k8, which are all real*8 (double precision) variables. k16 is a real*16 variable (quadruple precision). NOTE: k16 does not currently work with 32-bit gfortran. Does it work on your computer? On the Suns, kind=4 is for single precision (4-byte real), kind=8 is for double precision (real*8), and kind=16 is for 16-byte real. Note that the precision of numbers may be specified by appending them with an underscore and the kind value. Thus we write 8.9 8 to indicate that 8.9 is to represented as an 8-byte real number. The use of ‘kind’ is intended to give you greater control over the degree of precision in your programs and ultimately make codes that are less platform dependent in their behavior. I’m not sure if this has been achieved! It appears that F90 also allows complex variables to be declared as double precision, something not allowed in F77. We will check if this is actually true later when we consider complex variables. IMPORTANT NOTE: You must define the extra-precision variables using numbers with the appropriate precision. If you write: a8 = 8.9 !***Not correct if a8 is real*8

you will get single precision accuracy. Even the ‘dble’ operator (which works in F77, at least on the Suns) will not work in F90 in assigning variables:

11.9d0 or k8 = 8.idy2. if they continue to be compiled using F77.imn2. EXTENDED PRECISION a8 = dble(8. Many of my existing F77 routines use dble( ) to define double precision numbers. or if the use of dble( ) in this way is non-standard Fortran. you must say k16 = 8.4. The key is to write: a8 = 8. You will want to use the DT TIMEDIF subroutine. and real*8 for timdif.9) !***Not correct if a8 is real*8 79 will assign a8 only at single precision accuracy.sc2.9_16 rather than k16=8.9d0 or k16=8. unless all of the dble( ) commands are rewritten.84d-2 is 0. which will assign k16 only to double precision accuracy. I don’t know if this is a bug in Sun F90. Make sure that all of the variables match and are of the same type (integer.timdif) !correct way to set double precision variables . that is: subroutine DT_TIMEDIF(iyr1. These will not work correctly if they are changed to F90. however.9 8.imon1. They are fine. To get the full 16-byte precision (only on the Suns or 64-bit Macs).23d3 is 1230.imon2.imn1.sc1.ihr2. the final argument). Have the program print out this number of seconds. You should also be aware that & in column 6 of F77 code is how lines are continued. 0.0084.idy1.ihr1. ASSIGNMENT F10 Examine the datetime. thus 1. etc.f source code in ∼shearer/PROG/SUBS (also see class website) and write a F90 program to compute the number of seconds that have elapsed since noon on your birth date (or the exact time if you know it) until a user specified date and time.9_8 Note that the 0 following the d is the power of 10. real. & iyr2.

i2. i4. you can do the same to store integers of varying sizes.1 Integer sizes Just as you can set aside fixed numbers of bytes for real numbers. using two different ways to define the integers: program testinteger implicit none integer*2 i2 integer i4 integer*8 i8 integer (kind=2) :: k2 integer (kind=4) :: k4 integer (kind=8) :: k8 i8 = 32000 i4 = i8 i2 = i8 print *. The following example program shows how this works. i8 i8 = 32000**2 i4 = i8 i2 = i8 print *. These are sometimes called short and long integers. i4. i2. i4.11. However. This will require using one of the other subroutines in datetime. i8 end program testinteger This will produce the output: . respectively. E-mail me the source code of your program. FORTRAN Extra credit: Determine the date and time when you will be (or were) exactly one billion seconds old. which have 32 bits and thus will go (approximately) from −231 to 231 . i2. The standard is 4-byte integers. CHAPTER 4. 2-byte and 8-byte integers are also allowed. i8 i8 = 32000 i8 = i8**4 i4 = i8 i2 = i8 print *.80 is actually all one line.f Mark your calendar for a party! 4.

dimension(100) :: a. real.2)).2)). even though they are not explicitly tested in the program. Older Fortran programs would define the same arrays as follows: real a(100).12. The new standard has the advantage. ARRAYS 32000 0 0 32000 1024000000 0 32000 1024000000 1048576000000000000 81 The zero fields in the output are incorrect and indicate that the number was too large to be stored in the given variable type. Also note that array elements are written using parentheses. Here is an example program that uses an array to compute prime numbers less than 100: . dimension(-100:100) :: a. k4 and k8 (defined using the kind statement) will give the same results. of being able to easily define many arrays with identical dimensions. Note that k2. Note that the default starting array number is 1 (not 0 as in C). dimension(50.1) to index(50. A nice feature of Fortran is that we can specify the lower and upper array boundaries explicitly in the declaration. dimension(0:50.4. 2) :: index In this case there are 201 values for a and b (from a(-100) to a(100)) and 102 values for index (from index(0. Regular integers suffice for most purposes. however. Short integers are useful to save space for data sets that don’t require bigger numbers (i.1) to index(50. b integer. beyond about ±32000).2) This syntax will still work and is easier to read for short programs. 4.2) :: index which defines a and b as 100 element arrays (a(1) to a(100)) and index as a 50x2 element array (index(1. e. b integer.12 Arrays Arrays are defined in F90 as in this example real. not brackets as in C..e.. b(100) integer index(50.g.

We need check numbers. i. set prod to 1) all multiples of 3. only up to sqrt(100) because larger factors would already have been eliminated. prod(maxnum). this list is the array prod. parameter :: maxnum=100 integer :: i. We then start with the number 2 and eliminate all multiples of 2 up to the maximum value of 1000. When we are finished.e. max_j prod(i*j) = 1 enddo end if end do do i = 2. FORTRAN program prime implicit none integer. this is all i such that prod(i) = 0.nprime end program prime The method is sometimes called the sieve of Eratosthenes. The strategy is to then flag numbers that are not prime by setting the corresponding array values to one. max_i if (prod(i) == 0) then max_j = maxnum/i do j = 2. max_i.. We count the number of primes using the counter variable nprime. maxnum if (prod(i) == 0) then nprime = nprime + 1 print "(i4)". we simply print out all numbers that were not eliminated. i end if enddo print *. named after a Greek mathematician from the 3rd century BC. j.82 CHAPTER 4. We can skip 4 because 4 and all its multiples were already eliminated. maxnum prod(i) = 0 enddo max_i = floor(sqrt(real(maxnum))) do i = 2. max_j. In the program. We start with a list of numbers from 2 to 100 and consider them all possible primes. ’Number of primes found = ’. We then move to 3 and eliminate (i. nprime=0 do i = 1. We initialize the array by setting its values to zero. In our case. A new aspect of this program is the defining of maxnum as a parameter: .

Here is the code: program prime2 implicit none integer. j. To to this. max_i if (prod(i) == 0) then max_j = maxnum/i do j = 2. Let’s modify the program to list 10 primes per line.4. we save the prime numbers in a separate array called pnum. max_j. Note that in the statement max_i = floor(sqrt(real(maxnum))) it is necessary to convert maxnum to a real number before taking the square root. pnum integer :: i. ARRAYS integer. parameter :: maxnum=1000 integer. maxnum if (prod(i) == 0) then nprime = nprime + 1 pnum(nprime) = i end if . if we had written sqrt(maxnum) we would have gotten an error during compilation. This is because the argument to the Fortran sqrt function must be real. nprime=0 do i = 1. maxnum prod(i) = 0 enddo max_i = floor(sqrt(real(maxnum))) do i = 2. parameter :: maxnum=100 83 This tells the program to set maxnum to 100 and that this value will never be changed during the program.12. max_i. This makes it easy for us to change the size of our prime search by changing the value of maxnum without having to change anything else in the program. dimension(maxnum) :: prod. This program lists the prime numbers with one number per output line and thus will become cumbersome for larger values of maxnum. max_j prod(i*j) = 1 enddo end if end do do i = 2. It also allows the array dimension for prod (in the next line) to be set by maxnum.

Array values can be assigned one element at a time. ’Number of primes found = ’. More complicated expressions are also possible. y =2 sets all y values to 2. Note that the format specifier 10i5 applies to the first 10 numbers and then is reused for the next 10. nprime) end program prime2 Note that we use the new F90 convention for setting up the arrays.84 CHAPTER 4. The individual elements can be specified if they are listed between ‘(/’ and ‘/)’ (Warning: Don’t put a space between . y end program testarray and its output: 1 2 3 15 30 40 1 1 1 2 2 2 Note that when an array is set to a scalar. FORTRAN enddo print *. but we do introduce a new concept in the output line: print "(10i5)". i. etc. print "(5(i4.. (i. i = 1. 40 /) print *. 3 /). The program is pretty self-explanatory. 2. The parentheses around (pnum. every array element is set to the value of the scalar.g. or can be assigned in single statements as in this F90 example: program testarray implicit none integer. y y = 2 print *. i=1.. nprime) will print the primes to the right of their count.nprime) are required.i4. nprime print "(10i5)". i = 1. nprime) This is termed an implicit do loop and is very useful in input/output (I/O) statements. y = 1 print *.e.2x))". e. (pnum(i). x x = (/ 15. x print *. (pnum(i). 30. i = 1. dimension(3) :: x = (/ 1. pnum(i).

There are some cases when we would prefer not to advance to the next line following a print statement."(i4)") i end if end if enddo print * print *. max_j prod(i*j) = 1 enddo end if end do do i = 2. pnum in program prime rather than wasting the three lines we used later to set all elements in prod to zero. ARRAYS 85 the / and the parenthesis!!). The number of values must match the dimension of the vector.10) /= 0) then write (*.12. We will discuss this more later when we consider two-dimensional arrays in detail. ’Number of primes found = ’. maxnum if (prod(i) == 0) then nprime = nprime + 1 if (mod(nprime. Instead. So we see that we could have written: integer. advance=’no’) i else write (*. max_i if (prod(i) == 0) then max_j = maxnum/i do j = 2.4. nprime=0 max_i = floor(sqrt(real(maxnum))) do i = 2. dimension(maxnum) :: prod = 0. we would like to have output continue on the same line. max_i.nprime end program prime3 The statement . Here is an example of how this can be used to print 10 prime numbers per line without having to store the prime numbers in a separate array: program prime3 implicit none integer. j. parameter :: maxnum=1000 integer :: i. max_j. prod(maxnum)=0."(i4)".

The statement write (*. except that it does not advance to the next line. "(i4)") i CHAPTER 4. FORTRAN works exactly the same as the print statement we used previously. a print * statement is needed to be sure that the final output (Number of primes found) is on a separate line.1 Checking for problems with the -fcheck=bounds option Suppose when writing the prime number program. Following the enddo. I don’t think this is standard Fortran so you may get into trouble at some point with this convention. Thus the above line could be replaced with print "(i4. However.86 write (*.$)". the carriage return (advancement to next line) can also be suppressed simply by adding a $ to the format statement.advance=’no’) i does the same thing. ‘write’ can go to the screen or to a file. we made the mistake of writing: max_j = maxnum rather than max_j = maxnum/i When the program is run. at some point the product i*j in the line prod(i*j) = 1 will exceed the array dimensions of prod (maxnum). The program will then start overwriting adjacent memory locations and disaster will result. The program checks to see if the prime count (nprime) is divisible by 10. under both F77 and F90. (‘print’ only goes to the screen. Most commonly the program will crash with the following kind of message: . NOTE: With the Suns. not free format). "(i4)". if not then the output does not advance. The * in the above write statement means standard output. 4. i and the result would be the same.12.

(in these cases. it is the -fcheck=bounds option and can be invoked either by compiling prime4 with: gfortran -fcheck=bounds prime4.f90 -o prime4 or changing the Makefile to: %: %. These are not very helpful error messages because they do not tell you where in the program the problem occurred. Here is an example program that prints out 20 random values from between 0 and 1. that I recommend that you ALWAYS use this option when you are first getting your programs to work. ASSIGNMENT F11 Fortran 90 includes a built in random number subroutine (called ‘random number’). and will save you so much time in debugging your programs.f90 gfortran -fcheck=bounds $< -o $* (remember the tab before gfortran!) If you have compiled your program with this option. so for programs where run time is a factor. However. you should then recompile without -fcheck=bounds for the final working version. upper bound of dimension 1 exceeded (1002 > 1000) This is so helpful.12. see below). It does slow the code somewhat. ARRAYS Bus error or Segmentation Fault 87 These types of errors result from exceeding array boundaries or mismatched subroutine arguments. there is usually a compiler option you can set that will provide more useful diagnostics. . you may also want to experiment with the -O compiler to make your code run faster.f90 Fortran runtime error: Array reference out of bounds for array ’prod’.4. For gfortran./prime4 At line 11 of file prime4. then the computer will check to see if your array indices exceed their boundaries and tell you where the problem occurs: shearer@katmai 324> .

2 More about random numbers To learn more about random number generators. For each random number generated.2. then add one to the appropriate array element to keep track of how many of the numbers are in that bin. Test the randomness by counting the number of these that fall in each of 10 evenly spaced bins between 0 and 1 (i. I have not tested the built-in F90 random number generator to see how well it measures up. 4. you want any problems to be completely reproducible. xran enddo end program listrand CHAPTER 4. But this requires the user to think of different input numbers.e. To avoid this. if you are debugging a program. But in other cases. For example. 0 to 0. 20 call random_number(xran) print *. please consult the book Numerical Recipes.88 program listrand integer :: i real :: xran do i = 1. Here is an example of what your output might look like: 0 1 2 3 4 5 6 7 8 9 1009 1048 1001 1038 1008 959 993 925 1017 1002 HINT: Set up an integer array with 10 elements and initialize all the values to zero. which has a discussion about good algorithms and bad algorithms.1. Print these counts to the screen.12. we can .. but it seems pretty good for most purposes.).1 to 0. 0. FORTRAN Write a simple F90 program to generate 10000 random numbers between 0 and 1. You may notice that if you use random number in a program that you will get the same numbers every time you run the program. you will want to get different results each time. This is desirable in many cases. etc. One simple way to achieve this would be to ask the user to input an integer and then compute that many random numbers before continuing to the main program.

4.. ARRAYS 89 randomize the start of the random number generator itself by using some number that will always be different. This turns out to be annoyingly hard to do in F90. make sure that seed is dimensioned to narg. narg integer. e.y) . count_rate. narg changed from 8 to 12 and I had to rewrite this little program. ’idate = ’. ’seed = ’. xran enddo end program listrandseed Once you have this working. count.12.g. count_max) seed(1) = count seed(2:9) = idate(8:1:-1) seed(10:12) = idate(6:8) print *. 20 call random_number(xran) print *. count_max. narg call random_seed(PUT=seed) do i = 1.12.3 Arrays as subroutine arguments Suppose we have defined an array x as: integer :: x(100) If we use x in the argument list for a subroutine. for example from the system clock on the computer. When I recently changed computers. seed call random_seed(SIZE=narg) print *.n. ’narg = ’. Here is an example program: program listrandseed implicit none integer :: i. call SUMTOT(x. count_rate. dimension(8) :: idate integer. you may want to remove the print statements in the random seed part. But before doing so. idate call system_clock(count. 4. dimension(12) :: seed real :: xran ! randomize start of random numbers call date_and_time(VALUES=idate) print *.

13 Character strings A character string may be declared in F90 as follows: character (len = 20) :: name declares the variable “name” to be a character string of length 20. regardless of any trailing blanks Substrings may be obtained as follows for name = “Bill Clinton”: . We will discuss later how to write subroutines that will work for arrays of differing size in the calling program. 4.90 CHAPTER 4. FORTRAN we include x without any parentheses. then trailing blanks are added so name actually is “Bill Clinton ” If. One can also define an array of character strings: character (len = 20). then name would contain “Bill Clint” as the extra letters would be cut off (no error results).g. on the other hand. e. The length of a character string may be obtained with the len function: len("Bill") will give 4 len(" ") will give 2 len(name) will give 20 if name was declared as 20 characters long. name was declared as 10 characters long.. name_array(100)*20 or character*20 name. name = "Bill Clinton" The quotes (apostrophes will also work) are required. The subroutine argument list must also include a matching array of the same size. All array values are passed to and from the subroutine. dimension(100) :: name_array The old F77 ways to define these strings will still work in F90: character name*20. name_array(100) A string variable can be assigned as. If name in this case was declared as 20 characters long.

Note the blank before “was” is necessary for there to be a space between the word. This can be done with the built in function len trim. the “trim” function is very useful. Another built in function is called “trim” which gives the string without any trailing blanks. For example. the built in funtion index can be used: index("Clinton". When trailing blanks are present.4. CHARACTER STRINGS name(1:4) is "Bill" name(6:12) is "Clinton" name(6:6) is "C" Thus. the // operator can be used: text1 = "Bill Clinton" // " was elected in 1992. "in") returns 3 index("Clinton". we could change the last name as follows: name = "Bill Clinton" name(6:12) = "Jones " Note that the trailing blanks are necessary to overwrite the “on” The following moves the string one character to the right: name(2:13) = name(1:12) This was not allowed in F77 (because of the overlap) but is OK in F90." sets text1 to the complete sentence (text1 must have been already declared of sufficient length). To find the position of a substring within a string. 91 Often one wants to know the length of a string without any trailing blanks. then name = "Bill Clinton" text1 = name // " was elected in 1992" sets text1 to: Bill Clinton was elected in 1992 .13. "no") returns 0 (indicates string not found) To append one string onto the end of another (concatenation). "on") returns 6 index("Clinton". if name is declared as 20 characters long.

Thus Bill Clinton would be read in as “Bill” (unless the full name were enclosed in quotes. name is not recommended in this case because it will only read until the first blank. The free format read statement: read *. There is an online version of the original program at: http://chayden.index(name.” the David Lodge satire of academia." end if end program vote Note the format for the read statement: read "(a)".92 while CHAPTER 4. "Then you are likely a Democrat. ASSIGNMENT F12 Write a simple version of the famous 1960s program." else if (index(name. ’Who did you vote for in 1992?’ read "(a)".’ush’) /= 0) then print *." else print *.’lin’) /= 0) then print *. FORTRAN text1 = trim(name) // " was elected in 1992" will produce the correct result. A humorous fictional account of such a program is contained in “Small World."Then you are likely a Republican. name does not need to use a80 although that would also work. Here is an example program that illustrates how to input a string: program vote implicit none character (len = 80) :: name print *.or. that simulates a psychologist talking to a patient.’eor’) /= 0 .index( but who wants to make the user do that?). name if (index(name. Begin your program by asking the patient: ."Then you are likely an independent voter.html Programs of this type are now called “bots” and examples can be found at alicebot.’ill’) /= 0 .

computes their product.14. Your program will be more realistic if you use random numbers (see above) to randomly select from a series of possible responses so that the computer does not keep saying the same thing." If you identify no key words on your list. Search this line for various key words that you can then use to guide the computer’s response. Why is it important to you?" If the string contains "!". respond: "There is no need for that kind of language. Design the program so that it will continue this “conversation” between doctor and patient. outfile integer :: i. What is really bothering you?" If the string contains "mother" then respond: "Tell me more about your mother. 4. Here is a program that reads pairs of numbers from an input file. all off our examples have involved input from the keyboard and output to the screen. y. then respond with something generic like: "Go on. ios real :: x. then respond: "You seem pretty upset. and outputs the original numbers and their product to an output file. program fileinout implicit none character (len=100) :: infile. z print *. Some suggestions: If the input string contains a "?". infile ." or "Tell me more about it." If the string contains any swear words. and write data to them.4. ’Enter input file name’ read "(a)".14 I/O with files So far. read from them. then respond: "Let me ask the questions. I/O WITH FILES "How are you?" 93 Then use the index function to input a line from the user/patient." Be creative but don’t spend an infinite amount of time on this assignment. Now let us see how to open files.

This statement opens the file with unit 11. file=infile. Another value for status is: . you will reach the end of the file immediately and the program will terminate without any obvious errors (except that you will now have zero length files in your directory!). outfile open (12. status=’old’) print *. file=infile is what provides the filename. y if (ios < 0) then exit else if (ios > 0) then print *. If you have not set status=’old’ then the program will create a new file and when you try to read from it.94 open (11. unit 5 is defined as the default standard (keyboard) input and unit 6 is defined as the default standard (monitor) output. ’***Warning. status=’old’) Files must be assigned “unit numbers” for I/O. file=outfile) CHAPTER 4. i cycle endif z = x * y write (12. FORTRAN do i = 1. iostat = ios) x.*. then the program will terminate and print an error condition. file=infile. z enddo close (11) close (12) end program fileinout We open the input file with the statement: open (11. y. On most systems. I have gotten into the habit of using units 11. 999999999 !more lines than any likely input file read (11. Note that we could “hardwire” a file name here by writing: open (11. 12 and 13 for most of my I/O. When you say status=’old’ and the file does not exist. status=’old’) The status=’old’ is optional. read error on line: ’. so these numbers should always be avoided as unit numbers. file="file1". but I recommend always using it for opening files which should already exist.*) x. ’Enter output file name’ read "(a)".

y This does a free-format read from unit 11 (for a fixed format. a priori.). the * is replaced with a format specifier such as “(i2. This is why we use “i” in the do loop. Because we do not know. we need some way to recognize when we have reached the end of the file (EOF). i cycle endif For ios < 0. read error on line: ’. ’***Warning. the result being an erroneous duplicate line in the output file. iostat = ios) x. we use “cycle” to skip this line and read the next line. We read data from the input file with the statement: read (11. and negative if the end of the file is reached. The “iostat = ios” specifier does this by assigning the local variable ios (which we must declare as an integer) that is zero for a normal read. Without the “cycle”. *. they will say something like: . how long the input file is. the program would write an output line using the same values of x and y used for the previous line. This assigns unit 12 to the output file (the input and output file unit numbers must be different!). we check its values to see if there is an EOF or error condition: if (ios < 0) then exit else if (ios > 0) then print *. 2f6. we exit the do loop because there are no more lines to read.2)” etc. For ios > 0. Rather. Once ios has been set. Being able to print the line number is useful because otherwise we would not know where to look for the problem in a big input file. Note that we are free to choose any name for ios that we want as long as it is declared as an integer.file=outfile) so that we can overwrite existing file names.4. in this example we choose to simply write: open (12. we print a warning message and specify the line number.14. I/O WITH FILES status=’new’ file must not already exist (useful to avoid overwriting existing files) 95 However. Following the warning message. We should note at this point that older Fortran programs do not use this method of testing for the end of the file. positive if there is an error during the read.

after the EOF but before we end the program it is good practice to close the files: close (11) close (12) . *. Continuing to examine the program fileinout. end = 123) x. y CHAPTER 4. Finally. In the new approach.*. the program crashes on the faulty input. we write the original numbers and their product using a free format write to unit 12: write (12. y. using the iostat= convention. despite this there is one aspect in which the old way of doing things is better than the new way. y if (ios < 0) exit z = x * y write (12. z enddo In this case.f90. Suppose there is an error in the input file. In the old way of doing things. z Note that x and y will probably not be in the same format as in the input file. In the old way of doing things. you should never write code like this: ! example of what NOT to do! do read (11.*) x.96 read (11. FORTRAN where 123 is a statement label that the program will branch to when the end of file is reached. The result will be that the output file will repeat the results from the previous line. This method still works in F90 but you lose style points for having to use a statement label. however. But this code does not check for this and will therefore continue running. This is not good. any read errors are ignored. the program will crash on the faulty input. iostat = ios) x. for example a stray character in one of the input lines instead of two numbers. You never want to ignore errors without at least being aware of them. However. because we have introduced an error into the output that might not be immediately obvious.*) x. any input error would be flagged by assigning a positive number to ios. So if you use iostat= then you always should explicitly look for errors. retaining the previous values for x and y. y. In other words.

000 -2. 1:3) = (/ 1.000 -10.000 0.000 0. Output the 5 “demeaned” numbers to an output file. MORE ABOUT MULTI-DIMENSIONAL ARRAYS although the files will be closed automatically anyway when the program ends. ASSIGNMENT F13 97 Write a program that reads from a text file containing 5 numbers per line. dimension(2. 3 /) a(2.f90” program listed above as a template for the file handling part of your code.000 1.000 2.000 20.000 0.000 10. Allow the user to specify the input and output file names.000 0. dimension(2. Here is a test program that illustrates how the numbers in a can be specified and how they are stored in memory: program testmatrix implicit none integer.000 0. For example.000 0. 6 /) print *. 5.000 Hint: Use the “fileinout.3) integer.000 0. 1:3) = (/ 4.000 -2.15 More about multi-dimensional arrays Two-dimensional arrays in Fortran may be defined as follows: integer a(2.000 -4.000 2. if the input file contains: 10 20 1 2 3 2 4 6 5 5 5 30 40 50 4 5 8 10 5 5 your program should write to the output file: -20.15. and the second from 1 to 3 (recall that the default starting array index is 1 in Fortran).000 4. a end program testmatrix .000 0.3) :: a a(1. Compute the mean of the 5 numbers and then subtract the mean from each of the 5 original numbers.3) :: a !F77 convention !F90 convention This defines a matrix in which the first indices will vary from 1 to 2. 2. 4.000 -1.4.

1). The ‘print *. a(2.1).1) b(2.npts) where i is the seismogram number. We have a filtering subroutine that will act on a single time series vector. 3 /) is an example of what is called an “array constructor” and is a sequence of scalar values along one array dimension only.2.2) b(1.1.2) This is important to remember when passing arrays to and from subroutines for cases when the array in the main program has more dimensions than the array in the subroutine.2)=2. a(2. 2. and a(1. i) and would be of the form: .1. If we dimension the array in the main program as b(1000.3)=3.2). a(1.2) b(2. 1:3) = (/ 1. for example: a(1.1. Finally note how the array is printed.1. a(1. For example. 2.1) b(2. a’ statement will dump the values of a in the same order that they are stored in memory. Fortran varies the first array element first.i).1)=1.1) b(1.2) b(2. note how the array values are specified. FORTRAN First.1) b(1. (/ 1. the result is: a(1.2). etc. suppose we wished to store 100 seismograms of 1000 points each in the main program.2) would be stored as: b(1.2. 3 /) thus setting a(1.2. The filter can then act on b(1:npts.3).2. a(1. a(2.98 The output of this program is: 1 4 2 5 3 6 CHAPTER 4. In this case.100) then we can call the subroutine using a statement like: call FILTER(b(1. In doing this. then the second.3) Similarly a three-order array b(2.2. We equate this to the desired part of the a matrix by writing.

1.3)". -7.3) enddo end subroutine PRINTMAT end program matmult .j) = c(i. -1. .1:3) = (/ -5.j) + a(i. 3.2 /) b(3.1000) because then each 1000-point time series would not be continuous in memory.4. 0.2 /) a(2.1:3) = (/ -5. "Matrix c = a*b follows" call PRINTMAT(c) contains subroutine PRINTMAT(x) real. Note that this would not work if the array was dimensioned as b(100.1:3) = (/ 9.1:3) = (/ -1. -6.j) = 0.5 /) b(2. -2.3 /) a(3.j). 3.j) enddo enddo enddo print *.3.3) :: a.8. dimension(3.1:3) = (/ -8. 99 This is a very common type of construction. -1.1. j. 3 print "(3f8. b.0. "Matrix b follows" call PRINTMAT(b) print *.15. j=1.2.0 do k = 1. 3.k) * b(k.1. dimension(n) :: c . 3 c(i. MORE ABOUT MULTI-DIMENSIONAL ARRAYS subroutine FILTER(c. 3 c(i.0 /) do i = 1.2 /) b(1.3. 3 do j = 1. 4.1:3) = (/ 9. 2.3) :: x do i = 1. "Matrix a follows" call PRINTMAT(a) print *. c integer :: i.4. Here is an example program to multiply two matrices: program matmult implicit none real. k a(1. (x(i. n) real. dimension(3.

This is very handle to cut off the trailing blanks and limit unnecessary extra spaces (and sometimes lines) in the output.100 CHAPTER 4.5 7. This example performs the matrix multiplication exactly as one would in F77. FORTRAN Note the use of the internal subroutine PRINTMAT to display the results. Thus.6 980205 08:45:22. Here is an example of this: program stringarray implicit none character (len = 80).42 10.6 . trim(name(2)) end program stringarray The program can store up to 10 name of 80 characters each.1 Arrays of strings As we have discussed..2 6. MATMUL.16 A more complex example of data processing Suppose we have a data file (e.8 10. Add another subroutine that computes the transpose of a square matrix. "Our last president was ".g. 4.8 11.15. it does not take advantage of some of the new array capabilities of F90.2 9. 4. there is a built in function. a string is just an array of characters. In fact. datafile1) that contains a series of measurements that has the following form: 980204 22:03:34. in F90 that performs matrix multiplication. Compute the transpose of c and add this to the output listing. dimension(10) :: name name(1) = "Bill Clinton" name(2) = "George Bush" print *. a 1-D array of strings will be a 2-D character array.20 5. "Our current president is ". trim(name(1)) print *. Note the use of the ‘trim’ function when printing the names. ASSIGNMENT F14 Modify the matmult program so that the matrix multiplication is done in a subroutine. My plan is to have more to say about these special F90 capabilities later in the class.

4.16. A MORE COMPLEX EXAMPLE OF DATA PROCESSING 980205 20:13:42.88 15.0 13.8 12.9 14.2 etc.


The structure is that there are date/time identifiers and then a series of measurements made at that time. The problem in reading this file is that we don’t know how many measurement lines will follow each date/time line so we can’t simply perform a formatted read on each line from the file. Let us assume that we want to compute the mean of these measurements and write a new file which stores this information on the same line as the date/time. In this case, our desired output file (e.g., datafile2) will look like: 980204 22:03:34.42 980205 08:45:22.20 980205 20:13:42.88 10.60 6.43 13.97 4 3 4

where the final column gives the number of measurements. Here is how such a program could be written: program procfile implicit none character (len=100) :: infile, outfile character (len=20) :: linebuf, event integer :: ios, nevent=0, ndata=0 real :: x, sum=0.0, xavg print *, ’Enter input file name’ read "(a)", infile open (11, file=infile, status=’old’) print *, ’Enter output file name’ read "(a)", outfile open (12, file=outfile) do read (11,’(a)’, iostat = ios) linebuf if (ios < 0) exit if (linebuf(1:1) /= ’ ’) then ! no init blank, must be event nevent = nevent + 1 if (nevent /= 1) then !need to output previous event info call WRITE_EVENT ndata = 0 sum = 0 end if

102 event = linebuf else read (linebuf,*) x sum = sum + x ndata = ndata + 1 end if enddo call WRITE_EVENT close (11) close (12) contains

CHAPTER 4. FORTRAN ! has starting blank, must be measurement

subroutine WRITE_EVENT if (ndata /= 0) then xavg = sum/real(ndata) else xavg = 0. end if write (12,"(a20, f7.2, i5)") event, xavg, ndata end subroutine WRITE_EVENT end program procfile The beginning of the program where the files are opened is the same as in fileinout.f90 (our earlier example of file I/O). Using an infinite do loop, we read lines from the input file using: read (11,’(a)’, iostat = ios) linebuf Because we don’t know the format of each line before we read it, we read into a character string (linebuf) that will serve to temporary store the contents of the line (a line “buffer” as they say in the computer world). We use iostat=ios to set ios to a flag that can be used to identify when the end of the file occurs so that we can exit the do loop. As discussed previously, we really should also check for an error condition (i.e., ios > 0), but we don’t bother here because errors are unlikely when reading in a string (yes, we are being a bit sloppy!). Next, we check the contents of the first character in linebuf. If is not a blank, then we know we have an event line. In this case we increment the nevent counter variable by one. If we have not just read the first event, then we have read a new event, thus terminating the data input from the previous event. In this case we need to write the processed event info to the output file (we can’t do this until this



point because we don’t know how many data points there will be) and reset sum and ndata to zero. Finally we set event = linebuf to store the event line until we need to output it. If, on the other hand, the first character in linebuf is blank, then we have a data line. We then read the value of x out of linebuf: read (linebuf,*) x This is called an “internal read” and is the first time that we have shown this. It allows the program to do a formatted read from a string, rather than from an external file. We do a free format read (*), but one could also use a format specifier. After reading the measurement value into x, we suitably increment a running sum of x and the number of measurements. When we reach the end of the input file, we have to output the results of the final set of measurements. To avoid repeating a block of code for this operation, we use an F90 internal subroutine (WRITE EVENT). This is used twice, inside the loop as we output information from the last event before going on to the next one, and outside the loop where we output the information from the last event. Note that we must check to see if there are no measurements for an event line, in which case we do not divide by zero but simply set xavg to zero. There should be no possibility of mistaking this for a real measurement in the output file because the number of measurements in this case will also be zero. ASSIGNMENT F15 Obtain the data file, scsn.phase.dat, from the class web site. This is a list of earthquakes and arrival time data from the Southern California Seismic Network (SCSN) for the first two days of August 2000. (Files like this are readily obtainable from the SCEC Data Center at if you ever want to obtain more of these data. The format is called the SCEC DC phase format.) Here is what part of the file looks like: 2000/08/01 14:44:12.6 L 1.1 WRC VHZ 911 P IU1 WCS VHZ 885 P E 3 WVP VHZ 925 P IU1 TOW VHZ 813 P E 2 CLC VHZ 202 P E 2 WMF VHZ 906 P E 3 c 35.962 -117.693 4.41 1.26 9.98 1.85 11.54 2.25 18.28 3.78 18.49 3.37 22.86 3.94 5.2 A 9159024 8 51 0 0

104 WMF VHZ 906 S E 2 22.86 7.08 WNM VHZ 908 P E 3 23.74 4.23 2000/08/01 14:45:36.8 L 1.3 h 34.806 -116.271 CDY VHZ 184 P IU0 6.66 1.73 RAG VHZ 1034 P IU1 17.58 3.19 RAG VHZ 1034 S E 2 17.58 5.77 RMM VHZ 647 P ID1 37.23 6.33 TPM VHZ 1033 P IU1 52.29 8.88 GRP VHZ 355 P IU1 61.21 10.14 0299 C 65535 P IU1 11395.79 7.39 2000/08/01 15:04:17.9 L 1.4 h 34.810 -116.268 CDY VHZ 184 P IU0 6.76 1.73 RAG VHZ 1034 P IU1 17.76 3.16 etc.


7.3 A 9159025





7.1 A 9159030





There is a line for each earthquake with the date and time (UT not local time). For the first line in the above example, the additional bits include: L = local event 1.1 = magnitude c = how magnitude was computed (coda in this case) 35.962 = lat -117.693 = lon 5.2 = depth (km) A = SCSN assigned quality (A=best) 9159024 = cusp id number 8 = number of lines of phase arrival time info The station info lines include: WRC = station name VHZ = station channel 911 = ? P = phase name (normally P or S) IU1 = phase pick info 4.41 = station-event distance (km) 1.26 = travel time (s from event origin time)

(=X for assignment) (=T for assignment)

Your task is to write a F90 program to read this file and write to an output file a series of (X,T) points with (one X-T pair per line) for all P arrivals for all events between 3 and 8 km depth. Then make an X-Y plot of the T-X points using whatever plotting method you are most familiar with. That is, plot time on the y-axis and distance on the x-axis and plot the coordinates of each point. E-mail me a copy of the F90 program source code and a PDF file of the X-Y plot. The good news about this data format is that it does include a number in the event line that lists the number of phase lines that will follow. The bad news is that sometimes the last 1 or 2 phase lines are “garbage” in that they have numbers



instead of station names and are some kind of calibration info. You will have to figure out how to recognize and discard these lines in your program. Also the phase lines begin with a tab character rather than a long series of blanks; this may complicate things somewhat. Hint: Don’t try to write your entire program all at once. First, get a version working that simply reads the input file and prints out the parts of each line that you will need (i.e., the depth and number of phase lines for the event line, the phase name and the X and P values for the phase lines). Once you have this working correctly, then go on to add the part to output the (X,T) points.


Example sorting routine from Numerical Recipes

The book Numerical Recipes contains a large number of useful subroutines (there are both Fortran and C versions) that are fully explained in the text. You can find F77 source code (1st edition of NR) for these routines in: ~shearer/PROG/SUBS/NUMRECIP To illustrate the use of the Numerical Recipes routines, here is an example program that generates a list of random numbers, sorts them using the NR function piksrt, and then prints out the sorted list. program sortrand implicit none integer, parameter :: NPTS=100 integer :: i real, dimension(npts) :: xran do i = 1, NPTS call random_number(xran(i)) enddo call PIKSRT(NPTS,xran) print "(10f7.4)", (xran(i), i=1,npts) end program sortrand The program sets the xran array to random numbers. It then calls the NR subroutine PIKSRT to sort the numbers before printing them out. We must either include the PIKSRT source code or link with a PIKSRT object code when we compile this program. Here is the PIKSRT source code:

o which will create a piksrt f90. we could just append the source code onto the end of our program.o file (replace f90 with gfortran if you are using gfortran).106 SUBROUTINE PIKSRT(N. so it is safest to separately compile the source code in each case). Unfortunately.1. In general.N A=ARR(J) DO 11 I=J-1. and uses ‘continue’ statements in the do loops. it’s better than many examples. does not have these problems and is fully F90 compatible. however.f -o piksrt_f90. ASSIGNMENT F16 . It has all capital letters and has line numbers.ARR) DIMENSION ARR(N) DO 12 J=2. FORTRAN 11 10 12 This ugly code is typical of old Fortran programs. f77 and f90 object files are not always compatible (they are in this case.o -o sortrand or by using a Makefile as discussed earlier. This example.LE. F77 and older code will not compile under F90 because of old-style comment lines (‘C’ in column 1) and old-style line continuation flags (non-& character in column 6). This would be our best choice if the subroutine source code is lengthy and/or is non-F90 compatible. The important thing for us is that the code works—we don’t want to bother rewriting it and possibly breaking it.-1 IF(ARR(I). Actually. ‘go to’ statements.f90 piksrt_f90. because the do loops are indented. Thus. f90 sortrand.A)GO TO 10 ARR(I+1)=ARR(I) CONTINUE I=0 ARR(I+1)=A CONTINUE RETURN END CHAPTER 4. Alternatively. but it is dangerous to assume that they always will be.o with a f77 program. The f90 is my own convention to label f77 source code that has been compiled under f90 so that I don’t try to link piksrt f90. we could compile the subroutine under F90 as follows: f90 -c piksrt.

However. Do the median computation in the form of a subroutine that returns the median value. Southern California GPS sites are usually identified with 4 character names. The random number generation should be in your main program. for example. xmed) !x=array. but does NOT resort the input array in the process. It would be much faster to read the station information file once and then save the information during the time that the program is running. For portability. you can simply call the same subroutine.g. and close the file every time we need to determine a station location.18 Example of saving values in a subroutine A common convention in geophysics is to name an instrument site with a short ascii string.18.. file I/O is relatively slow so we won’t want to open. read. Make sure that your program gives the correct result for both even and odd numbers of points. Then whenever you need to compute a median of some numbers within a program. xmed=median Hint: Within your median-computing subroutine. 4. without including information about the station.4. given the station name. Thus. e. In seismology. Data processing programs will often require this information. n=# of points. Often data products are labeled by the station name. but this would become very cumbersome for large numbers of stations and would limit the flexibility and portability of the code. such as its location. A better approach is to save the station information in a file and have the computer read from the file to access the information when necessary. ideally all of this overhead would be performed in a function that we could use in many programs without having to worry about the format of the station file or the size of the array that are required to store it. n. not within the MEDIAN subroutine which should be a general purpose routine that simply inputs an array of numbers and returns the median value. copy the input array to another array before calling PIKSRT. call MEDIAN(x. station names are usually designated with 3 to 4 character names. there is frequently a need for a computer routine that will retrieve information about a station. EXAMPLE OF SAVING VALUES IN A SUBROUTINE 107 Modify the sortrand program to return the median of a user-specified number of random numbers. One could hardwire this information into the program with a series of if statements. .

i1. slon.0) enddo 7 . flon.NMAX read (11. slat(i). slon. parameter :: NMAX=5000 character (len = 4) :: snam character (len = 4).selev = ’. f10. felev integer :: i.’(a)’) stname if (stname == ’stop’) exit call GET_STAT(stname. open (11.false.selev enddo end program testgetstat ! subroutine GET_STAT gets the lat/lon/elev of a station ! with a given name from the GSN station list ! ! Inputs: snam = station name (a4) ! Returns: flat = station latitude ! flon = station longitude ! felev = station elevation (m) ! NOTES: Station list must be alphabetized ! If station name is not found. FORTRAN In order to do this. ’slat.true. selev. ’Enter station name (stop to stop)’ read (*. slon. selev do print *.slon. dimension(NMAX) :: slat. save firstcall.slat.slat.7. slon(i). we need to retain the values of certain variables within the function for subsequent calls. then returned ! variables are set to -999. slat.5.gsn’ do i=1.selev) print *. stname. selev real :: flat. ’Reading station file: stlist.108 CHAPTER 4. nsta if (firstcall) then firstcall = .gsn’.flon. nsta. status=’old’) print *. file=’stlist. selev(i) format (a4. i2.flat. f11.slon.slon.end=12) stname(i).5. f5. dimension(NMAX) :: stname real.felev) implicit none integer. it logical :: firstcall = . program testgetstat implicit none character (len = 4) :: stname real :: slat. Here is an example that will return station coordinates for some of the GSN (Global Seismic Network) stations. ! Program reads and saves station info on first call ! subroutine GET_STAT(snam.

the first time (and only the first time) that the subroutine is called.NMAX i = NMAX + 1 12 nsta = i-1 close (11) print *. firstcall can have two possible values: . Normally. the values of variables in a subroutine are not retained between calls. felev = -999. EXAMPLE OF SAVING VALUES IN A SUBROUTINE 109 print *. flon = -999.nsta end if i1 = 1 i2 = nsta do it = 1.18.true.4. end subroutine GET_STAT The main program is a short driver program that enables us to test that the GET STAT subroutine is working properly. ’***station not found ’. It is always a good idea to use little programs like this to test functions that are being developed. This is our first example of a logical variable: logical :: firstcall = .true. 15 i = (i1+i2)/2 if (snam == stname(i)) then flat = slat(i) flon = slon(i) felev = selev(i) return else if (snam < stname(i)) then i2 = i-1 else i1 = i+1 end if enddo print *. snam flat = -999.true.’Number of stations read = ’. Here we set it to . The save statement specifies which variable values are to be saved between subroutine calls: .false. or . It then saves the information in memory to use for subsequent calls. the subroutine reads the station file only the first time the subroutine is called.’***Warning: number of stations in file may exceed ’. BEFORE using the functions in larger programs. The “save” command is used to specify those variables that are to be saved between calls. For efficiency.

76560 2442 AAK 42. we write if (firstcall) then Notice that a logical variable can be the sole argument for an if test. For example.94620 -106. they are set to 1 and nsta. so that this block of code will not be excuting upon subsequent calls to the subroutine.88370 -176. slat. the subroutine does not simply loop through the station list until it finds a match. slon. Or perhaps the firstcall flag is not working properly. FORTRAN save firstcall. This reminds the user of the program about what is being done and it helpful in case there is a problem or error later in the program.35389 13.45670 1840 ANMO 34. stname.false. in which case these output lines will result each time we call the routine.35000 60 ALQ 34. Next.77730 706 ALE 82. it exploits that fact that the stations are in alphabetical order. perhaps we have a faulty station file that has only 1 station.11890 678 ADK 51.50330 -62. i1 and i2 are indices that are designed to bracket the target station in the list. then i1 is set to i+1. Initially. (2e15 must be greater than NMAX to make sure we do enough iterations) Note that . not just the first time.02920 38. The station file has the form: AAE 9.68440 116 AFI -13. nsta To read the station file upon the first call to the subroutine. For speed.90930 -171.94620 -106. then we can set the return variables.86890 32. In routines like this.63900 74.40500 720 . then i2 is set to i-1.49400 1645 ABKT 37. If they are the same. Instead.79359 883 AQU 42. The station in the station list at i is compared to the target station. selev. We iterate using this procedure 15 times to narrow in on the station name. If the stlist station is less than the target station.110 CHAPTER 4.93040 58. i is set to a point halfway between i1 and i2.45670 1840 ANTO 39. . the first and last station indices. I like to print out information about the file that is being read during the first call. We then set firstcall = . If the stlist station is greater than the target station (later in the alphabet).

19 Complex numbers A nice feature of Fortran is that complex numbers are a standard feature.o Don’t bother to do the separate calculation for small values of del. 111 If we don’t find the target stname in the station list. slon and sdep are passed back from the function to the main program.19. a print *. c print *. b. slat. slon. you will need to be able to compute the distance between two points on a sphere. stname. c print *. b c = a*b print *. 4. slat. Name your new function NEAR STAT and also include a testnearstat driver program to test the operation of the function. abs(c) print *. We also set the station coordinates to numbers that are unlikely to be confused with real station locations in case the user of the function does not notice the warning message (or chooses to ignore it!). COMPLEX NUMBERS else if (snam < stname(i)) then is a valid check to see if string variables are in alphabetical order. lon) point and return the station name and its coordinates. ’Enter second complex number’ read *. sqrt(c) end program testcomplex . The NEAR STAT suboutine should be of the form: subroutine NEAR_STAT(plat. To find the nearest station. ’sqrt of product = ’. ’Product = ’.4. then we print out a warning message. plon. sdep) where plat and plon are the coordinates going into the subroutine and stname. ASSIGNMENT F17 Modify GET STAT to find the nearest station to a given (lat.gsn file from http://igppweb. You can get the shearer/SIO233/. Here is a program to show how they can be declared and used: program testcomplex implicit none complex :: a. ’abs of product = ’.ucsd. ’Enter first complex number’ read *. Use the SPH AZI from the notes or the SPH DIST subroutine from ∼shearer/SUBS/sphere subs.

second number is the imaginary part).7211103 sqrt of product = (0. Notice that in F90 you don’t need to use special forms for the functions abs and sqrt (e.112 Here is an example of running the program: rock% testcomplex Enter first complex number (1. If you try to enter or or even 1. ’Imag part = ’. .4) abs of product = 0. ’a = ’.6. ai) print *. ’Enter imaginary part’ read *. cabs and csqrt as you will see sometimes in older code). a ar = real(a) ai = aimag(a) print *. ai a = cmplx(ar. There are conversion functions to build complex numbers from two real numbers and vice versa.. ai print *. as shown in this example code: program testcomplex2 implicit none complex :: a real :: ar. FORTRAN Complex numbers are represented as a pair of numbers in parenthesis separated by a comma (first number is the real part.g. ’Exp(a) = ’. 1 1 1 (1 1) you will get an error.a a = exp(a) print *.-0. ’Enter real part’ read *. ar print *.5. ar print *.2460795. ai end program testcomplex2 and its output rock% testcomplex2 Enter real part . 1) Enter second complex number (-.1) Product = (-0.81274545) CHAPTER 4. ’Real part = ’. This is the only format that will work for the free format read.-0.

2.20 Array operations in F90 F90 allows many operations on vectors and matrices to be performed in single statements without the necessity of writing do loops over the array indices (as was necessary in F77). c real :: x print c = a print c = 2 print c = a *. Include a driver program to test your function for selected input values. ’a + 1 = ’.607 + 0.240i exp( 0. Make sure that your code gets the correct answer for these examples: exp( 1.20. 2.2.932i exp(-0. Here is an example program that demonstrates some of these operations on vectors.1312044.4717266) Real part = -1. c * a *. ARRAY OPERATIONS IN F90 1 Enter imaginary part 2 a = (1.1312044 Imag part = 2.2i) = 0.0.002 + 2.1 + Can you find any differences between the built in exp function are the results obtained with the formula? 4. 3. program vectormath implicit none real.0i) = 0. c * a .0.3i) = -2.362 + 0.0) Exp(a) = (-1.4717266 113 ASSIGNMENT F18 Write a program to test the built in complex exponential function against the formula e^z = e^(x+iy) = e^x e^(iy) = (e^x cos y) + i (e^x sin y) which you will have to adapt for your program.5 + 0.0 + 1.4.0 /). a + 1 *. 4.0. ’a = ’. b = 2.0. 5. dimension(5) :: a = (/ 1. ’2 * a = ’.

)**2) print *. c c = exp(a) print *. c22 integer. x c = a c(4:5) = 0. b) print *.b) follows" call PRINTMAT(c22. Here are some examples: program matrixmath implicit none real. 2) c22 = matmul(a23. 2) :: a32.2. c c = a * b print *. b22. 2.5 /) b32(1:3.7. x end program vectormath Note that even fairly complicated expressions are possible provided the programmer keeps track of what is a vector and what is a scalar. ’a + b = ’. 3. ’sum of squares of difference from mean = ’.1. ’a with two zeros on end = ’. b32) !this works but matmul(b32. "Matrix c22 = matmul(a. ’b = ’. 3) b32(1:3.4. b c = a + b print *. dimension(3. b32. 2) .2 /) print *. ’Matrix b32 follows’ call PRINTMAT(b32. dimension(2) :: loc2 integer :: i. 2) = (/ -5. 3.sum(a)/5. ’a * b = ’. j.2 /) a23(2. ’sqrt(a) = ’. c c = sin(a) print *.2) :: a22.0 print *.8.1:3) = (/ -5. 3. 0. 3) :: a23. a23) does not print *. ’Matrix a23 follows’ call PRINTMAT(a23. ’a * a = ’.3. dimension(2. x x = sum( (a . FORTRAN print *. 1) = (/ 9.3 /) print *. ’a dot b = ’. c x = sum(a) print *.1:3) = (/ 9. c print *. ’exp(a) = ’. Operations are also possible on matrices. -1.3. k a23(1. c23 real. -2. 1. c c = sqrt(a) print *. b23. dimension(2.1. c32 real. 4. 2. c x = dot_product(a. -6. ’sin(a) = ’. ’sum(a) = ’.114 CHAPTER 4.

loc2 print *. maxloc. n) real. for example to find the index of the maximum value of a vector bvec: loc = maxloc(a) Note that loc must be defined as an integer array with dimension(1). size(a23(1. maxval(a23) print *. (x(i. dimension(m.n) enddo end subroutine PRINTMAT end program matrixmath 115 This demonstrates the intrinsic functions matmul. size(a23) print *. j=1. NOTE: If maxloc is applied to a one-dimensional array.4. ’a23(loc2(1). Note that the statement loc2 = maxloc(a23) works only if loc2 is defined as an integer array with dimension(2).:)) contains subroutine PRINTMAT(x. 3) print *. ’maxloc(a23) = ’. ’size(a23) = ’. loc2(2)) = ’. minval and minloc. loc2(2)) b23 = a23 + transpose(b32) print *. 2. m. n do i = 1.:)) = ’. that determine the minimum value and location within an array. m print "(10f8. The maxloc function returns the location of the maximum value in the array. not the multiplication of the individual array elements as occurs from writing simply a*b.b) is true matrix multiplication. a23(loc2(1). maxloc(a23) loc2 = maxloc(a23) print *. ARRAY OPERATIONS IN F90 print *. ’size(a23(1. maxval. ’Matrix b23 = a32 + transpose(b32) follows’ call PRINTMAT(b23. You will get an error message during compilation if loc is defined simply as an integer. ’loc2 = ’. ’maxval(a23) = ’.3)".j). . Note that matmul(a. transpose. and size. n) :: x integer :: m.20. There are corresponding functions.

n)) do i = 1. This memory must be set aside even when it is not needed—a wasteful practice. (y(i. j). i. ’sum = ’. m) deallocate(y) deallocate(yy) contains subroutine PRINTMAT(x.n)) allocate (yy(n. n) :: x . n (# rows. n) real. i read *. ’Enter m.21 Allocatable arrays An awkward aspect of older Fortran programs is the need to declare arrays to the maximum possible size that could ever be needed when running the program. m print *.116 CHAPTER 4. allocatable :: x real. m. n allocate (x(n)) do i = 1. FORTRAN It would be interesting to test whether programs using the intrinsic array func- tions in F90 run any faster than those written using do loops. m print *. Here is an example program: program setarray implicit none real. dimension(m. dimension(:. n) enddo yy = matmul(y. ’Enter row # ’. 4. transpose(y)) print *. j = 1. m. xsum deallocate(x) !this frees up memory print *. F90 avoids this by allowing memory to be allocated and deallocated on the fly. ’y * yt = ’ call PRINTMAT(yy. :). dimension(:). n allocate (y(m. j. yy real :: xsum integer :: n. # columns)’ read *. n call random_number(x(i)) enddo xsum = sum(x) print *. allocatable :: y. m. ’Enter number of points’ read *.

j=1. we wanted to set up a data base containing information (name.22. for example. student(i)%name. & student(i)%height. weight (e. m print "(10f8. or may not. Here is a program that uses a structure to read in this information and print the name of the lightest person: program namebase implicit none integer. Bob 27 69 183)’ read *. This is called a “Structure” in C and a “Derived Data Type” in F90. height..4.3)". height. (x(i. ’Enter first name. STRUCTURES IN F90 integer :: m. be of the same data type. ’Oldest student = ’. dimension(nmax) :: student integer :: i real :: weightmin do i = 1.j). age. student(maxloc(student%age))%name end program namebase The statements: type person character (len=20) :: name . Suppose.g.n) enddo end subroutine PRINTMAT end program setarray 117 4. ’Lightest student = ’. student(minloc(student%weight))%name print *. weight) about 3 different people. & student(i)%weight enddo print *.22 Structures in F90 It is often convenient to have a user-defined array of data elements that may. This is a new feature that was not included in F77. age. weight end type person type(person). & student(i)%age. nmax print *. n do i = 1. parameter :: nmax=3 type person character (len=20) :: name integer :: age real :: height.

e. we can say: student(3) = student(2) rather than having to say: . dimension(nmax) :: student In this line. i. Note that the array index goes BEFORE the %member. The members of the structure are referenced by appending %member to the name. for example. where member refers to the specific member defined in the structure. dimension(nmax) :: grads. The contents are a character string (of length 20). not after. an integer for the age. height and weight. student(1)%age is the age of student(1).” Note the nifty use of the minloc and maxloc functions. The next line creates the array student that has this structure: type(person). undergrads type(person) :: teacher which sets up structure arrays for grads and undergrads and a single structure for teacher. weight end type person CHAPTER 4. So.118 integer :: age real :: height. age. This example does not really make obvious the advantages of a structure because we could easily have maintained separate arrays for name. A clearer advantage of the structure approach is that we can reassign all of the members with a single statement. The % operator is also sometimes called the “component selector. FORTRAN create a defined type that can be used to name a variable later in the program. avoiding the need to write do loops. the defined type is given the name “person” which is NOT a variable name.. Rather it is a name that can later to used to define the actual variable name(s) that will have this structure. In this example. It can be used to define more than one variable name and these variables do not need to be arrays. type(person) acts just like the integer and real statements that we are used to. These contents are termed the “members” or “components” of the structure. Here is another example of this: type(person). and real number for the height and weight.

k=2. n ! test integer math call system_clock(count1. In F90. k2 real :: dt. then one can add print statements that keep track of how long the different parts take to run. as illustrated in this example program that tests how long different types of math take: program testspeed implicit none integer :: n.2. dt call system_clock(count1. there is one key part of the program that takes most of the time. ’ integer +-. n k = k*k2 k = k/k2 enddo . count1.k2 enddo call system_clock(count2. n k = k + k2 k = k .23 Writing fast programs Modern computers are amazingly fast compared to those from 10 to 20 years ago and thus even inefficient code will often run fast enough. count_rate) dt = real(count2-count1)/real(count_rate) print *. i. x2 print *. we cannot compare structures as in the statement: if (student(3) == student(2) ) then ! ILLEGAL!! 119 4. So it’s always good to think about ways to make code more efficient. count_rate) k2 = 5 do i = 1. x=1. count_rate. However.23.4. this can be done using the builtin function system clock. ’Enter number of operations’ read *. dt = ’. WRITING FAST PROGRAMS student(3)%name = student(2)%name student(3)%age = student(2)%age etc. But any code that takes more than a few seconds to run is potentially more useful if it could run faster. If it’s not obvious by inspection. count_rate) k2 = 5 do i = 1. count2. In most cases. The first step is to identify that part.

dt call system_clock(count1. ’ real */. n x = x*x2 x = x/x2 enddo call system_clock(count2.k2 enddo call system_clock(count2. ’ integer */. count_rate) x2 = 3.14159 do i = 1. dt CHAPTER 4. dt = ’. count_rate) x2 = 5. ’ real +-. dt ! test trig functions call system_clock(count1. n k = k + k2 k = k .k2 if (k > 2) k = k . FORTRAN ! test if statement call system_clock(count1. dt = ’. count_rate) dt = real(count2-count1)/real(count_rate) print *. n x = x + x2 x = x . dt ! test real math call system_clock(count1.with if statement. dt = ’. ’ sin/cos. n x = sin(x2) x = cos(x2) enddo call system_clock(count2.14159 do i = 1. dt end program testspeed On my Macbook Air (2 GHz Intel Core i7). dt = ’. ’ integer +. count_rate) dt = real(count2-count1)/real(count_rate) print *. count_rate) dt = real(count2-count1)/real(count_rate) print *. count_rate) x2 = 3. count_rate) k2 = 5 do i = 1.14159 do i = 1. count_rate) dt = real(count2-count1)/real(count_rate) print *.x2 enddo call system_clock(count2. dt = ’. this produces: .120 call system_clock(count2. count_rate) dt = real(count2-count1)/real(count_rate) print *.

/testspeed Enter number of operations 99999999 integer +-. i.44499999 Before we continue. avoid computing trig functions and using if statements inside do loops) is not accurate. this is done using the “-O” option. In gfortran. we should stop for a minute to be amazed.19100000 real */. dt = 3. Some really smart people must be optimizing computer chips and the F90 compiler.1700000 real +-.7980000 integer +..50000001E-02 integer */. But it’s still worth knowing how to identify the slow part of your code. dt = 0.95999998 sin/cos.f90 -o testspeed Here is what I get for this program after optimization: shearer@khan 86> .with if statement. And it appears that if statements take hardly any time at all! Thus much of the advice that I was prepared to give you (try to use integers instead of reals.23. dt = 0.with if statement.4.22499999 real +-. WRITING FAST PROGRAMS shearer@khan 84> . dt = 0./testspeed Enter number of operations 99999999 integer +-. real arithmetic is comparable to integer arithmetic and sometimes even faster.44499999 integer */.12400000 . My little laptop is doing 200 million operations in about a second or less! Somewhat surprisingly.e.63099998 sin/cos.1 The -O option But there is another way to make your code run faster and it’s always surprising to me how many students don’t know about it. Even more surprisingly. gfortran -O testspeed. dt = 0. Most modern computer compilers have an option to “optimize” code to make it run faster. dt = 1. dt = 0. dt = 3. 4. dt = 1.57099998 real */.20000015E-02 integer +. so that you can devise ways to make it run faster. dt = 0. the trig functions only take about a factor of two longer. dt = 0. dt = 121 0.23.

j). the real mult/divide is 1. Suppose we have a 100000 × 10 real array that we wish to store on disk. compiled both with and without the -O option.testio1’) call system_clock(count1. FORTRAN The integer add/subtract is 13 times faster. clock speed). along with the details of your computer (i. why not use it all the time? It takes longer to compile programs using -O and the executables are not as stable. count_rate real :: dt open (12. name. type. count1. and the sin/cos is an astonishing 560 times faster1 . i.1 integer :: i. j=1.f90. count2. ’(10e12. I recommend that you debug your programs without using -O.10) :: a = 1.4)’) (a(i. However. file=’out. on Macs go to ’About This Mac’ under the Apple menu and send me the processor details..999 operations. j. chip. the integer mult/divide is 5 times faster. with a little deviousness.10) enddo 1 Does it recognize that we are computing the same thing? I suspect so! .. use -O to improve their speed (if necessary). Send me the output results for 99.5 times faster. but then once they are stable and working. FORTRAN has generally not been considered to be as flexible as C in the way that it handles i/o operations. ASSIGNMENT F19 Compile and run the program testspeed. it is possible to write FORTRAN programs that are capable of extremely fast i/o. We could output this simply as an ascii file: program testio1 implicit none real. your program is more likely to crash or give the wrong answer (!).999. For example. 100000 write (12.e.24 Fast I/O in Fortran Unless you are a serious “number cruncher” you are likely to find that input/output operations (reading and writing to file) take more time than any arithmetic operations. 4. Thus. dimension(100000. the real add/subtract is 3 times faster. count_rate) do i = 1. The key to making FORTRAN do fast i/o is to use unformatted binary read/write operations. Since -O makes code run faster.122 CHAPTER 4.e.

1 Mb file. FAST I/O IN FORTRAN call system_clock(count2. To make it easier to keep track of things. The total speed improvement compared to ASCII is about a factor of 120. A further improvement occurs when we store the entire array directly: open (12. j=1. ’dt = ’. for example. and date/time information.form=’unformatted’) write (12) a close (12) On my laptop. this takes about 0.10) enddo close (12) On my laptop.24.1 Mb file in about 0. this takes about 0. coordinates for the station. selev. we could output this as a binary file using similar loops over the indices: open (12. this generates a 4.file=’out.j).testio3’. system clock. 2 GHz Intel Core i7).067 s (10 times faster) and generates a 4. For example. it is often a good idea to define a data type (structure). count_rate) dt = real(count2-count1)/real(count_rate) print *.8 Mb file. Similar speed improvements can be noted upon reading these files.dt close (12) end program testio1 123 Notice the use of the intrinsic function. form=’unformatted’) do i = 1. file=’out. of a 4 character station name. type station_info character (len=4) :: stname real :: slat. On my laptop (Macbook Air. slon. Next. consisting. we can define a suitable data type and then create an array of these data types. In this case.testio2’.4.7 s and creates a 12. 100000 write (12) (a(i. suppose our array actually consists of 10000 “lines” of data with 10 values for each line. it is not always convenient to refer to data within a big array.006 s. Of course. The message is that for speedy i/o of large data sets in FORTRAN. sec . to monitor how long the output takes. we should read/write large arrays in blocks. This is how Guy’s GFS programs work and my routines to store travel time data.

we just set aa to the appropriate part of a: i=523 do 50 j=1. The beauty of this is that these variables can be of mixed data types.124 CHAPTER 4.imn.sec equivalence (aa(1).slat. stlist(5633)%stname is the station name of the 5633th line of data.selev. However. For example. ihr. 4. In order to examine the record 523. for large data sets and data processing. while preserving the ability to access its individual parts.. but a kludge is possible using the equivalence statement.ihr. & imon. binary is often better because it permits much faster I/O and the files will generally be smaller than their ascii counterparts. ascii is easier to work with and to understand and is often the preferred format when file size or speed is not a problem. dimension(10000) :: stlist We can now perform i/o very simply using the stlist array. You are also assured of retaining the full machine precision for numerical values (you don’t risk deciding later that you really should have stored 4 places to the right of the decimal.j) continue 50 The stname. we could we define a small array aa with 10 elements and set these elements to be equal to the individual variable names that we want: real aa(10) common/com1/stname. binary formats are somewhat less portable then ascii and require more user knowledge about their format.slon.stname) The equivalence statement sets the values of aa to the same place in memory as the 10 variable names defined in the common block. FORTRAN integer :: iyr. stlist(232)%slat is the latitude of the 232th line. not 3). F77 does not allow for structures.24. For example. . imon.iday. However. etc. imn end type station_info type(station_info).iyr. etc. This trick is used in Guy’s GFS routines and in many of my older I/O routines.10 aa(j)=a(i. slat. are now set.iday.1 Ascii versus binary files There is a tradeoff between speed and convenience for ascii versus binary files.

FAST I/O IN FORTRAN ASSIGNMENT F20 125 Compile and run the program testio.24. clock speed). along with the details of your computer (name.4. Then try it again after compiling with the -O option.f90 on your computer and send me the timing results for the three different ways to perform the I/O. chip. Does -O help with I/O speed? . type.


The New Yorker.1 Tic-tac-toe . ‘You’re a human being. 1999 As a goal for some of our F90 programming exercises. After looking the situation over. 5. Surely there should be some advantage in that. as long as they do something. 8.Chapter 5 Fun programs Let’s be honest—the examples in most programming books are pretty boring. So to help us stay motivated.nearly all the people I take down there have precisely the same response to the prospect of playing ticktacktoe with a chicken. don’t stop there. Although tic-tac-toe is a fully solved game in the sense that it is well known that a draw always results if both players play optimally (indeed even chickens have been trained to play the game). it is of sufficient complexity that writing a working program may seem a daunting task to the beginning programmer.. But the only way to get good at programming is to write lots of programs. Devising efficient sorting algorithms may be of academic interest. they say. Feb. ‘The chicken plays every day. I haven’t played in years. Some of them say.’ Calvin Trillin. this chapter contains examples of programs that are fun to write and fun to run. but these programs are pretty far from the science that most of us do. ‘The chicken gets to go first!’ ‘But she’s a chicken.’ Some of my guests.. I always report with some embarrassment. we are going to write a program to play tic-tac-toe. 127 .’ I say. It doesn’t really matter what they do.

1 for 1st player. it will be good to agree on some standardization of the different components. 2nd will simply determine where the program starts. the problem can be made more tractable by splitting the task up into smaller pieces. 2 for 2nd player). We will also need a way to display the board and to input moves from the human player.. when the program asks the human for a move. Let us begin by writing an external subroutine that will print to the screen the current state of the board. We will need to input to the subroutine the board variable and a variable to define which player is x in the game. this subroutine might have the form: subroutine printboard(board. However. computer difference is fundamental to the program. x vs. e.128 CHAPTER 5. playerx) . dimension(9) :: board Now. however. some kind of flag for who goes first. For convenience. to make sure that our programs will readily be able to play each other. 1st vs. etc. Obviously there are other choices that we could have made for this (1 for x. First. FUN PROGRAMS As is usually the case. 1 | 2 | 3 ---+---+--4 | 5 | 6 ---+---+--7 | 8 | 9 Thus. 1 if the human has moved in the space. the human will enter a number from 1 to 9. 2 for oh. and 2 if the computer has moved in the space. but this makes the most sense to me because the human vs. In other words. There are obviously many. some kind of flag for who is x and who is oh. Clearly we will need a way to store the current state of the board (who has moved where). let’s use the same convention for storing the moves within the program. many different ways to write this program. let us assume that the spaces on the board are defined by the numbers 1-9. Let us consider how we are going to approach this problem.g. Define an array called board that will store the moves that have been made: integer. oh is simply a naming convention. let us specify that board will have the value 0 if the space is still open.

The ’&’ line continuation characters are used only to make the mapping to the 3x3 board more obvious. 2. 2 /) playerx = 2 printboard should produce: | | ---+---+--| x | o ---+---+--| | x Note that in these examples board is a 1-D array with nine elements. & 0. Then write a series of print statments to do the actual output. 0. ‘x’. if there is currently a blank space in the move location. To implement this. Make sure that you do not change any of the values in the board array or that of playerx. let us write a function of the form: . 0 /) playerx = 1 printboard should produce: x | o | x ---+---+--| o | ---+---+--| | board = (/ 0. 1. 0. & 0. depending upon the contents of board and playerx.5. TIC-TAC-TOE 129 We assume that playerx = 1 if the human is x. Here are some examples: board = (/ 1. 1. Hint: Define a character array cboard(9) within your subroutine.e. or ‘o’. i. & 0. 0. 0.1. 0. 2. our program will need some way to determine if a proposed move is a valid move. You only want to print out the current state of the board. & 0. 2. Next.. playerx = 2 if the computer is x. the elements of which you set to ‘ ’. ASSIGNMENT TTT1 Write the external subroutine printboard. together with a test main program to check if it is working properly.

ASSIGNMENT TTT2 Write the function checkmove. Also. If it is invalid. do NOT print out anything within this function to warn of an invalid move. move) which will return 1 if the move is valid. FUN PROGRAMS integer function checkmove(board. Note that board is the array defined above and move is the proposed move. Repeat until a valid move is entered. 0 otherwise. we need a function to determine if there is a current winner (3 in a row) or if the game is drawn (all spaces filled. Let’s call this function readmove: integer function readmove(board) which will return a valid move as entered by the keyboard. together with a test main program to check if it is working properly. we need a function that will prompt the human for a move. the calling program can print out the message. It should check to see if the move is valid and prompt the human again in the cases of invalid moves. then alert the user and prompt again for a valid move. To make the function robust. no winner). This function will have the form: integer function checkwinner(board) .130 CHAPTER 5. If a warning is necessary. ASSIGNMENT TTT3 Write the external function readmove. together with a test main program to check if it is working properly. That should be done later in the main program. The function should ask the user to enter a move. We may want to use this function for multiple purposes in the program and we don’t necssarily want it to print anything out. Make sure you do not change any of the values in the board array or of the move variable. If it is valid. Next. Next. then use the checkmove function to check whether it is valid. return zero if move is outside of the range 1 to 9. return the move to the main program. IMPORTANT: Do not change the board array within the readmove function.

2. 3 win(2. e. 8. Make sure you do not change the board array. we can make improvements to findmove. however. that is playerx is not needed and . together with a test program to check if it is working properly. 4.1:3) = (/ 4. etc. 9 win(4.1.3) win(1. 2 if player 2 has won. . Your subroutine should not use any arguments other than board. Important: Do NOT change the board array within the subroutine. then check to see if all board locations are full (the draw criteria).1:3) = (/ 1. let’s write findmove in two stages. TIC-TAC-TOE 131 and will return 1 if player 1 has won. Then.1:3) = (/ 1. Testing this function will be easiest once the complete program is finished. and 0 otherwise. We will implement this as a function: integer function findmove(board) which will return the “best” move for the computer (player 2) to make. dimension(8. If there is no winner. 3 if the game is drawn. one needs a working version of findmove. :: win /) /) /) /) Then loop over these 8 possibilities and check to see if the 3 board values are all ones or all twos. integer. 6 win(3.. First.g. ASSIGNMENT TTT4 Write the external function checkwinner. To complete the program. To get around this problem. after we have the complete program working. 5. 7 . let’s write a very stupid version that will simply return a valid move. that should be done only within the main program.1:3) = (/ 7. ASSIGNMENT TTT5 Write a working version of findmove. together with a test main program to check if it is working properly. The most challenging part of your TTT program will be determining the best move for the computer to make. Hint: Define an 2-D integer array that stores the locations of the eight possible ways to win.5.

including all functions in an e-mail. a suitable message should be printed and the program stopped. please give your findmove function the name: function findmove_lastname(board) where lastname is your last name. you can figure out if you are making the first move within find move simply by checking to see if the board is empty. I will check the operation of your program and also attempt to have the programs play each other. you’re on your own! ASSIGNMENT TTT7 Refine your program to incorporate a smart findmove function. Beyond this. . If there is not a winner/draw. nor should your findmove subroutine need to know who is going first. Please only include ‘board’ in the argument list to findmove— this function should not need to know who is ‘X’ or who went first. This will make it easier for me to test your routines all at once. then the program should continue with the next move. The board array should be initialized to zero. Now we are ready to put these pieces together into a main program that will actually play the game. the program will have to determine whose move it is (a function of the move number and who went first) and then either prompt the user or use the findmove function to pick a move. the program should check for a win or draw. For each move. then next check to see if there is a winning move for the human that should be blocked. Hint: Just loop through the moves 1 to 9 until you find an empty space (board(i) = 0). pick a random valid move. To facilitate the latter goal. For a slightly more interesting “stupid” program. If not. FUN PROGRAMS should not be used. Following the move. Send me the complete program. Of course. If there is a win or draw. we will want to improve on our initial findmove function to make the program smarter. Please also make sure that you do not modify the board array within findmove. Finally.132 CHAPTER 5. An obvious strategy for this is to first check to see if any winning moves are possible. ASSIGNMENT TTT6 Construct a working version of the complete tic-tac-toe program. This program should ask the user if he/she wants to go first and if he/she wants x or oh (the latter is the playerx flag in the printboard function).

we begin by considering a complex number.0 = 3.2. at least in certain regions of the complex plane. To generate the Mandelbrot set.3 + 0.42 0.00i 12. i. when computed over and over again.32 + 1.e.00i -3.57 0.59i 0.4 = 12.1 = 2.49i |z| |z| |z| |z| = = = = 0.48i 0. such as the Mandelbrot set. FRACTALS 133 5. However. The basic idea behind most fractal calculations is that there are certain complex functions that.16 = -0. c.0i then 1st 2nd 3rd 4th 5th iteration: iteration: iteration: iteration: iteration: z z z z z = = = = = 0.4 = 153.61 0.00i -0. . will either diverge or remain bounded. We then apply the following algorithm: set z = 0 to start then repeatedly compute z = z*z + c until |z| > 2 OR the number of iterations exceeds some threshold then output the number of iterations For example. we can stop computing z once its absolute value (the complex absolute value or modulus is defined as the distance of a point in the complex plane from the origin. Whether or not they diverge turns out to be extremely sensitive to small changes in the initial complex value that starts the calculation.2 Fractals Generating beautiful images of fractals. z will remain bounded even after an infinite number of iterations.44 + 0.25 + 2.5 + 1.49 In this case.30 = 0. However.19 + 25.00i 151.4 and the size of z explodes toward infinite values.3i then 1st 2nd 3rd 4th iteration: iteration: iteration: iteration: z z z z = 0. if c = 0.50 + 1.63i |z| |z| |z| |z| |z| = 1.30 = 0. is surprisingly easy on the computer and provides good practice in using complex numbers. if c = 0. By the 10th iteration it will exceed the floating point range of most computers.02 + + + + 0. —z— = abs(a+bi) = sqrt(a*a+b*b) ) exceeds 2 because it can be shown that divergence is guaranteed at this point.5. The most famous of all fractal images is the Mandelbrot set.30i 0.

iy. ny dx = (x2 . ny. by checking after some large number of iterations (1000 is a common choice). y1. 1000 z = c + z*z if (cabs(z) > 2) exit enddo idat = idat + 1 dat(idat) = it enddo enddo print *. however. y1.y1) / real(ny) allocate(dat(nx*ny)) idat=0 do ix = 1. We may obtain a good approximation. ’Finished calculation’ ndat = idat print *. dimension(2) :: nxny complex :: c. ny’ read *. y1. ny cr = x1 + dx/2.x1) / real(nx) dy = (y2 . dimension(:). y2. ci) z = cmplx(0. dimension(4) :: wind print *. ndat. We also may take advantage of the fact that it is known that z 2 + c will diverge whenever |z| > 2. allocatable :: dat real :: x1. ci integer :: nx. Here is an example F90 program that performs this calculation for user-specified parts of the complex plane and outputs a binary file that can be read and plotted using MatLab or Python: program mandel implicit none real. x2.ndat . nx. dy. x1.134 CHAPTER 5. FUN PROGRAMS We repeat this calulation for a series of different values of c and plot the resulting output as a function of the location of c on the complex plane. x2. nbytes. nx do iy = 1. ’ndat = ’.0) do it = 1. dx. it. cr. ix. z2 real. + dx*real(ix-1) ci = y1 + dy/2.0. y2. 0. ’Enter x1. z. + dy*real(iy-1) c = cmplx(cr. status integer. nx. idat. x2. The Mandelbrot set is the set of all complex numbers c for which the size of z 2 + c is finite even after an infinite number of iterations. y2.

dat.0.5. + dy*real(iy-1) c = cmplx(cr. nx do iy = 1. Although the image is really two-dimensional. I store the results in the 1-D array. because this simplies the output of the results. Notice how allocate is used to set dat to dimension(nx*ny) on the fly. ci) z = cmplx(0. The number of points computed in x and y are input as nx and ny. FRACTALS open (12. defined by the user-defined limits x1 and x2 for the real part and y1 and y2 for the complex part. The spacing in x and y are defined by: dx = (x2 . Here are the main loops that actually do the calculation: idat=0 do ix = 1.y1) / real(ny) Note the conversion of the integer variables nx and ny to floats prior to performing the division. + dx*real(ix-1) ci = y1 + dy/2. 0. ny cr = x1 + dx/2.2. nx=50 and ny=50 will result in an image 50 pixels wide by 50 pixels tall. file=’fractal. form=’unformatted’) nxny(1) = nx nxny(2) = ny write (12) nxny wind(1) = x1 wind(2) = x2 wind(3) = y1 wind(4) = y2 write (12) wind write (12) dat end program mandel 135 The program computes the result for a grid of points in the complex plane. This will determine the resolution of the plot. For example.bin’.0) do it = 1. 1000 z = c + z*z if (cabs(z) > 2) exit enddo idat = idat + 1 dat(idat) = it enddo enddo .x1) / real(nx) dy = (y2 .

i. . The next step is to save this information to a file. using idat as a counter. The iteration number is saved in the dat array.e. wind(1) = x1 wind(2) = x2 wind(3) = y1 wind(4) = y2 write (12) wind Finally. wind.. etc. For speed in the case of a large dat array. larger values indicate slower divergence). We set up the 2-element int array.136 CHAPTER 5. x2. nxny.f90 -o mandel The Mandelbrot set is approximated in our program by places on the complex plane where the output value (contained in the dat array) is 1000. form=’unformatted’) We use form=’unformatted’ to specify that this is a binary file. We create and open the file with open (12. we use a binary file. The calculation is halted if |z| > 2 by exiting the for loop. to handle the output of x1.bin’. the z function has not diverged even after 1000 iterations. we write the output array to the file write (2) dat For this program. to handle the output of nx and ny: nxny(1) = nx nxny(2) = ny write (12) nxny and we set up a 4-element float array. Output values less than 1000 provide a message of how quickly the function diverges (small values indicate rapid divergence. The calculation is done for a maximum of 1000 iterations. we write some header information that will help MatLab or Python to know the size of the array and the values of x1. FUN PROGRAMS The real and imaginary parts of c are set to the center of the “pixel” with sides dx and dy. Writing to a binary file in Fortran is done using the write statement without a format. Plots of the output usually use colors to indicate the different output values. Before writing the dat array to the file. not an ascii file. and y2. file=’fractal. y1. it is a good idea to compile with the -O compiler option to make it run faster: gfortran -O mandel.

FRACTALS 137 5. hold on.bin’) % Fortran I/O has extra four bytes at beginning and end of writes [dum. fclose(fid). a script called plotfractal. [z.2. count] = fread(fid. [1]. nx = size(1) ny = size(2) [dum. ’int’). 5. count] = fread( #! /usr/bin/env python import numpy import array . count] = fread(fid. count] = fread(fid. So we need to read these extra btyes with our Matlab script into a dummy variable or we will not be properly aligned with the data fields.1 Plotting using MatLab Here is how to plot our output using Matlab: clf reset clear [fid. One detail is that Fortran (unlike C) writes an extra 4 bytes before and after each of the binary writes. message] = fopen(’fractal. [4]. count] = fread(fid.5. [nx. [size. y1. z2 = log10(z).2. ’int’). [2]. count] = fread(fid. z2 ). axis(’square’). colorbar. ’int’). ’int’). [1]. [1]. x2]. imagesc( [x1. count] = fread(fid. [dum. x2. ’int’). y2] ). ’float’) [dum. We set the output array to z and use imagesc to plot the result using the default color scheme. [wind.2 Plotting using Python Here is one way to plot our output using Python. [y1. y2]. axis( [x1. [1]. ’int’).ny]. x1 x2 y1 y2 = = = = wind(1) wind(2) wind(3) wind(4) [dum. [1]. count] = fread(fid.2. We plot log(z) rather than z because it shows some of the details a little better. ’int’).

dy) X. \ cmap=pylab.fromfile(file.y) z = X + Y k = 0 for iy in range(0. dat[1].axis(’equal’) pylab. y1.138 import matplotlib matplotlib. 6) x1 = wind[1] x2 = wind[2] y1 = wind[3] y2 = wind[4] print ’x1.array(’f’) dat = array..y1)/ny x = numpy. x1.x2. there are probably better ways to do this. x2.fromfile(file. FUN PROGRAMS #set "backend" so plot appears on screen #open in binary mode #deprecated . ny): for ix in range(0.log10(z) #only goes to ny-1! #only goes to nx-1! #plots look better if we take log pylab. we exclude ends b2 = wind.array(’l’) wind = array. y2..use("TkAgg") import pylab nxny = array. but .y1.x1)/nx dy = (y2 . ny CHAPTER 5.bin’. Reds) Because I’m not a Python expert.fromfile(file.fromfile #note that nxny goes from 0 to 3. 1 + nxny[1]*nxny[2]) print ’dat[1] to dat[4] = ’. dat[4] dx = (x2 .y2 =’.\ extent=(x1.arange(x1 + dx/2.array(’f’) file = open(’fractal.y1. ny = ’. dat[3].imshow(zlog.colorbar() pylab. dat[2].read does same thing as .Y = pylab.arange(y1 + dy/2. nx): k = k + 1 z[ix. dx) y = nx.interpolation=’bilinear’. iy] = dat[k] zlog = numpy. y2 b3 = dat. mode=’rb’) b1 = nxny. x2. (nice choices: Accent.x2.meshgrid(x.Spectral) # cm is color map pylab.y2). 4) nx = nxny[1] ny = nxny[2] print ’nx.

where ‘l’ is for reading long (4-btye) integers and ‘f’ is for reading reals. but as a Python novice I’m not sure how else to do this. we read into the nxny array: b1 = nxny. we assign the middle two values as: nx = nxny[1] ny = nxny[2] In a similar manner.fromfile(file. but the first and last are discarded because Fortran writes an extra 4 bytes before and after every binary write.Y in the same way that Lisa did in her gravity example: . we read in and assign the wind array and the x1.y and X. FRACTALS this is what I have figured out so far.bin’. we read in the appropriate sized dat array: b3 = dat.fromfile(file. 4) This array has 4 values.array(’l’) wind = array. y2 values: b2 x1 x2 y1 y2 = = = = = wind. 139 We follow Lisa’s example for plotting the gravity anomaly and import matplotlib. The following statements set up the format for the three arrays in the file. and b3 are not used.5. we compute dx and dy and set up x.bin’ for reading in binary mode: file = open(’fractal.fromfile(file. Next. nxny = array. mode=’rb’) Next.array(’f’) dat = array. y1.2. x2. Because the array index goes from 0 to 3. b2. 1 + nxny[1]*nxny[2]) Note that b1. 6) wind[1] wind[2] wind[3] wind[4] #open in binary mode Knowing the values of nx and ny.array(’f’) The following statement opens up the binary file ‘fractal. We also import ‘array’ which helps in setting up the binary input format. This seems awkward to me.

\ cmap=pylab.x2. y2. 1. It’s fun to explore the effect of different color maps in Python.x1)/nx dy = (y2 .Spectral) # cm is color map (nice choices: Accent.25. Reds) Note that we have added the ‘extent’ option to properly define the axes labels.interpolation=’bilinear’. I first assign z to dummy values in a way that ensures that it has the correct dimensions: z = X + Y Next. dy) X.arange(y1 + dy/2.25 (i.axis(’equal’) pylab.colorbar() pylab.y1.Y. x2. we need to assign the values in the dat array to a 2-D array aligned with X. we explicitly copy the values from dat to the z array: k = 0 for iy in range(0.y) Note that the last value of x will be x2 . Spectral.meshgrid(x.5. iy] = dat[k] #only goes to ny-1! #only goes to nx-1! The plot will look nicer if we take the log before plotting: zlog = numpy.. again following Lisa’s example: pylab. FUN PROGRAMS Next. 0. ny): for ix in range(0..scipy.. -1.3 Good targets and more about fractals The entire Mandelbrot set may be imaged in the window real -2 to 0. imag -1.\ extent=(x1.25 to 1.e.imshow(zlog. CHAPTER 5. Following Lisa’s example.dx/2.25) .5. dx) y = numpy.Y = pylab.log10(z) Finally we make the colormaps 5.arange(x1 + dx/2.2. nx): k = k + 1 z[ix.y1)/ny x = numpy.140 dx = (x2 .y2). Here is a site that shows lots of them: http://www.

K.25 0. 1. the November 1987 article talks about the related Julia sets. You may have to consult a book on complex numbers to find suitable formulae to compute sin(z).py) programs to plot examples of the Julia sets and the biomorphs.27 Further details about generating fractals may be found in a series of articles by A. 2.30 -0. Here are some suggestions for places to look: -0.703 -0. Please e-mail me the PDF files and copies of your F90 and Matlab or Python source code.73 -0. Part (2) is harder because you will have to generate more complicated complex functions than those that are used for the Mandelbrot and Julia sets.282 0. and the July 1989 article is about fractals called “biomorphs” that look like little creatures.75 -0. The August 1985 article describes the Mandelbrot set. Produce PDF files of 3 especially nice images of Julia sets.693 0.25 0. FRACTALS 141 It is also fun to zoom in on details of the image.c and plotfractal. Dewdney in the Computer Recreations section that used to appear in Scientific American.m (or plotfractal.72 0. ASSIGNMENT FRAC1 Rewrite the mandel.2. Have fun! . Reproduce and make images of as many of the biomorphs as you can that are shown on p. There are also lots of books on fractals that have many beautiful images. The study of fractal is related to chaos theory and the fact that in physical systems (weather is one example) are inherently unpredictable on large time scales because small perturbations to the starting conditions will cause large changes over time.5.35 -0. You will want to first read the appropriate Scientific American articles. etc. 110 of the biomorph article.292 -0.65 0.26 0.90 0. z z .95 -0.


once you’ve done all your fancy calculations in or this new (and very excellent) one: http://www. say.python-course. just put the following line at the end of your . We at SIO often use Bob Parker’s Plotxy program which produces lovely X-Y plots. simply type: % python You should get something that looks like this: 143 . supply your academic e-mail address and follow the instructions. But the modern standard is to be able to plot in 3D and to make plots interactive. why Python? It is flexible.php.framework/Versions/Current/bin/ $path) To make sure you have installed Python file: set path = (/Library/Frameworks/Python.php. it is easy to install. how were you planning on looking at your data? Now you have experienced GMT. Finally. So. The answer is. There are lots of numerical. psxy. The only potentially tricky bit is setting your path properly. There are numerous online tutorials.1 Introducing Python You may be wondering why. it is possible to do a lot of different plots with. after spending over a month learning Fortran. for example at: Other options are Excel. we are now switching to Python.enthought. or Kaleidograph or Matlab all of which are expensive (especially Matlab) and Excel plots are downright ugly. Really. freely available and cross platform. It is easy to learn and well documented. statistical and visualization packages. To do this. but getting your data into a suitable format will require some manipulation and the plots are rather clunky.python.Chapter 6 Lisa’s Python Notes 6. Go to: http://www.

and c in the above session as variables and + as an operation.144 CHAPTER 6.1-2 (32-bit)| (default. >>> If you don’t get something about Enthought Python. c d.enthought. And.f=4. numerical packages. PC users may have to type ˆC instead.2 |EPD 7. And there were funny lines that seemed to set three numbers at once: . build 5493)] on darwin Type "packages". Otherwise. After each command. the variables above are obviously behaving as integers. c=a+b. type the control key (here-after ˆ) and D at the same time. you are in an interactive mode with the prompt >>>.). you are probably using the standard Mac Os version. press the return key and see what happens: >>> >>> 2 >>> >>> >>> >>> >>> 5 >>> 4 >>> >>> a=2 a b=2 c=a+b c c+=1 c a=2.f=6 # note also that the symbol ’#’ means the rest of the line is a comment! To get out of Python interactive mode and back to your beloved command line. Jul 27 2011. etc.www.1-2 (32-bit) Python 2. Like Matlab. b=2.6 # note syntax! d=4.7. 13:29:32) [GCC 4. you can just start typing commands. which has none of the whistles and bells we want (plotting. so start over with the Introduction.5. You may have been surprised that we didn’t declare variables up front (C programmers always have to). "demo" or "enthought" for more information. not floating point variables (no decimals) but they are not letters between i and n.1 (Apple Version: 7. b.e. we are ready to begin! 6. you will recognize a.0. LISA’S PYTHON NOTES Enthought Python Distribution -. From your Fortran programming experience.e=5.2 An Interactive Python session As you have just fired up Python.

it may take a while.e. . They increment and decrement respectively. • For math functions. that out of the way. well. then the name of the function we wish to use.subtracts. for do you pronounce ‘NumPy’. 6. but after that it should be very quick. The first time you do this after installing Python. including ‘-‘ and ’ ’. we must first “import” the module with the command import. To use NumPy functions.5. Robert Kern). It can. / divides. the function just returns the value of π. • Parentheses determine order of operation (as in Fortran). * multiplies. First of all . give us the value of π as numpy. According to Important People at Enthought (e. c and >>> d. integers are i − n and floating points are all else .3. It is way more fun to say Numpee! So.f=6 Here are some rules governing variables and operations in Python: 145 • Variable names are composed of alphanumeric characters. NB: There is online help for any python function or method: just type help(FUNC). A module is just a collection of functions. c=a+b.f=4. .6. • + adds. b=2. • They do NOT have to be specified in advance (unlike C) • In fortran. You can make them whatever you want.6 # note syntax! d=4. it should be pronounced “Num” as in “Number” and “Pie” as in.not the case in Python. what can NumPy do for us? Turns out. Note how the module name comes first. we can use various modules that either come standard with python (the math module) or are additions that come with the Enthought Python Edition we are using (the NumPy module). a whole heck of a lot! But for now we will just scratch the surface.g.3 A first look at NumPy O. or Python.e=5. A FIRST LOOK AT NUMPY >>> a=2.pi. • They are case sensitive: ‘a’ is not the same as ’A’.K. pie. % gives the remainder. ** raises to the power • These two are fun: += and -=. Oops. In this case.

but you have to call them with the numpy.FUNC syntax. but allows you to call NumPy anything you want .g.pi in the second case.1415926535897931 This makes all the functions in NumPy available to you. returned a floating point variable (2.pi # or N. which is a heavy load on your memory. some use: N This does the same as the first. That way I know what module the functions I’m using are coming from especially because we don’t know off-hand ALL the functions available in any given module and there might be conflicts with my own function names or two different modules could have the same function (like math and numpy). 3. like pi or sqrt: >>> from numpy import pi. sqrt # pi and square root >>> pi 3. Here is a (partial) list of some useful NumPy functions: .146 CHAPTER 6. >>> import numpy as np # or anything else! >>> np..1415926535897931 This imports all the umpty-ump functions. LISA’S PYTHON NOTES There are four styles of the import command which all do pretty much the same thing but differ in how you have to call the function after importing: >>> import numpy >>> numpy.1415926535897931 >>> sqrt(4) save typing? To import all the functions from NumPy and not have to type numpy at all: >>> from numpy import * >>> pi 3.0 Did you notice how sqrt(4) where 4 was an integer. but you can also just import a few.1415926535897931 e.pi 3.0)? Good housekeeping Tip #1: I tend to import modules using the first option above.

variable types matter.6.sqrt(b**2-4.0 # a floating point ..4 Variable types The time has come to talk about variable types. We’ve been very relaxed up to now. Like Fortran. while numpy.You can convert from degrees to radians by multiplying by: numpy. as opposed to numpy. the argument is in RADIANS!. If you are desperate. VARIABLE TYPES 147 absolute(x) absolute value arccos(x) arccosine arcsin(x) arcsine arctan(x) arctangent arctan2(y. string and complex variable types. But .pi which has none.) y 6.sin(numpy.*a) quad1 y=numpy. Here are some examples: >>> number=1 # an integer >>> Number=1. floating point (both long and short).5 import numpy a=2 b=-12 c=16 quad1 = (-b + numpy. because we don’t have to declare them up front and we can often even change them from one type to another on the fly. It is pretty clever about figuring out what is required.x) arctangent of y/x in correct quadrant (***very useful!) cos(x) cosine cosh(x) hyperbolic cosine exp(x) exponential log(x) natural logarithm log10(x) base 10 log sin(x) sine sinh(x) hyperbolic sine sqrt(x) square root tan(x) tangent tanh(x) hyperbolic tangent Note that in the trigonometric functions. Also notice how these functions have parentheses.*a*c))/(2.pi just returns the value of π. Python has integer. you can always use your Python interpreter as a calculator: >>> >>> >>> >>> >>> >>> 4 >>> >>> 0.pi/6.4.pi/180. The difference is that these take arguments. so here goes.

but we also have more complicated data structures. false. 6. if you want a float. long(Number).148 CHAPTER 6.whatever you want really. complex(real. 6. LISA’S PYTHON NOTES >>> NUMBER=’1’ # a string >>> complex=1j # a complex number with imaginary part 1 >>> complex(3. float(NUMBER). like strings and integers and floats . str(number). it is possible that you will convert the float to an integer when you really wanted all those numbers after the decimal! So.1 Lists • Lists are denoted with [] and can contain any arbitrary set of items. use a float. We’ll go through some attributes of the various data structures.imag) long() converts to a double precision floating point and complex() converts the two parts to a complex number.0 [ a float] >>> NUMBER+NUMBER 11 [a string] >>> number+NUMBER [Gives you an angry error message] Lesson learned: you can’t add a number and a string. tuples.1) # the complex number 3+1i Try doing math with these! >>> number+number 2 [ an integer] >>> number+Number 2. and string addition is different! But you really have to be careful with this.5 Data Structures In Fortran. starting with lists. If you multiply a float by an integer. or. you encountered arrays. and not For the record. There is another kind of variable called “boolean”. the integer ‘1’ is true and ‘0’ is false.5. and. and dictionaries. like lists. You can convert from one type to another (if appropriate) with: int(Number). These can be used to control the flow of the program as we shall learn later. These are: true. In Python of course we also have arrays. that group arbitrary variables together. including other lists! . which was a nice way to group a sequence of numbers that belonged together.

2]] # defines a list >>> mylist[2] # refers to the third item ‘400’ >>> mylist[-1] # refers to the last item [24.0. added on. but an independent entity: >>>mycopy=mylist[:] Now try: >>>mylist[2]=1003 >>>mycopy[2] ‘new’ . To copy a list BEWARE! You can make a copy . DATA STRUCTURES 149 • Items in the list are referred to by an index number. Note that this is different from Fortran which starts counting in arrays with the number 1. inserted.[24.3 # replaces the second item >>> del mylist[3] # deletes the fourth element To slice out a chunk of the middle of a list: >>> newlist=mylist[1:3] This takes items 2 and 3 out (note it takes out up to but not including the last item number . etc. -2 (second to last). Or. starting with 0. sliced. replaced. so: >>> mycopy=mylist >>>mylist[2]=‘new’ >>>mycopy[2] ‘new’ See how mycopy got changed when we changed mylist? To spawn a new list that is a copy. • Items can be sorted.‘spam’. deleted.2.6.42.but it isn’t a copy like in Fortran. etc. concatenated.5.don’t ask me why).2] >>> mylist[1]=26.‘400’. Examples: >>> mylist=[‘a’. • You can count from the end to the beginning by starting with -1 (the last item in the list). but it is just another name for the SAME OBJECT. counted. we can slice it this way: >>> newlist=mylist[3:] which takes from the fourth item (starting from 0!) to the end.

Unlike in Fortran.K. To find more of the things you can and cannot do to strings.3 6. mylist is an object. etc. “Sam’s spam”. What do objects have that might be handy? Objects have “methods” which allow you to do things to them.0. ’400’. strings can be more interesting. While there are more kinds of numbers (complex.5. see: http://docs. Python is “object oriented”. a popular concept in coding circles. what is an object? Well.. 42..0. [24. even as mylist changed.2 More about strings Numbers are numbers. see: They can be sliced (newerstring = newstring[0:3]). Methods have the form: object.method() Here are two examples: >>> mylist. They are denoted with parentheses.sort() # sorts the list alphanumerically >>> mylist [2.). 2].append(‘me too’) # appends a string to mylist >>> mylist.python. Cool.4 Data structures as objects Tuples What? Tuples? Tuples consist of a number of values separated by ’me too’. ‘hello’) >>> t[0] 1234 . ’spam’] For a complete list of methods for lists.5. We’ll learn more about what that means later.150 CHAPTER 6. but for right now you can walk around feeling smug that you are learning an object oriented programming language.g. 2.html#moreon-lists 6.html#strings 6. Unlike can’t do this: newstring[0]=’b’. ‘spam’. ’a’. but they CANNOT be changed in place . LISA’S PYTHON NOTES So now mycopy stayed the way it was. >>> t = 1234. they can be denoted with single. double or triple quotes: e. ‘hello’ >>> t (1234. O. 2.python. or """ Hi there I can type as many lines as I want """ Strings can be added together (newstring = ’spam’ + ’alot’).0.5.

But just to make things a little confusing. Unlike lists. . but not so arrays .5. usually numbers (integers or floats). However. Why use arrays when you can use lists? They are far more efficient than lists particularly for things like matrix math. So here is a bit more about them. arrays have to be all of the same data type (dtype). One useful one is: >>> Telnos.6 N-dimensional arrays Arrays in Python are more similar to arrays in Fortran than they are to lists.‘lab’:46531.html#tuples-and-sequences 6. they use alphanumeric ‘keys’: I love dictionaries.‘lab’.python. you can slice. They are also somewhat like lists. For a more complete accounting of although there appears to be something called a character array.‘jeff’.python. DATA STRUCTURES 151 Tuples are sort of like lists.‘jeff’:44707} # defines a dictionary To return the value associated with a specific key: >>> Telnos[‘lisa’] 46084 To change a key value: >>> Telnos[’lisa’]=46048 To add a new key value: >>> Telnos[‘newguy’]=48888 Dictionaries also have some methods.html#dictionaries 6.5. but like strings. Also. To define one: >>> Telnos={‘lisa’:46084.they are much pickier and we’ll see how to set them up later.‘newguy’] which returns a list of all the keys. concatenate.6.5. their elements cannot be changed. then append to it as but instead of integer indices. the size and shape of an array must be known a priori and not determined on the fly like lists.5 Dictionaries! Dictionaries are denoted by {}. For more see: http://docs. see: http://docs. For example we can define a list with L=[].keys() [‘lisa’. etc.

84615385. 0].. . [ 1. array([[ 1. transpose() etc. ndim.5. 0. 1.10. 2]]) >>> B=numpy. 0. [1.0]. 0.. [4. 1. 8..76923077.. 4]. 4. 3.array([[1. e.].4)) >>> E array([[ 1.2). 2.23076923.2. size.152 CHAPTER 6. LISA’S PYTHON NOTES there are several different data objects that are loosely called arrays. shape.reshape(2.75303490e-308]. 8.1. 2.linspace(0. 2. 9]]) >>> C=numpy. >>> D array([[ 0.15384615.stop.90979621e-313.. [4.stop.2]]) >>> A array([[1.1.3].2.5. 6. 3. [5.) respectively.08539798e-071.2.]..ndarray(shape=(2. dtype=float) >>> G # note how this is initalized with really low numbers (but not zeros).step).]]) >>> E=numpy. In some of the online examples you will find the short-cuts for arange() and linspace as r (-5.07692308.69230769. 3. 3. ]) >>> G=numpy. character arrays and matrices. 6.30769231.ones((2. Python arrays have methods like dtype. The function linspace creates an array with 14 evenly spaced elements between the start and stop values while arange creates an array with elements at colorbluestep intervals between the starting and stopping values. 1. I’m just going to briefly introduce arrays and matrices here. [ 1.46153846.]]) >>> F=numpy. Here are a few ways of making arrays: >>> import numpy >>> A= numpy.arange(0.20j) and r (-5.5.. 7. 1.92307692. 10. Did you notice how some of these require parentheses and some ..zeros((2. ravel(). 7. 2.61538462. 0. 1.53846154. reshape(). 3]. 1. 1. 5. arrays.38461538.. 1. 1.6]].[4. 6.g. 5. [ 0.3].5) >>> B array([[0. 2. These are all subclasses of ndarray.N) and arange(start.[4. 9.05363949e-309]]) Note the difference between linspace(start.3)) # Notice the zeros and the size is specified by a tuple.numpy...14) >>> F array([ 0.int32) >>> C array([[1.1).10.array([[1. 0. 3]. 6]]) >>> D=numpy.[1. 2.

6. arrays made in the above example are of different data types. To find out what data type an array is. [5. [1. The shape of an array is how many elements are along each axis. DATA STRUCTURES 153 don’t? The answer is that some of these are functions and some are classes. but we want a 3x2 array.3]. So. unlike lists have dimensions and shape.2. both of which we will get to later.2. just use the method dtype as in: >>> D.0].reshape((3.[1.2]]) # just to remind you >>> A. Let’s see what the methods can do. 3]. 2. First. Python returns a tuple with the shape information using the shape method: >>> C. naturally we see that the C array is a 2x3 array. 3) Let’s say we don’t want a 2x3 array for the sequence in the array C.1. 1. To get Python to tell us this. Python can reshape an array with a different shape tuple like this: >>> C.[4.5. 2]] b) ax is = 2 axis = 1 As shown above our A array has two dimensions (axis 0 and 1). 4]. 2.array([[1.dtype dtype(’float64’) >>> And of course arrays. [4.shape (2.2)) array([[1. 6]]) . 0]. 2]. Dimensions tell us how many axes there are with axes defined as in this illustration: a) A array: axis = 1 axis = 0 axis = 0 [[1. [3. ones and ndarray used a shape tuple in order to define the arrays in the examples above. we use the ndim method: >>> A= numpy.ndim 2 Notice how zeros.

5. Check out this website for more differences between the two: http://www. While arrays are intended to be general purpose n-dimensional arrays for numerical for Matlab guessed it . 5.asarray(L)) 6. 6.concatenate() method.T array([[1. 4. 4. 3. or from a list. For a lot more tricks with arrays. You can see that this is 6 here. 5. Alternatively we can use the ravel() method which doesn’t require us to know the size in advance: >>> C. The syntax for slicing of arrays is similar to that for lists: >>> B=A[0:2] # carve the top two lines off of matrix A from above array([[1.scipy.size) and use that in the reshape size tuple. [3. from a list or tuple to an array: A=numpy.scipy. matrices are better for linear algebra type problems: you can take the inverse and find hermition easier (. A matrix is another subclass of ndarray with special advantages for particular applications. 6]) There are other ways to reshape. [4. We could do that with reshape of course using a tuple with the size of the array (the total number of elements). a tuple or an array to a NumPy array: a=numpy.tolist(). 2. Python scripts are programs that can be run and re-run from the command line. We could even get python to tell us what the size is (C.6 Python Scripts Are you tired of typing yet? Like UNIX shell scripts.array(L). so here goes. go to the NumPy Reference website here: http://docs.ravel() array([1. [2. 3]. We promised to tell you about matrix objects.154 CHAPTER 6. 8]. 2.H methods) and matrix multiplication works like it does in Matlab for matrix objects. we can concatenate two arrays together with the .I and . 7]. 9]]) Also. You can type in the same .transpose() # this is the same as A. To convert the A array to a list: L=A. slice and dice arrays. LISA’S PYTHON NOTES And sometimes we just want all the elements lined up along one axis. whereas arrays do element-wise computations (we’ll learn more about this later). 6]]) Lots of applications in Earth Science require the transpose of an array: >>> A.

NOT Word! And then you can run them like this: %python < myscript. the first line MUST be: #! /usr/bin/env python so that the file is interpreted as Python. #! /usr/bin/env # simple Python print "The pump print ’She said produces: % . Because the message is a The second line is a comment line. Anything to the right of # is assumed to be a comment (Remember that in Fortran ! serves the same function).py Or you can put in a header line identifying the script as python (#!/usr/bin/env python).. Unlike Fortran or C. make it executable (chmod a+x). you CANNOT start with a comment line (try switching lines 1 and 2 and see what happens). TextWrangler./ Here is a familiar example that creates a script using the UNIX cat command. and run it like this: % myscript. print ’test message’ ^-D % chmod a+x printmess.e. PYTHON SCRIPTS 155 stuff you’ve been doing interactively into a script file (ending in . You can get an apostrophe in your output by using double quotes and quote marks by using single quotes. emacs. Notice that print goes by default to your % .py test message In a Python script./printmess. you can use single or double quotes for the test The pump don’t work ’cuz the vandals took the handles She said "I know what it’s like to be dead" % python test program 2 ( don’t work ’cuz the vandals took the handles" "I know what it\’s like to be dead"’ . You can edit scripts with: #!/usr/bin/env python # simple Python test program (printmess. makes it executable and then runs it: % cat > printmess. etc. i.6.

abge print ’adif = ’. the \’ is necessary to prevent an error (try it).156 CHAPTER 6.abge NameError: name ’abge’ is not defined Error messages are a desirable feature of Python. When you run the program. In Python. You don’t want the program to run by assigning some arbitrary value to abge and giving you a wrong". as in an end-quote for a string in this example. We use the backslash to say that we really really want a quote mark here. but do not require it. there are if statements and do loops which are bounded by the statements if. ASSIGNMENT P1 Write a Python script to print your favorite pithy phrase. This is an example of a Python ‘escape code’. Many of these programs encourage the use of indentation to make the code more readable. for example. Yet many languages will do exactly that. LISA’S PYTHON NOTES In the second print statement.1 aend = 3. e-mail your script to ltauxe@ucsd. adif You had intended to type ’abeg’ but typed ’abge’ instead. These are used to escape some special meaning. you get an error message: Traceback (most recent call last): File ". including Fortran (we can avoid this potential problem in Fortran by using the ’implicit none’ statement at the beginning our our programs). Other escape codes are listed here: http://www. indentation is the way that code blocks are defined . The trick is that all code indented .edu 6. line 4. to be executed under certain conditions.python-course. the initiating statement terminates in a colon./undeclared.9 adif = aend .php Here’s another example of a program . endif and do.this one has an typo in line 4: #! /usr/bin/env python abeg = 2. Also.there are no terminating statements. In Fortran. endo respectively. in <module> adif = aend .7 A first look at code blocks Any reasonable programming language must provide a way to group blocks of code together.

Use with caution! • There is a cheat that comes in handy when you are writing a complicated program and want to put in the code blocks but don’t want them to DO anything yet: the command pass does nothing and can be used to stand in for a code block. The code block terminates when the next line is less indented.6. • If a code block consists of a single statement. A typical Python program looks like this: program statement block 1 top statement: block 1 statement block 1 statement \ ha-ha i can break the indentation convention! block 1 statement block 2 top statement: block 2 statement block 2 statement block 3 top statement: block 3 statement block 3 statement block 4 top statement: block 4 single line of code block 2 statement block 2 statement block 1 statement block 1 statement program statement Exceptions to the code indentation rules are: • Any statement can be continued on the next line with the continuation character \ and the indentation of the following line is arbitrary. I use only spaces because I use vi to write my code. the Python IDLE program. .7. Good housekeeping Tip #2: Always use only spaces or only tabs in your code indentation. Others use Xcode. A FIRST LOOK AT CODE BLOCKS 157 the same number of spaces (or tabs) to the right belong together. then that may be placed on the same line as the colon. or TextWrangler to write their code and some of these things use tabs by default. • The command break breaks you out of the code block. Whatever you do BE CONSISTENT because tabs are not the same as spaces in Python even if you can’t tell the difference just by looking at it.

and “if” statements.step) but returns integers instead of floats. the program prints out the ’All done’ string. Note also that the line could have been on the previous line after the colon.stop.1): # note absence of Indices list. The script uses this integer as the ‘stop’ value in the range() function.1 The for loop Here is an example of a “for loop” that is similar to the way you would do it in Fortran.step) is just like numpy. like numpy. At that point. the program block terminates. Python makes i step through the list of numbers from 0 to 2.158 CHAPTER 6.‘ocelot’]. I’ll show you how Python uses code blocks to create “do” and “while” loops. The length of mylist is an integer value returned by len(mylist). Note how the print command is indented .arange(). [ The minus one convention is hard to get use to for Fortran programmers.‘spam’.7. so we could (and will) just use the command range(stop). which returns a list of integers from 0 to the stop value MINUS ONE at intervals of one. But. Python is far more fun than the Fortran-like for i in syntax in the above code snippet.‘spam’. 6.stop.this is the program block that is executed for each i. there is a short hand form when the minimum is zero and the interval is one.‘spam’. start and step print mylist[i] print ’All done’ This script creates the list mylist with the line mylist=[42. But never-mind.‘ocelot’] for i in range(0. LISA’S PYTHON NOTES In the following. because there is only one line in the program block. but it is typical of Python syntax (and also of C) so just deal with it.len(mylist).‘ocelot’] for item in mylist: # note absence of range statement print item print ’All done’ . Also.arange(start. When i finishes it’s business. this way works too and is more Fortran like. Here is another script which does just that (why not?): #!/usr/bin/env python mylist=[42. range(start.] Anyway. There is no “enddo” statement or equivalent in Python. printing the ith element of mylist. In Python we can just step through a list directly. : #!/usr/bin/env python mylist=[42.

4f’ %(theta.6. The expression ctheta = np. ctheta. but it makes sense to use variable names that mean what they do. # remember conversion to radians for theta in range(90): # short form of range. ttheta) Let’s pick this one apart a bit. It is easier to understand what ‘item’ stands for than just the Fortran style of i.pi/180.7. 5.tan(theta*deg2rad) # define ttheta as tangent of theta print ’%5.cos(theta*deg2rad) # define ctheta as cosine of theta stheta = np. It creates a table of trigonometry functions. stheta. Ideally theta should be a real variable while in fact it is an integer in this expression.4f %8. ttheta) To make the output look nice.1f and %8. in fact any text there is reproduced exactly in the output.4f %8. A FIRST LOOK AT CODE BLOCKS 159 Note that of course we could have used any variable name instead of ‘item’. Instead.89] ctheta = np.2.4f’ %(theta. Note that we could have also converted theta to a float first with the command float(theta). it makes absolutely no difference (try it!). Also notice how deg2rad is defined: deg2rad = np.. print ’%5. spitting them out with a formatted print statement: #! /usr/bin/env python import numpy as np deg2rad = np.1). we do not use print theta. stheta. stheta.cos(theta*deg2rad) uses the numpy cosine function. The single blank space between %5. While in this case.4f is included in the output. thus to put commas between the output numbers. ctheta.1f %8. returns [0.1f is for 5 spaces of floating point output..1f %8. we explicitly specify the output format. ttheta which would space the numbers irregularly among the columns and put out really long numbers. The format for each number follows the %. Here is an example with a little more heft to it. write: .sin(theta*deg2rad)# define stheta as sine of theta ttheta = np. ctheta. notice the use of the variable deg2rad to convert from degrees to radians. using the NumPy function for π and the decimal point after 180. with 1 space to the right of the decimal point (in Fortran this is f5. The output format is given in the quotes.1. but fortunately Python figures that out and converts it to a real. In fact: Good housekeeping Tip #3: Always use a decimal if you want your variable to be a floating point variable. First.pi/180. it is a good practice to use real numbers if you want your variable to stay real.4f %8.4f %8.

Here is a juicy complicated statement: if ( (a > b and c <= 0) or d == 0): code block There are rules for the order of operations for these things like.4f.4f. indented text. For the “if” block. <= <= <= <= less than or equal to . ttheta) Tabs (\t) would be formatted like this: print ’%5.4f. < ¡< < < less than . LISA’S PYTHON NOTES print ’%5. & & and . For both of these.or. You can look it up in the .and. the code block is executed if the top statement is TRUE. we need to evaluate a statement using Python of course also has comparisons and they work in similar ways with a few differences. There are also if and while code blocks. ttheta) 6.\t’ %8. ctheta. otherwise skip it.160 CHAPTER 6. multiplication gets done before addition.le.4f’ %(theta.or.7.4f’ %(theta. == == == == equals . if it is TRUE.and. Here’s a handy table with comparisons (relational operators) in different languages: Comparisons F 77 F90 C MATLAB PYTHON meaning . then execute. stheta.2 If and while blocks The “for loop” is just one way of controlling flow in Python. ctheta. > > > > greater than . %8. You know all about comparisons from Fortran. —— — or These operators can be combined to make complex tests. %8. To decide if something is TRUE or not (in the boolean sense).4f’\t’ But these are easy to forget. the code is executed once but in a “while” block. The key to flow control therefore is in the top statement of each code block. /= != ∼= != does not equal . These execute code blocks the same way as for loops (colon terminated top statements.). .1f ’\t’ the code keeps executing as long as the statement remains TRUE. stheta. >= >= >= >= greater than or equal to . . %8. etc.

do this: print "susie in list but george isn’t" While loops As already mentioned. while . try this one print ’susie and george both in list’ else: # if both statements are false. In Python these are: elif and else. better. the elif code block gets executed if the top if statement is FALSE and the elif statement is TRUE. One nice aspect of Python compared to C is that if you make a mistake and type. A FIRST LOOK AT CODE BLOCKS 161 documentation if you are unsure or. In C this is a valid statement with a completely different meaning than is intended! Finer points of ‘if ’ blocks The simplest ‘if’ block works just like we have described: if (2+2)==4: # note the use of ’==’ and parentheses in comparison statement print ‘I can put two and two together!’ However. for example. As in the Fortran equivalent else if. Good housekeeping Tip #4: Use parentheses liberally .’doug’.7.make the order of operation completely unambiguous even if you could get away with fewer. the ‘while’ block continues executing as long as the while top statement is TRUE.’denise’] if ’susie’ in mylist: pass # don’t do anything if ’susie’ not in mylist: print ’call susie and apologize!’ mylist. Consider these examples: #!/usr/bin/env python mylist=[’jane’. then Python will execute the block following the else. the if block is only executed once.append(’susie’) elif ’george’ in mylist: # if first statement is false. just put in enough parenthesis to make it completely clear to anyone reading your code.6. If both the top if and the elif statements are FALSE but the else statement is TRUE. In other words. as in Fortran (and C and any other reasonable programming language). there are whistles and bells to the ‘if’ code blocks. if (a = 0): you will get an error message during compilation.

In the following we will explore some of the more useful I/O options in Python.’ instead of ’>>>’ once you type a statement it recognizes as a top statement. You learned a rudimentary way of spitting stuff out already using the print statement. LISA’S PYTHON NOTES the while block keeps looping until the statement turns FALSE.8 File I/O in Python Python would be no better than a rather awkward graphing calculator (and we haven’t even gotten to the graphing part yet) if we couldn’t read data in and spit data out.... . a+=1 . The interactive shell responds with ’. Here are a few examples: #!/usr/bin/env python a=1 while a < 10: print a a+=1 print "I’m done counting!" 6. but there is a lot more to file I/O in Python..7.Y in the first two columns as in GMT) and output the data any way we want.. print a . simply hit return: >>> a=1 >>> while a<10: ...8.. E-mail it to ltauxe@ucsd...1 Reading data in From a file If you are using Python interactively or want interactivity in a script.. use the command: raw input(). To signal that you are done with the program block.3 Code blocks in interactive Python All of these program blocks can also be done in an interactive session also using indentation.162 CHAPTER 6.[return to execute block] ASSIGNMENT P2 Rewrite your Fortran Assignment F4 in Python.. We would like to be able to read in a variety of file formats (not just X. It acts as a prompt and reads in whatever is supplied prior to a return as a string. 6..

I use the form ’rU’ for unformatted reading because I often want to read in files that were saved in Dos. or whatever and read it into 9. yes. Mac OR Unix line endings and ’rU’ figures all that out for you.68440 etc. The function open() has some bells and whistles to it and has the form open(name[.8. raw input() is a simple but rather annoying way to enter things into a program.list’) StationNFO=f. you will get this behavor: % ReadStations. The approach to this is similar to Fortran: we must first open the file. complete with methods. Here is a script (ReadStations.txt) with cat. The ‘name’ argument is the file name to open and ‘mode’ is the way in which it should be opened. myfile.6. X. like readlines() which. mode[.93040 For a complete list of these. read in the data and print it out line by line. see: http://docs.76560 2442 AAE 42. Just in case you are . FILE I/O IN PYTHON X=[] # make a list to put the data in ans=float(raw_input("Input numeric value for X: X.html The open() function returns an object.02920 38.63900 37.. buffering]) where the stuff in square brackets is optional. writing ’w’ or appending ’a’.py that will open the file station. paste. Excel (saved as a text file). #!/usr/bin/env python f=open(’station. the variable ans will be read in as a string variable. most commonly for reading ’r’. reads all the lines.49400 1645 AAK 58.append(ans) # append the value to X print X[-1] # print the last item in the list ")) 163 In this example.readlines() for line in StationNFO: print line If you run this script.88370 -176.python. converted to a float and appended to the list.list from the chapter on GMT. then read it in and parse lines into the desired variables. one of Python’s built-in functions. To open a file we use the command open().g.11890 678 ABKT 116 ADK 51. Another (less annoying) way is put the data in a file (e.

63900 74.93040 ’ 9.02920 38.49400 1645 AAK \n’ ’ 37.90930 -171. The latter is how a tab appears if you were to. To split the line.[].164 CHAPTER which parses out the lines and puts numbers (floats or integers) in the right lists: #!/usr/bin/env python Lats.g.’. If you are curious about the line endings. but Python reads in the entire line as a string and ignores the spaces or other possible delimiters (commas. Here is a slightly modified version of ReadStations. tabs.02920 38.strip(’\n’) Putting this into the code results in this behavior: % 9.[]# creates lists to put things in StationNFO=open(’station.[] .split()). LISA’S PYTHON NOTES curious. printing the line also printed the line feed (\n) as an extra line.readlines() # combines the open and readlines methods! . but the most common ones are ’.76560 2442 AAE 42.68440 116 ADK \n’ ’ -13.93040 58. Anything could be a separator. Fortran automatically splits on the spaces so you probably didn’t have to worry about this sort of thing yet.’.Lons. it will split on spaces.11890 678 ABKT\n’ ’ 51. To clean this off of each line. ’.list’). print out the representation of the line.63900 74. try typing out the ‘representation’ of the line repr(line) in the above script and you get all the stuff that is normally invisible like the apostrophes and the line terminations: % ReadStations.StaName=[].49400 1645 AAK 37.). Lons.77730 706 AFI \n’ etc. which shows all the invisibles. ParseStations.11890 678 ABKT Let’s say you want to read in the data table into lists called Lats. I never use the ’buffering’ argument and don’t know what it does. line. and StaIDs (the first three columns). You need to split each line into its columns and append the correct column into the appropriate list.76560 2442 AAE \n’ ’ 42. etc. If no separator is specified (e.. we use the string function split([sep]) where [sep] is an optional semi-colons.StaIDs. Mac files in ’\r’ and Dos (and windows) lines end in ’\r\n’. say.88370 -176. Unix lines end in ’\n’. Notice how in our first version. and ’\t’. we can use the string strip() function: print line.

list We could also use command line switches by reading in arguments from the command line.[]# creates lists to put things in StationNFO=sys.2 Command line switches #!/usr/bin/env python import sys Lats.8.Lons[-1]. Python can also read from standard input. FILE I/O IN PYTHON 165 for line in StationNFO: nfo=line.append(int(nfo[2])) # puts integer of 3rd column into StaIDs StaName.Lons.append(float(nfo[1]))# puts float of 2nd column into Lons < station.Lons[-1].append(int(nfo[2])) # puts integer of 3rd column into StaIDs StaName.split() # strips off the line ending and splits on spaces Lats. So.[].readlines() # reads from standard input for line in StationNFO: nfo=line.strip(’\n’).StaIDs[-1] # prints out last thing appended From standard input As in Fortran.argv. instead of specifying a file name in the open command. In the following example.Lons.append(float(nfo[0])) # puts float of 1st column into Lats .StaName=[].strip(’\n’).index(’-f’)+1] # find index of ’-f’ and increment by one StationNFO=open(file.append(float(nfo[0])) # puts float of 1st column into Lats Lons.[]# creates lists to put things in if ’-f’ in sys.[] . we use the switch ’-f’ with the following argument begin the file name: 6.append(float(nfo[1]))# puts float of 2nd column into Lons StaIDs. we could substitute the following line: #!/usr/bin/env python import sys Lats.StaIDs.stdin.split() # strips off the line ending and splits on spaces Lats.append(nfo[3])# puts the ID string into StaName print Lats[-1]. To do this.strip(’\n’). we need a system specific module.8.’rU’).[].StaIDs.6.append(float(nfo[0])) # puts float of 1st column into Lats Lons.argv[sys.argv: # look in list of command line arguments file=sys. called sys which among other things has a stdin method.[] .readlines() # open file for line in StationNFO: nfo=line.StaName=[].split() # strips off the line ending and splits on spaces Lats.append(nfo[3])# puts the ID string into StaName print Lats[-1].StaIDs[-1] # prints out last thing appended The program can be invoked with: % ReadStations.

list Reading numeric files In the special case where the data in a file are entirely numeric.append(int(nfo[2])) # puts integer of 3rd column into StaIDs StaName.Easting. LISA’S PYTHON NOTES print StaName. O. Zone which spits out something like this: % ConvertStations. I could then write it out somehow.readlines() for line in StationNFO: nfo=line.StaIDs[-1] # prints out last thing appended This version can be invoked with: % ReadStations. It would be nice if after having done this to the data.strip(’\n’).com/p/pyproj/issues/attachmentText?id=27&aid= -80884174771817564 & -f station.split() lat=float(nfo[0]) lon=float(nfo[1]) StaName= nfo[3] Zone. Northing=UTM.append(float(nfo[1]))# puts float of 2nd column into Lons StaIDs.append(nfo[3])# puts the ID string into StaName print Lats[-1].py) to convert each of the stations in my list to their UTM equivalents (assuming these were in a WGS-84 ellipsoid).170087 998088. 6. Northing.3 Writing data out Let’s say I have a Python module that will convert latitudes and longitudes to UTM coordinates.list’).py&token=46ab62caa041c3f240ca0e55b7b25ad6 I wrote a script (ConvertStations. Easting. ’: ’ AAE : 474238. preferably to a you can read in the file with a special numpy function loadtxt(). Of course I could use the print command like this: #!/usr/bin/env python import UTM # imports the UTM module Ellipsoid=23-1 # UTMs code for WGS-84 StationNFO=open(’station.469113 37P . I really do have one that I downloaded from here: http://code.8.Lons[-1].LLtoUTM(Ellipsoid.166 CHAPTER 6. This reads the data into a list whereby each element of the list is a list of numbers from each line.

07766 2L etc.683618 8462168.8. I can open an output file [for appending ‘a’ or (over)writing ’w’] write a formatted string using the write method on the output file object with format string: #!/usr/bin/env python import UTM # imports the UTM module outfile=open(’mynewfile’. Zone)) The write statement uses the syntax: ’format string’%(list of variables tuple).py > mynewfile 167 But we yearn for more.Easting.92944 40S ADK : 521722.split() lat=float(nfo[0]) lon=float(nfo[1]) StaName= nfo[3] Zone. Format strings have these rules: • For each variable in (what you. FILE I/O IN PYTHON AAK : 458516.g. Northing. Zone)) The only significant changes are 1) the object outfile is opened for writing..6. more elegantly.3e for 10 characters with 3 after the decimal • where the number of characters include the decimal and padded spaces • As noted before.’w’) # creates outfile object Ellipsoid=23-1 # UTMs code for WGS-84 StationNFO=open(’station.write(’%s %s %s %s\n’%( outfile.strip(’\n’). Northing. Note that this will clobber anything in a pre-existing file by that name and 2) the output file gets written to in the statement with a write method on the output file object: outfile.45385 43T ABKT : 598330.. Northing=UTM.write(’%s %s %s %s\n’%(StaName.1f for 7 characters with 1 after the decimal %10. %i for integer.115522 4720850. %e for exponent • you can also specify further. So. the format string can include punctuation: .625 1U AFI : 416023. I could save the output with a UNIX re-direct: ConvertStations.179764 5748148.list’).712671 4198681.lon.LLtoUTM(Ellipsoid.) you need a format: %s for string. e.: %7. %f for float. Easting. Easting.readlines() for line in StationNFO: nfo=line.

770654 4690300. the ’\n’ string puts a UNIX line ending on it.y=4.56906 13S ANMO 366981.179764 5748148.%s\t%10.666259 9161062. The basic structure of a program with a Python function is: #!/usr/bin/env python def FUNCNAME(in_args): """ DOC STRING """ some code that the functions does something . or finding the great circle distance between two points on Earth.843985 3868044. A session using the script (ConvertStations2.170087 script.45385 43T ABKT 598330.56906 13S ANTO 482347.2.’hi there’.3e’%( LISA’S PYTHON NOTES x. we also have a way to do this of course. or converting between UTM and latitude/longitude coordinates (as in UTM.683618 8462168.07766 2L ALE 509467. Without that.843985 3868044. In % head mynewfile AAE 474238.1f. the whole file is but a single line (very annoying).9 Functions So far you have learned how to use functions from program modules like NumPy. my new favorite package).7807 36S AQU 368638.29194 20X ALQ 366981.115522 4720850.168 CHAPTER 6.469113 37P AAK 458516.254856 4413225.625 1U AFI 416023.hi there and a peek at the resulting file could look like this: % ConvertStations2.300e+03 • In the ConvertStations2.8. you learned about subroutines and functions which do this sort of work for you. You can imagine that there are many bits of code that you might write that you will want to use again and again. say converting between degrees and radians and back.712671 4198681. In Fortran.y) 4.1797 33T I’m assuming you know what the UNIX head command does or at least how to find out! 6.3e3 print ’%7.92944 40S ADK 521722.

6.141592653589793 print gimmepi() 2) You could use a Fortran like style. 1) You could have a function that doesn’t need any arguments at all: #!/usr/bin/env python def gimmepi(): """ returns pi """ return 3.’hi there’) print_args(42) .deg2rad(42. where there is a set list of what are called ‘formal’ variables that must be passed: #!/usr/bin/env python def deg2rad(degrees): """ converts degrees to radians """ return degrees*3.9.) 3) You could have a more flexible need for variables. separated by commas.9. print ’42 degrees in radians is: ’. If you want to pass some variables to the function. there are no output variables here. FUNCTIONS return out_args FUNCNAME(in_args) # this calls the function 169 6. they go where in arg sits.1 Line by line analysis def FUNCNAME(in args): The first line must have ’def’ as the first three letters.4.141592653589793/180. Unlike in Fortran. must have a function name with parentheses and a terminal colon. There are four different ways to handle argument passing. You signal this by putting *args in the in args list (along with any formal variables you want): #!/usr/bin/env python def print_args(*args): """ prints argument list """ print ’You sent me these arguments: ’ for arg in args: print arg print_args(1.

or other block of code. Return statement You don’t need this unless you want to pass back information to the calling body (see. This can later be used to remind you of what you thought you were doing years later. Function body This part of the code must be indented. Trust me . make a habit of always including one. I recommend that you just start doing it that way too. just like in a for loop. LISA’S PYTHON NOTES 4) You can use a keyworded. Python separates the entrance and the exit. we have to call the main program with the final (not indented) line main(): .arg2=42.9.170 CHAPTER 6. for example print kwargs() above). It can be used to print out a help message by the calling program and it also let’s others know what you intended.2 Main program as function It is considered good Python style to treat your main program block as a function too.) In any case. kwargs[key]) print_kwargs(arg1=’one’. where variables are passed back the same way they get in. See how it can be done in the gimme pi() example above. variable-length list by putting **kwargs in for in args: #!/usr/bin/env python def print_kwargs(**kwargs): """ prints keyworded argument list """ for key in kwargs: print ’%s %s’ %(key. In this case. (This helps with using the document string as a help function and building program documentation in’ll be glad you did.that means that you can write as many lines as you want. But unlike in Fortran. Notice the use of the triple quotes before and after the documentation string . 6. through the first line.arg3=’ocelot’) Doc String Although you can certainly write functional code without a document string.

so it won’t know about anything declared below as it goes through the script line by line. Your functions can then be called from within your program in the same way as for NumPy.141592653589793 def deg2rad(degrees): """ converts degrees to radians """ return degrees*3. This is because Python is an interpreter and not compiled . we’ve been running lots of functions and they were not in the program we used to call them.arg2=42. I can use the functions. all the functions preceded the main function. def print_args(*args): """ prints argument list """ print ’You sent me these arguments: ’ for arg in args: print arg I could then just import the module myfuncs from within another program.141592653589793/180.6.9. kwargs[key]) def main(): """ calls function print_kwargs """ print_kwargs(arg1=’one’. FUNCTIONS #!/usr/bin/env python def print_kwargs(**kwargs): """ prints keyworded argument list """ for key in kwargs: print ’%s %s’ %(key.arg3=’ocelot’) main() # runs the main program 171 Notice how in the above examples. just like we did with def gimmepi(): """ returns pi """ return 3. So let’s say I put all the above functions in a file called myfuncs. On the other hand. The trick here is that you can put a bunch of functions in a separate file (in your path) and import it. or just call for help: % python . or just interactively.



>>> import myfuncs >>> print myfuncs.gimmepi() 3.14159265359 >>> print myfuncs.print_args.__doc__ prints argument list >>>


Scope of variables

As in Fortran, inside a function, variable names have their own meaning which in many cases will be different from inside the calling function. So, variables names declared inside a function stay in the function. This is true unless you declare them to be “global”. Here is an example in which the main program “knows” about the functions variable V: def myfunc(): global V V=123 def main(): myfunc() print V main() In addition to being able to write your own functions, of course Python has LOTS of modules and a gazzillion functions. The enthought distribution that you are using Includes plotting, numerical recipes, trig functions, image manipulation, animation, and many more. We will explore some of these in the rest of the class. ASSIGNMENT P3: Write a subroutine module that has these functions: • a function that returns the bulk parameters relating to the Earth from this website: Also include the average radius of: 6,371 km • a function that converts degrees to radians • one that converts radians to degrees • one that converts longitude and latitude to cartesian coordinates. [hint, x = cos(az) cos(pl), y = sin(az) cos(pl), z = sin(pl)]], assuming a radius of unity • one that converts cartesian coordinates back to longitude and latitude



• and one that calculates the great circle distance between two points using the function to get the angular separation and the radius of the Earth to get the arc length. Assume the average radius of the Earth (gotten from the first function). Then write a program that takes keyboard entry for an longitude and latitude pair and prints out the X,Y,Z, converts back and prints the new longitude and latitude out (as a check) and gives you the great circle distance in km. [HINT: Take a look at the function SPH AZI in the Fortran chapter.] E-mail your code to


Combining F90 code with Python

Now you have the very basics of Python programming under your belt, we can try to pull together the different threads you have been learning by investigation how to combine F90 with Python. You might ask why not just use Python? or Fortran? The answer is that there is a lot of Fortran code lying around that you might want to use, but no way to visualize the data, so you want Python for that. Or you are solving an extremely computationally intensive problem (global climate model, or convection in the Earth’s core or mantle, or ....) and you need code that is as fast as possible. Although NumPy is compiled and therefore very fast, Fortran is still the fastest thing around. For whatever reason, you are taking a class in both Fortran and Python so it makes pedagogical sense to try to tie the two halves together. The next question is “How?”. There are several different approaches to this ranging from the simple to the sophisticated. The simple approach would be to create output files with Fortran and the read it in and plot it or whatever with Python. A more sophisticated approach would be to call subroutines and functions from a Fortran module which is imported like any other module into Python. This is more tricky and involves a Python package called f2py which came with your Python distribution. I have tested f2py using the gfortran and python packages that were recommended for this class and it worked fine. But I also had to get rid of my beloved antique /usr/local/bin/g77 compiler, but you probably don’t have one. This is just a trouble shooting tip. For reference, the URLs for these are: and



Because these websites change quickly, I also put the .dmg files on the class website: and Assuming you have installed everything properly, there we will cover three ways to use f2py in the following. These are: • Brute force: Try to get f2py to create a compiled module (ending in .so) from a standard F90 program, which can then be imported like any other module. Because Fortran subroutines have arguments that both go into the subroutine and come out, and Python doesn’t, f2py has to make guesses as to the use of variables and does its best. This works in simple cases, but can fail badly at times. • Signature File: Ask f2py to read through the code, picking out all the variables and create what is called a “signature file” (ending in .pyf). This has f2py’s guesses as to what the variables are supposed to do. The signature file can be edited to supply the correct intent of variables. Then f2py can create the compiled module based on what is in the signature file, which functions with fewer errors (from bad guesses). • F90 surgery: The Fortran code can be modified itself to help f2py in interpreting variables.


Brute force f2py method:

Let’s start with an example using the program gcf2.f90 from the chapter on Fortran. This has a function to calculate greatest common factors. In fact we don’t need all the fiddly bits at the top - just the function getgcf. Let’s save it in a file called gcf.f90: function getgcf(x, y) implicit none integer :: getgcf, x, y, i, z do i = 1, min(x,y) if (mod(x, i) == 0 .and. mod(y, i) == 0) getgcf = i end do end function getgcf To compile the function (or the whole program!), use this syntax:

6.10. COMBINING F90 CODE WITH PYTHON f2py -c gcf.f90 -m gcf


The -c switch specifies which file to compile and the -m switch specifies the stem of the output file. f2py will create something called that stem with .so appended to it, so if all is well you will get a file called The output file is a callable module from within python: >>> import gcf # note that no .so is needed >>> gcf.getgcf(8,4) # call the function in the usual way 4 The brute force method is not without potential problems. For example, we could use the function without checking for variable type and send the F90 function something with the wrong type, getting back the wrong answer with no error message. Also, f2py assumes that all variables are going IN to the subroutine and doesn’t know that some are intended to come out. So we need a way to “teach” f2py which variables are intended to go in and which are intended to come out. This can be done either with a “signature file” if you can’t modify the Fortran code itself, or by inserting a few python hints into the Fortran code itself. To illustrate the problem, let’s consider another F90 subroutine sph azi from the Fortran chapter: subroutine SPH_AZI(flat1, flon1, flat2, flon2, del, azi) implicit none real :: flat1,flon1,flat2,flon2,del,azi,pi,raddeg,theta1,theta2, phi1,phi2,stheta1,stheta2,ctheta1,ctheta2, sang,cang,ang,caz,saz,az if ( (flat1 == flat2 .and. flon1 == flon2) .or. & (flat1 == 90. .and. flat2 == 90.) .or. & (flat1 == -90. .and. flat2 == -90.) ) then del=0. azi=0. return end if pi=3.141592654 raddeg=pi/180. theta1=(90.-flat1)*raddeg theta2=(90.-flat2)*raddeg phi1=flon1*raddeg phi2=flon2*raddeg stheta1=sin(theta1) stheta2=sin(theta2) ctheta1=cos(theta1) ctheta2=cos(theta2)

& &



cang=stheta1*stheta2*cos(phi2-phi1)+ctheta1*ctheta2 ang=acos(cang) del=ang/raddeg sang=sqrt(1.-cang*cang) caz=(ctheta2-ctheta1*cang)/(sang*stheta1) saz=-stheta2*sin(phi1-phi2)/sang az=atan2(saz,caz) azi=az/raddeg if ( azi=azi+360. end subroutine SPH_AZI Let’s try the brute force f2py way: f2py -c sph_azi.f90 -m sph_azi and try sph azi out in Python: %python >>> import sph_azi >>> delta,azi=0.,0. # have to declare these.. >>> sph_azi.sph_azi(33,-117,41,-72,delta,azi) # note module/function name are same. >>> print delta, azi 0.0 0.0 Well, that didn’t work. The problem is that Python can’t get the variables delta, azi back out from the subroutine. The Fortran style of using the entrance as the exit makes it tough to figure out which variables are supposed to go in and which are supposed to come out, to f2py doesn’t even try. The solution is to use the “signature file” method.


Signature files

We can use f2py to create a signature file sph azi.pyf with the command: f2py sph_azi.f90 -m sph_azi -h sph_azi.pyf The syntax is a little different from the brute force method in that we are not compiling sph azi yet, we are just creating the .pyf file (specified by the -h switch, for use in the eventual sph azi module (specified by the -m switch). If we look inside the ph azi.pyf file, we find: ! -*- f90 -*! Note: the context of this file is case sensitive. python module sph_azi ! in

all we have is a list of all the variables f2py found. This is done with the by inserted the function intent(in) or intent(out) after the variable type: python module sph_azi ! in interface ! in :sph_azi subroutine sph_azi(flat1.ioc. we can compile sph azi with the command: % f2py -c sph_azi1. ! See http://cens.flon1.pyf sph_azi. Because in the case of sph azi this is not true (del and azi are coming out). Let’s see if that one works better: % python >>> import sph_azi .del. COMBINING F90 CODE WITH PYTHON 177 interface ! in :sph_azi subroutine sph_azi(flat1.pyf file to explicitly say which variables are coming in and which are coming out.flon1.pyf.flon2.flon2. so the variable names within the . Note that while Fortran doesn’t care about case. (You can suppress this with the –nlower code are converted to lower case by default.6. Python does.10.f90 real :: flat1 real :: flon1 real :: flat2 real :: flon2 real :: del real :: azi end subroutine sph_azi end interface end python module sph_azi ! This file was auto-generated with f2py (version:2).f90 which creates a new file sph azi.flat2.del. we must edit the .ee/projects/f2py2e/ At this point.pyf file as sph azi1.azi) real intent(in) :: flat1 real intent(in):: flon1 real intent(in):: flat2 real intent(in) :: flon2 real intent(out) :: del real intent(out) :: azi end subroutine sph_azi end interface end python module sph_azi If we save the modified .) The default assumption is that all of the variables found are headed IN to the subroutine and not intended to come out.azi) ! in :sph_azi:sph_azi.

41. flon1.azi=sph_azi.ang. IF you can modify the F90 source.flat2. flon2. return end if pi=3. saved as sph azi2.and. 6. azi=0. . .141592654 etc. . We can then compile the modified code with the command: f2py -c -m sph_azi2 sph_azi2. huh?).) ) then del=0. flon1 == flon2) !f2py intent(in) flat1 !f2py intent(in) flon1 !f2py intent(in) flat2 !f2py intent(in) flon2 !f2py intent(out) del !f2py intent(out) azi if ( (flat1 == flat2 .azi.or. without touching it.stheta2.or.) . flat2 == 90. but f2py will recognize (sneaky. & (flat1 == 90. azi 36. you can skip the signature file by inserting special commands.ctheta2.cang. then use Cf2py instead of ‘f2py’ but this isn’t included in the Enthought Python you installed.raddeg.f90 This works just like the signature file example but using the module name sph azi2 instead of sph azi. LISA’S PYTHON NOTES >>> delta.0623321533 And it does! 6.3 F90 Surgery In the last section we saw how to use F90 code. & (flat1 == -90. flat2. just by clarifying a few things for poor old f2py.del.4012794495 64.and. & sang.f90: subroutine SPH_AZI(flat1.10.flon1.and. & phi1.sph_azi(33.caz. and I have never used it. called ‘f2py directives’ that the Fortran compiler will ignore (because they start with a ’ !’).flon2.saz. so you are on your own here. del.-117.theta2.phi2.-72) >>> print delta.ctheta1.4 A few more things you need to know: • NB: If you are modifying Fortran 77. flat2 == -90.pi.178 CHAPTER 6. azi) implicit none real :: flat1. Here is an example of a duly modified code.10.theta1.

11 Classes Before we go any further. use. there are many references to a module named Numeric. see the documentation available here: http://www. ASSIGNMENT P4 Modify your ASSIGNMENT F8 such that that main program is in Python and calls your F90 subroutine.6. Here is an simple example of a class definition: . Use the F90 surgery method above to modify your subroutine such that it compiles without the use of signature files. we need to learn some basic concepts about classes. but somewhat dated reference manual available here: http://cens. • For more detailed information on what f2py is really doing. use: intent(inout) • For variables are are change in Note that in the latter.allocatable) 179 • Watch out with arrays – Fortran and the default NumPy arrays are the transpose of one another! There are ways spelled out in the NumPy documentation for making your Pytnon arrays behave the same as the Fortran ones .edu There is also a helpful.. CLASSES • For variables that are both in and out.g. for example and a rudimentary understanding of what they are and how they work will come in handy when we start doing anything but the simplest plotting exercises. e. which is a predecessor of NumPy . intent(out. Class objects lie behind go read that before you get fancy ideas. • f2py converts all the Fortran subroutine names to lower case.ioc. You can suppress this with a –n-lower option. use: intent(inplace) • For allocatable variables.scipy. A class object is created by a call to a “class definition” which which can be thought of as a blueprint for the class object. E-mail both files plus the script you would use to compile them to ltauxe@ucsd. These are the basis of “object oriented programming” OOP (that again!) don’t try to call it because you don’t have it installed.

C is an object with “attributes” (variables) and “methods”. retrieves the current value of that attribute.132741228718345 >>> C.r=2. .283185307179586 In spite of superficial similarities. LISA’S PYTHON NOTES class Circle: """ This is simple example of a class """ pi=3. followed by any variables you want to pass into the method.pi # retrieve an attribute 3.180 CHAPTER 6.area() # get a new area 6. it defined the attribute r. >>> C. Attributes can be changed (as in C. So the init method initializes the instance attributes of an object. or “self”.0 >>> C=Shapes. to use it.r): self. which gets passed in when the class is first called.r**2 def circumference(self): return 2. Asking for any attribute (note the lack of parentheses).Circle(r)). Although the Shape module is imported just the same as any other.Circle(r) # create a class instance with r=4. we first have to create a class “instance” (C=Shapes. In the above case. All methods (parts that start with “def”). The other methods (area and circumference) are defined like any function except note the use of ’self’ as the first argument.141592653589793 >>> C. no other parameters are passed in because the only one used is r. classes are not the same as functions.area() # retrieve a method we can use it in a Python session in a manner similar to function modules: >>> import Shapes # import the class >>> r=4. have an argument list. so the argument list consists of only self.0 # change the value of r >>> C.0). The first argument has to be a reference to the class instance itself. Calling these methods returns the current values of these methods.5*self.pi*self.r=2. This is required in all class method definitions.r=r def area(self): return 0.r Saving this class in a file called Shapes. In our case.*pi*self.141592653589793 def __init__(self.

12.sthurlow. Actually matplotlib is a collection of a bunch of other modules. where appropriate.12 Matplotlib So far you have learned the basics of Python. • these classes should have methods that return things 6.sourceforge. circumference. sphere. MATPLOTLIB 181 You can make a subclass (child) of the parent class which has all the attributes and methods of the parent. • write a class called Earth that has attributes using the bulk parameters from assignment P3 • write a program that uses the Earth density. If you are curious about classes. For a fairly complete and readable tour of matplotlib.1 A first plot Let’s start with a simple plot script (matplotlib1. the bottom line about classes is that they are in the same category of things as variables. http://www. they are ‘data structures’ .pdf and here: http://matplotlib. mass (pass the argument density). So. methods and classes. check out these links: http://matplotlib. ASSIGNMENT P5 • Write a module called Shapes • Shapes should have classes for: circle. That is.they hold data. radius from the Earth class. How does this compare with the mass given by the Earth class? 6. The most mature and the one I am most familiar with is matplotlib. dictionaries. lists. etc. passes these to the sphere class and calculates the mass. a popular graphics module of Python. but you can find useful tutorials online: (e. But Python was sold as a way of visualizing data and we haven’t yet seen a single plot! There are many plotting options within the Python umbrella. NumPy and how to link F90 code with Python. and cube. there’s lots more to know about classes that we don’t have time to get into. cylinder.12.. but may have a few attributes and methods of its own. You do this by setting up another class definition within a .g. toolkits. and the methods to process that data.

3]) # plot some numbers pylab.lines.Line2D object at 0x4bd6eb0>] The bit about [<matplotlib. we can view it with the show method.182 CHAPTER 6. there are LOTS of methods. it imports matplotlib. we call the plot method with a list as an argument. such as the Y axis label can be changes with the ylabel method. In the above example. When we are done customizing the plot instance.the class instance is implied and is the “current plot”.plot([1. I use the very old school backend called “TkAgg” backend because it “works”. including. so step 3 is: import pylab.use("TkAgg") >>> import pylab >>> pylab.2.plot([1. It must be loaded alongside matplotlib.use(“TkAgg”). So step 2 sets the backend: matplotlib.plot([1. After that the fun starts. As I mentioned. Figures are rendered on “backends” so they appear on screen. Some work better on different operating systems. we will get a plot something like this: .g. if you do the above example in interactive mode: >>> import matplotlib >>> matplotlib. matplotlib uses the concept of “classes” to make plots and this has just happened behind the scenes.3]).use("TkAgg") # my favorite backend import pylab # module with matplotlib pylab.figure()) and then referred to it later with the command fig. Attributes of the pylab class. an xlabel method. The module matplotlib itself contains a lot of other modules. In any case. We could have named the plot instance with a the figure() method (e. When that gets # reveal the plot The first step should be obvious by now.2.lines. pylab is the “business end” that has a lot of plotting methods and classes. but we don’t have to in this simple case . it assumes they are y values and supplies the x values for you. LISA’S PYTHON NOTES #!/usr/bin/env python import matplotlib matplotlib. You can tell this.3]) [<matplotlib.2. surprise. There are a lot of different backends with slightly different looks. One of these..ylabel(’Y’) # label the y-axis pylab. fig=pylab.Line2D object at 0x4bd6eb0>] is Python’s way of telling you that you just created an object and something about it. As you can imagine. when you give plot() a single sequence of values (as above).

we won’t be able to change the plot any more and in fact.. you can tweak the program like this: #!/usr/bin/env python import matplotlib matplotlib.png. or save them with the disk icon.ion() # turn on interactivity pylab. .3]) pylab. The . .png file formats.svg.eps’) The method pylab.FMT can be one of several.savefig(’myfig. If you find it annoying to always have to close figures with the little red button. e.g.eps.pdf.ylabel(’Y’) pylab.12. MATPLOTLIB 183 Use the red button to close the plot window Use these buttons to save and modify your plot Once that happens. .gif. Adobe Illustrator likes .2.jpg. .draw() # draw the current plot ans=raw_input(’press [s] to save figure. Some of these (the vector graphics ones . .FMT). we won’t get our terminal back until the little plot window is closed.6.svg. You can save your plot with the little disk icon in a variety of formats. or . any other key to quit: ’) if ans==’s’: pylab. . ."TkAgg") import pylab pylab.eps while Microsoft products like .plot([1.savefig(FILENAME.).

Y2 . and ’g^’ are green triangles.s.10) r=x* which produces the plot: 1. and I invite you to check out the matplotlib documentation. Y1 .x.arange(0.5 0. if you give plot() a single sequence of values.0 0. As mentioned earlier. you can probably figure out that a line style of ’r–’ is a red dashed line.c.pi/180. There are many other attributes that can be controlled: linewidth. ps. dash style. Garbage in. eps and svg) can be opened in Adobe Illustrator for modification.cos(r) s=numpy. it assumes they are y values and supplies the x values for you. X2 .). etc.     1. line style 2.plot(x. line style 1.sin(r) #!/usr/bin/env python import matplotlib matplotlib.0 0. But don’t panic. where ’line style’ is a string that specifies the line style as illustrated in this script called matplotlib2.360. LISA’S PYTHON NOTES like pdf. But plot() takes an arbitrary number of arguments of the form: (X1 .’r--’.184 CHAPTER 6.0 0 50 100 150 200 250 300 350 . garbage out. keyword argument passing and other pythonalia to be able to figure things out on your own. you should understand enough about classes. By now. etc.use("TkAgg") import pylab.5 From the code. c=numpy.’g^’) pylab.numpy x=numpy.

*numpy. The values are 0-1 in relative figure coordinates. so we didn’t have to name it.sourceforge.7. MATPLOTLIB 185 I’m going to lead you through a few more examples.figure(num=1.use("TkAgg") import pylab. numpy def f(t): return numpy.6. add axes([0.figsize=(5. e. In the preceding examples. but for fancier figures with several #!/usr/bin/env python import matplotlib matplotlib. including adding subplots. If you want more freedom. 6. that subplot becomes the current figure for plotting on.. bottom.02) fig=pylab. To illustrate these new concepts. Notice the syntax whereby figsize is a method with width and height (in inches) specified by a tuple and fignum is the figure number.add subplot(121) for 1 row.5)) .. use the add axes([left. we only had one figure.arange(0. After each add subplot command.pi*t) t1= numpy. matplotlib3.0.7)).0. we can create named figure objects by invoking a figure instance: fig = pylab.5.figure Once we have a figure instance (sometimes called a “container”). To do this. one column and this is the first plot. and that there are many more: consult the list of **kwargs in the online documentation located here: http://matplotlib.g. To make plots side by api.cos(2. two columns..figure(num=1. height]) 0 method.1) t2= numpy.figsize=(7.pyplot. pylab has the concept of “current figure” which subsequent commands refer to.width. you want to make a subplot at an arbitrary place.exp(-t)*numpy.arange(0.. say.0.1.5. which I hope will speed you on your plotting way..0.2 Multiple figures and more customization As already mentioned. etc. we can do all kinds of things. we can use the syntax: fig.add_subplot(211) Here the argument 211 means 2 rows.1. you would use: fig. Notice that these are keyword arguments.0.3]).12. consider the example code.html#matplotlib.

.2 −0.’k-’) fig.[1.75.add_axes([.ylabel(’Inset’) pylab.6 −0.8 1.2 0. LISA’S PYTHON NOTES fig.f(t1).2 0.g.5 0.plot(t2.use("TkAgg") import pylab.f(t1).0 − which produces: 1.0 2 3 4 5 1.0].4 0.186 CHAPTER 6. legend and arrow methods..0 0. using the title.1].4 0.1].0 −0.0 Inset 1 0.6 0.’r-’. Let’s decorate one of our early examples to show how some of these things work: #!/usr/bin/env python import matplotlib matplotlib.6 0.25.arange(0.0 0.6 0.’r-’) pylab.numpy.1].6.4 −0.plot([0.plot(t1.cos(2*numpy.numpy x=numpy.[0.3 Adding text We already met xlabel and ylabel. But text can be added in a other ways.8 0 1.2 0.12.’r--’) pylab.10]) pylab.5 −1.add_subplot(212) pylab.10) ..plot(t1.0 0.pi*t2). e.4 0.0 0.360.add_subplot(211) pylab.8 0. text.8 0.xlabel(’Time (ms)’) fig.’bo’) pylab.[0. you should be able to figure out what everything in that script does by yourself! 6.0 0 1 2 Time (ms) 3 4 5 By now..

legend([’cos(x)’.s.0 0 50 100 150 200 250 300 350 $\theta .’k-’) pylab. Also note that the legend and xlabel methods use a special format for strings (r’LateX String’) which allows embedded LaTeX equation syntax to make scientific equations look right . color and the like. So.-. kwargs) method also has optional key word arguments.25).x.6.0 187 Fun with trig 0.xlabel(r’$\theta’) which produces this plot: 1.0). which has a lot of other attributes as well.5 0.\ xy=(175.string.’pithy note’) pylab.s2.     cos(x) sin(x) sin(x ) 2 1.0 triangles! 0.’g^’. the arrow gets drawn with the annotate method.\ shrink=0. The pylab.sin(r)**2 pylab. MATPLOTLIB r=x* now you have to learn LaTeX!.text(250.text(x.\ ’sin(x)’.05)) pylab.pi/180. size.5.cos(r) s=numpy.5 pithy note The title appears at the top of the plot.r’$\sin(x^2$)’]. every line or point style that you want in your legend. append a label to the label list after the relevant plot command. specifying font.title(’Fun with trig’) pylab.x.xytext=(110.plot(x. Text labels get places at the x and y coordinates on the plot and the legend will appear in the upper/lower right/left corner as specified in the string. c=numpy.-.c.y.’lower left’) pylab.sin(r) s2=numpy. The legend ’labelist’ is a list of labels for each plot element. Finally.’r--’.annotate(’triangles!’.\ arrowprops=dict(facecolor=’black’.12.

2"/> . This is ALWAYS a good approach ..xml looked something like this: <?xml version="1.188 CHAPTER 6. The best thing to do is to look through the online documentation for a plot that looks like what you need.dat has δ 18 O data versus age (in ka). I’m just going to show you a few examples. LISA’S PYTHON NOTES Check the matplotlib documentation for details.. e. This a compressed (gnu zip) XML file. whisker plots. then modify it. For those of you who don’t know. the file (called merged catalog. ASSIGNMENT P6 The file SPECMAP. -the LaTeX code for δ 18 O is: $\delta^{18}O$ • send the script to me at ltauxe@ucsd. Write a Python program that : • reads in the data and • makes a simple X. 1984 variations in oxygen isotopic ratio of seawater controlled by changes in global ice volume which in turn was forced by the Earth’s orbit.7"/> <param name="latitude" value="38.start with something that works and fiddle with it until it suits your own particular needs. histograms.7862"/> <param name="depth" value="1. from the website: http://earthquake.7"/> <param name="magnitude" value=" 6.php by clicking on the “XML merged catalog. contour plots. After unzipping it (by clicking on it). this is classic record of Imbrie et al.Y plot with symbols connected by lines • put Age on the X axis and δ 18 O on the Y.g. past 7 days” link.8147"/> <param name="longitude" value="-122. magnitude etc.0" encoding="UTF-8"?> <merge> <event id="71672091" network-code="NC" time-stamp="2011/11/03_23:03:32 " version="2"> <param name="year" value="2011"/> <param name="month" value="10"/> <param name="day" value="28"/> <param name="hour" value="21"/> <param name="minute" value="21"/> <param name="second" value="52.4 Histograms I downloaded a week’s worth of earthquake location.usgs. pie charts. There are lots of graphing styles possible with matplotlib.

readlines() EQs=[] # list to put EQ dictionaries in linenum=0 while linenum <len(input): if ’event id’ in input[linenum]: # new event EQ={} # define a dictionary linenum+=2 # increment past time-stamp while ’param’ in input[linenum]: record=input[linenum].append(EQ) linenum+=1 # look for next event id return EQs EQs=readEQs(’merged_catalog.hist(Magnitudes.strip(’"’) EQ[datakey]=record[2].6"/> <param name="azimuthal-gap" value="42"/> <param name="magnitude-type" value="D"/> <param name="magnitude-type-ext" value="Mcd = coda duration magnitude"/> <param name="num-stations-mag" value="3"/> <param name="stand-mag-error" value="0. In this example.12.bins=50.normed=True) # plot ’em .strip(’"’) linenum+=1 # keep going until </event> if ’</event>’ in input[linenum]: # done with event EQs. I plot a histogram of the magnitudes: #!/usr/bin/env python import matplotlib matplotlib.use("TkAgg") import pylab def readEQs(infile): input=open(infile.xml’) Magnitudes=[] # set up container for eq in EQs: # step through earthquake dictionaries Magnitudes.split()[0]. Reading in all the data.00"/> <param name="hor-error" value="0.split(’=’) datakey=record[1].ylabel(’Frequency’) pylab. I can plot them various ways.append(float(eq[’magnitude’])) # collect magnitudes pylab. MATPLOTLIB 189 <param name="num-phases" value="8"/> <param name="dist-first-station" value="0.’rU’).0"/> <param name="rms-error" value="0.6.1"/> <param name="location-method" value="h"/> <param name="location-method-ext" value="Hypoinverse (Confirmed by human review)"/> </event> <event id="71672096" network-code="NC" time-stamp="2011/10/28_21:30:19 " version="0"> <param name="year" value="2011"/> <param name="month" value="10"/> etc.xlabel(’Richter Magnitude’) pylab.8"/> <param name="ver-error" value="0.strip(’\n’).strip(’/>’).

incrementing linenum until we have all the keys picked off and hit the ’<event >’ line. we split on the space which puts the key name (which puts the key name enclosed in quotes in the first element of a list. First.6 Frequency 0. We can label the plot as per usual and display it with show(). LISA’S PYTHON NOTES 3 4 Richter Magnitude 5 6 7 In the example. hunt through the list.2 0. EQ. strip off the end of line character and the quotes.3 0. we look for the new event marker. To get the key name. then split the record on its ’=’. This way. We pair the value with the key in the EQ dictionary and continue. This we use as the key in the dictionary. . We plot the histogram using the pylab. To get the value. The dictionaries get appended to a list. After we have parsed the data file into a list of dictionaries. picking out the magnitude data and after turning it into a float. We keep going until we have read all the data.4 0. The second element contains the key and the third element the value. we just put the float of the ’Magnitude’ column into the list Magnitudes. we make a list for the thing we one to plot (Magnitudes). In this case.1 0. any particular key could easily get fished out later for plotting. please notice the clever way in which we parse the XML code.0 0 1 2 CHAPTER 6.7 0.5 0.hist method. we append it to a list of all the dictionaries.8 0. This gives a element list with what we need. These get plotted in the histogram. increment linenum and press on. which we select and strip off the quotes.190 0. append it to the list. we use the third element in the ’record’ list (record[2]). When we are done with a dictionary.

append(float(num)) Labels.Labels=[].8): # assume no magnitudes bigger than 8 last week! num=0 # initialize count for eq in EQs: eqm=float(eq[’magnitude’]) if eqm<m and eqm>bin0:num+=1 # count all magnitudes in this bin Fracs.use("TkAgg") import pylab from readEQs import * EQs=readEQs(’merged_catalog.12. So if you want to see data as a pie chart. say the fraction of earthquakes in each magnitude bin from the last example. but some people love them.12.xml’) Fracs.title(’Silly Pie Chart’) pylab.6.[] bin0=0 for m in range(1.pie(Fracs. .5 Pie Charts I mostly think pie charts are silly.append(str(bin0)+’-’+str(m)) bin0=m # increment to next bin pylab. we can modify the script thusly: #!/usr/bin/env python import matplotlib matplotlib. labels=Labels) pylab. MATPLOTLIB 191 6.axis(’equal’) # make the pie round! Silly Pie Chart 0-1 6-7 5-6 4-5 1-2 3-4 2-3 Notice how the function readEQs from the histogram example has been put into a module by itself and then called within this program.

Here is a simple example.360.lon_0=0.resolution=’c’) # create a map instance map.drawcoastlines() map.12.eps) # save the figure in EPS format .Lats) # calculates the projection of the X. Once you know Python.30)) # draws longitudes from list map. using our earthquake data from the histogram example to make a mollweide projection with the earthquake locations as red dots.basemap import Basemap EQs=readEQs(’merged_catalog.plot(X. LISA’S PYTHON NOTES 6.numpy from readEQs import * from mpl_toolkits. but python can make maps too.192 CHAPTER 6.drawmapboundary() map.arange(-60. it can be much easier to use GMT because the same principles apply and all of the power of matplotlib is available for enhancing your plots.’ro’) # uses pylab’s plot to plot these arrays pylab. We generate maps with a special “toolkit” of matplotlib called Basemap.drawparallels(numpy.30)) # draws latitudes from list X.Y pylab.append(float(eq[’latitude’])) # collect the latitudes (as floats) Lons.Y=map(Lons.6 Basemap Most of your maps can be made with GMT.90.Y.use("TkAgg") import pylab.[] # set up lists for location data for eq in EQs: # step through the list of earthquakes Lats.xml’) # read in data (see histogram example) Lats.append(float(eq[’longitude’])) map=Basemap(projection=’moll’.Lons=[].arange(0.drawmeridians(numpy. #!/usr/bin/env python import matplotlib matplotlib.savefig(map.

12.360. resolution.arange. The details of these key word arguments depend on the projection you choose. To draw the coastlines.6. instead of struggling with two completely different and incompatible plotting packages. all the things you set with switches in pscoast are set with keyword arguments in the call to Basemap. Lons). The basic concept of Basemap is that you create a map class instance with a call to Basemap. Then we fish out the latitude and longitudes from each earthquake dictionary (eq) and append the floating point equivalent (remember they are strings in the dictionary!) into the relevant lists (Lats. GMT is you can build on your knowledge of matplotlib. check the documentation available here: http://matplotlib. but we could have used range(0. the class chews on them and spits out x. The advantage of using Basemap over.).html ASSIGNMENT P7 Redo your GMT1 assignment using the Basemap toolkit!. one of the more useful for Earth Scientists is the contour plot.github. central longitudes. map center. you can modify attributes in using methods available to this particular subclass. etc. Here is a example of the gravity anomaly . To draw the lines of longitude we use the method drawmeridians() with the an array (or list) containing the longitudes you want to plot. After you create the map instance (called map) in the above example.y values based on the projection we specified when creating the map instance with Basemap. MATPLOTLIB 193 In this example.g.e.30) or any arbitrary integer or floating point list. By sending in the longitudes and latitudes of the earthquake locations as arguments to the map class. EQs is read in with the same file reading function from the histogram example. Y lists using the ‘regular’ pylab plotting functions. use the method drawcoastlines(). We can go on and decorate the map with anything available in pylab. For more examples. The attributes of you map (e. projection. Now we can plot the returned X. i.12. Add a point labelled “Now I’m here!” and the location of SIO. Now we want to plot a bunch of points on the map.. In this case we generated the array with numpy. the list of earthquake dictionaries.. Drawing the lines of latitude works the same way (with the drawparallels() method).7 Contour plots Of the many plotting methods available in matplotlib. 6. map boundaries.

Spectral) pylab.imshow(g.*(h**2+z**2)) . # radius in meters z=3.arange(-2.pi*R**3.interpolation=’bilinear’. Then we calculate the gravity anomaly g for a spherical mass with radius (R) at depth of z with the command: g=(G*4. each column in Y is a copy of y and there is a column for every element in x.sqrt(X**2+Y**2) calculates the horizontal distance h from the origin for every point on the X.20 20 1.*drho)/(3.*numpy.Y grid.*drho)/(3.15 0 20 40 60 80 100 120 The first new function for us in the above example is meshgrid.05 40 0.45 100 0.axis(’equal’) pylab.*(h**2+z**2)) pylab.0.arange(-2.Y=pylab.meshgrid(x.60 80 0.1) X.sqrt(X**2+Y**2) g=(G**z.pi*R**3.1) y=numpy.90 0.75 60 0. The line h=numpy.*z. LISA’S PYTHON NOTES #!/usr/bin/env python import numpy import matplotlib matplotlib.use("TkAgg") import pylab G=6. These have the dimensions of x by y.0.2. Each row of X is the same as x and there is a row for every element in y.y) h=numpy.colorbar() pylab.2.   1e 7 0 1. This makes 2D arrays X and Y for a 3D mesh/surface plots.*numpy.67e-11 # grav constant in Nm^2/kg^2 (SI) R=2.*z.30 0.*z. # depth of burial drho=500 # density contrast in kg/m^3 x=numpy.194 created by a buried sphere: CHAPTER 6.

.. we can take advantage of the computational tools available in NumPy and another scientific package called Scipy.. and polyval(coeffs.44295575e-08] 1.. arange().44221090e-08 1.. Order is two for a quadratic polynomial. be aware that a lot of people are red-green color blind and appreciate some other color contrast. 1.42112058e-08 1.40028722e-08 1. Now meet polyfit(x.42112058e-08 1.order).46508813e-08 . DEEPER INTO NUMPY AND SCIPY 195 You can find the formula for this in any geophysics text book.y..42148210e-08 1. among others.46470410e-08 1.46508813e-08 [ 1.. [ 1..x)..46508813e-08 .48751394e-08 [ 1..use("TkAgg") .48751394e-08 1.42148210e-08 1.42112058e-08 .44295575e-08 1.48751394e-08 1.42112058e-08 [ 1.. When choosing color maps. See how these work in the following example: #!/usr/bin/env python import matplotlib matplotlib.13 Deeper into NumPy and Scipy Now we have some plotting skills under our belt.44295575e-08] 1.44295575e-08 1.. 1.46470410e-08 1. looks like this: [[ 1. 1. (y = ax2 + bx + c) and three for cubic (y = ax3 + bx2 + cx + d).46470410e-08] 1.40028722e-08 1.42148210e-08]] It is a 2D array in which every element is the value of g at that grid point.6..40028722e-08] 1.37971509e-08 1.46470410e-08 1...48751394e-08 .. To find a best fit line (y = mx + b where m is the slope and b is the intercept) we can use polyfit() by setting for order to one. now we have g which if you print it out... but here we plot it as a contour plot.44295575e-08 [ 1. 6.44295575e-08 .. There are a bunch of ways to visualize this.40028722e-08 1. arctan2().46508813e-08 . sin()..44295575e-08 1. like the blue-orange one chosen here.44295575e-08 . pi(). 1.. 1. The former fits an n-order polynomial to input data and returns a list of the coefficients and the latter evaluates the value at x using coefficients returned from polyfit. We have already met these: cos().42148210e-08] 1.13.51063696e-08 1. 1. Anyway.44221090e-08 1. To do this we interpolate between all the grid points and choose a color map translating the value of g into a color from blue to orange.

2 ].0 3. 19. it returns a list coeffs=[ 1.’ro’) coeffs=numpy. 34.plot(x.plot(X. y) which are red dots.. 11. LISA’S PYTHON NOTES import numpy.12 -0.3095 0.1) Y=numpy. we sent it new values for y (y2) and asked for a second order polynomial fit.24.5 2.86. We plot these values as the red 45 40 35 30 25 20 15 10 5 0 1.4.plot(X.X) pylab.Y2. ..plot(x.3.5 3.].polyfit(x. This list can be passed directly into polyval().5 4.x[-1]+.X) pylab.196 CHAPTER 6.arange(x[0].polyfit(x.42.Y.7975 1.1) pylab.0 2.2) Y2=numpy.4...polyval(coeffs.’b-’) pylab. b.4.’bs’) coeffs2=numpy.y2.5925] which are a..87] pylab.8. which returns the y values evaluated at the positions in the X list (or array) that is passed in.polyval(coeffs2.2.[1.pylab from numpy import random x. c respectively.5 In the first call to the function polyfit().5. In the second call to the function polyfit(). with the coefficients m and b.y.y. so be careful.2] # defines two lists X=numpy. strangely it has no commas.0 4.y=[1.1. coeffs2 is [ 1. compared to the original data points (x.0 1.3.’r-’) y2=[3.y2. This in turn gets churned through polyval() and plotted as the blue curve (as compared to y2 which are the blue dots).

].]. 3. Now we delve deeper.reshape(5.:-1:2] array([[ 6.. we have the index() method: L. 20. 22. 13.. And you also know that B=L[2:] takes all the elements from 2 to the end.. And to use a part of a list (a slice) we use. so for the list L=[0.... 13... 19.]]) . >>> B[1:3.5.13. 15. The index of the last item is -1.. 17. or i:j:k.2. 14..6) array([[ 0. 10. 14.1 More on slicing with arrays We zoomed by the finer points of list and array indexing earlier in the chapter. 10.]]) Let’s pick about the statement B[1:3. 7.. 26. eager to get to plotting... 15.:-1:2] to see if we can understand what it does.4. 16.g. 16... we step through all the j’s for each i at step k.. 9. 11.6..].30) >>> B=A. First a review of lists.]]) 4.. [ 12. 13.. We actually already used this method when we implemented command line arguments..index(4). we all but the last element: >>> B[1:3.... 16.linspace(0... 8. indexing starts with 0. so things get hairy fast. [ 12. in other words. 29.. which will return the number 2. 10... 10.8]..]. but these are multidimensional objects. 8. 15. The basic syntax is the same: [start:stop:step]. which defines B as a list with L’s elements 2 and 3 (4 and 6).:-1] array([[ 6..]]) Here j goes from [:-1]..6. 7. 14. e. 5..29. 16. 2. 17. 23. You will recall that in python. DEEPER INTO NUMPY AND SCIPY 197 6.]. 21.. The first part alone returns lines 2 and 3: >>> B[1:3] array([[ 6. This is best shown with examples: >>> import numpy >>> A=numpy. [ 6. 9.. for example. To find out what the index for the number 4 is. [ 12.. so L[-1]=8. [ 12. 8. 7.. if the step is omitted it is assumed to be 1.... 28.. 1. We know that to reassign a given index a new value we use the syntax L[1]=2. 9.]. 25..13... L[1] is 2. [ 18. 14. 27. Arrays (and matrices) work in a similar fashion to lists. but it wasn’t really explained. you can infer that the basic syntax for slicing is [start:stop:step]. [ 24.. 8... but with Python arrays. B=L[2:4].. From these examples.]. 11..

] If you really want to step through element by element.] 23. print e . 16. 3.0 3..scipy. 15. 28. 22.. or bootstrap statistics. [ 12.. 16.0 etc. LISA’S PYTHON NOTES And finally. 19. 14. print r .html 6. we learned that for loops with lists just step through item by item. 26. 20. These applications require that you be able to generate random numbers from a variety .0 1.]]) For more on array slicing (indexing).org/doc/numpy/reference/arrays. 8. see: http://docs. 13. For example. 27. they steps through row by row (like in slicing).indexing. see: http://docs.:-1:2] array([[ 6. 4. [ 24..3 Random Numbers Many scientific investigations use techniques such as Monte Carlo simulations.html 6.. >>> for r in B: .. 0. 7.scipy.2 Looping through arrays Earlier in the course. For more on looping (or iterating).. 9. 2. 8.nditer..ravel(): . In n-dimensional arrays.] 17. [ 0.198 CHAPTER 6.].13. which you (hopefully) will learn about in future classes. 5.. which takes every other element: >>> B[1:3. 14. 21. [ 18.. [ 6.13. 1. [ 12.] 29. 11..0 2. 25. 10. we have the step of 2. you can use the ravel() method which flattens an N-dimensional array to a single dimension: >>> for e in B.]

The other embellishments were to the hist() module in matplotlib by increasing the number of bins (the default is too few in my opinion) and to change the color of the columns to a pretty shade of orange. .random.hist(Nums.13.facecolor=’orange’) read the documentation at: http://docs.title(’Uniform distribution’) 35 30 25 20 15 10 5 0 10 12 Uniform distribution 14 16 18 20 The new twist here is the call to the uniform() method of the random() module of NumPy.uniform(min. DEEPER INTO NUMPY AND SCIPY 199 of distributions.20 bins=(max-min)*2 Nums=[] for n in range(N): Nums. Python does this with the numpy.use("TkAgg") import pylab from numpy import random N. This returns uniformly distributed numbers between the min and max values specified.bins=bins.random module.6.html Let’s look at a few of these: #!/usr/bin/env python import matplotlib matplotlib.scipy.10.max)) pylab. To learn more.

Numpy has a number of useful functions and there are many more hidden in the stats module of the Scipy package. . Here we have an example of how to use it to retrieve numbers from a normal distribution with a mean of 10 and a standard deviation of 2: #!/usr/bin/env python import matplotlib matplotlib. LISA’S PYTHON NOTES 6.13.10. but the all time favorite is the normal. There are a large number of statistical packages available in the Enthought Python Distribution we are using for this class.4 Normal Distribution There are dozens of other distributions available in the random module.2 Nums=[] for i in range(N): Nums.bins=20.title(’Normal distribution’) pylab.normal(mu.sigma)) pylab.use("TkAgg") import pylab from numpy import random N.sigma=500.hist(Nums.200 CHAPTER 6.facecolor=’orange’) pylab.append( Statistics in Python All this talk about normal distributions makes me hungry for some statistical 60 50 40 30 20 10 02 4 6 Normal distribution 8 10 12 14 16 6. or Gaussian distribution.

scipy. standard deviation and sum. but to get you started. numpy..std()..sigma)) ANums=numpy. standard deviation and sum of our sample (Nums using the functions numpy.mean(ANums). we get: 10. we can use some of the fake data generated by the random. DEEPER INTO NUMPY AND SCIPY 201 For a summary of available functions. For fun. numpy. Let’s start with 1D arrays and find the mean.sum(ANums) We wanted to calculate the mean. with an √ N of 10.scipy. When we run this code.std(ANums).statistics.13.numpy.sigma=500.40647292 Note that you will get a different answer every time you run this because the random sample really is pretty random.html and http://docs.html Here we will consider a few useful functions to give you a feel for how they work.2 Nums=[] for i in range(N): Nums. not lists. From the normal distribution see: The documentation is still a bit thin.6.042.append(random. The mean and standard deviation here are Calculate the mean and standard error (standard deviation/ N ) values .array(Nums) print numpy. we generated a list of numbers drawn from a distribution with µ = 10 and sigma = 2: #!/usr/bin/env python import numpy from numpy import random N.0428129458 2. which are close to the true values of 10 and 2 respectively. see: http://docs..normal() function and see how the actual means and standard deviations of a data set drawn from a normal distribution compare with the true mean of µ and standard deviation σ. These work on arrays. so we first convert to an array: ANums=numpy. and 2.normal(mu.0027. ASSIGNMENT P8: Modify the statistics example above to calculate 1000 versions of Nums.10.mean(). numpy.array(Nums).sum().0027306608 5021.

4]) 6. i. etc.[4..3].GUIs Having introduced you to the joys of command lines. Plot a histogram of the means. For what fraction of the 1000 samples is this true? We can also use the statistics methods on n-dimensional arrays. radio buttons. it first builds the GUI then waits for something to happen (a menu to be selected or a mouse click or some data to be entered.202 CHAPTER 6.. The newer wxPython has now reached some maturity and comes standard with the Enthought Python Distribution. so we’ll use wxPython in this class.2.[1.2]]) >>> A.2.sum(axis=1) array([6.wxpython. they are fun. 6..wxpython.14 Graphical User Interfaces .com/wxpython/ and http://wiki. They allows greater degree of interactivity with your data visualization. The standard error times 1.0].org/Getting%20Started http://zetcode. . we can illustrate the use of the numpy..a state called an event loop. ) . There are a number of ways of creating GUIs in Python. They can streamline data analysis in an intuitive way. The oldest and most standard way is called Tkinter which is based on the even older UNIX language Tk.1. LISA’S PYTHON NOTES for each sample. And. When the program It seems to be the way things are going. why now a lecture on GUIs? GUIs work differently than all the other scripts we have been writing in that they don’t just start at one end and proceed through to the end .96 is the 95% confidence bound for the mean. see: http://wiki.e.sum(axis=0) array([6. sliders. the argument can specify the axis along which we want to do the calculation. Okay. how do I make a GUI? GUIs are composed of a number of things like text boxes. Recalling the arrays from before.array([[1.the program flow can be controlled by the user. the mean ± these bounds should contain the true mean (10) 95% of the time. 5.sum() function as follows: >>> A= numpy. GUIs let command line phobic people use your software. Here. 5]) >>> A. called widgets.

14.App app is an instance thereof Specify what happens on initialization.6.Show() app.MainLoop() Imports the necessary wxPython package App() is a sub class of pylab.Frame() frame. reveals the window . Frame is a class for the main windows frame is a particular window instance. GRAPHICAL USER INTERFACES .GUIS There are six essential parts to a wxPython GUI: import wx app = App() OnInit() or init () function frame = starts the progam 203 Here is a simple example that makes a window with an image in it: Did you know this was called the “shebang” line? STARTS THE MAIN EVENT LOOP wxPython package describes the application subclass initializes the App subclass makes an image object makes the main window (frame in wxPython) describes the frame in this application prepares image for display initializes the frame and displays the image resizes the window around the image makes a status bar which makes this window: .

events. by Rappin . Things that trigger actions like mouse movements and clicks. check boxes. .204 CHAPTER 6. button clicks. and layout. Setting up your GUI with a nice layout Getting data in and out. radio buttons. LISA’S PYTHON NOTES Elements of a GUI: Widgets Things you put on your GUI like text boxes. etc. dialogs. pull down menus. etc.a great intro to GUIs. The example is for a simple editor illustrating widgets. menu selections. see figure below. Pop up windows with information or action items. Events Dialogs and Messages Layout Input and Output Here are some common GUI widgets: Check boxes Buttons Menus List boxes Text Entry Radio Buttons Common GUI widgets From “wxPython in Action”. buttons.

bind it to OnQuit & add to box button id as result.6. GRAPHICAL USER INTERFACES .GUIS 205 Make a container to put things in Make a box for layout management Make an text editing window & add to box Dialog pop up returns Make a button. if result Fix up layout a bit is OK button which looks like this: Now let’s add some file I/O: .14. dies Kills program.

. append the Menu object under the label “File” and stick it on the top of the frame Bind actions to each menu item ( g OnOpen to ID_OPEN) (e. You can open a file for editing (but saving it costs extra. opens it and reads it into the text editor (named control) which creates a text box and a file menu.) You can edit this.206 CHAPTER 6. p Gets the file name. append two options with a separator Make a menuBar object. LISA’S PYTHON NOTES Define some ID numbers for future use Make a Menu object. but you can’t save it.g.

q to quit: ") if ans==’q’: break pylab. But here are a few examples for fun. GRAPHICAL USER INTERFACES .4)) while 1: Nums=[] try: # executes unless error! mu=float(raw_input(’Enter mean: ’)) sig=float(raw_input(’Enter sigma: ’)) for i in range(N): Option 1) Program queries with raw input(): #!/usr/bin/env python import matplotlib matplotlib.GUIS 207 6. read in the mean and standard deviation using raw input() queries (annoying!) 2.clf() # clears figure so we can plot a new one . read them in as command line switches 4.sys import exceptions # new module that allows error trapping! from numpy import random """random_2_i""" N.6.hist(Nums. some of which use GUIs: 1. The mean and standard deviation were hardwired into the code.draw() ans=raw_input("Press return to continue. read them in from a file using a redirect < 3.2 pylab. 5. There are a bunch of ways we could make this program more customizable.sigma=500. read them in from Entry boxes using a GUI.sigma)) pylab.1 Interacting with plots In the section on statistics. construct a command and running the program automatically through the command line as in the above ideas.title(’Normal distribution’) pylab.figure(1.10.14.facecolor=’orange’) pylab. and call a method from within the GUI You should already know how to do the first three options from what you have already learned.use("TkAgg") import pylab.bins=20.14.append(random.ion() fig=pylab. I demonstrated a program to calculate gaussian data and plot them as a histogram.normal(mu. read them in from Entry boxes using a GUI.

LISA’S PYTHON NOTES except TypeError: # executes if there is a TypeError print ’Invalid entries. the error trap syntax: try: execute some code if no error happens except: do this if you get an error . try again’ print ’Quitting’ which produces this: The program will keep updating the figure until you type ‘q’. will give you a warning and then go back up to the top of the while loop.208 CHAPTER 6.note you can specify the error type. when you enter an invalid number. There are two new things in this code snippet. which could come in handy: 1) the pylab. which clears the figure and allows us to plot a new one and 2) error trapping with the module exceptions. In this example. Option 2) Read from standard input #!/usr/bin/env python .clf() command.

mu.hist(Nums.sigma)) pylab.argv[sys.argv: sig=float(sys.draw() raw_input("Any key to quit") This uses the already familiar use of command line switches and can be run with a command like: % random_2_switch. GRAPHICAL USER INTERFACES .Nums=500.facecolor=’orange’) pylab.normal(mu.float(params[1]) for i in range(N): Nums.index(’-sig’)+1]) Nums=[] for i in range(N): Nums.argv.bins=20.facecolor=’orange’) pylab.stdin.sys from numpy import random """random\_2\_file.argv.index(’-mu’)+1]) if ’-sig’ in sys.bins=20.4)) pylab.dat contains the desired parameters.2 -mu 10 -sig 2 .py""" fig=pylab.readline() N.normal(mu.title(’Normal distribution’) line=sys.append(random.use("TkAgg") import pylab.argv: mu=float(""" N.title(’Normal distribution’) pylab.use("TkAgg") import pylab.hist(Nums.sigma=500.sigma=float(params[0]).[] params=line.6.sys from numpy import random """random\_2\_switch.append( < random_file.14.sigma)) pylab.figsize=(5.split() mu.dat 209 The file random file.ion() if ’-mu’ in We can execute this program with a command like: % random_2_file.argv[sys. Option 3) Command line switch #!/usr/bin/env python import matplotlib matplotlib.GUIS import matplotlib matplotlib.figure(1.10.

Frame): def __init__(self.ID_STD."".Size(300.DLG_PNT(panel. parent.std_entry.Show() return True class MyFrame(wx.PlotGauss) def PlotGauss(self.event): commandstring=’random_2_switch.__init__(self.DLG_PNT(panel.\""" ID_MEAN.Center() self.-1." STD".wx.frame.std_entry=wx.std_label=wx.5)) self. LISA’S PYTHON NOTES Option 4) Construct command line and run from within GUI: #!/usr/bin/env python import os.TextCtrl(panel.-1) self.wx """ gauss_GUI_cmd.TextCtrl(panel.5).id.80.self.DLG_SZE(panel.ID_MEAN.40.wx. wx.12)) self.mean_entry.mean_entry=wx.40.20)) self.title.DLG_PNT(panel.-1.EVT_BUTTON.12)) button.45).GetValue() print ’running: ’.15.’Gauss command line’) self.15.Panel(self."".title): wx.StaticText(panel.StaticText(panel.40.system(commandstring) app=App(False) app.102 class App(wx."Plot".wx.ID_STD=101.frame=MyFrame(None.-1.-1.300)) panel=wx.-1).210 CHAPTER 6.commandstring os.DLG_PNT(panel.20).DLG_PNT(panel.wx.12)) button=wx.DLG_SZE(panel.MainLoop() And we get: ." Mean".parent.wx.25.frame.wx.App): def OnInit(self): -mu ’+self.GetValue() +’ -sig ’+self.Frame.

ID_STD. event): HERE WE DO THE PLOTTING def OnQuit(self.Frame. GRAPHICAL USER INTERFACES .\ FigureManager.backends.wx ID_MEAN.event): # quits nicely .wx. -1.NewId().__init__(self. "matplotlib in wxFrame") HERE WE INITIALIZE SOME STUFF LIKE BUTTONS AND AND THE PLOT WINDOW def PlotGauss(self.GUIS 211 Option 5) Embedding plot in GUI This is the most elegant option of all and makes us real GUI experts: Basic Structure: #!/usr/bin/env python import matplotlib.NewId().6.Frame): # initializes plot window def __init__(self): wx.use(’TkAgg’) from matplotlib. NavigationToolbar2Wx # import some matplotlib tools for wxPython import numpy.backend_wx import FigureCanvasWx.ID_PLOT=wx.wx.14.pylab. matplotlib.NewId() # makes wxPython assign ids class PlotFigure(wx. None.

Size(fw.GROW) # puts in the std label box.Add(self.fig = pylab.’) self.fig.canvas = FigureCanvasWx(self.-1.plotbutton.quitbutton=wx.Realize() # attach it to the canvas tw. Let’s take a closer look at the PlotFigure class. LISA’S PYTHON NOTES # a quick start for simple apps.GetSizeTuple() # get the size of the toolbar fw.Add(self.-1.EVT_BUTTON.canvas.Bind(wx.-1.SetValue(’2. I need two boxes for this: one to put all the text entry and plot widgets in and one to assemble everything nicely in.BoxSizer(wx.mean_entry=wx.PySimpleApp() frame = PlotFigure() frame.fig) # make a canvas object.mean_label. wx. I want some text entry boxes for putting in the mean and standard deviation I want a button to trigger a new plot.StaticText(self. So.mean_entry." STD") self. wx.GROW) # puts in the mean text entry box box. fh = self."") # makes a text entry box self. I want a toolbar under my figure.Button(self.OnQuit) # binds button to OnQuit box.Show() app.-1. self.self. Actually.MainLoop() CHAPTER 6. first. wx.Bind(wx.SetValue(’10.PlotGauss(self) # make PlotGauss a method of this class self.toolbar. I want a plot window to stick my matplotlib figure.ID_MEAN. These all need to be laid out in a reasonable fashion. This is where I design the basic GUI.Button(self.std_entry."Plot") # makes a button labeled ’Plot’ self.Destroy() app = wx.Add(self. wx.plotbutton.std_entry.std_label.StaticText(self.GROW) # puts in the plot button Now let’s work on the main box .self. and I want a button to quit the program nicely.plotbutton=wx. attach the figure self.212 self. 0.Add(self.mean_label=wx.’) # initializes the value to 10.figsize=(5.EVT_BUTTON.std_label=wx.toolbar.toolbar = NavigationToolbar2Wx(self.TextCtrl(self.mean_entry.PlotGauss) # binds button to PlotGauss self.4)) # make a figure instance self. 0. th)) # set the width of the toolbar to the canvas . I need to make some boxes to put things in.SetSize(wx.HORIZONTAL) # makes a box to put things in . self.horizontally self."Quit") # makes a button labeled ’Quit’ self.quitbutton.GROW) # puts in the std text entry box box.ID_STD." Mean") # makes a label self.toolbar. -1."") self. th = self.GROW) # puts the ’mean’ label into the box called ‘sizer’: self. wx. 0. 0. 0.add_subplot(111) # put a starter plot in it self.GetSizeTuple() # get the size of the canvas self.figure(num=1.Add(self. To create the entry and plot widgets and putting them in a box I can use the following code: box=wx.canvas) # make a toolbar self.TextCtrl(self.std_entry=wx.

wx from numpy import random """Program gauss_GUI_embed.canvas. -1.clf() # clear the current figure mu=float(self.Frame.use(’TkAgg’) from matplotlib.sigma)) pylab.NewId(). th)) sizer = wx.std_entry.canvas. etc."") self. GRAPHICAL USER INTERFACES . "matplotlib in wxFrame") self. None.GROW) # put in the canvas sizer.’) self. fh = self.toolbar.NewId().\ FigureManager.GROW) # put in the toolbar self.__init__(self.wx.toolbar.std_entry=wx.[] for i in range(N): Nums.ID_MEAN.GROW) box=wx.ID_PLOT=wx.figsize=(5.GUIS 213 sizer = wx.hist(Nums.figure(num=1) # set the current figure to #1 pylab.GROW) # put in the widget box (with text entry boxes.std_entry.Realize() tw.backends.canvas = FigureCanvasWx(self.GROW) # put in the quit button sizer.mean_entry=wx.ID_STD.Add(self.Add(self. NavigationToolbar2Wx import numpy. 0.SetSizer(sizer) # resize things nicely self.LEFT|wx.backend_wx import FigureCanvasWx.4)) self.canvas.HORIZONTAL) self.GetSizeTuple() fw." STD") self.Size(fw. wx.StaticText(self. event): pylab.ID_STD. -1.fig = pylab. 1. things will add vertically sizer. wx.gui_repaint() # refresh the canvas frame with the new plot Putting it all together we have: #!/usr/bin/env python import matplotlib.14.mean_label=wx.Add(self.canvas.draw() # redraw the plot window self. 0.BoxSizer(wx.mean_entry.SetSize(wx.BoxSizer(wx.SetValue(’10. self.TOP|wx. 1. wx.toolbar.Fit() # make things fit in properly And finally the plot function bit: def PlotGauss(self.VERTICAL) sizer.StaticText(self.wx.TOP|wx.Add(self.Add(box.GetValue()) # retrieve mu.append(random.toolbar = NavigationToolbar2Wx(self.BoxSizer(wx. th = self.figure(num=1." Mean") self.canvas) self. sigma from their boxes sigma=float(self.std_label=wx.6.Frame): def __init__(self): wx.-1.’) .py""" ID_MEAN.NewId() class PlotFigure(wx.LEFT|wx. wx.VERTICAL) # make a box called sizer.SetValue(’2.fig) self.quitbutton.pylab.-1.Nums=500.bins=20.mean_entry.GetValue()) # and make them floats N.TextCtrl(self.toolbar.normal(mu.facecolor=’orange’) self."") self.) sizer.GetSizeTuple() self. matplotlib.TextCtrl(self. 0.canvas. wx.

we learned about the pylab module. axes. LISA’S PYTHON NOTES self. .facecolor=’orange’) self. 0.GROW) sizer.Fit() self.canvas.14."Plot") self.quitbutton=wx.Add(box. tickmarks.quitbutton.214 CHAPTER 6.mean_entry. 0..Add(self.hist(Nums.append(random.std_entry.Add(self.GROW) sizer. 0.Bind(wx. wx. wx.Add(self. To take control of the plots (placement of figures.Button(self.Bind(wx.gui_repaint() def OnQuit(self. 0. 0.normal(mu.EVT_BUTTON."Quit") self.mean_label.add_subplot(111) self..plotbutton. we used pylab handle the details for us.EVT_BUTTON.canvas. It also quits nicely when you click on ‘quit’.self.event): self.-1. wx. Behind the scenes.[] for i in range(N): Nums.fig.GROW) self.-1. event): pylab. wx.sigma)) pylab. and Axes) and things that get drawn in them called “primitives” (lines. 0.plotbutton=wx.self.SetSizer(sizer) self.std_label. the Renderer (the thing that does the drawing) and the Artist (controls the Renderer to paint on the FigureCanvas).OnQuit) box.toolbar.plotbutton. 6. wx.GROW) box.GROW) box. pylab is an interface to three layers in matplotlib: the FigureCanvas (the area onto which the figure gets drawn).) you need to know more about Artist containers (Figure. wx.sigma=float(self.Add(self.Add(self. 0.figure(num=1) pylab. wx.MainLoop() This gives a completed GUI that responds to the text entry and replots the histogram when the plot button is clicked.clf() mu.GROW) box.PlotGauss) self.std_entry. fonts.mean_entry.GROW) sizer. Axis. Up to now.2 Event Handling in matplotlib In the section on matplotlib.PlotGauss(self) def PlotGauss(self.Button(self.quitbutton.PySimpleApp() frame = PlotFigure() frame.draw() self. 0.GetValue()) N.Add(self.. wx.GROW) box.GetValue()).Destroy() app = wx.Nums=500.Show() app.float(self.Add(self.bins=20.

s.color=’blue’.pi*t) c=numpy. BTW: This is how the legend commanworks.GUIS 215 rectangles.e. linewidth..6.draw() raw_input() .g.ion() # makes plot interactive fig=pylab. pylab keeps a record of each of these plot instances by adding to a list associated with the Axis instance and retrieved by the method ’lines’ (e.add_subplot(111) # Axes instance t=numpy. tick marks. text) are all*t) ax.sourceforge. Line color #!/usr/bin/env python import matplotlib matplotlib.add_subplot(111) Every time you plot something on fig with.arange(0. I realize that was way more than you wanted to know right now. the plot command.plot(t.. color. text.lines[-1]. When you use a command like add axes or add subplot you create an Axes instance. you can change its attributes (e.lines # prints all your plot instances print ’last line color: ’..draw() print ax.cos(2*numpy.g. So by identifying the line you want in the list. ax. if you remember.c.sin(2*numpy. images).figure() ax=fig. linestyle or marker).01) s=numpy.plot(t. numpy """ Program linecolor.lines is the list of plotting calls on the Axes instance ax).ax.lw=2) #Line2D instance ax.14. GRAPHICAL USER INTERFACES .set_color(’red’) # sets last line to red pylab. you create an object of the Line2D class (yes even points). axes. but we will need some idea of what FigureCanvas does in the following. For a nice tutorial look in the matplotlib documentation: http://matplotlib.lw=2) pylab.color=’magenta’.lines[-1]""" pylab.figure() # makes a figure instance ax=fig.use("TkAgg") import pylab.g.html#artist-tutorial Artist Artist objects (like lines. Remember how we made an Axes instance and called ax? fig=pylab.1.get_color() raw_input("Any key to change last line to red ") ax.

e.g. P wave arrival.\ ydata=%f’%(event. \ . we need the program to recognize key or mouse events and return these to the program.backend_bases import FigureCanvasBase # imports canvas tools pylab.216 Mouse events CHAPTER 6. xdata=%f.draw() def onclick(event): print ’""" import matplotlib.x.plot(data) ax. numpy matplotlib. onclick) using the FigureCanvas method mpl connect. We can use them to identify data points. y=%d. or to flag them as bad.mpl_connect(’button_press_event’.. stratigraphic tie point. \ onclick) Mouse events are the most common type of interaction with plots.: fig. event..’ro’) pylab.button.add_subplot(111) data=numpy. LISA’S PYTHON NOTES Earlier.use("TkAgg") import pylab from matplotlib. say by clicking on an individual box in the tictactoe example and have the program place an ’X’ or an ’O’ there.random. But we couldn’t interact with the plot directly.rand(10) # get 10 random numbers ax.figure() ax=fig.y. In wxPython we had events (EVT BUTTON) which were connected to callback functions (like OnQuit) using the method BIND. or pick them as special (e. say in a digitizer.g. event.canvas.plot(data. start or end point for a calculation) matplotlib supports several mouse events: Event Name Description ’button press event’: mouse button pressed ’button release event’ mouse button is released ’motion notify event’ mouse action mouse scroll wheel is rolled ’scroll event’ ’pick event’ an Artist object is selected Here is an example of a button press event: #!/usr/bin/env python """ Program onclick.g. In matplotlib we have a similar event ’button press event’ which can be connected to a function (e. we learned how to make GUIs using wxPython and even managed to embed a matplotlib figure into a wxPython Frame. To do this. x=%d.ion() fig=pylab.

When you create the object. but didn’t identify any particular plot object.plot(t+.pi*t) Plots some lines that are clickable.canvas. matplotlib.line=line self.s.picker=True) ax.pi.picker=True) lines=[] # makes a list to store clickable line objects . connect the ‘pick event’ to some action 3. """ fig=pylab.plot(t+.canvas. define the action. set the ‘picker’ to True (and usually some floating point tolerance).draw() # redraws line def main(): """ Program clickme.set_color(’red’) # makes red self.numpy class LineColor: """connects the picker to an Artist Line2D object and changes line color""" def __init__(self.figure() ax=fig.use("TkAgg") import pylab. In principle.1.01) s=numpy.line): self. axes) could be picked.25*numpy.ydata) cid=fig.xdata.line.sin(2*numpy.line. text. each object (line.line: return self. you have to do these things too: 1.arange(0.GUIS event.self.picker=True) ax..line.connect=\ self.14.color=’blue’.s.color=’cyan’.on_pick) def on_pick(self.5*numpy.event): # finds right line if event.canvas.figure.set_linewidth(2) # makes fatter self. connects them to the LineColor action. There is a catch however.add_subplot(111) t=numpy.6. GRAPHICAL USER INTERFACES . Consider the following program: #!/usr/bin/env python import matplotlib.pi.s. event.plot(t. 2.figure. rectangle.mpl_connect(\ ’pick_event’.color=’magenta’. we just identified the location of the mouse click.mpl_connect(’button_press_event’.line.artist!=self.\ onclick) # connect the button press to the function onclick raw_input() #pauses the program You could combine this with the editor we wrote before to make a digitizer! 217 In the last example.

[2. I wrote a really silly Tic-Tac-Toe program.myboxes): """ checks to see if boxes selected have won """ # check for diagonals first if ’11’ in myboxes and ’22’ in myboxes and ’33’ in myboxes: \ finish(who.5]) if ’13’ in myboxes and ’22’ in myboxes and ’31’ in myboxes: \ finish(who.yline. Then the objects in ax.5.[. just a clickable matplotlib window: #!/usr/bin/env python import matplotlib matplotlib. [.5]) # check for rows) if ’11’ in myboxes and ’21’ in myboxes and ’31’ in myboxes: \ .sys.5]. it connects the click action to the function on pick which turns the object red and fattens it up a bit.2. [.yline.5. To get you most of the way there. It is not a GUI.plot(xline. LISA’S PYTHON NOTES for line in ax.’g-’) raw_input(’you have lost to a stupid computer!’) pylab. quit) # quit on mouse click print ’click anywhere on plot to quit’ def quit(event): # graceful exit sys.canvas. Each plot instance gets stored in the list ax.exit() def winner(who.yline): """ Check who won""" if len(xline)>0: if who==0: # player wins pylab..xline.append(ln) # stores in the list pylab.218 CHAPTER 6.5. When you click on a line.lines: # steps through list of plot objects ln=LineColor(line) # make the line a LineColor objects lines.2.use("TkAgg") import pylab import numpy. it turns red and fattens up a bit. and it would be fun to make it work inside a GUI.draw() cid = fig. Your final is to do a tic-tac-toe program.5].show() main() The class LineColor is the action that happens when a plot object gets clicked on. The main program draws some lines.lines get turned into clickable LineColor objects. On initialization.2.5.plot(xline.’r-’) print ’you have won!’ else: # computer wins pylab.lines.mpl_connect(’button_press_event’.exceptions from numpy import random def finish(who.

5.Os) # check if winner.5.5]) # check for columns) if ’11’ in myboxes and ’12’ in myboxes finish(who. [2.append(boxes[ind]) winner([ind][1])-.5].2 xtext.2.5.1 else: # box 3.ydata # assign mouse click to x and y if y<1: # first row if x< 1: # box 1.[.’ \n’ Xs.ytext= 3.y """ what to do for mouse clicks""" x.5.1 xtext. 1 is computer box .1 elif x<2: # box else: # box 3.[.[2.color=’red’) # put a red x in print ’\n your move: box id ’.5.ytext= 1.2.6.Xs) # check if winner.1.index(box)] # delete box from boxes winner(0.[. 0 is player ## pick a box at random for the computer’s move! ind = random.’o’.2 elif x<2: # box 2.2.5. [.2.5].5]) if ’13’ in myboxes and ’23’ in myboxes finish(who.[.text(int(boxes[ind][0])-.\ fontsize=24.ytext= 1.2 xtext.5.3 xtext.3 xtext.2.5. return x. GRAPHICAL USER INTERFACES .3 ## check if legal move (if already taken!) box=str(xtext)+str(ytext) # make the box name if box not in Xs and box not in Os: # box not yet taken pylab.y=event.ytext= 2.1 xtext.2 xtext.1.xdata.3 xtext.text(xtext-. [.ytext= 3.’x’.5]) if ’12’ in myboxes and ’22’ in myboxes finish(who.5.GUIS finish(who.5].5]) if ’21’ in myboxes and ’22’ in myboxes finish(who.append(box) del boxes[boxes..2.5.ytext= 1.5].ytext= 2.5]) and ’32’ in myboxes: \ and ’33’ in myboxes: \ and ’13’ in myboxes: \ and ’23’ in myboxes: \ and ’33’ in myboxes: \ 219 def onclick(event): # if someone clicks in a square.color=’green’) # put green ’o’ in box Os.ytext-.5..fontsize=24.5]) if ’31’ in myboxes and ’32’ in myboxes finish(who.randint(0.[1.ytext= 2.3 elif x<2: # box 2.5.ytext= 3.5]. elif y<2: # second row if x< 1: # box 1.event.5].14. box.1 xtext. [. [.3 else: # box 3. [1.len(boxes)-1) # pick a box at random pylab.2 else: # third row if x< 1: # box 1.

0].1.Os.[0.0].1.text([0.’32’.3] # draw the canvas cid = fig.’11’) # labels boxes with their ids program""" global fig.2].text(0.[0.boxes # makes these have global scope pylab.1.1.’k-’) ax.2.’23’) ax. Tie these in to the Tic-Tac-Toe program (in the onlick() function) so you can play a more challenging game! Now put the whole thing inside a GUI.canvas.’23’.1.1].1.ion() boxes=[’11’.’13’) ax.[2.’21’) ax.0.figure() # create figure instance ax = fig.text(2.2].0.text(0.3].’k-’) ax.[1.3].Xs.’21’.’k-’) # make black lines ax.mpl_connect(’button_press_event’. For this (final) assignment.[’33’) pylab. choose another one\n’ ### now figure out computers move! c def main(): """ tictactoe2. 6.text(1.’ is taken!.1].’12’) ax.1.add_subplot(111) # make a subplot ax.1.’33’] # some box labels Xs=[] # list of all x moves Os=[] # list of all o moves fig = pylab.1.’22’) ax. write a program that calls on your F90 functions to calculate the computer’s moves instead randomly choosing an empty box.the contour intervals are elevations and our brains can reconstruct the 3D world by looking at the contours on the map.’13’.1.1. Think about a topographic map .plot([2.1.plot([1.1.’22’.220 CHAPTER 6.3]. LISA’S PYTHON NOTES del boxes[ind] # delete box from boxes ## check if computer won # else: # box already taken print " \n box ".’k-’) # draws a box ax.’32’) ax.’31’.text(2.text(0.1.plot([0. \ onclick) # tell what do do for mouse clicks‘ raw_input() # make program wait for response main() # run main program ASSIGNMENT P9: You have been writing Fortran code to play tic-tac-toe.plot([0.text(1.’31’) ax.’k-’) ax. .0.2.15 3D plotting with Python Contour plots are really just a way to visualize something that is inherently 3D on a 2D surface.’12’.

Y.arange(-2. see: http://matplotlib.y) h=numpy.1) y=numpy.1) X. 3D PLOTTING WITH PYTHON 221 But with computers we can visualize the 3D world in a more realistic manner.mplot3d import axes3d G=6. check out this website: http://github.*numpy.set_xlabel(’X’) ax. which is part of the enthought.set_ylabel(’Y’) ax.*(h**2+z**2)) fig=pylab. # radius in meters z=3. There are lots of 3D plotting packages. but if you are curious.*z.plot_surface(X.2.15.67e-11 # grav constant in Nm^2/kg^2 (SI) R=2. # depth of burial drho=500 # density contrast in kg/m^3 x=numpy.arange(-2.*z.use("TkAgg") import pylab.html But for more 3D horsepower.mayavi module. which comes with the Enthought Python Edition.*z.*drho)/(3.Y=pylab. See: http://github. This was way beyond what I**2+Y**2) g= (G*4.enthought.Axes3D(fig) ax. one using a 3D toolkit of matplotlib that uses the same logic as for ‘regular’ matplotlib.sourceforge.6.figure() ax=axes3d.html And then there is Mayavi itself.meshgrid(x.pi*R**3. and even within Python there are several different approaches.enthought. there is a module called mlab.g) ax.set_zlabel(’Z’) pylab. For more on this .*z.html Let’s start with a 3D version of the gravity anomaly of a buried sphere: #!/usr/bin/env python import matplotlib matplotlib.numpy from toolkits/mplot3d/index.0.

4 0. you can twirl the plot around to see it from various perspectives.1. fig.222 CHAPTER 6.2 4 Z −6 −4 −2 X 0 2 4 −6 −4 −2 0 2 Y In this example.1.1] mlab.mayavi import mlab def g(X. one of which is plot surface.figure(bgcolor=( s=mlab.*(h**2+z**2)) z=3.Y): G=6. To give you a flavor of what mlab can do. LISA’S PYTHON NOTES 1. which plots a wireframe surface on the meshgrid X.67e-11 # grav constant in Nm^2/kg^2 (SI) R=2.savefig() as before.6 0.g) mlab. Other methods are set xlabel() and so on.Y=numpy.-2. we import the axes3d module from the mplot3d toolkit of matplotlib. here is essentially the same code. We create an Axes3D instance called ax from the figure . You can save any of these with the little disk icon or with pylab. but using functions from mayavi.mlab: #!/usr/bin/env python import numpy from enthought.Y of the data in g. # depth of burial X. # radius in meters drho=500 # density contrast in kg/m^3 h=numpy. Note that when you try this example on your own computer.sqrt(X**2+Y**2) return 1e8*(G*4. Axes3D objects have lots of methods.*numpy.*z:2.2 1.*z:2.0 0.*drho)/(3.mgrid[-2.*z:0.pi*R**3.8 0.*z:0.

In mlab. and so on.1) is (1. I’ve picked out a few: . color gets set with the familiar r.0. Then the surface gets drawn with a call to mlab. so a color of (1.g.b but here the colors run from 0 (black) to 1 (full strength).1. There are lots more 3D plotting functions available in the two packages described here. To whet your appetite.6. The default is for a black background.figure creates a figure instance instance with the background color (bgcolor) set to white. 3D PLOTTING WITH PYTHON 223 The call to mlab.15.0) is red.

. anomalies.enthought.html . contour plots mesh() spherical harmonics flow() flow fields barchart() no idea. LISA’S PYTHON NOTES plot() scatter3d() plot_wireframe() PolyCollection() contour() bar3d() plot_surface() Examples from mplot3d. triangular_mesh() quiver3d() currents.224 CHAPTER 6. winds magnetic moments tessellation grids isopicnals or isothermals contour3d() Examples from the Mlab gallery plot3d() Magnetic field lines? imshow() points3d() pts in space color contour plots surf() contour_surf() topography.sourceforge..Axes3D examples http://matplotlib..

edu/class233/force.15. The program force. Lines of flux Professor R. 3D PLOTTING WITH PYTHON 225 Here are some considerations for you to help you decide which way you want to go: mplot3d versus mlab mplot3d (matplotlib) mlab (mayavi) Pros: Pros: mplot3d is a natural extension of pylab Prettier it is easier to learn Interactivity pylab functions work for mplot3d too More functions Can be animated :) Cons Cons Limited plotting styles no svg output ps and eps are buggy slower harder to learn for pylab masters 6.6.f has disappeared from Professor Parker’s website in the mean time but is available on the class website at: You run it with a session like this: it creates a file draws the magnetic lines of flux from the core outward and saves the data to a file like this: % force ================= .ucsd.f’. This was a slight modification of his ‘magmap’ program that calculates magnetic field vectors given a geomagnetic reference model (see Bob’s software website http://igppweb. In this section I will very briefly point out a few ways beyond the obvious X.15.ucsd.Y plots and maps that you have already encountered. Parker (our hero and professor emeritus of the SIO department) wrote a Fortran (f77) program called ‘∼parker/Software/).L.1 Geoscience applications There wouldn’t be much point in learning how to program in a geoscience class if there were no practical applications.

016 0.200 Evaluation r/a 0.071 0.54700 New field-line file opened in: lines.302 -0.316 -0.f05 =================== Field evaluated for IGRF 2005 Equatorial radius (km) 6378.123 0.699 0.950 0.945 0.066 -0.987 -0.910 Reference radius (km) 6371.686 -0.040 -0.998 0.385 -0.532 0.226 0.784 0. 0.272 0.382 etc.487 -0.642 0.632 0.547 output lines.139 0.831 -0.547 Maximum degree of accepted coefficients: 13 Coefficients normalized to radius: 0.547 output lines.132 0.054 -0.684 quit Magmap run complete .674 -0.164 0.160 0.226 CHAPTER 6.479 -0.516 0.049 0.170 Polar radius (km) 6356.842 0.856 -0.047 -0.083 0.790 0.f05 ================= Enter commands for spherical harmonic coefficients (? for help) 0.f05 exec =================== igrf 2005 lines 200 radius 0.767 -0.f05 Initial and terminal points 0.217 -0.266 -0.516 0.662 0.998 -0.995 0.955 0.306 Field line coordinates written to lines. LISA’S PYTHON NOTES Enter commands for spherical harmonic coefficients (? for help) igrf 2005 lines 200 radius 0.105 0.

049 0.00000 0.047 0.000 50.995 0.000”s Some of the field lines go WAY out in space (100 CMB radii). 3D PLOTTING WITH PYTHON 227 The red commands are typed by the user and then blue stuff is the program response.009 50.00000 1. we get: The thought occurs. This will create an output file lines.071 -0.005 1.070 -1.066 -0.00000 The first three columns are x.000 1. we’ll come back to this later.f05 which looks something like this: 0. Parker also provided a script (look) which chops off the parts of the lines that are more than 4 radii away.6.000 1. It also invokes Parker’s most famous program plotxy (which IS available on his website).15.054 -0. . When run with the command look 45 75 ¡ lines. y. wouldn’t this look cool in 3D? Here is a little script inspired by the plot3d() example from the Mlab gallery.054 -0. Each field line is separated from the rest by an entry with the number of points in the previous line and 3 “50.998 -0. z on a magnetic flux line and the fourth is R in units of core mantle boundary radii. Plotxy produces a postscript file mypost.040 0.998 2 50.f05. projects the 3D lines onto a plane specified by the user and saves the data in a new file.

array(lx).1)) # sets the background to white while line<len(Xs): if Rs[line]<5: # truncates far away field lines lx.plot3d( mlab.array(lr) mlab.y.array(ly)[line])[].r.array(lz).1.[].f05’).lines[3:-1:4] line=0 lx.append(Ys[line]) lz.lz.lz.plot3d(x.y.Zs.[] if Ys[line]==50.append(Rs[line]) elif Rs[line]>=5 and Ys[line]! which produces something like this (but in 3D you can wiggle it around .fromstring(open(’lines. LISA’S PYTHON NOTES #!/usr/bin/env python import numpy as np from enthought.array(lx).z.z.array(ly).append(Zs[line]) lr.r.colormap=’Spectral’)[].Rs=lines[0:-4:4][2:-2:4]. and line<len(Rs): x.[][].228 CHAPTER[].much more fun!): .: # detects the 50’s while Rs[line]>5 and Rs[line]!=50: line+=1 x.z.[].[] line+=1 mlab.array(lz).sep=’ ’) Xs.r=np.mayavi import mlab[].[].[] mlab.colormap=’Spectral’) lx.lz.lines[1:-3:4].read()

[pv[1].sum(X*X).0)) mlab.0)) mlab.sum(X*Y) . Or the preferred orientation of mineral grains or clasts in a sedimentary deposit. or point masses in space.Z. 3D PLOTTING WITH PYTHON Eigenvectors 229 Linear algebra has a lot of applications in the geosciences.append(float(rec[2])) X.transpose()[2].but they are in three dimensions.25.numpy.evects.[].readlines() x.evects=linalg.sum(Z*Z)]])’.7.outline(color=(.1.array([[numpy.strip(’\n’).evals[0] print ’major axis: ’. Or the orientations of a stress or strain tensors. And the list goes on.1.0).0.scale_factor=0.evects.transpose()[0]*3. ’ with variance of ’.evals[1] print ’minor axis: ’.sum(X*Z)].numpy.6.Y.Z=numpy.\ [pv[2].plot3d([pv[0]. Or you want a best fit plane.-pv[0]].append(float(rec[1])) z.-pv[1]].append(float(rec[0])) y.y. Or you want to know the principal axis of the moment of inertia tensor. These could be the end points of unit vectors (directions).tube_radius=0.1)) mlab. mlab.array(y).split() x.numpy.Y.numpy.5) mlab.sum(Y*Y).points3d(X.[] for line in dat: rec=line.numpy.eig(T) print ’principal axis: ’. Say you have a bunch of points and want to calculate a best-fit line through them .numpy.array(x). #!/usr/bin/env python import numpy from numpy import linalg from enthought. Or the directions of the anisotropy of just about anything.\ [numpy.’rU’).evals[2] pv=evects.opacity=.sum(Z*X).array(z) T=numpy.transpose()[0].z=[].color=(0. for example. say the fault surface through a bunch of earthquakes.sum(Y*X).mayavi import mlab dat=open(’points.0. One of the most useful tricks is to calculate what are called “eigenparameters”. Here is an example that finds the eigenvectors and eigenvalues of what is called the covariance matrix of a bunch of 3D points.-pv[2]]. ’ with variance of ’.figure(bgcolor=(1.\ [numpy.numpy.color=(0.evects. ’ with variance of ’.15.transpose()[1].sum(Y*Z)].numpy.sum(Z*Y).

7349e-02 1.5916e+00 1. The largest (principal) eigenvalue corresponds to the principal eigenvector and is the axis along which the variance (spread) is the greatest.1998e+00 7.9620e-02 2. so are the first column of the evects array: evects= [[ 0.9863e-01 5.1122e-01 2.70464008 -0.3741e-01 2.02362748] .4537e+00 etc.6767e-01 1.6928e+00 9. 5.230 CHAPTER 6. Then the sums of the products and squares get put into a coherence matrix of the form:   x2 xy xz xy y2 yz xz yz  .70917141 0.2025e+00 4. z2  The function linalg.9248e-01 9.0015e+00 -2. These get turned into which looks like this: 1.4844e+00 1.1087e+00 It then parses the data into lists of floating point variables.6763e-01 -1.7284e-02 1.eigs() returns the eigenvectors and eigenvalues of this “T” matrix.7332e-01 6.8151e+00 1.7893e-01 1.1443e-02 7. One “feature” of this function is that the coordinates of the eigenvectors are along axis 0. The minor eigenvector corresponds to the axis along which the variance is least. LISA’S PYTHON NOTES This script opens a file called points.

99947976] 0.99947976 -0.70917141 0. Nice. The principal eigenvector gets assigned to the array pv.02195351]] 231 That is why to print out the vectors: % points.03223454 0. 3D PLOTTING WITH PYTHON [-0. mlab.02195351] with variance of 8.70956409 principal axis: [ 0.7.501077006 minor axis: [ 0.outline(color=(.plot3d plots the principal eigenvector as a green tube.55431560739 I take the transpose.0)) puts a red box around the figure and mlab.03223454 0.70464008 -0. he function points3d plots the points a nice shade of grey (opacity low).172618519 major axis: [-0.001072] with variance of 733.02362748 0.001072 [ 0.70429883] with variance of 30.70429883 -0. .


These are text files that end in .Chapter 7 Peter’s Python Notes These notes will reflect my attempt to learn Python from Lisa’s lecture test message % 233 .py) print ’test message’ Provided one has execute permission on this file (chmod 755 printmess. However. so we will start immediately with Python scripts. it quickly becomes tiresome to enter everything manually. This assumes that Enthought Python is However. My strategy will be to write a series of programs that mimic the programs in my Fortran90 notes. Python is similar to Matlab in this way.framework/Versions/Current/bin/python It is possible to run Python from the command line (like Matlab). My first program is called printmess./printmess. in which case it functions like a fancy calculator. enter: % which python which should return: /Library/Frameworks/ #! /usr/bin/env python # simple Python test program (printmess. both Python and Matlab are much slower to run than compiled languages like Fortran and C. However. this can be run by entering: % .py and can be thought of as Python source code. To verify this. which execute a series of Python commands. unlike F90 source code they do not need to be compiled before they are run.

/printmess2. PETER’S PYTHON NOTES Notice that we need to start with .py) don’t work ’cuz the vandals took the handles" "I know what it\’s like to be dead"’ 7.e. You can get an apostrophe in your output by using double quotes and quote marks by using single quotes. The first line MUST be: #! /usr/bin/env python so that the file is interpreted as Python.. You can use single or double quotes for the test message. Notice that print goes by default to your screen. python test program 2 ( #! /usr/bin/env python a = 2 b = 3 c = a*b print ’product = ’. is not in our path (for security reasons). The second line is a comment line. you CANNOT start with a comment line (try switching lines 1 and 2 and see what happens). i. c . Anything to the right of # is assumed to be a comment (in Fortran ! serves the same function). Unlike Fortran or C. the backslash in front of the apostrophe is necessary to prevent an error (try it).py The pump don’t work ’cuz the vandals took the handles She said "I know what it’s like to be dead" % In the second print statement.1 How to multiply two integers Here is a simple Python program to multiply 2 and 3 (multint./ because . ASSIGNMENT P1 Write a Python script to print your favorite pithy phrase.234 CHAPTER 7. #! /usr/bin/env # simple Python print "The pump print ’She said produces: % .".abge print ’adif = ’. i. numbers. unlike C or Fortran their type is not explicitly defined. complex. Instead it is determined by the syntax upon first use. underscores ( ). Unlike Fortran. b and c. 7. and % (remainder). x = 2 defines x as integer x = 2.9 adif = aend . HOW TO MULTIPLY TWO INTEGERS 235 The program uses three variables./undeclared. string. When you run the program.e. defines x as real x = ’2’ defines x as a string Basic Python has a very limited number of math operations. To get more advanced math operations. use the numpy module (see below).1. which include +. Yet many languages will do exactly that. You don’t want the program to run by assigning some arbitrary value to abge and giving you a wrong answer. the letters a.1 aend = 3.. However. including real (floating point). The remaining characters can be any combination of letters. ** (to power of).abge NameError: name ’abge’ is not defined This is a desirable feature of Python. / (divide). in <module> adif = aend . line 4. Variables in Python can be of many types.1 Declaring variables Consider the following program with a typo in line 4: #! /usr/bin/env python abeg = 2. -. adif You had intended to type ’abeg’ but typed ’abge’ instead. Variable names should always start with a letter. . and dashes (-). integer.1. and logical. * (multiply). including Fortran (we can avoid this potential problem in Fortran by using the ’implicit none’ statement at the beginning of our programs). you get an error message: Traceback (most recent call last): File ". variables are CASE SENSITIVE (x is different from X).

This option is rarely a good idea because it makes the code harder to read.sin(numpy./testnumpy. see gcc example below)). we need to import the numpy module and then then import the individual commands.pi/6.sin( code (multint2. #! /usr/bin/env python a = 2.pi print ’sin(pi/6) = ’. Here is another way to write the multint. I suggest that you never use semicolons in this way.) produces: % . np. print ’product = ’.5 Notice that. /.pi/6. This makes the code more like C. a*b Notice that more than one command can be included on a line if the commands are separated by a semicolon (also OK in F90). numpy. and % (modulus operator. 7. For example (testnumpy.. i.14159265359 sin(pi/6) = 0. -. PETER’S PYTHON NOTES #! /usr/bin/env python import numpy print ’pi = ’. by importing everything: from numpy import * . trig and other highorder math functions. b = 3. We can save typing by importing numpy as a name that we assign.1. For sqrt. ** (power). #! /usr/bin/env python import numpy as np #or anything else print ’pi = ’. Unless you have a really good reason to put more than one command on a line (saving space is NOT a good reason!).pi print ’sin(pi/6) = ’.py pi = 3. lots of times.2 Numpy Standard Python only includes basic arithmetic operators (+. like almost all languages. np. *.2 Alternate coding options There are always lots of ways to write the same program.236 CHAPTER 7.e.) You can avoid having to type even the np. It can be annoying to have to type numpy. the trig arguments are in radians.

.3. 1): This begins the “for” loop and contains a lot of interesting syntax. Here is an example program that generates a table of trig functions: #! /usr/bin/env python import numpy as np degrad = 180. You code will be clearer and less error prone if you include the prefix to show which functions and variables are coming from numpy.tan(theta/degrad) print ’%5./3.g. ttheta) Notice the use of the variable degrad to convert from degrees to radians. stheta. but the indentation is optional. Here the indentation is how Python knows what is inside the loop and where the loop ends. the lines that follow that are inside of the for loop MUST be indented.sin(theta/degrad) ttheta = np. 90. this is NOT recommended because one can lose track of where things come from.cos(theta/degrad) stheta = np. In C. so two lines may appear to have the same indentation but actually be different.4f %8. Next comes for theta in range(0.3 Making a trig table using a ‘for’ statement Any advanced programming language must provide a way to loop over a series of values for a variable. 90.7. C or Fortran). Thus.4f’ %(theta. In FORTRAN this is done with the “do” loop. . because Python has NO STATEMENT TO END THE LOOP (e. For clarity. sqrt 237 in which case one can use pi and sqrt with no prefixes. this is most naturally implemented with the “for” statement. ctheta. 1): ctheta = np. However. MAKING A TRIG TABLE USING A ‘FOR’ STATEMENT or just a few functions: from numpy import pi. Unlike most languages (e. 7. enddo in Fortran).g.4f %8.1415927 for theta in range(0. The key point is that the 4 lines following the for statement.1f %8.. it is safest to NEVER USE TABS so that one can always can see exactly what the true indentation is. Python uses its own version of the for loop. must ALL BE INDENTED EXACTLY THE SAME. Tabs and blanks are treated differently in Python. most people indent loops in other languages. Statements that expect a subsequent indentation level end in a colon (:).

e.238 CHAPTER 7. ctheta.cos(theta/degrad) This uses the numpy cosine function. This is consistent with F90. Better style is to write ctheta = np. write: . Instead.cos(float(theta)/degrad) where ‘float’ converts from integer to real (‘int’ converts from real to integer). which does not allow real do loops. stheta. step 1. 90) would give the same numbers. theta will assume a series of specified values. we explicitly specify the output format using a format specification: print ’%5.1). You’re right to think this makes no sense but it is typical of Python syntax. Range is an integer function that in this case will assume the values from 0 to 89 (!). Loops with real increments are not considered good programming practice because of the precision problems that repeated sums can cause. range(0. 1). ttheta) Here the output format is given in the single quotes. i.sin(rtheta_deg) etc.. stheta.4f’ %(theta. ctheta. Note that because range is an integer function. 90. thus to put commas between the output numbers. or for maximum efficiency we could write rtheta_deg = float(theta)/degrad ctheta = np. we do not use print theta. but fortunately Python figures out that int/real should be real (see more discussion of this later). Next comes ctheta = np.1f %8.4f %8. you cannot enter real values as limits to define theta as real in the for loop. although they were OK in older versions of Fortran. PETER’S PYTHON NOTES Within the for loop. ttheta which would space the numbers irregularly among the columns. The 1 for step is optional because 1 is the default step size. The format for each number follows the space to the right of the decimal point (in Fortran this is f5. Ideally theta should be a real variable in this expression. the upper limit is always one more than the last value used.4f %8. in this case given by range(0.cos(rtheta_deg) stheta = np. Why 89? Because it is the last number less than 90. To make the output look nice. The single blank space between text there is reproduced exactly in the output.

This example highlights a (minor) disadvantage of Python.. %8. functions have different names than Fortran and C (which use asin.4f. we cannot add spaces in the top line so that the formats and their variables line up perfectly. cosine and tangent function in the trigtable program.4f’ \ %(theta. because this is all considered to be one line by the Python interpreter. etc.1f.3.) 7. stheta. ctheta. MAKING A TRIG TABLE USING A ‘FOR’ STATEMENT 239 print ’%5.4f %8.3. Here are more numpy math functions: absolute(x) arccos(x) arcsin(x) arctan(x) arctan2(y. ttheta) Another way to write the print line is: print ’%5.2 Possible integer/real problems As an aside. Because it cares about the spaces between the different formats. stheta. ctheta.7. 7.1 Numpy mathematical functions We used the numpy sine.1f %8. %8.4f.x) cos(x) cosh(x) exp(x) log(x) log10(x) sin(x) sinh(x) sqrt(x) tan(x) tanh(x) absolute value arccosine arcsine arctangent arctangent of y/x in correct quadrant (***very useful!) cosine hyperbolic cosine exponential natural logarithm base 10 log sine hyperbolic sine square root tangent hyperbolic tangent Note that the arcsin.3. etc. Notice that in this case the 2nd line does not have to be indented to match the other lines. acos. note that the trigtable program uses: .4f’ %(theta. but it certainly makes the code easier to understand. Aligning things this neatly is probably more trouble than it’s worth. %8. ttheta) Here we have used the continuation character to split the statement into two lines.4f %8.

1000]: for name in ["Sue". for theta in range(0./3 = ’.sin(phi/degrad) + (2/3) * np./3. = 0. However./3 = 0. "Dave". 2. 90./3. 2. the program will compute a real quotient. "Dave". 2/3 print ’2./3.240 degrad = 180. = ’.cos(theta/degrad)**2 which will definitely produce the wrong answer! 7. this caution is not needed in this case. "Mary"]: names = ("Sue". It is only when both numbers are written as integers that the result is truncated. I have gotten into the habit of always including the decimal point in real expressions to avoid someday accidentally writing something like: a = np.666666666667 As long as one part of the fraction is real./3 print ’2/3. 100. 10. PETER’S PYTHON NOTES The reason is to make completely sure that the program will compute a real quotient and not an integer quotient. 2/3. 1): mimics the do loop syntax in Fortran. Here are some examples: for x in [1. In fact.1415927 CHAPTER 7.1415927 rather than simply degrad = 180/3. print ’2. However. = 0. as the following program demonstrates: #! /usr/bin/env python print ’2/3 = ’. = ’. the Python for loop is a much more versatile operator than the Fortran do loop.666666666667 2/3.666666666667 2. "Mary") for name in names: # x will assume these 4 values in the loop # name will assume these 3 names # example of tuple (see below) # name will assume these 3 names . Running the program yields: 2/3 = 0 2./3.4 More about Python for loops The for loop in the trigtable program.

INPUT USING KEYBOARD 241 7. Here are some common examples: %8i %10. but are included in the ‘math’ module.0 to 6.g. NOTE: sinh and cosh are not included in numpy.0 at increments of 0.4g %7s 8 characters 10 character 10 characters use either f 7 characters for integer. 4 to right of decimal in scientific notation. so we convert it to a real number using the float function. The prompt “Enter number here: ” will print on the screen and the user types the number to the right of this and hits return. \%-8i) include + sign ( .5 Input using keyboard So far all of our example programs have run without prompting the user for any information. we will want to first prompt the user to input the data.g. and cosh(x) (the hyperbolic sine and cosine) for values of x ranging in radians from 0. let’s learn how to input data from the keyboard.7...1 More about formats There are many different formats that can specified.4. So you will need to include the line ‘import math’ and then write math.4f %10.g.5..sinh. In most programs. To expand our abilities. 3 to right of decimal or e as appropriate of string output Flags can go immediately after the % to customize these: + 0 left justify (e. right justified field width. \%+8i) zero fill on left (e. The input is ALWAYS a string variable. \%09i) ASSIGNMENT P2 Write a Python program to print a table of x. to get the functions. so here is an example of how to input a number: a = float(raw_input("Enter number here: ")) “raw input” is preferred over “input” for reasons I don’t fully understand that have to do with hacking issues. etc. 7. sinh(x). Use a suitable format to make nicely aligned columns of numbers. We can write a program to multiply two numbers as follows (usermult.3e %10.

This is done using the split operator by appending . it will crash because if will try to convert something like ’2.242 CHAPTER 7. This program will work correctly as long as a blank is used to separate the numbers being input. We now have the two strings ”5” and ”23” and we use a ‘for loop’ to assign x to each in turn and convert to the real variables a and b using the float function. b = 1.6 If statements Next. you will have a hard time convincing me that this syntax is easier to learn than: print *.e. b which is how you input two numbers in Fortran. PETER’S PYTHON NOTES #! /usr/bin/env python a = float(raw_input("Enter first number: ")) b = float(raw_input("Enter second number: ")) c = a*b print ’Product = ’. If the user enters a comma following the first number. c The logic is as follows: The raw input will be a string. in Python you can write a.split() to the string. the Fortran version will accept a comma between the numbers without giving an error. a. This is surprisingly complicated to do in Python (at least as far as I could tell. That is.split’ operator looks for blanks. "Enter two numbers" read *.py): .. more experienced users can correct me). 2 to assign two numbers in one line. not commas. c This is a little clunky because ideally we might want to input the numbers on the same line. Here is one way to do this (usermult2. b = [float(x) for x in raw_input("Enter two numbers: "). i. 7. the ’.split()] c = a*b print ’Product = ’. As a long-time Fortran programmer. In addition. let’s modify this program so that it will allow the user to continue entering numbers until he/she wants to stop (usermult3.’ to a #! /usr/bin/env python a. such as ”5 23” which we then need to split into two parts. Note that a and b can be assigned together.

The end of the if block is shown simply by the end of the indentation. The program will allow the user to continuing entering numbers to be multiplied. . The ”if” statement checks for this and exits the loop in this case: if (a==0 and b==0): break The break statement (exit in Fortran) breaks out of the while loop. b = [float(x) for x in raw_input \ ("Enter two numbers (zeros to stop): "). When the user wishes to stop the program (in a more elegant way than hitting [CNTRL] C!). unless we explicitly break out of it. ( #! /usr/bin/env python while (1 < 2): a. e. the loop will continue forever. but we could also execute a block of code. c Notice that this block must be indented relative to the if statement line.7. and that there is no ‘end if’ line (just like there is no ‘end do’ line for the while loop). x = x + 1 in which case x will assume the values from 1 to 10 (easy to also do with a for loop). we just execute a single command.split()] if (a==0 and b==0): print ’You entered two zeros’ print ’so the program will now end’ break c = a*b print ’Product = ’.split()] if (a==0 and b==0): break c = a*b print ’Product = ’. In this case. c 243 In this case we use a while loop. which continues until the following statement is no longer true.... . b = [float(x) for x in raw_input \ ("Enter two numbers: ").g. But of course we could include a variable in the expression as in: x = 1 while (x < 11): . Since 1 is always less than 2.. he/she enters zeros for both arguments. IF STATEMENTS #! /usr/bin/env python while (1 < 2): a.

gt. i. .. These operators can be combined to make complex tests. PETER’S PYTHON NOTES will work the same.or. .. . b = True while (b) or even the bizarre b = 1 < 2 while (b) A list of relational operators (e. 77 C == != < <= > >= && || MATLAB == ~= < <= > >= & | PYTHON == != < <= > >= and or meaning equals does not equal less than less than or equal to greater than greater than or equal to . But I think it looks nicer with them. . It’s probably better to write while (True): which uses the boolean expression ‘True’ (similarly ‘False’ is also permitted) . if ( (a > b and c <= 0) or d == 0): .eq. Getting the while loop to go forever by using ‘1 < 2’ is a bit of a kludge.g. . e. . i.. and you will get less confused when you switch between computer languages if you always leave them in. used in while and if statements) in different languages is as follows: FORTRAN 90 == /= < <= > >= .ge. .le.244 The parentheses in while (1 < 2): are optional.g..e.and.and. Note that we could use a variable for this purpose.e. while 1 < 2: CHAPTER

one block of code will be executed (once one of the ‘if’ tests is satisfied. for example. In C this is a valid statement with a completely different meaning than is intended! 7.7. it computes and displays the square root using the numpy. Look it up in a book if you are unsure or.7 If. If it is positive. just put in enough parenthesis to make it completely clear to anyone reading your code. ELIF. At most. the program stops. better. it does not check the others). The final ‘else’ is optional. IF. ask the user to try again. else constructs A more versatile form of the if statement is as follows: if (logical expression): (block of code) elif (logical expression): (block of code) elif (logical expression): (block of code) . elif. One nice aspect of Python compared to C is that if you make a mistake and type.sqrt() function. If the user enters zero. As many elif statements as required can be used. if (a = 0): you will get an error message during that repeatedly prompt the user for a positive real number. Here is a demonstration program (usersqrt. else: (block of code) Note that ‘elif’ is the Python version of the F90 ‘else if’ and that the blocks of code can contain many lines. ELSE CONSTRUCTS 245 There is very likely a specific order of operations for these things which I can’t remember very well. If it is negative. #! /usr/bin/env python import numpy as np while (True): a = float(raw_input("Enter positive real number (0 to stop) ")) if (a < 0): print ’This number is negative!’ . The final ‘else’ will be executed if none of the preceding if statements is true.7. .

Finally. b) + 1): if (a % i == 0 and b % i == 0): imax = i print ’Greatest common factor = ’. Stop the program if the users enters zeros for all three values. b.split()] if (a == 0 and b == 0): break else: for i in range(1. Note that ‘a % i’ computes the modulus (remainder) of a/i. ASSIGNMENT P3 Write a Python program to repeatedly ask the user for the constants a.sqrt(a) print ’sqrt = ’. feel free to enter them on three separate lines. b = [int(x) for x in raw_input \ ("Enter two numbers (zeros to stop): "). Using the quadratic formula. PETER’S PYTHON NOTES This program is very similar to the F90 version we saw earlier. The ‘continue’ line (optional in this case) continues the ‘while loop’ and serves the same function as the F90 ‘cycle’ command. The ‘break’ line leaves the while loop and thus ends the program. so we changed the user input line to ‘int(x)’ from the ‘float(x)’ that we used for the earlier programs. but it has fewer lines due to the lack of enddo and endif statements. note that we add one to min(a. imax The structure is similar to the corresponding F90 gcf program. Test your program for some simple examples to make sure it is working correctly (a=1. Output the number of real roots and their values.246 continue elif (a == 0): break else: b = np. c=-3 should return -3 and 1). Recall that ‘exit’ is the F90 equivalent. b=2. b CHAPTER 7. Note that a and b must be integers. HINTS: If you have trouble getting Python to read in all three numbers on one line.8 Greatest common factor example Here is a program that illustrates some of the concepts that we just learned: #! /usr/bin/env python # compute the greatest common factor of two integers while (True): a. min(a.b) because the Python upper limit is one . have the program identify and compute any real roots. 7. and c in the quadratic equation a*x**2+b*x+c=0.

it is a good strategy to break the problem down into smaller pieces by defining functions or subroutines to perform smaller tasks. USER DEFINED FUNCTIONS 247 less than the number in the range argument (this is hard to remember for F90 programers!). ASSIGNMENT P4 Modify gcf.7. To illustrate how to define your own function in Python.9 User defined functions (To motivate this. It is easier to use parts of the program in a different program. b) + 1): if (a % i == 0 and b % i == 0): imax = i return imax while (True): a. 2. To . Your code is more modular and easier to understand. let’s repeat the F90 notes here:) As the length and complexity of a computer program grows.9. b = [int(x) for x in raw_input \ ("Enter two numbers (zeros to stop): "). b) print ’Greatest common factor = ’. You can test these pieces individually to see if they work before trying to get the complete program to to compute the least common multiple of two integers. where functions and subroutines normally follow the main program. 7. imax Because Python is not compiled (it just interprets your script line by line). This provides several advantages: 1. This is opposite to the convention in Fortran. here again is the greatest common factor program: #! /usr/bin/env python # use a function to compute the greatest common factor of two integers def GETGCF(a. you define your functions BEFORE the main program.split()] if (a == 0 and b == 0): break else: imax = GETGCF(a. 3. min(a. b): for i in range(1.

we introduce subroutines at this point. GETGCF(a. we don’t really need the imax in the main program—we could have simply written: else: print ’Greatest common factor = ’. we will do the SPH AZI example using a function in userdist.) def SPH_AZI(flat1. flon2): import numpy as np if ( (flat1 == flat2 and flon1 == flon2) or (flat1 == 90. For greater accuracy. flon1. from N (deg. you must start with ‘def’ and then the name of the function and any arguments: def GETGCF(a. I’m not sure if there is an exact equivalent in Python.5 degrees. we know the function ends when the indentation ends. use double precision or perform a separate calculation for close ranges using Cartesian geometry. that is. flat2. Of course. However. something you call with variables in an argument list that can be used for both input and output from the subroutine.) or \ \ . b) In the F90 notes. imax is returned to the calling program with the ‘return’ statement. Python functions are more versatile than Fortran functions because they can return more than one value.lon on Earth (2) This routine is inaccurate for del less than about 0. and flat2 == #! /usr/bin/env python # # # # # # # # # # # # # # # # # SPH_AZI computes distance and azimuth between two points on sphere Inputs: flat1 flon2 flat2 flon2 Returns: del azi Notes: (1) applies to geocentric not geographic lat. The contents of GETGCF are indented. = = = = = = latitude of first point (degrees) longitude of first point (degrees) latitude of second point (degrees) longitude of second point (degrees) angular separation between points (degrees) azimuth at 1st point to 2nd point. PETER’S PYTHON NOTES define a function.248 CHAPTER 7. Thus. b): Notice the syntax: a and b are passed into the function from the calling program.

lon: ").arccos(cang) delta = ang/raddeg sang = np. . If you use Xcode to do your editing.arctan2(saz. return delta. . lat2. .9.cos(phi2 . delta. azi 249 Notice that delta and azi are not part of the argument list. lon1. lon: ").phi2)/sang az = np.sin(theta2) ctheta1 = np. caz) azi = az/raddeg if (azi < 0.split()] delta. so you have a clue that you should not use them for variable names.sin(phi1 .9. lat2.) ): delta = 0. lon1 = [float(x) for x in raw_input \ ("Enter first point lat.7. then the key words show up in different colors. return delta.1 Python keywords When I first tried translating this program from the F90 version.pi/180. lon2 = [float(x) for x in raw_input \ ("Enter second point lat.split()] lat2. azi = ’. azi = SPH_AZI(lat1.cos(theta1) ctheta2 = np.flat1)*raddeg theta2 = (90. azi while (True): lat1.sqrt(1. azi = 0. Here are the keywords in basic Python: .sin(theta1) stheta2 = np.cos(theta2) cang = stheta1*stheta2*np. theta1 = (90.cang*cang) caz = (ctheta2 . USER DEFINED FUNCTIONS (flat1 == -90. I had trouble because it turns out that ‘del’ is a special word in Python and is used to delete items from lists (we have not talked about this yet). lon1.phi1)+ctheta1*ctheta2 ang = np. lon2) print ’delta. lon2) 7. but both are returned from SPH AZI when we write: delta.ctheta1*cang)/(sang*stheta1) saz = -stheta2*np. So I had to change the variable name ‘del’ to ‘delta’ to get it to work.): azi = azi + 360. azi = SPH_AZI(lat1. azi raddeg = np.flat2)*raddeg phi1 = flon1*raddeg phi2 = flon2*raddeg stheta1 = np. and flat2 == -90.

but I have not found this yet. . To avoid this.): azi = azi + 360. return # SPH_AZI computes distance and azimuth between two points on sphere # .’ Thanks. at least for a Python newbie like me. Note that ‘string’ is not one of the Python keywords. for example. azi and then our userdist2. But the one the really bugs me is ‘lambda’ as one would like to think that a Greek letter would always be OK to use in mathematical expressions1 . named. that really clears things up! 1 . It would be good to find a complete list of program names to avoid in Python. caz) azi = az/raddeg if (azi < 0.9. but created a module that prevented numpy from working in my other Python scripts! I believe the problem is that there is a module called ‘string’ but am not sure about this. One website says that it is best described as ‘a tool for building callback handlers. az =’. it is not easy to understand what lambda actually does. it’s annoying and inefficient to have to include it in each script. sph subs. we can simply include the function in a separate script. The program worked fine.2 Using functions in separate files If we want to use SPH AZI in multiple programs. PETER’S PYTHON NOTES not or pass print raise return try while with yield DO NOT USE THESE AS VARIABLE NAMES! Most of these words kind of sound like things that make sense at some level. ANOTHER WARNING: Another potential pitfall is using certain ‘special’ names for your Python script. . Can any of you find such a list or a way to generate it? script can have the form: #! /usr/bin/env python Incidentally. although we aren’t going to discuss them until we need to.250 and as assert break class continue def del elif else except exec finally for from global if import in is lambda CHAPTER 7.arctan2(saz. I ran into this recently when I called one of my programs ‘string.

dtype=int) In this case. not parenthesis. like C. unlike suffix when we import sph subs and that we choose ‘ss’ as the prefix to use before the function names (analogous to using ‘np’ as the prefix for the numpy script must be in the same directory as userdist2. azi = ss. lon: "). dtype=float) ii = ARRAYS import sph_subs as ss while (True): script. When you run the userdist2. not one. to refer to specific array values. maxnum+1): prod[i] = 0 max_i = int(np. delta.10 Arrays Here are some examples of how to define arrays in Python using numpy: #! /usr/bin/env python import numpy as np a = np. lon1.0] but not b[50. azi = ’. lon2) print ’delta. dtype=int) for i in range(1. azi 251 Note that we drop the . lon: "). Notice that in Python.sqrt(maxnum)) .SPH_AZI(lat1. This is a binary file (don’t try to edit it). lat2.pyc. a is defined as a vector (1-D array) with 100 real elements and ii is defined as a 50 x 2 matrix of integers. Annoyingly.split()] delta. Here is an example program that uses an array to compute prime numbers less than 100: #! /usr/bin/env python import numpy as np maxnum = 100 prod = np. 7.ndarray(shape=(maxnum+1). and the ‘b’ array includes b[0. in the above example the ‘a’ array has values from a[0] to a[99].split()] lat2.2]. a file called sph subs. lon2 = [float(x) for x in raw_input \ ("Enter second point lat. lon1 = [float(x) for x in raw_input \ ("Enter first point lat.10.7.2). Thus.ndarray(shape=(50. which helps future scripts to load faster. is automatically created. we use brackets.ndarray(shape=(100). array indices start with zero. The sph subs.

252 CHAPTER 7. Here is the code: #! /usr/bin/env python import numpy as np maxnum = 1000 prod = np. Actually. dtype=int) pnum = prod for i in range(1. maxnum+1): prod[i] = 0 max_i = int(np.ndarray(shape=(maxnum+1). nprime Note that we set the upper limit of the prod array to maxnum+1. max_i+1): if (prod[i] == 0): max_j = maxnum/i for j in range(2. max_j+1): prod[i*j] = 1 nprime = 0 for i in range(2. so that the actual array goes from prod[0] to prod[maxnum] (recall that array indices start with zero). PETER’S PYTHON NOTES for i in range(2. we also don’t use prod[1] for anything. Now let’s change the code to print out many numbers per line by saving the prime numbers in a separate array called pnum. We don’t use prod[0] for anything. nprime print pnum[1:nprime+1] . max_i+1): if (prod[i] == 0): max_j = maxnum/i for j in range(2. max_j+1): prod[i*j] = 1 nprime = 0 for i in range(2. just like in the F90 version. maxnum+1): if (prod[i] == 0): nprime = nprime + 1 print i print ’Number of primes found = ’. maxnum+1): if (prod[i] == 0): nprime = nprime + 1 pnum[nprime] = i print ’Number of primes found = ’.sqrt(maxnum)) for i in range(2.

at some point it would be nice to know how to make an explicitly formatted output table of the primes like we did in the F90 notes.11. pnum. 7. Here are some examples: . I was not able to easily find an example of this by Googling around.7. It’s confusing because of the difference from the F90 convention. we can specify a range of array indices using pnum[1:nprime+1] and how Python adds an opening and closing bracket around the array contents upon output. CHARACTER STRINGS 253 Notice that we can define the second array.ndarray). Recall that we ran into this before with ‘range’ and ‘shape’ in (np. but for completeness. The output looks pretty nice.11 Character strings You can define a string variable in Python very simply: s1 = ’Peter’ and combine strings like this: s1 = ’Peter’ s2 = ’Shearer’ s3 = s1 + ’ ’ + s2 There are lots of built in functions to manipulate strings in Python. like in F90. Why is the upper limit nprime+1 and not nprime? Because of the non-intuitive way Python sets the upper limits. the same size as the first array by simply saying pnum = prod The output of this code is: Number of primes [ 2 3 5 7 67 71 73 79 157 163 167 173 257 263 269 271 367 373 379 383 467 479 487 491 599 601 607 613 709 719 727 733 829 839 853 857 967 971 977 983 found = 168 11 13 17 19 83 89 97 101 179 181 191 193 277 281 283 293 389 397 401 409 499 503 509 521 617 619 631 641 739 743 751 757 859 863 877 881 991 997] 23 103 197 307 419 523 643 761 883 29 107 199 311 421 541 647 769 887 31 109 211 313 431 547 653 773 907 37 113 223 317 433 557 659 787 911 41 127 227 331 439 563 661 797 919 43 131 229 337 443 569 673 809 929 47 137 233 347 449 571 677 811 937 53 139 239 349 457 577 683 821 941 59 149 241 353 461 587 691 823 947 61 151 251 359 463 593 701 827 953 Notice that.

f90. computes their product.split() name1. translated into Python: #! /usr/bin/env python name = raw_input("Who did you vote for in 1992? ") if (name. and outputs the original numbers and their product to an output file: #! /usr/bin/env python infile = raw_input("Enter input file name: ") filein = open(infile.find(’lin’) != -1): print ’Then you are likely a Democrat.find(’eor’) != -1 or name.’ 7.split() print name1 print name2 and its output: Peter 13 6 [’Peter’.12 I/O with files Here is the Python version of fileinout.254 #! /usr/bin/env python s1 = ’Peter Shearer’ print s1[0:5] print len(s1) print s1. name2 = s1.find(’ill’) != -1 or name.’ elif (name.find(’Sh’) print s1.’ else: print ’Then you are likely an independent voter. ’r’) . PETER’S PYTHON NOTES Here is the voter program from the F90 notes. a program that reads pairs of numbers from an input file.find(’ush’) != -1): print ’Then you are likely a Republican. ’Shearer’] Peter Shearer CHAPTER 7.

z) fileout. First we read and open the input file: infile = raw_input("Enter input file name: ") filein = open(infile. This is good to specify because it will prevent our accidentally writing on top of it.3f \n" % (x. y = [float(a) for a in line. we use a while loop to read the input file one line at a time: while (True): line = filein. Next. The optional 2nd argument ‘r’ opens the file for read only. ’w’) This is almost identical to the input version. Next we open file file and assign it to object infile (this is like a unit number in F90).3f %10. Next we split line into two parts (assumes the numbers are separated with blanks and no commas) and then converts to two real numbers (we saw this before when we input two numbers on one line). except we specify ‘w’ for write.split()] z = x * y .7.3f %10.readline() if not line: break We use the readline method to read line (a string) from the object filein. Similarly we read in and open the output file: outfile = raw_input("Enter output file name: ") fileout = open(outfile.close fileout. I/O WITH FILES outfile = raw_input("Enter output file name: ") fileout = open(outfile. y = [float(a) for a in line. ’r’) 255 The first line here is similar to what we used before to input numbers except this time all we need is the string returned by raw input. If there is nothing more to read. and then computes their product: x.split()] z = x * y line2 = "%10.close Let’s examine how it works.write(line2) filein. ’w’) while (True): line = filein.readline() if not line: break x.12. It also means the file must already exist. then ‘not line’ will be true and we exit the while loop. y.

PETER’S PYTHON NOTES Next we perform a formatted write of the three numbers to line2 (another string variable) and then write this to object line2: line2 = "%10.split()] z = x * y fileout.3f %10.write(line2) When we are done (having left the while loop with the break). z) fileout.3f \n" % (x.3f %10. z)) This should be self-explanatory.3f \n" % (x.3f %10. y = [float(a) for a in line.close fileout. y = [float(a) for a in line. Here is a more compact version of fileinout. ’w’) lines = filein. we close the two files: filein. ’w’) for line in filein: x.3f %10. y.readlines() for line in lines: x.split()] z = x * y fileout.write("%10. z)) filein. This is even more true in Python than it was in Fortran. we could read the entire input file in at once: #! /usr/bin/env python filein = open(raw_input("Enter input file name: "). y. ’r’) fileout = open(raw_input("Enter output file name: ").close #! /usr/bin/env python filein = open(raw_input("Enter input file name: ").close . except for the line for line in filein: which is a new syntax and shows how Python will automatically grab one line at a time from the input file object. Alternatively. y. ’r’) fileout = open(raw_input("Enter output file name: ").3f %10.3f \n" % (x.write("%10.3f %10.close There are typically many ways to write the same program.256 CHAPTER 7.

.. There are a variety of plot packages available for Python.. y) pylab. 1. 3.9. 7. For now. 4.. look at Lisa’s notes. 3.plot(x.13.7. 1.2. Let’s start with an example program ( which produces Figure 7.g. Next.] These are not the same as the arrays that we used earlier. 4. 2. USING TUPLES AND LISTS 257 where we use ‘readlines’ rather than ‘readline’ in order to input the entire file. Any Python experts want to try to find this approach? 7. In fact they could be a mixture of different types of variables (e.1.] y = [1. We are going to use matplotlib because this is what Lisa uses. but somehow directly read x and y as vectors. Please consult her notes for more details. int. The first three lines are necessary to import the plotting packages and define some of their attributes.use("TkAgg") import pylab x = [1. compute z as a vector. 4.9. 3. 4..] pylab.. Then notice how we can pull out one line at a time by writing: for line in lines: There is probably even a way to do this where we don’t loop over the lines.14 Plotting with Python A big advantage of Python over Fortran is the ability to make plots directly from Python scripts..] y = [1. but in this example .13 Using tuples and lists This is a placeholder.. we define two lists of 4 numbers each: x = [1. 3.2. and then output the vectors directly to the output file.. #! /usr/bin/env python import matplotlib matplotlib. float. string).

. 4.use("TkAgg") import pylab x = [1.2.5.plot(x. Now let’s improve the appearance of this plot and add some labels (xyplot2.png) by using the appropriate suffix on the file name. 1.9.xlim( which brings up the pop-up window. PETER’S PYTHON NOTES Figure 7.] y = [1.ylim(0.. we plot the points and display the result: pylab.] pylab. You can save it in different format (e. 4. 4.5. 3.1: The pop-up window that results from xyplot. 3. Next.eps. they need to be of the same type and size. .py): #! /usr/bin/env python import matplotlib matplotlib. You must close the window (click on the ref button in the far upper left) to get back to your terminal window. 2.5) y) pylab. From the window. . you can save the plot by clicking on the little microdisk icon..258 CHAPTER 7. 4.5) .

4.title(’My x-y points’) pylab. and line types (r=red. c=cyan.plot(x. w=white.plot 3rd argument can indicate various colors. *=star. y. p=pentagon.2: The pop-up window that results from xyplot2. m=magenta. :=dotted line. PLOTTING WITH PYTHON pylab.ylim(0. None=no connecting lines). ’bs’) where the optional pylab.ylabel(’Y axis’) -.7. x=x.=dashdotted line. D=diamond. symbols.xlabel(’X axis’) 259 Figure 7.5.5) pylab.=dot. which produces Figure 7. s=square. In this case we define the plot limits so that the endpoints do not sit on the plot axes: pylab. 4. ’bs’) pylab. o=circle. –=dashed line. k=black. h=hexagon.5) and we plot the points with blue squares: pylab. +=plus.plot(x. . g=green.5. carat=triangle. y. b=blue.xlim(0.14. y=yellow.2. -=solid line. .

PETER’S PYTHON NOTES 7. http://docs.linalg... (2.14.9).1 Example of computing least-squares line As a example to illustrate both Python matrix math and plotting capabilities.0]) Similarly.e. G is the linear operator for predicting the data from the model. 3.2). where a is the y-intercept and b is the slope. and (4. we defined the x and y vectors as lists.T .mat([1. (3.h.2. To do more advanced matrix operations.s. e.html): import numpy as np import numpy. given by yT d = y. let’s compute and plot the best-fitting line to the points from the last section. 3. This is a standard form for linear problems: d = Gm where d is a data vector with the y-values of the data. Note that the 2x4 matrix in this case consists of a column vector with ones (that are multiplied by a) and a column vector containing the x values of the data points (which are multiplied by b.s. and m is the desired model. 4]) y = np.9   1     3.9.linalg (see. [1.h. we set up the 2x4 G matrix: G = np. we also import the linear algebra package numpy. (1. 4.2  =  1 1 4    1 2 a  3 b 4  (7.0.linalg as lin In the last [1. 3. 1). 4]]) and the 1x2 column vector d.mat([1.2]. Our program will need to import numpy to do basic matrix arithmetic. Then we can express the desired fit to the data as the matrix equation: 1 1  1.mat([[1. best fits the l. In this case the model is simply the coefficients a and b of the line. 1.260 CHAPTER 7. [1. 3]. i. using the numpy mat method: x = np.scipy. 2.1].1) where the goal is to adjust a and b so that the r.g. but we now need to make them matrices. 4). 1. such as computing inverses and eigenvalues. Let the equation of the line be y = a + bx. the slope).

T #data vector #model vector for least-squares fit m = lin.1].2]) d2 = np.mat([[1. 2.inv(G.use("TkAgg") import pylab import numpy as np import numpy.T * d print ’m = \n’. 4]]) d = y. In our case. 3].0. 4. we compute the y values for x values of 0.05 + 1.8]. To solve for m.03 ∗ x.mat([0. 4.inv is the linalg matrix inverse function.2].mat([1.2: x2 = np.2]) Note to Geophysics Graduate students: The formula for m given here is the sort of thing that you are expected to know how to derive before you take your departmental exam.e.mat([1. [1.T * G) * G.inv(G. m = GT G Translated to Python. [1. 1. i.8.T is the transpose operator. 3. m x2 = np.7.8 and 4. 4.2.0]) G = np.mat([0. such as inverse and determinant x = np. 4. 3.T * G) * G.8. we apply the standard formula for the least-squares solution2 to d = Gm. here is the complete program: #! /usr/bin/env python import matplotlib matplotlib.9. See a linear algebra or statistics text for details 2 . [1. To plot this line. this becomes m = lin. 0.mat([[1.2) #matrix ops.linalg as lin −1 GT d (7.T * d print ’m = \n’. [1.. m = [[-0. PLOTTING WITH PYTHON 261 where . The print statement is to show the coefficients a and b in the best-fitting line. 4]) y = np. m will also be a 2-vector that contains the y-intercept and slope of the best fitting line.03]] The best-fitting line is of the form y = −0.2]]) * m Putting it all together.05] [ 1.14. m where lin.

The only way I succeeded in plotting the line is pylab.T. ’sb’) pylab.ylabel(’Y axis’) pylab.2]]) * m pylab. ’r-’) fails.5. 4. PETER’S PYTHON NOTES d2 = np. ’r-’) #(x2. For some weird reason (bug?). In addition.3.8]. This makes no sense to me! Figure 7.ylim(0. 4.plot(x.xlim(0.3: The pop-up window that results from xyplot3.plot(x2.plot(x2. d2. ’sr’) works and pylab. 4. 0.5) pylab.T) fails for lines.title(’My best-fitting line’) pylab.’X axis’) pylab. d2. d2. ’sr’) works.T.plot(x2. but pylab. d2.plot( which produces the plot shown in Figure 7. d2. ’r-’).mat([[1.T. I had trouble getting the red line to plot using the matrix input to pylab.5.5) pylab. ’r-’) fails.linalg least-squares . d2. but works for symbols (bug?) pylab. [1. pylab. pylab.plot(x2.T. y.262 CHAPTER 7. Note that this problem can also be solved using the numpy.

7. m 263 . d) print ’m = \n’. residues.14.lstsq(G. PLOTTING WITH PYTHON solution function lstsq: m. rank. s = lin.


It is very easy to use (WYSIWYG) and is the “standard” word processor of choice in many institutions. Advantages of LaTeX: 1. but you will find it well worth your effort. By using macros. A far better choice is TeX or LaTeX. It is not. 2. I will describe running LaTeX from the UNIX command line although I am actually most familiar with using it on my Mac using a fancy implementation (TexShop). LaTeX takes a little while to learn at first. It has particular difficulty handling equations and specialized typesetting requirements. It is in the public domain so you are not supporting the Evil Empire. IGPP scientists typically use either Word of Latex for this purpose (some old timers still use troff. 5. 3. it is a far more powerful and versatile system than all that pull down menu crap you find in most commercial word processors. ideal for writing scientific articles.Chapter 8 LaTeX Someday you will want to publish the results of your research. however. PCs or UNIX machines. 4. AGU uses LaTeX for its electronic submission of articles and abstracts. which you can download from: 265 . They provide macros to match the style of their journals so that preparing cameraready copy is trivial. You can run it on Macs. Most of you probably already know how to use Word. a UNIX precursor to LaTeX). You can produce beautiful looking equations much more easily than with programs like Word.

\end{document} which will produce: Today (November 30. this will generate the file samp1. or letter. From this example you can see that Latex is not WYSIWYG! To typeset this document. The guts of the document are then enclosed between the \begin{document} and \end{document} commands. enter: latex samp1 Assuming you have no errors in the input file. Kopka and Daly.1 A simple example Use your favorite text editor to create the file samp1. an increase of 1\% over yesterday. This example highlights some of the special characters and macros in Latex. ‘\today’ invokes a macro to print today’s date and ‘\pound’ will print the British pound symbol. 2012) the rate of exchange between the British pound and the American dollar is £1 = $1. The document must first define a document class.e. you must precede them with a backslash.. article. an increase of 1% over yesterday. A Guide to Latex2e): \documentclass{article} \begin{document} Today (\today) the rate of exchange between the British pound and the American dollar is \pounds 1 = \$1. enter: xdvi samp1 . i. To preview this file. report.63.tex (an example from the Latex book. LATEX 8.266 http://pages.63. Options are book.dvi. The following characters are normally interpreted as Latex commands: $ & % # _ { } To print these out in your text.uoregon. \$ \& \% \# \_ \{ \} In this CHAPTER 8.

you can change the default for this directly: \documentclass{article} \begin{document} \setlength{\parindent}{0. it only considers the first blank. \end{document} This will now indent all paragraphs by 0. It also ignores extra blanks. but the inverse function $p(x)$ is multi valued. An even nicer function is the combination \begin{equation} .ps 267 Notice that Latex automatically indented the first line of the paragraph.2 Example with equations \documentclass{article} \begin{document} \setlength{\parindent}{0. To avoid this. New paragraphs are defined by adding a blank line between blocks of text.0in} The function $X(p)$ is more nicely behaved than $T(X)$ since it does not cross itself (there is a single value of $X$ for each value of $p$). enter: dvips samp1 -o samp1. an increase of 1\% over yesterday. use the command for the target paragraph: \documentclass{article} \begin{document} \noindent Today (\today) the rate of exchange between the British pound and the American dollar is \pounds 1 = \$1. an increase of 1\% over yesterday.2. 8.8. To remove paragraph indenting.5 inches. EXAMPLE WITH EQUATIONS To convert the file to a Postscript file.63. \end{document} To globally change the paragraph indenting.63. just set this parameter to zero.5in} Today (\today) the rate of exchange between the British pound and the American dollar is \pounds 1 = \$1. Latex ignores the carriage returns at the ends of each line in the input file.

Variables within the equations are automatically put into italics. \eta. dz \end{eqnarray} where $\eta$ is the vertical slowness.268 CHAPTER 8. An even nicer function is the combination τ (p) = T (p) − pX(p).3) (8. Note that equations within the text are enclosed with $ signs. dz \end{equation} or \begin{eqnarray} \tau(p) &=& 2 \int_0^{z_p} (u^2-p^2)^{1/2} \. \begin{equation} and \end{equation} are used to put the equation on a separate line. . superscripts with the carat. but the inverse function p(x) is multi valued. It can be calculated very simply: \begin{equation} \tau(p) = 2 \int_0^{z_p} \left[ {u^2 \over {(u^2-p^2)^{1/2}}} {p^2 \over {(u^2-p^2)^{1/2}}} \right] \. Fractions are written as. note how the limits are written. for example.4) = 2 0 where η is the vertical slowness. dz \\ &=& 2 \int_0^{z_p} \eta(z) \. LATEX \tau(p) = T(p) . Greek letters are defined as \tau. \end{equation} where $\tau$ is called the {\it delay time}. Subscripts are defined with the underscore ( ). etc. It can be calculated very simply: zp (8. where τ is called the delay time.1) τ (p) = 2 0 p2 u2 − 2 (u2 − p2 )1/2 (u − p2 )1/2 zp dz (8. {x \over y}.pX(p). \int is for the integral symbol.2) or τ (p) = 2 0 zp (u2 − p2 )1/2 dz η(z) dz (8. \end{document} which typesets as: The function X(p) is more nicely behaved than T (X) since it does not cross itself (there is a single value of X for each value of p). Equations are automatically numbered (this can be changed if desired). Curly brackets are used to separate things—they do not appear in the typeset version.

Every line except the last line has a carriage return (\\). 8.2 Font attributes = = = = = switch to italics switch to slanted font switch to upright (normal) font switch to bold switch (back) to regular weight \itshape \slshape \upshape \bfseries \mdseries These commands can be invoked in several different ways to put “in situ” in italics and then return to normal font: \itshape in situ \upshape OR {\itshape in situ} . Note that &=& is used to define what it is that is being aligned.3.3 8.8. Although TeX generally does an excellent job of spacing equations.3. is used to place a tiny amount of space before the dz. In this case \. sometimes some fine tuning will help.1 Changing the default parameters Font size There is a standard font size declared for each document class. arranged in increasing order of size: \tiny \scriptsize \footnotesize \small \normalsize \large \Large \LARGE \huge \Huge 8. One easy way to change the size is with the following commands.3. CHANGING THE DEFAULT PARAMETERS 269 The \begin{eqnarray} section is used to align the = signs in the two lines of equations. In most cases this is Roman 10 pt.

as well as {\small small}. as well as small. and {\scriptsize scriptsize} type. \renewcommand{\baselinestretch}{2} . footnotesize. and LARGE type. Large.270 OR \begin{itshape} in situ \end{itshape} CHAPTER 8. \end{document} which produces: Let’s test different ways to say in situ in italics. This will result in double spacing. Here is an example of how these options can be used: \documentclass{article} \begin{document} Let’s test different ways to say \itshape in situ \upshape in italics. indeed \begin{itshape} in situ \end{itshape} can be written in italics in at least three different ways. LATEX These different options also apply to the font sizes listed above. {\footnotesize footnotesize}. Change normal (single) line spacing by a factor of 2.3.3 Line spacing There is a default line spacing created whenever a new font is selected. This must be called before \begindocument or before a new font declaration. Here are examples of two different ways that this can be changed: \setlength{\baselineskip}{10pt} Change line spacing to 10 point (single spacing for 10pt font). and scriptsize type. and {\LARGE LARGE} type. Next let’s experiment with {\large large}. indeed in situ can be written in italics in at least three different ways. 8. Next let’s experiment with large. {\Large Large}. There are several different ways to say in situ in italics. There are several different ways to say {\itshape in situ} in italics.

pdf} \end{center} \caption{Here is the caption for this plot.. blah.8. . EPS.. 8. blah. Blah. \end{document} which will produce: We are now going to show how to embed a Postscript file into a LaTex document using the includegraphics command. \begin{figure}[h] \begin{center} \includegraphics[scale=0. positioned below the plot.7]{plot_1.4 Including graphics Postscript. Here is an example that uses graphicx: \documentclass{article} \usepackage{graphicx} \begin{document} \setlength{\baselineskip}{20pt} We are now going to show how to embed a Postscript file into a LaTex document using the includegraphics command.63. an increase of 1\% over yesterday.63. Let’s write one more line here so that we get up to three lines and can see the spacing better. 2012) the rate of exchange between the British pound and the American dollar is £1 = $1. \end{document} which produces: 271 Today (November 30.} \end{figure} This will be automatically And then here is some more text to show where the next block of text will appear. an increase of 1% over yesterday. and PDF files can easily be embedded as figures in a Latex document by including Latex extension packages such as graphics or graphicx. INCLUDING GRAPHICS Here is an example: \documentclass{article} \begin{document} \setlength{\baselineskip}{20pt} Today (\today) the rate of exchange between the British pound and the American dollar is \pounds 1 = \$1. Let’s write one more line here so that we get up to three lines and can see the spacing better.4.

The \begin{figure} macro has various options for where the figure will be positioned.pdf} which specifies exactly what part of the page will be windowed and displayed. [tb] will position the figure at either then top or bottom of the page. This will be automatically positioned below the plot. In this example. And then here is some more text to show where the next block of text will appear. \includegraphics[bb=2in 4in 7in 9in. an easier option is to use the Mac Preview program to open Postscript or EPS files (from Adobe Illustrator . or at the top [t] or bottom of the page [b]. e. Blah. scale=0. i.1: Here is the caption for this plot.272 CHAPTER 8.. LATEX Figure 8. you also may need to apply a “bounding box” to remove the surrounding white space using the bb= option. Depending upon how the figure is positioned in the PDF file. In my experience. Note that the graphicx package is loaded with the \usepackage{graphicx} command at the start of the file.e. blah. including at the present location in the text [h]. This is necessary for PDF figures that appear in only part of an entire page and it can be tedious to find the right bounding box. the figure is scaled to 70% of its original size..7]{plot_1..g. blah.. These options can be combined.

8. they are tightly windowed and the bb option is not needed. In this case.tex.W. Addison-Wesley.5. H.tex are also included. WANT TO KNOW MORE? 273 or other graphics programs) and then save them within Preview as PDF files. New York. users have control over the starting figure number. Check out David McMillan’s great Latex example file.. ex. A Guide to Latex 2e. Daly.tex. The accompanying files psfig. A good Latex reference book is: Kopka. and which you can find in ∼shearer/CLASS/COMP/LATEX. . 1995. Figures are automatically numbered.5 Want to know more? There is a huge amount of material about Latex on the web. and gnufig. hobbes.


Let’s start with an example Postscript file (mypost1): newpath 144 72 moveto 288 432 lineto stroke showpage We start with the NEWPATH operator. This empties the current path and declares we are starting a new path (because we are at the beginning of the file. However. and is generally easy to understand. but there is still an option to save in Postscript). you can also generate your own Postscript files and that is the subject of these notes. Next we move to the point (144. this command is not actually necessary here but it’s a good idea to start with this). These numbers move onto a “stack” and are then read by the moveto command. Postscript is ideally suited for user generated graphics because it is in ascii (plain text). you can print to a file rather than to the printer and it will save whatever you were going to print out as a Postscript file (most people save as a PDF file. 72): 144 72 moveto The default coordinate system for Postscript files is in units of 1/72 of an inch. For example on the Macs. You can generate Postscript files automatically from programs. is well documented.Chapter 9 Postscript plotting PostScript is a page description language that is used by most modern printers for both text and graphics. The arguments for moveto are the x and y coordinates. Thus. measured from the lower left corner of the page. this command moves us to a point 2 inches to the right of 275 .

i. you will need to cancel the print job on the printer and/or kill the job on your computer. Both Bob Parker and I prefer to use 1/1000 inch coordinates. You don’t want 200 pages of text to come out of the printer when you really wanted a single page of graphics! If you ever do make this mistake.072 scale % Coords are 1/1000 th inch . If you are like me. (mypost2). then the printer will just print out the ascii text. We can also send it to a Postscript printer. 6 inches): 288 432 lineto You can think of this as a “draw” command except the draw is not actually executed yet—it is just added to the currently defined path. to be sure that the printer recognizes that it is a Postscript file. This can by adding the following line at the beginning of your file: 0. This is the “current point” and we can think of this as a pen location. POSTSCRIPT PLOTTING the left page edge and 1 inch above the page bottom. we should always start the file with %! PostScript file.072 0. Next we add a line segment between the current point and a new point at (288 432) (4 inches. This is no big deal with a small file like this but is a big problem for a large Postscript file. we display the current page: showpage We can preview this file with pageview or ghostview. However.e. we use the “stroke” command: stroke Finally.276 CHAPTER 9. you will find the 1/72 inch coordinate system an annoyance. %! PostScript file newpath 144 72 moveto 288 432 lineto stroke showpage If you don’t start with this. To draw the path on the page.

072 times as large as they would have been drawn with the old coordinate system. Note that % is used to add comments.277 This means that objects will be drawn 0. Why use 1/1000 inch as the coordinate instead of inches directly? The nice thing about 1/1000 inch is that this is roughly the limit of what the human eye can resolve on the page so it is not likely that one will need to divide things smaller than this.072 0.072 0.072 = 1 inch. We can save more space if we shorten the “moveto” and “lineto” commands since they will be used many times in a complicated file. Thus. one can avoid decimal places in the numbers and can save a little bit of space in the file. Our revised Postscript file thus becomes (mypost3): %! PostScript file /m {moveto} def /d {lineto} def 0. The coordinate 1000 thus now indicates 1000*(1/72)*0. Anything to the right of the % is assumed to be a comment (the first line is a special “comment” that the printer recognizes).072 scale newpath 2000 1000 m 4000 6000 d stroke showpage Now let’s draw a box with thicker lines than our starting examples (mypost4): %! PostScript file /m {moveto} def /d {lineto} def 0.072 scale newpath 4000 4000 4000 5000 5000 5000 5000 4000 4000 4000 m d d d d % Coords are 1/1000 th inch % Coords are 1/1000 th inch . We can shorten then by defining our own shorter operators: /m {moveto} def /d {lineto} def This tells the Postscipt interpreter to replace “m” with “moveto” and “d” with “lineto”.

The resulting plot will have a slight notch in the starting corner.072 scale newpath 4000 4000 m 4000 5000 d 5000 5000 d 5000 4000 d closepath 30 setlinewidth stroke CLOSEPATH adds a line segment from the current point to the initial point in the path.072 0. % Coords are 1/1000 th inch % Coords are 1/1000 th inch .072 0.072 scale newpath 4000 4000 m 4000 5000 d 5000 5000 d 5000 4000 d closepath 0.278 30 setlinewidth stroke showpage CHAPTER 9. we set the gray level for printing at 0. Before actually drawing the box. we can fill in the box using the FILL command (mypost6): %! PostScript file /m {moveto} def /d {lineto} def 0.5 setgray fill showpage Before doing the fill. we can use the “closepath” command (mypost5): %! PostScript file /m {moveto} def /d {lineto} def 0. Once a closed path is defined. thus we don’t need the fourth LINETO command. POSTSCRIPT PLOTTING We draw the four sides with four “d” (lineto) commands. we set the line width to 30/1000 inch. To avoid this. The gray levels range from zero (black) to one (white).5. It also closes the path with a mitered join so we don’t have the notch as in the previous example.

I could go on with these examples but it would be better to just consult a Postscript book to learn more about all the things one can do. Two good ones are: Postscript Language. Here is an example (mypost7): %! PostScript file /m {moveto} def /d {lineto} def 0. For convenience. I have written a set of Fortran subroutines for making Postscript files that handle a lot of the bookkeeping details and allow the user to concentrate on the graphics.072 0. both by Adobe Systems and printed by Addison-Wesley.3 inches.072 scale % Coords are 1/1000 th inch /Times-Roman findfont 300 scalefont setfont 2000 3000 moveto (Example text) show showpage Here we set the type of font with “/Times-Roman findfont” and then set the font size with: 300 scalefont This sets the font height to 0. one could write the appropriate commands to a file. There are lots of different choices for the fonts.9. Well. 9.1. Finally. we print the string “Example text” at the current location using the SHOW command: (Example text) show We must enclose the text in parentheses to denote it as a string. We then move to the point (2000 3000). PSPLOT FORTRAN SUBROUTINES 279 Of course we can also print text of various sizes and types. Language Reference Manual. Given knowledge of the Postscript language. These routines are contained in: . The scaled font must then be set to the current font with the SETFONT command. The main choices for science graphics are Helvetica and Times and their bold and italic variations.1 PSPLOT Fortran subroutines It is useful to be able to generate Postscript files directly from within a Fortran program. Tutorial and Cookbook and Postscript.

10. 2. 3. The argument could also be a string variable.0.) call PSEND end program testpsplot The resulting plot is shown in Figure 9.5) call PSMOVE(2.. .x2. 7.) call PSAXES(1.5.5. POSTSCRIPT PLOTTING /users/shearer/PROG/PLOT/psplot. ’i3’..a Documentation for these routines is contained in: /users/shearer/PROG/PLOT/psplot. 0. 8. 0. they should be linked with: /users/shearer/PROG/PLOT/psplotlib.5. units 17 and 18 should not be used in any program that uses the psplot routines). call PSWIND(1.y2) define the location of a coordinate “box” on the page in inches. 3...0.y) coordinates of the lower left and upper right corner of the this rectangle in inches. allowing the user to input the name.. 0.280 CHAPTER 9.y1.0.. 0.5. 10. 0.. 7. 10. 0..5.5. The first four numbers (x1. 3. 5.0) define the (x.) call PSDRAW(5. We could of course give the file any name we want at this stage. ’i3’) call PSLAX(’X label’..5.0) and (7.f To call these routines from a F90 program. (1. 0. Here is an example program that uses some of these routines: program testpsplot implicit none call PSFILE(’mypost’) call PSWIND(1.05. 7.. Let us consider the commands one at a time: call PSFILE(’mypost’) This opens the Postscript file with name “mypost” (assigning it to Fortran unit number 17. 7. 20.05.1. 2. 0.. ’Y label’.) This defines a user coordinate system that will be used for subsequent psplot commands. In this case. 7..

0.y4) define the corresponding values at these points for the user scale.05. 10. Thus in this case. The next four numbers (x3. Often we will want to plot the frame defined by this imaginary box (as in the PSAXES command below) but this is not required to define the coordinate transformation... The position of the frame is assumed to be defined by the corners set in WINDOW. ’i3’.20). the lower left point in user coordinates is (0.9.x4.ytic.1. 2.yticl.05. 0) while the upper right point is (10. The position of the frame is assumed to be defined by the corners set in PSWIND. Here is the documentation for the PSAXES command: PSAXES(xtic..xlab. call PSAXES(1.1: The result of the testpsplot program.ylab. 5.yfrmt) makes a frame with tics and tic labels as specified.y3.. xtic = small tic increment ylab = numbered tic increment (length is 2*nxtic) xticl = small tic length (inches) xfrmt = format for x-axis numbers (see PSNUMB for format details) etc. PSPLOT FORTRAN SUBROUTINES 281 Figure 9. All other points will be linearly interpolated (or extrapolated) using these values.xticl.xfrmt. for y Note: Don’t make tic increments negative even for reversed . 0. ’i3’) This draws a frame with tics and numbered tic labels as specified.

to ’ ’. 20.5.05... the program will not put a showpage command at the end of the file and your Postscript plot will not work! WARNING: Most of the numerical inputs to the PSPLOT routines must be real numbers! Do not use 2 instead of 2. ’i3’) PSLAX(’X label’.. 0.5.0. however.4) PSTIT(’Example title’.e.5.. ’i3’. ’Y label’.. y integer :: i. 0. 7. 0. 0.. icol character (len=10) :: text call PSFILE(’mypost’) call PSWIND(1..5. 5. Next we draw axes labels with the PSLAX command: call PSLAX(’X label’. that you can use ‘i3’ for the format for the axes numbers if you know that there won’t be decimal places in the numbers. 0.) Note.. 4. i.) Finally.. 1. 0.. See the psplot. 0. 0. Here is a more complicated example that demonstrates many of the PSPLOT subroutines.. 2.0. 0.5) The labels are offset by 0. 3. If you don’t want tic labels or a particular axis. 10.) call call call call PSAXES(1. 3.3.282 CHAPTER 9.8): call PSMOVE(2. 2.2) PSNOTE(’note that you might want to put down here’) call PSFRAM(1. ’Y label’. 5. set xfrmt or yfrmt to a blank character.) call PSBOX(1.2) and (5.5) . 8.. because the integer and real binary representations of 2 are different (the subroutines have no way of knowing that you used 2 rather than 2..) call PSDRAW(5.5. 2. Next we draw a line between user-coordinate points at (2. 10. program testpsplot2 implicit none real :: x. we must close the plot file: call PSEND If you leave out this step. 1. PSAXES should figure it out correctly.0.doc file for details. POSTSCRIPT PLOTTING scale plots.5 inches from the frame. 7.05..

) call PSTIC(0. 0) call PSNUMB(float(icol). 9.9.15) call PSMOVE(x.i1)’) ’lorg’.1.05) PSANG(0. 1. 15..3’) do icol=1.15 x=2. 0.5.1. i call PSLAB(text) enddo call call call call call call call call call call call call call call call call call PSMOVE(5.’i3’) enddo call PSGRAY(0. 0. 7.) call PSGRAY(0.) call PSMOVE(0.’f6.y) call PSCOL(icol) call PSSYMB(-3. 0.5.1415926 call PSNUMB(x.. 0.. 10. PSPLOT FORTRAN SUBROUTINES call PSCBOX(1..5 y=float(i)*2 call PSMOVE(x. 0. 0.9 call PSLORG(i) x=8.) PSSYMB(2.) call PSDRAW(1.) PSSYMB(1.’(a4.. 6.1) write (text. y) call PSSYMB(1. 2.) do i=1. 1) x = 3.1) PSANG(45..0... 7.) PSFONT(’hb14’) PSSYMB(3..y) call PSTIC(0. 1.) PSCOL(2) PSLORG(1) PSLAB(’Red text’) PSMOVE(5...5 y=float(icol)+2.) PSCOL(1) PSLAB(’bold text’) 283 .) call PSDRAW(1. 0.) PSCOL(3) PSLAB(’blue text’) PSMOVE(5.2. 12. call PSMOVE(x.05) PSANG(90.. 1.

05) PSANG(0. POSTSCRIPT PLOTTING call PSEND end program testpsplot2 Figure 9.284 call call call call call call PSMOVE(5. 0.2.) PSCOL(1) PSLAB(’small font’) CHAPTER 9. This can be rather tricky to use but is powerful once you understand how it works. Here is an example program: ..2: The result of the testpsplot2 program. and the resulting plot is shown in Figure 9.) PSFONT(’h8’) PSSYMB(3. The PSIMAG command allows the display of a bitmap in either black and white or color. 15.

1. 10. j integer*2. 0..05.. 1) call PSAXES(0. green. 7./50.) !must be 0 to 255 enddo enddo call PSIMAG(ibuf...15) call PSEND end program testpsimag and the resulting plot is shown in Figure 9. dimension(3. 5.25.i.i.)) blue = 0 ibuf3(1. 285 .05. 50. 50..0.1. 0.i.j) = red !must be 0 to 255 ibuf3(2. 50..2. 0. 50. blue real :: gray call PSFILE(’mypost’) ! First do black and white image call PSWIND(1. ’f4..4) call PSTIT(’Square root of x*y’ .j) = nint(gray*255. ’i3’. 50 gray = sqrt(real(i*j))/50. dimension(50. 0. 50 do j = 1.1’) call PSLAX(’Postscript Red’. 7.2. 0.1. 50) :: ibuf integer*2.3. 50.9.j) = green ibuf3(3. 0.3. 0.0. 5. 0. 50 red = nint(real(i)*(255.05. ’i3’) call PSLAX(’X label’. 6./50. 0) call PSAXES(5.5.45) call PSTIT(’RGB colors. 50) :: ibuf3 integer :: red. 10.1’. 0.15) ! Then do color image call PSWIND(1.5.1. 0. 0. 0.5.. ’f4.05.. 0. ibuf(i.. Green = 0’. 0.)) green = nint(real(j)*(255. 50. 0.) do i = 1. 9. 0. ’Postscript Green’.0. ’Y label’.5. 50 do j = 1. PSPLOT FORTRAN SUBROUTINES program testpsimag implicit none integer :: i. 50. 1.j) = blue enddo enddo call PSIMAG(ibuf3..) do i = 1.. 2.

3: The result of the testpsimag program. POSTSCRIPT PLOTTING Figure 9. .286 CHAPTER 9.

Sign up to vote on this title
UsefulNot useful