Python executable hangs with plt.show() - python-2.7

I am creating a GUI application (EXE) in Python 2.7 on Win 10 platform.
The application is supposed to plot a graph (using matplotlib) with user provided parameters. When the user changes the values and presses the plot button again, new graph should be plotted on the same figure retaining the previous curves for ease of comparison (also a requirement).
I had to use plt.show() at the end of the script to show the graph when running the exe file of my program.
Problem: Application freezes and crashes when the plot button is pressed the second time. For the first time, everything goes fine and the graph is displayed.
Solutions tried:
Going thru so many threads, I tried following solutions without luck:
Used plt.draw() instead of plt.show() because the later blocks program execution. But draw() does not display the graphs.
Tried plt.pause(), the application gives RunTime error and crashes.
Also played with ion() / ioff().
Tried plt.show(block = False), the application crashes on second click on plot button.
I came across various backends that can be used with matplotlib and suspected that plt.show() might work well with other backends. Tried TkAgg, WxAgg, and others but no luck.
I would really appreciate if someone can help me with this...already tried for 3 days!!
Code sample:
from PyQt4 import QtCore, QtGui
import numpy as np
import matplotlib
matplotlib.use('TkAgg') #Trying different backends
import matplotlib.pyplot as plt
plt.rc('xtick', labelsize = 16)
plt.rc('ytick', labelsize = 16)
import FileDialog #These three imports needed for EXE
import tkFileDialog
import tkMessageBox
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
#UI elements code...
def retranslateUi(self, MainWindow):
#Other code lines
def my_Plot_Function():
#Some calculations
plt.figure('My title')
plt.plot(x, y, label = 'My Label')
plt.grid(True)
plt.axhline(y = 0, color = 'k')
plt.xlabel(' X ', fontsize = 16)
plt.ylabel(' Y ', fontsize = 16)
plt.legend(prop={'size': 14})
plt.show()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

Related

PyQt4 - can't get video to run with QMovie or Phonon

