Source code for lightcurve_strategies.starry

"""Hypothesis strategies for ``jaxoplanet.starry`` objects."""

from __future__ import annotations

import math

from hypothesis import strategies as st
from hypothesis.strategies import SearchStrategy
from jaxoplanet.orbits.keplerian import Body, Central
from jaxoplanet.starry.orbit import SurfaceSystem
from jaxoplanet.starry.surface import Surface
from jaxoplanet.starry.ylm import Ylm

from lightcurve_strategies.keplerian import bodies, centrals


[docs] @st.composite def surfaces( draw: st.DrawFn, *, y: SearchStrategy[Ylm | None] | None = None, inc: SearchStrategy[float] | None = None, obl: SearchStrategy[float | None] | None = None, period: SearchStrategy[float | None] | None = None, amplitude: SearchStrategy[float] | None = None, u: SearchStrategy[tuple] | None = None, ) -> Surface: """Generate random ``jaxoplanet.starry.Surface`` instances. Conservative defaults matching the ``Surface()`` constructor defaults. Unlike the keplerian strategies, ``surfaces()`` does not perform ``astropy.units.Quantity`` conversion — all parameters are in radians or dimensionless and are passed through to ``Surface()`` directly. Parameters ---------- y: Strategy for spherical harmonic map. Default: ``just(None)`` (uniform map). Typically use ``st.just(ylm_instance)`` with a pre-built ``Ylm`` rather than generating randomly. inc: Strategy for inclination (radians). Default: ``just(π/2)``. obl: Strategy for obliquity (radians). Default: ``just(None)``. period: Strategy for rotation period. Default: ``just(None)``. amplitude: Strategy for luminosity amplitude. Default: ``just(1.0)``. u: Strategy for limb-darkening coefficients tuple. Default: ``just(())``. """ if y is None: y = st.just(None) if inc is None: inc = st.just(0.5 * math.pi) if obl is None: obl = st.just(None) if period is None: period = st.just(None) if amplitude is None: amplitude = st.just(1.0) if u is None: u = st.just(()) y_val = draw(y) inc_val = draw(inc) obl_val = draw(obl) period_val = draw(period) amplitude_val = draw(amplitude) u_val = draw(u) kwargs: dict = {} if y_val is not None: kwargs["y"] = y_val if inc_val is not None: kwargs["inc"] = inc_val if obl_val is not None: kwargs["obl"] = obl_val if period_val is not None: kwargs["period"] = period_val kwargs["amplitude"] = amplitude_val kwargs["u"] = u_val return Surface(**kwargs)
[docs] @st.composite def surface_systems( draw: st.DrawFn, *, central: SearchStrategy[Central] | None = None, central_surface: SearchStrategy[Surface] | None = None, body: SearchStrategy[tuple[Body, Surface | None]] | None = None, min_bodies: int = 0, max_bodies: int = 5, ) -> SurfaceSystem: """Generate random ``jaxoplanet.starry.orbit.SurfaceSystem`` instances. Parameters ---------- central: Strategy for the central star. Default: ``centrals()``. central_surface: Strategy for the central surface. Default: ``surfaces()``. body: Strategy producing ``(Body, Surface | None)`` tuples. Default: ``st.tuples(bodies(), surfaces())``. min_bodies: Minimum number of bodies. Default: ``0``. max_bodies: Maximum number of bodies. Default: ``5``. """ if central is None: central = centrals() if central_surface is None: central_surface = surfaces() if body is None: body = st.tuples(bodies(), surfaces()) central_val: Central = draw(central) central_surface_val: Surface = draw(central_surface) n_bodies: int = draw(st.integers(min_value=min_bodies, max_value=max_bodies)) sys = SurfaceSystem(central=central_val, central_surface=central_surface_val) for _ in range(n_bodies): body_obj, surface_obj = draw(body) sys = sys.add_body(body=body_obj, surface=surface_obj) return sys