William Stein wrote: > On Nov 17, 2007 6:14 PM, Jason Grout <[EMAIL PROTECTED]> wrote: > \> >> I'm pretty excited about this! I think it would be extremely >>>> amazingly >>>> useful if you could make up some more examples like this one >>>> >>>> sage: a = Slider(1,10) >>>> sage: plot(sin(a()*x),-3,3) >>> Why not just >>> >>>> plot(sin(a*x),-3,3) >>> instead of >>> >>>> plot(sin(a()*x),-3,3) >> >> Your first example is what I was originally thinking. It would be >> simpler. I wasn't sure how it would work to have a slider object >> multiplied by something, etc. I figured in the end that rather than >> rewrite all the multiplication, addition, subtraction, etc., it'd be >> easier to have the __call__ method in "a" return whatever the current >> value of "a" was, and then let Sage take care of how to use that value >> in the expression. >> >> Can we have "a" be a Slider object and have a*something (or a+something, >> etc.) make sense without rewriting a bunch of code to have operations >> work with Widget objects? > > I think the simplest thing to implement would be something like this (which > would be in the notebook): > > <arbitrary html form named "foo" with widgets, sliders, etc., that > anybody who knows > html could layout and create. various form objects are named> > > {{{ > %form foo > > a = %dom['slider'] > b = %dom['button'] > > // Arbitrary Sage code that might use a and b to draw things, etc. > }}} > > When the page is rendered to html, a cell starting with "%form foo" would > be tied to some even for the foo form. The lines a = %dom['slider'], etc., > would be preparsed in javascript to set the variables a and b to the values > of the corresponding DOM elements (where DOM = Document Object > Model). Then the remaining aribitrary Sage code would be executed > and the output box be displayed.
Doing things this way (keeping the widgets and associated variables in the notebook on a per-cell basis instead of making them definable and accessible from the Sage command line) avoids the following issue. If, for example, we have sage: x=Slider([1..10]) sage: x() Then what I said originally should mean that the output of the second command contains a slider for x and underneath that the value of x. As you change the slider, the value of x changes. However, what if you then say: sage: x.value = 3 Should the slider representing x and the value above automatically change to 3? It seems that they should, but my implementation won't do this since the first two lines are not re-examined and changed. Also, if you then do another sage: x() and change the slider, can the notebook know to evaluate all the expressions with x() in them and update them if we change the slider? I read a bit more of the docs behind the Manipulate function and the dynamic features in Mathematica 6. I'll try to summarize what I understand. In Mathematica, the basic new functionality we are discussing is contained in the Dynamic and DynamicModule commands. Typing "Dynamic[x]" will output the current value of x and the output is changed as x changes throughout the program. Mathematica is smart about this, though, and doesn't update things that are not visible, so you don't see a performance penalty for a complex graphic based on x that is not in view, for example. Also, the output is updated only every 0.2 seconds (and is configurable), so outputting Dynamic[x] while x is being reset in a tight loop, for example, will not update x for every run through the loop. The updating happens on a different, higher-priorty thread than the main computation. Thus, even while a computation is running, the frontend can ask for the value of a variable or the value of a dynamic computation and the kernel will put things on hold, do the frontend computation, and then pick up where it left off. Also, you can have Mathematica return a short computation while a variable is being continuously updated (like a slider being dragged) and a final longer computation once the variable has settled down. Mathematica uses this in the plots---computing an approximate plot with just a few triangles while a slider is being dragged, but then the full plot when a slider is released. Of course, having Dynamic[x] can be awfully confusing if you then use x for something else in the program (all your previous results using Dynamic[x] will change!). The DynamicModule command lets you create local variables that are used in the Dynamic command. That means that executing DynamicModule[{x},Dynamic[Sin[x]]] twice will use different local variables (these are generated using a gensym functionality from the frontend). These two commands, for example, are translated (behind the user's back) to: Dynamic[Sin[x$1]] and Dynamic[Sin[x$2]], where x$1 and x$2 are the names of the local variables. Thus the Manipulate command Manipulate[Sin[x],{x,1,10}] is (greatly simplified to) DynamicModule[{x},f[x]]] where f[x] is a function that creates a Slider with value x (Slider[Dynamic[x]]) and an output cell containing Dynamic[Sin[x]]. In other words, the variable is not the slider, but the slider is just another function that provides a graphical way to view the value of a variable and to set the variable (and in this case, the slider is the only way to access and set the variable). All the heavy lifting is done with the Dynamic command. So, all in all, having the Manipulate functionality is just scratching the surface of the much more general and powerful Dynamic command. However, the functionality of Manipulate will probably get used much more often in classrooms than the full power of the Dynamic command. So what can we do? I think the heavy lifting of the Dynamic command is beyond our reach with our current interface. Is there enough smarts in the javascript to be able to optimize which outputs to update and how often to update them, even while another computation is running? I don't think so. However, we can implement something like the Manipulate command. I think William's idea is the way to go: make the variable equal to a slider in the front end and make that variable local to one input cell. The only way to change the variable would be to move the slider in the front end. You could use the variable (read only) in SAGE commands. When a command is typed into the notebook, the notebook first substitutes in any widget variables, and then passes the computation back to Sage to compute. Doing things this way (keeping the widget variables only in the interface) avoids the much more difficult task of basically implementing the Dynamic command using our current setup. Thoughts? -Jason --~--~---------~--~----~------------~-------~--~----~ To post to this group, send email to sage-devel@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sage-devel URLs: http://sage.scipy.org/sage/ and http://modular.math.washington.edu/sage/ -~----------~----~----~----~------~----~------~--~---