diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 00dc6dff5..65225f495 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,122 @@ Fragment files in ``upcoming_changes/`` are assembled into this file by .. towncrier release notes start +0.11.0 (2026-10-23) +=================== + +API and Behaviour Changes +------------------------- + +- Changed 3-D panels created with ``elevation=0`` to render at 0 degrees; they were previously drawn as if the elevation were 30 degrees. (`#80 `_) +- :meth:`Figure.get_axes ` now lists every grid + axes the figure created, including ones with no plot attached yet, as + matplotlib does — so ``fig, ax = apl.subplots(1, 1); fig.get_axes()[0] is ax``. + Floating insets are still not listed. + + +New Features +------------ + +- Added :meth:`~anyplotlib.Plot3D.set_rotation` and :meth:`~anyplotlib.Plot3D.set_drag_mode` to turn 3-D data to any orientation independently of the camera, by code or by dragging, with the result readable from :attr:`~anyplotlib.Plot3D.rotation` and ``event.rotation``. (`#80 `_) +- Added :meth:`~anyplotlib.Plot3D.add_patch` to draw filled regions and paths on 3-D panels, with edges along great circles, the far side dimmed, and a choice of turning with the data or staying fixed while it rotates. (`#81 `_) +- Added :attr:`~anyplotlib.Plot2D.transform` (an :class:`~anyplotlib.ImageTransform`), + :meth:`~anyplotlib.Plot2D.data_to_pixel`, :meth:`~anyplotlib.Plot2D.pixel_to_data` + and read-only :attr:`~anyplotlib.Plot2D.x_axis` / :attr:`~anyplotlib.Plot2D.y_axis` + for converting between calibrated data units and the image-pixel coordinates + that 2-D widgets and markers use, including offset, non-unit, descending and + non-uniform axes. +- Added :meth:`Axes.set_xlabel `, + :meth:`~anyplotlib.Axes.set_ylabel` and :meth:`~anyplotlib.Axes.set_title`, + which work before a plot is attached: the axes keeps the labels and applies + them to the plot that is attached first and to any plot that later replaces + it (a second ``imshow``/``plot``/… call on the same axes). +- Added :meth:`Figure.on_close `, the + :attr:`~anyplotlib.Figure.closed` and :attr:`~anyplotlib.Figure.displayed` + flags and an idempotent :meth:`Figure.display `; + :meth:`~anyplotlib.Figure.close` now also fires ``close`` on the figure's own + callbacks (before the panels'), and still hides the figure if a handler raises. +- Added ``coords="data"`` to every :class:`~anyplotlib.Plot2D` ``add_*_widget`` + method (and :meth:`~anyplotlib.Plot2D.add_widget`): the widget then takes and + reports its geometry — attribute reads, :meth:`~anyplotlib.Widget.get`, + :meth:`~anyplotlib.Widget.to_dict`, :meth:`~anyplotlib.Widget.set` and so the + values seen in drag callbacks — in the panel's calibrated axis units instead + of image pixels. See :attr:`~anyplotlib.Widget.coords` and + :meth:`~anyplotlib.Widget.set_coords`; 1-D and bar widget methods accept + ``coords="data"`` too. + A data-coordinate rectangle spans ``[x, x + w] × [y, y + h]`` in data, with + ``(x, y)`` its corner of smallest data x and y and positive ``w``, ``h``, so it + covers the right pixels with ``origin="lower"`` or a descending axis. +- Added ``coords="data"`` to the :class:`~anyplotlib.Plot2D` marker methods and + :meth:`MarkerRegistry.add `: positions + and data-sized lengths are then given in the panel's calibrated axis units + and converted to image pixels on every render, so the markers follow + :meth:`~anyplotlib.Plot2D.set_extent`. See + :attr:`MarkerGroup.coords `. +- Added ``extent=(left, right, bottom, top)`` to :meth:`Axes.imshow + ` and :meth:`Plot2D.set_extent_edges + `, which calibrate an image from its + outer edges the way matplotlib's ``imshow(extent=...)`` does. +- Added a public ``notify`` keyword to :meth:`~anyplotlib.Widget.set` + (``widget.set(x=..., notify=False)``) to move a widget from Python without + firing its ``pointer_move`` handlers; ``_notify`` remains as an alias. +- Added read-only :attr:`Axes.figure `, + :attr:`~anyplotlib.Axes.primary_plot`, :attr:`~anyplotlib.Axes.plots`, + :attr:`~anyplotlib.Axes.image_plot` and :attr:`~anyplotlib.Axes.has_plot` so + code holding an axes can reach its figure and plot without private attributes. +- Added read-only :attr:`MarkerGroup.marker_type + ` and + :attr:`~anyplotlib.markers.MarkerGroup.name`, and + :meth:`MarkerGroup.get ` for reading a + group's properties back. +- Added read-only :attr:`~anyplotlib.Widget.plot` (the owning plot, ``None`` + once removed) and :attr:`~anyplotlib.Widget.kind` (``"rectangle"``, + ``"vline"``, …) so code holding only a widget handle can find its plot and + type without private attributes. +- Added rotation, anchor alignment and ``$...$`` TeX typesetting to ``texts`` + markers (wire fields ``rotation`` in radians, ``halign``, ``valign``): + labels anchor at their offset point, rotate counter-clockwise like + matplotlib's, and math markup renders through the existing axis-label TeX + engine instead of showing raw dollars. +- Marker kwargs now accept a length-1 sequence wherever a scalar is accepted + (``radius=[5]``, ``linewidths=(1.5,)``, ``edgecolors=["#f00"]``), broadcasting + it across the group as matplotlib's property cycling does. + + +Bug Fixes +--------- + +- :meth:`Figure.close ` now also closes the + underlying ipywidgets comm (removing the figure's front-end views) and drops + it from ipywidgets' instance registry, so a closed figure that is no longer + referenced — and its plot data — can be garbage collected. Previously every + figure stayed alive for the life of the process. +- :meth:`Figure.close ` now runs the figure-level and + each panel's ``close`` handlers independently: a handler that raises no + longer skips the remaining ones. The figure is still marked closed and + hidden, and the first exception is re-raised once all handlers have run. +- A widget's ``repr`` now shows its geometry in the widget's own + :attr:`~anyplotlib.Widget.coords` frame (and says ``coords='data'`` for a + data-coordinate widget on a 2-D panel) instead of the image pixels stored for + the renderer. +- Fixed :meth:`~anyplotlib.callbacks._EventMixin.add_event_handler` raising + ``AttributeError`` for bound methods, and made ``remove_handler(obj.method)`` + find a handler registered as ``obj.method``. +- Fixed empty marker groups (``offsets=np.zeros((0, 2))``) raising + ``ValueError: offsets must be shape (N, 2)`` when created or updated with + ``coords="data"``; an empty ``offsets=[]`` is now accepted in either frame. + + +Documentation +------------- + +- Added a *Fonts and Labels* gallery example covering text-marker size, + weight, outline, rotation, alignment and ``$...$`` math, alongside the + panel's own title and axis labels. +- Documented that after :meth:`~anyplotlib.Plot2D.set_extent` a + ``coords="data"`` widget stays on the same pixels (its data values change) + while a ``coords="data"`` marker group keeps its data position. + + 0.10.1 (2026-09-17) =================== diff --git a/docs/_root/index.html b/docs/_root/index.html index 6faf8f7c9..d980cfcd5 100644 --- a/docs/_root/index.html +++ b/docs/_root/index.html @@ -4,12 +4,12 @@ anyplotlib – redirecting… - - + +

- Redirecting to v0.10.1 documentation… + Redirecting to v0.11.0 documentation…

diff --git a/docs/_root/switcher.json b/docs/_root/switcher.json index a55dde46c..fe80986ef 100644 --- a/docs/_root/switcher.json +++ b/docs/_root/switcher.json @@ -4,6 +4,11 @@ "version": "dev", "url": "https://cssfrancis.github.io/anyplotlib/dev/" }, + { + "name": "v0.11.0 (stable)", + "version": "v0.11.0", + "url": "https://cssfrancis.github.io/anyplotlib/v0.11.0/" + }, { "name": "v0.10.1 (stable)", "version": "v0.10.1", diff --git a/docs/conf.py b/docs/conf.py index b19d8e3fa..c2ac056e8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,7 @@ project = "anyplotlib" copyright = "2026, anyplotlib contributors" author = "anyplotlib contributors" -release = "0.10.1" +release = "0.11.0" # When built in CI the workflow sets DOCS_VERSION to the tag name (e.g. # "v0.1.0") or "dev". Fall back to "dev" for local builds. diff --git a/pyproject.toml b/pyproject.toml index d3e7a7e6d..85b811104 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ exclude = [ [project] name = "anyplotlib" -version = "0.10.1" +version = "0.11.0" description = "A plotting library using python, javascript and anywidget for performant in browser plotting." readme = "README.md" license = { text = "MIT" } diff --git a/upcoming_changes/+axes-deferred-labels.new_feature.rst b/upcoming_changes/+axes-deferred-labels.new_feature.rst deleted file mode 100644 index d24c232d9..000000000 --- a/upcoming_changes/+axes-deferred-labels.new_feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added :meth:`Axes.set_xlabel `, -:meth:`~anyplotlib.Axes.set_ylabel` and :meth:`~anyplotlib.Axes.set_title`, -which work before a plot is attached: the axes keeps the labels and applies -them to the plot that is attached first and to any plot that later replaces -it (a second ``imshow``/``plot``/… call on the same axes). diff --git a/upcoming_changes/+axes-identity.new_feature.rst b/upcoming_changes/+axes-identity.new_feature.rst deleted file mode 100644 index 872b878c6..000000000 --- a/upcoming_changes/+axes-identity.new_feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added read-only :attr:`Axes.figure `, -:attr:`~anyplotlib.Axes.primary_plot`, :attr:`~anyplotlib.Axes.plots`, -:attr:`~anyplotlib.Axes.image_plot` and :attr:`~anyplotlib.Axes.has_plot` so -code holding an axes can reach its figure and plot without private attributes. diff --git a/upcoming_changes/+bound-method-handlers.bugfix.rst b/upcoming_changes/+bound-method-handlers.bugfix.rst deleted file mode 100644 index 7ad09e890..000000000 --- a/upcoming_changes/+bound-method-handlers.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed :meth:`~anyplotlib.callbacks._EventMixin.add_event_handler` raising -``AttributeError`` for bound methods, and made ``remove_handler(obj.method)`` -find a handler registered as ``obj.method``. diff --git a/upcoming_changes/+figure-close-independent-handlers.bugfix.rst b/upcoming_changes/+figure-close-independent-handlers.bugfix.rst deleted file mode 100644 index b80d1e302..000000000 --- a/upcoming_changes/+figure-close-independent-handlers.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -:meth:`Figure.close ` now runs the figure-level and -each panel's ``close`` handlers independently: a handler that raises no -longer skips the remaining ones. The figure is still marked closed and -hidden, and the first exception is re-raised once all handlers have run. diff --git a/upcoming_changes/+figure-close-releases-widget.bugfix.rst b/upcoming_changes/+figure-close-releases-widget.bugfix.rst deleted file mode 100644 index 137a18d7c..000000000 --- a/upcoming_changes/+figure-close-releases-widget.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -:meth:`Figure.close ` now also closes the -underlying ipywidgets comm (removing the figure's front-end views) and drops -it from ipywidgets' instance registry, so a closed figure that is no longer -referenced — and its plot data — can be garbage collected. Previously every -figure stayed alive for the life of the process. diff --git a/upcoming_changes/+figure-get-axes-empty.api_change.rst b/upcoming_changes/+figure-get-axes-empty.api_change.rst deleted file mode 100644 index 01da72973..000000000 --- a/upcoming_changes/+figure-get-axes-empty.api_change.rst +++ /dev/null @@ -1,4 +0,0 @@ -:meth:`Figure.get_axes ` now lists every grid -axes the figure created, including ones with no plot attached yet, as -matplotlib does — so ``fig, ax = apl.subplots(1, 1); fig.get_axes()[0] is ax``. -Floating insets are still not listed. diff --git a/upcoming_changes/+figure-lifecycle.new_feature.rst b/upcoming_changes/+figure-lifecycle.new_feature.rst deleted file mode 100644 index 946bf89ac..000000000 --- a/upcoming_changes/+figure-lifecycle.new_feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added :meth:`Figure.on_close `, the -:attr:`~anyplotlib.Figure.closed` and :attr:`~anyplotlib.Figure.displayed` -flags and an idempotent :meth:`Figure.display `; -:meth:`~anyplotlib.Figure.close` now also fires ``close`` on the figure's own -callbacks (before the panels'), and still hides the figure if a handler raises. diff --git a/upcoming_changes/+fonts-labels-example.doc.rst b/upcoming_changes/+fonts-labels-example.doc.rst deleted file mode 100644 index 602cb0f6c..000000000 --- a/upcoming_changes/+fonts-labels-example.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added a *Fonts and Labels* gallery example covering text-marker size, -weight, outline, rotation, alignment and ``$...$`` math, alongside the -panel's own title and axis labels. diff --git a/upcoming_changes/+imshow-extent.new_feature.rst b/upcoming_changes/+imshow-extent.new_feature.rst deleted file mode 100644 index a4c5fb398..000000000 --- a/upcoming_changes/+imshow-extent.new_feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added ``extent=(left, right, bottom, top)`` to :meth:`Axes.imshow -` and :meth:`Plot2D.set_extent_edges -`, which calibrate an image from its -outer edges the way matplotlib's ``imshow(extent=...)`` does. diff --git a/upcoming_changes/+marker-data-coords.new_feature.rst b/upcoming_changes/+marker-data-coords.new_feature.rst deleted file mode 100644 index 18cebf980..000000000 --- a/upcoming_changes/+marker-data-coords.new_feature.rst +++ /dev/null @@ -1,6 +0,0 @@ -Added ``coords="data"`` to the :class:`~anyplotlib.Plot2D` marker methods and -:meth:`MarkerRegistry.add `: positions -and data-sized lengths are then given in the panel's calibrated axis units -and converted to image pixels on every render, so the markers follow -:meth:`~anyplotlib.Plot2D.set_extent`. See -:attr:`MarkerGroup.coords `. diff --git a/upcoming_changes/+marker-empty-data-coords.bugfix.rst b/upcoming_changes/+marker-empty-data-coords.bugfix.rst deleted file mode 100644 index 55bf34ecc..000000000 --- a/upcoming_changes/+marker-empty-data-coords.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed empty marker groups (``offsets=np.zeros((0, 2))``) raising -``ValueError: offsets must be shape (N, 2)`` when created or updated with -``coords="data"``; an empty ``offsets=[]`` is now accepted in either frame. diff --git a/upcoming_changes/+marker-length1-broadcast.new_feature.rst b/upcoming_changes/+marker-length1-broadcast.new_feature.rst deleted file mode 100644 index dae15325b..000000000 --- a/upcoming_changes/+marker-length1-broadcast.new_feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -Marker kwargs now accept a length-1 sequence wherever a scalar is accepted -(``radius=[5]``, ``linewidths=(1.5,)``, ``edgecolors=["#f00"]``), broadcasting -it across the group as matplotlib's property cycling does. diff --git a/upcoming_changes/+markergroup-accessors.new_feature.rst b/upcoming_changes/+markergroup-accessors.new_feature.rst deleted file mode 100644 index 8977b6c75..000000000 --- a/upcoming_changes/+markergroup-accessors.new_feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added read-only :attr:`MarkerGroup.marker_type -` and -:attr:`~anyplotlib.markers.MarkerGroup.name`, and -:meth:`MarkerGroup.get ` for reading a -group's properties back. diff --git a/upcoming_changes/+plot2d-transform.new_feature.rst b/upcoming_changes/+plot2d-transform.new_feature.rst deleted file mode 100644 index bcc940697..000000000 --- a/upcoming_changes/+plot2d-transform.new_feature.rst +++ /dev/null @@ -1,6 +0,0 @@ -Added :attr:`~anyplotlib.Plot2D.transform` (an :class:`~anyplotlib.ImageTransform`), -:meth:`~anyplotlib.Plot2D.data_to_pixel`, :meth:`~anyplotlib.Plot2D.pixel_to_data` -and read-only :attr:`~anyplotlib.Plot2D.x_axis` / :attr:`~anyplotlib.Plot2D.y_axis` -for converting between calibrated data units and the image-pixel coordinates -that 2-D widgets and markers use, including offset, non-unit, descending and -non-uniform axes. diff --git a/upcoming_changes/+texts-tex-rotation.new_feature.rst b/upcoming_changes/+texts-tex-rotation.new_feature.rst deleted file mode 100644 index 7fdfca539..000000000 --- a/upcoming_changes/+texts-tex-rotation.new_feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added rotation, anchor alignment and ``$...$`` TeX typesetting to ``texts`` -markers (wire fields ``rotation`` in radians, ``halign``, ``valign``): -labels anchor at their offset point, rotate counter-clockwise like -matplotlib's, and math markup renders through the existing axis-label TeX -engine instead of showing raw dollars. diff --git a/upcoming_changes/+widget-data-coords-recalibration.doc.rst b/upcoming_changes/+widget-data-coords-recalibration.doc.rst deleted file mode 100644 index 15099641b..000000000 --- a/upcoming_changes/+widget-data-coords-recalibration.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Documented that after :meth:`~anyplotlib.Plot2D.set_extent` a -``coords="data"`` widget stays on the same pixels (its data values change) -while a ``coords="data"`` marker group keeps its data position. diff --git a/upcoming_changes/+widget-data-coords.new_feature.rst b/upcoming_changes/+widget-data-coords.new_feature.rst deleted file mode 100644 index 24d67a6be..000000000 --- a/upcoming_changes/+widget-data-coords.new_feature.rst +++ /dev/null @@ -1,11 +0,0 @@ -Added ``coords="data"`` to every :class:`~anyplotlib.Plot2D` ``add_*_widget`` -method (and :meth:`~anyplotlib.Plot2D.add_widget`): the widget then takes and -reports its geometry — attribute reads, :meth:`~anyplotlib.Widget.get`, -:meth:`~anyplotlib.Widget.to_dict`, :meth:`~anyplotlib.Widget.set` and so the -values seen in drag callbacks — in the panel's calibrated axis units instead -of image pixels. See :attr:`~anyplotlib.Widget.coords` and -:meth:`~anyplotlib.Widget.set_coords`; 1-D and bar widget methods accept -``coords="data"`` too. -A data-coordinate rectangle spans ``[x, x + w] × [y, y + h]`` in data, with -``(x, y)`` its corner of smallest data x and y and positive ``w``, ``h``, so it -covers the right pixels with ``origin="lower"`` or a descending axis. diff --git a/upcoming_changes/+widget-identity.new_feature.rst b/upcoming_changes/+widget-identity.new_feature.rst deleted file mode 100644 index 3f2c8e8c8..000000000 --- a/upcoming_changes/+widget-identity.new_feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added read-only :attr:`~anyplotlib.Widget.plot` (the owning plot, ``None`` -once removed) and :attr:`~anyplotlib.Widget.kind` (``"rectangle"``, -``"vline"``, …) so code holding only a widget handle can find its plot and -type without private attributes. diff --git a/upcoming_changes/+widget-repr-frame.bugfix.rst b/upcoming_changes/+widget-repr-frame.bugfix.rst deleted file mode 100644 index 8b204e6af..000000000 --- a/upcoming_changes/+widget-repr-frame.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -A widget's ``repr`` now shows its geometry in the widget's own -:attr:`~anyplotlib.Widget.coords` frame (and says ``coords='data'`` for a -data-coordinate widget on a 2-D panel) instead of the image pixels stored for -the renderer. diff --git a/upcoming_changes/+widget-set-notify.new_feature.rst b/upcoming_changes/+widget-set-notify.new_feature.rst deleted file mode 100644 index 859009fae..000000000 --- a/upcoming_changes/+widget-set-notify.new_feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added a public ``notify`` keyword to :meth:`~anyplotlib.Widget.set` -(``widget.set(x=..., notify=False)``) to move a widget from Python without -firing its ``pointer_move`` handlers; ``_notify`` remains as an alias. diff --git a/upcoming_changes/80.api_change.rst b/upcoming_changes/80.api_change.rst deleted file mode 100644 index bf060fed6..000000000 --- a/upcoming_changes/80.api_change.rst +++ /dev/null @@ -1 +0,0 @@ -Changed 3-D panels created with ``elevation=0`` to render at 0 degrees; they were previously drawn as if the elevation were 30 degrees. diff --git a/upcoming_changes/80.new_feature.rst b/upcoming_changes/80.new_feature.rst deleted file mode 100644 index f1df1c12a..000000000 --- a/upcoming_changes/80.new_feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added :meth:`~anyplotlib.Plot3D.set_rotation` and :meth:`~anyplotlib.Plot3D.set_drag_mode` to turn 3-D data to any orientation independently of the camera, by code or by dragging, with the result readable from :attr:`~anyplotlib.Plot3D.rotation` and ``event.rotation``. diff --git a/upcoming_changes/81.new_feature.rst b/upcoming_changes/81.new_feature.rst deleted file mode 100644 index 6212e8105..000000000 --- a/upcoming_changes/81.new_feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added :meth:`~anyplotlib.Plot3D.add_patch` to draw filled regions and paths on 3-D panels, with edges along great circles, the far side dimmed, and a choice of turning with the data or staying fixed while it rotates.