Mike C.
Mike C.

Reputation: 1921

Plotting datapoints and line at the same time with Matplotlib Widget

I'm trying to plot both a line and data points on the same axis in Matplotlib. When I try to plot the line first, the data points get cleared and the same is true when I try to plot the data points first. Here is the minimal code:

from PyQt4 import QtGui
import sys
import ui_sof_test  #Gui File
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)
        self.call_test()
    def call_test(self):
        x = [1,2,3,4,5,6,7,8,9,10]
        y = [1000,2000,3000,4000,5000,6000,7000,8000,9000,10000]
        self.plot_test(x,y)
    def plot_test(self, x, y):        
        ax1 = self.mplwidget.axes
        fig = self.mplwidget.figure #Add a figure 
        ax1.plot(x, y, 'k', linestyle = "solid", linewidth = 1)
        ax1.plot(x, y, "ro")        
        #Log scale
        ax1.set_xscale('log')
        ax1.set_yscale('log')
        #format tick labels
        ax1.axis([1, 20, 100, 100000])
        #set Limits        

        #Gridlines
        #Plot y axis minor tick marks

        minorLocatory = AutoMinorLocator()
        ax1.yaxis.set_minor_locator(minorLocatory)
        ax1.tick_params(which='both', width= 0.5)
        ax1.tick_params(which='major', length=7)
        ax1.tick_params(which='minor', length=4, color='k')
        ax1.minorticks_on()
        #Make Border of Chart White
        fig.set_facecolor('white')
        #Plot Grid        
        ax1.grid(b=True, which='both', color='k', linestyle='-')    

        #Draw Chart
        fig.canvas.update()
        fig.canvas.draw()    

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
 ` 

Here is python code created from the PYQT4 UI file. Just save it as ui_sof_test.py:

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(1441, 705)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.tabWidget = QtGui.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 1111, 671))
        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
        self.tab = QtGui.QWidget()
        self.tab.setObjectName(_fromUtf8("tab"))
        self.mplwidget = MatplotlibWidget(self.tab)
        self.mplwidget.setGeometry(QtCore.QRect(10, 20, 761, 461))
        self.mplwidget.setObjectName(_fromUtf8("mplwidget"))
        self.tabWidget.addTab(self.tab, _fromUtf8(""))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1441, 21))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "Motor Tester", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Test", None))

from matplotlibwidget import MatplotlibWidget

Upvotes: 0

Views: 418

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339120

For some reason the first plot gets removed from the axes upon plotting the second one.
A workaround would be to add the first plot manually after plotting the second.

line, = ax1.plot(x, y, 'k', linestyle = "solid", linewidth = 1)
line2, = ax1.plot(x, y, marker="o", color="red", ls="")  
ax1.add_artist(line)

Because in principle the plotting procedure works fine (as shown below), the reason needs to be the use of MatplotlibWidget, for which I'm uncertain about what it actually does.

But if we replace it by

fig = Figure()
ax = fig.add_subplot(111)
self.mplwidget = FigureCanvas(fig)
self.tabWidget.addTab(self.mplwidget, _fromUtf8(""))

where we have imported

from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

and later use

ax1 = self.mplwidget.figure.axes[0]

the plot is shown as expected. So you may just cease to use MatplotlibWidget, if it's causing such strange problems.


Minimal example that shows that the principle plotting works as expected:

import matplotlib.pyplot as plt
from  matplotlib.ticker import AutoMinorLocator
import numpy as np

class C():
    def __init__(self):
        self.mplwidget = self
        self.figure = plt.figure()
        self.axes = self.figure.add_subplot(111)

    def plot_test(self, x, y):
        ax1 = self.mplwidget.axes
        fig = self.mplwidget.figure #Add a figure 
        ax1.plot(x, y, 'k', linestyle = "solid", linewidth = 1)
        ax1.plot(x, y, "ro")        
        #Log scale
        ax1.set_xscale('log')
        ax1.set_yscale('log')
        #format tick labels
        ax1.axis([1, 20, 100, 100000])
        #set Limits        

        #Gridlines
        #Plot y axis minor tick marks
        minorLocatory = AutoMinorLocator()
        ax1.yaxis.set_minor_locator(minorLocatory)
        ax1.tick_params(which='both', width= 0.5)
        ax1.tick_params(which='major', length=7)
        ax1.tick_params(which='minor', length=4, color='k')
        ax1.minorticks_on()
        #Make Border of Chart White
        fig.set_facecolor('white')
        #Plot Grid        
        ax1.grid(b=True, which='both', color='k', linestyle='-')         
        #Draw Chart
        fig.canvas.update()
        fig.canvas.draw()

x, y = np.linspace(1,20), np.logspace(2, 5)

c = C()
c.plot_test(x,y)
plt.show()   

enter image description here

Upvotes: 2

Related Questions