utils module#

This module provides common utility functions for the xsnow package.

These functions are designed to be used across different modules to reduce code duplication and improve maintainability.

xsnow.utils.get_logger(name, to_console=True, level_console=20, to_file=False, logfile=None, level_file=10, logger=None, alter_logger=False)#

Create or adjust a logger with optional console and file handlers.

Parameters:
  • name (str) – Logger name to use if a logger instance is not provided.

  • to_console (bool) – Whether to log to the console (stream handler).

  • level_console (int) – Logging level for console output.

  • to_file (bool) – Whether to log to a file.

  • logfile (Optional[str]) – Path to the logfile when to_file is True.

  • level_file (int) – Logging level for file output.

  • logger (Optional[Logger]) – An existing logger to configure. If provided and alter_logger is False, the logger is returned unchanged.

  • alter_logger (bool) – When True, update the provided logger to match the requested handlers and levels. When False, the logger is returned as-is.

Return type:

Logger

Returns:

A configured logging.Logger instance.

Raises:
  • ValueError – If to_file is True but neither logfile nor an

  • existing file handler on logger is available.

xsnow.utils.get_backend(array_like)#

Determines the appropriate numerical backend (NumPy or CuPy) for a given object.

This function inspects the underlying data in an xarray object to see if it’s a CuPy array (on a GPU) or a NumPy array (on the CPU) and returns the corresponding module.

Parameters:

array_like (Union[xsnowDataset, Dataset, DataArray]) – An xsnowDataset, xarray.Dataset, or xarray.DataArray.

Return type:

Any

Returns:

The numpy or cupy module.

xsnow.utils.print(*values, force_details=False, **kwargs)#

xsnow-aware print that can force detailed __repr__ on xsnowDataset objects.

Parameters:
  • *values (Any) – Values to print.

  • force_details (bool) – If True, call xsnowDataset.__repr__(force_details=True) on any xsnowDataset arguments.

  • **kwargs (Any) – Passed through to built-in print (sep, end, file, flush).

Return type:

None

xsnow.utils.normalize_slope_coords(ds, slope_coord_names=None, verify_consistency=True, allow_per_location=False, logger=None)#

Normalize slope coordinates to have only ‘slope’ dimension.

When combining datasets from multiple locations, slope metadata like ‘azimuth’ and ‘inclination’ may end up with dimensions (location, slope) instead of just (slope). This function fixes that by:

  1. Detecting coordinates that have both ‘location’ and ‘slope’ dimensions

  2. Verifying values are consistent across locations (if requested)

  3. Reducing to just the ‘slope’ dimension (or keeping per-location if allowed)

Parameters:
  • ds (xr.Dataset) – Input dataset potentially with multi-dimensional slope coords

  • slope_coord_names (list of str, optional) – Explicit list of coordinate names to normalize. If None, will auto-detect coordinates with ‘slope’ dimension that also have other dimensions.

  • verify_consistency (bool, default True) – If True, verify that slope coordinate values are identical across all locations before reducing dimensions. Raises ValueError if inconsistent and allow_per_location=False.

  • allow_per_location (bool, default False) – If True, when slopes vary by location, preserve the (location, slope) dimensions instead of forcing normalization. This is useful when different locations legitimately have different slope angles.

  • logger (logging.Logger, optional) – Provide user configured logger, or create new one per default

Returns:

Dataset with normalized slope coordinates

Return type:

xr.Dataset

Raises:

ValueError – If verify_consistency=True, allow_per_location=False, and slope coordinates vary across locations

Examples

>>> ds = xsnow.read("data/pros/gridded/")
>>> # azimuth might have dims (location, slope)
>>> ds = normalize_slope_coords(ds)
>>> # Now azimuth has only (slope,)
>>> # Allow per-location slopes to be preserved
>>> ds = normalize_slope_coords(ds, allow_per_location=True)
>>> # If slopes differ, keeps (location, slope) dimensions

Notes

This function modifies coordinate dimensions but preserves all data variables unchanged. It’s designed to be called after merging datasets from multiple locations.

xsnow.utils.detect_slope_coord_issues(ds)#

Detect potential issues with slope coordinate dimensions.

Returns a diagnostic dictionary describing any problems found.

Parameters:

ds (xr.Dataset) – Dataset to check

Returns:

Diagnostic information with keys: - ‘has_issues’: bool, True if problems detected - ‘multidim_coords’: list of coordinate names with multiple dimensions - ‘inconsistent_coords’: list of coordinates that vary across locations - ‘recommendations’: list of suggested fixes

Return type:

dict

xsnow.utils.reorder_dims(ds, preferred_order=('location', 'time', 'slope', 'realization', 'layer'), last_dims=None)#

Reorder dataset dimensions without dropping data, coords, or attrs.

Parameters:
  • ds (xsnowDataset or xr.Dataset) – Dataset to reorder.

  • preferred_order (sequence of str) – Dimensions to place first in the given order.

  • last_dims (sequence of str, optional) – Dimensions to force to the end in the given order.

Return type:

Union[xsnowDataset, Dataset]

Notes

  • Any dimensions not in preferred_order or last_dims keep their original relative order and are placed between the two groups.

  • All coordinates, data variables, attrs, and encoding are preserved.

  • Rebuilds the dataset to enforce deterministic discovery order for ds.dims.