Interactive Visualization
This tutorial demonstrates the interactive visualization tools in opensoundscape.visualization. These tools are designed for use in Jupyter or VS Code notebooks and provide:
``inspect``: Display a grid of spectrograms with click-to-play audio
``annotate``: Like
inspect, but with toggle buttons to label clips in-place``explore_features``: Interactive scatter plot that shows spectrograms for selected points
``explore_histogram``: Interactive histogram with per-label toggles and audio inspection
Requirements
These functions require the optional viz dependencies:
pip install opensoundscape[viz]
This installs ipywidgets and plotly.
[1]:
# if this is a Google Colab notebook, install opensoundscape in the runtime environment
if 'google.colab' in str(get_ipython()):
%pip install "opensoundscape[viz]"
Setup
Download a sample audio file and create a DataFrame of clips to work with.
[ ]:
from opensoundscape import Audio
from opensoundscape.visualization import (
inspect,
annotate,
explore_features,
explore_histogram,
)
import opensoundscape as opso
import numpy as np
import pandas as pd
from pathlib import Path
[3]:
# Download a 60-second birdsong recording
url = "https://tinyurl.com/birds60s"
audio = Audio.from_url(url)
# Save locally so visualization functions can load clips by file path
audio_path = Path("demo_audio.wav")
audio.save(audio_path)
print(f"Audio duration: {audio.duration:.1f}s, sample rate: {audio.sample_rate} Hz")
Audio duration: 60.0s, sample rate: 32000 Hz
[ ]:
# Create a DataFrame of 3-second clips spanning the recording in 1-second steps
clip_df = opso.utils.make_clip_df(audio_path, clip_duration=3.0, clip_overlap=2.0)
clip_df.head()
| file | start_time | end_time |
|---|---|---|
| demo_audio.wav | 0.0 | 3.0 |
| 1.0 | 4.0 | |
| 2.0 | 5.0 | |
| 3.0 | 6.0 | |
| 4.0 | 7.0 |
inspect: View and listen to clips
inspect displays a grid of spectrograms. Click any spectrogram to play its audio.
[ ]:
widget = inspect(
clip_df,
N=10,
bandpass_range=(500, 10000),
cell_width=180,
cell_height=150,
)
annotate: Label clips interactively
annotate displays spectrograms with toggle buttons below each clip. Clicking a button sets clip_df.at[row_index, button_name] = True; clicking again sets it to None. The DataFrame is modified in-place.
[ ]:
clips_to_label = clip_df.reset_index().sample(5)
widget = annotate(
clips_to_label,
annotation_buttons=["Wood Thrush", "Black-and-White Warbler"],
N=8,
bandpass_range=(500, 10000),
dB_range=(-50, 0),
)
[11]:
# After toggling some buttons above, check the annotations
clips_to_label.head()
[11]:
| file | start_time | end_time | Wood Thrush | Black-and-White Warbler | |
|---|---|---|---|---|---|
| 47 | demo_audio.wav | 47.0 | 50.0 | None | None |
| 22 | demo_audio.wav | 22.0 | 25.0 | None | None |
| 20 | demo_audio.wav | 20.0 | 23.0 | None | None |
| 4 | demo_audio.wav | 4.0 | 7.0 | True | None |
| 26 | demo_audio.wav | 26.0 | 29.0 | True | None |
Generate synthetic features for demo
For explore_features and explore_histogram, we need a DataFrame with numeric feature columns, scores, and category labels. We generate random values here for demonstration.
[12]:
np.random.seed(42)
# Add random 2D features (e.g. from UMAP or PCA of audio embeddings)
clip_df["feature_x"] = np.random.randn(len(clip_df))
clip_df["feature_y"] = np.random.randn(len(clip_df))
# Add a random score (e.g. classifier confidence)
clip_df["score"] = np.random.uniform(0, 1, len(clip_df))
# Add a random category label
clip_df["category"] = np.random.choice(["song", "call", "noise"], size=len(clip_df))
clip_df.head()
[12]:
| feature_x | feature_y | score | category | |||
|---|---|---|---|---|---|---|
| file | start_time | end_time | ||||
| demo_audio.wav | 0.0 | 3.0 | 0.496714 | -0.479174 | 0.237638 | noise |
| 1.0 | 4.0 | -0.138264 | -0.185659 | 0.728216 | noise | |
| 2.0 | 5.0 | 0.647689 | -1.106335 | 0.367783 | song | |
| 3.0 | 6.0 | 1.523030 | -1.196207 | 0.632306 | song | |
| 4.0 | 7.0 | -0.234153 | 0.812526 | 0.633530 | noise |
explore_features: Interactive scatter plot
explore_features shows a Plotly scatter plot of your data. Use box select or lasso select to highlight points, and spectrograms for the selected clips will appear below the plot.
Use the color_col argument to color points by a categorical column.
[ ]:
fw = explore_features(
clip_df,
x_col="feature_x",
y_col="feature_y",
color_col="category",
# kwargs below are passed to inspect() for selected points
N=6,
bandpass_range=(500, 10000),
cell_width=150,
cell_height=120,
)
explore_histogram: Interactive histogram
explore_histogram displays overlaid histograms of a numeric column, split by a label column. Each label gets a color-matched toggle button to show/hide its histogram. Click “Inspect random selection” to view spectrograms of clips in the current x-axis range.
[ ]:
fw = explore_histogram(
clip_df,
value_col="score",
label_col="category",
bins=15,
# kwargs below are passed to inspect()
N=6,
bandpass_range=(500, 10000),
cell_width=150,
cell_height=120,
)
Clean up
Uncomment and run this cell to remove the temporary audio file created for this tutorial.
[ ]:
# audio_path.unlink()
# print("Cleaned up temporary files.")