New Mexico Tech
Earth and Environmental Science

ERTH 401 / GEOP 501 - Computational Methods & Tools

Lab 4: Python Functions

Exercise 1 - Review

This week we're going to learn about functions in Python. However, before we delve into this topic, we're going to do a refresher exercise on lists and iteration.

Deliverable 1

We're going to combine everything that we learned and add something extra. We will be using the open function to open a data file consisting of latitudes, longitudes and station names. Open returns a file object, which provides several operations that can operatoe on this datatype. We will use the read() function, which returns the entire file contents in one single string (if called without a parameter). String objects provide another set of functions. Here, we'll use the split function to split the single string that contains all of the file contents into a list of strings using any whitespace (spaces, tabulators, new lines) as a separator. Download PBO_coords.txt and make sure that it is in the same folder that you are currently operating in. Run this code first to see what kind of data you are working with:

with open('PBO_coords.txt') as f:
    data = f.read().split()

#at this point, we have the whole contents of 'PBO_coords.txt' in the variable data and we can close the file, by leaving the 'with' statement

print data

We've wrapped this into the (maybe) odd looking "with" statement. This ensures that the file will be closed at the end of "with". Why is this important? Apart from good practice, write access to a file is granted only once. So if you wanted to add something to a file from this program, but you didn't close the file when you were done and the program kept running, nobody else can write to the file.

Now we are going to organize the data and change it from a normal list into a nested list. To do so, you will have to iterate over all items in data, organize latitude, longitude, and station name into a sub-list, and add this sublist to newlist such that (note that all this can happen outside the with statement, similar to the "print data" above):

print newlist[0]

Should output:

['-174.204754770', '52.209504660', 'AB01']

Instead of:

-174.204754770

Exercise 2 - Dictionaries

Now we're going to introduce another very useful datatype: the dictionary. Dictionaries are similar to lists, but there are a few differences. First, lists are ordered sequences, while dictionaries are unordered sequences. Second, lists are indexed by numbers and dictionaries are indexed with keys. Dictionary keys can be any string or number or more complex datatypes such as datetime objects. Try this code to see how it works:

x = {'a': 1, 'b': 2, 3: 4}
x['a']
x[3]
x[1] #This line won't work
y = {'numbers': [0, 1, 2, 3, 4, 5, 6, 7, 8], 'letters': ['a', 'b', 'c', 'd']}
y['numbers']
y['letters']
y['symbols'] = ['!', '@', '#']
y

Make sure that you understand how this code works and why x[1] doesn't work before you move on.

Deliverable 2

We can use dictionaries to better organize our coordinate data from the first deliverable. Instead of searching for indices of station names to access their coordinates, you can organize your data into a dictionary so that:

$> station_dict['AB01']

Will return:

['-174.204754770', '52.209504660']

This means you can use the station name directly as a key to look up information in your data structure. As the second part of your deliverable, turn all the data from PBO_coords.txt into a dictionary that works like the station_dict in the example above.

Exercise 3 - Functions

A function is a block of code that can be reused to perform a specific task. This may sound similar to iteration, but functions differ in that they may be called at any time during the program, and instead of running multiple times like a loop, they only run once for every time that you call them.

There are built in functions (some of which we have already used) and user defined functions. Here are some of the built-in functions that we have already used:

int()
float()
str()
type()
enumerate()
range()

Built-in functions, like user-defined functions, take in an input and produce an output. The difference is that we do not have to separately define these functions, since they were already written by the creators of Python to solve simple problems.

As you develop larger programs, it is useful to divide a program into user-defined functions. There are several reasons why you should do this:

Let's take a look at an example user-defined function:

def larger(x, y):
    if x > y:
        return x
    elif y > x:
        return y
    else:
        return None

print larger(5, 10)

The return command is defining the output of the program. This program looks for the larger number and returns it as the output.
Now, try using larger(5). It will give you an error because the function is only defined to take two arguments.

Deliverable 3

Turn the code from the second deliverable into a function. The function should be defined as:

def file_to_dict(filename):

The input for the function should be the file name and the output should be the dictionary of the station names and coordinates. Make sure to save this function to a file called stations.py, such that run with BARD_coords2.txt (saved to the same directory as stations.py):

$> import stations
$> station_dict = stations.file_to_dict('BARD_coords2.txt')
$> print station_dict['DIAB']

prints:

[-121.9156, 37.8786]

This time, instead of importing a built-in library, we are importing a user defined module. You can read more about this here. For the rest of the deliverables, we will continue adding functions to stations.py so that we can eventually import a group of tools to analyze coordinate data with only import stations.

Exercise 3 - Multiple functions

It is possible to call other functions within a function. This can be very useful for complex programs. Here's an example program which combines an old function that we used with another function:

def larger(x, y):
    if x > y:
        return x
    else:
        return y

def largest_comparison(numlist):
    for num in range(len(numlist)-1):
        print larger(numlist[num], numlist[num+1])

Deliverable 4

For this exercise, reuse the code from the second deliverable by making a function which counts the number of stations. The function should be defined as:

def number_of_stations(file):

You can read the dictionary documentation here to find an easy way to do this. Again, this function should go into stations.py such that:

$> import stations
$> print stations.number_of_stations('BARD_coords2.txt')
31

Deliverable 5

Now, we're going to write another function which uses code from lab 3 (the program which finds coordinates within a certain range) and integrates it with the second deliverable to calculate all the stations within the geographic coordinates given by the user. The input will be:

def find_stations(dict, lat-min, lat-max, lon-min, lon-max):

And the output will be a list of station names that are within these boundaries. This function should go into stations.py such that:

$> import stations
$> station_dict = stations.file_to_dict('BARD_coords2.txt')
$> stations.find_stations(station_dict, 37, 38, -122, -121)
['DIAB', 'LUTZ', 'MONB', 'MHCB', 'SODB']

rg <at> nmt <dot> edu | Last modified: September 21 2017 03:54.