FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

colorbar might shrink plots if used with twinx · Issue #8823 · matplotlib/matplotlib · GitHub

Repository navigation

colorbar might shrink plots if used with twinx #8823

Closed

Description

Bug report

Changing plot alignment for different placing of colorbar() in twinx plot

If one combines a pcolormesh plot/hist2d plot with a standard plot by using twinx, the graph from the plot moves to wrong x values if the colorbar is called after the plot call. If it is called before, the alignment is fine.

I am not sure if this is a bug or just wrong usage.
However, one of the resulting graphs has a wrong extent that might lead to misinterpretations.

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt

data = np.random.random((64, 128)) * 2.0
x = np.arange(128)
y = np.arange(64)
plt.pcolormesh(x, y, data)

#plt.colorbar() --> here it works fine
plt.twinx()
plt.colorbar()
# --> here it gives wrong x values for the orange plot

plt.plot(x, np.sin(x/10), color="orange", lw=4)

plt.show()

Actual outcome

Next to the confusing layout the plot shows actually a wrong graph:
the orange plot just goes to around x=100 but should go to x=128.
(The axis of the colorbar is correct and shows the range of data.)

Expected outcome

If colorbar is called before twinx, the orange graph has the correct extent.

I am not sure if this is a bug or a wrong usage of matplotlib. In any case the wrong extent of the (in this case) orange plot is a dangerous behavior that might lead to misinterpretations of the data.

Matplotlib version

  • Operating System: Ubuntu 14.04.1
  • Matplotlib Version: 2.0.0rc1
  • Python Version: 3.4.3
  • Jupyter Version: 1.0.0 (I am using %matplotlib inline)
  • Other Libraries: numpy 1.12.0b1

I installed matplotlib via pip.

Activity

  1. efiring commented on Jun 29, 2017

    Member

    I would call it a shortcoming of the twinx implementation: it makes a second Axes at the same position as the first, but it has no mechanism for ensuring that if the position of either is subsequently changed, the position of the other is also changed to match it. Ideally, the position of both Axes would be the same object so that it would not be necessary to use callbacks to keep them synchronized. There are several attributes related to position, so I'm not sure whether this would be a simple change, a difficult one, or a complete can of worms.

  2. added this to the milestone on Jun 30, 2017
  3. jklymak commented on Dec 11, 2017

    Member

    #9082 addresses this (though you can't use the pyplot interface)

    data = np.random.random((64, 128)) * 2.0
    x = np.arange(128)
    y = np.arange(64)
    fig, ax = plt.subplots(constrained_layout=True)
    pcm = ax.pcolormesh(x, y, data)
    
    #plt.colorbar() --> here it works fine
    ax2 = ax.twinx()
    fig.colorbar(pcm)
    # --> here it gives wrong x values for the orange plot
    
    ax2.plot(x, np.sin(x/10), color="orange", lw=4)
    
    plt.show()

  4. PrometheusPi commented on Dec 12, 2017

    Author

    @jklymak Thanks for posting this. I will cherry pick your pull request.

  5. efiring commented on Jan 21, 2018

    Member

    This is also addressed by #10033.

  6. efiring commented on Jan 26, 2018

    Member

    Closed by #10033.

  7. modified the milestones: , v2.2.0 on Feb 12, 2018
  8. bactone commented on Nov 24, 2021

    while I got the same problem, here is my code: if a twinx exist, then if you remove the colorbar, and the axe shrink, even if you apply tight layout, it won't recover.

    import sys
    import numpy as np
    from PyQt5 import QtWidgets
    
    import matplotlib
    from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
    from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
    import matplotlib.pyplot as plt
    
    
    matplotlib.use("Qt5Agg")
    
    
    class MplCanvas(FigureCanvasQTAgg):
        def __init__(self, parent=None, width=5, height=4, dpi=100):
            self.fig = plt.figure(figsize=(width, height), dpi=dpi)
            self.axe = self.fig.add_subplot(1, 1, 1, label='good')
            super().__init__(self.fig)
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
    
            v_layout = QtWidgets.QVBoxLayout()
    
            self.canvas = MplCanvas(self, width=5, height=4, dpi=100)
            self.axe = self.canvas.axe
            self.figure = self.canvas.fig
            
            # draw a scatter plot on self.axe
            np.random.seed(19680801)
            rx, ry = 3., 1.
            area = rx * ry * np.pi
            theta = np.arange(0, 2 * np.pi + 0.01, 0.1)
            verts = np.column_stack([rx / area * np.cos(theta), ry / area * np.sin(theta)])
            x, y, s, c = np.random.rand(4, 30)
            s *= 10 ** 2
            self.image = self.axe.scatter(x, y, s=s, c=c, marker=verts)
    
            # add a twinx: it fails the tight layout*********************
            x = np.arange(0, 1, 0.01)
            y = np.random.randn(len(x))
            self.ax2 = self.axe.twinx()
            self.ax2.plot(x, y, lw=2, linestyle='-', label='signal')
            # ***********************************************************
    
            toolbar = NavigationToolbar(self.canvas, self)
            v_layout.addWidget(toolbar)
    
            v_layout.addWidget(self.canvas)
            label = QtWidgets.QLabel('Show Color Bar')
            self.checkBox_colorBar = QtWidgets.QCheckBox(self)
            h_layout = QtWidgets.QHBoxLayout(self)
            h_layout.addWidget(label)
            h_layout.addWidget(self.checkBox_colorBar)
    
            v_layout.addLayout(h_layout)
    
            widget = QtWidgets.QWidget()
            widget.setLayout(v_layout)
            self.setCentralWidget(widget)
    
            self.checkBox_colorBar.toggled.connect(self.showColorBar)
    
        def showColorBar(self):
    
            color_bar = self.image.colorbar  # None if no color bar
    
            if self.checkBox_colorBar.isChecked():
                if color_bar is None:
                    self.figure.colorbar(self.image)
            else:
                if color_bar is not None:
                    color_bar.remove()
                    del color_bar
    
            self.canvas.draw()
    
    
    if __name__ == '__main__':
    
        app = QtWidgets.QApplication(sys.argv)
    
        window = MainWindow()
        mw = window
        mw.show()
        app.exec_()

    it gives out the following result if toggle the show color bar check box a few times.



  9. jklymak commented on Nov 24, 2021

    Member

    Please open a new bug report including all relevant version info. However I do not think removing a Colorbar will magically reallocate its space using tight_layout. It may work with constrained_layout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL