Part 2 of LASSO-ShCu Tutorial: Quick-look 3-D Isosurface Plotting
This notebook contains an example 3-D isosurface plot using Plotly for the LASSO-ShCu wrfstat
data. We follow the example from the Plotly documentation. We have separated this example out from lasso-shcu.ipynb since this plot is big and may cause issues for viewing the file contents without running the notebook oneself.
Author: William.Gustafson@pnnl.gov
Date: 13-May-2024
Objective of this notebook: Use plotting of 3-D isosurfaces as an example for working with the simulated cloud data from LASSO-ShCu wrfstat files.
# Libraries required for this tutorial...
from datetime import datetime, timedelta
import numpy as np
import xarray as xr
import plotly.graph_objects as go
First, we need to read the data into memory, similarly to how we did it in the lasso-shcu.ipynb notebook.
# Read in the wrfstat data...
# path_shcu_root = "/gpfs/wolf2/arm/atm124/world-shared/arm-summer-school-2024/lasso_tutorial/ShCu/untar/" # on cumulus
path_shcu_root = "/data/project/ARM_Summer_School_2024_Data/lasso_tutorial/ShCu/untar" # on Jupyter
case_date = datetime(2019, 4, 4)
sim_id = 4
hour_to_plot = 17
ds_stat = xr.open_dataset(f"{path_shcu_root}/{case_date:%Y%m%d}/sim{sim_id:04d}/raw_model/wrfstat_d01_{case_date:%Y-%m-%d_12:00:00}.nc")
ds_stat["Time"] = ds_stat["XTIME"] # Fix the time coordinate
ERROR 1: PROJ: proj_create_from_database: Open of /opt/conda/share/proj failed
Now, we can make the plot, which in this case is a 3-D volume rendering of the cloud liquid water content. We only plot one quadrant of the data to keep the memory and compute usage down.
# Get the domain size and set the limitations on plot size...
nt, nz, ny, nx = ds_stat["CSV_LWC"].shape
nx_use = int(nx/3)
ny_use = int(ny/3)
nz_use = int(nz/4)
# Define the coordinates as a volume...
# We set this up in units of km using domain-averaged height data and
# assuming 100-m grid spacing.
Z, Y, X = np.meshgrid(ds_stat["CSP_Z"].sel(Time=f"{case_date:%Y-%m-%d} {hour_to_plot}:00").isel(bottom_top=slice(0,nz_use)).values*1e-3,
np.arange(0,ny_use)*0.1, # 0.1 is the conversion to km assuming dy=100 m
np.arange(0,nx_use)*0.1, # and the same for dx
indexing='ij')
# Pull the data to plot...
plot_data = ds_stat["CSV_LWC"].\
sel(Time=f"{case_date:%Y-%m-%d} {hour_to_plot}:00").\
isel(west_east=slice(0,nx_use), south_north=slice(0,ny_use), bottom_top=slice(0,nz_use)).\
values
# And, make the plot...
fig = go.Figure(data=go.Isosurface(
x=X.flatten(), y=Y.flatten(), z=Z.flatten(),
value=plot_data.flatten(),
isomin=0.0001, isomax=0.001,
colorscale='temps'
))
fig.show()