Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ parts:
- file: markdown
- file: notebooks
- file: markdown-notebooks
- file: ecosystem
259 changes: 259 additions & 0 deletions book/ecosystem.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "b862b964-62fc-48b7-96db-d7f3b868ced1",
"metadata": {
"tags": []
},
"source": [
"# Integration with the scientific Python ecosystem 🐍\n",
"\n",
"In this tutorial, we'll try out the integration between PyGMT and other common packages in the scientific Python ecosystem.\n",
"\n",
"\n",
"Besides [pygmt](https://www.pygmt.org), we'll also be using:\n",
"\n",
"- [GeoPandas](https://geopandas.org/en/stable/) for managing geospatial tabular data\n",
"- [Panel](https://panel.holoviz.org/index.html) for interactive visualizations\n",
"- [Xarray](https://xarray.dev/) for managing n-dimensional labelled arrays\n"
]
},
{
"cell_type": "markdown",
"id": "62d489cd-c901-42a2-b51a-9b21842b34df",
"metadata": {},
"source": [
"## Plotting geospatial vector data with GeoPandas and PyGMT\n",
"\n",
"We'll extend the GeoPandas [Mapping and Plotting Tools Examples](https://geopandas.org/en/stable/docs/user_guide/mapping.html) to show how to create choropleth maps using PyGMT.\n",
"\n",
"**References**:\n",
"\n",
" - GeoPandas User Guide - https://geopandas.org/en/stable/docs/user_guide/"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6436dfbb-be9c-4c2b-901a-a8fc7cde4ae8",
"metadata": {},
"outputs": [],
"source": [
"import pygmt\n",
"import geopandas as gpd"
]
},
{
"cell_type": "markdown",
"id": "a0f88acb-e463-4193-a7ef-33837b2f5fdf",
"metadata": {},
"source": [
"We'll load sample data provided through the GeoPandas package and inspect the GeoDataFrame."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8cf79e91-8ce0-48ec-8812-1395d3d0eddf",
"metadata": {},
"outputs": [],
"source": [
"world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6a44f98e-5b50-463f-829a-cd0fa25a6aa1",
"metadata": {},
"outputs": [],
"source": [
"world.head()"
]
},
{
"cell_type": "markdown",
"id": "65adae6a-3933-453b-bd4b-4e04e018d02d",
"metadata": {},
"source": [
"Following the [GeoPandas example](https://geopandas.org/en/stable/docs/user_guide/mapping.html#choropleth-maps), we'll create a Choropleth map showing the GDP per capita, but will use PyGMT to plot the data using the [Hammer projection](https://www.pygmt.org/latest/projections/misc/misc_hammer.html#hammer)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "76b850c4-e5bc-42bd-ba13-7b52b4f60dc2",
"metadata": {},
"outputs": [],
"source": [
"# Calculate the GDP per capita\n",
"world = world[(world.pop_est>0) & (world.name!=\"Antarctica\")]\n",
"world['gdp_per_cap'] = world.gdp_md_est / world.pop_est\n",
"\n",
"# Find the range of data values for creating a colormap\n",
"cmap_bounds = pygmt.info(data=world['gdp_per_cap'], per_column=True)\n"
]
},
{
"cell_type": "markdown",
"id": "864091e5-85e2-4452-ab44-5cbeaa2ac8a9",
"metadata": {},
"source": [
"Now, we'll plot the data on a PyGMT figure, by creating a figure instance, laying down a basemap, plotting the GeoDataFrame, and adding a colorbar!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "15a21a74-8531-4e74-86e1-a85e6eaef793",
"metadata": {},
"outputs": [],
"source": [
"# Create an instance of the pygmt.Figure class\n",
"fig = pygmt.Figure()\n",
"# Create a colormap for the figure\n",
"pygmt.makecpt(cmap=\"bilbao\", series=cmap_bounds)\n",
"# Create a basemap\n",
"fig.basemap(region=\"g\", projection=\"H15c\", frame=True)\n",
"# Plot the GeoDataFrame\n",
"# - Use `close=True` to specify that the polygons should be forced closed\n",
"# - Plot the polygon outlines with a 1 point, black pen\n",
"# - Set that the color should be based on the `gdb_per_cap` using the `color, `cmap`, and `aspatial` parameters\n",
"fig.plot(data=world, pen=\"1p,black\", close=True, color=\"+z\", cmap=True, aspatial=\"Z=gdp_per_cap\")\n",
"# Add a colorbar\n",
"fig.colorbar(position=\"JMR\", frame=\"a0.02\")\n",
"# Display the output\n",
"fig.show()\n"
]
},
{
"cell_type": "markdown",
"id": "b73a6666-6c2c-4f49-a92b-995ade576ccc",
"metadata": {},
"source": [
"## Interactive data visualization with Xarray, Panel, and PyGMT"
]
},
{
"cell_type": "markdown",
"id": "1bf15df6-6a4f-4221-af66-0db1c5b1e328",
"metadata": {},
"source": [
"In this section, we'll create some interactive visualizations of oceanographic data!\n",
"\n",
"We'll use [Panel](https://panel.holoviz.org/index.html), which is a Python library\n",
"for connecting interactive widgets with plots! We'll use Panel with\n",
"[PyGMT](https://www.pygmt.org) and [xarray](https://www.xarray.dev) to visualize\n",
"the objectively interpolated mean field for in-situ temperature from the World Ocean Atlas.\n",
"\n",
"**References**:\n",
"\n",
"- Temperature visualization based on https://rabernat.github.io/intro_to_physical_oceanography/02-c_ocean_temperature_salinity_stratification.html\n",
"- Interactive setup based on https://github.com/weiji14/30DayMapChallenge2021/blob/main/day25_interactive.py\n",
"- Data from the NOAA World Ocean Atlas, stored on the IRI Data Library at http://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NODC/.WOA09/."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dbcff01f-fac0-4c1d-bb66-89dcb2e7711b",
"metadata": {},
"outputs": [],
"source": [
"import panel as pn\n",
"import xarray as xr\n",
"import pygmt\n",
"pn.extension()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7b2f9cb8-add6-45c2-9f54-8e33ed9e6f02",
"metadata": {},
"outputs": [],
"source": [
"# Download the dataset from the IRI Data Library\n",
"url = 'http://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NODC/.WOA09/.Grid-1x1/.Annual/.temperature/.t_an/dods'\n",
"woa_temp = xr.open_dataset(url)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b11ea510-7540-475e-9217-be4204cb1ea3",
"metadata": {},
"outputs": [],
"source": [
"# Make a panel widget for controlling the depth plotted\n",
"depth_slider = pn.widgets.DiscreteSlider(name='Discrete Slider', options=woa_temp.coords['depth'].values.astype(int).tolist(), value=0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3496d4db-92d9-45ee-9d48-6b4f00a19361",
"metadata": {},
"outputs": [],
"source": [
"# Make a function for plotting the depth slice with PyGMT\n",
"\n",
"@pn.depends(depth=depth_slider)\n",
"def view(depth: int):\n",
" fig = pygmt.Figure()\n",
" pygmt.makecpt(cmap=\"vik\", series=[-2,30])\n",
" fig.grdimage(grid=woa_temp.t_an.sel(depth=depth).isel(time=0), cmap=True, projection=\"R15c\", frame=True)\n",
" fig.colorbar(frame=\"a5\")\n",
" return fig"
]
},
{
"cell_type": "markdown",
"id": "d339433c-1c7a-4769-8986-edfb2a9897ed",
"metadata": {},
"source": [
"### Make the interactive dashboard!\n",
"\n",
"Now to put everything together! The 'dashboard' will be very simple.\n",
"The 'depth' slider is placed next to the map using `panel.Column`.\n",
"Selecting different depths will update the data plotted! Find out more at\n",
"https://panel.holoviz.org/getting_started/index.html#using-panel.\n",
"\n",
"Note: This is meant to run in a Jupyter lab/notebook environment.\n",
"The grdinfo warning can be ignored."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cc8d2f88-6e37-4ca4-9ebc-4bdf1e00ec8e",
"metadata": {},
"outputs": [],
"source": [
"pn.Column(depth_slider, view)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies:
- python=3.9
- pip=22
# Optional dependencies
- panel=0.12.4
- geopandas=0.10.2
- jupyter-book=0.12.3
- laspy=2.1.2
Expand Down