Title: [MNT]: Refactor data limits · Issue #30342 · matplotlib/matplotlib · GitHub
Open Graph Title: [MNT]: Refactor data limits · Issue #30342 · matplotlib/matplotlib
X Title: [MNT]: Refactor data limits · Issue #30342 · matplotlib/matplotlib
Description: Summary For now, this is a ticket to collect my thoughts. It's not completely thought though and therefore not yet actionable. Data limits are stored in Axes.dataLim and updated via a push-mechanism (plotting functions that add artists a...
Open Graph Description: Summary For now, this is a ticket to collect my thoughts. It's not completely thought though and therefore not yet actionable. Data limits are stored in Axes.dataLim and updated via a push-mechanis...
X Description: Summary For now, this is a ticket to collect my thoughts. It's not completely thought though and therefore not yet actionable. Data limits are stored in Axes.dataLim and updated via a push-mech...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/30342
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[MNT]: Refactor data limits","articleBody":"### Summary\n\nFor now, this is a ticket to collect my thoughts. It's not completely thought though and therefore not yet actionable.\n\nData limits are stored in `Axes.dataLim` and updated via a push-mechanism (plotting functions that add artists also update the data limits). This has several disadvantages:\n- Changes to the data within an Artist cannot be automatically be picked up; one needs to explicitly call `Axes.relim`.\n- Syncing dataLim for shared axes is tedious\n- The concept does not work well with clearing shared axes (https://github.com/matplotlib/matplotlib/issues/28851#issuecomment-2371603978).\n\n### Proposed fix\n\nWe should rearchitect data limit handling:\n\nBreak the strong coupling between Axes and data limits: Create a `_DataLimits` class that does all the limit related operations:\n```\nclass _DataLimits:\n def __init__(axes):\n self.axes = axes\n self.datalim = BBox.null()\n \n def relim(...):\n # pull pull code from Axes.relim in here\n```\nand remove it from Axes\n```\nclass AxesBase:\n def __init__(...):\n [...]\n self._datalimits = _DataLimits(self)\n # remove self.dataLim\n\n @property\n def dataLim(self):\n return self._datalimits.dataLim\n\n @dataLim.setter\n def dataLim(self, lim):\n self._datalimits.dataLim = lim\n\n def relim(...):\n self._datalimits.relim(....)\n```\n\nWhen we have managed this, we can improve:\n- DataLimits could handle multiple Axes. This allows much better handling of sharing We can then have one DataLimits instance, which collects data information from multiple Axes. This single DataLimits instance is used on all shared Axes. (Note: We likely have to have separate DataLimits objects for x and y to support all kinds of sharing)\n- We can make DataLimits lazy - they are just called from the Axes now. All the state handling is encapsulated in DataLimits. (Possibly, combined with a refactoring so that we can query Artists for their data limits. - Then `_DataLimits` just has to loop over all artists on all handled Axes and collect the limit information.\n\n---\n\n*Edit:* Thinking about it a bit more: data limits should not be shared - they are an individual property of the respective Axes. What needs synchronization / sharing on `sharex/y` is view limits.\n\nSince `Axes.dataLim` is public, people can write to it (either replace the whole instance or update its attributes). Properly shielding against that is quite a hassle, because we'd need to have an immuatble BBox. So for the time being, we are bound to `dataLim` as BBox being the data representation. That combined with the realization that data limits should not be shared implies there's likely not a large benefit in refactoring.\n\nSharing should be handled on the level view limits.\n\nWe can still make the data limits lazy - as we do with `viewLim` https://github.com/matplotlib/matplotlib/blob/b2e8b936e057ffc7b0d1505c5703988172041d4b/lib/matplotlib/axes/_base.py#L889-893.","author":{"url":"https://github.com/timhoffm","@type":"Person","name":"timhoffm"},"datePublished":"2025-07-22T14:33:00.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":5},"url":"https://github.com/30342/matplotlib/issues/30342"}
| 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:186ed466-14c2-ba35-084a-aad5f0913a02 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E590:183DA9:11407A3:1793F17:6A521352 |
| html-safe-nonce | a8650f3bd6d9e74141dbadfa75c6917efa7772f774d018ba31ad507522a161b2 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFNTkwOjE4M0RBOToxMTQwN0EzOjE3OTNGMTc6NkE1MjEzNTIiLCJ2aXNpdG9yX2lkIjoiODA2NjM1NDUxMzkxNTgxMDY0MiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 630427f532c17d1d3c9e90c3687b2f326308be2b4187a921722c1ac5e8f836a2 |
| hovercard-subject-tag | issue:3252942079 |
| 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/30342/issue_layout |
| twitter:image | https://opengraph.githubassets.com/8059d0fd2759190d61f3f12abb09ca98bf61e5f23e6da37a7dbdcc740f30b91a/matplotlib/matplotlib/issues/30342 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/8059d0fd2759190d61f3f12abb09ca98bf61e5f23e6da37a7dbdcc740f30b91a/matplotlib/matplotlib/issues/30342 |
| og:image:alt | Summary For now, this is a ticket to collect my thoughts. It's not completely thought though and therefore not yet actionable. Data limits are stored in Axes.dataLim and updated via a push-mechanis... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | timhoffm |
| 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 | 7aed05249554b889eb33d002851a973eebcc7e91 |
| ui-target | canary-2 |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width