Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion benchmarks/low_rank_hypertoroidal_fourier.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from time import perf_counter

import numpy as np

from pyrecest.distributions.hypertorus.hypertoroidal_fourier_distribution import (
HypertoroidalFourierDistribution,
)
Expand Down
1 change: 0 additions & 1 deletion examples/basic/dp_extended_target_subclustering.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""

import numpy as np

from pyrecest.experimental.dp_measurement_subclusters import (
DPMeasurementSubclusterConfig,
fit_dp_measurement_subclusters,
Expand Down
30 changes: 24 additions & 6 deletions examples/basic/nonparametric_cardinality_priors.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,36 @@ def main():
pitman_yor_prior = PitmanYorProcessCardinalityPrior(discount=0.5, strength=2.0)

print("cluster sizes:", cluster_sizes)
print("DP assignment probabilities: ", dirichlet_prior.predictive_assignment_probabilities(cluster_sizes))
print("PYP assignment probabilities:", pitman_yor_prior.predictive_assignment_probabilities(cluster_sizes))
print("DP expected clusters after 50 observations: ", round(dirichlet_prior.expected_number_of_clusters(50), 3))
print("PYP expected clusters after 50 observations:", round(pitman_yor_prior.expected_number_of_clusters(50), 3))
print(
"DP assignment probabilities: ",
dirichlet_prior.predictive_assignment_probabilities(cluster_sizes),
)
print(
"PYP assignment probabilities:",
pitman_yor_prior.predictive_assignment_probabilities(cluster_sizes),
)
print(
"DP expected clusters after 50 observations: ",
round(dirichlet_prior.expected_number_of_clusters(50), 3),
)
print(
"PYP expected clusters after 50 observations:",
round(pitman_yor_prior.expected_number_of_clusters(50), 3),
)

birth_probability = PitmanYorBirthProbability(
discount=0.5,
strength=1.0,
base_birth_existence_probability=0.8,
)
print("first unassigned-measurement birth probability:", birth_probability(num_existing_components=0, num_new_births=0))
print("second burst birth probability: ", birth_probability(num_existing_components=0, num_new_births=1))
print(
"first unassigned-measurement birth probability:",
birth_probability(num_existing_components=0, num_new_births=0),
)
print(
"second burst birth probability: ",
birth_probability(num_existing_components=0, num_new_births=1),
)


if __name__ == "__main__":
Expand Down
11 changes: 8 additions & 3 deletions examples/experimental/multisensor_ddp_association.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
from __future__ import annotations

import numpy as np

from pyrecest.experimental import SensorAssociationBlock, multisensor_ddp_association_update
from pyrecest.experimental import (
SensorAssociationBlock,
multisensor_ddp_association_update,
)


def main() -> None:
Expand Down Expand Up @@ -37,7 +39,10 @@ def main() -> None:
for sensor_id, posterior in result.sensor_posteriors.items():
print(sensor_id, posterior.hard_assignments)

print("updated target weights:", dict(zip(target_labels, result.updated_target_weights, strict=True)))
print(
"updated target weights:",
dict(zip(target_labels, result.updated_target_weights, strict=True)),
)
print("updated birth weight:", result.updated_birth_weight)
print("expected clutter count:", result.expected_clutter_count)

Expand Down
2 changes: 1 addition & 1 deletion scripts/check_public_api_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,4 @@ def main(argv: list[str] | None = None) -> int:


if __name__ == "__main__":
raise SystemExit(main())
raise SystemExit(main())
8 changes: 6 additions & 2 deletions src/pyrecest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,9 @@ def _patch_raw_pytorch_cumulative_facade() -> None:

try:
import pyrecest._backend.pytorch as pytorch_backend # pylint: disable=import-outside-toplevel
from pyrecest._backend_submodules import _copy_result_to_out # pylint: disable=import-outside-toplevel
from pyrecest._backend_submodules import ( # pylint: disable=import-outside-toplevel
_copy_result_to_out,
)
except ModuleNotFoundError: # pragma: no cover - only relevant without PyTorch
return

Expand All @@ -486,7 +488,9 @@ def wrapped_cumulative(x, axis=None, dtype=None, out=None):

import pyrecest.backend as backend # pylint: disable=import-outside-toplevel

selected_backend_is_pytorch = getattr(backend, "__backend_name__", None) == "pytorch"
selected_backend_is_pytorch = (
getattr(backend, "__backend_name__", None) == "pytorch"
)
for helper_name in ("cumsum", "cumprod"):
cumulative = getattr(pytorch_backend, helper_name, None)
if cumulative is None:
Expand Down
12 changes: 9 additions & 3 deletions src/pyrecest/_backend/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,9 @@ def _torch_cross(a, b, torch, *, axisa=-1, axisb=-1, axisc=-1, axis=None):
a_dim = a.shape[-1]
b_dim = b.shape[-1]
if a_dim not in (2, 3) or b_dim not in (2, 3):
raise ValueError("incompatible dimensions for cross product (dimension must be 2 or 3)")
raise ValueError(
"incompatible dimensions for cross product (dimension must be 2 or 3)"
)

a0 = a[..., 0]
a1 = a[..., 1]
Expand Down Expand Up @@ -345,9 +347,13 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None):
if torch_pair is not None:
a, b = torch_pair
torch = _torch_module_for_values(a, b)
return _torch_cross(a, b, torch, axisa=axisa, axisb=axisb, axisc=axisc, axis=axis)
return _torch_cross(
a, b, torch, axisa=axisa, axisb=axisb, axisc=axisc, axis=axis
)

