Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/pyrecest/_backend/jax/random/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ def _validate_and_classify_multivariate_normal_cov(cov, mean_dim):
raise ValueError("cov must be positive semidefinite")

scale = _LEGACY._jnp.max(_LEGACY._jnp.abs(eigenvalues))
rank_tolerance = (
_LEGACY._jnp.finfo(cov_float.dtype).eps * max(mean_dim, 1) * scale
)
rank_tolerance = _LEGACY._jnp.finfo(cov_float.dtype).eps * max(mean_dim, 1) * scale
requires_svd = bool(_LEGACY._jnp.any(eigenvalues <= rank_tolerance))
return cov, requires_svd

Expand Down
10 changes: 7 additions & 3 deletions src/pyrecest/_backend/numpy/linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@

from .._shared_numpy.linalg import (
_normalize_fractional_matrix_power_exponent,
fractional_matrix_power as _fractional_matrix_power,
)
from .._shared_numpy.linalg import fractional_matrix_power as _fractional_matrix_power
from .._shared_numpy.linalg import (
is_single_matrix_pd,
logm as _logm,
)
from .._shared_numpy.linalg import logm as _logm
from .._shared_numpy.linalg import (
polar,
qr,
quadratic_assignment,
solve,
solve_sylvester,
sqrtm as _sqrtm,
)
from .._shared_numpy.linalg import sqrtm as _sqrtm


def _empty_zero_by_zero_matrix_result(value):
Expand Down
4 changes: 1 addition & 3 deletions src/pyrecest/_backend/pytorch/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,7 @@ def _validate_randint_array_dtype_bounds(low, high, dtype):
# representable by the output dtype, as in randint(255, 256, dtype=uint8).
# For int64, input tensors cannot represent max + 1, so every accepted high
# value is already within the valid endpoint range.
if dtype != _torch.int64 and bool(
_torch.any(high_int64 > dtype_info.max + 1)
):
if dtype != _torch.int64 and bool(_torch.any(high_int64 > dtype_info.max + 1)):
raise ValueError(f"high is out of bounds for {dtype_name}")


Expand Down
32 changes: 8 additions & 24 deletions src/pyrecest/_backend/pytorch/random/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,7 @@ def _sample_array_randint_exactly(low, high, dtype, generator):
bounds = torch.stack((flat_low, flat_high), dim=1)
unique_bounds, inverse = torch.unique(bounds, dim=0, return_inverse=True)
order = torch.argsort(inverse)
counts = torch.bincount(
inverse, minlength=unique_bounds.shape[0]
).tolist()
counts = torch.bincount(inverse, minlength=unique_bounds.shape[0]).tolist()

offset = 0
for bound_pair, count in zip(unique_bounds, counts):
Expand Down Expand Up @@ -234,9 +232,7 @@ def _randint_array_with_wide_arithmetic(low, high, size, *args, **kwargs):
unexpected = ", ".join(sorted(sampling_kwargs))
raise TypeError(f"Unexpected keyword argument(s): {unexpected}")

result = _sample_array_randint_exactly(
low, high, requested_dtype, generator
)
result = _sample_array_randint_exactly(low, high, requested_dtype, generator)
if out is not None:
out.copy_(result)
return out
Expand Down Expand Up @@ -284,9 +280,7 @@ def uniform(low=0.0, high=1.0, size=None, dtype=None):
span = high - low
if bool(torch.any(~torch.isfinite(span))):
raise OverflowError(_UNIFORM_RANGE_ERROR)
return span * torch.rand(
size, dtype=arithmetic_dtype, device=device
) + low
return span * torch.rand(size, dtype=arithmetic_dtype, device=device) + low


def _singular_multivariate_normal_factor(mean, cov, tol):
Expand Down Expand Up @@ -321,15 +315,11 @@ def _singular_multivariate_normal_factor(mean, cov, tol):
return None

scale = torch.max(torch.abs(eigenvalues))
rank_tolerance = (
torch.finfo(cov.dtype).eps * max(mean.shape[0], 1) * scale
)
rank_tolerance = torch.finfo(cov.dtype).eps * max(mean.shape[0], 1) * scale
if bool(torch.all(eigenvalues > rank_tolerance)):
return None

