Skip to content

Conversation

@cvanelteren
Copy link
Collaborator

@cvanelteren cvanelteren commented Dec 14, 2025

Closes #297,#270

This PR introduces UltraLayout, a novel constraint-based layout system using kiwisolver that enables aesthetically pleasing positioning for non-orthogonal subplot arrangements (e.g., [[1, 1, 2, 2], [0, 3, 3, 0]] where subplot 3 should be centered between subplots 1 and 2). The existing gridspec works great for orthogonal layouts but fails to produce visually balanced results when subplots span multiple rows/columns in non-aligned ways. UltraLayout automatically detects non-orthogonal layouts, applies constraint satisfaction to compute optimal positions that respect spacing, ratios, and aesthetic balance (e.g., centering subplots between neighbors), and gracefully falls back to the standard grid layout if kiwisolver is not installed or for orthogonal arrangements. This enhancement is fully backward compatible, adds zero overhead for standard grid layouts, includes comprehensive test coverage in ultraplot/tests/test_ultralayout.py, and provides a foundation for more sophisticated layout constraints in the future.

Make subplot param probes backend-safe: GridSpec.get_subplot_params now returns a read-only snapshot of our margins/spaces and locally_modified_subplot_params returns False. This keeps Positron/other backends from erroring while preserving our restriction on mutating Matplotlib’s subplot params.

cvanelteren and others added 30 commits January 30, 2025 20:20
* add baseline comparison to workflow

* update ticker to prevent empty comparison

* corrected directory

* corrected 2nd part

* removed 2nd baseline

* removed 2nd baseline

* removed print

* added style

* add style drop on both versions

* Update .github/workflows/build-ultraplot.yml

Co-authored-by: Matthew R. Becker <[email protected]>

* should fail

* should fail attempt 2

* should fail attempt 3

* restoring after fail

* failing again to check if html is uploaded

* failing again to check if html is uploaded

* Update .github/workflows/build-ultraplot.yml

Co-authored-by: Matthew R. Becker <[email protected]>

* set to always execute

* add continue on error

* Update main.yml

* Update build-ultraplot.yml

* think it also needs other files

* removing failure and ready for merge

---------

Co-authored-by: Matthew R. Becker <[email protected]>
* update readthedocs env

* Update .readthedocs.yml

Co-authored-by: Matthew R. Becker <[email protected]>

* Update .readthedocs.yml

Co-authored-by: Matthew R. Becker <[email protected]>

---------

Co-authored-by: Matthew R. Becker <[email protected]>
* forcing draw to ensure UltraPlot is correctly visualized

* added comment and merging

---------

