gauravlochab commited on
Commit
e737d2f
·
1 Parent(s): cb9360a

fix: remove module and put it back in app.py

Browse files
Files changed (1) hide show
  1. app.py +583 -3
app.py CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
3
  import gradio as gr
4
  import plotly.graph_objects as go
5
  import plotly.express as px
 
6
  from datetime import datetime, timedelta
7
  import json
8
  # Commenting out blockchain-related imports that cause loading issues
@@ -12,10 +13,589 @@ import numpy as np
12
  import matplotlib.pyplot as plt
13
  import matplotlib.dates as mdates
14
  import random
 
 
15
  # Comment out the import for now and replace with dummy functions
16
  # from app_trans_new import create_transcation_visualizations,create_active_agents_visualizations
17
- # Import APR visualization functions from the new module
18
- from apr_visualization import generate_apr_visualizations
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  # Create dummy functions for the commented out imports
21
  def create_transcation_visualizations():
@@ -390,4 +970,4 @@ def dashboard():
390
 
391
  # Launch the dashboard
392
  if __name__ == "__main__":
393
- dashboard().launch()
 
3
  import gradio as gr
4
  import plotly.graph_objects as go
5
  import plotly.express as px
6
+ from plotly.subplots import make_subplots
7
  from datetime import datetime, timedelta
8
  import json
9
  # Commenting out blockchain-related imports that cause loading issues
 
13
  import matplotlib.pyplot as plt
14
  import matplotlib.dates as mdates
15
  import random
16
+ import logging
17
+ from typing import List, Dict, Any
18
  # Comment out the import for now and replace with dummy functions
19
  # from app_trans_new import create_transcation_visualizations,create_active_agents_visualizations
