update docs
Browse files
app.py
CHANGED
@@ -5,135 +5,151 @@ from io import BytesIO
|
|
5 |
from PIL import Image
|
6 |
import matplotlib.patches as mpatches
|
7 |
import mplcursors
|
|
|
8 |
|
9 |
-
# Initialize the lesson plan graph as a directed graph
|
10 |
-
lesson_graph = nx.DiGraph()
|
11 |
-
|
12 |
-
# Define color map for node types
|
13 |
-
color_map = {
|
14 |
-
"User": "#FF9999", # Light Red
|
15 |
-
"Subject": "#66B2FF", # Light Blue
|
16 |
-
"Grade Level": "#99FF99", # Light Green
|
17 |
-
"Learning Objective": "#FFCC99", # Light Orange
|
18 |
-
"Activity": "#FF99FF", # Light Purple
|
19 |
-
"Assessment": "#FFFF99", # Light Yellow
|
20 |
-
"Resource": "#99FFFF", # Light Cyan
|
21 |
-
"School Board": "#CCCCCC" # Light Gray
|
22 |
-
}
|
23 |
-
|
24 |
-
def add_to_graph(teacher_name, subject, grade_level, learning_objective, activity, assessment, resource, school_board):
|
25 |
-
global lesson_graph
|
26 |
-
|
27 |
-
# Clear previous graph
|
28 |
-
lesson_graph.clear()
|
29 |
-
|
30 |
-
# Add nodes to the graph with more properties
|
31 |
-
lesson_graph.add_node(teacher_name, type="User", role="Teacher")
|
32 |
-
lesson_graph.add_node(subject, type="Subject", description="Core subject area")
|
33 |
-
lesson_graph.add_node(grade_level, type="Grade Level", description="Target grade for the lesson")
|
34 |
-
lesson_graph.add_node(learning_objective, type="Learning Objective", description="Main goal of the lesson")
|
35 |
-
lesson_graph.add_node(activity, type="Activity", description="Main class activity")
|
36 |
-
lesson_graph.add_node(assessment, type="Assessment", description="Method of evaluating learning")
|
37 |
-
lesson_graph.add_node(resource, type="Resource", description="Materials needed for the lesson")
|
38 |
-
lesson_graph.add_node(school_board, type="School Board", description="Governing educational body")
|
39 |
-
|
40 |
-
# Add edges to the graph (maintaining directional relationships)
|
41 |
-
lesson_graph.add_edge(teacher_name, subject, relationship="TEACHES")
|
42 |
-
lesson_graph.add_edge(subject, learning_objective, relationship="COVERS")
|
43 |
-
lesson_graph.add_edge(subject, grade_level, relationship="HAS_GRADE")
|
44 |
-
lesson_graph.add_edge(activity, learning_objective, relationship="ACHIEVES")
|
45 |
-
lesson_graph.add_edge(activity, resource, relationship="REQUIRES")
|
46 |
-
lesson_graph.add_edge(learning_objective, assessment, relationship="EVALUATED_BY")
|
47 |
-
lesson_graph.add_edge(teacher_name, school_board, relationship="BELONGS_TO")
|
48 |
-
lesson_graph.add_edge(learning_objective, school_board, relationship="ALIGNS_WITH")
|
49 |
-
|
50 |
-
# Generate search string
|
51 |
-
search_string = f"{subject} {grade_level} {learning_objective} {activity} {resource}".strip()
|
52 |
-
|
53 |
-
# Visualize the graph using Matplotlib
|
54 |
-
fig, ax = plt.subplots(figsize=(14, 10))
|
55 |
-
pos = nx.spring_layout(lesson_graph, k=0.9, iterations=50)
|
56 |
-
|
57 |
-
# Draw nodes with color coding
|
58 |
-
node_colors = [color_map[lesson_graph.nodes[node]['type']] for node in lesson_graph.nodes()]
|
59 |
-
nx.draw_networkx_nodes(lesson_graph, pos, node_color=node_colors, node_size=3000, alpha=0.8, ax=ax)
|
60 |
-
|
61 |
-
# Draw edges with arrows to show direction
|
62 |
-
nx.draw_networkx_edges(lesson_graph, pos, edge_color='gray', arrows=True, arrowsize=20, ax=ax)
|
63 |
-
nx.draw_networkx_labels(lesson_graph, pos, font_size=10, font_weight="bold", ax=ax)
|
64 |
-
|
65 |
-
# Add edge labels
|
66 |
-
edge_labels = nx.get_edge_attributes(lesson_graph, 'relationship')
|
67 |
-
nx.draw_networkx_edge_labels(lesson_graph, pos, edge_labels=edge_labels, font_size=8, ax=ax)
|
68 |
-
|
69 |
-
# Create a legend that categorizes node types
|
70 |
-
legend_elements = [mpatches.Patch(color=color, label=node_type) for node_type, color in color_map.items()]
|
71 |
-
plt.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(1, 1), title="Node Types")
|
72 |
-
|
73 |
-
plt.title("Your Educational Landscape", fontsize=16)
|
74 |
-
plt.axis('off')
|
75 |
-
plt.tight_layout()
|
76 |
-
|
77 |
-
# Add hover functionality
|
78 |
-
cursor = mplcursors.cursor(hover=True)
|
79 |
-
|
80 |
-
@cursor.connect("add")
|
81 |
-
def on_add(sel):
|
82 |
-
node = list(lesson_graph.nodes())[sel.target.index]
|
83 |
-
node_data = lesson_graph.nodes[node]
|
84 |
-
sel.annotation.set_text(f"Node: {node}\nType: {node_data['type']}\n{node_data.get('description', '')}")
|
85 |
-
|
86 |
-
# Save the plot to a bytes object
|
87 |
-
buf = BytesIO()
|
88 |
-
plt.savefig(buf, format="png", dpi=300, bbox_inches="tight")
|
89 |
-
buf.seek(0)
|
90 |
-
plt.close(fig)
|
91 |
-
|
92 |
-
# Convert BytesIO to PIL Image
|
93 |
-
image = Image.open(buf)
|
94 |
-
|
95 |
-
return search_string, image
|
96 |
-
|
97 |
-
def clear_graph():
|
98 |
-
global lesson_graph
|
99 |
-
lesson_graph.clear()
|
100 |
-
return "Landscape cleared. You can start a new lesson plan."
|
101 |
|
102 |
-
|
|
|
|
|
|
|
|
|
103 |
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
|
106 |
-
def
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
"
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
"relationship": lesson_graph.edges[u, v]["relationship"]
|
123 |
-
}
|
124 |
-
for u, v in lesson_graph.edges()
|
125 |
-
]
|
126 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
|
128 |
-
#
|
129 |
-
|
|
|
130 |
|
131 |
-
|
132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
|
138 |
# Gradio interface
|
139 |
demo = gr.Blocks()
|
@@ -160,9 +176,9 @@ with demo:
|
|
160 |
|
161 |
with gr.Row():
|
162 |
generate_btn = gr.Button("Map Your Lesson Plan")
|
|
|
163 |
clear_btn = gr.Button("Clear Landscape")
|
164 |
|
165 |
-
|
166 |
examples = [
|
167 |
["Sarah Johnson", "Oakville District School Board", "Earth Science", "Grade 7", "Understand the water cycle and its impact on Earth's climate", "Create a terrarium to model the water cycle", "Group presentation on terrarium observations", "Terrarium kit, climate diagrams"],
|
168 |
["Marek Nowak", "Warsaw School District", "Matematyka", "Klasa 2", "Zrozumienie podstawowych operacji matematycznych", "Rozwiązywanie prostych zadań tekstowych", "Praca grupowa nad rozwiązywaniem zadań", "Podręcznik, karty pracy, tablica interaktywna"]
|
@@ -172,21 +188,47 @@ with demo:
|
|
172 |
|
173 |
search_output = gr.Textbox(label="Content Discovery Search String")
|
174 |
graph_output = gr.Image(label="Your Educational Landscape")
|
175 |
-
graph_btn = gr.Button("Display Graph (JSON)")
|
176 |
message_output = gr.Textbox(label="Landscape Status")
|
177 |
|
178 |
generate_btn.click(
|
179 |
-
|
180 |
inputs=[teacher_name, subject, grade_level, learning_objective, activity, assessment, resource, school_board],
|
181 |
outputs=[search_output, graph_output]
|
182 |
)
|
183 |
|
184 |
graph_btn.click(
|
185 |
-
graph_to_json,
|
186 |
outputs=[message_output]
|
187 |
)
|
188 |
|
189 |
-
clear_btn.click(clear_graph, outputs=message_output)
|
|
|
|
|
|
|
|
|
|
|
|
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
# Launch the EduScape app
|
192 |
demo.launch()
|
|
|
|
5 |
from PIL import Image
|
6 |
import matplotlib.patches as mpatches
|
7 |
import mplcursors
|
8 |
+
import json
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
+
class LessonGraph:
|
12 |
+
"""
|
13 |
+
Class to handle the lesson plan graph construction and manipulation.
|
14 |
+
This encapsulates graph-related logic and avoids using global variables.
|
15 |
+
"""
|
16 |
|
17 |
+
def __init__(self):
|
18 |
+
self.graph = nx.DiGraph()
|
19 |
+
self.color_map = {
|
20 |
+
"User": "#FF9999", # Light Red
|
21 |
+
"Subject": "#66B2FF", # Light Blue
|
22 |
+
"Grade Level": "#99FF99", # Light Green
|
23 |
+
"Learning Objective": "#FFCC99", # Light Orange
|
24 |
+
"Activity": "#FF99FF", # Light Purple
|
25 |
+
"Assessment": "#FFFF99", # Light Yellow
|
26 |
+
"Resource": "#99FFFF", # Light Cyan
|
27 |
+
"School Board": "#CCCCCC" # Light Gray
|
28 |
+
}
|
29 |
|
30 |
+
def add_lesson_plan(self, teacher_name, subject, grade_level, learning_objective, activity, assessment, resource, school_board):
|
31 |
+
"""
|
32 |
+
Add nodes and edges to the lesson plan graph for the given inputs.
|
33 |
+
"""
|
34 |
+
self.graph.clear() # Clear previous graph
|
35 |
+
|
36 |
+
# Define node details and add them to the graph
|
37 |
+
nodes = {
|
38 |
+
teacher_name: {"type": "User", "role": "Teacher"},
|
39 |
+
subject: {"type": "Subject", "description": "Core subject area"},
|
40 |
+
grade_level: {"type": "Grade Level", "description": "Target grade for the lesson"},
|
41 |
+
learning_objective: {"type": "Learning Objective", "description": "Main goal of the lesson"},
|
42 |
+
activity: {"type": "Activity", "description": "Main class activity"},
|
43 |
+
assessment: {"type": "Assessment", "description": "Method of evaluating learning"},
|
44 |
+
resource: {"type": "Resource", "description": "Materials needed for the lesson"},
|
45 |
+
school_board: {"type": "School Board", "description": "Governing educational body"}
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
+
|
48 |
+
for node, attributes in nodes.items():
|
49 |
+
self.graph.add_node(node, **attributes)
|
50 |
+
|
51 |
+
# Define the relationships between nodes
|
52 |
+
self.graph.add_edges_from([
|
53 |
+
(teacher_name, subject, {"relationship": "TEACHES"}),
|
54 |
+
(subject, learning_objective, {"relationship": "COVERS"}),
|
55 |
+
(subject, grade_level, {"relationship": "HAS_GRADE"}),
|
56 |
+
(activity, learning_objective, {"relationship": "ACHIEVES"}),
|
57 |
+
(activity, resource, {"relationship": "REQUIRES"}),
|
58 |
+
(learning_objective, assessment, {"relationship": "EVALUATED_BY"}),
|
59 |
+
(teacher_name, school_board, {"relationship": "BELONGS_TO"}),
|
60 |
+
(learning_objective, school_board, {"relationship": "ALIGNS_WITH"})
|
61 |
+
])
|
62 |
+
|
63 |
+
# Return search string for content discovery
|
64 |
+
return f"{subject} {grade_level} {learning_objective} {activity} {resource}".strip()
|
65 |
+
|
66 |
+
def draw_graph(self):
|
67 |
+
"""
|
68 |
+
Visualize the graph using Matplotlib, handling layout, labels, and interactivity.
|
69 |
+
"""
|
70 |
+
fig, ax = plt.subplots(figsize=(14, 10))
|
71 |
+
pos = nx.spring_layout(self.graph, k=0.9, iterations=50)
|
72 |
+
|
73 |
+
# Draw nodes with color coding
|
74 |
+
node_colors = [self.color_map[self.graph.nodes[node]['type']] for node in self.graph.nodes()]
|
75 |
+
nx.draw_networkx_nodes(self.graph, pos, node_color=node_colors, node_size=3000, alpha=0.8, ax=ax)
|
76 |
+
|
77 |
+
# Draw edges and labels
|
78 |
+
nx.draw_networkx_edges(self.graph, pos, edge_color='gray', arrows=True, arrowsize=20, ax=ax)
|
79 |
+
nx.draw_networkx_labels(self.graph, pos, font_size=10, font_weight="bold", ax=ax)
|
80 |
+
|
81 |
+
edge_labels = nx.get_edge_attributes(self.graph, 'relationship')
|
82 |
+
nx.draw_networkx_edge_labels(self.graph, pos, edge_labels=edge_labels, font_size=8, ax=ax)
|
83 |
|
84 |
+
# Add legend for node types
|
85 |
+
legend_elements = [mpatches.Patch(color=color, label=node_type) for node_type, color in self.color_map.items()]
|
86 |
+
plt.legend(handles=legend_elements, loc='upper left', bbox_to_anchor=(1, 1), title="Node Types")
|
87 |
|
88 |
+
plt.title("Your Educational Landscape", fontsize=16)
|
89 |
+
plt.axis('off')
|
90 |
+
plt.tight_layout()
|
91 |
+
|
92 |
+
# Add interactivity for hovering over nodes
|
93 |
+
cursor = mplcursors.cursor(hover=True)
|
94 |
+
@cursor.connect("add")
|
95 |
+
def on_add(sel):
|
96 |
+
node = list(self.graph.nodes())[sel.target.index]
|
97 |
+
node_data = self.graph.nodes[node]
|
98 |
+
sel.annotation.set_text(f"Node: {node}\nType: {node_data['type']}\n{node_data.get('description', '')}")
|
99 |
+
|
100 |
+
# Save the plot to a BytesIO object
|
101 |
+
buf = BytesIO()
|
102 |
+
plt.savefig(buf, format="png", dpi=300, bbox_inches="tight")
|
103 |
+
buf.seek(0)
|
104 |
+
plt.close(fig)
|
105 |
+
|
106 |
+
return Image.open(buf)
|
107 |
+
|
108 |
+
def clear_graph(self):
|
109 |
+
"""
|
110 |
+
Clears the lesson plan graph, allowing users to start fresh.
|
111 |
+
"""
|
112 |
+
self.graph.clear()
|
113 |
+
return "Landscape cleared. You can start a new lesson plan."
|
114 |
+
|
115 |
+
def graph_to_json(self):
|
116 |
+
"""
|
117 |
+
Converts the current lesson plan graph into a JSON string format and returns the result.
|
118 |
|
119 |
+
Returns:
|
120 |
+
- str: JSON string representation of the graph or an error message.
|
121 |
+
"""
|
122 |
+
try:
|
123 |
+
# Convert the lesson_graph to a dictionary format
|
124 |
+
graph_data = {
|
125 |
+
"nodes": [
|
126 |
+
{
|
127 |
+
"id": node,
|
128 |
+
"type": self.graph.nodes[node]["type"],
|
129 |
+
"description": self.graph.nodes[node].get("description", "")
|
130 |
+
}
|
131 |
+
for node in self.graph.nodes()
|
132 |
+
],
|
133 |
+
"edges": [
|
134 |
+
{
|
135 |
+
"source": u,
|
136 |
+
"target": v,
|
137 |
+
"relationship": self.graph.edges[u, v]["relationship"]
|
138 |
+
}
|
139 |
+
for u, v in self.graph.edges()
|
140 |
+
]
|
141 |
+
}
|
142 |
+
|
143 |
+
# Convert dictionary to JSON string
|
144 |
+
return json.dumps(graph_data, indent=4)
|
145 |
+
|
146 |
+
except Exception as e:
|
147 |
+
# If any error occurs, catch it and display it in the message_output
|
148 |
+
return f"An error occurred: {str(e)}"
|
149 |
+
|
150 |
+
|
151 |
+
# Instantiate the LessonGraph class
|
152 |
+
lesson_graph = LessonGraph()
|
153 |
|
154 |
# Gradio interface
|
155 |
demo = gr.Blocks()
|
|
|
176 |
|
177 |
with gr.Row():
|
178 |
generate_btn = gr.Button("Map Your Lesson Plan")
|
179 |
+
graph_btn = gr.Button("Display Graph (JSON)")
|
180 |
clear_btn = gr.Button("Clear Landscape")
|
181 |
|
|
|
182 |
examples = [
|
183 |
["Sarah Johnson", "Oakville District School Board", "Earth Science", "Grade 7", "Understand the water cycle and its impact on Earth's climate", "Create a terrarium to model the water cycle", "Group presentation on terrarium observations", "Terrarium kit, climate diagrams"],
|
184 |
["Marek Nowak", "Warsaw School District", "Matematyka", "Klasa 2", "Zrozumienie podstawowych operacji matematycznych", "Rozwiązywanie prostych zadań tekstowych", "Praca grupowa nad rozwiązywaniem zadań", "Podręcznik, karty pracy, tablica interaktywna"]
|
|
|
188 |
|
189 |
search_output = gr.Textbox(label="Content Discovery Search String")
|
190 |
graph_output = gr.Image(label="Your Educational Landscape")
|
|
|
191 |
message_output = gr.Textbox(label="Landscape Status")
|
192 |
|
193 |
generate_btn.click(
|
194 |
+
lesson_graph.add_lesson_plan,
|
195 |
inputs=[teacher_name, subject, grade_level, learning_objective, activity, assessment, resource, school_board],
|
196 |
outputs=[search_output, graph_output]
|
197 |
)
|
198 |
|
199 |
graph_btn.click(
|
200 |
+
lesson_graph.graph_to_json,
|
201 |
outputs=[message_output]
|
202 |
)
|
203 |
|
204 |
+
clear_btn.click(lesson_graph.clear_graph, outputs=message_output)
|
205 |
+
|
206 |
+
# Add Markdown section explaining the purpose and use of the app
|
207 |
+
gr.Markdown("""
|
208 |
+
## Purpose of EduScape: Understanding Lesson Plans as a Graph
|
209 |
+
|
210 |
+
EduScape helps educators visualize lesson plans as a graph, where key lesson elements (teacher, subject, grade level, learning objectives, activities, assessments, and resources) are represented as nodes with logical relationships. This structure allows teachers to better understand the connections between different parts of their lessons, facilitating clearer planning and discovery of resources.
|
211 |
|
212 |
+
### Key Features:
|
213 |
+
- **User Input-Driven Graph Construction**: Educators can input details like teacher name, subject, grade level, learning objective, activity, assessment, and resources to automatically construct a lesson plan graph.
|
214 |
+
- **Graph Visualization**: Each element of the lesson plan is represented as a node, and the connections between these elements (like how an activity achieves the learning objective) are visualized through edges.
|
215 |
+
- **Content Discovery**: The system generates a search string based on input, which can help the teacher discover content or resources to support their lesson plan.
|
216 |
+
|
217 |
+
### Logical Flow of the Knowledge Graph:
|
218 |
+
1. The **Teacher** node connects to the **Subject** node (representing what the teacher teaches).
|
219 |
+
2. The **Subject** node connects to both the **Grade Level** and **Learning Objective** (defining what is taught and to whom).
|
220 |
+
3. The **Activity** node links to the **Learning Objective** (showing how the objective is achieved through student engagement).
|
221 |
+
4. The **Assessment** node connects to the **Learning Objective** (indicating how learning is evaluated).
|
222 |
+
5. The **Resource** node connects to the **Activity** (detailing what materials are needed for the activity).
|
223 |
+
6. The **Teacher** also connects to the **School Board** (showing which governing body the teacher belongs to).
|
224 |
+
7. The **Learning Objective** aligns with **School Board** standards (ensuring that the lesson adheres to curriculum requirements).
|
225 |
+
|
226 |
+
### Example Use Case:
|
227 |
+
A teacher, Sarah Johnson, inputs her lesson plan for Grade 7 Earth Science focused on understanding the water cycle. She adds an activity where students create a terrarium and a group presentation for assessment. The system visualizes the relationships between these elements in the graph and generates a content discovery string to help her find additional resources like a terrarium kit or climate diagrams.
|
228 |
+
|
229 |
+
EduScape ensures that teachers can organize their lessons effectively while aligning with the curriculum and potentially discovering paid or free resources to enhance their lesson delivery.
|
230 |
+
""")
|
231 |
+
|
232 |
# Launch the EduScape app
|
233 |
demo.launch()
|
234 |
+
|