Skip to content

Visualize MPAS mesh in python #281

Description

@bradyrx

I've been working on a method to visualize MPAS-O output on a static plot in python as an alternative to the more time-consuming route of rendering viz in ParaView. I'm looking for a way to faithfully represent the grid without regridding.

It seems like datashader/holoviews/geoviews is the way to go, but I'm having trouble getting it to work fully. I'm wondering if anyone has used this route or has a solution.

Method 1: Datashader points and shade:

from colorcet import cwr
import datashader 
import datashader.transfer_functions as tf


# Single time slice of air-sea CO2 flux.
ds = xr.open_dataset('MPAS-O.fgco2.nc')
verts = pd.DataFrame({'x': ds.lonCell, 'y': ds.latCell, 'z': ds.fgco2})

cvs = datashader.Canvas(plot_height=400,plot_width=400)
tf.shade(cvs.points(verts, 'x', 'y', agg=datashader.mean('z')), cmap=cwr,
         )

Screen Shot 2020-01-27 at 1 03 29 PM

This produces a map by coloring each pixel with an RGB value. This isn't a faithful representation of the grid, and I haven't found an easy way to plot this on a map projection.

Method 2: Trimesh

This is ultimately what I'd like to get working. This can easily be drawn on a map projection using geoviews once it works.

import datashader
import datashader.transfer_functions as tf
import pandas as pd
import xarray as xr

ds = xr.open_dataset('MPAS-O.fgco2.nc')
mesh = xr.open_dataset('oRRS30to10v3.171128.nc')

# Set up table with coordinates for each `nCell` index as well as the data being plotted ('z')
verts = pd.DataFrame({'x': ds.lonCell, 'y': ds.latCell, 'z': ds.fgco2})

# Construct indices for each triangle.
cell0 = mesh.nCells  # Base cell
cell1 = mesh.cellsOnCell.isel(maxEdges=1) - 1  # NE cell
cell2 = mesh.cellsOnCell.isel(maxEdges=2) - 1  # N cell

# Points to the triangle vertices (`verts`) for each triangle being plotted.
tris = pd.DataFrame({'v0': cell0, 'v1': cell1, 'v2': cell2})

cvs = datashader.Canvas(plot_height=400, plot_width=400)
tf.shade(cvs.trimesh(verts, tris))

Screen Shot 2020-01-27 at 3 44 10 PM

I tried also including all possible triangles, without success.

# Pairs of neighboring cell indices to construct triangles from.
PAIRS = [
    (0,1),
    (1,2),
    (2,3),
    (3,4),
    (4,5),
    (5,0)
]

cell0 = mesh.nCells
df = pd.DataFrame()
for idx in PAIRS:
    cell1 = mesh.cellsOnCell.isel(maxEdges=idx[0]) - 1
    cell2 = mesh.cellsOnCell.isel(maxEdges=idx[1]) - 1
    tris = pd.DataFrame({'v0': cell0,
                         'v1': cell1,
                         'v2': cell2})
    df = pd.concat([df, tris], ignore_index=True)

cvs = datashader.Canvas(plot_height=400,plot_width=400)
tf.shade(cvs.trimesh(verts, df), cmap=cwr)

Screen Shot 2020-01-27 at 3 46 25 PM

Any thoughts? The tris argument should be a three-column list of pointers to indices in verts to form a non-overlapping set of all triangles on the mesh.

Resources

https://datashader.org/user_guide/Trimesh.html

https://holoviews.org/reference/elements/bokeh/TriMesh.html

https://twitter.com/oceanographer/status/1126803420579545094

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions