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 -*-importsysfromPyQt4importQtGuifrommatplotlib.figureimportFigurefrommatplotlib.backends.backend_qt4aggimport (
FigureCanvasQTAggasFigureCanvas)
classMplCanvas(FigureCanvas):
"""Class to represent the FigureCanvas widget"""def__init__(self):
# Setup Matplotlib Figure and Axisself.fig=Figure(facecolor="white")
self.axes=self.fig.add_subplot(111)
# Initialization of the canvassuper(MplCanvas, self).__init__(self.fig)
# Define the widget as expandableFigureCanvas.setSizePolicy(self,
QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
# Notify the system of updated policyFigureCanvas.updateGeometry(self)
# Call tight_layout on resize#self.mpl_connect('resize_event', self.fig.tight_layout)classMplWidget(QtGui.QWidget):
"""Widget defined in Qt Designer"""def__init__(self, parent=None):
super(MplWidget, self).__init__(parent)
# Set canvas and navigation toolbarself.canvas=MplCanvas()
# Layout as vertical boxself.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.
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.
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()?
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)
.
Reacted by Goto Hayato, rileypeterson, Jack Youstra and Prem Chandra Singh
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()?
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 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).
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.
@WeatherGodhttps://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)
.
(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.
#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 👎
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!
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.
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.
Activity
tacaswell commented on Mar 20, 2015
Minimal code to reproduce:
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 commented on Mar 20, 2015
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:
WeatherGod commented on Mar 20, 2015
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:
tacaswell commented on Mar 20, 2015
@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 commented on Mar 20, 2015
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
lafrech commented on 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
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 commented on Mar 20, 2015
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 commented on Mar 20, 2015
Right. I get the point (clipboard being GUI dependent, etc.). Thanks for the tip.
jklymak commented on 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 👎
github-actions commented on Mar 11, 2023
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!
jklymak commented on 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 commented on 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.