Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

UXarray logo

MPAS Ocean

In this recipe, you will learn how to create visualizations of global ocean depth data using MPAS-Ocean model output. The recipe includes techniques for both global-scale visualization and regional analysis, with a specific focus on the Gulf of Mexico region.

Visualization Objectives

This recipe will guide you through creating:

  • Global ocean visualizations using the Robinson projection with raster-based plotting

  • Regional depth analysis of the Gulf of Mexico using vector polygons


Data Preparation

Global Ocean Data

The global MPAS-Ocean grid data requires no preprocessing for our visualization purposes, as it already encompasses the complete global domain.

28571

Regional Focus: Gulf of Mexico

To create a detailed regional visualization of the Gulf of Mexico, we’ll perform a spatial subset of our global data. By applying a bounding circle operation centered at 90°W longitude and 25°N latitude with a 9-degree radius, we can focus our analysis specifically on the Gulf region. This subsetting approach significantly reduces the computational demands of our visualization routines.

156

Global Ocean Depth Visualization

For our global visualization, we selected the Robinson projection combined with raster plotting to effectively display worldwide ocean depth data. The 4.0 pixel ratio setting ensures clear resolution while maintaining efficient performance across the entire global domain.

Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Regional Visualization: Gulf of Mexico

For our detailed analysis of the Gulf of Mexico region, we transition to a vector-based polygon visualization approach. This shift from our global visualization strategy is driven by the reduced computational demands of our regional subset, which contains only 164 faces. Vector polygons offer several advantages at this scale, including precise boundary representation and enhanced detail visualization.

/home/runner/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/cartopy/io/__init__.py:263: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/110m_cultural/ne_110m_admin_1_states_provinces_lakes.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/dimension.py:1493, in Dimensioned._repr_mimebundle_(self, include, exclude)
   1486 def _repr_mimebundle_(self, include=None, exclude=None):
   1487     """Resolves the class hierarchy for the class rendering the
   1488     object using any display hooks registered on Store.display
   1489     hooks.  The output of all registered display_hooks is then
   1490     combined and returned.
   1491 
   1492     """
-> 1493     return Store.render(self)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/options.py:1519, in Store.render(cls, obj)
   1517 data, metadata = {}, {}
   1518 for hook in hooks:
-> 1519     ret = hook(obj)
   1520     if ret is None:
   1521         continue

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/ipython/display_hooks.py:330, in pprint_display(obj)
    328 if not ip.display_formatter.formatters["text/plain"].pprint:
    329     return None
--> 330 return display(obj, raw_output=True)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/ipython/display_hooks.py:298, in display(obj, raw_output, **kwargs)
    296 elif isinstance(obj, (CompositeOverlay, ViewableElement)):
    297     with option_state(obj):
--> 298         output = element_display(obj)
    299 elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
    300     with option_state(obj):

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/ipython/display_hooks.py:193, in display_hook.<locals>.wrapped(element)
    191 try:
    192     max_frames = OutputSettings.options["max_frames"]
--> 193     mimebundle = fn(element, max_frames=max_frames)
    194     if mimebundle is None:
    195         return {}, {}

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/ipython/display_hooks.py:231, in element_display(element, max_frames)
    228 if type(element) not in Store.registry[backend]:
    229     return None
--> 231 return render(element)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/ipython/display_hooks.py:62, in render(obj, **kwargs)
     59 if renderer.fig == "pdf":
     60     renderer = renderer.instance(fig="png")
---> 62 return renderer.components(obj, **kwargs)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/renderer.py:439, in Renderer.components(self, obj, fmt, comm, **kwargs)
    437     plot = obj
    438 else:
--> 439     plot, fmt = self._validate(obj, fmt)
    441 if not isinstance(plot, Viewable):
    442     html = self._figure_data(plot, fmt, as_script=True, **kwargs)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/renderer.py:370, in Renderer._validate(self, obj, fmt, **kwargs)
    368     plot = HoloViewsPane(obj, center=self.center, backend=self.backend, renderer=self)
    369 else:
--> 370     plot = self.get_plot(obj, renderer=self, **kwargs)
    372 all_formats = set(fig_formats + holomap_formats)
    373 if fmt not in all_formats:

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/renderer.py:300, in Renderer.get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
    296     defaults = [kd.default for kd in plot.dimensions]
    297     init_key = tuple(
    298         v if d is None else d for v, d in zip(plot.keys[0], defaults, strict=None)
    299     )
--> 300     plot.update(init_key)
    301 else:
    302     plot = obj

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/mpl/plot.py:335, in MPLPlot.update(self, key)
    333 def update(self, key):
    334     if len(self) == 1 and key in (0, self.keys[0]) and not self.drawn:
--> 335         return self.initialize_plot()
    336     return self.__getitem__(key)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/mpl/plot.py:64, in mpl_rc_context.<locals>.wrapper(self, *args, **kwargs)
     62 def wrapper(self, *args, **kwargs):
     63     with _rc_context(self.fig_rcparams):
---> 64         return f(self, *args, **kwargs)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/mpl/element.py:1444, in OverlayPlot.initialize_plot(self, ranges)
   1442 ranges = self.compute_ranges(self.hmap, key, ranges)
   1443 for k, subplot in self.subplots.items():
