Auxiliary functions

Auxiliary functions for QC.

marine_qc.auxiliary.convert_to(value, source_units, target_units)[source]

Convert a float or sequence from source units to target units.

Parameters:
  • value (SequenceNumberType) – A single float value, None, or a sequence (e.g., list, tuple, array-like) containing floats and/or None values. None values are passed through unchanged.

  • source_units (str) – The unit(s) of the input value(s), e.g., ‘degC’, ‘km/h’.

  • target_units (str) – The unit(s) to convert to, e.g., ‘K’, ‘m/s’. If set to “unknown”, the value(s) will be converted to the base SI units of the source_units, e.g., ‘degC’ to ‘kelvin’, ‘km/h’ to ‘meter/s’.

Return type:

SequenceNumberType

Returns:

SequenceNumberType – The converted value(s), preserving the input structure (scalar, list, tuple, array). None values remain unchanged.

Examples

>>> convert_to(100, "degC", "K")
373.15
>>> convert_to([0, 100], "degC", "K")
[273.15, 373.15]
>>> convert_to([None, 100], "degC", "K")
[None, 373.15]
>>> convert_to(5, "km", "unknown")  # Converts to base unit 'meter'
5000.0
marine_qc.auxiliary.convert_units(**units_by_name)[source]

Decorator to automatically convert specified function arguments to target units.

This decorator allows a function to accept inputs in various units and automatically converts them to desired target units before the function executes. It is especially useful for scientific or engineering functions where users may provide inputs in different unit systems.

Parameters:

**units_by_name (str) – Keyword arguments mapping function argument names to their target units. Special case: if a target unit is “unknown”, it will be converted to the base SI unit for the given source unit (e.g., “degC” ? “K”, “km/h” ? “m/s”).

Return type:

Callable[..., Any]

Returns:

Callable[..., Any] – A decorator that converts specified parameters to the target units prior to executing the decorated function.

Notes

  • The decorated function must be called with a units keyword argument, which can be:
    • A dictionary mapping argument names to their source units, or

    • A single string unit applied to all arguments.

  • Parameters not listed in units_by_name are not converted.

  • Parameters with None values are skipped.

  • If a target unit is “unknown”, the value is converted to the base SI unit.

Examples

>>> @convert_units(temperature="K")
... def func_single(temperature):
...     print(f"Temperature: {temperature:.2f} K")
>>> func_single(25.0, units={"temperature": "degC"})
Temperature: 298.15 K
>>> @convert_units(speed="m/s", altitude="m")
... def func_multiple(speed, altitude):
...     print(f"Speed: {speed:.1f} m/s, Altitude: {altitude:.0f} m")
>>> func_multiple(72.0, 0.5, units={"speed": "km/h", "altitude": "km"})
Speed: 20.0 m/s, Altitude: 500 m
>>> @convert_units(distance="unknown")
... def func_base(distance):
...     print(f"Distance in SI units: {distance} m")
>>> func_base(1.2, units={"distance": "km"})
Distance in SI units: 1200.0 m
marine_qc.auxiliary.ensure_arrays(**values)[source]

Ensure that all input values are NumPy arrays.

Parameters:

**values (Mapping[str, Any]) – Mapping of names to values expected to be NumPy arrays.

Return type:

tuple[ndarray[tuple[Any, ...], dtype[Any]], ...]

Returns:

tuple of np.ndarray – A tuple containing the NumPy arrays corresponding to the input values, in the same order as provided.

Raises:

TypeError – If any input value is not a NumPy array.

marine_qc.auxiliary.format_return_type(result_array, *input_values, dtype=<class 'int'>)[source]

Convert the result numpy array(s) to the same type as the input value.

If result_array is a sequence of arrays, format each element recursively, preserving the container type.

Parameters:
  • result_array (np.ndarray) – The numpy array of results.

  • *input_values (Any) – One or more original input values to infer the desired return type from.

  • dtype (type, optional) – Desired data type of the result. Default is int.

Return type:

Any

Returns:

Same type as input(s) – The result formatted to match the type of the first valid input value.

marine_qc.auxiliary.generic_decorator(pre_handler=None, post_handler=None)[source]

Create a decorator that binds function arguments and applies pre- and post-processing handlers.

This decorator factory allows you to inspect, modify, or validate function arguments before and after the original function is called. Reserved keyword arguments can be passed to the handlers via _decorator_kwargs and removed from the call to the original function.

Parameters:
  • pre_handler (Callable[[dict], None]) – A function that takes the bound arguments dictionary (bound_args.arguments) and optionally additional keyword arguments, to inspect or modify arguments before the decorated function executes. Signature: handler(arguments: dict, **meta_kwargs) -> None.

  • post_handler (Callable[[dict], None]) – A function that takes the bound arguments dictionary (bound_args.arguments) and optionally additional keyword arguments, to inspect or modify arguments after the decorated function executes. Signature: handler(arguments: dict, **meta_kwargs) -> None.

