Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Combination of lambda function and plot3d(?)

I'm having trouble understanding why the following code doesn't work like I'd hoped:

def test1():
    base_frame = point3d((.5,.5,1), color='red', size=10)
    def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
    frames = []
    for t in [0,1]:
        pic = base_frame
        pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))  
        #It works if you uncomment the next line:
        #pic.save('/tmp/foo.png')
        frames += [pic,]
    return(frames)

What happens is that both the frames (or all of them if I create more than two) end up containing the last plot. It appears that the plot doesn't get "evaluated" when I want it to. So far, the only mechanism I've found that can force it to be evaluated is inserting a .show() or a .save(), which won't work to well in a larger loop.

Now, I understand that the function "f" I've got here could have been rendered as an expression rather than a function. Then there's no problem. But in the real program, things are more complicated, and (afict) I really need the lambda.

Can anyone help me understand what's happening here, and how I might get this to work?

Combination of lambda function and plot3d(?)

I'm having trouble understanding why the following code doesn't work like I'd hoped:

def test1():
    base_frame = point3d((.5,.5,1), color='red', size=10)
    def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
    frames = []
    for t in [0,1]:
        pic = base_frame
        pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))  
        #It works if you uncomment the next line:
        #pic.save('/tmp/foo.png')
        frames += [pic,]
    return(frames)

What happens is that both the frames (or all of them if I create more than two) end up containing the last plot. It appears that the plot doesn't get "evaluated" when I want it to. So far, the only mechanism I've found that can force it to be evaluated is inserting a .show() or a .save(), which won't work to well in a larger loop.

Now, I understand that the function "f" I've got here could have been rendered as an expression rather than a function. Then there's no problem. But in the real program, things are more complicated, and (afict) I really need the lambda.

Can anyone help me understand what's happening here, and how I might get this to work?

---------- UPDATE -----------

Here is another attempt that didn't appear to work:

def test2():
    var('x,y,t')
    base_frame = point3d((.5,.5,1), color='red', size=10)
    def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
    frames = []
    for t in [0,1]:
        pic = base_frame
        def g(x,y): return(f(x,y,t))
        pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))
        frames += [pic,]
    return(frames)

And here is code based on Niles suggestion which does appear to fix the problem:

def test3():
    var('x,y,t')
    base_frame = point3d((.5,.5,1), color='red', size=10)
    def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
    frames = []
    for t in [0,1]:
        pic = base_frame
        ff = lambda t:lambda x,y:f(x,y,t)
        pic += plot3d(ff(t)(x,y), (x, 0, 1), (y, 0, 1))                     
        frames += [pic,]
    return(frames)
click to hide/show revision 3
Hopefully clarifying the problem

Combination of lambda function and plot3d(?)

I'm having trouble understanding why the following code doesn't work like I'd hoped:

def test1():
    base_frame = point3d((.5,.5,1), color='red', size=10)
    def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
    frames = []
    for t in [0,1]:
        pic = base_frame
        pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))  
        #It works if you uncomment the next line:
        #pic.save('/tmp/foo.png')
        frames += [pic,]
    return(frames)

What happens is that both the frames (or all of them if I create more than two) end up containing the last plot. It appears that the plot doesn't get "evaluated" when I want it to. So far, the only mechanism I've found that can force it to be evaluated is inserting a .show() or a .save(), which won't work to well in a larger loop.

Now, I understand that the function "f" I've got here could have been rendered as an expression rather than a function. Then there's no problem. But in the real program, things are more complicated, and (afict) I really need the lambda.

Can anyone help me understand what's happening here, and how I might get this to work?

---------- UPDATE -----------

I realize I haven't been all that clear (in my own mind, as well as in my explanation) of what the problem is here. I think there are two issues (1) Getting the "lambda" thing to work, and (2) getting the plot to "evaluate." Here is another attempt are three updated test cases, which contain a function that didn't appear to work:actually requires the lambda: test1() does what I want, but at the price of having to save every frame to a file. test2() and test3() do get the plot3d function to evaluate, but in both of those cases, I lose the "lambda" functionality and so the function being plotted isn't right.

#
# Test file
#

# Make sure I'm using the same function in all three tests.
# I need a function that actually requires the use of lambda
var('x,y,t')
def test2():
    var('x,y,t')
    f(x,y,t):
    if x < .5: return(sin(pi*x)*sin(pi*y))
    else: return(sin(pi*x)*sin(pi*y)*e^(-t))

# Might as well define the base frame here too
base_frame = point3d((.5,.5,1), color='red', size=10)
  def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
test1():
    frames = []
    for t in [0,1]:
        pic = base_frame
        def g(x,y): return(f(x,y,t))
        pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))
        # This "save" appears to force the line above to be "evaluated"
        pic.save('/tmp/foo.png')
        frames += [pic,]
    return(frames)

And here is code based on Niles suggestion which does appear to fix the problem:


def test2():
    frames = []
    for t in [0,1]:
        pic = base_frame
        def g(x,y): return(f(x,y,t))
        pic += plot3d(g(x,y), (x, 0, 1), (y, 0, 1))
        frames += [pic,]
    return(frames)

def test3():
    var('x,y,t')
    base_frame = point3d((.5,.5,1), color='red', size=10)
    def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
    frames = []
    for t in [0,1]:
        pic = base_frame
        ff = lambda t:lambda x,y:f(x,y,t)
        pic += plot3d(ff(t)(x,y), (x, 0, 1), (y, 0, 1))                     
1))
        frames += [pic,]
    return(frames)