coordinax.hypothesis#
Hypothesis strategies for property-based testing with coordinax.
This package provides Hypothesis strategies for generating random coordinax objects (angles, distances, parallaxes, distance moduli) for property-based testing.
Installation#
pip install coordinax.hypothesis
uv add coordinax.hypothesis
Quick Start#
from hypothesis import given
import coordinax.main as cx
import coordinax.hypothesis.main as cxst
@given(angle=cxst.angles())
def test_angle_property(angle):
"""Test that all angles are valid Angle objects."""
assert isinstance(angle, cx.Angle)
@given(dist=cxst.distances())
def test_distance_property(dist):
"""Test that all distances are valid Distance objects."""
assert isinstance(dist, cx.Distance)
assert dist.value >= 0 # distances are non-negative by default
Strategies#
angles(wrap_to=None, **kwargs)#
Generate random unxt.Angle objects for testing.
This strategy builds on unxt_hypothesis.quantities() to generate angles with optional wrapping bounds. The strategy is useful for property-based testing of angle-related computations.
Parameters:
wrap_to(SearchStrategy[tuple[Quantity, Quantity]] | None): Optional hypothesis strategy that generates a tuple of (min_bound, max_bound) for angle wrapping. If None, generates angles without wrapping (default: None).**kwargs: Additional keyword arguments passed toquantities(). Common options include:units(str): Unit for the angle (e.g., βradβ, βdegβ)min_value(float): Minimum value for the anglemax_value(float): Maximum value for the angleshape(int | tuple | SearchStrategy): Shape of the generated angle array
Returns: SearchStrategy[unxt.Angle]
Examples:
from hypothesis import given, strategies as st
import unxt as u
import coordinax.hypothesis.main as cxst
# Generate basic angles (no wrapping)
@given(angle=cxst.angles())
def test_basic_angle(angle):
assert isinstance(angle, u.Angle)
# Generate angles in degrees
@given(angle=cxst.angles(units="deg"))
def test_angle_degrees(angle):
assert angle.unit == "deg"
# Generate angles with wrapping bounds [0, 360) degrees
@given(angle=cxst.angles(wrap_to=st.just((u.Q(0, "deg"), u.Q(360, "deg")))))
def test_angle_with_wrapping(angle):
assert angle.wrap_to is not None
min_bound, max_bound = angle.wrap_to
assert min_bound.to("deg").value == 0
assert max_bound.to("deg").value == 360
# Generate angle arrays
@given(angle=cxst.angles(shape=10))
def test_angle_array(angle):
assert angle.shape == (10,)
# Generate 2D angle arrays
@given(angle=cxst.angles(shape=(5, 3)))
def test_angle_2d(angle):
assert angle.shape == (5, 3)
distances(check_negative=True, **kwargs)#
Generate random coordinax.distances.Distance objects for testing.
This strategy builds on unxt_hypothesis.quantities to generate distances with automatic handling of the non-negativity constraint. The strategy is useful for property-based testing of distance-related computations.
Parameters:
check_negative(bool | SearchStrategy[bool]): Whether to enforce non-negative distances. IfTrue(default), generated distances will be >= 0. Can be a hypothesis strategy to vary this behavior across test examples.**kwargs: Additional keyword arguments passed tounxt_hypothesis.quantities. Common options include:units(str): Unit for the distance (e.g., βkpcβ, βmβ, βAUβ)shape(int | tuple | SearchStrategy): Shape of the generated distance arrayelements(SearchStrategy): Strategy for generating array elements. Whencheck_negative=True, the min_value will be automatically adjusted to 0 if needed.
Returns: SearchStrategy[coordinax.distances.Distance]
Examples:
from hypothesis import given, strategies as st
import coordinax.distances as cxd
import coordinax.hypothesis.main as cxst
# Generate basic non-negative distances
@given(dist=cxst.distances())
def test_basic_distance(dist):
assert isinstance(dist, cx.Distance)
assert dist.value >= 0
# Generate distances in specific units
@given(dist=cxst.distances(units="kpc"))
def test_distance_kpc(dist):
assert dist.unit == "kpc"
# Allow negative distances
@given(dist=cxst.distances(check_negative=False))
def test_signed_distance(dist):
assert isinstance(dist, cx.Distance)
# Can be positive or negative
# Generate distance arrays
@given(dist=cxst.distances(shape=10))
def test_distance_array(dist):
assert dist.shape == (10,)
assert all(dist.value >= 0)
# Control the value range
@given(dist=cxst.distances(elements=st.floats(min_value=10.0, max_value=100.0)))
def test_distance_range(dist):
assert 10.0 <= dist.value <= 100.0
distance_moduli(**kwargs)#
Generate random coordinax.astro.DistanceModulus objects for testing. distance and angle strategiesategy builds on unxt_hypothesis.quantities to generate distance moduli (apparent minus absolute magnitude). Distance moduli are always in units of βmagβ. The strategy is useful for property-based testing of magnitude-based distance computations.
Parameters:
**kwargs: Additional keyword arguments passed tounxt_hypothesis.quantities. Common options include:shape(int | tuple | SearchStrategy): Shape of the generated distance modulus arrayelements(SearchStrategy): Strategy for generating array elements
Returns: SearchStrategy[coordinax.astro.DistanceModulus]
Examples:
from hypothesis import given, strategies as st
import coordinax.astro as cxastro
import coordinax.hypothesis.astro as cxastrost
# Generate basic distance moduli
@given(dm=cxastrost.distance_moduli())
def test_basic_dm(dm):
assert isinstance(dm, cxastro.DistanceModulus)
assert dm.unit == "mag"
# Generate distance modulus arrays
@given(dm=cxastrost.distance_moduli(shape=10))
def test_dm_array(dm):
assert dm.shape == (10,)
assert dm.unit == "mag"
# Control the value range (e.g., typical values 0-30 mag)
@given(dm=cxastrost.distance_moduli(elements=st.floats(min_value=0.0, max_value=30.0)))
def test_dm_range(dm):
assert 0.0 <= dm.value <= 30.0
parallaxes(check_negative=True, **kwargs)#
Generate random coordinax.astro.Parallax objects for testing.
This strategy builds on unxt_hypothesis.quantities to generate parallaxes with automatic handling of the non-negativity constraint. While theoretically parallax must be non-negative (tan(p) = 1 AU / d), noisy direct measurements can yield negative values. The strategy is useful for property-based testing of parallax-based distance computations.
Parameters:
check_negative(bool | SearchStrategy[bool]): Whether to enforce non-negative parallaxes. IfTrue(default), generated parallaxes will be >= 0. Can be a hypothesis strategy to vary this behavior across test examples. Set toFalsewhen testing handling of noisy measurements.**kwargs: Additional keyword arguments passed tounxt_hypothesis.quantities(). Common options include:units(str): Unit for the parallax (e.g., βmasβ, βarcsecβ, βdegβ)shape(int | tuple | SearchStrategy): Shape of the generated parallax arrayelements(SearchStrategy): Strategy for generating array elements. Whencheck_negative=True, the min_value will be automatically adjusted to 0 if needed.
Returns: SearchStrategy[coordinax.astro.Parallax]
Examples:
from hypothesis import given, strategies as st
import coordinax.astro as cxastro
import coordinax.hypothesis.astro as cxastrost
# Generate basic non-negative parallaxes
@given(plx=cxastrost.parallaxes())
def test_basic_parallax(plx):
assert isinstance(plx, cxastro.Parallax)
assert plx.value >= 0
# Generate parallaxes in milliarcseconds
@given(plx=cxastrost.parallaxes(units="mas"))
def test_parallax_mas(plx):
assert plx.unit == "mas"
# Allow negative parallaxes (for noisy measurements)
@given(plx=cxastrost.parallaxes(check_negative=False))
def test_noisy_parallax(plx):
assert isinstance(plx, cxastro.Parallax)
# Can be positive or negative
# Generate parallax arrays
@given(plx=cxastrost.parallaxes(shape=10))
def test_parallax_array(plx):
assert plx.shape == (10,)
assert all(plx.value >= 0)
# Control the value range (e.g., nearby stars with large parallax)
@given(
plx=cxastrost.parallaxes(units="mas", elements=st.floats(min_value=1.0, max_value=100.0))
)
def test_nearby_parallax(plx):
assert 1.0 <= plx.to("mas").value <= 100.0
Integration with unxt-hypothesis#
The coordinax.hypothesis package builds on top of unxt-hypothesis strategies.
For more advanced usage patterns, see the Testing Guide.
Contributing#
Contributions are welcome! Please see the coordinax contributing guide for details.
License#
coordinax.hypothesis is licensed under the MIT License. See the LICENSE file for details.