Spaces:
Sleeping
Sleeping
devjas1
commited on
Commit
·
a044ede
1
Parent(s):
5824afe
(FEAT): Adds educational interface for interactive learning system
Browse filesIntroduces a comprehensive educational interface for POLYMEROS, enabling interactive learning in polymer science and AI.
Implements features such as competency assessments, personalized learning paths, and a virtual laboratory, enhancing user engagement and adaptive learning capabilities.
Establishes session management to track user progress and preferences, allowing for tailored recommendations and analytics.
Improves overall learning experience by providing structured educational tools within a user-friendly environment.
- pages/Educational_Interface.py +405 -0
pages/Educational_Interface.py
ADDED
@@ -0,0 +1,405 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Educational Interface Page for POLYMEROS
|
3 |
+
Interactive learning system with adaptive progression and virtual laboratory
|
4 |
+
"""
|
5 |
+
|
6 |
+
import streamlit as st
|
7 |
+
import numpy as np
|
8 |
+
import matplotlib.pyplot as plt
|
9 |
+
import json
|
10 |
+
from typing import Dict, List, Any
|
11 |
+
|
12 |
+
# Import POLYMEROS educational components
|
13 |
+
import sys
|
14 |
+
import os
|
15 |
+
|
16 |
+
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "modules"))
|
17 |
+
|
18 |
+
from modules.educational_framework import EducationalFramework
|
19 |
+
|
20 |
+
|
21 |
+
def init_educational_session():
|
22 |
+
"""Initialize educational session state"""
|
23 |
+
if "educational_framework" not in st.session_state:
|
24 |
+
st.session_state.educational_framework = EducationalFramework()
|
25 |
+
|
26 |
+
if "current_user_id" not in st.session_state:
|
27 |
+
st.session_state.current_user_id = "demo_user"
|
28 |
+
|
29 |
+
if "user_progress" not in st.session_state:
|
30 |
+
st.session_state.user_progress = (
|
31 |
+
st.session_state.educational_framework.initialize_user(
|
32 |
+
st.session_state.current_user_id
|
33 |
+
)
|
34 |
+
)
|
35 |
+
|
36 |
+
|
37 |
+
def render_competency_assessment():
|
38 |
+
"""Render interactive competency assessment"""
|
39 |
+
st.header("🧪 Knowledge Assessment")
|
40 |
+
|
41 |
+
domains = ["spectroscopy_basics", "polymer_aging", "ai_ml_concepts"]
|
42 |
+
selected_domain = st.selectbox(
|
43 |
+
"Select assessment domain:",
|
44 |
+
domains,
|
45 |
+
format_func=lambda x: x.replace("_", " ").title(),
|
46 |
+
)
|
47 |
+
|
48 |
+
framework = st.session_state.educational_framework
|
49 |
+
assessor = framework.competency_assessor
|
50 |
+
|
51 |
+
if selected_domain in assessor.assessment_tasks:
|
52 |
+
tasks = assessor.assessment_tasks[selected_domain]
|
53 |
+
|
54 |
+
st.subheader(f"Assessment: {selected_domain.replace('_', ' ').title()}")
|
55 |
+
|
56 |
+
responses = []
|
57 |
+
for i, task in enumerate(tasks):
|
58 |
+
st.write(f"**Question {i+1}:** {task['question']}")
|
59 |
+
|
60 |
+
response = st.radio(
|
61 |
+
f"Select answer for question {i+1}:",
|
62 |
+
options=range(len(task["options"])),
|
63 |
+
format_func=lambda x, task=task: task["options"][x],
|
64 |
+
key=f"q_{selected_domain}_{i}",
|
65 |
+
index=0,
|
66 |
+
)
|
67 |
+
responses.append(response)
|
68 |
+
|
69 |
+
if st.button("Submit Assessment", key=f"submit_{selected_domain}"):
|
70 |
+
results = framework.assess_user_competency(selected_domain, responses)
|
71 |
+
|
72 |
+
st.success(f"Assessment completed! Score: {results['score']:.1%}")
|
73 |
+
st.write(f"**Your level:** {results['level']}")
|
74 |
+
|
75 |
+
st.subheader("Detailed Feedback:")
|
76 |
+
for feedback in results["feedback"]:
|
77 |
+
st.write(feedback)
|
78 |
+
|
79 |
+
st.subheader("Recommendations:")
|
80 |
+
for rec in results["recommendations"]:
|
81 |
+
st.write(f"• {rec}")
|
82 |
+
|
83 |
+
|
84 |
+
def render_learning_path():
|
85 |
+
"""Render personalized learning path"""
|
86 |
+
st.header("🎯 Your Learning Path")
|
87 |
+
|
88 |
+
user_progress = st.session_state.user_progress
|
89 |
+
framework = st.session_state.educational_framework
|
90 |
+
|
91 |
+
# Display current progress
|
92 |
+
col1, col2, col3 = st.columns(3)
|
93 |
+
|
94 |
+
with col1:
|
95 |
+
st.metric("Completed Objectives", len(user_progress.completed_objectives))
|
96 |
+
|
97 |
+
with col2:
|
98 |
+
avg_score = (
|
99 |
+
np.mean(list(user_progress.competency_scores.values()))
|
100 |
+
if user_progress.competency_scores
|
101 |
+
else 0
|
102 |
+
)
|
103 |
+
st.metric("Average Score", f"{avg_score:.1%}")
|
104 |
+
|
105 |
+
with col3:
|
106 |
+
st.metric("Current Level", user_progress.current_level.title())
|
107 |
+
|
108 |
+
# Learning style selection
|
109 |
+
st.subheader("Learning Preferences")
|
110 |
+
learning_styles = ["visual", "hands-on", "theoretical", "collaborative"]
|
111 |
+
|
112 |
+
current_style = user_progress.preferred_learning_style
|
113 |
+
new_style = st.selectbox(
|
114 |
+
"Preferred learning style:",
|
115 |
+
learning_styles,
|
116 |
+
index=(
|
117 |
+
learning_styles.index(current_style)
|
118 |
+
if current_style in learning_styles
|
119 |
+
else 0
|
120 |
+
),
|
121 |
+
)
|
122 |
+
|
123 |
+
if new_style != current_style:
|
124 |
+
user_progress.preferred_learning_style = new_style
|
125 |
+
framework.save_user_progress()
|
126 |
+
st.success("Learning style updated!")
|
127 |
+
|
128 |
+
# Target competencies
|
129 |
+
st.subheader("Learning Goals")
|
130 |
+
target_competencies = st.multiselect(
|
131 |
+
"Select areas you want to focus on:",
|
132 |
+
["spectroscopy", "polymer_science", "machine_learning", "data_analysis"],
|
133 |
+
default=["spectroscopy", "polymer_science"],
|
134 |
+
)
|
135 |
+
|
136 |
+
if st.button("Generate Learning Path"):
|
137 |
+
learning_path = framework.get_personalized_learning_path(target_competencies)
|
138 |
+
|
139 |
+
if learning_path:
|
140 |
+
st.subheader("Recommended Learning Path:")
|
141 |
+
|
142 |
+
for i, item in enumerate(learning_path):
|
143 |
+
objective = item["objective"]
|
144 |
+
|
145 |
+
with st.expander(
|
146 |
+
f"{i+1}. {objective['title']} (Level {objective['difficulty_level']})"
|
147 |
+
):
|
148 |
+
st.write(f"**Description:** {objective['description']}")
|
149 |
+
st.write(
|
150 |
+
f"**Estimated time:** {objective['estimated_time']} minutes"
|
151 |
+
)
|
152 |
+
st.write(
|
153 |
+
f"**Recommended approach:** {item['recommended_approach']}"
|
154 |
+
)
|
155 |
+
|
156 |
+
if item["priority_resources"]:
|
157 |
+
st.write("**Priority resources:**")
|
158 |
+
for resource in item["priority_resources"]:
|
159 |
+
st.write(f"- {resource['type']}: {resource['url']}")
|
160 |
+
else:
|
161 |
+
st.info("Complete an assessment to get personalized recommendations!")
|
162 |
+
|
163 |
+
|
164 |
+
def render_virtual_laboratory():
|
165 |
+
"""Render virtual laboratory interface"""
|
166 |
+
st.header("🔬 Virtual Laboratory")
|
167 |
+
|
168 |
+
framework = st.session_state.educational_framework
|
169 |
+
virtual_lab = framework.virtual_lab
|
170 |
+
|
171 |
+
# Select experiment
|
172 |
+
experiments = list(virtual_lab.experiments.keys())
|
173 |
+
selected_experiment = st.selectbox(
|
174 |
+
"Select experiment:",
|
175 |
+
experiments,
|
176 |
+
format_func=lambda x: virtual_lab.experiments[x]["title"],
|
177 |
+
)
|
178 |
+
|
179 |
+
experiment_info = virtual_lab.experiments[selected_experiment]
|
180 |
+
|
181 |
+
st.subheader(experiment_info["title"])
|
182 |
+
st.write(f"**Description:** {experiment_info['description']}")
|
183 |
+
st.write(f"**Difficulty:** {experiment_info['difficulty']}/5")
|
184 |
+
st.write(f"**Estimated time:** {experiment_info['estimated_time']} minutes")
|
185 |
+
|
186 |
+
# Experiment-specific inputs
|
187 |
+
if selected_experiment == "polymer_identification":
|
188 |
+
st.subheader("Polymer Identification Challenge")
|
189 |
+
polymer_type = st.selectbox(
|
190 |
+
"Select polymer to analyze:", ["PE", "PP", "PS", "PVC"]
|
191 |
+
)
|
192 |
+
|
193 |
+
if st.button("Generate Spectrum"):
|
194 |
+
result = framework.run_virtual_experiment(
|
195 |
+
selected_experiment, {"polymer_type": polymer_type}
|
196 |
+
)
|
197 |
+
|
198 |
+
if result.get("success"):
|
199 |
+
# Plot the spectrum
|
200 |
+
fig, ax = plt.subplots(figsize=(10, 6))
|
201 |
+
ax.plot(result["wavenumbers"], result["spectrum"])
|
202 |
+
ax.set_xlabel("Wavenumber (cm⁻¹)")
|
203 |
+
ax.set_ylabel("Intensity")
|
204 |
+
ax.set_title(f"Unknown Polymer Spectrum")
|
205 |
+
ax.grid(True, alpha=0.3)
|
206 |
+
st.pyplot(fig)
|
207 |
+
|
208 |
+
st.subheader("Analysis Hints:")
|
209 |
+
for hint in result["hints"]:
|
210 |
+
st.write(f"💡 {hint}")
|
211 |
+
|
212 |
+
# User identification
|
213 |
+
user_guess = st.selectbox(
|
214 |
+
"Your identification:", ["PE", "PP", "PS", "PVC"]
|
215 |
+
)
|
216 |
+
if st.button("Submit Identification"):
|
217 |
+
if user_guess == polymer_type:
|
218 |
+
st.success("🎉 Correct! Well done!")
|
219 |
+
else:
|
220 |
+
st.error(f"❌ Incorrect. The correct answer is {polymer_type}")
|
221 |
+
|
222 |
+
elif selected_experiment == "aging_simulation":
|
223 |
+
st.subheader("Polymer Aging Simulation")
|
224 |
+
aging_time = st.slider("Aging time (hours):", 0, 200, 50)
|
225 |
+
|
226 |
+
if st.button("Run Aging Simulation"):
|
227 |
+
result = framework.run_virtual_experiment(
|
228 |
+
selected_experiment, {"aging_time": aging_time}
|
229 |
+
)
|
230 |
+
|
231 |
+
if result.get("success"):
|
232 |
+
# Plot comparison
|
233 |
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))
|
234 |
+
|
235 |
+
# Initial spectrum
|
236 |
+
ax1.plot(result["wavenumbers"], result["initial_spectrum"])
|
237 |
+
ax1.set_title("Initial Spectrum")
|
238 |
+
ax1.set_xlabel("Wavenumber (cm⁻¹)")
|
239 |
+
ax1.set_ylabel("Intensity")
|
240 |
+
ax1.grid(True, alpha=0.3)
|
241 |
+
|
242 |
+
# Aged spectrum
|
243 |
+
ax2.plot(result["wavenumbers"], result["aged_spectrum"])
|
244 |
+
ax2.set_title(f"After {aging_time} hours")
|
245 |
+
ax2.set_xlabel("Wavenumber (cm⁻¹)")
|
246 |
+
ax2.set_ylabel("Intensity")
|
247 |
+
ax2.grid(True, alpha=0.3)
|
248 |
+
|
249 |
+
plt.tight_layout()
|
250 |
+
st.pyplot(fig)
|
251 |
+
|
252 |
+
st.subheader("Observations:")
|
253 |
+
for obs in result["observations"]:
|
254 |
+
st.write(f"📊 {obs}")
|
255 |
+
|
256 |
+
elif selected_experiment == "model_training":
|
257 |
+
st.subheader("Train Your Own Model")
|
258 |
+
|
259 |
+
col1, col2 = st.columns(2)
|
260 |
+
with col1:
|
261 |
+
model_type = st.selectbox("Model type:", ["CNN", "ResNet", "Transformer"])
|
262 |
+
with col2:
|
263 |
+
epochs = st.slider("Training epochs:", 5, 50, 10)
|
264 |
+
|
265 |
+
if st.button("Start Training"):
|
266 |
+
with st.spinner("Training model..."):
|
267 |
+
result = framework.run_virtual_experiment(
|
268 |
+
selected_experiment, {"model_type": model_type, "epochs": epochs}
|
269 |
+
)
|
270 |
+
|
271 |
+
if result.get("success"):
|
272 |
+
# Plot training metrics
|
273 |
+
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
|
274 |
+
|
275 |
+
# Training loss
|
276 |
+
ax1.plot(result["train_losses"])
|
277 |
+
ax1.set_title("Training Loss")
|
278 |
+
ax1.set_xlabel("Epoch")
|
279 |
+
ax1.set_ylabel("Loss")
|
280 |
+
ax1.grid(True, alpha=0.3)
|
281 |
+
|
282 |
+
# Validation accuracy
|
283 |
+
ax2.plot(result["val_accuracies"])
|
284 |
+
ax2.set_title("Validation Accuracy")
|
285 |
+
ax2.set_xlabel("Epoch")
|
286 |
+
ax2.set_ylabel("Accuracy")
|
287 |
+
ax2.grid(True, alpha=0.3)
|
288 |
+
|
289 |
+
plt.tight_layout()
|
290 |
+
st.pyplot(fig)
|
291 |
+
|
292 |
+
st.success(
|
293 |
+
f"Training completed! Final accuracy: {result['final_accuracy']:.3f}"
|
294 |
+
)
|
295 |
+
|
296 |
+
st.subheader("Training Insights:")
|
297 |
+
for insight in result["insights"]:
|
298 |
+
st.write(f"🎯 {insight}")
|
299 |
+
|
300 |
+
|
301 |
+
def render_progress_analytics():
|
302 |
+
"""Render learning analytics dashboard"""
|
303 |
+
st.header("📊 Your Progress Analytics")
|
304 |
+
|
305 |
+
framework = st.session_state.educational_framework
|
306 |
+
analytics = framework.get_learning_analytics()
|
307 |
+
|
308 |
+
if analytics:
|
309 |
+
# Overview metrics
|
310 |
+
col1, col2, col3, col4 = st.columns(4)
|
311 |
+
|
312 |
+
with col1:
|
313 |
+
st.metric("Completed Objectives", analytics["completed_objectives"])
|
314 |
+
|
315 |
+
with col2:
|
316 |
+
st.metric("Study Time", f"{analytics['total_study_time']} min")
|
317 |
+
|
318 |
+
with col3:
|
319 |
+
st.metric("Current Level", analytics["current_level"].title())
|
320 |
+
|
321 |
+
with col4:
|
322 |
+
st.metric("Sessions", analytics["session_count"])
|
323 |
+
|
324 |
+
# Competency scores
|
325 |
+
if analytics["competency_scores"]:
|
326 |
+
st.subheader("Competency Scores")
|
327 |
+
|
328 |
+
domains = list(analytics["competency_scores"].keys())
|
329 |
+
scores = list(analytics["competency_scores"].values())
|
330 |
+
|
331 |
+
fig, ax = plt.subplots(figsize=(10, 6))
|
332 |
+
bars = ax.bar(domains, scores)
|
333 |
+
ax.set_ylabel("Score")
|
334 |
+
ax.set_title("Competency Assessment Results")
|
335 |
+
ax.set_ylim(0, 1)
|
336 |
+
|
337 |
+
# Color bars based on score
|
338 |
+
for bar, score in zip(bars, scores):
|
339 |
+
if score >= 0.8:
|
340 |
+
bar.set_color("green")
|
341 |
+
elif score >= 0.6:
|
342 |
+
bar.set_color("orange")
|
343 |
+
else:
|
344 |
+
bar.set_color("red")
|
345 |
+
|
346 |
+
plt.xticks(rotation=45)
|
347 |
+
plt.tight_layout()
|
348 |
+
st.pyplot(fig)
|
349 |
+
|
350 |
+
# Learning style
|
351 |
+
st.subheader("Learning Profile")
|
352 |
+
st.write(f"**Preferred learning style:** {analytics['learning_style'].title()}")
|
353 |
+
|
354 |
+
# Recommendations
|
355 |
+
recommendations = framework.get_learning_recommendations()
|
356 |
+
if recommendations:
|
357 |
+
st.subheader("Next Steps")
|
358 |
+
for rec in recommendations:
|
359 |
+
st.write(f"• {rec}")
|
360 |
+
else:
|
361 |
+
st.info("Complete assessments to see your progress analytics!")
|
362 |
+
|
363 |
+
|
364 |
+
def main():
|
365 |
+
"""Main educational interface"""
|
366 |
+
st.set_page_config(
|
367 |
+
page_title="POLYMEROS Educational Interface", page_icon="🎓", layout="wide"
|
368 |
+
)
|
369 |
+
|
370 |
+
st.title("🎓 POLYMEROS Educational Interface")
|
371 |
+
st.markdown("**Interactive Learning System for Polymer Science and AI**")
|
372 |
+
|
373 |
+
# Initialize session
|
374 |
+
init_educational_session()
|
375 |
+
|
376 |
+
# Sidebar navigation
|
377 |
+
st.sidebar.title("📚 Learning Modules")
|
378 |
+
page = st.sidebar.selectbox(
|
379 |
+
"Select module:",
|
380 |
+
[
|
381 |
+
"Knowledge Assessment",
|
382 |
+
"Learning Path",
|
383 |
+
"Virtual Laboratory",
|
384 |
+
"Progress Analytics",
|
385 |
+
],
|
386 |
+
)
|
387 |
+
|
388 |
+
# Render selected page
|
389 |
+
if page == "Knowledge Assessment":
|
390 |
+
render_competency_assessment()
|
391 |
+
elif page == "Learning Path":
|
392 |
+
render_learning_path()
|
393 |
+
elif page == "Virtual Laboratory":
|
394 |
+
render_virtual_laboratory()
|
395 |
+
elif page == "Progress Analytics":
|
396 |
+
render_progress_analytics()
|
397 |
+
|
398 |
+
# Footer
|
399 |
+
st.sidebar.markdown("---")
|
400 |
+
st.sidebar.markdown("**POLYMEROS Educational Framework**")
|
401 |
+
st.sidebar.markdown("*Adaptive learning for polymer science*")
|
402 |
+
|
403 |
+
|
404 |
+
if __name__ == "__main__":
|
405 |
+
main()
|