empyrean.PlanCandidates

class PlanCandidates(table, **kwargs)[source]

Bases: Table

Per-candidate information gain — one row per planned observation.

Mirrors a vector of empyrean::PlanCandidate field-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, index is the row in the companion PlanEphemeris table, 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_deg is 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-n rows by marginal_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_width

Width of the solve-for set this candidate folded into.

along_track_sigma_arcsec

Prior along-track 1σ on the sky plane, in the frame of the predicted sky motion.

cross_track_sigma_arcsec

Prior cross-track 1σ on the sky plane, same "no candidate folded" basis as along_track_sigma_arcsec.

cumulative_log_det

Cumulative lndetΣ\ln \det \Sigma, in AU and AU·day⁻¹ like PlanMetrics.log_det.

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_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_velocity_sigma_m_s

RSS velocity 1σ (m/s) at the orbit epoch, after this observation and every one folded before it.

dec_sigma_arcsec

Prior Dec 1σ, no candidate folded.

index

Row in PlanEphemeris for an optical candidate; rank among the radar candidates, ordered by epoch, for a radar one.

kind

"optical" or "radar".

marginal_position_improvement

Fractional position-σ improvement from this one observation, in [0,1][0, 1].

marginal_volume_reduction

Per-dimension generalized-variance ratio from this one observation, (detΣpost/detΣprior)1/6(\det \Sigma_\mathrm{post} / \det \Sigma_\mathrm{prior})^{1/6} 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_code

Observatory code (optical) or receive-station code (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.

position_angle_deg

Position angle of the predicted sky motion (degrees, east of north) — the axis the along/cross-track σ above are projected onto.

post_along_track_sigma_arcsec

Along-track 1σ after folding this observation and every one folded before it.

post_cross_track_sigma_arcsec

Cross-track 1σ after folding this observation and every one folded before it.

ra_sigma_arcsec

Prior RA·cosδ 1σ, no candidate folded.

radar_mode

"delay" / "doppler" / "both".

radar_provenance

Assumptions the link budget had to make to reach the SNR — for example a diameter derived from HH and pVp_V, or coherent integration left uncapped because the spin period is unknown.

radar_range_km

One-way topocentric range to the target at the receive epoch (km), from the predicted round-trip delay.

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.

schema

table

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 PlanEphemeris for 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, so True means “not assessed”, not “checked and cleared”. In particular no antenna-elevation or horizon test is applied, so a track below the horizon still reports True.

The filters are engine-set and not caller-configurable — no field on PlanningConfig or PlannedObservation reaches them. An unobservable candidate is reported rather than dropped, and is still folded into the cumulative_* columns and into PlanResult.posterior; see observable_only().

marginal_volume_reduction

Per-dimension generalized-variance ratio from this one observation, (detΣpost/detΣprior)1/6(\det \Sigma_\mathrm{post} / \det \Sigma_\mathrm{prior})^{1/6} 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 [0,1][0, 1]. 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 lndetΣ\ln \det \Sigma, 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_arcsec is 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 (180,180](-180, 180]; add 360 to negative values (equivalently numpy.mod(pa, 360.0)) for the conventional [0,360)[0, 360) 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 against along_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 HH and pVp_V, 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, and PlanResult.posterior still prices the whole submitted plan. To price the observable subset, rebuild planned without the unobservable candidates and call empyrean.evaluate_plan() again.

Return type:

PlanCandidates

select_station(obs_codes)[source]

Rows from one or more observatory / receive-station codes.

Return type:

PlanCandidates

Parameters:

obs_codes (str | Sequence[str])

best_by_information_gain(n=10)[source]

Top-n rows by marginal_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)