Skip to content

Core Concepts

bacetiner edited this page Oct 6, 2026 · 3 revisions

Four ideas cover the whole library: assets and collections describe what you are studying, image assets hold the pictures of them, pipeline steps do the work, and models are interchangeable engines behind the analysis steps.

The package is organised into four subpackages. rapidtools.core holds the domain objects, rapidtools.data_sources the clients for external imagery and local rasters, rapidtools.models the model wrappers, and rapidtools.processing the pipeline steps. Everything shown here is also re-exported at the top level (import rapidtools as rt). Full signatures live in the API reference.

Assets and collections

A PhysicalAsset is the digital twin of one real-world object: a building, a road segment, a utility pole, a vehicle. It holds a Shapely geometry, a dictionary of attributes, and an ImageCollection of the pictures taken of it (image_assets).

from shapely.geometry import Point
from rapidtools import PhysicalAsset

pole = PhysicalAsset(
    id='pole_123',
    geometry=Point(-118.14, 34.19),
    attributes={'asset_type': 'utility_pole', 'material': 'wood'},
)

A PhysicalAssetCollection is an ordered container of assets with unique IDs and constant-time lookup by ID. It reads and writes GeoJSON and Shapefiles, converts to a pandas DataFrame, filters by geometry or attribute, and merges with other collections.

from rapidtools import BoundingBox, PhysicalAssetCollection

buildings = PhysicalAssetCollection.from_geojson('buildings.geojson')
subset = buildings.filter_by_geometry(BoundingBox(-118.15, 34.18, -118.13, 34.20))
damaged = subset.filter_by_attribute('gemini_chs_level', '4')
damaged.to_shapefile('damaged.shp', ignore_properties=['image_assets'])

buildings['bldg_01']          # lookup by ID
buildings[:10]                # slice into a new collection
len(buildings), 'bldg_01' in buildings

filter_by_attribute takes an operator ('==' by default, for example '!='). filter_empty() drops assets that received no imagery. See Data Formats and Export for the file formats and the sidecar that keeps image assets across round trips.

Regions

BoundingBox and PolygonRegion describe areas of interest in WGS84 (longitude, latitude). A bounding box can be built from a raster's extent, a GeoJSON file or any geometry, buffered, split into tiles, and used to filter collections or to drive basemap downloads.

region = BoundingBox.from_raster('eaton_patch_20250214.tiff')
region = BoundingBox.from_geojson('area.geojson')
region.width, region.height, region.area
tiles = region.tile_by_area(0.0001)   # sub-boxes of at most 0.0001 square degrees

Image assets

An ImageAsset points at one image file and carries properties such as the WGS84 bounds of an aerial crop or the panorama ID of a street-level view, plus optional semantic and instance masks. Extractors create image assets and attach them to physical assets; analyzers and segmenters read them. An image asset can exist before its file is downloaded (allow_missing_file=True), which lets extractors decide what to fetch before spending bandwidth.

Street-level detection adds one more record: an Observation links an asset to a single sighting in a street-level image (image ID, bearing, range), so crops can be regenerated later without re-running detection.

Pipelines and stages

A Pipeline runs a list of steps over a collection. Each step is a callable that takes a collection and returns one, and declares a Stage:

Stage Components
DETECT SAM3OrthoFeatureExtractor discovers new assets in a raster; MapillaryFeatureExtractor discovers them along a street-level survey.
EXTRACT_IMAGERY AerialImageryExtractor, GoogleStreetViewImageExtractor, MapillaryImageExtractor, MapillaryObjectImageExtractor attach imagery to assets.
REGULARIZE BuildingRegularizer, RoadwayRegularizer clean geometries.
SEGMENT SAM3ImageSegmenter masks the attached images.
VERIFY DetectionVerifier shows each discovered object's crops to a model and removes what is not the requested class; DuplicateResolver then merges pairs of nearby objects the model is sure are one vehicle.
ANALYZE AssetAnalyzer writes model answers to attributes.
EXPORT / CUSTOM Your own callables; unknown steps run last.

Steps can be added in any order: the pipeline sorts them by stage before running, so an analyzer added before an extractor still runs after it. Any plain function can be a step, which is the easiest way to add a custom export or filter.

from rapidtools import Pipeline

def drop_unimaged(collection):
    return collection.filter_empty()

pipeline = Pipeline([analyzer, extractor, drop_unimaged])
result = pipeline.run(buildings)

A detection pipeline can start from an empty collection: Pipeline([detector, cropper, analyzer]).run(PhysicalAssetCollection()).

Every long-running component and the Pipeline accept a cancel_event (a threading.Event) and raise OperationCancelled at the next asset, tile or batch, keeping partial results. Call rapidtools.configure_logging() to see progress; importing the package never touches logging. Details are in the cancellation and logging guide.

Models and analyzers

Every model wrapper, hosted or local, implements run_inference(image_inputs, prompt) and returns a ModelOutput (with text, and for segmentation models masks and bounding_boxes). Build one with rapidtools.models.load() and its registry key, then hand it to AssetAnalyzer. Switching providers is a one-word change; the analyzer picks threaded execution for APIs and batched execution for local models on its own.

from rapidtools import AssetAnalyzer
from rapidtools.models import GenerationConfig, load

model = load('claude', api_key='sk-ant-...')
analyzer = AssetAnalyzer(
    model,
    prompt='Return JSON with a damage_level key (0-4).',
    generation=GenerationConfig(json_mode=True, temperature=0.0),
)

Answers are written as attributes prefixed with the provider key (claude_damage_level); pass attribute_prefix= to choose your own. Hosted models run max_workers requests in parallel under a RateLimitPolicy (shared cooldown after a failure, then retry passes over the assets that failed). Local models run in batches of batch_size. max_images_per_asset and image_filter choose which attached images the model sees.

The provider-specific classes such as GeminiAssetAnalyzer and Gemma4AssetAnalyzer still work but are deprecated in favour of AssetAnalyzer(load(...)). See Supported Models and Vision-Language Models.

Where to go next

Clone this wiki locally