File size: 3,312 Bytes
5a3b9db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import json

def plot_risk_distribution(df: pd.DataFrame):
    fig = px.histogram(df, x="Risk Score", nbins=50, color_discrete_sequence=["#2196F3"])
    fig.update_layout(
        title=dict(text="Risk Score Distribution", font=dict(color="#ECEFF1", size=18)),
        xaxis_title=dict(text="Risk Score", font=dict(color="#B0BEC5")),
        yaxis_title=dict(text="Event Count", font=dict(color="#B0BEC5")),
        template="plotly_dark",
        plot_bgcolor="rgba(0,0,0,0)",
        paper_bgcolor="rgba(0,0,0,0)",
        margin=dict(l=40, r=20, t=50, b=40),
        font=dict(color="#B0BEC5")
    )
    return fig

def plot_attack_categories(df: pd.DataFrame):
    counts = df["Attack Classification"].value_counts().reset_index()
    counts.columns = ["Category", "Count"]
    fig = px.pie(
        counts, 
        names="Category", 
        values="Count", 
        hole=0.4,
        color_discrete_sequence=px.colors.sequential.Tealgrn
    )
    fig.update_traces(textposition='inside', textinfo='percent+label')
    fig.update_layout(
        title=dict(text="Threat Context Distribution", font=dict(color="#ECEFF1", size=18)),
        template="plotly_dark",
        plot_bgcolor="rgba(0,0,0,0)",
        paper_bgcolor="rgba(0,0,0,0)",
        margin=dict(l=20, r=20, t=50, b=20),
        showlegend=True,
        legend=dict(orientation="h", yanchor="bottom", y=-0.2, xanchor="center", x=0.5, font=dict(color="#B0BEC5"))
    )
    return fig

def plot_shap_bars(shap_json: str):
    try:
        data = json.loads(shap_json)
        if not data:
            return go.Figure()
        df = pd.DataFrame(data).sort_values("contribution", ascending=True)
        fig = px.bar(df, x="contribution", y="feature", orientation='h', color_discrete_sequence=["#9C27B0"])
        fig.update_layout(
            title=dict(text="AI Explainability (SHAP)", font=dict(color="#ECEFF1", size=16)),
            xaxis_title=dict(text="Contribution Impact", font=dict(color="#B0BEC5")),
            yaxis_title="",
            template="plotly_dark",
            plot_bgcolor="rgba(0,0,0,0)",
            paper_bgcolor="rgba(0,0,0,0)",
            margin=dict(l=10, r=20, t=40, b=30),
            font=dict(color="#B0BEC5")
        )
        return fig
    except:
        return go.Figure()

def plot_risk_breakdown(risk_json: str):
    try:
        data = json.loads(risk_json)
        # Filter out final risk score to just show the additive components
        components = {k: v for k, v in data.items() if "Contribution" in k and k != "Final Risk Score"}
        
        fig = px.pie(
            names=list(components.keys()), 
            values=list(components.values()), 
            hole=0.4,
            color_discrete_sequence=px.colors.qualitative.Pastel
        )
        fig.update_traces(textinfo='value+label', textposition='inside')
        fig.update_layout(
            title=dict(text="Risk Fusion Breakdown", font=dict(color="#ECEFF1", size=16)),
            template="plotly_dark",
            plot_bgcolor="rgba(0,0,0,0)",
            paper_bgcolor="rgba(0,0,0,0)",
            margin=dict(l=20, r=20, t=40, b=20),
            showlegend=False
        )
        return fig
    except:
        return go.Figure()