Spaces:
Sleeping
Sleeping
Download src/streamlit_app.py from hacendado/LabelDashboard: direct link, hf CLI and curl.
- Browser
- Download file 10.4 kB
-
https://huggingface.co/spaces/hacendado/LabelDashboard/resolve/main/src/streamlit_app.py
- Command line
-
hf download hf://spaces/hacendado/LabelDashboard/src/streamlit_app.py
-
curl -L -o streamlit_app.py https://huggingface.co/spaces/hacendado/LabelDashboard/resolve/main/src/streamlit_app.py
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 | |
| def get_data_processor(): | |
| return DataProcessor() | |
| # Load and cache data | |
| # Cache for 5 minutes | |
| def load_annotation_data(): | |
| processor = get_data_processor() | |
| return processor.process_annotations() | |
| 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() |