Unverified 提交 2b57f74f authored 作者: Jesse Grabowski's avatar Jesse Grabowski 提交者: GitHub

Add example gallery to docs (#1150)

* Add example gallery * Add example gallery * Update rtd environment * Fix typo in `generate_gallery.py` * Add graph rewriting tutorial to examples * Add default gallery image * Fix default image path * Add default image * Add scan tutorial example * Add header links to github/colab/binder Add ablog with tags, authors, and categories Modify example notebooks * Update license and package name in footer Delete placeholder notebook * Delete docs for `sandbox` module * rename `pytensor.tensor.var._tensor_py_operators` -> `pytensor.tensor.variable._tensor_py_operators` * Fix underline lengths * Remove reference to depreciated functions * Add end of file newline * Remove references to sandbox * Try adding sitemap and robots.txt * pre-commit * Add cross-references and fix formatting * Fix cross-reference
上级 1fc678c5
{% if pagename in ablog %}
<!-- Generate correct links and render github/binder/colab badges -->
{% set gh_basepath = github_user + '/' + github_repo + '/blob/' + github_version + '/' %}
{% set encoded_base = github_user + '%252F' + github_repo %}
{% set gh_binder = github_user + '/' + github_repo + '/' + github_version %}
{% set doc_path_aux = doc_path | trim('/') %}
{% set file_path = doc_path_aux + '/' + pagename + ".ipynb" %}
{% set encoded_path = file_path | replace("/", "%252F") %}
<div class="sd-text-right">
<p>
<a href="{{ github_url + '/' + gh_basepath + file_path }}", role="button" target="_blank">
<img src="{{ pathto('_static/github.svg', 1) }}" alt="View On GitHub"></a>
<a href="{{ 'https://mybinder.org/v2/gh/' + sandbox_repo + '?urlpath=git-pull%3Frepo%3Dhttps%253A%252F%252Fgithub.com%252F' + encoded_base + '%26urlpath%3Dtree%252F' + github_repo + '%252F' + encoded_path + '%26branch%3D' + github_version }}" target="_blank">
<img src="{{ pathto('_static/binder.svg', 1) }}" alt="Open In Binder"></a>
<a href="{{ 'https://colab.research.google.com/github/' + gh_basepath + file_path }}" target="_blank">
<img src="{{ pathto('_static/colab.svg', 1) }}" alt="Open In Colab"/></a>
</p>
</div>
{% endif %}
\ No newline at end of file
<!-- continuation of examples/page_footer.md -->
{% if pagename in ablog %}
{% set post = ablog[pagename] %}
{% for coll in post.author %}
{% if coll|length %}
{{ coll }}
{% if loop.index < post.author | length %},{% endif %}
{% else %}
{{ coll }}
{% if loop.index < post.author | length %},{% endif %}
{% endif %}
{% endfor %}. "{{ title.split(' ')[0] }}". In: <i>Pytensor Examples</i>. Ed. by Pytensor Team. <!-- DOI: <a href={{ doi_url }}>{{ doi_code }}</a> -->
{% endif %}
\ No newline at end of file
---
orphan: true
---
# Recent updates
<!-- auto generated by ablog so it's empty -->
# pytensor documentation build configuration file, created by
# sphinx-quickstart on Tue Oct 7 16:34:06 2008.
#
# This file is execfile()d with the current directory set to its containing
# directory.
#
# The contents of this file are pickled, so don't put values in the namespace
# that aren't pickleable (module imports are okay, they're removed
# automatically).
#
# All configuration values have a default value; values that are commented out
# serve to show the default value.
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use Path.absolute to make it
# absolute, like shown here.
# sys.path.append(str(Path("some/directory").absolute()))
import os
import inspect
import sys
import pytensor
from pathlib import Path
sys.path.insert(0, str(Path("..").resolve() / "scripts"))
# General configuration
# ---------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.todo",
......@@ -34,9 +16,22 @@ extensions = [
"sphinx.ext.linkcode",
"sphinx.ext.mathjax",
"sphinx_design",
"sphinx.ext.intersphinx"
"sphinx.ext.intersphinx",
"sphinx.ext.autosummary",
"sphinx.ext.autosectionlabel",
"ablog",
"myst_nb",
"generate_gallery",
"sphinx_sitemap",
]
# Don't auto-generate summary for class members.
numpydoc_show_class_members = False
autosummary_generate = True
autodoc_typehints = "none"
remove_from_toctrees = ["**/classmethods/*"]
intersphinx_mapping = {
"jax": ("https://jax.readthedocs.io/en/latest", None),
"numpy": ("https://numpy.org/doc/stable", None),
......@@ -92,6 +87,7 @@ today_fmt = "%B %d, %Y"
# List of directories, relative to source directories, that shouldn't be
# searched for source files.
exclude_dirs = ["images", "scripts", "sandbox"]
exclude_patterns = ['page_footer.md', '**/*.myst.md']
# The reST default role (used for this markup: `text`) to use for all
# documents.
......@@ -115,19 +111,15 @@ pygments_style = "sphinx"
# Options for HTML output
# -----------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
# html_style = 'default.css'
# html_theme = 'sphinxdoc'
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "pymc_sphinx_theme"
html_logo = "images/PyTensor_RGB.svg"
html_baseurl = "https://pytensor.readthedocs.io"
sitemap_url_scheme = f"{{lang}}{rtd_version}/{{link}}"
# html4_writer added to Fix colon & whitespace misalignment
# https://github.com/readthedocs/sphinx_rtd_theme/issues/766#issuecomment-513852197
# https://github.com/readthedocs/sphinx_rtd_theme/issues/766#issuecomment-629666319
# html4_writer = False
html_logo = "images/PyTensor_RGB.svg"
html_theme = "pymc_sphinx_theme"
html_theme_options = {
"use_search_override": False,
"icon_links": [
......@@ -156,15 +148,27 @@ html_theme_options = {
"type": "fontawesome",
},
],
"secondary_sidebar_items": ["page-toc", "edit-this-page", "sourcelink", "donate"],
"navbar_start": ["navbar-logo"],
"article_header_end": ["nb-badges"],
"article_footer_items": ["rendered_citation.html"],
}
html_context = {
"github_url": "https://github.com",
"github_user": "pymc-devs",
"github_repo": "pytensor",
"github_version": "main",
"github_version": version if "." in rtd_version else "main",
"sandbox_repo": f"pymc-devs/pymc-sandbox/{version}",
"doc_path": "doc",
"default_mode": "light",
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ["../_static"]
html_extra_path = ["_thumbnails", 'images', "robots.txt"]
templates_path = [".templates"]
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
......@@ -295,3 +299,62 @@ latex_documents = [
# If false, no module index is generated.
# latex_use_modindex = True
# -- MyST config -------------------------------------------------
myst_enable_extensions = [
"colon_fence",
"deflist",
"dollarmath",
"amsmath",
"substitution",
]
myst_dmath_double_inline = True
citation_code = f"""
```bibtex
@incollection{{citekey,
author = "<notebook authors, see above>",
title = "<notebook title>",
editor = "Pytensor Team",
booktitle = "Pytensor Examples",
}}
```
"""
myst_substitutions = {
"pip_dependencies": "{{ extra_dependencies }}",
"conda_dependencies": "{{ extra_dependencies }}",
"extra_install_notes": "",
"citation_code": citation_code,
}
nb_execution_mode = "off"
nbsphinx_execute = "never"
nbsphinx_allow_errors = True
rediraffe_redirects = {
"index.md": "gallery.md",
}
# -- Bibtex config -------------------------------------------------
bibtex_bibfiles = ["references.bib"]
bibtex_default_style = "unsrt"
bibtex_reference_style = "author_year"
# -- ablog config -------------------------------------------------
blog_baseurl = "https://pytensor.readthedocs.io/en/latest/index.html"
blog_title = "Pytensor Examples"
blog_path = "blog"
blog_authors = {
"contributors": ("Pytensor Contributors", "https://pytensor.readthedocs.io"),
}
blog_default_author = "contributors"
post_show_prev_next = False
fontawesome_included = True
# post_redirect_refresh = 1
# post_auto_image = 1
# post_auto_excerpt = 2
# notfound_urls_prefix = ""
......@@ -26,12 +26,4 @@ some of them might be outdated though:
* :ref:`unittest` -- Tutorial on how to use unittest in testing PyTensor.
* :ref:`sandbox_debugging_step_mode` -- How to step through the execution of
an PyTensor function and print the inputs and outputs of each op.
* :ref:`sandbox_elemwise` -- Description of element wise operations.
* :ref:`sandbox_randnb` -- Description of how PyTensor deals with random
numbers.
* :ref:`sparse` -- Description of the ``sparse`` type in PyTensor.
......@@ -14,6 +14,14 @@ dependencies:
- pillow
- pymc-sphinx-theme
- sphinx-design
- pygments
- pydot
- ipython
- myst-nb
- matplotlib
- watermark
- ablog
- pip
- pip:
- sphinx_sitemap
- -e ..
Adding JAX, Numba and Pytorch support for `Op`\s
=======================================
================================================
PyTensor is able to convert its graphs into JAX, Numba and Pytorch compiled functions. In order to do
this, each :class:`Op` in an PyTensor graph must have an equivalent JAX/Numba/Pytorch implementation function.
......@@ -7,7 +7,7 @@ this, each :class:`Op` in an PyTensor graph must have an equivalent JAX/Numba/Py
This tutorial will explain how JAX, Numba and Pytorch implementations are created for an :class:`Op`.
Step 1: Identify the PyTensor :class:`Op` you'd like to implement
------------------------------------------------------------------------
-----------------------------------------------------------------
Find the source for the PyTensor :class:`Op` you'd like to be supported and
identify the function signature and return values. These can be determined by
......@@ -98,7 +98,7 @@ how the inputs and outputs are used to compute the outputs for an :class:`Op`
in Python. This method is effectively what needs to be implemented.
Step 2: Find the relevant method in JAX/Numba/Pytorch (or something close)
---------------------------------------------------------
--------------------------------------------------------------------------
With a precise idea of what the PyTensor :class:`Op` does we need to figure out how
to implement it in JAX, Numba or Pytorch. In the best case scenario, there is a similarly named
......@@ -269,7 +269,7 @@ and :func:`torch.cumprod`
z[0] = np.cumprod(x, axis=self.axis)
Step 3: Register the function with the respective dispatcher
---------------------------------------------------------------
------------------------------------------------------------
With the PyTensor `Op` replicated, we'll need to register the
function with the backends `Linker`. This is done through the use of
......
## License notice
All the notebooks in this example gallery are provided under a
[3-Clause BSD License](https://github.com/pymc-devs/pytensor/blob/main/doc/LICENSE.txt)
which allows modification, and redistribution for any
use provided the copyright and license notices are preserved.
## Citing Pytensor Examples
To cite this notebook, please use the suggested citation below.
:::{important}
Many notebooks are adapted from other sources: blogs, books... In such cases you should
cite the original source as well.
Also remember to cite the relevant libraries used by your code.
:::
Here is an example citation template in bibtex:
{{ citation_code }}
which once rendered could look like:
<!-- continues in _templates/page.html!!! -->
<!-- I wanted to get some kind of automation to the process,
and html templates have access to many variables that are not available
from jinja-myst -->
\ No newline at end of file
差异被折叠。
差异被折叠。
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="109" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="109" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h64v20H0z"/><path fill="#579aca" d="M64 0h45v20H64z"/><path fill="url(#b)" d="M0 0h109v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAABZCAMAAABi1XidAAAB8lBMVEX///9XmsrmZYH1olJXmsr1olJXmsrmZYH1olJXmsr1olJXmsrmZYH1olL1olJXmsr1olJXmsrmZYH1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olJXmsrmZYH1olL1olL0nFf1olJXmsrmZYH1olJXmsq8dZb1olJXmsrmZYH1olJXmspXmspXmsr1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olLeaIVXmsrmZYH1olL1olL1olJXmsrmZYH1olLna31Xmsr1olJXmsr1olJXmsrmZYH1olLqoVr1olJXmsr1olJXmsrmZYH1olL1olKkfaPobXvviGabgadXmsqThKuofKHmZ4Dobnr1olJXmsr1olJXmspXmsr1olJXmsrfZ4TuhWn1olL1olJXmsqBi7X1olJXmspZmslbmMhbmsdemsVfl8ZgmsNim8Jpk8F0m7R4m7F5nLB6jbh7jbiDirOEibOGnKaMhq+PnaCVg6qWg6qegKaff6WhnpKofKGtnomxeZy3noG6dZi+n3vCcpPDcpPGn3bLb4/Mb47UbIrVa4rYoGjdaIbeaIXhoWHmZYHobXvpcHjqdHXreHLroVrsfG/uhGnuh2bwj2Hxk17yl1vzmljzm1j0nlX1olL3AJXWAAAAbXRSTlMAEBAQHx8gICAuLjAwMDw9PUBAQEpQUFBXV1hgYGBkcHBwcXl8gICAgoiIkJCQlJicnJ2goKCmqK+wsLC4usDAwMjP0NDQ1NbW3Nzg4ODi5+3v8PDw8/T09PX29vb39/f5+fr7+/z8/Pz9/v7+zczCxgAABC5JREFUeAHN1ul3k0UUBvCb1CTVpmpaitAGSLSpSuKCLWpbTKNJFGlcSMAFF63iUmRccNG6gLbuxkXU66JAUef/9LSpmXnyLr3T5AO/rzl5zj137p136BISy44fKJXuGN/d19PUfYeO67Znqtf2KH33Id1psXoFdW30sPZ1sMvs2D060AHqws4FHeJojLZqnw53cmfvg+XR8mC0OEjuxrXEkX5ydeVJLVIlV0e10PXk5k7dYeHu7Cj1j+49uKg7uLU61tGLw1lq27ugQYlclHC4bgv7VQ+TAyj5Zc/UjsPvs1sd5cWryWObtvWT2EPa4rtnWW3JkpjggEpbOsPr7F7EyNewtpBIslA7p43HCsnwooXTEc3UmPmCNn5lrqTJxy6nRmcavGZVt/3Da2pD5NHvsOHJCrdc1G2r3DITpU7yic7w/7Rxnjc0kt5GC4djiv2Sz3Fb2iEZg41/ddsFDoyuYrIkmFehz0HR2thPgQqMyQYb2OtB0WxsZ3BeG3+wpRb1vzl2UYBog8FfGhttFKjtAclnZYrRo9ryG9uG/FZQU4AEg8ZE9LjGMzTmqKXPLnlWVnIlQQTvxJf8ip7VgjZjyVPrjw1te5otM7RmP7xm+sK2Gv9I8Gi++BRbEkR9EBw8zRUcKxwp73xkaLiqQb+kGduJTNHG72zcW9LoJgqQxpP3/Tj//c3yB0tqzaml05/+orHLksVO+95kX7/7qgJvnjlrfr2Ggsyx0eoy9uPzN5SPd86aXggOsEKW2Prz7du3VID3/tzs/sSRs2w7ovVHKtjrX2pd7ZMlTxAYfBAL9jiDwfLkq55Tm7ifhMlTGPyCAs7RFRhn47JnlcB9RM5T97ASuZXIcVNuUDIndpDbdsfrqsOppeXl5Y+XVKdjFCTh+zGaVuj0d9zy05PPK3QzBamxdwtTCrzyg/2Rvf2EstUjordGwa/kx9mSJLr8mLLtCW8HHGJc2R5hS219IiF6PnTusOqcMl57gm0Z8kanKMAQg0qSyuZfn7zItsbGyO9QlnxY0eCuD1XL2ys/MsrQhltE7Ug0uFOzufJFE2PxBo/YAx8XPPdDwWN0MrDRYIZF0mSMKCNHgaIVFoBbNoLJ7tEQDKxGF0kcLQimojCZopv0OkNOyWCCg9XMVAi7ARJzQdM2QUh0gmBozjc3Skg6dSBRqDGYSUOu66Zg+I2fNZs/M3/f/Grl/XnyF1Gw3VKCez0PN5IUfFLqvgUN4C0qNqYs5YhPL+aVZYDE4IpUk57oSFnJm4FyCqqOE0jhY2SMyLFoo56zyo6becOS5UVDdj7Vih0zp+tcMhwRpBeLyqtIjlJKAIZSbI8SGSF3k0pA3mR5tHuwPFoa7N7reoq2bqCsAk1HqCu5uvI1n6JuRXI+S1Mco54YmYTwcn6Aeic+kssXi8XpXC4V3t7/ADuTNKaQJdScAAAAAElFTkSuQmCC"/> <text x="415" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="370">launch</text><text x="415" y="140" transform="scale(.1)" textLength="370">launch</text><text x="855" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="350">binder</text><text x="855" y="140" transform="scale(.1)" textLength="350">binder</text></g> </svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="117" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="117" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h30v20H0z"/><path fill="#007ec6" d="M30 0h87v20H30z"/><path fill="url(#b)" d="M0 0h117v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><svg x="4px" y="0px" width="22px" height="20px" viewBox="-2 0 28 24" style="background-color: #fff;border-radius: 1px;"><path style="fill:#ef9008;" d="M1.977,16.77c-2.667-2.277-2.605-7.079,0-9.357C2.919,8.057,3.522,9.075,4.49,9.691c-1.152,1.6-1.146,3.201-0.004,4.803C3.522,15.111,2.918,16.126,1.977,16.77z"/><path style="fill:#fdba18;" d="M12.257,17.114c-1.767-1.633-2.485-3.658-2.118-6.02c0.451-2.91,2.139-4.893,4.946-5.678c2.565-0.718,4.964-0.217,6.878,1.819c-0.884,0.743-1.707,1.547-2.434,2.446C18.488,8.827,17.319,8.435,16,8.856c-2.404,0.767-3.046,3.241-1.494,5.644c-0.241,0.275-0.493,0.541-0.721,0.826C13.295,15.939,12.511,16.3,12.257,17.114z"/><path style="fill:#ef9008;" d="M19.529,9.682c0.727-0.899,1.55-1.703,2.434-2.446c2.703,2.783,2.701,7.031-0.005,9.764c-2.648,2.674-6.936,2.725-9.701,0.115c0.254-0.814,1.038-1.175,1.528-1.788c0.228-0.285,0.48-0.552,0.721-0.826c1.053,0.916,2.254,1.268,3.6,0.83C20.502,14.551,21.151,11.927,19.529,9.682z"/><path style="fill:#fdba18;" d="M4.49,9.691C3.522,9.075,2.919,8.057,1.977,7.413c2.209-2.398,5.721-2.942,8.476-1.355c0.555,0.32,0.719,0.606,0.285,1.128c-0.157,0.188-0.258,0.422-0.391,0.631c-0.299,0.47-0.509,1.067-0.929,1.371C8.933,9.539,8.523,8.847,8.021,8.746C6.673,8.475,5.509,8.787,4.49,9.691z"/><path style="fill:#fdba18;" d="M1.977,16.77c0.941-0.644,1.545-1.659,2.509-2.277c1.373,1.152,2.85,1.433,4.45,0.499c0.332-0.194,0.503-0.088,0.673,0.19c0.386,0.635,0.753,1.285,1.181,1.89c0.34,0.48,0.222,0.715-0.253,1.006C7.84,19.73,4.205,19.188,1.977,16.77z"/></svg><text x="245" y="140" transform="scale(.1)" textLength="30"> </text><text x="725" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="770">Open in Colab</text><text x="725" y="140" transform="scale(.1)" textLength="770">Open in Colab</text></g> </svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="122" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="122" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#2f363d" d="M0 0h25v20H0z"/><path fill="#586069" d="M25 0h97v20H25z"/><path fill="url(#b)" d="M0 0h122v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZXNtb2tlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViIGljb248L3RpdGxlPjxwYXRoIGQ9Ik0xMiAuMjk3Yy02LjYzIDAtMTIgNS4zNzMtMTIgMTIgMCA1LjMwMyAzLjQzOCA5LjggOC4yMDUgMTEuMzg1LjYuMTEzLjgyLS4yNTguODItLjU3NyAwLS4yODUtLjAxLTEuMDQtLjAxNS0yLjA0LTMuMzM4LjcyNC00LjA0Mi0xLjYxLTQuMDQyLTEuNjFDNC40MjIgMTguMDcgMy42MzMgMTcuNyAzLjYzMyAxNy43Yy0xLjA4Ny0uNzQ0LjA4NC0uNzI5LjA4NC0uNzI5IDEuMjA1LjA4NCAxLjgzOCAxLjIzNiAxLjgzOCAxLjIzNiAxLjA3IDEuODM1IDIuODA5IDEuMzA1IDMuNDk1Ljk5OC4xMDgtLjc3Ni40MTctMS4zMDUuNzYtMS42MDUtMi42NjUtLjMtNS40NjYtMS4zMzItNS40NjYtNS45MyAwLTEuMzEuNDY1LTIuMzggMS4yMzUtMy4yMi0uMTM1LS4zMDMtLjU0LTEuNTIzLjEwNS0zLjE3NiAwIDAgMS4wMDUtLjMyMiAzLjMgMS4yMy45Ni0uMjY3IDEuOTgtLjM5OSAzLS40MDUgMS4wMi4wMDYgMi4wNC4xMzggMyAuNDA1IDIuMjgtMS41NTIgMy4yODUtMS4yMyAzLjI4NS0xLjIzLjY0NSAxLjY1My4yNCAyLjg3My4xMiAzLjE3Ni43NjUuODQgMS4yMyAxLjkxIDEuMjMgMy4yMiAwIDQuNjEtMi44MDUgNS42MjUtNS40NzUgNS45Mi40Mi4zNi44MSAxLjA5Ni44MSAyLjIyIDAgMS42MDYtLjAxNSAyLjg5Ni0uMDE1IDMuMjg2IDAgLjMxNS4yMS42OS44MjUuNTdDMjAuNTY1IDIyLjA5MiAyNCAxNy41OTIgMjQgMTIuMjk3YzAtNi42MjctNS4zNzMtMTItMTItMTIiLz48L3N2Zz4="/> <text x="735" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="870">View On GitHub</text><text x="735" y="140" transform="scale(.1)" textLength="870">View On GitHub</text></g> </svg>
\ No newline at end of file
......@@ -80,6 +80,7 @@ Community
introduction
user_guide
API <library/index>
Examples <gallery/gallery>
Contributing <dev_start_guide>
.. _Theano: https://github.com/Theano/Theano
......
......@@ -22,7 +22,6 @@ Modules
gradient
misc/pkl_utils
printing
sandbox/index
scalar/index
scan
sparse/index
......
......@@ -9,10 +9,6 @@
from pytensor.misc.pkl_utils import *
.. autofunction:: pytensor.misc.pkl_utils.dump
.. autofunction:: pytensor.misc.pkl_utils.load
.. autoclass:: pytensor.misc.pkl_utils.StripPickler
.. seealso::
......
.. _libdoc_sandbox:
==============================================================
:mod:`sandbox` -- Experimental Code
==============================================================
.. module:: sandbox
:platform: Unix, Windows
:synopsis: Experimental code
.. moduleauthor:: LISA
.. toctree::
:maxdepth: 1
linalg
.. ../../../../pytensor/sandbox/linalg/ops.py
.. ../../../../pytensor/sandbox/linalg
.. _libdoc_sandbox_linalg:
===================================================================
:mod:`sandbox.linalg` -- Linear Algebra Ops
===================================================================
.. module:: sandbox.linalg
:platform: Unix, Windows
:synopsis: Linear Algebra Ops
.. moduleauthor:: LISA
API
===
.. automodule:: pytensor.sandbox.linalg.ops
:members:
......@@ -477,7 +477,7 @@ them perfectly, but a `dscalar` otherwise.
you'll want to call.
.. autoclass:: pytensor.tensor.var._tensor_py_operators
.. autoclass:: pytensor.tensor.variable._tensor_py_operators
:members:
This mix-in class adds convenient attributes, methods, and support
......
User-agent: *
Sitemap: https://pytensor.readthedocs.io/en/latest/sitemap.xml
......@@ -145,7 +145,7 @@ might not have PyTensor installed, who are using a different Python version, or
you are planning to save your model for a long time (in which case version
mismatches might make it difficult to unpickle objects).
See :func:`pytensor.misc.pkl_utils.dump` and :func:`pytensor.misc.pkl_utils.load`.
See :meth:`pytensor.misc.pkl_utils.StripPickler.dump` and :meth:`pytensor.misc.pkl_utils.StripPickler.load`.
Long-Term Serialization
......
......@@ -43,6 +43,10 @@ dependencies:
- ipython
- pymc-sphinx-theme
- sphinx-design
- myst-nb
- matplotlib
- watermark
# code style
- ruff
# developer tools
......
......@@ -107,8 +107,6 @@ def add_tag_trace(thing: T, user_line: int | None = None) -> T:
"pytensor\\graph\\",
"pytensor/scalar/basic.py",
"pytensor\\scalar\\basic.py",
"pytensor/sandbox/",
"pytensor\\sandbox\\",
"pytensor/scan/",
"pytensor\\scan\\",
"pytensor/sparse/",
......
"""
Sphinx plugin to run generate a gallery for notebooks
Modified from the pymc project, which modified the seaborn project, which modified the mpld3 project.
"""
import base64
import json
import os
import shutil
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import sphinx
from matplotlib import image
logger = sphinx.util.logging.getLogger(__name__)
DOC_SRC = Path(__file__).resolve().parent.parent
DEFAULT_IMG_LOC = DOC_SRC / "doc" / "images" / "PyTensor_logo.png"
external_nbs = {}
HEAD = """
Example Gallery
===============
.. toctree::
:hidden:
"""
SECTION_TEMPLATE = """
.. _{section_id}:
{section_title}
{underlines}
.. grid:: 1 2 3 3
:gutter: 4
"""
ITEM_TEMPLATE = """
.. grid-item-card:: :doc:`{doc_name}`
:img-top: {image}
:link: {doc_reference}
:link-type: {link_type}
:shadow: none
"""
folder_title_map = {
"introduction": "Introduction",
"rewrites": "Graph Rewriting",
"scan": "Looping in Pytensor",
}
def create_thumbnail(infile, width=275, height=275, cx=0.5, cy=0.5, border=4):
"""Overwrites `infile` with a new file of the given size"""
im = image.imread(infile)
rows, cols = im.shape[:2]
size = min(rows, cols)
if size == cols:
xslice = slice(0, size)
ymin = min(max(0, int(cx * rows - size // 2)), rows - size)
yslice = slice(ymin, ymin + size)
else:
yslice = slice(0, size)
xmin = min(max(0, int(cx * cols - size // 2)), cols - size)
xslice = slice(xmin, xmin + size)
thumb = im[yslice, xslice]
thumb[:border, :, :3] = thumb[-border:, :, :3] = 0
thumb[:, :border, :3] = thumb[:, -border:, :3] = 0
dpi = 100
fig = plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi)
ax = fig.add_axes([0, 0, 1, 1], aspect="auto", frameon=False, xticks=[], yticks=[])
ax.imshow(thumb, aspect="auto", resample=True, interpolation="bilinear")
fig.savefig(infile, dpi=dpi)
plt.close(fig)
return fig
class NotebookGenerator:
"""Tools for generating an example page from a file"""
def __init__(self, filename, root_dir, folder):
self.folder = folder
self.basename = Path(filename).name
self.stripped_name = Path(filename).stem
self.image_dir = Path(root_dir) / "doc" / "_thumbnails" / folder
self.png_path = self.image_dir / f"{self.stripped_name}.png"
with filename.open(encoding="utf-8") as fid:
self.json_source = json.load(fid)
self.default_image_loc = DEFAULT_IMG_LOC
def extract_preview_pic(self):
"""By default, just uses the last image in the notebook."""
pic = None
for cell in self.json_source["cells"]:
for output in cell.get("outputs", []):
if "image/png" in output.get("data", []):
pic = output["data"]["image/png"]
if pic is not None:
return base64.b64decode(pic)
return None
def gen_previews(self):
preview = self.extract_preview_pic()
if preview is not None:
with self.png_path.open("wb") as buff:
buff.write(preview)
else:
logger.warning(
f"Didn't find any pictures in {self.basename}",
type="thumbnail_extractor",
)
shutil.copy(self.default_image_loc, self.png_path)
create_thumbnail(self.png_path)
def main(app):
logger.info("Starting thumbnail extractor.")
working_dir = Path.cwd()
os.chdir(app.builder.srcdir)
file = [HEAD]
for folder, title in folder_title_map.items():
file.append(
SECTION_TEMPLATE.format(
section_title=title, section_id=folder, underlines="-" * len(title)
)
)
thumbnail_dir = Path("_thumbnails") / folder
if not thumbnail_dir.exists():
Path.mkdir(thumbnail_dir, parents=True)
if folder in external_nbs.keys():
file += [
ITEM_TEMPLATE.format(
doc_name=descr["doc_name"],
image=descr["image"],
doc_reference=descr["doc_reference"],
link_type=descr["link_type"],
)
for descr in external_nbs[folder]
]
nb_paths = sorted(Path("gallery", folder).glob("*.ipynb"))
for nb_path in nb_paths:
nbg = NotebookGenerator(
filename=nb_path, root_dir=Path(".."), folder=folder
)
nbg.gen_previews()
file.append(
ITEM_TEMPLATE.format(
doc_name=Path(folder) / nbg.stripped_name,
image="/" + str(nbg.png_path),
doc_reference=Path(folder) / nbg.stripped_name,
link_type="doc",
)
)
with Path("gallery", "gallery.rst").open("w", encoding="utf-8") as f:
f.write("\n".join(file))
os.chdir(working_dir)
def setup(app):
app.connect("builder-inited", main)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论