Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
9a01cd5
start ndprocessors
kushalkolar Dec 25, 2025
c46455f
basic timeseries
kushalkolar Dec 27, 2025
d93fa5d
add __init__
kushalkolar Dec 27, 2025
fddefb8
heatmap for timeseries works!
kushalkolar Dec 28, 2025
d5e4c7d
NDPositions, basics work, reorganize, increase default scatter size
kushalkolar Dec 29, 2025
074669b
black
kushalkolar Jan 26, 2026
ff5c578
NDPositions working with multi-dim stack of lines, need to test windo…
kushalkolar Jan 30, 2026
3f412c5
scatter collection
kushalkolar Jan 30, 2026
dc30151
progress, need to change to other branch so committing
kushalkolar Jan 30, 2026
2b3c9b6
Merge branch 'main' into ndwidget
kushalkolar Jan 30, 2026
db98bde
better
kushalkolar Jan 30, 2026
3629f70
interpolation for heatmap
kushalkolar Jan 31, 2026
87ea418
better place for check
kushalkolar Jan 31, 2026
e5a8d40
window functions working on n_datapoints dim
kushalkolar Feb 1, 2026
8d050a7
p dim window funcs working for single and multiple dims I think
kushalkolar Feb 1, 2026
3731997
black
kushalkolar Feb 1, 2026
7d4e420
index_mappings is working I think, lightly tested on p dim
kushalkolar Feb 2, 2026
6cdcb17
remove nd_timeseries since nd_positions is sufficient
kushalkolar Feb 2, 2026
e5afb2a
Merge branch 'main' into ndwidget
kushalkolar Feb 4, 2026
4748e59
auto-replace buffers (#974)
kushalkolar Feb 4, 2026
aefe418
some basic OOC working
kushalkolar Feb 4, 2026
b6d6e62
max num of dipslay datapoints
kushalkolar Feb 6, 2026
976459b
scatter stack, not tested
kushalkolar Feb 11, 2026
a9bfa44
progress
kushalkolar Feb 11, 2026
1a26e76
Merge branch 'ndwidget' of https://github.com/fastplotlib/fastplotlib…
kushalkolar Feb 11, 2026
596b8e7
scatter collection updates
kushalkolar Feb 14, 2026
db2431f
tootip handlers for ndpositions
kushalkolar Feb 14, 2026
57d9a6b
refactoring, general NDPP_Pandas processor for any dataframe data
kushalkolar Feb 14, 2026
9efd69c
Merge branch 'main' into ndwidget
kushalkolar Feb 14, 2026
47ec02a
separate array logic and graphic logic in `ImageWidget` (#868)
kushalkolar Feb 16, 2026
777a1d5
update
kushalkolar Feb 16, 2026
1355733
basic minimal ndw orchestration working
kushalkolar Feb 17, 2026
78878b1
implement auto-x for timeseries
kushalkolar Feb 17, 2026
3ad64fa
bugfix update worldobject -> graphic map for image tiles
kushalkolar Feb 18, 2026
75361c0
bugfix linear selector set limits
kushalkolar Feb 18, 2026
38481c0
linear selector for timeseries
kushalkolar Feb 18, 2026
5e67318
return full data if display_window is Noen
kushalkolar Feb 18, 2026
65616b9
stupid merge conflicts
kushalkolar Feb 18, 2026
9d7328a
arrow key to step indices
kushalkolar Feb 19, 2026
05a38ec
imgui separator
kushalkolar Feb 23, 2026
0433058
fix and ui stuff
kushalkolar Feb 23, 2026
f6322ee
both auto x range modes working
kushalkolar Feb 23, 2026
a71c931
progress
kushalkolar Feb 23, 2026
a2529cc
moving stuff
kushalkolar Feb 24, 2026
d53cb8f
much much better organization of things
kushalkolar Feb 24, 2026
fb42ae0
GlobalIndexVector working with ndpostions and ndimage
kushalkolar Feb 24, 2026
fabb65a
examples
kushalkolar Feb 24, 2026
1642978
progress
kushalkolar Feb 25, 2026
8df9fb3
do not reset vmin vmax when replacing Image buffer
kushalkolar Feb 26, 2026
7e83262
WIP migrate to xarray
kushalkolar Feb 28, 2026
117cb4f
Merge branch 'ndwidget' of https://github.com/fastplotlib/fastplotlib…
kushalkolar Feb 28, 2026
b220f94
window funcs in NDProcessor class using xarray, WIP, not tested
kushalkolar Feb 28, 2026
6f09b5d
typo
kushalkolar Feb 28, 2026
be437fa
basic single index slicing working with xarray
kushalkolar Mar 2, 2026
404bb7b
window funcs working for NDPositions and NDPP_Pands
kushalkolar Mar 3, 2026
42eb3f9
display_window window funcs working for NDPositions
kushalkolar Mar 3, 2026
c251a6d
imgui stuff
kushalkolar Mar 3, 2026
4ba9807
finish migrate NDImage to xarray, basics work
kushalkolar Mar 3, 2026
4f005ed
NDImage working mostly, behavior viz is back
kushalkolar Mar 3, 2026
597c48b
better flipping logic
kushalkolar Mar 3, 2026
68571b7
update examples
kushalkolar Mar 3, 2026
cad17c8
more progress
kushalkolar Mar 4, 2026
4c902ba
update example
kushalkolar Mar 4, 2026
1248e8e
histogram working for images
kushalkolar Mar 4, 2026
2ca3fbf
NDProcessor property aliases
kushalkolar Mar 4, 2026
782951f
more aliasing
kushalkolar Mar 4, 2026
5c6c360
fix
kushalkolar Mar 4, 2026
ca44b94
update example
kushalkolar Mar 4, 2026
2f68007
fix
kushalkolar Mar 4, 2026
7f2bcad
ui
kushalkolar Mar 4, 2026
c79c283
cleanup old iw-array, imports, add deprecation warning on old iw
kushalkolar Mar 4, 2026
611f897
add ndwidget section to deps with xarray
kushalkolar Mar 4, 2026
05907ed
nice repr for NDProcessor
kushalkolar Mar 5, 2026
61b20f7
Merge branch 'main' into ndwidget
kushalkolar Mar 5, 2026
04718f8
imgui right click menu for ndgraphics
kushalkolar Mar 5, 2026
0f03bd2
better
kushalkolar Mar 5, 2026
057308d
controller options separate window
kushalkolar Mar 5, 2026
0335af7
update imgui
kushalkolar Mar 5, 2026
5ee11ec
fix
kushalkolar Mar 6, 2026
eb91846
fix compute histogram
kushalkolar Mar 8, 2026
64d6150
other features WIP
kushalkolar Mar 14, 2026
a1e2995
Merge branch 'ndwidget' of https://github.com/fastplotlib/fastplotlib…
kushalkolar Mar 14, 2026
8b8626d
basics of other features works with ScatterStack for colors, markers,…
kushalkolar Mar 15, 2026
6727f45
require min pygfx v0.16.0 due to gc hash fix necessary for NDWidget
kushalkolar Mar 15, 2026
f8b1ea4
fix PlotArea.y_range
kushalkolar Mar 15, 2026
9374820
fix to create isolated buffer for colors when buffer replaced
kushalkolar Mar 15, 2026
ef7c29c
np.empty
kushalkolar Mar 15, 2026
c591d5c
cmap_transform_each WIP
kushalkolar Mar 15, 2026
7f5e5e5
progress
kushalkolar Mar 15, 2026
62ed939
fix
kushalkolar Mar 15, 2026
148c6c3
replace graphic when data changed, tweak index_mappings
kushalkolar Mar 17, 2026
62de35c
Merge branch 'ndwidget' of https://github.com/fastplotlib/fastplotlib…
kushalkolar Mar 17, 2026
75bcd3a
Merge branch 'main' into ndwidget
kushalkolar Mar 17, 2026
db49219
Update installation docs (#1013)
kushalkolar Mar 17, 2026
d00eb01
Merge branch 'main' into ndwidget
kushalkolar Mar 17, 2026
f6f8141
cmap lib handles image colormaps now
kushalkolar Mar 17, 2026
c2dff86
multi-windows ndwidget, maintain features like cmap when switching gr…
kushalkolar Mar 17, 2026
8e30d23
Merge branch 'ndwidget' of https://github.com/fastplotlib/fastplotlib…
kushalkolar Mar 17, 2026
0b603e9
progress
kushalkolar Mar 18, 2026
7e862ee
lighting objects only when a mesh is added
kushalkolar Mar 18, 2026
4a66438
fix
kushalkolar Mar 18, 2026
06d5266
update axes only when camera or view changes
kushalkolar Mar 18, 2026
066094a
clean heatmap func
kushalkolar Mar 18, 2026
d1d1f6c
stupid print
kushalkolar Mar 18, 2026
9372ec6
docstrings, comments
kushalkolar Mar 19, 2026
c354c67
remove unused attr, comments
kushalkolar Mar 19, 2026
4e8b8f5
remove print
kushalkolar Mar 19, 2026
0b1bc0b
add NDGraphic.pause, expose histogram widget
kushalkolar Mar 20, 2026
3e755f6
ndg pause in imgui
kushalkolar Mar 20, 2026
894de55
add helper function to convert heatmap timeseries to postional data s…
kushalkolar Mar 20, 2026
ef28878
index wans't calling handlers
kushalkolar Mar 21, 2026
7351507
Merge branch 'ndwidget' of https://github.com/fastplotlib/fastplotlib…
kushalkolar Mar 23, 2026
7778403
remove
kushalkolar Mar 23, 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 .github/workflows/docs-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: build docs
run: |
cd docs
RTD_BUILD=1 make html SPHINXOPTS="-W --keep-going"
DOCS_BUILD=1 make html SPHINXOPTS="-W --keep-going"

# set environment variable `DOCS_VERSION_DIR` to either the pr-branch name, "dev", or the release version tag
- name: set output pr
Expand Down
33 changes: 15 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,31 +63,28 @@ Questions, issues, ideas? You are welcome to post an [issue](https://github.com/

To install use pip:

```bash
# with imgui and jupyterlab
pip install -U "fastplotlib[notebook,imgui]"
### With imgui support (recommended)

# minimal install, install glfw, pyqt6 or pyside6 separately
pip install -U fastplotlib
Without jupyterlab support, install desired GUI framework such as glfw, PyQt6, or PySide6 separately.

# with imgui
pip install -U "fastplotlib[imgui]"
pip install -U "fastplotlib[imgui]"

# to use in jupyterlab without imgui
pip install -U "fastplotlib[notebook]"
```
With jupyterlab support.

We strongly recommend installing ``simplejpeg`` for use in notebooks, you must first install [libjpeg-turbo](https://libjpeg-turbo.org/)
pip install -U "fastplotlib[notebook,imgui]"

- If you use ``conda``, you can get ``libjpeg-turbo`` through conda.
- If you are on linux, you can get it through your distro's package manager.
- For Windows and Mac compiled binaries are available on their release page: https://github.com/libjpeg-turbo/libjpeg-turbo/releases
### Without imgui

Once you have ``libjpeg-turbo``:
Minimal, install desired GUI library such as PyQt6, PySide6, or glfw separately.

pip install fastplotlib

With jupyterlab support only.

pip install -U "fastplotlib[notebook]"

Fastplotlib is also available on conda-forge. For imgui support you will need to separately install `imgui-bundle`, and for jupyterlab you will need to install `jupyter-rfb` and `simplejpeg` which are all available on conda-forge.

```bash
pip install simplejpeg
```

> **Note:**
> `fastplotlib` and `pygfx` are fast evolving projects, the version available through pip might be outdated, you will need to follow the "For developers" instructions below if you want the latest features. You can find the release history here: https://github.com/fastplotlib/fastplotlib/releases
Expand Down
1 change: 1 addition & 0 deletions docs/source/api/graphics/LineGraphic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Properties
LineGraphic.axes
LineGraphic.block_events
LineGraphic.cmap
LineGraphic.color_mode
LineGraphic.colors
LineGraphic.data
LineGraphic.deleted
Expand Down
1 change: 1 addition & 0 deletions docs/source/api/graphics/ScatterGraphic.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Properties
ScatterGraphic.axes
ScatterGraphic.block_events
ScatterGraphic.cmap
ScatterGraphic.color_mode
ScatterGraphic.colors
ScatterGraphic.data
ScatterGraphic.deleted
Expand Down
35 changes: 21 additions & 14 deletions docs/source/user_guide/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,38 @@ Installation

To install use pip:

.. code-block::
With imgui support (recommended)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

# with imgui and jupyterlab
pip install -U "fastplotlib[notebook,imgui]"
Without jupyterlab support, install desired GUI framework such as glfw, PyQt6, or PySide6 separately.

# minimal install, install glfw, pyqt6 or pyside6 separately
pip install -U fastplotlib
.. code-block::

# with imgui
pip install -U "fastplotlib[imgui]"

# to use in jupyterlab, no imgui
pip install -U "fastplotlib[notebook]"
With jupyterlab support.

We strongly recommend installing ``simplejpeg`` for use in notebooks, you must first install `libjpeg-turbo <https://libjpeg-turbo.org/>`_.
.. code-block::

pip install -U "fastplotlib[notebook,imgui]"

- If you use ``conda``, you can get ``libjpeg-turbo`` through conda.
- If you are on linux you can get it through your distro's package manager.
- For Windows and Mac compiled binaries are available on their release page: https://github.com/libjpeg-turbo/libjpeg-turbo/releases
Without imgui
^^^^^^^^^^^^^

Once you have ``libjpeg-turbo``:
Minimal, install desired GUI library such as PyQt6, PySide6, or glfw separately.

.. code-block::

pip install simplejpeg
pip install fastplotlib

With jupyterlab support only.

.. code-block::

pip install -U "fastplotlib[notebook]"

Fastplotlib is also available on conda-forge. For imgui support you will need to separately install ``imgui-bundle``, and for jupyterlab you will need to install ``jupyter-rfb`` and ``simplejpeg`` which are all available on conda-forge.


What is ``fastplotlib``?
------------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/events/cmap_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
xs = np.linspace(0, 4 * np.pi, 100)
ys = np.sin(xs)

figure["sine"].add_line(np.column_stack([xs, ys]))
figure["sine"].add_line(np.column_stack([xs, ys]), color_mode="vertex")

# make a 2D gaussian cloud
cloud_data = np.random.normal(0, scale=3, size=1000).reshape(500, 2)
Expand Down
2 changes: 1 addition & 1 deletion examples/gridplot/multigraphic_gridplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def make_circle(center, radius: float, n_points: int = 75) -> np.ndarray:
gaussian_cloud2 = np.random.multivariate_normal(mean, covariance, n_points)

# add the scatter graphics to the figure
figure["scatter"].add_scatter(data=gaussian_cloud, sizes=2, cmap="jet")
figure["scatter"].add_scatter(data=gaussian_cloud, sizes=2, cmap="jet", color_mode="vertex")
figure["scatter"].add_scatter(data=gaussian_cloud2, colors="r", sizes=2)

figure.show()
Expand Down
4 changes: 2 additions & 2 deletions examples/guis/imgui_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@
figure = fpl.Figure(size=(700, 560))

# make some scatter points at every 10th point
figure[0, 0].add_scatter(data[::10], colors="cyan", sizes=15, name="sine-scatter", uniform_color=True)
figure[0, 0].add_scatter(data[::10], colors="cyan", sizes=15, name="sine-scatter")

# place a line above the scatter
figure[0, 0].add_line(data, thickness=3, colors="r", name="sine-wave", uniform_color=True)
figure[0, 0].add_line(data, thickness=3, colors="r", name="sine-wave")


class ImguiExample(EdgeWindow):
Expand Down
50 changes: 50 additions & 0 deletions examples/image/image_reshaping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
Image reshaping
===============

An example that shows replacement of the image data with new data of a different shape. Under the hood, this creates a
new buffer and a new array of Textures on the GPU that replace the older Textures. Creating a new buffer and textures
has a performance cost, so you should do this only if you need to or if the performance drawback is not a concern for
your use case.

Note that the vmin-vmax is reset when you replace the buffers.
"""

# test_example = false
# sphinx_gallery_pygfx_docs = 'animate'


import numpy as np
import fastplotlib as fpl

# create some data, diagonal sinusoidal bands
xs = np.linspace(0, 2300, 2300, dtype=np.float16)
full_data = np.vstack([np.cos(np.sqrt(xs + (np.pi / 2) * i)) * i for i in range(2_300)])

figure = fpl.Figure()

image = figure[0, 0].add_image(full_data)

figure.show()

i, j = 1, 1


def update():
global i, j
# set the new image data as a subset of the full data
row = np.abs(np.sin(i)) * 2300
col = np.abs(np.cos(i)) * 2300
image.data = full_data[: int(row), : int(col)]

i += 0.01
j += 0.01


figure.add_animations(update)

# 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()
4 changes: 2 additions & 2 deletions examples/line/line_cmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
data=sine_data,
thickness=10,
cmap="plasma",
cmap_transform=sine_data[:, 1]
cmap_transform=sine_data[:, 1],
)

# qualitative colormaps, useful for cluster labels or other types of categorical labels
Expand All @@ -36,7 +36,7 @@
data=cosine_data,
thickness=10,
cmap="tab10",
cmap_transform=labels
cmap_transform=labels,
)

figure.show()
Expand Down
25 changes: 22 additions & 3 deletions examples/line/line_cmap_more.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,35 @@
# set colormap by mapping data using a transform
# here we map the color using the y-values of the sine data
# i.e., the color is a function of sine(x)
line2 = figure[0, 0].add_line(sine, thickness=10, cmap="jet", cmap_transform=sine[:, 1], offset=(0, 4, 0))
line2 = figure[0, 0].add_line(
sine,
thickness=10,
cmap="jet",
cmap_transform=sine[:, 1],
offset=(0, 4, 0),
)

# make a line and change the cmap afterward, here we are using the cosine instead fot the transform
line3 = figure[0, 0].add_line(sine, thickness=10, cmap="jet", cmap_transform=cosine[:, 1], offset=(0, 6, 0))
line3 = figure[0, 0].add_line(
sine,
thickness=10,
cmap="jet",
cmap_transform=cosine[:, 1],
offset=(0, 6, 0)
)

# change the cmap
line3.cmap = "bwr"

# use quantitative colormaps with categorical cmap_transforms
labels = [0] * 25 + [1] * 5 + [2] * 50 + [3] * 20
line4 = figure[0, 0].add_line(sine, thickness=10, cmap="tab10", cmap_transform=labels, offset=(0, 8, 0))
line4 = figure[0, 0].add_line(
sine,
thickness=10,
cmap="tab10",
cmap_transform=labels,
offset=(0, 8, 0),
)

# some text labels
for i in range(5):
Expand Down
4 changes: 3 additions & 1 deletion examples/line/line_colorslice.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
sine = figure[0, 0].add_line(
data=sine_data,
thickness=5,
colors="magenta"
colors="magenta",
color_mode="vertex", # initialize with same color across vertices, but we will change the per-vertex colors later
)

# you can also use colormaps for lines!
Expand All @@ -56,6 +57,7 @@
data=zeros_data,
thickness=8,
colors="w",
color_mode="vertex", # initialize with same color across vertices, but we will change the per-vertex colors later
offset=(0, 10, 0)
)

Expand Down
1 change: 1 addition & 0 deletions examples/line_collection/line_collection_slicing.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
multi_data,
thickness=[2, 10, 2, 5, 5, 5, 8, 8, 8, 9, 3, 3, 3, 4, 4],
separation=4,
color_mode="vertex", # this will allow us to set per-vertex colors on each line
metadatas=list(range(15)), # some metadata
names=list("abcdefghijklmno"), # unique name for each line
)
Expand Down
1 change: 1 addition & 0 deletions examples/machine_learning/kmeans.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
sizes=5,
cmap="tab10", # use a qualitative cmap
cmap_transform=kmeans.labels_, # color by the predicted cluster
uniform_size=False,
)

# initial index
Expand Down
91 changes: 91 additions & 0 deletions examples/misc/buffer_replace_gc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"""
Buffer replacement garbage collection test
==========================================

This is an example that used for a manual test to ensure that GPU VRAM is free when buffers are replaced.

Use while monitoring VRAM usage with nvidia-smi
"""

# test_example = false
# sphinx_gallery_pygfx_docs = 'code'


from typing import Literal
import numpy as np
import fastplotlib as fpl
from fastplotlib.ui import EdgeWindow
from imgui_bundle import imgui


def generate_dataset(size: int) -> dict[str, np.ndarray]:
return {
"data": np.random.rand(size, 3),
"colors": np.random.rand(size, 4),
# TODO: there's a wgpu bind group issue with edge_colors, will figure out later
# "edge_colors": np.random.rand(size, 4),
"markers": np.random.choice(list("osD+x^v<>*"), size=size),
"sizes": np.random.rand(size) * 5,
"point_rotations": np.random.rand(size) * 180,
}


datasets = {
"init": generate_dataset(50_000),
"small": generate_dataset(100),
"large": generate_dataset(5_000_000),
}


class UI(EdgeWindow):
def __init__(self, figure):
super().__init__(figure=figure, size=200, location="right", title="UI")
init_data = datasets["init"]
self._figure["line"].add_line(
data=init_data["data"], colors=init_data["colors"], name="line"
)
self._figure["scatter"].add_scatter(
**init_data,
uniform_size=False,
uniform_marker=False,
uniform_edge_color=False,
point_rotation_mode="vertex",
name="scatter",
)

def update(self):
for graphic in ["line", "scatter"]:
if graphic == "line":
features = ["data", "colors"]

elif graphic == "scatter":
features = list(datasets["init"].keys())

for size in ["small", "large"]:
for fea in features:
if imgui.button(f"{size} - {graphic} - {fea}"):
self._replace(graphic, fea, size)

def _replace(
self,
graphic: Literal["line", "scatter", "image"],
feature: Literal["data", "colors", "markers", "sizes", "point_rotations"],
size: Literal["small", "large"],
):
new_value = datasets[size][feature]

setattr(self._figure[graphic][graphic], feature, new_value)


figure = fpl.Figure(shape=(3, 1), size=(700, 1600), names=["line", "scatter", "image"])
ui = UI(figure)
figure.add_gui(ui)

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