8000 Pie chart labels out of Figure, even with tight_layout · Issue #4251 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Pie chart labels out of Figure, even with tight_layout #4251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lafrech opened this issue Mar 20, 2015 · 12 comments
Closed

Pie chart labels out of Figure, even with tight_layout #4251

lafrech opened this issue Mar 20, 2015 · 12 comments
Labels
keep Items to be ignored by the “Stale” Github Action New feature topic: geometry manager LayoutEngine, Constrained layout, Tight layout topic: text

Comments

@lafrech
Copy link
lafrech commented Mar 20, 2015

Hi.

I'm drawing a pie chart and the labels are cut off of the Figure. I thought this would be solved by tight_layout (as per this issue for instance) but this does not seem to be the case, at least for a pie chart.

Below is a code snippet to reproduce. In fact, tight_layout makes it even worse since it ignores the labels and crops tighter to the pie.

Is there a way around this ?

Am I doing things wrong ?

# -*- coding: utf-8 -*-

import sys

from PyQt4 import QtGui

from matplotlib.figure import Figure

from matplotlib.backends.backend_qt4agg import (
    FigureCanvasQTAgg as FigureCanvas)

class MplCanvas(FigureCanvas):
    """Class to represent the FigureCanvas widget"""
    def __init__(self):

        # Setup Matplotlib Figure and Axis
        self.fig = Figure(facecolor="white")
        self.axes = self.fig.add_subplot(111)

        # Initialization of the canvas
        super(MplCanvas, self).__init__(self.fig)

        # Define the widget as expandable
        FigureCanvas.setSizePolicy(self,
                                   QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)

        # Notify the system of updated policy
        FigureCanvas.updateGeometry(self)

        # Call tight_layout on resize
        #self.mpl_connect('resize_event', self.fig.tight_layout)

class MplWidget(QtGui.QWidget):
    """Widget defined in Qt Designer"""
    def __init__(self, parent = None):

        super(MplWidget, self).__init__(parent)

        # Set canvas and navigation toolbar
        self.canvas = MplCanvas()

        # Layout as vertical box
        self.vbl = QtGui.QVBoxLayout()
        self.vbl.addWidget(self.canvas)
        self.setLayout(self.vbl)


if __name__ == "__main__":

    app = QtGui.QApplication(sys.argv)

    W = MplWidget()

    W.canvas.axes.cla()

    values = [0.2, 0.5, 0.3]
    labels = ['label',
              'looooooog label',
              'very loooooooooooooooooooooooog label'
             ]

    W.canvas.axes.pie(values, labels=labels)
    W.canvas.axes.axis('equal')

    W.canvas.fig.tight_layout()
    W.canvas.draw()
    W.show()

    sys.exit(app.exec_())

I'm using python 2.7 and Matplotlib 1.4.3~rc1 from Debian experimental.

@tacaswell tacaswell added this to the next point release milestone Mar 20, 2015
@tacaswell tacaswell added topic: text topic: geometry manager LayoutEngine, Constrained layout, Tight layout labels Mar 20, 2015
@tacaswell
Copy link
Member

Minimal code to reproduce:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

values = [0.2, 0.5, 0.3]
labels = ['label',
          'looooooog label',
          'very loooooooooooooooooooooooog label'
         ]

ax.pie(values, labels=labels)
ax.axis('equal')

fig.tight_layout()
plt.draw()

It is easier for use if your examples use the pyplot interface for managing the figure/axes as the details of the embedding should not matter.

This is an interesting pathological example. As I understand it tight_layout was intended to deal with overlaps between axes and axes labels when there are multiple axes in the same figure. Normally Artists are clipped to an axes so all tight_layout looks at is the position (ex specified bounding box of the axes is figure fraction units). However in the case of pie we turn the axes and clipping of the text + wedges off by default so the assumption made in tight_layout is no longer true as the text may fall outside of axes and be visible.

@WeatherGod
Copy link
Member

Yeah, tight_layout() is specifically designed for preventing overlaps of
subplots when laying them out. The minimal code to reproduce is actually
incorrect because it is only one subplot, and so tight_layout() really
wouldn't be doing much here (it'll do a bit of neatening up, but nothing
significant).

The feature you are (sort of) looking for is the bbox_inches='tight'
option to savefig(), but that is only available upon save. Maybe it is time
to consider bringing that out of savefig()?

On Fri, Mar 20, 2015 at 9:49 AM, Thomas A Caswell notifications@github.com
wrote:

Minimal code to reproduce:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

values = [0.2, 0.5, 0.3]
labels = ['label',
'looooooog label',
'very loooooooooooooooooooooooog label'
]

ax.pie(values, labels=labels)
ax.axis('equal')

fig.tight_layout()
plt.draw()

It is easier for use if your examples use the pyplot interface for
managing the figure/axes as the details of the embedding should not matter.

This is an interesting pathological example. As I understand it
tight_layout was intended to deal with overlaps between axes and axes
labels when there are multiple axes in the same figure. Normally Artists
are clipped to an axes so all tight_layout looks at is the position (ex
specified bounding box of the axes is figure fraction units). However in
the case of pie we turn the axes and clipping of the text + wedges off by
default so the assumption made in tight_layout is no longer true as the
text may fall outside of axes and be visible.


Reply to this email directly or view it on GitHub
#4251 (comment)
.

@WeatherGod
Copy link
Member

