Source code for ugants.utils
# (C) Crown Copyright, Met Office. All rights reserved.
#
# This file is part of UG-ANTS and is released under the BSD 3-Clause license.
# See LICENSE.txt in the root of the repository for full licensing details.
"""General processing utility routines."""
def _check_and_normalise_index_in_range(dimension_index, number_of_dimensions, name):
"""
Check that a dimension index is in a given range, and convert negative values.
Convert any -N to (ndims - N).
Error if the resulting index is < 0 or >= ndim.
Parameters
----------
dimension_index : int
index of an array dimension
number_of_dimensions : int
number of dimensions of parent object
name : str
original arg-name, for constructing error message only
Returns
-------
int
a valid dimension number, always between 0 and (ndims - 1)
"""
result = dimension_index
if result < 0:
result += number_of_dimensions
if result < 0 or result >= number_of_dimensions:
message = (
f"Value of '{name}' arg is out of valid range "
f"-{number_of_dimensions} to {number_of_dimensions - 1} : "
f"got {dimension_index}."
)
raise ValueError(message)
return result
def _one_dimension_transpose_indices(number_of_dimensions, from_dim, to_dim):
"""
Return suitable transposition indices to re-locate one dimension of an array-like.
Parameters
----------
number_of_dimensions : int
the number of dimensions in the array-like to be transposed. Also, the number
of indices in the result.
from_dim : int
the dimension number to 'move'. ``-1`` means the last
to_dim : int
new index of the moved dimension. ``0`` means to first dim, ``-1`` to the last.
Returns
-------
list of int
The appropriate indices to pass into a 'transpose' call,
e.g. :func:`numpy.transpose` or :meth:`iris.cube.Cube.transpose`.
Contains the values 0 .. ('ndims' - 1), in some permutation.
"""
if number_of_dimensions == 0:
raise ValueError("Cannot transpose with 0 dimensions.")
from_dim = _check_and_normalise_index_in_range(
from_dim, number_of_dimensions, "from_dim"
)
to_dim = _check_and_normalise_index_in_range(to_dim, number_of_dimensions, "to_dim")
dims = list(range(number_of_dimensions))
dims.remove(from_dim)
dims = dims[:to_dim] + [from_dim] + dims[to_dim:]
return dims
[docs]
def move_one_dimension(content, from_dim, to_dim):
"""
Move one dimension of an array.
Transpose the input, to shift the selected dimension from one place to another in
the index order. Negative indices are also supported.
Parameters
----------
content : :class:`numpy.ndarray` or :class:`iris.cube.Cube`
an array-like (cube, numpy or Dask array) to be transposed
from_dim : int
the dimension number to 'move'. ``-1`` means the last
to_dim : int
index of the 'moved' dimension within the output.
``0`` means to the first dimension, ``-1`` to the last.
Returns
-------
:class:`numpy.ndarray` or :class:`iris.cube.Cube`
the result of an appropriate ``content.transpose()`` operation.
"""
ndims = content.ndim
dims = _one_dimension_transpose_indices(ndims, from_dim, to_dim)
result = content.transpose(dims)
return result