Browse Source

Implemented probe blocks

Yentl Van Tendeloo 8 years ago
parent
commit
dc6254b19c

+ 16 - 0
integration/code/cbd_design.mvc

@@ -11,6 +11,15 @@ SCD CausalBlockDiagrams_Design{
         $
     }
 
+    Class String {
+        $
+            if (bool_not(is_physical_string(self))):
+                return "String has no string value"!
+            else:
+                return "OK"!
+        $
+    }
+
     Class Block{}
     Class ICBlock{}
 
@@ -28,6 +37,12 @@ SCD CausalBlockDiagrams_Design{
     Class DelayBlock{}
     Class IntegratorBlock{}
     Class DerivatorBlock{}
+    Class ProbeBlock{
+        name : String {
+            target_lower_cardinality = 1
+            target_upper_cardinality = 1
+        }
+    }
 
     Association Link(Block, Block){}
     Association InitialCondition(Block, ICBlock){
@@ -40,6 +55,7 @@ SCD CausalBlockDiagrams_Design{
     Inheritance (NegatorBlock, Block){}
     Inheritance (MultiplyBlock, Block){}
     Inheritance (InverseBlock, Block){}
+    Inheritance (ProbeBlock, Block){}
     Inheritance (ICBlock, Block){}
     Inheritance (DelayBlock, ICBlock){}
     Inheritance (IntegratorBlock, ICBlock){}

+ 18 - 0
integration/code/cbd_runtime.mvc

@@ -11,6 +11,15 @@ SCD CausalBlockDiagrams_Runtime{
         $
     }
 
+    Class String {
+        $
+            if (bool_not(is_physical_string(self))):
+                return "String has no string value"!
+            else:
+                return "OK"!
+        $
+    }
+
     Class Block{
         signal : Float {
             target_lower_cardinality = 1
@@ -31,6 +40,13 @@ SCD CausalBlockDiagrams_Runtime{
         }
     }
 
+    Class ProbeBlock{
+        name : String {
+            target_lower_cardinality = 1
+            target_upper_cardinality = 1
+        }
+    }
+
     Class AdditionBlock{}
     Class NegatorBlock{}
     Class MultiplyBlock{}
@@ -42,6 +58,7 @@ SCD CausalBlockDiagrams_Runtime{
             target_upper_cardinality = 1
         }
     }
+
     Class DerivatorBlock{}
     Class Time{
         lower_cardinality = 1
@@ -74,6 +91,7 @@ SCD CausalBlockDiagrams_Runtime{
     Inheritance (DelayBlock, ICBlock){}
     Inheritance (DerivatorBlock, ICBlock){}
     Inheritance (IntegratorBlock, ICBlock){}
+    Inheritance (ProbeBlock, Block){}
 }
 
 export CausalBlockDiagrams_Runtime to models/CausalBlockDiagrams_Runtime

+ 8 - 2
integration/code/cbd_semantics.alc

@@ -30,6 +30,8 @@ Element function retype_to_runtime(design_model : Element):
 		element_name = instantiate_node(runtime_model, mm_type_name, element_name)
 		if (is_nominal_instance(design_model, element_name, "ConstantBlock")):
 			instantiate_attribute(runtime_model, element_name, "value", read_attribute(design_model, element_name, "value"))
+		elif (is_nominal_instance(design_model, element_name, "ProbeBlock")):
+			instantiate_attribute(runtime_model, element_name, "name", read_attribute(design_model, element_name, "name"))
 
 	// Don't merge this together with the block conversion, as the destination block might not exist yet!
 	all_links = allInstances(design_model, "Link")
@@ -309,7 +311,6 @@ Boolean function solve_scc(model : Element, scc : Element):
 		unset_attribute(model, block, "signal")
 		instantiate_attribute(model, block, "signal", m[i][read_nr_out(scc)])
 		log((("Solved " + block) + " to ") + cast_v2s(m[i][read_nr_out(scc)]))
-		output((("SIM_PROBE " + cast_v2s(block)) + " ") + cast_v2s(m[i][read_nr_out(scc)]))
 		i = i + 1
 
 	return True!
@@ -422,10 +423,15 @@ Void function step_simulation(model : Element, schedule : Element):
 						signal = (cast_s2f(cast_v2s(read_attribute(model, selected, "signal"))) - cast_s2f(cast_v2s(read_attribute(model, block, "last_in")))) / delta_t
 					unset_attribute(model, block, "last_in")
 				set_add(memory_blocks, block)
+			elif (blocktype == "ProbeBlock"):
+				incoming = allIncomingAssociationInstances(model, block, "Link")
+				while (read_nr_out(incoming) > 0):
+					selected = readAssociationSource(model, set_pop(incoming))
+					signal = cast_s2f(cast_v2s(read_attribute(model, selected, "signal")))
+					output((("SIM_PROBE " + cast_v2s(read_attribute(model, block, "name"))) + " ") + cast_v2s(signal))
 
 			unset_attribute(model, block, "signal")
 			instantiate_attribute(model, block, "signal", signal)
-			output((("SIM_PROBE " + cast_v2s(block)) + " ") + cast_v2s(signal))
 	output("SIM_END")
 	
 	while (read_nr_out(memory_blocks) > 0):

+ 84 - 22
interface/CBD/main.py

@@ -21,7 +21,6 @@ username = "test"
 root = Tk()
 
 canvas = Canvas(root, width=MAX_WIDTH, height=MAX_HEIGHT, bg="white")
-canvas.pack()
 
 name = 0
 
@@ -210,11 +209,13 @@ class InterfaceCore():
                 new_value = tkSimpleDialog.askstring("Attribute modification", attr, initialvalue=old_value)
                 if t == "Float":
                     new_value = float(new_value)
+                elif t == "String":
+                    new_value = str(new_value)
                 else:
                     print("Got unknown type: " + str(t))
                 self.mv.set_attribute(lname, attr, new_value)
 
-        elif self.mode not in ["AdditionBlock", "NegatorBlock", "ConstantBlock", "MultiplyBlock", "ConstantBlock", "InverseBlock", "DelayBlock", "IntegratorBlock", "DerivatorBlock"]:
+        elif self.mode not in ["AdditionBlock", "NegatorBlock", "ConstantBlock", "MultiplyBlock", "ConstantBlock", "InverseBlock", "DelayBlock", "IntegratorBlock", "DerivatorBlock", "ProbeBlock"]:
             print("Cannot create something not guaranteed to be block type!")
         else:
             global name
@@ -311,21 +312,30 @@ def integrator():
 def delete(event):
     core.delete(event.x, event.y)
 
-Button(root, text="+", command=addition).pack()
-Button(root, text="-x", command=negation).pack()
-Button(root, text="*", command=multiply).pack()
-Button(root, text="1/x", command=inverse).pack()
-Button(root, text="Constant", command=constant).pack()
-Button(root, text="Delay", command=delay).pack()
-Button(root, text="d/dx", command=derivator).pack()
-Button(root, text="integrator", command=integrator).pack()
-
-Button(root, text="Link", command=link).pack()
-Button(root, text="InitialCondition", command=ic).pack()
-
-Button(root, text="SIM", command=simulate).pack()
-Button(root, text="STEP", command=step).pack()
-Button(root, text="PAUSE", command=pause).pack()
+def make_probe():
+    core.set_mode("ProbeBlock")
+
+buttons = [
+        Button(root, text="+", command=addition), 
+        Button(root, text="-x", command=negation), 
+        Button(root, text="*", command=multiply), 
+        Button(root, text="1/x", command=inverse), 
+        Button(root, text="Constant", command=constant), 
+        Button(root, text="Delay", command=delay), 
+        Button(root, text="d/dx", command=derivator), 
+        Button(root, text="integrator", command=integrator), 
+        Button(root, text="Probe", command=make_probe),
+        Button(root, text="Link", command=link), 
+        Button(root, text="InitialCondition", command=ic), 
+        Button(root, text="SIM", command=simulate), 
+        Button(root, text="STEP", command=step), 
+        Button(root, text="PAUSE", command=pause), 
+    ]
+
+for i, b in enumerate(buttons):
+    b.grid(row=0, column=i)
+
+canvas.grid(row=1,column=0,columnspan=len(buttons))
 
 core.canvas = canvas
 
@@ -344,7 +354,56 @@ visual = Toplevel(root)
 probes = {}
 values = {}
 
-#simulation = [(1, {"a": 1, "b": 2}), (2, {"a": 3}), (3, {"a": 4, "b": 6})]
+# Example:
+#    simulation = [(1, {"a": 1, "b": 2}), (2, {"a": 3}), (3, {"a": 4, "b": 6})]
+
+# Class from StackOverflow
+class VerticalScrolledFrame(Frame):
+    """A pure Tkinter scrollable frame that actually works!
+    * Use the 'interior' attribute to place widgets inside the scrollable frame
+    * Construct and pack/place/grid normally
+    * This frame only allows vertical scrolling
+
+    """
+    def __init__(self, parent, *args, **kw):
+        Frame.__init__(self, parent, *args, **kw)            
+
+        # create a canvas object and a vertical scrollbar for scrolling it
+        vscrollbar = Scrollbar(self, orient=VERTICAL)
+        vscrollbar.pack(fill=Y, side=RIGHT, expand=FALSE)
+        canvas = Canvas(self, bd=0, highlightthickness=0,
+                        yscrollcommand=vscrollbar.set)
+        canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
+        vscrollbar.config(command=canvas.yview)
+
+        # reset the view
+        canvas.xview_moveto(0)
+        canvas.yview_moveto(0)
+
+        # create a frame inside the canvas which will be scrolled with it
+        self.interior = interior = Frame(canvas)
+        interior_id = canvas.create_window(0, 0, window=interior,
+                                           anchor=NW)
+
+        # track changes to the canvas and frame width and sync them,
+        # also updating the scrollbar
+        def _configure_interior(event):
+            # update the scrollbars to match the size of the inner frame
+            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
+            canvas.config(scrollregion="0 0 %s %s" % size)
+            if interior.winfo_reqwidth() != canvas.winfo_width():
+                # update the canvas's width to fit the inner frame
+                canvas.config(width=interior.winfo_reqwidth())
+        interior.bind('<Configure>', _configure_interior)
+
+        def _configure_canvas(event):
+            if interior.winfo_reqwidth() != canvas.winfo_width():
+                # update the inner frame's width to fill the canvas
+                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
+        canvas.bind('<Configure>', _configure_canvas)
+
+frame = VerticalScrolledFrame(visual)
+frame.pack(fill=BOTH,expand=True)
 
 def update_graphs():
     while simulation:
@@ -353,11 +412,13 @@ def update_graphs():
             if k in probes:
                 fcanvas, a = probes[k]
             else:
-                f = Figure(figsize=(5,5), dpi=100)
+                f = Figure()
                 a = f.add_subplot(111)
                 a.plot([], [])
+                print(k)
+                f.suptitle(k)
 
-                fcanvas = FigureCanvasTkAgg(f, visual)
+                fcanvas = FigureCanvasTkAgg(f, frame.interior)
                 fcanvas.show()
                 fcanvas.get_tk_widget().pack()
 
@@ -370,6 +431,7 @@ def update_graphs():
             a.clear()
             a.plot(values[k][0], values[k][1], linestyle="none", marker="o")
             fcanvas.draw()
-    root.after(50, update_graphs)
-root.after(50, update_graphs)
+    root.after(100, update_graphs)
+
+root.after(100, update_graphs)
 root.mainloop()