Skip to content

CLI

Command-line interface built with Typer. Provides the same 3-stage pipeline as the Python API, plus daemon management and config introspection.

# Run pipeline stages
urbansolarcarver preprocessing -c config.yaml
urbansolarcarver thresholding  -c config.yaml -f outputs/preprocessing/manifest.json
urbansolarcarver exporting     -c config.yaml -f outputs/thresholding/manifest.json

# Override any config value on the fly
urbansolarcarver preprocessing -c config.yaml -o voxel_size=0.5 -o mode=irradiance

# Inspect the full config schema
urbansolarcarver schema

# Daemon lifecycle
urbansolarcarver daemon start
urbansolarcarver daemon stop

urbansolarcarver.carver_cli

UrbanSolarCarver command-line interface.

Exposes the three-stage pipeline (preprocessing -> thresholding -> exporting) as individual subcommands, plus a one-shot run that chains all three. Performance evaluation is out of scope — use Ladybug/Honeybee/Radiance on the exported mesh.

Utility commands: - validate: load and validate a YAML config without running anything. - schema: print a filterable parameter reference (by mode or keyword). - daemon: start / stop / status of the persistent GPU daemon used by Grasshopper and the --daemon flag on pipeline commands.

Design decisions ~~~~~~~~~~~~~~~~ All heavy imports (torch, warp, api_core) are deferred to function bodies so that lightweight commands (--help, schema, validate, daemon) start instantly (~0.3 s) without initialising CUDA or compiling Warp kernels. The _api() helper loads urbansolarcarver.api lazily on first access.

The --daemon flag on each pipeline command sends the job to a running daemon over localhost TCP (multiprocessing.connection), sharing the same RPC mechanism used by the Grasshopper plugin.

main(ctx, version=Option(False, '--version', '-V', callback=_version_callback, is_eager=True, help='Show version and exit'), quiet=Option(False, '--quiet', '-q', help='Suppress torch/warp banners and non-essential output'))

GPU-accelerated solar envelope generation for urban design.

run(config=Option(..., '-c', '--config', exists=True, readable=True, help='YAML config path'), override=Option([], '-o', '--override', help='Override config KEY=VALUE'), out_dir=Option(None, '--out', help='Output root directory'), daemon=Option(False, '--daemon', help='Send to running daemon instead of running locally'), quiet=Option(False, '-q', '--quiet', help='Minimal output'))

Chain all three stages and write the final carved mesh.

This is the simplest entry point — equivalent to calling preprocessing, thresholding, and exporting in sequence. For iterating on threshold parameters without re-computing scores, use the individual stage commands.

cmd_preprocessing(config=Option(..., '-c', '--config', exists=True, readable=True, help='YAML config path'), override=Option([], '-o', '--override', help='Override config fields'), out_dir=Option(None, '--out', help='Output directory'), daemon=Option(False, '--daemon', help='Send to running daemon'), quiet=Option(False, '-q', '--quiet', help='Minimal output'), dry_run=Option(False, '--dry-run', help='Estimate grid size and memory, then exit without running'))

Voxelize, sample surfaces, trace rays, and write scores.

Outputs scores.npy, voxel_grid.npy, and manifest.json into the output directory. The manifest is consumed by the thresholding stage.

cmd_thresholding(from_manifest=Option(None, '-f', '--from', help='Path to preprocessing manifest.json (auto-detected if omitted)'), config=Option(..., '-c', '--config', exists=True, readable=True, help='YAML config path'), override=Option([], '-o', '--override', help='Override config fields'), out_dir=Option(None, '--out', help='Output directory'), daemon=Option(False, '--daemon', help='Send to running daemon'), quiet=Option(False, '-q', '--quiet', help='Minimal output'))

Normalize scores and apply the selected thresholding strategy.

Reads the preprocessing manifest (-f) to locate scores.npy, applies the threshold from the config, and writes mask.npy.

This is the cheapest stage — designed for rapid iteration. Re-run with different -o threshold=... or -o carve_fraction=... values without recomputing scores.

cmd_exporting(from_manifest=Option(None, '-f', '--from', help='Path to thresholding manifest.json (auto-detected if omitted)'), config=Option(..., '-c', '--config', exists=True, readable=True, help='YAML config path'), override=Option([], '-o', '--override', help='Override config fields'), out_dir=Option(None, '--out', help='Output directory'), daemon=Option(False, '--daemon', help='Send to running daemon'), quiet=Option(False, '-q', '--quiet', help='Minimal output'))

Reconstruct a triangle mesh from the binary carving mask.

Reads the thresholding manifest (-f) to locate mask.npy, prunes small disconnected clusters, reconstructs a triangle mesh (cubic faces or SDF-smoothed marching cubes), and writes carved_mesh.ply.

validate(config=Option(..., '-c', '--config', exists=True, readable=True, help='YAML config path'), override=Option([], '-o', '--override', help='Override config fields'))

Parse and validate the YAML config through Pydantic.

Checks schema validity, value bounds, and that referenced file paths (meshes, EPW) exist on disk. Does not initialise CUDA or import torch.

schema(mode=Option(None, '--mode', '-m', help='Show only parameters relevant to this mode'), search=Option(None, '--search', '-s', help='Filter parameters by name or description substring'))

Print the full UserConfig parameter table.

Reads field metadata from the Pydantic schema — no heavy imports needed. Filter by mode (--mode benefit) to see only the parameters that mode uses, or search by keyword (--search threshold).

daemon_start(foreground=Option(False, '-F', '--foreground', help='Run daemon in this console (blocks)'), python=Option(None, '--python', help='Python interpreter to use for the daemon process'))

Start the GPU daemon as a detached background process.

On Windows, uses pythonw.exe by default to avoid a visible console window. Use -F to run in the foreground (useful for debugging). Polls until the daemon accepts connections, then prints a confirmation.

daemon_stop()

Send a shutdown command to the running daemon.

daemon_status()

Probe the daemon with a ping to check if it's alive and accepting commands.