Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bjlittle/geovista
Cartographic rendering and mesh analytics powered by PyVista
https://github.com/bjlittle/geovista
cartography curvilinear earth-science grid mesh python pyvista rectilinear ugrid unstructured vtk
Last synced: 12 days ago
JSON representation
Cartographic rendering and mesh analytics powered by PyVista
- Host: GitHub
- URL: https://github.com/bjlittle/geovista
- Owner: bjlittle
- License: bsd-3-clause
- Created: 2021-05-11T15:40:46.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-10-29T09:31:41.000Z (12 days ago)
- Last Synced: 2024-10-29T11:06:18.153Z (12 days ago)
- Topics: cartography, curvilinear, earth-science, grid, mesh, python, pyvista, rectilinear, ugrid, unstructured, vtk
- Language: Python
- Homepage: https://geovista.readthedocs.io/
- Size: 6.28 MB
- Stars: 160
- Watchers: 11
- Forks: 26
- Open Issues: 31
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Citation: CITATION.cff
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
Cartographic rendering and mesh analytics powered by PyVista| | |
|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| โ๏ธ CI | [![ci-citation](https://github.com/bjlittle/geovista/actions/workflows/ci-citation.yml/badge.svg)](https://github.com/bjlittle/geovista/actions/workflows/ci-citation.yml) [![ci-locks](https://github.com/bjlittle/geovista/actions/workflows/ci-locks.yml/badge.svg)](https://github.com/bjlittle/geovista/actions/workflows/ci-locks.yml) [![ci-manifest](https://github.com/bjlittle/geovista/actions/workflows/ci-manifest.yml/badge.svg)](https://github.com/bjlittle/geovista/actions/workflows/ci-manifest.yml) [![ci-tests](https://github.com/bjlittle/geovista/actions/workflows/ci-tests.yml/badge.svg)](https://github.com/bjlittle/geovista/actions/workflows/ci-tests.yml) [![ci-wheels](https://github.com/bjlittle/geovista/actions/workflows/ci-wheels.yml/badge.svg)](https://github.com/bjlittle/geovista/actions/workflows/ci-wheels.yml) [![pre-commit](https://results.pre-commit.ci/badge/github/bjlittle/geovista/main.svg)](https://results.pre-commit.ci/latest/github/bjlittle/geovista/main) |
| ๐ฌ Community | [![Contributor Covenant](https://img.shields.io/badge/contributor%20covenant-2.1-4baaaa.svg)](https://github.com/bjlittle/geovista/blob/main/CODE_OF_CONDUCT.md) [![GH Discussions](https://img.shields.io/badge/github-discussions%20%F0%9F%92%AC-yellow?logo=github&logoColor=lightgrey)](https://github.com/bjlittle/geovista/discussions) [![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/geovista_devs?label=@geovista_devs)](https://twitter.com/geovista_devs) [![YouTube Channel Subscribers](https://img.shields.io/youtube/channel/subscribers/UCMJIzZ23r_3fvtqNpYi57Lw?label=@geovista_devs)](https://www.youtube.com/@geovista_devs/videos) [![All Contributors](https://img.shields.io/github/all-contributors/bjlittle/geovista?color=ee8449)](https://geovista.readthedocs.io/en/latest/reference/about.html#contributors) [![Mentioned in Awesome Open Geoscience](https://awesome.re/mentioned-badge.svg)](https://github.com/softwareunderground/awesome-open-geoscience) |
| ๐ Docs | [![Documentation Status](https://readthedocs.org/projects/geovista/badge/?version=latest)](https://geovista.readthedocs.io/en/latest/?badge=latest) |
| ๐ Health | [![codecov](https://codecov.io/gh/bjlittle/geovista/branch/main/graph/badge.svg?token=RVVXGP1SD3)](https://codecov.io/gh/bjlittle/geovista) |
| โจ Meta | [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![SPEC 0 โ Minimum Supported Dependencies](https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038)](https://scientific-python.org/specs/spec-0000/) [![license - bsd-3-clause](https://img.shields.io/github/license/bjlittle/geovista)](https://github.com/bjlittle/geovista/blob/main/LICENSE) [![conda platform](https://img.shields.io/conda/pn/conda-forge/geovista.svg)](https://anaconda.org/conda-forge/geovista) |
| ๐ฆ Package | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.7608302.svg)](https://doi.org/10.5281/zenodo.7608302) [![conda-forge](https://img.shields.io/conda/vn/conda-forge/geovista?color=orange&label=conda-forge&logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/geovista) [![pypi](https://img.shields.io/pypi/v/geovista?color=orange&label=pypi&logo=python&logoColor=white)](https://pypi.org/project/geovista/) [![pypi - python version](https://img.shields.io/pypi/pyversions/geovista.svg?color=orange&logo=python&label=python&logoColor=white)](https://pypi.org/project/geovista/) |
| ๐งฐ Repo | [![commits-since](https://img.shields.io/github/commits-since/bjlittle/geovista/latest.svg)](https://github.com/bjlittle/geovista/commits/main) [![contributors](https://img.shields.io/github/contributors/bjlittle/geovista)](https://github.com/bjlittle/geovista/graphs/contributors) [![release](https://img.shields.io/github/v/release/bjlittle/geovista)](https://github.com/bjlittle/geovista/releases) |
| ๐ก๏ธ Status | [![scitools](https://img.shields.io/badge/scitools-ownership%20pending-yellow)](https://github.com/bjlittle/geovista/issues/167) |
| | |## Rediscover Your Data
[WW3 SMC time-series ๐ฅ](https://github.com/bjlittle/geovista/assets/2051656/876d877e-a6fa-42ff-8153-08c41ff8a19e)
GeoVista is built on the shoulders of giants, namely [PyVista](https://docs.pyvista.org/version/stable/) and
[VTK](https://vtk.org/documentation/), thus allowing it to easily leverage the power of the GPU.As a result, it offers a paradigm shift in rendering performance and interactive user experience, as demonstrated by
this realtime, time-series animation of WAVEWATCH IIIยฎ third-generation wave model (**WAVE**-height, **WAT**er depth
and **C**urrent **H**indcasting) data developed at [NOAA](https://www.noaa.gov/)/[NCEP](https://www.weather.gov/ncep/).The animation shows a time-series of Sea Surface Wave Significant Height data located on the cell faces of a
quasi-unstructured Spherical Multi-Cell (SMC) grid.Bring your data alive with GeoVista! ๐
Tempted? Keen to know more? Well, let's begin ...
## Motivation
The goal of GeoVista is simple; to complement [PyVista](https://docs.pyvista.org/index.html) with a convenient
cartographic capability.In this regard, from a design perspective we aim to keep GeoVista as **pure** to PyVista as possible i.e.,
**minimise specialisation** as far as practically possible in order to **maximise native compatibility** within the
PyVista and [VTK](https://vtk.org/) ecosystems.We intend GeoVista to be a cartographic gateway into the powerful world of PyVista, and all that it offers.
GeoVista is intentionally agnostic to packages such as [geopandas](https://geopandas.org/en/stable/),
[iris](https://scitools-iris.readthedocs.io/en/latest/?badge=latest), [xarray](https://docs.xarray.dev/en/stable/)
et al, which specialise in preparing your spatial data for visualisation. Rather, we delegate that responsibility and
choice of tool to you the user, as we want GeoVista to remain as flexible and open-ended as possible to the entire
Scientific Python community.Simply put, "*[GeoVista](https://geovista.readthedocs.io/) is to
[PyVista](https://docs.pyvista.org/)*", as
"*[Cartopy](https://scitools.org.uk/cartopy/docs/latest/) is to
[Matplotlib](https://matplotlib.org/)*". Well, that's the aspiration.## Installation
GeoVista is available on both [conda-forge](https://anaconda.org/conda-forge/geovista) and [PyPI](https://pypi.org/project/geovista/).
We recommend using [conda](https://docs.conda.io/projects/conda/en/latest/index.html) to install GeoVista ๐
### Conda
GeoVista is available on [conda-forge](https://anaconda.org/conda-forge/geovista), and can be easily installed with
[conda](https://docs.conda.io/projects/conda/en/latest/index.html):
```shell
conda install -c conda-forge geovista
```
For more information see our [conda-forge feedstock](https://github.com/conda-forge/geovista-feedstock) and
[prefix.dev dashboard](https://prefix.dev/channels/conda-forge/packages/geovista).### Pip
GeoVista is also available on [PyPI](https://pypi.org/project/geovista/):
```shell
pip install geovista
```Checkout out our [PyPI Download Stats](https://pypistats.org/packages/geovista), if you like that kinda thing.
## Quick Start
GeoVista comes with various pre-canned resources to help get you started on your visualisation journey.
### Resources
GeoVista makes use of various resources, such as rasters, VTK meshes,
[Natural Earth](https://www.naturalearthdata.com/features/) features, and sample model data.If you want to download and cache all registered GeoVista resources to make them available offline, simply:
```shell
geovista download --all
```
Alternatively, just leave GeoVista to download resources on-the-fly, as and when she needs them.To view the list of registered resources, simply:
```shell
geovista download --list
```Want to know more?
```shell
geovista download --help
```### Plotting Examples
Let's explore a sample of various oceanographic and atmospheric model data using GeoVista.
#### WAVEWATCH III
First, let's render a [WAVEWATCH III](https://github.com/NOAA-EMC/WW3) (WW3) **unstructured** triangular mesh, with
[10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/), a
[1:50m Natural Earth Cross-Blended Hypsometric Tints](https://www.naturalearthdata.com/downloads/50m-raster-data/50m-cross-blend-hypso/)
base layer, and the gorgeous perceptually uniform [cmocean balance](https://matplotlib.org/cmocean/#balance) diverging
colormap.๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import ww3_global_tri
import geovista.theme# Load the sample data.
sample = ww3_global_tri()# Create the mesh from the sample data.
mesh = gv.Transform.from_unstructured(
sample.lons, sample.lats, connectivity=sample.connectivity, data=sample.data
)# Plot the mesh.
p = gv.GeoPlotter()
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, show_edges=True, scalar_bar_args=sargs)
p.add_base_layer(texture=gv.natural_earth_hypsometric())
p.add_coastlines()
p.add_graticule()
p.view_xy(negative=True)
p.add_axes()
p.show()
```
#### Finite Volume Community Ocean Model
Now, let's visualise the bathymetry of the
[Plymouth Sound and Tamar River](https://www.google.com/maps/place/Plymouth+Sound/@50.3337382,-4.2215988,12z/data=!4m5!3m4!1s0x486c93516bbce307:0xded7654eaf4f8f83!8m2!3d50.3638359!4d-4.1441365)
from an [FVCOM](https://www.fvcom.org/) **unstructured** mesh, as kindly provided by the
[Plymouth Marine Laboratory](https://pml.ac.uk/) using the lush [cmocean deep](https://matplotlib.org/cmocean/#deep) colormap.๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import fvcom_tamar
import geovista.theme# Load the sample data.
sample = fvcom_tamar()# Create the mesh from the sample data.
mesh = gv.Transform.from_unstructured(
sample.lons,
sample.lats,
connectivity=sample.connectivity,
data=sample.face,
name="face",
)# Warp the mesh nodes by the bathymetry.
mesh.point_data["node"] = sample.node
mesh.compute_normals(cell_normals=False, point_normals=True, inplace=True)
mesh.warp_by_scalar(scalars="node", inplace=True, factor=2e-5)# Plot the mesh.
p = gv.GeoPlotter()
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, cmap="deep", scalar_bar_args=sargs)
p.add_axes()
p.show()
```
#### CF UGRID
##### Local Area Model
Initial projection support is available within GeoVista for **Cylindrical** and **Pseudo-Cylindrical** projections. As
GeoVista matures and stabilises, we'll aim to complement this capability with other classes of projections, such as
**Azimuthal** and **Conic**.In the meantime, let's showcase our basic projection support with some high-resolution **unstructured** Local Area Model
(LAM) data reprojected to [Mollweide](https://proj.org/operations/projections/moll.html) using a
[PROJ](https://proj.org/index.html) string, with
[10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/) and a
[1:50m Natural Earth Cross-Blended Hypsometric Tints](https://www.naturalearthdata.com/downloads/50m-raster-data/50m-cross-blend-hypso/)
base layer.๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import lam_pacific
import geovista.theme# Load the sample data.
sample = lam_pacific()# Create the mesh from the sample data.
mesh = gv.Transform.from_unstructured(
sample.lons,
sample.lats,
connectivity=sample.connectivity,
data=sample.data,
)# Plot the mesh on a mollweide projection using a Proj string.
p = gv.GeoPlotter(crs="+proj=moll")
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, scalar_bar_args=sargs)
p.add_base_layer(texture=gv.natural_earth_hypsometric())
p.add_coastlines()
p.add_graticule()
p.add_axes()
p.view_xy()
p.show()
```
Using the same **unstructured** LAM data, reproject to
[Equidistant Cylindrical](https://proj.org/operations/projections/eqc.html) but this time using a
[Cartopy Plate Carrรฉe CRS](https://scitools.org.uk/cartopy/docs/latest/reference/projections.html#cartopy.crs.PlateCarree),
also with [10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/)
and a
[1:50m Natural Earth Cross-Blended Hypsometric Tints](https://www.naturalearthdata.com/downloads/50m-raster-data/50m-cross-blend-hypso/)
base layer.๐ Click for code ...
```python
import cartopy.crs as ccrsimport geovista as gv
from geovista.pantry.data import lam_pacific
import geovista.theme# Load the sample data.
sample = lam_pacific()# Create the mesh from the sample data.
mesh = gv.Transform.from_unstructured(
sample.lons,
sample.lats,
connectivity=sample.connectivity,
data=sample.data,
)# Plot the mesh on a Plate Carrรฉe projection using a cartopy CRS.
p = gv.GeoPlotter(crs=ccrs.PlateCarree(central_longitude=180))
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, scalar_bar_args=sargs)
p.add_base_layer(texture=gv.natural_earth_hypsometric())
p.add_coastlines()
p.add_graticule()
p.add_axes()
p.view_xy()
p.show()
```
#### LFRic Cube-Sphere
Now render a [Met Office LFRic](https://www.metoffice.gov.uk/research/approach/modelling-systems/lfric) C48 cube-sphere
**unstructured** mesh of Sea Surface Temperature data on a
[Robinson Projection](https://proj.org/operations/projections/robin.html) using an ESRI SRID, with
[10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/) and a
[cmocean thermal](https://matplotlib.org/cmocean/#thermal) colormap.๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import lfric_sst
import geovista.theme# Load the sample data.
sample = lfric_sst()# Create the mesh from the sample data.
mesh = gv.Transform.from_unstructured(
sample.lons,
sample.lats,
connectivity=sample.connectivity,
data=sample.data,
)# Plot the mesh on a Robinson projection using an ESRI spatial reference identifier.
p = gv.GeoPlotter(crs="ESRI:54030")
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, cmap="thermal", show_edges=True, scalar_bar_args=sargs)
p.add_coastlines()
p.view_xy()
p.add_axes()
p.show()
```
#### NEMO ORCA2
So far we've demonstrated GeoVista's ability to cope with **unstructured** data. Now let's plot a **curvilinear** mesh
using Nucleus for European Modelling of the Ocean (NEMO) ORCA2 Sea Water Potential Temperature data, with
[10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/) and a
[1:50m Natural Earth I](https://www.naturalearthdata.com/downloads/50m-raster-data/50m-natural-earth-1/) base layer.๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import nemo_orca2
import geovista.theme# Load sample data.
sample = nemo_orca2()# Create the mesh from the sample data.
mesh = gv.Transform.from_2d(sample.lons, sample.lats, data=sample.data)# Remove cells from the mesh with NaN values.
mesh = mesh.threshold()# Plot the mesh.
p = gv.GeoPlotter()
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, show_edges=True, scalar_bar_args=sargs)
p.add_base_layer(texture=gv.natural_earth_1())
p.add_coastlines()
p.view_xy()
p.add_axes()
p.show()
```
#### OISST AVHRR
Now let's render a [NOAA/NCEI Optimum Interpolation SST](https://www.ncei.noaa.gov/products/optimum-interpolation-sst)
(OISST) Advanced Very High Resolution Radiometer (AVHRR) **rectilinear** mesh, with
[10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/) and a
[NASA Blue Marble](https://visibleearth.nasa.gov/collection/1484/blue-marble) base layer.๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import oisst_avhrr_sst
import geovista.theme# Load sample data.
sample = oisst_avhrr_sst()# Create the mesh from the sample data.
mesh = gv.Transform.from_1d(sample.lons, sample.lats, data=sample.data)# Remove cells from the mesh with NaN values.
mesh = mesh.threshold()# Plot the mesh.
p = gv.GeoPlotter()
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, scalar_bar_args=sargs)
p.add_base_layer(texture=gv.blue_marble())
p.add_coastlines()
p.view_xz()
p.add_axes()
p.show()
```
#### DYNAMICO
Finally, to demonstrate support for non-traditional cell geometries i.e., not triangles or quadrilaterals, we plot
the **unstructured** mesh from the [DYNAMICO](https://gitlab.in2p3.fr/ipsl/projets/dynamico/dynamico) project. This
model uses hexagonal and pentagonal cells, and is a new dynamical core for
[LMD-Z](https://www.lmd.ipsl.fr/en/modelisations/lmdz-en/), the atmospheric General Circulation Model (GCM) part of the
[IPSL-CM](https://cmc.ipsl.fr/ipsl-climate-models/) Earth System Model. The render also contains
[10m Natural Earth coastlines](https://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-coastline/).๐ Click for code ...
```python
import geovista as gv
from geovista.pantry.data import dynamico
import geovista.theme# Load sample data.
sample = dynamico()# Create the mesh from the sample data.
mesh = gv.Transform.from_unstructured(sample.lons, sample.lats, data=sample.data)# Plot the mesh.
p = gv.GeoPlotter()
sargs = {"title": f"{sample.name} / {sample.units}"}
p.add_mesh(mesh, scalar_bar_args=sargs)
p.add_coastlines()
p.add_axes()
p.show()
```
## Further Examples
"Please, sir, I want some more", Charles Dickens, Oliver Twist, 1838.Certainly, our pleasure! From the command line, simply:
```bash
geovista examples --run all --verbose
```Want to know more?
```shell
geovista examples --help
```## Candy Store ๐ฌ
We've opened the doors to the [Candy Store ๐ฌ](https://github.com/bjlittle/geovista/discussions/1033).
A community space where you can openly share and promote how you're using
GeoVista for your work, research or pleasure!Showcase your most awesome GeoVista eye candy with undiluted pride and tell
us more about your work.We'd ๐ to hear from you!
## Documentation
The [documentation](https://geovista.readthedocs.io/en/latest/) is built by [Sphinx](https://www.sphinx-doc.org/en/master/) and hosted on [Read the Docs](https://docs.readthedocs.io/en/stable/).
## Ecosystem
Whilst you're here, why not hop on over to the [pyvista-xarray](https://github.com/pyvista/pyvista-xarray) project and
check it out!It's aiming to provide `xarray DataArray accessors for PyVista to visualize datasets in 3D` for the
[xarray](https://github.com/pydata/xarray) community, and will be building on top of GeoVista ๐## Support
Need help? ๐ข
Why not check out our [existing GitHub issues](https://github.com/bjlittle/geovista/issues). See something similar?
Well, give it a ๐ to raise its priority and feel free to chip in on the conversation. Otherwise, don't hesitate to
create a [new GitHub issue](https://github.com/bjlittle/geovista/issues/new/choose) instead.However, if you'd rather have a natter, then head on over to our
[GitHub Discussions](https://github.com/bjlittle/geovista/discussions). That's definitely the place to wax lyrical all
things GeoVista!## License
GeoVista is distributed under the terms of the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html) license.
## Star History
Diggin' GeoVista? Then why not show it some ๐ with a GitHub โญ!
It's a simple click that means the world to us, and helps others discover our
community too![![Star History Chart](https://api.star-history.com/svg?repos=bjlittle/geovista&type=Date)](https://star-history.com/#bjlittle/geovista&Date)
## [#ShowYourStripes](https://showyourstripes.info/s/globe)
**Graphics and Lead Scientist**: [Ed Hawkins](http://www.met.reading.ac.uk/~ed/home/index.php), National Centre for Atmospheric Science, University of Reading.
**Data**: Berkeley Earth, NOAA, UK Met Office, MeteoSwiss, DWD, SMHI, UoR, Meteo France & ZAMG.
#ShowYourStripes is distributed under a
Creative Commons Attribution 4.0 International License