I have embedded a matplotlib figure into my PyQt5 GUI and I'm having trouble specifying a custom style. Only the font size of the legend is changing. Is there a difference to the use of this with an embedded plot using the QT5Agg backend?
Normally I can specify a custom style sheet using the following but this doesn't seem to be working with the embedded figure:
import matplotlib.pyplot as plt
plt.style.use('./Plotting styles/wfa setup graphic.mplstyle')
the style sheet is as follows:
backend: Qt5Agg
# Labels
axes.titlesize : 30
#axes.labelsize : 20
#Lines
lines.linewidth : 3
lines.markersize : 10
#Axis
axes.spines.right : False
axes.spines.top : False
xtick.labelsize : 40
ytick.labelsize : 40
#Legend
legend.fontsize : 20
I'm implementing the figure using the following:
from PyQt5.QtWidgets import *
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import numpy as np
class MplWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.canvas = FigureCanvas(Figure())
vertical_layout = QVBoxLayout()
vertical_layout.addWidget(self.canvas)
self.setLayout(vertical_layout)
# define plot widget
plt_stg_res2 = MplWidget()
# define figure
fig = plt_stg_res2.canvas.figure
# clear the figure
fig.clf()
# create axes
ax1 = fig.add_subplot(111)
# apply custom style
plt.style.use('./Plotting styles/wfa setup graphic.mplstyle')
#plt.style.context(matplotlib_styles.plot_style_stage_overlays())
# These are the colors that will be used in the plot
ax1.set_prop_cycle(color=[
'#1f77b4', '#aec7e8', '#ff7f0e', '#ffbb78', '#2ca02c', '#98df8a',
'#d62728', '#ff9896', '#9467bd', '#c5b0d5', '#8c564b', '#c49c94',
'#e377c2', '#f7b6d2', '#7f7f7f', '#c7c7c7', '#bcbd22', '#dbdb8d',
'#17becf', '#9edae5'])
# plot equity curve from all passes
for opt_pass in self.passes.values():
# Plot each line separately with its own color.
trade_time = np.array([self.start_date] + opt_pass.deal_time)
balance = np.cumsum(np.array([self.start_balance] + opt_pass.deal_profit))
line, = ax1.plot(trade_time, balance, label=f'Pass {opt_pass.pass_num}', lw=1)
ax1.legend(bbox_to_anchor=(1, 1.05), loc='right')
ax1.set_xlabel('Date')
ax1.set_ylabel(f"Balance ({opt_inputs['currency']})")
# Remove the plot frame lines. They are unnecessary here.
ax1.spines['top'].set_visible(True)
ax1.spines['bottom'].set_visible(True)
ax1.spines['right'].set_visible(True)
ax1.spines['left'].set_visible(True)
ax1.tick_params(axis='both', which='both', labelsize=8,
bottom=True, top=False, labelbottom=True,
left=False, right=True, labelleft=True)
# Add Title
fig.suptitle(f'Equity Curves for each Optimisation Pass '
f'in {self.stage_name}', fontsize=12, ha="center")
plt_stg_res2.canvas.draw()
Related
I have a troubleing bug that i just could not understands it's origin. Several days of attempts and still no luck.
I'm trying to create a line cursor that correspond to played audio with FuncAnimation and for some reason, the animation is created twice ONLY when the callback (line_select_callback) that activates the function is triggered from RectangleSelector widget after drawing wiith the mouse. when I use a standard TK button to activate the SAME function (line_select_callback), it operates well.
some debugging code with reevant prints is present.
I've created minimal working example.
My guess is it has something to do with the figure that is not attached to the tk window, and is silently activated in addition to the embedded figure, I'm not really sure.
Any help will be very much appreciated, Thanks! :)
import os
import threading
import tkinter as tk
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg)
from matplotlib.widgets import RectangleSelector
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import animation
class LineAnimation:
def __init__(self, fig, ax):
print(' enter LineAnimation ctor')
# Parameters
self.ax = ax
self.fig = fig
self.xdata, self.ydata = [], []
self.ln, = plt.plot([], [], 'ro')
# Print figures list
figures = [manager.canvas.figure
for manager in matplotlib._pylab_helpers.Gcf.get_all_fig_managers()]
print('figures BEFORE animation: ', figures)
self.animation = animation.FuncAnimation(fig=self.fig,
func=self.update,
init_func=self.init,
frames=np.linspace(0, 2 * np.pi, 128),
interval=25,
blit=True, repeat=False,
cache_frame_data=False)
self.fig.canvas.draw()
# Print figures list
figures = [manager.canvas.figure
for manager in matplotlib._pylab_helpers.Gcf.get_all_fig_managers()]
print('figures AFTER animation: ', figures, '\n')
def init(self):
# Prints for debugging
print('\nenter init animate')
print('Thread id: ', threading.get_ident())
print('Process id: ', os.getpid(), '\n')
# Init
self.ax.set_xlim(0, 2*np.pi)
self.ax.set_ylim(-1, 1)
return self.ln,
def update(self, frame):
self.xdata.append(frame)
self.ydata.append(np.sin(frame))
self.ln.set_data(self.xdata, self.ydata)
return self.ln,
class Example:
def __init__(self):
# init window
self.root = tk.Tk(className=' Species segmentation')
self.fig, self.ax = plt.subplots()
# init sine audio file
self.fs = 44100
self.dur = 2
self.freq = 440
self.x = np.sin(2*np.pi*np.arange(self.fs*self.dur)*self.freq/self.fs)
# plt.ion()
# Embedd in tk
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root) # A tk.DrawingArea.
self.canvas.draw()
self.canvas.get_tk_widget().grid()
# Plot something
self.N = 100000
self.xp = np.linspace(0, 10, self.N)
self.ax.plot(self.xp, np.sin(2*np.pi*self.xp))
self.ax.set_title(
"Plot for demonstration purpuse")
# init Rectangle Selector
self.RS = RectangleSelector(self.ax, self.line_select_callback,
drawtype='box', useblit=True,
button=[1, 3], # avoid using middle button
minspanx=5, minspany=5,
spancoords='pixels', interactive=True,
rectprops={'facecolor': 'yellow', 'edgecolor': 'black', 'alpha': 0.15, 'fill': True})
self.canvas.draw()
# plt.show()
tk.mainloop()
def line_select_callback(self, eclick, erelease):
print('enter line_select_callback')
self.anim = LineAnimation(
self.fig,
self.ax)
self.fig.canvas.draw()
# plt.show()
Example()
I managed to isolate the cause for this issue: The presence of the
rectangle selector (which uses blitting) and the use of animation (which also uses blitting) on the same axes.
I've managed to create the animation properly, but only when I disabled the rectangle selector
self.RS.set_active(False)
self.RS.update()
self.canvas.flush_events()
and removed his artists (i needed to do that manually in my code) using:
for a in self.RS.artists:
a.set_visible(False)
after that, The animation worked properly.
I want to display history of CPU and RAM usage in Jupyter Notebook in real time. Something like this (Process Explorer in Windows):
I don't interactivity so I use matplotlib in inline mode. I run a separate background thread and try to update two different plots from there. It works well with one plot but the second one blinks and has duplicates.
Here's a minimal example (also I pickle/unpickle plot so I can initialize it only once and reuse later).
Installed packages:
ipykernel 5.1.3
ipywidgets 7.5.1
jupyter 1.0.0
jupyter-core 4.6.1
matplotlib 3.1.1
notebook 6.0.0
import pickle
import threading
import time
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np
def init_history_plot():
"""
Create plot template (dump)
Returns: pickled str
"""
# plt.figure(figsize=(15, 1.2))
# ax = plt.axes()
fig, ax = plt.subplots(figsize=(15, 1.2))
# Y axis min-max
ax.set_ylim(0, 100)
# ax.get_xaxis().set_visible(False)
ax.grid(axis='y')
# right tick labels https://stackoverflow.com/a/13369977
ax.yaxis.tick_right()
# hide ticks https://stackoverflow.com/a/33707647
ax.yaxis.set_ticks_position('none')
# borders https://stackoverflow.com/a/27361819
# for i in ax.spines.values(): # 'left', 'right', 'top', 'bottom'
# ax.spines[i].set_visible(False)
# https://stackoverflow.com/questions/18603959/borderless-matplotlib-plots
ax.set_frame_on(False)
dat = pickle.dumps(fig)
plt.close()
return dat
def load_figure(dump):
"""
Load Figure from dump
Returns: (Figure, Axes)
"""
# https://github.com/ipython/ipykernel/issues/231
import ipykernel.pylab.backend_inline as back_inline
import matplotlib.backends.backend_agg as back_agg
back_inline.new_figure_manager_given_figure = back_agg.new_figure_manager_given_figure
figure = pickle.loads(dump)
# https://github.com/matplotlib/matplotlib/issues/17627/
figure._cachedRenderer = None
return figure, figure.axes[0]
template_fig = init_history_plot()
btn_start = widgets.ToggleButton(description="Start thread")
plt1_parent = widgets.Output()
plt2_parent = widgets.Output()
_interface = widgets.VBox(children=[btn_start, plt1_parent, plt2_parent])
def worker():
while btn_start.value:
with plt1_parent:
plt1_parent.clear_output(wait=True)
fig, ax = load_figure(template_fig)
dat = np.random.normal(scale=20, size=50) + 50
ax.plot(dat, color='green')
plt.show()
# THE FOLLOWING BLOCK BLINKS
with plt2_parent:
plt2_parent.clear_output(wait=True)
fig, ax = load_figure(template_fig)
dat = np.random.normal(scale=20, size=50) + 50
ax.plot(dat, color='red')
plt.show()
############################
time.sleep(1)
def start_thread(_):
if btn_start.value:
thread = threading.Thread(target=worker)
thread.start()
btn_start.observe(start_thread, 'value')
_interface
I think your code is really cool, and so I greedily stole it because I also want to have plots that live-update in a Jupyter notebook without blocking the kernel.
Anyway, the weird flickering was bothering me as well. I tried switching from threading to asyncio, simply because I am more familiar with asyncio than threading, and that actually seems to have solved the problem! Though I have no idea why.
Try:
import pickle
import asyncio
import time
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np
def init_history_plot():
"""
Create plot template (dump)
Returns: pickled str
"""
# plt.figure(figsize=(15, 1.2))
# ax = plt.axes()
fig, ax = plt.subplots(figsize=(15, 1.2))
# Y axis min-max
ax.set_ylim(0, 100)
# ax.get_xaxis().set_visible(False)
ax.grid(axis='y')
# right tick labels https://stackoverflow.com/a/13369977
ax.yaxis.tick_right()
# hide ticks https://stackoverflow.com/a/33707647
ax.yaxis.set_ticks_position('none')
# borders https://stackoverflow.com/a/27361819
# for i in ax.spines.values(): # 'left', 'right', 'top', 'bottom'
# ax.spines[i].set_visible(False)
# https://stackoverflow.com/questions/18603959/borderless-matplotlib-plots
ax.set_frame_on(False)
dat = pickle.dumps(fig)
plt.close()
return dat
def load_figure(dump):
"""
Load Figure from dump
Returns: (Figure, Axes)
"""
# https://github.com/ipython/ipykernel/issues/231
import ipykernel.pylab.backend_inline as back_inline
import matplotlib.backends.backend_agg as back_agg
back_inline.new_figure_manager_given_figure = back_agg.new_figure_manager_given_figure
figure = pickle.loads(dump)
# https://github.com/matplotlib/matplotlib/issues/17627/
figure._cachedRenderer = None
return figure, figure.axes[0]
template_fig = init_history_plot()
btn_start = widgets.ToggleButton(description="Start thread")
plt1_parent = widgets.Output()
plt2_parent = widgets.Output()
_interface = widgets.VBox(children=[btn_start, plt1_parent, plt2_parent])
async def worker():
while btn_start.value:
with plt1_parent:
plt1_parent.clear_output(wait=True)
fig, ax = load_figure(template_fig)
dat = np.random.normal(scale=20, size=50) + 50
ax.plot(dat, color='green')
plt.show()
with plt2_parent:
plt2_parent.clear_output(wait=True)
fig, ax = load_figure(template_fig)
dat = np.random.normal(scale=20, size=50) + 50
ax.plot(dat, color='red')
plt.show()
await asyncio.sleep(1)
def start_thread(_):
if btn_start.value:
task = asyncio.create_task(worker())
btn_start.observe(start_thread, 'value')
_interface
I want to display sensor data on a PyQT GUI with a matplotlib animation.
I already have a working Plot which gets updates every time I receive new sensor value from an external source with this code:
def __init__(self):
self.fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = self.fig.add_subplot(111)
self.axes.grid()
self.xdata = []
self.ydata = []
self.entry_limit = 50
self.line, = self.axes.plot([0], [0], 'r')
def update_figure_with_new_value(self, xval: float, yval: float):
self.xdata.append(xval)
self.ydata.append(yval)
if len(self.xdata) > self.entry_limit:
self.xdata.pop(0)
self.ydata.pop(0)
self.line.set_data(self.xdata, self.ydata)
self.axes.relim()
self.axes.autoscale_view()
self.fig.canvas.draw()
self.fig.canvas.flush_events()
I want now to extend the plot to show another data series with the same x-axis. I tried to achieve this with the following additions to the init-code above:
self.axes2 = self.axes.twinx()
self.y2data = []
self.line2, = self.axes2.plot([0], [0], 'b')
and in the update_figure_with_new_value() function (for test purpose I just tried to add 1 to yval, I will extend the params of the function later):
self.y2data.append(yval+1)
if len(self.y2data) > self.entry_limit:
self.y2data.pop(0)
self.line2.set_data(self.xdata, self.ydata)
self.axes2.relim()
self.axes2.autoscale_view()
But instead of getting two lines in the plot which should have the exact same movement but just shifted by one I get vertical lines for the second plot axis (blue). The first axis (red) remains unchanged and is ok.
How can I use matplotlib to update multiple axis so that they display the right values?
I'm using python 3.4.0 with matplotlib 2.0.0.
Since there is no minimal example available, it's hard to tell the reason for this undesired behaviour. In principle ax.relim() and ax.autoscale_view() should do what you need.
So here is a complete example which works fine and updates both scales when being run with python 2.7, matplotlib 2.0 and PyQt4:
import numpy as np
import matplotlib.pyplot as plt
from PyQt4 import QtGui, QtCore
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.widget = QtGui.QWidget()
self.setCentralWidget(self.widget)
self.widget.setLayout(QtGui.QVBoxLayout())
self.widget.layout().setContentsMargins(0,0,0,0)
self.widget.layout().setSpacing(0)
self.fig = Figure(figsize=(5,4), dpi=100)
self.axes = self.fig.add_subplot(111)
self.axes.grid()
self.xdata = [0]
self.ydata = [0]
self.entry_limit = 50
self.line, = self.axes.plot([], [], 'r', lw=3)
self.axes2 = self.axes.twinx()
self.y2data = [0]
self.line2, = self.axes2.plot([], [], 'b')
self.canvas = FigureCanvas(self.fig)
self.canvas.draw()
self.nav = NavigationToolbar(self.canvas, self.widget)
self.widget.layout().addWidget(self.nav)
self.widget.layout().addWidget(self.canvas)
self.show()
self.ctimer = QtCore.QTimer()
self.ctimer.timeout.connect(self.update)
self.ctimer.start(150)
def update(self):
y = np.random.rand(1)
self.update_figure_with_new_value(self.xdata[-1]+1,y)
def update_figure_with_new_value(self, xval,yval):
self.xdata.append(xval)
self.ydata.append(yval)
if len(self.xdata) > self.entry_limit:
self.xdata.pop(0)
self.ydata.pop(0)
self.y2data.pop(0)
self.line.set_data(self.xdata, self.ydata)
self.axes.relim()
self.axes.autoscale_view()
self.y2data.append(yval+np.random.rand(1)*0.17)
self.line2.set_data(self.xdata, self.y2data)
self.axes2.relim()
self.axes2.autoscale_view()
self.fig.canvas.draw()
self.fig.canvas.flush_events()
if __name__ == "__main__":
qapp = QtGui.QApplication([])
a = Window()
exit(qapp.exec_())
You may want to test this and report back if it is working or not.
I am trying to move a dot to a particular location on the graph dynamically based on real-time data. I'm basically plotting the graph, emitting a signal from a worker thread which calls the 'move_dot' function. It works, however it is slow. I can only call one frame per second. I'm using the MPL widget in pythonxy. I am also using Windows. Is there a way to speed this up?
Here is the code:
from PyQt4 import QtGui
import ui_sof_test #Gui File
import sys
from matplotlib.ticker import AutoMinorLocator
class Gui(QtGui.QMainWindow, ui_sof_test.Ui_MainWindow):
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self) # This is defined in ui_pumptest.py file automatically
self.mpl_plot(0)
self.move_dot()
cursorplot = 0
def move_dot(self, x = 100, y = 5, color = 'r'):
fig = self.mplwidget_3.figure
par = fig.add_subplot(111)
ax3 = par.twinx()
plty = fig.gca()
plty.yaxis.set_visible(False)
ax3.plot(x, y, color, marker = 'o', linewidth = 1)
fig.canvas.draw()
#ax3.cla()
def mpl_plot(self, plot_page, replot = 0): #Data stored in lists
fig = self.mplwidget_3.figure #Add a figure
#Clears Figure if data is replotted
if replot == 1:
fig.clf()
plty = fig.gca()
plty.yaxis.set_visible(False)
par0 = fig.add_subplot(111)
#Add Axes
plt = par0.twinx()
#Plot Chart
plt.hold(False)
plt.plot([0,100,200,300,400,500], [1,3,2,4,7,5], 'b', linestyle = "dashed", linewidth = 1)
#Plot Factory Power
minorLocatorx = AutoMinorLocator()
plt.xaxis.set_minor_locator(minorLocatorx)
plt.tick_params(which='both', width= 0.5)
plt.tick_params(which='major', length=7)
plt.tick_params(which='minor', length=4, color='k')
#Plot y axis minor tick marks
minorLocatory = AutoMinorLocator()
plt.yaxis.set_minor_locator(minorLocatory)
plt.tick_params(which='both', width= 0.5)
plt.tick_params(which='major', length=7)
plt.tick_params(which='minor', length=4, color='k')
plt.minorticks_on()
#Make Border of Chart White
fig.set_facecolor('white')
#Plot Grid
plt.grid(b=True, which='both', color='k', linestyle='-')
#Manually make vertical gridlines. Above line doesn't make vertical lines for some reason
for xmaj in plt.xaxis.get_majorticklocs():
plt.axvline(x=xmaj, color = 'k',ls='-')
for xmin in plt.xaxis.get_minorticklocs():
plt.axvline(x=xmin, color = 'k', ls='-')
#Set Scales
plt.yaxis.tick_left()
# Set Axes Colors
plt.tick_params(axis='y', colors='b')
# Set Chart Labels
plt.yaxis.set_label_position("left")
plt.set_xlabel(" ")
plt.set_ylabel(" " , color = 'b')
fig.canvas.draw()
self.move_dot()
def main():
app = QtGui.QApplication(sys.argv) # A new instance of QApplication
form = Gui() # We set the form to be our ExampleApp (design)
form.show() # Show the form
app.exec_() # and execute the. app
if __name__ == '__main__': # if we're running file directly and not importing it
main() # run the main function
def plot(self, fig):
ax = fig.gca()
This plot function is called, when dropping an item on a Qt MatPlotLib Widget. Finally everything will be updated by .draw(). The problem, which occurred is the following:
Calling an external function, that accomplishes plotting, ax has to be the current axis (fig/axis are not passed as argument(s). Therefore I had to add
pyplot.sca(ax)
Everything was fine. Just somehow, maybe becaus of updating to python(x,y) 2.7.5.1 (mpl is 1.3.1), I get this error Axes instance argument was not found in a figure. It's just in this case, when I want this external function (scipy dendrogram func) to draw on the predefined axis. I tried to follow it
[Dbg]>>> fig
<matplotlib.figure.Figure object at 0x0A119A90>
[Dbg]>>> fig.gca()
<matplotlib.axes.AxesSubplot object at 0x0A119CD0>
then stepping into the subroutine pyplot.sca(ax)
managers = _pylab_helpers.Gcf.get_all_fig_managers()
for m in managers:
if ax in m.canvas.figure.axes:
_pylab_helpers.Gcf.set_active(m)
m.canvas.figure.sca(ax)
return
raise ValueError("Axes instance argument was not found in a figure.")
The list seems to be empty
[Dbg]>>> managers
[]
Maybe some of you has an idea, what could be the problem, though remote diagnosis might be difficult. An alternate way of making dendrogram plot on the fig/axes I want it to, would be helpful, too.
Please also give a hint on what should be used to update a plot as to MatplotlibWidget, figure and axes have a draw method.
Edit: Tried to create a MWE. Isn't there anybody experiencing the same error or who can tell me what's the problem here?
import sys
from matplotlibwidget import MatplotlibWidget
from matplotlib import pyplot
from PyQt4.QtGui import QMainWindow, QApplication
import scipy.cluster.hierarchy as hac
import numpy as np
class ApplicationWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.mplwidget = MatplotlibWidget(self, title='Example',
xlabel='Observation', ylabel='Distance', hold=True)
self.mplwidget.setFocus()
self.setCentralWidget(self.mplwidget)
def plotScree(self, Z, fig):
ax = fig.gca()
ax.plot(range(len(Z)), Z[::-1,2])
def plot(self, Z, fig):
ax = fig.gca()
pyplot.sca(ax)
hac.dendrogram(Z)
app = QApplication(sys.argv)
win = ApplicationWindow()
X = np.random.random(100).reshape(25, 4)
Z = hac.linkage(X)
#win.plotScree(Z, win.mplwidget.figure)
win.plot(Z, win.mplwidget.figure)
win.show()
sys.exit(app.exec_())
The implementation of matplotlibwidget in Python(x,y) appears to be broken.
I believe the file in question is this one. If you change line 67 of that file to read self.figure = pypolt.figure(figsize=(width, height), dpi=dpi) then your code will work as you want. I've included a full copy of the modified code below so you can just copy/paste that into your project and use that matplotlibwidget instead of importing the one from python(x,y)
The problem appears to be that instantiating the Figure object directly, skips over a whole load of figure manager construction, which is why that error was being raised. I suggest you file a bug report with Python(x,y) and link to this post!
Full code with modified line (see repository link above for license)
from PyQt4.QtGui import QSizePolicy
from PyQt4.QtCore import QSize
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure
from matplotlib import rcParams
rcParams['font.size'] = 9
from matplotlib import pyplot
class MatplotlibWidget(Canvas):
"""
MatplotlibWidget inherits PyQt4.QtGui.QWidget
and matplotlib.backend_bases.FigureCanvasBase
Options: option_name (default_value)
-------
parent (None): parent widget
title (''): figure title
xlabel (''): X-axis label
ylabel (''): Y-axis label
xlim (None): X-axis limits ([min, max])
ylim (None): Y-axis limits ([min, max])
xscale ('linear'): X-axis scale
yscale ('linear'): Y-axis scale
width (4): width in inches
height (3): height in inches
dpi (100): resolution in dpi
hold (False): if False, figure will be cleared each time plot is called
Widget attributes:
-----------------
figure: instance of matplotlib.figure.Figure
axes: figure axes
Example:
-------
self.widget = MatplotlibWidget(self, yscale='log', hold=True)
from numpy import linspace
x = linspace(-10, 10)
self.widget.axes.plot(x, x**2)
self.wdiget.axes.plot(x, x**3)
"""
def __init__(self, parent=None, title='', xlabel='', ylabel='',
xlim=None, ylim=None, xscale='linear', yscale='linear',
width=4, height=3, dpi=100, hold=False):
self.figure = pyplot.figure(figsize=(width, height), dpi=dpi)
self.axes = self.figure.add_subplot(111)
self.axes.set_title(title)
self.axes.set_xlabel(xlabel)
self.axes.set_ylabel(ylabel)
if xscale is not None:
self.axes.set_xscale(xscale)
if yscale is not None:
self.axes.set_yscale(yscale)
if xlim is not None:
self.axes.set_xlim(*xlim)
if ylim is not None:
self.axes.set_ylim(*ylim)
self.axes.hold(hold)
Canvas.__init__(self, self.figure)
self.setParent(parent)
Canvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
Canvas.updateGeometry(self)
def sizeHint(self):
w, h = self.get_width_height()
return QSize(w, h)
def minimumSizeHint(self):
return QSize(10, 10)