Python - Matplotlib responsive window without blocking - python-2.7

I have a main thread which collects data in real time. When it receives some data it adds the data to a stack. The stack is then processed by another thread which writes the data to disk.
Now i also want this thread to plot some of the data (every minute or so). I really like Matplotlibs 3D scatter plot (you can rotate and zoom with the mouse etc.). Problem is, either the window is blocking, so my program doesn't continue, or, if I make it non-blocking, the window controls are unresponsive (no mouse rotation etc.). Is there a way I can have both? I tried doing the Matplotlib stuff in another thread, but then it complains it needs to be in the main thread (tried this with default QT4 and TkAgg backend).
File: plotter.py
import numpy as np
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import threading
class plotter:
def showThread(self):
plt.show()
def __init__(self):
print "plotter initializing"
# plt.ion()
fig = plt.figure()
ax1 = Axes3D(fig)
self.ax1 = ax1
ax1.scatter([0],[0],[0])
ax1.set_xlim3d(0,512,30)
ax1.set_ylim3d(0,256,30)
ax1.set_zlim3d(0,20,5)
plt.draw()
t = threading.Thread(target=self.showThread)
t.start()
def plot(self,xlist,ylist,zlist):
#This function updates the plot..
self.ax1.scatter(xlist,ylist,zlist)
self.ax1.set_xlim3d(0,512,30)
self.ax1.set_ylim3d(0,256,30)
self.ax1.set_zlim3d(0,20,5)
plt.draw()
Error TkInter:
TclError: out of stack space (infinite loop?)
Error QT4 (gives more errors):
File "/usr/lib64/python2.6/site-packages/matplotlib/backends/backend_qt4.py", line 73, in mainloop
signal.signal(signal.SIGINT, signal.SIG_DFL)
ValueError: signal only works in main thread

Related

Saving data from traceplot in PyMC3

