Source code for oineus.diff.cubical

from typing import Optional

import numpy as np
import eagerpy as epy

from .. import _oineus
from .diff_filtration import DiffFiltration
from ._tensor_utils import tensor_to_real_numpy, gather_values


_GRID_CLASS_BY_NDIM = {
    1: _oineus.Grid_1D,
    2: _oineus.Grid_2D,
    3: _oineus.Grid_3D,
}


[docs] def cube_filtration(data, negate: bool = False, wrap: bool = False, max_dim: Optional[int] = None, values_on: str = "vertices", n_threads: int = 1) -> DiffFiltration: """Differentiable cubical filtration from tensor-valued grid data. Mirrors `oineus.cube_filtration`, but returns a `DiffFiltration` whose filtration values are gathered back onto the autograd-tracked input. Args: data: 1D/2D/3D tensor-like (PyTorch/JAX/NumPy) of grid values. negate: Compute upper-star (superlevel) instead of lower-star. wrap: Not supported; raises if True. max_dim: Maximal cube dimension; defaults to ``data.ndim``. values_on: ``"vertices"`` (default) or ``"cells"``. Critical indices are flat indices into the original data array in either case. n_threads: Threads for C++ filtration construction. """ if wrap: raise RuntimeError("cube_filtration: wrap=True is not supported") tensor = epy.astensor(data) np_data = tensor_to_real_numpy(tensor) ndim = np_data.ndim grid_cls = _GRID_CLASS_BY_NDIM.get(ndim) if grid_cls is None: raise RuntimeError( f"cube_filtration: data.ndim={ndim} not supported, must be 1, 2, or 3" ) if max_dim is None: max_dim = ndim grid = grid_cls(np_data, wrap=wrap, values_on=values_on) fil, crit = grid.cube_filtration_and_critical_indices( max_dim=max_dim, negate=negate, n_threads=n_threads, ) crit = np.asarray(crit, dtype=np.int64) values = gather_values(tensor, crit) return DiffFiltration(fil, values)