donb-hf commited on
Commit
31f7bae
·
verified ·
1 Parent(s): 0d7cabd

update docs

Browse files
Files changed (1) hide show
  1. app.py +168 -126
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
- import json
 
 
 
 
103
 
104
- import json
 
 
 
 
 
 
 
 
 
 
 
105
 
106
- def graph_to_json():
107
- try:
108
- # Convert the lesson_graph to a dictionary format
109
- graph_data = {
110
- "nodes": [
111
- {
112
- "id": node,
113
- "type": lesson_graph.nodes[node]["type"],
114
- "description": lesson_graph.nodes[node].get("description", "")
115
- }
116
- for node in lesson_graph.nodes()
117
- ],
118
- "edges": [
119
- {
120
- "source": u,
121
- "target": v,
122
- "relationship": lesson_graph.edges[u, v]["relationship"]
123
- }
124
- for u, v in lesson_graph.edges()
125
- ]
126
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- # Convert dictionary to JSON string
129
- json_data = json.dumps(graph_data, indent=4)
 
130
 
131
- # Instead of writing to a file, return the JSON data as a message
132
- return f"Graph Data in JSON Format:\n{json_data}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
- except Exception as e:
135
- # If any error occurs, catch it and display it in the message_output
136
- return f"An error occurred: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- add_to_graph,
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
+