Skip to content

Utils

Utility functions for Tolvera.

CONSTS

Dict of CONSTS that can be used in Taichi scope

Source code in src/tolvera/utils.py
class CONSTS:
    """
    Dict of CONSTS that can be used in Taichi scope
    """

    def __init__(self, dict: dict[str, (DataType, Any)]):
        self.struct = ti.types.struct(**{k: v[0] for k, v in dict.items()})
        self.consts = self.struct(**{k: v[1] for k, v in dict.items()})

    def __getattr__(self, name):
        try:
            return self.consts[name]
        except:
            raise AttributeError(f"CONSTS has no attribute {name}")

    def __getitem__(self, name):
        try:
            return self.consts[name]
        except:
            raise AttributeError(f"CONSTS has no attribute {name}")

dotdict

Bases: dict

dot.notation access to dictionary attributes

Source code in src/tolvera/utils.py
class dotdict(dict):
    """dot.notation access to dictionary attributes"""
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

create_and_validate_slice(arg, target_array)

Creates and validates a slice object based on the target array.

Source code in src/tolvera/utils.py
def create_and_validate_slice(
    arg: Union[int, tuple[int, ...], slice], target_array: np.ndarray
) -> slice:
    """
    Creates and validates a slice object based on the target array.
    """
    try:
        slice_obj = create_safe_slice(arg)
        if not validate_slice(slice_obj, target_array):
            raise ValueError(f"Invalid slice: {slice_obj}")
        return slice_obj
    except Exception as e:
        raise type(e)(f"Error creating slice: {e}")

create_ndslices(dims)

Create a multi-dimensional slice from a list of tuples.

Parameters:

Name Type Description Default
dims list[tuple]

A list of tuples containing the slice parameters for each dimension.

required

Returns:

Type Description
s_

np.s_: A multi-dimensional slice object.

Source code in src/tolvera/utils.py
def create_ndslices(dims: list[tuple]) -> np.s_:
    """
    Create a multi-dimensional slice from a list of tuples.

    Args:
        dims (list[tuple]): A list of tuples containing the slice parameters for each dimension.

    Returns:
        np.s_: A multi-dimensional slice object.
    """
    return np.s_[tuple(slice(*dim) if isinstance(dim, tuple) else dim for dim in dims)]

create_safe_slice(arg)

Creates a slice object based on the input argument.

Parameters:

Name Type Description Default
arg (int, tuple, slice)

The argument for creating the slice. It can be an integer, a tuple with slice parameters, or a slice object itself.

required

Returns:

Name Type Description
slice slice

A slice object created based on the provided argument.

Source code in src/tolvera/utils.py
def create_safe_slice(arg: Union[int, tuple[int, ...], slice]) -> slice:
    """
    Creates a slice object based on the input argument.

    Args:
        arg (int, tuple, slice): The argument for creating the slice. It can be an integer,
                                 a tuple with slice parameters, or a slice object itself.

    Returns:
        slice: A slice object created based on the provided argument.
    """
    try:
        if isinstance(arg, slice):
            return arg
        elif isinstance(arg, tuple):
            return slice(*arg)
        elif isinstance(arg, int):
            return slice(arg, arg + 1)
        else:
            raise TypeError(f"Invalid slice type: {type(arg)} {arg}")
    except Exception as e:
        raise type(e)(f"[create_safe_slice] Error creating slice: {e}")

flatten(lst)

Flatten a nested list or return a non-nested list as is.

Source code in src/tolvera/utils.py
def flatten(lst):
    """Flatten a nested list or return a non-nested list as is."""
    if all(isinstance(el, list) for el in lst):
        return [item for sublist in lst for item in sublist]
    return lst

generic_slice(array, slice_params)

Slices a NumPy array based on a tuple of slice parameters for each dimension.

Parameters:

Name Type Description Default
array ndarray

The array to be sliced.

required
slice_params tuple

A tuple where each item is either an integer, a tuple with slice parameters, or a slice object.

required

Returns:

Name Type Description
ndarray ndarray

The sliced array.

