Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Feature Comparison

Scatter plot interactif : choisis deux features en X et Y. Clique sur un point pour écouter le son.

import os
import json
import pandas as pd
import plotly.graph_objects as go
import ipywidgets as widgets
from IPython.display import display, Audio
import warnings
warnings.filterwarnings('ignore')
outputs_folder = "../outputs"
data = []
for sound_folder in os.listdir(outputs_folder):
    json_path = os.path.join(outputs_folder, sound_folder, "results.json")
    if os.path.exists(json_path):
        with open(json_path, "r") as f:
            result = json.load(f)
            result["group"] = sound_folder[0]
            data.append(result)

df = pd.DataFrame(data)
audio_dir = os.path.abspath("../data/sounds")
df["audio_path"] = df["file"].apply(lambda x: os.path.join(audio_dir, x))
print(f"✓ {len(df)} sons chargés")
✓ 52 sons chargés
features = {
    "F0 moyen (Hz)":          "f0_mean",
    "Variabilité F0":          "f0_variability",
    "Intensité (RMS)":         "global_intensity",
    "Centroïde spectral (Hz)": "spectral_centroid_mean",
    "Largeur de bande (Hz)":   "spectral_bandwidth_mean",
    "Rolloff spectral (Hz)":   "spectral_rolloff_mean",
    "Durée (s)":               "duration"
}

feature_selector  = widgets.Dropdown(options=list(features.keys()),
                                     description="Feature X",
                                     style={"description_width": "initial"})
feature_selector2 = widgets.Dropdown(options=list(features.keys()),
                                     value=list(features.keys())[1],
                                     description="Feature Y",
                                     style={"description_width": "initial"})
audio_out         = widgets.Output()
fig_container     = widgets.Output()

def update_plot(fx, fy):
    with fig_container:
        fig_container.clear_output(wait=True)
        fig = go.FigureWidget()
        for grp, color in [("A", "#1f77b4"), ("J", "#ff7f0e")]:
            sub = df[df["group"] == grp]
            fig.add_trace(go.Scatter(
                x=sub[features[fx]], y=sub[features[fy]],
                mode="markers", name=f"Groupe {grp}",
                marker=dict(size=10, color=color, opacity=0.8),
                text=sub["file"].values,
                customdata=sub[["audio_path", "f0_mean", "f0_variability",
                                 "global_intensity", "spectral_centroid_mean",
                                 "spectral_bandwidth_mean", "duration"]].values,
                hovertemplate=(
                    "<b>%{text}</b><br>"
                    "F0: %{customdata[1]:.1f} Hz<br>"
                    "Variabilité F0: %{customdata[2]:.2f}<br>"
                    "Intensité: %{customdata[3]:.5f}<br>"
                    "Centroïde: %{customdata[4]:.0f} Hz<br>"
                    "Largeur bande: %{customdata[5]:.0f} Hz<br>"
                    "Durée: %{customdata[6]:.2f} s<br>"
                    "<i>Cliquer pour écouter</i><extra></extra>"
                )
            ))
        fig.update_layout(title=f"{fx} vs {fy} — Cliquer pour écouter",
                          xaxis_title=fx, yaxis_title=fy)

        def on_click(trace, points, state):
            if points.point_inds:
                idx = points.point_inds[0]
                path = trace.customdata[idx][0]
                name = trace.text[idx]
                with audio_out:
                    audio_out.clear_output()
                    print(f"▶ {name}")
                    display(Audio(path, autoplay=True))

        for trace in fig.data:
            trace.on_click(on_click)
        display(fig)

plot_out = widgets.interactive_output(
    update_plot, {"fx": feature_selector, "fy": feature_selector2}
)
display(feature_selector, feature_selector2, fig_container, audio_out)
update_plot(feature_selector.value, feature_selector2.value)
Loading...
Loading...
Loading...
Loading...