Spaces:
Sleeping
Sleeping
| import plotly.graph_objects as go | |
| import plotly.express as px | |
| from plotly.subplots import make_subplots | |
| import numpy as np | |
| from collections import Counter | |
| from typing import List, Dict, Optional | |
| from models import handle_errors, ThemeContext | |
| # Optimized Plotly Visualization System | |
| class PlotlyVisualizer: | |
| """Enhanced Plotly visualizations""" | |
| def create_sentiment_gauge(result: Dict, theme: ThemeContext) -> go.Figure: | |
| """Create animated sentiment gauge""" | |
| colors = theme.colors | |
| if result.get('has_neutral', False): | |
| # Three-way gauge | |
| fig = go.Figure(go.Indicator( | |
| mode="gauge+number+delta", | |
| value=result['pos_prob'] * 100, | |
| domain={'x': [0, 1], 'y': [0, 1]}, | |
| title={'text': f"Sentiment: {result['sentiment']}"}, | |
| delta={'reference': 50}, | |
| gauge={ | |
| 'axis': {'range': [None, 100]}, | |
| 'bar': {'color': colors['pos'] if result['sentiment'] == 'Positive' else colors['neg']}, | |
| 'steps': [ | |
| {'range': [0, 33], 'color': colors['neg']}, | |
| {'range': [33, 67], 'color': colors['neu']}, | |
| {'range': [67, 100], 'color': colors['pos']} | |
| ], | |
| 'threshold': { | |
| 'line': {'color': "red", 'width': 4}, | |
| 'thickness': 0.75, | |
| 'value': 90 | |
| } | |
| } | |
| )) | |
| else: | |
| # Two-way gauge | |
| fig = go.Figure(go.Indicator( | |
| mode="gauge+number", | |
| value=result['confidence'] * 100, | |
| domain={'x': [0, 1], 'y': [0, 1]}, | |
| title={'text': f"Confidence: {result['sentiment']}"}, | |
| gauge={ | |
| 'axis': {'range': [None, 100]}, | |
| 'bar': {'color': colors['pos'] if result['sentiment'] == 'Positive' else colors['neg']}, | |
| 'steps': [ | |
| {'range': [0, 50], 'color': "lightgray"}, | |
| {'range': [50, 100], 'color': "gray"} | |
| ] | |
| } | |
| )) | |
| fig.update_layout(height=400, font={'size': 16}) | |
| return fig | |
| def create_probability_bars(result: Dict, theme: ThemeContext) -> go.Figure: | |
| """Create probability bar chart""" | |
| colors = theme.colors | |
| if result.get('has_neutral', False): | |
| labels = ['Negative', 'Neutral', 'Positive'] | |
| values = [result['neg_prob'], result['neu_prob'], result['pos_prob']] | |
| bar_colors = [colors['neg'], colors['neu'], colors['pos']] | |
| else: | |
| labels = ['Negative', 'Positive'] | |
| values = [result['neg_prob'], result['pos_prob']] | |
| bar_colors = [colors['neg'], colors['pos']] | |
| fig = go.Figure(data=[ | |
| go.Bar(x=labels, y=values, marker_color=bar_colors, | |
| text=[f'{v:.3f}' for v in values], textposition='outside') | |
| ]) | |
| fig.update_layout( | |
| title="Sentiment Probabilities", | |
| yaxis_title="Probability", | |
| height=400, | |
| showlegend=False | |
| ) | |
| return fig | |
| def create_batch_summary(results: List[Dict], theme: ThemeContext) -> go.Figure: | |
| """Create batch analysis summary""" | |
| colors = theme.colors | |
| # Count sentiments | |
| sentiments = [r['sentiment'] for r in results if 'sentiment' in r and r['sentiment'] != 'Error'] | |
| sentiment_counts = Counter(sentiments) | |
| # Create pie chart | |
| fig = go.Figure(data=[go.Pie( | |
| labels=list(sentiment_counts.keys()), | |
| values=list(sentiment_counts.values()), | |
| marker_colors=[colors.get(s.lower()[:3], '#999999') for s in sentiment_counts.keys()], | |
| textinfo='label+percent', | |
| hole=0.3 | |
| )]) | |
| fig.update_layout( | |
| title=f"Batch Analysis Summary ({len(results)} texts)", | |
| height=400 | |
| ) | |
| return fig | |
| def create_confidence_distribution(results: List[Dict]) -> go.Figure: | |
| """Create confidence distribution plot""" | |
| confidences = [r['confidence'] for r in results if 'confidence' in r and r['sentiment'] != 'Error'] | |
| if not confidences: | |
| return go.Figure() | |
| fig = go.Figure(data=[go.Histogram( | |
| x=confidences, | |
| nbinsx=20, | |
| marker_color='skyblue', | |
| opacity=0.7 | |
| )]) | |
| fig.update_layout( | |
| title="Confidence Distribution", | |
| xaxis_title="Confidence Score", | |
| yaxis_title="Frequency", | |
| height=400 | |
| ) | |
| return fig | |
| def create_history_dashboard(history: List[Dict], theme: ThemeContext) -> go.Figure: | |
| """Create comprehensive history dashboard""" | |
| if len(history) < 2: | |
| return go.Figure() | |
| # Create subplots | |
| fig = make_subplots( | |
| rows=2, cols=2, | |
| subplot_titles=['Sentiment Timeline', 'Confidence Distribution', | |
| 'Language Distribution', 'Sentiment Summary'], | |
| specs=[[{"secondary_y": False}, {"secondary_y": False}], | |
| [{"type": "pie"}, {"type": "bar"}]] | |
| ) | |
| # Extract data | |
| indices = list(range(len(history))) | |
| pos_probs = [item.get('pos_prob', 0) for item in history] | |
| confidences = [item['confidence'] for item in history] | |
| sentiments = [item['sentiment'] for item in history] | |
| languages = [item.get('language', 'en') for item in history] | |
| # Sentiment timeline | |
| colors_map = {'Positive': theme.colors['pos'], 'Negative': theme.colors['neg'], 'Neutral': theme.colors['neu']} | |
| colors = [colors_map.get(s, '#999999') for s in sentiments] | |
| fig.add_trace( | |
| go.Scatter(x=indices, y=pos_probs, mode='lines+markers', | |
| marker=dict(color=colors, size=8), | |
| name='Positive Probability'), | |
| row=1, col=1 | |
| ) | |
| # Confidence distribution | |
| fig.add_trace( | |
| go.Histogram(x=confidences, nbinsx=10, name='Confidence'), | |
| row=1, col=2 | |
| ) | |
| # Language distribution | |
| lang_counts = Counter(languages) | |
| fig.add_trace( | |
| go.Pie(labels=list(lang_counts.keys()), values=list(lang_counts.values()), | |
| name="Languages"), | |
| row=2, col=1 | |
| ) | |
| # Sentiment summary | |
| sent_counts = Counter(sentiments) | |
| sent_colors = [colors_map.get(k, '#999999') for k in sent_counts.keys()] | |
| fig.add_trace( | |
| go.Bar(x=list(sent_counts.keys()), y=list(sent_counts.values()), | |
| marker_color=sent_colors), | |
| row=2, col=2 | |
| ) | |
| fig.update_layout(height=800, showlegend=False) | |
| return fig |