I'm having problems getting any video player to work with my PyQt4 setup (having tried both phonon and QMovie). The below QMovie script is from an example where several users commented it as functional. For me, it runs but only opens a window (with Loading... centered) that never actually plays the .gif (I've tried several working .gif files from numerous examples online, so the file is not the problem). I've commented out the results from running the three debugging steps as well.
What can I do next?
import sys
import os
import sip
sip.setapi('QVariant', 2)
from PyQt4 import QtGui, QtCore
class BusyLabel(QtGui.QWidget):
def __init__(self, gif, parent = None, text = None):
QtGui.QWidget.__init__(self, parent)
self.hlayout = QtGui.QHBoxLayout(self)
self.hlayout.setSpacing(0)
self.hlayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.hlayout)
# Movie
self.movieLabel = QtGui.QLabel(self)
self.movieLabel.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
self.movieLabel.setAlignment(QtCore.Qt.AlignCenter)
self.movie = QtGui.QMovie(gif, QtCore.QByteArray(), self)
self.movie.setScaledSize(QtCore.QSize(20,20))
self.movie.setCacheMode(QtGui.QMovie.CacheAll)
self.movie.setSpeed(100)
print self.movie.isValid() #output = False
print self.movie.supportedFormats() #output = []
self.movieLabel.setMovie(self.movie)
self.hlayout.addWidget(self.movieLabel)
# Label
self.label = QtGui.QLabel(text)
self.hlayout.addWidget(self.label)
self.movie.start()
def setText(self, text):
self.label.setText(text)
def start(self):
self.show()
self.movie.start()
def stop(self):
self.hide()
self.movie.stop()
if __name__ == "__main__":
gif = 'test1.gif'
print os.path.exists(gif) #output = True
app = QtGui.QApplication(sys.argv)
player = BusyLabel(gif)
player.setText('Loading...')
player.start()
player.show()
sys.exit(app.exec_())
output:
True
False
[]
(For those curious about my other attempts, running a popular Phonon script gave the error: phonon backend plugin could not be loaded... I'll take anything at this point)
I'm providing here complete, working code that I've written to answer this (my) problem. All you need is PyQt4 and Matplotlib, I hope this might help someone else facing similar troubles down the road:
https://github.com/evanseitz/PyQt4_VideoPlayer

PyQt4 label crashes when a function is called instead of using raw_input?

I boiled the original code down to a small section that still reproduces the issue. The below code works fine with action = raw_input('next action? ') instead of action = self.fake(). WHY??!! Specifically, the 'label' window will hang and crash using the class function, but will display the two overlaid images no problem using the user input. I cannot fathom how the two are impacting PyQt, especially since the changes are being made AFTER the image update.
import time
import sys
from PyQt4 import QtGui
class Basement(object):
def __init__(self):
self.app = QtGui.QApplication(sys.argv)
self.label = QtGui.QLabel()
def update_image(self):
self.im = QtGui.QImage('n-wall.png')
painter = QtGui.QPainter()
c_image = QtGui.QImage('bed.png')
painter.begin(self.im)
painter.drawImage(10, 10, c_image)
painter.end()
self.label.setPixmap(QtGui.QPixmap.fromImage(self.im))
self.label.show()
def fake(self):
return 'left'
def play_game(self):
### Update graphics / text
self.update_image()
### Decide action
action = self.fake()
#action = raw_input('next action? ')
time.sleep(5)
B = Basement()
B.play_game()

Show matplotlib plot inline in jupyter when plot is created in external function

I am running an inference algorithm and would like to show the likelihood function after each iteration. However, the plotting function is part of a package that i am importing. I've managed to cobble it together such that the plot is shown using the tkAgg backend in an external gui window, but is there any way to make it show as an inline plot? Here is what I'm using now:
Minimal Working Example
Jupyter Code
%matplotlib inline
#import matplotlib
#matplotlib.use('tkAgg')
import matplotlib.pyplot as plt
import sys
import numpy as np
sys.path.append('/path/to/file')
#______________________________________________________________
import testclass
a = testclass.test()
a.iterator()
as can be seen below this should iteratively plot a series of dots updating the plot with one dot at a time. When I run it inline I only get the full plot after it has finished running.
Class Code
import numpy as np
import matplotlib
matplotlib.use('tkAgg')
import matplotlib.pyplot as plt
import time
class test(object):
def __init__(self):
self.x = np.random.randint(0,50,size=5)
def iterator(self):
for i in range(5):
self.plotter(i)
st = time.time()
while (time.time()-st)<2:
pass
def plotter(self,i):
if not hasattr(self,'fig'):
self.fig = plt.figure()
else:
plt.close(self.fig)
self.fig = plt.figure()
#plt.ion()
self.fig.gca().plot(self.x[:i],'o')
self.fig.show()
Original Code
Notebook Code
import matplotlib
matplotlib.use('tkAgg')
import mypackage
class_instance = mypackage.myclass()
myclass.fit(n_iterations=100)
the plotting function is a bound method of the class and is called by the fit method.
Plotting Function Function
def update_plot(self,r,LLst,kkk):
if not hasattr(self,'LL_fig'):
self.LL_fig = plt.figure()
else:
plt.close(self.LL_fig)
self.LL_fig = plt.figure()
#plt.ion()
#self.LL_fig.clf()
ax = self.LL_fig.gca()
ax.plot(LLst[1:],linestyle='-',marker='.')
#plt.gca().set_xlim([0,np.max([50,kkk])])
ax.set_xlim([0,np.max([50,kkk])])
ax.set_xlabel('EM iter')
ax.set_ylabel('$\mathcal{L}( \\theta )$')
seaborn.despine(trim=True,offset=15)
#plt.draw()
self.LL_fig.show()
#display.clear_output(wait=True)
#display.display(plt.gcf())
sys.stdout.write("\riter: %s || LL: %s || message: %s" %(kkk,np.round(LLst[-1],decimals=2), r['status']))
sys.stdout.flush()
Also, if I don't close and 're-initialise' the figure each time, the plot starts coming up empty. Any help would be much appreciated!
edit:
if I try using matplotlib inline instead of tkAgg backend I get the following warning message:
UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure
"matplotlib is currently using a non-GUI backend, "
Use the cell magic %matplotlib inline (if you aren't familiar with cell magics, just place it in a line on its on in one of your cells)

wxPython can't properly position a matplotlib block

I've taken the code to draw a rectangle over image form here, and modified it a little bit to suite my purposes. The only problem I have, it doesn't appear to be full screen, even though I make fr.ShowFullScreen(True). There is a grey area around the image.
Edited code is below (the rectangle part is not relevant):
# Use the wxPython backend of matplotlib
import matplotlib
matplotlib.use('WXAgg')
# Matplotlib elements used to draw the bounding rectangle
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
# wxPython stuff for the demo
import wx
class RectangleSelectImagePanel(wx.Panel):
def __init__(self, parent, pathToImage=None):
# Initialise the parent
wx.Panel.__init__(self, parent)
# Intitialise the matplotlib figure
self.figure = Figure(figsize=(20,15), dpi=80)
# Create an axes, turn off the labels and add them to the figure
self.axes = self.figure.add_subplot(1, 1, 1)
self.axes.set_axis_off()
# Add the figure to the wxFigureCanvas
self.canvas = FigureCanvas(self, -1, self.figure)
# Sizer to contain the canvas
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 0, wx.ALL)
self.SetSizer(self.sizer)
self.Fit()
def setImage(self, pathToImage):
'''Sets the background image of the canvas'''
import matplotlib.image as mpimg
# Load the image into matplotlib
image = matplotlib.image.imread(pathToImage)
# left in as anchor for image size
self.imageSize = image.shape[0:2]
print self.imageSize
#
# Add the image to the figure and redraw the canvas. Also ensure the aspect ratio of the image is retained.
self.axes.imshow(image, interpolation="quadric", aspect='auto')
self.canvas.draw()
if __name__ == "__main__":
# Create an demo application
app = wx.App()
# Create a frame and a RectangleSelectorPanel
fr = wx.Frame(None, title='test')
panel = RectangleSelectImagePanel(fr)
# Set the image in the panel
from matplotlib.cbook import get_sample_data
imgpath = get_sample_data('logo2.png', asfileobj=False)
panel.setImage(imgpath)
# Start the demo app
fr.ShowFullScreen(True)
app.MainLoop()
probably what you need is subplots_adjust.
from pylab import *
from matplotlib.cbook import get_sample_data
imgpath = get_sample_data('logo2.png', asfileobj=False)
image = matplotlib.image.imread(imgpath)
imshow(image, aspect='auto')
subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
This will produce a plot that has no margin around the image.
So, if you put
self.figure.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
after imshow line, you will get something closer to what you need.
Then, you will probably have to adjust the figsize parameter too. for my 1920 x 1080 display, I will need 1920.0/80 inch by 1080.0/80 inch so (24,13.5)

Aptana 3 Pydev not getting Tk() window after running

I am new to Aptana, and have searched the net to see how it handles gui development.
I have tried the following code. It shows no bugs in the console. However, it will not give me the Tk() window named myGui.
from Tkinter import *
import ttk
def main():
myGui = Tk()
myGui.title("My Gui New")
myGui.geometry('400x200+200+200')
l = Label(myGui, text="Help")
l.pack()
if __name__ == "__main__":
main()
Any pointers. I able to get my functions to run in the console, but this Gui development is not working out so well.
The-IT is right, you do want to add myGui.mainloop() to the end of main.
Normally when I'm working in Tkinter I try to move some of the information in your function main into the if... clause. This makes larger, more complex interfaces much easier to handle.
A good start is to use a class:
from Tkinter import *
from ttk import *
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
self.create_widgets()
def create_widgets(self):
self.l = Label(self, text='Help')
self.l.pack()
if __name__ == '__main__':
root = Tk()
app = App(root)
root.mainloop()
The benefits of this is that you can easily introduce toplevels, add additonal widgets (in an organized fashion) and have clearer code. You can also use the classes to make templates for other widgets; in this case, you are building a special frame class and giving it whatever attributes you want. The same can be done for buttons, entries, and other frames. I'm not familiar with aptana3, but this should work with no problem. Just make sure your indentation is consistent.