The pipeline starts from a single file of tree crowns. Either a GeoPackage (.gpkg) or an ESRI shapefile (.shp) works. Everything downstream goes through neoncrops.crown_io.read_crowns(), so if it loads cleanly there, the rest of the pipeline will accept it.
| Column | Type | Description |
|---|---|---|
individual |
string | Stable ID for the tree. Used as the per-tree key in dataset.csv. |
siteID |
string | NEON 4-letter site code (e.g. OSBS). Drives UTM zone lookup. |
| geometry | Polygon, MultiPolygon, Point, or MultiPoint | The crown shape, or a stem location. |
The file's CRS comes from the file itself (.prj for shapefiles, header for GeoPackage). Anything geopandas can read is fine. read_crowns reprojects the geometry to WGS84 (EPSG:4326) on load, so downstream code only ever sees one CRS regardless of what the file shipped in.
| Column | Type | Used for |
|---|---|---|
tile_easting, tile_northing |
int | NEON 1km tile SW corner. Auto-computed from the geometry centroid in the site's UTM zone if missing. |
taxonID |
string | Carried through to dataset.csv for downstream training. |
anno_year |
int | If present, the pipeline only crops this year's tiles. If absent, every requested year is tried. |
detection_method |
string | Free-form label (e.g. deepforest, fallback). Carried through to the crop log. |
height, score, crown_id |
various | Carried through unchanged. |
The loader sets a geometry_type column on each row:
- polygon (or multipolygon): cropped against the bounding box of the polygon.
- point (or multipoint): cropped against a square buffer applied at crop time, controlled by
--fallback_buffer_minrun_crops(default 2m, giving a 4x4m crop). Set this to match the field plot accuracy of your stem coordinates.
Mixed files work. A polygon row uses the polygon, a point row in the same file uses the buffer. No buffering happens at load time.
Shapefiles cap column names at 10 characters. The loader accepts the truncated names and renames them back:
| Truncated | Canonical |
|---|---|
tile_easti |
tile_easting |
tile_north |
tile_northing |
detection_ |
detection_method |
If you have other long column names you want preserved, GeoPackage avoids the issue.
Below: 30 OSBS crowns from tests/data/example_crowns.gpkg, plotted in the OSBS UTM zone. The dashed squares are the four 1km NEON tiles the crowns fall on. Tile origin labels show the (easting, northing) pair the loader writes into tile_easting/tile_northing. Six of the 30 are stem-fallback rows (red); the other 24 are real polygons (blue).
from neoncrops.crown_io import read_crowns
g = read_crowns("tests/data/example_crowns.gpkg")
print(g[["individual", "siteID", "tile_easting", "tile_northing", "geometry_type"]].head())Next step: feed this file into 02_tile_manifest.md to get the list of NEON tiles to download.
