Vegetation Phenology¶
Vegetation phenology analysis from MODIS products via NASA EarthData.
Requires NASA Earthdata credentials and pip install hyplan[phenology].
Vegetation phenology analysis for airborne remote sensing campaign planning.
Provides historical NDVI/EVI seasonality, LAI/FPAR, and phenological
transition dates from MODIS products via NASA EarthData. Requires
pip install hyplan[phenology] and NASA Earthdata credentials.
Supported products:
NDVI/EVI (MOD13A1/MYD13A1): 16-day composites at 500 m.
LAI/FPAR (MOD15A2H): 8-day composites at 500 m.
Phenology transitions (MCD12Q2): annual greenup, peak, senescence, and dormancy dates at 500 m.
- fetch_phenology(polygon_file, product='ndvi', year_start=2003, year_stop=2022, satellite='terra', spatial_mode='mean', source='appeears')[source]¶
Fetch historical vegetation phenology data for flight planning.
Two data sources are available:
AppEEARS (
source="appeears", default): Submits a point sample request to NASA’s AppEEARS service, which extracts time series server-side and returns only the values. Fast (minutes) but samples at polygon centroids rather than full spatial averaging.Granule download (
source="granules"): Downloads full MODIS HDF4 granules viaearthaccess, clips to each polygon, and computes spatial statistics locally. Slower (downloads GBs of data) but provides full spatial coverage includingpixel_statsmode.
Parameters¶
- polygon_filestr
Path to a GeoJSON or shapefile with a
Namecolumn.- productstr
One of
"ndvi","evi","lai","fpar","phenology". Default"ndvi".- year_startint
First year to include (default 2003).
- year_stopint
Last year to include, inclusive (default 2022).
- satellitestr
"terra","aqua", or"combined"(Terra + Aqua merged). Only applies to ndvi/evi. Default"terra".- spatial_modestr
"mean"for a single spatial mean per polygon per timestep, or"pixel_stats"for mean/std/min/max/count. Default"mean". Ignored forproduct="phenology"."pixel_stats"requiressource="granules".- sourcestr
"appeears"(default) for fast server-side extraction, or"granules"for full granule download with local processing.
Returns¶
- pd.DataFrame
Schema depends on product:
ndvi/evi/lai/fpar (spatial_mode=”mean”):
polygon_id,date,year,day_of_year,valuendvi/evi/lai/fpar (spatial_mode=”pixel_stats”):
polygon_id,date,year,day_of_year,value_mean,value_std,value_min,value_max,pixel_countphenology:
polygon_id,year,greenup_doy,midgreenup_doy,peak_doy,maturity_doy,midgreendown_doy,senescence_doy,dormancy_doy
Raises¶
- HyPlanValueError
If the polygon file lacks a
Namecolumn, product is not recognized, or satellite is invalid.- HyPlanRuntimeError
If required packages are missing or authentication fails.
- rtype:
DataFrame
- fetch_phenology_spatial(polygon_file, product='ndvi', year_start=2003, year_stop=2022, satellite='terra')[source]¶
Compute per-pixel time-averaged vegetation index for each polygon.
Returns a dictionary mapping polygon name to an xarray DataArray with dimensions
(latitude, longitude).- Return type:
dict[str, ‘xr.DataArray’]
- Parameters:
Parameters¶
- polygon_filestr
Path to a GeoJSON or shapefile with a
Namecolumn.- productstr
"ndvi"or"evi". Default"ndvi".- year_startint
First year (default 2003).
- year_stopint
Last year (default 2022).
- satellitestr
"terra","aqua", or"combined".
Returns¶
- dict[str, xarray.DataArray]
Polygon name to DataArray of mean vegetation index values.
- summarize_phenology_by_doy(df, window=None)[source]¶
Compute a typical-year vegetation index profile per polygon.
Averages VI values across all years for each
(polygon_id, day_of_year)pair, producing a single seasonal profile per polygon.- Return type:
DataFrame- Parameters:
df (DataFrame)
window (int | None)
Parameters¶
- dfpd.DataFrame
DataFrame with columns
polygon_id,year,day_of_year,value(as returned byfetch_phenology()withproduct="ndvi"/"evi"/"lai"/"fpar").- windowint or None
Optional rolling-mean window size (centered) applied to the per-polygon DOY mean.
Nonedisables smoothing.
Returns¶
- pd.DataFrame
Columns:
polygon_id,day_of_year,value_mean,value_std,value_count.
- extract_phenology_stages(df)[source]¶
Compute mean and std of phenological transition DOYs per polygon.
- Return type:
DataFrame- Parameters:
df (DataFrame)
Parameters¶
- dfpd.DataFrame
DataFrame from
fetch_phenology()withproduct="phenology". Must contain columnspolygon_id,year, and all stage DOY columns.
Returns¶
- pd.DataFrame
Columns:
polygon_idplus{stage}_meanand{stage}_stdfor each transition stage.
- plot_seasonal_profile(summary_df, ax=None, show_std=True, ylabel='NDVI', **kwargs)[source]¶
Line plot of mean vegetation index by DOY, one line per polygon.
Parameters¶
- summary_dfpd.DataFrame
Output of
summarize_phenology_by_doy().- axplt.Axes or None
Matplotlib Axes to plot on. Created if
None.- show_stdbool
If
True, draw a shaded +/-1 std-dev band.- ylabelstr
Y-axis label (e.g.
"NDVI","EVI","LAI").- **kwargs
Passed to
ax.plot().
Returns¶
plt.Axes
- plot_phenology_calendar(stages_df, ax=None)[source]¶
Gantt-style chart of phenological stages across months.
Each polygon gets a horizontal row with colored bars spanning from one transition to the next.
- Return type:
Axes- Parameters:
stages_df (DataFrame)
ax (Axes | None)
Parameters¶
- stages_dfpd.DataFrame
Output of
extract_phenology_stages().- axplt.Axes or None
Matplotlib Axes to plot on. Created if
None.
Returns¶
plt.Axes
- plot_year_over_year_heatmap(df, polygon_id=None, ax=None, cmap='YlGn', vmin=0.0, vmax=1.0)[source]¶
Heatmap of vegetation index by DOY (x) and year (y).
- Return type:
Axes- Parameters:
Parameters¶
- dfpd.DataFrame
DataFrame from
fetch_phenology()with columnspolygon_id,year,day_of_year,value.- polygon_idstr or None
Which polygon to plot. Required if multiple polygons exist. If
Noneand only one polygon exists, uses that one.- axplt.Axes or None
Matplotlib Axes to plot on. Created if
None.- cmapstr
Colormap name. Default
"YlGn".- vmin, vmaxfloat
Color scale bounds.
Returns¶
plt.Axes
- plot_cloud_phenology_combined(cloud_summary_df, phenology_summary_df, ax=None, layout='overlay')[source]¶
Combined cloud fraction and vegetation index seasonal plot.
- Return type:
Figure|Axes- Parameters:
cloud_summary_df (DataFrame)
phenology_summary_df (DataFrame)
ax (Axes | None)
layout (str)
Parameters¶
- cloud_summary_dfpd.DataFrame
Output of
summarize_cloud_fraction_by_doy().- phenology_summary_dfpd.DataFrame
Output of
summarize_phenology_by_doy().- axplt.Axes or None
For
"overlay"mode, the Axes to use (created ifNone). Ignored for"side_by_side".- layoutstr
"overlay"(twin y-axes) or"side_by_side"(two panels).
Returns¶
- plt.Axes or plt.Figure
plt.Axesfor"overlay",plt.Figurefor"side_by_side".