lunar_toolkit.workspace
¶
DuckDB workspace (<work_dir>/lunar.duckdb): image footprints, stereo overlaps and bundle-adjustment statistics.
WorkspaceError
¶
Bases: RuntimeError
The workspace cannot do what was asked (e.g. no spatial extension).
Workspace(path, *, memory_limit='1GB', threads=None, read_only=False, spatial=True)
¶
A DuckDB database of images, stereo pairs and bundle-adjustment results.
| Parameters: |
|
|---|
Notes
Tables: images (observation columns plus footprint, a GEOMETRY in metres
in the polar stereographic projection of hemi, PS_PROJ4),
pairs (the last pairs result), ba_runs,
ba_residual_stats, ba_pixel_residuals, ba_match_offsets, ba_points, ba_convergence,
ba_camera_offsets (by run) and rejection_params. Views:
ba_image_stats (per image before / after), ba_run_summary and
image_rejections (Bertone et al. 2026 rules with rejection_params); the
table macro image_rejections_at(max_offset_p85, max_large_residual_fraction,
large_residual_px, min_matches) takes other thresholds.
Example
::
with Workspace("work/malapert") as ws:
ws.add_observations(obs)
pairs = ws.pairs(aoi={"point": (-85.9, 0.0), "radius_km": 5})
ws.load_bundle_adjust("work/malapert/ba/run")
ws.query("SELECT * FROM image_rejections")
query(sql, params=None)
¶
Run SQL; returns the result as a DataFrame (empty for statements without one).
tables()
¶
name, type (table / view) and rows of the workspace's tables and views.
export(table, path)
¶
Write a table or view to Parquet (.parquet) or CSV (anything else).
GEOMETRY columns are written as WKT in CSV and as WKB (GeoParquet) in Parquet.
add_observations(df, *, rings=None)
¶
Insert or replace (by product_id) observation rows in images.
| Parameters: |
|
|---|
| Returns: |
|
|---|
add_index_rows(df, dataset='edr')
¶
add_observations of CumIndex rows
(footprints from FP_WKT, corners or FP_*).
pairs(aoi=None, *, convergence=(10.0, 60.0), ideal_convergence=(15.0, 45.0), max_incidence_diff=20.0, max_azimuth_diff=30.0, min_overlap=0.1, min_aoi_coverage=0.0, max_resolution_ratio=None, same_instrument=True, require_geometry=False, min_time_sep_s=60.0, weights=None, product_ids=None, table='pairs')
¶
Rank stereo pairs of images with a SQL spatial self-join.
Parameters are those of
lunar_toolkit.stereo.find_stereo_pairs, plus product_ids
(only these images) and table (where the result is stored; None keeps it out of the database).
| Returns: |
|
|---|
Notes
Candidate pairs come from a bounding-box spatial join (ST_Intersects_Extent,
R-tree built by DuckDB's spatial join operator) of the footprints of each
hemisphere, clipped to the AOI; then the attribute filters, overlap area / fraction (ST_Area of
ST_Intersection in metres, divided by the projection's areal scale at the
centroid), AOI coverage, incidence / azimuth / emission / resolution / time
differences and the overlap centroid are SQL. The convergence angle and
b_h are then computed for the candidates with numpy
(lunar_toolkit.stereo.convergence_angles: sub-spacecraft
point + altitude, pushbroom-corrected), exactly as find_stereo_pairs, and the
score is lunar_toolkit.stereo.score_pairs. Footprint edges are
great circles in both (densified here), so overlap areas and fractions agree with
find_stereo_pairs to ~1e-3 relative.
set_rejection_params(config=None, **overrides)
¶
Thresholds of the image_rejections view, from config (default
SfsConfig).
Keyword overrides: max_offset_p85, max_large_residual_fraction,
large_residual_px, min_matches (None disables the first two rules).
load_bundle_adjust(prefix, run=None)
¶
Load ASP bundle_adjust outputs <prefix>-* as run run (replacing it).
run defaults to the prefix's directory name (ba, ba_refine). Reads,
when present: -initial / -final_residuals_stats.txt and
_raw_pixels.txt (ba_residual_stats, ba_pixel_residuals),
-mapproj_match_offset_stats.txt (ba_match_offsets; -1 becomes NULL),
-initial / -final_residuals_pointmap.csv (ba_points, with polar
stereographic x / y), -convergence_angles.txt (ba_convergence)
and -camera_offsets.txt (ba_camera_offsets).
| Returns: |
|
|---|
runs()
¶
Loaded bundle-adjustment runs.
rejections(run)
¶
image_rejections of run: image file name -> reason.
ba_report(run)
¶
Per-image table of run in
lunar_toolkit.sfs_report.read_ba_reports form, or
None.
convergence(run)
¶
ba_convergence of run as left, right, p25, p50, p75, matches.
point_residuals(run, stage='final')
¶
mean_residual_px of the run / stage residual point map.
summary()
¶
The ba_run_summary view.
workspace_path(work_dir)
¶
<work_dir>/lunar.duckdb, or work_dir itself when it names a .duckdb file.
spatial_available()
¶
Whether DuckDB's spatial extension loads (installing it when needed).
find_stereo_pairs_duckdb(obs_df, aoi=None, *, workspace=None, **kwargs)
¶
lunar_toolkit.stereo.find_stereo_pairs through
Workspace.pairs.
The observations are written to images of workspace (default: a scratch
in-memory one) and index_1 / index_2 are mapped back to obs_df row
labels; keyword arguments are those of find_stereo_pairs.
flag_images_sql(residual_stats, residual_norms, offsets, **thresholds)
¶
image_rejections of parsed final-stage reports (see
lunar_toolkit.sfs.flag_images).