Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cc88479
basic scaffold done
kushalkolar Sep 13, 2026
08af418
inheritance
kushalkolar Sep 13, 2026
9bf1c7c
done
kushalkolar Sep 14, 2026
364e8bf
config works!
kushalkolar Sep 14, 2026
8cbe3ee
config on graphics
kushalkolar Sep 14, 2026
0082501
axes config
kushalkolar Sep 14, 2026
bce7736
full config implementation basically works
kushalkolar Sep 14, 2026
593111e
fix
kushalkolar Sep 14, 2026
ad75df4
mixins call Graphic construtors with kwargs nothing is positional
kushalkolar Sep 14, 2026
e8e2f0e
print
kushalkolar Sep 14, 2026
97d6e47
config presets
kushalkolar Sep 14, 2026
5fb0ffd
comments, docstrings
kushalkolar Sep 14, 2026
26a5aab
docstrings
kushalkolar Sep 14, 2026
febb665
remove ConfigValue
kushalkolar Sep 15, 2026
62606a4
comments
kushalkolar Sep 15, 2026
a54c021
much better add graphics mixin using descriptors, examples, fix a test
kushalkolar Sep 15, 2026
575c028
anotehr example
kushalkolar Sep 15, 2026
3b92364
GlobalConfig.to_dict()
kushalkolar Sep 15, 2026
bc25682
docs
kushalkolar Sep 15, 2026
82ba3e1
reset to default config after each screenshot test
kushalkolar Sep 15, 2026
c16ee88
add_<graphics>() stub generator, fix maintain_aspect logic w.r.t. con…
kushalkolar Sep 15, 2026
09dfc8d
change so maintain_aspect can be tested better
kushalkolar Sep 15, 2026
7366725
docstring
kushalkolar Sep 15, 2026
23901a3
reset config after running each docs gallery examle
kushalkolar Sep 15, 2026
dcd63bf
better example
kushalkolar Sep 15, 2026
b8dd4b3
docs
kushalkolar Sep 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/source/api/layouts/subplot.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Properties
Subplot.directional_light
Subplot.docks
Subplot.frame
Subplot.frame_spacing
Subplot.graphics
Subplot.imgui_right_click
Subplot.imgui_windows
Expand All @@ -53,7 +54,6 @@ Methods
:toctree: Subplot_api

Subplot.add_animations
Subplot.add_collection
Subplot.add_graphic
Subplot.add_image
Subplot.add_image_collection
Expand Down
1 change: 1 addition & 0 deletions docs/source/api/ui/ImguiWindow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Properties
.. autosummary::
:toctree: ImguiWindow_api

ImguiWindow.collapsed
ImguiWindow.height
ImguiWindow.location
ImguiWindow.size
Expand Down
44 changes: 44 additions & 0 deletions docs/source/api/widgets/ImageWidget.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.. _api.ImageWidget:

ImageWidget
***********

===========
ImageWidget
===========
.. currentmodule:: fastplotlib

Constructor
~~~~~~~~~~~
.. autosummary::
:toctree: ImageWidget_api

ImageWidget

Properties
~~~~~~~~~~
.. autosummary::
:toctree: ImageWidget_api

ImageWidget.cmap
ImageWidget.current_index
ImageWidget.data
ImageWidget.figure
ImageWidget.frame_apply
ImageWidget.managed_graphics
ImageWidget.slider_dims
ImageWidget.window_funcs

Methods
~~~~~~~
.. autosummary::
:toctree: ImageWidget_api

ImageWidget.add_event_handler
ImageWidget.clear_event_handlers
ImageWidget.close
ImageWidget.remove_event_handler
ImageWidget.reset_vmin_vmax
ImageWidget.set_data
ImageWidget.show

1 change: 1 addition & 0 deletions docs/source/api/widgets/NDWidget.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Properties
NDWidget.indices
NDWidget.ndgraphics
NDWidget.ranges
NDWidget.ui_sliders

Methods
~~~~~~~
Expand Down
1 change: 1 addition & 0 deletions docs/source/api/widgets/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Widgets
:maxdepth: 1

NDWidget
ImageWidget
3 changes: 3 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"../../examples/image_volume",
"../../examples/heatmap",
# "../../examples/image_widget",
"../../examples/global_config",
"../../examples/gridplot",
"../../examples/window_layouts",
"../../examples/controllers",
Expand All @@ -83,6 +84,8 @@
"ignore_pattern": r"__init__\.py",
"nested_sections": False,
"thumbnail_size": (250, 250),
# run before each example, must be a string since a callable is not serializable
"reset_modules": ("gallery_reset.reset_fastplotlib_style",),
}

