matplotlib / basemap

Plot on map projections (with coastlines and political boundaries) using matplotlib
MIT License
780 stars 392 forks source link

matplotlib basemap colorbar exception : Given element not contained in the stack #544

Open redstoneleo opened 2 years ago

redstoneleo commented 2 years ago

please see it at https://github.com/matplotlib/matplotlib/issues/23186

molinav commented 10 months ago

Hi @redstoneleo! Sorry for the late reply. I have taken your example snippet and I paste it here for the record:

import sys

import numpy as np
from matplotlib import cm
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from mpl_toolkits.basemap import Basemap
from PyQt5 import QtWidgets

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, parent=None):

        super().__init__(parent)

        button1 = QtWidgets.QPushButton("button1")
        button2 = QtWidgets.QPushButton("button2")

        self.map_canvas = FigureCanvas(Figure(figsize=(20, 20)))
        self.map_toolbar = NavigationToolbar(self.map_canvas, self)

        central_widget = QtWidgets.QWidget()
        self.setCentralWidget(central_widget)
        lay = QtWidgets.QGridLayout(central_widget)
        lay.addWidget(button1, 0, 0)
        lay.addWidget(button2, 0, 1)
        lay.addWidget(self.map_canvas, 1, 0, 1, 2)

        self.addToolBar(self.map_toolbar)

        button1.clicked.connect(self.update_plot)
        button2.clicked.connect(self.update_plot)

        self.ax = self.map_canvas.figure.subplots()
        self.ax.set_axis_off()

    def update_plot(self):

        self.ax.clear()

        m = Basemap(width=12000000, height=9000000, projection="lcc",
                    resolution="c", lat_0=19., lon_0=73., ax=self.ax)
        m.drawcoastlines(linewidth=1)

        x, y, z = np.random.rand(3, 1000000)
        x *= 12e6
        y *= 9e6
        z *= 20000

        gridsize = 100
        m.hexbin(x, y, C=z, gridsize=gridsize, cmap=cm.YlGnBu)

        # cb = m.colorbar()
        self.map_canvas.draw()

if __name__ == "__main__":

    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)

    window = MainWindow()
    window.show()

    sys.exit(app.exec_())

If cb = m.colorbar() is commented as above, then your snippet is working for me on Windows x64 with Python 3.11, basemap 1.4.0-dev and matplotlib 3.7.4 (image below is after clicking the left button): image

If I uncomment cb = m.colorbar(), I get an error after clicking the left button, but it is different from the one reported in your other issue:

Traceback (most recent call last):
  File "C:\Users\vic\OneDrive\Workspace\github\example.py", line 55, in update_plot
    cb = m.colorbar()
         ^^^^^^^^^^^^
  File "C:\ProgramData\pyenv-win\pyenv-win\versions\py311\Lib\site-packages\mpl_toolkits\basemap\__init__.py", line 4707, in colorbar
    fig.sca(ax) # reset parent axes as current axes.
    ^^^^^^^^^^^
  File "C:\ProgramData\pyenv-win\pyenv-win\versions\py311\Lib\site-packages\matplotlib\figure.py", line 1645, in sca
    self._axstack.bubble(a)
  File "C:\ProgramData\pyenv-win\pyenv-win\versions\py311\Lib\site-packages\matplotlib\figure.py", line 97, in bubble
    raise ValueError("Axes has not been added yet")
ValueError: Axes has not been added yet

So I can confirm you that something is not working with Basemap.colorbar as expected. I do not think a bugfix can be made for basemap 1.4.0, because I want to release today or tomorrow, but I will try to inspect the issue when I get some time.