-
Notifications
You must be signed in to change notification settings - Fork 10
Start tutorial showing how to use PyGMT with other packages #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
a1f1da9
Start tutorial showing how to use PyGMT with other packages
c3074d6
Download data as netcdf
cc596af
Plot population rather than gdp
4846996
Apply suggestions from code review
df6fe91
Only open first time index
49eb647
Add a static grdimage example
a81158a
Merge branch 'main' into pydata-integration
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,3 +14,4 @@ parts: | |
| - file: notebooks | ||
| - file: markdown-notebooks | ||
| - file: first-figure | ||
| - file: ecosystem | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,266 @@ | ||
| { | ||
| "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'))\n", | ||
| "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 world population estimates, 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 populations in millions per capita\n", | ||
| "world = world[(world.pop_est>0) & (world.name!=\"Antarctica\")]\n", | ||
| "world['pop_est'] = world.pop_est * 1e-6\n", | ||
| "\n", | ||
| "# Find the range of data values for creating a colormap\n", | ||
| "cmap_bounds = pygmt.info(data=world['pop_est'], per_column=True)\n", | ||
| "cmap_bounds" | ||
| ] | ||
| }, | ||
| { | ||
| "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=\"d\", 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 `pop_est` using the `color, `cmap`, and `aspatial` parameters\n", | ||
| "fig.plot(data=world, pen=\"1p,black\", close=True, color=\"+z\", cmap=True, aspatial=\"Z=pop_est\")\n", | ||
| "# Add a colorbar\n", | ||
| "fig.colorbar(position=\"JMR\", frame='a200+lPopulation (millions)')\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 = 'https://iridl.ldeo.columbia.edu/SOURCES/.NOAA/.NODC/.WOA09/.Grid-1x1/.Annual/.temperature/.t_an/data.nc'\n", | ||
| "netcdf_file = pygmt.which(fname=url, download=True)\n", | ||
| "woa_temp = xr.open_dataset(netcdf_file).isel(time=0)\n", | ||
| "woa_temp" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": null, | ||
| "id": "1c72a673", | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "# Make a static plot of sea surface temperature\n", | ||
| "fig = pygmt.Figure()\n", | ||
| "fig.grdimage(grid=woa_temp.t_an.sel(depth=0), cmap=\"vik\", projection=\"R15c\", frame=True)\n", | ||
| "fig.show()" | ||
| ] | ||
| }, | ||
| { | ||
| "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='Depth (m)', options=woa_temp.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), 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 | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.