diff --git a/.gitignore b/.gitignore index 90026803..e335afc0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ docs/_static/charts/*.html docs/api/autogen docs/api/public +docs/examples_gallery_out/ +docs/sg_execution_times.rst # ============================================================================ diff --git a/MANIFEST.in b/MANIFEST.in index 13c169dc..4ebf8d5d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -27,6 +27,8 @@ recursive-include docs/_static/css *.css recursive-include docs/_static/img *.png *.webp *.svg *.gif *.jpg recursive-include docs/_static/js *.js recursive-include docs/_templates *.html +exclude docs/sg_execution_times.rst +prune docs/examples_gallery_out prune docs/_build prune docs/api/autogen prune docs/api/public diff --git a/Makefile b/Makefile index e13afd42..c61a7a48 100644 --- a/Makefile +++ b/Makefile @@ -94,8 +94,9 @@ clean-all: clean-docs clean-build clean-pyc clean-cov clean-ci-caches clean-tox .PHONY: clean-docs clean-docs: ## remove documentation build artifacts @echo "==> Removing documentation build artifacts..." - @rm -fr docs/_build/ docs/api/autogen/ docs/api/public/ + @rm -fr docs/_build/ docs/api/autogen/ docs/api/public/ docs/examples_gallery_out @find . -wholename 'docs/_static/charts/*.html' -exec rm -fr {} + + @rm -f docs/sg_execution_times.rst .PHONY: clean-build diff --git a/docs/_static/css/sphinx_gallery_overwrite.css b/docs/_static/css/sphinx_gallery_overwrite.css new file mode 100644 index 00000000..0e4a7f44 --- /dev/null +++ b/docs/_static/css/sphinx_gallery_overwrite.css @@ -0,0 +1,3 @@ +div.sphx-glr-download-link-note { + display: none; +} diff --git a/docs/conf.py b/docs/conf.py index d525f428..72aa631c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -76,6 +76,7 @@ # "sphinx_autodoc_typehints", "sphinx_copybutton", "sphinx_design", + "sphinx_gallery.gen_gallery", "sphinx_inline_tabs", "sphinx_paramlinks", "sphinx_remove_toctrees", @@ -120,6 +121,7 @@ html_css_files = [ "css/misc_overrides.css", + "css/sphinx_gallery_overwrite.css", "css/versionmodified_admonitions.css", # FontAwesome CSS for footer icons # https://fontawesome.com/search @@ -344,6 +346,18 @@ def _get_package_type_aliases(package_name: str) -> set[str]: remove_from_toctrees = ["api/internal/*"] +# -- sphinx-gallery config ------------------------------------------------------------------------- +sphinx_gallery_conf = { + "examples_dirs": "examples_gallery_in", + "gallery_dirs": "examples_gallery_out", + "run_stale_examples": True, + "download_all_examples": False, + "image_scrapers": ("plotly.io._sg_scraper.plotly_sg_scraper",), + "show_memory": False, + "show_signature": False, + "min_reported_time": 6, +} + # -- sphinx-paramlinks ----------------------------------------------------------------------------- paramlinks_hyperlink_param = "name" @@ -416,6 +430,21 @@ def compile_all_plotly_charts() -> None: end_of_file_fixer(files) +def rename_plotly_io_show() -> None: + """Rename usages of `plotly.io.show` to `fig.show`.""" + from pathlib import Path + + for file in Path("examples_gallery_out/").iterdir(): + if file.suffix not in {".py", ".rst", ".ipynb"}: + continue + new_lines = [] + for line in file.read_text().split("\n"): + if "import plotly.io as pio" in line: + continue + new_lines.append(line.replace("pio.show(fig)", "fig.show()")) + file.write_text("\n".join(new_lines)) + + def dispatch(fn: Callable[[], None]) -> Callable[..., None]: def wrapper(*args: Any, **kwargs: Any) -> None: fn() @@ -425,4 +454,5 @@ def wrapper(*args: Any, **kwargs: Any) -> None: def setup(app: Sphinx) -> None: # app.connect("builder-inited", dispatch(write_plotlyjs_bundle), priority=501) + app.connect("builder-inited", dispatch(rename_plotly_io_show)) app.connect("builder-inited", dispatch(compile_all_plotly_charts), priority=502) diff --git a/docs/examples_gallery_in/README.rst b/docs/examples_gallery_in/README.rst new file mode 100644 index 00000000..3334fe3b --- /dev/null +++ b/docs/examples_gallery_in/README.rst @@ -0,0 +1,7 @@ +:hide-toc: + +Examples gallery +================== + +This page contains example plots. Click on a thumbnail to see the full +graph and source code. diff --git a/docs/examples_gallery_in/plot_probly.py b/docs/examples_gallery_in/plot_probly.py new file mode 100644 index 00000000..a9f31c2b --- /dev/null +++ b/docs/examples_gallery_in/plot_probly.py @@ -0,0 +1,83 @@ +""" +probly dataset +================= + +In this example, we will be replicating the first ridgeline plot example in +`this _from Data to Viz_ post `_ +, which uses the _probly_ dataset. You can find the _plobly_ dataset on +multiple sources like in the +`bokeh `_ +python interactive visualization library. I'll be using the +`same source `_ +used in the original post. +""" + +from __future__ import annotations + +import numpy as np +import plotly.io as pio + +from ridgeplot import ridgeplot +from ridgeplot.datasets import load_probly + +# %% +# Load the probly dataset +df = load_probly() + +# %% +# Let's grab the subset of columns used in the example +column_names = [ + "Almost Certainly", + "Very Good Chance", + "We Believe", + "Likely", + "About Even", + "Little Chance", + "Chances Are Slight", + "Almost No Chance", +] +df = df[column_names] + +# %% +# Not only does :func:`~ridgeplot.ridgeplot()` come configured with sensible defaults +# but is also fully configurable to your own style and preference! + +fig = ridgeplot( + # Get your samples in the correct format + samples=df.to_numpy().T, + # We can specify the bandwidth used for KDE + bandwidth=4, + # and the range of points for which the KDE is evaluated + kde_points=np.linspace(-12.5, 112.5, 500), + # You can pass any plotly color scale here + colorscale="viridis", + # In the example, the distributions seem to be colored the + # row's index. Have a look at the other available options! + colormode="row-index", + # Set the transparency level + opacity=0.65, + # Always label your plots! Don't be evil... + labels=column_names, + # Adjust the vertical spacing between the distributions + spacing=5 / 9, +) + +# %% +# And you can still update and extend the final +# Plotly Figure using standard Plotly methods +fig.update_layout( + height=560, + width=800, + font_size=16, + plot_bgcolor="white", + xaxis_tickvals=[-12.5, 0, 12.5, 25, 37.5, 50, 62.5, 75, 87.5, 100, 112.5], + xaxis_ticktext=["", "0", "", "25", "", "50", "", "75", "", "100", ""], + xaxis_gridcolor="rgba(0, 0, 0, 0.1)", + yaxis_gridcolor="rgba(0, 0, 0, 0.1)", + yaxis_title=dict(text="Assigned Probability (%)", font_size=13), + showlegend=False, +) + +# %% +# Show us the work! +pio.show(fig) diff --git a/docs/index.md b/docs/index.md index e00a20a2..55614699 100644 --- a/docs/index.md +++ b/docs/index.md @@ -65,6 +65,7 @@ hidden: true --- getting_started/installation getting_started/getting_started +examples_gallery_out/index.rst ``` ```{toctree} diff --git a/requirements/docs.txt b/requirements/docs.txt index aac42d7b..d5cde4bd 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -23,8 +23,17 @@ sphinx_thebe sphinxcontrib-apidoc sphinxext-opengraph -# matplotlib is used to generate social cards +# Sphinx-Gallery dependencies +sphinx-gallery +# kaleido is used to export static images from Plotly +# figures, which is used by sphinx-gallery to generate +# thumbnails for the examples gallery +kaleido +# matplotlib is an implicit dependency of sphinx-gallery. +# although we don't need it for this project, we +# still need to declare the dependency here. matplotlib -# Cleanup generated files +# Use the `pre_commit_hooks` Python package to cleanup +# generated files as 'build-finished' Sphinx hooks pre_commit_hooks diff --git a/ruff.toml b/ruff.toml index 1c0fd6c4..ec71d165 100644 --- a/ruff.toml +++ b/ruff.toml @@ -88,8 +88,12 @@ ignore = [ "D100", # Missing docstring in public module "ARG001", # Unused function argument "INP001", # File {x} is part of an implicit namespace package. Add an `__init__.py` - "S101", # Use of assert detected - "T201", # `print` found + "T201", # `print` found +] +"docs/examples_gallery_in/*" = [ + "INP001", # File {x} is part of an implicit namespace package. Add an `__init__.py`. + "B018", # Found useless expression. Either assign it to a variable or remove it. + "T201", # `print` found ] "tests/*" = [ "D100", # Missing docstring in public module