Skip to content

add ImageVolumeGraphic #791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"subsection_order": ExplicitOrder(
[
"../../examples/image",
"../../examples/image_volume",
"../../examples/heatmap",
"../../examples/image_widget",
"../../examples/gridplot",
Expand Down
2 changes: 2 additions & 0 deletions examples/image_volume/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Image Volume Examples
=====================
83 changes: 83 additions & 0 deletions examples/image_volume/image_volume_4d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
Volume movie
============

"""

# test_example = false
# sphinx_gallery_pygfx_docs = 'screenshot'

import numpy as np
from scipy.ndimage import gaussian_filter
import fastplotlib as fpl
from tqdm import tqdm


def generate_data(p=1, noise=.5, T=256, framerate=30, firerate=2., ):
gamma = np.array([.9])
dims = (128, 128, 30) # size of image
sig = (4, 4, 2) # neurons size
bkgrd = 10
N = 150 # number of neurons
np.random.seed(0)
centers = np.asarray([[np.random.randint(s, x - s)
for x, s in zip(dims, sig)] for i in range(N)])
Y = np.zeros((T,) + dims, dtype=np.float32)
trueSpikes = np.random.rand(N, T) < firerate / float(framerate)
trueSpikes[:, 0] = 0
truth = trueSpikes.astype(np.float32)
for i in tqdm(range(2, T)):
if p == 2:
truth[:, i] += gamma[0] * truth[:, i - 1] + gamma[1] * truth[:, i - 2]
else:
truth[:, i] += gamma[0] * truth[:, i - 1]
for i in tqdm(range(N)):
Y[:, centers[i, 0], centers[i, 1], centers[i, 2]] = truth[i]
tmp = np.zeros(dims)
tmp[tuple(np.array(dims)//2)] = 1.
print("gaussing filtering")
z = np.linalg.norm(gaussian_filter(tmp, sig).ravel())

print("finishing")
Y = bkgrd + noise * np.random.randn(*Y.shape) + 10 * gaussian_filter(Y, (0,) + sig) / z

return Y


voldata = generate_data()

fig = fpl.Figure(cameras="3d", controller_types="orbit", size=(700, 560))

vmin, vmax = fpl.utils.quick_min_max(voldata)

volume = fig[0, 0].add_image_volume(voldata[0], vmin=vmin, vmax=vmax, interpolation="linear", cmap="gnuplot2")

hlut = fpl.HistogramLUTTool(voldata, volume)

fig[0, 0].docks["right"].size = 100
fig[0, 0].docks["right"].controller.enabled = False
fig[0, 0].docks["right"].add_graphic(hlut)
fig[0, 0].docks["right"].auto_scale(maintain_aspect=False)

fig.show()


i = 0
def update():
global i

volume.data = voldata[i]

i += 1
if i == voldata.shape[0]:
i = 0


fig.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()
29 changes: 29 additions & 0 deletions examples/image_volume/image_volume_mip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Volume Mip mode
===============

View a volume, uses the fly controller by default so you can fly around the scene using WASD keys and the mouse:
https://docs.pygfx.org/stable/_autosummary/controllers/pygfx.controllers.FlyController.html#pygfx.controllers.FlyController
"""

# test_example = false
# sphinx_gallery_pygfx_docs = 'screenshot'

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

voldata = iio.imread("imageio:stent.npz").astype(np.float32)

fig = fpl.Figure(cameras="3d", controller_types="orbit", size=(700, 560))

fig[0, 0].add_image_volume(voldata, mode="iso")

fig.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()
56 changes: 56 additions & 0 deletions examples/image_volume/image_volume_non_orthogonal_slicing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
Volume non-orthogonal slicing
=============================

Perform non-orthogonal slicing of image volumes.

For an example with UI sliders see the "Volume modes" example.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'screenshot'

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


voldata = iio.imread("imageio:stent.npz").astype(np.float32)

fig = fpl.Figure(
cameras="3d",
controller_types="orbit",
size=(700, 560)
)

vol = fig[0, 0].add_image_volume(voldata, mode="slice")

# a plane is defined by ax + by + cz + d = 0
# the plane property sets (a, b, c, d)
vol.plane = (0, 0.5, 0.5, -70)

# just a pre-saved camera state to view the plot area
state = {
"position": np.array([-160.0, 105.0, 205.0]),
"rotation": np.array([-0.1, -0.6, -0.07, 0.8]),
"scale": np.array([1., 1., 1.]),
"reference_up": np.array([0., 1., 0.]),
"fov": 50.0,
"width": 128.0,
"height": 128.0,
"depth": 315,
"zoom": 0.75,
"maintain_aspect": True,
"depth_range": None
}

fig.show()

fig[0, 0].camera.set_state(state)


# 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()
75 changes: 75 additions & 0 deletions examples/image_volume/image_volume_share_buffer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
Volume share buffers
====================

Share the data buffer between two graphics. This example creates one Graphic using MIP rendering, and another graphic
to display a slice of the volume. We can share the data buffer on the GPU between these graphics.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'screenshot'

from imgui_bundle import imgui
import fastplotlib as fpl
from fastplotlib.ui import EdgeWindow
import imageio.v3 as iio
from skimage.filters import gaussian


data = iio.imread("imageio:stent.npz")


figure = fpl.Figure(
cameras="3d",
controller_types="orbit",
size=(700, 560),
)

# MIP rendering is the default `mode`
vol_mip = figure[0, 0].add_image_volume(gaussian(data, sigma=2.0))

# make another graphic to show a slice of the volume
vol_slice = figure[0, 0].add_image_volume(
vol_mip.data, # pass the data property from the previous volume so they share the same buffer on the GPU
mode="slice",
plane=(0, -0.5, -0.5, 50),
offset=(150, 0, 0) # place the graphic at x=150
)


class GUI(EdgeWindow):
def __init__(self, figure, title="change data buffer", location="right", size=200):
super().__init__(figure, title=title, location=location, size=size)
self._sigma = 2

def update(self):
changed, self._sigma = imgui.slider_int("sigma", v=self._sigma, v_min=0, v_max=5)

if changed:
vol_mip.data = gaussian(data, sigma=self._sigma)
vol_mip.reset_vmin_vmax()
vol_slice.reset_vmin_vmax()

imgui.text("Select plane defined by:\nax + by + cz + d = 0")
_, a = imgui.slider_float("a", v=vol_slice.plane[0], v_min=-1, v_max=1.0)
_, b = imgui.slider_float("b", v=vol_slice.plane[1], v_min=-1, v_max=1.0)
_, c = imgui.slider_float("c", v=vol_slice.plane[2], v_min=-1, v_max=1.0)

largest_dim = max(vol_slice.data.value.shape)
_, d = imgui.slider_float(
"d", v=vol_slice.plane[3], v_min=0, v_max=largest_dim * 2
)

vol_slice.plane = (a, b, c, d)

gui = GUI(figure)
figure.add_gui(gui)

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()
64 changes: 64 additions & 0 deletions examples/image_volume/image_volume_slicing_animation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""
Volume non-orthogonal slicing animation
=======================================

Perform non-orthogonal slicing of image volumes.

For an example with UI sliders see the "Volume modes" example.
"""

# test_example = false
# sphinx_gallery_pygfx_docs = 'animate 8s'

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


voldata = iio.imread("imageio:stent.npz").astype(np.float32)

fig = fpl.Figure(
cameras="3d",
controller_types="orbit",
size=(700, 560)
)

vol = fig[0, 0].add_image_volume(voldata, mode="slice")

# a plane is defined by ax + by + cz + d = 0
# the plane property sets (a, b, c, d)
vol.plane = (0, 0.5, 0.5, -20)

# just a pre-saved camera state to view the plot area
state = {
"position": np.array([-110.0, 160.0, 240.0]),
"rotation": np.array([-0.25, -0.5, -0.15, 0.85]),
"scale": np.array([1., 1., 1.]),
"reference_up": np.array([0., 1., 0.]),
"fov": 50.0,
"width": 128.0,
"height": 128.0,
"depth": 315,
"zoom": 0.75,
"maintain_aspect": True,
"depth_range": None
}

def update():
# increase d by 1
vol.plane = (0, 0.5, 0.5, vol.plane[-1] - 1)
if vol.plane[-1] < -200:
vol.plane = (0, 0.5, 0.5, -20)

fig[0, 0].add_animations(update)

fig.show()

fig[0, 0].camera.set_state(state)


# 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
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy