Local drone processing¶
Module: spectralbridge.pipelines.drone.
Direct-module reference; consult the linked workflow for processing context.
API glossary ยท Workflow / scientific context
Signatures and documentation below are collected from the current source. Advanced objects are not newly declared stable by inclusion here.
Audience: advanced.
DroneCorrectionUnavailableError ¶
DroneCorrectionUnavailableError(message: str, audit: dict[str, Any])
Raised when a requested drone correction cannot produce a valid output.
Audience: advanced.
DronePipelineIncompleteError ¶
DronePipelineIncompleteError(message: str, results: dict[str, Any])
A run did not satisfy its requested scientific output contract.
Audience: advanced.
DroneInputSource
dataclass
¶
DroneInputSource(source_path: Path, source_type: str, flight_stem: str)
Describe one supported discovered drone HDF5/TIFF source and its provenance.
Audience: advanced.
DroneOutputRequirement
dataclass
¶
DroneOutputRequirement(name: str, kind: str, paths: tuple[Path, ...])
Describe one canonical product required by a selected drone extraction/translation workflow.
Audience: advanced.
load_drone_manifest ¶
load_drone_manifest(manifest_path: str | Path) -> dict[str, datetime]
Load drone flight acquisition datetimes from a CSV manifest.
The manifest is expected to include Plot, Day of data collection,
and Mean Time of data collection (24 hr clock) columns. Flight
identifiers are normalized to uppercase underscore-separated tokens such as
AOP_GOLDHILL. Rows with missing identifiers or malformed datetimes are
skipped with warnings so a partially messy field manifest can still support
valid flights.
Audience: advanced.
lookup_flight_datetime ¶
lookup_flight_datetime(flight_id: str, manifest: dict[str, datetime] | None) -> datetime | None
Return a manifest datetime for a derived drone flight identifier.
Matching rules are deliberately conservative and deterministic:
- identifiers are compared after uppercasing and collapsing separators to underscores;
- an exact match wins first;
- a trailing
YYYYMMDDtoken is ignored, soAOP_GOLDHILL_20230814matches manifest rowAOP_GOLDHILL; - if needed, separators are ignored for compact matching, so
SPR1matches manifest rowSPR-1; - if neither rule matches, the longest manifest key that prefixes the derived flight stem wins.
Audience: advanced.
clean_name ¶
clean_name(name: str) -> str
Normalise a source name minimally for filesystem-safe output filenames.
Audience: advanced.
derive_drone_flight_stem ¶
derive_drone_flight_stem(h5_path: str | Path) -> str
Derive a drone flight stem from the package folder rather than the inner HDF5.
Audience: advanced.
build_drone_output_paths ¶
build_drone_output_paths(output_root: str | Path, *, flight_stem: str) -> dict[str, Path]
Return per-flight drone paths under a dedicated flight directory.
Audience: advanced.
required_drone_outputs ¶
required_drone_outputs(path_map: dict[str, Path], *, extraction_mode: str, translation_targets: Sequence[str] = (), include_report: bool = False) -> tuple[DroneOutputRequirement, ...]
Describe the per-flight artifacts required by the requested workflow.
The same contract drives final validation and orchestration tests. Optional actual-Landsat comparison is excluded because scene availability is external.
Audience: advanced.
summarize_drone_h5_solar_geometry ¶
summarize_drone_h5_solar_geometry(h5_path: str | Path) -> dict[str, Any]
Return solar geometry provenance and summary stats for a drone working H5.
Audience: advanced.
diagnose_drone_h5_solar_geometry ¶
diagnose_drone_h5_solar_geometry(h5_path: str | Path, *, acquisition_datetime: datetime | str | None = None, naive_timezone: str | None = None, candidate_timezones: Sequence[str] = ('UTC',), solar_summary: dict[str, Any] | None = None) -> dict[str, Any]
Compare source H5 angles with scene-center solar position, read-only.
Naive timestamps have unknown provenance unless naive_timezone is
explicitly supplied. Candidate interpretations are informational only.
Thresholds (5/20 degrees) are deliberately provisional review bands, not
a calibration or permission to replace supplied correction geometry.
Audience: advanced.
convert_drone_tiff_to_h5 ¶
convert_drone_tiff_to_h5(reflectance_tiff_path: str | Path, *, output_h5_path: str | Path, wavelengths_nm: Sequence[float] | ndarray | None = None, fwhm_nm: Sequence[float] | ndarray | None = None, sensor_zenith_tiff: str | Path | None = None, sensor_azimuth_tiff: str | Path | None = None, slope_tiff: str | Path | None = None, aspect_tiff: str | Path | None = None, solar_zenith_tiff: str | Path | None = None, solar_azimuth_tiff: str | Path | None = None, solar_zenith_deg: float | None = None, solar_azimuth_deg: float | None = None, sensor_zenith_deg: float | None = None, sensor_azimuth_deg: float | None = None, acquisition_datetime: datetime | str | None = None, require_solar_geometry: bool = False, overwrite: bool = False) -> Path
Convert a supported georeferenced multiband reflectance TIFF and aligned ancillary inputs to the drone HDF5 contract.
Audience: advanced.
resolve_band_map ¶
resolve_band_map(wavelengths: list[float] | ndarray, targets: dict[str, int]) -> dict[str, dict[str, float | int]]
Map conceptual drone band names to nearest wavelength coordinates, recording selected indices and distances.
Audience: advanced.
validate_drone_h5_metadata ¶
validate_drone_h5_metadata(h5_path: str | Path) -> dict[str, Any]
Validate minimally required drone H5 metadata and return a structured summary.
Audience: advanced.
export_h5_to_envi ¶
export_h5_to_envi(h5_path: str | Path, *, output_stem: str | Path, brightness_offset: float = 0.0, overwrite: bool = False, cube: NeonCube | None = None) -> tuple[Path, Path]
Export a local H5 cube to ENVI using a drone-native filename stem.
Audience: advanced.
build_drone_config ¶
build_drone_config(*, h5_path: Path, envi_img: Path, envi_hdr: Path, corrected_img: Path, corrected_hdr: Path, wavelengths: list[float], fwhm: list[float] | None, band_map: dict[str, dict[str, float | int]], apply_topo: bool, apply_brdf: bool, use_ndvi_brdf_bins: bool) -> dict[str, Any]
Build the explicit local drone correction configuration from existing paths, wavelengths and correction flags.
Audience: advanced.
apply_drone_corrections ¶
apply_drone_corrections(*, cube: NeonCube, envi_img: Path, envi_hdr: Path, corrected_stem: Path, apply_topo: bool, apply_brdf: bool, use_ndvi_brdf_bins: bool = False, overwrite: bool = False) -> tuple[Path, Path, dict[str, Any]]
Apply optional topo/BRDF corrections to a drone ENVI export.
run_drone_pipeline now requests both topo and BRDF correction by
default. Each correction still remains conditional on the required
ancillary geometry being available for the current cube.
Audience: advanced.
collect_drone_spatial_diagnostics ¶
collect_drone_spatial_diagnostics(*, raster_img: Path, polygons_path: Path) -> dict[str, Any]
Collect drone-only raster/polygon overlay diagnostics before extraction.
Audience: advanced.
save_drone_overlay_debug_plot ¶
save_drone_overlay_debug_plot(*, polygons_path: Path, raster_bounds: list[float] | tuple[float, float, float, float], raster_crs: str | None, output_path: Path) -> Path
Write a lightweight overlay PNG for drone polygon/raster diagnostics.
Audience: public. Also exported as spectralbridge.pipelines.run_drone_pipeline, spectralbridge.run_drone_pipeline.
run_drone_pipeline ¶
run_drone_pipeline(input_h5_dir: str | Path, polygon_path: str | Path | None = None, output_dir: str | Path = '.', apply_topo: bool = True, apply_brdf: bool = True, use_ndvi_brdf_bins: bool = False, apply_brightness_adjustment: bool = False, overwrite: bool = False, tiff_wavelengths_nm: Sequence[float] | ndarray | None = None, tiff_fwhm_nm: Sequence[float] | ndarray | None = None, tiff_solar_zenith_deg: float | None = None, tiff_solar_azimuth_deg: float | None = None, tiff_sensor_zenith_deg: float | None = None, tiff_sensor_azimuth_deg: float | None = None, drone_manifest_path: str | Path | None = None, drone_manifest_timezone: str | None = 'UTC', require_solar_geometry: bool = True, extraction_mode: str | None = None, parquet_chunk_size: int = 2048, merge_extractions: bool = False, apply_translation: bool = False, translation_coefficients: str | Path | None = None, translation_weighting: str | None = None, translation_strict: bool = False, landsat_qa: bool = False, landsat_product: str | Path | None = None, landsat_search_days: int = 16, comparison_neon_product: str | Path | None = None, raise_on_incomplete: bool = True, solar_qa_timezone: str | None = None) -> dict[str, Any]
Run the drone pipeline from local HDF5 or reflectance TIFF sources.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_h5_dir
|
str | Path
|
Existing local supported HDF5/TIFF file or directory; discovery recurses through source packages. |
required |
polygon_path
|
str | Path | None
|
Existing polygon vector dataset for extraction; coordinates are handled by the established polygon workflow. |
None
|
output_dir
|
str | Path
|
Directory for generated products; bulk outputs must be outside the read-only input tree. |
'.'
|
apply_topo
|
bool
|
Enable the existing topographic correction when required terrain/geometry metadata are available. |
True
|
apply_brdf
|
bool
|
Enable the existing BRDF correction when required angular metadata are available. |
True
|
use_ndvi_brdf_bins
|
bool
|
Opt into the existing NDVI-stratified BRDF fitting behavior rather than the default fit. |
False
|
apply_brightness_adjustment
|
bool
|
Opt into the established brightness adjustment; does not change the packaged coefficients. |
False
|
overwrite
|
bool
|
Replace existing requested products; False preserves reusable products or rejects a conflicting destination. |
False
|
tiff_wavelengths_nm
|
Sequence[float] | ndarray | None
|
Explicit per-band center wavelengths in nanometers for TIFF inputs lacking embedded spectral metadata; must match band order/count. |
None
|
tiff_fwhm_nm
|
Sequence[float] | ndarray | None
|
Per-band full widths at half maximum in nanometers, aligned with TIFF bands; None uses supported metadata. |
None
|
tiff_solar_zenith_deg
|
float | None
|
Explicit TIFF solar zenith in degrees when valid embedded metadata are unavailable. |
None
|
tiff_solar_azimuth_deg
|
float | None
|
Explicit TIFF solar azimuth in degrees when valid embedded metadata are unavailable. |
None
|
tiff_sensor_zenith_deg
|
float | None
|
Explicit TIFF view zenith in degrees when valid embedded metadata are unavailable. |
None
|
tiff_sensor_azimuth_deg
|
float | None
|
Explicit TIFF view azimuth in degrees when valid embedded metadata are unavailable. |
None
|
drone_manifest_path
|
str | Path | None
|
Existing flight manifest providing acquisition identity/time; None uses supported discovery or embedded metadata. |
None
|
drone_manifest_timezone
|
str | None
|
Timezone used to interpret manifest acquisition times; the default is UTC. |
'UTC'
|
require_solar_geometry
|
bool
|
Require scientifically usable solar geometry before correction rather than silently proceeding without it. |
True
|
extraction_mode
|
str | None
|
'full' writes pixel Parquet, 'polygon' requires polygons; None preserves the entry point's documented default extraction behavior. |
None
|
parquet_chunk_size
|
int
|
Positive pixel/window processing budget for bounded extraction; the default and interpretation follow the selected producer. |
2048
|
merge_extractions
|
bool
|
Explicit opt-in to legacy campaign-wide pixel-table merging; normal bulk consumers use separate completed flights. |
False
|
apply_translation
|
bool
|
Create separate Landsat-like application products using the reviewed coefficient registry; does not overwrite corrected native MicaSense. |
False
|
translation_coefficients
|
str | Path | None
|
Optional reviewed registry JSON path; None uses the packaged static coefficient set. |
None
|
translation_weighting
|
str | None
|
Optional reviewed weighting selection; normal production uses the predetermined site-balanced weighting. |
None
|
translation_strict
|
bool
|
Treat unsupported/flagged translation conditions as blocking rather than returning the configured non-strict status. |
False
|
landsat_qa
|
bool
|
Enable actual Landsat comparison QA for translated products; requires apply_translation=True and appropriate data/dependencies. |
False
|
landsat_product
|
str | Path | None
|
Optional existing actual Landsat product for independent comparison; None permits the documented search path. |
None
|
landsat_search_days
|
int
|
Nonnegative acquisition-date search radius in days for actual Landsat comparison. |
16
|
comparison_neon_product
|
str | Path | None
|
Optional independent NEON product for common-support comparison QA. |
None
|
raise_on_incomplete
|
bool
|
Raise DronePipelineIncompleteError when flights fail or are scientifically blocked; its results attribute retains structured status. |
True
|
solar_qa_timezone
|
str | None
|
Optional timezone override for solar-geometry QA; None follows the existing metadata/timezone resolution. |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Per-flight processed/reused/failed/blocked outcomes and QA/output paths; incomplete runs normally raise with this payload attached. |
Raises:
| Type | Description |
|---|---|
DroneCorrectionUnavailableError
|
If scientifically required correction inputs cannot be validated. |
DronePipelineIncompleteError
|
If any requested flight is incomplete and raise_on_incomplete is True; inspect the attached results. |
ValueError
|
If the supplied options, dimensions, support or provenance violate the input contract. |
Notes
extraction_mode="full" writes a full-pixel Parquet table from the
corrected drone ENVI product. "polygon" uses polygon_path and the
existing polygon extraction path. The default preserves historical
behavior: polygon mode when polygons are supplied, otherwise QA-only.
Per-flight extraction products remain separate by default;
merge_extractions=True opts into legacy campaign-wide pixel-table
materialization. Bulk analysis does not require that merge.
Translation is opt-in and consumes a versioned packaged registry by default,
or an explicitly supplied reviewed bulk artifact. The predetermined
production weighting is site-balanced. It creates separate Landsat-like
products; corrected native MicaSense is never overwritten.
By default an incomplete run raises :class:DronePipelineIncompleteError
with the structured result available as exc.results.
See Also
spectralbridge.pipelines.pipeline.process_one_flightline : Related source-derived API contract.
Examples:
Requires an existing supported source tree with usable spectral/spatial/solar metadata. Choose a separate output directory.
>>> from spectralbridge import run_drone_pipeline
>>> result = run_drone_pipeline(input_h5_dir=source_dir, output_dir=output_dir)
Explicitly exported constants and type aliases¶
These values describe package metadata, schemas or configuration; they are not observations from a production dataset.
| Name | Source expression |
|---|---|
DRONE_TARGET_BANDS |
{'blue': 444, 'green': 560, 'red': 650, 'nir': 862} |