Search code examples
pythonmatplotlibpyqtsuppress-warningsmplot3d

How to Suppress/Ignore(/Fix) matplotlib Axes3D ValueError?


As requested, here's the minimum, working example (below); my apologies that it's so much, but this seems to be an issue that requires overhead structure (specifically the presence of the 2d and 3d axes on two separate tabs at once, but not when 3d or 2d is alone):

import sys, os
pyDir = os.path.dirname(os.path.abspath(__file__)) #python file location

from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'
import sip
sip.setapi('QString', 2)
import matplotlib
matplotlib.use('Agg')
#matplotlib.use('Qt4Agg')
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from matplotlib.widgets import Slider, Button
import mpl_toolkits.axes_grid1
import matplotlib.path as pltPath
import matplotlib.image as mpimg
from matplotlib.ticker import MaxNLocator
from matplotlib import rc
from mpl_toolkits.mplot3d import Axes3D


class P4(QtGui.QWidget):

    def __init__(self, parent=None):
        super(P4, self).__init__(parent)
        P4.layout = QtGui.QGridLayout(self)
        P4.layout.setContentsMargins(20,20,20,20)
        P4.layout.setSpacing(10)

        P4.button_pic1 = QtGui.QPushButton('View Plots', self)
        P4.button_pic1.clicked.connect(self.RC_vid1)
        P4.layout.addWidget(P4.button_pic1, 2, 8, 1, 1)
        P4.button_pic1.show()

    def RC_vid1(self):

        global PrD_window
        try:
            PrD_window.close()
        except:
            pass

        PrD_window = PrD_Viz()
        PrD_window.show()

################################################################################

class PrD_Viz(QtGui.QMainWindow):
    def __init__(self):
        super(PrD_Viz, self).__init__()
        self.left = 10
        self.top = 10
        self.initUI()

    def initUI(self):
        vid_tab2 = ManifoldCanvas(self)
        vid_tab3 = PsiCanvas(self)
        global vid_tabs
        vid_tabs = QtGui.QTabWidget(self)
        vid_tabs.addTab(vid_tab2, 'Plot 1')
        vid_tabs.addTab(vid_tab3, 'Plot 2')

        style = """QTabWidget::tab-bar{
                alignment: center;
                }"""
        self.setStyleSheet(style)
        self.setCentralWidget(vid_tabs)
        self.setWindowModality(QtCore.Qt.ApplicationModal) #freezes out parent window
        self.show()

class ManifoldCanvas(QtGui.QDialog):
    pts_orig = []

    def __init__(self, parent=None):
        super(ManifoldCanvas, self).__init__(parent)

        self.figure = Figure(dpi=200)
        self.ax = self.figure.add_subplot(111)
        self.figure.set_tight_layout(True)
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)

        x=[1,5,9]
        y=[2,6,10]

        ManifoldCanvas.pts_orig = zip(x,y)
        for i in ManifoldCanvas.pts_orig:
            x,y = i
            self.ax.scatter(x,y,s=1,c='#1f77b4')

        self.canvas.draw_idle()

        layout = QtGui.QGridLayout()
        layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize)
        layout.addWidget(self.toolbar, 0,0,1,5)
        layout.addWidget(self.canvas, 1,0,1,5)

        self.setLayout(layout)

class PsiCanvas(QtGui.QDialog):

    def __init__(self, parent=None):
        super(PsiCanvas, self).__init__(parent)

        self.psi1 = [10,11,12]
        self.psi2 = [24,19,18]
        self.psi3 = [99,90, 105]

        # create canvas and plot data:
        self.figure = Figure(dpi=200)
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.ax = Axes3D(self.figure)
        self.ax.mouse_init()

        self.ax.scatter(self.psi1, self.psi2, self.psi3, label='psi_dif', linewidths= .5, edgecolors='k', c='#d62728') #C3

        self.canvas.draw_idle() #refresh canvas

        layout = QtGui.QGridLayout()
        layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize)
        layout.addWidget(self.toolbar, 0,0,1,4)
        layout.addWidget(self.canvas, 1,0,4,4)

        self.setLayout(layout)

