ipygany

ipygany is a library that allows client side GPU rendering. This is useful because the data is sotred on the server and manipulations of the visualisation are near realtime.

This example:

  1. Imports a netcdf file using xarray

  2. Converts the netcdf file to a pyvista structured mesh

  3. Converts the pyvista mesh to ipygany mesh

  4. Colors and warps the mesh

  5. Shows the interaction

Imports

import pyvista as pv
import numpy as np
import xarray as xr

from ipygany import PolyMesh, Scene, IsoColor, WarpByScalar, ColorBar, colormaps
from ipywidgets import VBox, FloatSlider, FileUpload, Dropdown, jslink

Data upload

# Create file upload
# To load several files press shift with selecting - 
#all the files have to be selected at the same time.

file_upload = FileUpload(multiple=False)
file_upload
ds = xr.open_dataset(file_upload.data[0])
ds
<xarray.Dataset>
Dimensions:  (lat: 180, lon: 360)
Coordinates:
  * lon      (lon) float64 -179.5 -178.5 -177.5 -176.5 ... 177.5 178.5 179.5
  * lat      (lat) float64 -89.5 -88.5 -87.5 -86.5 -85.5 ... 86.5 87.5 88.5 89.5
Data variables:
    TOPO     (lat, lon) float32 187.9 179.5 420.2 ... -3.48e+03 -3.48e+03
Attributes:
    history:  Created with add_noise.ncl -- 08.06.21 JBL

Create pyvista structured mesh

xx, yy, zz = np.meshgrid(np.radians(ds['lon']), 
                         np.radians(ds['lat']), 
                         [0])

# Transform to spherical coordinates
radius = 6371.0e6
x = radius * np.cos(yy) * np.cos(xx)
y = radius * np.cos(yy) * np.sin(xx)
z = radius * np.sin(yy)

grid = pv.StructuredGrid(x, y, z)

# Add data to mesh
for var in ds.data_vars:
    grid[var] = np.array(ds[var]).ravel(order='F')

Convert pyvista mesh to ipygany mesh

# Turn the PyVista mesh into a PolyMesh
mesh = PolyMesh.from_vtk(grid)

# Color the mesh
colored_mesh = IsoColor(mesh, min=ds.TOPO.min(), max=ds.TOPO.max())
# setup warping
warped_mesh = WarpByScalar(colored_mesh, input='TOPO', factor=0)
# Link a slider to the warp value
warp_slider = FloatSlider(min=0., max=10., value=0)

def on_slider_change(change):
    warped_mesh.factor = change['new'] * -10000

warp_slider.observe(on_slider_change, 'value')

# Create a colorbar widget
colorbar = ColorBar(colored_mesh)

# Colormap choice widget
colormap = Dropdown(
    options=colormaps,
    description='colormap:'
)

jslink((colored_mesh, 'colormap'), (colormap, 'index'))

VBox((colormap, warp_slider, Scene([warped_mesh])))