factor = eigenvectors * torch.sqrt(
torch.clamp(eigenvalues, min=0.0)
).unsqueeze(0)
factor = eigenvectors * torch.sqrt(torch.clamp(eigenvalues, min=0.0)).unsqueeze(0)
return mean, factor


Expand All @@ -355,21 +345,15 @@ def multivariate_normal(mean, cov, size=None, *args, **kwargs):
tol = _validate_multivariate_normal_tol(tol)

try:
return _LEGACY.multivariate_normal(
mean, cov, size=size, *args, **kwargs
)
return _LEGACY.multivariate_normal(mean, cov, size=size, *args, **kwargs)
except ValueError:
if args or kwargs:
raise
singular_parameters = _singular_multivariate_normal_factor(
mean, cov, tol
)
singular_parameters = _singular_multivariate_normal_factor(mean, cov, tol)
if singular_parameters is None:
raise
singular_mean, factor = singular_parameters
return _sample_singular_multivariate_normal(
singular_mean, factor, size
)
return _sample_singular_multivariate_normal(singular_mean, factor, size)


__all__ = sorted(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,7 @@ def array_equal(a, b, equal_nan=False):

comparison = torch_module.eq(a, b)
if dtype.is_floating_point or dtype.is_complex:
comparison = comparison | (
torch_module.isnan(a) & torch_module.isnan(b)
)
comparison = comparison | (torch_module.isnan(a) & torch_module.isnan(b))
return bool(torch_module.all(comparison))

array_equal.__name__ = getattr(original_array_equal, "__name__", "array_equal")
Expand Down
10 changes: 2 additions & 8 deletions src/pyrecest/calibration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
"times_s",
}
)
_ORIGINAL_AGGREGATE_SUMMARY_METRIC_ATTR = (
"_pyrecest_original_aggregate_summary_metric"
)
_ORIGINAL_AGGREGATE_SUMMARY_METRIC_ATTR = "_pyrecest_original_aggregate_summary_metric"
_ORIGINAL_AGGREGATE_TIME_OFFSET_SWEEPS_ATTR = (
"_pyrecest_original_aggregate_time_offset_sweeps"
)
Expand Down Expand Up @@ -190,9 +188,7 @@ def _aggregate_summary_metric(
_bias_module._as_nonnegative_finite_float,
)