################################################################################
# overhead GUI control: 

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        tab4 = P4(self)

        global tabs
        tabs = QtGui.QTabWidget(self)
        tabs.resize(250,150)

        tabs.addTab(tab4, 'Eigenfunctions')

        self.setCentralWidget(tabs)
        self.show()


if __name__ == '__main__':

    app = QtGui.QApplication.instance()
    if app is None:
        app = QtGui.QApplication([])

    w = MainWindow()
    sys.exit(app.exec_())

The plot behaves perfectly on linux and macOS (with no warnings on macOS), but on linux, I'm getting this dreadful paragraph of errors each time the plot is shown in the GUI (which ends up polluting the terminal):

/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axis3d.py:270: RuntimeWarning: invalid value encountered in true_divide
  ax_scale = self.axes.bbox.size / self.figure.bbox.size
Traceback (most recent call last):
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 176, in __draw_idle_agg
    FigureCanvasAgg.draw(self)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/matplotlib/backends/backend_agg.py", line 474, in draw
    self.figure.draw(self.renderer)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/matplotlib/artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/matplotlib/figure.py", line 1159, in draw
    func(*args)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 290, in draw
    ax.draw(renderer)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/mpl_toolkits/mplot3d/axis3d.py", line 288, in draw
    self.label.draw(renderer)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/matplotlib/artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/data/ees/anaconda/envs/manifold/lib/python2.7/site-packages/matplotlib/text.py", line 757, in draw
    raise ValueError("posx and posy should be finite values")
ValueError: posx and posy should be finite values

I'd like to either suppress this error or fix it; any advice would be tremendously appreciated.


