Assignment 6 - Parsing and Visualizing Data

Due: Saturday, February 15, 2020, at 5pm

You may work alone or with a partner, but you must type up the code yourself. You may also discuss the assignment at a high level with other students. You should list any student with whom you discussed the assignment, and the manner of discussion (high-level, partner, etc.) in a readme.txt file that you include with your submission.

You should submit your assignment as a .zip file on Moodle.

You will work in two different files for this assignment. Additionally, you will need some data files.

  • Problem 1: skeleton code and data file. You should save the code file as shapeParser.py and the data file as shapes.csv, both in a folder with graphics.py.
  • Problem 2: skeleton code and data file. You should save the code file as weatherPlotter.py and the data file as weatherData.csv.

Parts of this assignment:

Note on style:

The following style guidelines are expected moving forward, and will typically constitute 5-10 points of each assignment (out of 100 points).

  • Variable names should be clear and easy to understand, should not start with a capital letter, and should only be a single letter when appropriate (usually for i, j, and k as indices, potentially for x and y as coordinates, and maybe p as a point, c for a circle, r for a rectangle, etc.).
  • It’s good to use empty lines to break code into logical chunks.
  • Comments should be used for anything complex, and typically for chunks of 3-5 lines of code, but not every line.
  • Don’t leave extra print statements in the code, even if you left them commented out.
  • Make sure not to have code that computes the right answer by doing extra work (e.g., leaving a computation in a for loop when it could have occurred after the for loop, only once).

Note: The example triangle-drawing program on page 108 of the textbook demonstrates a great use of empty lines and comments, and has very clear variable names. It is a good model to follow for style.

Problem 1: Parsing a CSV file into shapes

# You should be fully equipped to complete this problem after lesson 15 (Friday Feb. 7).

In this problem, you will complete the implementation of a program that parses a .csv file into a window of shapes. An example is in shapes.csv:

window,800,600

circle,600,200,40,blue
triangle,700,200,700,300,600,100,red
rectangle,50,60,200,400,yellow
square,40,40,30,magenta

circle,60,400,25
triangle,400,200,400,300,300,400
rectangle,770,500,650,250
square,500,400,100

As you can see, most lines of the file contain either the window information or information for a single shape, and a shape may or may not have a color specified. Some lines are empty, and your code should simply ignore them (but not crash when they are encountered).

We talked in class about top-down design. An alternative is bottom-up design. In bottom-up design, you determine the functions you need to complete the smaller-scale tasks, and then determine how to connect them together.

Note: there are useful libraries that can help you parse CSV files, but I do not want you to use them for this assignment. I want to be sure that you can parse the file on your own first.

Part a: complete shape-parsing functions

For the first part of this problem, you should complete the implementations of the four shape-parsing functions:

  • parseCircle
  • parseSquare
  • parseRectangle
  • parseTriangle

Pay careful attention to the expected input types in the documentation for each function. For example, for a circle, note that it takes in a list of strings, and that list should have either three or four values in it:

def parseCircle(vals):
    """
    Creates a Circle object based on the values given in vals.

    Assumes vals is either a list [x,y,r,color] of strings,
    or [x,y,r].

    x: x-coordinate of center point (expect an int in the str)
    y: y-coordinate of center point (expect an int in the str)
    r: radius (expect a float in the str)
    color: optional color (str)
    """
    # TODO
    return Circle(Point(0,0),0) # replace with your code

Part b: putting the pieces together

These functions all need to get used to parse a file into a list of shapes and a GraphWin object. An early part of software design is pseudocode. Pseudocode represents plans for code without having the actual syntax (so no colons, function calls, etc.). The function parseShapesFromFile needs to read in the lines of the CSV file and parse each line (at least, each one that isn’t blank) into a shape. The pseudocode for this function is given to you in comments:

