Greppo: All you need is 4 minutes to build an Interactive Geospatial Webapp
Sarma Tangirala
Posted on November 30, 2021
Introduction
Looking to build a Geospatial dashboard for your python script? This blog post is for you! Read along for 3 easy steps to get started with Greppo, a python prototyping tool to quickly build interactive Geo-spatial web apps.
For this tutorial we will be building an app that will visualize some Geospatial data from San Francisco. The data lists the public amenities available in the city. We will plot this data and summarize the count of amenities within an area selected by the user using a Bar Chart.
The code used in this tutorial can be found here.
If you’re like me and like to quickly jump to the end of a tutorial and play around with the web app simply,
- Clone this repo.
- Navigate to
Basic-amenities-in-SFO
. - Install greppo via pip
pip install greppo
. - On a console run,
greppo serve app.py
.
Alternatively, here’s a link to a deployed app instance that is currently running if you want to play around hands-free.
3 Easy Steps
Setup Dir
mkdir greppo-quickstart
cd greppo-quickstart
Install Greppo
It is recommended that you install greppo
inside a Python virtual environment. For this tutorial we are going to use virtualenv (see here for other environment managers)
virtualenv ENV
source ENV/bin/activate
pip install greppo
Setup the Python Script
Create an empty python script
touch app.py
Import Greppo
from greppo import app
import geopandas as gpd
First let's import greppo and geopandas. For greppo, app
is the entry point for adding interactive and visual components to your application. With app
we can instruct greppo to add a map layer, or a bar chart, or set up APIs to variables. Geopandas is imported as gpd
by convention to read vector data.
Read in the data using Geopandas
sfo_amenities = gpd.read_file("./SFO_Amenities.geojson")
amenities = list(sfo_amenities['amenity'].unique())
For this tutorial go ahead and download the data from here and here in the Greppo demos github repo (you can download with wget or curl, or simply copy the raw contents via github).
In the snippet above we read the geojson file and get a list of the amenities available using .unique()
.
Setup Base Layer for Map
app.base_layer(
name="CartoDB Light",
visible=True,
url="https://cartodb-basemaps-a.global.ssl.fastly.net/light_all/{z}/{x}/{y}@2x.png",
subdomains=None,
attribution='© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors | Carto Tile',
)
The base layer is the map interface onto which we will project our (computed) data. Here we are using a basic CartoDB Light variant.
Setup the Data as an Overlay Layer
app.overlay_layer(
sfo_amenities,
title="SFO Amenities",
description="Location of some basic amenities in San Francisco",
style={"fillColor": "#F87979"},
visible=True,
)
With the base layer setup from the previous snippet, we now set up the data that will be visualized on the map. This is done with the overlay_layer
API, and the first argument is the geojson file that we read in step 1.
Setup Draw Feature
default_area_selection = gpd.read_file("./SFO_Selection.geojson")
area_selection = app.draw_feature(
name="Draw area selection", features=default_area_selection, geometry=["Polygon"]
)
For this tutorial, to demonstrate the flexibility and power of Greppo, we set up a draw feature that the user can interact with. In this example we read a set of default draw features as a geojson. The default features can be omitted (ie. don’t pass in default_area_selection
).
Here area_selection
is a list of polygons. For interactivity Greppo binds the state of the user interaction to this variable area_selection
. That is, whenever app.py runs or is updated, area_selection
will contain all the polygons as seen on the screen. To be clear, app.py can always assume area_selection will have the data it cares about and can perform computations on that (see next step).
Perform computation on the data
With the variable binding setup in the snippet above, we can now use the polygons from the draw feature to perform some computation,
selected_amenities = sfo_amenities.loc[sfo_amenities.within(
area_selection.at[0, 'geometry'])]
selected_amenities_count_df = selected_amenities['amenity'].value_counts()
In this code snippet we take the first polygon from area_selection
and filter out the counts of amenities within the selected_amenities
data frame, and create a new data frame selected_amenities_count_df
.
Next we get the counts by values from the created data frame as an example of some python processing that is performed in a usual business setting,
selected_amenities_count = []
for amenity in amenities:
if(amenity in selected_amenities_count_df.index):
selected_amenities_count.append(
selected_amenities_count_df[amenity].item())
else:
selected_amenities_count.append(0)
Plotting the Data as a Chart
We are almost done with our app now! With the main parts in the previous snippets out of the way, let’s plot a bar chart of the counts. This is a common scenario where we have some data that we manipulate on the map layer and we want to summarize the data and visualize it.
Let's do that with a bar chart,
app.bar_chart(
name="amenities-sfo-select",
title="Amenities in SFO",
description="The count of the basic amenities within the selected area in SFO.",
x=amenities,
y=selected_amenities_count,
backgroundColor="rgb(200, 50, 150)",
)
Serve the Grepp App :)
With app.py
ready, let’s serve the app with Greppo and look at our output!
Simply run the serve command on the console,
greppo serve app.py
(Note: It will take a few seconds to run if this is the first time you’re prototyping with Greppo because Python is generating cached .pyc
for fast execution)
You should get the following output,
INFO: Started server process [76886]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
Now, head on over to http://0.0.0.0:8080
in your favorite browser and viola!
On the right you should see,
- The base layer.
- The data as an overlay layer.
- A default draw feature on the right.
On the left you should see,
- Some options to change the base layer.
- An on/off toggle for the overlay layer.
- lat/long details of the draw feature as seen on the right.
- A bar chart.
Now go ahead and interact with the map! Edit the existing polygon by hitting the edit button on the toolbar,
which should change to,
When you hit edit the existing polygon will show up with it’s edges,
Go ahead and drag the points around the red dots on the map and hit Save
.
Hit the update button which should now turn red, and note the numbers on the bar chart refresh!
As an exercise, modify the code from step 6 to account for multiple polygons on the draw feature and try combining the values (hint: simply loop through the list of polygons, extract the geojson data and add them up!)
Conclusion
It took us about 4 mins to get started with this simple example and that’s the flexibility of Greppo. Here’s a link to the docs if you’d like to learn more!
Feel free to reach out with questions or feedback!
Happy hacking!
Posted on November 30, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 30, 2021