Spaces:
Sleeping
Sleeping
gauravlochab
commited on
Commit
·
28c8cbd
1
Parent(s):
aae782c
chore: clean up the graph and add cumulative average graph
Browse files
app.py
CHANGED
|
@@ -652,22 +652,31 @@ def create_combined_time_series_graph(df):
|
|
| 652 |
avg_apr_data_with_ma = avg_apr_data.copy()
|
| 653 |
avg_apr_data_with_ma['moving_avg'] = None # Initialize the moving average column
|
| 654 |
|
| 655 |
-
# Define the time window for the moving average (
|
| 656 |
-
time_window = pd.Timedelta(hours=
|
| 657 |
logger.info(f"Calculating moving average with time window of {time_window}")
|
| 658 |
|
| 659 |
-
# Calculate
|
|
|
|
|
|
|
|
|
|
|
|
|
| 660 |
for i, row in avg_apr_data_with_ma.iterrows():
|
| 661 |
current_time = row['timestamp']
|
| 662 |
window_start = current_time - time_window
|
| 663 |
|
| 664 |
-
# Get all data points within the time window
|
| 665 |
window_data = apr_data_sorted[
|
| 666 |
(apr_data_sorted['timestamp'] >= window_start) &
|
| 667 |
(apr_data_sorted['timestamp'] <= current_time)
|
| 668 |
]
|
| 669 |
|
| 670 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 671 |
if not window_data.empty:
|
| 672 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = window_data['apr'].mean()
|
| 673 |
logger.debug(f"Time window {window_start} to {current_time}: {len(window_data)} points, avg={window_data['apr'].mean()}")
|
|
@@ -675,8 +684,16 @@ def create_combined_time_series_graph(df):
|
|
| 675 |
# If no data points in the window, use the current value
|
| 676 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = row['apr']
|
| 677 |
logger.debug(f"No data points in time window for {current_time}, using current value {row['apr']}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 678 |
|
| 679 |
-
logger.info(f"Calculated time-based moving
|
| 680 |
|
| 681 |
# Plot individual agent data points with agent names in hover, but limit display for scalability
|
| 682 |
if not apr_data.empty:
|
|
@@ -696,56 +713,19 @@ def create_combined_time_series_graph(df):
|
|
| 696 |
|
| 697 |
logger.info(f"Showing {len(top_agents)} agents by default out of {len(unique_agents)} total agents")
|
| 698 |
|
| 699 |
-
#
|
| 700 |
-
|
| 701 |
-
agent_data = apr_data[apr_data['agent_name'] == agent_name]
|
| 702 |
-
|
| 703 |
-
# Explicitly convert to Python lists
|
| 704 |
-
x_values = agent_data['timestamp'].tolist()
|
| 705 |
-
y_values = agent_data['apr'].tolist()
|
| 706 |
-
|
| 707 |
-
# Determine if this agent should be visible by default
|
| 708 |
-
is_visible = agent_name in top_agents
|
| 709 |
-
|
| 710 |
-
# Add data points as markers
|
| 711 |
-
fig.add_trace(
|
| 712 |
-
go.Scatter(
|
| 713 |
-
x=x_values,
|
| 714 |
-
y=y_values,
|
| 715 |
-
mode='markers', # Only markers for original data
|
| 716 |
-
marker=dict(
|
| 717 |
-
color=color_map[agent_name],
|
| 718 |
-
symbol='circle',
|
| 719 |
-
size=10,
|
| 720 |
-
line=dict(width=1, color='black')
|
| 721 |
-
),
|
| 722 |
-
name=f'Agent: {agent_name}',
|
| 723 |
-
hovertemplate='Time: %{x}<br>APR: %{y:.2f}<br>Agent: ' + agent_name + '<extra></extra>',
|
| 724 |
-
visible=is_visible # Only top agents visible by default
|
| 725 |
-
)
|
| 726 |
-
)
|
| 727 |
-
logger.info(f"Added data points for agent {agent_name} with {len(x_values)} points (visible: {is_visible})")
|
| 728 |
|
| 729 |
-
# Add moving average as a smooth line
|
| 730 |
x_values_ma = avg_apr_data_with_ma['timestamp'].tolist()
|
| 731 |
y_values_ma = avg_apr_data_with_ma['moving_avg'].tolist()
|
| 732 |
|
| 733 |
-
# Create
|
| 734 |
-
|
| 735 |
-
hover_data = []
|
| 736 |
for idx, row in avg_apr_data_with_ma.iterrows():
|
| 737 |
timestamp = row['timestamp']
|
| 738 |
-
|
| 739 |
-
|
| 740 |
-
# Find all agents with data in the time window
|
| 741 |
-
agents_in_window = apr_data[
|
| 742 |
-
(apr_data['timestamp'] >= window_start) &
|
| 743 |
-
(apr_data['timestamp'] <= timestamp)
|
| 744 |
-
]
|
| 745 |
-
|
| 746 |
-
# Simplified hover text without detailed data points
|
| 747 |
-
hover_data.append(
|
| 748 |
-
f"Time: {timestamp}<br>Moving Avg APR (2h window): {row['moving_avg']:.2f}"
|
| 749 |
)
|
| 750 |
|
| 751 |
fig.add_trace(
|
|
@@ -753,13 +733,37 @@ def create_combined_time_series_graph(df):
|
|
| 753 |
x=x_values_ma,
|
| 754 |
y=y_values_ma,
|
| 755 |
mode='lines', # Only lines for moving average
|
| 756 |
-
line=dict(color='red', width=
|
| 757 |
-
name='Moving Average APR (
|
| 758 |
-
hovertext=
|
| 759 |
hoverinfo='text'
|
| 760 |
)
|
| 761 |
)
|
| 762 |
-
logger.info(f"Added
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 763 |
|
| 764 |
# Update layout - use simple boolean values everywhere
|
| 765 |
fig.update_layout(
|
|
@@ -781,16 +785,7 @@ def create_combined_time_series_graph(df):
|
|
| 781 |
hovermode="closest"
|
| 782 |
)
|
| 783 |
|
| 784 |
-
#
|
| 785 |
-
if len(unique_agents) > MAX_VISIBLE_AGENTS:
|
| 786 |
-
fig.add_annotation(
|
| 787 |
-
text=f"Note: Only showing top {MAX_VISIBLE_AGENTS} agents by default. Toggle others in legend.",
|
| 788 |
-
xref="paper", yref="paper",
|
| 789 |
-
x=0.5, y=1.05,
|
| 790 |
-
showarrow=False,
|
| 791 |
-
font=dict(size=12, color="gray"),
|
| 792 |
-
align="center"
|
| 793 |
-
)
|
| 794 |
|
| 795 |
# FORCE FIXED Y-AXIS RANGE
|
| 796 |
fig.update_yaxes(
|
|
@@ -855,73 +850,65 @@ def create_combined_time_series_graph(df):
|
|
| 855 |
# Sort by timestamp
|
| 856 |
avg_apr_data = avg_apr_data.sort_values('timestamp')
|
| 857 |
|
| 858 |
-
# Calculate
|
| 859 |
avg_apr_data_with_ma = avg_apr_data.copy()
|
| 860 |
-
avg_apr_data_with_ma['moving_avg'] = None
|
|
|
|
| 861 |
|
| 862 |
-
# Define the time window (
|
| 863 |
-
time_window = pd.Timedelta(hours=
|
| 864 |
|
| 865 |
-
# Calculate the moving
|
| 866 |
for i, row in avg_apr_data_with_ma.iterrows():
|
| 867 |
current_time = row['timestamp']
|
| 868 |
window_start = current_time - time_window
|
| 869 |
|
| 870 |
-
# Get all data points within the time window
|
| 871 |
window_data = apr_data[
|
| 872 |
(apr_data['timestamp'] >= window_start) &
|
| 873 |
(apr_data['timestamp'] <= current_time)
|
| 874 |
]
|
| 875 |
|
| 876 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 877 |
if not window_data.empty:
|
| 878 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = window_data['apr'].mean()
|
| 879 |
else:
|
| 880 |
# If no data points in the window, use the current value
|
| 881 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = row['apr']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 882 |
|
| 883 |
-
#
|
| 884 |
-
|
| 885 |
-
colors = px.colors.qualitative.Plotly[:len(unique_agents)]
|
| 886 |
-
color_map = {agent: colors[i % len(colors)] for i, agent in enumerate(unique_agents)}
|
| 887 |
-
|
| 888 |
-
# Calculate the total number of data points per agent
|
| 889 |
-
agent_counts = apr_data['agent_name'].value_counts()
|
| 890 |
-
|
| 891 |
-
# Determine how many agents to show individually (limit to top 5 most active)
|
| 892 |
-
MAX_VISIBLE_AGENTS = 5
|
| 893 |
-
top_agents = agent_counts.nlargest(min(MAX_VISIBLE_AGENTS, len(agent_counts))).index.tolist()
|
| 894 |
|
| 895 |
-
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
|
| 899 |
-
|
| 900 |
-
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
go.Scatter(
|
| 904 |
-
x=agent_data['timestamp'],
|
| 905 |
-
y=agent_data['apr'],
|
| 906 |
-
mode='markers',
|
| 907 |
-
name=f'Agent: {agent_name}',
|
| 908 |
-
marker=dict(
|
| 909 |
-
size=10,
|
| 910 |
-
color=color_map[agent_name]
|
| 911 |
-
),
|
| 912 |
-
hovertemplate='Time: %{x}<br>APR: %{y:.2f}<br>Agent: ' + agent_name + '<extra></extra>',
|
| 913 |
-
visible=is_visible # Only top agents visible by default
|
| 914 |
-
)
|
| 915 |
)
|
|
|
|
| 916 |
|
| 917 |
-
# Add moving average as
|
| 918 |
simple_fig.add_trace(
|
| 919 |
go.Scatter(
|
| 920 |
x=avg_apr_data_with_ma['timestamp'],
|
| 921 |
-
y=avg_apr_data_with_ma['
|
| 922 |
mode='lines',
|
| 923 |
-
name='
|
| 924 |
-
line=dict(width=
|
| 925 |
)
|
| 926 |
)
|
| 927 |
|
|
@@ -935,16 +922,7 @@ def create_combined_time_series_graph(df):
|
|
| 935 |
width=1000
|
| 936 |
)
|
| 937 |
|
| 938 |
-
#
|
| 939 |
-
if len(unique_agents) > MAX_VISIBLE_AGENTS:
|
| 940 |
-
simple_fig.add_annotation(
|
| 941 |
-
text=f"Note: Only showing top {MAX_VISIBLE_AGENTS} agents by default. Toggle others in legend.",
|
| 942 |
-
xref="paper", yref="paper",
|
| 943 |
-
x=0.5, y=1.05,
|
| 944 |
-
showarrow=False,
|
| 945 |
-
font=dict(size=12, color="gray"),
|
| 946 |
-
align="center"
|
| 947 |
-
)
|
| 948 |
|
| 949 |
# Return the simple figure
|
| 950 |
return simple_fig
|
|
|
|
| 652 |
avg_apr_data_with_ma = avg_apr_data.copy()
|
| 653 |
avg_apr_data_with_ma['moving_avg'] = None # Initialize the moving average column
|
| 654 |
|
| 655 |
+
# Define the time window for the moving average (6 hours)
|
| 656 |
+
time_window = pd.Timedelta(hours=6)
|
| 657 |
logger.info(f"Calculating moving average with time window of {time_window}")
|
| 658 |
|
| 659 |
+
# Calculate two moving averages: one with 2-hour window and one with infinite window
|
| 660 |
+
avg_apr_data_with_ma['moving_avg'] = None # 2-hour window
|
| 661 |
+
avg_apr_data_with_ma['infinite_avg'] = None # Infinite window (all data up to timestamp)
|
| 662 |
+
|
| 663 |
+
# Calculate the moving averages for each timestamp
|
| 664 |
for i, row in avg_apr_data_with_ma.iterrows():
|
| 665 |
current_time = row['timestamp']
|
| 666 |
window_start = current_time - time_window
|
| 667 |
|
| 668 |
+
# Get all data points within the 2-hour time window
|
| 669 |
window_data = apr_data_sorted[
|
| 670 |
(apr_data_sorted['timestamp'] >= window_start) &
|
| 671 |
(apr_data_sorted['timestamp'] <= current_time)
|
| 672 |
]
|
| 673 |
|
| 674 |
+
# Get all data points up to the current timestamp (infinite window)
|
| 675 |
+
infinite_window_data = apr_data_sorted[
|
| 676 |
+
apr_data_sorted['timestamp'] <= current_time
|
| 677 |
+
]
|
| 678 |
+
|
| 679 |
+
# Calculate the average APR for the 2-hour time window
|
| 680 |
if not window_data.empty:
|
| 681 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = window_data['apr'].mean()
|
| 682 |
logger.debug(f"Time window {window_start} to {current_time}: {len(window_data)} points, avg={window_data['apr'].mean()}")
|
|
|
|
| 684 |
# If no data points in the window, use the current value
|
| 685 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = row['apr']
|
| 686 |
logger.debug(f"No data points in time window for {current_time}, using current value {row['apr']}")
|
| 687 |
+
|
| 688 |
+
# Calculate the average APR for the infinite window
|
| 689 |
+
if not infinite_window_data.empty:
|
| 690 |
+
avg_apr_data_with_ma.at[i, 'infinite_avg'] = infinite_window_data['apr'].mean()
|
| 691 |
+
logger.debug(f"Infinite window up to {current_time}: {len(infinite_window_data)} points, avg={infinite_window_data['apr'].mean()}")
|
| 692 |
+
else:
|
| 693 |
+
# This should never happen, but just in case
|
| 694 |
+
avg_apr_data_with_ma.at[i, 'infinite_avg'] = row['apr']
|
| 695 |
|
| 696 |
+
logger.info(f"Calculated time-based moving averages with {len(avg_apr_data_with_ma)} points")
|
| 697 |
|
| 698 |
# Plot individual agent data points with agent names in hover, but limit display for scalability
|
| 699 |
if not apr_data.empty:
|
|
|
|
| 713 |
|
| 714 |
logger.info(f"Showing {len(top_agents)} agents by default out of {len(unique_agents)} total agents")
|
| 715 |
|
| 716 |
+
# No longer showing individual agent data points as requested
|
| 717 |
+
logger.info("Skipping individual agent data points as requested")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 718 |
|
| 719 |
+
# Add 2-hour moving average as a smooth line
|
| 720 |
x_values_ma = avg_apr_data_with_ma['timestamp'].tolist()
|
| 721 |
y_values_ma = avg_apr_data_with_ma['moving_avg'].tolist()
|
| 722 |
|
| 723 |
+
# Create hover template for the 2-hour moving average line
|
| 724 |
+
hover_data_2h = []
|
|
|
|
| 725 |
for idx, row in avg_apr_data_with_ma.iterrows():
|
| 726 |
timestamp = row['timestamp']
|
| 727 |
+
hover_data_2h.append(
|
| 728 |
+
f"Time: {timestamp}<br>Moving Avg APR (6h window): {row['moving_avg']:.2f}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 729 |
)
|
| 730 |
|
| 731 |
fig.add_trace(
|
|
|
|
| 733 |
x=x_values_ma,
|
| 734 |
y=y_values_ma,
|
| 735 |
mode='lines', # Only lines for moving average
|
| 736 |
+
line=dict(color='red', width=2), # Thinner line
|
| 737 |
+
name='Moving Average APR (6h window)',
|
| 738 |
+
hovertext=hover_data_2h,
|
| 739 |
hoverinfo='text'
|
| 740 |
)
|
| 741 |
)
|
| 742 |
+
logger.info(f"Added 2-hour moving average APR trace with {len(x_values_ma)} points")
|
| 743 |
+
|
| 744 |
+
# Add infinite window moving average as another line
|
| 745 |
+
y_values_infinite = avg_apr_data_with_ma['infinite_avg'].tolist()
|
| 746 |
+
|
| 747 |
+
# Create hover template for the infinite window moving average line
|
| 748 |
+
hover_data_infinite = []
|
| 749 |
+
for idx, row in avg_apr_data_with_ma.iterrows():
|
| 750 |
+
timestamp = row['timestamp']
|
| 751 |
+
hover_data_infinite.append(
|
| 752 |
+
f"Time: {timestamp}<br>Cumulative Avg APR (all data): {row['infinite_avg']:.2f}"
|
| 753 |
+
)
|
| 754 |
+
|
| 755 |
+
fig.add_trace(
|
| 756 |
+
go.Scatter(
|
| 757 |
+
x=x_values_ma,
|
| 758 |
+
y=y_values_infinite,
|
| 759 |
+
mode='lines', # Only lines for moving average
|
| 760 |
+
line=dict(color='green', width=4), # Thicker solid line
|
| 761 |
+
name='Cumulative Average APR (all data)',
|
| 762 |
+
hovertext=hover_data_infinite,
|
| 763 |
+
hoverinfo='text'
|
| 764 |
+
)
|
| 765 |
+
)
|
| 766 |
+
logger.info(f"Added infinite window moving average APR trace with {len(x_values_ma)} points")
|
| 767 |
|
| 768 |
# Update layout - use simple boolean values everywhere
|
| 769 |
fig.update_layout(
|
|
|
|
| 785 |
hovermode="closest"
|
| 786 |
)
|
| 787 |
|
| 788 |
+
# No longer need the note about hidden agents since we're not showing individual agents
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 789 |
|
| 790 |
# FORCE FIXED Y-AXIS RANGE
|
| 791 |
fig.update_yaxes(
|
|
|
|
| 850 |
# Sort by timestamp
|
| 851 |
avg_apr_data = avg_apr_data.sort_values('timestamp')
|
| 852 |
|
| 853 |
+
# Calculate both moving averages for the fallback graph
|
| 854 |
avg_apr_data_with_ma = avg_apr_data.copy()
|
| 855 |
+
avg_apr_data_with_ma['moving_avg'] = None # 2-hour window
|
| 856 |
+
avg_apr_data_with_ma['infinite_avg'] = None # Infinite window
|
| 857 |
|
| 858 |
+
# Define the time window (6 hours)
|
| 859 |
+
time_window = pd.Timedelta(hours=6)
|
| 860 |
|
| 861 |
+
# Calculate the moving averages for each timestamp
|
| 862 |
for i, row in avg_apr_data_with_ma.iterrows():
|
| 863 |
current_time = row['timestamp']
|
| 864 |
window_start = current_time - time_window
|
| 865 |
|
| 866 |
+
# Get all data points within the 2-hour time window
|
| 867 |
window_data = apr_data[
|
| 868 |
(apr_data['timestamp'] >= window_start) &
|
| 869 |
(apr_data['timestamp'] <= current_time)
|
| 870 |
]
|
| 871 |
|
| 872 |
+
# Get all data points up to the current timestamp (infinite window)
|
| 873 |
+
infinite_window_data = apr_data[
|
| 874 |
+
apr_data['timestamp'] <= current_time
|
| 875 |
+
]
|
| 876 |
+
|
| 877 |
+
# Calculate the average APR for the 2-hour time window
|
| 878 |
if not window_data.empty:
|
| 879 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = window_data['apr'].mean()
|
| 880 |
else:
|
| 881 |
# If no data points in the window, use the current value
|
| 882 |
avg_apr_data_with_ma.at[i, 'moving_avg'] = row['apr']
|
| 883 |
+
|
| 884 |
+
# Calculate the average APR for the infinite window
|
| 885 |
+
if not infinite_window_data.empty:
|
| 886 |
+
avg_apr_data_with_ma.at[i, 'infinite_avg'] = infinite_window_data['apr'].mean()
|
| 887 |
+
else:
|
| 888 |
+
avg_apr_data_with_ma.at[i, 'infinite_avg'] = row['apr']
|
| 889 |
|
| 890 |
+
# No longer showing individual agent data points in fallback graph as requested
|
| 891 |
+
logger.info("Skipping individual agent data points in fallback graph as requested")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 892 |
|
| 893 |
+
# Add 2-hour moving average as a line
|
| 894 |
+
simple_fig.add_trace(
|
| 895 |
+
go.Scatter(
|
| 896 |
+
x=avg_apr_data_with_ma['timestamp'],
|
| 897 |
+
y=avg_apr_data_with_ma['moving_avg'],
|
| 898 |
+
mode='lines',
|
| 899 |
+
name='Moving Average APR (6h window)',
|
| 900 |
+
line=dict(width=2, color='red') # Thinner line
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 901 |
)
|
| 902 |
+
)
|
| 903 |
|
| 904 |
+
# Add infinite window moving average as another line
|
| 905 |
simple_fig.add_trace(
|
| 906 |
go.Scatter(
|
| 907 |
x=avg_apr_data_with_ma['timestamp'],
|
| 908 |
+
y=avg_apr_data_with_ma['infinite_avg'],
|
| 909 |
mode='lines',
|
| 910 |
+
name='Cumulative Average APR (all data)',
|
| 911 |
+
line=dict(width=4, color='green') # Thicker solid line
|
| 912 |
)
|
| 913 |
)
|
| 914 |
|
|
|
|
| 922 |
width=1000
|
| 923 |
)
|
| 924 |
|
| 925 |
+
# No longer need the note about hidden agents since we're not showing individual agents
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 926 |
|
| 927 |
# Return the simple figure
|
| 928 |
return simple_fig
|