Move dot faster with Matplotlib - python

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

Related

Hiding lines after plotting in matplotlib

I am trying to implement the solution presented by #Joe Kington in the following stack overflow thread:
Hiding lines after showing a pyplot figure
I have 16 lines I am trying to plot with this method, each of which have their own unique color and label. While #Joe Kington's solution works fine to get the plot to display, I cannot transfer his interactive method to my code with the interactive functionality of clicking on the legend entries to hide a line. That is, my code plots my data without error but there is no interactive functionality occurring.
I have tried:
setting the unique labels to be raw strings and regular strings
setting up every line to plot to be iterated over as in #Joe Kington's solution
using smaller legend labels
rearranging blocks of my code in the event that the functions defined in #Joe Kington's solution are out of scope
#Joe Kington's solution is below, which works fine:
import numpy as np
import matplotlib.pyplot as plt
def main():
x = np.arange(10)
fig, ax = plt.subplots()
for i in range(1, 31):
ax.plot(x, i * x, label=r'$y={}x$'.format(i))
ax.legend(loc='upper left', bbox_to_anchor=(1.05, 1),
ncol=2, borderaxespad=0)
fig.subplots_adjust(right=0.55)
fig.suptitle('Right-click to hide all\nMiddle-click to show all',
va='top', size='large')
leg = interactive_legend()
return fig, ax, leg
def interactive_legend(ax=None):
if ax is None:
ax = plt.gca()
if ax.legend_ is None:
ax.legend()
return InteractiveLegend(ax.get_legend())
class InteractiveLegend(object):
def __init__(self, legend):
self.legend = legend
self.fig = legend.axes.figure
self.lookup_artist, self.lookup_handle = self._build_lookups(legend)
self._setup_connections()
self.update()
def _setup_connections(self):
for artist in self.legend.texts + self.legend.legendHandles:
artist.set_picker(10) # 10 points tolerance
self.fig.canvas.mpl_connect('pick_event', self.on_pick)
self.fig.canvas.mpl_connect('button_press_event', self.on_click)
def _build_lookups(self, legend):
labels = [t.get_text() for t in legend.texts]
handles = legend.legendHandles
label2handle = dict(zip(labels, handles))
handle2text = dict(zip(handles, legend.texts))
lookup_artist = {}
lookup_handle = {}
for artist in legend.axes.get_children():
if artist.get_label() in labels:
handle = label2handle[artist.get_label()]
lookup_handle[artist] = handle
lookup_artist[handle] = artist
lookup_artist[handle2text[handle]] = artist
lookup_handle.update(zip(handles, handles))
lookup_handle.update(zip(legend.texts, handles))
return lookup_artist, lookup_handle
def on_pick(self, event):
handle = event.artist
if handle in self.lookup_artist:
artist = self.lookup_artist[handle]
artist.set_visible(not artist.get_visible())
self.update()
def on_click(self, event):
if event.button == 3:
visible = False
elif event.button == 2:
visible = True
else:
return
for artist in self.lookup_artist.values():
artist.set_visible(visible)
self.update()
def update(self):
for artist in self.lookup_artist.values():
handle = self.lookup_handle[artist]
if artist.get_visible():
handle.set_visible(True)
else:
handle.set_visible(False)
self.fig.canvas.draw()
def show(self):
plt.show()
if __name__ == '__main__':
fig, ax, leg = main()
plt.show()
Here is a snippet of my code that isn't working that is defined in a module plotting in a function called main() (I have other modifications I need to make such as changing axis labels, unique colors, etc.):
import numpy as np
import matplotlib.pyplot as plt
def main(t,n,timeSpan):
colors = ['blue','red','green','black','magenta','teal','orange','chartreuse','purple','sienna','goldenrod','lightgray','olive','cyan','maroon','pink']
labels = [r'foo1',r'bar2',r'foo3',r'bar4',r'foo5',r'bar6',r'foo7',r'bar8',r'foo9',r'bar10',r'foo11',r'bar12',r'foo13',r'bar14',r'foo15',r'bar16']
fig, ax = plt.subplots(figsize=(15,8))
for i in range(0, len(colors)):
ax.plot(t, n[:,i], color = colors[i], label = labels[i])
ax.set_xlabel('x label')
ax.set_ylabel('y label')
ax.set_xlim([0,timeSpan])
ax.set_ylim([0,110])
ax.legend(loc='upper left', bbox_to_anchor=(1.05, 1),
ncol=2, borderaxespad=0)
fig.subplots_adjust(right=0.55)
fig.suptitle('Title\n(Right-click to hide all\nMiddle-click to show all)',
va='top', size='large')
leg = interactive_legend()
plt.show()
def interactive_legend(ax=None):
if ax is None:
ax = plt.gca()
if ax.legend_ is None:
ax.legend()
return InteractiveLegend(ax.get_legend())
class InteractiveLegend(object):
def __init__(self, legend):
self.legend = legend
self.fig = legend.axes.figure
self.lookup_artist, self.lookup_handle = self._build_lookups(legend)
self._setup_connections()
self.update()
def _setup_connections(self):
for artist in self.legend.texts + self.legend.legendHandles:
artist.set_picker(10) # 10 points tolerance
self.fig.canvas.mpl_connect('pick_event', self.on_pick)
self.fig.canvas.mpl_connect('button_press_event', self.on_click)
def _build_lookups(self, legend):
labels = [t.get_text() for t in legend.texts]
handles = legend.legendHandles
label2handle = dict(zip(labels, handles))
handle2text = dict(zip(handles, legend.texts))
lookup_artist = {}
lookup_handle = {}
for artist in legend.axes.get_children():
if artist.get_label() in labels:
handle = label2handle[artist.get_label()]
lookup_handle[artist] = handle
lookup_artist[handle] = artist
lookup_artist[handle2text[handle]] = artist
lookup_handle.update(zip(handles, handles))
lookup_handle.update(zip(legend.texts, handles))
return lookup_artist, lookup_handle
def on_pick(self, event):
handle = event.artist
if handle in self.lookup_artist:
artist = self.lookup_artist[handle]
artist.set_visible(not artist.get_visible())
self.update()
def on_click(self, event):
if event.button == 3:
visible = False
elif event.button == 2:
visible = True
else:
return
for artist in self.lookup_artist.values():
artist.set_visible(visible)
self.update()
def update(self):
for artist in self.lookup_artist.values():
handle = self.lookup_handle[artist]
if artist.get_visible():
handle.set_visible(True)
else:
handle.set_visible(False)
self.fig.canvas.draw()
def show(self):
plt.show()
t = np.arange(1000)
n = np.zeros([1000,16])
for i in range(0, 1000):
for j in range(0, 16):
n[i][j] = t[i] * j
timeSpan = 1000
# if __name__ == "__main__":
# main(t,n,timeSpan)
colors = ['blue','red','green','black','magenta','teal','orange','chartreuse','purple','sienna','goldenrod','lightgray','olive','cyan','maroon','pink']
labels = [r'foo1',r'bar2',r'foo3',r'bar4',r'foo5',r'bar6',r'foo7',r'bar8',r'foo9',r'bar10',r'foo11',r'bar12',r'foo13',r'bar14',r'foo15',r'bar16']
fig, ax = plt.subplots(figsize=(15,8))
for i in range(0, len(colors)):
ax.plot(t, n[:,i], color = colors[i], label = labels[i])
ax.set_xlabel('x label')
ax.set_ylabel('y label')
ax.set_xlim([0,timeSpan])
ax.set_ylim([0,110])
ax.legend(loc='upper left', bbox_to_anchor=(1.05, 1),
ncol=2, borderaxespad=0)
fig.subplots_adjust(right=0.55)
fig.suptitle('Title\n(Right-click to hide all\nMiddle-click to show all)',
va='top', size='large')
leg = interactive_legend()
plt.show()
I have determined that when I leave the code as is it works, but when I comment out lines 113-131 and call main() from lines 111 and 112 insead, it no longer works. Is this a scope issue? Not sure why the way I am calling the interactive_legend() function determines whether it works or not.

