Skip to content

Port ToroidalVMRivestDistribution from libDirectional#1595

Merged
FlorianPfaff merged 2 commits intomainfrom
copilot/port-toroidal-vm-rivest-distribution
Apr 1, 2026
Merged

Port ToroidalVMRivestDistribution from libDirectional#1595
FlorianPfaff merged 2 commits intomainfrom
copilot/port-toroidal-vm-rivest-distribution

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

Ports the bivariate von Mises distribution (Rivest 1988 variant) from the MATLAB libDirectional library into PyRecEst.

New distribution: ToroidalVMRivestDistribution

Models dependent unit vectors on the torus via two correlation parameters alpha and beta (corresponding to A = diag([alpha, beta])):

from pyrecest.distributions import ToroidalVMRivestDistribution
import numpy as np

dist = ToroidalVMRivestDistribution(
    mu=np.array([1.0, 2.0]),
    kappa=np.array([0.7, 1.4]),
    alpha=np.array(0.5),
    beta=np.array(0.3),
)
dist.pdf(np.array([1.5, 2.5]))          # evaluate density
dist.trigonometric_moment(1)            # analytical first moment
dist.circular_correlation_jammalamadaka()  # analytical correlation
dist.shift(np.array([0.5, 1.0]))        # returns shifted copy

Changes

  • hypertorus/toroidal_vm_rivest_distribution.py — new class extending AbstractToroidalDistribution with:
    • norm_const: double series over modified Bessel functions (truncated at ±10 terms)
    • pdf: vectorized evaluation supporting batched inputs
    • trigonometric_moment: closed-form for n=1; falls back to numerical otherwise
    • circular_correlation_jammalamadaka: analytical override of the base class numerical fallback
    • shift: returns a new instance with shifted mu
  • distributions/__init__.py — exports ToroidalVMRivestDistribution
  • tests/distributions/test_toroidal_vm_rivest_distribution.py — 15 tests covering normalization, pdf correctness, analytical vs. numerical moments, shift, correlation, and the zero-correlation special case (reduces to independent von Mises product)

Agent-Logs-Url: https://github.com/FlorianPfaff/PyRecEst/sessions/1e342ef5-dc88-44ad-91de-467da7fa7c06

Co-authored-by: FlorianPfaff <6773539+FlorianPfaff@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 31, 2026

MegaLinter analysis: Success

Descriptor Linter Files Fixed Errors Warnings Elapsed time
✅ COPYPASTE jscpd yes no no 7.43s
✅ JSON prettier 2 0 0 0 0.48s
✅ JSON v8r 2 0 0 2.34s
✅ MARKDOWN markdownlint 1 0 0 0 0.65s
✅ MARKDOWN markdown-table-formatter 1 0 0 0 0.2s
✅ PYTHON bandit 252 0 0 3.09s
✅ PYTHON black 252 2 0 0 4.47s
✅ PYTHON flake8 252 0 0 1.76s
✅ PYTHON isort 252 2 0 0 0.48s
✅ PYTHON mypy 252 0 0 3.98s
✅ PYTHON pylint 252 0 0 70.32s
✅ PYTHON ruff 252 2 0 0 0.04s
✅ REPOSITORY checkov yes no no 23.33s
✅ REPOSITORY gitleaks yes no no 4.47s
✅ REPOSITORY git_diff yes no no 0.02s
✅ REPOSITORY secretlint yes no no 6.32s
✅ REPOSITORY syft yes no no 3.1s
✅ REPOSITORY trivy-sbom yes no no 1.82s
✅ REPOSITORY trufflehog yes no no 15.63s
✅ YAML prettier 4 0 0 0 0.49s
✅ YAML v8r 4 0 0 5.01s
✅ YAML yamllint 4 0 0 0.43s

See detailed reports in MegaLinter artifacts

Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@9.4.0 --custom-flavor-setup --custom-flavor-linters PYTHON_PYLINT,PYTHON_BLACK,PYTHON_FLAKE8,PYTHON_ISORT,PYTHON_BANDIT,PYTHON_MYPY,PYTHON_RUFF,COPYPASTE_JSCPD,JSON_V8R,JSON_PRETTIER,MARKDOWN_MARKDOWNLINT,MARKDOWN_MARKDOWN_TABLE_FORMATTER,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,REPOSITORY_GITLEAKS,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG,YAML_PRETTIER,YAML_YAMLLINT,YAML_V8R

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 1, 2026

Test Results

   12 files  ±  0     12 suites  ±0   3h 16m 35s ⏱️ + 4m 36s
  561 tests + 15    561 ✅ + 15      0 💤 ± 0  0 ❌ ±0 
6 944 runs  +180  5 744 ✅ +156  1 200 💤 +24  0 ❌ ±0 

Results for commit 60b71f7. ± Comparison against base commit deb475e.

@FlorianPfaff
Copy link
Copy Markdown
Owner

@copilot Can you fix the megalinter errors?

…ls, fix shift parameter name

Agent-Logs-Url: https://github.com/FlorianPfaff/PyRecEst/sessions/92c57208-1113-44b6-b1aa-a4d4504e018f

Co-authored-by: FlorianPfaff <6773539+FlorianPfaff@users.noreply.github.com>
auto-merge was automatically disabled April 1, 2026 15:44

Head branch was pushed to by a user without write access

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 1, 2026

@copilot Can you fix the megalinter errors?

Fixed in 8b974d1. Three issues were addressed:

  • flake8/ruff E741: renamed loop variable lell (ambiguous name) in norm_const, trigonometric_moment, and the correlation helper
  • pylint R0914: extracted a _correlation_series_sums() helper method from circular_correlation_jammalamadaka to reduce local variable count from 17 to within the 15-variable limit
  • pylint W0237: renamed shift_anglesshift_by to match the base class parameter name

Copilot AI requested a review from FlorianPfaff April 1, 2026 15:45
@FlorianPfaff FlorianPfaff enabled auto-merge April 1, 2026 16:04
@FlorianPfaff FlorianPfaff merged commit c34f224 into main Apr 1, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants