orbix.viz.orbit#

Sky-plane and 3D orbit plots: extract, delegate to eyepiece, decorate.

orbix supplies only what eyepiece cannot know: how to turn an orbit into tracks (propagation, projection, units), which axis is RA (and that astronomers draw it increasing to the left), and where periapsis and the nodes sit. The rendering itself is eyepiece’s sky_fan and trail, so figures drawn here match every other figure built on eyepiece.

Every function that accepts an orbit also accepts bare track arrays, for consumers holding precomputed coordinates (a CSV of posterior traces, a cached ephemeris) rather than a live KeplerianOrbit. On the bare-array door the units belong to the caller, so no axis labels are set.

Functions#

_resolve_color(ep, style)

Resolve style (color, SourceStyles entry, or None) to a color.

_neutral(level)

A tone level of the way from the axes facecolor to the text color.

_orbit_look(style, ep, depth)

The 3D orbit rendering defaults: marker color and path-line kwargs.

size_by_radius(radius_Rearth, *[, ms_range, ...])

Marker diameters encoding planet radii, geometrically interpolated.

_per_track(values, n_tracks, name)

Broadcast a scalar or length-K sequence to one float per track.

_sky_tracks(orbit_or_radec, t_jd, Ms_kg, dist_pc, ...)

Normalize the input to (ra, dec) arrays of shape (K, T).

plot_sky_track(orbit_or_radec[, t_jd, Ms_kg, dist_pc, ...])

Draw sky-plane orbit tracks: one orbit, or a fan of K candidates.

_positions(orbit_or_xyz, t_jd, Ms_kg, trig_solver)

Normalize the input to positions of shape (K, T, 3).

_nu_to_trig_E(nu, e)

Convert a true anomaly to (sinE, cosE) of the eccentric anomaly.

_mark_geometry(orbit)

Exact periapsis and node positions per orbit, from the elements.

plot_orbit(orbit_or_xyz[, t_jd, Ms_kg, trig_solver, ...])

Draw one or more orbits in 3D, star-centric AU, via eyepiece.trail.

Module Contents#

orbix.viz.orbit._resolve_color(ep, style)[source]#

Resolve style (color, SourceStyles entry, or None) to a color.

None resolves to the active palette’s first color through the public SourceStyles mechanism, at call time, so a mode switch between two calls is honored.

orbix.viz.orbit._neutral(level)[source]#

A tone level of the way from the axes facecolor to the text color.

Resolved from the active rcParams at call time, so the same level is a light gray on a dark background and a dark gray on a light one – the scenery inverts with the mode instead of freezing one gray for both.

orbix.viz.orbit._orbit_look(style, ep, depth)[source]#

The 3D orbit rendering defaults: marker color and path-line kwargs.

With no style and depth="markers", the look is the classic star-chart one: markers in the mode’s text color (white dots on a dark background) over a transparent dashed gray path. Under any other depth cue there are no markers, so the path itself has to be the visible element and takes the text color rather than a dim gray – otherwise an unstyled orbit renders as a barely-there gray line. A style opts out into that source’s color either way.

orbix.viz.orbit.size_by_radius(radius_Rearth, *, ms_range=(3.0, 9.0), radius_range_Rearth=(0.38, 11.2))[source]#

Marker diameters encoding planet radii, geometrically interpolated.

The base marker size is the anchor the depth cue swells around, so it is the place physical meaning lives. This maps radii onto diameters the same way the original hand-tuned renders mapped mass onto marker size: geometrically between ms_range across radius_range_Rearth (Mercury to Jupiter by default), so a super-Earth reads visibly larger than a sub-Earth without Jupiter dwarfing everything. Radii outside the range clip to its ends.

The result is a set of marker DIAMETERS in points, which is what animate_orbit(base_ms=...) takes (matplotlib’s ms). Do NOT pass it to plot_orbit(marker_scale=...): that reaches scatter(s=...), an AREA in points squared, so the diameters would be read as areas and the encoding silently square-rooted – an 11.2-Earth-radius planet drawn 1.48x an Earth instead of 2.19x. Square the result first if you need an area.