return _np.cross(_np.asarray(a), _np.asarray(b), axisa=axisa, axisb=axisb, axisc=axisc, axis=axis)
return _np.cross(
_np.asarray(a), _np.asarray(b), axisa=axisa, axisb=axisb, axisc=axisc, axis=axis
)


def matvec(matrix, vector):
Expand Down
2 changes: 1 addition & 1 deletion src/pyrecest/_backend/_shared_numpy/_rng_pkg/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Compatibility package for shared NumPy RNG helpers."""

import sys as _sys
from importlib import util as _importlib_util
from pathlib import Path as _Path
import sys as _sys

import numpy as _np

Expand Down
3 changes: 2 additions & 1 deletion src/pyrecest/_backend/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ def get_api_backend_support(api_name: str) -> dict[str, str]:
def iter_api_backend_capabilities() -> tuple[tuple[str, dict[str, str]], ...]:
"""Return public API backend support rows in a stable order."""
return tuple(
(api_name, dict(row)) for api_name, row in sorted(API_BACKEND_CAPABILITIES.items())
(api_name, dict(row))
for api_name, row in sorted(API_BACKEND_CAPABILITIES.items())
)


Expand Down
7 changes: 5 additions & 2 deletions src/pyrecest/_backend/capabilities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ def _patch_pytorch_dot_outer_device_contract() -> None:

helper_names = ("dot", "outer")
if all(
getattr(getattr(raw_pytorch, helper_name, None), "_pyrecest_device_contract", False)
getattr(
getattr(raw_pytorch, helper_name, None), "_pyrecest_device_contract", False
)
for helper_name in helper_names
):
if getattr(backend, "__backend_name__", None) == "pytorch":
Expand Down Expand Up @@ -157,7 +159,8 @@ def get_api_backend_support(api_name: str) -> dict[str, str]:
def iter_api_backend_capabilities() -> tuple[tuple[str, dict[str, str]], ...]:
"""Return public API backend support rows in a stable order."""
return tuple(
(api_name, dict(row)) for api_name, row in sorted(API_BACKEND_CAPABILITIES.items())
(api_name, dict(row))
for api_name, row in sorted(API_BACKEND_CAPABILITIES.items())
)


Expand Down
1 change: 1 addition & 0 deletions src/pyrecest/_backend/jax/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ def cov(
def diagonal(a, offset=0, axis1=0, axis2=1):
return _jnp.diagonal(_jnp.asarray(a), offset=offset, axis1=axis1, axis2=axis2)


def squeeze(a, axis=None):
return _jnp.squeeze(_jnp.asarray(a), axis=axis)

Expand Down
5 changes: 3 additions & 2 deletions src/pyrecest/_backend/jax/fft.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import numpy as _np
from jax.numpy import fft as _fft


_BOOLEAN_FFT_AXIS_ERROR = "axis must be an integer, not boolean"
_BOOLEAN_FFT_LENGTH_ERROR = "n must be an integer length, not boolean"
_FFT_SHAPE_SEQUENCE_ERROR = "s must be None or a sequence of integer lengths"
Expand Down Expand Up @@ -82,7 +81,9 @@ def _normalize_fft_sequence_item(value, boolean_error, integer_error):
raise TypeError(integer_error) from exc


def _normalize_fft_integer_sequence(value, sequence_error, boolean_error, integer_error):
def _normalize_fft_integer_sequence(
value, sequence_error, boolean_error, integer_error
):
"""Normalize NumPy/JAX scalar-array entries inside FFT integer sequences."""
if value is None:
return None
Expand Down
4 changes: 3 additions & 1 deletion src/pyrecest/_backend/jax/random/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

_LEGACY_MODULE_NAME = __name__ + "._legacy"
_LEGACY_PATH = _Path(__file__).resolve().parent.parent / "random.py"
_LEGACY_SPEC = _importlib_util.spec_from_file_location(_LEGACY_MODULE_NAME, _LEGACY_PATH)
_LEGACY_SPEC = _importlib_util.spec_from_file_location(
_LEGACY_MODULE_NAME, _LEGACY_PATH
)
if _LEGACY_SPEC is None or _LEGACY_SPEC.loader is None: # pragma: no cover
raise ImportError(f"Cannot load legacy JAX random backend from {_LEGACY_PATH}")
_LEGACY = _importlib_util.module_from_spec(_LEGACY_SPEC)
Expand Down
5 changes: 4 additions & 1 deletion src/pyrecest/_backend/pytorch/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ def _preferred_tensor_device(value):
def _move_tensors_to_device(tensors, device):
if device is None:
return tensors
return [tensor.to(device=device) if tensor.device != device else tensor for tensor in tensors]
return [
tensor.to(device=device) if tensor.device != device else tensor
for tensor in tensors
]


def array(val, dtype=None):
Expand Down
15 changes: 9 additions & 6 deletions src/pyrecest/_backend/pytorch/_dtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
from pyrecest._backend._dtype_utils import (
get_default_dtype as _shared_get_default_dtype,
)
from torch import bool as torch_bool
from torch import (
bool as torch_bool,
complex64,
complex128,
float16,
Expand Down Expand Up @@ -171,9 +171,8 @@ def _is_random_array_parameter(value):


def _is_binary_array_operand(value):
return (
isinstance(value, (list, tuple))
or (not isinstance(value, (str, bytes)) and hasattr(value, "__array__"))
return isinstance(value, (list, tuple)) or (
not isinstance(value, (str, bytes)) and hasattr(value, "__array__")
)


Expand Down Expand Up @@ -301,7 +300,9 @@ def _wrapped(x1, x2, *args, **kwargs):
x1 = _torch.tensor(x1)
if box_x2 and not _torch.is_tensor(x2):
x2 = _binary_tensor_operand(x2, x1)
elif not box_x2 and not _torch.is_tensor(x2) and _is_binary_array_operand(x2):
elif (
not box_x2 and not _torch.is_tensor(x2) and _is_binary_array_operand(x2)
):
x2 = _binary_tensor_operand(x2, x1)

return func(x1, x2, *args, **kwargs)
Expand All @@ -318,7 +319,9 @@ def _patch_parent_log1p_arraylike_contract() -> None:
"""Make PyTorch backend ``log1p`` accept NumPy-style array-like inputs."""
try:
import pyrecest._backend.pytorch as pytorch_backend # pylint: disable=import-outside-toplevel
except ModuleNotFoundError: # pragma: no cover - parent backend import failed earlier
except (
ModuleNotFoundError
): # pragma: no cover - parent backend import failed earlier
return

original_log1p = getattr(pytorch_backend, "log1p", None)
Expand Down
8 changes: 6 additions & 2 deletions src/pyrecest/_backend/pytorch/random/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

_LEGACY_MODULE_NAME = __name__.rsplit(".", 1)[0] + "._random_legacy"
_LEGACY_PATH = _Path(__file__).resolve().parent.parent / "random.py"
_LEGACY_SPEC = _importlib_util.spec_from_file_location(_LEGACY_MODULE_NAME, _LEGACY_PATH)
_LEGACY_SPEC = _importlib_util.spec_from_file_location(
_LEGACY_MODULE_NAME, _LEGACY_PATH
)
if _LEGACY_SPEC is None or _LEGACY_SPEC.loader is None: # pragma: no cover
raise ImportError(f"Cannot load legacy PyTorch random backend from {_LEGACY_PATH}")
_LEGACY = _importlib_util.module_from_spec(_LEGACY_SPEC)
Expand All @@ -30,7 +32,9 @@ def _probability_accumulation_dtype(probabilities):

def _normalize_nonnegative_probabilities(probabilities):
torch = _LEGACY._torch
probabilities = probabilities.to(dtype=_probability_accumulation_dtype(probabilities))
probabilities = probabilities.to(
dtype=_probability_accumulation_dtype(probabilities)
)
if bool(torch.any(probabilities < 0)):
raise ValueError(_PROBABILITY_SUM_ERROR)
scale = probabilities.max()
Expand Down
Loading