extra_conf = find_examples_for_gallery(EXAMPLES_DIR)
Expand Down
7 changes: 7 additions & 0 deletions docs/source/gallery_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import fastplotlib as fpl


def reset_fastplotlib_style(gallery_conf, fname):
"""run by sphinx-gallery before each example, see ``reset_modules`` in conf.py"""
# the config is global, restore the defaults that a previous example may have set
fpl.style.default()
98 changes: 98 additions & 0 deletions docs/source/user_guide/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -883,3 +883,101 @@ notebook.
Note that this only works if you are using jupyterlab or ipython locally, this cannot be used for remote rendering.
You can forward windows (ex: X11 forwarding) but this is much slower than the remote rendering described in the
previous section.

Global configuration
--------------------

You can configure global defaults for various components such as ``Figure``, ``Subplot``, ``Axes``
and the graphics. Defaults are set on the class under ``config``, grouped by the method that takes
the argument, where ``init`` is the constructor::

import fastplotlib as fpl

fpl.LineGraphic.config.init.colors = "magenta"
fpl.LineGraphic.config.init.thickness = 5.0
fpl.ImageGraphic.config.init.cmap = "gray"
fpl.Axes.config.init.grids = False
fpl.Figure.config.init.size = (900, 700)
fpl.Figure.config.show.axes_visible = False
fpl.layouts.Subplot.config.init.toolbar = False
fpl.layouts.Subplot.config.auto_scale.zoom = 0.9

Configurable components:

+----------------------------------------------------+--------------------------+
| component | configurable methods |
+====================================================+==========================+
| ``fastplotlib.Figure`` | ``init``, ``show`` |
+----------------------------------------------------+--------------------------+
| ``fastplotlib.layouts.Subplot`` | ``init``, ``auto_scale`` |
+----------------------------------------------------+--------------------------+
| ``fastplotlib.Axes`` | ``init`` |
+----------------------------------------------------+--------------------------+
| every ``Graphic``, ex. ``fastplotlib.LineGraphic`` | ``init`` |
+----------------------------------------------------+--------------------------+

Print every configurable class with all of its options and their current values::

fpl.global_config.print_config()

Get the same thing as a dict of ``{class: {method: {option: value}}}``::

import copy

config = fpl.global_config.to_dict()

config[fpl.LineGraphic]["init"]["colors"] # "magenta"

# deepcopy for a snapshot since some config options are mutable, ex: dicts
snapshot = copy.deepcopy(fpl.global_config.to_dict())

A config value is only used if an argument value is not explicitly provided::

import numpy as np

ys = np.sin(np.linspace(0, 2 * np.pi, 100))

fig = fpl.Figure()

line = fig[0, 0].add_line(ys) # magenta, from the config
other = fig[0, 0].add_line(ys, colors="w") # white

Config values are read when an object is created, so setting one affects everything created after it
and nothing that already exists.

Options are set on the class, not on an instance::

fpl.LineGraphic.config.init.colors = "magenta" # this is how you set it
line.config.init.colors = "magenta" # raises AttributeError

Setting an option that does not exist raises an ``AttributeError`` that lists the valid options.

Graphic collections have no config of their own. The graphics in a collection are created from the
config of the graphic it holds, so ``LineGraphic.config.init.colors`` is also the color of the
lines in a ``LineCollection``.

Options that are dicts
^^^^^^^^^^^^^^^^^^^^^^

Some options are themselves kwargs, such as ``Subplot.config.init.frame_kwargs`` and
``Axes.config.init.grid_kwargs``. Assigning to one of these replaces the whole dict.
``fastplotlib.global_config.update()`` merges dicts instead, recursing into nested dicts::

fpl.global_config.update(
fpl.layouts.Subplot.config.init,
# changes the title font size, but keeps the current title face_color config
frame_kwargs={"title_kwargs": {"font_size": 10}},
)

Styles
^^^^^^

``fastplotlib.style`` holds preset styles, and styles can be merged with subsequent calls::

fpl.style.light()
fpl.style.compact()

Available styles are:

.. autoclass:: fastplotlib.style
:members:
2 changes: 2 additions & 0 deletions examples/global_config/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Global Config
=============
35 changes: 35 additions & 0 deletions examples/global_config/config_axes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
Axes Config
===========

Configuration values are used for any argument that is not explicitly passed.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'screenshot'

import numpy as np
import fastplotlib as fpl

# these can also be set simultaneously:
# fpl.global_config.update(fpl.Axes.config.init, color="red", tick_size=16, line_width=4)
fpl.Axes.config.init.color = "red"
fpl.Axes.config.init.tick_size = 16
fpl.Axes.config.init.line_width = 4

