Source code for pyfracval.utils

"""Utility functions for vector operations and array manipulation.

.. deprecated::
    This module is being split into domain-specific sub-modules.
    Import from the specific module instead:

    - :mod:`pyfracval.geometry` — Rodrigues rotation, sphere intersection
    - :mod:`pyfracval.fractal` — Fractal metrics and validation
    - :mod:`pyfracval.overlap` — Overlap calculation dispatch
    - :mod:`pyfracval.cca_kernels` — CCA-specific JIT kernels
    - :mod:`pyfracval.pca_kernels` — PCA-specific JIT kernels

All symbols remain importable from this module for backward compatibility.
"""

import logging

import numpy as np

from .cca_kernels import (
    _GOLDEN_RATIO,
    _TWO_PI,
    _cca_reintento_kernel,
    batch_check_overlaps_cca,
    batch_rotate_cluster_cca,
)
from .fractal import (
    calculate_cluster_properties,
    calculate_mass,
    calculate_rg,
    compute_empirical_rg,
    compute_pair_correlation_dimensions,
    gamma_calculation,
    validate_fractal_structure,
)
from .geometry import (
    FLOATING_POINT_ERROR,
    _rodrigues_rotation_2d,
    _two_sphere_intersection_kernel,
    random_point_sc,
    rodrigues_rotation,
    spherical_cap_angle,
    two_sphere_intersection,
)
from .overlap import (
    PARALLEL_OVERLAP_THRESHOLD,
    calculate_max_overlap_cca,
    calculate_max_overlap_cca_auto,
    calculate_max_overlap_cca_fast,
    calculate_max_overlap_cca_parallel,
    calculate_max_overlap_pca,
    calculate_max_overlap_pca_auto,
    calculate_max_overlap_pca_fast,
    calculate_max_overlap_pca_parallel,
)
from .pca_kernels import (
    batch_calculate_positions_pca,
    batch_check_overlaps_pca,
)

logger = logging.getLogger(__name__)


[docs] def shuffle_array( arr: np.ndarray, rng: np.random.Generator | None = None ) -> np.ndarray: """Randomly shuffle elements of a 1D array in-place (Fisher-Yates). Modifies the input array directly. Mimics Fortran randsample behavior. Parameters ---------- arr : The 1D NumPy array to shuffle. rng : np.random.Generator | None, optional A NumPy Generator instance for reproducible randomness. If None, a fresh Generator is created. Returns ------- The input `arr`, modified in-place. """ _rng = rng if rng is not None else np.random.default_rng() n = len(arr) for i in range(n - 1): # Random index from i to n-1 j = int(_rng.integers(i, n)) # Swap elements arr[i], arr[j] = arr[j], arr[i] return arr
[docs] def sort_clusters(i_orden: np.ndarray) -> np.ndarray: """Sort cluster information array `i_orden` by cluster size (count). Parameters ---------- i_orden : np.ndarray The Mx3 NumPy array [start_idx, end_idx, count]. Returns ------- np.ndarray A new Mx3 array sorted by the 'count' column (column index 2). Raises ------ ValueError If `i_orden` is not an Mx3 array. """ if i_orden.ndim != 2 or i_orden.shape[1] != 3: raise ValueError("i_orden must be an Mx3 array") if i_orden.shape[0] == 0: return i_orden # Return empty array if input is empty # Get the indices that would sort the 'count' column (index 2) sort_indices = np.argsort(i_orden[:, 2], kind="stable") return i_orden[sort_indices]
# def cross_product(a: np.ndarray, b: np.ndarray) -> np.ndarray: # """Calculate the cross product of two 3D vectors. # Parameters # ---------- # a : np.ndarray # The first 3D vector. # b : np.ndarray # The second 3D vector. # Returns # ------- # np.ndarray # The 3D cross product vector. # See Also # -------- # numpy.cross : NumPy's implementation. # """ # return np.cross(a, b) # def normalize(v: np.ndarray) -> np.ndarray: # """Normalize a vector to unit length. # Returns a zero vector if the input vector's norm is close to zero. # Parameters # ---------- # v : np.ndarray # The vector (1D array) to normalize. # Returns # ------- # np.ndarray # The normalized vector, or a zero vector if the norm is negligible. # """ # norm = np.linalg.norm(v) # if norm < 1e-12: # Use tolerance instead of exact zero check # return np.zeros_like(v) # return v / norm __all__ = [ "FLOATING_POINT_ERROR", "rodrigues_rotation", "_rodrigues_rotation_2d", "two_sphere_intersection", "_two_sphere_intersection_kernel", "spherical_cap_angle", "random_point_sc", "calculate_mass", "calculate_rg", "gamma_calculation", "calculate_cluster_properties", "compute_empirical_rg", "compute_pair_correlation_dimensions", "validate_fractal_structure", "PARALLEL_OVERLAP_THRESHOLD", "calculate_max_overlap_cca", "calculate_max_overlap_pca", "calculate_max_overlap_pca_fast", "calculate_max_overlap_cca_fast", "calculate_max_overlap_pca_parallel", "calculate_max_overlap_cca_parallel", "calculate_max_overlap_pca_auto", "calculate_max_overlap_cca_auto", "_GOLDEN_RATIO", "_TWO_PI", "_cca_reintento_kernel", "batch_check_overlaps_cca", "batch_rotate_cluster_cca", "batch_calculate_positions_pca", "batch_check_overlaps_pca", "shuffle_array", "sort_clusters", ]