def parseShapesFromFile(filename):
    """
    Opens the file specified by filename for reading, and parses
    the window dimensions and the shapes.

    returns: the Window object and a list of shapes
    """
    # Open the file for reading
    # Specify variables for the window and the shape list
    # Go through each line in the file
        # Skip over any empty lines
        # Split the line into strings on the commas
        # Use the first string in the line to determine which object to create
    # Close the file
    # Return the window and shapes list

Part c: drawing the shapes

One of the beautiful things about the shapes in graphics.py is that they all have a draw method. For a variable shape that represents any type of shape object, you can call shape.draw(win) to draw that shape in the GraphWin object win. This is called polymorphism.

To see this for yourself, you need to add a couple of lines of code to main to actually draw the shapes to the window.

def main():
    # Read in the provided file and parse it into a window and shapes
    filename = "test.csv"
    win, shapes = parseShapesFromFile(filename)

    # Draw each shape (in order) in the window
    pass # TODO: replace with your code

    # Wait to close until the user clicks
    win.getMouse()

Here is the output you should see for the example file:

<image: shapes>

Problem 2: Visualizing weather data

# You should be fully equipped to complete this problem after lesson 15 (Friday Feb. 7).

This problem will require Matplotlib, so make sure to get it if you haven’t already. You can get it from the command prompt (search “cmd” in Windows or “Terminal” on a Mac), with the following command:

pip3 install matplotlib

Part a: parsing the data

I downloaded a bunch of weather data from NOAA’s website. It is provided to you in a CSV file called weatherData.csv.

Disclaimer: All of the data is as-provided by NOAA, except there was no minimum temperature for 4/25/2019. To avoid extra parsing headache on your part, I chose a minimum temperature for that day to be the average of the two days on either side.

Here are the first few lines of the file:

NAME,DATE,PRCP,SNOW,TMAX,TMIN
OWATONNA MN US,1/1/2019,0,0,33,2
OWATONNA MN US,1/2/2019,0,0,13,3
OWATONNA MN US,1/3/2019,0,0,25,13
OWATONNA MN US,1/4/2019,0,0,41,24
OWATONNA MN US,1/5/2019,0,0,43,27
OWATONNA MN US,1/6/2019,0,0,44,26

For the first part of this problem, you should implement the parseData function. This function should grab the date strings and minimum and maximum temperatures (as ints) for each date from the file, and return three lists.

def parseData(filename):
    """
    Opens the CSV file with name filename for reading, and reads in the data.

    filename: string
    returns: three lists:
      - one of dates (strings)
      - one of minimum temps (ints)
      - one of maximum temps (ints),
    """
    dates = []
    minTemps = []
    maxTemps = []

    # TODO: Problem 2a
    # your code here

    return dates, minTemps, maxTemps

Part b: plotting the data

Given the data you’ve parsed out of the file from part a, you should plot the data using Matplotlib. Your plot should have:

  • both the minimum and maximum values in the same plot
  • a title
  • axes labels
  • a legend

Hint: Check out the function plot, which takes arguments such as x and y as lists for the x-coordinates and y-coordinates of the data, and an optional parameter label that is used in the legend.

Here is what it should look like:

<image: plot of temperatures in 2019>

To do this, fill in the function plotData:

def plotData(dates, minTemps, maxTemps):
    """
    Plots both the minimum and maximum temperature for each day
    in the same plot.
    """
    # TODO: Problem 2b
    pass # replace with your code

For this subproblem (and no others), you are encouraged to explore online for help using Matplotlib. This can include the Matplotlib documentation and stack overflow. Just make sure to cite any website (with the full URL) you visit in your readme.txt. Note that you should still only be collaborating closely (e.g., viewing code) with your partner, if you choose to have one.

What you should submit

You should submit a single .zip file on Moodle. It should contain the following files:

  • readme.txt (collaboration statement listing collaborators and form of collaboration, and any websites visited for problem 2b)
  • shapeParser.py (Problem 1)
  • weatherPlotter.py (Problem 2)