Prac05: Grids and Files
Last updated on 2024-10-02 | Edit this page
Overview
Questions
- How can we make data persistent - so that it exists before and/or after our programs run? (spoiler: it’s files)
- What are the methods/functions we need to use to work with files?
- How can list comprehensions simplify our code?
- How can we work with 2D arrays to create simulations?
Objectives
- Understand and use text files to store and load data
- Apply list comprehensions to simplify code
- Develop simple grid-based simulations using 2-dimensional arrays: fire modelling, Game of Life
- Experiment with parameters to investigate how they alter the outcomes of simulations
Introduction
In this practical you will read and write data using text files. You will also work with some grid-based algorithms – testing out different values to see how their parameters affect outcomes. We will also look at using list comprehensions to simplify our code.
Activity 1 - Reading a CSV File
Type in the following code, weather.py, for displaying the weather stored in a file:
PYTHON
#
# weather.py: Print min and max temps from a file
# (source: http://www.bom.gov.au/climate/)
import matplotlib.pyplot as plt
fileobj = open(‘marchweather.csv’, ‘r’)
# add file reading code here
line1 = ??
line2 = ??
fileobj.close()
mins = # add splitting code here, each stirng value will need to be coverted to float
maxs = # add splitting code here
dates = range(1,32)
plt.plot(dates, mins, dates, maxs)
plt.show()
Modify the code to read the data from the marchweather.csv file – available on Blackboard and here. You should download it to your Prac05 directory, look at its contents and format, then modify the code accordingly. Hint: look at split method, and list comprehensions in lecture slides.
Activity 2 - Reading another CSV file
This time, go to the Bureau of Meteorology site and download the full list of weather data for March. This time we will plot the min, max, 9am and 3pm temperatures… http://www.bom.gov.au/climate/dwo/202303/html/IDCJDW6111.202303.shtml
You can change the year and month by changing “202303” to another year+month (in two places)
Save the data by scrolling down to the “Other Formats” section and
right-clicking on the plain text version. Save it to your
Desktop
or Prac05
directory as
marchweatherfull.csv
. If you open it in vim you can see all
the data, but there are headers describing the data that we don’t need
to read in. Remove the header lines at the top of the file using
dd
(in vim’s command mode) and then save the file. You now
have your dataset.
Write a new program, marchweather2.py
to read in the
values and plot them. You will need to pick out columns from each line
you read in from the file. First split it into a list, then pick out the
values and assign them to the min, max, nine and three lists/arrays.
The code below will help start you off:
PYTHON
fileobj = open(‘marchweatherfull.csv’, ‘r’)
data = fileobj.readlines()
fileobj.close()
mins = [] # make an empty list to store the mins column on each line of the file
# note that each entry will need to be converted to a float
# do the same for maxs, nines and threes
for line in data:
splitline = line.split(‘,’)
mins.append(splitline[2])
maxs.append(splitline[3])
nines.append(splitline[10])
threes.append(splitline[16])
Then add a plt.plot()
call to plot lines for mins, maxs,
nines and threes. Make sure you set up the x values (dates) as in
Activity 1.
Activity 3 - Writing to a CSV file
Take your marchweather2.py
and modify it to write the
four lists of values into a csv file, four values per line. You may have
to convert them to strings when building each line to write.
Activity 4 - List comprehensions
Using list comprehensions can reduce and simplify your code. In the lecture, we saw some examples of using list comprehensions. Using the lecture slides as a guide, write code to do the following using both loops and list comprehensions for each:
- Make a list
numbers
with the numbers from 1 to 5 - Write a function
triple(n)
and use it to triple each number in numbers - Write code to read in a string and extract all of the numbers (Hint:
isdigit()
) - Write code to capitalise the first letter of each word in a list of words (Hint:you can use use “+” to put the word back together)
You may find places in the previous activities where list comprehensions could have been used.
Activity 5 - Heat Diffusion
Download and run heat.py
, available in the practical
area on Blackboard and here. There have been
some changes made over time to improve readability
PYTHON
import numpy as np
import matplotlib.pyplot as plt
size = 20
currg = np.zeros((size,size))
print(currg)
for i in range(size):
currg[i,0] = 10
nextg = np.zeros((size,size))
for timestep in range(5):
for r in range(1, size-1):
for c in range (1, size-1 ):
### HIGHLIGHTED CODE
nextg[r,c] = (currg[r-1,c-1]*0.1 + currg[r-1,c]*0.1
+ currg[r-1,c+1]*0.1 + currg[r,c-1]*0.1
+ currg[r,c]*0.2 + currg[r,c+1]*0.1
+ currg[r+1,c-1]*0.1 + currg[r+1,c]*0.1
+ currg[r+1,c+1]*0.1)
### HIGHLIGHTED CODE
for i in range(size):
nextg[i,0] = 10
print("Time step: ", timestep)
print(nextg)
currg = nextg.copy()
plt.imshow(currg, cmap=plt.cm.hot)
plt.show()
Make the following modifications to the code. The first improves readability, the second gives the user more information about the progression of the heat diffusion. Make sure you understand what the code does. Re-run the program after each change to see that it still works.
- Modify the program to replace the highlighted code with the more
readable code below:
nextg[r,c] = 0.1 * (currg[r-1:r+2,c-1:c+2].sum() + currg[r,c])
- Modify the code to plot the current grid at the end of each timestep
Activity 6 - Heat Diffusion with Functions
Our heat.py
program has an ugly line of code to
calculate the next values for each cell - TMI (too much information). We
modified it in the previous activity to have cleaner code, but can make
the code even more readable by hiding these ugly details in a
function.
Copy heat.py
to heatfun.py
and create a
function calcheat(subarray)
to factor this calculation out.
You can then call the function as:
The lines to put in the function is:
This apporach passes only the 3x3 subgrid of the
array into the function - protecting the rest of the array from
accidental changes. We also return
the result - making it
clearer what changes are happening to the array.
Activity 7 - Reading (yet another) CSV file
Copy your heat.py
and call the copy
heatsource.py
. This time we are going to read a heat source
in from a file.
Create a file heatsource.csv to
hold the heatsource:
(note, you can copy a line using yy
and p
in vim - yank and paste)
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
10,0,0,0,0,0,0,0,0,0
In our original program we had two loops to set up and maintain the heat source:
for i in range (size):
currg[i,0]=10
This could also have been done in a more Pythonic way with:
currg[:,0] = 10
We are going to replace those lines with code to read the heat source from our file and update in each loop from our new h array to maintain the heat source.
Replace the first heat source code instance with the following to read data from a file:
PYTHON
# create heat source
hlist = []
fileobj = open('heatsource.csv','r')
for line in fileobj:
line_s = line.strip()
ints = [float(x) for x in line_s.split(',')] # list comprehension
hlist.append(ints)
fileobj.close()
harray = np.array(hlist) # heat source array to maintain the heat generation in the simulation
currg = harray.copy()
And in the loop the heat source needs to be updated using the new h array…
PYTHON
# Calculate heat diffusion
for timestep in range(100):
for r in range(1,size-1):
for c in range (1, size-1):
nextg[r,c]=calcheat(curr[r-1:r+2,c-1:c+2]) # heat diffusion
for r in range(size):
for c in range(size):
if harray[r,c] > nextg[r,c]: # maintaining heat source
nextg[r,c] = harray[r,c]
currg = nextg.copy()
Your code should now output the same information as it did before – test it and see.
In a similar way to list comprehensions, we can simplify the four
lines of code above to one line using
np.where(harray > nextg, harray, nextg)
. This will
overwrite values in nextg where the value in harray is larger:
Copy heatsource.csv
to heatsource2.csv
,
change the values in heatsource2.csv
, and make the
necessary changes to heatsource.py
to see how it changes
the output of the program.
Activity 8 - Fireplan
Access the Interactivate app at: http://www.shodor.org/interactivate/activities/FireAssessment/
Explore the use of the app and how it is making use of the grid and neighbours. Also look at the use of graphics to represent the different states of a cell. What different graphics are used for the states and what do they represent?
Activity 9 - Game of Life
Have a read of https://web.stanford.edu/class/sts129/Alife/html/Life.htm (a very old-school web page!) to see how the Game of Life works.
Use your mouse to enter some life into the Game of Life Simulator https://playgameoflife.com/ , then click run to see the outcomes. How long does your population survive? Try some of the shapes from the Stanford website to see how they behave.
We won’t be implementing the Game of Life algorithm, but you could try writing some pseudocode for how you might approach it, or look online for some descriptions of algorithms.
Submission
Update the README file to include all files created in this practical.
All of your work for this week’s practical should be submitted via Blackboard using the Practical 05 link. This should be done as a single “zipped” file. Submit the resulting file through Blackboard. (refer to Practical 00 or 01 for instructions on zipping files.
There are no direct marks for these submissions, but they may be taken into account when finalising your mark for the unit. Go to the Assessment link on Blackboard and click on Practical 05 for the submission page.
And that’s the end of Practical 05!
Key Points
- Files can provide persistent data that exists before and/or after our programs run? These files can also be used for sharing information, and allow more complex problems
- We need to open files to have an object to represent the state of the files, and let us access input/output (I/O) functions. Files should be closed when we’ve finished reading/writing data.
- Text files are strings, with three read functions - read(), readline(), readlines() and one write function - write()
- See https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files for more about files
- We can reduce the number of lines of code using list comprehensions - creating a new list from an
- existing list/sequence + transformation + conditions.
- Gridding algorithms allow us to use 2D+ arrays to create simulations - we just need to define how to calculate the next value in each cell on each timestep
Reflection
- Knowledge: What are the three different read methods we can use on a file? What is the difference between them?
- Comprehension: What does the line file2.write(…) do in Activity 4?
-
Application: Given the Game of Life rules, what
would happen to the centre cell in the following cases:
-
Analysis: What variation of “neighbours” does
heatsource.py
use? How would the code change if it were to use the other neighbour approach? - Synthesis: How would you create a heat source input file with a 4x4 heat source in the centre of the 10x10 grid?
-
Evaluation: Name two advantages to reading initial
data from a file as in the updated
heatsource.py
.
Challenge
For those who want to explore a bit more of the topics covered in this practical. Note that the challenges are not assessed but may form part of the prac tests or exam.
- Follow the workflow from Activity 3 to process and plot February weather data.
- For students based in Australia, find another country’s weather data sharing site, or an international one
- If you are not in Australia, see if you can find you local government’s weather data sharing site.
- Find and download some Game of Life* code and get it running.