unxts.hypothesis API#
Complete API documentation for all unxts.hypothesis strategies.
Hypothesis strategies for unxt.
This is the canonical package (unxts.hypothesis). The legacy unxt_hypothesis
package continues to work via a thin backward-compatible shim.
- unxts.hypothesis.derived_units(base: str | UnitBase | FunctionUnitBase | SearchStrategy[UnitBase | FunctionUnitBase], /, *, integer_powers: bool = True, max_complexity: int = 3)#
Generate hypothesis strategy for units from a given base unit.
This strategy generates units that are dimensionally equivalent to the input base unit by combining the base unit’s base units and discovered composed forms.
- Parameters:
draw (st.DrawFn) – Hypothesis draw function (automatically provided by @st.composite).
base (
Union[str,UnitBase,FunctionUnitBase,SearchStrategy[UnitBase|FunctionUnitBase]]) – Base unit (e.g., “m”, “s”, “kg”) or a hypothesis strategy that generates such units.integer_powers (
bool) – If True, only generate units with integer powers of base units. Default is True.max_complexity (
int) – Maximum number of additional base unit factors to combine. Higher values create more complex compound units. Default is 3.
- Returns:
A unit with the same physical dimension as the input.
- Return type:
SearchStrategy[UnitBase|FunctionUnitBase]
Examples
>>> import hypothesis.strategies as st >>> from hypothesis import given >>> import unxts.hypothesis as ust >>> import unxt as u
Generate units derived from a base unit:
>>> @given(unit=ust.derived_units("m")) ... def test_length_units(unit): ... assert u.dimension_of(unit) == u.dimension("length")
Generate units from a strategy:
>>> @given(unit=ust.derived_units(st.sampled_from(["km/s", "m/s^2"]))) ... def test_velocity_derived(unit): ... assert u.dimension_of(unit) in ( ... u.dimension("velocity"), ... u.dimension("acceleration"), ... )
Control complexity of generated units:
>>> @given(unit=ust.derived_units("kg", max_complexity=1)) ... def test_simple_mass_units(unit): ... assert u.dimension_of(unit) == u.dimension("mass")
Allow non-integer powers:
>>> @given(unit=ust.derived_units("m", integer_powers=False)) ... def test_fractional_powers(unit): ... dim = u.dimension_of(unit) ... assert dim == u.dimension("length")
- unxts.hypothesis.units(dimension: str | PhysicalType | SearchStrategy[PhysicalType] = named_dimensions(), /, **kwargs: Any)#
Generate hypothesis strategy for units with a given physical dimension.
This strategy generates units that are dimensionally equivalent to the input dimension by combining the dimension’s base units and discovered composed forms.
- Parameters:
draw (st.DrawFn) – Hypothesis draw function (automatically provided by @st.composite).
dimension (
Union[str,PhysicalType,SearchStrategy[PhysicalType]]) – Physical dimension (e.g., “velocity”, “length”) or a hypothesis strategy that generates such dimensions. Default is a strategy sampling from the Astropy physical types (seenamed_dimensions).**kwargs (
Any) –Additional keyword arguments passed to derived_units(). For example:
- integer_powersbool
If True, only generate units with integer powers of base units. Default is True.
- max_complexityint
Maximum number of additional base unit factors to combine. Higher values create more complex compound units. Default is 3.
- Returns:
A unit with the same physical dimension as the input.
- Return type:
SearchStrategy[UnitBase|FunctionUnitBase]
Examples
>>> import hypothesis.strategies as st >>> from hypothesis import given >>> import unxts.hypothesis as ust >>> import unxt as u
>>> @given(unit=ust.units("velocity")) ... def test_velocity_units(unit): ... assert u.dimension_of(unit) == u.dimension("velocity")
>>> @given(unit=ust.units("length", integer_powers=False)) ... def test_length_units(unit): ... dim = u.dimension_of(unit) ... assert dim == u.dimension("length")
The dimension argument can also be a strategy:
>>> from hypothesis import strategies as st >>> @given(unit=ust.units(st.sampled_from(["length", "time", "mass"]))) ... def test_multiple_dimensions(unit): ... dim = u.dimension_of(unit) ... assert dim in [ ... u.dimension("length"), ... u.dimension("time"), ... u.dimension("mass"), ... ]
Notes
The strategy works by:
Getting the canonical unit for the dimension
Decomposing it into base SI units
Finding composed forms using .compose()
Generating random combinations by multiplying/dividing other units with cancelling dimensions
- unxts.hypothesis.unitsystems(*units: str | UnitBase | FunctionUnitBase | SearchStrategy[UnitBase | FunctionUnitBase])#
Generate hypothesis strategy for unxt UnitSystem objects.
This strategy supports all the same unit input options as u.unitsystem(). The additional capability provided here is that any unit input can also be a hypothesis strategy, enabling property-based testing with varying units.
- Parameters:
draw (st.DrawFn) – Hypothesis draw function (automatically provided by @st.composite).
*units (
Union[str,UnitBase,FunctionUnitBase,SearchStrategy[UnitBase|FunctionUnitBase]]) – Variable number of unit specifications. Each can be: - str: Fixed unit string (e.g., “kpc”, “Myr”, “Msun”) - unxt.AbstractUnit: Fixed unit object - SearchStrategy: Strategy that generates units
- Returns:
A UnitSystem object created from the specified units.
- Return type:
SearchStrategy[AbstractUnitSystem]
Examples
>>> from hypothesis import given, strategies as st >>> import unxt as u >>> import unxts.hypothesis as ust
Create a unit system with fixed units:
>>> @given(usys=ust.unitsystems("m", "s", "kg", "rad")) ... def test_mks_system(usys): ... assert isinstance(usys, u.AbstractUnitSystem) ... assert len(usys) == 4
Create a unit system with varying length units:
>>> @given(usys=ust.unitsystems(ust.units("length"), "s", "kg", "rad")) ... def test_varying_length_system(usys): ... assert isinstance(usys, u.AbstractUnitSystem) ... assert len(usys) == 4 ... # Length unit will vary, but time is always seconds ... assert usys["time"] == u.unit("s")
Use predefined unit systems by name:
>>> @given(usys=st.just(u.unitsystem("galactic"))) # a fixed system ... def test_galactic_system(usys): ... assert isinstance(usys, u.AbstractUnitSystem) ... assert len(usys) == 4
- unxts.hypothesis.quantities(unit: str | UnitBase | FunctionUnitBase | SearchStrategy[UnitBase | FunctionUnitBase | PhysicalType] | PhysicalType = units(named_dimensions()), *, quantity_cls: type[AbstractQuantity] = <class 'unxt._src.quantity.quantity.Quantity'>, dtype: Any | SearchStrategy[dtype] = <class 'jax.numpy.float32'>, shape: int | tuple[int, ...] | ~hypothesis.strategies.SearchStrategy[int | tuple[int, ...]]=(), elements: SearchStrategy[float] | None = None, unique: bool = False, static_value: bool | SearchStrategy[bool] = False, **kwargs: Any)#
Generate hypothesis strategy for unxt Quantity objects.
This strategy combines JAX array generation with unit specifications to create valid Quantity objects for property-based testing. By default it generates the lightweight unxt.Quantity; pass
quantity_cls(e.g. unxts.parametric.ParametricQuantity) to generate another unxt.AbstractQuantity subclass.- Parameters:
draw (st.DrawFn) – Hypothesis draw function (automatically provided by @st.composite).
unit (
Union[str,UnitBase,FunctionUnitBase,SearchStrategy[UnitBase|FunctionUnitBase|PhysicalType],PhysicalType]) –Unit specification for the Quantity. Can be:
str: Fixed unit (e.g., “kpc”, “km/s”)
unxt.AbstractUnit: Fixed unit object
unxt.AbstractDimension: Dimension to derive unit from (uses unxts.hypothesis.units strategy)
SearchStrategy: Strategy that generates units (e.g., from units()) or dimensions. The default strategy samples from the Astropy physical types (see
named_dimensions).
quantity_cls (
type[AbstractQuantity]) – The target quantity class to convert to. Default is unxt.Quantity. Can be any unxt.AbstractQuantity subclass like unxts.parametric.ParametricQuantity or unxt.Angle.dtype (
Union[Any,SearchStrategy[dtype]]) – NumPy/JAX dtype for the underlying array. Default is jnp.float32. Can also be a SearchStrategy that generates dtypes.shape (
Union[int,tuple[int,...],SearchStrategy[int|tuple[int,...]]]) –Shape of the array. Can be:
int: 1D array of that length
tuple: fixed shape
SearchStrategy: strategy that generates shapes
elements (
Optional[SearchStrategy[float]]) – Strategy for generating array elements. If None, uses finite floats.unique (
bool) – Whether array elements should be unique. Default is False.static_value (
Union[bool,SearchStrategy[bool]]) – Whether to wrap the generated array in unxt.quantity.StaticValue. Default is False.**kwargs (
Any) – Additional keyword arguments forwarded toquantity_cls.
- Returns:
A Quantity object with the specified unit and array properties (or an instance of
quantity_clsif provided).- Return type:
SearchStrategy[AbstractQuantity]
Examples
Basic usage with fixed unit and shape:
>>> from hypothesis import given, strategies as st >>> import jax.numpy as jnp >>> import unxt as u >>> import unxts.hypothesis as ust
>>> @given(q=ust.quantities("kpc", shape=3)) ... def test_position(q): ... assert q.unit == u.unit("kpc") ... assert q.shape == (3,)
>>> @given(q=ust.quantities("km/s", shape=())) ... def test_scalar_velocity(q): ... assert q.unit == u.unit("km/s") ... assert q.shape == ()
Using a unit strategy to vary units across test runs:
>>> @given(q=ust.quantities(ust.units("length"), shape=3)) ... def test_length_with_varying_units(q): ... # Unit will vary across test runs ... assert u.dimension_of(q) == u.dimension("length") ... assert q.shape == (3,)
As a convenience, instead of nesting strategies with
ust.units, you can directly pass the dimension object (not a string) toust.quantities:>>> @given(q=ust.quantities(u.dimension("velocity"), shape=3)) ... def test_velocity_from_dimension(q): ... # Will generate different velocity units (m/s, km/s, etc.) ... assert u.dimension_of(q) == u.dimension("velocity") ... assert q.shape == (3,)
This (and
ust.units) support a strategy for dimensions:>>> dim_strat = st.sampled_from([u.dimension("length"), u.dimension("mass")]) >>> @given(q=ust.quantities(dim_strat, shape=())) ... def test_mixed_dimensions(q): ... # Will generate either length or mass quantities ... dim = u.dimension_of(q) ... assert dim in (u.dimension("length"), u.dimension("mass"))
Using dtype as a strategy:
>>> dtype_strat = st.sampled_from([jnp.float32, jnp.int32]) >>> @given(q=ust.quantities("m", dtype=dtype_strat)) ... def test_varying_dtype(q): ... # dtype will vary between float32 and int32 ... assert q.dtype in (jnp.float32, jnp.int32)
Using elements to constrain value ranges for distances (positive values):
>>> @given( ... q=ust.quantities( ... "kpc", shape=3, elements=st.floats(min_value=0, max_value=100, width=32) ... ) ... ) ... def test_positive_distance(q): ... # All elements will be positive (suitable for distances) ... assert jnp.all(q.value >= 0) ... assert jnp.all(q.value <= 100)
Using elements for longitude angles (0 to 360 degrees):
>>> @given( ... q=ust.quantities( ... "deg", ... shape=(), ... elements=st.floats(min_value=0, max_value=360, width=32), ... ) ... ) ... def test_longitude_range(q): ... # Longitude in [0, 360] degrees ... assert 0 <= q.value <= 360
Using quantity_cls to generate Angle objects:
>>> @given(angle=ust.quantities("rad", quantity_cls=u.Angle, shape=3)) ... def test_angle_generation(angle): ... # Creates Angle instances instead of the default Quantity ... assert isinstance(angle, u.Angle) ... assert angle.unit == u.unit("rad") ... assert angle.shape == (3,)
- unxts.hypothesis.wrap_to(quantity: AbstractQuantity | SearchStrategy[AbstractQuantity], /, min: AbstractQuantity | SearchStrategy[AbstractQuantity], max: AbstractQuantity | SearchStrategy[AbstractQuantity])#
Generate hypothesis strategy for wrapped quantities.
This strategy takes a quantity strategy and wraps the generated values to the specified [min, max) range using the wrap_to function.
- Parameters:
draw – Hypothesis draw function (automatically provided by @st.composite).
quantity (
Union[AbstractQuantity,SearchStrategy[AbstractQuantity]]) – Quantity or strategy that generates the base quantity to wrap.min (
Union[AbstractQuantity,SearchStrategy[AbstractQuantity]]) – Minimum value of the wrapping range (inclusive).max (
Union[AbstractQuantity,SearchStrategy[AbstractQuantity]]) – Maximum value of the wrapping range (exclusive).
- Returns:
The wrapped quantity in the range [min, max).
- Return type:
SearchStrategy[AbstractQuantity]
Examples
Wrap angles to 0-360 degree range:
>>> from hypothesis import given >>> import hypothesis.strategies as st >>> import unxt as u >>> import unxts.hypothesis as ust
>>> @given( ... angle=ust.wrap_to( ... ust.quantities("deg", quantity_cls=u.Angle), ... min=u.Q(0, "deg"), ... max=u.Q(360, "deg"), ... ) ... ) ... def test_wrapped_angle(angle): ... assert 0 <= angle.value <= 360
Wrap angles with dynamic min/max:
>>> @given( ... angle=ust.wrap_to( ... ust.quantities("rad", quantity_cls=u.Angle), ... min=st.just(u.Q(0, "rad")), ... max=st.just(u.Q(6.28318530718, "rad")), ... ) ... ) ... def test_wrapped_angle_rad(angle): ... assert 0 <= angle.value <= 6.28318530718
- unxts.hypothesis.angles(*, wrap_to: tuple[Quantity | SearchStrategy[Quantity], Quantity | SearchStrategy[Quantity]] | None | SearchStrategy[tuple[Quantity | SearchStrategy[Quantity], Quantity | SearchStrategy[Quantity]] | None] = None, **kwargs: Any)#
Strategy for generating Angle instances.
- Parameters:
draw – Hypothesis draw function. Automatically provided by hypothesis.
wrap_to (
Union[tuple[Union[Quantity,SearchStrategy[Quantity]],Union[Quantity,SearchStrategy[Quantity]]],None,SearchStrategy[tuple[Union[Quantity,SearchStrategy[Quantity]],Union[Quantity,SearchStrategy[Quantity]]] |None]]) – Strategy for generating (min, max) bounds for angle wrapping. If None, the angle will have no wrapping specified.**kwargs (
Any) – Additional keyword arguments passed to unxts.hypothesis.quantities. Common options include ‘dtype’, ‘shape’, ‘elements’, ‘unique’. The arguments ‘unit’ and ‘quantity_cls’ are set automatically and should not be provided.
- Returns:
A strategy that generates Angle instances.
- Return type:
SearchStrategy[Angle]
Examples
>>> from hypothesis import given >>> from unxts.hypothesis import angles >>> import unxt as u
>>> @given(angle=angles()) ... def test_angle(angle): ... assert isinstance(angle, u.Angle)
With wrapping:
>>> from hypothesis import strategies as st >>> wrap_bounds = st.just((u.Q(0, "deg"), u.Q(360, "deg"))) >>> @given(angle=angles(wrap_to=wrap_bounds)) ... def test_wrapped_angle(angle): ... assert angle.wrap_to is not None
- unxts.hypothesis.named_dimensions()#
Generate a named dimension from Astropy’s physical type catalogue.
This strategy samples from a finalized, pre-computed set of 134 named physical dimensions derived from Astropy’s physical type system. These dimensions are guaranteed to be resolvable by unxt.dimension().
The set of dimension names is curated from Astropy’s physical types and excludes names that cannot be directly interpreted by unxt (e.g., names with parenthetical qualifiers like “electrical charge (EMU)”).
- Parameters:
draw (st.DrawFn) – Hypothesis draw function (automatically provided by @st.composite).
- Returns:
A randomly selected dimension from the set of named dimensions.
- Return type:
SearchStrategy[PhysicalType]
Examples
Basic usage - generate a dimension:
>>> from hypothesis import given >>> import unxt as u >>> import unxts.hypothesis as ust
>>> @given(dim=ust.named_dimensions()) ... def test_physics_dimension(dim): ... assert isinstance(dim, u.AbstractDimension)
Using with unit generation to create quantities of any dimension:
>>> @given( ... dim=ust.named_dimensions(), ... q=ust.quantities(u.dimension("length"), shape=3), ... ) ... def test_dimension_and_quantity(dim, q): ... # dim varies across test runs from 134 physical types ... assert isinstance(dim, u.AbstractDimension) ... assert q.shape == (3,)
Combine with units strategy:
>>> @given(unit=ust.units(ust.named_dimensions())) ... def test_any_unit(unit): ... # Generate units from any named physical dimension ... assert isinstance(unit, u.AbstractUnit) ... expected_dims = [u.dimension(name) for name in ust.DIMENSION_NAMES] ... assert u.dimension_of(unit) in expected_dims
Property-based testing across all 134 physical types:
>>> @given(dim=ust.named_dimensions()) ... def test_all_dimensions_are_valid(dim): ... # This test will run with 100 different random dimensions ... # (by default, Hypothesis runs 100 examples) ... assert isinstance(dim, u.AbstractDimension) ... assert dim in {u.dimension(name) for name in ust.DIMENSION_NAMES}
See also
DIMENSION_NAMESThe tuple of all available dimension names.
unxt.dimensionCreate a dimension from a name string.
unitsGenerate units with a specific dimension.
quantitiesGenerate quantities with a specific dimension.