API Reference
This section provides detailed documentation for all Planet Ruler modules and functions.
Core Modules
Geometry Module
- planet_ruler.geometry.horizon_distance(r, h)[source]
Estimate the distance to the horizon (limb) given a height and radius.
- planet_ruler.geometry.limb_camera_angle(r, h)[source]
The angle the camera must tilt in theta_x or theta_y to center the limb. Complement of theta (angle of limb down from the x-y plane).
- planet_ruler.geometry.focal_length(w, fov)[source]
The size of the CCD (inferred) based on focal length and field of view.
- planet_ruler.geometry.detector_size(f, fov)[source]
The size of the CCD (inferred) based on focal length and field of view.
- planet_ruler.geometry.field_of_view(f, w)[source]
The size of the CCD (inferred) based on focal length and field of view.
- planet_ruler.geometry.intrinsic_transform(camera_coords, f=1, px=1, py=1, x0=0, y0=0)[source]
Transform from camera coordinates into image coordinates.
- Parameters:
camera_coords (np.ndarray) – Coordinates of the limb in camera space. Array has Nx4 shape where N is the number of x-axis pixels in the image.
f (float) – Focal length of the camera (m).
px (float) – The scale of x pixels.
py (float) – The scale of y pixels.
x0 (float) – The x-axis principle point (should be center of image in pixel coordinates).
y0 (float) – The y-axis principle point. (should be center of image in pixel coordinates).
- Returns:
Coordinates in image space.
- Return type:
pixel_coords (np.ndarray)
- planet_ruler.geometry.extrinsic_transform(world_coords, theta_x=0, theta_y=0, theta_z=0, origin_x=0, origin_y=0, origin_z=0)[source]
Transform from world coordinates into camera coordinates. Note that for a limb calculation we will define origin_x/y/z as the camera position – these should all be set to zero.
- Parameters:
world_coords (np.ndarray) – Coordinates of the limb in the world. Array has Nx4 shape where N is the number of x-axis pixels in the image.
theta_x (float) – Rotation around the x (horizontal) axis, AKA pitch. (radians)
theta_y (float) – Rotation around the y (toward the limb) axis, AKA roll. (radians)
theta_z (float) – Rotation around the z (vertical) axis, AKA yaw. (radians)
origin_x (float) – Horizontal offset from the object in question to the camera (m).
origin_y (float) – Distance from the object in question to the camera (m).
origin_z (float) – Height difference from the object in question to the camera (m).
- Returns:
Coordinates in camera space.
- Return type:
camera_coords (np.ndarray)
- planet_ruler.geometry.limb_arc_sample(r, n_pix_x, n_pix_y, h=1, f=None, fov=None, w=None, x0=0, y0=0, theta_x=0, theta_y=0, theta_z=0, origin_x=0, origin_y=0, origin_z=0, return_full=False, num_sample=5000)[source]
Calculate the limb orientation in an image given the physical parameters of the system.
- Parameters:
n_pix_x (int) – Width of image (pixels).
n_pix_y (int) – Height of image (pixels).
r (float) – Radius of the body in question.
h (float) – Height above surface (units should match radius).
f (float) – Focal length of the camera (m).
fov (float) – Field of view, assuming square (degrees).
w (float) – detector size (float): Width of CCD (m).
x0 (float) – The x-axis principle point.
y0 (float) – The y-axis principle point.
theta_x (float) – Rotation around the x (horizontal) axis, AKA pitch. (radians)
theta_y (float) – Rotation around the y (toward the limb) axis, AKA roll. (radians)
theta_z (float) – Rotation around the z (vertical) axis, AKA yaw. (radians)
origin_x (float) – Horizontal offset from the object in question to the camera (m).
origin_y (float) – Distance from the object in question to the camera (m).
origin_z (float) – Height difference from the object in question to the camera (m).
return_full (bool) – Return both the x and y coordinates of the limb in camera space. Note these will not be interpolated back on to the pixel grid.
num_sample (
int) – The number of points sampled from the simulated limb – will be interpolated onto pixel grid. [default 1000]
- Return type:
- planet_ruler.geometry.get_rotation_matrix(theta_x, theta_y, theta_z)[source]
Compute combined rotation matrix from Euler angles. Extracted from extrinsic_transform for reuse.
- Returns:
3x3 rotation matrix
- Return type:
R
- planet_ruler.geometry.limb_arc(r, n_pix_x, n_pix_y, h=1, f=None, fov=None, w=None, x0=0, y0=0, theta_x=0, theta_y=0, theta_z=0, origin_x=0, origin_y=0, origin_z=0, return_full=False, **kwargs)[source]
Calculate limb position analytically at each pixel x-coordinate.
No sampling or interpolation - directly solves for phi at each column. This eliminates edge artifacts and is sometimes faster than sampling methods.
Mathematical approach: 1. Limb is parameterized by angle phi around circle 2. For each x_pixel, solve: x_pixel = f(phi) for phi 3. This reduces to: a·cos(phi) + b·sin(phi) = c 4. Standard analytical solution exists!
Args: (same as original limb_arc)
- Returns:
Array of y-coordinates for each x-pixel column
- Return type:
y_pixel
The geometry module contains fundamental mathematical functions for planetary calculations:
Horizon calculations: horizon_distance, limb_camera_angle
Camera optics: focal_length, detector_size, field_of_view
Coordinate transforms: intrinsic_transform, extrinsic_transform
Limb arc modeling: limb_arc, limb_arc_sample - generates theoretical limb curves
Rotation matrices: get_rotation_matrix - Euler angle to rotation matrix conversion
Image Processing Module
- planet_ruler.image.load_image(filepath)[source]
Load a 3 or 4-channel image from filepath into an array.
- planet_ruler.image.directional_gradient_blur(image, sigma_base=2.0, streak_length=20, decay_rate=0.2, normalize_gradients=True)[source]
Blur along gradient directions to create smooth ‘streaks’ toward edges.
For each pixel, follow its gradient direction outward, averaging pixels along that ray with exponential decay. This: - Smooths noisy/weak gradients (striations with inconsistent directions) - Strengthens coherent gradients (limb where all gradients align) - Creates smooth ‘valleys’ guiding optimizer toward strong edges
- Parameters:
image (np.ndarray) – Input image (H x W or H x W x 3)
sigma_base (float) – Initial gradient smoothing for direction estimation
streak_length (int) – How far to follow gradient direction (pixels)
decay_rate (float) – Exponential decay rate (higher = faster decay)
normalize_gradients (bool) –
True: Use unit vectors (direction only) - RECOMMENDED All pixels sample same distance regardless of gradient strength. Consistent, predictable behavior.
False: Use full gradient magnitude as direction Strong gradients sample further. Can create artifacts.
- Returns:
Blurred gradient magnitude field grad_angle (np.ndarray): Gradient angle field
- Return type:
blurred_grad_mag (np.ndarray)
- Note: This is UNI-directional (samples in one direction only).
Use bidirectional_gradient_blur() to preserve peak locations.
- planet_ruler.image.bilinear_interpolate(array, y, x)[source]
Bilinear interpolation for 2D array at non-integer coordinates.
- Parameters:
array – 2D array to sample from
y – Arrays of y and x coordinates (can be non-integer)
x – Arrays of y and x coordinates (can be non-integer)
- Returns:
Interpolated values at (y, x) positions
- planet_ruler.image.bidirectional_gradient_blur(image, sigma_base=2.0, streak_length=20, decay_rate=0.2, normalize_gradients=True)[source]
Blur in BOTH directions along gradient (forward and backward).
This creates symmetric streaks on both sides of edges, preserving the location of gradient maxima while smoothing the field.
- Parameters:
image – Input image
sigma_base – Initial smoothing for gradient estimation
streak_length – How far to sample in each direction
decay_rate – Exponential decay (higher = faster falloff)
normalize_gradients – Use unit vectors (direction only) vs full magnitude
- Returns:
Smoothed gradient magnitude field grad_angle: Original gradient angle field
- Return type:
blurred_mag
- planet_ruler.image.gradient_break(im_arr, log=False, y_min=0, y_max=-1, window_length=None, polyorder=1, deriv=0, delta=1)[source]
Scan each vertical line of an image for the maximum change in brightness gradient – usually corresponds to a horizon.
- Parameters:
im_arr (np.ndarray) – Image array.
log (bool) – Use the log(gradient). Sometimes good for smoothing.
y_min (int) – Minimum y-position to consider.
y_max (int) – Maximum y-position to consider.
window_length (int) – Width of window to apply smoothing for each vertical. Larger means less noise but less sensitivity.
polyorder (int) – Polynomial order for smoothing.
deriv (int) – Derivative level for smoothing.
delta (int) – Delta for smoothing.
- Returns:
image array (np.ndarray)
- class planet_ruler.image.MaskSegmenter(image, method='sam', downsample_factor=1, interactive=True, **backend_kwargs)[source]
Bases:
objectMethod-agnostic mask-based segmentation.
Supports pluggable backends (SAM, custom algorithms, etc.) with optional downsampling and interactive classification.
- class planet_ruler.image.SegmentationBackend[source]
Bases:
objectBase class for segmentation backends.
- class planet_ruler.image.SAMBackend(model_size='vit_b')[source]
Bases:
SegmentationBackendSegment Anything Model backend.
- class planet_ruler.image.CustomBackend(segment_fn)[source]
Bases:
SegmentationBackendCustom user-provided segmentation backend.
- planet_ruler.image.smooth_limb(y, method='rolling-median', window_length=50, polyorder=1, deriv=0, delta=1)[source]
Smooth the limb position values.
- Parameters:
y (np.ndarray) – Y-locations of the string for each column.
method (str) – Smoothing method. Must be one of [‘bin-interpolate’, ‘savgol’, ‘rolling-mean’, ‘rolling-median’].
window_length (int) – The length of the filter window (i.e., the number of coefficients). If mode is ‘interp’, window_length must be less than or equal to the size of x.
polyorder (float) – The order of the polynomial used to fit the samples. polyorder must be less than window_length.
deriv (int) – The order of the derivative to compute. This must be a non-negative integer. The default is 0, which means to filter the data without differentiating.
delta (int) – The spacing of the samples to which the filter will be applied. This is only used if deriv > 0. Default is 1.0.
- Returns:
Y-locations of the smoothed string for each column.
- Return type:
position (np.ndarray)
- planet_ruler.image.fill_nans(limb)[source]
Fill NaNs for the limb position values.
- Parameters:
limb (np.ndarray) – Y-locations of the limb on the image.
- Returns:
Y-locations of the limb on the image.
- Return type:
limb (np.ndarray)
- planet_ruler.image.gradient_field(image, kernel_smoothing=5.0, directional_smoothing=50, directional_decay_rate=0.15)[source]
Pre-compute gradient field AND its derivatives for fast sub-pixel interpolation. Uses directional blur for enhanced edge detection.
- Parameters:
image (
ndarray) – Input imagekernel_smoothing (
float) – Sigma for initial gradient direction estimationdirectional_smoothing (
int) – Distance to sample in each direction (±pixels). Set to 0 to bypass directional smoothing entirely.directional_decay_rate (
float) – Exponential decay rate for directional blur
- Returns:
- Dictionary containing gradient field components:
grad_mag: Gradient magnitude array
grad_angle: Gradient angle array
grad_sin: Sin of gradient angle (for interpolation)
grad_cos: Cos of gradient angle (for interpolation)
grad_mag_dy, grad_mag_dx: Derivatives of gradient magnitude
grad_sin_dy, grad_sin_dx: Derivatives of sine component
grad_cos_dy, grad_cos_dx: Derivatives of cosine component
image_height, image_width: Dimensions
- Return type:
The image module handles computer vision tasks:
Image loading: load_image - loads and validates image files
Gradient-field detection: gradient_field - automated limb detection using directional blur and flux analysis
Legacy detection: gradient_break - simpler gradient-based detection
Image segmentation: MaskSegmenter class with pluggable backends including Segment Anything integration (optional)
Limb processing: smooth_limb, fill_nans - post-processing operations
Interpolation: bilinear_interpolate - sub-pixel image sampling
Observation Module
- class planet_ruler.observation.PlanetObservation(image_filepath)[source]
Bases:
objectBase class for planet observations.
- Parameters:
image_filepath (str) – Path to image file.
- class planet_ruler.observation.LimbObservation(image_filepath, fit_config, limb_detection='manual', minimizer='differential-evolution')[source]
Bases:
PlanetObservationObservation of a planet’s limb (horizon).
- Parameters:
- __init__(image_filepath, fit_config, limb_detection='manual', minimizer='differential-evolution')[source]
- analyze(detect_limb_kwargs=None, fit_limb_kwargs=None)[source]
Perform complete limb analysis: detection + fitting in one call.
- property radius_km: float
Get the fitted planetary radius in kilometers.
- Returns:
Planetary radius in km, or 0 if not fitted
- Return type:
- property altitude_km: float
Get the observer altitude in kilometers.
- Returns:
Observer altitude in km, or 0 if not fitted
- Return type:
- property focal_length_mm: float
Get the camera focal length in millimeters.
- Returns:
Focal length in mm, or 0 if not fitted
- Return type:
- property radius_uncertainty: float
Get parameter uncertainty for radius.
Automatically selects best method based on minimizer: - differential_evolution: Uses population spread (fast, exact) - dual_annealing/basinhopping: Uses Hessian approximation (fast, approximate)
- Returns:
Radius uncertainty in km (1-sigma), or 0 if not available
- Return type:
- parameter_uncertainty(parameter, method='auto', scale_factor=1.0, confidence_level=0.68, **kwargs)[source]
Get uncertainty for any fitted parameter.
- Parameters:
parameter (
str) – Parameter name (e.g., ‘r’, ‘h’, ‘f’, ‘theta_x’)method (
Literal['auto','hessian','profile','bootstrap']) – Uncertainty method - ‘auto’: Choose based on minimizer (recommended) - ‘hessian’: Fast Hessian approximation - ‘profile’: Slow but accurate profile likelihood - ‘bootstrap’: Multiple fits (very slow)scale_factor (
float) – Scale result (e.g., 1000.0 for m→km)confidence_level (
float) – Confidence level (0.68=1σ, 0.95=2σ)**kwargs – Additional arguments passed to uncertainty calculator
- Return type:
- Returns:
dict with ‘uncertainty’, ‘method’, ‘confidence_level’, ‘additional_info’
Examples
# Radius uncertainty in km (1-sigma) obs.parameter_uncertainty(‘r’, scale_factor=1000.0)
# Altitude uncertainty in km (2-sigma / 95% CI) obs.parameter_uncertainty(‘h’, scale_factor=1000.0, confidence_level=0.95)
# Focal length uncertainty in mm (using profile likelihood) obs.parameter_uncertainty(‘f’, scale_factor=1000.0, method=’profile’)
- plot_3d(**kwargs)[source]
Create 3D visualization of the planetary geometry.
- Parameters:
**kwargs – Arguments passed to plot_3d_solution
- Return type:
- load_fit_config(fit_config)[source]
Load the fit configuration from file, setting all parameters to their initial values. Missing values are filled with defaults.
- register_limb(limb)[source]
Register a detected limb.
- Parameters:
limb (np.ndarray) – Limb vector (y pixel coordinates).
- Return type:
- detect_limb(detection_method=None, log=False, y_min=0, y_max=-1, window_length=501, polyorder=1, deriv=0, delta=1, segmentation_method='sam', downsample_factor=1, interactive=True, **segmentation_kwargs)[source]
Use the instance-defined method to find the limb in our observation. Kwargs are passed to the method.
- Parameters:
detection_method (literal) –
- Detection method. Must be one of
manual
gradient-break
gradient-field
segmentation
Default (None) uses the class attribute self.limb_detection.
log (bool) – Use the log(gradient). Sometimes good for smoothing.
y_min (int) – Minimum y-position to consider.
y_max (int) – Maximum y-position to consider.
window_length (int) – Width of window to apply smoothing for each vertical. Larger means less noise but less sensitivity.
polyorder (int) – Polynomial order for smoothing.
deriv (int) – Derivative level for smoothing.
delta (int) – Delta for smoothing.
segmentation_method (str) – Model used for segmentation. Must be one of [‘sam’].
downsample_factor (int) – Downsampling used for segmentation.
interactive (bool) – Prompts user to verify segmentation via annotation tool.
segmentation_kwargs (dict) – Kwargs passed to segmentation engine.
- Return type:
- smooth_limb(fill_nan=True, **kwargs)[source]
Apply the smooth_limb function to current observation.
- fit_limb(loss_function='l2', max_iter=15000, resolution_stages=None, max_iter_per_stage=None, n_jobs=1, seed=0, image_smoothing=None, kernel_smoothing=5.0, directional_smoothing=50, directional_decay_rate=0.15, prefer_direction=None, minimizer=None, minimizer_preset='balanced', minimizer_kwargs=None, warm_start=False, dashboard=False, dashboard_kwargs=None, target_planet='earth', verbose=False)[source]
Fit the limb to determine planetary parameters.
Supports single-resolution or multi-resolution (coarse-to-fine) optimization. Multi-resolution is recommended for gradient_field loss to avoid local minima.
- Parameters:
loss_function (
Literal['l2','l1','log-l1','gradient_field']) – Loss function type - ‘l2’, ‘l1’, ‘log-l1’: Traditional (requires detected limb) - ‘gradient_field’: Direct gradient alignment (no detection needed)max_iter (
int) – Maximum iterations (for single-resolution or total if multires)resolution_stages (
Union[List[int],Literal['auto'],None]) –Resolution strategy - None: Single resolution (original behavior) - ‘auto’: Auto-determine stages based on image size - List[int]: Custom stages, e.g., [4, 2, 1] = 1/4 → 1/2 → full NOTE: Multi-resolution only works with gradient_field loss functions.
Traditional loss functions (l2, l1, log-l1) require single resolution.
max_iter_per_stage (
Optional[List[int]]) – Iterations per stage (auto if None)n_jobs (
int) – Number of parallel workersseed (
int) – Random seed for reproducibilityimage_smoothing (
Optional[float]) – For gradient_field - Gaussian blur sigma applied to image before gradient computation. Removes high-frequency artifacts (crater rims, striations) that could mislead optimization. Different from kernel_smoothing.kernel_smoothing (
float) – For gradient_field - initial blur for gradient direction estimation. Makes the gradient field smoother for directional sampling.directional_smoothing (
int) – For gradient_field - sampling distance along gradientsdirectional_decay_rate (
float) – For gradient_field - exponential decay for samplesprefer_direction (
Optional[Literal['up','down']]) – For gradient_field - prefer ‘up’ or ‘down’ gradients where ‘up’ means dark-sky/bright-planet and v.v. (None = no preference, choose best gradient regardless of direction)minimizer (str) – Choice of minimizer. Supports ‘differential-evolution’, ‘dual-annealing’, and ‘basinhopping’.
minimizer_preset (
Literal['fast','balanced','robust','scipy-default']) – Optimization strategy - ‘fast’: Quick convergence, may miss global minimum - ‘balanced’: Good trade-off (default) - ‘robust’: Thorough exploration, slowerminimizer_kwargs (
Optional[Dict]) – Override specific minimizer parameters (advanced)warm_start (
bool) – If True, use previous fit’s results as starting point (useful for iterative refinement). If False (default), use original init_parameter_values. Note: Multi-resolution stages always warm-start from previous stages automatically. This parameter is for warm-starting across separate fit_limb() calls.dashboard (
bool) – Show live progress dashboard during optimizationdashboard_kwargs (
Optional[Dict]) – Additional kwargs for FitDashboard - output_capture: OutputCapture instance for print/log display - show_output: Show output section (default True if capture provided) - max_output_lines: Number of output lines to show (default 3) - min_refresh_delay: Fixed refresh delay (0.0 for adaptive, default) - refresh_frequency: Refresh every N iterations (default 1)target_planet (
str) – Reference planet for dashboard comparisons (‘earth’, ‘mars’, ‘jupiter’, ‘saturn’, ‘moon’, ‘pluto’)verbose (
bool) – Print detailed progress
- Returns:
For method chaining
- Return type:
self
Examples
# Simple single-resolution fit obs.fit_limb()
# Auto multi-resolution for gradient field obs.fit_limb(loss_function=’gradient_field’, resolution_stages=’auto’)
# Remove image artifacts before optimization obs.fit_limb(
loss_function=’gradient_field’, resolution_stages=’auto’, image_smoothing=2.0, # Remove crater rims, striations kernel_smoothing=5.0 # Smooth gradient field
)
# Custom stages with robust optimization obs.fit_limb(
loss_function=’gradient_field’, resolution_stages=[8, 4, 2, 1], minimizer_preset=’robust’
)
# Override specific minimizer parameters obs.fit_limb(
loss_function=’gradient_field’, minimizer_kwargs={‘popsize’: 25, ‘atol’: 0.5}
)
# Dashboard with output capture from planet_ruler.dashboard import OutputCapture capture = OutputCapture() with capture:
- obs.fit_limb(
loss_function=’gradient_field’, dashboard=True, dashboard_kwargs={‘output_capture’: capture}
)
# Iterative refinement with warm start obs.fit_limb(loss_function=’gradient_field’, resolution_stages=’auto’) obs.fit_limb(loss_function=’gradient_field’, warm_start=True,
minimizer_preset=’robust’) # Refine with more thorough search
- planet_ruler.observation.package_results(observation)[source]
Consolidate the results of a fit to see final vs. initial values.
- Parameters:
observation (object) – Instance of LimbObservation (must have used differential evolution minimizer).
- Returns:
- DataFrame of results including
fit value
initial value
parameter
- Return type:
results (pd.DataFrame)
The observation module provides high-level interfaces:
PlanetObservation: Base class for planetary observations
LimbObservation: Complete workflow for limb-based radius fitting (default: manual annotation)
Results processing: unpack_diff_evol_posteriors, package_results
Annotation Module
Manual Limb Annotation Tool for Planet Ruler
Allows users to click points on a horizon image and generate a sparse target for fitting with the existing planet_ruler pipeline.
- class planet_ruler.annotate.ToolTip(widget, text)[source]
Bases:
objectSimple tooltip that appears on hover.
- planet_ruler.annotate.create_tooltip(widget, text)[source]
Helper function to create tooltip for a widget.
- class planet_ruler.annotate.TkLimbAnnotator(image_path, initial_stretch=1.0, initial_zoom=None)[source]
Bases:
objectTkinter-based interactive tool for manually annotating planet limbs.
Features: - Zoom with scroll wheel (fit large images in window) - Vertical stretch buttons (stretch pixels vertically for precision) - Scrollable canvas for navigating - Click to add points, right-click to undo - Save/load points to JSON - Generate sparse target array for CostFunction
- class planet_ruler.annotate.TkMaskSelector(image, masks, initial_zoom=None)[source]
Bases:
objectInteractive mask classification tool for segmentation results.
Works with ANY segmentation method - completely backend-agnostic. Allows users to classify masks as ‘planet’, ‘sky’, or ‘exclude’ for horizon detection. Aligns with Planet Ruler’s educational philosophy of transparency over black-box automation.
- Parameters:
image (
ndarray) – Original image array (H x W x 3)masks (
list) – List of masks in any of these formats: - List of np.ndarray (boolean H x W arrays) - List of dicts with ‘mask’ or ‘segmentation’ key - Mixed formats are OKinitial_zoom (
Optional[float]) – Initial zoom level (None = auto-fit to window)
The annotation module provides interactive manual limb detection:
TkLimbAnnotator: Interactive GUI for manual horizon point selection
Point management: Add, remove, and edit limb points with mouse interaction
Image controls: Zoom, pan, and contrast adjustment for precise annotation
File I/O: Save and load annotation sessions to/from JSON files
Target generation: Convert point annotations to dense limb arrays
Camera Module
Automatic extraction of camera parameters from smartphone images. Uses EXIF data and a phone camera database.
- planet_ruler.camera.get_focal_length_35mm_equiv(exif_data)[source]
Get 35mm equivalent focal length (more reliable for phones).
- planet_ruler.camera.calculate_sensor_dimensions(focal_length_mm, focal_length_35mm)[source]
Calculate sensor dimensions from focal length ratio. Uses the relationship: focal_length_mm / sensor_width = focal_length_35mm / 36mm
- planet_ruler.camera.get_sensor_statistics_by_type(camera_type)[source]
Calculate sensor dimension statistics for a given camera type. Returns median, min, and max for sensor width and height.
- Return type:
- planet_ruler.camera.infer_camera_type(exif_data)[source]
Try to infer camera type from EXIF data even if exact model unknown.
- planet_ruler.camera.extract_camera_parameters(image_path)[source]
Automatically extract all camera parameters from any camera image. Handles phones, point-and-shoot cameras, DSLRs, mirrorless, etc.
- Returns:
- Camera parameters including:
focal_length_mm: focal length in millimeters
sensor_width_mm: sensor width in millimeters
sensor_height_mm: sensor height in millimeters
sensor_width_min: minimum sensor width (if using type statistics)
sensor_width_max: maximum sensor width (if using type statistics)
image_width_px: image width in pixels
image_height_px: image height in pixels
camera_model: detected camera model
camera_type: ‘phone’, ‘compact’, ‘dslr’, ‘mirrorless’, or ‘unknown’
confidence: ‘high’, ‘medium’, or ‘low’
- Return type:
- planet_ruler.camera.get_gps_altitude(image_path)[source]
Extract GPS altitude from EXIF data if available.
- Returns:
Altitude in meters, or None if not available
- Return type:
- planet_ruler.camera.get_initial_radius(planet='earth', perturbation_factor=0.5, seed=None)[source]
Get initial radius guess with perturbation.
- planet_ruler.camera.create_config_from_image(image_path, altitude_m=None, planet='earth', param_tolerance=0.1, perturbation_factor=0.5, seed=None)[source]
Create a complete planet_ruler configuration from an image. Works with any camera - phones, point-and-shoot, DSLRs, etc.
- Parameters:
image_path (
str) – Path to the imagealtitude_m (
Optional[float]) – Altitude in meters (REQUIRED if not in GPS data)planet (
str) – Planet name for initial radius guess (default: ‘earth’)param_tolerance (
float) – Fractional tolerance for parameter limits (default: 0.1 = ±10%)perturbation_factor (
float) – Initial radius perturbation (default: 0.5 = ±50%)seed (
Optional[int]) – Random seed for reproducibility (default: None = unseeded)
- Returns:
Configuration ready for planet_ruler
- Return type:
- Raises:
ValueError – If altitude cannot be determined from GPS and not provided manually
Notes
Initial radius is randomly perturbed to avoid local minima and prove data-driven results
For uncertainty quantification, consider running multiple times (multi-start optimization)
Theta parameters (orientation) have wide default limits to handle r-h coupling
The camera module provides automatic camera parameter extraction from image EXIF data:
EXIF processing: extract_exif, get_camera_model, get_focal_length_mm
Camera database: Comprehensive database of sensor dimensions for phones, DSLRs, mirrorless cameras
Parameter extraction: extract_camera_parameters - automatic detection of focal length and sensor size
GPS integration: get_gps_altitude - extract altitude from GPS EXIF data
Configuration generation: create_config_from_image - complete auto-config from any camera image
Planet radii: get_initial_radius - perturbed initial radius guesses for robust optimization
Fitting and Optimization
- planet_ruler.fit.unpack_parameters(params, template)[source]
Turn a list of parameters back into a dict.
- planet_ruler.fit.pack_parameters(params, template)[source]
Turn a dict of parameters (or defaults) into a list.
- class planet_ruler.fit.CostFunction(target, function, free_parameters, init_parameter_values, loss_function='l2', kernel_smoothing=5.0, directional_smoothing=30, directional_decay_rate=0.15, prefer_direction=None)[source]
Bases:
objectWrapper to simplify interface with the minimization at hand.
- Parameters:
target (np.ndarray) – True value(s), e.g., the actual limb position. For gradient_field loss, this should be the image.
function (Callable) – Function mapping parameters to target of interest.
free_parameters (list) – List of free parameter names.
init_parameter_values (dict) – Initial values for named parameters.
loss_function (str) – Type of loss function, must be one of [‘l2’, ‘l1’, ‘log-l1’, ‘gradient_field’].
kernel_smoothing – For gradient_field - initial blur for gradient direction estimation. Makes the gradient field smoother for directional sampling.
directional_smoothing – For gradient_field - sampling distance along gradients
directional_decay_rate – For gradient_field - exponential decay for samples
prefer_direction (
Optional[str]) – For gradient_field - prefer ‘up’ or ‘down’ gradients where ‘up’ means dark-sky/bright-planet and v.v. (None = no preference, choose best gradient regardless of direction)
- __init__(target, function, free_parameters, init_parameter_values, loss_function='l2', kernel_smoothing=5.0, directional_smoothing=30, directional_decay_rate=0.15, prefer_direction=None)[source]
- planet_ruler.fit.calculate_parameter_uncertainty(observation, parameter='r', method='auto', uncertainty_type='std', scale_factor=1.0)[source]
Calculate parameter uncertainty from fitting results.
Provides a flexible interface for uncertainty estimation that works with different optimization methods and uncertainty metrics.
- Parameters:
observation – LimbObservation object with completed fit
parameter (str) – Parameter name to calculate uncertainty for (default: “r”)
method (str) – Uncertainty calculation method: - “auto”: Automatically detect method from fit results - “differential_evolution”: Use DE population posteriors - “bootstrap”: Use bootstrap resampling (future implementation) - “hessian”: Use Hessian-based uncertainty (future implementation)
uncertainty_type (str) – Type of uncertainty measure: - “std”: Standard deviation of parameter distribution - “ptp”: Peak-to-peak range (max - min) - “iqr”: Interquartile range (75th - 25th percentile) - “ci”: Confidence interval (returns dict with bounds)
scale_factor (float) – Scale factor to apply to results (e.g., 1000 for km units)
- Returns:
- Dictionary containing uncertainty information:
”value”: Fitted parameter value (scaled)
”uncertainty”: Uncertainty estimate (scaled)
”method”: Method used for uncertainty calculation
”type”: Type of uncertainty measure used
”raw_data”: Raw parameter samples if available
- Return type:
- Raises:
ValueError – If uncertainty method is not supported or data is insufficient
AttributeError – If observation doesn’t have required fit results
- planet_ruler.fit.format_parameter_result(uncertainty_result, units='')[source]
Format parameter uncertainty results for display.
- planet_ruler.fit.unpack_diff_evol_posteriors(observation)[source]
Extract the final state population of a differential evolution minimization and organize as a DataFrame.
- Parameters:
observation (object) – Instance of LimbObservation (must have used differential evolution minimizer).
- Returns:
Population (rows) and properties (columns).
- Return type:
population (pd.DataFrame)
The fit module handles parameter optimization:
CostFunction: Configurable cost function for parameter fitting
Parameter handling: pack_parameters, unpack_parameters
Uncertainty analysis: calculate_parameter_uncertainty, format_parameter_result
Uncertainty Module
- planet_ruler.uncertainty.calculate_parameter_uncertainty(observation, parameter, method='auto', scale_factor=1.0, confidence_level=0.68, n_bootstrap=20, **kwargs)[source]
Calculate uncertainty for a fitted parameter using appropriate method.
Automatically selects best method based on minimizer used: - differential_evolution: Population spread (fast, exact) - dual_annealing/basinhopping: Hessian approximation (fast, approximate) - any: Profile likelihood or bootstrap (slow, accurate)
- Parameters:
observation – LimbObservation instance with completed fit
parameter (
str) – Parameter name (e.g., ‘r’, ‘h’, ‘f’)method (
Literal['auto','hessian','profile','bootstrap']) – Uncertainty estimation method - ‘auto’: Choose based on minimizer and available data - ‘hessian’: Inverse Hessian at optimum (fast) - ‘profile’: Profile likelihood (slow but accurate) - ‘bootstrap’: Multiple fits with different seeds (slow)scale_factor (
float) – Scale result (e.g., 1000.0 to convert m→km)confidence_level (
float) – Confidence level (0.68=1σ, 0.95=2σ)n_bootstrap (
int) – Number of bootstrap iterations
- Returns:
‘uncertainty’: The uncertainty value
’method’: Method used
’confidence_level’: Confidence level
’additional_info’: Method-specific details
- Return type:
dict with keys
The uncertainty module provides comprehensive parameter uncertainty estimation:
Multiple methods: Population spread, Hessian approximation, profile likelihood, bootstrap
Auto-selection: Automatically chooses best method based on minimizer used
Confidence intervals: Configurable confidence levels (68%, 95%, 99%, etc.)
Method-specific details: Additional diagnostics for each uncertainty estimation method
Available Uncertainty Methods:
population: Uses parameter spread from differential-evolution population (fast, exact for DE)
hessian: Inverse Hessian approximation at optimum (fast, approximate, works with all minimizers)
profile: Profile likelihood re-optimization (slow, most accurate, works with all minimizers)
bootstrap: Multiple fits with different seeds (slow, robust, partially implemented)
auto: Automatically selects population for DE, hessian for others
Plotting and Visualization
- planet_ruler.plot.plot_image(im_arr, gradient=False, show=True)[source]
Display an image using matplotlib.pyplot.imshow.
- planet_ruler.plot.plot_limb(y, show=True, c='y', s=10, alpha=0.2)[source]
Display the limb (usually on top of an image).
- planet_ruler.plot.plot_3d_solution(r, h=1, zoom=1, savefile=None, legend=True, vertical_axis='z', azim=None, roll=None, x_axis=False, y_axis=True, z_axis=False, **kwargs)[source]
Plot a limb solution in 3D.
- Parameters:
r (float) – Radius of the body in question.
h (float) – Height above surface (units should match radius).
zoom (float) – Shrink the height according to a zoom factor to make viewing easier.
savefile (str) – Path to optionally save figure.
legend (bool) – Display the legend.
vertical_axis (str) – Which axis will be used as the vertical (x, y, or z).
azim (float) – Viewing azimuth.
roll (float) – Viewing roll.
x_axis (bool) – Plot the x-axis.
y_axis (bool) – Plot the y-axis.
z_axis (bool) – Plot the z-axis.
kwargs – Absorbs other solution kwargs that don’t matter for physical space.
- Return type:
- planet_ruler.plot.plot_topography(image)[source]
Display the full limb, including the section not seen in the image.
- Parameters:
image (np.ndarray) – Image array.
- Return type:
- planet_ruler.plot.plot_gradient_field_at_limb(y_pixels, image, image_smoothing=None, kernel_smoothing=5.0, directional_smoothing=50, directional_decay_rate=0.15, sample_spacing=50, arrow_scale=20)[source]
Visualize gradient field along a proposed limb curve.
- Parameters:
y_pixels (np.ndarray) – Y-coordinates of limb at each x-position
image (np.ndarray) – Input image (H x W x 3 or H x W)
image_smoothing (int) – For gradient_field - Gaussian blur sigma applied to image before gradient computation. Removes high-frequency artifacts (crater rims, striations) that could mislead optimization. Different from kernel_smoothing.
kernel_smoothing (float) – Initial smoothing for gradient direction estimation
directional_smoothing (int) – How far to sample along gradients
directional_decay_rate (float) – Exponential decay rate for sampling
sample_spacing (int) – Sample every N pixels along x-axis
arrow_scale (float) – Scale factor for arrow lengths
- Returns:
Matplotlib figure and axis objects
- Return type:
fig, ax
- planet_ruler.plot.compare_blur_methods(image, y_pixels=None)[source]
Compare gradient magnitude with different blur methods.
- Parameters:
image – Input image
y_pixels – Optional limb curve to overlay
- planet_ruler.plot.compare_gradient_fields(y_pixels_list, labels, image, image_smoothing=None, kernel_smoothing=5.0, directional_smoothing=30, directional_decay_rate=0.15)[source]
Compare gradient alignment for multiple proposed limbs.
- Parameters:
y_pixels_list (list) – List of y-coordinate arrays (different limb proposals)
labels (list) – Labels for each limb
image (np.ndarray) – Input image
kernel_smoothing (float) – Initial smoothing for gradient direction estimation
directional_smoothing (int) – How far to sample along gradients
directional_decay_rate (float) – Exponential decay rate for sampling
- planet_ruler.plot.plot_diff_evol_posteriors(observation, show_points=False, log=True)[source]
Extract and display the final state population of a differential evolution minimization.
- planet_ruler.plot.plot_full_limb(observation, x_min=None, x_max=None, y_min=None, y_max=None)[source]
Display the full limb, including the section not seen in the image.
- planet_ruler.plot.plot_residuals(observation, show_sparse_markers=True, marker_size=10, alpha=0.6, figsize=(16, 6), show_image=False, image_alpha=0.4, band_size=30)[source]
Plot residuals between the fitted limb and the detected target limb.
- Parameters:
observation – Instance of LimbObservation that has been fitted.
show_sparse_markers (
bool) – Use larger markers for sparse data.marker_size (
int) – Size of markers for sparse data.alpha (
float) – Transparency of residual markers/line.figsize (
tuple) – Figure size (width, height).show_image (
bool) – Show straightened image strip as background.image_alpha (
float) – Transparency of background image.band_size (
int) – Size of band around residuals to plot (in pixels)
- Return type:
- planet_ruler.plot.plot_gradient_field_quiver(image, step=2, scale=0.15, limb_y=None, roi_height=None, image_smoothing=None, kernel_smoothing=5.0, directional_smoothing=50, directional_decay_rate=0.15, downsample_factor=32, figsize=(16, 10), cmap='hot')[source]
Plot gradient field as quiver (arrow) plot.
- Parameters:
image (
ndarray) – Input image array.step (
int) – Spacing between arrows (every Nth pixel).limb_y (
Optional[ndarray]) – Optional limb curve to overlay (y-coordinates).roi_height (
Optional[int]) – If provided, only show ±roi_height pixels around limb.image_smoothing (
Optional[int]) – For gradient_field - Gaussian blur sigma applied to image before gradient computation. Removes high-frequency artifacts (crater rims, striations) that could mislead optimization. Different from kernel_smoothing.kernel_smoothing (
float) – Sigma for initial gradient direction estimation.directional_smoothing (
int) – Distance for directional blur sampling.directional_decay_rate (
float) – Exponential decay for directional blur.downsample_factor (
int) – Downsample image by this factor before computing gradients. Values > 1 reduce resolution (e.g., 2 = half resolution, 4 = quarter). Useful for visualizing gradient field at different optimization stages.figsize (
tuple) – Figure size (width, height).cmap (
str) – Colormap for gradient magnitude.
- Return type:
- planet_ruler.plot.plot_segmentation_masks(observation)[source]
Display all the classes/masks generated by the segmentation.
- planet_ruler.plot.plot_sam_masks(masks, labels=None, colors=None, alpha=0.5, image=None, figsize=(16, 10), title=None, show=True)[source]
Plot multiple SAM segmentation masks as separate labeled objects with legend.
- Parameters:
masks (list) – List of SAM mask dictionaries with ‘segmentation’ keys containing boolean arrays. Can also be a list of boolean arrays directly.
labels (list) – Labels for each mask (for legend). If None, uses “Mask 0”, “Mask 1”, etc.
colors (list) – Colors for each mask. If None, uses a default color cycle.
alpha (float) – Transparency of mask overlays (0=transparent, 1=opaque).
image (np.ndarray) – Optional background image to display under masks.
figsize (tuple) – Figure size in inches.
title (str) – Optional title for the plot.
show (bool) – Whether to display the plot immediately.
- Returns:
(fig, ax) matplotlib figure and axis objects.
- Return type:
Example
>>> masks = [{'segmentation': planet_mask}, {'segmentation': sky_mask}] >>> fig, ax = plot_sam_masks( ... masks, ... labels=['Planet', 'Sky'], ... colors=['yellow', 'cyan'], ... image=observation.image ... )
The plot module provides visualization functions:
Image display: plot_image - displays images with optional gradient overlay
Limb visualization: plot_limb - plots detected horizon curves
3D solutions: plot_3d_solution - 3D parameter space visualization
Topography: plot_topography - terrain height visualization
Analysis plots: plot_diff_evol_posteriors - differential evolution posterior distributions
Full limb plots: plot_full_limb - complete limb visualization with uncertainty
Segmentation plots: plot_segmentation_masks - image segmentation mask visualization
Validation Module
Validation functions for planet_ruler.
- planet_ruler.validation.validate_limb_config(config, strict=True)[source]
Validate that a planet_ruler configuration is internally consistent.
Checks: 1. Initial parameter values are within their specified limits 2. Theta parameter limits are wide enough (avoid r-h coupling issues) 3. Radius limits span reasonable range for robust optimization
- Parameters:
- Raises:
AssertionError – If strict=True and validation fails
- Return type:
Example
>>> config = { ... 'init_parameter_values': {'r': 6371000, 'theta_x': 0.1}, ... 'parameter_limits': {'r': [1e6, 1e8], 'theta_x': [-3.14, 3.14]} ... } >>> validate_config(config) # Passes
The validation module provides configuration validation:
Config validation: validate_limb_config - checks parameter limits, theta ranges, and consistency
Parameter bounds: Validates initial values are within specified limits
Optimization warnings: Identifies potential issues with tight constraints that could affect convergence
Command-Line Interface
Command-line interface for planet_ruler
This module provides a simple CLI for measuring planetary radii from horizon photographs.
The CLI module provides command-line access to planet_ruler:
Main interface: main - primary CLI entry point
Measurement: measure_command - automated radius measurement from images
Demo functionality: demo_command - run example scenarios
Configuration: load_config, list_command - manage configuration files
Dashboard Module
Live progress dashboard for parameter optimization.
Displays real-time updates during fit_limb() optimization, showing: - Current parameter estimates (radius, altitude, focal length) - Optimization progress and convergence - Loss function evolution - Smart warnings and educational hints
Works in: terminal, Jupyter notebooks, IPython Updates in-place (no scrolling spam)
Example
>>> obs = LimbObservation("photo.jpg", "config.yaml")
>>> obs.detect_limb(method="manual")
>>> obs.fit_limb(dashboard=True) # Shows live dashboard during fitting
- class planet_ruler.dashboard.OutputCapture(max_lines=5, line_width=55, capture_stderr=True)[source]
Bases:
objectCapture stdout/stderr for display in dashboard.
Thread-safe ring buffer that stores recent output lines. Designed to integrate with FitDashboard for live output display.
- Parameters:
Examples
>>> capture = OutputCapture(max_lines=5) >>> with capture: ... print("Iteration 100: loss = 123.45") ... print("Warning: parameter drift detected") >>> lines = capture.get_lines()
- class planet_ruler.dashboard.FitDashboard(initial_params, target_planet='earth', max_iter=None, free_params=None, total_stages=1, cumulative_max_iter=None, min_refresh_delay=0.0, refresh_frequency=1, output_capture=None, show_output=True, max_output_lines=3, max_warnings=3, max_hints=3, min_message_display_time=3.0, width=63)[source]
Bases:
objectLive dashboard for optimization progress.
Shows real-time parameter estimates, convergence status, and helpful warnings during fit_limb() optimization.
- Parameters:
initial_params (dict) – Initial parameter values (r, h, f, w, etc.)
target_planet (str, default 'earth') – Reference planet for comparison (‘earth’, ‘mars’, etc.)
max_iter (int, optional) – Maximum iterations (if known)
free_params (list of str, optional) – Which parameters are being optimized
total_stages (int, default 1) – Number of optimization stages (for multi-resolution)
cumulative_max_iter (int, optional) – Total iterations across all stages
min_refresh_delay (float, default 0.0) – Minimum time (seconds) between refreshes (0.0 enables adaptive)
refresh_frequency (int, default 1) – Refresh every N iterations
output_capture (OutputCapture, optional) – Output capture instance for displaying print/log statements
show_output (bool, default True) – Show output section in dashboard (requires output_capture)
max_output_lines (int, default 3) – Maximum number of output lines to display
max_warnings (int, default 3) – Number of warning message slots
max_hints (int, default 3) – Number of hint message slots
min_message_display_time (float, default 3.0) – Minimum time (seconds) to display warnings/hints before removal
width (int, default 63) – Dashboard width in characters (includes borders)
- __init__(initial_params, target_planet='earth', max_iter=None, free_params=None, total_stages=1, cumulative_max_iter=None, min_refresh_delay=0.0, refresh_frequency=1, output_capture=None, show_output=True, max_output_lines=3, max_warnings=3, max_hints=3, min_message_display_time=3.0, width=63)[source]
- update(current_params, loss)[source]
Update dashboard with current optimization state.
Called by optimizer callback at each iteration.
The dashboard module provides real-time optimization monitoring:
FitDashboard: Live progress dashboard with adaptive refresh rate
OutputCapture: Capture stdout/stderr for display in dashboard
Adaptive refresh: Automatically adjusts update frequency (20Hz → 2Hz) based on optimization activity
Configurable display: Adjust width, message slots, and display time
Demo and Configuration
The demo module manages example scenarios:
Parameter loading: load_demo_parameters - loads predefined planetary scenarios
Interactive widgets: make_dropdown - creates UI elements for Jupyter notebooks
Function Categories
Mathematical Functions
Core geometric calculations:
Estimate the distance to the horizon (limb) given a height and radius. |
|
The angle the camera must tilt in theta_x or theta_y to center the limb. |
|
The size of the CCD (inferred) based on focal length and field of view. |
|
The size of the CCD (inferred) based on focal length and field of view. |
|
The size of the CCD (inferred) based on focal length and field of view. |
|
Compute combined rotation matrix from Euler angles. |
Image Processing Functions
Computer vision and image analysis:
|
Load a 3 or 4-channel image from filepath into an array. |
|
Scan each vertical line of an image for the maximum change in brightness gradient -- usually corresponds to a horizon. |
|
Smooth the limb position values. |
Fill NaNs for the limb position values. |
|
Bilinear interpolation for 2D array at non-integer coordinates. |
|
|
Pre-compute gradient field AND its derivatives for fast sub-pixel interpolation. |
Manual Annotation Functions
Interactive limb detection and annotation:
|
Tkinter-based interactive tool for manually annotating planet limbs. |
Start the application. |
|
Get the current sparse target array. |
|
Generate sparse target array. |
|
Save points to JSON. |
|
Load points from JSON. |
Camera Parameter Functions
Automatic camera parameter extraction:
|
Extract EXIF data from image. |
|
Extract camera model from EXIF data. |
Extract focal length in mm from EXIF. |
|
Get 35mm equivalent focal length (more reliable for phones). |
|
Automatically extract all camera parameters from any camera image. |
|
|
Extract GPS altitude from EXIF data if available. |
Create a complete planet_ruler configuration from an image. |
|
Get initial radius guess with perturbation. |
Coordinate Transform Functions
Camera geometry and projections:
Transform from camera coordinates into image coordinates. |
|
Transform from world coordinates into camera coordinates. |
|
|
Calculate limb position analytically at each pixel x-coordinate. |
Calculate the limb orientation in an image given the physical parameters of the system. |
Optimization Functions
Parameter fitting and uncertainty:
|
Turn a dict of parameters (or defaults) into a list. |
|
Turn a list of parameters back into a dict. |
Calculate parameter uncertainty from fitting results. |
|
Format parameter uncertainty results for display. |
|
|
Calculate uncertainty for a fitted parameter using appropriate method. |
|
Uncertainty from differential evolution population. |
|
Uncertainty from inverse Hessian (covariance) at optimum. |
|
Uncertainty from profile likelihood. |
|
Uncertainty from bootstrap: run optimizer multiple times with different seeds. |
Validation Functions
Configuration and parameter validation:
Validate that a planet_ruler configuration is internally consistent. |
Command-Line Functions
CLI interface and commands:
Main CLI entry point. |
|
Handle the measure command. |
|
Handle the demo command. |
|
Handle the list command. |
|
|
Load configuration from YAML or JSON file. |
Visualization Functions
Plotting and display:
|
Display an image using matplotlib.pyplot.imshow. |
|
Display the limb (usually on top of an image). |
|
Plot a limb solution in 3D. |
Display the full limb, including the section not seen in the image. |
|
Extract and display the final state population of a differential evolution minimization. |
|
|
Display the full limb, including the section not seen in the image. |
Display all the classes/masks generated by the segmentation. |
Classes
CostFunction
- class planet_ruler.fit.CostFunction(target, function, free_parameters, init_parameter_values, loss_function='l2', kernel_smoothing=5.0, directional_smoothing=30, directional_decay_rate=0.15, prefer_direction=None)[source]
Bases:
objectWrapper to simplify interface with the minimization at hand.
- Parameters:
target (np.ndarray) – True value(s), e.g., the actual limb position. For gradient_field loss, this should be the image.
function (Callable) – Function mapping parameters to target of interest.
free_parameters (list) – List of free parameter names.
init_parameter_values (dict) – Initial values for named parameters.
loss_function (str) – Type of loss function, must be one of [‘l2’, ‘l1’, ‘log-l1’, ‘gradient_field’].
kernel_smoothing – For gradient_field - initial blur for gradient direction estimation. Makes the gradient field smoother for directional sampling.
directional_smoothing – For gradient_field - sampling distance along gradients
directional_decay_rate – For gradient_field - exponential decay for samples
prefer_direction (
Optional[str]) – For gradient_field - prefer ‘up’ or ‘down’ gradients where ‘up’ means dark-sky/bright-planet and v.v. (None = no preference, choose best gradient regardless of direction)
- __init__(target, function, free_parameters, init_parameter_values, loss_function='l2', kernel_smoothing=5.0, directional_smoothing=30, directional_decay_rate=0.15, prefer_direction=None)[source]
Cost function wrapper for optimization problems. Supports multiple loss functions (L1, L2, log-L1) and flexible parameter handling.
PlanetObservation
- class planet_ruler.observation.PlanetObservation(image_filepath)[source]
Bases:
objectBase class for planet observations.
- Parameters:
image_filepath (str) – Path to image file.
Base class for planetary observations. Handles image loading and basic plotting functionality.
LimbObservation
- class planet_ruler.observation.LimbObservation(image_filepath, fit_config, limb_detection='manual', minimizer='differential-evolution')[source]
Bases:
PlanetObservationObservation of a planet’s limb (horizon).
- Parameters:
- __init__(image_filepath, fit_config, limb_detection='manual', minimizer='differential-evolution')[source]
- analyze(detect_limb_kwargs=None, fit_limb_kwargs=None)[source]
Perform complete limb analysis: detection + fitting in one call.
- property radius_km: float
Get the fitted planetary radius in kilometers.
- Returns:
Planetary radius in km, or 0 if not fitted
- Return type:
- property altitude_km: float
Get the observer altitude in kilometers.
- Returns:
Observer altitude in km, or 0 if not fitted
- Return type:
- property focal_length_mm: float
Get the camera focal length in millimeters.
- Returns:
Focal length in mm, or 0 if not fitted
- Return type:
- property radius_uncertainty: float
Get parameter uncertainty for radius.
Automatically selects best method based on minimizer: - differential_evolution: Uses population spread (fast, exact) - dual_annealing/basinhopping: Uses Hessian approximation (fast, approximate)
- Returns:
Radius uncertainty in km (1-sigma), or 0 if not available
- Return type:
- parameter_uncertainty(parameter, method='auto', scale_factor=1.0, confidence_level=0.68, **kwargs)[source]
Get uncertainty for any fitted parameter.
- Parameters:
parameter (
str) – Parameter name (e.g., ‘r’, ‘h’, ‘f’, ‘theta_x’)method (
Literal['auto','hessian','profile','bootstrap']) – Uncertainty method - ‘auto’: Choose based on minimizer (recommended) - ‘hessian’: Fast Hessian approximation - ‘profile’: Slow but accurate profile likelihood - ‘bootstrap’: Multiple fits (very slow)scale_factor (
float) – Scale result (e.g., 1000.0 for m→km)confidence_level (
float) – Confidence level (0.68=1σ, 0.95=2σ)**kwargs – Additional arguments passed to uncertainty calculator
- Return type:
- Returns:
dict with ‘uncertainty’, ‘method’, ‘confidence_level’, ‘additional_info’
Examples
# Radius uncertainty in km (1-sigma) obs.parameter_uncertainty(‘r’, scale_factor=1000.0)
# Altitude uncertainty in km (2-sigma / 95% CI) obs.parameter_uncertainty(‘h’, scale_factor=1000.0, confidence_level=0.95)
# Focal length uncertainty in mm (using profile likelihood) obs.parameter_uncertainty(‘f’, scale_factor=1000.0, method=’profile’)
- plot_3d(**kwargs)[source]
Create 3D visualization of the planetary geometry.
- Parameters:
**kwargs – Arguments passed to plot_3d_solution
- Return type:
- load_fit_config(fit_config)[source]
Load the fit configuration from file, setting all parameters to their initial values. Missing values are filled with defaults.
- register_limb(limb)[source]
Register a detected limb.
- Parameters:
limb (np.ndarray) – Limb vector (y pixel coordinates).
- Return type:
- detect_limb(detection_method=None, log=False, y_min=0, y_max=-1, window_length=501, polyorder=1, deriv=0, delta=1, segmentation_method='sam', downsample_factor=1, interactive=True, **segmentation_kwargs)[source]
Use the instance-defined method to find the limb in our observation. Kwargs are passed to the method.
- Parameters:
detection_method (literal) –
- Detection method. Must be one of
manual
gradient-break
gradient-field
segmentation
Default (None) uses the class attribute self.limb_detection.
log (bool) – Use the log(gradient). Sometimes good for smoothing.
y_min (int) – Minimum y-position to consider.
y_max (int) – Maximum y-position to consider.
window_length (int) – Width of window to apply smoothing for each vertical. Larger means less noise but less sensitivity.
polyorder (int) – Polynomial order for smoothing.
deriv (int) – Derivative level for smoothing.
delta (int) – Delta for smoothing.
segmentation_method (str) – Model used for segmentation. Must be one of [‘sam’].
downsample_factor (int) – Downsampling used for segmentation.
interactive (bool) – Prompts user to verify segmentation via annotation tool.
segmentation_kwargs (dict) – Kwargs passed to segmentation engine.
- Return type:
- smooth_limb(fill_nan=True, **kwargs)[source]
Apply the smooth_limb function to current observation.
- fit_limb(loss_function='l2', max_iter=15000, resolution_stages=None, max_iter_per_stage=None, n_jobs=1, seed=0, image_smoothing=None, kernel_smoothing=5.0, directional_smoothing=50, directional_decay_rate=0.15, prefer_direction=None, minimizer=None, minimizer_preset='balanced', minimizer_kwargs=None, warm_start=False, dashboard=False, dashboard_kwargs=None, target_planet='earth', verbose=False)[source]
Fit the limb to determine planetary parameters.
Supports single-resolution or multi-resolution (coarse-to-fine) optimization. Multi-resolution is recommended for gradient_field loss to avoid local minima.
- Parameters:
loss_function (
Literal['l2','l1','log-l1','gradient_field']) – Loss function type - ‘l2’, ‘l1’, ‘log-l1’: Traditional (requires detected limb) - ‘gradient_field’: Direct gradient alignment (no detection needed)max_iter (
int) – Maximum iterations (for single-resolution or total if multires)resolution_stages (
Union[List[int],Literal['auto'],None]) –Resolution strategy - None: Single resolution (original behavior) - ‘auto’: Auto-determine stages based on image size - List[int]: Custom stages, e.g., [4, 2, 1] = 1/4 → 1/2 → full NOTE: Multi-resolution only works with gradient_field loss functions.
Traditional loss functions (l2, l1, log-l1) require single resolution.
max_iter_per_stage (
Optional[List[int]]) – Iterations per stage (auto if None)n_jobs (
int) – Number of parallel workersseed (
int) – Random seed for reproducibilityimage_smoothing (
Optional[float]) – For gradient_field - Gaussian blur sigma applied to image before gradient computation. Removes high-frequency artifacts (crater rims, striations) that could mislead optimization. Different from kernel_smoothing.kernel_smoothing (
float) – For gradient_field - initial blur for gradient direction estimation. Makes the gradient field smoother for directional sampling.directional_smoothing (
int) – For gradient_field - sampling distance along gradientsdirectional_decay_rate (
float) – For gradient_field - exponential decay for samplesprefer_direction (
Optional[Literal['up','down']]) – For gradient_field - prefer ‘up’ or ‘down’ gradients where ‘up’ means dark-sky/bright-planet and v.v. (None = no preference, choose best gradient regardless of direction)minimizer (str) – Choice of minimizer. Supports ‘differential-evolution’, ‘dual-annealing’, and ‘basinhopping’.
minimizer_preset (
Literal['fast','balanced','robust','scipy-default']) – Optimization strategy - ‘fast’: Quick convergence, may miss global minimum - ‘balanced’: Good trade-off (default) - ‘robust’: Thorough exploration, slowerminimizer_kwargs (
Optional[Dict]) – Override specific minimizer parameters (advanced)warm_start (
bool) – If True, use previous fit’s results as starting point (useful for iterative refinement). If False (default), use original init_parameter_values. Note: Multi-resolution stages always warm-start from previous stages automatically. This parameter is for warm-starting across separate fit_limb() calls.dashboard (
bool) – Show live progress dashboard during optimizationdashboard_kwargs (
Optional[Dict]) – Additional kwargs for FitDashboard - output_capture: OutputCapture instance for print/log display - show_output: Show output section (default True if capture provided) - max_output_lines: Number of output lines to show (default 3) - min_refresh_delay: Fixed refresh delay (0.0 for adaptive, default) - refresh_frequency: Refresh every N iterations (default 1)target_planet (
str) – Reference planet for dashboard comparisons (‘earth’, ‘mars’, ‘jupiter’, ‘saturn’, ‘moon’, ‘pluto’)verbose (
bool) – Print detailed progress
- Returns:
For method chaining
- Return type:
self
Examples
# Simple single-resolution fit obs.fit_limb()
# Auto multi-resolution for gradient field obs.fit_limb(loss_function=’gradient_field’, resolution_stages=’auto’)
# Remove image artifacts before optimization obs.fit_limb(
loss_function=’gradient_field’, resolution_stages=’auto’, image_smoothing=2.0, # Remove crater rims, striations kernel_smoothing=5.0 # Smooth gradient field
)
# Custom stages with robust optimization obs.fit_limb(
loss_function=’gradient_field’, resolution_stages=[8, 4, 2, 1], minimizer_preset=’robust’
)
# Override specific minimizer parameters obs.fit_limb(
loss_function=’gradient_field’, minimizer_kwargs={‘popsize’: 25, ‘atol’: 0.5}
)
# Dashboard with output capture from planet_ruler.dashboard import OutputCapture capture = OutputCapture() with capture:
- obs.fit_limb(
loss_function=’gradient_field’, dashboard=True, dashboard_kwargs={‘output_capture’: capture}
)
# Iterative refinement with warm start obs.fit_limb(loss_function=’gradient_field’, resolution_stages=’auto’) obs.fit_limb(loss_function=’gradient_field’, warm_start=True,
minimizer_preset=’robust’) # Refine with more thorough search
Complete workflow class for limb-based planetary radius determination. Default detection method is interactive manual annotation. Includes horizon detection, limb fitting with multi-resolution optimization, and comprehensive uncertainty analysis.
Detection Methods Available:
manual (default): Interactive GUI for precise point selection
gradient-break: Simple gradient-based detection
gradient-field: Automated detection using gradient flow analysis with directional blur
segmentation: AI-powered automatic detection (requires PyTorch + Segment Anything)
Key Features:
Multi-resolution optimization with coarse-to-fine refinement
Multiple uncertainty estimation methods (population spread, Hessian, profile likelihood)
Flexible cost functions (gradient-field flux, L1, L2, log-L1)
Support for multiple minimizers (differential-evolution, dual-annealing, basinhopping)
MaskSegmenter
- class planet_ruler.image.MaskSegmenter(image, method='sam', downsample_factor=1, interactive=True, **backend_kwargs)[source]
Bases:
objectMethod-agnostic mask-based segmentation.
Supports pluggable backends (SAM, custom algorithms, etc.) with optional downsampling and interactive classification.
Advanced image segmentation with pluggable backends. Supports Segment Anything model (optional dependency) and custom segmentation functions. Provides automated mask generation, interactive classification, and limb extraction from complex images.
TkLimbAnnotator
- class planet_ruler.annotate.TkLimbAnnotator(image_path, initial_stretch=1.0, initial_zoom=None)[source]
Bases:
objectTkinter-based interactive tool for manually annotating planet limbs.
Features: - Zoom with scroll wheel (fit large images in window) - Vertical stretch buttons (stretch pixels vertically for precision) - Scrollable canvas for navigating - Click to add points, right-click to undo - Save/load points to JSON - Generate sparse target array for CostFunction
Interactive GUI for manual limb annotation. Provides precise user control over horizon detection with no additional dependencies required.
Key Features:
Interactive point selection: Left click to add points, right click to remove
Zoom and pan: Mouse wheel zoom, drag to pan for precise annotation
Contrast adjustment: Arrow keys to adjust image stretch/brightness
Session management: Save (‘s’) and load (‘l’) annotation sessions
Target generation: Convert sparse points to dense limb arrays
Constants and Configuration
Camera Database
The camera module includes a comprehensive database of sensor dimensions for automatic parameter extraction:
Smartphones: iPhone models (iPhone 11-14 series), Samsung Galaxy, Google Pixel, etc.
Point-and-shoot: Canon PowerShot series, Nikon Coolpix, Sony Cyber-shot
DSLRs: Canon EOS series, Nikon D series, Sony Alpha
Mirrorless: Sony ILCE series, Canon EOS R, Nikon Z series
Generic sensors: Common sensor sizes (1/2.3”, 1/1.7”, APS-C, Full Frame)
Planet Radius Database
Built-in planetary radii for initial optimization guesses (automatically perturbed):
Earth: 6,371,000 m
Mars: 3,389,500 m
Jupiter: 69,911,000 m
Saturn: 58,232,000 m
Moon: 1,737,400 m
Pluto: 1,188,300 m
And others…
Default Parameters
The following default values are used throughout Planet Ruler:
ISS altitude: 418,000 m
Image processing window: 21 pixels
Optimization tolerance: 1e-6
Maximum iterations: 1000
Perturbation factor: 50% (for initial radius guessing)
File Formats
Supported file formats:
Images: JPEG, PNG, TIFF, BMP (with EXIF support)
Configuration: YAML (.yaml, .yml), JSON (.json)
Data output: CSV, JSON, pickle
Annotation sessions: JSON
Error Handling
Planet Ruler raises specific exceptions for different error conditions:
ValueError: Invalid parameter values or configurations
FileNotFoundError: Missing image or configuration files
ImportError: Missing optional dependencies (e.g., PyTorch for Segment Anything)
RuntimeError: Optimization convergence failures
AssertionError: Configuration validation failures (when strict=True)
See individual function documentation for specific error conditions and handling recommendations.