Skip to content

Add systematic distribution representation conversion#1929

Merged
FlorianPfaff merged 7 commits intomainfrom
feature/representation-conversion
May 1, 2026
Merged

Add systematic distribution representation conversion#1929
FlorianPfaff merged 7 commits intomainfrom
feature/representation-conversion

Conversation

@FlorianPfaff
Copy link
Copy Markdown
Owner

This PR adds a first systematic representation-conversion layer for PyRecEst.

Main changes:

  • adds pyrecest.distributions.conversion
  • introduces convert_distribution, can_convert, register_conversion, and ConversionResult
  • delegates to existing target-side from_distribution(...) hooks
  • adds convert_to(...) / approximate_as(...) convenience methods to AbstractDistributionType
  • adds tests for Gaussian-to-Dirac conversion, identity conversion, conversion metadata, and argument validation
  • adds documentation and MkDocs navigation for representation conversion

Design notes:

  • The implementation is target-centric and intentionally non-disruptive: existing representation-specific conversion logic stays in the target class.
  • The first public import path is pyrecest.distributions.conversion; a later cleanup PR can re-export the gateway from pyrecest.distributions if desired.
  • This PR focuses on the conversion gateway and avoids larger refactors of the distribution inheritance hierarchy.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

MegaLinter analysis: Error

Descriptor Linter Files Fixed Errors Warnings Elapsed time
✅ COPYPASTE jscpd yes no no 14.32s
✅ JSON prettier 2 0 0 0 0.45s
✅ JSON v8r 2 0 0 2.51s
✅ MARKDOWN markdownlint 22 0 0 0 1.12s
✅ MARKDOWN markdown-table-formatter 22 0 0 0 0.34s
✅ PYTHON bandit 447 0 0 6.74s
✅ PYTHON black 447 5 0 0 10.02s
✅ PYTHON flake8 447 0 0 3.48s
✅ PYTHON isort 447 6 0 0 0.83s
❌ PYTHON mypy 447 1 0 5.87s
✅ PYTHON pylint 447 0 0 142.2s
✅ PYTHON ruff 447 6 0 0 0.08s
✅ REPOSITORY checkov yes no no 23.29s
✅ REPOSITORY gitleaks yes no no 10.98s
✅ REPOSITORY git_diff yes no no 0.07s
✅ REPOSITORY secretlint yes no no 8.15s
✅ REPOSITORY syft yes no no 3.87s
✅ REPOSITORY trivy-sbom yes no no 3.2s
✅ REPOSITORY trufflehog yes no no 20.03s
✅ YAML prettier 5 0 0 0 0.5s
✅ YAML v8r 5 0 0 5.17s
✅ YAML yamllint 5 0 0 0.46s

Detailed Issues

❌ PYTHON / mypy - 1 error
src/pyrecest/distributions/conversion.py:250: error: Argument 3 to "_validate_conversion_arguments" has incompatible type "str | Any | None"; expected "str"  [arg-type]
src/pyrecest/utils/history_recorder.py:34: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs  [annotation-unchecked]
src/pyrecest/distributions/so3_bingham_distribution.py:84: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs  [annotation-unchecked]
src/pyrecest/smoothers/unscented_rauch_tung_striebel_smoother.py:50: note: By default the bodies of untyped functions are not checked, consider using --check-untyped-defs  [annotation-unchecked]
Found 1 error in 1 file (checked 447 source files)

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

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an initial, target-centric “representation conversion” gateway for PyRecEst distributions, providing a single public API to convert/approximate between distribution representations while delegating conversion logic to existing from_distribution(...) hooks.

Changes:

  • Added pyrecest.distributions.conversion with convert_distribution, can_convert, register_conversion, registered_conversions, and ConversionResult metadata.
  • Added convert_to(...) / approximate_as(...) convenience methods on AbstractDistributionType.
  • Added unit tests and user documentation (MkDocs page + navigation + API overview mention).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/distributions/test_conversion.py Adds tests for conversion routing, identity conversion metadata, and argument validation.
src/pyrecest/distributions/conversion.py Implements the conversion registry and gateway dispatch + metadata + kwargs validation.
src/pyrecest/distributions/abstract_distribution_type.py Adds convenience wrappers delegating to the conversion gateway.
mkdocs.yml Adds MkDocs nav entry for the new representation conversion guide.
docs/representation-conversion.md Documents the conversion gateway, metadata, and registration API.
docs/api-overview.md Adds a brief API overview mention and link to the new conversion docs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +172 to +200
for entry in _matching_registered_conversions(distribution, target_type):
converted = _call_conversion_callable(entry.converter, distribution, kwargs)
result = ConversionResult(
distribution=converted,
source_type=source_type,
target_type=target_type,
method=entry.method,
exact=entry.exact,
parameters=dict(kwargs),
)
return result if return_info else result.distribution

from_distribution = getattr(target_type, "from_distribution", None)
if callable(from_distribution):
converted = _call_conversion_callable(
from_distribution,
distribution,
kwargs,
conversion_name=f"{target_type.__name__}.from_distribution",
)
result = ConversionResult(
distribution=converted,
source_type=source_type,
target_type=target_type,
method=f"{target_type.__name__}.from_distribution",
exact=False,
parameters=dict(kwargs),
)
return result if return_info else result.distribution
_validate_conversion_arguments(func, kwargs, name)
try:
return func(distribution, **kwargs)
except TypeError as exc:
"""Convert or approximate this distribution as ``target_type``.

This is a convenience wrapper around
:func:`pyrecest.distributions.convert_distribution`.
- `CircularFourierDistribution.from_distribution(...)` builds Fourier
coefficients from samples or grid values.
- `GaussianDistribution.from_distribution(...)` performs Gaussian moment
matching when the source exposes `mean()` and `covariance()`.
@FlorianPfaff FlorianPfaff disabled auto-merge May 1, 2026 20:18
@FlorianPfaff FlorianPfaff merged commit 115ed6e into main May 1, 2026
21 of 22 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