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/
-~----------~----~----~----~------~----~------~--~---

Reply via email to