API/Reference
Index
Transits.AbstractLimbDark
Transits.AbstractLimbDark
Transits.IntegratedLimbDark
Transits.Kipping13
Transits.PolynomialLimbDark
Transits.QuadLimbDark
Transits.SecondaryLimbDark
Transits.compute
Transits.compute
Light Curves
Transits.AbstractLimbDark
— TypeAbstractLimbDark
A limb dark law need only need to implement compute(::Law, b, r)
to extend the limb darkening interface.
See also
Transits.AbstractLimbDark
— Method(::AbstractLimbDark)(b, r)
An alias for calling compute
Examples
julia> ld = PolynomialLimbDark([0.4, 0.26]);
julia> ld(0, 0.01)
0.9998785437247428
Transits.PolynomialLimbDark
— TypePolynomialLimbDark(u::AbstractVector)
Polynomial limb darkening using analytical integrals. The length of the u
vector is equivalent to the order of polynomial used; e.g., [0.2, 0.3]
corresponds to quadratic limb darkening.
Mathematical form
\[I(\mu) \propto 1 - u_1(1-\mu) - u_2(1-\mu)^2 - \dots - u_N(1-\mu)^N\]
which is equivalent to the series
\[I(\mu) \propto -\sum_{i=0}^N{u_i(1-\mu)^i}\]
with the definition $u_0 \equiv -1$.
Examples
u = [0.4, 0.26] # quadratic and below is 100% analytical
ld = PolynomialLimbDark(u)
ld(0.1, 0.01)
# output
0.9998787880717668
u2 = vcat(u, ones(12) ./ 12)
ld2 = PolynomialLimbDark(u2)
ld2(0.1, 0.01)
# output
0.9998740059086433
References
Agol, Luger, Foreman-Mackey (2020)
"Analytic Planetary Transit Light Curves and Derivatives for Stars with Polynomial Limb Darkening"
"starry: Analytic Occultation Light Curves"
Transits.QuadLimbDark
— TypeQuadLimbDark(u::AbstractVector)
A specialized implementation of PolynomialLimbDark
with a maximum of two terms (quadratic form). This has a completely closed-form solution without any numerical integration. This means there are no intermediate allocations and reduced numerical error.
Mathematical form
\[I(\mu) \propto 1 - u_1(1-\mu) - u_2(1-\mu)^2\]
Higher-order terms will be ignored; no error will be thrown
Examples
ld = QuadLimbDark(Float64[]) # constant term only
b = [0, 1, 2] # impact parameter
r = 0.01 # radius ratio
ld.(b, r)
# output
3-element Vector{Float64}:
0.9999
0.9999501061035608
1.0
ld = QuadLimbDark([0.4, 0.26]) # max two terms
ld.(b, r)
# output
3-element Vector{Float64}:
0.9998785437247428
0.999974726693709
1.0
References
See references for PolynomialLimbDark
Transits.IntegratedLimbDark
— TypeIntegratedLimbDark(limbdark; N=21, basis=:legendre)
IntegratedLimbDark(u; kwargs...)
Computes the time-averaged flux in the middle of an exposure by wrapping a limb darkening law limbdark
with a quadrature scheme. For each time step t
, N
extra points are super-sampled from t-texp/2
to t+texp/2
and the time-averaged flux is calculated via quadrature.
If a set of limb darkening coefficients, u
, is provided, a PolynomialLimbDark
law will be used by default.
Mathematical form
\[\bar{F}(t) = \frac{1}{\Delta t}\int_{t-\Delta t / 2}^{t+\Delta t / 2}{F(t')dt'}\]
where $F$ is the wrapped limb darkening law and $\Delta t$ is the exposure time.
Quadrature
The integration is approximated via Guassian quadrature
\[\frac{1}{\Delta t} \int{F(t')dt'} \approx \frac12\sum_i^N{w_i * F(\frac{\Delta t}{2}\xi_i + t)}\]
where the weights w_i
and nodes ξ_i
are defined by the given quadrature rule. The nodes are defined by evaluating orthogonal polynomials N
times between -1 and 1. Notice the change of interval required to go from the natural bounds of the orthogonal polynomial basis, -1, 1
, to the range defined by the exposure time.
The following bases are available from FastGaussQuadrature.jl. In addition, a function can be passed which calculates nodes, weights = f(N)
.
:legendre
- Legendre polynomial base on the open(-1, 1)
:radau
- Legendre polynomial base on the semi-open[-1, 1)
interval:lobatto
- Legendre polynomial base on the closed[-1, 1]
interval
Transits.SecondaryLimbDark
— TypeSecondaryLimbDark(primary::AbstractLimbDark,
secondary::AbstractLimbDark;
brightness_ratio=1)
SecondaryLimbDark(u_p::AbstractVector, u_s=u_p; kwargs...)
Compose two limb darkening laws together to add a secondary eclipse. If vectors of coefficients are provided, laws will automatically be constructed using PolynomialLimbDark
. The surface brightness ratio is given in terms of the host; e.g., if the companion is half as bright as the host, the ratio would be 0.5.
SecondaryLimbDark
only works with an orbit, since the companion's reference frame needs to be calculated. This means you can't call it using an impact parameter like ld(b, r)
directly.
Mathematical form
\[f(t, r) = \frac{2f_p(t, r) + \eta r^2 f_s(t', r')}{1 + f_p(t, r) + \eta r^2 f_s(t', r')}\]
where $f_p$ is to the primary flux, $f_s$ is to the secondary flux, and $\eta$ is the surface brightness ratio. $t'$ and $r'$ correspond to the time and radius ratio from the companion's reference frame.
Examples
using Orbits
# equal size and limb darkening
r = 1.0
u = [0.4, 0.26]
# companion is 1/10 as bright
brightness_ratio = 0.1
ld = SecondaryLimbDark(u; brightness_ratio)
orbit = SimpleOrbit(period=2, duration=0.5)
fp = ld(orbit, 0, r) # primary egress
fs = ld(orbit, 1, r) # secondary egress
fp ≈ brightness_ratio * fs
# output
true
Transits.compute
— Functioncompute(::AbstractLimbDark, b, r; kwargs...)
Compute the relative flux for the given impact parameter b
and radius ratio r
. The impact parameter is unitless. The radius ratio is given in terms of the host; e.g., if the companion is half the size of the host, r=0.5.
Transits.compute
— Methodcompute(::AbstractLimbDark, orbit::AbstractOrbit, t, r)
Compute the relative flux by calculating the impact parameter at time t
from the given orbit. The time needs to be compatible with the period of the orbit, nominally in days.
Examples
julia> using Orbits
julia> ld = PolynomialLimbDark([0.4, 0.26]);
julia> orbit = SimpleOrbit(period=3, duration=1);
julia> ld(orbit, 0, 0.1) # primary egress
0.9878664434953113
julia> ld(orbit, 0.1, 0.1) # 0.1 d
0.9879670695533511
this works effortlessly with libraries like Unitful.jl
julia> using Unitful
julia> orbit = SimpleOrbit(period=3u"d", duration=3u"hr");
julia> ld(orbit, 0u"d", 0.1)
0.9878664434953113
Gradients
Gradients and jacobians are integrated directly into ChainRules.jl via frule
s and rrule
s. For most users, this just means using AD libraries like ForwardDiff.jl and Zygote.jl is effortless and fast.
using Transits
using Zygote
lightcurve(X) = compute(PolynomialLimbDark(X[3:end]), X[1], X[2])
grad(X) = lightcurve'(X) # Zygote gradient
grad([0.1, 0.1, 0.4, 0.26])
# output
4-element Vector{Float64}:
0.0004972185834858653
-0.2419262730830416
-0.0048107583897073185
-0.0024501564976671724
To help demonstrate the logic behind these chain rules, here we derive a simple gradient function manually.
using ChainRulesCore
u_n = [0.4, 0.26]
μ = 0.1
ror = 0.1
X0 = [μ, ror, u_n...]
function gradr(X)
ld, ld_pullback = rrule(PolynomialLimbDark, X[3:end])
f, f_pullback = rrule(compute, ld, X[1], X[2])
f̄ = one(eltype(X))
_, l̄d, b̄, r̄ = f_pullback(f̄)
_, ū_n = ld_pullback(l̄d)
return [b̄, r̄, ū_n...]
end
gradr([0.1, 0.1, 0.4, 0.26])
# output
4-element Vector{Float64}:
0.0004972185834858653
-0.2419262730830416
-0.0048107583897073185
-0.0024501564976671724
For the most granular support for gradients and jacobians, peer into the depths of polynomial/poly-grad.jl
and polynomial/quad-grad.jl
. These functions are not part of the public API and are not guaranteed any stability according to semantic versioning.
Distributions
Transits.Kipping13
— TypeKipping13()
A non-informative prior for two-parameter limb-darkening coefficients using triangular sampling (Kipping 2013).
Examples
julia> using StableRNGs; rng = StableRNG(10);
julia> rand(rng, Kipping13())
2-element Vector{Float64}:
0.3361047299132651
-0.025681638815114587
julia> rand(rng, Kipping13(), 5)
2×5 Matrix{Float64}:
0.0621057 0.992689 1.77965 0.784055 0.186386
0.0659477 -0.236613 -0.795884 -0.187791 0.592194
References
"Efficient, uninformative sampling of limb darkening coefficients for two-parameter laws"