Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

@ksunden
Copy link
Member

@ksunden ksunden commented Dec 16, 2025

As this is intended for the Matplotlib 3.12 cycle, this will remain in draft until at least
we have branched off 3.11.x. There is a list of TODOs at the bottom, many of which I would
prefer to address before leaving draft anyway, but I may also decide some would be better as
unique follow-ons. In particular there are known test failures that do need addressing.

PR summary

Overview

This is part one of integrating the data prototype work into the main library.
The primary focus is on the actual Containers, rather than the other portion of the data prototype work, which is the transformation pipeline.
These two pieces are not entirely separable, as containers which do calculations do still use a light version of the latter, but custom edges are not yet exposed to users here.

Developer perspective

  • This is primarily targeted at unifying the model of internal state, while also allowing that model to be extended
    • As such, many of the changes involve removing private state, and condensing into the container
    • Some computation is also put into the container, particularly where draw time parameters are derived from other user supplied parameters

User perspective

  • Intention is to be as backwards compatible as possible
    • Some slight tweaks around caching logic, in particular, which I imagine could change some things (but have not actually proven they do)
  • Opt-in to using custom containers:
    • set_container method added to the affected artist classes
    • Containers are duck-typed, implementing describe and query
    • Some reference/generic containers are avialable via mpl_data_containers
    • For simple things, such as lines and images, usually only requires supply x/y(/image) data
      • For more complex things such as collections, an understanding of the default containers is needed

Some example code

>>> from mpl_data_containers.containers import FuncContainer
>>> fc = FuncContainer({"x": (("N",), lambda x: x), "y": (("N",), lambda x: np.sin(1 / x))})
>>> line = mpl.lines.Line2D([],[])
>>> line.set_container(fc)
>>> ax = plt.gca()
>>> ax.add_line(line)
<matplotlib.lines.Line2D object at 0x70b989d59550>
>>> # These two lines help somewhat with triggering redraws, but not yet where I want it
>>> plt.ion()
>>> line.recache(True) 
>>> plt.show()
"""
===================================
(Infinitly) Zoomable Mandelbrot Set
===================================

A mandelbrot set which is computed using a :class:`.containers.FuncContainer`
and represented using a :class:`wrappers.ImageWrapper`.

The mandelbrot recomputes as it is zoomed in and/or panned.

"""

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

from mpl_data_containers.containers import FuncContainer

from matplotlib.colors import Normalize

maxiter = 75


def mandelbrot_set(X, Y, maxiter, *, horizon=3, power=2):
    C = X + Y[:, None] * 1j
    N = np.zeros_like(C, dtype=int)
    Z = np.zeros_like(C)
    for n in range(maxiter):
        mask = abs(Z) < horizon
        N += mask
        Z[mask] = Z[mask] ** power + C[mask]
    N[N == maxiter] = -1
    return Z, N


fc = FuncContainer(
    {},
    xyfuncs={
        "x": ((2,), lambda x, y: [x[0], x[-1]]),
        "y": ((2,), lambda x, y: [y[0], y[-1]]),
        "image": (("N", "M"), lambda x, y: mandelbrot_set(x, y, maxiter)[1]),
    },
)
cmap = plt.get_cmap()
cmap.set_under("w")

fig, ax = plt.subplots()

im = mpl.image.AxesImage(ax)
im.set_container(fc)

ax.add_artist(im)
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)

ax.set_aspect("equal")  # No equivalent yet

plt.ion()
plt.show()

Remaining TODOs:

  • Proper docs (Wrote up a fair bit of this for this PR, but not formatted for the web docs/would like to be more complete)
    • Dev oriented
    • User oriented
  • Fix known bugs/test failures
    • 3D using removed internal state
    • Subtle NaN behavior
    • Line2D some caching logic seems not 100% right (it's mostly there)
  • Add tests
  • Extend to further classes
    • In particular Text (have partial implementation, but removed because I was unhappy with it in its current state)

@story645
Copy link
Member

story645 commented Dec 16, 2025

At this stage of draft, what in particular do you need feedback on? And can you provide a sketch/diagram of where/how this plays w/ the drawing stack?

Also can this PR be broken up into the ArrayContainer and then the specialized containers separately?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.