|
import matplotlib.pyplot as plt |
|
import io |
|
import streamlit as st |
|
from graphviz import Digraph |
|
|
|
class Visualization: |
|
def plot_intervention_statistics(self, intervention_stats): |
|
sessions_held = intervention_stats['Intervention Sessions Held'].values[0] |
|
sessions_not_held = intervention_stats['Intervention Sessions Not Held'].values[0] |
|
|
|
fig, ax = plt.subplots() |
|
ax.bar(['Intervention Sessions'], [sessions_held], label='Held', color='#358E66') |
|
ax.bar(['Intervention Sessions'], [sessions_not_held], bottom=[sessions_held], label='Not Held', color='#91D6B8') |
|
|
|
ax.text(0, sessions_held / 2, str(sessions_held), ha='center', va='center', color='white', fontweight='bold', fontsize=14) |
|
ax.text(0, sessions_held + sessions_not_held / 2, str(sessions_not_held), ha='center', va='center', color='black', fontweight='bold', fontsize=14) |
|
|
|
ax.set_ylabel('Dosage') |
|
ax.set_title('Intervention Dosage', fontsize=16) |
|
handles, labels = ax.get_legend_handles_labels() |
|
ax.legend(handles[::-1], labels[::-1]) |
|
|
|
ax.spines['top'].set_visible(False) |
|
ax.spines['right'].set_visible(False) |
|
|
|
st.pyplot(fig) |
|
return fig |
|
|
|
def plot_student_metrics(self, student_metrics_df, attendance_avg_stats, engagement_avg_stats): |
|
fig, ax = plt.subplots(figsize=(10, 6)) |
|
bar_width = 0.35 |
|
index = range(len(student_metrics_df)) |
|
|
|
attendance_bars = ax.bar( |
|
[i - bar_width / 2 for i in index], |
|
student_metrics_df['Attendance (%)'], |
|
width=bar_width, label='Attendance (%)', |
|
color='#005288', alpha=0.7 |
|
) |
|
engagement_bars = ax.bar( |
|
[i + bar_width / 2 for i in index], |
|
student_metrics_df['Engagement (%)'], |
|
width=bar_width, label='Engagement (%)', |
|
color='#3AB0FF', alpha=0.7 |
|
) |
|
|
|
for bar in attendance_bars: |
|
height = bar.get_height() |
|
ax.text(bar.get_x() + bar.get_width() / 2, height, f'{height:.0f}%', ha='center', va='bottom', color='black') |
|
|
|
for bar in engagement_bars: |
|
height = bar.get_height() |
|
ax.text(bar.get_x() + bar.get_width() / 2, height, f'{height:.0f}%', ha='center', va='bottom', color='black') |
|
|
|
|
|
x_min, x_max = ax.get_xlim() |
|
|
|
|
|
ax.fill_betweenx(y=[90, 100], x1=x_min, x2=x_max, color='#005288', alpha=0.2, label='Attendance Threshold: ≥ 90%') |
|
ax.fill_betweenx(y=[80, 90], x1=x_min, x2=x_max, color='#3AB0FF', alpha=0.2, label='Engagement Threshold: ≥ 80%') |
|
|
|
|
|
|
|
|
|
ax.axhline(y=attendance_avg_stats, color='#005288', linestyle='--', linewidth=1.5, label=f'Attendance Average: {attendance_avg_stats}%') |
|
ax.axhline(y=engagement_avg_stats, color='#3AB0FF', linestyle='--', linewidth=1.5, label=f'Engagement Average: {engagement_avg_stats}%') |
|
|
|
|
|
ax.set_xlim(left=x_min, right=x_max) |
|
|
|
ax.set_xlabel('Student') |
|
ax.set_ylabel('Percentage (%)') |
|
ax.set_title('Student Attendance and Engagement Metrics') |
|
ax.legend(loc='upper right', frameon=False) |
|
ax.set_xticks(index) |
|
ax.set_xticklabels(student_metrics_df['Student'], rotation=0, ha='right') |
|
ax.set_ylim(0, 140) |
|
ax.yaxis.set_ticks(range(0, 124, 25)) |
|
|
|
ax.spines['top'].set_visible(False) |
|
ax.spines['right'].set_visible(False) |
|
|
|
plt.tight_layout() |
|
st.pyplot(fig) |
|
return fig |
|
|
|
def build_tree_diagram(self, row): |
|
dot = Digraph() |
|
|
|
|
|
student_name = row['Student'] |
|
dot.node("Student", student_name) |
|
|
|
|
|
dot.edge("Student", "Q1") |
|
|
|
|
|
dot.node("Q1", "Has the student attended ≥ 90% of interventions?") |
|
|
|
if row["Attended ≥ 90%"] == "No": |
|
|
|
dot.node("A1", "Address Attendance", shape="box") |
|
dot.edge("Q1", "A1", label="No") |
|
else: |
|
|
|
dot.node("Q2", "Has the student been engaged ≥ 80% of intervention time?") |
|
dot.edge("Q1", "Q2", label="Yes") |
|
|
|
if row["Engagement ≥ 80%"] == "No": |
|
|
|
dot.node("A2", "Address Engagement", shape="box") |
|
dot.edge("Q2", "A2", label="No") |
|
else: |
|
|
|
dot.node("A3", "Consider barriers, fidelity, and progress monitoring", shape="box") |
|
dot.edge("Q2", "A3", label="Yes") |
|
|
|
return dot |
|
|
|
def download_chart(self, fig, filename): |
|
buffer = io.BytesIO() |
|
fig.savefig(buffer, format='png') |
|
buffer.seek(0) |
|
st.download_button(label="Download Chart", data=buffer, file_name=filename, mime='image/png', icon="📊", use_container_width=True) |
|
|