Below is the code for a simple Bayesian Linear regression. After I obtain the trace and the plots for the parameters, is there any way in which I can save the data that created the plots in a file so that if I need to plot it again I can simply plot it from the data in the file rather than running the whole simulation again?
import pymc3 as pm
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0,9,5)
y = 2*x + 5
yerr=np.random.rand(len(x))
def soln(x, p1, p2):
return p1+p2*x
with pm.Model() as model:
# Define priors
intercept = pm.Normal('Intercept', 15, sd=5)
slope = pm.Normal('Slope', 20, sd=5)
# Model solution
sol = soln(x, intercept, slope)
# Define likelihood
likelihood = pm.Normal('Y', mu=sol,
sd=yerr, observed=y)
# Sampling
trace = pm.sample(1000, nchains = 1)
pm.traceplot(trace)
print pm.summary(trace, ['Slope'])
print pm.summary(trace, ['Intercept'])
plt.show()
There are two easy ways of doing this:
Use a version after 3.4.1 (currently this means installing from master, with pip install git+https://github.com/pymc-devs/pymc3). There is a new feature that allows saving and loading traces efficiently. Note that you need access to the model that created the trace:
...
pm.save_trace(trace, 'linreg.trace')
# later
with model:
trace = pm.load_trace('linreg.trace')
Use cPickle (or pickle in python 3). Note that pickle is at least a little insecure, don't unpickle data from untrusted sources:
import cPickle as pickle # just `import pickle` on python 3
...
with open('trace.pkl', 'wb') as buff:
pickle.dump(trace, buff)
#later
with open('trace.pkl', 'rb') as buff:
trace = pickle.load(buff)
Update for someone like me who is still coming over to this question:
load_trace and save_trace functions were removed. Since version 4.0 even the deprecation waring for these functions were removed.
The way to do it is now to use arviz:
with model:
trace = pymc.sample(return_inferencedata=True)
trace.to_netcdf("filename.nc")
And it can be loaded with:
trace = arviz.from_netcdf("filename.nc")
This way works for me :
# saving trace
pm.save_trace(trace=trace_nb, directory=r"c:\Users\xxx\Documents\xxx\traces\trace_nb")
# loading saved traces
with model_nb:
t_nb = pm.load_trace(directory=r"c:\Users\xxx\Documents\xxx\traces\trace_nb")

Jupyter/ipython notebook : how to prevent plot redraw using interactive widget

I am struggling to have construct an interactive tool in jupyter notebook. Based on the discussion here : IPython Notebook widgets for Matplotlib interactivity, I've build the following example:
%matplotlib notebook
import matplotlib.pyplot as plt
from ipywidgets import Select,interactive,Dropdown
from IPython.display import display
fig,ax = plt.subplots()
ax.plot(range(5))
vline = ax.axvline(1, color='k')
hline = ax.axhline(0.5, color='k')
def set_cursor(x, y):
vline.set_xdata((x, x))
hline.set_ydata((y, y))
ax.figure.canvas.draw_idle()
interactive(set_cursor, x=ax.get_xlim(), y=ax.get_ylim())
It works pretty well except that that the last line (interactive...) has to be run in a different cell.
If I want to launch everything in the same cell (or from the same object if use a Class approach, which is what I want at the end), I have to use the following code:
%matplotlib notebook
import matplotlib.pyplot as plt
from ipywidgets import Select,interactive,Dropdown
from IPython.display import display
fig,ax = plt.subplots()
ax.plot(range(5))
vline = ax.axvline(1, color='k')
hline = ax.axhline(0.5, color='k')
def set_cursor(x, y):
vline.set_xdata((x, x))
hline.set_ydata((y, y))
ax.figure.canvas.draw_idle()
display(fig)
tool = interactive(set_cursor, x=ax.get_xlim(), y=ax.get_ylim())
display(tool)
But in this case, the complete figure is redraw each time a new value is selected in a widget
Is there any possibility to get everything launch smoothly from the same cell ?
Any idea is more than welcome !

pygame program exits with no error message when run with pythonw

I'm trying to run a pygame program using pythonw to avoid having the console window show up. This causes a weird issue related to print statements.
Basically, the program will just exit after a few seconds with no error message. The more printing I do, the faster it happens.
If I run it in idle or at the command prompt (or in linux) the program works fine. This problem only happens when launched with pythonw (right-click, Open With, pythonw).
I'm using python 2.7.11 on Windows XP 32-bit. pygame 1.9.1release.
Is there a workaround for this? Why does the program simply terminate with no error?
import pygame
from pygame.locals import *
succeeded, failed = pygame.init()
display_surface = pygame.display.set_mode((320, 240))
clock = pygame.time.Clock()
terminate = False
while terminate is False:
for event in pygame.event.get():
if event.type == QUIT:
terminate = True
area = display_surface.fill((0,100,0))
pygame.display.flip()
elapsed = clock.tick(20)
print str(elapsed)*20
pygame.quit()
You don't need to remove print statements. Save them for later debugging. ;-)
Two steps to solve this problem:
Firstly, keep all the code in py file - don't change it to pyw now; Say it is actualCode.py
Then, create a new file runAs.pyw with the following lines in it
# In runAs.pyw file, we will first send stdout to StringIO so that it is not printed
import sys # access to stdout
import StringIO # StringIO implements a file like class without the need of disc
sys.stdout = StringIO.StringIO() # sends stdout to StringIO (not printed anymore)
import actualCode # or whatever the name of your file is, see further details below
Note that, just importing actualCode runs the file, so, in actualCode.py you should not enclose the code which is executed, in what I call is it main running file condition. For example,
# In actualCode.py file
....
....
....
if __name__ == '__main__': # Don't use this condition; it evaluates to false when imported
... # These lines won't be executed when this file is imported,
... # So, keep these lines outside
# Note: The file in your question, as it is, is fine

PyQt4 and Qwt Error when opening

i´m trying to do a simple plot, using PyQt4 and Qwt5. When i start the app, it shows as i expected, but i can´t do anything, such as click or zoom for example. And if i minimize it, the plot disappears.
This is my code:
import sys
from PyQt4 import Qt
import numpy as np
import PyQt4.Qwt5.iqt
from PyQt4.Qwt5.qplt
class SimpleData(QwtPlot):
def __init__(self):
QwtPlot.__init__(self)
x = np.arange(-2*np.pi, 2*np.pi, 0.01)
p = IPlot(Curve(x, np.cos(x), Pen(Magenta,2), "cos(x)"),
Curve(x, np.exp(x), Pen(Red), "exp(x)", Y2),
Axis(Right, Log),"Ejemplo de PyQt con PyQwt")
x = x[0: -1: 10]
p.plot(Curve(x, np.cos(x-np.pi/4), Symbol(Circle, Yellow), "circle"),
Curve(x, np.cos(x+np.pi/4), Pen(Blue), Symbol(Square, Cyan), "Square"))
app = QApplication(sys.argv)
app.exec_()
The indentation is correct, maybe i made a mistake writting it here, but it´s ok.
Another thing, when i close the app, i get this error:
QObject::killTimers: timers cannot be stopped from another thread
[Finished in 2.6s with exit code -1073741510]
Thank you for your time and answers. I hope you can help me.

python 2.7 while loop, ttk.progressbar not working

I am working on a progress bar that keeps track of a certain function in pygame.
The following code causes a loop that I must force quit. And I can not figure our my error. Any help would be great.
from Tkinter import *
import ttk
import sys
import pygame
myGui = Tk()
myGui.title("Progress Bar")
myGui.geometry("400x200+200+300")
value_progress = StringVar()
pygame.mixer.init()
pygame.mixer.music.load("/home/david/Documents/aaa.mp3")
pygame.mixer.music.play()
def position():
global value_progress
while pygame.mixer.music.get_busy() == True:
value_progress.set(float(pygame.mixer.music.get_pos()))
b = Button(myGui, text="Start", )
b.pack()
p = ttk.Progressbar(myGui, variable=value_progress,
mode='determinate', length=350,
maximum= 512920)
p.pack()
I call the function from the shell. and then it stalls and does not come out of it.
This is only the progress bar portion of my work. However, it causes the program to crash every time.
Do not loop. Instead try following code:
def position():
global value_progress
if pygame.mixer.music.get_busy():
value_progress.set(float(pygame.mixer.music.get_pos()))
myGui.after(100, position)
Tk.after(ms, f) call f after specified ms millisecond.