-> 1444     subplot.initialize_plot(ranges=ranges)
   1445     if isinstance(element, CompositeOverlay):
   1446         frame = element.get(k, None)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/mpl/plot.py:64, in mpl_rc_context.<locals>.wrapper(self, *args, **kwargs)
     62 def wrapper(self, *args, **kwargs):
     63     with _rc_context(self.fig_rcparams):
---> 64         return f(self, *args, **kwargs)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/mpl/element.py:685, in ElementPlot.initialize_plot(self, ranges)
    683 if self.show_legend:
    684     style["label"] = element.label
--> 685 handles, axis_kwargs = self.render_artists(element, ranges, style, ax)
    686 self.handles.update(handles)
    688 trigger = self._trigger

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/plotting/mpl/element.py:656, in ElementPlot.render_artists(self, element, ranges, style, ax)
    655 def render_artists(self, element, ranges, style, ax):
--> 656     plot_data, plot_kwargs, axis_kwargs = self.get_data(element, ranges, style)
    657     legend = plot_kwargs.pop("cat_legend", None)
    658     with abbreviated_exception():

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/geoviews/plotting/mpl/__init__.py:237, in GeoPlot.get_data(self, element, ranges, style)
    235 def get_data(self, element, ranges, style):
    236     if self._project_operation and self.geographic:
--> 237         element = self._project_operation(element, projection=self.projection)
    238     return super().get_data(element, ranges, style)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/param/parameterized.py:6426, in ParameterizedFunction.__new__(class_, *args, **params)
   6424 inst = class_.instance()
   6425 inst.param._set_name(class_.__name__)
-> 6426 return inst.__call__(*args, **params)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/operation.py:236, in Operation.__call__(self, element, **kwargs)
    234 kwargs["link_dataset"] = self._propagate_dataset
    235 kwargs["link_inputs"] = self.p.link_inputs
--> 236 return element.apply(self, **kwargs)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/accessors.py:47, in AccessorPipelineMeta.pipelined.<locals>.pipelined_call(*args, **kwargs)
     44     inst._obj._in_method = True
     46 try:
---> 47     result = __call__(*args, **kwargs)
     49     if not in_method:
     50         init_op = factory.instance(
     51             output_type=type(inst),
     52             kwargs={"mode": getattr(inst, "mode", None)},
     53         )

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/accessors.py:228, in Apply.__call__(self, apply_function, streams, link_inputs, link_dataset, dynamic, per_element, **kwargs)
    226 if hasattr(apply_function, "dynamic"):
    227     inner_kwargs["dynamic"] = False
--> 228 new_obj = apply_function(self._obj, **inner_kwargs)
    229 if (
    230     link_dataset
    231     and isinstance(self._obj, Dataset)
    232     and isinstance(new_obj, Dataset)
    233     and new_obj._dataset is None
    234 ):
    235     new_obj._dataset = self._obj.dataset

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/operation.py:230, in Operation.__call__(self, element, **kwargs)
    226         return element.clone([(k, self._apply(el, key=k)) for k, el in element.items()])
    227     elif (self._per_element and isinstance(element, Element)) or (
    228         not self._per_element and isinstance(element, ViewableElement)
    229     ):
--> 230         return self._apply(element)
    231 elif "streams" not in kwargs:
    232     kwargs["streams"] = self.p.streams

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/operation.py:156, in Operation._apply(self, element, key)
    154     if not in_method:
    155         element._in_method = True
--> 156 ret = self._process(element, key)
    157 if hasattr(element, "_in_method") and not in_method:
    158     element._in_method = in_method

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/geoviews/operation/projection.py:72, in _project_operation._process(self, element, key)
     71 def _process(self, element, key=None):
---> 72     return element.map(self._process_element, self.supported_types)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/data/__init__.py:234, in PipelineMeta.pipelined.<locals>.pipelined_fn(*args, **kwargs)
    231     inst._in_method = True
    233 try:
--> 234     result = method_fn(*args, **kwargs)
    236     op = method_op.instance(
    237         input_type=type(inst),
    238         method_name=method_name,
    239         args=list(args[1:]),
    240         kwargs=kwargs,
    241     )
    243     if not in_method:

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/data/__init__.py:1349, in Dataset.map(self, *args, **kwargs)
   1347 @wraps(LabelledData.map)
   1348 def map(self, *args, **kwargs):
-> 1349     return super().map(*args, **kwargs)

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/holoviews/core/dimension.py:846, in LabelledData.map(self, map_fn, specs, clone)
    844     return deep_mapped
    845 else:
--> 846     return map_fn(self) if applies else self

File ~/micromamba/envs/unstructured-grid-viz-cookbook-dev/lib/python3.14/site-packages/geoviews/operation/projection.py:89, in project_path._process_element(self, element)
     86 crs = element.crs
     87 proj = self.p.projection
     88 if (isinstance(crs, ccrs.PlateCarree) and not isinstance(proj, ccrs.PlateCarree)
---> 89     and crs.proj4_params['lon_0'] != 0):
     90     element = self.instance(projection=ccrs.PlateCarree())(element)
     92 if isinstance(proj, ccrs.CRS) and not isinstance(proj, ccrs.Projection):

KeyError: 'lon_0'
:Overlay .Polygons.I :Polygons [Longitude,Latitude] (bottomDepth) .Coastline.I :Feature [Longitude,Latitude] .States.I :Feature [Longitude,Latitude]
<Figure size 666.667x666.667 with 1 Axes>