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...
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
In [ ]:# set_center's arguments are longitude, latitude, and zoom level M.set_center(-74, 43, 6)
It is important to understand that
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>
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.
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))
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.
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.
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.
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
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
In [ ]:p = M.layers.annotation.polygons 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, lat2=p.bounds)) ops.transform(project, p).area
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