xs = np.linspace(-10, 10, 100)
ys = np.sin(xs)
data = np.column_stack([xs, ys])

figure = fpl.Figure(size=(700, 560))

figure[0, 0].add_line(data)

figure.show()


# NOTE: fpl.loop.run() should not be used for interactive sessions
# See the "JupyterLab and IPython" section in the user guide
if __name__ == "__main__":
print(__doc__)
fpl.loop.run()
38 changes: 38 additions & 0 deletions examples/global_config/config_figure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
Figure Config
=============

Configuration values are used for any argument that is not explicitly passed.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'screenshot'

import numpy as np
import fastplotlib as fpl

# a tall figure to fit a stack of lines
fpl.Figure.config.init.size = (700, 1000)

# used by Figure.show()
fpl.Figure.config.show.axes_visible = False
fpl.layouts.Subplot.config.auto_scale.maintain_aspect = False

xs = np.linspace(0, 4 * np.pi, 100)
ys = np.sin(xs)
data = np.column_stack([xs, ys])

# 10 sine waves to stack
stack_data = np.stack([data] * 5)

figure = fpl.Figure()

figure[0, 0].add_line_stack(stack_data)

figure.show()

# NOTE: fpl.loop.run() should not be used for interactive sessions
# See the "JupyterLab and IPython" section in the user guide
if __name__ == "__main__":
print(__doc__)
fpl.loop.run()
62 changes: 62 additions & 0 deletions examples/global_config/config_graphics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""
Graphics Config
===============

Configuration values are used for any argument that is not explicitly passed.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'screenshot'

import imageio.v3 as iio
import numpy as np
import fastplotlib as fpl

fpl.LineGraphic.config.init.colors = "magenta"
fpl.LineGraphic.config.init.thickness = 4

fpl.ScatterGraphic.config.init.markers = "^"
fpl.ScatterGraphic.config.init.sizes = 20
fpl.ScatterGraphic.config.init.colors = "r"

fpl.VectorsGraphic.config.init.color = "cyan"

fpl.ImageGraphic.config.init.cmap = "viridis"

xs = np.linspace(0, 4 * np.pi, 100)
ys = np.sin(xs)
line_data = np.column_stack([xs, ys])
cosine_data = np.column_stack([xs, np.cos(xs)])

# 5 sine waves to stack
stack_data = np.stack([line_data] * 5)

# uniform x, y positions for the vectors and their directions
x, y = np.meshgrid(np.arange(0, 2 * np.pi, 0.4), np.arange(0, 2 * np.pi, 0.4))
positions = np.column_stack([x.ravel(), y.ravel()])
directions = np.column_stack([np.cos(x).ravel(), np.sin(y).ravel()])

image_data = iio.imread("imageio:camera.png")

figure = fpl.Figure(shape=(2, 2), size=(700, 800))

figure[0, 0].add_line(cosine_data, offset=(0, -3, 0))

# any explicitly provided arg , e.g.`colors`, overrides the config value
figure[0, 0].add_scatter(line_data[::5], colors="green")

# a stack creates lines, so they use the LineGraphic config too
figure[0, 1].add_line_stack(stack_data)

figure[1, 0].add_vectors(positions=positions, directions=directions)

figure[1, 1].add_image(image_data)

figure.show()


# NOTE: fpl.loop.run() should not be used for interactive sessions
# See the "JupyterLab and IPython" section in the user guide
if __name__ == "__main__":
print(__doc__)
fpl.loop.run()
39 changes: 39 additions & 0 deletions examples/global_config/config_style1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
Light and Compact Style
=======================

A style is a preset of configuration values.
Once called, it effects all subsequent Figures/graphic objects that the style sets.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'screenshot'

import numpy as np
import fastplotlib as fpl

# white background, black axes, dark graphic colors
fpl.style.light()

# no subplot toolbar, thin subplot frame
# this configuration is merged with the existing light preset from above
fpl.style.compact()

xs = np.linspace(-10, 10, 100)
ys = np.sin(xs)
data = np.column_stack([xs, ys])

figure = fpl.Figure(shape=(2, 1), size=(700, 560))

# the colors of the line and the scatter come from the style
figure[0, 0].add_line(data)
figure[1, 0].add_scatter(data)

figure.show()


# NOTE: fpl.loop.run() should not be used for interactive sessions
# See the "JupyterLab and IPython" section in the user guide
if __name__ == "__main__":
print(__doc__)
fpl.loop.run()
Loading