Title: FIX: fill contourf minimum region when it falls just below the lowest level (#21382) by SharadhNaidu · Pull Request #31902 · matplotlib/matplotlib · GitHub
Open Graph Title: FIX: fill contourf minimum region when it falls just below the lowest level (#21382) by SharadhNaidu · Pull Request #31902 · matplotlib/matplotlib
X Title: FIX: fill contourf minimum region when it falls just below the lowest level (#21382) by SharadhNaidu · Pull Request #31902 · matplotlib/matplotlib
Description: PR summary Closes #21382. contourf leaves the minimum-valued region unfilled when the data minimum falls a floating-point hair below the lowest contour level instead of being exactly equal to it. The reported case is a data minimum of -1.7e-13 (a computed value that "should" be 0), but the same thing happens whenever rounding in automatic level selection puts the lowest level just above the data minimum. The cause is in ContourSet._get_lowers_and_uppers. The lowest filled interval is only extended downwards to include the data minimum when self.zmin == lowers[0] exactly: z0 = np.array([[0., 0., 2.], [0., 0., 1.], [2., 1., 0.]]) # min == 0 -> filled z1 = np.array([[0., 0., 2.], [0., 0., 1.], [2., 1., -1.7e-13]]) # min ~ -1e-13 -> clipped This picks up the discussion on the issue (thanks @anntzer and @tacaswell): the data minimum is, within floating-point error, on the lowest level, so that level should be treated as coincident with it. What this changes Compare the lowest level against the data minimum with a tolerance scaled to the data range, rather than with strict equality: tol = (self.zmax - self.zmin) * 1e-12 if 0 <= lowers[0] - self.zmin <= tol: ... This strictly generalises the previous behaviour: the test is a superset of the old ==, so every case that extended the lowest interval before still extends it identically. It only additionally catches the case where the level sits within floating-point tolerance above the minimum. The check is deliberately one-sided and tolerance-bounded so that a genuine gap is left alone. For example, user-specified levels that start above the data minimum mark a region that should stay unfilled, and that gap is many orders of magnitude larger than range * 1e-12, so it is untouched. The 1e-12 factor follows the precedent in #31844: comfortably above numeric noise (~1e-15) yet far below any meaningful contour spacing. I implemented this in _get_lowers_and_uppers rather than in level selection to keep the blast radius small and avoid perturbing the public levels array / colorbar. Happy to move it into the locator path instead if that is preferred. Tests test_contourf_min_at_lowest_level (check_figures_equal, parametrised over 0.0, -1e-13, -1.7e-13): a float-noise minimum must render identically to a clean minimum of zero. test_contourf_lowest_level_gap_not_filled: a user-specified lowest level above the data minimum is not back-filled (guards against over-extending). PR checklist "closes #21382" is in the PR description. New/changed code is tested. Bug fix; no API changes, so no API change notes or what's-new entry.
Open Graph Description: PR summary Closes #21382. contourf leaves the minimum-valued region unfilled when the data minimum falls a floating-point hair below the lowest contour level instead of being exactly equal to it. T...
X Description: PR summary Closes #21382. contourf leaves the minimum-valued region unfilled when the data minimum falls a floating-point hair below the lowest contour level instead of being exactly equal to it. T...
Opengraph URL: https://github.com/matplotlib/matplotlib/pull/31902
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:ea6f55ba-92e9-b3f9-187b-a96a9cdcc9c1 |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | D66C:20A2E2:4D0572:674672:6A51C7E8 |
| html-safe-nonce | 87b3901be0b08a38999a1288e40c1e2c094d71d1b8f967c2ccaf534fdc47f589 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJENjZDOjIwQTJFMjo0RDA1NzI6Njc0NjcyOjZBNTFDN0U4IiwidmlzaXRvcl9pZCI6IjgwMTYwODUzNzkxNjQ3ODQ2MTYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | ea222c3968cca81e82b0bcd5298b4a5761b572e6c889cbf231704c3e9c2d5b18 |
| hovercard-subject-tag | pull_request:3865810240 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,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/matplotlib/matplotlib/pull/31902/files |
| twitter:image | https://avatars.githubusercontent.com/u/185215496?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/185215496?s=400&v=4 |
| og:image:alt | PR summary Closes #21382. contourf leaves the minimum-valued region unfilled when the data minimum falls a floating-point hair below the lowest contour level instead of being exactly equal to it. T... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| diff-view | unified |
| 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 full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7aed05249554b889eb33d002851a973eebcc7e91 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width