FEMIC LidarBC Products
FHOPS consumes versioned FEMIC LidarBC product bundles. It does not run LiDAR discovery, materialization, terrain compilation, or canopy processing.
Bundle Contract
A FEMIC bundle contains manifest.json, provenance/selection.json, and
products/. FHOPS pins:
bundle_idandbundle_version;manifest_sha256;each product
sha256andrelative_path.
fhops.scenario.lidar.load_femic_lidar_bundle validates the manifest,
checksums, OGL-BC licence, native CRS, per-product resolution and vertical
datum, and source-tile membership.
Python Usage
from pathlib import Path
from fhops.scenario.lidar import (
bundle_pin,
load_femic_lidar_bundle,
summarize_femic_lidar_for_polygons,
)
bundle = load_femic_lidar_bundle(
Path("data/femic/lidarbc-2026.10.0"),
expected_bundle_id="lidarbc-995fb1f771f4d7fe",
)
pin = bundle_pin(bundle)
rows = summarize_femic_lidar_for_polygons(
bundle,
Path("data/blocks.gpkg"),
product="slope",
id_field="block_id",
)
Polygon summaries require fhops[lidar]. Polygon and product CRS must match;
there is no silent reprojection or resampling.
Scenario Pin and Support
A scenario can pin one or more bundle versions and record aggregated support evidence. Both sections are optional, so existing scenarios remain valid:
lidar_products:
- bundle_id: lidarbc-tfl6-2026.10
bundle_version: 2026.10.0-tfl6
manifest_sha256: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
licence_id: OGL-BC
manifest_path: lidarbc-tfl6-2026.10/manifest.json
lidar_support:
- support_unit: block # block | landing | road
support_id: B01
bundle_id: lidarbc-tfl6-2026.10
bundle_version: 2026.10.0-tfl6
product: slope
aggregation: area_weighted_mean
native_resolution_m: 1.0
support_area_m2: 12000.0
valid_pixels: 12000
slope_percent: 8.2
aspect_degrees: 135.0
roughness_m: 0.12
canopy_cover_percent: 62.0
canopy_height_m: 24.5
vertical_structure_index: 0.47
vertical_structure_class: multi_layer
provenance: FEMIC p79.8; 1 m slope/CHM; area-weighted within block polygon
Rules:
lidar_supportblock/landing ids must exist in the scenario; road ids must exist when aroad_constructiontable is present;support rows must reference a pinned
bundle_id/bundle_versionwhen pins are present;duplicate pins/support rows are rejected;
native resolution, aggregation, support area, valid pixels, and provenance record how the FEMIC summary was made; FHOPS does not compute or resample those values in P14.1.
Operability Report
After mapping support rows, report advisory system compatibility:
fhops scenario lidar operability scenarios/tfl6/scenario.yaml --json
The report classifies each block as ground, cable, or helicopter from block/landing
slope, roughness, and canopy evidence. It compares the scenario’s current harvest_system_id
with the terrain class, recommends a class-compatible registered system, and labels any fallback
source (block.ground_slope_percent or class-average roughness). Move-in, landing, and road cost
multipliers are advisory and are not applied by the solver in P14.4. Thresholds are planning
assumptions, not field-validated rules; see notes/p14_operability_validation.md.
Operator Workflow
Validate a delivered bundle without touching a scenario:
fhops scenario lidar validate data/femic/lidarbc-tfl6-2026.10
Pin it in a scenario AOI:
fhops scenario lidar register scenarios/tfl6/scenario.yaml \
data/femic/lidarbc-tfl6-2026.10 \
--expected-bundle-id lidarbc-995fb1f771f4d7fe
Registration validates the bundle and the scenario, checks that the scenario geo.crs matches
the bundle product CRS, records the block-GeoJSON AOI bbox when present, writes the bundle pin and
per-product checksums, and reloads the scenario through the normal loader before replacing it.
Use --dry-run to print the pin without writing. No source tile is downloaded or materialized.
Map native-resolution products to block and landing support:
fhops scenario lidar map scenarios/tfl6/scenario.yaml \
data/femic/lidarbc-tfl6-2026.10 \
--statistic mean \
--product slope_percent=slope \
--product canopy_height_m=chm
Known product names (slope, aspect, roughness, canopy_cover, canopy_height,
chm, vertical_structure) map automatically. Each output row keeps the product name,
native resolution, valid-pixel count, support area (for projected CRS), aggregation, and
provenance. Block/landing polygons must already match the product CRS; --roads-geojson adds
optional road support. Nothing is resampled. --dry-run prints rows without writing.
Phase Close-Out
P14 is complete. The end-to-end run validated the real bundle, mapped the public seven-block TFL 6
fixture (18 support rows, no warnings), classified 5 ground and 2 cable blocks, and returned a
200-iteration smoke-solve objective of 1434.9 with 1717.5 m³ production and zero sequencing
violations. WS4/FHOPS block slope/CHM parity was 0.0; the bundle is 12.8 MiB and the committed
fixture is 35.7 KiB. OGL-BC attribution and bundle/product checksums are preserved in
examples/lidar_tfl6/provenance.json.
Reports: notes/reports/p14-closeout.md and notes/reports/p14-validation.json. Operability
thresholds and cost context remain planning assumptions, not field-validated or calibrated
production constraints.