Day 3: Working with Data and Writing Readable Code#
Note
Do not use AI tools to complete the exercises. The goal is to learn how to write code yourself, not to rely on AI tools.
Learning Goals#
Use a clear and consistent directory structure in your project.
Modularize your code for better reusability.
Explain the differences between inheritance and composition in object-oriented programming.
Name classes, functions, and variables in a way that makes their purpose clear to enhance code readability.
Create static and interactive maps in Python.
(Merge code from another branch into yours and resolve possible merge conflicts.)
Coding Goals#
We want to analyze pedestrian routes in regard to solar exposure and length in Heidelberg, generated by openrouteservice (ORS). This specialized version of openrouteservice considers the solar exposure of roads throughout the day and takes it into account when calculating the route. The routes were generated for different times of the day and different destinations, such as schools or workplaces.
To analyze the routes, we need to write a class that can read the ORS response and calculate metrics for the routes. We will try to reuse code from the Line
class we created on day 2. The data is available via heibox (see below).
Preparation#
Pull the latest changes from the main branch of the Gitlab repository https://courses.gistools.geog.uni-heidelberg.de/advancedgeoscripting/advanced-geoscripting to your local repository:
git checkout main
git pull origin main
If you have local changes in your own branch that you want to keep, create commits. Otherwise, you may use git stash
to temporarily remove your local changes.
Create a new branch from the main branch, using your name and the suffix
_day3
for the branch name (for example: lisa_day3).Download the generated routes from heiBOX: https://heibox.uni-heidelberg.de/f/5c03a0175317493a96f1/?dl=1 and store them in the directory
./data
in your repository.
Exercises#
First, take a look at the content of the ORS response. Open the file
data/HEAL_routes_170/1pm/routes_heal_1_bus.geojson
in the IDE. Find the following information in the file and its name. Extract the data using Python:The coordinates of the route as a list.
The length of the route.
The duration of the route.
The route ID from the file name.
The destination type from the file name.
The time of day from the file name.
Since it is very cumbersome to extract the information from a dictionary, we will write a Route
class that extracts and stores all relevant information.
Write a
Route
class to handle the route data according to the specifications below.A
Route
object should be created by giving a path of the geojson file, e.g.route = Route("data/route_school_morning.geojson")
The class should extract the following information from the file and store it as attributes in the class: -
id
: The ID of the route from the file name.
-destination_type
: The type of destination (e.g., “school”, “work”, etc.) from the file name.
-time_of_day
: The time of day when the route was generated, from the file name.
-coordinates
: A list of tuples containing the coordinates of the route.The class should contain the following methods from the
Line
class from day 2:
-length
: A method that calculates the length of the route using theLine
class from day 1.
-slopes
: A method that calculates the slopes of the route segments using theLine
class from day 1.Think about how we could build a
Route
class, so that it takes advantage of the methods we need from the existingLine
class. We’ll discuss this in the group.Implement a basic version of the
Route
class that extracts the required attributes from the file name and stores the geometry of the route.Check if the
length()
method of theLine
class works for theRoute
class. Write a test that uses the distance calculated by openrouteservice as a reference value.Add a method
convert_coordinates()
that converts the coordinates from WGS84 to UTM coordinates (for Heidelberg, use EPSG:25832).Push your changes to Gitlab and create a merge request.
Bonus#
Write a method called
plot()
that plots the route on a static image with a basemap. Tip: Usegeopandas
andcontextily
for this.Write a method called
explore()
that creates an interactive map of the route using theexplore
method of GeoPandas.Write a method called
as_dataframe()
that converts the route to a GeoDataFrame.Write a method called
get_solar_exposure
which extracts the solar exposure index along the route from thevalues
section of the ORS response. It should return a GeoDataFrame with the solar exposure index values for each segment of the route. The segments should be defined asLineString
geometries.
Explanation for the values
section in the ORS response:
First number: Start node
Second number: End node
Third number: Solar exposure index value from start node to end node
Value range: 0 (no sun) - 100 (all sun)
Write a method that calculates the mean solar exposure index of the route. It should be a weighted mean depending on the length of the route segments.