Lab 3: More Functions and
Drawing with Turtle Graphics
Drawing with Turtle Graphics
If you find typos or problems with the lab instructions, please let us know.
The goal of this exercise is to begin to implement more complex programs and to become familiar with Python’s Turtle package. In particular, you will:
Read data from a (csv) file
Use a loop to process data
Create graphical programs using Python’s Turtle package
Visualize the path and strength of hurricanes
There is both a pair and an individual component of this lab. The individual component will be completed first. You may not start the pair portion until both you and your partner have completed the individual component. When you get to the pair portion, you must use pair programming. Remember that this means two people will work at the same computer, one driver and one navigator. The driver does the typing and using the mouse, while the navigator makes suggestions, points out errors, and helps guide the process. You should switch roles every 15-30 minutes.
Before you begin this lab, you will create an empty (no README, no .gitignore, no license) private github repo for you and your partner to use. Although there are both individual and pair programming exercises, you will still create only one private repository between the two of you. However, your pair will create four Google Colab notebooks:
One notebook each (2 total) for the individual exercises in this lab
Two notebooks for the pair programming exercises
The GitHub repo for your pair should be named spis23-lab03-Felix-Ryan (but with your first names instead of Felix and Ryan). Unlike the previous lab, lab03 comes with some starter code and data files, so we must create this repo absolutely empty: do not check the "Add a README file" box.
Here are the full instructions:
Go to the "Repositories" tab in the SPIS 2023 GitHub organization by clicking here: https://github.com/orgs/ucsd-cse-spis-2023/repositories
Click "New Repository"
In the "Repository name" text box, enter spis23-lab03-Name1-Name2, where:
Name1 is the first pair partner’s preferred first name
Name2 is the second pair partner’s preferred first name
Be sure that "Private" is checked (not "Public")
Do not check the "Add a README file" box
Click the "Create repository" box at the bottom-right
After you create the new repository, you will see a new screen with various ways to set up your new repo. If you scroll down on the screen, you will see an option "... or import code from another repository", as shown in the image below. Cick on the grey "Import code" button.
Please enter this URL, as shown, into the box under "Your old repository's clone URL" and then click Begin Import.
https://github.com/ucsd-cse-spis-2023/lab03starter.git
It may take a few minutes, but when you return to the repo on GitHub you should see some starter code, as shown at right. GitHub will also send you an email when it has finished importing the repo.
Next, add you pair partner's GitHub account to the new repo so that you both can work on it. See the instructions in Part 2 here: Google Colab and GitHub.
Verify that your partner(s) can access your GitHub repo before continuing; the GitHub repo should be set up so that both members of your GitHub team can access it, but be sure before you continue. If you have any issues with this please see a mentor.
Next, you will complete the individual portion of your assignment, each adding your Colab notebook to this shared repo.
This first part of the lab is individual. However, we want you to work synchronously with your partner and support them as they go through these exercises. For this individual portion, each pair partner will create and work in a Google Colab notebook called lab03Warmup_Name.ipynb (where Name is the first name of the pair partner). For example, if the students are named Felix and Ryan, then Felix should create and work in a Google Colab notebook called lab03Warmup_Felix.ipynb, and Ryan should create and work in a Google Colab notebook called lab03Warmup_Ryan.ipynb.
To warm up with the Turtle, you will use the Turtle to draw your first initial (the first letter of your first name) on the screen.
You should complete the entirety of step 1.1 and 1.2 individually. You may talk to your partner and have them help you, or give help to your partner, but you should try to do as much of it on your own as possible, and all the code you write should be done individually.
At the top of your notebook place a text cell with your name and a description of what this notebook will do (a program to draw the first letter of your name).
In order to work with the Turtle, you will first need to install a version of the Turtle library specifically for Google Colab notebooks. Create a new code cell and paste the following line:
!pip install ColabTurtlePlus
which is not actually Python code, but is a special syntax to request Colab to install the library that you need. Click the play button to run the command, which will take several seconds to complete.
We still need to import the turtle module. Do this by adding a new code cell and putting the line:
from ColabTurtlePlus.Turtle import *
into the new cell. This above line tells Python about the turtle library and allows you to call its functions. After you execute this cell, a message will be displayed reminding us to call the clearscreen() function before any other function calls in a cell. This will wipe the Canvas clean; otherwise we would be drawing on top of the old output.
If you leave your notebook alone for a while, a message will pop up that you need to reconnect. Once you reconnect, you will need to execute all of the cells again, including installing ColabTurtlePlus and the import code above.
Next, let’s write a simple function that uses the Turtle package to draw a shape. Copy the following code into a new code cell in your notebook.
def draw_picture(the_turtle):
''' Draw a simple picture using a turtle '''
the_turtle.forward(100)
the_turtle.left(90)
the_turtle.forward(100)
the_turtle.left(90)
the_turtle.forward(100)
the_turtle.left(90)
the_turtle.forward(100)
the_turtle.left(90)
my_turtle = Turtle() # Create a new Turtle object
my_turtle.speed(5)
draw_picture(my_turtle) # make the new Turtle draw the shape
What happens when you run this cell?
If you find that the turtle is moving too fast or too slow, trying altering the argument to the speed method above. You can choose an integer between 1 (slowest) and 13 (fastest).
Modify the function in various ways to see what happens:
Change the number in the first the_turtle.forward() call in the draw_picture function. What’s the role of the number?
Change the values in the calls to the_turtle.left(). What units are being used?
You might notice that there seem to be two names “turtle” in the code above, plus Turtle() with a capital letter, and () after it. What’s going on?!
The Turtle library works a little differently than other libraries we’ve looked at so far, in that it uses a style of coding called “Object Oriented Programming”. You’ll learn much more about objects in CSE 8A or CSE 11, but for now you can think of objects as complex types of data that also have built-in functions associated with them.
Turtle() is a special function (called a constructor) that creates a new Turtle object. The constructor Turtle() is part of the Turtle module that we imported with: from ColabTurtlePlus.Turtle import *
When we write my_turtle = Turtle() the right hand side creates a new Turtle object, and the variable my_turtle becomes a reference to that object.
When we make the function call draw_picture(my_turtle) the formal parameter the_turtle in the function definition (which starts with def draw_picture(the_turtle):) gets the value of the variable my_turtle.
Therefore in the code above, the variables my_turtle and the_turtle both refer to the same Turtle object. If that's clear, great—but if not, read through the code and this explanation a few times until that sinks in.
Understanding this point—the idea that the formal parameter of a function gets the value of the argument in the function call—is a big deal in terms of understanding how to work with functions in Python, so it's worth asking for help from your mentor if this is a sticking point for you.
In the example above, my_turtle and the_turtle both referred to the same Turtle object. However, it is possible to have more than one Turtle object in a given Python program.
For example, try adding the following code to the end of the cell you've been working on. Because there are now three different calls to Turtle() (the two new ones plus the original my_turtle = Turtle()) you now have three entirely different Turtle objects. They can move around the screen and draw things independently of each other.
Try running the code. Can you explain what’s happening? With your pair partner, take turns explaining what's going on to one another. You could also try modifying the code to see if you can predict what will happen.
Note that you can optionally add turtle1.speed(1) after you create turtle1, and do the same for turtle2, if you want to see things more clearly. Each turtle may have it's own different speed.
turtle1 = Turtle()
turtle2 = Turtle()
turtle1.setpos(-50, -50)
turtle2.setpos(200, 100)
turtle1.forward(100)
turtle2.left(90)
turtle2.forward(100)
In the code above you noticed that by calling Turtle() three times we got three Turtles that we could control independently. However, if you know you only want to use one Turtle, Python will provide an “anonymous Turtle” that you can control without actually creating explicitly. So you might sometimes see lines of code that look like
forward(100)
The forward call will control the first Turtle created. Python will always create this first Turtle, even if you do not include any call to Turtle().
It’s a good idea to check out the library documentation (a.k.a. reference manual, API docs, etc.) when you’re learning how to use a new library (aka set of methods). For common Python libraries, documentation will often be hosted on docs.python.org. You can click here for the documentation for this specific version of the Colab Turtle library on the author's website: Documentation for ColabTurtlePlus v2.0.1
Here's the entry in the documentation for the function that lets us move forward:
forward(units) | fd(units)
Moves the turtle in the direction it is facing, by units pixels
By the way, the vertical bar "|" above is used to denote an alternative. So that means that there are two different aliases or names for the forward function: calling forward(units) or fd(units) will do exactly the same thing.
You can browse the documentation and learn about many, many other things you can do with your turtles, including changing color, changing the shape, etc.
Now is a good time to make sure you’ve got helpful comments in your notebook and that you’ve saved it (Google Colab should save it automatically).
Commit your code back to GitHub using part 4 of these instructions: Google Colab and GitHub
Create a new file named drawLetter_YourFirstName.py. In that file, write the following method:
draw_A(the_turtle)
Note that the name of this method should correspond to the letter you are drawing. So if my name is Chris, my function would be named draw_C. The parameter to this method, the_turtle, is the turtle you should use to draw the letter. Note: you don't want to include any calls to clearscreen() in your function because you only want to clear the canvas at the beginning of each cell and not during a function call.
Feel free to be creative here. Right now, you can draw the letter any size, using any style. You will probably find the functions penup and pendown useful, but check the documentation for other functions that will allow you to change the style of the lines your turtle draws. Also, if there are any curves in your letter, then be sure to check out the documentation of the circle(radius, extent) function (the steps parameter is not rquired).
Test your function to see if it works by creating at least two different Turtles, moving one of these Turtles away from its default position (you probably want to lift the pen before moving the Turtle), and then calling your draw_A function with each Turtle. You should see two letters drawn, one drawn by each Turtle (one after the other). Does the output look good? Do both the Turtles draw?
If there are bugs in your code (we’d be surprised if there weren’t!) fix them before moving on.
It's better to only do GitHub commits for working notebooks. (If you need to commit non-working code to your repo, be sure it has an appropriate comment on it.)
Also: be careful not to move your turtle off the screen, because you won't able to see it drawing!
At this point you are almost finished with the individual portion and ready to commit and push your code so far. Here’s a checklist to make sure you haven’t forgotten anything:
Do you have a comment at the top of your files?
Do you have a draw function for your first initial?
Does this function have one parameter: a turtle?
Does this function have a reasonable docstring (recall from class what a docstring is)
Did you test your function with at least two Turtles to make sure it’s working correctly? (And is it?) If so, you are ready to submit!
Make a commit to GitHub when you have a working version (these instructions explain how)
At this point you are done with the individual portion. If your partner is not yet done, DO NOT CONTINUE. Here are some things you can do while you wait for your partner:
Work on APS
View and respond to the enrichment video
Make your letter prettier/more interesting
Make more functions to draw more letters (try drawing out your whole name!)
STOP! Do not start on this part of the lab until BOTH partners have completed the individual portion. When you do start, make sure you use pair programming.
Discuss the following questions with your partner, then put your joint answers into comments at the top of a new notebook named lab03Letters_Name1_Name2.ipynb.
What is the “anonymous turtle”?
In the code below, what is the difference between my_turtle and Turtle()?
my_turtle = Turtle()
draw_picture(my_turtle)
Imagine that I have a turtle in a variable named my_turtle. What line of code will change that turtle’s y-position to 100?
Choose one of your draw_A (or whatever letter you used) functions and copy it into your lab03Letters_pair.ipynb notebook. Then, modify the function as follows:
Add another parameter to your draw_A function: draw_A(the_turtle, size)
size will determine the size of your letter.
Modify the code in the method so that it respects the size parameter. You are free to use any interpretation of size that you wish, but your letter must be drawn in different sizes for different values of that parameter. Make sure you modify the docstring for your modified function so that it accurately reflects what this new version of the function does.
Finally, test your new function to make sure that it respects the size parameter. Fix any bugs you find, then save a copy in GitHub (that is, commit).
Switch driver and navigator if you have not yet done so.
This part of the assignment is based on a SIGCSE Nifty Assignment.
In this part, you and your partner will use the Turtle to animate the paths of some real hurricanes! Your goal is to build a program that functions like the one in this video. Here are the details:
Navigate to your pair's repo on GitHub, and click on the irma.ipynb to open the notebook. Then, click on the "Open in Colab" button to open the starter file irma.ipynb in Colab. You won't be able to edit this notebook directly. Instead create a copy (click on the File menu and then click "Open a copy in Drive") and name it lab03irma_Name1_Name2.ipynb
In the irma_setup() function, the following are done for you:
Creating the screen and turtle
The turtle’s shape is changed to that of a hurricane
Loading a background image of the Atlantic
Setting the world coordinates of the screen to match the latitude and longitude on the map
Do not change the irma_setup() function!
You will add your code into the function irma(). Read the comments and the code in that function and make sure you understand what it does so far. Try moving the turtle (t) around and see it animate. Notice the coordinates of the world have been changed from their default. The x values in the new coordinate system range from -90 to -17.66 and the y values range from 0 to 45. Since the Turtle starts at (0,0) you cannot see it. Try moving it to a location where you can see it in the new coordinate frame and making it move.
Remember, before you can run any code, you must execute the first six cells in order. These cells install the Turtle library we're using, fetch the images and data, import the necessary libraries, customize the output images, define variations on the Turtle classes for this lab, and define the irma_setup() function described above.
You will also notice that this starter code uses a file named irma.csv in the data directory. This data was scraped from Weather Underground, last accessed 9/14/2017. This file contains data about hurricane Irma. Each line contains 6 columns separated by commas (thus the .csv file extension). The file can be opened directly in Excel or another spreadsheet program for a columnar view. The first line of the file describes what each column is. Here are the first 3 lines of the file, separated into their columns:
Date Time Lat Lon Wind Pressure
30-Aug 15:00 GMT 16.4 -30.3 50 1004
30-Aug 21:00 GMT 16.4 -31.2 60 1001
The only columns relevant to your code are Lat (the latitude), Lon (the longitude), and Wind (the wind speed in miles per hour). Carefully check out the Lon (longitude) and Lat (latitude) values -- which value correlates with x and which value correlates with y?
You might have to run the turtle code several times before seeing correct output, as the Repl output screen sometimes freezes or is laggy.
Using the data in irma.csv, your irma function must show hurricane Irma’s path. Your solution should look like the video and must include the following:
Correctly show each point in the data file (together with lines between each point)
At each point, if the storm has hurricane strength winds, you must write what category the storm is, otherwise, draw no text. You can use Google to find the wind speeds for each category of hurricane.
Color code the hurricane strength:
Red for Category 5
Orange for Category 4
Yellow for Category 3
Green for Category 2
Blue for Category 1
White if not hurricane strength
The thickness of the line should change in proportion to the hurricane category.
Check out the video example listed earlier if you're wondering how this should look like.
Notice that the starter code already uses the csv package to read the lines from the data file. The csv package is already imported at the top of the irma.py file, and we’ve provided some comments and code to help you understand how you can read the lines and get the data out of the lines in the file. Make sure you understand how this works before you attempt to change the code. If you have questions, ask a mentor.
We have provided some comments in the starter code to help you out, but this is a more open-ended task than you’ve done in the past. Make a plan with your partner before you attempt to start coding
Make sure you run your code, and look at the data, to test your code.
Ensure the following:
Does your line start in the same position as the demo? Remember, you need to move the turtle to the starting latitude/longitude with the pen UP so you don’t draw a line that’s not part of the hurricane data.
Do the number and order of 1s, 2s, 3s, etc, on your path as well as the color of the points in your path, match the demo?
Does the path go in the same direction as in the demo?
When you run your code on other data files, do you get the path you’d expect (after looking at the data)? You can change which file is opened inside of the irma() function (look for hurricaneFile). The starter code has copied the entire data directory of CSVs from the starter repo into the /content/ directory in the Colab notebook's filesystem.
Once you’ve got your hurricane tracker working, make sure of the following:
Do you have your names and a comment at the top of each file?
Do you have docstrings for each function you wrote?
Did you use meaningful variable names?
Did you use appropriate commenting in your code when something might be unclear to the reader?
Once you can answer yes to all of the following make sure that you save ALL of your files from this lab (the files from the individual part (i.e. 2 between the two of you) and the two files you created for the pair part) to your repo, then follow the instructions described in Part 4 here to save each of your notebook sto your pair's GitHub repo.
Then you are done! But of course, you’re never done, so keep working on creative extensions of your own!