Source code in src/tolvera/utils.py
def generic_slice(
    array: np.ndarray,
    slice_params: Union[
        tuple[Union[int, tuple[int, ...], slice], ...],
        Union[int, tuple[int, ...], slice],
    ],
) -> np.ndarray:
    """
    Slices a NumPy array based on a tuple of slice parameters for each dimension.

    Args:
        array (np.ndarray): The array to be sliced.
        slice_params (tuple): A tuple where each item is either an integer, a tuple with
                             slice parameters, or a slice object.

    Returns:
        ndarray: The sliced array.
    """
    if not isinstance(slice_params, tuple):
        slice_params = (slice_params,)
    slices = tuple(create_safe_slice(param) for param in slice_params)
    return array.__getitem__(slices)

time_function(func, *args, **kwargs)

Time how long it takes to run a function and print the result

Source code in src/tolvera/utils.py
def time_function(func, *args, **kwargs):
    """Time how long it takes to run a function and print the result"""
    start = time.time()
    ret = func(*args, **kwargs)
    end = time.time()
    print(f"[Tolvera.utils] {func.__name__}() ran in {end-start:.4f}s")
    if ret is not None:
        return (ret, end - start)
    return end - start

validate_json_path(path)

Validate a JSON file path. It uses validate_path for initial validation.

Parameters:

Name Type Description Default
path str

The JSON file path to be validated.

required

Returns:

Name Type Description
bool bool

True if the path is a valid JSON file path, raises an exception otherwise.

Raises:

Type Description
ValueError

If the path does not end with '.json'.

Source code in src/tolvera/utils.py
def validate_json_path(path: str) -> bool:
    """
    Validate a JSON file path. It uses validate_path for initial validation.

    Args:
        path (str): The JSON file path to be validated.

    Returns:
        bool: True if the path is a valid JSON file path, raises an exception otherwise.

    Raises:
        ValueError: If the path does not end with '.json'.
    """
    # Using validate_path for basic path validation
    validate_path(path)

    if not path.endswith(".json"):
        raise ValueError("Path should end with '.json'")

    return True

validate_path(path)

Validate a path using os.path and pathlib.

Parameters:

Name Type Description Default
path str

The path to be validated.

required

Returns:

Name Type Description
bool bool

True if the path is valid, raises an exception otherwise.

Raises:

Type Description
TypeError

If the input is not a string.

FileNotFoundError

If the path does not exist.

PermissionError

If the path is not accessible.

Source code in src/tolvera/utils.py
def validate_path(path: str) -> bool:
    """
    Validate a path using os.path and pathlib.

    Args:
        path (str): The path to be validated.

    Returns:
        bool: True if the path is valid, raises an exception otherwise.

    Raises:
        TypeError: If the input is not a string.
        FileNotFoundError: If the path does not exist.
        PermissionError: If the path is not accessible.
    """
    if not isinstance(path, str):
        raise TypeError(f"Expected a string for path, but received {type(path)}")

    path_obj = Path(path)
    if not path_obj.is_file():
        raise FileNotFoundError(f"The path {path} does not exist or is not a file")

    if not os.access(path, os.R_OK):
        raise PermissionError(f"The path {path} is not accessible")

    return True

validate_slice(slice_obj, target_array)

Validates if the given slice object is applicable to the target ndarray.

Parameters:

Name Type Description Default
slice_obj tuple[slice]

A tuple containing slice objects for each dimension.

required
target_array ndarray

The array to be sliced.

required

Returns:

Name Type Description
bool bool

True if the slice is valid for the given array, False otherwise.

Source code in src/tolvera/utils.py
def validate_slice(slice_obj: tuple[slice], target_array: np.ndarray) -> bool:
    """
    Validates if the given slice object is applicable to the target ndarray.

    Args:
        slice_obj (tuple[slice]): A tuple containing slice objects for each dimension.
        target_array (np.ndarray): The array to be sliced.

    Returns:
        bool: True if the slice is valid for the given array, False otherwise.
    """
    if len(slice_obj) != target_array.ndim:
        return False

    for sl, size in zip(slice_obj, target_array.shape):
        # Check if slice start and stop are within the dimension size
        start, stop, _ = sl.indices(size)
        if not (0 <= start < size and (0 <= stop <= size or stop == -1)):
            return False
    return True