# Revision history [back]

### 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)


### 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)