LabelDashboard / src /streamlit_app.py
Alvaro Hidalgo Romera
added dashboard connected to GCS
0c2bb61
Raw History Blame Contribute Delete
10.4 kB
import streamlit as st
import pandas as pd
import plotly.express as px
from datetime import datetime
from data_processor import DataProcessor
# Configure page
st.set_page_config(
page_title="Label Dashboard",
page_icon="πŸ“Š",
layout="wide",
initial_sidebar_state="expanded"
)
# Initialize data processor
@st.cache_resource
def get_data_processor():
return DataProcessor()
# Load and cache data
@st.cache_data(ttl=300) # Cache for 5 minutes
def load_annotation_data():
processor = get_data_processor()
return processor.process_annotations()
@st.cache_data(ttl=300)
def load_annotations_dataframe():
processor = get_data_processor()
return processor.get_annotations_dataframe()
# Add cache clearing functionality
def clear_cache():
st.cache_data.clear()
st.cache_resource.clear()
def main():
st.title("πŸ“Š Label Dashboard")
st.markdown("---")
# Add cache clear button in sidebar
with st.sidebar:
if st.button("Clear Cache & Reload"):
clear_cache()
st.rerun()
# Load data
with st.spinner("Loading annotation data..."):
try:
metrics = load_annotation_data()
df = load_annotations_dataframe()
if metrics.total_annotations == 0:
st.warning("No annotation data found. Please check your environment configuration.")
return
except Exception as e:
st.error(f"Error loading data: {e}")
st.error("Try clicking 'Clear Cache & Reload' in the sidebar if this persists")
return
# Main dashboard tabs
tab1, tab2, tab3, tab4 = st.tabs(["πŸ“ˆ Overview", "🎯 Accuracy", "πŸ‘₯ Productivity", "πŸ“… Timeline"])
# Overview Tab
with tab1:
st.header("Project Overview")
# Key metrics row
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric(
"Total Annotations",
metrics.total_annotations,
help="Total number of annotations processed"
)
with col2:
st.metric(
"Prediction Accuracy",
f"{metrics.prediction_accuracy:.1%}",
help="Percentage of predictions that were not corrected"
)
with col3:
st.metric(
"Avg Lead Time",
f"{metrics.avg_lead_time:.1f}s",
help="Average time to complete an annotation"
)
with col4:
st.metric(
"Correction Rate",
f"{metrics.correction_rate:.1%}",
help="Percentage of predictions that were corrected"
)
# Label distribution
st.subheader("Label Distribution")
if metrics.label_distribution:
label_df = pd.DataFrame(
list(metrics.label_distribution.items()),
columns=['Label', 'Count']
)
fig = px.pie(
label_df,
values='Count',
names='Label',
title="Distribution of Labels"
)
st.plotly_chart(fig, use_container_width=True)
else:
st.info("No label data available.")
# Accuracy Tab
with tab2:
st.header("Prediction Accuracy Analysis")
# Accuracy metrics
col1, col2 = st.columns(2)
with col1:
# Accuracy pie chart
accuracy_data = pd.DataFrame({
'Status': ['Correct Predictions', 'Corrected Predictions'],
'Count': [
metrics.prediction_accuracy * metrics.total_annotations,
metrics.correction_rate * metrics.total_annotations
]
})
fig = px.pie(
accuracy_data,
values='Count',
names='Status',
title="Prediction Accuracy Breakdown",
color_discrete_map={
'Correct Predictions': '#2E8B57',
'Corrected Predictions': '#CD5C5C'
}
)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Accuracy by user
if not df.empty:
user_accuracy = df.groupby('user_email')['origin'].apply(
lambda x: (x == 'prediction').mean()
).reset_index()
user_accuracy.columns = ['User', 'Accuracy']
user_accuracy['Accuracy'] = user_accuracy['Accuracy'] * 100
fig = px.bar(
user_accuracy,
x='User',
y='Accuracy',
title="Prediction Accuracy by User",
labels={'Accuracy': 'Accuracy (%)'}
)
fig.update_xaxes(tickangle=45)
st.plotly_chart(fig, use_container_width=True)
# Productivity Tab
with tab3:
st.header("User Productivity")
# User productivity metrics
if metrics.annotations_per_user:
col1, col2 = st.columns(2)
with col1:
# Annotations per user
user_df = pd.DataFrame(
list(metrics.annotations_per_user.items()),
columns=['User', 'Annotations']
)
fig = px.bar(
user_df,
x='User',
y='Annotations',
title="Annotations per User"
)
fig.update_xaxes(tickangle=45)
st.plotly_chart(fig, use_container_width=True)
with col2:
# Average lead time by user
if not df.empty:
user_leadtime = df.groupby('user_email')['lead_time'].mean().reset_index()
user_leadtime.columns = ['User', 'Avg Lead Time']
fig = px.bar(
user_leadtime,
x='User',
y='Avg Lead Time',
title="Average Lead Time by User",
labels={'Avg Lead Time': 'Lead Time (seconds)'}
)
fig.update_xaxes(tickangle=45)
st.plotly_chart(fig, use_container_width=True)
# Detailed user table
st.subheader("User Statistics")
if not df.empty:
user_stats = df.groupby('user_email').agg({
'id': 'count',
'lead_time': 'mean',
'origin': lambda x: (x == 'prediction').mean()
}).reset_index()
user_stats.columns = ['User', 'Total Annotations', 'Avg Lead Time', 'Accuracy']
user_stats['Accuracy'] = user_stats['Accuracy'] * 100
user_stats = user_stats.round(2)
st.dataframe(user_stats, use_container_width=True)
# Timeline Tab
with tab4:
st.header("Timeline Analysis")
# Daily throughput
if metrics.throughput_by_date:
throughput_df = pd.DataFrame(
list(metrics.throughput_by_date.items()),
columns=['Date', 'Annotations']
)
throughput_df['Date'] = pd.to_datetime(throughput_df['Date'])
throughput_df = throughput_df.sort_values('Date')
fig = px.line(
throughput_df,
x='Date',
y='Annotations',
title="Daily Annotation Throughput",
markers=True
)
st.plotly_chart(fig, use_container_width=True)
# Show throughput statistics
col1, col2, col3 = st.columns(3)
with col1:
st.metric(
"Peak Day",
int(throughput_df.loc[throughput_df['Annotations'].idxmax(), 'Annotations']),
help="Highest number of annotations in a single day"
)
with col2:
st.metric(
"Average Daily",
f"{throughput_df['Annotations'].mean():.1f}",
help="Average annotations per day"
)
with col3:
st.metric(
"Active Days",
len(throughput_df),
help="Number of days with annotation activity"
)
# Timeline with filters
st.subheader("Detailed Timeline")
if not df.empty:
# Date range filter
col1, col2 = st.columns(2)
with col1:
start_date = st.date_input(
"Start Date",
value=df['created_at'].min().date() if 'created_at' in df.columns else datetime.now().date()
)
with col2:
end_date = st.date_input(
"End Date",
value=df['created_at'].max().date() if 'created_at' in df.columns else datetime.now().date()
)
# Filter data
if 'created_at' in df.columns:
filtered_df = df[
(df['created_at'].dt.date >= start_date) &
(df['created_at'].dt.date <= end_date)
]
if not filtered_df.empty:
# Show filtered timeline
daily_stats = filtered_df.groupby(filtered_df['created_at'].dt.date).agg({
'id': 'count',
'lead_time': 'mean',
'origin': lambda x: (x == 'prediction').mean()
}).reset_index()
daily_stats.columns = ['Date', 'Count', 'Avg Lead Time', 'Accuracy']
daily_stats['Accuracy'] = daily_stats['Accuracy'] * 100
st.dataframe(daily_stats, use_container_width=True)
if __name__ == "__main__":
main()