diff --git a/workshop/jupyter/content/notebooks/07-visualization.ipynb b/workshop/jupyter/content/notebooks/07-visualization.ipynb index b5927d4..eac2594 100644 --- a/workshop/jupyter/content/notebooks/07-visualization.ipynb +++ b/workshop/jupyter/content/notebooks/07-visualization.ipynb @@ -8,10 +8,10 @@ "When it comes to visualizing geospatial data with/on maps with Python, a great number of tools and techniques\n", "are available. In this lesson we will explore several of these:\n", "\n", - "* [Folium](https://github.com/python-visualization/folium)\n", - "* [ipyleaflet](https://ipyleaflet.readthedocs.io)\n", - "* [Bokeh](https://bokeh.pydata.org)\n", - "* [pydeck](https://pydeck.gl) - optional\n" + "* [Folium](#Folium)\n", + "* [ipyleaflet](#ipyleaflet)\n", + "* [Bokeh](#Bokeh)\n", + "* [pydeck](#pydeck)\n" ] }, { @@ -21,14 +21,13 @@ "## Folium\n", "Whenever you visit a website that has some kind of interactive map, it\n", "is quite probable that you are witnessing a map that has been made with\n", - "a JavaScript library called [Leaflet](http://leafletjs.com). The\n", - "other popular library you might encounter is\n", - "[OpenLayers](https://openlayers.org).\n", + "a JavaScript library called [Leaflet](http://leafletjs.com). Other popular libraries you may encounter are\n", + "[OpenLayers](https://openlayers.org) and [maplibre](https://maplibre.org/).\n", "\n", "The Python module \n", "[Folium](https://github.com/python-visualization/folium) makes\n", "it possible to visualize data that has been manipulated in Python on an\n", - "interactive Leaflet map.\n", + "interactive Leaflet map in a jupyter notebook or website generated from python code.\n", "\n", "### Basics\n", "We will start with the most minimal map using the default OpenStreetMap base map.\n", @@ -158,8 +157,17 @@ "metadata": {}, "source": [ "And [open this map with overlay here](test/07-folium-2.html). \n", - "\n", - "Much more is possible with Folium, we just scratched the surface here!" + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Folium and Streamlit\n", + "Folium can also be [combined with Streamlit](https://folium.streamlit.app/). \n", + "[Streamlit](https://streamlit.io) is a platform to create interactive web apps for your python data scripts.\n", + "\n" ] }, { @@ -170,12 +178,10 @@ } }, "source": [ - "## Interactive maps in the Jupyter notebook with ipyleaflet\n", - "ipyleaflet is a Jupyter/Leaflet bridge enabling interactive maps in the Jupyter notebook.\n", - "(Although one can always save the results and use these maps in non-Jupyter contexts!).\n", - "\n", - "`ipyleaflet` is based on [ipywidgets](https://ipywidgets.readthedocs.io).\n", - "ipywidgets are interactive HTML widgets for Jupyter notebooks and the IPython kernel.\n", + "## ipyleaflet\n", + "[ipyleaflet](https://ipyleaflet.readthedocs.io) provides similar functionality as folium, however because\n", + "it is based on [ipywidgets](https://ipywidgets.readthedocs.io), it integrates with other components from\n", + "the ipywidgets ecosystem (sliders, datagrids, tabs).\n", "\n", "Links:\n", "\n", @@ -444,8 +450,10 @@ "source": [ "## Bokeh\n", "\n", - "Bokeh is a very powerful framework to produce powerful maps in combination\n", - "with data. With Geopandas and Bokeh one can produce nice looking interactive maps like in the image below:\n", + "Bokeh is a powerful framework to produce tailored interactive map and data visualisations.\n", + "Map features are limited compared to Folium, but there are more options to tailor the behaviour.\n", + "Bokeh provides mechanisms to interact with a server side application. With Geopandas and Bokeh\n", + "one can produce a nice looking interactive map like in the image below:\n", "\n", "![Bokeh and Geopandas Example](images/bokeh-example1.jpg)\n", "*Interactive Map with Bokeh and GeoPandas - Source: [CSC L6](https://automating-gis-processes.github.io/CSC/lessons/L6/interactive-map-bokeh.html)*\n" @@ -886,35 +894,64 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## pydeck - OPTIONAL\n", - "\n", - "[pydeck](https://pydeck.gl/) is a WebGL2-powered, highly performant large-scale data visualization framework.\n", - "We leave it you to explore pydeck through [its documentation](https://pydeck.gl/).\n", - "\n", - "pydeck is part of [deck.gl](https://deck.gl/).\n", - "\n", - "![From deck.gl repo Example](images/deck.gl.jpg)\n", - "\n", - "From their [GitHub README](https://github.com/visgl/deck.gl):\n", + "## pydeck\n", "\n", - "*\"deck.gl is designed to simplify high-performance, WebGL-based visualization of large data sets.\n", - "Users can quickly get impressive visual results with minimal effort by composing existing layers,\n", - "or leverage deck.gl's extensible architecture to address custom needs.*\n", + "Up till this point we've looked at 2D data visualisations. With [pydeck](https://pydeck.gl/)\n", + "we switch to WebGL-powered data visualization, including 3D and vector tiles.\n", + "pydeck is a python wrapper for the [deck.gl](https://deck.gl/) javascript library.\n", + "deck.gl visualisations typically use a vector tile background (from [mapbox](https://mapbox.com), [maptiler](https://www.maptiler.com/), or similar)\n", "\n", - "*deck.gl maps **data** (usually an array of JSON objects) into a stack of visual **layers** - e.g. icons, polygons, texts; and look at them with **views**: e.g. map, first-person, orthographic.*\n", + "![Example by deck.gl](images/deck.gl.jpg)\n", "\n", - "*deck.gl handles a number of challenges out of the box:*\n", + "The code snippet below creates a deck.gl view based on some sample data with tooltips.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 0, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "import pydeck as pdk\n", + "import pandas as pd\n", + "\n", + "# Sample data: 6 locations with population\n", + "data = pd.DataFrame({\n", + " 'lat': [43.5081, 43.2967, 43.0500, 43.3438, 42.6507, 42.9228],\n", + " 'lon': [16.4402, 17.0177, 17.4333, 17.8078, 18.0944, 17.6158],\n", + " 'pop': [160000 , 13000, 6500, 105000, 41000, 4000],\n", + " 'city': ['Split', 'Makarska', 'Ploče', 'Mostar', 'Dubrovnik', 'Neum']\n", + "})\n", + "\n", + "# Define a scatterplot layer\n", + "layer = pdk.Layer(\n", + " 'ScatterplotLayer',\n", + " data=data,\n", + " get_position='[lon, lat]',\n", + " get_radius='pop / 10',\n", + " get_fill_color='[180, 0, 200, 140]',\n", + " pickable=True\n", + ")\n", "\n", - "* *Performant rendering and updating of large data sets*\n", - "* *Interactive event handling such as picking, highlighting and filtering*\n", - "* *Cartographic projections and integration with major basemap providers*\n", - "* *A catalog of proven, well-tested layers*\n", + "# Define map view\n", + "view_state = pdk.ViewState(\n", + " latitude=42.7,\n", + " longitude=16.8,\n", + " zoom=7,\n", + " pitch=30,\n", + " bearing=10\n", + ")\n", "\n", - "*Deck.gl is designed to be highly customizable.*\n", - "*All layers come with flexible APIs to allow programmatic control of each aspect of the rendering.*\n", - "*All core classes such are easily extendable by the users to address custom use cases.\"*\n", + "# Render view\n", + "deck = pdk.Deck(\n", + " layers=[layer],\n", + " initial_view_state=view_state,\n", + " tooltip={\"text\": \"{city}\"}\n", + ")\n", "\n", - "deck.gl comes in several flavors (programming languages): JavaScript (`deck.gl`) and Python (`pydeck`)." + "deck.show()" ] }, { diff --git a/workshop/jupyter/requirements.txt b/workshop/jupyter/requirements.txt index 307b67f..2b00c6a 100644 --- a/workshop/jupyter/requirements.txt +++ b/workshop/jupyter/requirements.txt @@ -9,5 +9,6 @@ folium bokeh==2.4.3 ipyleaflet pandas-bokeh +pydeck pygeometa # >0.7 removed by Just matplotlib