Can mouse be used as paintbrush with matplotlib?

I'd like an onclick event to overlay the coordinate the user clicks in a figure with a certain colour.
Note:
I do not want to actually edit the picture. This is only on the displayed figure, as an indicative measure of where the user has clicked.
You can adpat the LineBuilder example on the matplotlib event handling tutorial page:
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.xs = list(line.get_xdata())
self.ys = list(line.get_ydata())
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
def __call__(self, event):
print('click', event)
if event.inaxes!=self.line.axes: return
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click to add points')
line, = ax.plot([], [], linestyle="none", marker="o", color="r")
linebuilder = LineBuilder(line)
plt.show()

Legend transparent to horizontal grid in matplotlib

I'm working with the following class:
import numpy as np
import matplotlib
matplotlib.use('Qt4Agg')
import matplotlib.pyplot as plt
import matplotlib.ticker as plticker
class matplotLIV():
def __init__(self, BaseFilename, temperatures, length=None, width=None, area=None, title = '', ylim=None):
self.BaseFilename = BaseFilename
self.temperatures = temperatures
if length and width:
self.length = length
self.width = width
self.area = length*width*1e-5
else:
self.area = area
self.title = title
self.ylim = ylim
filenames = [("%s_%sK.txt" % (self.BaseFilename, str(temp)), temp) for temp in self.temperatures]
self.rawData = [(np.loadtxt(fname), temp) for fname, temp in filenames]
self.colors = colors = ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#e6ab02', '#a6761d', '#666666']
self.maxValueRow = (0,0,0)
def plot(self):
self.fig = plt.figure()
self.ax1 = self.fig.add_subplot(111)
ax1 = self.ax1
ax1.tick_params(bottom='off')
ax1.xaxis.tick_top()
self.ax2 = ax1.twinx()
ax2 = self.ax2
self.ax3 = ax2.twiny()
ax3 = self.ax3
ax3.xaxis.tick_bottom()
ax1.set_xlabel("current / A")
ax1.xaxis.set_label_position('top')
ax1.set_ylabel("voltage / V")
ax2.set_ylabel("light intensity / arb. u.")
ax3.set_xlabel(r'current density / $\mathregular{Acm^{-2}}$')
ax3.xaxis.set_label_position('bottom')
for i, (datafile, label) in enumerate(self.rawData):
self.checkMaxValues(datafile)
ax1.plot( datafile[:,0], datafile[:,1], color=self.colors[i], label='%sK' % str(label))
ax2.plot( datafile[:,0], datafile[:,2], color=self.colors[i], label='%sK' % str(label), linewidth=2)
ax1.margins(x=0)
ax1.grid(True, axis='y')
ax3.grid(True)
start, end = ax1.get_xlim()
self.setAxesScale(ax1, ax2)
if self.ylim:
ax2.set_ylim(top=self.ylim)
ax3.set_xlim(start/self.area, end/self.area)
leg = ax2.legend(loc='upper left')
self.fig.suptitle(self.title, y=0.98, weight='bold')
self.fig.subplots_adjust(top=0.86)
loc = plticker.MultipleLocator(base=20.0) # this locator puts ticks at regular intervals
ax3.xaxis.set_major_locator(loc)
def checkMaxValues(self, data):
maxInd = data.argmax(axis=0)[2]
if data[maxInd][2] > self.maxValueRow[2]:
self.maxValueRow = data[maxInd]
def setAxesScale(self, ax1, ax2):
yrange = ax1.get_ylim()
y1Fraction = self.maxValueRow[1]/yrange[1]
y2Fraction = y1Fraction - 0.02
ax2.set_ylim(top=self.maxValueRow[2]/y2Fraction)
def show(self):
plt.savefig(self.BaseFilename + '.pdf')
plt.show()
which you can run with this sample code:
import matplotLIV as mpliv
######## configuration
BaseFilename = "testdata"
temperatures = (5,)
area = 1e-8
######## end of configuration
liv = mpliv.matplotLIV(BaseFilename, temperatures, area=area)
liv.plot()
liv.show()
on this file: http://pastebin.com/GMAC3mUu
The problem that I'm experiencing is that the legend is transparent to the grid. Oddly enough, it is only the vertical grid that you can see through the legend box:
Is this a bug? If not, how do I set the legend so it is NOT transparent?
The problem is the vertical grid is on ax3, and the legend is on ax2, so the grid is plotted after the legend.
One way around this is pasted below (just the section you need to modify). You need to plot the legend on ax3, and explicitly tell it which lines and labels you want.
# make a list for the lines that you are plotting
l1 = []
l2 = []
for i, (datafile, label) in enumerate(self.rawData):
self.checkMaxValues(datafile)
# Give your lines some names (l1,l2)
l1+=ax1.plot( datafile[:,0], datafile[:,1], color=self.colors[i], label='%sK' % str(label))
l2+=ax2.plot( datafile[:,0], datafile[:,2], color=self.colors[i], label='%sK' % str(label), linewidth=2)
# Define which lines to put in the legend. If you want l1 too, then use lns = l1+l2
lns = l2
labs = [l.get_label() for l in lns]
ax1.margins(x=0)
ax1.grid(True, axis='y')
ax3.grid(True)
start, end = ax1.get_xlim()
self.setAxesScale(ax1, ax2)
if self.ylim:
ax2.set_ylim(top=self.ylim)
ax3.set_xlim(start/self.area, end/self.area)
# Set the legend on ax3, not ax2
leg = ax3.legend(lns,labs,loc='upper left')