20
+ # APR visualization functions integrated directly
21
+
22
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
23
+ logger = logging.getLogger(__name__)
24
+
25
+ # Global variable to store the data for reuse
26
+ global_df = None
27
+
28
+ # Configuration
29
+ API_BASE_URL = "https://afmdb.autonolas.tech"
30
+
31
+ def get_agent_type_by_name(type_name: str) -> Dict[str, Any]:
32
+ """Get agent type by name"""
33
+ response = requests.get(f"{API_BASE_URL}/api/agent-types/name/{type_name}")
34
+ if response.status_code == 404:
35
+ logger.error(f"Agent type '{type_name}' not found")
36
+ return None
37
+ response.raise_for_status()
38
+ return response.json()
39
+
40
+ def get_attribute_definition_by_name(attr_name: str) -> Dict[str, Any]:
41
+ """Get attribute definition by name"""
42
+ response = requests.get(f"{API_BASE_URL}/api/attributes/name/{attr_name}")
43
+ if response.status_code == 404:
44
+ logger.error(f"Attribute definition '{attr_name}' not found")
45
+ return None
46
+ response.raise_for_status()
47
+ return response.json()
48
+
49
+ def get_agents_by_type(type_id: int) -> List[Dict[str, Any]]:
50
+ """Get all agents of a specific type"""
51
+ response = requests.get(f"{API_BASE_URL}/api/agent-types/{type_id}/agents/")
52
+ if response.status_code == 404:
53
+ logger.error(f"No agents found for type ID {type_id}")
54
+ return []
55
+ response.raise_for_status()
56
+ return response.json()
57
+
58
+ def get_attribute_values_by_type_and_attr(agents: List[Dict[str, Any]], attr_def_id: int) -> List[Dict[str, Any]]:
59
+ """Get all attribute values for a specific attribute definition across all agents of a given list"""
60
+ all_attributes = []
61
+
62
+ # For each agent, get their attributes and filter for the one we want
63
+ for agent in agents:
64
+ agent_id = agent["agent_id"]
65
+
66
+ # Call the /api/agents/{agent_id}/attributes/ endpoint
67
+ response = requests.get(f"{API_BASE_URL}/api/agents/{agent_id}/attributes/", params={"limit": 1000})
68
+ if response.status_code == 404:
69
+ logger.error(f"No attributes found for agent ID {agent_id}")
70
+ continue
71
+
72
+ try:
73
+ response.raise_for_status()
74
+ agent_attrs = response.json()
75
+
76
+ # Filter for the specific attribute definition ID
77
+ filtered_attrs = [attr for attr in agent_attrs if attr.get("attr_def_id") == attr_def_id]
78
+ all_attributes.extend(filtered_attrs)
79
+ except requests.exceptions.RequestException as e:
80
+ logger.error(f"Error fetching attributes for agent ID {agent_id}: {e}")
81
+
82
+ return all_attributes
83
+
84
+ def get_agent_name(agent_id: int, agents: List[Dict[str, Any]]) -> str:
85
+ """Get agent name from agent ID"""
86
+ for agent in agents:
87
+ if agent["agent_id"] == agent_id:
88
+ return agent["agent_name"]
89
+ return "Unknown"
90
+
91
+ def extract_apr_value(attr: Dict[str, Any]) -> Dict[str, Any]:
92
+ """Extract APR value and timestamp from JSON value"""
93
+ try:
94
+ # The APR value is stored in the json_value field
95
+ if attr["json_value"] is None:
96
+ return {"apr": None, "timestamp": None, "agent_id": attr["agent_id"], "is_dummy": False}
97
+
98
+ # If json_value is a string, parse it
99
+ if isinstance(attr["json_value"], str):
100
+ json_data = json.loads(attr["json_value"])
101
+ else:
102
+ json_data = attr["json_value"]
103
+
104
+ apr = json_data.get("apr")
105
+ timestamp = json_data.get("timestamp")
106
+
107
+ # Convert timestamp to datetime if it exists
108
+ timestamp_dt = None
109
+ if timestamp:
110
+ timestamp_dt = datetime.fromtimestamp(timestamp)
111
+
112
+ return {"apr": apr, "timestamp": timestamp_dt, "agent_id": attr["agent_id"], "is_dummy": False}
113
+ except (json.JSONDecodeError, KeyError, TypeError) as e:
114
+ logger.error(f"Error parsing JSON value: {e} for agent_id: {attr.get('agent_id')}")
115
+ return {"apr": None, "timestamp": None, "agent_id": attr["agent_id"], "is_dummy": False}
116
+
117
+ def fetch_apr_data_from_db():
118
+ """
119
+ Fetch APR data from database using the API.
120
+ """
121
+ global global_df
122
+
123
+ try:
124
+ # Step 1: Find the Modius agent type
125
+ modius_type = get_agent_type_by_name("Modius")
126
+ if not modius_type:
127
+ logger.error("Modius agent type not found, using placeholder data")
128
+ global_df = pd.DataFrame([])
129
+ return global_df
130
+
131
+ type_id = modius_type["type_id"]
132
+
133
+ # Step 2: Find the APR attribute definition
134
+ apr_attr_def = get_attribute_definition_by_name("APR")
135
+ if not apr_attr_def:
136
+ logger.error("APR attribute definition not found, using placeholder data")
137
+ global_df = pd.DataFrame([])
138
+ return global_df
139
+
140
+ attr_def_id = apr_attr_def["attr_def_id"]
141
+
142
+ # Step 3: Get all agents of type Modius
143
+ modius_agents = get_agents_by_type(type_id)
144
+ if not modius_agents:
145
+ logger.error("No agents of type 'Modius' found")
146
+ global_df = pd.DataFrame([])
147
+ return global_df
148
+
149
+ # Step 4: Fetch all APR values for Modius agents
150
+ apr_attributes = get_attribute_values_by_type_and_attr(modius_agents, attr_def_id)
151
+ if not apr_attributes:
152
+ logger.error("No APR values found for 'Modius' agents")
153
+ global_df = pd.DataFrame([])
154
+ return global_df
155
+
156
+ # Step 5: Extract APR data
157
+ apr_data_list = []
158
+ for attr in apr_attributes:
159
+ apr_data = extract_apr_value(attr)
160
+ if apr_data["apr"] is not None and apr_data["timestamp"] is not None:
161
+ # Get agent name
162
+ agent_name = get_agent_name(attr["agent_id"], modius_agents)
163
+ # Add agent name to the data
164
+ apr_data["agent_name"] = agent_name
165
+ # Add is_dummy flag (all real data)
166
+ apr_data["is_dummy"] = False
167
+
168
+ # Mark negative values as "Performance" metrics
169
+ if apr_data["apr"] < 0:
170
+ apr_data["metric_type"] = "Performance"
171
+ else:
172
+ apr_data["metric_type"] = "APR"
173
+
174
+ apr_data_list.append(apr_data)
175
+
176
+ # Convert list of dictionaries to DataFrame
177
+ if not apr_data_list:
178
+ logger.error("No valid APR data extracted")
179
+ global_df = pd.DataFrame([])
180
+ return global_df
181
+
182
+ global_df = pd.DataFrame(apr_data_list)
183
+ return global_df
184
+
185
+ except requests.exceptions.RequestException as e:
186
+ logger.error(f"API request error: {e}")
187
+ global_df = pd.DataFrame([])
188
+ return global_df
189
+ except Exception as e:
190
+ logger.error(f"Error fetching APR data: {e}")
191
+ global_df = pd.DataFrame([])
192
+ return global_df
193
+
194
+ def generate_apr_visualizations():
195
+ """Generate APR visualizations with real data only (no dummy data)"""
196
+ global global_df
197
+
198
+ # Fetch data from database
199
+ df = fetch_apr_data_from_db()
200
+
201
+ # If we got no data at all, return placeholder figures
202
+ if df.empty:
203
+ logger.info("No APR data available. Using fallback visualization.")
204
+ # Create empty visualizations with a message using Plotly
205
+ fig = go.Figure()
206
+ fig.add_annotation(
207
+ x=0.5, y=0.5,
208
+ text="No APR data available",
209
+ font=dict(size=20),
210
+ showarrow=False
211
+ )
212
+ fig.update_layout(
213
+ xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
214
+ yaxis=dict(showgrid=False, zeroline=False, showticklabels=False)
215
+ )
216
+
217
+ # Save as static files for reference
218
+ fig.write_html("modius_apr_per_agent_graph.html")
219
+ fig.write_image("modius_apr_per_agent_graph.png")
220
+ fig.write_html("modius_apr_combined_graph.html")
221
+ fig.write_image("modius_apr_combined_graph.png")
222
+
223
+ csv_file = None
224
+ return fig, fig, csv_file
225
+
226
+ # No longer generating dummy data
227
+ # Set global_df for access by other functions
228
+ global_df = df
229
+
230
+ # Save to CSV before creating visualizations
231
+ csv_file = save_to_csv(df)
232
+
233
+ # Create per-agent time series graph (returns figure object)
234
+ per_agent_fig = create_time_series_graph_per_agent(df)
235
+
236
+ # Create combined time series graph (returns figure object)
237
+ combined_fig = create_combined_time_series_graph(df)
238
+
239
+ return per_agent_fig, combined_fig, csv_file
240
+
241
+ def create_time_series_graph_per_agent(df):
242
+ """Create a time series graph for each agent using Plotly"""
243
+ # Get unique agents
244
+ unique_agents = df['agent_id'].unique()
245
+
246
+ if len(unique_agents) == 0:
247
+ logger.error("No agent data to plot")
248
+ fig = go.Figure()
249
+ fig.add_annotation(
250
+ text="No agent data available",
251
+ x=0.5, y=0.5,
252
+ showarrow=False, font=dict(size=20)
253
+ )
254
+ return fig
255
+
256
+ # Create a subplot figure for each agent
257
+ fig = make_subplots(rows=len(unique_agents), cols=1,
258
+ subplot_titles=[f"Agent: {df[df['agent_id'] == agent_id]['agent_name'].iloc[0]}"
259
+ for agent_id in unique_agents],
260
+ vertical_spacing=0.1)
261
+
262
+ # Plot data for each agent
263
+ for i, agent_id in enumerate(unique_agents):
264
+ agent_data = df[df['agent_id'] == agent_id].copy()
265
+ agent_name = agent_data['agent_name'].iloc[0]
266
+ row = i + 1
267
+
268
+ # Add zero line to separate APR and Performance
269
+ fig.add_shape(
270
+ type="line", line=dict(dash="solid", width=1.5, color="black"),
271
+ y0=0, y1=0, x0=agent_data['timestamp'].min(), x1=agent_data['timestamp'].max(),
272
+ row=row, col=1
273
+ )
274
+
275
+ # Add background colors
276
+ fig.add_shape(
277
+ type="rect", fillcolor="rgba(230, 243, 255, 0.3)", line=dict(width=0),
278
+ y0=0, y1=1000, x0=agent_data['timestamp'].min(), x1=agent_data['timestamp'].max(),
279
+ row=row, col=1, layer="below"
280
+ )
281
+ fig.add_shape(
282
+ type="rect", fillcolor="rgba(255, 230, 230, 0.3)", line=dict(width=0),
283
+ y0=-1000, y1=0, x0=agent_data['timestamp'].min(), x1=agent_data['timestamp'].max(),
284
+ row=row, col=1, layer="below"
285
+ )
286
+
287
+ # Create separate dataframes for different data types
288
+ apr_data = agent_data[agent_data['metric_type'] == 'APR']
289
+ perf_data = agent_data[agent_data['metric_type'] == 'Performance']
290
+
291
+ # Sort all data by timestamp for the line plots
292
+ combined_agent_data = agent_data.sort_values('timestamp')
293
+
294
+ # Add main line connecting all points
295
+ fig.add_trace(
296
+ go.Scatter(
297
+ x=combined_agent_data['timestamp'],
298
+ y=combined_agent_data['apr'],
299
+ mode='lines',
300
+ line=dict(color='purple', width=2),
301
+ name=f'{agent_name}',
302
+ legendgroup=agent_name,
303
+ showlegend=(i == 0), # Only show in legend once
304
+ hovertemplate='Time: %{x}<br>Value: %{y:.2f}<extra></extra>'
305
+ ),
306
+ row=row, col=1
307
+ )
308
+
309
+ # Add scatter points for APR values
310
+ if not apr_data.empty:
311
+ fig.add_trace(
312
+ go.Scatter(
313
+ x=apr_data['timestamp'],
314
+ y=apr_data['apr'],
315
+ mode='markers',
316
+ marker=dict(color='blue', size=10, symbol='circle'),
317
+ name='APR',
318
+ legendgroup='APR',
319
+ showlegend=(i == 0),
320
+ hovertemplate='Time: %{x}<br>APR: %{y:.2f}<extra></extra>'
321
+ ),
322
+ row=row, col=1
323
+ )
324
+
325
+ # Add scatter points for Performance values
326
+ if not perf_data.empty:
327
+ fig.add_trace(
328
+ go.Scatter(
329
+ x=perf_data['timestamp'],
330
+ y=perf_data['apr'],
331
+ mode='markers',
332
+ marker=dict(color='red', size=10, symbol='square'),
333
+ name='Performance',
334
+ legendgroup='Performance',
335
+ showlegend=(i == 0),
336
+ hovertemplate='Time: %{x}<br>Performance: %{y:.2f}<extra></extra>'
337
+ ),
338
+ row=row, col=1
339
+ )
340
+
341
+ # Update axes
342
+ fig.update_xaxes(title_text="Time", row=row, col=1)
343
+ fig.update_yaxes(title_text="Value", row=row, col=1, gridcolor='rgba(0,0,0,0.1)')
344
+
345
+ # Update layout
346
+ fig.update_layout(
347
+ height=400 * len(unique_agents),
348
+ width=1000,
349
+ title_text="APR and Performance Values per Agent",
350
+ template="plotly_white",
351
+ legend=dict(
352
+ orientation="h",
353
+ yanchor="bottom",
354
+ y=1.02,
355
+ xanchor="right",
356
+ x=1
357
+ ),
358
+ margin=dict(r=20, l=20, t=30, b=20),
359
+ hovermode="closest"
360
+ )
361
+
362
+ # Save the figure (still useful for reference)
363
+ graph_file = "modius_apr_per_agent_graph.html"
364
+ fig.write_html(graph_file, include_plotlyjs='cdn', full_html=False)
365
+
366
+ # Also save as image for compatibility
367
+ img_file = "modius_apr_per_agent_graph.png"
368
+ fig.write_image(img_file)
369
+
370
+ logger.info(f"Per-agent graph saved to {graph_file} and {img_file}")
371
+
372
+ # Return the figure object for direct use in Gradio
373
+ return fig
374
+
375
+ def create_combined_time_series_graph(df):
376
+ """Create a combined time series graph for all agents using Plotly"""
377
+ if len(df) == 0:
378
+ logger.error("No data to plot combined graph")
379
+ fig = go.Figure()
380
+ fig.add_annotation(
381
+ text="No data available",
382
+ x=0.5, y=0.5,
383
+ showarrow=False, font=dict(size=20)
384
+ )
385
+ return fig
386
+
387
+ # Create Plotly figure
388
+ fig = go.Figure()
389
+
390
+ # Get unique agents
391
+ unique_agents = df['agent_id'].unique()
392
+
393
+ # Define a color scale for different agents
394
+ colors = px.colors.qualitative.Plotly[:len(unique_agents)]
395
+
396
+ # Add background shapes for APR and Performance regions
397
+ min_time = df['timestamp'].min()
398
+ max_time = df['timestamp'].max()
399
+
400
+ # Add shape for APR region (above zero)
401
+ fig.add_shape(
402
+ type="rect",
403
+ fillcolor="rgba(230, 243, 255, 0.3)",
404
+ line=dict(width=0),
405
+ y0=0, y1=1000,
406
+ x0=min_time, x1=max_time,
407
+ layer="below"
408
+ )
409
+
410
+ # Add shape for Performance region (below zero)
411
+ fig.add_shape(
412
+ type="rect",
413
+ fillcolor="rgba(255, 230, 230, 0.3)",
414
+ line=dict(width=0),
415
+ y0=-1000, y1=0,
416
+ x0=min_time, x1=max_time,
417
+ layer="below"
418
+ )
419
+
420
+ # Add zero line
421
+ fig.add_shape(
422
+ type="line",
423
+ line=dict(dash="solid", width=1.5, color="black"),
424
+ y0=0, y1=0,
425
+ x0=min_time, x1=max_time
426
+ )
427
+
428
+ # Add data for each agent
429
+ for i, agent_id in enumerate(unique_agents):
430
+ agent_data = df[df['agent_id'] == agent_id].copy()
431
+ agent_name = agent_data['agent_name'].iloc[0]
432
+ color = colors[i % len(colors)]
433
+
434
+ # Sort the data by timestamp
435
+ agent_data = agent_data.sort_values('timestamp')
436
+
437
+ # Add the combined line for both APR and Performance
438
+ fig.add_trace(
439
+ go.Scatter(
440
+ x=agent_data['timestamp'],
441
+ y=agent_data['apr'],
442
+ mode='lines',
443
+ line=dict(color=color, width=2),
444
+ name=f'{agent_name}',
445
+ legendgroup=agent_name,
446
+ hovertemplate='Time: %{x}<br>Value: %{y:.2f}<br>Agent: ' + agent_name + '<extra></extra>'
447
+ )
448
+ )
449
+
450
+ # Add scatter points for APR values
451
+ apr_data = agent_data[agent_data['metric_type'] == 'APR']
452
+ if not apr_data.empty:
453
+ fig.add_trace(
454
+ go.Scatter(
455
+ x=apr_data['timestamp'],
456
+ y=apr_data['apr'],
457
+ mode='markers',
458
+ marker=dict(color=color, symbol='circle', size=8),
459
+ name=f'{agent_name} APR',
460
+ legendgroup=agent_name,
461
+ showlegend=False,
462
+ hovertemplate='Time: %{x}<br>APR: %{y:.2f}<br>Agent: ' + agent_name + '<extra></extra>'
463
+ )
464
+ )
465
+
466
+ # Add scatter points for Performance values
467
+ perf_data = agent_data[agent_data['metric_type'] == 'Performance']
468
+ if not perf_data.empty:
469
+ fig.add_trace(
470
+ go.Scatter(
471
+ x=perf_data['timestamp'],
472
+ y=perf_data['apr'],
473
+ mode='markers',
474
+ marker=dict(color=color, symbol='square', size=8),
475
+ name=f'{agent_name} Perf',
476
+ legendgroup=agent_name,
477
+ showlegend=False,
478
+ hovertemplate='Time: %{x}<br>Performance: %{y:.2f}<br>Agent: ' + agent_name + '<extra></extra>'
479
+ )
480
+ )
481
+
482
+ # Update layout
483
+ fig.update_layout(
484
+ title="APR and Performance Values for All Agents",
485
+ xaxis_title="Time",
486
+ yaxis_title="Value",
487
+ template="plotly_white",
488
+ height=600,
489
+ width=1000,
490
+ legend=dict(
491
+ orientation="h",
492
+ yanchor="bottom",
493
+ y=1.02,
494
+ xanchor="right",
495
+ x=1,
496
+ groupclick="toggleitem"
497
+ ),
498
+ margin=dict(r=20, l=20, t=30, b=20),
499
+ hovermode="closest"
500
+ )
501
+
502
+ # Update axes
503
+ fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')
504
+ fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')
505
+
506
+ # Save the figure (still useful for reference)
507
+ graph_file = "modius_apr_combined_graph.html"
508
+ fig.write_html(graph_file, include_plotlyjs='cdn', full_html=False)
509
+
510
+ # Also save as image for compatibility
511
+ img_file = "modius_apr_combined_graph.png"
512
+ fig.write_image(img_file)
513
+
514
+ logger.info(f"Combined graph saved to {graph_file} and {img_file}")
515
+
516
+ # Return the figure object for direct use in Gradio
517
+ return fig
518
+
519
+ def save_to_csv(df):
520
+ """Save the APR data DataFrame to a CSV file and return the file path"""
521
+ if df.empty:
522
+ logger.error("No APR data to save to CSV")
523
+ return None
524
+
525
+ # Define the CSV file path
526
+ csv_file = "modius_apr_values.csv"
527
+
528
+ # Save to CSV
529
+ df.to_csv(csv_file, index=False)
530
+ logger.info(f"APR data saved to {csv_file}")
531
+
532
+ # Also generate a statistics CSV file
533
+ stats_df = generate_statistics_from_data(df)
534
+ stats_csv = "modius_apr_statistics.csv"
535
+ stats_df.to_csv(stats_csv, index=False)
536
+ logger.info(f"Statistics saved to {stats_csv}")
537
+
538
+ return csv_file
539
+
540
+ def generate_statistics_from_data(df):
541
+ """Generate statistics from the APR data"""
542
+ if df.empty:
543
+ return pd.DataFrame()
544
+
545
+ # Get unique agents
546
+ unique_agents = df['agent_id'].unique()
547
+ stats_list = []
548
+
549
+ # Generate per-agent statistics
550
+ for agent_id in unique_agents:
551
+ agent_data = df[df['agent_id'] == agent_id]
552
+ agent_name = agent_data['agent_name'].iloc[0]
553
+
554
+ # APR statistics
555
+ apr_data = agent_data[agent_data['metric_type'] == 'APR']
556
+ real_apr = apr_data[apr_data['is_dummy'] == False]
557
+
558
+ # Performance statistics
559
+ perf_data = agent_data[agent_data['metric_type'] == 'Performance']
560
+ real_perf = perf_data[perf_data['is_dummy'] == False]
561
+
562
+ stats = {
563
+ 'agent_id': agent_id,
564
+ 'agent_name': agent_name,
565
+ 'total_points': len(agent_data),
566
+ 'apr_points': len(apr_data),
567
+ 'performance_points': len(perf_data),
568
+ 'real_apr_points': len(real_apr),
569
+ 'real_performance_points': len(real_perf),
570
+ 'avg_apr': apr_data['apr'].mean() if not apr_data.empty else None,
571
+ 'avg_performance': perf_data['apr'].mean() if not perf_data.empty else None,
572
+ 'max_apr': apr_data['apr'].max() if not apr_data.empty else None,
573
+ 'min_apr': apr_data['apr'].min() if not apr_data.empty else None,
574
+ 'latest_timestamp': agent_data['timestamp'].max().strftime('%Y-%m-%d %H:%M:%S') if not agent_data.empty else None
575
+ }
576
+ stats_list.append(stats)
577
+
578
+ # Generate overall statistics
579
+ apr_only = df[df['metric_type'] == 'APR']
580
+ perf_only = df[df['metric_type'] == 'Performance']
581
+
582
+ overall_stats = {
583
+ 'agent_id': 'ALL',
584
+ 'agent_name': 'All Agents',
585
+ 'total_points': len(df),
586
+ 'apr_points': len(apr_only),
587
+ 'performance_points': len(perf_only),
588
+ 'real_apr_points': len(apr_only[apr_only['is_dummy'] == False]),
589
+ 'real_performance_points': len(perf_only[perf_only['is_dummy'] == False]),
590
+ 'avg_apr': apr_only['apr'].mean() if not apr_only.empty else None,
591
+ 'avg_performance': perf_only['apr'].mean() if not perf_only.empty else None,
592
+ 'max_apr': apr_only['apr'].max() if not apr_only.empty else None,
593
+ 'min_apr': apr_only['apr'].min() if not apr_only.empty else None,
594
+ 'latest_timestamp': df['timestamp'].max().strftime('%Y-%m-%d %H:%M:%S') if not df.empty else None
595
+ }
596
+ stats_list.append(overall_stats)
597
+
598
+ return pd.DataFrame(stats_list)
599
 
600
  # Create dummy functions for the commented out imports
601
  def create_transcation_visualizations():
 
970
 
971
  # Launch the dashboard
972
  if __name__ == "__main__":
973
+ dashboard().launch()