diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 34e963579..1daf71acb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,15 +56,6 @@ repos: minimum_pre_commit_version: 2.8.0 name: Check notebooks have watermark (see Jupyter style guide from PyMC docs) types: [jupyter] - - id: add-tags - entry: python scripts/add_tags.py - language: python - name: Add PyMC3 classes used to tags - types: [jupyter] - additional_dependencies: - - nbqa==1.1.1 - - beautifulsoup4==4.9.3 - - myst_parser==0.13.7 - repo: https://github.com/mwouts/jupytext rev: v1.13.7 hooks: diff --git a/_templates/postcard_categories.html b/_templates/postcard_categories.html index 94e132108..053d86bfc 100644 --- a/_templates/postcard_categories.html +++ b/_templates/postcard_categories.html @@ -50,14 +50,14 @@

{% set t_bool = "tutorial" in post.category|map('string') %} - + {% set h_bool = "how-to" in post.category|map('string') %} - +
{% set e_bool = "explanation" in post.category|map('string') %} - + {% set r_bool = "reference" in post.category|map('string') %} - +
diff --git a/examples/conf.py b/examples/conf.py index 50d39ead6..466c5c091 100644 --- a/examples/conf.py +++ b/examples/conf.py @@ -69,6 +69,7 @@ {"name": "API", "url": "https://docs.pymc.io/en/stable/api.html"}, ], "page_sidebar_items": ["postcard", "page-toc", "edit-this-page"], + "google_analytics_id": "G-6KPRBTE6WV", } version = os.environ.get("READTHEDOCS_VERSION", "") version = version if "." in version else "main" @@ -99,12 +100,11 @@ # "sidebar-nav-bs.html", "postcard_categories.html", "tagcloud.html", - "sidebar-ethical-ads.html", ], } # ablog config -blog_baseurl = "https://examples.pymc.io" +blog_baseurl = "https://docs.pymc.io/projects/examples/en/latest/" blog_title = "PyMC Examples" blog_path = "blog" blog_authors = { @@ -145,22 +145,8 @@ bibtex_reference_style = "author_year" # OpenGraph config -# ogp_site_url = "https://predictablynoisy.com" -# ogp_image = "https://predictablynoisy.com/_static/profile-bw.png" +# use default readthedocs integration aka no config here -# codeautolink config -from IPython.core.inputtransformer2 import TransformerManager - - -def ipython_cell_transform(source): - out = TransformerManager().transform_cell(source) - return source, out - - -# codeautolink -codeautolink_custom_blocks = { - "ipython3": ipython_cell_transform, -} codeautolink_autodoc_inject = False codeautolink_concat_default = True @@ -172,7 +158,7 @@ def ipython_cell_transform(source): "mpl": ("https://matplotlib.org/", None), "numpy": ("https://numpy.org/doc/stable/", None), "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), - "pymc": ("https://docs.pymc.io/en/stable/", None), + "pymc": ("https://docs.pymc.io/en/latest/", None), "scipy": ("https://docs.scipy.org/doc/scipy/reference/", None), "xarray": ("http://xarray.pydata.org/en/stable/", None), } diff --git a/examples/index.md b/examples/index.md index 485cbe5a9..045bdd2b3 100644 --- a/examples/index.md +++ b/examples/index.md @@ -76,4 +76,5 @@ has tags in its metadata they are listed on the right sidebar after the {fas}`ta :hidden: blog +object_index/index ::: diff --git a/examples/object_index/distributions.rst b/examples/object_index/distributions.rst new file mode 100644 index 000000000..ae6890387 --- /dev/null +++ b/examples/object_index/distributions.rst @@ -0,0 +1,9 @@ +------------- +Distributions +------------- + +.. toctree:: + :maxdepth: 2 + + distributions/continuous + distributions/discrete diff --git a/examples/object_index/distributions/continuous.rst b/examples/object_index/distributions/continuous.rst new file mode 100644 index 000000000..e89671b54 --- /dev/null +++ b/examples/object_index/distributions/continuous.rst @@ -0,0 +1,14 @@ +Continuous +********** + +.. autolink-examples:: pymc.Beta + :type: class + :collapse: + +.. autolink-examples:: pymc.Exponential + :type: class + :collapse: + +.. autolink-examples:: pymc.Normal + :type: class + :collapse: diff --git a/examples/object_index/distributions/discrete.rst b/examples/object_index/distributions/discrete.rst new file mode 100644 index 000000000..17154cb86 --- /dev/null +++ b/examples/object_index/distributions/discrete.rst @@ -0,0 +1,6 @@ +Discrete +******** + +.. autolink-examples:: pymc.Poisson + :type: class + :collapse: diff --git a/examples/object_index/index.rst b/examples/object_index/index.rst new file mode 100644 index 000000000..2cd800629 --- /dev/null +++ b/examples/object_index/index.rst @@ -0,0 +1,20 @@ +================ +Object use index +================ + +This page is structured like the {ref}`PyMC API Reference page ` and +for each function in the API it lists all the examples where that PyMC object +is used. + +.. warning:: + + This page is still a proof of concept only. See + `pymc-examples#289 `_ + for more details. + +.. toctree:: + :maxdepth: 2 + + distributions + samplers + diff --git a/examples/object_index/samplers.rst b/examples/object_index/samplers.rst new file mode 100644 index 000000000..9bfeb8703 --- /dev/null +++ b/examples/object_index/samplers.rst @@ -0,0 +1,31 @@ +------------------ +Sampling functions +------------------ + +.. autolink-examples:: pymc.sample + :type: func + :collapse: + +.. autolink-examples:: pymc.sample_posterior_predictive + :type: func + :collapse: + +.. autolink-examples:: pymc.sample_prior_predictive + :type: func + :collapse: + +-------- +Samplers +-------- + +.. autolink-examples:: pymc.NUTS + :type: class + :collapse: + +.. autolink-examples:: pymc.Metropolis + :type: class + :collapse: + +.. autolink-examples:: pymc.Slice + :type: class + :collapse: diff --git a/scripts/__init__.py b/scripts/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/scripts/add_tags.py b/scripts/add_tags.py deleted file mode 100644 index b30d4ea72..000000000 --- a/scripts/add_tags.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -Automatically add tags to notebook based on which PyMC3 classes are used. - -E.g. if a notebook contains a section like - - :::{post} 30 Aug, 2021 - :tags: glm, mcmc, exploratory analysis - :category: beginner - ::: - -in a markdown cell, and uses the class pymc3.Categorical, then this script -will change that part of the markdown cell to: - - :::{post} 30 Aug, 2021 - :tags: glm, mcmc, exploratory analysis, pymc3.Categorical - :category: beginner - ::: - -Example of how to run this: - - python scripts/add_tags.py examples/getting_started.ipynb - -""" -import sys -from myst_parser.main import to_tokens, MdParserConfig -import subprocess -import os -import json -import argparse - - -def main(argv=None): - parser = argparse.ArgumentParser() - parser.add_argument("files", nargs="*") - args = parser.parse_args(argv) - - for file in args.files: - # Find which PyMC3 classes are used in the code. - output = subprocess.run( - [ - "nbqa", - "scripts.find_pm_classes", - file, - ], - stdout=subprocess.PIPE, - text=True, - ) - classes = {f"pymc3.{obj}" for obj in output.stdout.splitlines()} - - # Tokenize the notebook's markdown cells. - with open(file, encoding="utf-8") as fd: - content = fd.read() - notebook = json.loads(content) - markdown_cells = "\n".join( - [ - "\n".join(cell["source"]) - for cell in notebook["cells"] - if cell["cell_type"] == "markdown" - ] - ) - config = MdParserConfig(enable_extensions=["dollarmath", "colon_fence"]) - tokens = to_tokens(markdown_cells, config=config) - - # Find a ```{post} or :::{post} code block, and look for a line - # starting with tags: or :tags:. - tags = None - for token in tokens: - if token.tag == "code" and token.info.startswith("{post}"): - for line in token.content.splitlines(): - if line.startswith("tags: "): - line_start = "tags: " - original_line = line - tags = {tag.strip() for tag in line[len(line_start) :].split(",")} - break - elif line.startswith(":tags: "): - line_start = ":tags: " - original_line = line - tags = {tag.strip() for tag in line[len(line_start) :].split(",")} - break - - # If tags were found, then append any PyMC3 classes which might have - # been missed. - if tags is not None: - new_tags = ", ".join(sorted(tags.union(classes))) - new_line = f"{line_start}{new_tags}" - content = content.replace(original_line, new_line) - with open(file, "w", encoding="utf-8") as fd: - fd.write(content) - - -if __name__ == "__main__": - exit(main()) diff --git a/scripts/find_pm_classes.py b/scripts/find_pm_classes.py deleted file mode 100644 index 751b1caf8..000000000 --- a/scripts/find_pm_classes.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Find all PyMC3 classes used in script. - -This'll find both call of - - pymc3.Categorical(... - -and - - from pymc3 import Categorical - Categorical -""" -import ast -import sys - - -class ImportVisitor(ast.NodeVisitor): - def __init__(self, file): - self.imports = set() - - def visit_ImportFrom(self, node: ast.ImportFrom): - if node.module.split(".")[0] == "pymc3": - for name in node.names: - if name.name[0].isupper(): - self.imports.add(name.name) - - -class CallVisitor(ast.NodeVisitor): - def __init__(self, file, imports): - self.file = file - self.imports = imports - self.classes_used = set() - - def visit_Call(self, node: ast.Call): - if isinstance(node.func, ast.Attribute): - if isinstance(node.func.value, ast.Name): - if node.func.value.id in {"pm", "pymc3"}: - if node.func.attr[0].isupper(): - self.classes_used.add(node.func.attr) - elif isinstance(node.func, ast.Name): - if node.func.id in self.imports: - self.classes_used.add(node.func.id) - - -if __name__ == "__main__": - for file in sys.argv[1:]: - with open(file) as fd: - content = fd.read() - tree = ast.parse(content) - - import_visitor = ImportVisitor(file) - import_visitor.visit(tree) - - visitor = CallVisitor(file, import_visitor.imports) - visitor.visit(tree) - for i in visitor.classes_used: - print(i)