-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Preserve legend settings when regenerating in Qt figure options dialog #31553
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1098,6 +1098,34 @@ def set_frame_on(self, b): | |
|
|
||
| draw_frame = set_frame_on # Backcompat alias. | ||
|
|
||
| def _get_properties(self): | ||
| """ | ||
| Return a dictionary of legend properties for recreation. | ||
|
|
||
| This is used by the Qt figure options dialog to preserve legend | ||
| settings when regenerating the legend. | ||
| """ | ||
| props = { | ||
| 'loc': self._loc, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The list seems incomplete. On what basis did you select the properties? |
||
| 'fontsize': self._fontsize, | ||
| 'frameon': self.get_frame_on(), | ||
| 'shadow': self.shadow, | ||
| 'framealpha': self.get_frame().get_alpha(), | ||
| 'title': self.get_title().get_text(), | ||
| 'columnspacing': self.columnspacing, | ||
| 'labelspacing': self.labelspacing, | ||
| 'handlelength': self.handlelength, | ||
| 'handletextpad': self.handletextpad, | ||
| 'borderpad': self.borderpad, | ||
| 'borderaxespad': self.borderaxespad, | ||
| 'markerscale': self.markerscale, | ||
| } | ||
| if self._bbox_to_anchor is not None: | ||
| props['bbox_to_anchor'] = self._bbox_to_anchor.bounds | ||
| if self._mode is not None: | ||
| props['mode'] = self._mode | ||
|
Comment on lines
+1123
to
+1126
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can these two not be always returned? If that is the case document that they are only conditionally present and explain why. |
||
| return props | ||
|
|
||
| def get_bbox_to_anchor(self): | ||
| """Return the bbox that the legend will be anchored to.""" | ||
| if self._bbox_to_anchor is None: | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,126 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """Tests for legend property preservation.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import matplotlib | ||||||||||||||||||||||||||||||||||||||||||||||||||
| matplotlib.use('Agg') | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import matplotlib.pyplot as plt | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_get_properties_basic(): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Test that Legend._get_properties() returns the correct properties. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| fig, ax = plt.subplots() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.plot(range(5), label='a') | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.plot(range(3)[::-1], label='b') | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.legend( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| loc='upper right', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| fontsize=14, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| frameon=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| shadow=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| title='My Legend', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ncols=2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| columnspacing=3.0, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| labelspacing=1.5, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| handlelength=4.0, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| handletextpad=1.2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+26
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make it more compact and safe by not repeating the names and values
Suggested change
to be continued below |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| legend = ax.get_legend() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| props = legend._get_properties() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['loc'] == legend._loc | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['fontsize'] == 14 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['frameon'] is False | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['shadow'] is True | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['title'] == 'My Legend' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['columnspacing'] == 3.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['labelspacing'] == 1.5 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['handlelength'] == 4.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['handletextpad'] == 1.2 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert 'bbox_to_anchor' not in props | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert 'mode' not in props | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+31
to
+41
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Make sure you include all props returned by _get_properties to get full coverage and be able to just assert dict equality. |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| plt.close(fig) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Not needed. Closing is automatic in tests. |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_get_properties_with_mode_and_bbox(): | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Test that _get_properties() includes mode and bbox_to_anchor | ||||||||||||||||||||||||||||||||||||||||||||||||||
| when they are set. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| fig, ax = plt.subplots() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.plot(range(5), label='a') | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.legend( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| bbox_to_anchor=(0, 1.02, 1, 0.2), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| loc='lower left', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| mode='expand', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ncols=2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| legend = ax.get_legend() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| props = legend._get_properties() | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| assert props['mode'] == 'expand' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert 'bbox_to_anchor' in props | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| plt.close(fig) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_get_properties_roundtrip(): | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this tests tell us more compared to |
||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Test that properties from _get_properties() can be used to | ||||||||||||||||||||||||||||||||||||||||||||||||||
| recreate a legend with the same settings. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| fig, ax = plt.subplots() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.plot(range(5), label='a') | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.plot(range(3)[::-1], label='b') | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.legend( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| loc='upper right', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| fontsize=14, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| frameon=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| shadow=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| title='My Legend', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ncols=2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| columnspacing=3.0, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| labelspacing=1.5, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| handlelength=4.0, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| handletextpad=1.2, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| old_legend = ax.get_legend() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| props = old_legend._get_properties() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ncols = old_legend._ncols | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| # Recreate legend using extracted properties | ||||||||||||||||||||||||||||||||||||||||||||||||||
| new_legend = ax.legend(ncols=ncols, **props) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend._fontsize == 14 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.get_frame_on() is False | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.shadow is True | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.get_title().get_text() == 'My Legend' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend._ncols == 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.columnspacing == 3.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.labelspacing == 1.5 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.handlelength == 4.0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.handletextpad == 1.2 | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| plt.close(fig) | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_legend_regeneration_no_existing_legend(): | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I completely do not understand this test. There is no regeneration. You only create one legend. This test does not touch any library code modified in this PR. |
||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Test that regenerating a legend when none exists still works. | ||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| fig, ax = plt.subplots() | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ax.plot(range(5), label='a') | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| assert ax.get_legend() is None | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| new_legend = ax.legend(ncols=1) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend is not None | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(new_legend.get_texts()) == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| assert new_legend.get_texts()[0].get_text() == 'a' | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| plt.close(fig) | ||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to not include
draggablein_get_properties()?