Skip to content
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

Mayavi example #69

Merged
merged 42 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
28184fb
Mayavi example for mkdocs-gallery documentation
GenevieveBuckley Jul 27, 2023
9d95acd
Include leading zeros in example filenames
GenevieveBuckley Jul 27, 2023
ffe536e
Remove TODO notes about mayavi examples
GenevieveBuckley Jul 27, 2023
78f45e9
Merge branch 'main' into mayavi-example
GenevieveBuckley Nov 21, 2023
c020b0d
Add mayavi dependency for CI tests with nox
GenevieveBuckley Nov 21, 2023
d4de128
Try mayavi installed from master branch, since mayavi release 4.7.4 w…
GenevieveBuckley Nov 21, 2023
aeea56a
Pin mayavi and dependencies vtk, pyqt5, to avoid installation problems
GenevieveBuckley Nov 21, 2023
dd0e6f5
Mayavi test time dependencies, still trying to fix pip wheel build pr…
GenevieveBuckley Nov 21, 2023
79d3366
Fix mayavi dependencies typos
GenevieveBuckley Nov 21, 2023
3b590bb
Setup Qt libraries in github actions with tlambert03/setup-qt-libs@v1
GenevieveBuckley Nov 21, 2023
c5f72ea
Try aganders/headless-gui github action to resolve pyqt xfb errors
GenevieveBuckley Nov 21, 2023
729be0e
Github actions set-output command deprecated, see https://github.blog…
GenevieveBuckley Nov 21, 2023
4bd2fe8
Setup Qt libraries in run all tests github action
GenevieveBuckley Nov 21, 2023
44f3eca
Try to fix github actions pyqt xfb error, for mayavi demo example
GenevieveBuckley Nov 21, 2023
1414d97
Add PyOpenGL to test dependencies, try to resolve Windows CI error
GenevieveBuckley Nov 21, 2023
21ac5b1
Try OpenGL_Actions github action to potentially resolve Windows OpenG…
GenevieveBuckley Nov 21, 2023
7332dfd
Revert, openGL github action did not work
GenevieveBuckley Nov 21, 2023
8ae45a9
mayavi not supported on python 3.7, exclude from these tests
GenevieveBuckley Nov 21, 2023
8e1dee4
Try optional install of mayavi where python>=3.8
GenevieveBuckley Nov 21, 2023
6ab8d14
Try/except mayavi import, since we are skipping the mayavi scraper on…
GenevieveBuckley Nov 21, 2023
1c4d0ef
Image scrapers need to return HTML strings, not None type
GenevieveBuckley Nov 22, 2023
2d6b03c
Try again to have optional mayavi tests
GenevieveBuckley Nov 22, 2023
ec4ec22
Try again
GenevieveBuckley Nov 22, 2023
5d9c02b
Edit mkdocs.yml file to skip plot_10_mayavi.py example where mayavi d…
GenevieveBuckley Nov 23, 2023
f3f4c5a
Fix typo, missing colon :
GenevieveBuckley Nov 23, 2023
eebe7de
Fix path to mayavi example file
GenevieveBuckley Nov 23, 2023
7e3e63f
Fixes for noxfile.py, optionally skip mayavi example on Windows & pyt…
GenevieveBuckley Nov 23, 2023
7280f1f
More noxfile changes
GenevieveBuckley Nov 23, 2023
359ef95
noxfile, explicitly specify mkdocs config yaml file for all mkdocs bu…
GenevieveBuckley Nov 23, 2023
ba986c1
noxfile, if/then statement logic accidentally reversed, fixing it
GenevieveBuckley Nov 23, 2023
b60c294
noxfile, fix up if/then logic
GenevieveBuckley Nov 23, 2023
5595aa3
Check mkdocs-no-mayavi.yml exists before attempting to delete it
GenevieveBuckley Nov 23, 2023
b2c8729
noxfile adjustments
GenevieveBuckley Nov 23, 2023
e9c4875
noxfile, should use or instead of and
GenevieveBuckley Nov 23, 2023
93dd1a9
Swap order of dependency installs
GenevieveBuckley Nov 23, 2023
5b15cbf
noxfile cleanup of mkdocs-no-mayavi.yml file must happen only at the …
GenevieveBuckley Nov 23, 2023
ebb2500
Fix indentation level
GenevieveBuckley Nov 23, 2023
a9af2cb
Fix python 3.8 test on ubuntu
GenevieveBuckley Nov 23, 2023
d5fe33c
Use variable for logic about whether mayavi example should run
GenevieveBuckley Dec 5, 2023
5864c2b
Use pyvista headless display action, smarie suggests it is the best o…
GenevieveBuckley Dec 5, 2023
fd39136
Try mayavi example on windows, now we are using pyvista headless gith…
GenevieveBuckley Dec 5, 2023
6af6e44
Remove inaccurate comment, have fixed OpenGL problem on Windows using…
GenevieveBuckley Dec 5, 2023
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
5 changes: 5 additions & 0 deletions .github/workflows/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ jobs:
python-version: 3.9
architecture: x64