_base_bias_as_numeric_array = getattr(
_bias_module, _ORIGINAL_BIAS_NUMERIC_ARRAY_ATTR
)
_base_bias_as_numeric_array = getattr(_bias_module, _ORIGINAL_BIAS_NUMERIC_ARRAY_ATTR)
_base_bias_as_nonnegative_int = getattr(
_bias_module, _ORIGINAL_BIAS_NONNEGATIVE_INT_ATTR
)
Expand Down Expand Up @@ -244,8 +240,6 @@ def _as_numeric_vector(value: Any, name: str) -> np.ndarray:
TimeOffsetFitResult,
_aggregate_std_metric,
_validate_error_metric,
)
from .time_offset import ( # noqa: E402
apply_time_offset,
fit_time_offset,
interpolate_reference_values,
Expand Down
4 changes: 1 addition & 3 deletions src/pyrecest/calibration/_time_offset_grid_extreme_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
_ORIGINAL_ATTR = "_pyrecest_original_make_offset_grid"


def _extreme_range_grid(
min_s: float, max_s: float, step_s: float
) -> np.ndarray:
def _extreme_range_grid(min_s: float, max_s: float, step_s: float) -> np.ndarray:
original = getattr(_time_offset, _ORIGINAL_ATTR)
min_s = _time_offset._as_finite_float(min_s, "min_s")
max_s = _time_offset._as_finite_float(max_s, "max_s")
Expand Down
1 change: 0 additions & 1 deletion src/pyrecest/distributions/abstract_custom_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

from .abstract_distribution_type import AbstractDistributionType


_INVALID_INTEGRAL_TYPES = (
bool,
np.bool_,
Expand Down
8 changes: 6 additions & 2 deletions src/pyrecest/distributions/abstract_dirac_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,25 @@
# pylint: disable=redefined-builtin,no-name-in-module,no-member
from pyrecest.backend import (
all,
)
from pyrecest.backend import any as backend_any
from pyrecest.backend import (
apply_along_axis,
arange,
argmax,
asarray,
)
from pyrecest.backend import any as backend_any
from pyrecest.backend import copy as backend_copy
from pyrecest.backend import max as backend_max
from pyrecest.backend import (
exp,
int32,
int64,
isclose,
isfinite,
log,
)
from pyrecest.backend import max as backend_max
from pyrecest.backend import (
ones,
random,
reshape,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
from ..nonperiodic.gaussian_distribution import GaussianDistribution
from .abstract_hypercylindrical_distribution import AbstractHypercylindricalDistribution


_INVALID_SCALAR_TYPES = (
str,
bytes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
from pyrecest.distributions.nonperiodic.custom_linear_distribution import (
CustomLinearDistribution,
)
from pyrecest.distributions.nonperiodic.gaussian_distribution import GaussianDistribution
from pyrecest.distributions.nonperiodic.gaussian_distribution import (
GaussianDistribution,
)
from pyrecest.distributions.nonperiodic.linear_mixture import LinearMixture


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

from .abstract_hyperspherical_distribution import AbstractHypersphericalDistribution


_INVALID_REAL_SCALAR_TYPES = (
bool,
np.bool_,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from .abstract_hyperspherical_distribution import AbstractHypersphericalDistribution
from .bingham_distribution import BinghamDistribution


_INVALID_REAL_SCALAR_TYPES = (
bool,
np.bool_,
Expand Down
7 changes: 3 additions & 4 deletions src/pyrecest/evaluation/check_and_fix_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from numbers import Integral, Real

import numpy as np

from pyrecest.distributions import AbstractManifoldSpecificDistribution


Expand All @@ -12,9 +11,9 @@ def _is_integer_count(value):


def _validate_probability(value, name):
if isinstance(value, (bool, np.bool_, np.datetime64, np.timedelta64)) or not isinstance(
value, Real
):
if isinstance(
value, (bool, np.bool_, np.datetime64, np.timedelta64)
) or not isinstance(value, Real):
raise TypeError(f"{name} must be a real scalar")
value = float(value)
if not np.isfinite(value) or not 0.0 <= value <= 1.0:
Expand Down
8 changes: 2 additions & 6 deletions src/pyrecest/evaluation/get_distance_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,7 @@ def distance_function(xest, xtrue):
return distance_function


def _target_matrix_candidates(
value, name: str
) -> list[tuple[numpy.ndarray, int]]:
def _target_matrix_candidates(value, name: str) -> list[tuple[numpy.ndarray, int]]:
value = _as_real_numeric_array(value, name)
if value.ndim not in (1, 2):
raise ValueError(f"{name} must be a one- or two-dimensional target set")
Expand Down Expand Up @@ -272,9 +270,7 @@ def _capped_pairwise_euclidean_distances(
where=same_sign,
)
absolute_difference = numpy.abs(same_sign_difference)
same_sign_below_cutoff = same_sign & (
absolute_difference < cutoff_distance
)
same_sign_below_cutoff = same_sign & (absolute_difference < cutoff_distance)
numpy.divide(
absolute_difference,
cutoff_distance,
Expand Down
6 changes: 2 additions & 4 deletions src/pyrecest/evaluation/summarize_filter_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ def _validate_summary_filter_counts(
name: count for name, count in summary_counts.items() if count != expected_count
}
if mismatched:
details = ", ".join(
f"{name}={count}" for name, count in mismatched.items()
)
details = ", ".join(f"{name}={count}" for name, count in mismatched.items())
raise ValueError(
"filter_configs and computed summaries must describe the same number "
f"of filters; filter_configs={expected_count}, {details}"
Expand All @@ -44,7 +42,7 @@ def summarize_filter_results(
run_failed,
last_filter_states=None,
last_estimates=None,
**_
**_,
):
if pyrecest.backend.__backend_name__ == "jax": # pylint: disable=no-member
raise NotImplementedError("Not supported for the JAX backend.")
Expand Down
8 changes: 4 additions & 4 deletions src/pyrecest/evaluation/tracking_metrics/_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ class TrackingSequence:

def __post_init__(self) -> None:
num_gt_ids = _nonnegative_int(self.num_gt_ids, name="num_gt_ids")
num_tracker_ids = _nonnegative_int(
self.num_tracker_ids, name="num_tracker_ids"
)
num_tracker_ids = _nonnegative_int(self.num_tracker_ids, name="num_tracker_ids")
gt_frames = tuple(
_identity_array(values, num_gt_ids, f"gt_ids[{index}]")
for index, values in enumerate(self.gt_ids)
Expand All @@ -36,7 +34,9 @@ def __post_init__(self) -> None:
for index, values in enumerate(self.tracker_ids)
)
if len(gt_frames) != len(tracker_frames):
raise ValueError("gt_ids and tracker_ids must contain the same number of frames")
raise ValueError(
"gt_ids and tracker_ids must contain the same number of frames"
)
if len(self.similarity_scores) != len(gt_frames):
raise ValueError("similarity_scores must contain one matrix per frame")
similarities = tuple(
Expand Down
4 changes: 1 addition & 3 deletions src/pyrecest/experimental/dvs/vectorized_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ def tracker_signed_normal_flows_vectorized(
except Exception: # pragma: no cover - backend-specific safety fallback
return np.asarray(
[
tracker.signed_normal_flow_for_measurement(
measurement, unit_velocity
)
tracker.signed_normal_flow_for_measurement(measurement, unit_velocity)
for measurement in measurements
],
dtype=float,
Expand Down
4 changes: 1 addition & 3 deletions src/pyrecest/filters/block_particle_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,7 @@ def set_particles(self, particles, weights=None, block_weights=None):
normalized_block_weights = None
if hasattr(self, "_block_weights"):
if block_weights is not None:
normalized_block_weights = self._normalize_block_weights(
block_weights
)
normalized_block_weights = self._normalize_block_weights(block_weights)
elif normalized_weights is not None:
normalized_block_weights = self._normalize_block_weights(
normalized_weights
Expand Down
9 changes: 2 additions & 7 deletions src/pyrecest/filters/daum_huang_particle_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,7 @@ def __init__(
self.flow_type if flow_type is None else flow_type
)
self.n_steps = _validate_positive_int(n_steps, "n_steps")
self.step_schedule = (
None if step_schedule is None else tuple(step_schedule)
)
self.step_schedule = None if step_schedule is None else tuple(step_schedule)
self.jitter = _validate_nonnegative_float(jitter, "jitter")

def update_identity(self, meas_noise, measurement, **kwargs):
Expand Down Expand Up @@ -744,10 +742,7 @@ def _regularize_cov_np(covariance, jitter):
eigenvalues = np.linalg.eigvalsh(covariance)
spectral_scale = max(float(np.max(np.abs(eigenvalues))), 1.0)
tolerance = (
10.0
* np.finfo(float).eps
* max(covariance.shape[0], 1)
* spectral_scale
10.0 * np.finfo(float).eps * max(covariance.shape[0], 1) * spectral_scale
)
min_eigenvalue = float(eigenvalues[0])
if min_eigenvalue < -tolerance:
Expand Down
4 changes: 1 addition & 3 deletions src/pyrecest/filters/dirichlet_process_birth_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,7 @@ def predict_linear(
"""Predict targets and decay DP birth-atom counts."""
survival_probability = self._normalize_birth_atom_survival_probability()
pruning_threshold = self._normalize_birth_atom_pruning_threshold()
maximum_number_of_birth_atoms = (
self._normalize_maximum_number_of_birth_atoms()
)
maximum_number_of_birth_atoms = self._normalize_maximum_number_of_birth_atoms()

super().predict_linear(
system_matrices,
Expand Down
4 changes: 1 addition & 3 deletions src/pyrecest/filters/gaussian_hypothesis_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,7 @@ def moment_match_gaussian_hypotheses(
continue
probability = float(weight)
sqrt_probability = np.sqrt(probability)
scaled_diff = (
sqrt_probability * hypothesis.mean - sqrt_probability * mean
)
scaled_diff = sqrt_probability * hypothesis.mean - sqrt_probability * mean
covariance += probability * hypothesis.covariance + np.outer(
scaled_diff,
scaled_diff,
Expand Down
Loading