Title: [Bug]: (Tight) layout engine breaks for 3D patches · Issue #27361 · matplotlib/matplotlib · GitHub
Open Graph Title: [Bug]: (Tight) layout engine breaks for 3D patches · Issue #27361 · matplotlib/matplotlib
X Title: [Bug]: (Tight) layout engine breaks for 3D patches · Issue #27361 · matplotlib/matplotlib
Description: Bug summary The tight layout sometimes breaks for plots with 3D patches because 'PathPatch3D' object has no attribute '_path2d'. Code for reproduction import matplotlib.pyplot as plt import matplotlib.patches as pat import mpl_toolkits.m...
Open Graph Description: Bug summary The tight layout sometimes breaks for plots with 3D patches because 'PathPatch3D' object has no attribute '_path2d'. Code for reproduction import matplotlib.pyplot as plt import matplot...
X Description: Bug summary The tight layout sometimes breaks for plots with 3D patches because 'PathPatch3D' object has no attribute '_path2d'. Code for reproduction import matplotlib.pyplot as pl...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/27361
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[Bug]: (Tight) layout engine breaks for 3D patches","articleBody":"### Bug summary\r\n\r\nThe tight layout sometimes breaks for plots with 3D patches because 'PathPatch3D' object has no attribute '_path2d'.\r\n\r\n### Code for reproduction\r\n\r\n```python\r\nimport matplotlib.pyplot as plt\r\nimport matplotlib.patches as pat\r\nimport mpl_toolkits.mplot3d.art3d as art3d\r\n\r\nfig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"}, layout=\"tight\") # , dpi=300)\r\n\r\np = pat.Rectangle((0, 0), 1.0, 1.0)\r\nax.add_patch(p)\r\nart3d.pathpatch_2d_to_3d(p)\r\n\r\n# fig.set_dpi(300)\r\n# fig.tight_layout()\r\n\r\nfig.savefig(\"test.pdf\") #, dpi=300)\r\n```\r\n\r\n\r\n### Actual outcome\r\n```\r\nTraceback (most recent call last):\r\n File \"/home/tobias/mne3.py\", line 11, in \u003cmodule\u003e\r\n fig.savefig(\"test.pdf\") #, dpi=300)\r\n ^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/figure.py\", line 3343, in savefig\r\n self.canvas.print_figure(fname, **kwargs)\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/backends/backend_qtagg.py\", line 75, in print_figure\r\n super().print_figure(*args, **kwargs)\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/backend_bases.py\", line 2342, in print_figure\r\n self.figure.draw(renderer)\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/artist.py\", line 95, in draw_wrapper\r\n result = draw(artist, renderer, *args, **kwargs)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/artist.py\", line 72, in draw_wrapper\r\n return draw(artist, renderer)\r\n ^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/figure.py\", line 3134, in draw\r\n self.get_layout_engine().execute(self)\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/layout_engine.py\", line 178, in execute\r\n kwargs = get_tight_layout_figure(\r\n ^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/_tight_layout.py\", line 266, in get_tight_layout_figure\r\n kwargs = _auto_adjust_subplotpars(fig, renderer,\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/_tight_layout.py\", line 82, in _auto_adjust_subplotpars\r\n bb += [martist._get_tightbbox_for_layout_only(ax, renderer)]\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/artist.py\", line 1415, in _get_tightbbox_for_layout_only\r\n return obj.get_tightbbox(*args, **{**kwargs, \"for_layout_only\": True})\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/mpl_toolkits/mplot3d/axes3d.py\", line 3189, in get_tightbbox\r\n ret = super().get_tightbbox(renderer,\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/axes/_base.py\", line 4408, in get_tightbbox\r\n bbox = a.get_tightbbox(renderer)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/artist.py\", line 367, in get_tightbbox\r\n bbox = self.get_window_extent(renderer)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/matplotlib/patches.py\", line 604, in get_window_extent\r\n return self.get_path().get_extents(self.get_transform())\r\n ^^^^^^^^^^^^^^^\r\n File \"/home/tobias/.local/lib/python3.11/site-packages/mpl_toolkits/mplot3d/art3d.py\", line 420, in get_path\r\n return self._path2d\r\n ^^^^^^^^^^^^\r\nAttributeError: 'PathPatch3D' object has no attribute '_path2d'\r\n```\r\n### Expected outcome\r\n\r\nThe following code actually produces (something that is at least close enough to) the expected outcome. It does **NOT** produce an error even though I would expect it to be equivalent.\r\n```python\r\nimport matplotlib.pyplot as plt\r\nimport matplotlib.patches as pat\r\nimport mpl_toolkits.mplot3d.art3d as art3d\r\n\r\nfig, ax = plt.subplots(subplot_kw={\"projection\": \"3d\"})\r\n\r\np = pat.Rectangle((0, 0), 1.0, 1.0)\r\nax.add_patch(p)\r\nart3d.pathpatch_2d_to_3d(p)\r\n\r\nfig.tight_layout()\r\n\r\nfig.savefig(\"test.pdf\")\r\n```\r\nThe result is different compared to the case without the tight layout engine, so I assume it is doing something. However I am not sure if it is fully doing it's job.\r\n\r\n### Additional information\r\n\r\nWhether I get an error or not depends on some weird circumstances (e.g. the behaviour depends on dpi settings). I left some possible modifications as comments in the minimal example above. Here is a short summary of some test I did:\r\n\r\n- `layout=\"tight\"` works with `fig.savefig(\"test.png\")` but **NOT** with `fig.savefig(\"test.png\", dpi=300)`.\r\n- Similarly if I use `plt.subplots(..., dpi=300)` or `fig.set_dpi(300)` the call to `fig.tight_layout()` already gives an error and **NOT** the call to `fig.savefig()`.\r\n- In most cases where it breaks for `layout=\"tight\"` it also breaks for `\"compressed\"` or `\"constrained\"`.\r\n\r\n### Operating system\r\n\r\nArch\r\n\r\n### Matplotlib Version\r\n\r\n3.7.1\r\n\r\n### Matplotlib Backend\r\n\r\nQtAgg\r\n\r\n### Python version\r\n\r\nPython 3.11.5\r\n\r\n### Jupyter version\r\n\r\n_No response_\r\n\r\n### Installation\r\n\r\nLinux package manager","author":{"url":"https://github.com/thrien","@type":"Person","name":"thrien"},"datePublished":"2023-11-22T19:23:45.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":8},"url":"https://github.com/27361/matplotlib/issues/27361"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:b51977e2-c968-04c2-98fa-0fdcad0008b6 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E83A:135646:D9514F:1250CF7:6A52CC41 |
| html-safe-nonce | 4845dc4661a6fc9ae8f10bf3231abf921852b548ae5e43f2eb129dae9ca2a1dd |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFODNBOjEzNTY0NjpEOTUxNEY6MTI1MENGNzo2QTUyQ0M0MSIsInZpc2l0b3JfaWQiOiIyODA3OTQyNjgzODEyODc1MzI5IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 5c8904b83884b1ca25fbfbf96ef0bffe8fec08c4f816d23383fc8159798e0f0b |
| hovercard-subject-tag | issue:2006992258 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/matplotlib/matplotlib/27361/issue_layout |
| twitter:image | https://opengraph.githubassets.com/6c059d8f697ff549822497c6da8585aba8b765b12816983ef1bd9fb0b2c7011e/matplotlib/matplotlib/issues/27361 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/6c059d8f697ff549822497c6da8585aba8b765b12816983ef1bd9fb0b2c7011e/matplotlib/matplotlib/issues/27361 |
| og:image:alt | Bug summary The tight layout sometimes breaks for plots with 3D patches because 'PathPatch3D' object has no attribute '_path2d'. Code for reproduction import matplotlib.pyplot as plt import matplot... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | thrien |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git |
| octolytics-dimension-user_id | 215947 |
| octolytics-dimension-user_login | matplotlib |
| octolytics-dimension-repository_id | 1385122 |
| octolytics-dimension-repository_nwo | matplotlib/matplotlib |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1385122 |
| octolytics-dimension-repository_network_root_nwo | matplotlib/matplotlib |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width