Tutorial: MicaSense Local Drone Workflow¶
This tutorial shows the supported path for local drone or MicaSense-style inputs. The workflow preserves drone-native provenance, discovers HDF5 files or reflectance TIFF packages recursively, converts TIFF sources into the working HDF5 contract when needed, writes ENVI products, extracts polygon Parquet tables when a polygon layer is provided, and renders QA artifacts.
There is no dedicated spectralbridge-micasense-to-landsat CLI today. Use the
Python API shown here.
Inputs¶
Prepare a folder containing local drone exports. The pipeline can start from either existing HDF5 files or reflectance TIFF packages.
Example HDF5 layout:
drone_h5_exports/
SPR1-06-28-23 ExportPackage/
*.h5
SPR2-06-28-23 ExportPackage/
*.h5
Example TIFF layout:
drone_tiff_exports/
SPR1-06-28-23 ExportPackage/
aligned_orthomosaic.tif
slope.tif
aspect.tif
sensor_zenith.tif
sensor_azimuth.tif
If you want polygon-level tables, also prepare a polygon layer supported by GeoPandas, such as GeoPackage or GeoJSON.
Input contract¶
For existing HDF5 inputs, SpectralBridge treats the local HDF5 export as the
authoritative drone input. Reflectance and ancillary rasters are expected to
already share the same spatial orientation and (lines, columns) footprint.
For TIFF-backed inputs, SpectralBridge now creates the per-flight
__working.h5 file itself before continuing through the existing drone
workflow. The TIFF bridge is intentionally strict:
- reflectance TIFFs must be multiband rasters
- ancillary TIFFs must already match the reflectance raster shape, transform, and CRS
- TIFF packages are expected to provide aligned sidecars for:
slopeaspectsensor_zenithorview_zenithsensor_azimuthorview_azimuth- solar geometry can come from:
- aligned
solar_zenith/solar_azimuthTIFFs, - scalar
tiff_solar_zenith_deg/tiff_solar_azimuth_degarguments passed torun_drone_pipeline, or - a flight manifest CSV passed as
drone_manifest_path
SpectralBridge includes the Macrosystems drone field manifest as bundled package
data. When drone_manifest_path is omitted, run_drone_pipeline() uses that
bundled manifest by default. Pass drone_manifest_path only when you want to
override the bundled file with a different campaign manifest.
If both an HDF5 file and a reflectance TIFF resolve to the same derived flight stem within one package, the existing HDF5 input takes precedence.
By default, TIFF-backed conversion uses the 10-band wavelength/FWHM vectors
from the Erick notebook workflow when the reflectance raster has 10 bands. For
other band counts, pass explicit tiff_wavelengths_nm and tiff_fwhm_nm
values.
Run the drone pipeline¶
from spectralbridge import run_drone_pipeline
results = run_drone_pipeline(
input_h5_dir="drone_inputs",
polygon_path="Datasets/niwot_aop_polygons_2023_12_8_23_analysis_ready_half_diam.gpkg",
output_dir="drone_outputs",
apply_topo=True,
apply_brdf=True,
use_ndvi_brdf_bins=False,
apply_brightness_adjustment=False,
)
Set polygon_path=None when you only need ENVI and QA products.
The bundled manifest is used only when explicit solar rasters or scalar solar angles are not supplied. Custom manifest CSVs must include:
PlotDay of data collectionMean Time of data collection (24 hr clock)
Derived flight stems such as AOP_GOLDHILL_20230814 match manifest rows such
as AOP_GOLDHILL. SpectralBridge uses the matched acquisition datetime plus
the reflectance TIFF CRS/transform to compute per-pixel Solar_Zenith_Angle
and Solar_Azimuth_Angle datasets in the generated working HDF5.
Manifest datetimes without timezone information are treated as UTC.
When apply_topo=True or apply_brdf=True, solar geometry is required by
default. Set require_solar_geometry=False only when you intentionally want to
allow an uncorrected fallback for incomplete inputs.
Each per-flight QA audit records:
solar_geometry_source:raster,scalar,manifest_computed, ormissingacquisition_datetime_used- solar zenith mean/min/max
- solar azimuth mean/min/max
If your TIFF source does not use the default 10-band Erick notebook spectral definition, also pass:
tiff_wavelengths_nm=[...]
tiff_fwhm_nm=[...]
Outputs¶
Each discovered flight gets its own output folder:
drone_outputs/
<flight_stem>/
<flight_stem>__working.h5
<flight_stem>__envi.img
<flight_stem>__envi.hdr
<flight_stem>__corrected.img
<flight_stem>__corrected.hdr
<flight_stem>__polygon_index.parquet
<flight_stem>__polygons.parquet
<flight_stem>__qa.png
<flight_stem>__qa.json
drone_merged.parquet
drone_qa_summary.json
Parquet remains the authoritative tabular output. CSV sidecars, when present in drone workflows, are convenience copies for external tools.
Inspect the run¶
from pathlib import Path
output_dir = Path("drone_outputs")
print(results["qa_summary_path"])
print(results["merged"])
for qa_png in output_dir.glob("*/*__qa.png"):
print(qa_png)
The QA JSON records whether requested topographic or BRDF corrections were applied, skipped because ancillary data were unavailable, or reverted because the corrected product failed quality checks.
Relation to Landsat harmonization¶
The local drone path does not invent NEON-style filenames and does not run the NEON download workflow. Landsat-style products for NEON flightlines are still generated by the standard sensor harmonization stage and use names such as:
*_landsat_tm_envi.img
*_landsat_oli_envi.img
*_micasense_envi.img
*_micasense_to_match_oli_oli2_envi.img
Those NEON outputs are documented in Outputs & file structure.