Parameters:
  • radius_Rearth – Planet radii in Earth radii, scalar or (K,).

  • ms_range – Marker diameters in points at the two ends of the radius range.

  • radius_range_Rearth – The radii mapped onto ms_range’s ends.

Returns:

Marker diameters in points, shape (K,).

orbix.viz.orbit._per_track(values, n_tracks, name)[source]#

Broadcast a scalar or length-K sequence to one float per track.

orbix.viz.orbit._sky_tracks(orbit_or_radec, t_jd, Ms_kg, dist_pc, trig_solver)[source]#

Normalize the input to (ra, dec) arrays of shape (K, T).

Returns:

(ra, dec, from_orbit) where from_orbit records whether the tracks were propagated here (and are therefore known to be in arcsec) or handed in raw.

orbix.viz.orbit.plot_sky_track(orbit_or_radec, t_jd=None, *, Ms_kg=None, dist_pc=None, trig_solver=None, ax=None, style=None, colors=None, weights=None, data=None, iwa=None, invert_ra=True, fan_kw=None)[source]#

Draw sky-plane orbit tracks: one orbit, or a fan of K candidates.

A (K,)-batched orbit (posterior draws through KeplerianOrbit.from_period, for instance) becomes a fan of K tracks faded by weights; a single orbit becomes one solid track. Delegation is to eyepiece.sky_fan, which owns the equal aspect, the central-star marker, the optional inner-working-angle disk, and the optional observed-epoch errorbars.

Parameters:
  • orbit_or_radec – An AbstractOrbit (propagated here, requiring t_jd, Ms_kg, dist_pc), or bare tracks: an (ra, dec) pair of (T,) or (K, T) arrays, or an array shaped (2, T) or (K, 2, T). Bare tracks are in whatever units the caller made them, so no axis labels are set on that door.

  • t_jd – Times in Julian Days, shape (T,). Orbit door only.

  • Ms_kg – Stellar mass in kg. Orbit door only.

  • dist_pc – Distance to the star in parsecs. Orbit door only.

  • trig_solver – Optional Kepler solver forwarded to the orbit; None uses orbix’s default.

  • ax – Axes to draw into. None creates a new figure and axes.

  • style – A color, or a SourceStyles entry, applied to every track – a fan of candidates for one planet is one source, so it takes one color rather than cycling the palette. None uses the active palette’s first color.

  • colors – Optional per-track color list (length K), for a fan whose tracks carry distinct meaning (period-alias families, for instance). Overrides style for the track colors.

  • weights – Optional per-track weights (length K), fading each track’s alpha; typically posterior mass per draw.

  • data – Optional (ra, dec, err) tuple of observed epochs, drawn as errorbars by sky_fan.

  • iwa – Optional inner-working-angle radius, in the same units as the tracks (arcsec on the orbit door), drawn as a shaded disk.

  • invert_ra – Invert the x axis so RA offset increases to the left (the astronomer’s convention; orbix’s own frame maps x to RA with no flip). An already-inverted axis is left alone, so overplotting onto the same axes does not flip it back.

  • fan_kw – Extra kwargs for each track’s ax.plot call, routed through sky_fan and applied last. For a single track the base alpha defaults to 0.75 (a solid line) instead of sky_fan’s fan default.

Returns:

artists "lines" (one Line2D per track), plus "ellipse" when iwa is given and "collection" when data is given.

Return type:

The eyepiece.PlotResult from sky_fan

orbix.viz.orbit._positions(orbit_or_xyz, t_jd, Ms_kg, trig_solver)[source]#

Normalize the input to positions of shape (K, T, 3).

Returns:

(positions, orbit_or_none) – the orbit comes back so exact mark geometry can be computed from its elements rather than re-derived from the sampled track.

