geeViz.outputLib.reports

Generate reports from Earth Engine data with LLM-powered narratives.

geeViz.outputLib.reports provides a Report class that combines chartingLib.summarize_and_chart() results, thumbLib thumbnails, and Gemini-generated narratives into styled HTML or Markdown reports.

All Earth Engine data requests (charts, tables, thumbnails, GIFs) and LLM narratives for every section are executed in parallel using concurrent.futures. Only the executive summary waits for all sections to finish before it is generated.

Layouts

  • "report" (default) — traditional multi-page portrait layout, sections flow vertically.

  • "poster" — landscape multi-column layout, designed for large-format printing or screen display. Sections tile into a responsive grid.

Themes

Two built-in themes match the geeView color palette:

  • "dark" (default) — deep brown/black background with warm gray text

  • "light" — white background with deep brown text

Example:

import geeViz.geeView as gv
from geeViz.outputLib import reports as rl

ee = gv.ee
report = rl.Report(
    title="Wasatch Front Assessment",
    theme="dark",
    layout="poster",       # landscape multi-column
)
report.header_text = "An analysis of land cover and fire trends."

report.add_section(
    ee_obj=lcms.select(['Land_Cover']),
    geometry=counties,
    title="LCMS Land Cover",
    stacked=True,
    scale=60,
)

# PDF with static chart images
report.generate(format="pdf", output_path="report.pdf")

# HTML (interactive charts)
report.generate(format="html", output_path="report.html")

Classes

Report([title, model, api_key, prompt, ...])

Build and generate reports from Earth Engine data.

Exceptions

ReportGenerationError(errors[, ...])

Raised by Report.generate() when one or more sections failed during data / thumbnail / narrative computation and strict=True (the default).

exception geeViz.outputLib.reports.ReportGenerationError(errors: dict, succeeded_sections: list | None = None, html: str | None = None)[source]

Bases: RuntimeError

Raised by Report.generate() when one or more sections failed during data / thumbnail / narrative computation and strict=True (the default).

Prior behavior — errors were caught per-section and injected as red boxes INSIDE the rendered report. That’s fine for a human reviewer who reads the final HTML, but for an agent calling rl.build_report(...).generate() inside run_code the final HTML looks like a normal string — the agent has no cheap way to tell “one section broke, I should debug and retry” apart from “everything worked”. Raising surfaces the failures the same way any other Python exception would, so the agent’s normal error-handling loop kicks in.

errors

Section title -> error string. Includes executive-summary errors as "__summary__" if present.

Type:

dict[str, str]

failed_sections

Section titles that failed, in the order they were added. Convenience for logging.

Type:

list[str]

succeeded_sections

Section titles that completed without error. Included so an operator (or the agent) can see at a glance “3 of 5 sections finished; 2 broke” instead of just the failure list. Excludes the executive summary.

Type:

list[str]

summary

Multi-line human-readable “X succeeded, Y failed” block with a ✓/✗ per section title. Attached both as this attribute and prepended to str(err) so it lands in tracebacks by default.

Type:

str

html

The report content that WOULD have been written to disk. Non-strict callers can pass strict=False to receive this via the normal return path; strict callers can still read it off the exception if they want to inspect the partial output before retrying.

Type:

str | None

class geeViz.outputLib.reports.Report(title='Report', model='gemini-3-flash-preview', api_key=None, prompt=None, header_text=None, header_icon=None, theme='dark', layout='report', tone='neutral', max_workers=6)[source]

Bases: object

Build and generate reports from Earth Engine data.

Parameters:
  • title (str) – Report title.

  • model (str) – Gemini model name. Default "gemini-3-flash-preview".

  • api_key (str, optional) – Google API key. If not provided, loaded from the GEMINI_API_KEY environment variable (via .env).

  • prompt (str, optional) – Additional guidance for the executive summary.

  • header_text (str, optional) – Introductory text shown below the title.

  • header_icon (str, optional) – Path to a PNG/JPG image for the report header icon. If None, uses the built-in geeViz logo (theme-aware). Pass False to suppress the icon entirely.

  • theme (str) – Color theme — "dark" or "light". Default "dark".

  • layout (str) – Layout mode — "report" (portrait, vertical flow) or "poster" (landscape, multi-column grid). Default "report".

  • tone (str) – Narrative tone for LLM-generated text. Built-in options: "neutral" (default) — data-driven, no superlatives or narrative; "informative" — accessible, explains significance; "technical" — formal, precise terminology. Can also be a custom string with tone instructions.

  • max_workers (int) – Thread pool size for parallel EE requests. Default 6.

Example:

report = Report(title="My Analysis", theme="light", layout="report")
report.add_section(ee_obj=lcms, geometry=area, title="Land Cover")
html = report.generate(format="html", output_path="report.html")
add_section(ee_obj, geometry, title='Section', prompt=None, generate_table=True, generate_chart=True, thumb_format='png', chart_types=None, **kwargs)[source]

Add a data section to the report.

