-
-
Notifications
You must be signed in to change notification settings - Fork 68
/
dynamic.py
84 lines (65 loc) · 2.3 KB
/
dynamic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# Modified from sage_salvus.py in the sagemath/cloud github project
# Original version licensed GPLv2+ by William Stein
#TODO: Need some way of having controls without output and without
#having a 'dirty' indicator. Just javascript controls. This should
#be an argument to interact, like @interact(output=False) or something
# also, need an easy way to make controls read-only (especially if
# they are just displaying a value)
import sys
from interact_sagecell import interact
def _dynamic(var, control=None):
if control is None:
control = sys._sage_.namespace.get(var,'')
# Workaround for not having the nonlocal statement in python 2.x
old_value = [sys._sage_.namespace.get(var,None)]
@interact(layout=[[(var,12)]], output=False)
def f(self, x=(var,control)):
if x is not old_value[0]:
# avoid infinite recursion: if control is already set,
# leave it alone
sys._sage_.namespace[var]=x
old_value[0] = x
def g(var,y):
f.x = y
sys._sage_.namespace.on(var,'change', g)
if var in sys._sage_.namespace:
g(var, sys._sage_.namespace[var])
def dynamic(*args, **kwds):
"""
Make variables in the global namespace dynamically linked to a control from the
interact label (see the documentation for interact).
EXAMPLES:
Make a control linked to a variable that doesn't yet exist::
dynamic('newname')
Make a slider and a selector, linked to t and x::
dynamic(t=(1..10), x=[1,2,3,4])
t = 5 # this changes the control
"""
for var in args:
if not isinstance(var, str):
i = id(var)
for k,v in sys._sage_.namespace.items():
if id(v) == i:
_dynamic(k)
return
else:
_dynamic(var)
for var, control in kwds.items():
_dynamic(var, control)
def dynamic_expression(v, vars):
"""
sage: t=5
sage: dynamic(t)
sage: dynamic_expression('2*t','t')
"""
# control
@interact(output=False, readonly=True)
def f(t=(0,2)):
pass
# update function
def g(var,val):
f.t = eval(v)
for vv in vars:
sys._sage_.namespace.on(vv,'change',g)
imports = {"dynamic": dynamic,
"dynamic_expression": dynamic_expression}