Return type:

Callable[..., Any]

Returns:

Callable – A decorator that wraps any function. When applied, the function’s arguments are bound and passed to the handlers before execution.

Notes

  • Handlers can define a _decorator_kwargs attribute (a set of reserved keyword argument names). These reserved kwargs will be extracted from the decorated function’s call kwargs, passed to the handler, and removed before calling the original function.

  • The original function is called with the possibly modified bound arguments after handler processing.

marine_qc.auxiliary.inspect_arrays(params, sortby=None)[source]

Decorator to convert and validate specified function input parameters as 1D NumPy arrays.

This decorator ensures that specified input arguments are sequence-like, converts them to 1D NumPy arrays, validates that they are one-dimensional, and checks that all arrays have the same length. Optionally, the arrays can be sorted by another parameter and later restored to the original order.

Parameters:
  • params (list of str) – Names of parameters to inspect in the decorated function. Each specified parameter will be converted to a 1D NumPy array and validated.

  • sortby (str, optional) – Name of a parameter to sort the arrays by, if desired. The result will be returned in the original order of this parameter.

Return type:

Callable[..., Any]

Returns:

Callable[..., Any] – A decorator that, when applied, converts the specified parameters to 1D NumPy arrays, validates them, optionally sorts them, and passes them to the decorated function.

Raises:

ValueError – If a specified parameter is missing from the function arguments. If any specified parameter is not one-dimensional. If the lengths of the specified arrays do not all match.

Notes

  • If sortby is specified, the result of the function is reordered to match the original order of sortby after the function executes.

Examples

>>> @inspect_arrays(["a", "b"])
... def add_arrays(a, b):
...     return a + b
>>> add_arrays([1, 2, 3], [4, 5, 6])
array([5, 7, 9])
>>> add_arrays([1, 2], [3, 4, 5])
Traceback (most recent call last):
    ...
ValueError: Input ['a', 'b'] must all have the same length.
marine_qc.auxiliary.is_scalar_like(x)[source]

Return True if the input is scalar-like.

A value is considered scalar-like if it is one of the following:

  • Built-in Python scalars: int, float, bool, None

  • Strings and bytes

  • NumPy scalars (subclasses of np.generic), e.g. np.int32, np.float64, np.datetime64

  • Zero-dimensional NumPy arrays (e.g. np.array(5))

  • Pandas scalar types:
    • pd.Timestamp

    • pd.Timedelta

    • pd.NA

    • pd.NaT

  • Python datetime types:
    • datetime.date

    • datetime.datetime

    • datetime.time

Container types such as lists, tuples, sets, dicts, pandas Series, pandas DataFrame, and NumPy arrays with one or more dimensions are not considered scalar-like.

Parameters:

x (Any) – The value to check.

Return type:

bool

Returns:

bool – True if x is scalar-like, False otherwise.

marine_qc.auxiliary.isvalid(inval)[source]

Check if a value(s) are numerically valid (not None or NaN).

Parameters:

inval (ValueNumberType) – Input value(s) to be tested.

Return type:

bool | ndarray[tuple[Any, ...], dtype[bool]]

Returns:

bool or np.ndarray of bool – Returns False where the input is None or NaN, True otherwise. Returns a boolean scalar if input is scalar, else a boolean array.

marine_qc.auxiliary.post_format_return_type(params, dtype=<class 'int'>, multiple=False)[source]

Decorator to format a function’s return value to match the type of its original input(s).

This decorator ensures that the output of the decorated function is converted back to the same structure/type as the original input(s) specified by params. It uses a context object (_ctx) if available to retrieve the original inputs before any preprocessing was applied. If no context is found, it falls back to the current bound arguments.

Parameters:
  • params (list of str) – List of parameter names whose original input types should be used to format the return value.

  • dtype (type, optional) – Desired data type of the result. Default is int.

  • multiple (bool, optional) – If True, assumes the function returns a sequence of results (e.g., a tuple), and applies format_return_type to each element individually. If False (default), applies format_return_type once on the entire result.

Return type:

Callable[..., Any]

Returns:

Callable[..., Any] – A decorator that modifies the decorated function’s output to match the input types.

Notes

  • Assumes a TypeContext object may be passed via _ctx keyword argument, storing original input values for accurate type formatting.

  • Falls back gracefully if no context is available, using current arguments.

  • Useful when function inputs are preprocessed (e.g., converted to arrays), and the output should match the original input types.