Co-authored-by: Matthew R. Becker <[email protected]>
…ver MPL versions (#51)

* test: adjust test matrix to use one locale and multiple matplotlib versions

* fix: cannot use mpl 3.10 yet due to basemap

* set version dynamically in matrix reading from pyproject.toml

* fix typo

* fix typo

* another attempt

* jq should work

* attempt fix with jq version

* prod: parse mpl dep for versions

---------

Co-authored-by: cvanelteren <[email protected]>
* make dep and release tags to push

* add or

* Update .github/workflows/publish-pypi.yml

* Update .github/workflows/publish-pypi.yml

* add success to build

* Update .github/workflows/build-ultraplot.yml

---------

Co-authored-by: Matthew R. Becker <[email protected]>
* fix: correct chain of logic for publish workflow

* Update publish-pypi.yml

* Add verbose flag to PyPI publish and update build commands
* fix: get pypi publish working

* prod: run packaging build on PRs to check that it works

* fix: try to get git config correct

* fix: get prod too

* fix: ignore race conditions

* fix: ignore race conditions
---------

Co-authored-by: Matthew R. Becker <[email protected]>
* fix: ensure pypi readme works ok

* test: publish to test pypi once to ensure it is working

* test: turn off local versions

* test: hack it in once

* fix: remove hacks for testing
* feat: deduplicate pypi publish workflow

* see what is there

* fix: download to path

* fix: need test then prod

* fix: remove testing items

* style: remove extra newline

* style: ensure consistent caps

* prod: cancel in progress jobs for ci
updates:
- [github.com/psf/black-pre-commit-mirror: 24.8.0 → 25.1.0](psf/black-pre-commit-mirror@24.8.0...25.1.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* use norm explicitly

* remove debug statement

* add second test

* edge case when norm is string

* removed additional space

* make test into img compare

* updated warning message

* remove debug statement
* use seed for reproducibility

* use seed for reproducibility
- pass colormaps as dictionary to demo functions
* allows cycle to be a tuple

* allow iterable

* add colormap tests

* added high level unittest

* added low level tests for cycle and colormap

* added com. function for cycler object

* remove erroneous logic when plotting singular data and a new cycler is used

* black formatting

* remove print from test

* removed spurious input

* replace logic with numpy

* updated singular comment

* remove type hinting

* correct value error

* rm another print statement

* rm comment

* reorder cases

* styling the comments
* fix and slightly refactor

* black formatting

* added unittest

* fix typo

* add nans
Fixes an issue where autoapi and autodoc would interfere. Links to the docs were not shown properly.
* explicitly override minor locator if given

* removed print statement

* added comment

* black formatting

* added comments to unittest

* add return
* filter out property if not set

* add tests for empty

* reshuffle the tests

* add explicit cycle test

* Add Python build commands and new color cycle test

---------

Co-authored-by: Matthew R. Becker <[email protected]>
* removes error in geoaxes

* install different package

* add font-cache refresh
* glyph not available in text gyro; setting fallback font
pre-commit-ci bot and others added 7 commits January 6, 2026 06:37
updates:
- [github.com/psf/black-pre-commit-mirror: 25.11.0 → 25.12.0](psf/black-pre-commit-mirror@25.11.0...25.12.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* Shrink title to avoid abc overlap

* Skip title auto-scaling when fontsize is set

* Add tests for abc/title auto-scaling

* Fix title overlap tests and zero-size axes draw

* Shrink titles when abc overlaps across locations

* update tests

* re-add tests

* Clarify padding variable names in _update_title_position

Renamed local variables to better reflect their purpose:
- abcpad -> abc_title_sep_pts (abc-title separation in points)
- pad -> abc_title_sep (abc-title separation in axes coords)
- abc_pad -> abc_offset (user's horizontal offset in axes coords)

Added comprehensive inline comments explaining:
- The difference between abc-title separation (spacing when co-located)
  and abc offset (user's horizontal shift via abcpad parameter)
- Unit conversions from points to axes coordinates
- Source and purpose of each variable

Updated documentation:
- Enhanced abcpad parameter docstring to clarify it's a horizontal offset
- Added inline comments to instance variables at initialization

This addresses co-author feedback requesting clarification of the
relationship between abcpad, self._abc_pad, pad, and abc_pad variables.

No API changes - all modifications are internal refactoring only.
@cvanelteren
Copy link
Collaborator Author

cvanelteren commented Jan 11, 2026

This PR is turning into a beast. It replaces one of the fundamentals of UltraPlot: its layout mechanism. It improves the layout by moving towards a constraint based approach (using kiwisolver). In the PR we separate gridspec from the layout to focus content on managing the layout (Gridspec) and drawing and aligning the plot (UltraLayout). While we get a small performance boost (+- 3-5%) the major improvement is behind the scenes and the user facing API is not affected. In addition, we allow for probe functions to pass through solving an issue with the IDE Positron (#270).

To aid in the review, I constructed the following checklist. I am aiming for a 2.0 release giving us some time to review and or iron out some kinks before merging. I am not expecting the 2.0 to be there for a while (couple of months) as we slowly progress and clean existing PRs with higher priority. Say we aim for the latest being May 2026.

The visual tests look good (locally) even though they fail on size, visually they look good

PR Review Checklist (novo-layout)

  • Layout semantics

    • Panels stack correctly on shared sides; panel widths/heights respect main grid spacing.
    • Ref sizing/aspect: refwidth/refheight targets preserved, sizes snapped to pixel grid, zero-tolerance resizes when refs are explicit.
    • Auto-layout does not re-run tight/aspect after final resize; whitespace looks stable.
  • UltraLayout

    • New ultralayout.py solver API is clear; enabled by default when kiwi is available.
    • tests/test_ultralayout.py covers core scenarios; solver on/off behavior is sane.
  • Robustness fixes

  • Tests/baselines

    • Imshow baselines updated (test_inbounds_data, test_standardized_input, test_colorbar) reflect square layout.
    • Key suites pass: pytest ultraplot/tests/test_imshow.py --mpl, pytest ultraplot/tests/test_ultralayout.py.
  • Behavior spot-checks

    • Manual plot with panels + imshow/pcolor shows correct spacing and square images.
    • Interactive backend draw doesn’t raise and feels at least as responsive as main.

@cvanelteren
Copy link
Collaborator Author

Some examples
image
image

@cvanelteren cvanelteren marked this pull request as ready for review January 11, 2026 02:01
@cvanelteren cvanelteren self-assigned this Jan 11, 2026

This comment was marked as resolved.

This comment was marked as resolved.

@cvanelteren
Copy link
Collaborator Author

Closing in favor of PR from ultralayout-clean (clean history).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Colorbar not aligning with custom layout

7 participants