Source code for mhm_tools.post.ratio

"""
Compute the spatial ratio between model and reference datasets.

This script is intended for NetCDF files that represent aggregated fields
(e.g., long-term averages, climatologies, or single-time snapshots), rather
than full time series. It interpolates the model dataset onto the reference
grid to ensure spatial alignment and then computes the ratio (model ÷ reference)
at each grid cell. Division by zero is handled safely by masking with NaN.

The result is plotted as a map and, if requested, saved as a NetCDF file.

Authors
-------
- Jeisson Leal
"""

from pathlib import Path
from typing import Optional

import numpy as np
import xarray as xr

from mhm_tools.common.file_handler import write_xarray_to_file
from mhm_tools.common.netcdf import read_dataset
from mhm_tools.common.plotter import plot_map
from mhm_tools.common.xarray_utils import get_coord_key, normalize_lat_lon


[docs] def calc_ratio( # noqa: PLR0913 ref_input_dir: str, mod_input_dir: str, reference_pattern: str, model_pattern: str, ref_var: str, mod_var: str, colorbar_label: str, title: str, output_dir: str, output_file_png: str, save_ncfile: bool, output_file_nc: str, x_min: Optional[float] = None, x_max: Optional[float] = None, y_min: Optional[float] = None, y_max: Optional[float] = None, cmap: str = "RdBu", vmin: Optional[float] = None, vmax: Optional[float] = None, ) -> None: """Compute long-term mean ratio between model and reference datasets and plot the result.""" ds_ref = read_dataset(file_path=str(Path(ref_input_dir) / reference_pattern)) ds_mod = read_dataset(file_path=str(Path(mod_input_dir) / model_pattern)) # Gets coords names ref_lat = get_coord_key(ds_ref, lat=True) ref_lon = get_coord_key(ds_ref, lon=True) mod_lat = get_coord_key(ds_mod, lat=True) mod_lon = get_coord_key(ds_mod, lon=True) # Sets lon and lat names and lat and lon and returns the da da_ref = normalize_lat_lon(ds_ref, lat_key=ref_lat, lon_key=ref_lon)[ ref_var ].squeeze("time") da_mod = normalize_lat_lon(ds_mod, lat_key=mod_lat, lon_key=mod_lon)[ mod_var ].squeeze("time") # Interpolate model to reference grid to avoid alignment errors da_mod_interp = da_mod.interp_like(da_ref) # calculating ratio, if true prevents division by 0 ratio = xr.where(da_ref != 0, da_mod_interp / da_ref, np.nan) # Sets output path to save plot out_path_dir = Path(output_dir) out_path_dir.mkdir(parents=True, exist_ok=True) out_path = out_path_dir / output_file_png plot_map( data=ratio, cb_label=colorbar_label, title=title, out_path=out_path, cmap=cmap, x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max, vmin=vmin, vmax=vmax, ) # If set, saves ratio file if save_ncfile: write_xarray_to_file(ds=ratio, file_path=out_path_dir / output_file_nc)