"""
MPAS to XDMF Converter
======================
This module provides the :py:class:`MpasToXdmf` class and a command-line
interface for converting MPAS NetCDF files to XDMF + HDF5 format, suitable
for visualization in ParaView and other tools.
Features
--------
- Supports cell-, edge-, and vertex-centered variables.
- Allows slicing along extra dimensions (e.g., nVertLevels).
- Combines mesh and time series files.
- Selects variables by name or by special keys (e.g., 'allOnCells').
Example Usage
-------------
Python:
>>> from mpas_tools.viz.mpas_to_xdmf.mpas_to_xdmf import MpasToXdmf
>>> converter = MpasToXdmf()
>>> converter.load(mesh_filename="mesh.nc", time_series_filenames="output.*.nc",
... variables=["temperature", "salinity"], xtime_var="xtime")
>>> converter.convert_to_xdmf(out_dir="output_dir", extra_dims={"nVertLevels": [0, 1, 2]})
Command line:
$ mpas_to_xdmf -m mesh.nc -t output.*.nc -v temperature salinity -o output_dir -d nVertLevels=0:3
See Also
--------
- Documentation: https://mpas-dev.github.io/MPAS-Tools/latest/mpas_to_xdmf.html
""" # noqa: E501
from mpas_tools.viz.mpas_to_xdmf.io import (
_convert_to_xdmf,
_load_dataset,
_parse_extra_dims,
_process_extra_dims,
)
from mpas_tools.viz.mpas_to_xdmf.mesh import _get_ds_mesh
from mpas_tools.viz.mpas_to_xdmf.time import _set_time
[docs]
class MpasToXdmf:
"""
A class for converting MPAS NetCDF files to XDMF + HDF5 format for
visualization in ParaView.
Attributes
----------
ds : xarray.Dataset
The dataset containing variables to convert.
ds_mesh : xarray.Dataset
The mesh dataset (may be the same as ds if no time series is provided).
Notes
-----
- Use the `load()` method to read mesh and time series files.
- Use `convert_to_xdmf()` to write XDMF and HDF5 files.
- Special variable keys: 'allOnCells', 'allOnEdges', 'allOnVertices'.
- Extra dimensions can be sliced using the `extra_dims` argument.
"""
[docs]
def __init__(self, ds=None, ds_mesh=None, xtime_var=None):
"""
Initialize the converter with a mesh file and optional time series
files.
Parameters
----------
ds : xarray.Dataset, optional
An xarray Dataset containing variables to convert. If ds_mesh is
not provided, ds must also contain mesh variables.
ds_mesh : xarray.Dataset, optional
An xarray Dataset representing the mesh. If not provided, ds is
used as the mesh.
xtime_var : str, optional
Name of the variable containing time information (e.g., 'xtime').
"""
if ds is not None and ds_mesh is None:
ds_mesh = ds
if ds_mesh is not None:
self.ds_mesh = _get_ds_mesh(ds_mesh)
self.ds = ds
if ds is not None:
_set_time(ds=ds, xtime_var=xtime_var)
[docs]
def load(
self,
mesh_filename,
time_series_filenames=None,
variables=None,
xtime_var=None,
):
"""
Load the MPAS mesh file and optionally combine it with time series
files into a single xarray Dataset.
Parameters
----------
mesh_filename : str
Path to the MPAS mesh file (NetCDF).
time_series_filenames : list of str or str, optional
List of NetCDF filenames or a wildcard string for time series
files. If None, only the mesh file is used.
variables : list of str, optional
List of variables to convert. Special keys:
- 'allOnCells': all variables with dimension 'nCells'
- 'allOnEdges': all variables with dimension 'nEdges'
- 'allOnVertices': all variables with dimension 'nVertices'
If None, all variables are included.
xtime_var : str, optional
Name of the variable containing time information (e.g., 'xtime').
"""
self.ds_mesh, self.ds = _load_dataset(
mesh_filename=mesh_filename,
time_series_filenames=time_series_filenames,
variables=variables,
xtime_var=xtime_var,
)
[docs]
def convert_to_xdmf(self, out_dir, extra_dims=None, quiet=False):
"""
Convert the loaded xarray Dataset to XDMF + HDF5 format.
Parameters
----------
out_dir : str
Directory where XDMF and HDF5 files will be saved.
extra_dims : dict, optional
Dictionary mapping extra dimensions to their selected indices.
Example: {'nVertLevels': [0, 1, 2]}
If None, all indices are included.
quiet : bool, optional
If True, suppress progress output.
Output
------
- XDMF files (.xdmf) and HDF5 files (.h5) in the specified directory.
Raises
------
ValueError
If required files or variables are missing.
"""
# Process extra dimensions
self.ds = _process_extra_dims(self.ds, extra_dims)
_convert_to_xdmf(
ds=self.ds,
ds_mesh=self.ds_mesh,
out_dir=out_dir,
quiet=quiet,
)
[docs]
def main():
"""
Command-line interface for the MpasToXdmf.
Usage
-----
$ mpas_to_xdmf -m mesh.nc -t output.*.nc -v temperature salinity -o output_dir -d nVertLevels=0:3
See `mpas_to_xdmf --help` for all options.
""" # noqa: E501
import argparse
parser = argparse.ArgumentParser(
description=(
'Convert MPAS NetCDF files to XDMF + HDF5 format for ParaView.'
)
)
parser.add_argument(
'-m', '--mesh', required=True, help='Path to the MPAS mesh file.'
)
parser.add_argument(
'-t',
'--time-series',
nargs='*',
help=(
'Wildcard or list of time series files. If not provided, the '
'mesh file will be used.'
),
)
parser.add_argument(
'-v',
'--variables',
nargs='*',
help=(
'List of variables to convert. Special keys include: '
"'allOnCells' (variables with dimension `nCells`), "
"'allOnEdges' (variables with dimension `nEdges`), and "
"'allOnVertices' (variables with dimension `nVertices`). "
'If not provided, all variables will be converted.'
),
)
parser.add_argument(
'-o',
'--output-dir',
required=True,
help='Directory to save XDMF files.',
)
parser.add_argument(
'-x',
'--xtime',
help='Name of the variable containing time information.',
)
parser.add_argument(
'-d',
'--dim-list',
nargs='+',
help=(
'List of dimensions and indices to slice '
'(e.g., nVertLevels=0:10:2).'
),
)
parser.add_argument(
'-q',
'--quiet',
action='store_true',
help='Suppress progress output.',
)
args = parser.parse_args()
converter = MpasToXdmf()
converter.load(
mesh_filename=args.mesh,
time_series_filenames=args.time_series,
variables=args.variables,
xtime_var=args.xtime,
)
# Parse extra dimensions
extra_dims = _parse_extra_dims(args.dim_list, converter.ds)
converter.convert_to_xdmf(
out_dir=args.output_dir,
extra_dims=extra_dims,
quiet=args.quiet,
)