I am trying to do an animation program in VTK, in which I could make the VTK objects animate
but I failed to do pausing animation and restart animation, I came to know recently to stop the VTK timer but after if I click the animate button again to start then the program got crashed with following error, I have only one clue that the following line is crashing but this line will work at the first time of animation button click but fails on the second button click!!. The second function "animation_Stop" is my attempt of stopping the function by destroying the whole function, so I hoped I could avoid the program crash but it was also a failure!!
Error:
python.exe has stopped working
Error line:
self.renderWindowInteractor.SetRenderWindow(obj_renwin.renwin)
Please note my detailed code lines for animation and someone please help me to restart
and pause the animation in vtk python
def animation(self,obj_renwin,X):
if X==1:
print "start or restart animation"
self.renderWindowInteractor = vtk.vtkRenderWindowInteractor()
objRen=self.renderWindowInteractor.GetRenderWindow()
self.renderWindowInteractor.SetRenderWindow(obj_renwin.renwin)
obj_renwin.renwin.Render()
self.renderWindowInteractor.Initialize()
cb = vtkTimerCallback()
cb.actor = obj_renwin.actor
self.renderWindowInteractor.AddObserver('TimerEvent', cb.execute)
self.timerId = self.renderWindowInteractor.CreateRepeatingTimer(5);
if X==2:
print "stop animation"
self.renderWindowInteractor.DestroyTimer(self.timerId)
def animation_Stop(self,obj_renwin):
print "stop animation"
#self.animation(obj_renwin,1).destroy()
del (ConeRender.Cone.animation)
If you start the vtkTimer like that:
vtkSmartPointer<vtkTimerCallback> cb =
vtkSmartPointer<vtkTimerCallback>::New();
interactor->AddObserver(vtkCommand::TimerEvent, cb);
you may consider to stop/pause the timer with
vtkCommand::EndInteraction
i.e.
interactor->InvokeEvent(vtkCommand::TimerEvent, cb);
[It is just a moment thought, you can try it] ... :)
Related
I set up a Jupyter Notebook where I'm running a recursive function that clears the output like so, creating an animated output:
from IPython.display import clear_output
active = True
def animate:
myOutput = ""
# do stuff
clear_output(wait=True)
print(myOutput)
sleep(0.2)
if active:
animate()
and that's working perfectly.
But now I want to add in one more step: A speed toggle. What I'm animating is a debugging visualization of a cursor moving through interpreted code as an interpreter I'm writing parses that code. I tried conditional slow-downs to have more time to read what's going on as the parsing continues, but what I really need is to be able to click a button to toggle the speed between fast and slow. Maybe I'll use a slider, but for now I just want a button for proof of concept.
This sounds simple enough. Note that I'm writing this statefully as a class because I need to read / write the state from within another imported class.
Jupyter block 1:
import ipywidgets as widgets
from IPython.display import display
out = widgets.Output()
class ToggleState():
def __init__(self):
self.button = widgets.Button(description="Toggle")
self.button.on_click(self.toggle)
display(self.button)
self.toggleState = False
print("Toggle State:", self.toggleState)
def toggle(self, arg): # arg has to be accepted here to meet on_click requirements
self.toggleState = not self.toggleState
print("Toggle State:", self.toggleState)
def read(self):
return self.toggleState
toggleState = ToggleState()
Then, in Jupyter block 2, note I decided to to do this in a separate block because the clear_output I'm doing with the animate func clears the button if it's in the same block, and therein lies the problem:
active = True
def animate:
myOutput = ""
# do stuff
clear_output(wait=True)
print(myOutput)
if toggleState.read():
sleep(5)
else:
sleep(0.2)
if active:
animate()
But the problem with this approach was that two blocks don't actually run at the same time (without using parallel kernels which is way more complexity than I care for) so that button can't keep receiving input in the previous block. Seems obvious now, but I didn't think about it.
How can I clear input in a way that doesn't delete my button too (so I can put the button in the animating block)?
Edit:
I thought I figured the solution, but only part of it:
Using the Output widget:
out = widgets.Output()
and
with out:
clear_output(wait=True) # clears only the logged output
# logging code
We can render to two separate stdouts within the same block. This works to an extent, as in the animation renders and the button isn't cleared. But still while the animation loop is running the button seems to be incapable of processing input. So it does seem like a synchronous code / event loop blocking problem. What's the issue here?
Do I need an alternative to sleep that frees up the event loop?
Edit 2:
After searching async code in Python, I learned about asyncio but I'm still struggling. Jupyter already runs the code via asyncio.run(), but the components obviously have to be defined as async for that to matter. I defined animate as async and tried using async sleeps, but the event loops still seems to be locked for the button.
I'm trying to do something in a Jupyter notebook that runs a continuous process, but with a pause button to interrupt it. Below is a simplified version of what I've done so far, but it seems Ipython wants to complete the entire run() function before it executes commands it receives from the button. The problem, of course, being that run() will never finish unless interrupted.
Interestingly, the below strategy works just fine in my Tkinter frontend so long as I put a pause(0.0001) at the end of the updateGraph() function. Architecturally, I'd be curious why Tkinter is willing to listen to input events during that pause but Jupyter isn't. But more importantly, is there a way to get Jupyter to listen while running run()?
from ipywidgets import Button
from IPython.display import display
startstop = Button(description='Run')
startstop.click = run
display(startstop)
def run(b=None):
running=True
while running:
#Do stuff and update display
updateGraph()
startstop.click = pause
startstop.description = 'Pause'
def pause(b=None):
running = False
startstop.click = run
startstop.description = 'Run'
I prefer using Keyboard for this purpose. It is a much simpler approach to the same problem...
import keyboard
def run():
running=True
while running:
pass # some code here...
if keyboard.is_pressed('alt'):
break
run()
Press Alt key anytime to stop the execution of the program.
I have written a little script to batch plot some data. This script cannot run without a window displaying the newly created plot opening. It stops running till the window is manually closed, then the script continues to run. So my question is as follows:
Is there a way automatically close an output window from within a python script?
Here is the script
import pynbody
import numpy as np
import pynbody.plot.sph as sph
f = open('files.txt', 'r')
for line in f:
line = line[0:-1]
s = pynbody.load(line)
sph.image(s.gas,qty="temp",width=16, filename=line[0:-6]+line[-5:len(line)], units='K', cmap="YlOrRd", ret_im=False , approximate_fast=False)
#At the end of the loop I would like to close the output window so the script
#will continue to run
The pynbody.plot.sph package seems as it should be able to turn the output window on and off within the sph.image function call but I have exhausted all the possibilities and am now resorting to this to get the script running.
I found the answer using this link
view and then close the figure automatically in matplotlib?
Essentially, here's the answer:
plt.show(block=False) # block = False allows automatic closing of the image
# the following command will close the graph in 3 seconds
time.sleep(3)
plt.close()
According to the documentation, you should set the noplot argument to True
Add a line pynbody.plot.plt.close() to the for loop.
Definition: pynbody.plot.plt.close(*args) Docstring: Close a figure
window.
close() by itself closes the current figure
close(h) where h is a :class:Figure instance, closes that
figure
close(num) closes figure number num
close(name) where name is a string, closes figure with that
label
close('all') closes all the figure windows
I am attempting for a homework assignment to implement Simon Says in python. I'm trying to do it using the turtle library (a requirement).
However, I've run into a stumbling block in that while I can get the screen to register click events (currently just printing the x,y coordinates) I can't get it to wait for a click event.
Specifically what I'm planning on doing is having areas on the screen that when they click within that location it is considered as if they had clicked a button. Screen clears and game does whatever.
However, in experiments in trying to get a working 'button' all that it does is set it so it prints the x,y coordinates but the rest of the program finishes. Didn't wait for the user to click anything. I tried a blocking method of...
while clicked == False:
pass
or
while clicked == False:
time.sleep(1)
but both methods hangs the program until I manually interrupt and then it'll print the clicks.
Am I missing an option somewhere?
Turtles don´t have buttons, but they do have callbacks for clicks.
Furthermore, you should use onclick for Screen to detect general clicks and onclick for turtle to detect clicking in turtles. You can, for example, make a 4 BIG turtles with different colors by using a dynamic shape.
Also, turtle is based on Tk, so you must be aware of things like mainloop()
The following program give some hints for Python 2.7.5.
import turtle as t
from random import randint
class MyTurtle(t.Turtle) :
def __init__(self,**args) :
t.Turtle.__init__(self,**args)
def mygoto(self,x,y) :
t1.goto(x,y)
print x,y
def randonics(self,x,y) :
self.left(randint(90,270))
def minegoto(x,y) :
print x,y
t1.goto(x,y)
wt=t.Screen()
t1=MyTurtle()
wt.register_shape("big",((0,0),(30,0),(30,30),(0,30)))
t1.shape("big")
wt.onclick(t1.mygoto,btn=1)
wt.onclick(minegoto,btn=2)
t1.onclick(t1.randonics,btn=3)
t1.goto(100,100)
t.mainloop()
So after extensive search there isn't necessarily a way pause execution of the code in python while using turtle to wait for some click event. Maybe in Tk I could do that but not in turtle.
However, there is a way to get around that. As an example. A method sets up the fake button on the screen, sets the click event, and terminates. The click event when clicked calls the next method needed for execution. So until the button is clicked the actual code isn't doing anything but remains in memory for use.
So more specifically.
1. Create a 'button'.
2. Have your program behave normally until it needs to wait for a click event.
3. Set up the on screen click (or on turtle) in such a way when the 'button' is clicked the next part of the code is run.
Special note. The code in question can't depend on waiting for a click event for later on in code. Instead, the click causes the next part of the execution of your code.
You can make the function registered with onclick() test the x,y position. If it is inside some region you do whatever you must.
I don´t see the difference between what you want to do and what this code does, the modification of turtle position is just an example, you can do anything when a click is captured by onclick(), even start a thread if you really need it (using Creating Threads in python)
import turtle as t
from random import randint
from threading import Thread
from time import sleep
def threaded_function(arg,t1):
for i in range(arg):
print "running",i
sleep(1)
t1.forward(i*10)
def minegoto(x,y) :
print x,y
t1.goto(x,y)
thread = Thread(target = threaded_function, args = (10,t1 ))
thread.start()
thread.join()
print "thread finished...exiting"
wt=t.Screen()
t1=t.Turtle()
wt.register_shape("big",((0,0),(30,0),(30,30),(0,30)))
t1.shape("big")
wt.onclick(minegoto,btn=1)
t1.goto(100,100)
t.mainloop()
I have a python program using pyplot (backend:tkagg), in which simply a matplotlib is created with some stuff in it.
When I want to exit the program, I immediately call:
plt.close('all')
to shut it down.
Strangely enough, the program dosnt exit.
Following it with the debugger I saw that after everithing is done, it returns to
class Show(ShowBase):
def mainloop(self):
Tk.mainloop()
in backend_tkagg.py,
followed by
if not is_interactive():
self.mainloop()
in the same file, then to
def show(*args, **kw):
global _show
_show(*args, **kw)
in pyplot.py
So it appears that I am still in the pyplot loop!
How do I exit from it correctly?
thanks...
You are not in the pyplot loop per-say, but the main loop associated with the GUI toolkit (this is the loop that deals with all the user interactions with the GUI). I suspect it is safe to just call exit() in your program and let object clean up deal with properly tearing down the TK objects/mainloop
maybe related :
Exit Tks mainloop in Python?,