I should note that Thomas's intuition is still correct. If there were
multiple subplots, I don't think tight_layout() would work properly since
it doesn't properly caclulate the bbox of each subplot.

On Fri, Mar 20, 2015 at 9:58 AM, Benjamin Root ben.root@ou.edu wrote:

Yeah, tight_layout() is specifically designed for preventing overlaps of
subplots when laying them out. The minimal code to reproduce is actually
incorrect because it is only one subplot, and so tight_layout() really
wouldn't be doing much here (it'll do a bit of neatening up, but nothing
significant).

The feature you are (sort of) looking for is the bbox_inches='tight'
option to savefig(), but that is only available upon save. Maybe it is time
to consider bringing that out of savefig()?

On Fri, Mar 20, 2015 at 9:49 AM, Thomas A Caswell <
notifications@github.com> wrote:

Minimal code to reproduce:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

values = [0.2, 0.5, 0.3]
labels = ['label',
'looooooog label',
'very loooooooooooooooooooooooog label'
]

ax.pie(values, labels=labels)
ax.axis('equal')

fig.tight_layout()
plt.draw()

It is easier for use if your examples use the pyplot interface for
managing the figure/axes as the details of the embedding should not matter.

This is an interesting pathological example. As I understand it
tight_layout was intended to deal with overlaps between axes and axes
labels when there are multiple axes in the same figure. Normally Artists
are clipped to an axes so all tight_layout looks at is the position (ex
specified bounding box of the axes is figure fraction units). However in
the case of pie we turn the axes and clipping of the text + wedges off
by default so the assumption made in tight_layout is no longer true as
the text may fall outside of axes and be visible.


Reply to this email directly or view it on GitHub
#4251 (comment)
.

@tacaswell
Copy link
Member

@WeatherGod It is still doing something here, because there are no tick labels it is expanding the one axes to have the bounding box [0, 1, 0, 1] (or as close to that as the aspect allows).

@WeatherGod
Copy link
Member

Well, yeah, that's what it is supposed to do. However, it won't resize any
text objects if they aren't tick labels, axes labels, titles, or suptitles,
and I don't think I would want it to mess around with any other text
objects. If we do, we would have to be very careful about that.

Meanwhile, bbox_inches='tight' resizes the figure to accomodate all visible
artist objects, but won't mess around with anything else.

On Fri, Mar 20, 2015 at 10:08 AM, Thomas A Caswell <notifications@github.com

wrote:

@WeatherGod https://github.com/WeatherGod It is still doing something
here, because there are no tick labels it is expanding the one axes to have
the bounding box [0, 1, 0, 1](or as close to that as the aspect allows).


Reply to this email directly or view it on GitHub
#4251 (comment)
.

@lafrech
Copy link
Author
lafrech commented Mar 20, 2015

(Sorry about the snippet. I didn't figure out about pyplot. Thanks for writing the minimal example.)

These concepts are pretty new to me. I searched through the docs, but my understanding of the insides of Matplotlib is close to zero. However, I think WeatherGod is probably right about the parallel with the savefig() function, at least from a user perpective.

Ultimately, I'd like to copy the plot to the clipboard to insert it in a document. Currently, I can either

  • export it to the filesystem as an image file then insert it
  • copy the widget to the clipboard, which is really easy, but then I need the widget to display perfectly (labels included).

A modification to the savefig() function that would allow saving to clipboard would be a workaround for my use case. Of course, having the plot display correctly in the widget in the first place would be even better.

@tacaswell
Copy link
Member

You can save to a StringIO object which you can then (I assume?) shove in to the clipboard.

The internals of mpl are militantly GUI/OS independent so getting clipboard functionality down into savefig may be difficult.

@lafrech
Copy link
Author
lafrech commented Mar 20, 2015

Right. I get the point (clipboard being GUI dependent, etc.). Thanks for the tip.

@tacaswell tacaswell modified the milestones: proposed next point release, next point release Jul 16, 2015
@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Oct 3, 2017
@jklymak
Copy link
Member
jklymak commented Mar 8, 2018

#10682 gets this example closer with cosntrained_layout. But differences between the rendered and final fontsize mean I need to throw a few extra fig.canvas.draw() commands in there 👎

@jklymak jklymak modified the milestones: needs sorting, v3.0 Mar 18, 2018
@dstansby dstansby modified the milestones: v3.0, needs sorting Jul 26, 2018
@github-actions
Copy link

This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

@github-actions github-actions bot added the status: inactive Marked by the “Stale” Github Action label Mar 11, 2023
@jklymak jklymak added keep Items to be ignored by the “Stale” Github Action and removed status: inactive Marked by the “Stale” Github Action labels Mar 11, 2023
@jklymak
Copy link
Member
jklymak commented Mar 11, 2023

This is still a problem, even if you don't use ax.axis('equal') . The bounding box of the labels is not set until draw time. If you remove ax.axis('equal') and throw a fig.draw_without_rendering in there, it works OK.

@jklymak
Copy link
Member
jklymak commented Mar 12, 2023

Actually I'll close this. This is a case where we don't know the extent of the text until it is draw at the correct location, which we don't know until after a draw. We already document that some cases require fig.draw_without_rendering(), and this is one of them.

@jklymak jklymak closed this as not planned Won't fix, can't repro, duplicate, stale Mar 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
keep Items to be ignored by the “Stale” Github Action New feature topic: geometry manager LayoutEngine, Constrained layout, Tight layout topic: text
Projects
None yet
Development

No branches or pull requests

5 participants
0