Parameters:
  • ee_objee.Image or ee.ImageCollection to summarize.

  • geometryee.Geometry, ee.Feature, or ee.FeatureCollection — the AOI. Applied both as the reduceRegion boundary and as the thumbnail clip region.

  • title (str) – Section heading. Also used as the executive-summary anchor. Default "Section".

  • prompt (str, optional) – Per-section LLM guidance appended to the report-level prompt when generating the narrative. Use to nudge tone, focal metric, or comparison years.

  • generate_table (bool) – Include the data table under the chart. Default True.

  • generate_chart (bool) – Include the chart. Default True.

  • thumb_format (str or None) –

    Thumbnail image format. Default "png".

    • "png" — single composite thumbnail (works for both ee.Image and ee.ImageCollection).

    • "gif" — animated GIF with per-frame date labels (ee.ImageCollection only).

    • "filmstrip" — grid of individual time-step frames (ee.ImageCollection only). Used by PDF export.

    • None or False — no thumbnail.

  • chart_types (list[str] | str | None) –

    Which charts to render. Accepts a list, a single string, or a comma-delimited string. Each entry maps to a summarize_and_chart(chart_type=...) call. Valid: "bar", "stacked_bar", "line+markers", "stacked_line+markers", "donut", "scatter", "sankey". When "sankey" is in the list, the sankey, transition_periods, sankey_band_name, and min_percentage kwargs feed that chart. Empty / None auto-detects one chart type. Recommended max length: 3.

    Examples:

    chart_types="sankey"
    chart_types="sankey,bar"
    chart_types=["line+markers"]
    

  • **kwargs

    All other keyword arguments. Params prefixed thumb_ are extracted and forwarded to thumbLib; everything else goes to chartingLib.summarize_and_chart().

    Thumbnail kwargs (all optional):

    • thumb_viz_params (dict): Viz dict, same shape as Map.addLayer — e.g. {'autoViz': True, 'canAreaChart': True} or {'min': 0, 'max': 1, 'palette': ['red','green']}. Autoviz picks up class props (<band>_class_values / _names / _palette).

    • thumb_band_name (str): Which band to render when ee_obj has multiple bands.

    • thumb_dimensions (int | str): Output pixel size — 512 or "1024x768". Default 512.

    • thumb_crs (str): Reprojection CRS for the thumbnail, e.g. "EPSG:32612". Default lets EE pick from the first pixel — which yields lat/lon for global datasets and can look rotated for high-latitude AOIs. Set an appropriate UTM zone (or the AOI’s native CRS) to keep the frame upright.

    • thumb_transform (list): Custom affine transform when thumb_crs is set. Advanced.

    • thumb_geometry (ee.Geometry): Override clip region. Defaults to the section geometry.

    • thumb_bg_color (str): Background hex.

    • thumb_fps (int): GIF frames-per-second. Default 2. Bare alias: fps=.

    • thumb_max_frames (int): Cap frames for gif/filmstrip when the collection is long. Bare alias: max_frames=.

    • thumb_columns (int): Filmstrip grid width. Bare alias: columns=.

    • thumb_burn_in_date (bool): Overlay date label on gif frames. Bare alias: burn_in_date=.

    • thumb_date_format (str): strftime format for burned-in dates (gif/filmstrip). Default "%Y".

    • thumb_date_position (str): "tl" | "tr" | "bl" | "br" — corner for the burned-in date. Bare alias: date_position=.

    • burn_in_legend (bool): Draw the autoviz legend into the thumbnail canvas.

    • legend_scale (float): Scale factor for the burned-in legend.

    Chart / summarize kwargs (forwarded verbatim, examples):

    • scale (int): reduceRegion pixel scale (metres).

    • feature_label (str): FeatureCollection property to label bars/donut wedges with.

    • stacked (bool): Stack multi-series charts.

    • sankey (bool): Enable sankey rendering.

    • transition_periods (list[list[str]]): For sankey charts, pairs of ISO dates defining transitions.

    • sankey_band_name (str): Band to sankey on when ee_obj is multi-band.

    • min_percentage (float): Minimum node/link % to render in sankey — below this collapses to “Other”.

    • max_classes (int): Cap categorical classes on bar/donut/stacked charts.

    • areaChartParams (dict): Same shape as viz-time areaChartParams — {'shouldUnmask': True, 'unmaskValue': 0} etc.

    See geeViz.chartingLib.summarize_and_chart and geeViz.outputLib.thumbs for the full surface.

Returns:

self (for method chaining).

Return type:

Report

property errors

Dict of per-section (and executive-summary) errors from the most recent generate() call.

Empty dict when everything succeeded — non-empty iff generate(strict=False) finished with at least one failure. strict=True callers get the same dict off ReportGenerationError.errors, so this property is primarily useful when you deliberately opted out of strict mode and now want to poll status before deciding what to do.

Returns:

Section title -> "ErrorType: message". The executive-summary failure key is "__summary__".

Return type:

dict[str, str]

metadata()[source]

Return a summary DataFrame describing each section’s generated outputs.

Each row corresponds to one section. Columns include the section title, what was requested, what was produced, data dimensions, and any errors. Call this after generate() to inspect results.

Returns:

pandas.DataFrame with one row per section.

generate(format='html', output_path=None, strict=True)[source]

Generate the report.

All section data (charts, tables, thumbnails, GIFs) and LLM narratives are computed in parallel. Only the executive summary waits for all sections to finish first.

Parameters:
  • format (str) – Output format — "html", "md", or "pdf". PDF uses kaleido to render charts as static PNG images and pdfkit/wkhtmltopdf for the final conversion. If wkhtmltopdf is not installed, a print-ready HTML file with @page CSS directives is generated instead (open in a browser and Print → Save as PDF).

  • output_path (str, optional) – File path to write. If None, returns the content as a string (except for PDF which always requires a path).

  • strict (bool, default True) –

    When True, raise ReportGenerationError if any section (or the executive summary) recorded an error during compute. The exception carries per-section error details AND the partial HTML so callers can inspect what would have been written.

    When False, keep the legacy silent-partial behavior — errors get inlined into the report as red boxes and nothing is raised. Use strict=False when you want a “best-effort” report for a human reviewer and are OK seeing errors embedded in the output.

    Agents driving report generation via run_code should keep the default. The raised exception makes report failures look like any other Python error in their normal debug loop, instead of a silent partial success.

Returns:

The report content (or the file path if output_path given).

Return type:

str

Raises:

ReportGenerationError – If strict=True and any section (or the summary) errored. Inspect .errors for the per-section detail and .html for the partial content.