Geometry table subsystem
Overview
The geometry subsystem computes geometric quantities for each observation and
writes them as tables. It is the geometry_support package; the
Architecture chapter introduces its principal classes. This
chapter describes the modules and the contracts that are easy to get wrong.
Entry point
process_tables() (in
metadata_tools.geometry_support.process) parses the command line through
get_args() and walks the output tree
(the tree that already holds the supplemental index files). For each volume it
constructs a Suite and calls
create(). The --new_only
option skips volumes that already contain an *_inventory.csv; supplying
explicit volumes disables it.
Suite
Suite reads the volume’s
observations through the host’s from_index hook, builds the per-mode
meshgrids once, and creates a list of tables for each requested level (an
inventory table plus sky, ring, and body tables). It loops over observations,
building a Record per level and
dispatching each record to every table whose level matches. A RuntimeError is
raised if a volume contains more than one index file.
Record and prep
Record holds one observation’s
state: the primary body (from
get_primary()), the selected
bodies, the oops backplane, and the level-specific column dictionaries from
the metadata_tools.columns package.
add() calls
prep_row(), which evaluates each
column’s backplane key, applies the excluded-pixel mask, and formats the result;
postprocess() then applies
the null-linking rules so that linked columns go null together.
Masks
construct_excluded_mask() builds the
boolean mask of pixels to exclude for a column, honoring the column’s masker,
shadower, and face codes. It depends only on oops and numpy so it can be
unit-tested without a host plugin.
Formatting and formats
formatted_column() turns a
masked oops scalar into one or two formatted column strings, converting
radians to degrees, handling cyclic (longitude) ranges, ISO times, null values,
valid-range clipping, and overflow. It is driven by an entry from
FORMAT_DICT.
The format-dictionary contract
FORMAT_DICT maps each column
name to a ten-element tuple:
(flag, number_of_values, column_width, standard_format, overflow_format,
null_value, valid_minimum, valid_maximum, link_id, link)
where flag controls unit conversion ("RAD"/"DEG" radians to degrees,
"360" degrees with 360-degree periodicity, "-180" the
(-180, 180) range, "ISO" time, "" no change), and link_id /
link tie columns together for null-linking.
ALT_FORMAT_DICT holds alternate
formats keyed by (column_name, alt_format_tag).
Body selection
metadata_tools.geometry_support.bodies_select decides which bodies appear
in a record: the primary and secondaries are always included; children of the
primary and any additions are included when they intersect the field of view;
the target and its parent are always included. It also produces the
field-of-view inventory and, when SPICE pointing is unavailable, sets the
record’s pointing_available flag so the row is written with null geometry.
Important invariants
Units. Backplane values are in radians; columns whose
flagis"RAD","DEG","360", or"-180"are converted to degrees byformatted_column(). Do not pre-convert.Column-description tuples. A column description is
(backplane_key, (masker, shadower, face))with an optional trailing alternate-format tag. The masker/shadower strings concatenate"P"(planet),"R"(rings), and"M"(blocker body); the face is"D","N", or"". These tuples live in themetadata_tools.columnspackage.Meshgrids are built once per
Suiteand selected per observation by telemetry mode; they are not rebuilt per row.Summary vs. detailed. A summary call writes exactly one row per observation, even if every value is null; a detailed call writes only rows for non-empty tiles.