Skip to content

Visualize MPAS mesh in python #281

@bradyrx

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

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