empyrean.PlanCandidates¶
- class PlanCandidates(table, **kwargs)[source]
Bases:
TablePer-candidate information gain — one row per planned observation.
Mirrors a vector of
empyrean::PlanCandidatefield-for-field.Rows are in the engine’s evaluation order, which is not necessarily the order the candidates were supplied in, so a row does not carry its input epoch. For an optical row,
indexis the row in the companionPlanEphemeristable, which does carry the epoch along with the predicted sky position; for a radar row it is that candidate’s position among the radar candidates.Angular quantities are in arcseconds;
position_angle_degis in degrees (east of north).Methods
__init__(table, **kwargs)apply_mask(mask)Return a new table with rows filtered to match a boolean mask.
as_column([nullable, metadata])Embed the Table as a column in another Table.
attributes()Return a dictionary of the table's attributes.
best_by_information_gain([n])Top-
nrows bymarginal_volume_reduction, in rank order — the best candidate first, not table order.chunk_counts()Returns the number of discrete memory chunks that make up each of the Table's underlying arrays.
column(column_name)Returns the column with the given name as a raw pyarrow ChunkedArray.
drop_duplicates([subset, keep])Drop duplicate rows from a ~quivr.Table.
empty(**kwargs)Create an empty instance of the table.
flattened_table()Completely flatten the Table's underlying Arrow table, taking into account any nested structure, and return the data table itself.
fragmented()Returns true if the Table has any fragmented arrays.
from_csv(input_file[, validate])Read a table from a CSV file.
from_dataframe(df[, validate])Load a DataFrame into the Table.
from_feather(path[, validate])Read a table from a Feather file.
from_flat_dataframe(df[, validate])Load a flattened DataFrame into the Table.
from_kwargs([validate, permit_nulls])Create a Table instance from keyword arguments.
from_parquet(path[, memory_map, ...])Read a table from a Parquet file.
from_pyarrow(table[, validate, permit_nulls])Create a new table from a pyarrow Table.
invalid_mask()Return a boolean mask indicating which rows are invalid.
is_valid()Validate the table against the schema.
null_mask()Return a boolean mask indicating which rows of the entire table are null.
nulls(size, **kwargs)Create a table with nulls.
observable_only()Rows with
observable == True.select(column_name, value)Select from the table by exact match, returning a new Table which only contains rows for which the value in column_name equals value.
select_station(obs_codes)Rows from one or more observatory / receive-station codes.
separate_invalid()Separates rows that have invalid data from those that have valid data.
set_column(name, data)Return a copy of the table with a particular column replaced with new data.
sort_by(by)Sorts the Table by the given column name (or multiple columns).
take(row_indices)Return a new Table with only the rows at the given indices.
to_csv(path[, attribute_columns])Write the table to a CSV file.
to_dataframe([flatten, attr_handling])Returns self as a pandas DataFrame.
to_feather(path, **kwargs)Write the table to a Feather file.
to_parquet(path, **kwargs)Write the table to a Parquet file.
to_structarray()Returns self as a StructArray.
unique_indices([subset, keep])Get the indices of the first or last occurrence of each unique row in the table.
validate()Validate the table against the schema, raising an exception if invalid.
where(expr)Return a new table with rows filtered to match an expression.
with_table(table)Attributes
active_widthWidth of the solve-for set this candidate folded into.
along_track_sigma_arcsecPrior along-track 1σ on the sky plane, in the frame of the predicted sky motion.
cross_track_sigma_arcsecPrior cross-track 1σ on the sky plane, same "no candidate folded" basis as
along_track_sigma_arcsec.cumulative_log_detCumulative , in AU and AU·day⁻¹ like
PlanMetrics.log_det.cumulative_position_sigma_kmRSS position 1σ (km) after this observation and every one folded before it — including any reported unobservable, since the fold does not consult
observable.cumulative_semi_major_kmSemi-major axis of the cumulative 1σ position ellipsoid (km).
cumulative_semi_minor_kmSemi-minor axis of the cumulative 1σ position ellipsoid (km).
cumulative_velocity_sigma_m_sRSS velocity 1σ (m/s) at the orbit epoch, after this observation and every one folded before it.
dec_sigma_arcsecPrior Dec 1σ, no candidate folded.
indexRow in
PlanEphemerisfor an optical candidate; rank among the radar candidates, ordered by epoch, for a radar one.kind"optical"or"radar".marginal_position_improvementFractional position-σ improvement from this one observation, in .
marginal_volume_reductionPer-dimension generalized-variance ratio from this one observation, over the 6×6 state covariance (≤ 1) — a D-optimality score normalized to one dimension, so it reads as a linear scale factor and is comparable across plans.
obs_codeObservatory code (optical) or receive-station code (radar).
observableWhether the candidate passes its observability filters — with a different meaning per
kind, so branch on it before using this as a gate.position_angle_degPosition angle of the predicted sky motion (degrees, east of north) — the axis the along/cross-track σ above are projected onto.
post_along_track_sigma_arcsecAlong-track 1σ after folding this observation and every one folded before it.
post_cross_track_sigma_arcsecCross-track 1σ after folding this observation and every one folded before it.
ra_sigma_arcsecPrior RA·cosδ 1σ, no candidate folded.
radar_mode"delay"/"doppler"/"both".radar_provenanceAssumptions the link budget had to make to reach the SNR — for example a diameter derived from and , or coherent integration left uncapped because the spin period is unknown.
radar_range_kmOne-way topocentric range to the target at the receive epoch (km), from the predicted round-trip delay.
radar_snrEffective SNR the measurement σ was derived from (a linear power ratio, not dB) — the supplied value, or the one the link budget produced.
schematable- Parameters:
table (Table)
kwargs (AttributeValueType)
- schema: ClassVar[Schema] = index: uint64 not null obs_code: large_string not null kind: large_string not null observable: bool not null marginal_volume_reduction: double not null marginal_position_improvement: double not null active_width: uint64 not null cumulative_position_sigma_km: double not null cumulative_velocity_sigma_m_s: double not null cumulative_semi_major_km: double not null cumulative_semi_minor_km: double not null cumulative_log_det: double not null along_track_sigma_arcsec: double cross_track_sigma_arcsec: double ra_sigma_arcsec: double dec_sigma_arcsec: double position_angle_deg: double post_along_track_sigma_arcsec: double post_cross_track_sigma_arcsec: double radar_mode: large_string radar_snr: double radar_range_km: double radar_provenance: large_list<item: large_string> not null child 0, item: large_string
- index
Row in
PlanEphemerisfor an optical candidate; rank among the radar candidates, ordered by epoch, for a radar one.A radar row carries no epoch of its own, so this rank is the only key back to the input: sort the radar candidates you submitted by epoch and the n-th is the row with
index == n.
- obs_code
Observatory code (optical) or receive-station code (radar).
- kind
"optical"or"radar".
- observable
Whether the candidate passes its observability filters — with a different meaning per
kind, so branch on it before using this as a gate.On an optical row this is a real engine verdict, and today it is a solar-elongation test and nothing else: the limiting magnitude the engine would also apply cannot fire, because the target’s absolute magnitude does not reach the planner. On a radar row it is always
True— no radar feasibility test runs on this entry point, soTruemeans “not assessed”, not “checked and cleared”. In particular no antenna-elevation or horizon test is applied, so a track below the horizon still reportsTrue.The filters are engine-set and not caller-configurable — no field on
PlanningConfigorPlannedObservationreaches them. An unobservable candidate is reported rather than dropped, and is still folded into thecumulative_*columns and intoPlanResult.posterior; seeobservable_only().
- marginal_volume_reduction
Per-dimension generalized-variance ratio from this one observation, over the 6×6 state covariance (≤ 1) — a D-optimality score normalized to one dimension, so it reads as a linear scale factor and is comparable across plans.
The 1σ ellipsoid volume ratio is this value cubed, and the raw determinant ratio is it to the sixth power. Conditional on the candidates folded before this one — see
best_by_information_gain().
- marginal_position_improvement
Fractional position-σ improvement from this one observation, in . Conditional on the candidates folded before it, like
marginal_volume_reduction.
- active_width
Width of the solve-for set this candidate folded into. Always 6 (state-only) on this entry point — the non-gravitational solve is not exposed; see the Notes on
empyrean.evaluate_plan().
- cumulative_position_sigma_km
RSS position 1σ (km) after this observation and every one folded before it — including any reported unobservable, since the fold does not consult
observable.
- cumulative_velocity_sigma_m_s
RSS velocity 1σ (m/s) at the orbit epoch, after this observation and every one folded before it.
- cumulative_semi_major_km
Semi-major axis of the cumulative 1σ position ellipsoid (km).
- cumulative_semi_minor_km
Semi-minor axis of the cumulative 1σ position ellipsoid (km).
- cumulative_log_det
Cumulative , in AU and AU·day⁻¹ like
PlanMetrics.log_det.
- along_track_sigma_arcsec
Prior along-track 1σ on the sky plane, in the frame of the predicted sky motion. Null on a radar row: radar measures line-of-sight range and range-rate, so there is no on-sky geometry to report.
“Prior” is literal — the campaign prior mapped to this candidate’s epoch with no candidate folded, not even this one. Its partner
post_along_track_sigma_arcsecis cumulative, so the pair is not a single-observation bracket.
- cross_track_sigma_arcsec
Prior cross-track 1σ on the sky plane, same “no candidate folded” basis as
along_track_sigma_arcsec. Null on a radar row.Along- and cross-track are a projection onto the sky-motion frame, not the principal axes of the sky covariance, so cross-track may legitimately exceed along-track.
- ra_sigma_arcsec
Prior RA·cosδ 1σ, no candidate folded. Null on a radar row.
- dec_sigma_arcsec
Prior Dec 1σ, no candidate folded. Null on a radar row.
- position_angle_deg
Position angle of the predicted sky motion (degrees, east of north) — the axis the along/cross-track σ above are projected onto. Null on a radar row.
This is kinematic and does not depend on the covariance: it is not the orientation of the sky-plane uncertainty ellipse. The range is ; add 360 to negative values (equivalently
numpy.mod(pa, 360.0)) for the conventional position-angle convention.
- post_along_track_sigma_arcsec
Along-track 1σ after folding this observation and every one folded before it. Null on a radar row.
Cumulative, on the same basis as the
cumulative_*columns — not the far end of a single-observation bracket againstalong_track_sigma_arcsec, which folds nothing.
- post_cross_track_sigma_arcsec
Cross-track 1σ after folding this observation and every one folded before it. Cumulative, like
post_along_track_sigma_arcsec. Null on a radar row.
- radar_mode
"delay"/"doppler"/"both". Null on an optical row.
- radar_snr
Effective SNR the measurement σ was derived from (a linear power ratio, not dB) — the supplied value, or the one the link budget produced. Null on an optical row.
- radar_range_km
One-way topocentric range to the target at the receive epoch (km), from the predicted round-trip delay. Null on an optical row.
- radar_provenance
Assumptions the link budget had to make to reach the SNR — for example a diameter derived from and , or coherent integration left uncapped because the spin period is unknown. Empty for an optical candidate, a caller-supplied SNR, or a fully specified link budget. Never summarized to a code: a note the engine adds later would be lost.
- observable_only()[source]
Rows with
observable == True.Warning
This filters rows, not information. Every candidate was folded regardless of its verdict, so a surviving row’s
cumulative_*columns still contain the contributions of the rows this dropped, andPlanResult.posteriorstill prices the whole submitted plan. To price the observable subset, rebuildplannedwithout the unobservable candidates and callempyrean.evaluate_plan()again.- Return type:
PlanCandidates
- select_station(obs_codes)[source]
Rows from one or more observatory / receive-station codes.
- best_by_information_gain(n=10)[source]
Top-
nrows bymarginal_volume_reduction, in rank order — the best candidate first, not table order.The metric is a reduction factor, so smaller is better: a candidate that halves the generalized variance ranks above one that barely moves it. NaN rows sort last. Ties keep their relative table order.
Warning
The gains are order-conditional. The engine folds candidates in ascending epoch order and measures each against the covariance that already contains every earlier one, so a later candidate is scored against a tighter prior and reports a smaller gain. Two identical observations do not score identically. This ranks conditional contributions within one campaign; to compare candidates head to head, evaluate a separate one-candidate plan for each.
- Return type:
PlanCandidates- Parameters:
n (int)