- name: Setup headless display
uses: pyvista/setup-headless-display-action@v2
with:
qt: true

- name: Install noxfile requirements
run: pip install -r noxfile-requirements.txt

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
24 changes: 24 additions & 0 deletions docs/examples/plot_10_mayavi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Example with the mayavi graphing library
========================================

Mkdocs-Gallery supports examples made with the
[mayavi library](http://docs.enthought.com/mayavi/mayavi/).

This mayavi demo is from the
[mayavi documentation](https://docs.enthought.com/mayavi/mayavi/mlab.html#a-demo).
"""

# Create the data.
from numpy import pi, sin, cos, mgrid
dphi, dtheta = pi/250.0, pi/250.0
[phi,theta] = mgrid[0:pi+dphi*1.5:dphi,0:2*pi+dtheta*1.5:dtheta]
m0 = 4; m1 = 3; m2 = 2; m3 = 3; m4 = 6; m5 = 2; m6 = 6; m7 = 4;
r = sin(m0*phi)**m1 + cos(m2*phi)**m3 + sin(m4*theta)**m5 + cos(m6*theta)**m7
x = r*sin(phi)*cos(theta)
y = r*cos(phi)
z = r*sin(phi)*sin(theta)

# View it.
from mayavi import mlab
s = mlab.mesh(x, y, z)
6 changes: 3 additions & 3 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ plugins:
examples_dirs:
- docs/examples # path to your example scripts, relative to mkdocs.yml
- docs/tutorials
# TODO mayavi_examples
gallery_dirs:
- docs/generated/gallery # where to save gallery generated output. Note that you may or may not include them in
- docs/generated/tutorials
# TODO tutorials and mayavi_examples

backreferences_dir: docs/generated/backreferences # where to generate the back references summary
doc_module: ['mkdocs_gallery', 'numpy']
# reference_url: {sphinx_gallery: None},
image_scrapers: matplotlib
image_scrapers:
- matplotlib
- mayavi
compress_images: ['images', 'thumbnails']
# specify the order of examples to be according to filename
within_subsection_order: FileNameSortKey
Expand Down
75 changes: 53 additions & 22 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
from itertools import product
from json import dumps
import logging
import os
import sys

import nox # noqa
from packaging import version
from pathlib import Path # noqa
import sys

# add parent folder to python path so that we can import noxfile_utils.py
# note that you need to "pip install -r noxfile-requiterements.txt" for this file to work.
sys.path.append(str(Path(__file__).parent / "ci_tools"))
from nox_utils import PY27, PY37, PY36, PY35, PY38, PY39, PY310, PY311, power_session, rm_folder, rm_file, PowerSession # noqa
from nox_utils import PY37, PY38, PY39, PY310, PY311, power_session, rm_folder, rm_file, PowerSession # noqa


pkg_name = "mkdocs_gallery"
Expand All @@ -26,7 +28,6 @@
PY38: {"coverage": True, "pkg_specs": {"pip": ">19"}},
}


# set the default activated sessions, minimal for CI
nox.options.sessions = ["tests", "flake8", "docs"] # , "docs", "gh_pages"
nox.options.error_on_missing_interpreters = True
Expand Down Expand Up @@ -87,9 +88,23 @@ def tests(session: PowerSession, coverage, pkg_specs):

# install all requirements
session.install_reqs(setup=True, install=True, tests=True, versions_dct=pkg_specs)

# Since our tests are currently limited, use our own doc generation as a test
session.install_reqs(phase="tests", phase_reqs=MKDOCS_GALLERY_EXAMPLES_REQS)
cannot_run_mayavi = version.parse(session.python) < version.parse(PY38)
if cannot_run_mayavi:
session.install_reqs(phase="tests", phase_reqs=MKDOCS_GALLERY_EXAMPLES_REQS)
else:
session.install_reqs(phase="tests", phase_reqs=MKDOCS_GALLERY_EXAMPLES_REQS+MKDOCS_GALLERY_EXAMPLES_MAYAVI_REQS)

# Edit mkdocs config file
with open("mkdocs.yml", "r") as f:
mkdocs_config = f.readlines()
# Ignore failing mayavi example where mayavi is not installed
if cannot_run_mayavi:
with open("mkdocs-no-mayavi.yml", "w") as f:
for line in mkdocs_config:
if line == " expected_failing_examples:\n":
line = line + " - docs/examples/plot_10_mayavi.py\n"
f.write(line)

# install CI-only dependencies
# if install_ci_deps:
Expand All @@ -114,9 +129,15 @@ def tests(session: PowerSession, coverage, pkg_specs):
session.run2("python -m pytest --cache-clear -v tests/")

# since our tests are too limited, we use our own mkdocs build as additional test for now.
session.run2("python -m mkdocs build")
if cannot_run_mayavi:
session.run2("python -m mkdocs build -f mkdocs-no-mayavi.yml")
else:
session.run2("python -m mkdocs build -f mkdocs.yml")
# -- add a second build so that we can go through the caching/md5 side
session.run2("python -m mkdocs build")
if cannot_run_mayavi:
session.run2("python -m mkdocs build -f mkdocs-no-mayavi.yml")
else:
session.run2("python -m mkdocs build -f mkdocs.yml")
else:
# install self in "develop" mode so that coverage can be measured
session.install2('-e', '.', '--no-deps')
Expand All @@ -132,11 +153,19 @@ def tests(session: PowerSession, coverage, pkg_specs):
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))

# -- use the doc generation for coverage
session.run2("coverage run --append --source src/{pkg_name} -m mkdocs build"
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))
if cannot_run_mayavi:
session.run2("coverage run --append --source src/{pkg_name} -m mkdocs build -f mkdocs-no-mayavi.yml"
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))
else:
session.run2("coverage run --append --source src/{pkg_name} -m mkdocs build -f mkdocs.yml"
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))
# -- add a second build so that we can go through the caching/md5 side
session.run2("coverage run --append --source src/{pkg_name} -m mkdocs build"
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))
if cannot_run_mayavi:
session.run2("coverage run --append --source src/{pkg_name} -m mkdocs build -f mkdocs-no-mayavi.yml"
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))
else:
session.run2("coverage run --append --source src/{pkg_name} -m mkdocs build -f mkdocs.yml"
"".format(pkg_name=pkg_name, test_xml=Folders.test_xml, test_html=Folders.test_html))

session.run2("coverage report")
session.run2("coverage xml -o '{covxml}'".format(covxml=Folders.coverage_xml))
Expand All @@ -149,6 +178,9 @@ def tests(session: PowerSession, coverage, pkg_specs):
# Use our own package to generate the badge
session.run2("genbadge tests -i '%s' -o '%s' -t 100" % (Folders.test_xml, Folders.test_badge))
session.run2("genbadge coverage -i '%s' -o '%s'" % (Folders.coverage_xml, Folders.coverage_badge))
# Cleanup
if os.path.exists("mkdocs-no-mayavi.yml"):
os.remove("mkdocs-no-mayavi.yml")


@power_session(python=PY39, logsdir=Folders.runlogs)
Expand Down Expand Up @@ -179,15 +211,18 @@ def flake8(session: PowerSession):
"statsmodels",
"plotly",
# "memory_profiler",
"pillow" # PIL, required for image rescaling
"pillow", # PIL, required for image rescaling
]
MKDOCS_GALLERY_EXAMPLES_MAYAVI_REQS = [
"PyQt5", # PyQt is required for the mayavi backend
"git+https://github.com/enthought/mayavi.git", # we want mayavi>=4.7.4 when available due to https://github.com/enthought/mayavi/pull/1272
]


@power_session(python=[PY39])
def docs(session: PowerSession):
"""Generates the doc and serves it on a local http server. Pass '-- build' to build statically instead."""

session.install_reqs(phase="docs", phase_reqs=["mkdocs"] + MKDOCS_GALLERY_EXAMPLES_REQS)
session.install_reqs(phase="docs", phase_reqs=["mkdocs"] + MKDOCS_GALLERY_EXAMPLES_REQS + MKDOCS_GALLERY_EXAMPLES_MAYAVI_REQS)

# Install the plugin
session.install2('.')
Expand All @@ -196,30 +231,26 @@ def docs(session: PowerSession):
# use posargs instead of "serve"
session.run2("mkdocs %s" % " ".join(session.posargs))
else:
session.run2("mkdocs serve")
session.run2("mkdocs serve -f mkdocs.yml")


@power_session(python=[PY39])
def publish(session: PowerSession):
"""Deploy the docs+reports on github pages. Note: this rebuilds the docs"""

session.install_reqs(
phase="mkdocs",
phase_reqs=["mkdocs"] + MKDOCS_GALLERY_EXAMPLES_REQS
)
session.install_reqs(phase="mkdocs", phase_reqs=["mkdocs"] + MKDOCS_GALLERY_EXAMPLES_REQS + MKDOCS_GALLERY_EXAMPLES_MAYAVI_REQS)

# Install the plugin
session.install2('.')

# possibly rebuild the docs in a static way (mkdocs serve does not build locally)
session.run2("mkdocs build")
session.run2("mkdocs build -f mkdocs.yml")

# check that the doc has been generated with coverage
if not Folders.site_reports.exists():
raise ValueError("Test reports have not been built yet. Please run 'nox -s tests-3.7' first")

# publish the docs
session.run2("mkdocs gh-deploy")
session.run2("mkdocs gh-deploy -f mkdocs.yml")

# publish the coverage - now in github actions only
# session.install_reqs(phase="codecov", phase_reqs=["codecov", "keyring"])
Expand Down
10 changes: 7 additions & 3 deletions src/mkdocs_gallery/scrapers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from pathlib import Path, PurePosixPath
from textwrap import indent
from typing import Dict, List, Optional
from warnings import filterwarnings
from warnings import filterwarnings, warn

from .errors import ExtensionError
from .gen_data_model import GalleryScript
Expand Down Expand Up @@ -303,14 +303,18 @@ def mayavi_scraper(block, script: GalleryScript):
The ReSTructuredText that will be rendered to HTML containing
the images. This is often produced by :func:`figure_md_or_html`.
"""
from mayavi import mlab
try:
from mayavi import mlab
except ModuleNotFoundError:
warn("No module named 'mayavi', skipping mayavi image scraper.")
return "" # skip scraper function

image_path_iterator = script.run_vars.image_path_iterator
image_paths = list()
e = mlab.get_engine()
for scene, image_path in zip(e.scenes, image_path_iterator):
try:
mlab.savefig(image_path, figure=scene)
mlab.savefig(str(image_path), figure=scene)
smarie marked this conversation as resolved.
Show resolved Hide resolved
except Exception:
mlab.close(all=True)
raise
Expand Down
Loading