CLI Tools

Command-line interface for Planet Four catalog production.

Installation

The p4 CLI is installed automatically when you install p4tools:

pip install -e .

This registers the p4 entry point (defined via console_scripts in pyproject.toml). The CLI depends on Typer and Rich.

Commands Overview

Command Description
p4 setup Configure the Planet Four data root and database path
p4 info Show current configuration and database summary
p4 db-stats Show database statistics and top tiles/obsids by marking count
p4 cluster-tile Cluster a single tile with optional inline plot
p4 cluster-obsid Cluster all tiles for a HiRISE observation ID
p4 produce Run full catalog production with parallel processing

Parallel Execution Helper

run_parallel_with_progress is a general-purpose utility that wraps ProcessPoolExecutor with a Rich progress bar. It is used by the produce command to parallelize clustering and fnotching across hundreds of observation IDs.


source

run_parallel_with_progress


def run_parallel_with_progress(
    func, # A *picklable* top-level function.  Must accept a single positional
argument (the item) plus any keyword arguments from *func_kwargs*.
    items, # Items to map over.
    max_workers:int=4, # Number of parallel processes.
    description:str='Processing', # Label shown in the progress bar.
    func_kwargs:dict | None=None, # Extra keyword arguments forwarded to *func*.
): # Successful results in the original item order (skipping failures).

*Execute func(item, **func_kwargs) in parallel with a Rich progress bar.*

p4 setup

Configures the ~/.p4tools.ini file with the path to the data root directory where clustering results are stored. Optionally also stores the path to the raw Planet Four Parquet database.

p4 setup ~/planet4_data --db ~/planet4_data/p4_raw.parquet

This replaces the old interactive prompt that ran at import time when no config file existed.


source

setup


def setup(
    data_root:str=<typer.models.ArgumentInfo object at 0x7f4846579820>,
    db:Optional[str]=<typer.models.OptionInfo object at 0x7f4848267890>
):

Configure the Planet Four data root (and optionally the raw database path).

p4 info

Displays the current configuration in a Rich table: config file location, data root path, and all key/value pairs from the INI file.

p4 info

source

info


def info(
    
):

Show current configuration and database summary.

p4 db-stats

Shows summary statistics for a raw Planet Four database: total markings, unique tiles and obsids, breakdown by marking type, averages, and the top tiles/obsids ranked by number of markings. Useful for picking example tile IDs and obsids to test with cluster-tile / cluster-obsid.

p4 db-stats --db ~/planet4_data/p4_raw.parquet
p4 db-stats --db ~/planet4_data/p4_raw.parquet --top 20

source

db_stats


def db_stats(
    db:Optional[str]=<typer.models.OptionInfo object at 0x7f4846579010>,
    top:int=<typer.models.OptionInfo object at 0x7f4846579430>
):

Show database statistics and top tiles/obsids by marking count.

p4 random-tile

Picks a random tile whose marking count is within 50% of the database average — i.e. a “typical” tile, useful for quick test runs.

p4 random-tile
p4 random-tile --db ~/planet4_data/p4_raw.parquet

source

random_tile


def random_tile(
    db:Optional[str]=<typer.models.OptionInfo object at 0x7f484657a4e0>
):

Print a random tile ID with a near-average marking count.

Terminal Image Display

_display_inline_image renders a PNG/JPEG inline in the terminal using the iTerm2 inline image protocol (also supported by WezTerm). Falls back to printing the file path on unsupported terminals. Used by cluster-tile to show plots without leaving the CLI.

p4 cluster-tile

Clusters citizen science markings on a single Planet Four tile using DBSCAN, then displays a summary table with fan/blotch cluster counts. With --plot (the default), it also renders a 3-panel figure showing the tile image, clustered fans, and clustered blotches.

# Cluster a single tile
p4 cluster-tile APF00003qk --db ~/planet4_data/p4_raw.parquet

# Without the inline plot
p4 cluster-tile APF00003qk --db ~/planet4_data/p4_raw.parquet --no-plot

source

cluster_tile


def cluster_tile(
    tile_id:str=<typer.models.ArgumentInfo object at 0x7f4846579d90>,
    db:Optional[str]=<typer.models.OptionInfo object at 0x7f4846578cb0>,
    savedir:Optional[str]=<typer.models.OptionInfo object at 0x7f484657af30>,
    plot:bool=<typer.models.OptionInfo object at 0x7f484657bf20>
):

Cluster a single Planet Four tile and display the results.

p4 cluster-obsid

Clusters all tiles belonging to a HiRISE observation. This is the obsid-level equivalent of cluster-tile. Optionally runs fnotching (fan/blotch ambiguity resolution) after clustering.

# Cluster only
p4 cluster-obsid ESP_011296_0975 --db ~/planet4_data/p4_raw.parquet

# Cluster + fnotch
p4 cluster-obsid ESP_011296_0975 --db ~/planet4_data/p4_raw.parquet --fnotch

source

cluster_obsid


def cluster_obsid(
    obsid:str=<typer.models.ArgumentInfo object at 0x7f48465793d0>,
    db:Optional[str]=<typer.models.OptionInfo object at 0x7f4846579e20>,
    savedir:Optional[str]=<typer.models.OptionInfo object at 0x7f4846579a30>,
    fnotch:bool=<typer.models.OptionInfo object at 0x7f4846579a60>
):

Cluster all tiles for a HiRISE observation ID.

p4 create-mosaic

Downloads HiRISE RED4/RED5 CCD images and runs the ISIS pipeline to create a RED45 mosaic cube for a single observation. Useful for testing mosaic creation before running full production.

p4 create-mosaic ESP_011350_0945
p4 create-mosaic ESP_011350_0945 --overwrite

source

create_mosaic


def create_mosaic(
    obsid:str=<typer.models.ArgumentInfo object at 0x7f484657a390>,
    overwrite:bool=<typer.models.OptionInfo object at 0x7f484657a3c0>
):

Create a RED45 mosaic cube for a single observation ID.

Picklable Wrappers

_cluster_single and _fnotch_single are top-level wrapper functions that can be pickled by ProcessPoolExecutor. They perform lazy imports to avoid serialization issues with module-level state.

p4 produce

The main catalog production command. Runs the full pipeline in four phases:

  1. Clustering — Parallel DBSCAN clustering of all observation IDs
  2. Fnotching — Parallel fan/blotch ambiguity resolution
  3. Post-processing — L1C summaries, tile/marking coordinates, metadata
  4. Marking IDs — Assigns unique identifiers to all catalog entries

Uses run_parallel_with_progress for phases 1 and 2, with configurable worker count. Supports --dry-run to preview the work without executing.

# Full production run
p4 produce v3.1 --db ~/planet4_data/p4_raw.parquet --workers 8

# Preview what would be done
p4 produce v3.1 --db ~/planet4_data/p4_raw.parquet --dry-run

source

produce


def produce(
    version:str=<typer.models.ArgumentInfo object at 0x7f4846579d60>,
    db:Optional[str]=<typer.models.OptionInfo object at 0x7f484657b7d0>,
    workers:int=<typer.models.OptionInfo object at 0x7f484657aff0>,
    dry_run:bool=<typer.models.OptionInfo object at 0x7f484657a3f0>
):

Run full catalog production with parallel processing and Rich progress.