Visualization#
TEEHR integrates with HoloViews/hvPlot and GeoViews for interactive visualization of timeseries and spatial data. This section demonstrates common visualization patterns for TEEHR evaluation results.
Note
This section is under development. Additional examples and interactive visualizations will be added in future releases.
Prerequisites#
TEEHR includes visualization dependencies (installed with the main package):
HoloViews/hvPlot: Interactive plotting for timeseries data
GeoViews: Geographic visualization with Bokeh backend
matplotlib: Static plotting support
import holoviews as hv
import hvplot.pandas
import geoviews as gv
from bokeh.io import output_notebook
# Enable notebook output
hv.extension('bokeh')
output_notebook()
Basic Timeseries Plot#
Plot observed vs. simulated timeseries for a single location:
import teehr
import hvplot.pandas
ev = teehr.LocalReadWriteEvaluation(dir_path="/path/to/evaluation")
# Get joined timeseries for a specific location
df = ev.joined_timeseries_view().filter(
"primary_location_id = 'usgs-01184000'"
).to_pandas()
# Plot primary (observed) vs secondary (simulated)
plot = df.hvplot.line(
x='value_time',
y=['primary_value', 'secondary_value'],
title='Streamflow: Observed vs. Simulated',
xlabel='Time',
ylabel='Streamflow (cfs)',
legend='top',
width=800,
height=400
)
plot
Forecast Timeseries#
Plot ensemble forecast with spread:
# Filter for forecast data with multiple members
df = ev.secondary_timeseries.filter(
"configuration_name = 'nwm30_medium_range'",
"primary_location_id = 'usgs-01184000'"
).to_pandas()
# Plot ensemble members
plot = df.hvplot.line(
x='value_time',
y='value',
by='reference_time',
title='Ensemble Forecast',
xlabel='Time',
ylabel='Streamflow (cfs)',
width=800,
height=400
)
plot
Basic Map#
Display locations with attributes:
import geoviews as gv
import geoviews.tile_sources as gts
gv.extension('bokeh')
ev = teehr.LocalReadWriteEvaluation(dir_path="/path/to/evaluation")
# Get locations as GeoDataFrame
gdf = ev.locations.to_geopandas()
# Create point layer
points = gv.Points(gdf).opts(
size=8,
color='blue',
tools=['hover'],
)
# Add basemap tiles
tiles = gts.OSM
# Combine layers
map_plot = tiles * points
map_plot.opts(width=700, height=500, title='Evaluation Locations')
Metrics on a Map#
Visualize performance metrics spatially:
import geoviews as gv
from bokeh.palettes import RdYlGn11
ev = teehr.LocalReadWriteEvaluation(dir_path="/path/to/evaluation")
# Calculate metrics with geometry
from teehr.metrics import DeterministicMetrics
metrics_gdf = ev.joined_timeseries_view().aggregate(
metrics=[DeterministicMetrics.KlingGuptaEfficiency()],
group_by=["primary_location_id"],
).to_geopandas()
# Create colored points based on KGE
points = gv.Points(
metrics_gdf,
kdims=['geometry'],
vdims=['kling_gupta_efficiency', 'primary_location_id']
).opts(
size=10,
color='kling_gupta_efficiency',
cmap='RdYlGn',
clim=(0, 1),
colorbar=True,
tools=['hover'],
)
# Add basemap
tiles = gv.tile_sources.OSM
map_plot = tiles * points
map_plot.opts(
width=700,
height=500,
title='Kling-Gupta Efficiency by Location'
)
Hydrograph Comparison#
Compare observed and simulated hydrographs with metrics overlay:
import holoviews as hv
import hvplot.pandas
ev = teehr.LocalReadWriteEvaluation(dir_path="/path/to/evaluation")
# Get timeseries
df = ev.joined_timeseries_view().filter(
"primary_location_id = 'usgs-01184000'",
"configuration_name = 'nwm30_retrospective'"
).to_pandas()
# Calculate metrics
from teehr.metrics import DeterministicMetrics
metrics = ev.joined_timeseries_view().filter(
"primary_location_id = 'usgs-01184000'",
"configuration_name = 'nwm30_retrospective'"
).aggregate(
metrics=[
DeterministicMetrics.KlingGuptaEfficiency(),
DeterministicMetrics.NashSutcliffeEfficiency(),
],
group_by=["primary_location_id"]
).to_pandas()
kge = metrics['kling_gupta_efficiency'].values[0]
nse = metrics['nash_sutcliffe_efficiency'].values[0]
# Create hydrograph plot
obs_line = df.hvplot.line(
x='value_time', y='primary_value',
label='Observed', color='blue', line_width=1.5
)
sim_line = df.hvplot.line(
x='value_time', y='secondary_value',
label='Simulated', color='red', line_width=1.5, alpha=0.7
)
# Add metrics as text annotation
title = f'Hydrograph Comparison | KGE: {kge:.3f}, NSE: {nse:.3f}'
plot = (obs_line * sim_line).opts(
title=title,
xlabel='Time',
ylabel='Streamflow (cfs)',
legend_position='top_right',
width=900,
height=400
)
plot
Additional Resources#
For more visualization examples, see:
Example notebooks demonstrating TEEHR visualizations are available in the Example Notebooks section.