File size: 3,626 Bytes
0020ddc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# Created: 2026-03-07
# Purpose: Horizontal bar chart for 7 forensic audio features
# Dependencies: plotly, numpy

"""Horizontal bar chart visualization for 7 forensic audio features."""

import plotly.graph_objects as go


def plot_feature_bars(feature_stats: dict) -> go.Figure:
    """7๊ฐœ ํฌ๋ Œ์‹ ํ”ผ์ฒ˜๋ฅผ horizontal bar chart๋กœ ์‹œ๊ฐํ™”.



    Args:

        feature_stats: Dict with feature names as keys and normalized values (0-1)



    Returns:

        plotly Figure (horizontal bar chart)

    """
    # 7๊ฐœ ํฌ๋ Œ์‹ ํ”ผ์ฒ˜ (์งง์€ ๋ ˆ์ด๋ธ”)
    features = [
        "Spectral Flux",
        "H/P Ratio",
        "Temporal Accel",
        "Temporal Delta",
        "Percussive",
        "Harmonic",
        "Residual Energy",
    ]

    # ๊ธฐ๋ณธ๊ฐ’ (feature_stats๊ฐ€ ์—†์œผ๋ฉด ์ค‘๊ฐ„๊ฐ’)
    if not feature_stats:
        values = [0.5] * 7
    else:
        values = [
            feature_stats.get("spectral_flux", 0.5),
            feature_stats.get("hp_ratio", 0.5),
            feature_stats.get("temporal_accel", 0.5),
            feature_stats.get("temporal_delta", 0.5),
            feature_stats.get("percussive_strength", 0.5),
            feature_stats.get("harmonic_strength", 0.5),
            feature_stats.get("residual_energy", 0.5),
        ]

    # AI ๊ฐ€๋Šฅ์„ฑ ๊ธฐ์ค€: ๋†’์„์ˆ˜๋ก AI ์‹œ๊ทธ๋‹ˆ์ฒ˜
    # Residual Energy, H/P Ratio๋Š” ๋†’์„์ˆ˜๋ก AI
    # Temporal Delta/Accel๋Š” ๋‚ฎ์„์ˆ˜๋ก AI (๋ถ€๋“œ๋Ÿฌ์šด ๋ณ€ํ™”)
    # Harmonic/Percussive๋Š” ํŠน์ • ๋น„์œจ๋กœ ์ˆ˜๋ ด
    # Spectral Flux๋Š” ๋‚ฎ์„์ˆ˜๋ก AI (์ผ๊ด€์  ๋ณ€ํ™”)

    # AI ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๊ฐ•๋„์— ๋”ฐ๋ผ ์ƒ‰์ƒ ๊ฒฐ์ •
    colors = []
    for i, (feat, val) in enumerate(zip(features, values)):
        if "Residual" in feat or "H/P" in feat:
            # ๋†’์„์ˆ˜๋ก AI
            if val >= 0.7:
                colors.append('#ff4757')  # AI (red)
            elif val >= 0.4:
                colors.append('#ffa502')  # Uncertain (orange)
            else:
                colors.append('#2ed573')  # Human (green)
        elif "Temporal" in feat or "Spectral" in feat:
            # ๋‚ฎ์„์ˆ˜๋ก AI
            if val <= 0.3:
                colors.append('#ff4757')  # AI (red)
            elif val <= 0.6:
                colors.append('#ffa502')  # Uncertain (orange)
            else:
                colors.append('#2ed573')  # Human (green)
        else:
            # Harmonic/Percussive๋Š” ์ค‘๋ฆฝ
            colors.append('#5f9ea0')  # Neutral (cyan)

    fig = go.Figure(go.Bar(
        x=values,
        y=features,
        orientation='h',
        marker=dict(
            color=colors,
            line=dict(color='#fff', width=1)
        ),
        text=[f"{v:.2f}" for v in values],
        textposition='inside',
        textfont=dict(size=11, color='white', family='monospace'),
        hovertemplate="<b>%{y}</b><br>Score: %{x:.3f}<extra></extra>",
    ))

    fig.update_layout(
        xaxis=dict(
            title="Feature Strength",
            range=[0, 1],
            tickfont=dict(size=10, color='#aaa'),
            gridcolor='#333',
        ),
        yaxis=dict(
            tickfont=dict(size=11, color='white'),
        ),
        plot_bgcolor='#1a1a2e',
        paper_bgcolor='#1a1a2e',
        font=dict(color='white'),
        margin=dict(l=140, r=20, t=40, b=40),
        height=300,
        showlegend=False,
        title=dict(
            text="Forensic Feature Strength",
            font=dict(size=13),
            x=0.5, xanchor='center'
        )
    )

    return fig