petter2025's picture
Update core/visualizations.py
18c5d7e verified
raw
history blame
8.53 kB
"""
Enhanced investor-grade visualizations
"""
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np
from plotly.subplots import make_subplots
from datetime import datetime
from typing import Dict, Optional, List
from core.data_models import IncidentScenario
class EnhancedVisualizationEngine:
"""Interactive, investor-grade visualizations"""
def __init__(self):
self.color_palette = px.colors.qualitative.Set3
self.theme = {
"background": "rgba(0,0,0,0)",
"grid": "rgba(200,200,200,0.1)",
"critical": "#FF6B6B",
"warning": "#FFE66D",
"success": "#4ECDC4",
"info": "#45B7D1"
}
def create_interactive_timeline(self, scenario: IncidentScenario) -> go.Figure:
"""Create truly interactive timeline with annotations"""
fig = go.Figure()
# Create timeline events
events = [
{"time": "T-5m", "event": "📉 Cache hit rate drops below 20%", "type": "problem"},
{"time": "T-4m", "event": "⚠️ Database load exceeds 90%", "type": "alert"},
{"time": "T-3m", "event": "🤖 ARF detects pattern", "type": "detection"},
{"time": "T-2m", "event": "🧠 Analysis complete", "type": "analysis"},
{"time": "T-1m", "event": "⚡ Healing executed", "type": "action"},
{"time": "T-0m", "event": "✅ System recovered", "type": "recovery"}
]
# Color mapping
color_map = {
"problem": self.theme["critical"],
"alert": self.theme["warning"],
"detection": self.theme["info"],
"analysis": "#9B59B6",
"action": self.theme["success"],
"recovery": "#2ECC71"
}
# Add events
for event in events:
fig.add_trace(go.Scatter(
x=[event["time"]],
y=[1],
mode='markers+text',
marker=dict(
size=20,
color=color_map[event["type"]],
symbol='circle',
line=dict(width=2, color='white')
),
text=[event["event"]],
textposition="top center",
hoverinfo='text',
name=event["type"].capitalize(),
hovertemplate="<b>%{text}</b><br>Click for details<extra></extra>"
))
# Add connecting line
fig.add_trace(go.Scatter(
x=[e["time"] for e in events],
y=[1] * len(events),
mode='lines',
line=dict(color='gray', width=2, dash='dash'),
hoverinfo='none',
showlegend=False
))
fig.update_layout(
title="<b>Interactive Incident Timeline</b><br><sup>Click events for details</sup>",
height=450,
paper_bgcolor=self.theme["background"],
plot_bgcolor=self.theme["background"],
hovermode='closest',
clickmode='event+select',
yaxis=dict(
showticklabels=False,
range=[0.5, 1.5],
gridcolor=self.theme["grid"]
),
xaxis=dict(
gridcolor=self.theme["grid"]
),
showlegend=True,
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
)
)
return fig
def create_executive_dashboard(self, user_roi: Optional[Dict] = None) -> go.Figure:
"""Create comprehensive executive dashboard"""
fig = make_subplots(
rows=2, cols=2,
subplot_titles=(
'<b>Cost Transformation</b>',
'<b>Team Capacity Shift</b>',
'<b>MTTR Comparison</b>',
'<b>ROI Analysis</b>'
),
vertical_spacing=0.2,
horizontal_spacing=0.15
)
# 1. Cost Transformation
cost_labels = ['Without ARF', 'With ARF Enterprise', 'Net Savings']
cost_values = [2.96, 1.0, 1.96] # In millions
fig.add_trace(
go.Bar(
x=cost_labels,
y=cost_values,
marker_color=[self.theme["critical"], self.theme["success"], '#45B7D1'],
text=[f'${v}M' for v in cost_values],
textposition='auto',
name='Annual Cost',
hovertemplate="<b>%{x}</b><br>Cost: $%{y}M<extra></extra>"
),
row=1, col=1
)
# 2. Team Capacity Shift
activities = ['Firefighting', 'Innovation', 'Strategic Work']
before = [60, 20, 20]
after = [10, 60, 30]
fig.add_trace(
go.Bar(
x=activities,
y=before,
name='Before ARF',
marker_color=self.theme["critical"],
opacity=0.7,
hovertemplate="Before: %{y}%%<extra></extra>"
),
row=1, col=2
)
fig.add_trace(
go.Bar(
x=activities,
y=after,
name='After ARF Enterprise',
marker_color=self.theme["success"],
opacity=0.7,
hovertemplate="After: %{y}%%<extra></extra>"
),
row=1, col=2
)
# 3. MTTR Comparison
mttr_methods = ['Manual', 'Traditional', 'ARF OSS', 'ARF Enterprise']
mttr_times = [120, 45, 25, 8]
fig.add_trace(
go.Bar(
x=mttr_methods,
y=mttr_times,
marker_color=[self.theme["critical"], '#FFE66D', '#45B7D1', self.theme["success"]],
text=[f'{t} min' for t in mttr_times],
textposition='auto',
name='MTTR',
hovertemplate="<b>%{x}</b><br>Resolution: %{y} min<extra></extra>"
),
row=2, col=1
)
# 4. ROI Gauge
roi_value = user_roi.get('roi_multiplier', 5.2) if user_roi else 5.2
fig.add_trace(
go.Indicator(
mode="gauge+number+delta",
value=roi_value,
title={'text': "<b>ROI Multiplier</b>", 'font': {'size': 16}},
delta={'reference': 1.0, 'increasing': {'color': self.theme["success"]}},
gauge={
'axis': {'range': [0, 10], 'tickwidth': 1},
'bar': {'color': self.theme["success"]},
'steps': [
{'range': [0, 2], 'color': 'lightgray'},
{'range': [2, 4], 'color': 'gray'},
{'range': [4, 6], 'color': 'lightgreen'},
{'range': [6, 10], 'color': self.theme["success"]}
],
'threshold': {
'line': {'color': "red", 'width': 4},
'thickness': 0.75,
'value': roi_value
}
}
),
row=2, col=2
)
# Update layout
fig.update_layout(
height=700,
showlegend=True,
paper_bgcolor=self.theme["background"],
plot_bgcolor=self.theme["background"],
title_text="<b>Executive Business Dashboard</b>",
barmode='group',
legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01,
bgcolor='rgba(255,255,255,0.9)'
)
)
# Update axes
fig.update_xaxes(title_text="Cost Model", row=1, col=1, gridcolor=self.theme["grid"])
fig.update_yaxes(title_text="Annual Cost ($M)", row=1, col=1, gridcolor=self.theme["grid"])
fig.update_xaxes(title_text="Activity", row=1, col=2, gridcolor=self.theme["grid"])
fig.update_yaxes(title_text="Time Allocation (%)", row=1, col=2, gridcolor=self.theme["grid"])
fig.update_xaxes(title_text="Resolution Method", row=2, col=1, gridcolor=self.theme["grid"])
fig.update_yaxes(title_text="Minutes to Resolve", row=2, col=1, gridcolor=self.theme["grid"])
return fig