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 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.
# # 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 ...
In 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), ...)"?
Well, 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.
That'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): ...".
It'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.
In 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.)