From 3b0628104c3863eb37d3b6b8325180496200248d Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 1 Jul 2026 14:37:18 -0600 Subject: [PATCH 1/9] docs: add formatting rules --- formatting-rules.md | 250 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 formatting-rules.md diff --git a/formatting-rules.md b/formatting-rules.md new file mode 100644 index 0000000..df0a7cc --- /dev/null +++ b/formatting-rules.md @@ -0,0 +1,250 @@ +# Formatting Rules + +The following rules apply to Python. Defer to industry-standard best practices +for code other than Python. + +1. Lines longer than 120 characters should be broken across multiple lines. + + For function calls, put each argument on its own line. The function call + + ```python + thisIsAnExampleOfALongLine(someVeryLongArgument1, someVeryLongArgument2, someVeryLongArgument3, someVeryLongArgument4, someVeryLongArgument5) + ``` + + should be broken like: + + ```python + thisIsAnExampleOfALongLine( + someVeryLongArgument1, + someVeryLongArgument2, + someVeryLongArgument3, + someVeryLongArgument4, + someVeryLongArgument5 + ) + ``` + + For long non-function call expressions, use parentheses and keep each + continued expression element on its own line. Binary operators should stay + at the end of continued lines. The expression + + ```python + someVeryLongResultName = someVeryLongArgument1 + someVeryLongArgument2 + someVeryLongArgument3 + someVeryLongArgument4 + someVeryLongArgument5 + ``` + + should be broken like: + + ```python + someVeryLongResultName = ( + someVeryLongArgument1 + + someVeryLongArgument2 + + someVeryLongArgument3 + + someVeryLongArgument4 + + someVeryLongArgument5 + ) + ``` + +2. Lines of code ending with a colon (`:`) should be followed immediately by + executable code, or by a docstring where docstrings are valid. The + class-definition exception is that one blank line may separate a class + docstring from the first method or class attribute. Blank lines inside a + multi-line docstring are allowed. + + The following are *bad* examples: + + ```python + def myFunction(*args): + + """myFunction does something!""" + + _myFunctionInternals(*args) + ``` + + ```python + def myFunction(*args): + """myFunction does something!""" + + _myFunctionInternals(*args) + ``` + + ```python + def myFunction(*args): + """myFunction does something! + + Arguments: + args: Some arguments. + """ + + _myFunctionInternals(*args) + ``` + + ```python + if myCondition: + + + # This is a trivial comment about doSomething. + + doSomething() + ``` + + ```python + class MyClass: + + """MyClass containerizes something useful.""" + + def __init__(self): + _doInit(self) + ``` + + ```python + class MyClass: + + def __init__(self): + _doInit(self) + ``` + + The following are *good* examples: + + ```python + def myFunction(*args): + _myFunctionInternals(*args) + ``` + + ```python + def myFunction(*args): + """myFunction does something!""" + _myFunctionInternals(*args) + ``` + + ```python + def myFunction(*args): + """myFunction does something! + + Arguments: + args: Some arguments. + """ + _myFunctionInternals(*args) + ``` + + ```python + if myCondition: + doSomething() # This is a non-trivial comment about doSomething. + ``` + + ```python + class MyClass: + """MyClass containerizes something useful.""" + + def __init__(self): + _doInit(self) + ``` + + ```python + class MyClass: + def __init__(self): + _doInit(self) + ``` + +3. Within a function body, never use more than one contiguous blank line. A + single blank line may be used to separate substantial logical sections, but + short straight-line functions should not contain blank lines. + + For example + + ```python + def myFunction(*args): + intermediate = _myFunctionStep1(*args) + + + result = _myFunctionStep2(intermediate) + + + return result + ``` + + should be replaced by: + + ```python + def myFunction(*args): + intermediate = _myFunctionStep1(*args) + result = _myFunctionStep2(intermediate) + return result + ``` + + For very simple data transformations, prefer returning the result directly. For + example: + + ```python + def myFunction(*args): + intermediate = _myFunctionStep1(*args) + return _myFunctionStep2(intermediate) + ``` + +4. Comments should be full sentences, with exactly one space following the `#`. + + Bad comments: + + ```python + #bad comment + ``` + + ```python + # another bad comment + ``` + + A good comment: + + ```python + # This is a good comment. + ``` + + `TODO` comments and other inline memos should use the same spacing and + sentence style: + + ```python + # TODO: This is a complete sentence directing some future reader. + ``` + +5. Standalone `#` comments immediately after a line ending with a colon (`:`) or + immediately after a docstring are discouraged but not forbidden. Prefer + moving that information into the docstring or closer to the code it + describes. + +6. Code that must be disabled should *not* be commented out with triple quotes + or `#`. Remove it, or place it behind an explicit condition when it must + remain available. + + Bad: + + ```python + def myFunction(): + # return 'Hello world!' + return None + ``` + + ```python + def myFunction(): + """ + return 'Hello world!' + """ + return None + ``` + + Acceptable when the disabled path is intentionally retained: + + ```python + def myFunction(useGreeting): + if useGreeting: + return 'Hello world!' + return None + ``` + + Better when the disabled code is no longer needed: + + ```python + def myFunction(): + return None + ``` + +7. Defer to general best practices for rules not otherwise specified here. + These rules should be compatible with, or reinforce, common Python style + conventions. From 12dff8e3ad38a5c4f7057e1089ec4bcf3472c448 Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 22 Jul 2026 13:31:20 -0600 Subject: [PATCH 2/9] packaging: migrate from setup.py -> pyproject.toml * and associated doc changes * minimizing maintenance footprint * no need to keep multiple sources on package versions up-to-date anymore --- .github/workflows/lint.yml | 5 +- .github/workflows/test.yml | 9 +-- .readthedocs.yaml | 9 ++- INSTALL.md | 115 ------------------------------ conftest.py | 0 docs/conf.py | 2 +- docs/dev_docs/HowToTutorial.md | 15 ++-- docs/requirements.txt | 12 ---- docs/user_docs/getting_started.md | 4 +- docs/user_docs/install.rst | 48 ++++++++++++- pyproject.toml | 92 ++++++++++++++++++++++++ requirements.txt | 3 - setup.cfg | 2 - setup.py | 46 ------------ 14 files changed, 162 insertions(+), 200 deletions(-) delete mode 100644 INSTALL.md delete mode 100644 conftest.py delete mode 100644 docs/requirements.txt create mode 100644 pyproject.toml delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e6eb990..c65d163 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,11 +20,10 @@ jobs: python-version: 3.9 cache: 'pip' # optional, adds caching for faster builds - - name: Install dependencies + - name: Install UncertainSCI run: | python -m pip install --upgrade pip - pip install flake8 - pip install -r requirements.txt + pip install --editable .["test"] - name: Lint with flake8 run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 84ab488..7384939 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,15 +27,10 @@ jobs: - name: Display Python version run: python -c "import sys; print(sys.version)" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pytest pytest-cov - pip install -r requirements.txt - - name: Install UncertainSCI run: | - pip install --editable ./ + python -m pip install --upgrade pip + pip install --editable .["test"] - name: Run tests and compute coverage run: | diff --git a/.readthedocs.yaml b/.readthedocs.yaml index d2c2ad2..f7d9006 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,6 +10,8 @@ build: os: ubuntu-22.04 tools: python: "3.10" + apt_packages: + - pandoc # Build documentation in the docs/ directory with Sphinx sphinx: @@ -23,6 +25,7 @@ formats: all # Optionally declare the Python requirements required to build your docs python: install: - - requirements: requirements.txt - - requirements: docs/requirements.txt - - path: . + - method: pip + path: . + extra_requirements: + - docs diff --git a/INSTALL.md b/INSTALL.md deleted file mode 100644 index 58eae2d..0000000 --- a/INSTALL.md +++ /dev/null @@ -1,115 +0,0 @@ -# UncertainSCI Python Environment -People that install UncertainSCI can be sensibly categorized as follows: -- **Users**: people who want to use UncertainSCI but do not need to meddle with its internals -- **Developers**: people who want to meddle with UncertainSCI's internals - -These instructions explain how to install UncertainSCI for both of these use cases. - -**Python Versions:** UncertainSCI officially supports Python versions 3.9 to 3.11. Newer Python may incidentally work, but at this time its support has not been tested. - -## Dependency Overview -This is an overview of the dependencies for UncertainSCI for various use cases. - -### Base Dependencies -At a minimum, UncertainSCI requires all packages in the project's requirements.txt. - -### Doc Dependencies -To build the docs, UncertainSCI requires -- pandoc -- sphinx -- sphinxcontrib-bibtex -- sphinx-markdown-tables -- nbsphinx -- recommonmark - -### Testing & Linting Dependencies -To test and lint the codebase, UncertainSCI requires -- flake8 -- pytest -- pytest-cov - -### Nice-to-haves -- ipython -- jupyter - -## Environment for Production -It is assumed your production environment does not need docs (e.g., pandoc), testing nor linting (e.g., flake8 nor pytest), nor interactive interfaces (e.g., jupyter). The packages and tools for these features are therefore omitted from these installation instructions. - -### With conda -1. Change to the repository root. -2. Set the `ENVNAME` and `PYVER` variables. On *NIX, - ```shell - export ENVNAME= - export PYVER= - ``` - On Windows, - ```shell - $ENVNAME="" - $PYVER="" - ``` -3. Create and activate the conda environment, then install UncertainSCI, - ```shell - conda create -n $ENVNAME python=$PYVER pandoc - conda activate $ENVNAME - python -m pip install . - ``` - -### Without conda -1. You have already installed the version of Python with which you wish to run UncertainSCI. -2. Change to the repository root. -3. Create and activate a virtual environment inside of which to run UncertainSCI, - ```shell - python -m venv .venv - ``` - Activate the virtual environment according to your system. -4. Install UncertainSCI, - ```shell - python -m pip install . - ``` - -## Environment for Development -It is assumed to develop UncertainSCI that you want to be able to build the docs, test and flake the codebase, and have reasonably modern interactive tools. - -### With conda -1. Change to the repository root. -2. Set the `ENVNAME` and `PYVER` variables. On *NIX, - ```shell - export ENVNAME= - export PYVER= - ``` - On Windows, - ```shell - $ENVNAME="" - $PYVER="" - ``` -3. Create and activate the conda environment, then install UncertainSCI, - ```shell - conda create -n $ENVNAME python=$PYVER pandoc - conda activate $ENVNAME - python -m pip install . - ``` -4. Install development helpers, - ```shell - python -m pip install pandoc sphinx sphinxcontrib-bibtex sphinx-markdown-tables nbsphinx recommonmark # docs - python -m pip install flake8 pytest pytest-cov # linting and testing - python -m pip install ipython jupyter # nice-to-haves - ``` - -### Without conda -1. You have already installed the version of Python with which you wish to run UncertainSCI. -2. Change to the repository root. -3. Create and activate a virtual environment inside of which to run UncertainSCI, - ```shell - python -m venv .venv - ``` - Activate the virtual environment according to your system. -4. Install UncertainSCI, - ```shell - python -m pip install . - ``` -5. Install development helpers, - ```shell - python -m pip install pandoc sphinx sphinxcontrib-bibtex sphinx-markdown-tables nbsphinx recommonmark # docs - python -m pip install flake8 pytest pytest-cov # linting and testing - python -m pip install ipython jupyter # nice-to-haves - ``` diff --git a/conftest.py b/conftest.py deleted file mode 100644 index e69de29..0000000 diff --git a/docs/conf.py b/docs/conf.py index 48099ca..9c541d2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -99,7 +99,7 @@ import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +# html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # 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, diff --git a/docs/dev_docs/HowToTutorial.md b/docs/dev_docs/HowToTutorial.md index 74ce189..c880bd8 100644 --- a/docs/dev_docs/HowToTutorial.md +++ b/docs/dev_docs/HowToTutorial.md @@ -23,7 +23,7 @@ Jess Tate To make a Tutorial for UncertainSCI, start with an up-to-date version of the code and documentation. Download the source code or clone the repository from [github](https://github.com/SCIInstitute/UncertainSCI.git). We suggest [creating a fork](#creating-your-uncertainsci-fork) of the repository so that you can track your changes and create pull requests to the UncertainSCI repository. UncertainSCI requirements are found [here](../user_docs/getting_started.html#system-requirements) #### Dependencies and Development Tools -UncertainSCI uses Read the Docs and Sphinx to build and host tutorial documentation. This platform converts markdown files to html for web viewing using Sphinx, a Python Library. Testing the new documentation may require building the web pages locally for viewing. This will require installing Python, pip, Sphinx, Recommonmark, and other packages in the [`docs/requirements.txt` file](https://github.com/SCIInstitute/UncertainSCI/blob/master/docs/requirements.txt). More information can be found in [the walkthorugh]( ) and on the [Sphinx documentation](https://www.sphinx-doc.org). +UncertainSCI uses Read the Docs and Sphinx to build and host tutorial documentation. This platform converts markdown files to html for web viewing using Sphinx, a Python Library. Testing the new documentation may require building the web pages locally for viewing. This will require installing Python, pip, Sphinx, Recommonmark, and the other packages in the `docs` optional dependency group. More information can be found in [the walkthorugh]( ) and on the [Sphinx documentation](https://www.sphinx-doc.org). #### Creating Your UncertainSCI Fork With your own github account, go to the [UncertainSCI Github page](https://github.com/SCIInstitute/UncertainSCI). Click the fork button on the upper right side of the page. It will ask you where to move the fork to, chose your own account. Once the repository is forked, clone it to your local machine with the following command. @@ -121,13 +121,18 @@ For the new tutorial to be visible on the [tutorials page](../tutorials/index.ht Testing the documentation locally involves building documentation website on your local machine using Sphinx and Recommonmark. These instructions are adapted from [Read the Docs' help page](https://docs.readthedocs.io/en/stable/intro/getting-started-with-sphinx.html). #### Installing Shpinx -To install the Sphinx, make sure that a relatively recent version of Python 3. Installing sphinx and other dependencies is easiest with [pip](https://pip.pypa.io/en/stable/installing/), just run +To install Sphinx, make sure that a relatively recent version of Python 3 is available. The notebook documentation also requires the standalone Pandoc executable. With conda, install Pandoc first: ``` -pip install -r requirements.txt +conda install -c conda-forge pandoc ``` -in the `UncertainSCI/docs` folder and the relavent python dependencies, including Sphinx, will be installed. -Alternatively, the dependencies listed in [`UncertainSCI/docs/requirements.txt` file](https://github.com/SCIInstitute/UncertainSCI/blob/master/docs/requirements.txt) could be installed seperately. +Then install the Python documentation dependencies with [pip](https://pip.pypa.io/en/stable/installing/): +``` +python -m pip install ".[docs]" +``` +in the repository root and the relavent python dependencies, including Sphinx, will be installed. + +Alternatively, install Pandoc with your operating system package manager and install the dependencies listed in the `docs` optional dependency group in `pyproject.toml` seperately. Please [ask](https://github.com/SCIInstitute/UncertainSCI/discussions) if you have any questions. diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 26f5ae6..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,12 +0,0 @@ -docutils -pygments -recommonmark -sphinx -sphinx-issues -sphinx-markdown-tables -sphinx-notfound-page -sphinx_rtd_theme>=1.3.0 -sphinxcontrib-bibtex -sphinx-markdown-tables -nbsphinx -ipykernel \ No newline at end of file diff --git a/docs/user_docs/getting_started.md b/docs/user_docs/getting_started.md index 92b100d..2b2a306 100644 --- a/docs/user_docs/getting_started.md +++ b/docs/user_docs/getting_started.md @@ -3,7 +3,7 @@ ## System Requirements -Requires Python 3 and modules listed in `requirements.txt` +Requires Python 3.9, 3.10, or 3.11. Runtime dependencies are installed automatically when installing UncertainSCI. ## Getting UncertainSCI @@ -15,7 +15,7 @@ The source code for UncertainSCI can be downloaded from the [Github page](https: ### Installing UncertainSCI From Source -UncertainSCI can be built from source code using the `setup.py` script. To call this script, navagate to the source root directory in a terminal window and run the command `pip install .` or `python -m pip install .` +UncertainSCI can be built from source code using the project metadata in `pyproject.toml`. To install it, navagate to the source root directory in a terminal window and run the command `pip install .` or `python -m pip install .` ## UncertainSCI Overview diff --git a/docs/user_docs/install.rst b/docs/user_docs/install.rst index 98759a5..a8599f1 100644 --- a/docs/user_docs/install.rst +++ b/docs/user_docs/install.rst @@ -1,4 +1,50 @@ Installation ============ -Use ``pip install -r requirements.txt`` to install dependencies. +UncertainSCI supports Python 3.9, 3.10, and 3.11. + +From PyPI +--------- + +Install the latest published package with: + +.. code-block:: shell + + python -m pip install UncertainSCI + +From Source +----------- + +From a `source checkout `_, install +the package with: + +.. code-block:: shell + + python -m pip install . + +Optional dependency targets are available for common tasks: + +.. code-block:: shell + + python -m pip install ".[docs]" + python -m pip install ".[interactive]" + python -m pip install ".[dev]" + +Building the notebook documentation also requires the standalone Pandoc +executable. With conda, install it with: + +.. code-block:: shell + + conda install -c conda-forge pandoc + +Alternatively, install Pandoc with your operating system package manager. + +Targets can be combined with a comma, such as: + +.. code-block:: shell + + python -m pip install ".[docs,interactive]" + +Note that the ``dev`` target includes all optional dependencies plus development +tools such as ``flake8``, ``pytest``, and ``pytest-cov``. If you're looking for +a quick start in development, use ``dev``. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..27f9228 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,92 @@ +[build-system] +requires = ["setuptools>=61"] +build-backend = "setuptools.build_meta" + +[project] +name = "UncertainSCI" +version = "1.0.1.1" +description = "A Non-invasive Uncertainty Quantification tool" +readme = { file = "README.md", content-type = "text/markdown" } +requires-python = ">=3.9,<3.12" +license = { text = "MIT" } +authors = [ + { name = "UncertainSCI Developers", email = "uncertainsci@sci.utah.edu" }, +] +keywords = ["Uncertainty Quantification", "Simulation"] +classifiers = [ + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Education", + "Intended Audience :: Healthcare Industry", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Medical Science Apps.", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Software Development :: Libraries", + "Operating System :: Android", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Operating System :: Unix", + "Operating System :: MacOS", +] +dependencies = [ + "matplotlib>=3.1.3", + "numpy>=1.25,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.*", + "packaging", + "scipy>=1.4.1", +] + +[project.optional-dependencies] +docs = [ + "docutils", + "ipykernel", + "nbsphinx", + "pygments", + "recommonmark", + "sphinx", + "sphinx-issues", + "sphinx-markdown-tables", + "sphinx-notfound-page", + "sphinx_rtd_theme>=1.3.0", + "sphinxcontrib-bibtex", +] +interactive = [ + "ipython", + "jupyter", +] +dev = [ + "docutils", + "flake8", + "ipykernel", + "ipython", + "jupyter", + "nbsphinx", + "pygments", + "pytest", + "pytest-cov", + "recommonmark", + "sphinx", + "sphinx-issues", + "sphinx-markdown-tables", + "sphinx-notfound-page", + "sphinx_rtd_theme>=1.3.0", + "sphinxcontrib-bibtex", +] + +[project.urls] +Homepage = "https://sci.utah.edu/sci-software/simulation/uncertainsci.html" +Documentation = "https://uncertainsci.readthedocs.io" +Source = "https://github.com/SCIInstitute/UncertainSCI" +Download = "https://github.com/SCIInstitute/UncertainSCI" + +[tool.setuptools] +package-dir = { "" = "." } + +[tool.setuptools.packages.find] +where = ["."] +include = ["UncertainSCI*"] diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 38f8343..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -matplotlib>=3.1.3 -numpy>=1.25 -scipy>=1.4.1 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 08aedd7..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -description_file = README.md diff --git a/setup.py b/setup.py deleted file mode 100644 index 7af1ab1..0000000 --- a/setup.py +++ /dev/null @@ -1,46 +0,0 @@ -from setuptools import setup, find_packages - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name='UncertainSCI', - version='1.0.1.1', - author='UncertainSCI Developers', - author_email='uncertainsci@sci.utah.edu', - packages=find_packages(), - package_dir={'': '.'}, - download_url=r'https://github.com/SCIInstitute/UncertainSCI', - description=r'A Non-invasive Uncertainty Quantification tool', - long_description= long_description, - long_description_content_type="text/markdown", - classifiers=[ - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "Intended Audience :: Education", - "Intended Audience :: Healthcare Industry", - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering", - "Topic :: Scientific/Engineering :: Medical Science Apps.", - "Topic :: Scientific/Engineering :: Information Analysis", - "Topic :: Software Development :: Libraries", - "Operating System :: Android", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Operating System :: Unix", - "Operating System :: MacOS" - ], - license='MIT', - keywords='Uncertainty Quantification, Simulation', - url=r'https://sci.utah.edu/sci-software/simulation/uncertainsci.html', - install_requires=[ - "matplotlib>=3.1.3", - "numpy>=1.25", - "scipy>=1.4.1" - ] - ) From a7d3938daf8b10f0882ea014dfec28a0ec270b13 Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 22 Jul 2026 14:53:24 -0600 Subject: [PATCH 3/9] docs: fix many doc problems and migrate to new doc tooling --- docs/about.md | 5 -- docs/conf.py | 111 ++++++++---------------- docs/dev_docs/HowToTutorial.md | 66 +++++++------- docs/dev_docs/contribute.md | 22 +++-- docs/index.rst | 14 +-- docs/references.rst | 4 + docs/tutorials/demos/pce_statistics.rst | 2 +- docs/tutorials/demos/simple_boxplots.md | 10 +-- docs/tutorials/models.md | 3 - docs/tutorials/parameters.md | 3 - docs/tutorials/template.md | 28 +++--- docs/user_docs/faq.md | 8 -- docs/user_docs/getting_started.md | 12 +-- docs/user_docs/specs.md | 8 -- pyproject.toml | 16 +--- 15 files changed, 105 insertions(+), 207 deletions(-) delete mode 100644 docs/about.md create mode 100644 docs/references.rst delete mode 100644 docs/user_docs/faq.md delete mode 100644 docs/user_docs/specs.md diff --git a/docs/about.md b/docs/about.md deleted file mode 100644 index 14445c6..0000000 --- a/docs/about.md +++ /dev/null @@ -1,5 +0,0 @@ - - -# UncertainSCI - -[UncertainSCI](https://github.com/SCIInstitute/UncertainSCI) diff --git a/docs/conf.py b/docs/conf.py index 9c541d2..e75ed8c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,18 +6,10 @@ # -- Path setup -------------------------------------------------------------- -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os +import pathlib import sys -import shlex - -sys.path.insert(0, os.path.abspath('../')) -import recommonmark -from recommonmark.transform import AutoStructify +sys.path.insert(0, str((pathlib.Path(__file__) / '../').resolve())) # -- Project information ----------------------------------------------------- @@ -26,109 +18,76 @@ copyright = '2020, The Scientific Computing and Imaging Institute at the University of Utah' author = 'Jake Bergquist, Dana Brooks, Zexin Liu, Rob MacLeod, Akil Narayan, Sumientra Rampersad, Lindsay Rupp, Jess Tate, Dan White' -github_doc_root = 'https://github.com/SCIInstitute/UncertainSCI/tree/master/docs' - -# The full version, including alpha/beta/rc tags +# FIXME: This versioning makes no sense: we should import it from a local import of +# module itself; also need to clarify what "version" vs "release" means and adopt +# [semver](https://semver.org/). version = '1.0' release = '1.0.1' # -- 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.intersphinx', 'sphinx.ext.napoleon', - 'recommonmark', + 'myst_nb', + 'sphinx_copybutton', 'sphinxcontrib.bibtex', - 'sphinx_markdown_tables', - 'nbsphinx' ] -# Path for bibtex files -bibtex_bibfiles = ['references.bib'] -bibtex_default_style = 'unsrt' -bibtex_encoding = 'latin' - - -# Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] source_suffix = { '.rst': 'restructuredtext', - '.md': 'markdown', + '.md': 'myst-nb', + '.ipynb': 'myst-nb', } -suppress_warnings = [ - 'nbsphinx', -] - -pygments_style = 'sphinx' - -# the master toctree doc master_doc = 'index' +language = 'en' -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = 'python' -# -- Options for HTML output ------------------------------------------------- +# -- Extension Configuration ------------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -# html_theme = 'alabaster' +# Path for bibtex files +bibtex_bibfiles = ['references.bib'] +bibtex_default_style = 'unsrt' +bibtex_encoding = 'latin' -#html_theme = 'groundwork' +pygments_style = 'sphinx' -# html_style = '/css/main.css' +intersphinx_mapping = { + 'python': ('https://docs.python.org/3', None), + 'numpy': ('https://numpy.org/doc/stable/', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/', None), + 'matplotlib': ('https://matplotlib.org/stable/', None), +} -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' +myst_enable_extensions = [ + 'amsmath', + 'colon_fence', + 'deflist', + 'dollarmath', + 'html_image', +] -#if not on_rtd: -import sphinx_rtd_theme - -html_theme = 'sphinx_rtd_theme' -# html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +myst_heading_anchors = 4 -# 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". +nb_execution_mode = 'auto' +# -- Options for HTML output ------------------------------------------------- -html_static_path = ['_static'] +html_theme = 'sphinx_rtd_theme' +html_static_path = ['_static'] html_css_files = ['css/main.css'] html_title = project - html_logo = '_static/UncertainSCI.png' - html_theme_options = { 'logo_only': True } - - -def setup(app): - app.add_config_value('recommonmark_config', { - #'url_resolver': lambda url: github_doc_root + url, - 'auto_toc_tree_section': 'Contents', - 'enable_math': False, - 'enable_inline_math': False, - 'enable_eval_rst': True, - }, True) - app.add_transform(AutoStructify) - - - diff --git a/docs/dev_docs/HowToTutorial.md b/docs/dev_docs/HowToTutorial.md index c880bd8..3985ca7 100644 --- a/docs/dev_docs/HowToTutorial.md +++ b/docs/dev_docs/HowToTutorial.md @@ -2,9 +2,6 @@ # Making Tutorials - This project was supported by grants from the National Institute of Biomedical Imaging and Bioengineering (U24EB029012) from the National Institutes of Health. @@ -20,10 +17,10 @@ Jess Tate ### Software requirements #### UncertainSCI -To make a Tutorial for UncertainSCI, start with an up-to-date version of the code and documentation. Download the source code or clone the repository from [github](https://github.com/SCIInstitute/UncertainSCI.git). We suggest [creating a fork](#creating-your-uncertainsci-fork) of the repository so that you can track your changes and create pull requests to the UncertainSCI repository. UncertainSCI requirements are found [here](../user_docs/getting_started.html#system-requirements) +To make a Tutorial for UncertainSCI, start with an up-to-date version of the code and documentation. Download the source code or clone the repository from [github](https://github.com/SCIInstitute/UncertainSCI.git). We suggest [creating a fork](#creating-your-uncertainsci-fork) of the repository so that you can track your changes and create pull requests to the UncertainSCI repository. UncertainSCI requirements are found [here](../user_docs/getting_started.md#system-requirements) #### Dependencies and Development Tools -UncertainSCI uses Read the Docs and Sphinx to build and host tutorial documentation. This platform converts markdown files to html for web viewing using Sphinx, a Python Library. Testing the new documentation may require building the web pages locally for viewing. This will require installing Python, pip, Sphinx, Recommonmark, and the other packages in the `docs` optional dependency group. More information can be found in [the walkthorugh]( ) and on the [Sphinx documentation](https://www.sphinx-doc.org). +UncertainSCI uses Read the Docs and Sphinx to build and host tutorial documentation. This platform converts markdown files to html for web viewing using Sphinx, a Python Library. Testing the new documentation may require building the web pages locally for viewing. This will require installing Python, pip, Sphinx, MyST-NB, and the other packages in the `docs` optional dependency group. More information can be found in [testing locally](#testing-locally) and on the [Sphinx documentation](https://www.sphinx-doc.org). #### Creating Your UncertainSCI Fork With your own github account, go to the [UncertainSCI Github page](https://github.com/SCIInstitute/UncertainSCI). Click the fork button on the upper right side of the page. It will ask you where to move the fork to, chose your own account. Once the repository is forked, clone it to your local machine with the following command. @@ -74,12 +71,8 @@ To make a new tutorial, a markdown file is required for the content of the tutor ### Markdown File The main file needed for a new tutorial is a markdown file. The file should have an file ending of *.md* and should be located in the `UncertainSCI/docs/tutorials/` directory. There is a [template file](https://github.com/SCIInstitute/UncertainSCI/blob/master/docs/tutorials/template.md) that can be used, or an existing tutorial like this one can be used. -If using math equations in a latex, a call to the mathjax server is required at the begining of the document: -``` - -``` +Math equations can be written directly in Markdown. MyST-NB and Sphinx handle +math rendering during the documentation build. Sphinx will build the menu and table of contents from the header names, and the document will be formated correctly if the proper markdown headings levels are used. For instance, the Document title should be the first content: ``` @@ -111,14 +104,14 @@ Additional files added to the `tutorials` folder should be minimized as much as ### Linking to New Tutorial -For the new tutorial to be visible on the [tutorials page](../tutorials/index.html#tutorials), add the filename to the list in the [`UncertainSCI/docs/tutorials/index.rst` file](https://github.com/SCIInstitute/UncertainSCI/blob/master/docs/tutorials/index.rst). +For the new tutorial to be visible on the [tutorials page](../tutorials/index.rst), add the filename to the list in the [`UncertainSCI/docs/tutorials/index.rst` file](https://github.com/SCIInstitute/UncertainSCI/blob/master/docs/tutorials/index.rst). ## Testing Documentation **This chapter describes how to test the look and content of the new tutorial. Test the generated github-pages with either a local Sphinx build or using the online build on Read the Docs.** ### Testing Locally -Testing the documentation locally involves building documentation website on your local machine using Sphinx and Recommonmark. These instructions are adapted from [Read the Docs' help page](https://docs.readthedocs.io/en/stable/intro/getting-started-with-sphinx.html). +Testing the documentation locally involves building documentation website on your local machine using Sphinx and MyST-NB. These instructions are adapted from [Read the Docs' help page](https://docs.readthedocs.io/en/stable/intro/getting-started-with-sphinx.html). #### Installing Shpinx To install Sphinx, make sure that a relatively recent version of Python 3 is available. The notebook documentation also requires the standalone Pandoc executable. With conda, install Pandoc first: @@ -181,18 +174,18 @@ And to reference (not working with Sphinx): ### Math -Math equations can be used in Markdown using [MathJax](http://docs.mathjax.org/en/latest/basic/mathematics.html). Mathjax will convert LaTex format: -``` -$$ \frac{\partial \rho}{\partial t} + \nabla \cdot \vec{j} = 0 \,. \label{eq:continuity} $$ -``` -$$ \frac{\partial \rho}{\partial t} + \nabla \cdot \vec{j} = 0 \,. \label{eq:continuity} $$ -It can also use MathJax specific tags: +Math equations can be used directly in Markdown. MyST-NB and Sphinx will render LaTeX-style math: ``` -\\[ x = {-b \pm \sqrt{b^2-4ac} \over 2a} \\] +$$ +\frac{\partial \rho}{\partial t} + \nabla \cdot \vec{j} = 0 \,. \label{eq:continuity} +$$ ``` -\\[ x = {-b \pm \sqrt{b^2-4ac} \over 2a} \\] -inline equations use the `\\(\mathbf{p}\\)` sytanx: \\(\mathbf{p}\\) +$$ +\frac{\partial \rho}{\partial t} + \nabla \cdot \vec{j} = 0 \,. \label{eq:continuity} +$$ + +Inline equations use dollar delimiters, as in ``$\mathbf{p}$``: $\mathbf{p}$ ### Citations @@ -203,21 +196,21 @@ Citations to include in the UncertainSCI docs can be included in the `UncertainS After the reference has been added to `UncertainSCI/docs/references.bib`, the final step is to include the command in the appropriate place. -The sphinxcontrib-bibtex is built to run with rst in Sphinx. However, it can be used in markdown using the [AutoStructify](https://recommonmark.readthedocs.io/en/latest/auto_structify.html) package. This will require using using an `eval_rst` block as follows: +The sphinxcontrib-bibtex is built to run with rst in Sphinx. However, it can be used in Markdown through MyST's `eval-rst` directive as follows: ```` -```eval_rst +```{eval-rst} The whole paragraph will need to be in the eval_rst block :cite:p:`JDT:Bur2020`. For multiple references: :cite:p:`JDT:Bur2020,gupta1983` ``` ```` -```eval_rst +```{eval-rst} The whole paragraph will need to be in the eval_rst block :cite:p:`JDT:Bur2020`. For multiple references: :cite:p:`JDT:Bur2020,gupta1983` ``` add a bibliography section ```` -```eval_rst +```{eval-rst} .. bibliography:: ../references.bib ``` ```` @@ -225,7 +218,7 @@ add a bibliography section TODO: move bibliography section back here when docutils and rtd theme play nicely together #### Bibliography -```eval_rst +```{eval-rst} .. bibliography:: ../references.bib ``` @@ -250,9 +243,9 @@ Including links in Markdown is simple, just use `<>` or `[]()`. For example, an ``` [Adding Content](#adding-content) ``` -When using internal links to sections, include the name of the section, all lower case and with `-` replacing spaces, and all special characters ommited. Linking to other pages in within the UncertainSCI documentation requires a relative path. [Demos](../tutorials/demos.html#demos) is: +When using internal links to sections, include the name of the section, all lower case and with `-` replacing spaces, and all special characters ommited. Linking to other pages in within the UncertainSCI documentation requires a relative path. [Demos](../tutorials/demos/index.rst) is: ``` -[Demos](../tutorials/demos.html#demos) +[Demos](../tutorials/demos/index.rst) ``` Links to other websites can include the full URL. Using `<>` will show the URL, `[]()` will hide it with other text. ``` @@ -264,7 +257,7 @@ Links to other websites can include the full URL. Using `<>` will show the URL, ### Tables -Tables can be used with normal markdown syntax with the [sphinx-markdown-tables](https://github.com/ryanfox/sphinx-markdown-tables) package +Tables can be used with normal Markdown syntax through MyST. ``` | Syntax | Description | @@ -279,7 +272,7 @@ Tables can be used with normal markdown syntax with the [sphinx-markdown-tables] | Paragraph | Text | -```eval_rst +```{eval-rst} +------------+------------+-----------+ | Header 1 | Header 2 | Header 3 | +============+============+===========+ @@ -293,13 +286,13 @@ Tables can be used with normal markdown syntax with the [sphinx-markdown-tables] ### Referencing Sphinx -To link the UncertainSCI API generated using Sphinx, Use this syntax: [`[text](../api_docs/pce.html#polynomial-chaos-expansions)`](../api_docs/pce.html#polynomial-chaos-expansions). +To link the UncertainSCI API generated using Sphinx, Use this syntax: [`[text](../api_docs/pce.rst)`](../api_docs/pce.rst). ## Content Guide -Try to be comprehensive, yet consise, and keep in mind the target audience for the tutorial. It is ok to write an advanced tutorial that builds on more basic knowledge, but please make this expectation clear and link to tutorials and materials that will help the reader develop the required understanding. Include code snippets, example scripts, screenshots, and videos as appropriate. Please use [existing tutorials](../tutorials/index.html#Contents) as try to match the style, flow, and level of detail they provide. +Try to be comprehensive, yet consise, and keep in mind the target audience for the tutorial. It is ok to write an advanced tutorial that builds on more basic knowledge, but please make this expectation clear and link to tutorials and materials that will help the reader develop the required understanding. Include code snippets, example scripts, screenshots, and videos as appropriate. Please use [existing tutorials](../tutorials/index.rst) as try to match the style, flow, and level of detail they provide. ## Supplemental Materials @@ -307,7 +300,7 @@ Some things to consider including with the tutorial. ### Example Scripts -Example scripts should be located in the `UncertainSCI/demos/` directory. Consider using one of the existing demos as a template and try to follow the coding standards outlined in the [contribution guide](contribute.html). +Example scripts should be located in the `UncertainSCI/demos/` directory. Consider using one of the existing demos as a template and try to follow the coding standards outlined in the [contribution guide](contribute.md). ### Movies @@ -337,6 +330,5 @@ Datasets should be located serperately, unless the size is small. Please [ask]( ### Bibliography -```eval_rst -.. bibliography:: ../references.bib -``` + +The documentation bibliography is centralized in the references page. diff --git a/docs/dev_docs/contribute.md b/docs/dev_docs/contribute.md index 1b6e17a..0ac4a34 100644 --- a/docs/dev_docs/contribute.md +++ b/docs/dev_docs/contribute.md @@ -4,25 +4,25 @@ Thank you for you contributions to UncertainSCI! We welcome and appreciate and ## Community Support -A great way to start contributing to UncertainSCI is to submit and answer questions on our [discussion board]. +A great way to start contributing to UncertainSCI is to submit and answer questions on our [discussion board](https://github.com/SCIInstitute/UncertainSCI/discussions). -Other ways of contacting the communtity are located on our [support page](../user_docs/support.html#support) +Other ways of contacting the communtity are located on our [support page](../user_docs/support.md). ## Bugs and Features -We encourage users to report any bugs they find and request any features they'd like as a [GitHub issue]. If you would like to tackle any issues, please volunteer by commenting in the issue or [assigning yourself]. +We encourage users to report any bugs they find and request any features they'd like as a [GitHub issue](https://github.com/SCIInstitute/UncertainSCI/issues). If you would like to tackle any issues, please volunteer by commenting in the issue or [assigning yourself](https://docs.github.com/en/issues/tracking-your-work-with-issues/assigning-issues-and-pull-requests-to-other-github-users). ## Make a Tutorial -If you have a tutorial you'd like to share, we'd love to have it. We have a [Tutorial Tutorial](HowToTutorial.html) to explain how to make and contribute tutorials. +If you have a tutorial you'd like to share, we'd love to have it. We have a [Tutorial Tutorial](HowToTutorial.md) to explain how to make and contribute tutorials. ## Contribute Code We appreciate to code maintenance and development that our community can provide. If you'd like to submit a bug fix, dependency update, or an added feature, please keep in mind the [style guide](#style-guide), create a [fork](#fork-repo) of the UncertainSCI repo, and use a [Pull Request](#pull-requests) to add it to UncertainSCI. -It is best practice to make sure that there is [GitHub issue] to describe the required changes to the code, and having these issues documented become more important with the scope of the additions and changes. Possible additions can also be discussed on our [discussion board]. +It is best practice to make sure that there is a [GitHub issue](https://github.com/SCIInstitute/UncertainSCI/issues) to describe the required changes to the code, and having these issues documented become more important with the scope of the additions and changes. Possible additions can also be discussed on our [discussion board](https://github.com/SCIInstitute/UncertainSCI/discussions). ### Fork Repo @@ -64,12 +64,12 @@ Please see the [Github help page](https://help.github.com) for more information. ### Pull Requests -With the contributions added to a branch on a fork of UncertainSCI, it is ready to create a [pull request]. While this can be done in many ways, the easiest is probably through the web page of the forked repo. When navigating to the main page, it will usually display the a `contribute` button near the top of the page for recently updated branches. This is a shortcut to creating a pull request to the main repo and branch. Alternatively, a pull request can be created from the pull request tab of either the main repo or the fork. Before making a pull request, please make sure that you've tried your best to follow the [style guide](#style-guide), and that the branch is up-to-date with the lastest master branch. Also, please update or add [testing](#testing) as appropriate. +With the contributions added to a branch on a fork of UncertainSCI, it is ready to create a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests). While this can be done in many ways, the easiest is probably through the web page of the forked repo. When navigating to the main page, it will usually display the a `contribute` button near the top of the page for recently updated branches. This is a shortcut to creating a pull request to the main repo and branch. Alternatively, a pull request can be created from the pull request tab of either the main repo or the fork. Before making a pull request, please make sure that you've tried your best to follow the [style guide](#style-guide), and that the branch is up-to-date with the lastest master branch. Also, please update or add [testing](#testing) as appropriate. -Once the pull request is created, the maintainers of UncertainSCI will assign reviewers who will test and review the code to ensure that it meets the requirements of the style guide and is stable. It is best to limit the size of each pull request to facilitate review, so if there are major new additions, please add a [GitHub issue] to track the progress. +Once the pull request is created, the maintainers of UncertainSCI will assign reviewers who will test and review the code to ensure that it meets the requirements of the style guide and is stable. It is best to limit the size of each pull request to facilitate review, so if there are major new additions, please add a [GitHub issue](https://github.com/SCIInstitute/UncertainSCI/issues) to track the progress. -## Syle Guide +## Style Guide If you are editing code, take a few minutes to look at the code around you and determine its style. Please try to keep the style of new code as similar as possible to unchanged code to avoid jarring inconsistencies in the style. @@ -92,16 +92,14 @@ If you are editing code, take a few minutes to look at the code around you and d ### Demos and Usecases -New demos and usecases are always welcome. Please add self-contained scripts demonstrating core functionality to the [demos folder]. Demos that require external packages can be located in seperate repos, such as this [UQ BEM heart position usecase] +New demos and usecases are always welcome. Please add self-contained scripts demonstrating core functionality to the [demos folder](https://github.com/SCIInstitute/UncertainSCI/tree/master/demos). Demos that require external packages can be located in seperate repos, such as this [UQ BEM heart position usecase](https://github.com/SCIInstitute/UQExampleBEMHeartPosition) ### Testing -In addition to demos, please add unit testing to new function contributed to UncertainSCI using pytest. Unit test should be placed in the [test folder], which contains several tests to use as examples. To run the test, use the command: +In addition to demos, please add unit testing to new function contributed to UncertainSCI using pytest. Unit test should be placed in the [test folder](https://github.com/SCIInstitute/UncertainSCI/tree/master/tests), which contains several tests to use as examples. To run the test, use the command: ``` pytest tests ``` - - diff --git a/docs/index.rst b/docs/index.rst index d84d5b5..c21866c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,12 +23,13 @@ Currently implemented in UncertainSCI is Polynomial Chaos Expansion (PCE) with a :maxdepth: 2 :caption: Contents: + user_docs/install user_docs/getting_started user_docs/support tutorials/index dev_docs/index api_docs/index - + references Contributors =============== @@ -39,20 +40,9 @@ Acknowledgements This project was supported by grants from the National Institute of Biomedical Imaging and Bioengineering (U24EB029012) from the National Institutes of Health. -.. - TODO: move bibliography back here when the docutils and sphinx_rtd_theme play nicely together - - Indices and Tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` - - -Bibliography -================ -.. bibliography:: ./references.bib - :cited: - diff --git a/docs/references.rst b/docs/references.rst new file mode 100644 index 0000000..b065c39 --- /dev/null +++ b/docs/references.rst @@ -0,0 +1,4 @@ +References +========== + +.. bibliography:: references.bib diff --git a/docs/tutorials/demos/pce_statistics.rst b/docs/tutorials/demos/pce_statistics.rst index e592289..546be6c 100644 --- a/docs/tutorials/demos/pce_statistics.rst +++ b/docs/tutorials/demos/pce_statistics.rst @@ -1,5 +1,5 @@ PCE Statistics -===== +============== Building PCE emulators ---------------------- diff --git a/docs/tutorials/demos/simple_boxplots.md b/docs/tutorials/demos/simple_boxplots.md index f93f53a..58c6ec4 100644 --- a/docs/tutorials/demos/simple_boxplots.md +++ b/docs/tutorials/demos/simple_boxplots.md @@ -1,8 +1,5 @@ # Simple example with boxplots - This project was supported by grants from the National Institute of Biomedical Imaging and Bioengineering (U24EB029012) from the National Institutes of Health. @@ -32,11 +29,11 @@ b = 0.05 f = ishigami_function(a,b) ``` -This generates a function `f` of three parameters. See the [`[Ishigami Function]`](../models.html#ishigami-function) description for more information about this model. +This generates a function `f` of three parameters. See the [Ishigami Function](../models.md#ishigami-function) description for more information about this model. ### Parameter distributions -A more complete discussion of creating parameter distributions is given in the [`[Defining Random Parameters]`](../parameters.html) tutorial. Here we only present a simple setup. We will assume that our three parameters, +A more complete discussion of creating parameter distributions is given in the [Defining Random Parameters](../parameters.md) tutorial. Here we only present a simple setup. We will assume that our three parameters, \begin{align} \mathbf{P} = (P_1, P_2, P_3) \in \mathbb{R}^3 @@ -56,7 +53,7 @@ p3 = BetaDistribution(alpha=1, beta=1, domain=bounds) p = TensorialDistribution(distributions=[p1, p2, p3]) ``` -We have used the fact that a `BetaDistribution` with parameters `alpha=beta=1` corresponds to the uniform distribution. See [`[Beta Distribution]`](../parameters.html#beta-distribution) for more information about the Beta distribution. Note also that we have individually defined the parameters, and then combined them into a single three-dimensional random parameter using the `TensorialDistribution` command. +We have used the fact that a `BetaDistribution` with parameters `alpha=beta=1` corresponds to the uniform distribution. See [Beta Distribution](../parameters.md#beta-distribution) for more information about the Beta distribution. Note also that we have individually defined the parameters, and then combined them into a single three-dimensional random parameter using the `TensorialDistribution` command. ### Defining polynomial order @@ -107,4 +104,3 @@ We generate boxplots using standard Monte Carlo sampling and also sampling from Boxplots are generated using the `matplotlib` boxplot feature. ![Boxplot comparisons](../../_static/simple_boxplots.png "Boxplots") - diff --git a/docs/tutorials/models.md b/docs/tutorials/models.md index e97ffea..894250b 100644 --- a/docs/tutorials/models.md +++ b/docs/tutorials/models.md @@ -1,8 +1,5 @@ # Built-in forward models - This project was supported by grants from the National Institute of Biomedical Imaging and Bioengineering (U24EB029012) from the National Institutes of Health. diff --git a/docs/tutorials/parameters.md b/docs/tutorials/parameters.md index 23aa773..f21f999 100644 --- a/docs/tutorials/parameters.md +++ b/docs/tutorials/parameters.md @@ -1,8 +1,5 @@ # Defining random parameters - This project was supported by grants from the National Institute of Biomedical Imaging and Bioengineering (U24EB029012) from the National Institutes of Health. diff --git a/docs/tutorials/template.md b/docs/tutorials/template.md index 8f854f3..5951c50 100644 --- a/docs/tutorials/template.md +++ b/docs/tutorials/template.md @@ -1,8 +1,5 @@ # Template for Tutorial - This project was supported by grants from the National Institute of Biomedical Imaging and Bioengineering (U24EB029012) from the National Institutes of Health. @@ -41,30 +38,27 @@ Example Subsection. These can go to 6 `#`'s. Subsections are optional for tab ![Example for including an image in tutorial.](../_static/UncertainSCI.png "UncertainSCI example image") ### Math -Math equations use [MathJax](http://docs.mathjax.org/en/latest/basic/mathematics.html). This requires the inclusion of this near the beginning of the document: -``` - -``` +Math equations can be written directly in Markdown. MyST-NB and Sphinx handle math rendering during the documentation build. Example equation: -\\[ x = {-b \pm \sqrt{b^2-4ac} \over 2a} \\] -$$ \frac{\partial \rho}{\partial t} + \nabla \cdot \vec{j} = 0 \,. \label{eq:continuity} $$ -inline equations use the `\\(\mathbf{p}\\)` sytanx: \\(\mathbf{p}\\) +$$ +\frac{\partial \rho}{\partial t} + \nabla \cdot \vec{j} = 0 \,. \label{eq:continuity} +$$ + +Inline equations use dollar delimiters, as in ``$ a^2 + b^2 = c^2 $``, which displays as $a^2 + b^2 = c^2$. ### Citations -Sphinx has a built in citation manager for bibtex: [sphinxcontrib-bibtex](https://sphinxcontrib-bibtex.readthedocs.io/en/latest/). Works well for RST, but we are still working on it for markdown. The sphinxcontrib-bibtex is built to run with rst in Sphinx. However, it can be used in markdown using the [AutoStructify](https://recommonmark.readthedocs.io/en/latest/auto_structify.html) package. +Sphinx has a built in citation manager for bibtex: [sphinxcontrib-bibtex](https://sphinxcontrib-bibtex.readthedocs.io/en/latest/). Use MyST's `eval-rst` directive when a Markdown page needs an rst-only citation directive. -```eval_rst +```{eval-rst} The whole paragraph will need to be in the eval_rst block :cite:p:`JDT:Bur2020`. For multiple references: :cite:p:`JDT:Bur2020,gupta1983` ``` add a bibliography section ```` -```eval_rst +```{eval-rst} .. bibliography:: ``` ```` @@ -88,7 +82,7 @@ External link: , or [Markdown](https://www.markdo ### Tables -Tables can be used with normal markdown syntax with the [sphinx-markdown-tables](https://github.com/ryanfox/sphinx-markdown-tables) package +Tables can be used with normal Markdown syntax through MyST. ``` | Syntax | Description | @@ -106,7 +100,7 @@ Tables can be used with normal markdown syntax with the [sphinx-markdown-tables] ### Referencing Sphynx -To link the UncertainSCI API generated using Sphynx, Use this syntax: [`[text](../api_docs/pce.html#polynomial-chaos-expansions)`](../api_docs/pce.html#polynomial-chaos-expansions) +To link the UncertainSCI API generated using Sphinx, use this syntax: [`[text](../api_docs/pce.rst)`](../api_docs/pce.rst) diff --git a/docs/user_docs/faq.md b/docs/user_docs/faq.md deleted file mode 100644 index 6adcb0f..0000000 --- a/docs/user_docs/faq.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "FAQs" -category: null -layout: default ---- - - -### FAQs content... diff --git a/docs/user_docs/getting_started.md b/docs/user_docs/getting_started.md index 2b2a306..7189f1c 100644 --- a/docs/user_docs/getting_started.md +++ b/docs/user_docs/getting_started.md @@ -19,7 +19,7 @@ UncertainSCI can be built from source code using the project metadata in `pyproj ## UncertainSCI Overview -Users can evaluate the effect of input uncertainty on forward models with UncertainSCI's implementation of [polynomial Chaos expansion (PCE)](../api_docs/pce.html). The pipeline for the process is shown in the following image: +Users can evaluate the effect of input uncertainty on forward models with UncertainSCI's implementation of [polynomial Chaos expansion (PCE)](../api_docs/pce.rst). The pipeline for the process is shown in the following image: ![User pipeline for UncertainSCI. After the user inputs parameter distributions, UncertainSCI will compute an efficient sampling scheme. The parameter samples are run through the targeted modeling pipeline, which can be implemented in external software tools. The computed solutions are collected and compiled into relevant statistics with UncertainSCI.](../../paper/UncertainSCI_pipeline.png) @@ -45,7 +45,7 @@ Distribution type of the parameters may effect the number of samples, but to a m #### Running UncertainSCI for Sample Generation -With the model setup, the user will need to setup the input parameter distribution using UncertainSCI's [distribution datatype](../api_docs/distributions.html). While there are a few distribution types to choose from, the [Beta distribution](../api_docs/distributions.html#UncertainSCI.distributions.BetaDistribution) is a common choice. If we had three input parameters, we can define a different beta distribution for each, thus: +With the model setup, the user will need to setup the input parameter distribution using UncertainSCI's [distribution datatype](../api_docs/distributions.rst). While there are a few distribution types to choose from, the {class}`UncertainSCI.distributions.BetaDistribution` is a common choice. If we had three input parameters, we can define a different beta distribution for each, thus: ```Python from UncertainSCI.distributions import BetaDistribution @@ -62,7 +62,7 @@ After the input parameters are set, we can generate a parameter sampling that wi # # Polynomial order order = 5 ``` -Now we can create the [PCE object](../api_docs/pce.html#module-UncertainSCI.pce) and generate parameter samples: +Now we can create the {class}`UncertainSCI.pce.PolynomialChaosExpansion` object and generate parameter samples: ```Python from UncertainSCI.pce import PolynomialChaosExpansion @@ -118,13 +118,13 @@ piechart_sensitivity(pce) plt.show() ``` -The [API documentation](../api_docs/index.html) explains the implementation of UncertainSCI in more detail. +The [API documentation](../api_docs/index.rst) explains the implementation of UncertainSCI in more detail. ## Running UncertainSCI Demos -There are a number of demos included with UncertainSCI to test it's installation and to demonstrate its use. The [previous description](#running-uncertainsci) can be found as a notebook with some more details [here](../tutorials/notebooks/build_pce.html) and as a script in `demos/build_pce.py`. +There are a number of demos included with UncertainSCI to test it's installation and to demonstrate its use. The [previous description](#running-uncertainsci) can be found as a notebook with some more details [here](../tutorials/notebooks/build_pce.ipynb) and as a script in `demos/build_pce.py`. The demo scripts can be a way to quickly test the installation. Make sure that UncertainSCI is [installed](#getting-uncertainsci), then simply call the script with python using the command `python demos/build_pce.py`. Other demos can be run similarily. -We have included a number of demos and [tutorials](../tutorials/index.html) to teach users how to use UncertainSCI with various examples. +We have included a number of demos and [tutorials](../tutorials/index.rst) to teach users how to use UncertainSCI with various examples. diff --git a/docs/user_docs/specs.md b/docs/user_docs/specs.md deleted file mode 100644 index 1ab6e6d..0000000 --- a/docs/user_docs/specs.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Specifications" -category: null -layout: default ---- - - -### Specifications content... diff --git a/pyproject.toml b/pyproject.toml index 27f9228..4b64a17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,15 +43,11 @@ dependencies = [ [project.optional-dependencies] docs = [ - "docutils", "ipykernel", - "nbsphinx", + "myst-nb", "pygments", - "recommonmark", "sphinx", - "sphinx-issues", - "sphinx-markdown-tables", - "sphinx-notfound-page", + "sphinx-copybutton", "sphinx_rtd_theme>=1.3.0", "sphinxcontrib-bibtex", ] @@ -60,20 +56,16 @@ interactive = [ "jupyter", ] dev = [ - "docutils", "flake8", "ipykernel", "ipython", "jupyter", - "nbsphinx", + "myst-nb", "pygments", "pytest", "pytest-cov", - "recommonmark", "sphinx", - "sphinx-issues", - "sphinx-markdown-tables", - "sphinx-notfound-page", + "sphinx-copybutton", "sphinx_rtd_theme>=1.3.0", "sphinxcontrib-bibtex", ] From 55a4c0412521b077f322e29b64089b54c27d9d8a Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 22 Jul 2026 14:54:21 -0600 Subject: [PATCH 4/9] docs: remove evaluation(s) tutorial notebooks * executed by myst_nb at doc build * also fix links in notebooks --- docs/tutorials/notebooks/adapt_pce.ipynb | 3097 +--------------------- docs/tutorials/notebooks/build_pce.ipynb | 143 +- 2 files changed, 43 insertions(+), 3197 deletions(-) diff --git a/docs/tutorials/notebooks/adapt_pce.ipynb b/docs/tutorials/notebooks/adapt_pce.ipynb index 7c0f870..ec3c352 100644 --- a/docs/tutorials/notebooks/adapt_pce.ipynb +++ b/docs/tutorials/notebooks/adapt_pce.ipynb @@ -12,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "927510c7", "metadata": {}, "outputs": [], @@ -62,7 +62,7 @@ "source": [ "### Define Forward model\n", "\n", - "The model in this example is a 1D laplacian ODE. See the `laplace_ode_1d` [method](../models.html) or `UncertainSCI/model_examples.py` for details.\n", + "The model in this example is a 1D laplacian ODE. See the `laplace_ode_1d` [method](../models.md) or `UncertainSCI/model_examples.py` for details.\n", "\n", "$$\n", "-\\frac{d}{dx} a(x,p) \\cdot \\frac{d}{dx} u(x,p) = f(x)\n", @@ -87,7 +87,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "303bbbe3", "metadata": {}, "outputs": [], @@ -123,7 +123,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "26f5e93b", "metadata": {}, "outputs": [], @@ -143,12 +143,12 @@ "source": [ "### Initial Expressivity of the PCE\n", "\n", - "This example uses a different setup than you might see in [other examples](./build_pce.html). Other setups will be equivalent for many non-adaptive cases, but it is useful to operate with the index set in this example. Another important distinction that is necessary for the adaptive case is supplying the model as a lambda function to the PCE object. " + "This example uses a different setup than you might see in [other examples](./build_pce.ipynb). Other setups will be equivalent for many non-adaptive cases, but it is useful to operate with the index set in this example. Another important distinction that is necessary for the adaptive case is supplying the model as a lambda function to the PCE object. " ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "aa4edbf2", "metadata": {}, "outputs": [], @@ -161,7 +161,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "55932726", "metadata": {}, "outputs": [], @@ -185,92 +185,10 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "id": "7c289e10", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "new indices: 1, new samples: 4\n", - "old residual: 1.418e-09, old loocv: 4.334e-06\n", - "new residual: 1.424e-09, new loocv: 4.259e-06\n", - "new indices: 1, new samples: 4\n", - "old residual: 1.424e-09, old loocv: 4.259e-06\n", - "new residual: 1.446e-09, new loocv: 4.243e-06\n", - "new indices: 1, new samples: 4\n", - "old residual: 1.446e-09, old loocv: 4.243e-06\n", - "new residual: 9.789e-10, new loocv: 2.748e-06\n", - "new indices: 1, new samples: 4\n", - "old residual: 9.789e-10, old loocv: 2.748e-06\n", - "new residual: 9.637e-10, new loocv: 2.499e-06\n", - "new indices: 1, new samples: 4\n", - "old residual: 9.637e-10, old loocv: 2.499e-06\n", - "new residual: 6.000e-10, new loocv: 2.085e-06\n", - "new indices: 1, new samples: 4\n", - "old residual: 6.000e-10, old loocv: 2.085e-06\n", - "new residual: 2.177e-10, new loocv: 1.412e-06\n", - "new indices: 1, new samples: 4\n", - "old residual: 2.177e-10, old loocv: 1.412e-06\n", - "new residual: 9.205e-11, new loocv: 9.741e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 9.205e-11, old loocv: 9.741e-07\n", - "new residual: 6.980e-11, new loocv: 8.633e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 6.980e-11, old loocv: 8.633e-07\n", - "new residual: 6.651e-11, new loocv: 8.321e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 6.651e-11, old loocv: 8.321e-07\n", - "new residual: 7.158e-11, new loocv: 8.528e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 7.158e-11, old loocv: 8.528e-07\n", - "new residual: 4.889e-11, new loocv: 6.559e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 4.889e-11, old loocv: 6.559e-07\n", - "new residual: 4.642e-11, new loocv: 6.220e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 4.642e-11, old loocv: 6.220e-07\n", - "new residual: 4.520e-11, new loocv: 6.129e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 4.520e-11, old loocv: 6.129e-07\n", - "new residual: 4.639e-11, new loocv: 6.159e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 4.639e-11, old loocv: 6.159e-07\n", - "new residual: 3.642e-11, new loocv: 4.480e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 3.642e-11, old loocv: 4.480e-07\n", - "new residual: 3.216e-11, new loocv: 3.926e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 3.216e-11, old loocv: 3.926e-07\n", - "new residual: 3.096e-11, new loocv: 3.793e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 3.096e-11, old loocv: 3.793e-07\n", - "new residual: 2.029e-11, new loocv: 3.257e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 2.029e-11, old loocv: 3.257e-07\n", - "new residual: 7.890e-12, new loocv: 2.240e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 7.890e-12, old loocv: 2.240e-07\n", - "new residual: 2.909e-12, new loocv: 1.355e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 2.909e-12, old loocv: 1.355e-07\n", - "new residual: 1.907e-12, new loocv: 1.112e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 1.907e-12, old loocv: 1.112e-07\n", - "new residual: 1.733e-12, new loocv: 1.058e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 1.733e-12, old loocv: 1.058e-07\n", - "new residual: 1.723e-12, new loocv: 1.050e-07\n", - "new indices: 1, new samples: 4\n", - "old residual: 1.723e-12, old loocv: 1.050e-07\n", - "new residual: 1.540e-12, new loocv: 9.896e-08\n", - "new indices: 1, new samples: 4\n", - "old residual: 1.540e-12, old loocv: 9.896e-08\n", - "new residual: 1.594e-12, new loocv: 9.867e-08\n" - ] - } - ], + "outputs": [], "source": [ "# pce.adapt_robustness(max_new_samples=50)\n", "residuals, loocvs, added_indices, added_samples = pce.adapt_expressivity(max_new_samples=100, add_rule=3)\n" @@ -288,7 +206,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "id": "c20b30d4", "metadata": {}, "outputs": [], @@ -300,7 +218,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": null, "id": "49d326c7", "metadata": {}, "outputs": [], @@ -311,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": null, "id": "e4a19d74", "metadata": {}, "outputs": [], @@ -323,7 +241,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": null, "id": "e23f6ece", "metadata": {}, "outputs": [], @@ -335,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": null, "id": "4945132c", "metadata": {}, "outputs": [], @@ -361,7 +279,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": null, "id": "eb408ce7", "metadata": {}, "outputs": [], @@ -391,7 +309,7 @@ "source": [ "## Visualize Statistics\n", "\n", - "Similar to [other examples](./build_pce.html), we will plot the uncertainty over the domain of the domain of the model. This example shows how users might do so more manually instead of using the [built in plotting functions](./build_pce.html#output-visualizations)\n", + "Similar to [other examples](./build_pce.ipynb), we will plot the uncertainty over the domain of the domain of the model. This example shows how users might do so more manually instead of using the [built in plotting functions](./build_pce.ipynb#output-visualizations)\n", "\n", "### Plotting Setup\n", "\n", @@ -400,7 +318,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": null, "id": "cc0f4b63", "metadata": {}, "outputs": [], @@ -422,21 +340,10 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "id": "d1712790", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# # Visualization\n", "V = 50 # Number of MC samples to visualize\n", @@ -469,998 +376,10 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": null, "id": "5f53e3b2", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_device_pixel_ratio', {\n", - " device_pixel_ratio: fig.ratio,\n", - " });\n", - " }\n", - " fig.send_message('refresh', {});\n", - " };\n", - "\n", - " this.imageObj.onload = function () {\n", - " if (fig.image_mode === 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function () {\n", - " fig.ws.close();\n", - " };\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "};\n", - "\n", - "mpl.figure.prototype._init_header = function () {\n", - " var titlebar = document.createElement('div');\n", - " titlebar.classList =\n", - " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", - " var titletext = document.createElement('div');\n", - " titletext.classList = 'ui-dialog-title';\n", - " titletext.setAttribute(\n", - " 'style',\n", - " 'width: 100%; text-align: center; padding: 3px;'\n", - " );\n", - " titlebar.appendChild(titletext);\n", - " this.root.appendChild(titlebar);\n", - " this.header = titletext;\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._init_canvas = function () {\n", - " var fig = this;\n", - "\n", - " var canvas_div = (this.canvas_div = document.createElement('div'));\n", - " canvas_div.setAttribute(\n", - " 'style',\n", - " 'border: 1px solid #ddd;' +\n", - " 'box-sizing: content-box;' +\n", - " 'clear: both;' +\n", - " 'min-height: 1px;' +\n", - " 'min-width: 1px;' +\n", - " 'outline: 0;' +\n", - " 'overflow: hidden;' +\n", - " 'position: relative;' +\n", - " 'resize: both;'\n", - " );\n", - "\n", - " function on_keyboard_event_closure(name) {\n", - " return function (event) {\n", - " return fig.key_event(event, name);\n", - " };\n", - " }\n", - "\n", - " canvas_div.addEventListener(\n", - " 'keydown',\n", - " on_keyboard_event_closure('key_press')\n", - " );\n", - " canvas_div.addEventListener(\n", - " 'keyup',\n", - " on_keyboard_event_closure('key_release')\n", - " );\n", - "\n", - " this._canvas_extra_style(canvas_div);\n", - " this.root.appendChild(canvas_div);\n", - "\n", - " var canvas = (this.canvas = document.createElement('canvas'));\n", - " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", - "\n", - " this.context = canvas.getContext('2d');\n", - "\n", - " var backingStore =\n", - " this.context.backingStorePixelRatio ||\n", - " this.context.webkitBackingStorePixelRatio ||\n", - " this.context.mozBackingStorePixelRatio ||\n", - " this.context.msBackingStorePixelRatio ||\n", - " this.context.oBackingStorePixelRatio ||\n", - " this.context.backingStorePixelRatio ||\n", - " 1;\n", - "\n", - " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", - " 'canvas'\n", - " ));\n", - " rubberband_canvas.setAttribute(\n", - " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", - " );\n", - "\n", - " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", - " if (this.ResizeObserver === undefined) {\n", - " if (window.ResizeObserver !== undefined) {\n", - " this.ResizeObserver = window.ResizeObserver;\n", - " } else {\n", - " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", - " this.ResizeObserver = obs.ResizeObserver;\n", - " }\n", - " }\n", - "\n", - " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", - " var nentries = entries.length;\n", - " for (var i = 0; i < nentries; i++) {\n", - " var entry = entries[i];\n", - " var width, height;\n", - " if (entry.contentBoxSize) {\n", - " if (entry.contentBoxSize instanceof Array) {\n", - " // Chrome 84 implements new version of spec.\n", - " width = entry.contentBoxSize[0].inlineSize;\n", - " height = entry.contentBoxSize[0].blockSize;\n", - " } else {\n", - " // Firefox implements old version of spec.\n", - " width = entry.contentBoxSize.inlineSize;\n", - " height = entry.contentBoxSize.blockSize;\n", - " }\n", - " } else {\n", - " // Chrome <84 implements even older version of spec.\n", - " width = entry.contentRect.width;\n", - " height = entry.contentRect.height;\n", - " }\n", - "\n", - " // Keep the size of the canvas and rubber band canvas in sync with\n", - " // the canvas container.\n", - " if (entry.devicePixelContentBoxSize) {\n", - " // Chrome 84 implements new version of spec.\n", - " canvas.setAttribute(\n", - " 'width',\n", - " entry.devicePixelContentBoxSize[0].inlineSize\n", - " );\n", - " canvas.setAttribute(\n", - " 'height',\n", - " entry.devicePixelContentBoxSize[0].blockSize\n", - " );\n", - " } else {\n", - " canvas.setAttribute('width', width * fig.ratio);\n", - " canvas.setAttribute('height', height * fig.ratio);\n", - " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", - "\n", - " rubberband_canvas.setAttribute('width', width);\n", - " rubberband_canvas.setAttribute('height', height);\n", - "\n", - " // And update the size in Python. We ignore the initial 0/0 size\n", - " // that occurs as the element is placed into the DOM, which should\n", - " // otherwise not happen due to the minimum size styling.\n", - " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", - " fig.request_resize(width, height);\n", - " }\n", - " }\n", - " });\n", - " this.resizeObserverInstance.observe(canvas_div);\n", - "\n", - " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", - " }\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mousedown',\n", - " on_mouse_event_closure('button_press')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseup',\n", - " on_mouse_event_closure('button_release')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\n", - " );\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", - " 'mousemove',\n", - " on_mouse_event_closure('motion_notify')\n", - " );\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseenter',\n", - " on_mouse_event_closure('figure_enter')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseleave',\n", - " on_mouse_event_closure('figure_leave')\n", - " );\n", - "\n", - " canvas_div.addEventListener('wheel', function (event) {\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " on_mouse_event_closure('scroll')(event);\n", - " });\n", - "\n", - " canvas_div.appendChild(canvas);\n", - " canvas_div.appendChild(rubberband_canvas);\n", - "\n", - " this.rubberband_context = rubberband_canvas.getContext('2d');\n", - " this.rubberband_context.strokeStyle = '#000000';\n", - "\n", - " this._resize_canvas = function (width, height, forward) {\n", - " if (forward) {\n", - " canvas_div.style.width = width + 'px';\n", - " canvas_div.style.height = height + 'px';\n", - " }\n", - " };\n", - "\n", - " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", - " event.preventDefault();\n", - " return false;\n", - " });\n", - "\n", - " function set_focus() {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'mpl-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " continue;\n", - " }\n", - "\n", - " var button = (fig.buttons[name] = document.createElement('button'));\n", - " button.classList = 'mpl-widget';\n", - " button.setAttribute('role', 'button');\n", - " button.setAttribute('aria-disabled', 'false');\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - "\n", - " var icon_img = document.createElement('img');\n", - " icon_img.src = '_images/' + image + '.png';\n", - " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", - " icon_img.alt = tooltip;\n", - " button.appendChild(icon_img);\n", - "\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " var fmt_picker = document.createElement('select');\n", - " fmt_picker.classList = 'mpl-widget';\n", - " toolbar.appendChild(fmt_picker);\n", - " this.format_dropdown = fmt_picker;\n", - "\n", - " for (var ind in mpl.extensions) {\n", - " var fmt = mpl.extensions[ind];\n", - " var option = document.createElement('option');\n", - " option.selected = fmt === mpl.default_extension;\n", - " option.innerHTML = fmt;\n", - " fmt_picker.appendChild(option);\n", - " }\n", - "\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "};\n", - "\n", - "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", - " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", - " // which will in turn request a refresh of the image.\n", - " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", - "};\n", - "\n", - "mpl.figure.prototype.send_message = function (type, properties) {\n", - " properties['type'] = type;\n", - " properties['figure_id'] = this.id;\n", - " this.ws.send(JSON.stringify(properties));\n", - "};\n", - "\n", - "mpl.figure.prototype.send_draw_message = function () {\n", - " if (!this.waiting) {\n", - " this.waiting = true;\n", - " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " var format_dropdown = fig.format_dropdown;\n", - " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", - " fig.ondownload(fig, format);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", - " var size = msg['size'];\n", - " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", - " fig._resize_canvas(size[0], size[1], msg['forward']);\n", - " fig.send_message('refresh', {});\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", - " var x0 = msg['x0'] / fig.ratio;\n", - " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", - " var x1 = msg['x1'] / fig.ratio;\n", - " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", - " x0 = Math.floor(x0) + 0.5;\n", - " y0 = Math.floor(y0) + 0.5;\n", - " x1 = Math.floor(x1) + 0.5;\n", - " y1 = Math.floor(y1) + 0.5;\n", - " var min_x = Math.min(x0, x1);\n", - " var min_y = Math.min(y0, y1);\n", - " var width = Math.abs(x1 - x0);\n", - " var height = Math.abs(y1 - y0);\n", - "\n", - " fig.rubberband_context.clearRect(\n", - " 0,\n", - " 0,\n", - " fig.canvas.width / fig.ratio,\n", - " fig.canvas.height / fig.ratio\n", - " );\n", - "\n", - " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", - " // Updates the figure title.\n", - " fig.header.textContent = msg['label'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " fig.rubberband_canvas.style.cursor = msg['cursor'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_message = function (fig, msg) {\n", - " fig.message.textContent = msg['message'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", - " // Request the server to send over a new figure.\n", - " fig.send_draw_message();\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", - " fig.image_mode = msg['mode'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", - " for (var key in msg) {\n", - " if (!(key in fig.buttons)) {\n", - " continue;\n", - " }\n", - " fig.buttons[key].disabled = !msg[key];\n", - " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", - " if (msg['mode'] === 'PAN') {\n", - " fig.buttons['Pan'].classList.add('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " } else if (msg['mode'] === 'ZOOM') {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.add('active');\n", - " } else {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Called whenever the canvas gets updated.\n", - " this.send_message('ack', {});\n", - "};\n", - "\n", - "// A function to construct a web socket function for onmessage handling.\n", - "// Called in the figure constructor.\n", - "mpl.figure.prototype._make_on_message_function = function (fig) {\n", - " return function socket_on_message(evt) {\n", - " if (evt.data instanceof Blob) {\n", - " var img = evt.data;\n", - " if (img.type !== 'image/png') {\n", - " /* FIXME: We get \"Resource interpreted as Image but\n", - " * transferred with MIME type text/plain:\" errors on\n", - " * Chrome. But how to set the MIME type? It doesn't seem\n", - " * to be part of the websocket stream */\n", - " img.type = 'image/png';\n", - " }\n", - "\n", - " /* Free the memory for the previous frames */\n", - " if (fig.imageObj.src) {\n", - " (window.URL || window.webkitURL).revokeObjectURL(\n", - " fig.imageObj.src\n", - " );\n", - " }\n", - "\n", - " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", - " img\n", - " );\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " } else if (\n", - " typeof evt.data === 'string' &&\n", - " evt.data.slice(0, 21) === 'data:image/png;base64'\n", - " ) {\n", - " fig.imageObj.src = evt.data;\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " }\n", - "\n", - " var msg = JSON.parse(evt.data);\n", - " var msg_type = msg['type'];\n", - "\n", - " // Call the \"handle_{type}\" callback, which takes\n", - " // the figure and JSON message as its only arguments.\n", - " try {\n", - " var callback = fig['handle_' + msg_type];\n", - " } catch (e) {\n", - " console.log(\n", - " \"No handler for the '\" + msg_type + \"' message type: \",\n", - " msg\n", - " );\n", - " return;\n", - " }\n", - "\n", - " if (callback) {\n", - " try {\n", - " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", - " callback(fig, msg);\n", - " } catch (e) {\n", - " console.log(\n", - " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", - " e,\n", - " e.stack,\n", - " msg\n", - " );\n", - " }\n", - " }\n", - " };\n", - "};\n", - "\n", - "// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", - " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", - " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", - " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", - "\n", - "/*\n", - " * return a copy of an object with only non-object keys\n", - " * we need this to avoid circular references\n", - " * https://stackoverflow.com/a/24161582/3208463\n", - " */\n", - "function simpleKeys(original) {\n", - " return Object.keys(original).reduce(function (obj, key) {\n", - " if (typeof original[key] !== 'object') {\n", - " obj[key] = original[key];\n", - " }\n", - " return obj;\n", - " }, {});\n", - "}\n", - "\n", - "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", - " if (name === 'button_press') {\n", - " this.canvas.focus();\n", - " this.canvas_div.focus();\n", - " }\n", - "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", - "\n", - " this.send_message(name, {\n", - " x: x,\n", - " y: y,\n", - " button: event.button,\n", - " step: event.step,\n", - " guiEvent: simpleKeys(event),\n", - " });\n", - "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", - " // Handle any extra behaviour associated with a key event\n", - "};\n", - "\n", - "mpl.figure.prototype.key_event = function (event, name) {\n", - " // Prevent repeat events\n", - " if (name === 'key_press') {\n", - " if (event.key === this._key) {\n", - " return;\n", - " } else {\n", - " this._key = event.key;\n", - " }\n", - " }\n", - " if (name === 'key_release') {\n", - " this._key = null;\n", - " }\n", - "\n", - " var value = '';\n", - " if (event.ctrlKey && event.key !== 'Control') {\n", - " value += 'ctrl+';\n", - " }\n", - " else if (event.altKey && event.key !== 'Alt') {\n", - " value += 'alt+';\n", - " }\n", - " else if (event.shiftKey && event.key !== 'Shift') {\n", - " value += 'shift+';\n", - " }\n", - "\n", - " value += 'k' + event.key;\n", - "\n", - " this._key_event_extra(event, name);\n", - "\n", - " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", - " if (name === 'download') {\n", - " this.handle_save(this, null);\n", - " } else {\n", - " this.send_message('toolbar_button', { name: name });\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", - " this.message.textContent = tooltip;\n", - "};\n", - "\n", - "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", - "// prettier-ignore\n", - "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", - "\n", - "mpl.default_extension = \"png\";/* global mpl */\n", - "\n", - "var comm_websocket_adapter = function (comm) {\n", - " // Create a \"websocket\"-like object which calls the given IPython comm\n", - " // object with the appropriate methods. Currently this is a non binary\n", - " // socket, so there is still some room for performance tuning.\n", - " var ws = {};\n", - "\n", - " ws.binaryType = comm.kernel.ws.binaryType;\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " function updateReadyState(_event) {\n", - " if (comm.kernel.ws) {\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " } else {\n", - " ws.readyState = 3; // Closed state.\n", - " }\n", - " }\n", - " comm.kernel.ws.addEventListener('open', updateReadyState);\n", - " comm.kernel.ws.addEventListener('close', updateReadyState);\n", - " comm.kernel.ws.addEventListener('error', updateReadyState);\n", - "\n", - " ws.close = function () {\n", - " comm.close();\n", - " };\n", - " ws.send = function (m) {\n", - " //console.log('sending', m);\n", - " comm.send(m);\n", - " };\n", - " // Register the callback with on_msg.\n", - " comm.on_msg(function (msg) {\n", - " //console.log('receiving', msg['content']['data'], msg);\n", - " var data = msg['content']['data'];\n", - " if (data['blob'] !== undefined) {\n", - " data = {\n", - " data: new Blob(msg['buffers'], { type: data['blob'] }),\n", - " };\n", - " }\n", - " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", - " ws.onmessage(data);\n", - " });\n", - " return ws;\n", - "};\n", - "\n", - "mpl.mpl_figure_comm = function (comm, msg) {\n", - " // This is the function which gets called when the mpl process\n", - " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", - "\n", - " var id = msg.content.data.id;\n", - " // Get hold of the div created by the display call when the Comm\n", - " // socket was opened in Python.\n", - " var element = document.getElementById(id);\n", - " var ws_proxy = comm_websocket_adapter(comm);\n", - "\n", - " function ondownload(figure, _format) {\n", - " window.open(figure.canvas.toDataURL());\n", - " }\n", - "\n", - " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", - "\n", - " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", - " // web socket which is closed, not our websocket->open comm proxy.\n", - " ws_proxy.onopen();\n", - "\n", - " fig.parent_element = element;\n", - " fig.cell_info = mpl.find_output_cell(\"
\");\n", - " if (!fig.cell_info) {\n", - " console.error('Failed to find cell for figure', id, fig);\n", - " return;\n", - " }\n", - " fig.cell_info[0].output_area.element.on(\n", - " 'cleared',\n", - " { fig: fig },\n", - " fig._remove_fig_handler\n", - " );\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_close = function (fig, msg) {\n", - " var width = fig.canvas.width / fig.ratio;\n", - " fig.cell_info[0].output_area.element.off(\n", - " 'cleared',\n", - " fig._remove_fig_handler\n", - " );\n", - " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", - "\n", - " // Update the output cell to use the data from the current canvas.\n", - " fig.push_to_output();\n", - " var dataURL = fig.canvas.toDataURL();\n", - " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", - " // the notebook keyboard shortcuts fail.\n", - " IPython.keyboard_manager.enable();\n", - " fig.parent_element.innerHTML =\n", - " '';\n", - " fig.close_ws(fig, msg);\n", - "};\n", - "\n", - "mpl.figure.prototype.close_ws = function (fig, msg) {\n", - " fig.send_message('closing', msg);\n", - " // fig.ws.close()\n", - "};\n", - "\n", - "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", - " // Turn the data on the canvas into data in the output cell.\n", - " var width = this.canvas.width / this.ratio;\n", - " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] =\n", - " '';\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Tell IPython that the notebook contents must change.\n", - " IPython.notebook.set_dirty(true);\n", - " this.send_message('ack', {});\n", - " var fig = this;\n", - " // Wait a second, then push the new image to the DOM so\n", - " // that it is saved nicely (might be nice to debounce this).\n", - " setTimeout(function () {\n", - " fig.push_to_output();\n", - " }, 1000);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'btn-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " var button;\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " continue;\n", - " }\n", - "\n", - " button = fig.buttons[name] = document.createElement('button');\n", - " button.classList = 'btn btn-default';\n", - " button.href = '#';\n", - " button.title = name;\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message pull-right';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = document.createElement('div');\n", - " buttongrp.classList = 'btn-group inline pull-right';\n", - " button = document.createElement('button');\n", - " button.classList = 'btn btn-mini btn-primary';\n", - " button.href = '#';\n", - " button.title = 'Stop Interaction';\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', function (_evt) {\n", - " fig.handle_close(fig, {});\n", - " });\n", - " button.addEventListener(\n", - " 'mouseover',\n", - " on_mouseover_closure('Stop Interaction')\n", - " );\n", - " buttongrp.appendChild(button);\n", - " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", - " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", - "};\n", - "\n", - "mpl.figure.prototype._remove_fig_handler = function (event) {\n", - " var fig = event.data.fig;\n", - " if (event.target !== this) {\n", - " // Ignore bubbled events from children.\n", - " return;\n", - " }\n", - " fig.close_ws(fig, {});\n", - "};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (el) {\n", - " // this is important to make the div 'focusable\n", - " el.setAttribute('tabindex', 0);\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " } else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which === 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", - "\n", - "mpl.find_output_cell = function (html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i = 0; i < ncells; i++) {\n", - " var cell = cells[i];\n", - " if (cell.cell_type === 'code') {\n", - " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", - " var data = cell.output_area.outputs[j];\n", - " if (data.data) {\n", - " // IPython >= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] === html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "};\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel !== null) {\n", - " IPython.notebook.kernel.comm_manager.register_target(\n", - " 'matplotlib',\n", - " mpl.mpl_figure_comm\n", - " );\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# quantile plot\n", "plt.figure()\n", @@ -1519,998 +438,10 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "id": "eee0c068", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_device_pixel_ratio', {\n", - " device_pixel_ratio: fig.ratio,\n", - " });\n", - " }\n", - " fig.send_message('refresh', {});\n", - " };\n", - "\n", - " this.imageObj.onload = function () {\n", - " if (fig.image_mode === 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function () {\n", - " fig.ws.close();\n", - " };\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "};\n", - "\n", - "mpl.figure.prototype._init_header = function () {\n", - " var titlebar = document.createElement('div');\n", - " titlebar.classList =\n", - " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", - " var titletext = document.createElement('div');\n", - " titletext.classList = 'ui-dialog-title';\n", - " titletext.setAttribute(\n", - " 'style',\n", - " 'width: 100%; text-align: center; padding: 3px;'\n", - " );\n", - " titlebar.appendChild(titletext);\n", - " this.root.appendChild(titlebar);\n", - " this.header = titletext;\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._init_canvas = function () {\n", - " var fig = this;\n", - "\n", - " var canvas_div = (this.canvas_div = document.createElement('div'));\n", - " canvas_div.setAttribute(\n", - " 'style',\n", - " 'border: 1px solid #ddd;' +\n", - " 'box-sizing: content-box;' +\n", - " 'clear: both;' +\n", - " 'min-height: 1px;' +\n", - " 'min-width: 1px;' +\n", - " 'outline: 0;' +\n", - " 'overflow: hidden;' +\n", - " 'position: relative;' +\n", - " 'resize: both;'\n", - " );\n", - "\n", - " function on_keyboard_event_closure(name) {\n", - " return function (event) {\n", - " return fig.key_event(event, name);\n", - " };\n", - " }\n", - "\n", - " canvas_div.addEventListener(\n", - " 'keydown',\n", - " on_keyboard_event_closure('key_press')\n", - " );\n", - " canvas_div.addEventListener(\n", - " 'keyup',\n", - " on_keyboard_event_closure('key_release')\n", - " );\n", - "\n", - " this._canvas_extra_style(canvas_div);\n", - " this.root.appendChild(canvas_div);\n", - "\n", - " var canvas = (this.canvas = document.createElement('canvas'));\n", - " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", - "\n", - " this.context = canvas.getContext('2d');\n", - "\n", - " var backingStore =\n", - " this.context.backingStorePixelRatio ||\n", - " this.context.webkitBackingStorePixelRatio ||\n", - " this.context.mozBackingStorePixelRatio ||\n", - " this.context.msBackingStorePixelRatio ||\n", - " this.context.oBackingStorePixelRatio ||\n", - " this.context.backingStorePixelRatio ||\n", - " 1;\n", - "\n", - " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", - " 'canvas'\n", - " ));\n", - " rubberband_canvas.setAttribute(\n", - " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", - " );\n", - "\n", - " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", - " if (this.ResizeObserver === undefined) {\n", - " if (window.ResizeObserver !== undefined) {\n", - " this.ResizeObserver = window.ResizeObserver;\n", - " } else {\n", - " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", - " this.ResizeObserver = obs.ResizeObserver;\n", - " }\n", - " }\n", - "\n", - " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", - " var nentries = entries.length;\n", - " for (var i = 0; i < nentries; i++) {\n", - " var entry = entries[i];\n", - " var width, height;\n", - " if (entry.contentBoxSize) {\n", - " if (entry.contentBoxSize instanceof Array) {\n", - " // Chrome 84 implements new version of spec.\n", - " width = entry.contentBoxSize[0].inlineSize;\n", - " height = entry.contentBoxSize[0].blockSize;\n", - " } else {\n", - " // Firefox implements old version of spec.\n", - " width = entry.contentBoxSize.inlineSize;\n", - " height = entry.contentBoxSize.blockSize;\n", - " }\n", - " } else {\n", - " // Chrome <84 implements even older version of spec.\n", - " width = entry.contentRect.width;\n", - " height = entry.contentRect.height;\n", - " }\n", - "\n", - " // Keep the size of the canvas and rubber band canvas in sync with\n", - " // the canvas container.\n", - " if (entry.devicePixelContentBoxSize) {\n", - " // Chrome 84 implements new version of spec.\n", - " canvas.setAttribute(\n", - " 'width',\n", - " entry.devicePixelContentBoxSize[0].inlineSize\n", - " );\n", - " canvas.setAttribute(\n", - " 'height',\n", - " entry.devicePixelContentBoxSize[0].blockSize\n", - " );\n", - " } else {\n", - " canvas.setAttribute('width', width * fig.ratio);\n", - " canvas.setAttribute('height', height * fig.ratio);\n", - " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", - "\n", - " rubberband_canvas.setAttribute('width', width);\n", - " rubberband_canvas.setAttribute('height', height);\n", - "\n", - " // And update the size in Python. We ignore the initial 0/0 size\n", - " // that occurs as the element is placed into the DOM, which should\n", - " // otherwise not happen due to the minimum size styling.\n", - " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", - " fig.request_resize(width, height);\n", - " }\n", - " }\n", - " });\n", - " this.resizeObserverInstance.observe(canvas_div);\n", - "\n", - " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", - " }\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mousedown',\n", - " on_mouse_event_closure('button_press')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseup',\n", - " on_mouse_event_closure('button_release')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\n", - " );\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", - " 'mousemove',\n", - " on_mouse_event_closure('motion_notify')\n", - " );\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseenter',\n", - " on_mouse_event_closure('figure_enter')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseleave',\n", - " on_mouse_event_closure('figure_leave')\n", - " );\n", - "\n", - " canvas_div.addEventListener('wheel', function (event) {\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " on_mouse_event_closure('scroll')(event);\n", - " });\n", - "\n", - " canvas_div.appendChild(canvas);\n", - " canvas_div.appendChild(rubberband_canvas);\n", - "\n", - " this.rubberband_context = rubberband_canvas.getContext('2d');\n", - " this.rubberband_context.strokeStyle = '#000000';\n", - "\n", - " this._resize_canvas = function (width, height, forward) {\n", - " if (forward) {\n", - " canvas_div.style.width = width + 'px';\n", - " canvas_div.style.height = height + 'px';\n", - " }\n", - " };\n", - "\n", - " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", - " event.preventDefault();\n", - " return false;\n", - " });\n", - "\n", - " function set_focus() {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'mpl-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " continue;\n", - " }\n", - "\n", - " var button = (fig.buttons[name] = document.createElement('button'));\n", - " button.classList = 'mpl-widget';\n", - " button.setAttribute('role', 'button');\n", - " button.setAttribute('aria-disabled', 'false');\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - "\n", - " var icon_img = document.createElement('img');\n", - " icon_img.src = '_images/' + image + '.png';\n", - " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", - " icon_img.alt = tooltip;\n", - " button.appendChild(icon_img);\n", - "\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " var fmt_picker = document.createElement('select');\n", - " fmt_picker.classList = 'mpl-widget';\n", - " toolbar.appendChild(fmt_picker);\n", - " this.format_dropdown = fmt_picker;\n", - "\n", - " for (var ind in mpl.extensions) {\n", - " var fmt = mpl.extensions[ind];\n", - " var option = document.createElement('option');\n", - " option.selected = fmt === mpl.default_extension;\n", - " option.innerHTML = fmt;\n", - " fmt_picker.appendChild(option);\n", - " }\n", - "\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "};\n", - "\n", - "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", - " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", - " // which will in turn request a refresh of the image.\n", - " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", - "};\n", - "\n", - "mpl.figure.prototype.send_message = function (type, properties) {\n", - " properties['type'] = type;\n", - " properties['figure_id'] = this.id;\n", - " this.ws.send(JSON.stringify(properties));\n", - "};\n", - "\n", - "mpl.figure.prototype.send_draw_message = function () {\n", - " if (!this.waiting) {\n", - " this.waiting = true;\n", - " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " var format_dropdown = fig.format_dropdown;\n", - " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", - " fig.ondownload(fig, format);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", - " var size = msg['size'];\n", - " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", - " fig._resize_canvas(size[0], size[1], msg['forward']);\n", - " fig.send_message('refresh', {});\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", - " var x0 = msg['x0'] / fig.ratio;\n", - " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", - " var x1 = msg['x1'] / fig.ratio;\n", - " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", - " x0 = Math.floor(x0) + 0.5;\n", - " y0 = Math.floor(y0) + 0.5;\n", - " x1 = Math.floor(x1) + 0.5;\n", - " y1 = Math.floor(y1) + 0.5;\n", - " var min_x = Math.min(x0, x1);\n", - " var min_y = Math.min(y0, y1);\n", - " var width = Math.abs(x1 - x0);\n", - " var height = Math.abs(y1 - y0);\n", - "\n", - " fig.rubberband_context.clearRect(\n", - " 0,\n", - " 0,\n", - " fig.canvas.width / fig.ratio,\n", - " fig.canvas.height / fig.ratio\n", - " );\n", - "\n", - " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", - " // Updates the figure title.\n", - " fig.header.textContent = msg['label'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " fig.rubberband_canvas.style.cursor = msg['cursor'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_message = function (fig, msg) {\n", - " fig.message.textContent = msg['message'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", - " // Request the server to send over a new figure.\n", - " fig.send_draw_message();\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", - " fig.image_mode = msg['mode'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", - " for (var key in msg) {\n", - " if (!(key in fig.buttons)) {\n", - " continue;\n", - " }\n", - " fig.buttons[key].disabled = !msg[key];\n", - " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", - " if (msg['mode'] === 'PAN') {\n", - " fig.buttons['Pan'].classList.add('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " } else if (msg['mode'] === 'ZOOM') {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.add('active');\n", - " } else {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Called whenever the canvas gets updated.\n", - " this.send_message('ack', {});\n", - "};\n", - "\n", - "// A function to construct a web socket function for onmessage handling.\n", - "// Called in the figure constructor.\n", - "mpl.figure.prototype._make_on_message_function = function (fig) {\n", - " return function socket_on_message(evt) {\n", - " if (evt.data instanceof Blob) {\n", - " var img = evt.data;\n", - " if (img.type !== 'image/png') {\n", - " /* FIXME: We get \"Resource interpreted as Image but\n", - " * transferred with MIME type text/plain:\" errors on\n", - " * Chrome. But how to set the MIME type? It doesn't seem\n", - " * to be part of the websocket stream */\n", - " img.type = 'image/png';\n", - " }\n", - "\n", - " /* Free the memory for the previous frames */\n", - " if (fig.imageObj.src) {\n", - " (window.URL || window.webkitURL).revokeObjectURL(\n", - " fig.imageObj.src\n", - " );\n", - " }\n", - "\n", - " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", - " img\n", - " );\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " } else if (\n", - " typeof evt.data === 'string' &&\n", - " evt.data.slice(0, 21) === 'data:image/png;base64'\n", - " ) {\n", - " fig.imageObj.src = evt.data;\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " }\n", - "\n", - " var msg = JSON.parse(evt.data);\n", - " var msg_type = msg['type'];\n", - "\n", - " // Call the \"handle_{type}\" callback, which takes\n", - " // the figure and JSON message as its only arguments.\n", - " try {\n", - " var callback = fig['handle_' + msg_type];\n", - " } catch (e) {\n", - " console.log(\n", - " \"No handler for the '\" + msg_type + \"' message type: \",\n", - " msg\n", - " );\n", - " return;\n", - " }\n", - "\n", - " if (callback) {\n", - " try {\n", - " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", - " callback(fig, msg);\n", - " } catch (e) {\n", - " console.log(\n", - " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", - " e,\n", - " e.stack,\n", - " msg\n", - " );\n", - " }\n", - " }\n", - " };\n", - "};\n", - "\n", - "// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", - " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", - " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", - " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", - "\n", - "/*\n", - " * return a copy of an object with only non-object keys\n", - " * we need this to avoid circular references\n", - " * https://stackoverflow.com/a/24161582/3208463\n", - " */\n", - "function simpleKeys(original) {\n", - " return Object.keys(original).reduce(function (obj, key) {\n", - " if (typeof original[key] !== 'object') {\n", - " obj[key] = original[key];\n", - " }\n", - " return obj;\n", - " }, {});\n", - "}\n", - "\n", - "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", - " if (name === 'button_press') {\n", - " this.canvas.focus();\n", - " this.canvas_div.focus();\n", - " }\n", - "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", - "\n", - " this.send_message(name, {\n", - " x: x,\n", - " y: y,\n", - " button: event.button,\n", - " step: event.step,\n", - " guiEvent: simpleKeys(event),\n", - " });\n", - "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", - " // Handle any extra behaviour associated with a key event\n", - "};\n", - "\n", - "mpl.figure.prototype.key_event = function (event, name) {\n", - " // Prevent repeat events\n", - " if (name === 'key_press') {\n", - " if (event.key === this._key) {\n", - " return;\n", - " } else {\n", - " this._key = event.key;\n", - " }\n", - " }\n", - " if (name === 'key_release') {\n", - " this._key = null;\n", - " }\n", - "\n", - " var value = '';\n", - " if (event.ctrlKey && event.key !== 'Control') {\n", - " value += 'ctrl+';\n", - " }\n", - " else if (event.altKey && event.key !== 'Alt') {\n", - " value += 'alt+';\n", - " }\n", - " else if (event.shiftKey && event.key !== 'Shift') {\n", - " value += 'shift+';\n", - " }\n", - "\n", - " value += 'k' + event.key;\n", - "\n", - " this._key_event_extra(event, name);\n", - "\n", - " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", - " if (name === 'download') {\n", - " this.handle_save(this, null);\n", - " } else {\n", - " this.send_message('toolbar_button', { name: name });\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", - " this.message.textContent = tooltip;\n", - "};\n", - "\n", - "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", - "// prettier-ignore\n", - "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", - "\n", - "mpl.default_extension = \"png\";/* global mpl */\n", - "\n", - "var comm_websocket_adapter = function (comm) {\n", - " // Create a \"websocket\"-like object which calls the given IPython comm\n", - " // object with the appropriate methods. Currently this is a non binary\n", - " // socket, so there is still some room for performance tuning.\n", - " var ws = {};\n", - "\n", - " ws.binaryType = comm.kernel.ws.binaryType;\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " function updateReadyState(_event) {\n", - " if (comm.kernel.ws) {\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " } else {\n", - " ws.readyState = 3; // Closed state.\n", - " }\n", - " }\n", - " comm.kernel.ws.addEventListener('open', updateReadyState);\n", - " comm.kernel.ws.addEventListener('close', updateReadyState);\n", - " comm.kernel.ws.addEventListener('error', updateReadyState);\n", - "\n", - " ws.close = function () {\n", - " comm.close();\n", - " };\n", - " ws.send = function (m) {\n", - " //console.log('sending', m);\n", - " comm.send(m);\n", - " };\n", - " // Register the callback with on_msg.\n", - " comm.on_msg(function (msg) {\n", - " //console.log('receiving', msg['content']['data'], msg);\n", - " var data = msg['content']['data'];\n", - " if (data['blob'] !== undefined) {\n", - " data = {\n", - " data: new Blob(msg['buffers'], { type: data['blob'] }),\n", - " };\n", - " }\n", - " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", - " ws.onmessage(data);\n", - " });\n", - " return ws;\n", - "};\n", - "\n", - "mpl.mpl_figure_comm = function (comm, msg) {\n", - " // This is the function which gets called when the mpl process\n", - " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", - "\n", - " var id = msg.content.data.id;\n", - " // Get hold of the div created by the display call when the Comm\n", - " // socket was opened in Python.\n", - " var element = document.getElementById(id);\n", - " var ws_proxy = comm_websocket_adapter(comm);\n", - "\n", - " function ondownload(figure, _format) {\n", - " window.open(figure.canvas.toDataURL());\n", - " }\n", - "\n", - " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", - "\n", - " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", - " // web socket which is closed, not our websocket->open comm proxy.\n", - " ws_proxy.onopen();\n", - "\n", - " fig.parent_element = element;\n", - " fig.cell_info = mpl.find_output_cell(\"
\");\n", - " if (!fig.cell_info) {\n", - " console.error('Failed to find cell for figure', id, fig);\n", - " return;\n", - " }\n", - " fig.cell_info[0].output_area.element.on(\n", - " 'cleared',\n", - " { fig: fig },\n", - " fig._remove_fig_handler\n", - " );\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_close = function (fig, msg) {\n", - " var width = fig.canvas.width / fig.ratio;\n", - " fig.cell_info[0].output_area.element.off(\n", - " 'cleared',\n", - " fig._remove_fig_handler\n", - " );\n", - " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", - "\n", - " // Update the output cell to use the data from the current canvas.\n", - " fig.push_to_output();\n", - " var dataURL = fig.canvas.toDataURL();\n", - " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", - " // the notebook keyboard shortcuts fail.\n", - " IPython.keyboard_manager.enable();\n", - " fig.parent_element.innerHTML =\n", - " '';\n", - " fig.close_ws(fig, msg);\n", - "};\n", - "\n", - "mpl.figure.prototype.close_ws = function (fig, msg) {\n", - " fig.send_message('closing', msg);\n", - " // fig.ws.close()\n", - "};\n", - "\n", - "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", - " // Turn the data on the canvas into data in the output cell.\n", - " var width = this.canvas.width / this.ratio;\n", - " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] =\n", - " '';\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Tell IPython that the notebook contents must change.\n", - " IPython.notebook.set_dirty(true);\n", - " this.send_message('ack', {});\n", - " var fig = this;\n", - " // Wait a second, then push the new image to the DOM so\n", - " // that it is saved nicely (might be nice to debounce this).\n", - " setTimeout(function () {\n", - " fig.push_to_output();\n", - " }, 1000);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'btn-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " var button;\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " continue;\n", - " }\n", - "\n", - " button = fig.buttons[name] = document.createElement('button');\n", - " button.classList = 'btn btn-default';\n", - " button.href = '#';\n", - " button.title = name;\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message pull-right';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = document.createElement('div');\n", - " buttongrp.classList = 'btn-group inline pull-right';\n", - " button = document.createElement('button');\n", - " button.classList = 'btn btn-mini btn-primary';\n", - " button.href = '#';\n", - " button.title = 'Stop Interaction';\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', function (_evt) {\n", - " fig.handle_close(fig, {});\n", - " });\n", - " button.addEventListener(\n", - " 'mouseover',\n", - " on_mouseover_closure('Stop Interaction')\n", - " );\n", - " buttongrp.appendChild(button);\n", - " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", - " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", - "};\n", - "\n", - "mpl.figure.prototype._remove_fig_handler = function (event) {\n", - " var fig = event.data.fig;\n", - " if (event.target !== this) {\n", - " // Ignore bubbled events from children.\n", - " return;\n", - " }\n", - " fig.close_ws(fig, {});\n", - "};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (el) {\n", - " // this is important to make the div 'focusable\n", - " el.setAttribute('tabindex', 0);\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " } else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which === 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", - "\n", - "mpl.find_output_cell = function (html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i = 0; i < ncells; i++) {\n", - " var cell = cells[i];\n", - " if (cell.cell_type === 'code') {\n", - " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", - " var data = cell.output_area.outputs[j];\n", - " if (data.data) {\n", - " // IPython >= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] === html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "};\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel !== null) {\n", - " IPython.notebook.kernel.comm_manager.register_target(\n", - " 'matplotlib',\n", - " mpl.mpl_figure_comm\n", - " );\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Sensitivity due to variable interactions')" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Sensitivity pie chart, averaged over all model degrees of freedom\n", "average_global_SI = np.sum(global_sensitivity, axis=1)/N\n", @@ -2537,988 +468,10 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": null, "id": "8b7f9de8", "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "/* global mpl */\n", - "window.mpl = {};\n", - "\n", - "mpl.get_websocket_type = function () {\n", - " if (typeof WebSocket !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof MozWebSocket !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert(\n", - " 'Your browser does not have WebSocket support. ' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.'\n", - " );\n", - " }\n", - "};\n", - "\n", - "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = this.ws.binaryType !== undefined;\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById('mpl-warnings');\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent =\n", - " 'This browser does not support binary websocket messages. ' +\n", - " 'Performance may be slow.';\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = document.createElement('div');\n", - " this.root.setAttribute('style', 'display: inline-block');\n", - " this._root_extra_style(this.root);\n", - "\n", - " parent_element.appendChild(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message('supports_binary', { value: fig.supports_binary });\n", - " fig.send_message('send_image_mode', {});\n", - " if (fig.ratio !== 1) {\n", - " fig.send_message('set_device_pixel_ratio', {\n", - " device_pixel_ratio: fig.ratio,\n", - " });\n", - " }\n", - " fig.send_message('refresh', {});\n", - " };\n", - "\n", - " this.imageObj.onload = function () {\n", - " if (fig.image_mode === 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function () {\n", - " fig.ws.close();\n", - " };\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "};\n", - "\n", - "mpl.figure.prototype._init_header = function () {\n", - " var titlebar = document.createElement('div');\n", - " titlebar.classList =\n", - " 'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n", - " var titletext = document.createElement('div');\n", - " titletext.classList = 'ui-dialog-title';\n", - " titletext.setAttribute(\n", - " 'style',\n", - " 'width: 100%; text-align: center; padding: 3px;'\n", - " );\n", - " titlebar.appendChild(titletext);\n", - " this.root.appendChild(titlebar);\n", - " this.header = titletext;\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n", - "\n", - "mpl.figure.prototype._init_canvas = function () {\n", - " var fig = this;\n", - "\n", - " var canvas_div = (this.canvas_div = document.createElement('div'));\n", - " canvas_div.setAttribute(\n", - " 'style',\n", - " 'border: 1px solid #ddd;' +\n", - " 'box-sizing: content-box;' +\n", - " 'clear: both;' +\n", - " 'min-height: 1px;' +\n", - " 'min-width: 1px;' +\n", - " 'outline: 0;' +\n", - " 'overflow: hidden;' +\n", - " 'position: relative;' +\n", - " 'resize: both;'\n", - " );\n", - "\n", - " function on_keyboard_event_closure(name) {\n", - " return function (event) {\n", - " return fig.key_event(event, name);\n", - " };\n", - " }\n", - "\n", - " canvas_div.addEventListener(\n", - " 'keydown',\n", - " on_keyboard_event_closure('key_press')\n", - " );\n", - " canvas_div.addEventListener(\n", - " 'keyup',\n", - " on_keyboard_event_closure('key_release')\n", - " );\n", - "\n", - " this._canvas_extra_style(canvas_div);\n", - " this.root.appendChild(canvas_div);\n", - "\n", - " var canvas = (this.canvas = document.createElement('canvas'));\n", - " canvas.classList.add('mpl-canvas');\n", - " canvas.setAttribute('style', 'box-sizing: content-box;');\n", - "\n", - " this.context = canvas.getContext('2d');\n", - "\n", - " var backingStore =\n", - " this.context.backingStorePixelRatio ||\n", - " this.context.webkitBackingStorePixelRatio ||\n", - " this.context.mozBackingStorePixelRatio ||\n", - " this.context.msBackingStorePixelRatio ||\n", - " this.context.oBackingStorePixelRatio ||\n", - " this.context.backingStorePixelRatio ||\n", - " 1;\n", - "\n", - " this.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n", - " 'canvas'\n", - " ));\n", - " rubberband_canvas.setAttribute(\n", - " 'style',\n", - " 'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n", - " );\n", - "\n", - " // Apply a ponyfill if ResizeObserver is not implemented by browser.\n", - " if (this.ResizeObserver === undefined) {\n", - " if (window.ResizeObserver !== undefined) {\n", - " this.ResizeObserver = window.ResizeObserver;\n", - " } else {\n", - " var obs = _JSXTOOLS_RESIZE_OBSERVER({});\n", - " this.ResizeObserver = obs.ResizeObserver;\n", - " }\n", - " }\n", - "\n", - " this.resizeObserverInstance = new this.ResizeObserver(function (entries) {\n", - " var nentries = entries.length;\n", - " for (var i = 0; i < nentries; i++) {\n", - " var entry = entries[i];\n", - " var width, height;\n", - " if (entry.contentBoxSize) {\n", - " if (entry.contentBoxSize instanceof Array) {\n", - " // Chrome 84 implements new version of spec.\n", - " width = entry.contentBoxSize[0].inlineSize;\n", - " height = entry.contentBoxSize[0].blockSize;\n", - " } else {\n", - " // Firefox implements old version of spec.\n", - " width = entry.contentBoxSize.inlineSize;\n", - " height = entry.contentBoxSize.blockSize;\n", - " }\n", - " } else {\n", - " // Chrome <84 implements even older version of spec.\n", - " width = entry.contentRect.width;\n", - " height = entry.contentRect.height;\n", - " }\n", - "\n", - " // Keep the size of the canvas and rubber band canvas in sync with\n", - " // the canvas container.\n", - " if (entry.devicePixelContentBoxSize) {\n", - " // Chrome 84 implements new version of spec.\n", - " canvas.setAttribute(\n", - " 'width',\n", - " entry.devicePixelContentBoxSize[0].inlineSize\n", - " );\n", - " canvas.setAttribute(\n", - " 'height',\n", - " entry.devicePixelContentBoxSize[0].blockSize\n", - " );\n", - " } else {\n", - " canvas.setAttribute('width', width * fig.ratio);\n", - " canvas.setAttribute('height', height * fig.ratio);\n", - " }\n", - " canvas.setAttribute(\n", - " 'style',\n", - " 'width: ' + width + 'px; height: ' + height + 'px;'\n", - " );\n", - "\n", - " rubberband_canvas.setAttribute('width', width);\n", - " rubberband_canvas.setAttribute('height', height);\n", - "\n", - " // And update the size in Python. We ignore the initial 0/0 size\n", - " // that occurs as the element is placed into the DOM, which should\n", - " // otherwise not happen due to the minimum size styling.\n", - " if (fig.ws.readyState == 1 && width != 0 && height != 0) {\n", - " fig.request_resize(width, height);\n", - " }\n", - " }\n", - " });\n", - " this.resizeObserverInstance.observe(canvas_div);\n", - "\n", - " function on_mouse_event_closure(name) {\n", - " return function (event) {\n", - " return fig.mouse_event(event, name);\n", - " };\n", - " }\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mousedown',\n", - " on_mouse_event_closure('button_press')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseup',\n", - " on_mouse_event_closure('button_release')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'dblclick',\n", - " on_mouse_event_closure('dblclick')\n", - " );\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband_canvas.addEventListener(\n", - " 'mousemove',\n", - " on_mouse_event_closure('motion_notify')\n", - " );\n", - "\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseenter',\n", - " on_mouse_event_closure('figure_enter')\n", - " );\n", - " rubberband_canvas.addEventListener(\n", - " 'mouseleave',\n", - " on_mouse_event_closure('figure_leave')\n", - " );\n", - "\n", - " canvas_div.addEventListener('wheel', function (event) {\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " on_mouse_event_closure('scroll')(event);\n", - " });\n", - "\n", - " canvas_div.appendChild(canvas);\n", - " canvas_div.appendChild(rubberband_canvas);\n", - "\n", - " this.rubberband_context = rubberband_canvas.getContext('2d');\n", - " this.rubberband_context.strokeStyle = '#000000';\n", - "\n", - " this._resize_canvas = function (width, height, forward) {\n", - " if (forward) {\n", - " canvas_div.style.width = width + 'px';\n", - " canvas_div.style.height = height + 'px';\n", - " }\n", - " };\n", - "\n", - " // Disable right mouse context menu.\n", - " this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n", - " event.preventDefault();\n", - " return false;\n", - " });\n", - "\n", - " function set_focus() {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'mpl-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'mpl-button-group';\n", - " continue;\n", - " }\n", - "\n", - " var button = (fig.buttons[name] = document.createElement('button'));\n", - " button.classList = 'mpl-widget';\n", - " button.setAttribute('role', 'button');\n", - " button.setAttribute('aria-disabled', 'false');\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - "\n", - " var icon_img = document.createElement('img');\n", - " icon_img.src = '_images/' + image + '.png';\n", - " icon_img.srcset = '_images/' + image + '_large.png 2x';\n", - " icon_img.alt = tooltip;\n", - " button.appendChild(icon_img);\n", - "\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " var fmt_picker = document.createElement('select');\n", - " fmt_picker.classList = 'mpl-widget';\n", - " toolbar.appendChild(fmt_picker);\n", - " this.format_dropdown = fmt_picker;\n", - "\n", - " for (var ind in mpl.extensions) {\n", - " var fmt = mpl.extensions[ind];\n", - " var option = document.createElement('option');\n", - " option.selected = fmt === mpl.default_extension;\n", - " option.innerHTML = fmt;\n", - " fmt_picker.appendChild(option);\n", - " }\n", - "\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "};\n", - "\n", - "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n", - " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", - " // which will in turn request a refresh of the image.\n", - " this.send_message('resize', { width: x_pixels, height: y_pixels });\n", - "};\n", - "\n", - "mpl.figure.prototype.send_message = function (type, properties) {\n", - " properties['type'] = type;\n", - " properties['figure_id'] = this.id;\n", - " this.ws.send(JSON.stringify(properties));\n", - "};\n", - "\n", - "mpl.figure.prototype.send_draw_message = function () {\n", - " if (!this.waiting) {\n", - " this.waiting = true;\n", - " this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " var format_dropdown = fig.format_dropdown;\n", - " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", - " fig.ondownload(fig, format);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_resize = function (fig, msg) {\n", - " var size = msg['size'];\n", - " if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n", - " fig._resize_canvas(size[0], size[1], msg['forward']);\n", - " fig.send_message('refresh', {});\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n", - " var x0 = msg['x0'] / fig.ratio;\n", - " var y0 = (fig.canvas.height - msg['y0']) / fig.ratio;\n", - " var x1 = msg['x1'] / fig.ratio;\n", - " var y1 = (fig.canvas.height - msg['y1']) / fig.ratio;\n", - " x0 = Math.floor(x0) + 0.5;\n", - " y0 = Math.floor(y0) + 0.5;\n", - " x1 = Math.floor(x1) + 0.5;\n", - " y1 = Math.floor(y1) + 0.5;\n", - " var min_x = Math.min(x0, x1);\n", - " var min_y = Math.min(y0, y1);\n", - " var width = Math.abs(x1 - x0);\n", - " var height = Math.abs(y1 - y0);\n", - "\n", - " fig.rubberband_context.clearRect(\n", - " 0,\n", - " 0,\n", - " fig.canvas.width / fig.ratio,\n", - " fig.canvas.height / fig.ratio\n", - " );\n", - "\n", - " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n", - " // Updates the figure title.\n", - " fig.header.textContent = msg['label'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n", - " fig.rubberband_canvas.style.cursor = msg['cursor'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_message = function (fig, msg) {\n", - " fig.message.textContent = msg['message'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n", - " // Request the server to send over a new figure.\n", - " fig.send_draw_message();\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n", - " fig.image_mode = msg['mode'];\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n", - " for (var key in msg) {\n", - " if (!(key in fig.buttons)) {\n", - " continue;\n", - " }\n", - " fig.buttons[key].disabled = !msg[key];\n", - " fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n", - " if (msg['mode'] === 'PAN') {\n", - " fig.buttons['Pan'].classList.add('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " } else if (msg['mode'] === 'ZOOM') {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.add('active');\n", - " } else {\n", - " fig.buttons['Pan'].classList.remove('active');\n", - " fig.buttons['Zoom'].classList.remove('active');\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Called whenever the canvas gets updated.\n", - " this.send_message('ack', {});\n", - "};\n", - "\n", - "// A function to construct a web socket function for onmessage handling.\n", - "// Called in the figure constructor.\n", - "mpl.figure.prototype._make_on_message_function = function (fig) {\n", - " return function socket_on_message(evt) {\n", - " if (evt.data instanceof Blob) {\n", - " var img = evt.data;\n", - " if (img.type !== 'image/png') {\n", - " /* FIXME: We get \"Resource interpreted as Image but\n", - " * transferred with MIME type text/plain:\" errors on\n", - " * Chrome. But how to set the MIME type? It doesn't seem\n", - " * to be part of the websocket stream */\n", - " img.type = 'image/png';\n", - " }\n", - "\n", - " /* Free the memory for the previous frames */\n", - " if (fig.imageObj.src) {\n", - " (window.URL || window.webkitURL).revokeObjectURL(\n", - " fig.imageObj.src\n", - " );\n", - " }\n", - "\n", - " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", - " img\n", - " );\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " } else if (\n", - " typeof evt.data === 'string' &&\n", - " evt.data.slice(0, 21) === 'data:image/png;base64'\n", - " ) {\n", - " fig.imageObj.src = evt.data;\n", - " fig.updated_canvas_event();\n", - " fig.waiting = false;\n", - " return;\n", - " }\n", - "\n", - " var msg = JSON.parse(evt.data);\n", - " var msg_type = msg['type'];\n", - "\n", - " // Call the \"handle_{type}\" callback, which takes\n", - " // the figure and JSON message as its only arguments.\n", - " try {\n", - " var callback = fig['handle_' + msg_type];\n", - " } catch (e) {\n", - " console.log(\n", - " \"No handler for the '\" + msg_type + \"' message type: \",\n", - " msg\n", - " );\n", - " return;\n", - " }\n", - "\n", - " if (callback) {\n", - " try {\n", - " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", - " callback(fig, msg);\n", - " } catch (e) {\n", - " console.log(\n", - " \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n", - " e,\n", - " e.stack,\n", - " msg\n", - " );\n", - " }\n", - " }\n", - " };\n", - "};\n", - "\n", - "// from https://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", - "mpl.findpos = function (e) {\n", - " //this section is from http://www.quirksmode.org/js/events_properties.html\n", - " var targ;\n", - " if (!e) {\n", - " e = window.event;\n", - " }\n", - " if (e.target) {\n", - " targ = e.target;\n", - " } else if (e.srcElement) {\n", - " targ = e.srcElement;\n", - " }\n", - " if (targ.nodeType === 3) {\n", - " // defeat Safari bug\n", - " targ = targ.parentNode;\n", - " }\n", - "\n", - " // pageX,Y are the mouse positions relative to the document\n", - " var boundingRect = targ.getBoundingClientRect();\n", - " var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n", - " var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n", - "\n", - " return { x: x, y: y };\n", - "};\n", - "\n", - "/*\n", - " * return a copy of an object with only non-object keys\n", - " * we need this to avoid circular references\n", - " * https://stackoverflow.com/a/24161582/3208463\n", - " */\n", - "function simpleKeys(original) {\n", - " return Object.keys(original).reduce(function (obj, key) {\n", - " if (typeof original[key] !== 'object') {\n", - " obj[key] = original[key];\n", - " }\n", - " return obj;\n", - " }, {});\n", - "}\n", - "\n", - "mpl.figure.prototype.mouse_event = function (event, name) {\n", - " var canvas_pos = mpl.findpos(event);\n", - "\n", - " if (name === 'button_press') {\n", - " this.canvas.focus();\n", - " this.canvas_div.focus();\n", - " }\n", - "\n", - " var x = canvas_pos.x * this.ratio;\n", - " var y = canvas_pos.y * this.ratio;\n", - "\n", - " this.send_message(name, {\n", - " x: x,\n", - " y: y,\n", - " button: event.button,\n", - " step: event.step,\n", - " guiEvent: simpleKeys(event),\n", - " });\n", - "\n", - " /* This prevents the web browser from automatically changing to\n", - " * the text insertion cursor when the button is pressed. We want\n", - " * to control all of the cursor setting manually through the\n", - " * 'cursor' event from matplotlib */\n", - " event.preventDefault();\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n", - " // Handle any extra behaviour associated with a key event\n", - "};\n", - "\n", - "mpl.figure.prototype.key_event = function (event, name) {\n", - " // Prevent repeat events\n", - " if (name === 'key_press') {\n", - " if (event.key === this._key) {\n", - " return;\n", - " } else {\n", - " this._key = event.key;\n", - " }\n", - " }\n", - " if (name === 'key_release') {\n", - " this._key = null;\n", - " }\n", - "\n", - " var value = '';\n", - " if (event.ctrlKey && event.key !== 'Control') {\n", - " value += 'ctrl+';\n", - " }\n", - " else if (event.altKey && event.key !== 'Alt') {\n", - " value += 'alt+';\n", - " }\n", - " else if (event.shiftKey && event.key !== 'Shift') {\n", - " value += 'shift+';\n", - " }\n", - "\n", - " value += 'k' + event.key;\n", - "\n", - " this._key_event_extra(event, name);\n", - "\n", - " this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n", - " return false;\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n", - " if (name === 'download') {\n", - " this.handle_save(this, null);\n", - " } else {\n", - " this.send_message('toolbar_button', { name: name });\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n", - " this.message.textContent = tooltip;\n", - "};\n", - "\n", - "///////////////// REMAINING CONTENT GENERATED BY embed_js.py /////////////////\n", - "// prettier-ignore\n", - "var _JSXTOOLS_RESIZE_OBSERVER=function(A){var t,i=new WeakMap,n=new WeakMap,a=new WeakMap,r=new WeakMap,o=new Set;function s(e){if(!(this instanceof s))throw new TypeError(\"Constructor requires 'new' operator\");i.set(this,e)}function h(){throw new TypeError(\"Function is not a constructor\")}function c(e,t,i,n){e=0 in arguments?Number(arguments[0]):0,t=1 in arguments?Number(arguments[1]):0,i=2 in arguments?Number(arguments[2]):0,n=3 in arguments?Number(arguments[3]):0,this.right=(this.x=this.left=e)+(this.width=i),this.bottom=(this.y=this.top=t)+(this.height=n),Object.freeze(this)}function d(){t=requestAnimationFrame(d);var s=new WeakMap,p=new Set;o.forEach((function(t){r.get(t).forEach((function(i){var r=t instanceof window.SVGElement,o=a.get(t),d=r?0:parseFloat(o.paddingTop),f=r?0:parseFloat(o.paddingRight),l=r?0:parseFloat(o.paddingBottom),u=r?0:parseFloat(o.paddingLeft),g=r?0:parseFloat(o.borderTopWidth),m=r?0:parseFloat(o.borderRightWidth),w=r?0:parseFloat(o.borderBottomWidth),b=u+f,F=d+l,v=(r?0:parseFloat(o.borderLeftWidth))+m,W=g+w,y=r?0:t.offsetHeight-W-t.clientHeight,E=r?0:t.offsetWidth-v-t.clientWidth,R=b+v,z=F+W,M=r?t.width:parseFloat(o.width)-R-E,O=r?t.height:parseFloat(o.height)-z-y;if(n.has(t)){var k=n.get(t);if(k[0]===M&&k[1]===O)return}n.set(t,[M,O]);var S=Object.create(h.prototype);S.target=t,S.contentRect=new c(u,d,M,O),s.has(i)||(s.set(i,[]),p.add(i)),s.get(i).push(S)}))})),p.forEach((function(e){i.get(e).call(e,s.get(e),e)}))}return s.prototype.observe=function(i){if(i instanceof window.Element){r.has(i)||(r.set(i,new Set),o.add(i),a.set(i,window.getComputedStyle(i)));var n=r.get(i);n.has(this)||n.add(this),cancelAnimationFrame(t),t=requestAnimationFrame(d)}},s.prototype.unobserve=function(i){if(i instanceof window.Element&&r.has(i)){var n=r.get(i);n.has(this)&&(n.delete(this),n.size||(r.delete(i),o.delete(i))),n.size||r.delete(i),o.size||cancelAnimationFrame(t)}},A.DOMRectReadOnly=c,A.ResizeObserver=s,A.ResizeObserverEntry=h,A}; // eslint-disable-line\n", - "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", - "\n", - "mpl.extensions = [\"eps\", \"jpeg\", \"pgf\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", - "\n", - "mpl.default_extension = \"png\";/* global mpl */\n", - "\n", - "var comm_websocket_adapter = function (comm) {\n", - " // Create a \"websocket\"-like object which calls the given IPython comm\n", - " // object with the appropriate methods. Currently this is a non binary\n", - " // socket, so there is still some room for performance tuning.\n", - " var ws = {};\n", - "\n", - " ws.binaryType = comm.kernel.ws.binaryType;\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " function updateReadyState(_event) {\n", - " if (comm.kernel.ws) {\n", - " ws.readyState = comm.kernel.ws.readyState;\n", - " } else {\n", - " ws.readyState = 3; // Closed state.\n", - " }\n", - " }\n", - " comm.kernel.ws.addEventListener('open', updateReadyState);\n", - " comm.kernel.ws.addEventListener('close', updateReadyState);\n", - " comm.kernel.ws.addEventListener('error', updateReadyState);\n", - "\n", - " ws.close = function () {\n", - " comm.close();\n", - " };\n", - " ws.send = function (m) {\n", - " //console.log('sending', m);\n", - " comm.send(m);\n", - " };\n", - " // Register the callback with on_msg.\n", - " comm.on_msg(function (msg) {\n", - " //console.log('receiving', msg['content']['data'], msg);\n", - " var data = msg['content']['data'];\n", - " if (data['blob'] !== undefined) {\n", - " data = {\n", - " data: new Blob(msg['buffers'], { type: data['blob'] }),\n", - " };\n", - " }\n", - " // Pass the mpl event to the overridden (by mpl) onmessage function.\n", - " ws.onmessage(data);\n", - " });\n", - " return ws;\n", - "};\n", - "\n", - "mpl.mpl_figure_comm = function (comm, msg) {\n", - " // This is the function which gets called when the mpl process\n", - " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", - "\n", - " var id = msg.content.data.id;\n", - " // Get hold of the div created by the display call when the Comm\n", - " // socket was opened in Python.\n", - " var element = document.getElementById(id);\n", - " var ws_proxy = comm_websocket_adapter(comm);\n", - "\n", - " function ondownload(figure, _format) {\n", - " window.open(figure.canvas.toDataURL());\n", - " }\n", - "\n", - " var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n", - "\n", - " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", - " // web socket which is closed, not our websocket->open comm proxy.\n", - " ws_proxy.onopen();\n", - "\n", - " fig.parent_element = element;\n", - " fig.cell_info = mpl.find_output_cell(\"
\");\n", - " if (!fig.cell_info) {\n", - " console.error('Failed to find cell for figure', id, fig);\n", - " return;\n", - " }\n", - " fig.cell_info[0].output_area.element.on(\n", - " 'cleared',\n", - " { fig: fig },\n", - " fig._remove_fig_handler\n", - " );\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_close = function (fig, msg) {\n", - " var width = fig.canvas.width / fig.ratio;\n", - " fig.cell_info[0].output_area.element.off(\n", - " 'cleared',\n", - " fig._remove_fig_handler\n", - " );\n", - " fig.resizeObserverInstance.unobserve(fig.canvas_div);\n", - "\n", - " // Update the output cell to use the data from the current canvas.\n", - " fig.push_to_output();\n", - " var dataURL = fig.canvas.toDataURL();\n", - " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", - " // the notebook keyboard shortcuts fail.\n", - " IPython.keyboard_manager.enable();\n", - " fig.parent_element.innerHTML =\n", - " '';\n", - " fig.close_ws(fig, msg);\n", - "};\n", - "\n", - "mpl.figure.prototype.close_ws = function (fig, msg) {\n", - " fig.send_message('closing', msg);\n", - " // fig.ws.close()\n", - "};\n", - "\n", - "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n", - " // Turn the data on the canvas into data in the output cell.\n", - " var width = this.canvas.width / this.ratio;\n", - " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] =\n", - " '';\n", - "};\n", - "\n", - "mpl.figure.prototype.updated_canvas_event = function () {\n", - " // Tell IPython that the notebook contents must change.\n", - " IPython.notebook.set_dirty(true);\n", - " this.send_message('ack', {});\n", - " var fig = this;\n", - " // Wait a second, then push the new image to the DOM so\n", - " // that it is saved nicely (might be nice to debounce this).\n", - " setTimeout(function () {\n", - " fig.push_to_output();\n", - " }, 1000);\n", - "};\n", - "\n", - "mpl.figure.prototype._init_toolbar = function () {\n", - " var fig = this;\n", - "\n", - " var toolbar = document.createElement('div');\n", - " toolbar.classList = 'btn-toolbar';\n", - " this.root.appendChild(toolbar);\n", - "\n", - " function on_click_closure(name) {\n", - " return function (_event) {\n", - " return fig.toolbar_button_onclick(name);\n", - " };\n", - " }\n", - "\n", - " function on_mouseover_closure(tooltip) {\n", - " return function (event) {\n", - " if (!event.currentTarget.disabled) {\n", - " return fig.toolbar_button_onmouseover(tooltip);\n", - " }\n", - " };\n", - " }\n", - "\n", - " fig.buttons = {};\n", - " var buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " var button;\n", - " for (var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " /* Instead of a spacer, we start a new button group. */\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - " buttonGroup = document.createElement('div');\n", - " buttonGroup.classList = 'btn-group';\n", - " continue;\n", - " }\n", - "\n", - " button = fig.buttons[name] = document.createElement('button');\n", - " button.classList = 'btn btn-default';\n", - " button.href = '#';\n", - " button.title = name;\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', on_click_closure(method_name));\n", - " button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n", - " buttonGroup.appendChild(button);\n", - " }\n", - "\n", - " if (buttonGroup.hasChildNodes()) {\n", - " toolbar.appendChild(buttonGroup);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = document.createElement('span');\n", - " status_bar.classList = 'mpl-message pull-right';\n", - " toolbar.appendChild(status_bar);\n", - " this.message = status_bar;\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = document.createElement('div');\n", - " buttongrp.classList = 'btn-group inline pull-right';\n", - " button = document.createElement('button');\n", - " button.classList = 'btn btn-mini btn-primary';\n", - " button.href = '#';\n", - " button.title = 'Stop Interaction';\n", - " button.innerHTML = '';\n", - " button.addEventListener('click', function (_evt) {\n", - " fig.handle_close(fig, {});\n", - " });\n", - " button.addEventListener(\n", - " 'mouseover',\n", - " on_mouseover_closure('Stop Interaction')\n", - " );\n", - " buttongrp.appendChild(button);\n", - " var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n", - " titlebar.insertBefore(buttongrp, titlebar.firstChild);\n", - "};\n", - "\n", - "mpl.figure.prototype._remove_fig_handler = function (event) {\n", - " var fig = event.data.fig;\n", - " if (event.target !== this) {\n", - " // Ignore bubbled events from children.\n", - " return;\n", - " }\n", - " fig.close_ws(fig, {});\n", - "};\n", - "\n", - "mpl.figure.prototype._root_extra_style = function (el) {\n", - " el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n", - "};\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function (el) {\n", - " // this is important to make the div 'focusable\n", - " el.setAttribute('tabindex', 0);\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " } else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype._key_event_extra = function (event, _name) {\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which === 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "};\n", - "\n", - "mpl.figure.prototype.handle_save = function (fig, _msg) {\n", - " fig.ondownload(fig, null);\n", - "};\n", - "\n", - "mpl.find_output_cell = function (html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i = 0; i < ncells; i++) {\n", - " var cell = cells[i];\n", - " if (cell.cell_type === 'code') {\n", - " for (var j = 0; j < cell.output_area.outputs.length; j++) {\n", - " var data = cell.output_area.outputs[j];\n", - " if (data.data) {\n", - " // IPython >= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] === html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "};\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel !== null) {\n", - " IPython.notebook.kernel.comm_manager.register_target(\n", - " 'matplotlib',\n", - " mpl.mpl_figure_comm\n", - " );\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Index set plot\n", "fig = plt.figure()\n", diff --git a/docs/tutorials/notebooks/build_pce.ipynb b/docs/tutorials/notebooks/build_pce.ipynb index b720d94..b37f2a0 100644 --- a/docs/tutorials/notebooks/build_pce.ipynb +++ b/docs/tutorials/notebooks/build_pce.ipynb @@ -7,12 +7,12 @@ "source": [ "# Simple Example Showing UQ With PCE\n", "\n", - "This example shows some basic functionality of UncertainSCI using the polynomial Chaos emulators (PCE) to quantify uncertainty in a 1D function. It is essentially identical to `demos/build_pce.py` and uses a [1D Laplacian ODE](../models.html) as a model with three parameters" + "This example shows some basic functionality of UncertainSCI using the polynomial Chaos emulators (PCE) to quantify uncertainty in a 1D function. It is essentially identical to `demos/build_pce.py` and uses a [1D Laplacian ODE](../models.md) as a model with three parameters" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "e06c0581", "metadata": {}, "outputs": [], @@ -41,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3e7c6ba0", "metadata": {}, "outputs": [], @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "9f0ab690", "metadata": {}, "outputs": [], @@ -89,12 +89,12 @@ "-\\frac{d}{dx} a(x,p) \\cdot \\frac{d}{dx} u(x,p) = f(x)\n", "$$\n", "\n", - "with $x$ in $[-1,1]$ discretized with $N$ points, where $a(x,p)$ is a Fourier-Series-parameterized diffusion model with the variables $p_j=[a, b, z]$. See the `laplace_ode_1d` [method](../models.html) or `UncertainSCI/model_examples.py` for details." + "with $x$ in $[-1,1]$ discretized with $N$ points, where $a(x,p)$ is a Fourier-Series-parameterized diffusion model with the variables $p_j=[a, b, z]$. See the `laplace_ode_1d` [method](../models.md) or `UncertainSCI/model_examples.py` for details." ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "694c11f5", "metadata": {}, "outputs": [], @@ -124,19 +124,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "3b4d49ee", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Precomputing data for Jacobi parameters (alpha,beta) = (-0.500000, 0.000000)...Done\n", - "This queries the model 66 times\n" - ] - } - ], + "outputs": [], "source": [ "\n", "pce = PolynomialChaosExpansion(distribution=[p1, p2, p3], order=order, plabels=plabels)\n", @@ -157,7 +148,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "5d59274f", "metadata": {}, "outputs": [], @@ -179,45 +170,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "577c137c", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([1.75571628e-37, 5.64860235e-17, 2.10743598e-16, 4.30180091e-16,\n", - " 6.73615485e-16, 8.98426649e-16, 1.06808811e-15, 1.15833221e-15,\n", - " 1.16057868e-15, 1.08209494e-15, 9.43231789e-16, 7.72726181e-16,\n", - " 6.02299430e-16, 4.61625174e-16, 3.74362183e-16, 3.55551159e-16,\n", - " 4.10403164e-16, 5.34387196e-16, 7.14489737e-16, 9.31478341e-16,\n", - " 1.16290358e-15, 1.38643597e-15, 1.58302359e-15, 1.73934375e-15,\n", - " 1.84914225e-15, 1.91328322e-15, 1.93860602e-15, 1.93592175e-15,\n", - " 1.91761943e-15, 1.89536658e-15, 1.87829599e-15, 1.87191182e-15,\n", - " 1.87777401e-15, 1.89387162e-15, 1.91549769e-15, 1.93639635e-15,\n", - " 1.94995954e-15, 1.95029022e-15, 1.93300605e-15, 1.89571844e-15,\n", - " 1.83817752e-15, 1.76211869e-15, 1.67087823e-15, 1.56886365e-15,\n", - " 1.46096875e-15, 1.35201633e-15, 1.24629417e-15, 1.14722754e-15,\n", - " 1.05720583e-15, 9.77557484e-16, 9.08648189e-16, 8.50065649e-16,\n", - " 8.00849025e-16, 7.59724059e-16, 7.25312441e-16, 6.96294722e-16,\n", - " 6.71517851e-16, 6.50048858e-16, 6.31183955e-16, 6.14427000e-16,\n", - " 5.99452329e-16, 5.86065283e-16, 5.74169862e-16, 5.63747820e-16,\n", - " 5.54848130e-16, 5.47581156e-16, 5.42108762e-16, 5.38620514e-16,\n", - " 5.37288102e-16, 5.38194279e-16, 5.41239598e-16, 5.46038218e-16,\n", - " 5.51822165e-16, 5.57379403e-16, 5.61052914e-16, 5.60824129e-16,\n", - " 5.54493189e-16, 5.39951481e-16, 5.15520386e-16, 4.80308188e-16,\n", - " 4.34519740e-16, 3.79646212e-16, 3.18469931e-16, 2.54843985e-16,\n", - " 1.93246402e-16, 1.38157999e-16, 9.33612879e-17, 6.12921066e-17,\n", - " 4.25845893e-17, 3.59260824e-17, 3.82825975e-17, 4.54770963e-17,\n", - " 5.30202417e-17, 5.70278062e-17, 5.50298773e-17, 4.64948566e-17,\n", - " 3.29537537e-17, 1.77021507e-17, 5.15427668e-18, 0.00000000e+00])" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "pce.build(model_output=model_output)" ] @@ -234,7 +190,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "b9009892", "metadata": {}, "outputs": [], @@ -258,93 +214,30 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "09296b66", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAHGCAYAAACmS4sdAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd5hcVf348ff0srO9974pW1M32WRTSQid0AIISImCiIooX0V+YkNRQQUREJGOQmjSCaT3skl2s7333dmZrdP73N8f2YyEhBJaBM7reeZ5kju3nHvm7s5nT/kcmSRJEoIgCIIgCKeI/FQXQBAEQRCErzcRjAiCIAiCcEqJYEQQBEEQhFNKBCOCIAiCIJxSIhgRBEEQBOGUEsGIIAiCIAinlAhGBEEQBEE4pUQwIgiCIAjCKSWCEUEQBEEQTikRjAiCIAiCcEqJYET4SnjiiSeQyWTIZDK2bt163PuSJJGXl4dMJmPJkiVfePn+V+3evZtf/vKXTExMnLIy/PKXv0Qmk31prvdFlPfo89zd3X3Sx37QZ/ppzikInzcRjAhfKeHh4Tz66KPHbd+2bRsdHR2Eh4efglL979q9eze/+tWvTmkwIhzvrLPOYs+ePSQnJ5/0sR/0mX6acwrC500EI8JXypo1a3jppZewWq3HbH/00UeZP38+GRkZp6hkn9ySJUu4+uqrT3UxvjScTuepLsKnFh8fz7x589BoNP/T5xSEz4oIRoSvlMsuuwyAZ599NrTNYrHw0ksvce21157wmLa2Ni6//HISEhLQaDRMmzaNBx544Jh92tvbueaaa8jPz0ev15Oamso555xDXV3dMfsdbcJvaGjgsssuIzIyksTERK699losFstnfLcfbnh4mG9/+9ukp6ej0WiIj49nwYIFbNy4MVTWW2+9FYDs7Ozjurk+j3t+8803KSsrQ6PRkJ2dzT333HPCsp/stQ8dOsRFF11EdHQ0ubm5J329D3Iyx3/Uc/TKK68gk8nYtGnTccc+9NBDyGQyamtrgeO7VE6mPj7oM/2gbpqdO3eyfPlywsPD0ev1VFRU8Oabbx533v+V51r4alKe6gIIwmcpIiKCiy66iMcee4zrr78eOBKYyOVy1qxZw7333nvM/o2NjVRUVJCRkcGf/vQnkpKSeOedd/j+97/PyMgIv/jFLwAYHBwkNjaW3//+98THxzM2NsaTTz5JeXk51dXVTJky5ZjzXnjhhaxZs4brrruOuro6brvtNgAee+yxDy2/JEkEAoHjtkmShN/vP2a7UvnhP75XXnklhw4d4re//S0FBQVMTExw6NAhRkdHAVi7di1jY2Pcf//9vPzyy6Hm++nTp38u97xp0ybOO+885s+fz3PPPUcgEOCPf/wjJpPpuLKf7LUvuOACLr30Um644QYcDsdJX+9ETub4j/McnX322SQkJPD444+zfPnyY45/4oknmDlzJiUlJScsy8etjw/7TE80VmTbtm2sWLGCkpISHn30UTQaDQ8++CDnnHMOzz77LGvWrDlm/0/6XAvCR5IE4Svg8ccflwCpqqpK2rJliwRI9fX1kiRJ0pw5c6Srr75akiRJKiwslBYvXhw67vTTT5fS0tIki8VyzPluuukmSavVSmNjYye8nt/vl7xer5Sfny/98Ic/DG3/xS9+IQHSH//4x2P2v/HGGyWtVisFg8EPvY+jZf84r66urg89l8FgkG6++eYP3efuu+/+WOeSpE9/z+Xl5VJKSorkcrlC+1itVikmJkb6qF9FH3XtO+6447hjPs31Tvb4j/sc3XLLLZJOp5MmJiZC+zQ2NkqAdP/994e2HX2eP+hz+aD6kKQP/kxPdM558+ZJCQkJks1mO+bcRUVFUlpaWuiz+7TPtSB8FNFNI3zlLF68mNzcXB577DHq6uqoqqo6YReN2+1m06ZNrF69Gr1ej9/vD73OPPNM3G43e/fuBcDv9/O73/2O6dOno1arUSqVqNVq2traaGpqOu7c55577jH/Lykpwe12YzabP7Tss2bNoqqq6pjXzJkzOfvss4/bnpKS8qHnmjt3Lk888QR33nkne/fuxefzfVTVHeOzvGeHw0FVVRUXXHABWq02tE94eDjnnHPOp772hRdeeMz/T/Z673cyx5/Mc3TttdficrlYt25d6PjHH38cjUbD5Zdf/oHlOdn6+DgcDgf79u3joosuwmAwhLYrFAquvPJK+vv7aWlpOeaYT/pcC8JHEd00wleOTCbjmmuu4a9//Stut5uCggIqKyuP2290dBS/38/999/P/ffff8JzjYyMAHDLLbfwwAMP8JOf/ITFixcTHR2NXC5n7dq1uFyu446LjY095v9HBw2eaN/3Cg8PZ/bs2cdti42NPW77R1m3bh133nkn//znP/n5z3+O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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "mean_stdev_plot(pce, ensemble=50)" ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "13eae6c0", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAHFCAYAAAAg3/mzAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAACnlklEQVR4nOzdd3iTZffA8e+TpEm6S1taVsseZe8p4gIFxPX6ihMX/sQNvC6cOHGLvgoOBJyIr3vgwIEgqCAbWjaljELp3pnP74+bNE0Xbenu+VxXLtonT5I7pU1Ozn3uc2u6rusIIYQQQtQTQ30PQAghhBDNmwQjQgghhKhXEowIIYQQol5JMCKEEEKIeiXBiBBCCCHqlQQjQgghhKhXEowIIYQQol5JMCKEEEKIeiXBiBBCCCHqlQQjollYvHgxmqahaRorVqwodb2u63Tp0gVN0zjjjDNq9LE7dOjAddddV/T9ihUryh2HqHkfffQRc+fOLfM6TdOYPXt20fc1/X+TmJiIpmm88MILNXJ/NeWMM86o8d9zIU6FBCOiWQkODuadd94pdfz3339n7969BAcH1/oYBg4cyJ9//snAgQNr/bFExcHIn3/+ydSpU+t2QEKIUiQYEc3K5MmT+eyzz8jOzvY5/s477zBixAhiY2NrfQwhISEMHz6ckJCQWn+syujQoYNPdqA5GT58OO3atavvYQjR7EkwIpqVK664AoAlS5YUHcvKyuKzzz7jhhtuKPM2drudJ598kh49emCxWGjZsiXXX389x48f9znP4XBw77330qpVKwICAjjttNNYu3Ztqfsrayrgn3/+4fLLL6dDhw74+/vToUMHrrjiCg4cOOBzW89002+//cYtt9xCZGQkERERXHLJJRw5cqS6P5Zq++677+jfvz8Wi4WOHTvywgsvMHv2bDRNKzrHM1WxePHiUrcvOU2yZ88err/+erp27UpAQABt27Zl0qRJbN261ed2np/hkiVLePDBB2nTpg0hISGcc8457Ny5s+i8M844g++++44DBw4UTdMVH1vJxy/PP//8wwUXXEB4eDhWq5UBAwbwySefVPrn5Ha7eeqpp4iNjcVqtTJ48GB++eUXn3Nq+rmDmn587rnnaN++PVarlYEDB/L999+XOb4nn3yS7t274+/vT1hYGH379uWVV16p9HMU4lRIMCKalZCQEC699FIWLlxYdGzJkiUYDAYmT55c6ny3282FF17IM888w5VXXsl3333HM888w/LlyznjjDMoKCgoOvemm27ihRdeYMqUKXz11Vf861//4pJLLiEjI+Ok40pMTKR79+7MnTuXH3/8kWeffZbk5GSGDBlCampqqfOnTp2Kn58fH330Ec899xwrVqzg6quvruZPpXp++eUXLrzwQoKDg/n44495/vnn+eSTT1i0aFG17/PIkSNERETwzDPP8MMPP/D6669jMpkYNmxYqTdagAceeIADBw6wYMEC3nrrLXbv3s2kSZNwuVwAzJs3j1GjRtGqVSv+/PPPoktV/Pbbb4waNYrMzEzeeOMNvvrqK/r378/kyZPLDLDK8tprr/HDDz8wd+5cPvjgAwwGA+PHj/cZS00/d4DHHnuM++67j7Fjx/Lll19yyy23cNNNN5W6v+eee47Zs2dzxRVX8N1337F06VJuvPFGMjMzq/SzEqLadCGagUWLFumAvm7dOv23337TAX3btm26ruv6kCFD9Ouuu07XdV3v1auXPmbMmKLbLVmyRAf0zz77zOf+1q1bpwP6vHnzdF3X9YSEBB3QZ8yY4XPehx9+qAP6tddeW3TM8/i//fZbueN1Op16bm6uHhgYqL/yyiulnsett97qc/5zzz2nA3pycnKFPwe32607HA6fS/v27fWHH3641PGTGTZsmN6mTRu9oKCg6Fh2drYeHh6uF39p2b9/vw7oixYtKnUfgP7oo4+W+xhOp1O32+16165dfX62np/hhAkTfM7/5JNPdED/888/i45NnDhRb9++fZn3X/Lxy/q/6dGjhz5gwIBSP5Pzzz9fb926te5yucodv+e5l/dzOuecc2rtuWdkZOhWq1W/+OKLfc5bvXq1Dvj8np9//vl6//79yx2LELVNMiOi2RkzZgydO3dm4cKFbN26lXXr1pU7RfPtt98SFhbGpEmTcDqdRZf+/fvTqlWroqmW3377DYCrrrrK5/aXXXYZJpPppGPKzc3lvvvuo0uXLphMJkwmE0FBQeTl5ZGQkFDq/AsuuMDn+759+wKUmtYp6d1338XPz8/ncuDAAZ544olSxyuSl5fHunXruOSSS7BarUXHg4ODmTRp0kmfb3mcTidPP/00PXv2xGw2YzKZMJvN7N69u0Z/DpW1Z88eduzYUfT/Wvx3YMKECSQnJ5eZtSipvJ/TypUrizIZNf3c//zzTwoLC0v9To4cOZL27dv7HBs6dCibN2/m1ltv5ccffyxVUyVEbTv5q6QQTYymaVx//fW8+uqrFBYW0q1bN0aPHl3muceOHSMzMxOz2Vzm9Z4plLS0NABatWrlc73JZCIiIuKkY7ryyiv55ZdfePjhhxkyZAghISFomsaECRN8poI8St6nxWIBKPPc4iZNmsS6det8jl1wwQWcf/75/N///d9Jx+mRkZGB2+0u9Xyh9M+gKmbOnMnrr7/Offfdx5gxY2jRogUGg4GpU6fW6M+hso4dOwbA3Xffzd13313mOWVNo5VU3s/JbreTm5tLaGhojT/38n4nyzo2a9YsAgMD+eCDD3jjjTcwGo2cfvrpPPvsswwePPikz0+IUyXBiGiWrrvuOh555BHeeOMNnnrqqXLP8xSI/vDDD2Ve71kK7HljOHr0KG3bti263ul0Fr0plCcrK4tvv/2WRx99lPvvv7/ouM1mIz09vdLPqTIiIiJKvYmZzWbatGlTpTedFi1aoGkaR48eLXVdyWOejIDNZvM5XtbP5YMPPmDKlCk8/fTTPsdTU1MJCwur9PhqSmRkJKDerC+55JIyz+nevftJ76e8n5PZbCYoKAio+ede/HeyrMfu0KFD0fcmk4mZM2cyc+ZMMjMz+fnnn3nggQc499xzOXjwIAEBAVV+fCGqQqZpRLPUtm1b7rnnHiZNmsS1115b7nnnn38+aWlpuFwuBg8eXOrieSPyNJD68MMPfW7/ySef4HQ6KxyLpmnoul70ydZjwYIFPsWIDUlgYCBDhw7l888/p7CwsOh4Tk4O33zzjc+50dHRWK1WtmzZ4nP8q6++KnW/mqaV+jl89913HD58uNpjtVgs1c6UdO/ena5du7J58+Yy//8HDx5cqd405f2cRo8ejdFoBGr+uQ8fPhyr1Vrqd3LNmjUVTmOFhYVx6aWXctttt5Genk5iYmK1Hl+IqpDMiGi2nnnmmZOec/nll/Phhx8yYcIE7rrrLoYOHYqfnx+HDh3it99+48ILL+Tiiy8mLi6Oq6++mrlz5+Ln58c555zDtm3beOGFF07aTyQkJITTTz+d559/nsjISDp06MDvv//OO++8Uy/ZgMp64oknOO+88xg7diz/+c9/cLlcPPvsswQGBvpkdDRN4+qrr2bhwoV07tyZfv36sXbtWj766KNS93n++eezePFievToQd++fVm/fj3PP//8KfUC6dOnD59//jnz589n0KBBGAyGKmWB3nzzTcaPH8+5557LddddR9u2bUlPTychIYENGzbwv//976T3YTQaGTt2LDNnzsTtdvPss8+SnZ3NY489VnROTT/3Fi1acPfdd/Pkk08ydepU/v3vf3Pw4EFmz55dappm0qRJ9O7dm8GDB9OyZUsOHDjA3Llzad++PV27dq3W4wtRFRKMCFEBo9HI119/zSuvvML777/PnDlzMJlMtGvXjjFjxtCnT5+ic9955x2io6NZvHgxr776Kv379+ezzz7j8ssvP+njfPTRR9x1113ce++9OJ1ORo0axfLly5k4cWJtPr1T4lku+tBDDzF58mRatWrFrbfeSkFBgc+bLMCLL74IqCWkubm5nHXWWXz77bc+UwUAr7zyCn5+fsyZM4fc3FwGDhzI559/zkMPPVTtcd51111s376dBx54gKysLHRdR9f1St/+zDPPZO3atTz11FNMnz6djIwMIiIi6NmzJ5dddlml7uP222+nsLCQO++8k5SUFHr16sV3333HqFGjis6pjef++OOPExgYyLx583j//ffp0aMHb7zxRqn29GeeeSafffYZCxYsIDs7m1atWjF27FgefvjhkxYzC1ETNL0qf5VCCHESs2fP5rHHHqvSG74QonmTmhEhhBBC1CsJRoQQQghRr2SaRgghhBD1SjIjQgghhKhXEowIIYQQol5VKxiZN28eHTt2xGq1MmjQIFatWlXuudddd53P1t2eS69evao9aCGEEEI0HVWuGVm6dCnXXHNN0dbcb775JgsWLCA+Pp7Y2NhS52dlZfl0P3Q6nfTr14877riD2bNnV+ox3W43R44cITg4GE3TqjJcIYQQQtQTXdfJycmhTZs2GAwV5D+qus3v0KFD9WnTpvkc69Gjh37//fdX6vZffPGFrmmanpiYWOnHPHjwoA7IRS5ykYtc5CKXRng5ePBghe/zVerAarfbWb9+vc9mXgDjxo1jzZo1lbqPd955h3POOafUFtbF2Ww2n0219BPJm4MHD560tbYQQgghGobs7GxiYmJOuodTlYKR1NRUXC4X0dHRPsejo6PL3BmypOTkZL7//vsy96Qobs6cOaXaSYPaw0OCESGEEKJxOVmJRbUKWEveqa7rlarlWLx4MWFhYVx00UUV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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "quantile_plot(pce, bands=3, xvals=x, xlabel='$x$')" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "f9367274", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGZCAYAAAAUzjLvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8qNh9FAAAACXBIWXMAAA9hAAAPYQGoP6dpAABV5ElEQVR4nO3dd3hUZdoG8PtMn0x6JYFACKFDaNKlCYIoVhAXEBDLYllWlNW1LiD2hvrZG9hB3EUEpQooItI7oQVCCOm9Taae74+QgZBCEjLzTrl/18WumZw555mSM/e87UiyLMsgIiIin6UQXQARERGJxTBARETk4xgGiIiIfBzDABERkY9jGCAiIvJxDANEREQ+jmGAiIjIxzEMEBER+TiGASIiIh/HMOAmtm/fjltvvRWtW7eGVqtFVFQUBg4ciDlz5oguDZs3b4YkSdi8ebPjtl9++QXz5s2rdfu4uDjcddddTj+OMzS19it15MgRzJs3DykpKS4/dnOp7fVrqMWLF0OSJOzateuy2951112Ii4trfIGXOXZTnvv09HTMmzcP+/bta7Z6nKW8vBzz5s2r9fW5kueAvAPDgBv4+eefMWjQIBQXF+PVV1/FunXr8Pbbb2Pw4MFYunSp6PLQu3dvbNu2Db1793bc9ssvv2D+/Pm1br98+XI8++yzTj+ONzly5Ajmz5/v0Sfj2l4/T3DDDTdg27ZtiI6ObvR909PTMX/+fI8JA/Pnz681DFzJc0DeQSW6AAJeffVVtG3bFmvXroVKdeEl+dvf/oZXX31VYGWVAgMDMWDAgAZv36tXL5cch9yDxWKBJEke+/pFREQgIiJCdBnVGI1G6HQ6SJLkkuO543NArsWWATeQl5eH8PDwakGgikJR8yVaunQpBg4cCIPBAH9/f4wZMwZ79+6tts1dd90Ff39/nDx5Etdffz38/f0RGxuLOXPmwGQyVdv2gw8+QI8ePeDv74+AgAB06tQJTz31lOP3lzb/3nXXXXjvvfcAAJIkOf5Vfau9uKk9JycHGo2m1paCo0ePQpIkvPPOO40+zsiRI9GpUydcep0tWZaRkJCAG264oban2sFiseDxxx9HixYt4Ofnh6uvvho7duyosd28efNqPSHX1azakNemtn3dfvvtAIARI0Y4HufixYsd23z++efo0aMHdDodQkNDceuttyIpKane/e7fvx+SJOGzzz6r8bvVq1dDkiT89NNPAICTJ09ixowZaN++Pfz8/NCyZUvceOONOHjwYLX7Vb1GX331FebMmYOWLVtCq9Xi5MmTtXYT7Nq1C3/7298QFxcHvV6PuLg4TJo0CWfOnKm15oKCAsyYMQOhoaEwGAy48cYbcerUqXofJ1D5ur///vvo2bMn9Ho9QkJCMGHChAbdt7bXcvjw4ejWrRt27tyJIUOGwM/PD/Hx8Xj55Zdht9sdz0Xfvn0BADNmzHC8bhd3a+3atQs33XQTQkNDodPp0KtXL3z//fe1Hn/dunW4++67ERERAT8/P5hMpga/LgBQWFiIOXPmID4+HlqtFpGRkbj++utx9OhRpKSkOD7s58+f76i16u+0rvdzQ953zXmuIXEYBtzAwIEDsX37dvzzn//E9u3bYbFY6tz2xRdfxKRJk9ClSxd8//33+Oqrr1BSUoIhQ4bgyJEj1ba1WCy46aabMHLkSKxYsQJ33303Fi5ciFdeecWxzZIlS/Dggw9i2LBhWL58OX788Uc88sgjKCsrq7OGZ599FhMmTAAAbNu2zfGvtibGiIgIjBs3Dl988YXjJFpl0aJF0Gg0mDJlSqOP8/DDD+PYsWP49ddfq91n9erVSE5OxkMPPVRn/QBw33334fXXX8e0adOwYsUKjB8/HrfddhsKCgrqvV99GvPaXOyGG27Aiy++CAB47733HI+zKtC89NJLuOeee9C1a1f873//w9tvv40DBw5g4MCBOHHiRJ377dGjB3r16oVFixbV+N3ixYsdHxZAZXN3WFgYXn75ZaxZswbvvfceVCoV+vfvj2PHjtW4/5NPPonU1FR8+OGHWLlyJSIjI2utISUlBR07dsRbb72FtWvX4pVXXkFGRgb69u2L3NzcGtvfc889UCgU+Pbbb/HWW29hx44dGD58OAoLC+t8nAAwc+ZMzJ49G6NGjcKPP/6I999/H4cPH8agQYOQlZVV733rkpmZiSlTpuDOO+/ETz/9hLFjx+LJJ5/E119/DaCyW6TquX3mmWccr9u9994LANi0aRMGDx6MwsJCfPjhh1ixYgV69uyJO+64o1rQq3L33XdDrVbjq6++wg8//AC1Wt3g16WkpARXX301PvroI8yYMQMrV67Ehx9+iA4dOiAjIwPR0dFYs2aN4zmuqrW+7rzGvO+cda4hF5JJuNzcXPnqq6+WAcgAZLVaLQ8aNEh+6aWX5JKSEsd2qampskqlkmfNmlXt/iUlJXKLFi3kiRMnOm6bPn26DED+/vvvq217/fXXyx07dnT8/I9//EMODg6ut75NmzbJAORNmzY5bnvooYfkut4+bdq0kadPn+74+aeffpIByOvWrXPcZrVa5ZiYGHn8+PFNOo7NZpPj4+Plm2++udrtY8eOldu1ayfb7fY6H09SUpIMQH7kkUeq3f7NN9/IAKrVPnfu3FqPv2jRIhmAfPr0aVmWG/fa1GbZsmU1Hrssy3JBQYGs1+vl66+/vtrtqampslarlSdPnlzvft955x0ZgHzs2DHHbfn5+bJWq5XnzJlT5/2sVqtsNpvl9u3bV3ueql6joUOH1rhPba9fbfstLS2VDQaD/Pbbbztur3o+b7311mrbb926VQYgP//8847bpk+fLrdp08bx87Zt22QA8htvvFHtvmfPnpX1er38+OOP11nPxceuei1lWZaHDRsmA5C3b99ebdsuXbrIY8aMcfy8c+dOGYC8aNGiGvvt1KmT3KtXL9lisVS7fdy4cXJ0dLRss9mqHX/atGn11inLdb8uzz33nAxAXr9+fZ33zcnJkQHIc+fOrfG7S5+DxrzvmvNcQ+KwZcANhIWFYcuWLdi5cydefvll3HzzzTh+/DiefPJJdO/e3fENau3atbBarZg2bRqsVqvjn06nw7Bhw2oMDJIkCTfeeGO12xITE6s10fbr1w+FhYWYNGkSVqxYUeu3tSs1duxYtGjRoto31LVr1yI9PR133313k/apUCjwj3/8A6tWrUJqaioAIDk5GWvWrMGDDz5Yb1/rpk2bAKBGi8TEiRNr7appiMa+Ng21bds2GI3GGjMcYmNjcc0119RoGbnUlClToNVqq30T/e6772AymTBjxgzHbVarFS+++CK6dOkCjUYDlUoFjUaDEydO1NodMX78+AbVX1pain//+99ISEiASqWCSqWCv78/ysrKat3vpa/JoEGD0KZNG8drVptVq1ZBkiTceeed1Z77Fi1aoEePHk1+7lu0aIF+/fpVu+3Sv5+6nDx5EkePHnU8novruv7665GRkVGjxaW257Shr8vq1avRoUMHjBo1qikPtYbGvu/c5VxDTccw4Eauuuoq/Pvf/8ayZcuQnp6ORx55BCkpKY5BhFXNnX379oVara72b+nSpTX+uPz8/KDT6ardptVqUVFR4fh56tSp+Pzzz3HmzBmMHz8ekZGR6N+/P9avX99sj0ulUmHq1KlYvny5o7l38eLFiI6OxpgxY5q837vvvht6vR4ffvghgMomdr1ef9mAkZeXB6DyZH9pnWFhYU2qpbGvTUNV1VpbF0xMTIzj93UJDQ3FTTfdhC+//BI2mw1A5XPfr18/dO3a1bHdo48+imeffRa33HILVq5cie3bt2Pnzp3o0aMHjEZjjf02dNT55MmT8e677+Lee+/F2rVrsWPHDuzcuRMRERG17vfS16TqtvoeZ1ZWFmRZRlRUVI3n/q+//mryc1/be0Gr1dZad201AcC//vWvGjU9+OCDAFCjrtqe04a+Ljk5OWjVqlWjHl99Gvu+c5dzDTUdZxO4KbVajblz52LhwoU4dOgQACA8PBwA8MMPP6BNmzbNdqwZM2ZgxowZKCsrw++//465c+di3LhxOH78eLMdZ8aMGXjttdewZMkS3HHHHfjpp58we/ZsKJXKJu8zKCgI06dPx6effop//etfWLRoESZPnozg4OB671d1ks/MzETLli0dt1ut1honuaoTnMlkglarddx+6YncWa9NVa0ZGRk1fpeenu44bn1mzJiBZcuWYf369WjdujV27tyJDz74oNo2X3/9NaZNm+YYu1AlNze31uezIaPci4qKsGrVKsydOxdPPPGE43aTyYT8/Pxa75OZmVnrbQkJCXUeJzw8HJIkYcuWLdVeoyq13eZsVa/Lk08+idtuu63WbTp27Fjt59qe04a+LhEREUhLS7vCqi9ojvddbVxxrqGmYRhwA1UDfC5V1QwYExMDABgzZgxUKhWSk5Mb3EzbGAaDAWPHjoXZbMYtt9yCw4cP1/kHWnWCNRqN0Ov1l913586d0b9/fyxatAg2m61GM3VdLnecf/7zn3j//fcxYcIEFBYW4h//+Mdl9zl8+HAAwDfffIM+ffo4bv/+++9htVqrbVu1uM2BAwccI8cBYOXKldW2u9LX5uLHebGBAwdCr9fj66+/dsw4AIC0tDRs3LjRMcCyPqNHj0bLli2xaNEitG7dGjqdDpMmTaq2jSRJNT40f/75Z5w7d67eD+L6SJIEWZZr7PfTTz91tFJc6ptvvqn2/P355584c+aMY1BebcaNG4eXX34Z586dw8SJE5tUa1PV9bp17NgR7du3x/79+2t8kDdGQ1+XsWPH4j//+Q82btyIa665plG11qY53nf1acy5hlyDYcANjBkzBq1atcKNN96ITp06wW63Y9++fXjjjTfg7++Phx9+GEDlB9Nzzz2Hp59+GqdOncJ1112HkJAQZGVlYceOHTAYDI1eoOe+++6DXq/H4MGDER0djczMTLz00ksICgqq9uF3qe7duwMAXnnlFYwdOxZKpRKJiYnQaDR13ufuu+/GzJkzkZ6ejkGDBtX4ZtSU43To0AHXXXcdVq9ejauvvho9evS47D47d+6MO++8E2+99RbUajVGjRqFQ4cO4fXXX0dgYGC1ba+//nqEhobinnvuwXPPPQeVSoXFixfj7Nmz1ba70temW7duAICPP/4YAQEB0Ol0aNu2LcLCwvDss8/iqaeewrRp0zBp0iTk5eVh/vz50Ol0mDt37mUfr1KpxLRp0/Dmm28iMDAQt912G4KCgqptM27cOCxevBidOnVCYmIidu/ejddee+2Kmp4DAwMxdOhQvPbaawgPD0dcXBx+++03fPbZZ3W23uzatQv33nsvbr/9dpw9exZPP/00WrZs6Whar83gwYPx97//HTNmzMCuXbswdOhQGAwGZGRk4I8//kD37t3xwAMPNPlx1Kddu3bQ6/X45ptv0LlzZ/j7+yMmJgYxMTH46KOPMHbsWIwZMwZ33XUXWrZsifz8fCQlJWHPnj1YtmzZZfff0Ndl9uzZWLp0KW6++WY88cQT6NevH4xGI3777TeMGzcOI0aMQEBAANq0aYMVK1Zg5MiRCA0NdbwulwoODr7i992lmnquIRcRPYKRZHnp0qXy5MmT5fbt28v+/v6yWq2WW7duLU+dOlU+cuRIje1//PFHecSIEXJgYKCs1WrlNm3ayBMmTJA3bNjg2Gb69OmywWCocd9LR8d/8cUX8ogRI+SoqChZo9HIMTEx8sSJE+UDBw44tqltlLjJZJLvvfdeOSIiQpYkqdpI5EtnE1QpKiqS9Xq9DED+5JNPavy+scepsnjxYhmAvGTJkhr7rIvJZJLnzJkjR0ZGyjqdTh4wYIC8bdu2WmvfsWOHPGjQINlgMMgtW7aU586dK3/66ae11tKQ16Yub731lty2bVtZqVTWGKH+6aefyomJibJGo5GDgoLkm2++WT58+HCDH+/x48cds1VqG3FeUFAg33PPPXJkZKTs5+cnX3311fKWLVvkYcOGycOGDXNsV/UaLVu2rMY+anv90tLS5PHjx8shISFyQECAfN1118mHDh2q8TxXjWZft26dPHXqVDk4ONgxmv3EiRPVjnPpbIIqn3/+udy/f3/ZYDDIer1ebteunTxt2jR5165d9T43dc0m6Nq1a41tazv2d999J3fq1ElWq9U1Ruvv379fnjhxohwZGSmr1Wq5RYsW8jXXXCN/+OGHNY6/c+fOGsdr6OtSte3DDz8st27dWlar1XJkZKR8ww03yEePHnVss2HDBrlXr16yVqutNnOmtudAlhv2vmvOcw2JI8nyJau2EHmY8ePH46+//kJKSgrUarXocoiIPA5nE5BHMplM2LZtG95++20sX74cjz32GIPAFRo+fDhmz57d5Ps05f5E5B44ZoA8UkZGBgYNGoTAwEDMnDkTs2bNEl0SEZHHYhggjxQXF1fjugRERNQ0HDNARAAqV4xLS0tDYWFhtaAVGBiIIUOG4O2330a7du2q3Uer1cJsNtfYl0KhQHBwMB544AEsWLCg2hz6uLi4Wlfx46mISByOGSAiAIDNZkNpaSmGDRuGe++917Egk1arhSRJuPXWW2tcbKpPnz7w8/PDlClT0KVLF8ftQ4cOxTvvvIOFCxfi008/rXafnTt3IiMjAxkZGUhLS8OAAQMwZMgQ5z9AIqoTWwaICEDlAMDs7GwcPnwYkiQhJyfHcTXC3377DcOGDcPBgwcdayJcep9WrVohPT3dcbniI0eO4IknnsBPP/1U51UbH374YaxYscKxRDERicGWASICULkyXWlpKQICAqBQKKpdlvjaa68FAMdFoS42YMAAfPLJJ8jIyEBAQABeeuklnDhxAjabzXG529pWHPz444/x2WefYcWKFQwCRIIxDBARAODQoUPIyMhAp06d0KJFC/Ts2dPxu6rr0tc2PiAjI8NxpcjRo0c3aHnqzZs3Y9asWfjyyy8btGokETkXwwARIS8vD+Xl5bBarZg3bx4yMjKqXQ+gvLy81vsZjUasXbsWsiyjW7duOHLkCP766y+0b98eSqWy2n9XOXnyJMaPH4+nnnqqzov4EJFrccwAEcFut0Or1cJqtSI+Pt5xtbqqi9okJCTg5MmTWL58OW655RbH70JDQ1FRUYFevXrBbDbj+PHjkGUZc+bMQY8ePXDffffhjTfewMyZMx336d27N2JiYvD1119Xm2VQ2+WLicg1GAaICADQo0cPnDp1CqWlpTV+t2DBAjz77LPVwkBKSgratm1b674UCgWCgoIwc+ZMvPjii44P/fruw1MRkTgMA0RERD6OYwaIyCekpKRAkqQa/4YPHy66NCLhuBwxEfmE2NhYx1gIAMjMzMSoUaMwdOhQgVURuQd2ExCRz6moqMDw4cMRERGBFStWQKFgIyn5NrYMEJHPueeee1BSUoL169czCBCBYYCIfMzzzz+PNWvWYMeOHQgICBBdDpFbYDcBEfmM//73v5g0aRJWr16NkSNHii6HyG0wDBCRTzh06BD69++PRx99FA899JDjdo1Gg9DQUIGVEYnHMEBEPmHx4sWYMWNGjduHDRuGzZs3u74gIjfCMEBEROTjOIyWiIjIxzEMEBER+ThOLSTyAhUWGwrLLcgvM6Ow3IyCcgsKys0oKKv878JyMwqNFpisNtjsMux2wCbLsNllSHY7/q4uhMoagYQtCyGp1Ng1ti02RxdAq9RCp9JBr9JDp9TBoDYgTB+GCH0EIvwiEK4PR7g+HCoFTyVEnox/wUQeIL/MjNO5pUjOKcOpnDKczi1FWoHR8WFvtNiavG8VgJKAQijMgajYfwAAkNXbjt9sBxt0fwkSQnQhCNeHI0JfGRCqgkKMIQYJwQloFdCq2uWKici9MAwQuQmT1YaU3HKcyinFqdzKD/1TuaU4nVuGwnKLcw8uA5AujCU2KeyNuKuM/Ip85Ffk43jB8Vq30av0aBvUFgnBCUgITkC74HZoH9we0f7RV1o5ETUDhgEiAWRZxsnsUuw6U4DdZwqwJ7UAKbllsAub2yNBcdEXd5Oy4WGgIYxWI47kHcGRvCPVbvdX+yM+ON4RErqHd0fX8K5QK9TNenwiqh/DAJELGM027DtbiN1n8s9/+BeiyOjkb/uNIF/0vwBgkpo3DNSl1FKKAzkHcCDngOM2vUqPxPBE9Inqg6taXIXEiERolVqX1EPkqxgGiJwgu7gCO1LysSul8lv/kfRiWMV97b8s6fy/KiZF08cgXCmj1YjtmduxPXM7sB9QK9ToHt4dfaL6oE9UH/SK7AU/tZ+w+oi8EcMAUTOw22XsPVuITUez8evRbCRlFIsuqdGki8YMVAgMA5ey2C3Yk70He7L34JODn0AlqdAptBP6RvfF8FbD0TOyJxQSZ0kTXQmGAaImKjNZ8dvxHGxIysJvx3KQV2YWXdIVkKq1DFQorMIquRyrbMWhvEM4lHcIiw4tQqguFENbDcWI2BEYGDMQepVedIlEHodhgKgRiowWbDiShTWHM/H78RyYrK7pW3cFqdqYAfdpGbic/Ip8/HjyR/x48kfolDoMihmE0XGjMTx2OAxqg+jyiDwCwwDRZZSZrPj5QAZWHczAtuRcWGzu2/ffVDKqhwGjG3UTNEaFrQIbz27ExrMboVVqMThmMEbHjcaI2BEcZ0BUD4YBojrsTS3Akh1nsepAOsrMnvnh2FCVAwgvGjMA95np0FQmm6laMLi2zbWY0GEC+kT1EV0akdthGCC6SFG5Bf/bm4alO8/iaGaJ6HJcR3b8DwDA6MZjBprCZDNh1alVWHVqFdoFtcOEDhNwY7sbEaQNEl0akVtgGCACsC05D0t2pmLNoUyvGgfQYJJ08QKEKJc8v2WgLslFyXhl5yt4a89bGN1mNG7veDt6RfYSXRaRUAwD5LNySkz4YXcavt91Fqdzy0SXI5QsAxIuhKByyZNnRjSMyWbCylMrsfLUSiQEJzhaCwI1gaJLI3I5SZZl7xsNRVSP41kleG/TSfxyMMMrBwM2lgrAC4YiBMqhiPv2EUCSMPEJpeiyhNApdRgdNxrTu05Hh5AOosshchm2DJDPOJBWiHc3nsT6pCwwAtdU1TIgqdUAfLCrBJWzEX5K/gkrk1dieOxwzEycia7hXUWXReR0DAPk9Xaczse7m07i9+M5oktxb1UBSaMGYBJZiXAyZGw6uwmbzm7C4JaDcX/i/egZ2VN0WUROwzBAXuv34zl4d+NJ7EjJF12K25MgQaq6OJGaYeBiW89txdZzW9G3RV/MTJyJ/tH9RZdE1OwYBsiryLKM9Uey8N6mk9ifViS6HI8hA5Cq+k7UPC3UZmfmTuzM3ImeET1xX+J9GNpqqOiSiJoN/+rJa/xyMAPv/HrCt9YHaEaORYfUarGFuLl9Ofvw0K8PoXNoZ9zf435c0/oa0SURXTGGAfJ4h84VYf7Kw9iZUiC6FA8mAfL5bgKVb84kaKyk/CQ8vOlh9G3RF//u+290DO0ouiSiJmMYII+VW2rCa2uOYdnus7BzdsAVkWXZ0TIga3haaIydmTtxx6o7cFv72zCr1yyE6EJEl0TUaPyrJ49jsdmxeGsK3tl4AiUV3rVsrigSpAthQMXTQmPZZBuWHV+GNSlrcH/i/ZjUeRLUCna3kOdQiC6AqDF+TcrCmIW/44VfkhgEmpl0vpvArmY3QVOVmEvw2q7XMP6n8fjj3B+iyyFqMH4FII9wMrsUC1YdwW9cK8A5pAuzCewqfke4UqeLTuOBDQ9gSMsheKzvY2gb1FZ0SUT1Yhggt1ZcYcFb60/gy20psHJggNPIsoSqVQftHEDYbLac24JtGdswudNkPNTzIfip/USXRFQrfgUgt7XhSBZGvfEbPt96mkHABRwtA+wmaFZWuxVfHvkSt664FX+m/ym6HKJaMQyQ2yksN2P2kr2498tdyC7hSniu4hgzoJQEV+Kd0svSMXP9TMz9cy5KzFwLg9wLwwC5lXWHM3Htwt/x47500aX4GNmxzoBNzdOCM/3vxP9wy4pb8Hva76JLIXLgXz25hSKjBY8s3Ye/f7UbOWwNcLmLpxZalTwtOFt2eTaO7/wAWPEQYGIrAYnHAYQk3LbkPPxr2X6cKzSKLsVnVV6b4HzLAIcMOF1iYDxmHFgLyDbg9O/ALR8CcYNFl0U+jF8BSBiz1Y6XfknClE//YhBwA1VhwKrimAFn0iq1WJCRBqVsq7yhMBX4Yhyw7hnAZhFbHPkshgES4nhWCW5+bys++v0UlxJ2CxJgZxhwhVl+CYjPPln9RtkO/Pl/wOfXAYVnxRRGPo1hgFxu+d403PTuH0jKKBZdCp0ny4B0fp0BK7sJnKZ3UAKmHlxb9wbndgEfDQVOrHddUURgGCAXstrsmL/yMB5Zuh8VFrvocugiEuCYTWDhWcEp9EodFqSdhkK+zHvfmA98czvw63OA3eaa4sjn8c+eXCKv1IQ7P9uORVtTRJdCdZDOdxNYOKzYKWbr26J17ukGbi0DW94AvrwZKMlyal1EAMMAucDBtCLc9O5W/HUqX3QpVBcJqFqO2KLgII7m1j+oAyYdXNf4O6ZsAT4aAqTwokfkXAwD5FT/25OGCR/+ydkC7k6WLrQMKBkGmpNB5Yfnzhx3rOPQaKVZwBc3AX++27yFEV2EYYCcwmqzY95Ph/Ho9/thsnJ8gLurXGegsn/azDDQrP6liUVMQeqV7US2AeueBlY9Ath46W5qfuwdpGaXV2rCg9/swfbT7BbwKOfneJrZTdBsBgd3woS9TegeqMuuz4GCFOD2LwBdYPPtl3weWwaoWR1MK8KN//cHg4AHqmoZMCk4gr05BKj9Mf/UoebfcfJG4LPRlYsVETUThgFqNltO5OCOj7chvahCdCnUFOenvLGboHk8oYxGVJGTLriVkwR8MhJI2+Wc/ZPPYRigZvHLwQzcs3gXys38VumRZAmSnS0DzWV4cBfclPSrcw9Slg0sHgccXu7c45BPYBigK7ZkRypmfbcXZhsHCnq08y0DJgVfxysRrAnC3BN7XHMwqxFYNgPY+o5rjkdei2GArshHvyXjif8dhI0XGPBs0oVFhyokjla/Ek8jDOGl2S48ogysfxbY9KILj0nehmGAmuyVNUfx0uqjosugZiDLqJy+BrYMXInRIV1x3bHNYg7+2yvA2qfFHJs8HqcWUqPZ7TKeWXEI327naGbvcWHMgFHBloGmCNWG4JljO8QWse1dwFwGjFsISLz6JDUcwwA1isVmx+yl+/DzgQzRpVCzkh1hoEKyCK7FM/3HFoiQsjzRZQC7FwEWI3DL+4CCl6CkhmE3ATWY0WzDvV/sYhDwQpVXLawc92HkbIJGGxfSDSNPbBFdxgUHlgDLpgNWs+hKyEMwDFCDGM02TPt8O347niO6FHIKCdL5ZW6NYDdBY0TqwvBk0lbRZdSUtBJYMhmwcN0PujyGAboss9WOmV/vxs6UAtGlkJNUDiCsHDhoVLCboDHmmXUINBaJLqN2J9cD308DbHxNqX4MA1Qvu13GI9/vw+9sEfB+jpYBfnA01G0h3TEkeZvoMup3Yi2w/H7AzlkiVDeGAarXMysOcYyAj5CqWgY4gLBBovUReOyIG40TqM+hH4Bf5oiugtwYwwDV6bW1Rzl90GdIgN0GqNWQOSPtsiRIeM6ohH9FsehSGm7X58D6uaKrIDfFMEC1+nTLKby3KVl0GeRKdhsktVp0FR5hYkg3DDgteE2Bptj6FvDHQtFVkBtiGKAalu06ixd+SRJdBrmYZLcDGoaBy4n1a4FHD20WXUbTbZhX2UpAdBGGAapm7eFMPPG/g1VTzskHVL3Uks0KsGWgXgpJgQUlNviZy0SXcmV+ngMc/EF0FeRGGAbI4c/kXMz6bi8vOuRjJMiVicBuA9RclLQ+U4K6oU/qbtFlXDnZDvz4IHDWA7s6yCkYBggAcOhcEf7+5W6YrZx+5JukyqmFDAN1ijO0xMMHN4guo/nYTJWLEhWeFV0JuQGGAUJOiQn3fbkLpSauPOerZACQbZAZBmqllJR4obAcWquXreZXlgN8ewdgKhVdCQnGMODjzFY77v96NzKKvOwkR40m2WyQVbywTW3uCuqCxLT9ostwjuzDwH/v5aJEPo5hwMc9++Mh7D7DZYYJgN0KWc0wcKkE/1g8dGC96DKc6/hqYMN/RFdBArFN0Ict3noaS3exv9Bb5Kx4BeXH/sDFU0FUITEIG/tP6GK71di+cOt3KPrjWwAy7kTllQu7h4WgpE0gAroHIGdVDrL+lwVUfWGUgKABQWh5T0tYi6w4/vhxqAJUkFQS2j7ZFpowjSsepkupJBVeyCuE2uYDV//78/+A8I5A76miKyEB2DLgo7Yl5+H5n7mWgLfI3/ARyo9ucQQBhSEEAGAtyEDW93NhLc6utr0x9SCK/vgGUKqhbdkZOo2+ckIBgNS3UlF2qgxZ/82qTAgqABIgqSWUHS5DweYCpLyeAlWwCuowNcJGhXllEACA+wI7o0v6YdFluM6qR4AUN7wCIzkdw4APyiyqwKzv9sDKKYReo/TAekClgcIvCP49xyL2H18BChWgVENSaVCy95dq2xduXgQoVGjzr/+h1Z2vIi46HoEqFZKLSqCJ0qBoa1HlqEIbACuga6ODQqOAKliFwh2FsORYACVgt9oRNjpMyGN2ts4BbXDfgXWiy3AtuwVYdhdQmn3ZTcm7MAz4GIvNjoe+3YPcUh9o9vQRdnM5ZEsFYDXDXl4MfdteAAB1eCwg26FQqWE6d7TafSx5aZW/v0grrQ5GqxXWcivUUerK1gCtBOgB0zkTZFmGpcwC40kjFP4KSJDQ6q5WkBTedzEDtUKNF7Kyobb74EWbyrI5oNAHMQz4mBd+TuKAQS9jyU+/6CcZCr/KLgKlXzAg2yHbrLCVVX/NZaup8vcX7gZ/ReXgQXuFHSEDQhB9Z3Rlv4ERkC0y7BY7JJsEpb8SCp0CllwLkucn49CMQ0ialYS8DXlOfZyu9KB/R7TPOia6DHFO/wZseV10FeRCHEDoQ37an47Ff6aILoOcTKr6ol5tTenLf3vPM1e2FrW4owVUgSqEjQxD2MgLXQAlB0twZuEZKIOUsGRaoDAoIKkk2IpssJXbkPF1BjKWZEAfp0f05Gj4xfvVeayyo2XI+C4DpnMmqEJUiBgbgdBrQh2/Lz1UivSv0mEttiKwdyBiZsRAoar87mIrtyF5fjLiHo9zyliFxMB4zDiwttn363E2vwy0GQTEXS26EnIBtgz4iFM5pXjivwdEl0FOoA6NuegnydEKYDMWAZICklIFpSG42n0klRa28kLHz8XlRThlMgIAQgaG1DiG3W7H2ffPQhWsgqSpDBb2MjtsRTZIagmQAXWkGhHXR8C/qz9SXkuBpaD2JnZzjhkpb6bA0MGAds+1Q8S4CGR8k4GinUUAANku4+xHZxE6IhTxz8TDeMqIgs0XWjYyv89E6IhQpwQBrVKLBRlpUMq2Zt+3x5Ftld0FZbmiKyEXYBjwATa7jEe/349yM09w3kih8YOk1p0fQBgIY8o+AIAl7ywgKSBbLdC27FTtPuqwVpW/B1By5Ddk5J6DXqGAXq2CQlfztHDus3OABKgCVNCF66r9TrbIUOgUUKgVUBqUiLo1CppwDfI35tdab/6mfGjCNIieEg1djA6hw0IRPCQYuWsqP3RspTbYSmwIvSYUupY6BPQKgCndBAAoO1EGY4rRaYMWZ/klID77pFP27ZFKMoD//R3OvnLZ8OHDMXv2bKceg+rHMOADPvwtGfvOFooug5zIP/Ha8wMIi1C69xecfXdq5bUGbBbYrWYYT+9B6lsTkf7Zg8hd9QaCh88AbFakvTsN2Stfh1qlQbndjqviY1B6tBS28gvBseJcBYq2FQEqwFpkRct7W0JSSZA00oVWggo7zDlm+LWv7BqQNBLKjtd+Zb/yk+Xw7+Zf7baA7gEwphghW2UoA5RQBatQergUdrMdZcfLoIvVwW61I/2LdLSc3tIpgxZ7ByVg6kF2D9SQ/Cvwx5uiqyAnYxjwckkZxXh7wwnRZZCThY6aCb9OQ1A1NsB+vqtAFRKNqInzIZuMkC0m2MqLYS3Ogb51d4SMvA+2sspv72Zr5TfvLcdSkfJyCjK+yXDs+8ybZ6AKUkETokHEuAioQ9SInh4N2SZDNp//xigDodeEQh+nR+GfhTCeMsJaVPu1LqxFVigDq690qApUATbAWmqFJEmIfTAWOT/l4MRTJ6BvrUfIkBDk/pwL/y7+kDQSTj1/CsefON5sgxb1Sh0WpJ2GQuYI+lptfAE4u1N0FeREkizzyvXeymKz46Z3tyIpo1h0KeTGVJAxT2VDnx+ewImJ/fB0uz2Nur8p24Rzn51D+bFyQAHo2+ihaaFBxZkKtH+xfY3tj//7OEKGhCBiXITjtrITZTj9wml0fKsj1MHqmsfINOHMwjNoN78dTr90GmGjwxDQPQAnnj6Bto+3hS5WV+M+jfGkf2dMZqtA/cI7ADO3AOore65rM3z4cHTrVrlK5tdffw2lUokHHngACxYsgCR539RVd8SWAS/29oYTDALUQJUnXEsTLk2gjdQi/sl4dPmoCzq+2RHt5raDbJOhDq/5oQ4AqiBVjVYDW7ENUAIq/5oTnGRZxrlF59Diby0AGag4U4Ggq4KgClTB0NGAsqO1d0c0VP+gDph00McWF2qK3OPA5hedtvsvvvgCKpUK27dvxzvvvIOFCxfi008/ddrxqDqGAS+172whPvgtWXQZ5CGqvnxZlE1vKFRoFVAHq2Ers6H0YCkCewfWup1fgh9KD1e/ZG7poVLo4/SQVDW/BRb8XgCVvwqBvQId10mQbbLj/+UrWEnToPLDc2eOQwIbSBvkz3eBtN1O2XVsbCwWLlyIjh07YsqUKZg1axYWLlzolGNRTQwDXqjCYsOc7/fBxuWGqYGuJAyUHCxByYESmHPMKD1UitMvn4Y2WouQqyunKGYuy0Tax2mO7UNHhMKca0bGdxmoSK9Awe8FKPi9AOHXhdfYt7XYipyfcioXQAKgNCihjdEib10eyk+WoyypzDFosSn+pYlFTEFqk+/vc2QbsOJB4PwYk+Y0YMCAal0CAwcOxIkTJ2CzcRaUK3DRIS/02tpjSM65sqZT8jHnz8FmRePDgN1oR+ayTFgLrFAalAi8KhBR46Mc3/KthVaY8y4sf62J0CDu0ThkfJeB/F/zoQpWIXpKNIL6BtXYd8Y3GQgfGw51yIUuh5b3tsS5T84hb30ewseG17u4UX0GB3fChL3sHmi0nKOVCxKNmiu6EmpGDANeZvupPCzaelp0GeRhpPNpoClhIKhfEIL61fwgr9LqvlY1bjN0MiBhfsJl9x37QGyN2/zi/dD+pZoDExsjQO2P+acOXdE+fNqf7wBdbgJiejXbLv/6668aP7dv3x5KZRMGslCjsZvAi5SbrXjshwNg7wA1WlXLgNI3ptY9oYxGVFH65Tek2tmtwI8PAdbmu+DZ2bNn8eijj+LYsWP47rvv8H//9394+OGHm23/VD+2DHiRdzeeRGp+uegyyANVDaAz+UAYGB7cBTftXSO6DM+XfRjY+hYw7PFm2d20adNgNBrRr18/KJVKzJo1C3//+9+bZd90eQwDXuJsfjk+/YPdA9Q0VQO3TJJ3D9YK1gRh7onGraNA9djyJpB4BxDS5op2s3nzZsd/f/DBB1dYFDUFuwm8xAs/J8Fs9f5vdeQcVWO4vb1l4GmEIbw0W3QZ3sNqBNY+JboKagYMA15gW3Ie1hzOFF0GebLzacAkeW8YGB3SFdcd2yy6DO9zdBVwYoPoKugKMQx4OJtdxnOrjogugzycJFWOGahQ1H49AU8Xqg3BM8d2iC7De61+HLDVfslq8gwMAx5uyc5ULjlMV6xqamGF5J1h4D+2QISUNc9FjagW+cnA9o9EV0FXgGHAgxVXWPDmuuOiyyAvUDVmoELhfQMIx4V0w8gTW0SX4f1+exVg4PJYDAMe7O0NJ5BX1nzzfImMXtYyEKkLw5NJW0WX4RtMRcCm50VXQU3EMOChknNK8eW2FNFlkJeoWhLe27oJ5pl1CDQWiS7Dd+z+Asg+KroKagKGAQ/1ws9JsNi41CA1j6pFh7ypZeC2kO4YkrxNdBm+RbYBm18SXQU1AcOAB/r9eA42HuVcaWpG55sGyhXe0e0UrY/AY0c4TkCIIyuAzIOiq6BGYhjwQG+u56BBal4XWgY8f3qYBAnPGZXwr+AsGzFkYBNbBzwNw4CH+fNkLvadLRRdBnkZCQBUKtjg+V1PE0O6YcBprikg1LGfgXNc9tmTMAx4mHc3nRRdAnkpSa0WXcIVi/VrgUcPbRZdBgHAphdFV0CNwDDgQfakFuDPZM7jpeYnQQY0nh0GFJICC0ps8DOXiS6FAODkeuAsW2g8BcOAB3lvI1sFyDkkSIDasy9iOiWoG/qk7hZdBl1sI9cd8BQMAx4iKaMYG49xBgE5hwQZ8OBugjhDSzx8kBfLcTunfwNSuOiTJ2AY8BDvbToJ2fPHdpG7kmSPbRlQSkq8UFgOrbVCdClUm61vi66AGoBhwAOcyinFLwczRJdBXk5WeWYYuCuoCxLT9osug+pyYh2Qe0J0FXQZDAMe4IPNybCzVYCcSIIMWa0UXUajJfjH4qED60WXQfWSgb8+EF0EXQbDgJs7V2jEj/vOiS6DvJwEQPawbgKVpMILeYVQ27xj1USvtv87oDxfdBVUD4YBN/fxb8m8BgE5nyzDrvKs08F9gZ3RJf2w6DKoISzlwO5FoqugenjWX7+PKTJa8P2uNNFlkA+QANg9qJugc0Ab3HdgnegyqDF2fALYPH+5a2/FMODGlu9Jg9FiE10G+QJJhl3lGWFArVDjhaxsqO38YPEoJRnAof+JroLqwDDgxr7dkSq6BPIRkizD5iHdBA/6d0T7rGOiy6Cm+Os90RVQHTzjr98H7Tidj+NZpaLLIB8hAbArJdFlXFZiYDxmHFgrugxqqoz9QOpfoqugWjAMuKlvtp8RXQL5FBk2tXufDrRKLRZkpEEps+vMo+39WnQFVAv3/uv3UfllZqw+lCm6DPIhkizD6uYtA7P82iE+m9fn8HiHfwTM5aKroEswDLih5XvPwWy1iy6DfIzNjcNA76AETD3I2QNewVwCJP0kugq6BMOAG/phN6cTkmtJsMOqcs8woFfqsCDtNBQyA7LXYFeB22EYcDOH04uQlFEsugzyNTJgddMFCGfr26J17mnRZVBzSvkDKOC4KHfCMOBmlnGRIRJAggyLG54N+gd1wCR2D3ghuXKJYnIbbvjn77ssNjt+2p8uugzyNRIgyXZY3WzNIYPKD8+dOQ4JXI7bK+37Brwuu/tgGHAjG49mI7+MF10hAWTA4mbdBP/SxCKmwLULb/1+xoobvytHzBslkOYX48ejda9yOHOlEdL8Yrz1l6nefX6y24whi8oQ8koxQl4pxqgvy7DjXPXpkd8csCB2YQlCXynGY+sqqv0updCODv9XimKTl31wFqYCKVtEV0HnMQy4kdUHM0SXQD5KATvMCvf5sBkc3AkTDrv+0sRlZhk9ohR493pdvdv9eNSC7edsiAm4/KDLzWesmNRNjU3TDdh2jwGtgxQY/VUZzhVXDojMLbfj3pVGvH6tDmvvNOCL/Rb8fPxCCHngZyNeHqVFoNY9B3hekYM/iK6AznOz7wK+y2qzY9OxHNFlkA8zK9xjtH6A2h/zTx0Scuyx7dUY2159/idjrducK7bjH79UYO2dfrjh28vPl//mNr9qP39yow4/HLHg19NWTOuhwakCGUFaCXd0qzzuiLZKHMmx44YOwLcHLdAoJdzWWV3brj3fsdWA3Q4o+L1UNL4CbmJHSj6KjLzwCokhyXaYle7RMvCEMhpRRe45dsYuy5i63IjHBmnQNbJpgyzKLYDFDoTqK7/ptw9VoNwiY2+GDflGGTvP2ZAYpUS+UcZ/NlXg3bH1t1J4tLJsIG2H6CoIbBlwG+uPZIkugXyZLLtFGBge3AU37V0juow6vfKHGSoF8M/+mibv44kNFWgZIGFUfOXpN0Qv4Ytb9Jj2oxFGi4xpPdQYk6DC3SuMmNVPg9OFdty0pBwWGzBvuBYTunhZK0HSSqD1ANFV+DyGATfxa1K26BLIh0myHWaF2DX/gzVBmHtij9Aa6rM73Ya3t5uxZ6YBktS0/vtXt5rw3SELNt9lgO6iRZ5u7azGrRd1BWxOseJgtg3vXq9Dwjul+G68Hi38JfT7tAxD2ygRafCiRt2jPwNjXhBdhc9jGHADxzJLkJrPtbpJIFmGSfCYgacRhvDSg0JrqM+WVCuyy2S0XnjhaqI2GZizzoS3/jIjZXZAvfd//U8TXtxiwoZpBiRG1d3FYLLKePDnCnx9mx4n8+2w2oFhcZWn6g5hCmxPs+HGjl4UBgpOA1mHgaiuoivxaQwDbmD9EV6UiEQTGwZGh3TFdXtWCzt+Q0xNVDua9quM+bocUxPVmNGz/qb717aa8PwWE9be6YerYuofa7DgdxPGJqjQO1qJvRk2WO0Xum8stsoA4nWSVjEMCMYw4AbWs4uABJMgo0JhFXLsUG0InjnmHoPISs0yTuZfCEWnC+zYl2lDqF5C6yAFwqpPDIBaAbTwl9Ax/MIH/LTlRrQMkPDSqMqBf69uNeHZTSZ8e5seccEKZJZW7t9fI8FfU7274XC2DUsPW7FvpgEA0ClcAYUk4bM9ZrTwl3A0146+lwkTHunoSmD4v0VX4dMYBgTLLq7AgbRC0WWQr7PLMEliWgb+YwtESFmekGNfale6DSO+uNBl9+g6EwATpvdQY/Et+gbtI7XIDoV0oRn//Z1mmG3AhGXVpyrOHabBvOEXZgrIsoy/r6rAwjFaGM6HBL1awuJbdHjolwqYrMC71+vQMtCLugiqZB6svFZBSBvRlfgsSZa5HqRI325PxVPL3beflLyfSpKxSDqLr9usxJ+6sy499riQbnhpzy8uPSa5qRveBPreI7oKn+WFEdOzcLwAuQNJlmF0cTdBpC4MTyZtdekxyY1xaWKhGAYEMppt+DPZPZpHycfJMiok1y56Nc+sQ6CxyKXHJDeW8ofoCnwaw4BAe1ILYLK6xxKw5Nsk2GCUXNcycFtIdwxJ3uay45EHKMsBspNEV+GzGAYE2n2mQHQJRAAAyQ6UK1zTMhCtj8BjR9gkTLU4zfeFKAwDAjEMkNuQbaiA81sGJEh4zqiEf0Wx049FHijld9EV+CyGAUFkWcbeVIYBchOyjHIXjBmYGNINA067x5oC5IZStgKc4CYEw4AgJ7NLUVwhZpEXohpkGVYnrzMQ69cCjx7a7NRjkIcz5gNZYi5f7esYBgRhFwG5FScvaqeQFFhQYoOfucy5ByLPx3EDQjAMCMIwQG6laRfha7ApQd3QJ3W3cw9C3uHsX6Ir8EkMA4Ls5ngBciOywnlpIM7QEg8f3OC0/ZOXydgvugKfxDAgQEGZGadz2VxK7kNWOGfQllJS4oXCcmitFU7ZP3mhghTAWCi6Cp/DMCDAntQCDpgltyJLznlD3hXUBYlp/KZHjcTWAZdjGBCA4wXI3ciK5j8VJPjH4qED65t9v+QDGAZcjmFAgD0cL0Buxt7M3QQqSYUX8gqhtpmbdb/kIxgGXI5hQIAj6Vx9jdxMM3cT3BfYGV3SDzfrPsmHMAy4HMOAi+WWmrjYELkdezOeCToHtMF9B9Y13w7J9+QnA6ZS0VX4FIYBF+MsAnJH9mZqGVAr1HghKxtqu2svh0xeRrYDmQdFV+FTGAZc7HQOwwC5H1sznQke9O+I9lnHmmdn5Nu4LLFLMQy42Cm2DJA7aobrEiQGxmPGgbXNUAwRgPzToivwKQwDLnY6l/1g5H5sVzibQKvUYkFGGpSyrZkqIp9XwDDgSgwDLsYxA+SObIoraxmY5dcO8dknm6kaIgD5p0RX4FMYBlzIbpdxJq9cdBlENVxJy0DvoARMPcjZA9TMClLApVpdh2HAhc4VGmGyOvea8URNYWvimAG9UocFaaehkPm+pmZmrQCK00VX4TMYBlyIgwfJXdmaOLVwtr4tWueyb5echOMGXIZhwIVO53DwILknm6LxA//6B3XAJHYPkDNx3IDLMAy4EAcPkruyonHN/AaVH547cxwS2KdLTsTphS7DMOBCqfkcPEjuySo1rmXgX5pYxBSkOqkaovMKUkRX4DMYBlwop9QkugSiWlkbMZtgcHAnTDjMSxOTC5Rkiq7AZzAMuFBeKS/nSu6poS0DAWp/zD/FZWLJRcqyRVfgMxgGXCivjGGA3JMFDbuS5hPKaEQVcboXuUhpjugKfAbDgIsUV1hg5hoD5KYsDZhNMDy4C25K+tUF1RCdZyoCrOxedQWV6AJ8BbsIyJ2ZpfpbBoI1QZh7Yo+LqiFfIav9YNOFwKwNhVEdglJlMIoVgciTA5FrC0Cm1YA7Si2ICNaKLtXrMQy4SH4Z0y25r8uNGXgaYQgv5fXlqX6yNhBWXRhMmhCUq0NQqgxCoRSIPHsgcmwGZNj8cc5kQEqFHqfL9SioUAEl9e/zmnI7IoJdUr5PYxhwkSKjRXQJRHWqr2VgdEhXXLdntQurIXcgSwrIulBYdKEwaUJQpgpGsSIIhQhCnmxAli0AGRYDzpr8kGL0Q4pRC2OFEihq3joKjWxVdQWGARcpqWjYAC0iEUxS7WE1VBuCZ47tcHE15AyyUgO7PgxmbSgq1MEoVQWjWApEAQKRKwcg0+KPdIs/Uiv0SDHqcbZCA5tR/LCyYn6RcgmGARfhG5rcmQW1dxP8xxaIkLI8F1dDDSFrDLDpwmDShsKoDkaJIhjFUgDyEIgcWwAyrf5IM/shtcIPKUYdsso0gAcuglpYznOnKzAMuEgxWwbIjZlq6SYYF9INI/f8IqAa3yNDgqwLhvV8k3y5KhglyiAUSkHIswcg2+aPdKsBaSYDUiv0OFWuQ0mFCigWXbnzsYvVNRgGXKS4gm9ocl8mqXq/bKQuDE8mbRVUjeeTFSrY9aGwaENhUgc7+tsLEIRcOQBZVn+kW/yQdr6//YxRC1OF+CZ5d8Rzp2swDLgIxwyQO7t0AOE8sw6BxmYeCebBZJUeNn0oLJoQGDWVU+CKpEDkIxC59gBkWP2Rbq78cD9Vrsc5owZyuSS6bK9gtfNiWK7AMOAiXHCI3JUsSzDiQsvAbSHdMWTPzwIrcr7KKXCVTfJGdQhKFJVN8vmobJLPOt8kf6bCD6eNOuSVqgFegVwImVnAJRgGXITfEcidVZzvJojWR+CxI1sEV9M4lVPgQmDVhaLifH97VZN8vuxfbQrcmQo9Usr1KKtQNPsUOHIOmWnAJRgGiAhGmCFBwnNGJfwrxI5Kk5Ua2M/Pbzeqz89vr5oCZw9Als0f58xV89v1OGN0jylw5BzsJXANhgEXkdg0QG5KAlABMyaGdMMAJ3QPyGoDbPpQmDXnp8Bd1N+eY/dHltUfaebKUfKny/XI9NApcOQcdrYMuATDAJGPkyUJ4X4hePTQ5stvCwmyLuh8f3uoYwpcEQKRJwcg217ZJJ9m9sMZY2V/e1EDlpwlqguzgGswDLiIxFED5LbseESOgiUESFcFo0QR5FiVLsvmj3SzAWnn+9tPl+s4BY5cimMGXINhgMjH2WQJd+27Q3QZRLXimAHXYMR3EY4ZICJqPBlMA67AMOAiDANERI3HlgHXYBggIiK3xTEDrsEw4DJsGiAiaixmAddgGCAiIrelVvJjyhX4LLsI389ERI0XpFeLLsEn8CPKRfiGJiJqvGA/njtdgWHARUL8NKJLICLyOPwi5RoMAy4SamAYICJqLIYB12AYcBG2DBARNV4wz50uwTDgIiFsGSAiajS2DLgGw4CLhDLdEhE1GgcQugbDgIuEGPiGJiJqLLYMuAbDgIsE6NRQK7kKIRFRQ2lVCujUStFl+ASGARfiQBgiooZjF4HrMAy4EMcNEBE1HLsIXIdhwIU4boCIqOHYmuo6DAMuxLUGiIgarnWon+gSfAbDgAvFBOtFl0BE5DHahhtEl+AzGAZcKD6Cb2wiooaKC+M501UYBlwoPtxfdAlERB4jLpzdBK7CMOBC7dgyQETUYGwZcB2GAReKDNQhQKsSXQYRkduLDNDCwPOlyzAMuBjHDRARXV4cBw+6FMOAi8VHcNwAEdHltGUXgUsxDLhYPNMuEdFlsWXAtRgGXIwtA0REl9eWMwlcimHAxThmgIjo8tgy4FoMAy7WNtwABa9kTERUJ0nitEJXYxhwMZ1ayWWJiYjq0SbUDzq1UnQZPoVhQID2kRw3QERUl8RWwaJL8DkMAwLwjU5EVLcescGiS/A5DAMC9GodLLoEIiK31aNVkOgSfA7DgAC9YkMgcRAhEVENKoWErjEMA67GMCBAkJ+a1+kmIqpF+6gA6DUcPOhqDAOC9IoNEV0CEZHb6cnxAkIwDAjSu02w6BKIiNxO3zh+URKBYUCQvnGhoksgInI7PDeKwTAgSPtIf4QaNKLLICJyGy0CdYgN5TUJRGAYEESSJDaHERFd5CqeE4VhGBCof9sw0SUQEbkNdhGIwzAgUL+2fOMTEVUZEM8vSKIwDAjUJToQgTqV6DKIiIRrFaJHxxYBosvwWQwDAikUEoZ3jBRdBhGRcKM6R4kuwacxDAh2bRf+ARARjezML0YiMQwINqJTJDRKvgxE5LsCtCqOFxCMn0KC+WtVGNiOfwRE5LuGdoiAml+KhOKz7wZGd2VXARH5rlFd2EUgGsOAG7i2cxQvaUxEPkmpkDCCA6mFYxhwA5GBOvRoFSy6DCIil+vTOgTBflyaXTSGATfBrgIi8kXsInAPDANuYnSXFqJLICJyuZFcX8AtMAy4iYRIf8RHGESXQUTkMvHhBrSL8BddBoFhwK1wASIi8iWju7JF1F0wDLiR6/iHQUQ+5ParWokugc5jGHAjvVqHICGSTWZE5P36xoWwi8CNMAy4mb/1jRVdAhGR091+Fc917oRhwM3c1rsVr1VARF7NX6vCuMRo0WXQRfip42ZCDRquOUBEXm1cYjT8NCrRZdBFGAbc0OR+rUWXQETkNOwicD8MA25oYLswtAnzE10GEVGzS4j0R582IaLLoEswDLghSZJwBwcSEpEXuoOtAm6JYcBNTejTCioFL2VIRN5DrZRwa++WosugWjAMuKnIAB1GduYFPIjIe1zTKRLh/lrRZVAtGAbc2CQOJCQiL8LuT/fFMODGhraPQMtgvegyiIiuWFyYH4Z1YGunu2IYcGMKhYTJ/dk6QESeb+awdlByHJTbYhhwc9MGtkGgjotzEJHnahGow/jevCiRO+OnjJsL0Klx16A4vLPxpOhShEn74G7YirNr3O7f6waEjX4AAGDJPYuC3xahIvUQABnqsNaIuOXfUAXW3ixZfuxPFP31PSwFGYDdClVIDAL73gr/btc4tik9vAmFv30B2VIB/8TRCBlxt+N31qIsZC19FtHT34JCyzUhiOpz75C20Kj43dOdMQx4gLuvbovP/jiNMrNNdClCRE9fCNjtjp/NuWeQvfQZGDoNBgBYCjKQ+c3j8E+8FsFXT4GkNcCSdxaSUlPnPhV6fwQNnAh1aCygVMGYvAN5v7wFpV8Q9PF9YCsvQv6a/0PY9bOhCm6B7B/mQ9u6O/za9QUA5K19HyHD7mIQILqMED81uzs9AMOABwj20+DOAW3w0e+nRJcihNIvqNrPxr+WQRUcDW1sdwBA4e9fQt/uqmrf3NXBLerdp651YrWf1VfdjLJDG2FKOwJ9fB9YCzMhaf1g6DzUsb0lNxVo1xdlRzZDUqrg13FQczw8Iq82fVAcr0PgAdhu4yHuHRIPnZovl2yzoOzIZvgnXgtJkiDLdhhP7YIqJAZZS5/F2f+bgowvH0X58W0N36csw5iyD5b8NGhjuwEAVKEtIVtMMGclw2YsgTnjODQRcbAZS1C45RuEXnu/sx4ikdcwaJSYMait6DKoARjXPEREgBZ/69sai/9MEV2KUOXH/4K9ohSGbiMBAPayIshmI4q3/4DgIVMRMnwGjKd3I2f5i4ia9CJ0rbvXuS+7qQxp702HbLMAkgJhox+Avm0vAIBS54/wGx5B7qo3IVvNMHS7Bvr4Psj95S0E9BkHa1EWsv+7ALBbETR4MgydrnbJ4yfyJJP7t0aQn1p0GdQADAMeZOaweHy7PRVmm/3yG3up0gProI/vA1VAGABAliufC33CAAT2vQUAoImKh+lcEkr2ra43DEgaPaJnvAPZXIGKM/uQv/EzqIJbOLoQ/DoMgl+HC10BFakHYMk5g9Br70f6x39H+I2PQWkIQcaXj0IX2w1KQ7BzHjSRB9KoFLhvSLzoMqiB2O7sQaKD9Bjfx3fX9bYWZaPizH749xjjuE3pFwgolFCHV1/ZTB0WC1txTr37kyQF1CEx0ETFI7DfbTB0HIyibctq3Va2WpC/7gOEjnkI1oIMyHYbdK27Qx3WCurQljBlHLvyB0jkRcb3boXIQJ3oMqiBGAY8zIPDE3z2AkalB9dXjvY/P6IfACSlGtoW7WHNP1dtW0v+OSjrmFZYF1mWK7sMalH45xLo4vtA2yIBkO2A/cLMDtlurTbbgcjXKRUSHhjWTnQZ1AgMAx4mNtQPN/WIEV2Gy8myHaUHN8DQbSQkhbLa7wL734aypC0o2bcGloJ0FO9eCePJHQjofb1jm9xVb6Dgt8WOn4u2fQ/j6b2wFGbCkncWxTuWo+zwRhi6jqhxbHPOGZQf/R3BV98JAFCFtgIkBUr2r0N58k5Y8tKgiW7vnAdO5IFu7hGD1mGcdutJOGbAAz10TQJW7E+HzS6LLsVlKlL2wVacA//Ea2v8zq/DIISNeRBFfy1Dwa8fQxXaEhG3PgVdq66ObazFOYB0IfvaLSbkr38ftpI8SCoN1KGtED5ujmMqYRVZlpG/9l2EXHMfFJrKJk+FWouw62cjf/0HkG0WhF57P1QB4U565ESeRatSYM6YjqLLoEaSZFn2nU8UL/L08oP4Znuq6DKIiKq5f1g7PDG2k+gyqJHYTeChHr22AwK0bNghIvcRatDgoREcK+CJGAY8VJi/Fg9dkyC6DCIih39ek4AAHdcV8EQMAx5sxuA4xIbqRZdBRIT4cAOmDGgjugxqIoYBD6ZVKfHEdZ1Fl0FEhKdv6Ay1kh8pnoqvnIe7ITEa/duGii6DiHzYiI4RGNk5SnQZdAUYBrzAczd389mFiIhILI1SgWfHdRFdBl0hhgEv0LFFAKYNjBNdBhH5oBmD4xAf4S+6DLpCDANe4pFr2yMiQCu6DCLyIZEBWswaydU3vQHDgJcI0KnxJBf6ICIXemZcF/hzvROvwDDgRW7r3YqDCYnIJcZ2a+GT10nxVgwDXub123vAoFFefkMioiYKM2jw/C3dRJdBzYhhwMvEhvrhGY7sJSInWnBLN4T5c4ySN2EY8EKT+rXGiI4RossgIi90Y48YXN89WnQZ1MwYBrzUKxMSEeLHNcKJqPlEBGix4Oaul9+QPA7DgJeKDNBhAfv0iKgZvXhrdwT7aUSXQU7AMODFxiXG4EaO9iWiZnBbr5a4tguXHPZWDANe7vmbuyEqkAN9iKjpogK1mHsTuwe8GcOAlwvyU+OV8YmiyyAiD/by+EQE6TkGyZsxDPiA4R0jMbl/a9FlEJEHuuOqWIzoGCm6DHIyhgEf8cwNndEmzE90GUTkQbpEB2I+Zw/4BIYBH+GnUeGDKX2gV3N1QiK6vCC9Gh9N7QMdzxk+gWHAh3SJCcQrEzh+gIjqp5CAt//WE7GhbE30FQwDPuamHjGYOTRedBlE5MYeGdUBwzlOwKcwDPigx6/rhCHtw0WXQURu6NouUfjHNQmiyyAXYxjwQUqFhHcn9UZrNgES0UXiww14c2IPSJIkuhRyMYYBHxXkp8bH0/rAj5c7JiIABo0SH03tgwAd1xPwRQwDPqxTi0C8NqGH6DKIyA28dnsPtI8KEF0GCcIw4ONuSIzGA8PbiS6DiASaOTSelyX2cQwDhMdGd8TwjhGiyyAiAYa0D8fj13USXQYJxjBAUCgkvP23XogPN4guhYhcqEerIHx4Zx8oFRww6OsYBghA5WpjX93bH9FBOtGlEJELtIswYNGMfjBoVaJLITfAMEAOLYP1+Oqe/ggzaESXQkROFB2kw1f39Eco/9bpPIYBqiYh0h9f3N0PAfy2QOSVQvzU+OqefogJ1osuhdwIwwDV0K1lED6dfhV0ar49iLyJn0aJz+/qi4RITiGk6ni2p1r1jw/D+1N6Q63kwCIib6BRKvDhnX3Qq3WI6FLIDTEMUJ2u6RSF12/vAQ40JvJsCgl4Y2IPDO3AKcRUO4YBqtfNPVviuZu7iS6DiK7A/Ju64sYeMaLLIDfGMECXdeeANnhsTEfRZRBRE8we1R5TB8aJLoPcHMMANchDIxIwc1i86DKIqBFmj2qP2aM6iC6DPIAky7IsugjyHK+uOYr3NyeLLoOILuPJsZ0wcxivO0INwzBAjfbB5mS8suao6DKIqBaSVDlGYBq7BqgRGAaoSb7aloL//HQYfPcQuQ+FBLx8WyIm9o0VXQp5GIYBarL/7k7D4/89AJudbyEi0TRKBd6Y2IOzBqhJGAboiqw7nIl/LtmLCotddClEPsugUeLDqX0wpD3XEaCmYRigK7YrJR/3fLELRUaL6FKIfE6oQYPP7+qLnrHBokshD8YwQM3iRFYJpn++A+lFFaJLIfIZMUE6fHlPfyRE+osuhTwcwwA1m8yiCkz/fAeOZZWILoXI63WJDsRnd12F6CBefZCuHMMANasiowX/+HYPtpzIFV0Kkde6sUcMXh2fCL1GKboU8hIMA9Ts7HYZr607hg+4OBFRs1JIwOPXdcL9XEyImhnDADnN6oMZ+Ney/Sgz20SXQuTxgvRqvDOpF4bxyoPkBAwD5FQnskow86vdOJVbJroUIo/VIcofH0+9CnHhBtGlkJdiGCCnK6mw4JGl+7EhKUt0KUQeZ0zXKLw5sScMWpXoUsiL8aqFPmrNmjW4+uqrERwcjLCwMIwbNw7Jyc7p4w/QqfHJtD549NoOUEhOOQSR15Ek4JFRHfDhnX0YBMjp2DLgo/773/9CkiR0794dZWVl+M9//oOUlBTs27cPCoXzMuKmo9l4eMleFFdYnXYMIk8XoFVh4R09MapLlOhSyEcwDBAAICcnB5GRkTh48CC6devm1GOdySvDzK9242gm1yMgulS3loF4645eXEiIXIrdBD4qOTkZkydPRnx8PAIDA9G2bVsAQGpqqtOP3SbMgOUPDsbUAW0gsduACACgUkj45zUJWP7gYAYBcjl2RPmoG2+8EbGxsfjkk08QExMDu92Obt26wWw2u+T4eo0SC27phuu6tcDjPxzAuUKjS45L5I7iww14846evL4ACcOWAR+Ul5eHpKQkPPPMMxg5ciQ6d+6MgoICIbUMTgjHmtlDMPGqVkKOTySSJAHTB7bBz/8cwiBAQrFlwAeFhIQgLCwMH3/8MaKjo5GamoonnnhCWD0BOjVendAD13VrgSf+exDZJSZhtRC5SnSQDq9OSORlh8ktsGXABykUCixZsgS7d+9Gt27d8Mgjj+C1114TXRau6RSF9Y8Mwy09Y0SXQuRUN/eMwZrZQxkEyG1wNgG5pTWHMvD08kPIK3PNGAYiVwjxU+P5W7rjhsRo0aUQVcMwQG4rr9SEZ348hNWHMkWXQnTFbugejbk3dUFkgE50KUQ1MAyQ21tzKAMv/JKEs/mccUCep1OLAMy9sSsGtgsTXQpRnRgGyCOYrDZ89sdpvL8pGaUmrl5I7i/YT41Hr+2AKf3bQMl1uMnNMQyQR8kuqcDra4/hh91psPOdS25IqZAwqV8s5lzbESEGjehyiBqEYYA80qFzRXhu5RHsSMkXXQqRQ/+2oZh3U1d0jg4UXQpRozAMkEf7+UAGXlqdhLQCjicgcWKCdHjqhs4Yl8hpseSZGAbI41VYqsYTnESZ2Sa6HPIherUS9w1piweGJ0CvUYouh6jJGAbIa2QXV+DtX09g2a40mG120eWQF9OrlbhzQGvMHNYO4f5a0eUQXTGGAfI6GUVGfLA5GUt2noXZylBAzUenVuDO/m0wc1g7RAQwBJD3YBggr5VVXIEPNifjux2pMDEU0BXQq5WY1K817h8ez0WDyCsxDJDXyy6pwKKtKfj6rzMoqeAaBdRwQXo1pg+Kw4xBcZwmSF6NYYB8RqnJim+3n8Hnf6Qgs7hCdDnkxqICtbj36nhM7t8aBi0v7krej2GAfI7FZsePe8/h0y2ncSyrRHQ55Eb6tAnBpH6tcVOPGGhUvKgr+Q6GAfJpu88UYOnOVKw6kIFyTkv0SUF6NW7t1RKT+7dGh6gA0eUQCcEwQASgzGTFyv3pWLrrLPamFoouh1ygb1xlK8D13aOhU3ONAPJtDANElziRVYIlO89i+d5zyC8ziy6HmlGwnxq39WqFyf1jkRDJVgCiKgwDRHUwW+3YkJSFJTvP4o8TObwwkoeSJKBfXCgm9WuNsd1bQKtiKwDRpRgGiBrgXKERP+1Lx/ojmdh3tpDBwM2plRIGxIdhdNcWGN0lClGBXBuAqD4MA0SNlFtqwsakbKxPysIfJ3JhtHDgoTswaJQY3jESo7tGYUSnSATq1KJLIvIYDANEV6DCYsPWk7nYkJSFX5OykV1iEl2STwn312BU5yiM7hqFwQnh7AIgaiKGAaJmIssyDqQVYUNSFtYfycLRTK5h0NwUEtCpRSAGJ1R2AfRpHQKFQhJdFpHHYxggcpLskgrsOVOAPamF2H2mAAfPFfHCSY2kVyvRMzYYfeNCcFVcKHq1DkYAm/+Jmh3DAJGLmK12HE4vwu4zBdibWog9qQXIKOKyyBeLCNDiqjYh6NMmBH3jQtE1JhAqJVcCJHI2hgEigdILjdiTWoDdZwqw72whTmaVosTkGxdTCjNo0D7KHx2iApDYqvLbf5swg+iyiHwSwwCRm8kqrkBydilO5pTiZHYpknNKkZJbjsziCtg8bE6jUiEhJliHuDAD2oYbkBDpj/aRAegQ5Y8wf63o8ojoPIYBIg9hsdmRVmBEan555b+8MuSUmFBQbkGh0YKicjMKjRYUGy1OXwdBqZAQrFcj1KBBiEGDUL/K/w8zaBDmr0GbMD+0CTMgNsSPF/wh8gAMA0ReRpZlFButKDSaUVhuQUG5GUVGCwrLLSipsAAAJEk6//+AQpIgnf9vCRLO/wrS+dsNWiVC/DSOD/4wgwZBerVjH0Tk+RgGiIiIfBzb74iIiHwcwwAREZGPYxggIiLycQwDREREPo5hgIiIyMcxDBAREfk4hgEiIiIfxzBARETk4xgGiIiIfBzDABERkY9jGCAiIvJxDANEREQ+jmGAiIjIxzEMEBER+TiGASIiIh/HMEBEROTjGAaIiIh8HMMAERGRj2MYICIi8nEMA0RERD6OYYCIiMjHMQwQERH5OIYBIiIiH8cwQERE5OMYBoiIiHwcwwAREZGP+3/OzHnp56IxvgAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "piechart_sensitivity(pce)" ] From cd86e021727955c08500d254721d521552c9654e Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 22 Jul 2026 14:55:18 -0600 Subject: [PATCH 5/9] docs: fix errant docstrings in source --- UncertainSCI/distributions.py | 42 ++++++++----------- UncertainSCI/opoly1d.py | 77 ++++++++++++----------------------- UncertainSCI/pce.py | 52 +++++++++++------------ 3 files changed, 70 insertions(+), 101 deletions(-) diff --git a/UncertainSCI/distributions.py b/UncertainSCI/distributions.py index 6663337..472f92e 100644 --- a/UncertainSCI/distributions.py +++ b/UncertainSCI/distributions.py @@ -630,23 +630,19 @@ class BetaDistribution(ProbabilityDistribution): \\mu, \\sigma`. Parameters: - alpha (float or iterable of floats, optional): Shape parameter - associated to right-hand boundary. Defaults to 1. - beta (float or iterable of floats, optional): Shape parameter - associated to left-hand boundary. Defaults to 1. - mean (float or iterable of floats, optional): Mean of the distribution. - Defaults to None. - stdev (float or iterable of floats, optional): Standard deviation of - the distribution. Defaults to None. - dim (int, optional): Dimension of the distribution. Defaults to None. - domain (numpy.ndarray or similar, of size 2 x `dim`, optional): Compact - hypercube that is the support of the distribution. Defaults to None + alpha: Shape parameter associated to right-hand boundary. Defaults to 1. + beta: Shape parameter associated to left-hand boundary. Defaults to 1. + mean: Mean of the distribution. Defaults to None. + stdev: Standard deviation of the distribution. Defaults to None. + dim: Dimension of the distribution. Defaults to None. + domain: Compact hypercube of size 2 x ``dim`` that is the support of + the distribution. Defaults to None. Attributes: - dim (int): Dimension of the distribution. - alpha (float or np.ndarray): Shape parameter(s) alpha. - beta (float or np.ndarray): Shape parameter(s) beta. - polys (:class:`JacobiPolynomials` or list thereof): + dim: Dimension of the distribution. + alpha: Shape parameter(s) alpha. + beta: Shape parameter(s) beta. + polys: Jacobi polynomial family or list thereof. """ def __init__(self, alpha=None, beta=None, mean=None, stdev=None, dim=None, domain=None, bounds=None): @@ -992,17 +988,15 @@ class UniformDistribution(BetaDistribution): \\mu, \\sigma`. Parameters: - mean (float or iterable of floats, optional): Mean of the distribution. - Defaults to None. - stdev (float or iterable of floats, optional): Standard deviation of - the distribution. Defaults to None. - dim (int, optional): Dimension of the distribution. Defaults to None. - domain (numpy.ndarray or similar, of size 2 x `dim`, optional): Compact - hypercube that is the support of the distribution. Defaults to None + mean: Mean of the distribution. Defaults to None. + stdev: Standard deviation of the distribution. Defaults to None. + dim: Dimension of the distribution. Defaults to None. + domain: Compact hypercube of size 2 x ``dim`` that is the support of + the distribution. Defaults to None. Attributes: - dim (int): Dimension of the distribution. - polys (:class:`JacobiPolynomials` or list thereof): + dim: Dimension of the distribution. + polys: Jacobi polynomial family or list thereof. """ def __init__(self, mean=None, stdev=None, dim=None, domain=None, bounds=None): diff --git a/UncertainSCI/opoly1d.py b/UncertainSCI/opoly1d.py index 6665176..14d1846 100644 --- a/UncertainSCI/opoly1d.py +++ b/UncertainSCI/opoly1d.py @@ -366,7 +366,7 @@ def derivative_expansion_driver(ab, s, N, K): N: Computes coefficients for :math:`n \\leq N` K: Computes coefficients for :math:`k \\leq K`. Returns: - C: (N+1) x (K+1) numpy array containing coefficients. + Coefficient array with shape (N+1, K+1). """ assert ab.shape[1] == 2 @@ -435,15 +435,11 @@ def recurrence(self, N): recurrence_driver is performed to compute the desired coefficients, and the output is stored in the instance variable. - Parameters - ---------- - N: positive integer - Maximum polynomial degree for desired recurrence coefficients + Args: + N: Maximum polynomial degree for desired recurrence coefficients. - Returns - ------- - ab: ndarray - (N+1) x 2 array of recurrence coefficients. + Returns: + The recurrence coefficient array with shape (N+1, 2). """ if N+1 > self.ab.shape[0]: @@ -507,15 +503,12 @@ def apply_jacobi_matrix(self, v): appropriate size for the polynomial family. Applies the Jacobi matrix across the first dimension of v. - Parameters - ---------- - v: ndarray - Input vector or array + Args: + v: Input vector or array. - Returns - ------- - Jv: ndarray - J*v, where J is the Jacobi matrix of size v.shape[0]. + Returns: + The result of applying ``J*v``, where J is the Jacobi matrix of + size ``v.shape[0]``. """ N = v.shape[0] @@ -653,18 +646,12 @@ def tuple_product_generator(self, IC, ab=None): C[n,j] = < p_n p_j, p_alpha >, j, n \\in range(N) - Parameters - ---------- - IC: vector (1d array) - Values of input inner products - - ab: ndarray, optional - Recurrence coefficients + Args: + IC: Values of input inner products. + ab: Recurrence coefficients. - Returns - ------- - C: ndarray - Output coefficient expansion vector for beta + Returns: + The output coefficient expansion vector for beta. """ N = IC.size @@ -693,18 +680,12 @@ def tuple_product(self, N, alpha): The notation <., .> denotes the inner product under which the polynomial family is orthogonal. - Parameters - ---------- - N: integer - Size of matrix to return - - alpha: ndarray (1d) - Multi-index defining a polynomial product + Args: + N: Size of matrix to return. + alpha: Multi-index defining a polynomial product. - Returns - ------- - C: ndarray - Output N x N matrix containing integral values + Returns: + The matrix with shape (N, N) containing integral values. """ M = alpha.size @@ -737,18 +718,12 @@ def derivative_expansion(self, N, d): for j,n = 0, ..., N-1. - Parameters - ---------- - N: integer - Size of matrix to return - - d: integer - Derivative order + Args: + N: Size of matrix to return. + d: Derivative order. - Returns - ------- - C: ndarray - Output N x N matrix containing expansion coefficients + Returns: + The matrix with shape (N, N) containing expansion coefficients. """ assert N >= 0 @@ -904,7 +879,7 @@ def derivative_expansion(self, s, N, K=None): K: Computes coefficients for :math:`k \\leq K` (optional). If not given, is set to N. Returns: - C: (N+1) x (K+1) numpy array containing coefficients. + Coefficient array with shape (N+1, K+1). """ diff --git a/UncertainSCI/pce.py b/UncertainSCI/pce.py index 1fbb6bd..ba6459d 100644 --- a/UncertainSCI/pce.py +++ b/UncertainSCI/pce.py @@ -29,12 +29,11 @@ class PolynomialChaosExpansion(): Provides interface to construct and manipulate polynomial chaos expansions. Attributes: - ----------- - coefficients: A numpy array of polynomial chaos expansion coefficients. + coefficients: NumPy array of polynomial chaos expansion coefficients. indices: A MultiIndexSet instance specifying the polynomial - approximation space. + approximation space. distribution: A ProbabilityDistribution instance indicating the - distribution of the random variable. + distribution of the random variable. samples: The experimental or sample design in stochastic space. """ @@ -171,10 +170,10 @@ def map_to_standard_space(self, q): """Maps parameter values from model space to standard space. Parameters: - q (array-like): Samples in model space. + q: Samples in model space. Returns: - p (numpy.ndarray): Samples in standard space + Samples in standard space. """ q = np.asarray(q) @@ -186,10 +185,10 @@ def map_to_model_space(self, p): """Maps parameter values from standard space to model space. Parameters: - p (array-like): Samples in standard space. + p: Samples in standard space. Returns: - q (numpy.ndarray): Samples in model space + Samples in model space. """ p = np.asarray(p) @@ -200,8 +199,7 @@ def generate_samples(self, **kwargs): """Generates sample/experimental design for use in PCE construction. Parameters: - new_samples (array-like, optional): Specifies samples that must be - part of the ensemble. + new_samples: Optional samples that must be part of the ensemble. """ self.check_distribution() @@ -363,12 +361,14 @@ def augment_samples_idist(self, K, weights=None, fast_sampler=True): """ Augments random samples from induced distribution. Typically done via an adaptive refinement procedure. As such some inputs can be given to - customize how the samples are drawn in the context of adaptivity: + customize how the samples are drawn in the context of adaptivity. - K: how many samples to add (required) - weights: a discrete probability distribution on - self.index_set.get_indices() that describes how the induced - distrubtion is sampled. Default is uniform. + Args: + K: Number of samples to add. + weights: Discrete probability distribution on + ``self.index_set.get_indices()`` that describes how the induced + distribution is sampled. Default is uniform. + fast_sampler: Whether to use the fast induced-distribution sampler. """ return self.distribution.polys.idist_mixture_sampling(K, @@ -535,7 +535,7 @@ def build(self, model=None, model_output=None, **options): function should be a vector of size self.dim, and the output should be a 1D numpy array. If model_output is None, this is required. If model_output is given, this is ignored. - model_output: A numpy.ndarray corresponding to the output of the + model_output: NumPy array corresponding to the output of the model at the sample locations specified by self.samples. This is required if the input model is None. Returns: @@ -587,8 +587,8 @@ def mean(self): """Returns PCE mean. Returns: - numpy.ndarray: A vector containing the PCE mean, of size equal to the size - of the vector of the model output. + NumPy array containing the PCE mean, of size equal to the size of + the vector of the model output. """ self.assert_pce_built() @@ -599,8 +599,8 @@ def stdev(self): Returns PCE standard deviation Returns: - numpy.ndarray: A vector containing the PCE standard deviation, of size - equal to the size of the vector of the model output. + NumPy array containing the PCE standard deviation, of size equal to + the size of the vector of the model output. """ self.assert_pce_built() @@ -617,10 +617,10 @@ def pce_eval(self, p, components=None): ignored. If given as None (default), then all components are computed. Returns: - numpy.ndarray: An array containing evaluations (predictions) from the PCE - emulator. If the input components is None, this array is of size ( - self.p.shape[0] x self.coefficients.shape[1] ). Otherwise, the - second dimension is of size components.size. + Array containing evaluations (predictions) from the PCE emulator. + If the input components is None, this array is of size + ``self.p.shape[0] x self.coefficients.shape[1]``. Otherwise, the + second dimension is of size ``components.size``. """ self.assert_pce_built() @@ -793,8 +793,8 @@ def global_derivative_sensitivity(self, dim_list): dimensional indices in 0-based indexing. All entries must be between 0 and self.distribution.dim. Returns: - S: DxK array, where each row corresponds to the sensitivity index - :math:`S_i` across all K features of the PCE model. + DxK array, where each row corresponds to the sensitivity index + :math:`S_i` across all K features of the PCE model. """ indices = self.index_set.get_indices() From 4371b30bc0a1e9779780f2c9a76bb001ffd8fac7 Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 22 Jul 2026 17:07:59 -0600 Subject: [PATCH 6/9] docs: generate API reference via autosummary * remove old API reference; include PCE formalism in new top-level heading * autosummary'd items now leaving lots of errors and warnings about bad docstrings * have to fix later; this commit is already huge --- .gitignore | 1 + UncertainSCI/__init__.py | 4 +- UncertainSCI/distributions.py | 16 ++++++ UncertainSCI/families.py | 6 +-- UncertainSCI/indexing.py | 9 ++-- UncertainSCI/opoly1d.py | 17 +++--- docs/_templates/autosummary/class.rst | 4 ++ docs/_templates/autosummary/function.rst | 3 ++ docs/_templates/autosummary/module.rst | 68 ++++++++++++++++++++++++ docs/api_docs/distributions.rst | 39 -------------- docs/api_docs/index.rst | 12 ----- docs/api_docs/polynomials.rst | 25 --------- docs/api_docs/spaces.rst | 18 ------- docs/conf.py | 5 ++ docs/dev_docs/api/index.rst | 28 ++++++++++ docs/dev_docs/index.rst | 2 +- docs/formalism/index.rst | 7 +++ docs/{api_docs => formalism}/pce.rst | 8 --- docs/index.rst | 2 +- 19 files changed, 154 insertions(+), 120 deletions(-) create mode 100644 docs/_templates/autosummary/class.rst create mode 100644 docs/_templates/autosummary/function.rst create mode 100644 docs/_templates/autosummary/module.rst delete mode 100644 docs/api_docs/distributions.rst delete mode 100644 docs/api_docs/index.rst delete mode 100644 docs/api_docs/polynomials.rst delete mode 100644 docs/api_docs/spaces.rst create mode 100644 docs/dev_docs/api/index.rst create mode 100644 docs/formalism/index.rst rename docs/{api_docs => formalism}/pce.rst (94%) diff --git a/.gitignore b/.gitignore index 131f7a3..1de96dd 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,7 @@ instance/ # Sphinx documentation docs/_build/ +docs/**/generated/ # PyBuilder target/ diff --git a/UncertainSCI/__init__.py b/UncertainSCI/__init__.py index 8b13789..c5aa9ff 100644 --- a/UncertainSCI/__init__.py +++ b/UncertainSCI/__init__.py @@ -1 +1,3 @@ - +""" +A modern Python-based mathematical uncertainty toolkit. +""" diff --git a/UncertainSCI/distributions.py b/UncertainSCI/distributions.py index 472f92e..0cc024f 100644 --- a/UncertainSCI/distributions.py +++ b/UncertainSCI/distributions.py @@ -1,3 +1,19 @@ +""" +Classes and tools to define probability distributions. + +For PCE (:ref:`pce`), these distributions are evolved through a forward model defining +the stochastic variation of model parameters. + +Tensorizations within a distribution are possible across these families by +instantiating the distribution appropriately. Tensorizations across distributions +is also possible but requires individual instantiation of each distribution, followed +by a constructor call to the :class:`TensorialDistribution` class. + +For example, a three-dimensional random variable :math:`Y = (Y_1, Y_2, Y_3)` can have +independent components, with the distribution of :math:`Y_1` normal, :math:`Y_2` beta, +and :math:`Y_3` exponential. +""" + import numpy as np import scipy as sp from scipy import sparse as sprs diff --git a/UncertainSCI/families.py b/UncertainSCI/families.py index 12c04b1..ea5eb23 100644 --- a/UncertainSCI/families.py +++ b/UncertainSCI/families.py @@ -1,8 +1,6 @@ """ -Contains routines that specialize opoly1d things for classical orthogonal polynomial families -- jacobi polys -- hermite poly -- laguerre polys +Routines that specialize :mod:`UncertainSCI.opoly1d` for classical families of +orthogonal polynomials. """ import numpy as np diff --git a/UncertainSCI/indexing.py b/UncertainSCI/indexing.py index 9435db8..cfef452 100644 --- a/UncertainSCI/indexing.py +++ b/UncertainSCI/indexing.py @@ -1,3 +1,7 @@ +""" +Module containing indexing tools and families. +""" + from itertools import combinations import numpy as np @@ -463,8 +467,3 @@ def get_indices(self): return super().get_indices() else: return hyperbolic_cross_indices(self.dim, self.order) - - -if __name__ == "__main__": - - pass diff --git a/UncertainSCI/opoly1d.py b/UncertainSCI/opoly1d.py index 14d1846..98ef4d3 100644 --- a/UncertainSCI/opoly1d.py +++ b/UncertainSCI/opoly1d.py @@ -1,9 +1,15 @@ """ -Contains classes/methods for general univariate orthogonal polynomial families. -- evaluation -- gauss quadrature -- ratio evaluations -- linear/quadratic measure modifications +Classes and methods for general univariate orthogonal polynomials. + +In particular, this module enables: +- Evaluation +- Gaussian quadrature +- Rational evaluation +- Linear/quadratic measure modifications + +See Also: + :mod:`UncertainSCI.families` for tooling for specific families of orthogonal + polynomials. """ import numpy as np @@ -412,7 +418,6 @@ class OrthogonalPolynomialBasis1D: def __init__(self, recurrence=[], probability_measure=True): self.probability_measure = probability_measure self.ab = np.zeros([0, 2]) - pass def recurrence(self, N): """ diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst new file mode 100644 index 0000000..73e7ee2 --- /dev/null +++ b/docs/_templates/autosummary/class.rst @@ -0,0 +1,4 @@ +{{ name | escape | underline }} + +.. autoclass:: {{ fullname }} + :members: diff --git a/docs/_templates/autosummary/function.rst b/docs/_templates/autosummary/function.rst new file mode 100644 index 0000000..ef91acb --- /dev/null +++ b/docs/_templates/autosummary/function.rst @@ -0,0 +1,3 @@ +{{ name | escape | underline }} + +.. autofunction:: {{ fullname }} diff --git a/docs/_templates/autosummary/module.rst b/docs/_templates/autosummary/module.rst new file mode 100644 index 0000000..c61c1db --- /dev/null +++ b/docs/_templates/autosummary/module.rst @@ -0,0 +1,68 @@ +{{ name | escape | underline }} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {%- if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + :toctree: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + + {%- block functions %} + {%- if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + :signatures: none + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + + {%- block classes %} + {%- if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :signatures: none + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + + {%- block exceptions %} + {%- if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + :toctree: + :signatures: none + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {%- endblock %} + +{%- block modules %} +{%- if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :recursive: + :signatures: none +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{%- endblock %} diff --git a/docs/api_docs/distributions.rst b/docs/api_docs/distributions.rst deleted file mode 100644 index c9aa7b8..0000000 --- a/docs/api_docs/distributions.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. _distributions: - -Distributions -============= - -Introduction ------------- - -This module is used to define probability distributions. For computing polynomial Chaos expansions (see :ref:`pce`), these will be input distributions into a forward model defining the stochastic variation of model parameters. - -UncertainSCI currently supports the following types of random variables: - -- Beta distributions (See :class:`.BetaDistribution`) -- Exponential distributions (See :class:`.ExponentialDistribution`) -- Normal distributions (See :class:`.NormalDistribution`) -- Discrete uniform distributions (See :class:`.DiscreteUniformDistribution`) - -Tensorizations within a distribution are possible across these families by instantiating the distribution appropriately. Tensorizations across distributions is also possible, but requires individual instantiation of each distribution, followed by a constructor call to the TensorialDistribution class. (See :class:`.TensorialDistribution`) - -E.g., a three-dimensional random variable :math:`Y = (Y_1, Y_2, Y_3)` can have independent components, with the distribution of :math:`Y_1` normal, that of :math:`Y_2` beta, and that of :math:`Y_3` exponential. - -The distributions are located in the `distributions.py` file. - -.. automodule:: UncertainSCI.distributions -.. autoclass:: BetaDistribution - :members: - :undoc-members: -.. autoclass:: ExponentialDistribution - :members: - :undoc-members: -.. autoclass:: NormalDistribution - :members: - :undoc-members: -.. autoclass:: DiscreteUniformDistribution - :members: - :undoc-members: -.. autoclass:: TensorialDistribution - :members: - :undoc-members: diff --git a/docs/api_docs/index.rst b/docs/api_docs/index.rst deleted file mode 100644 index f2d16ef..0000000 --- a/docs/api_docs/index.rst +++ /dev/null @@ -1,12 +0,0 @@ -API Documentation -======================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - spaces - distributions - polynomials - pce - diff --git a/docs/api_docs/polynomials.rst b/docs/api_docs/polynomials.rst deleted file mode 100644 index 5f12d49..0000000 --- a/docs/api_docs/polynomials.rst +++ /dev/null @@ -1,25 +0,0 @@ -Polynomial Families -=================== - -The computational building blocks of polynomial Chaos expansions (PCE, see -:ref:`pce`) are methods for univariate orthogonal polynomial families. - -.. automodule:: UncertainSCI.opoly1d -.. autoclass:: OrthogonalPolynomialBasis1D - :members: - :undoc-members: - -.. automodule:: UncertainSCI.families -.. autoclass:: JacobiPolynomials - :members: - :undoc-members: -.. autoclass:: HermitePolynomials - :members: - :undoc-members: -.. autoclass:: LaguerrePolynomials - :members: - :undoc-members: -.. autoclass:: DiscreteChebyshevPolynomials - :members: - :undoc-members: - diff --git a/docs/api_docs/spaces.rst b/docs/api_docs/spaces.rst deleted file mode 100644 index 61dc737..0000000 --- a/docs/api_docs/spaces.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _spaces: - -Polynomial Spaces -================= - -The expressivity of a polynomial Chaos expansion (PCE, see :ref:`pce`) can be -set by specifying a particular polynomial space. - -.. automodule:: UncertainSCI.indexing -.. autoclass:: TotalDegreeSet - :members: - :undoc-members: -.. autoclass:: HyperbolicCrossSet - :members: - :undoc-members: -.. autoclass:: LpSet - :members: - :undoc-members: diff --git a/docs/conf.py b/docs/conf.py index e75ed8c..3cbea56 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,8 +29,10 @@ extensions = [ 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', 'sphinx.ext.intersphinx', 'sphinx.ext.napoleon', + 'sphinx.ext.viewcode', 'myst_nb', 'sphinx_copybutton', 'sphinxcontrib.bibtex', @@ -52,6 +54,9 @@ # -- Extension Configuration ------------------------------------------------- +autosummary_generate = True +autosummary_imported_members = True + # Path for bibtex files bibtex_bibfiles = ['references.bib'] bibtex_default_style = 'unsrt' diff --git a/docs/dev_docs/api/index.rst b/docs/dev_docs/api/index.rst new file mode 100644 index 0000000..e87a560 --- /dev/null +++ b/docs/dev_docs/api/index.rst @@ -0,0 +1,28 @@ +API Reference +============= + +.. automodule:: UncertainSCI + + +.. seealso:: + See :doc:`../formalism` for detail on the analytic properties of these tools. + + +.. rubric:: PCE Modules + +.. autosummary:: + :toctree: generated + :recursive: + :signatures: none + + distributions + families + indexing + model_examples + opoly1d + opolynd + pce + sampling + transformations + ttr + vis diff --git a/docs/dev_docs/index.rst b/docs/dev_docs/index.rst index 2a55677..d9cae50 100644 --- a/docs/dev_docs/index.rst +++ b/docs/dev_docs/index.rst @@ -7,4 +7,4 @@ Developer Documentation contribute HowToTutorial - + api/index diff --git a/docs/formalism/index.rst b/docs/formalism/index.rst new file mode 100644 index 0000000..70a45d7 --- /dev/null +++ b/docs/formalism/index.rst @@ -0,0 +1,7 @@ +Mathematical Formalism +====================== + +.. toctree:: + :maxdepth: 2 + + pce diff --git a/docs/api_docs/pce.rst b/docs/formalism/pce.rst similarity index 94% rename from docs/api_docs/pce.rst rename to docs/formalism/pce.rst index 826f42d..b17cb6a 100644 --- a/docs/api_docs/pce.rst +++ b/docs/formalism/pce.rst @@ -38,11 +38,3 @@ In order to utilize the PCE approaches in UncertainSCI, two items must be provid 1. The distribution of the random variable :math:`\xi`. See :ref:`distributions` for how to generate this distribution. 2. The type of polynomial functions in :eq:`expansion`. This amounts to defining a particular polynomial subspace. See :ref:`spaces` for how to generate this subspace. - -PolynomialChaosExpansion ------------------------- - -.. automodule:: UncertainSCI.pce -.. autoclass:: PolynomialChaosExpansion - :members: - :undoc-members: diff --git a/docs/index.rst b/docs/index.rst index c21866c..b3781be 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,8 +27,8 @@ Currently implemented in UncertainSCI is Polynomial Chaos Expansion (PCE) with a user_docs/getting_started user_docs/support tutorials/index + formalism/index dev_docs/index - api_docs/index references Contributors From 1b9d99aaaa6dde220c593e5aa9c6e6361098d110 Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Wed, 22 Jul 2026 17:09:34 -0600 Subject: [PATCH 7/9] docs: remove bin dir * dunno what it does * docs build fine without it --- docs/bin/addModuleStubPage.sh | 3 - docs/bin/jekyll-page | 109 ---------------------------------- 2 files changed, 112 deletions(-) delete mode 100644 docs/bin/addModuleStubPage.sh delete mode 100644 docs/bin/jekyll-page diff --git a/docs/bin/addModuleStubPage.sh b/docs/bin/addModuleStubPage.sh deleted file mode 100644 index fa7acde..0000000 --- a/docs/bin/addModuleStubPage.sh +++ /dev/null @@ -1,3 +0,0 @@ -moduleName=$1 -sed s/CreateLatVol/$moduleName/ _includes/modules/CreateLatVol.md > _includes/modules/$moduleName.md -ln -s ../_includes/modules/$moduleName.md modules/$moduleName.md diff --git a/docs/bin/jekyll-page b/docs/bin/jekyll-page deleted file mode 100644 index a8e2f2f..0000000 --- a/docs/bin/jekyll-page +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env ruby - -require 'date' -require 'optparse' - -options = { - # Expects to be in the bin/ sub-directory by default - :path => File.dirname(File.dirname(__FILE__)) -} - -parser = OptionParser.new do |opt| - opt.banner = 'usage: jekyll-page TITLE CATEGORY [FILENAME] [OPTIONS]' - opt.separator '' - opt.separator 'Options' - opt.on('-e', '--edit', 'Edit the page') do |edit| - options[:edit] = true - end - opt.on('-l', '--link', 'Relink pages') do |link| - options[:link] = true - end - opt.on('-p PATH', '--path PATH', String, 'Path to project root') do |path| - options[:path] = path - end - opt.separator '' -end - -parser.parse! - -title = ARGV[0] -category = ARGV[1] -filename = ARGV[2] - -# Resolve any relative links -BASE_DIR = File.expand_path(options[:path]) -POSTS_DIR = "#{BASE_DIR}/_posts" -PAGES_DIR = "#{BASE_DIR}/_pages" - -# Ensure the _posts directory exists (we are in the correct directory) -if not Dir.exists?(POSTS_DIR) - puts "#{POSTS_DIR} directory does not exists" - exit -end - -# Create _pages directory if it doesn't exist -if not Dir.exists?(PAGES_DIR) - Dir.mkdir(PAGES_DIR) -end - -if options[:link] - Dir.foreach(POSTS_DIR) do |name| - next if name[0] == '.' - nodate = name[/\d{4}-\d{2}-\d{2}-(?.*)/, 'rest'] - if File.symlink?("#{PAGES_DIR}/#{nodate}") - File.delete("#{PAGES_DIR}/#{nodate}") - end - abspath = File.absolute_path("#{POSTS_DIR}/#{name}") - File.symlink(abspath, "#{PAGES_DIR}/#{nodate}") - end -end - -if not title or not category - # This flag can be used by itself, exit silently if no arguments - # are defined - if not options[:link] - puts parser - end - exit -end - -if not filename - filename = title.downcase.gsub(/[^a-z0-9\s]/, '').gsub(/\s+/, '-') -end - -today=Date.today().strftime('%F') -now=DateTime.now().strftime('%F %T') - -filepath = "#{POSTS_DIR}/#{today}-#{filename}.md" -symlink = "#{PAGES_DIR}/#{filename}.md" - -if File.exists?(filepath) - puts "File #{filepath} already exists" - exit -end - -content = < Date: Wed, 22 Jul 2026 17:48:12 -0600 Subject: [PATCH 8/9] docs: fix some crossref issues --- UncertainSCI/transformations.py | 8 +++++--- docs/dev_docs/api/index.rst | 2 +- docs/formalism/pce.rst | 2 +- docs/tutorials/template.md | 2 +- docs/user_docs/getting_started.md | 8 +++++--- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/UncertainSCI/transformations.py b/UncertainSCI/transformations.py index 20219da..f478ba4 100644 --- a/UncertainSCI/transformations.py +++ b/UncertainSCI/transformations.py @@ -101,14 +101,16 @@ def jacobian_determinant(self): return np.abs(np.linalg.det(self.A)) def compose(self, other): - """ Returns composition of two AffineTransform's + """ + Returns composition of two AffineTransform's Args: other: An AffineTransform instance where the domain and range are - the same dimension as for self. + the same dimension as for self. + Returns: composition: AffineTransform instance, corresponding to the map - self :math:`\\circ` other + self :math:`\\circ` other """ A1 = np.asarray(self.A.todense()) diff --git a/docs/dev_docs/api/index.rst b/docs/dev_docs/api/index.rst index e87a560..2269188 100644 --- a/docs/dev_docs/api/index.rst +++ b/docs/dev_docs/api/index.rst @@ -5,7 +5,7 @@ API Reference .. seealso:: - See :doc:`../formalism` for detail on the analytic properties of these tools. + See :doc:`../../formalism/index` for detail on the analytic properties of these tools. .. rubric:: PCE Modules diff --git a/docs/formalism/pce.rst b/docs/formalism/pce.rst index b17cb6a..21c743d 100644 --- a/docs/formalism/pce.rst +++ b/docs/formalism/pce.rst @@ -36,5 +36,5 @@ For PCE approaches, most of the computation involves computing the coefficients In order to utilize the PCE approaches in UncertainSCI, two items must be provided: -1. The distribution of the random variable :math:`\xi`. See :ref:`distributions` for how to generate this distribution. +1. The distribution of the random variable :math:`\xi`. See :mod:`UncertainSCI.distributions` for how to generate this distribution. 2. The type of polynomial functions in :eq:`expansion`. This amounts to defining a particular polynomial subspace. See :ref:`spaces` for how to generate this subspace. diff --git a/docs/tutorials/template.md b/docs/tutorials/template.md index 5951c50..154ccfd 100644 --- a/docs/tutorials/template.md +++ b/docs/tutorials/template.md @@ -100,7 +100,7 @@ Tables can be used with normal Markdown syntax through MyST. ### Referencing Sphynx -To link the UncertainSCI API generated using Sphinx, use this syntax: [`[text](../api_docs/pce.rst)`](../api_docs/pce.rst) +To link the UncertainSCI API generated using Sphinx, use this syntax: [`[text](../formalism/pce)`](../formalism/pce) diff --git a/docs/user_docs/getting_started.md b/docs/user_docs/getting_started.md index 7189f1c..5119df6 100644 --- a/docs/user_docs/getting_started.md +++ b/docs/user_docs/getting_started.md @@ -19,7 +19,7 @@ UncertainSCI can be built from source code using the project metadata in `pyproj ## UncertainSCI Overview -Users can evaluate the effect of input uncertainty on forward models with UncertainSCI's implementation of [polynomial Chaos expansion (PCE)](../api_docs/pce.rst). The pipeline for the process is shown in the following image: +Users can evaluate the effect of input uncertainty on forward models with UncertainSCI's implementation of [polynomial Chaos expansion (PCE)](../formalism/pce). The pipeline for the process is shown in the following image: ![User pipeline for UncertainSCI. After the user inputs parameter distributions, UncertainSCI will compute an efficient sampling scheme. The parameter samples are run through the targeted modeling pipeline, which can be implemented in external software tools. The computed solutions are collected and compiled into relevant statistics with UncertainSCI.](../../paper/UncertainSCI_pipeline.png) @@ -45,7 +45,7 @@ Distribution type of the parameters may effect the number of samples, but to a m #### Running UncertainSCI for Sample Generation -With the model setup, the user will need to setup the input parameter distribution using UncertainSCI's [distribution datatype](../api_docs/distributions.rst). While there are a few distribution types to choose from, the {class}`UncertainSCI.distributions.BetaDistribution` is a common choice. If we had three input parameters, we can define a different beta distribution for each, thus: +With the model setup, the user will need to setup the input parameter distribution using UncertainSCI's [distribution datatype](../dev_docs/api/generated/UncertainSCI.distributions.rst). While there are a few distribution types to choose from, the {class}`UncertainSCI.distributions.BetaDistribution` is a common choice. If we had three input parameters, we can define a different beta distribution for each, thus: ```Python from UncertainSCI.distributions import BetaDistribution @@ -118,7 +118,9 @@ piechart_sensitivity(pce) plt.show() ``` -The [API documentation](../api_docs/index.rst) explains the implementation of UncertainSCI in more detail. +The [discussion of PCE in the Formalism section](../formalism/pce.rst) explains PCE in +more detail. Implementation details of UncertainSCI can be found in +[the API reference](../dev_docs/api/index.rst) and in the source code. ## Running UncertainSCI Demos From ffd8818aa1e004a47ffc15f0c1ec4fafd86358b8 Mon Sep 17 00:00:00 2001 From: Asher Merrill Date: Thu, 3 Sep 2026 13:06:10 -0600 Subject: [PATCH 9/9] actions: update workflows to use dev install target --- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c65d163..5191298 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: - name: Install UncertainSCI run: | python -m pip install --upgrade pip - pip install --editable .["test"] + pip install --editable .["dev"] - name: Lint with flake8 run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7384939..f343d13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: - name: Install UncertainSCI run: | python -m pip install --upgrade pip - pip install --editable .["test"] + pip install --editable .["dev"] - name: Run tests and compute coverage run: |