Spaces:
Runtime error
Runtime error
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| import io | |
| import base64 | |
| # Pie chart for conflict prediction | |
| def create_conflict_pie_chart(result): | |
| fig, ax = plt.subplots(figsize=(3, 2)) | |
| # Handle missing confidence | |
| if 'confidence' in result and result['confidence'] is not None: | |
| confidence = result['confidence'] | |
| else: | |
| confidence = 0.8 # Default confidence when not available | |
| if result['conflict_level'] == 'High Risk': | |
| colors = ['#ff6b6b', '#4ecdc4'] | |
| sizes = [confidence, 1 - confidence] | |
| labels = ['High Risk', 'Low Risk'] | |
| else: | |
| colors = ['#4ecdc4', '#ff6b6b'] | |
| sizes = [confidence, 1 - confidence] | |
| labels = ['Low Risk', 'High Risk'] | |
| wedges, texts, autotexts = ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', | |
| startangle=90, explode=(0.1, 0)) | |
| # Update title to handle missing confidence | |
| if 'confidence' in result and result['confidence'] is not None: | |
| title = f'Conflict Risk Prediction\nConfidence: {confidence:.1%}' | |
| else: | |
| title = f'Conflict Risk Prediction\nConfidence: {confidence:.1%} (estimated)' | |
| ax.set_title(title, fontsize=10, fontweight='bold', pad=10) | |
| for autotext in autotexts: | |
| autotext.set_color('white') | |
| autotext.set_fontweight('bold') | |
| ax.legend(wedges, labels, title="Risk Levels", loc="center left", bbox_to_anchor=(1, 0, 0.5, 1)) | |
| plt.tight_layout() | |
| img_buffer = io.BytesIO() | |
| plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight') | |
| img_buffer.seek(0) | |
| img_base64 = base64.b64encode(img_buffer.getvalue()).decode() | |
| plt.close() | |
| return f"data:image/png;base64,{img_base64}" | |
| # Histogram for addiction score (not currently used, but included for completeness) | |
| def create_addiction_score_chart(result, data=None): | |
| fig, ax = plt.subplots(figsize=(3, 2)) | |
| if data is not None and 'Addicted_Score' in data.columns: | |
| scores = data['Addicted_Score'].dropna() | |
| else: | |
| np.random.seed(42) | |
| scores = np.random.normal(5.5, 1.5, 1000) | |
| scores = np.clip(scores, 1, 10) | |
| n, bins, patches = ax.hist(scores, bins=20, alpha=0.7, color='#4ecdc4', | |
| edgecolor='black', linewidth=0.5) | |
| predicted_score = result['predicted_score'] | |
| ax.axvline(x=predicted_score, color='#ff6b6b', linewidth=3, | |
| label=f'Your Prediction: {predicted_score:.2f}') | |
| if 'confidence' in result: | |
| confidence = result['confidence'] | |
| ax.axvspan(predicted_score - 0.5, predicted_score + 0.5, | |
| alpha=0.3, color='#ff6b6b', | |
| label=f'Confidence: {confidence:.2f}') | |
| ax.set_title('Addiction Score Distribution with Your Prediction', | |
| fontsize=10, fontweight='bold', pad=10) | |
| ax.set_xlabel('Addiction Score (1-10)', fontsize=8, fontweight='bold') | |
| ax.set_ylabel('Frequency', fontsize=8, fontweight='bold') | |
| ax.axvspan(1, 3, alpha=0.2, color='green', label='Low Addiction (1-3)') | |
| ax.axvspan(3, 7, alpha=0.2, color='orange', label='Moderate Addiction (3-7)') | |
| ax.axvspan(7, 10, alpha=0.2, color='red', label='High Addiction (7-10)') | |
| ax.legend(loc='upper right', fontsize=7) | |
| ax.grid(True, alpha=0.3) | |
| ax.set_xlim(0, 10) | |
| plt.tight_layout() | |
| img_buffer = io.BytesIO() | |
| plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight') | |
| img_buffer.seek(0) | |
| img_base64 = base64.b64encode(img_buffer.getvalue()).decode() | |
| plt.close() | |
| return f"data:image/png;base64,{img_base64}" | |
| # Gauge chart for addiction score | |
| def create_addiction_gauge_chart(result): | |
| fig, ax = plt.subplots(figsize=(3, 2), subplot_kw={'projection': 'polar'}) | |
| predicted_score = result['predicted_score'] | |
| angle = (predicted_score - 1) * 20 | |
| theta = np.linspace(0, np.pi, 100) | |
| # Reduce black line thickness by 30% (from 3 to 2.1) | |
| ax.plot(theta, [1]*100, 'k-', linewidth=2.1) | |
| # Flip colors over y-axis - now high scores are on the left (0) and low scores on the right (pi) | |
| high_angle = np.linspace(0, 2*20*np.pi/180, 50) | |
| ax.fill_between(high_angle, 0, 1, alpha=0.3, color='red', label='High (7-10)') | |
| mod_angle = np.linspace(2*20*np.pi/180, 6*20*np.pi/180, 50) | |
| ax.fill_between(mod_angle, 0, 1, alpha=0.3, color='orange', label='Moderate (3-7)') | |
| low_angle = np.linspace(6*20*np.pi/180, np.pi, 50) | |
| ax.fill_between(low_angle, 0, 1, alpha=0.3, color='green', label='Low (1-3)') | |
| needle_angle = angle * np.pi / 180 | |
| # Reduce needle line thickness by 30% (from 4 to 2.8) | |
| ax.plot([needle_angle, needle_angle], [0, 1.2], 'k-', linewidth=2.8, label=f'Your Score: {predicted_score:.1f}') | |
| # Reduce round dot size by 50% (from 10 to 5) | |
| ax.plot(needle_angle, 1.2, 'ko', markersize=5, markeredgecolor='white', markeredgewidth=2) | |
| ax.set_title(f'Addiction Score Gauge\nPredicted: {predicted_score:.1f}/10', | |
| fontsize=8, fontweight='bold', pad=10) | |
| ax.set_xticks([]) | |
| ax.set_yticks([]) | |
| ax.set_ylim(0, 1.3) | |
| # Flip the gauge by adjusting text positions and angles | |
| ax.text(np.pi, 1.4, 'Low\n(1-3)', ha='center', va='center', fontsize=3, fontweight='bold') | |
| ax.text(np.pi/2, 1.4, 'Moderate\n(3-7)', ha='center', va='center', fontsize=3, fontweight='bold') | |
| ax.text(0, 1.4, 'High\n(7-10)', ha='center', va='center', fontsize=3, fontweight='bold') | |
| if 'confidence' in result: | |
| confidence = result['confidence'] | |
| ax.text(0, -0.3, f'Confidence: {confidence:.2f}', ha='center', va='center', | |
| fontsize=6, fontweight='bold', bbox=dict(boxstyle="round,pad=0.3", facecolor="lightblue")) | |
| plt.tight_layout() | |
| img_buffer = io.BytesIO() | |
| plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight') | |
| img_buffer.seek(0) | |
| img_base64 = base64.b64encode(img_buffer.getvalue()).decode() | |
| plt.close() | |
| return f"data:image/png;base64,{img_base64}" | |
| # Clustering: Elbow and Sleep vs Age scatter plot | |
| def create_clustering_charts(result, cluster_df=None, user_sleep=None, user_age=None, user_cluster=None, cluster_labels_map=None): | |
| fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5)) | |
| optimal_k = 3 | |
| k_values = range(1, 11) | |
| inertias = [150, 120, 85, 65, 55, 50, 47, 45, 43, 42] | |
| ax1.plot(k_values, inertias, 'bo-', linewidth=2, markersize=8) | |
| ax1.set_xlabel('Number of Clusters (k)', fontweight='bold') | |
| ax1.set_ylabel('Inertia', fontweight='bold') | |
| ax1.set_title('Elbow Method: Optimal K Selection', fontsize=12, fontweight='bold') | |
| ax1.grid(True, alpha=0.3) | |
| ax1.axvline(x=optimal_k, color='red', linestyle='--', alpha=0.7, label=f'Optimal k = {optimal_k}') | |
| ax1.legend() | |
| # Scatter plot: Sleep vs Age colored by cluster (always 3 clusters/colors) | |
| if cluster_df is not None and cluster_labels_map is not None: | |
| colors = ['#4ecdc4', '#ffd93d', '#ff6b6b'] | |
| for cluster in range(optimal_k): | |
| sub = cluster_df[cluster_df['cluster'] == cluster] | |
| color = colors[cluster % len(colors)] | |
| label = cluster_labels_map.get(cluster, f'Cluster {cluster}') | |
| ax2.scatter(sub['Sleep_Hours_Per_Night'], sub['Age'], c=color, alpha=0.7, s=50, label=label) | |
| # Highlight the user's point | |
| if user_sleep is not None and user_age is not None and user_cluster is not None: | |
| color = colors[user_cluster % len(colors)] | |
| ax2.scatter([user_sleep], [user_age], c='red', marker='*', s=250, edgecolors='black', linewidths=2, label='You') | |
| ax2.set_xlabel('Sleep Hours per Night', fontweight='bold') | |
| ax2.set_ylabel('Age', fontweight='bold') | |
| ax2.set_title(f'Cluster Analysis: Sleep vs Age (k={optimal_k})', fontsize=12, fontweight='bold') | |
| handles, labels = ax2.get_legend_handles_labels() | |
| # Remove duplicate 'You' label if present | |
| seen = set() | |
| new_handles, new_labels = [], [] | |
| for h, l in zip(handles, labels): | |
| if l not in seen: | |
| new_handles.append(h) | |
| new_labels.append(l) | |
| seen.add(l) | |
| ax2.legend(new_handles, new_labels) | |
| ax2.grid(True, alpha=0.3) | |
| plt.tight_layout() | |
| img_buffer = io.BytesIO() | |
| plt.savefig(img_buffer, format='png', dpi=300, bbox_inches='tight') | |
| img_buffer.seek(0) | |
| img_base64 = base64.b64encode(img_buffer.getvalue()).decode() | |
| plt.close() | |
| return f"data:image/png;base64,{img_base64}" |