Skip to content

Navigation Menu

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

reorganized Figure export stuff #710

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

Merged
merged 1 commit into from
Jan 26, 2025
Merged

reorganized Figure export stuff #710

merged 1 commit into from
Jan 26, 2025

Conversation

kushalkolar
Copy link
Member

@kushalkolar kushalkolar commented Jan 26, 2025

Adds a new method Figure.export_numpy().

Removes the FigureRecorder because that thing is hard to test and IMO kinda out of scope and a mess. Instead once we expose the "onedemand" render mode in fastplotlib which now exists in rendercanvs we can provide examples using Figure.export_numpy() to export frames as numpy arrays that can then be written to disk using the user's favorite video writer, such as opencv.

@apasarkar @FlynnOConnell

These examples currently don't work because we don't have "ondemand" mode in fastplotlib yet, documenting here for a future PR:

"""
ImageWidget export images or video
==================================

This example is meant to be run in an interactive shell. To run in a script use the offscreen canvas.

imageio is required to export to images.

This example uses opencv to export to a video but you don't have to use opencv, you
can use any other video writer that can write numpy arrays to video frames.
"""

# test_example = true
# sphinx_gallery_pygfx_docs = 'code'

# %%
import fastplotlib as fpl
import imageio.v3 as iio
import cv2


movie = iio.imread("imageio:cockatoo.mp4")

iw = fpl.ImageWidget(
    movie,
    rgb=[True],
    figure_kwargs={"size": (700, 560), "canvas": "offscreen"}  # for offscreen rendering provide "canvas": "offscreen"
)

# show image widget
iw.show()

# %%

# wait for image widget to display

# export a snapshot of the figure as it is currently displayed
iw.figure.export("./image.png")

# obtain a numpy array
frame = iw.figure.export_numpy(rgb=True)

# %%
# create a video writer
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
writer = cv2.VideoWriter(
    "./iw_video.mp4",
    fourcc,
    20.0,
    (frame.shape[1], frame.shape[0]),
)

# write a video file of the first 100 frames
for i in range(100):
    frame = iw.figure.export_numpy(rgb=True)
    writer.write(frame)
    iw.current_index = {"t": i}

writer.release()
"""
Figure export images or video
=============================

This example is meant to be run in an interactive shell. To run in a script use the offscreen canvas.

imageio is required to export to images.

This example uses opencv to export to a video but you don't have to use opencv, you
can use any other video writer that can write numpy arrays to video frames.
"""

# test_example = false
# sphinx_gallery_pygfx_docs = 'code'

# %%
import fastplotlib as fpl
import numpy as np
import cv2

# create a random distribution of 10,000 xyz coordinates
n_points = 10_000

# dimensions always have to be [n_points, xyz]
dims = (n_points, 3)

clouds_offset = 15

# create some random clouds
normal = np.random.normal(size=dims, scale=5)
# stack the data into a single array
cloud = np.vstack(
    [
        normal - clouds_offset,
        normal,
        normal + clouds_offset,
    ]
)

# color each of them separately
colors = ["yellow"] * n_points + ["cyan"] * n_points + ["magenta"] * n_points

# create plot
figure = fpl.Figure(
    size=(700, 560),
    canvas="offscreen"  # for offscreen rendering, ex. in a script
)
subplot_scatter = figure[0, 0]
# use an alpha value since this will be a lot of points
scatter_graphic = subplot_scatter.add_scatter(data=cloud, sizes=3, colors=colors, alpha=0.6)


def update():
    # move every point by a small amount
    deltas = np.random.normal(size=scatter_graphic.data.value.shape, loc=0, scale=0.05)
    scatter_graphic.data = scatter_graphic.data.value + deltas


figure.show()

# %%

# wait for figure to display

# export a snapshot of the figure as it is currently displayed
figure.export("./image.png")

# obtain a numpy array
frame = figure.export_numpy(rgb=True)

# %%
# create a video writer
fourcc = cv2.VideoWriter_fourcc(*'XVID')
writer = cv2.VideoWriter(
    "./scatter_video.avi",
    fourcc,
    50.0,
    (frame.shape[1], frame.shape[0]),
)

# write a video file with 500 frames
for i in range(500):
    frame = figure.export_numpy(rgb=True)
    writer.write(frame)
    # update the graphic
    update()

writer.release()

@kushalkolar kushalkolar requested a review from clewis7 as a code owner January 26, 2025 08:45
Copy link

📚 Docs preview built and uploaded! https://www.fastplotlib.org/ver/export-numpy

@clewis7
Copy link
Member

clewis7 commented Jan 26, 2025

@kushalkolar is this gtg?

@kushalkolar
Copy link
Member Author

Yup ready for review

@clewis7 clewis7 merged commit d4af1a9 into main Jan 26, 2025
46 of 52 checks passed
@clewis7 clewis7 deleted the export-numpy branch January 26, 2025 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
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.