DEV Community

Cover image for Greppo: All you need is 4 minutes to build an Interactive Geospatial Webapp
Sarma Tangirala
Sarma Tangirala

Posted on

Greppo: All you need is 4 minutes to build an Interactive Geospatial Webapp

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Setup the Python Script

Create an empty python script

touch app.py
Enter fullscreen mode Exit fullscreen mode

Import Greppo

from greppo import app
import geopandas as gpd
Enter fullscreen mode Exit fullscreen mode

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())
Enter fullscreen mode Exit fullscreen mode

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='&copy; <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors | Carto Tile',
)
Enter fullscreen mode Exit fullscreen mode

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,
)
Enter fullscreen mode Exit fullscreen mode

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"]
)
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)",
)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

(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)
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (0)