{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ipygany\n", "\n", "[ipygany](https://ipygany.readthedocs.io/en/latest/) 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.\n", "\n", "This example:\n", "1. Imports a netcdf file using xarray\n", "1. Converts the netcdf file to a pyvista structured mesh\n", "1. Converts the pyvista mesh to ipygany mesh\n", "1. Colors and warps the mesh\n", "1. Shows the interaction\n", "\n", "## Imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pyvista as pv\n", "import numpy as np\n", "import xarray as xr\n", "\n", "from ipygany import PolyMesh, Scene, IsoColor, WarpByScalar, ColorBar, colormaps\n", "from ipywidgets import VBox, FloatSlider, FileUpload, Dropdown, jslink" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data upload" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "94b526e389de48bf850bf4994f266bcc", "version_major": 2, "version_minor": 0 }, "text/plain": [ "FileUpload(value={}, description='Upload')" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Create file upload\n", "# To load several files press shift with selecting - \n", "#all the files have to be selected at the same time.\n", "\n", "file_upload = FileUpload(multiple=False)\n", "file_upload" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset>\n",
       "Dimensions:  (lat: 180, lon: 360)\n",
       "Coordinates:\n",
       "  * lon      (lon) float64 -179.5 -178.5 -177.5 -176.5 ... 177.5 178.5 179.5\n",
       "  * lat      (lat) float64 -89.5 -88.5 -87.5 -86.5 -85.5 ... 86.5 87.5 88.5 89.5\n",
       "Data variables:\n",
       "    TOPO     (lat, lon) float32 187.9 179.5 420.2 ... -3.48e+03 -3.48e+03\n",
       "Attributes:\n",
       "    history:  Created with add_noise.ncl -- 08.06.21 JBL
" ], "text/plain": [ "\n", "Dimensions: (lat: 180, lon: 360)\n", "Coordinates:\n", " * lon (lon) float64 -179.5 -178.5 -177.5 -176.5 ... 177.5 178.5 179.5\n", " * lat (lat) float64 -89.5 -88.5 -87.5 -86.5 -85.5 ... 86.5 87.5 88.5 89.5\n", "Data variables:\n", " TOPO (lat, lon) float32 ...\n", "Attributes:\n", " history: Created with add_noise.ncl -- 08.06.21 JBL" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds = xr.open_dataset(file_upload.data[0])\n", "ds" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create pyvista structured mesh" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "xx, yy, zz = np.meshgrid(np.radians(ds['lon']), \n", " np.radians(ds['lat']), \n", " [0])\n", "\n", "# Transform to spherical coordinates\n", "radius = 6371.0e6\n", "x = radius * np.cos(yy) * np.cos(xx)\n", "y = radius * np.cos(yy) * np.sin(xx)\n", "z = radius * np.sin(yy)\n", "\n", "grid = pv.StructuredGrid(x, y, z)\n", "\n", "# Add data to mesh\n", "for var in ds.data_vars:\n", " grid[var] = np.array(ds[var]).ravel(order='F')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Convert pyvista mesh to ipygany mesh" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Turn the PyVista mesh into a PolyMesh\n", "mesh = PolyMesh.from_vtk(grid)\n", "\n", "# Color the mesh\n", "colored_mesh = IsoColor(mesh, min=ds.TOPO.min(), max=ds.TOPO.max())\n", "# setup warping\n", "warped_mesh = WarpByScalar(colored_mesh, input='TOPO', factor=0)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d4b0fdb757ba4d099d5b0fa9ea478497", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(Dropdown(description='colormap:', options={'BrBG': 0, 'PRGn': 1, 'PiYG': 2, 'PuOr': 3, 'RdBu': …" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Link a slider to the warp value\n", "warp_slider = FloatSlider(min=0., max=10., value=0)\n", "\n", "def on_slider_change(change):\n", " warped_mesh.factor = change['new'] * -10000\n", "\n", "warp_slider.observe(on_slider_change, 'value')\n", "\n", "# Create a colorbar widget\n", "colorbar = ColorBar(colored_mesh)\n", "\n", "# Colormap choice widget\n", "colormap = Dropdown(\n", " options=colormaps,\n", " description='colormap:'\n", ")\n", "\n", "jslink((colored_mesh, 'colormap'), (colormap, 'index'))\n", "\n", "VBox((colormap, warp_slider, Scene([warped_mesh])))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python (pangeo)", "language": "python", "name": "python-pangeo" }, "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.7.9" } }, "nbformat": 4, "nbformat_minor": 4 }