orbix.viz.orbit._nu_to_trig_E(nu, e)[source]#

Convert a true anomaly to (sinE, cosE) of the eccentric anomaly.

orbix.viz.orbit._mark_geometry(orbit)[source]#

Exact periapsis and node positions per orbit, from the elements.

Positions come through the same A (cosE - e) + B sinE propagation form the orbit itself uses, so a mark sits exactly on the drawn track rather than on a re-derived approximation. The ascending node is identified analytically: z along the orbit is A_z (cosE - e) + B_z sinE, so its derivative in E is -A_z sinE + B_z cosE and the node with a positive derivative is ascending (E increases monotonically with time).

Returns:

(periapsis, ascending, descending), each (K, 3) in AU.

orbix.viz.orbit.plot_orbit(orbit_or_xyz, t_jd=None, *, Ms_kg=None, trig_solver=None, ax=None, style=None, marks=None, depth=None, marker_scale=25.0, trail_kw=None)[source]#

Draw one or more orbits in 3D, star-centric AU, via eyepiece.trail.

The trajectory rendering – connected path, depth-cued marker sizes, camera-aware layering – is trail’s; orbix adds the propagation, the star at the origin, symmetric axis limits so the orbit is not distorted, AU labels, and the optional exact periapsis/node marks.

trail bakes its depth cues from the camera at call time, so set the view first (ax.view_init(...) before calling this function) and keep the camera well off the orbit normal – a near-face-on view collapses the marker-size depth cue.

Parameters:
  • orbit_or_xyz – An AbstractOrbit (propagated here, requiring t_jd and Ms_kg), or bare positions shaped (T, 3) or (K, T, 3). Bare positions are in whatever units the caller made them, so no axis labels are set on that door.

  • t_jd – Times in Julian Days, shape (T,). Orbit door only.

  • Ms_kg – Stellar mass in kg. Orbit door only.

  • trig_solver – Optional Kepler solver forwarded to the orbit; None uses orbix’s default.

  • ax – A projection="3d" axes to draw into. None creates one.

  • style – A color, or a SourceStyles entry (which also sets the track marker), applied to every track: solid path and markers in that color. None gives the star-chart default – markers in the mode’s text color (white dots on a dark background) over a transparent dashed gray path.

  • marks – Optional set drawn from {"periapsis", "nodes"}. Orbit door only – exact mark geometry needs the elements, so bare xyz tracks raise if marks are requested. Periapsis is a diamond in the track color; the nodes are up/down triangles joined by a dashed line of nodes through the origin.

  • depth – Forwarded to eyepiece.trail: how the path shows which half faces the camera. None takes trail’s own default, the hidden-line convention – the whole orbit dashed and dim with the near half overdrawn solid. "markers" restores the older per-point markers, which also restores the star-chart look when no style is given. "none" drops the cue.

  • marker_scale – Forwarded to trail: marker AREA in points squared (matplotlib’s scatter(s=)) at full illumination, for the per-point depth cue a still figure needs. Pass 0.0 for a bare line – an animation does this, since its moving head carries the depth cue instead. Note the unit: this is an area, while size_by_radius returns diameters, so the two do not compose directly. Note also that trail’s still depth law takes marker area to zero on the far side, so a per-track marker_scale encoding a physical quantity is unrecoverable there; encode physical size on an animation’s base_ms instead, whose law is anchored at the base size.

  • trail_kw – Extra kwargs for the connecting-line ax.plot call, forwarded to trail and applied last.

Returns:

An eyepiece.PlotResult. For a single track the artists are trail’s "line" and "scatter"; for K tracks they are "lines" and "scatter" lists in track order. "scatter" holds one depth-cue artist per track, whichever the mode drew: a PathCollection under depth="markers", the solid near-half Line3D under the default hidden-line cue, and nothing at all under depth="none". Mark artists are appended to "scatter" (periapsis first, then nodes) and the line of nodes to "lines", after the per-track entries.