geeViz.outputLib.charts¶
Zonal Summary & Charting Library for GEE
geeViz.outputLib.charts provides a Python pipeline for running zonal statistics on ee.Image / ee.ImageCollection objects and producing Plotly charts (time series, bar, sankey). It mirrors the logic in the geeView JS frontend so that both human users and AI agents have a clean, efficient API for this common workflow.
Quick start:
>>> import geeViz.geeView as gv
>>> from geeViz.outputLib import charts as cl
>>> ee = gv.ee
>>> study_area = ee.Geometry.Polygon(
... [[[-106, 39.5], [-105, 39.5], [-105, 40.5], [-106, 40.5]]]
... )
>>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10")
>>> df, fig = cl.summarize_and_chart(
... lcms.select(['Land_Cover']),
... study_area,
... stacked=True,
... )
>>> print(df.to_markdown())
>>> fig.write_html("chart.html", include_plotlyjs="cdn")
See summarize_and_chart() for the full API and more examples.
Module Attributes
Valid chart type strings for |
Functions
|
Create a Plotly bar chart from a single-Image zonal stats DataFrame. |
|
Create a Plotly pie/donut chart from a single-Image zonal stats DataFrame. |
|
Create a subplot grid of pie/donut charts, one per feature. |
|
Create a grouped (or stacked) bar chart for multi-feature zonal stats. |
|
Create a subplot figure with one time-series chart per feature. |
|
Create a D3 Sankey diagram directly from transition data — no Plotly. |
|
Create a scatter plot of two bands across features. |
|
Create a Plotly time series chart from a zonal stats DataFrame. |
|
Determine whether the input geometry represents a single region or multiple. |
|
Detect the type of a GEE object and read its thematic class metadata. |
|
Render an HTML string to PNG bytes via headless Chrome/Edge screenshot. |
|
Parse continuous (mean/median/percentile/etc.) reduction results into a DataFrame. |
|
Parse frequency histogram reduction results into a DataFrame with class names as columns. |
|
Prepare a GEE object for reduction by stacking an ImageCollection into a single multi-band image. |
|
Build a Sankey diagram dataset from class transitions across time periods. |
|
Run |
|
Run |
|
Wrap sankey D3 HTML in an iframe for Jupyter notebook display. |
|
Return sankey HTML, accepting either a raw HTML string or legacy Plotly figure. |
|
Save a chart to an HTML file. |
|
Save a Plotly chart or D3 sankey HTML string as a PNG image. |
|
Capture a screenshot of a URL via headless Chrome using the DevTools Protocol (CDP). |
|
Run zonal statistics and produce a chart in one call. |
|
Truncate a class name preserving the end. |
|
Apply |
|
Compute zonal statistics for a GEE Image or ImageCollection over a geometry. |
- geeViz.outputLib.charts.CHART_TYPES = ['bar', 'stacked_bar', 'line', 'line+markers', 'stacked_line', 'stacked_line+markers', 'pie', 'donut', 'scatter', 'sankey']¶
Valid chart type strings for
chart_type/chart_typesparameters. Use these insummarize_and_chart(chart_type=...)orReport.add_section(chart_types=[...]).
- geeViz.outputLib.charts.truncate_class_name(name, max_length=30)[source]¶
Truncate a class name preserving the end.
If name is longer than max_length, keeps the beginning and end with
...in the middle (e.g."Grass-Forb-...Shrubs-Mix"). Roughly 2/3 of the budget goes to the start, 1/3 to the end.- Parameters:
name – The class name string.
max_length – Maximum allowed length.
Noneor0disables truncation. Default 30.
- Returns:
The (possibly truncated) name string.
- geeViz.outputLib.charts.truncate_class_names(names, max_length=30)[source]¶
Apply
truncate_class_name()to a list of names.- Parameters:
names – List of class name strings.
max_length – Maximum allowed length per name.
Noneor0disables truncation. Default 30.
- Returns:
New list with truncated names.
- geeViz.outputLib.charts.save_chart_html(fig, filename, include_plotlyjs='cdn', **kwargs)[source]¶
Save a chart to an HTML file.
Accepts either a Plotly
Figureor an HTML string (fromsummarize_and_chart(chart_type='sankey')).- Parameters:
fig –
plotly.graph_objects.Figureorstr(D3 sankey HTML).filename (str) – Output filename (e.g.
"chart.html").include_plotlyjs – How to include Plotly.js. Default
"cdn".
- Returns:
Path to the saved file.
- Return type:
str
- geeViz.outputLib.charts.screenshot_url(url, width=1280, height=900, wait_seconds=12)[source]¶
Capture a screenshot of a URL via headless Chrome using the DevTools Protocol (CDP).
Unlike the simple
--screenshotflag, this function connects to Chrome’s DevTools WebSocket and collects:JS console errors and warnings (
console.error/console.warn)Network failures (
net::ERR_*for any request)HTTP 4xx / 5xx responses on EE tile URLs (the most common map-layer bug)
Then takes a screenshot via
Page.captureScreenshotafterwait_secondsso that async tile requests have time to complete.- Parameters:
url (str) – URL to load (
http://orfile:///).width (int) – Viewport width in pixels.
height (int) – Viewport height in pixels.
wait_seconds (int) – Seconds to wait after page load before screenshotting. Longer values allow more EE tiles to load.
- Returns:
PNG bytes (or
Noneif screenshot failed / no browser found)List of console/network error strings for debugging
- Return type:
tuple[bytes | None, list[str]]
Requires
websocket-client(pip install websocket-client). Falls back to the simple--screenshotapproach (no console capture) ifwebsocket-clientis not installed.
- geeViz.outputLib.charts.html_to_png(html, width=900, height=1200, autocrop=True)[source]¶
Render an HTML string to PNG bytes via headless Chrome/Edge screenshot.
Uses a tall viewport and auto-crops empty space at the bottom so the output fits the actual content height.
- Parameters:
html (str) – Full HTML document string.
width (int) – Viewport width in pixels.
height (int) – Viewport height in pixels (tall default to avoid cutoff).
autocrop (bool) – Trim empty space from the bottom of the image.
- Returns:
PNG image bytes, or None if no browser is available.
- Return type:
bytes
- geeViz.outputLib.charts.save_chart_png(fig, filename, width=900, height=600, theme='dark', bg_color=None, font_color=None)[source]¶
Save a Plotly chart or D3 sankey HTML string as a PNG image.
Accepts either a Plotly
Figure(exported via kaleido) or an HTML string (fromsummarize_and_chart(chart_type='sankey')), which is rendered via headless Chrome/Edge screenshot.- Parameters:
fig –
plotly.graph_objects.Figureorstr(D3 sankey HTML).filename (str) – Output filename (e.g.
"chart.png").width (int) – Image width in pixels.
height (int) – Image height in pixels.
theme – Theme preset name or
Theme.bg_color – Background color override.
font_color – Font/text color override.
- Returns:
Path to the saved file.
- Return type:
str
Examples
>>> path = cl.save_chart_png(fig, "ndvi_trend.png") >>> path = cl.save_chart_png(sankey_html, "transitions.png")
- geeViz.outputLib.charts.sankey_to_html(fig, full_html=True, include_plotlyjs='cdn', renderer='d3', theme='dark', bg_color=None, font_color=None, hide_toolbar=False)[source]¶
Return sankey HTML, accepting either a raw HTML string or legacy Plotly figure.
Sankey charts from
summarize_and_chart(chart_type='sankey')are now returned as D3 HTML strings directly. This function is kept for backward compatibility — it passes HTML strings through unchanged.- Parameters:
fig – D3 HTML string (preferred) or legacy Plotly
Figure.full_html (bool) – Ignored for HTML strings.
include_plotlyjs – Ignored for HTML strings.
renderer (str) – Ignored (always D3).
theme – Theme preset for legacy Plotly figures.
bg_color – Background color override.
font_color – Font/text color override.
hide_toolbar (bool) – Hide the download button.
- Returns:
HTML string.
- Return type:
str
- geeViz.outputLib.charts.chart_multi_feature_timeseries(per_feature_dfs, colors=None, chart_type='line+markers', title='Time Series by Feature', x_label='Year', y_label=None, width=800, height=None, columns=2, legend_position='bottom', line_width=2, marker_size=5, max_x_tick_labels=10, max_y_tick_labels=None)[source]¶
Create a subplot figure with one time-series chart per feature.
Features are arranged in a grid with columns columns (default 2). Each subplot gets
heightpixels tall (total height scales with number of rows). The legend defaults to"bottom".- Parameters:
per_feature_dfs (dict) –
{feature_name: DataFrame}from_pivot_multi_feature_timeseries().colors (list, optional) – Hex color strings for each column.
chart_type (str, optional) –
"line+markers"(default),"line","bar","stacked_line","stacked_line+markers", or"stacked_bar".title (str, optional) – Overall chart title.
x_label (str, optional) – X-axis label.
y_label (str, optional) – Y-axis label.
width (int, optional) – Chart width in pixels.
height (int, optional) – Total chart height. When
Noneeach subplot gets 400 px.legend_position (dict or str, optional) – Legend layout. Default
"bottom".line_width (int or float, optional) – Line width in pixels. Defaults to
2.marker_size (int or float, optional) – Marker diameter in pixels. Defaults to
5.max_x_tick_labels (int, optional) – Maximum number of x-axis tick labels per subplot. Labels are thinned to every 2nd, 5th, 10th, etc. value when exceeded. Defaults to
10. Set toNoneor0to disable.max_y_tick_labels (int, optional) – Maximum number of y-axis tick labels per subplot. Uses Plotly’s
nticks. Defaults toNone(automatic).
- Returns:
plotly.graph_objects.Figure
- geeViz.outputLib.charts.get_obj_info(ee_obj, band_names=None, max_class_label_length=30)[source]¶
Detect the type of a GEE object and read its thematic class metadata.
- Parameters:
ee_obj (ee.Image or ee.ImageCollection) – The GEE object to inspect.
band_names (list or str, optional) – Override the band names to use. Accepts a list
['NDVI', 'NBR']or a comma-separated string'NDVI,NBR'. A single string is coerced to a one-element list.max_class_label_length (int, optional) – Maximum length for class name strings. Names longer than this are truncated with
...in the middle, preserving the end (e.g."Grass-Forb-...Shrubs-Mix"). Set toNoneor0to disable. Default 30.
- Returns:
- Keys
obj_type,band_names,is_thematic,class_info,size. class_infois{band_name: {class_values, class_names, class_palette}}
- Keys
- Return type:
dict
Examples
Inspect LCMS to see its thematic class metadata:
>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10") >>> info = cl.get_obj_info(lcms.select(['Land_Cover'])) >>> print(info['is_thematic']) True >>> print(info['class_info']['Land_Cover']['class_names']) ['Trees', 'Tall Shrubs & Trees Mix (AK Only)', ...]
- geeViz.outputLib.charts.detect_geometry_type(geometry)[source]¶
Determine whether the input geometry represents a single region or multiple.
- Parameters:
geometry – An
ee.Geometry,ee.Feature, oree.FeatureCollection.- Returns:
(geo_type, geometry)where geo_type is'single'or'multi',and geometry is an
ee.Geometry(single) oree.FeatureCollection(multi).
- Return type:
tuple
- geeViz.outputLib.charts.prepare_for_reduction(ee_obj, obj_info, x_axis_property='system:time_start', date_format='YYYY')[source]¶
Prepare a GEE object for reduction by stacking an ImageCollection into a single multi-band image.
- Parameters:
ee_obj –
ee.Imageoree.ImageCollection.obj_info (dict) – Output of
get_obj_info().x_axis_property (str, optional) – Property name to use for x-axis labels.
date_format (str, optional) – Earth Engine date format string (e.g.
'YYYY').
- Returns:
(stacked_image, stack_band_names, x_axis_labels)- Return type:
tuple
- geeViz.outputLib.charts.reduce_region(image, geometry, reducer, scale=30, crs=None, transform=None, tile_scale=4)[source]¶
Run
image.reduceRegionwith sensible defaults.If both
scaleandtransformare provided,scaleis set to None (transform takes precedence in GEE).- Parameters:
image (ee.Image) – The image to reduce.
geometry – An
ee.Geometryoree.Feature.reducer (ee.Reducer) – The reducer to apply.
scale (int, optional) – Pixel scale in meters. Defaults to 30.
crs (str, optional) – CRS string. Defaults to None.
transform (list, optional) – Affine transform. Defaults to None.
tile_scale (int, optional) – Tile scale for parallelism. Defaults to 4.
- Returns:
The reduction result dictionary.
- Return type:
dict
- geeViz.outputLib.charts.reduce_regions(image, features, reducer, scale=30, crs=None, transform=None, tile_scale=4)[source]¶
Run
image.reduceRegionsand return the result as a DataFrame.- Parameters:
image (ee.Image) – The image to reduce.
features (ee.FeatureCollection) – The zones.
reducer (ee.Reducer) – The reducer to apply.
scale (int, optional) – Pixel scale in meters. Defaults to 30.
crs (str, optional) – CRS string. Defaults to None.
transform (list, optional) – Affine transform. Defaults to None.
tile_scale (int, optional) – Tile scale for parallelism. Defaults to 4.
- Returns:
The reduction results.
- Return type:
pandas.DataFrame
- geeViz.outputLib.charts.parse_thematic_results(raw_dict, obj_info, x_axis_labels, area_format='Percentage', scale=30, split_str='----')[source]¶
Parse frequency histogram reduction results into a DataFrame with class names as columns.
- Parameters:
raw_dict (dict) – Output of
reduce_region()usingfrequencyHistogram.obj_info (dict) – Output of
get_obj_info().x_axis_labels (list) – Labels for the x-axis (e.g. years).
area_format (str, optional) – One of
'Percentage','Hectares','Acres','Pixels'.scale (int, optional) – Pixel scale used in reduction.
split_str (str, optional) – Band name separator.
- Returns:
- Rows are x-axis labels (or a single row for Image),
columns are class names.
- Return type:
pandas.DataFrame
- geeViz.outputLib.charts.parse_continuous_results(raw_dict, obj_info, x_axis_labels, split_str='----')[source]¶
Parse continuous (mean/median/percentile/etc.) reduction results into a DataFrame.
Handles single-output reducers (mean, median, sum) — one column per band — and multi-output reducers (percentile, minMax, mean+stdDev combine) — one column per band-output pair.
- Parameters:
raw_dict (dict) – Output of
reduce_region().obj_info (dict) – Output of
get_obj_info().x_axis_labels (list) – Labels for the x-axis.
split_str (str, optional) – Band name separator.
- Returns:
Rows are x-axis labels (or single row). For single-output reducers, columns are band names (
"NDVI"). For multi-output reducers, columns are"<band>_<output>"("TCC_p5","TCC_p50","TCC_p95").- Return type:
pandas.DataFrame
- geeViz.outputLib.charts.zonal_stats(ee_obj, geometry, band_names=None, reducer=None, scale=30, crs=None, transform=None, tile_scale=4, area_format='Percentage', x_axis_property='system:time_start', date_format='YYYY', include_masked_area=True)[source]¶
Compute zonal statistics for a GEE Image or ImageCollection over a geometry.
This is the main entry point for the data pipeline. It auto-detects the object type, whether data is thematic or continuous, the appropriate reducer, and the geometry type.
- Parameters:
ee_obj –
ee.Imageoree.ImageCollection.geometry –
ee.Geometry,ee.Feature, oree.FeatureCollection.band_names (list or str, optional) – Bands to include. Auto-detected if None. Accepts a list
['NDVI', 'NBR']or a comma-separated string'NDVI,NBR'.reducer (ee.Reducer, optional) – Override the auto-selected reducer.
scale (int, optional) – Pixel scale in meters. Defaults to 30.
crs (str, optional) – CRS string.
transform (list, optional) – Affine transform.
tile_scale (int, optional) – Tile scale for parallelism. Defaults to 4.
area_format (str, optional) – Area unit for thematic data. One of
'Percentage','Hectares','Acres','Pixels'.x_axis_property (str, optional) – Property for x-axis labels (ImageCollection).
date_format (str, optional) – Date format string for x-axis labels.
- Returns:
The zonal statistics table.
- Return type:
pandas.DataFrame
Examples
Get just the data (no chart) for an LCMS land cover time series:
>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> study_area = ee.Geometry.Polygon( ... [[[-106, 39.5], [-105, 39.5], [-105, 40.5], [-106, 40.5]]] ... ) >>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10") >>> df = cl.zonal_stats( ... lcms.select(['Land_Cover']), ... study_area, ... area_format='Percentage', ... ) >>> print(df.to_markdown())
Continuous data with a custom reducer:
>>> df = cl.zonal_stats( ... lcms.select(['Change_Raw_Probability_Slow_Loss']), ... study_area, ... reducer=ee.Reducer.mean(), ... )
- geeViz.outputLib.charts.prepare_sankey_data(ee_collection, band_name, transition_periods, class_info, geometry, scale=30, crs=None, transform=None, tile_scale=4, area_format='Percentage', min_percentage=0.2)[source]¶
Build a Sankey diagram dataset from class transitions across time periods.
For agent / LLM use: DO NOT call this function directly or copy its internal patterns (e.g.
.rename(["from"]), manual band extraction by year). Always callcl.summarize_and_chart(ic, geometry, band_names='<band>', chart_type='sankey', transition_periods=[year1, year2, year3], scale=100)which delegates here with the correct setup. This function is an internal helper exposed for advanced custom workflows only.For each consecutive pair of periods, this function:
Filters the collection to each period
Computes the mode for each period
Creates a transition image encoding
{from}0990{to}Runs
frequencyHistogramto count transitionsParses results into both a source/target/value DataFrame and a transition matrix DataFrame
- Parameters:
ee_collection (ee.ImageCollection) – The input collection.
band_name (str) – The thematic band to analyze.
transition_periods (list) – List of
[start_year, end_year]pairs.class_info (dict) – Class info dict for the band (from
get_obj_info()).geometry –
ee.Geometryoree.Feature.scale (int, optional) – Pixel scale in meters.
crs (str, optional) – CRS string.
transform (list, optional) – Affine transform.
tile_scale (int, optional) – Tile scale for parallelism.
area_format (str, optional) – Area unit.
min_percentage (float, optional) – Minimum percentage threshold for including a flow in the source-target table. The transition matrix always includes all observed transitions regardless of this threshold.
- Returns:
(sankey_df, matrix_dict)sankey_df (
pandas.DataFrame): Source-target-value table with columnssource,target,value,source_name,target_name,source_color,target_color,period. Flows belowmin_percentageare excluded.matrix_dict (
dict[str, pandas.DataFrame]): One transition matrix per consecutive period pair, keyed by"{from_period} → {to_period}". Each DataFrame has class names as both row and column labels, with values as converted counts.
- Return type:
tuple
Examples
Typically called via
summarize_and_chart(chart_type='sankey'), but can be used directly for custom sankey workflows:>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> study_area = ee.Geometry.Polygon( ... [[[-106, 39.5], [-105, 39.5], [-105, 40.5], [-106, 40.5]]] ... ) >>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10") >>> info = cl.get_obj_info(lcms.select(['Land_Use'])) >>> sankey_df, matrix_dict = cl.prepare_sankey_data( ... lcms.select(['Land_Use']), ... 'Land_Use', ... transition_periods=[[1990, 2000], [2000, 2010], [2010, 2023]], ... class_info=info['class_info']['Land_Use'], ... geometry=study_area, ... scale=30, ... ) >>> print(sankey_df.head().to_markdown()) >>> for label, mdf in matrix_dict.items(): ... print(f"\n{label}") ... print(mdf.to_markdown())
- geeViz.outputLib.charts.chart_time_series(df, colors=None, chart_type='line+markers', title='Time Series', x_label='Year', y_label=None, width=800, height=600, label_max_length=30, legend_position='right', line_width=2, marker_size=5, max_x_tick_labels=10, max_y_tick_labels=None)[source]¶
Create a Plotly time series chart from a zonal stats DataFrame.
- Parameters:
df (pandas.DataFrame) – Output of
zonal_stats()for an ImageCollection. Index = x-axis labels, columns = data series.colors (list, optional) – Hex color strings for each column.
chart_type (str, optional) –
"line+markers"(default),"line","bar","stacked_line","stacked_line+markers", or"stacked_bar".title (str, optional) – Chart title.
x_label (str, optional) – X-axis label.
y_label (str, optional) – Y-axis label.
width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
label_max_length (int, optional) – Max characters for legend labels.
legend_position (dict or str, optional) – Plotly legend layout dict (e.g.
{"orientation": "h", "x": 0.5, "y": -0.1}), or"right"/Nonefor the Plotly default.line_width (int or float, optional) – Line width in pixels for line/scatter traces. Defaults to
2.marker_size (int or float, optional) – Marker diameter in pixels for traces that include markers. Defaults to
5.max_x_tick_labels (int, optional) – Maximum number of x-axis tick labels to display. When the number of x values exceeds this, labels are thinned to every 2nd, 5th, 10th, etc. value. Defaults to
10. Set toNoneor0to disable.max_y_tick_labels (int, optional) – Maximum number of y-axis tick labels. Uses Plotly’s
nticks. Defaults toNone(automatic).
- Returns:
plotly.graph_objects.Figure
Examples
Build a time series chart from a zonal_stats DataFrame:
>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> study_area = ee.Geometry.Polygon( ... [[[-106, 39.5], [-105, 39.5], [-105, 40.5], [-106, 40.5]]] ... ) >>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10") >>> # Step 1: get the data >>> info = cl.get_obj_info(lcms.select(['Land_Cover'])) >>> df = cl.zonal_stats( ... lcms.select(['Land_Cover']), study_area, ... ) >>> # Step 2: chart it with class colors >>> colors = info['class_info']['Land_Cover']['class_palette'] >>> fig = cl.chart_time_series( ... df, colors=colors, ... title='LCMS Land Cover', ... y_label='% Area', ... ) >>> fig.show()
- geeViz.outputLib.charts.chart_bar(df, colors=None, title='Class Distribution', y_label=None, max_classes=30, chart_type='bar', width=800, height=600, legend_position='right')[source]¶
Create a Plotly bar chart from a single-Image zonal stats DataFrame.
Automatically chooses horizontal or vertical orientation based on label length.
- Parameters:
df (pandas.DataFrame) – Output of
zonal_stats()for a single Image. Single row, columns = class names.colors (list, optional) – Hex color strings for each bar.
title (str, optional) – Chart title.
y_label (str, optional) – Value axis label.
max_classes (int, optional) – Maximum number of classes to display.
width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
legend_position (dict or str, optional) – Plotly legend layout dict (e.g.
{"orientation": "h", "x": 0.5, "y": -0.1}), or"right"/Nonefor the Plotly default.
- Returns:
plotly.graph_objects.Figure
Examples
Bar chart of NLCD land cover for a single image:
>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> study_area = ee.Geometry.Polygon( ... [[[-106, 39.5], [-105, 39.5], [-105, 40.5], [-106, 40.5]]] ... ) >>> nlcd = ee.ImageCollection( ... "USGS/NLCD_RELEASES/2021_REL/NLCD" ... ).select(['landcover']).mode().set( ... ee.ImageCollection("USGS/NLCD_RELEASES/2021_REL/NLCD") ... .first().toDictionary() ... ) >>> info = cl.get_obj_info(nlcd) >>> df = cl.zonal_stats(nlcd, study_area) >>> colors = info['class_info']['landcover']['class_palette'] >>> fig = cl.chart_bar( ... df, colors=colors, title='NLCD Land Cover', ... ) >>> fig.show()
- geeViz.outputLib.charts.chart_donut(df, colors=None, title='Class Distribution', max_classes=30, width=800, height=600, legend_position='right', hole=0.45)[source]¶
Create a Plotly pie/donut chart from a single-Image zonal stats DataFrame.
Use
hole=0for a pie chart orhole=0.45(default) for a donut.Only valid for thematic (categorical) data from a single
ee.Image. RaisesValueErrorfor continuous data oree.ImageCollectioninputs.- Parameters:
df (pandas.DataFrame) – Output of
zonal_stats()for a single Image. Single row, columns = class names, values = area/%.colors (list, optional) – Hex color strings, one per class.
title (str, optional) – Chart title.
max_classes (int, optional) – Maximum number of classes to display. Smaller classes are grouped into “Other”. Defaults to
30.width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
legend_position (dict or str, optional) – Plotly legend dict or
"right"/"bottom".hole (float, optional) – Size of the centre hole (0–1). Defaults to
0.45.
- Returns:
plotly.graph_objects.Figure
- geeViz.outputLib.charts.chart_donut_multi_feature(df, colors=None, title='Class Distribution by Feature', max_classes=30, width=800, height=600, columns=2, legend_position='bottom', hole=0.45)[source]¶
Create a subplot grid of pie/donut charts, one per feature.
Use
hole=0for pie charts orhole=0.45(default) for donuts.For multi-feature
reduceRegionsoutput where the DataFrame index is the feature label and columns are class names.- Parameters:
df (pandas.DataFrame) – Output of
zonal_stats()withfeature_labelset. Index = feature names, columns = class names, values = area/%.colors (list, optional) – Hex color strings, one per class.
title (str, optional) – Overall chart title.
max_classes (int, optional) – Max classes per donut.
width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
columns (int, optional) – Number of subplot columns.
legend_position (dict or str, optional) – Legend position.
hole (float, optional) – Centre hole size.
- Returns:
plotly.graph_objects.Figure
- geeViz.outputLib.charts.chart_scatter(df, x_band, y_band, feature_label=None, title='Scatter Plot', width=800, height=600, legend_position='right', trendline=True, opacity=0.7, show_labels=None, thematic_col=None, class_names=None, class_palette=None, class_values=None)[source]¶
Create a scatter plot of two bands across features.
Each point represents one feature (e.g. a county, fire perimeter, or watershed). The x- and y-axes show the mean (or other reduced) value of two image bands over that feature.
When thematic_col is provided, points are colored by the thematic class value in that column, using the class palette and names from image properties.
- Parameters:
df (pandas.DataFrame) – DataFrame with at least two numeric columns for the x and y bands. Optionally a thematic_col column with integer class values.
x_band (str) – Column name for the x-axis.
y_band (str) – Column name for the y-axis.
feature_label (str, optional) – Name of the index (used in hover).
title (str, optional) – Chart title.
width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
legend_position (dict or str, optional) – Legend position.
trendline (bool, optional) – Draw a linear trendline. Defaults to
True.opacity (float, optional) – Point opacity (0-1). Lower values help visualize overlapping points. Defaults to
0.7.show_labels (bool, optional) – Label each point with the feature name. When
None(default), labels are shown only when the DataFrame has fewer than 30 rows.thematic_col (str, optional) – Column containing thematic class values used to color each point. Defaults to
None.class_names (list, optional) – Class name strings matching class_values.
class_palette (list, optional) – Hex color strings matching class_values.
class_values (list, optional) – Integer class values that map to class_names and class_palette.
- Returns:
plotly.graph_objects.Figure
- geeViz.outputLib.charts.chart_grouped_bar(df, colors=None, title='Zonal Summary by Feature', y_label=None, chart_type='bar', width=800, height=600, legend_position='right')[source]¶
Create a grouped (or stacked) bar chart for multi-feature zonal stats.
Each group on the x-axis is a feature (row) and each bar/segment within the group is a class (column). This is the natural chart type when
reduceRegionsreturns one row per zone.- Parameters:
df (pandas.DataFrame) – Rows = features (index used as labels), columns = class names, values = numeric area/percentage.
colors (list, optional) – Hex color strings, one per column (class).
title (str, optional) – Chart title.
y_label (str, optional) – Y-axis label.
stacked (bool, optional) – Stack bars instead of grouping. Defaults to False.
width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
legend_position (dict or str, optional) – Plotly legend layout dict (e.g.
{"orientation": "h", "x": 0.5, "y": -0.1}), or"right"/Nonefor the Plotly default.
- Returns:
plotly.graph_objects.Figure
Examples
Compare land cover across the 5 largest MTBS fire perimeters:
>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10") >>> fires = ee.FeatureCollection( ... "USFS/GTAC/MTBS/burned_area_boundaries/v1" ... ).sort("BurnBndAc", False).limit(5) >>> lc_mode = lcms.select(["Land_Cover"]).mode().set( ... lcms.first().toDictionary() ... ) >>> # summarize_and_chart handles reduceRegions + grouped bar: >>> df, fig = cl.summarize_and_chart( ... lc_mode, fires, ... feature_label="Incid_Name", ... title="Land Cover — 5 Largest Fires", ... stacked=True, width=800, ... ) >>> fig.show()
- geeViz.outputLib.charts.chart_sankey_d3(sankey_df, class_names, class_palette, transition_periods, title='Class Transitions', width=800, height=600, node_thickness=20, node_pad=15, opacity=0.9, theme='dark', bg_color=None, font_color=None, hide_toolbar=False)[source]¶
Create a D3 Sankey diagram directly from transition data — no Plotly.
Builds a self-contained HTML string with native SVG
linearGradientelements so each link fades from its source node color to its target node color. Usesd3-sankeyfor layout.This is the preferred rendering path for Sankey charts. Unlike
chart_sankey()(which builds a Plotly figure that must be post-processed bysankey_to_html()for gradients), this function goes straight from the rawsankey_dfto D3 HTML.- Parameters:
sankey_df (pandas.DataFrame) – Output of
prepare_sankey_data(). Columns:source,target,value,source_name,target_name,source_color,target_color.class_names (list) – List of class names.
class_palette (list) – List of hex color strings.
transition_periods (list) – Period list (for node labeling).
title (str, optional) – Chart title. Defaults to
"Class Transitions".width (int, optional) – Chart width in pixels.
height (int, optional) – Chart height in pixels.
node_thickness (int, optional) – Sankey node bar thickness.
node_pad (int, optional) – Padding between Sankey nodes.
opacity (float, optional) – Link opacity (0-1). Defaults to 0.9.
theme (str, optional) – Theme preset. Defaults to
"dark".bg_color (str, optional) – Background color override.
font_color (str, optional) – Font color override.
hide_toolbar (bool, optional) – Hide the download button.
- Returns:
Self-contained HTML string with embedded D3 Sankey chart.
- Return type:
str
Examples
>>> sankey_df, matrix_dict = cl.prepare_sankey_data( ... lcms.select(['Land_Use']), 'Land_Use', ... transition_periods=[1990, 2005, 2023], ... class_info=info['class_info'], geometry=study_area, ... ) >>> html = cl.chart_sankey_d3( ... sankey_df, info['class_info']['Land_Use']['class_names'], ... info['class_info']['Land_Use']['class_palette'], ... transition_periods=[1990, 2005, 2023], ... )
- geeViz.outputLib.charts.sankey_iframe(sankey_html, width=None, height=None)[source]¶
Wrap sankey D3 HTML in an iframe for Jupyter notebook display.
Jupyter sanitizes
<script>tags indisplay(HTML(...)), so D3 sankey charts must be embedded in an iframe. Uses adata:text/html;base64src for maximum compatibility across Jupyter environments (classic notebook, JupyterLab, VS Code).- Parameters:
sankey_html (str) – Full HTML string from
chart_sankey_d3()orsummarize_and_chart(chart_type='sankey').width (int, optional) – Iframe width in pixels. Auto-detected from the HTML when
None.height (int, optional) – Iframe height in pixels. Auto-detected from the HTML when
None.
- Returns:
HTML
<iframe>element suitable fordisplay(HTML(...)).- Return type:
str
Example
>>> from IPython.display import HTML, display >>> display(HTML(cl.sankey_iframe(sankey_html)))
- geeViz.outputLib.charts.summarize_and_chart(ee_obj, geometry=None, band_names=None, reducer=None, scale=30, crs=None, transform=None, tile_scale=4, area_format='Percentage', x_axis_property='system:time_start', date_format='YYYY', title=None, chart_type=None, sankey=False, transition_periods=None, sankey_band_name=None, min_percentage=0.2, palette=None, feature_label=None, width=800, height=600, opacity=0.9, legend_position='right', columns=2, include_masked_area=True, stacked=None, thematic_band_name=None, line_width=2, marker_size=5, class_visible=None, max_x_tick_labels=10, max_y_tick_labels=None, max_class_label_length=30, x_label=None, y_label=None, **_compat)[source]¶
Run zonal statistics and produce a chart in one call.
Orchestrates
zonal_stats()(orprepare_sankey_data()) and the appropriate chart function. The chart type is chosen automatically:ee.ImageCollection -> line chart (default
"line+markers").ee.Image -> bar chart (default
"bar").chart_type=”pie” -> pie chart (Image + thematic only).
chart_type=”donut” -> donut chart (pie with center hole; Image + thematic only).
chart_type=”scatter” -> scatter plot (Image + FeatureCollection only; uses 2 continuous bands as x/y axes, optionally colored by thematic_band_name).
chart_type=”sankey” -> Sankey transition diagram.
feature_label +
ee.FeatureCollection+ee.Image-> grouped bar or per-feature pie/donut chart.feature_label +
ee.FeatureCollection+ee.ImageCollection-> per-feature time series subplots.
- Parameters:
ee_obj –
ee.Imageoree.ImageCollection.geometry –
ee.Geometry,ee.Feature, oree.FeatureCollection.band_names (list or str, optional) – Bands to include. Accepts a list
['Land_Use']or a comma-separated string'Land_Use'. Auto-detected if None.reducer (ee.Reducer, optional) – Override the auto-selected reducer.
scale (int, optional) – Pixel scale in meters.
crs (str, optional) – CRS string.
transform (list, optional) – Affine transform.
tile_scale (int, optional) – Tile scale for parallelism.
area_format (str, optional) – Area unit for thematic data.
x_axis_property (str, optional) – Property for x-axis labels.
date_format (str, optional) – Date format string.
title (str, optional) – Chart title. Auto-generated if None.
chart_type (str, optional) – Chart type. One of
"bar","stacked_bar","pie"/"donut"(Image + thematic only),"scatter"(Image + FeatureCollection only),"sankey"(ImageCollection + thematic, requirestransition_periods),"histogram"(distribution of a continuous band; foree.Imageproduces a themed bar chart with bucket centers on x and counts on y, foree.ImageCollectionproduces a heatmap with time on x, bucket centers on y, and per-year percent as color — auto-routes a defaultee.Reducer.histogram(maxBuckets=50)when no reducer is given; passreducer=ee.Reducer.histogram(maxBuckets=N)for finer binning),"line","stacked_line","line+markers"(default for ImageCollection), or"stacked_line+markers". Defaults to"bar"for singleee.Image,"line+markers"foree.ImageCollection.stacked (bool, optional) – Deprecated — use
chart_typeinstead. WhenTrue, prepends"stacked_"tochart_type. Defaults toNone.sankey (bool, optional) – Deprecated — use
chart_type='sankey'instead. Still accepted for backward compatibility.transition_periods (list, optional) – Period list for Sankey.
sankey_band_name (str, optional) – Band for Sankey analysis.
min_percentage (float, optional) – Minimum percentage for Sankey flows.
palette (list, optional) – Hex color strings for each series/band. Overrides auto-detected class palette when provided.
feature_label (str, optional) – Property name to use as row labels when the geometry is a multi-feature
ee.FeatureCollection. Triggers thereduceRegionspath. Foree.Imageinput produces a grouped bar chart; foree.ImageCollectioninput produces per-feature time series subplots.width (int, optional) – Chart width in pixels (per cell for multi-feature subplots).
height (int, optional) – Chart height in pixels (per cell for multi-feature subplots).
opacity (float, optional) – Opacity for Sankey nodes and links (0-1). Defaults to 0.9.
legend_position (dict or str, optional) – Plotly legend layout dict for non-Sankey charts (e.g.
{"orientation": "h", "x": 0.5, "y": -0.1}), or"right"/Nonefor the Plotly default.columns (int, optional) – Number of subplot columns for multi-feature time series. Total width/height scale to
n_cols * width/n_rows * height. Defaults to 2.include_masked_area (bool, optional) – When
True(default) and using the histogram reducer, unmasked pixels with value 0 are included so percentages are relative to the total area, not just the unmasked portion. The sentinel class is removed from results.thematic_band_name (str, optional) – For
chart_type="scatter"only. Name of a thematic band in the image whose mode value per feature is used to color each scatter point. The image must carry{band}_class_values,{band}_class_names, and{band}_class_paletteproperties for the colors and legend entries. Defaults toNone(single-color points).line_width (int or float, optional) – Line width in pixels for time series traces. Defaults to
2.marker_size (int or float, optional) – Marker diameter in pixels for time series traces. Defaults to
5.class_visible (dict, optional) –
Per-class visibility control. Maps class names to booleans. Classes set to
Falseare toggled off in the chart legend (set to"legendonly"). The traces remain in the figure — users can click the legend to re-enable them. Useful for hiding background, no-data, or stable classes by default. Works for all chart paths including single-geometry, multi-feature time series subplots, and multi-feature bar/pie/donut charts. Example:class_visible={ "Non-Processing Area Mask": False, "Stable": False, "Background": False, }
When
None(default), all classes are visible.max_x_tick_labels (int, optional) – Maximum number of x-axis tick labels. When the data has more x values than this, tick labels are thinned to every 2nd, 5th, 10th, etc. value. Defaults to
10. Set toNoneor0to show all.max_y_tick_labels (int, optional) – Maximum number of y-axis tick labels. Passed as Plotly’s
nticks. Defaults toNone(Plotly automatic).max_class_label_length (int, optional) – Maximum length for class name strings in legends and labels. Longer names are truncated with
...in the middle, preserving the end. Set toNoneor0to disable. Default 30.
- Returns:
Depends on chart type:
Standard (single geometry):
{"df": DataFrame, "chart": Figure}Sankey:
{"df": sankey_df, "chart": sankey_html, "matrix": matrix_dict}wheresankey_htmlis a D3 HTML string (display withdisplay(HTML(cl.sankey_iframe(sankey_html)))), andmatrix_dictis{period_label: DataFrame}Multi-feature + ee.Image (bar/pie/donut):
{"df": DataFrame, "chart": Figure}Multi-feature + ee.ImageCollection:
{"df": dict, "chart": Figure}wheredictis{feature_name: DataFrame}Scatter:
{"df": DataFrame, "chart": Figure}where the DataFrame has columns for the two bands (and optionally the thematic band)
- Return type:
dict
Examples
Stacked time series of thematic land cover (auto-detects class properties from the image collection):
>>> import geeViz.geeView as gv >>> from geeViz.outputLib import charts as cl >>> ee = gv.ee >>> study_area = ee.Geometry.Polygon( ... [[[-106, 39.5], [-105, 39.5], [-105, 40.5], [-106, 40.5]]] ... ) >>> lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2024-10") >>> result = cl.summarize_and_chart( ... lcms.select(['Land_Cover']), ... study_area, ... title='LCMS Land Cover', ... stacked=True, ... ) >>> print(result["df"].to_markdown()) >>> result["chart"].write_html("lcms_land_cover.html", include_plotlyjs="cdn")
Sankey transition diagram with D3 gradient-colored links:
>>> result = cl.summarize_and_chart( ... lcms.select(['Land_Use']), ... study_area, ... chart_type='sankey', ... transition_periods=[1990, 2000, 2024], ... sankey_band_name='Land_Use', ... min_percentage=0.5, ... ) >>> # In notebooks: display(HTML(cl.sankey_iframe(result["chart"]))) >>> # Save to file: >>> cl.save_chart_html(result["chart"], "land_use_transitions.html")
Bar chart for a single image at a point (use
ee.Reducer.first()):>>> nlcd = ee.Image("USGS/NLCD_RELEASES/2021_REL/NLCD/2021") >>> point = ee.Geometry.Point([-104.99, 39.74]) >>> result = cl.summarize_and_chart( ... nlcd, ... point, ... reducer=ee.Reducer.first(), ... scale=30, ... title='NLCD Land Cover', ... )
Continuous time series (non-thematic bands auto-select
ee.Reducer.mean()):>>> import geeViz.getImagesLib as gil >>> composites = gil.getLandsatWrapper( ... study_area, 2000, 2024 ... )['composites'] >>> result = cl.summarize_and_chart( ... composites, ... study_area, ... band_names=['nir', 'swir1', 'swir2'], ... title='Spectral Band Means', ... palette=['D0D', '0DD', 'DD0'], ... )
Grouped bar chart comparing multiple features (uses reduceRegions internally):
>>> fires = ee.FeatureCollection( ... "USFS/GTAC/MTBS/burned_area_boundaries/v1" ... ) >>> top5 = fires.sort("BurnBndAc", False).limit(5) >>> lc_mode = lcms.select(["Land_Cover"]).mode().set( ... lcms.first().toDictionary() ... ) >>> result = cl.summarize_and_chart( ... lc_mode, ... top5, ... feature_label="Incid_Name", ... title="Land Cover — 5 Largest MTBS Fires", ... stacked=True, ... width=800, ... )
Thematic data without class properties — force frequencyHistogram or set properties on-the-fly:
>>> lcpri = ee.ImageCollection( ... "projects/sat-io/open-datasets/LCMAP/LCPRI" ... ).select(['b1'], ['LC']) >>> # Force thematic (class values used as labels): >>> result = cl.summarize_and_chart( ... lcpri, ... study_area, ... reducer=ee.Reducer.frequencyHistogram(), ... title='LCMAP LC Primary', ... ) >>> # Or set properties for proper names and colors: >>> lcpri_named = lcpri.map(lambda img: img.set({ ... 'LC_class_values': list(range(1, 10)), ... 'LC_class_names': ['Developed', 'Cropland', 'Grass/Shrub', ... 'Tree Cover', 'Water', 'Wetlands', 'Ice/Snow', ... 'Barren', 'Class Change'], ... 'LC_class_palette': ['E60000', 'A87000', 'E3E3C2', '1D6330', ... '476BA1', 'BAD9EB', 'FFFFFF', 'B3B0A3', 'A201FF'], ... })) >>> result = cl.summarize_and_chart( ... lcpri_named, study_area, stacked=True, ... )
Switch area format to hectares or acres:
>>> result_ha = cl.summarize_and_chart( ... lcms.select(['Land_Cover']), ... study_area, ... area_format='Hectares', ... title='LCMS Land Cover (Hectares)', ... )