Connect Qslider and MatplotlibWidget

I am a real beginner in python and try to connect a qslider to a matplotlibwidget.
That means if I change the value of the slider the graph should change. It seems that the value changes correctly, while the graph stays the same. Can anyone tell me how to connect the change of the slider with the graph? Here is my algorithm so far:
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 04 16:48:12 2014
#author: Christoph
"""
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure
from matplotlib import rcParams
import numpy as np
import scipy.constants as const
import sys
rcParams['font.size'] = 9
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 = 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, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
Canvas.updateGeometry(self)
def sizeHint(self):
w, h = self.get_width_height()
return QtGui.QSize(w, h)
def minimumSizeHint(self):
return QtGui.QSize(10, 10)
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Graphics Window
self.mpl = MatplotlibWidget(self, title='Graph',
xlabel='x',
ylabel='y',
hold=True)
self.mpl.setGeometry(0,0,1300,800)
self.setGeometry(0, 30, 1680, 800)
# Slider Resistance
title1=QtGui.QLabel(self)
title1.setText('R')
title1.move(1400,10)
self.value1=QtGui.QLabel(self)
self.value1.setText('1')
self.value1.move(1550,40)
cb=QtGui.QSlider(QtCore.Qt.Horizontal, self)
cb.setGeometry(1400,40,100,30)
cb.setMinimum(1)
cb.setMaximum(10000)
cb.valueChanged.connect(self.Rout)
self.plot(1, self.mpl.axes)
def Rout(self, position):
self.value1.setText('%i' %position)
self.plot(position, self.mpl.axes)
def plot(self, R, axes):
x=np.linspace(0,5,1001)
B=0.035
n1=0.115
H=2.06227451e-15
n2=1.37040209e-01
gamma=0.001*const.e
C=0.13
x=np.array(x)
diodetheo = H*(np.exp((const.e*x*n2)/(const.k*300))-1)
zaehler = 1+np.exp((B-C+n1*x)*const.e/(const.k*300))
nenner = 1+np.exp((B-C-n1*x)*const.e/(const.k*300))
A=8.7476434*10**(29)*gamma
D=gamma/2
klammer2 = (const.pi/2)+np.arctan((C-n1*x)/D)
y1 = A*np.log(zaehler/nenner)*klammer2
# plt.figure()
# plt.plot(x, diodetheo, 'g')
# plt.show()
indup=[]
inddown=[]
iup=[]
idown=[]
theo = (y1+diodetheo)*(10**(-12))*(100)/4
for i, Volt in enumerate(x):
xup=np.linspace(0,Volt,i+1)
last=Volt/R-xup/R
diff=np.array(last)-np.array(theo[0:i+1])
inter=np.where(np.diff(np.sign(diff)))[0]
if inter.size==0:
inter=np.array([0])
indup.append(inter[0])
inddown.append(inter[-1])
iup.append(theo[inter[0]])
idown.append(theo[inter[-1]])
up = np.array(iup)
down = np.array(idown)
down=np.flipud(down)
ytotal=np.concatenate((up, down))
xneg=np.flipud(x)
xtotal=np.concatenate((x,xneg))
#plt.figure()
#plt.plot(xtotal, ytotal, 'g')
#plt.show()
axes.plot(xtotal, ytotal, 'r')
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = ApplicationWindow()
win.show()
sys.exit(app.exec_())
Greetings
Christoph
OK I've made some changes to your code in order to make it works:
Change the function definition def plot(self, R, axes): for def plot(self, R):
Change the call self.plot(position, self.mpl.axes) on Rout accordingly to self.plot(position)
Change the final line axes.plot(xtotal, ytotal, 'r') on the previous plot function by:
self.mpl.axes.clear() #clear the previous plot
self.mpl.axes.plot(xtotal, ytotal, 'r') #replot
self.mpl.figure.canvas.draw() #redraw the canvas
Explanations:
First, you don't need to pass the axes to the plot function if it's already an attribute of self.mpl and is easy accessible. Second, when you make another plot you need to clear the previous one and also refresh the canvas.
Next all the code with modifications for easy use of copy-paste:
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as Canvas
from matplotlib.figure import Figure
from matplotlib import rcParams
import numpy as np
import scipy.constants as const
import sys
rcParams['font.size'] = 9
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 = 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, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
Canvas.updateGeometry(self)
def sizeHint(self):
w, h = self.get_width_height()
return QtGui.QSize(w, h)
def minimumSizeHint(self):
return QtGui.QSize(10, 10)
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
# Graphics Window
self.mpl = MatplotlibWidget(self, title='Graph',
xlabel='x',
ylabel='y',
hold=True)
self.mpl.setGeometry(0,0,1300,800)
self.setGeometry(0, 30, 1680, 800)
# Slider Resistance
title1=QtGui.QLabel(self)
title1.setText('R')
title1.move(1400,10)
self.value1=QtGui.QLabel(self)
self.value1.setText('1')
self.value1.move(1550,40)
cb=QtGui.QSlider(QtCore.Qt.Horizontal, self)
cb.setGeometry(1400,40,100,30)
cb.setMinimum(1)
cb.setMaximum(10000)
cb.valueChanged.connect(self.Rout)
self.plot(1)
def Rout(self, position):
self.value1.setText('%i' %position)
self.plot(position)
def plot(self, R):
x=np.linspace(0,5,1001)
B=0.035
n1=0.115
H=2.06227451e-15
n2=1.37040209e-01
gamma=0.001*const.e
C=0.13
x=np.array(x)
diodetheo = H*(np.exp((const.e*x*n2)/(const.k*300))-1)
zaehler = 1+np.exp((B-C+n1*x)*const.e/(const.k*300))
nenner = 1+np.exp((B-C-n1*x)*const.e/(const.k*300))
A=8.7476434*10**(29)*gamma
D=gamma/2
klammer2 = (const.pi/2)+np.arctan((C-n1*x)/D)
y1 = A*np.log(zaehler/nenner)*klammer2
# plt.figure()
# plt.plot(x, diodetheo, 'g')
# plt.show()
indup=[]
inddown=[]
iup=[]
idown=[]
theo = (y1+diodetheo)*(10**(-12))*(100)/4
for i, Volt in enumerate(x):
xup=np.linspace(0,Volt,i+1)
last=Volt/R-xup/R
diff=np.array(last)-np.array(theo[0:i+1])
inter=np.where(np.diff(np.sign(diff)))[0]
if inter.size==0:
inter=np.array([0])
indup.append(inter[0])
inddown.append(inter[-1])
iup.append(theo[inter[0]])
idown.append(theo[inter[-1]])
up = np.array(iup)
down = np.array(idown)
down=np.flipud(down)
ytotal=np.concatenate((up, down))
xneg=np.flipud(x)
xtotal=np.concatenate((x,xneg))
#plt.figure()
#plt.plot(xtotal, ytotal, 'g')
#plt.show()
self.mpl.axes.clear()
self.mpl.axes.plot(xtotal, ytotal, 'r')
self.mpl.figure.canvas.draw()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
win = ApplicationWindow()
win.show()
sys.exit(app.exec_())

matplotlib mouseclick event in pie chart

Is there a way in matplotlib and Python to return the value/label clicked in a pie chart. For example if user clicks on sliver A of pie chart, return value A. If user clicks on sliver B of B pie chart, return value B.
from matplotlib import pyplot as plt
# make a square figure and axes
plt.figure(figsize=(6,6))
ax = plt.axes([0.1, 0.1, 0.8, 0.8])
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15,30,45, 10]
explode=(0, 0.05, 0, 0)
p = plt.pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
plt.title('Raining Hogs and Dogs', bbox={'facecolor':'0.8', 'pad':5})
w = p[0][0]
plt.show()
class PieEventHandler:
def __init__(self,p):
self.p = p
self.fig = p[0].figure
self.ax = p[0].axes
self.fig.canvas.mpl_connect('button_press_event', self.onpress)
def onpress(self, event):
if event.inaxes!=self.ax:
return
for w in self.p:
(hit,_) = w.contains(event)
if hit:
print w.get_label()
handler = PieEventHandler(p[0])
references:
Color values in imshow for matplotlib?
http://matplotlib.org/examples/pylab_examples/pie_demo.html
:)
import matplotlib.pyplot as plt
def main():
# Make an example pie plot
fig = plt.figure()
ax = fig.add_subplot(111)
labels = ['Apple', 'Mango', 'Orange']
wedges, plt_labels = ax.pie([20, 40, 60], labels=labels)
ax.axis('equal')
make_picker(fig, wedges)
plt.show()
def make_picker(fig, wedges):
def onclick(event):
wedge = event.artist
label = wedge.get_label()
print label
# Make wedges selectable
for wedge in wedges:
wedge.set_picker(True)
fig.canvas.mpl_connect('pick_event', onclick)
if __name__ == '__main__':
main()

Categories

Resources