Spaces:
Running
Running
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
|