petter2025 commited on
Commit
18c5d7e
·
verified ·
1 Parent(s): c30c59f

Update core/visualizations.py

Browse files
Files changed (1) hide show
  1. core/visualizations.py +240 -0
core/visualizations.py CHANGED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Enhanced investor-grade visualizations
3
+ """
4
+
5
+ import plotly.graph_objects as go
6
+ import plotly.express as px
7
+ import pandas as pd
8
+ import numpy as np
9
+ from plotly.subplots import make_subplots
10
+ from datetime import datetime
11
+ from typing import Dict, Optional, List
12
+
13
+ from core.data_models import IncidentScenario
14
+
15
+ class EnhancedVisualizationEngine:
16
+ """Interactive, investor-grade visualizations"""
17
+
18
+ def __init__(self):
19
+ self.color_palette = px.colors.qualitative.Set3
20
+ self.theme = {
21
+ "background": "rgba(0,0,0,0)",
22
+ "grid": "rgba(200,200,200,0.1)",
23
+ "critical": "#FF6B6B",
24
+ "warning": "#FFE66D",
25
+ "success": "#4ECDC4",
26
+ "info": "#45B7D1"
27
+ }
28
+
29
+ def create_interactive_timeline(self, scenario: IncidentScenario) -> go.Figure:
30
+ """Create truly interactive timeline with annotations"""
31
+ fig = go.Figure()
32
+
33
+ # Create timeline events
34
+ events = [
35
+ {"time": "T-5m", "event": "📉 Cache hit rate drops below 20%", "type": "problem"},
36
+ {"time": "T-4m", "event": "⚠️ Database load exceeds 90%", "type": "alert"},
37
+ {"time": "T-3m", "event": "🤖 ARF detects pattern", "type": "detection"},
38
+ {"time": "T-2m", "event": "🧠 Analysis complete", "type": "analysis"},
39
+ {"time": "T-1m", "event": "⚡ Healing executed", "type": "action"},
40
+ {"time": "T-0m", "event": "✅ System recovered", "type": "recovery"}
41
+ ]
42
+
43
+ # Color mapping
44
+ color_map = {
45
+ "problem": self.theme["critical"],
46
+ "alert": self.theme["warning"],
47
+ "detection": self.theme["info"],
48
+ "analysis": "#9B59B6",
49
+ "action": self.theme["success"],
50
+ "recovery": "#2ECC71"
51
+ }
52
+
53
+ # Add events
54
+ for event in events:
55
+ fig.add_trace(go.Scatter(
56
+ x=[event["time"]],
57
+ y=[1],
58
+ mode='markers+text',
59
+ marker=dict(
60
+ size=20,
61
+ color=color_map[event["type"]],
62
+ symbol='circle',
63
+ line=dict(width=2, color='white')
64
+ ),
65
+ text=[event["event"]],
66
+ textposition="top center",
67
+ hoverinfo='text',
68
+ name=event["type"].capitalize(),
69
+ hovertemplate="<b>%{text}</b><br>Click for details<extra></extra>"
70
+ ))
71
+
72
+ # Add connecting line
73
+ fig.add_trace(go.Scatter(
74
+ x=[e["time"] for e in events],
75
+ y=[1] * len(events),
76
+ mode='lines',
77
+ line=dict(color='gray', width=2, dash='dash'),
78
+ hoverinfo='none',
79
+ showlegend=False
80
+ ))
81
+
82
+ fig.update_layout(
83
+ title="<b>Interactive Incident Timeline</b><br><sup>Click events for details</sup>",
84
+ height=450,
85
+ paper_bgcolor=self.theme["background"],
86
+ plot_bgcolor=self.theme["background"],
87
+ hovermode='closest',
88
+ clickmode='event+select',
89
+ yaxis=dict(
90
+ showticklabels=False,
91
+ range=[0.5, 1.5],
92
+ gridcolor=self.theme["grid"]
93
+ ),
94
+ xaxis=dict(
95
+ gridcolor=self.theme["grid"]
96
+ ),
97
+ showlegend=True,
98
+ legend=dict(
99
+ yanchor="top",
100
+ y=0.99,
101
+ xanchor="left",
102
+ x=0.01
103
+ )
104
+ )
105
+
106
+ return fig
107
+
108
+ def create_executive_dashboard(self, user_roi: Optional[Dict] = None) -> go.Figure:
109
+ """Create comprehensive executive dashboard"""
110
+ fig = make_subplots(
111
+ rows=2, cols=2,
112
+ subplot_titles=(
113
+ '<b>Cost Transformation</b>',
114
+ '<b>Team Capacity Shift</b>',
115
+ '<b>MTTR Comparison</b>',
116
+ '<b>ROI Analysis</b>'
117
+ ),
118
+ vertical_spacing=0.2,
119
+ horizontal_spacing=0.15
120
+ )
121
+
122
+ # 1. Cost Transformation
123
+ cost_labels = ['Without ARF', 'With ARF Enterprise', 'Net Savings']
124
+ cost_values = [2.96, 1.0, 1.96] # In millions
125
+
126
+ fig.add_trace(
127
+ go.Bar(
128
+ x=cost_labels,
129
+ y=cost_values,
130
+ marker_color=[self.theme["critical"], self.theme["success"], '#45B7D1'],
131
+ text=[f'${v}M' for v in cost_values],
132
+ textposition='auto',
133
+ name='Annual Cost',
134
+ hovertemplate="<b>%{x}</b><br>Cost: $%{y}M<extra></extra>"
135
+ ),
136
+ row=1, col=1
137
+ )
138
+
139
+ # 2. Team Capacity Shift
140
+ activities = ['Firefighting', 'Innovation', 'Strategic Work']
141
+ before = [60, 20, 20]
142
+ after = [10, 60, 30]
143
+
144
+ fig.add_trace(
145
+ go.Bar(
146
+ x=activities,
147
+ y=before,
148
+ name='Before ARF',
149
+ marker_color=self.theme["critical"],
150
+ opacity=0.7,
151
+ hovertemplate="Before: %{y}%%<extra></extra>"
152
+ ),
153
+ row=1, col=2
154
+ )
155
+
156
+ fig.add_trace(
157
+ go.Bar(
158
+ x=activities,
159
+ y=after,
160
+ name='After ARF Enterprise',
161
+ marker_color=self.theme["success"],
162
+ opacity=0.7,
163
+ hovertemplate="After: %{y}%%<extra></extra>"
164
+ ),
165
+ row=1, col=2
166
+ )
167
+
168
+ # 3. MTTR Comparison
169
+ mttr_methods = ['Manual', 'Traditional', 'ARF OSS', 'ARF Enterprise']
170
+ mttr_times = [120, 45, 25, 8]
171
+
172
+ fig.add_trace(
173
+ go.Bar(
174
+ x=mttr_methods,
175
+ y=mttr_times,
176
+ marker_color=[self.theme["critical"], '#FFE66D', '#45B7D1', self.theme["success"]],
177
+ text=[f'{t} min' for t in mttr_times],
178
+ textposition='auto',
179
+ name='MTTR',
180
+ hovertemplate="<b>%{x}</b><br>Resolution: %{y} min<extra></extra>"
181
+ ),
182
+ row=2, col=1
183
+ )
184
+
185
+ # 4. ROI Gauge
186
+ roi_value = user_roi.get('roi_multiplier', 5.2) if user_roi else 5.2
187
+
188
+ fig.add_trace(
189
+ go.Indicator(
190
+ mode="gauge+number+delta",
191
+ value=roi_value,
192
+ title={'text': "<b>ROI Multiplier</b>", 'font': {'size': 16}},
193
+ delta={'reference': 1.0, 'increasing': {'color': self.theme["success"]}},
194
+ gauge={
195
+ 'axis': {'range': [0, 10], 'tickwidth': 1},
196
+ 'bar': {'color': self.theme["success"]},
197
+ 'steps': [
198
+ {'range': [0, 2], 'color': 'lightgray'},
199
+ {'range': [2, 4], 'color': 'gray'},
200
+ {'range': [4, 6], 'color': 'lightgreen'},
201
+ {'range': [6, 10], 'color': self.theme["success"]}
202
+ ],
203
+ 'threshold': {
204
+ 'line': {'color': "red", 'width': 4},
205
+ 'thickness': 0.75,
206
+ 'value': roi_value
207
+ }
208
+ }
209
+ ),
210
+ row=2, col=2
211
+ )
212
+
213
+ # Update layout
214
+ fig.update_layout(
215
+ height=700,
216
+ showlegend=True,
217
+ paper_bgcolor=self.theme["background"],
218
+ plot_bgcolor=self.theme["background"],
219
+ title_text="<b>Executive Business Dashboard</b>",
220
+ barmode='group',
221
+ legend=dict(
222
+ yanchor="top",
223
+ y=0.99,
224
+ xanchor="left",
225
+ x=0.01,
226
+ bgcolor='rgba(255,255,255,0.9)'
227
+ )
228
+ )
229
+
230
+ # Update axes
231
+ fig.update_xaxes(title_text="Cost Model", row=1, col=1, gridcolor=self.theme["grid"])
232
+ fig.update_yaxes(title_text="Annual Cost ($M)", row=1, col=1, gridcolor=self.theme["grid"])
233
+
234
+ fig.update_xaxes(title_text="Activity", row=1, col=2, gridcolor=self.theme["grid"])
235
+ fig.update_yaxes(title_text="Time Allocation (%)", row=1, col=2, gridcolor=self.theme["grid"])
236
+
237
+ fig.update_xaxes(title_text="Resolution Method", row=2, col=1, gridcolor=self.theme["grid"])
238
+ fig.update_yaxes(title_text="Minutes to Resolve", row=2, col=1, gridcolor=self.theme["grid"])
239
+
240
+ return fig