ASKSAGE: Sage Q&A Forum - RSS feedhttps://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Wed, 22 Dec 2010 03:45:00 +0100Combination of lambda function and plot3d(?)https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/I'm having trouble understanding why the following code doesn't work like I'd hoped:
<pre>
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)
</pre>
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 are three updated test cases, which contain a function that 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.
<pre>
#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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)
</pre>Sat, 11 Dec 2010 16:56:06 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/Comment by Mike Witt for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22412#post-id-22412Holy cow, sorry about that typo! Now that I've fixed that, the plot seems to be evaluating properly, but I'm having another weird problem. I need to look over all three tests for a while and then I'll report back ...Mon, 13 Dec 2010 20:13:12 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22412#post-id-22412Comment by John Palmieri for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22413#post-id-22413In your test2, change the line "pic += ..." to "pic += plot3d(g(x,y), ...)". That change works for me both in the notebook and from the command line. (Right now, you're defining g(x,y) but using it anywhere.)Mon, 13 Dec 2010 17:51:23 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22413#post-id-22413Comment by Mike Witt for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22414#post-id-22414It's possible that I'm not understanding what you suggested correctly. Or, that there's a difference between the command line and notebook? I updated the question, showing what I tried (test2). Let me know if this wasn't what you meant. Note that I'm doing this all in the command line.Mon, 13 Dec 2010 16:01:40 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22414#post-id-22414Comment by John Palmieri for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22420#post-id-22420That's odd, because for me the two behave differently: if I enter your code in the notebook and then evaluate 'test1()[0]', I see different plots with your version vs. the version with "def g(x,y): ...".Sun, 12 Dec 2010 21:58:26 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22420#post-id-22420Comment by Mike Witt for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22421#post-id-22421Well, I tried it. It appeared to do the same thing as using the lambda. That is, my function evaluated x and y OK, but it didn't force the plot to be evaluated.Sun, 12 Dec 2010 12:59:24 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22421#post-id-22421Comment by John Palmieri for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22422#post-id-22422In your situation, can you replace the line "pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))" with lines like "def g(x,y): return f(x,y,t); pic += plot3d(g(x,y), ...)"?Sun, 12 Dec 2010 11:05:15 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22422#post-id-22422Comment by Mike Witt for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div>https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22411#post-id-22411Ok, I think I have a better explanation of what's going on now in the (yet again) updated ticket. Take a look if you have time.Mon, 13 Dec 2010 20:37:02 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22411#post-id-22411Answer by niles for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div> https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11857#post-id-11857This is quite puzzling; if you update `f` to the following, `test3` now raises the runtime error (probably `test2` too). It seems that the condition `x > .5` is being evaluated while `x` is still a variable instead of a number . . .
def f(x,y,t):
if x not in RR:
raise RuntimeError("checking x too soon")
if x > .5:
return(sin(pi*x)*sin(pi*y))
else:
return(sin(pi*x)*sin(pi*y)*e^(-t))
I also noticed that the `plot3d` function seems to just call `parametric_plot3d` in the end, so maybe working with `parametric_plot3d` directly could help focus too.
At this stage I guess I'm inclined to suggest that you define a full-blown class to handle making these plots -- then the value of `t` can be an attribute of the class, as well as the appropriate function of x,y and the appropriate plot. If namespace issues are part of the problem, then making each frame a new instance of some general class will, I think, help to avoid them.
Mon, 13 Dec 2010 22:33:47 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11857#post-id-11857Comment by Mike Witt for <p>This is quite puzzling; if you update <code>f</code> to the following, <code>test3</code> now raises the runtime error (probably <code>test2</code> too). It seems that the condition <code>x > .5</code> is being evaluated while <code>x</code> is still a variable instead of a number . . .</p>
<pre><code>def f(x,y,t):
if x not in RR:
raise RuntimeError("checking x too soon")
if x > .5:
return(sin(pi*x)*sin(pi*y))
else:
return(sin(pi*x)*sin(pi*y)*e^(-t))
</code></pre>
<p>I also noticed that the <code>plot3d</code> function seems to just call <code>parametric_plot3d</code> in the end, so maybe working with <code>parametric_plot3d</code> directly could help focus too.</p>
<p>At this stage I guess I'm inclined to suggest that you define a full-blown class to handle making these plots -- then the value of <code>t</code> can be an attribute of the class, as well as the appropriate function of x,y and the appropriate plot. If namespace issues are part of the problem, then making each frame a new instance of some general class will, I think, help to avoid them.</p>
https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22406#post-id-22406Well, it's already a class in the real code :-) But I basically agree. I need to rewrite the code with this issue in mind. It doesn't appear that there's going to be one or two line fix.Tue, 14 Dec 2010 12:10:23 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22406#post-id-22406Answer by Mike Witt for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div> https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11860#post-id-11860OK, well I think I've found a way to get the plot to evaluate. Apparently the method json_repr() will do it (with much less overhead than actually saving to a file):
<pre>
def test0():
var('x,y,t')
def f(x,y,t):
if x < .5: return(sin(pi*x)*sin(pi*y))
else: return(sin(pi*x)*sin(pi*y)*e^(-t))
base_frame = point3d((.5,.5,1), color='red', size=10)
frames = []
for t in [0,1]:
pic = base_frame
pic += plot3d(lambda x,y:f(x,y,t), (x, 0, 1), (y, 0, 1))
# This appears to force the line above to be "evaluated"
foo = pic.json_repr(pic.default_render_params())
frames += [pic,]
return(frames)
</pre>Tue, 14 Dec 2010 19:46:35 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11860#post-id-11860Answer by niles for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div> https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11843#post-id-11843I played with this a little, and I think I've been able to at least focus the problem a little more (using your `f` above):
sage: lambdas = [lambda x,y:f(x,y,t) for t in [0,1]]
sage: lambdas[0](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
sage: lambdas[1](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
So one aspect of the problem seems to be that the second lambda is overwriting the first..
----
UPDATE:
Oh wow -- this is a **python** bug! (Or is it a feature? [PEP 227](http://www.python.org/dev/peps/pep-0227/) seems to address something relevant; note especially the "Discussion" and "Examples" sections)
>>> lambdas = [lambda x,y: x*y*t for t in [1,2]]
>>> lambdas[0](2,3)
12
>>> lambdas[1](2,3)
12
----
UPDATE 2:
This morning I realized how to work around this problem: use nested lambda functions!
A python example:
>>> f = lambda t: lambda x,y: x*y*t
>>> f(2)(2,3)
12
>>> f(1)(2,3)
6
And a 3d plot example:
def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
base_frame = point3d((.5,.5,1), color='red', size=10)
L = lambda t: lambda x,y: f(x,y,t)
var('x,y')
(x, y)
frames = [plot3d(L(t)(x,y), (x, 0, 1), (y, 0, 1))+base_frame for t in [0,1]]
frames[0]
![image description](/upfiles/12922460711741685.jpg)
frames[1]
![image description](/upfiles/12922460857674627.jpg)
Sun, 12 Dec 2010 08:45:02 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11843#post-id-11843Comment by kcrisman for <p>I played with this a little, and I think I've been able to at least focus the problem a little more (using your <code>f</code> above):</p>
<pre><code>sage: lambdas = [lambda x,y:f(x,y,t) for t in [0,1]]
sage: lambdas[0](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
sage: lambdas[1](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
</code></pre>
<p>So one aspect of the problem seems to be that the second lambda is overwriting the first..</p>
<hr/>
<p>UPDATE:</p>
<p>Oh wow -- this is a <strong>python</strong> bug! (Or is it a feature? <a href="http://www.python.org/dev/peps/pep-0227/">PEP 227</a> seems to address something relevant; note especially the "Discussion" and "Examples" sections)</p>
<pre><code>>>> lambdas = [lambda x,y: x*y*t for t in [1,2]]
>>> lambdas[0](2,3)
12
>>> lambdas[1](2,3)
12
</code></pre>
<hr/>
<p>UPDATE 2:</p>
<p>This morning I realized how to work around this problem: use nested lambda functions!</p>
<p>A python example:</p>
<pre><code>>>> f = lambda t: lambda x,y: x*y*t
>>> f(2)(2,3)
12
>>> f(1)(2,3)
6
</code></pre>
<p>And a 3d plot example:</p>
<pre><code>def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
base_frame = point3d((.5,.5,1), color='red', size=10)
L = lambda t: lambda x,y: f(x,y,t)
var('x,y')
(x, y)
frames = [plot3d(L(t)(x,y), (x, 0, 1), (y, 0, 1))+base_frame for t in [0,1]]
frames[0]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460711741685.jpg"/></p>
<pre><code>frames[1]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460857674627.jpg"/></p>
https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22409#post-id-22409Niles, is this really a Python bug, or is the behavior expected and documented? Lisp-y things sometimes are a little counterintuitive... You might also want to see if it's still in Python 2.7 or 3.x, just out of curiosity...Mon, 13 Dec 2010 22:04:43 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22409#post-id-22409Comment by Mike Witt for <p>I played with this a little, and I think I've been able to at least focus the problem a little more (using your <code>f</code> above):</p>
<pre><code>sage: lambdas = [lambda x,y:f(x,y,t) for t in [0,1]]
sage: lambdas[0](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
sage: lambdas[1](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
</code></pre>
<p>So one aspect of the problem seems to be that the second lambda is overwriting the first..</p>
<hr/>
<p>UPDATE:</p>
<p>Oh wow -- this is a <strong>python</strong> bug! (Or is it a feature? <a href="http://www.python.org/dev/peps/pep-0227/">PEP 227</a> seems to address something relevant; note especially the "Discussion" and "Examples" sections)</p>
<pre><code>>>> lambdas = [lambda x,y: x*y*t for t in [1,2]]
>>> lambdas[0](2,3)
12
>>> lambdas[1](2,3)
12
</code></pre>
<hr/>
<p>UPDATE 2:</p>
<p>This morning I realized how to work around this problem: use nested lambda functions!</p>
<p>A python example:</p>
<pre><code>>>> f = lambda t: lambda x,y: x*y*t
>>> f(2)(2,3)
12
>>> f(1)(2,3)
6
</code></pre>
<p>And a 3d plot example:</p>
<pre><code>def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
base_frame = point3d((.5,.5,1), color='red', size=10)
L = lambda t: lambda x,y: f(x,y,t)
var('x,y')
(x, y)
frames = [plot3d(L(t)(x,y), (x, 0, 1), (y, 0, 1))+base_frame for t in [0,1]]
frames[0]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460711741685.jpg"/></p>
<pre><code>frames[1]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460857674627.jpg"/></p>
https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22410#post-id-22410I may have spoken too soon. I'm still trying to sort out the two different issues here. If you have a chance, please take a look at the newly updated ticket.Mon, 13 Dec 2010 20:38:06 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22410#post-id-22410Comment by Mike Witt for <p>I played with this a little, and I think I've been able to at least focus the problem a little more (using your <code>f</code> above):</p>
<pre><code>sage: lambdas = [lambda x,y:f(x,y,t) for t in [0,1]]
sage: lambdas[0](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
sage: lambdas[1](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
</code></pre>
<p>So one aspect of the problem seems to be that the second lambda is overwriting the first..</p>
<hr/>
<p>UPDATE:</p>
<p>Oh wow -- this is a <strong>python</strong> bug! (Or is it a feature? <a href="http://www.python.org/dev/peps/pep-0227/">PEP 227</a> seems to address something relevant; note especially the "Discussion" and "Examples" sections)</p>
<pre><code>>>> lambdas = [lambda x,y: x*y*t for t in [1,2]]
>>> lambdas[0](2,3)
12
>>> lambdas[1](2,3)
12
</code></pre>
<hr/>
<p>UPDATE 2:</p>
<p>This morning I realized how to work around this problem: use nested lambda functions!</p>
<p>A python example:</p>
<pre><code>>>> f = lambda t: lambda x,y: x*y*t
>>> f(2)(2,3)
12
>>> f(1)(2,3)
6
</code></pre>
<p>And a 3d plot example:</p>
<pre><code>def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
base_frame = point3d((.5,.5,1), color='red', size=10)
L = lambda t: lambda x,y: f(x,y,t)
var('x,y')
(x, y)
frames = [plot3d(L(t)(x,y), (x, 0, 1), (y, 0, 1))+base_frame for t in [0,1]]
frames[0]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460711741685.jpg"/></p>
<pre><code>frames[1]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460857674627.jpg"/></p>
https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22415#post-id-22415Fantastic. That does solve the problem!Mon, 13 Dec 2010 15:42:21 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22415#post-id-22415Comment by Jason Grout for <p>I played with this a little, and I think I've been able to at least focus the problem a little more (using your <code>f</code> above):</p>
<pre><code>sage: lambdas = [lambda x,y:f(x,y,t) for t in [0,1]]
sage: lambdas[0](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
sage: lambdas[1](.5,.5)
e^(-1)*sin(0.500000000000000*pi)^2
</code></pre>
<p>So one aspect of the problem seems to be that the second lambda is overwriting the first..</p>
<hr/>
<p>UPDATE:</p>
<p>Oh wow -- this is a <strong>python</strong> bug! (Or is it a feature? <a href="http://www.python.org/dev/peps/pep-0227/">PEP 227</a> seems to address something relevant; note especially the "Discussion" and "Examples" sections)</p>
<pre><code>>>> lambdas = [lambda x,y: x*y*t for t in [1,2]]
>>> lambdas[0](2,3)
12
>>> lambdas[1](2,3)
12
</code></pre>
<hr/>
<p>UPDATE 2:</p>
<p>This morning I realized how to work around this problem: use nested lambda functions!</p>
<p>A python example:</p>
<pre><code>>>> f = lambda t: lambda x,y: x*y*t
>>> f(2)(2,3)
12
>>> f(1)(2,3)
6
</code></pre>
<p>And a 3d plot example:</p>
<pre><code>def f(x,y,t): return(sin(pi*x)*sin(pi*y)*e^(-t))
base_frame = point3d((.5,.5,1), color='red', size=10)
L = lambda t: lambda x,y: f(x,y,t)
var('x,y')
(x, y)
frames = [plot3d(L(t)(x,y), (x, 0, 1), (y, 0, 1))+base_frame for t in [0,1]]
frames[0]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460711741685.jpg"/></p>
<pre><code>frames[1]
</code></pre>
<p><img alt="image description" src="/upfiles/12922460857674627.jpg"/></p>
https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22369#post-id-22369Even better, I think you could just do: lambda x,y,t=t: f(x,y,t) to capture the value of t when the lambda function is defined.Wed, 22 Dec 2010 03:45:00 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?comment=22369#post-id-22369Answer by Jason Grout for <div class="snippet"><p>I'm having trouble understanding why the following code doesn't work like I'd hoped:</p>
<pre>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)
</pre>
<p>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.</p>
<p>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.</p>
<p>Can anyone help me understand what's happening here, and how I might get this to work?</p>
<p>---------- UPDATE -----------</p>
<p>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 are three updated test cases, which contain a function that actually <em>requires</em> 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.</p>
<pre>#
# 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 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 test1():
frames = []
for t in [0,1]:
pic = base_frame
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)
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():
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 ...</pre><span class="expander"> <a>(more)</a></span></div> https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11892#post-id-11892The following example illustrates the problem Niles saw with using lambda. Notice that the t in the lambda is taken from the *current* value of t in the global scope:
sage: f=lambda x: (x,t)
sage: t=2
sage: f(1)
(1, 2)
sage: t=3
sage: f(1)
(1, 3)
sage:
See the first few answers of [http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters](http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters) for more discussion. Here is one workaround from those answers:
sage: f=lambda x,t=t: (x,t)
sage: t=1
sage: f(1)
(1, 100)
Wed, 22 Dec 2010 03:44:14 +0100https://ask.sagemath.org/question/7807/combination-of-lambda-function-and-plot3d/?answer=11892#post-id-11892