Welcome to the Geonotebook

GeoNotebook is an application that provides client/server enviroment with inteactive visualization and analysis capabilities using Jupyter notebook, GeoJS and other open source tools.

The example notesbooks in this directory will walk you through several of the features that the geonotebook plugin to Jupyter makes available. The first thing to know about is...

The geonotebook object

The M object is inserted into the kernel automatically once the notebook is started. This object lives inside the Python kernel's namespace and communicates information to (and receives information from) the GeoJS map. Note that nothing has been imported, but the M variable is still available.

Note: If you are viewing a static version of this notebook you will NOT see the GeoJS map that is dynamically added to a running notebook. Please see this Screen shot to get a sense of the running interface.


In [ ]:
M

Set the map's center

The M object exposes a number of different functions for interacting with the map (which should be located to the right of standard jupyter python cells).

Executing the following cell should set the center of the map to New York State.


In [ ]:
# set_center's arguments are longitude, latitude, and zoom level
M.set_center(-74, 43, 6)

What just happened?

It is important to understand that M.set_center(...) is a Python statement being made inside the Python kernel. It is using a remote procedure call to change the javascript map's location.

The standard Jupyter notebook has three components, (1) the client that makes up the notebook cells, (2) a web server that lists notebook files, directories and serves notebook assets like HTML and CSS (3) a kernel that executes commands in the chosen language (in our case Python).

When you executed the previous cell the string "M.set_center(-74, 43, 6)" was transmitted over a web socket to the webserver, then proxied through ZeroMQ to the IPykernel where it was evaluated as a Python expression. This is the standard way in which Jupyter notebook takes code from a web browser, and executes it in an interactive shell (kernel). M is an object in the kernel, and it has a function set_center. That function executed and returned a promise, which is why you see something in the cell output like <promise.promise.Promise at 0x7f567dd8f290>

While the set_center function returns a promise, it also has a side effect. This side effect uses a custom jupyter communication channel (or 'Comm') to tell the map to change its view port so the center is at (in this case) -74.0 latitude, 43.0 longitude, with a zoom level of 6.

The importaint take away here is this:

We executed a Python statement which changed the state of the GeoJS Map. 

As we work through these examples we'll see lots of examples of how the Python kernel can interact with the map and vice-versa.

Widget example

One question you may immediately ask yourself is, why not have the notebook cell talk to the map directly? Why get python involved at all? Well, because M.set_center is just a Python function, it can do things like leverage the existing widget extension to the notebook.

First you must ensure that ipywidgets extension is installed. If you are running from a virtual environment the following commands should suffice:


In [ ]:
!pip install ipywidgets
!jupyter nbextension enable --py widgetsnbextension --sys-prefix

If you are not running in a virtual environment (e.g. you are running with your globally installed python), you will need to install the ipywidgets plugin with your system's package manager. For more instructions check out the ipywidgets user guide


In [ ]:
from ipywidgets import interact
import ipywidgets as widgets

def map_widgets(lat=0.0, lon=0.0, zoom=4):
  M.set_center(lon, lat, zoom)
  
interact(map_widgets, lat=(-90.0, 90.0), lon=(-180.0, 180.0), zoom=(1, 9))

Annotations

In addition to supporting Python to Map communications, Geonotebook allows objects and events on the map to communicate back to the Python kernel. One of the primary ways in which this is used is through geonotebook annotations.

On the toolbar, next to the "CellToolbar" button, there should be three additional buttons with a circle, square and a polygon. Hovering over each of these reveals that they can be used to start a point, rectangle or polygon annotation.

Point annotations

Try clicking on the circle icon. Notice that the cursor, when it hovers over the map, is now a cross rather than an arrow. Click on the map and a circle annotation should appear.

Rectangle Annotations

Try clicking on the square icon. If you click on the map and hold down the left mouse button, then drag the mouse and release the left mouse button you should be able to create a rectangular annotation.

Polygon annotations

Try clicking on the polygon icon. Single click on a series of points to begin creating a polygon annotation. Double click on a point and the final segment will be added completing the annotation.

Annotations are made available on a special layer under M.layers


In [ ]:
M.layers.annotation

Each of the types of annotations are available under 'points', 'rectangles', and 'polygons' attributes on the AnnotationLayer object

Note Please make sure you have at least one of each annotation on the map


In [ ]:
M.layers.annotation.points

In [ ]:
M.layers.annotation.rectangles

In [ ]:
M.layers.annotation.polygons

Annotations inherit from shapely geometries, this means they support a wide range of spatial functions.


In [ ]:
p = M.layers.annotation.polygons[0]
p

You can get a list of coordinates for the polygon expressed in latitude and longitude


In [ ]:
# List the exterior coordinates of the annotation
# Expressed in latitude and longitude point pairs
list(p.exterior.coords)

Other properties like 'centroid' and 'area' are also available, keeping in mind that all coordinates are measured in latitude/longitude. This means properties like 'area' will not have much meaning. You can look at Shapely's transform method for information on how to translate these into to something more useful


In [ ]:
list(p.centroid.coords)

Here is an example of using shapely's transform method to convert coordinates from latitude/longitude (EPSG:4326) to Albers equal area (AEA). The resulting object gives area in units of meters squared


In [ ]:
import pyproj
import shapely.ops as ops
from functools import partial

project = partial(pyproj.transform,
                  pyproj.Proj(init='EPSG:4326'), 
                  pyproj.Proj(proj='aea',
                    lat1=p.bounds[1],
                    lat2=p.bounds[3]))

ops.transform(project, p).area

Wrapping up

These are some of the simplest examples of the functionality that the geonotebook offers. In subsequent example notebooks we'll look at loading raster datasets, and collections of raster datasets on the map, using annotations to mark regions of interest, and comparing those regions overt time using familar tools in the pydata stack like numpy and matplotlib