# Interact 3d plot(Polyhedron)

Hi there, I got confused about the interact:

def par(t):
tmp = [[200-t,-1,0,0],[300-t,0,-1,0],[400-t,-1,-1,-1],[600-t,0,-1,-3],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
G = Polyhedron(ieqs = tmp)
show(G.render_solid(rgbcolor='blue',alpha=.2)+G.render_wireframe(rgbcolor='black'))

@interact
def _(x=(0,10)):
par(x)


It is quite weird since in the examples of http://wiki.sagemath.org/interact/gra..., it seems that the interactive parameters could only be something controlling a plot. However in my case, the interactive parameter(x) is not used for controlling plot but for obtaining an [[],[]]. so it fails to interact. Any idea of that?

edit retag close merge delete

Sort by » oldest newest most voted

The problem seems to be that par should only take integer inputs. Even outside of the interact, par(2.5) does not show a picture but returns a number. You can restrict the possible inputs to integers by giving a step size for the parameters in the interact:

@interact
def _(x=(0,10,1)):
par(x)


This now shows pictures for each (integer) value of x.

more

Great! Thanks. in this way we should be able to animate a 3D plot. B.T.W. is it because Polyhedron only takes integer input that makes the function par(t) only takes integer inputs? An alternative way to animate the behavior of the Polyhedron is by using a loop and time.sleep(#). But it seems not work.

( 2012-03-29 09:33:19 -0500 )edit

If you want to animate a 3d plot, I think there must be a better way. Here's one hacky workaround:

First, generate a "dummy animation" with the number of frames you want, and note where the output images are stored:

N = 10
A = animate([i for i in range(N)])
print A.png()
os.system('ls '+ A.png())


This will return something like

/sagenb/sagenbws/.sage/temp/mod.math.washington.edu/13021/dir_3
00000000.png  00000002.png  00000004.png  00000006.png  00000008.png
00000001.png  00000003.png  00000005.png  00000007.png  00000009.png


Now save the list of images you want to animate, using the same names as those listed above:

def par(t):
tmp = [[200-t,-1,0,0],[300-t,0,-1,0],[400-t,-1,-1,-1],[600-t,0,-1,-3],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
G = Polyhedron(ieqs = tmp, field=RDF)
return G.render_solid(rgbcolor='blue',alpha=.2)+G.render_wireframe(rgbcolor='black')+plot3d(0,(0,200),(0,300),color='red',opacity=.1)

for i in range(N):
P = par(2+i)
P.save(A.png()+'/%08d.png'%i)


When you call A.show(), it just checks for images in the directory returned by A.png and uses convert or ffmpeg to return a gif animation. Since you've cleverly replaced the original images generated by the animate command with the ones you want, then you will get your animation with

A.show()


Note: it's been bugging me for a long time that there's no good way to animate 3D plots. Maybe this hack will convince someone else that they should figure out a better way to do it! Alternatively, maybe this will tell me that there's already a ticket open for fixing the animate command :)

Second note: the function par from the OP seems to return the same picture, just on different scales. This makes the animation basically constant, so I threw in a fixed rectangle in the xy plane because I couldn't immediately figure out the command to set xmin, xmax or the like for 3D plots. I also updated the Polyhedron command to use floating point numbers instead of integers. This makes par accept non-integral values for some reason, and thus means that the original interact from the OP should work with this updated par function.

more

p.s. note that the saved images are generated with Tachyon by default, and thus look somewhat different from what you see with the jmol viewer.

( 2012-03-29 11:07:34 -0500 )edit

Wow this is really magical. Thanks a lot!

( 2012-03-29 12:46:46 -0500 )edit