Skip to content

sphinx gallery for docs #437

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ instance/

# Sphinx documentation
docs/_build/
docs/source/_gallery

# PyBuilder
target/
Expand Down
56 changes: 56 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import fastplotlib

from sphinx_gallery.sorting import ExplicitOrder
import wgpu.gui.offscreen
import os
import sys

ROOT_DIR = os.path.abspath(os.path.join(__file__, "..", ".."))
sys.path.insert(0, ROOT_DIR)

# -- Sphix Gallery Hackz -----------------------------------------------------
# When building the gallery, render offscreen and don't process
# the event loop while parsing the example


def _ignore_offscreen_run():
wgpu.gui.offscreen.run = lambda: None
Comment on lines +20 to +21
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit should no longer be necessary. It's from a time when the offscreen backend still fired up asyncio (it does not do so anymore). The WGPU_FORCE_OFFSCREEN is the only thing needed.



os.environ["WGPU_FORCE_OFFSCREEN"] = "True"
_ignore_offscreen_run()

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

Expand All @@ -24,6 +44,7 @@
"sphinx_copybutton",
"sphinx_design",
"nbsphinx",
"sphinx_gallery.gen_gallery"
]

autosummary_generate = True
Expand All @@ -33,6 +54,41 @@

napoleon_custom_sections = ["Features"]

parent_path = os.path.abspath(os.path.join(ROOT_DIR, os.pardir))

sphinx_gallery_conf = {
"examples_dirs": f"{parent_path}/examples/desktop",
"gallery_dirs": "_gallery",
"backreferences_dir": "_gallery/backreferences",
# "exclude_implicit_doc": {
# "WgpuRenderer",
# "Resource",
# "WorldObject",
# "Geometry",
# "Material",
# "Controller",
# "Camera",
# "show",
# "Display",
# "Group",
# "Scene",
# "Light",
# },
"doc_module": ("fastplotlib",),
"image_scrapers": ("fastplotlib",),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you put "pygfx" here instead, I think you can use our scraper, so you don;t need the gallery_scraper.py.

# "subsection_order": ExplicitOrder(
# [
# f"{parent_path}/examples/desktop",
# # "../examples/feature_demo",
# # "../examples/validation",
# # "../examples/other",
# ]
# ),
"remove_config_comments": True,
# Exclude files in 'other' dir from being executed
"filename_pattern": r"^((?![\\/]other[\\/]).)*$",
}

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Welcome to fastplotlib's documentation!
:maxdepth: 1

GPU Info <user_guide/gpu>
Gallery <_gallery/index.rst>

.. toctree::
:maxdepth: 1
Expand Down
2 changes: 2 additions & 0 deletions examples/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Examples using fastplotlib
==========================
1 change: 1 addition & 0 deletions examples/desktop/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. rubric:: Desktop Examples
1 change: 1 addition & 0 deletions examples/desktop/gridplot/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.. rubric:: GridPlot Examples
4 changes: 3 additions & 1 deletion examples/desktop/gridplot/gridplot.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""
GridPlot Simple
============
===============

Example showing simple 2x2 GridPlot with Standard images from imageio.
"""

# test_example = true
# sphinx_gallery_fpl_render = True

import fastplotlib as fpl
import imageio.v3 as iio
Expand Down
1 change: 1 addition & 0 deletions examples/desktop/gridplot/gridplot_non_square.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

# test_example = true
# sphinx_gallery_fpl_render = True

import fastplotlib as fpl
import imageio.v3 as iio
Expand Down
10 changes: 10 additions & 0 deletions fastplotlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@

_notebook_print_banner()


def _get_sg_image_scraper():
import sphinx_gallery.scrapers
from .utils.gallery_scraper import fpl_scraper
# add webp as supported extension
sphinx_gallery.scrapers._KNOWN_IMG_EXTS += ("webp",)

return fpl_scraper


__all__ = [
"Plot",
"GridPlot",
Expand Down
101 changes: 101 additions & 0 deletions fastplotlib/utils/gallery_scraper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from pathlib import Path

import imageio.v3 as iio
from sphinx_gallery.scrapers import figure_rst
from wgpu.gui import WgpuCanvasBase

from pygfx.renderers import Renderer
from pygfx.utils.show import Display

# The scraper's default configuration. An example code-block
# may overwrite these values by setting comments of the form
#
# # sphinx_gallery_pygfx_<name> = <value>
#
# inside the code block. These comments will not be shown in the generated
# gallery example and will be reset after each code block.
default_config = {
"render": False, # if True, render an image
"animate": False, # if True, render a GIF
"target_name": "renderer", # the display to use
# GIF settings
"duration": 3, # how many seconds to record
"loop": 0, # loop forever
}


def fpl_scraper(block, block_vars, gallery_conf, **kwargs):
"""Scrape pygfx images and animations
Parameters
----------
block : tuple
A tuple containing the (label, content, line_number) of the block.
block_vars : dict
Dict of block variables.
gallery_conf : dict
Contains the configuration of Sphinx-Gallery
**kwargs : dict
Additional keyword arguments to pass to
:meth:`~matplotlib.figure.Figure.savefig`, e.g. ``format='svg'``.
The ``format`` kwarg in particular is used to set the file extension
of the output file (currently only 'png', 'jpg', and 'svg' are
supported).
Returns
-------
rst : str
The ReSTructuredText that will be rendered to HTML containing
the images. This is often produced by :func:`figure_rst`.
"""

# parse block-level config
scraper_config = default_config.copy()
config_prefix = "# sphinx_gallery_fpl_"
for line in block[1].split("\n"):
if not line.startswith(config_prefix):
continue

name, value = line[len(config_prefix):].split(" = ")
scraper_config[name] = eval(value)

if not scraper_config["render"] and not scraper_config["animate"]:
return "" # nothing to do

target = block_vars["example_globals"][scraper_config["target_name"]]
if isinstance(target, Display):
canvas = target.canvas
elif isinstance(target, Renderer):
canvas = target.target
elif isinstance(target, WgpuCanvasBase):
canvas = target
else:
raise ValueError("`target` must be a Display, Renderer, or Canvas.")

images = []

if scraper_config["render"]:
path_generator = block_vars["image_path_iterator"]
img_path = next(path_generator)
iio.imwrite(img_path, canvas.draw())
images.append(img_path)

if scraper_config["animate"]:
frames = []

# by default videos are rendered at ~ 30 FPS
n_frames = scraper_config["duration"] * 30

for _ in range(n_frames):
frames.append(canvas.draw())

path_generator = block_vars["image_path_iterator"]
img_path = Path(next(path_generator)).with_suffix(".webp")
iio.imwrite(
img_path,
frames,
duration=33,
loop=scraper_config["loop"],
lossless=True,
)
images.append(img_path)

return figure_rst(images, gallery_conf["src_dir"])
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"pandoc",
"jupyterlab",
"sidecar",
"sphinx-gallery",
"imageio",
"matplotlib"
],
"notebook": [
"jupyterlab",
Expand Down
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