Solution

  • UPDATE: The solution here is to simply remove the toolbars - apparently there is some background competition going on between 2d and 3d toolbars being active at the same time (but not for 2d and 2d toolbars)... weird. I'm leaving my other response present below this one, in case anyone runs into something similar where such a workaround might be helpful.


    Here's the workaround for this issue below; please see the comments NEW for everything that was needed for the fix. Basically, this error was happening when both matplotlib's 2d and 3d axes were needed at the same time (albeit on two separate tabs). Now, each plot is constructed live upon tab click.

    import sys, os
    pyDir = os.path.dirname(os.path.abspath(__file__)) #python file location
    
    from pyface.qt import QtGui, QtCore
    os.environ['ETS_TOOLKIT'] = 'qt4'
    import sip
    sip.setapi('QString', 2)
    import matplotlib
    matplotlib.use('Agg')
    #matplotlib.use('Qt4Agg')
    from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
    from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
    from matplotlib.figure import Figure
    from matplotlib.widgets import Slider, Button
    import mpl_toolkits.axes_grid1
    import matplotlib.path as pltPath
    import matplotlib.image as mpimg
    from matplotlib.ticker import MaxNLocator
    from matplotlib import rc
    from mpl_toolkits.mplot3d import Axes3D
    
    
    class P4(QtGui.QWidget):
    
        def __init__(self, parent=None):
            super(P4, self).__init__(parent)
            P4.layout = QtGui.QGridLayout(self)
            P4.layout.setContentsMargins(20,20,20,20)
            P4.layout.setSpacing(10)
    
            P4.button_pic1 = QtGui.QPushButton('View Plots', self)
            P4.button_pic1.clicked.connect(self.RC_vid1)
            P4.layout.addWidget(P4.button_pic1, 2, 8, 1, 1)
            P4.button_pic1.show()
    
        def RC_vid1(self):
    
            global PrD_window
            try:
                PrD_window.close()
            except:
                pass
    
            PrD_window = PrD_Viz()
            PrD_window.show()
    
    ################################################################################
    
    class PrD_Viz(QtGui.QMainWindow):
    
        currentTab = 0 #NEW
    
        def __init__(self):
            super(PrD_Viz, self).__init__()
            self.left = 10
            self.top = 10
            self.initUI()
    
        def initUI(self):
            vid_tab2 = ManifoldCanvas(self)
            vid_tab3 = PsiCanvas(self)
            global vid_tabs
            vid_tabs = QtGui.QTabWidget(self)
            vid_tabs.addTab(vid_tab2, 'Plot 1')
            vid_tabs.addTab(vid_tab3, 'Plot 2')
    
    
            style = """QTabWidget::tab-bar{
                    alignment: center;
                    }"""
            self.setStyleSheet(style)
            self.setCentralWidget(vid_tabs)
            self.setWindowModality(QtCore.Qt.ApplicationModal) #freezes out parent window
    
            if PrD_Viz.currentTab == 1: #NEW
                vid_tabs.setCurrentIndex(1) #NEW
            #NEW:
            vid_tabs.currentChanged.connect(self.onTabChange) #signal for tabs changed via direct click
    
            self.show()
        #NEW:
        def onTabChange(self, i):
            if i == 0:
                PrD_Viz.currentTab = 0
                self.initUI()
            elif i == 1:
                PrD_Viz.currentTab = 1
                self.initUI()
    
    
    class ManifoldCanvas(QtGui.QDialog):
        pts_orig = []
    
        def __init__(self, parent=None):
            super(ManifoldCanvas, self).__init__(parent)
    
            if PrD_Viz.currentTab == 0: #NEW
                self.figure = Figure(dpi=200)
                self.canvas = FigureCanvas(self.figure)
                self.toolbar = NavigationToolbar(self.canvas, self)
                self.ax = self.figure.add_subplot(111)
    
                x=[1,5,9,8]
                y=[2,6,10,11]
    
                ManifoldCanvas.pts_orig = zip(x,y)
                for i in ManifoldCanvas.pts_orig:
                    x,y = i
                    self.ax.scatter(x,y,s=1,c='#1f77b4')
    
                self.canvas.draw_idle()
    
                layout = QtGui.QGridLayout()
                layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize)
                layout.addWidget(self.toolbar, 0,0,1,5)
                layout.addWidget(self.canvas, 1,0,1,5)
    
                self.setLayout(layout)
    
    class PsiCanvas(QtGui.QDialog):
    
        def __init__(self, parent=None):
            super(PsiCanvas, self).__init__(parent)
    
            if PrD_Viz.currentTab == 1: #NEW
    
                self.psi1 = [10,11,12]
                self.psi2 = [24,19,18]
                self.psi3 = [99,90, 105]
    
                # create canvas and plot data:
                self.figure = Figure(dpi=200)
                self.canvas = FigureCanvas(self.figure)
                self.toolbar = NavigationToolbar(self.canvas, self)
                self.ax = Axes3D(self.figure)
                self.ax.mouse_init()
    
                self.ax.scatter(self.psi1, self.psi2, self.psi3, label='psi_dif', linewidths= .5, edgecolors='k', c='#d62728') #C3
    
                self.canvas.draw_idle() #refresh canvas
    
                layout = QtGui.QGridLayout()
                layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize)
                layout.addWidget(self.toolbar, 0,0,1,4)
                layout.addWidget(self.canvas, 1,0,4,4)
    
                self.setLayout(layout)
    
    
    ################################################################################
    # overhead GUI control: 
    
    class MainWindow(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
    
            tab4 = P4(self)
    
            global tabs
            tabs = QtGui.QTabWidget(self)
            tabs.resize(250,150)
    
            tabs.addTab(tab4, 'Eigenfunctions')
    
            self.setCentralWidget(tabs)
            self.show()
    
    
    if __name__ == '__main__':
    
        app = QtGui.QApplication.instance()
        if app is None:
            app = QtGui.QApplication([])
    
        w = MainWindow()
        sys.exit(app.exec_())