diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7ffaaf4c..a7399590 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,46 +7,28 @@ Replace this text with a description of the pull request including the issue num This is an itemised checklist for the QA process within UKHSA and represents the bare minimum a QA should be. -Full instructions on reviewing work can be found at Confluence on the [ONS QA of code guidance](https://best-practice-and-impact.github.io/qa-of-code-guidance/intro.html) page. - **To the reviewer:** Check the boxes once you have completed the checks below. -- [ ] It runs - - Can you get the code run to completion in a new instance and from top to bottom in the case of notebooks, or in a new R session? - - Can original analysis results be accurately & easily reproduced from the code? -- [] tests pass -- [] CI is successful +- [ ] CI is successful + - Did the test suite run sucessfully? + This is a basic form of Smoke Testing - [ ] Data and security - - Use nbstripout to prevent Jupyter notebook output being committed to git repositories - - Files containing individual user's secret files and config files are not in repo, however examples of these files and setup instructions are included in the repo. - - Secrets include s3 bucket names, login credentials, and organisation information. These can be handled using secrets.yml - - If you are unsure whether an item should be secret please discuss with repo owner - - The changes do not include unreleased policy or official information. + - Files containing individual user's secret files and config files are not in repo. + - No private or identifiable data has been added to the repo. + - [ ] Sensible - - Does the code execute the task accurately? This is a subjective challenge. + - Does the code execute the task accurately? + - Is the code tidy, commented and parsimonious? - Does the code do what the comments and readme say it does\*? - - Is the code robust enough to handle missing or challenging data? + - Is the code covered by useful unit tests? + - [ ] Documentation - - The purpose of the code is clearly defined, whether in a markdown chunk at the top of a notebook or in a README - - Assumptions of the analysis & input data are clearly displayed to the reader, whether in a markdown chunk at the top of a notebook or in a README + - The purpose of the code is clearly defined? + - If reasonable, has an exaple of the code been given in a notebook in the docs? - Comments are included in the code so the reader can follow why the code behaves in the way it does - - Teams with high quality documentation are better able to implement technical practices more readily and perform better as a whole (DORA, 2021). - - Is the code written in a standard way? (In a hurry this may be a nice to have, but if at all possible, this standard from the beginning can cut long term costs dramatically) - - Code is modular, storing functions & classes in the src and being imported into a notebook or script - - Projects should be based on the UKHSA repo template developed to work with cookiecutter - - Variable, function & module names should be intuitive to the reader - - For example, intuitive names include df_geo_lookup & non-intuitive names include foobar - - Common and useful checks for coding we use broadly across UKHSA include: - - Rstyler - - lintr - - black - - flake8 -- [ ] Pair coding review completed (optional, but highly recommended for QA in a hurry) - - Pair programming is a way of working and reviewing that can result in the same standard of work being completed 40%-50% faster (Williams et al., 2000, Nosek, 1998) and is better than solo programming for tasks involving efficient knowledge transferring and for working on highly connected systems (Dawande et al., 2008). - - Have the assignee and reviewer been on a video call or in person together during the code development in a line by line writing and review process? - -\* If the comments or readme do not have enough information, this check fails. + - Is the code written in a standard way (does it pass linting)? + - Variable, function & module names should be intuitive to the reader? ## How to QA this PR diff --git a/.github/workflows/book.yml b/.github/workflows/book.yml index 7e9a3eca..2440f8c7 100644 --- a/.github/workflows/book.yml +++ b/.github/workflows/book.yml @@ -30,23 +30,21 @@ jobs: uses: ts-graphviz/setup-graphviz@v1 # install python - - name: Set up Python 3.8 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: '3.10' - # install dependencies - - name: Install dependencies + # set up pygom + - name: Build and install pygom run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r docs/requirements.txt + pip install . - # set up pygom - - name: Build and install pygom + # install dependencies + - name: Install documentation dependencies run: | - python setup.py build - python setup.py install + pip install -r docs/requirements.txt # build the book # TODO check which flags are needed, -W @@ -56,8 +54,16 @@ jobs: # deploy book to github-pages - name: GitHub Pages - uses: peaceiris/actions-gh-pages@v3.6.1 + uses: peaceiris/actions-gh-pages@v4 + if: github.ref == 'refs/heads/main' with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: docs/_build/html - + # deploy book to github-pages dev + - name: GitHub Pages dev + uses: peaceiris/actions-gh-pages@v4 + if: github.ref == 'refs/heads/dev' + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/_build/html + destination_dir: dev diff --git a/.github/workflows/distribute_package.yml b/.github/workflows/distribute_package.yml new file mode 100644 index 00000000..7fef265c --- /dev/null +++ b/.github/workflows/distribute_package.yml @@ -0,0 +1,156 @@ +name: create PyGOM distributions + +on: + push: + branches: + - master + - dev + - feature/* + - bugfix/* + + pull_request: + branches: + - master + - dev + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.platform_id }} for Python v${{ matrix.python[1] }} + runs-on: ${{ matrix.os }} + strategy: + # Ensure that a wheel builder finishes even if another fails + fail-fast: false + matrix: + include: + # Window 64 bit + - os: windows-latest + python: [cp39, "3.9"] + platform_id: win_amd64 + - os: windows-latest + python: [cp310, "3.10"] + platform_id: win_amd64 + - os: windows-latest + python: [cp311, "3.11"] + platform_id: win_amd64 + - os: windows-latest + python: [cp312, "3.12"] + platform_id: win_amd64 + + # Python 3.9 in the manylinux build environment requires our dependencies to be + # built from source so we won't supply a wheel for 3.9 (source build will prevent lib + # version conflicts). + + # NumPy on Python 3.10 only supports 64bit and is only available with manylinux2014 + - os: ubuntu-latest + python: [cp310, "3.10"] + platform_id: manylinux_x86_64 + manylinux_image: manylinux2014 + - os: ubuntu-latest + python: [cp311, "3.11"] + platform_id: manylinux_x86_64 + manylinux_image: manylinux2014 + - os: ubuntu-latest + python: [cp312, "3.12"] + platform_id: manylinux_x86_64 + manylinux_image: manylinux2014 + + steps: + - uses: actions/checkout@v4 + with: + # We need quite a deep fetch so that we get the versioning right + fetch-depth: 500 + fetch-tags: true + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + # Used to host cibuildwheel + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python[1] }} + + - name: Install cibuildwheel + run: python -m pip install cibuildwheel>=2.19.2 + + # Need to duplicate these two lines as it seems Windows and Linux echo treats qutotes differently + - name: Build and test the wheels + if: matrix.os == 'ubuntu-latest' + run: python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_BUILD: ${{ matrix.python[0] }}-${{ matrix.platform_id }}* + CIBW_TEST_COMMAND: python -W default -m unittest discover --start-directory {project}/tests + # setuptools_scm workaround for https://github.com/pypa/setuptools_scm/issues/455 + CIBW_BEFORE_BUILD: ${{ github.ref == 'refs/heads/dev' && 'echo ''local_scheme = "no-local-version"'' >> pyproject.toml && git diff --color=always && git update-index --assume-unchanged pyproject.toml' || '' }} + - name: Build and test the wheels + if: matrix.os == 'windows-latest' + run: python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_BUILD: ${{ matrix.python[0] }}-${{ matrix.platform_id }}* + CIBW_TEST_COMMAND: python -W default -m unittest discover --start-directory {project}/tests + # setuptools_scm workaround for https://github.com/pypa/setuptools_scm/issues/455 + CIBW_BEFORE_BUILD: ${{ github.ref == 'refs/heads/dev' && 'echo local_scheme = "no-local-version" >> pyproject.toml && git diff --color=always && git update-index --assume-unchanged pyproject.toml' || '' }} + + # Upload the results + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.platform_id }}-${{ matrix.python[0] }} + path: ./wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + # We need quite a deep fetch so that we get the versioning right + fetch-depth: 500 + fetch-tags: true + + # setuptools_scm workaround for https://github.com/pypa/setuptools_scm/issues/455 + - name: Disable local version identifier on develop CI + if: github.ref == 'refs/heads/dev' + run: | + echo 'local_scheme = "no-local-version"' >> pyproject.toml + git diff --color=always + git update-index --assume-unchanged pyproject.toml + + - name: Build sdist + run: pipx run build --sdist + + - uses: actions/upload-artifact@v4 + with: + name: cibw-sdist + path: dist/*.tar.gz + + upload_pypi: + name: Upload release to PyPI + needs: [build_wheels, build_sdist] + runs-on: ubuntu-latest + environment: + name: pypi + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + # unpacks all CIBW artifacts into dist/ + pattern: cibw-* + path: dist + merge-multiple: true + + # This is the live push to PyPI on tagging the master branch + - uses: pypa/gh-action-pypi-publish@release/v1 + # Upload to PyPI on every tag starting with 'v' + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + with: + repository-url: https://pypi.org/p/pygom + + # Upload to PyPI *testing* every dev branch commit + - uses: pypa/gh-action-pypi-publish@release/v1 + # Upload to testing only if we are on the dev branch + if: github.ref == 'refs/heads/dev' + with: + # Testing only at this point + repository-url: https://test.pypi.org/legacy/ \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 420d7ffd..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,91 +0,0 @@ -name: pygom - -on: - push: - branches: - - master - - dev - - feature/* - - bugfix/* - - pull_request: - branches: - - master - - dev - -env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: true - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest] # macos-latest - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] - - steps: - - uses: actions/checkout@v2 - - - uses: actions/cache@v1 - if: startsWith(runner.os, 'Linux') - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - uses: actions/cache@v1 - if: startsWith(runner.os, 'macOS') - with: - path: ~/Library/Caches/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - uses: actions/cache@v1 - if: startsWith(runner.os, 'Windows') - with: - path: ~\AppData\Local\pip\Cache - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - name: Set up Python - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - - name: Check python version - run: python -c "import sys; print(sys.version)" - - - name: RC.exe for Windows - if: startsWith(runner.os, 'Windows') - run: | - function Invoke-VSDevEnvironment { - $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" - $installationPath = & $vswhere -prerelease -legacy -latest -property installationPath - $Command = Join-Path $installationPath "Common7\Tools\vsdevcmd.bat" - & "${env:COMSPEC}" /s /c "`"$Command`" -no_logo && set" | Foreach-Object { - if ($_ -match '^([^=]+)=(.*)') { - [System.Environment]::SetEnvironmentVariable($matches[1], $matches[2]) - } - } - } - Invoke-VSDevEnvironment - Get-Command rc.exe | Format-Table -AutoSize - echo "::add-path::$(Get-Command rc.exe | Split-Path)" - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Build and install package for c files - run: | - python setup.py build - python setup.py install - - name: Fix matplotlib backend for MacOS - if: startsWith(runner.os, 'macOS') - run: | - mkdir ~/.matplotlib - echo "backend: TkAgg" >> ~/.matplotlib/matplotlibrc - - name: Test and coverage - run: python setup.py test diff --git a/.github/workflows/test_package.yml b/.github/workflows/test_package.yml new file mode 100644 index 00000000..500f8913 --- /dev/null +++ b/.github/workflows/test_package.yml @@ -0,0 +1,71 @@ +name: create PyGOM distributions + +on: + push: + branches: + - master + - dev + - feature/* + - bugfix/* + + pull_request: + branches: + - master + - dev + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest] #, macos-13, macos-14] + python-version: ["3.9", "3.10", "3.11"] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/cache@v4 + if: startsWith(runner.os, 'Linux') + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - uses: actions/cache@v4 + if: startsWith(runner.os, 'macOS') + with: + path: ~/Library/Caches/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - uses: actions/cache@v4 + if: startsWith(runner.os, 'Windows') + with: + path: ~\AppData\Local\pip\Cache + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Check python version + run: python -c "import sys; print(sys.version)" + + - name: Install pip + run: | + python -m pip install --upgrade pip + + - name: Install coverage + run: | + python -m pip install codecov + + - name: install PyGOM + run: | + pip install . + + - name: Run tests + run: coverage run -m unittest discover --verbose --start-directory tests + + \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 80f66d3c..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include data/*.json diff --git a/README.md b/README.md new file mode 100644 index 00000000..7ac5ee83 --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# PyGOM - Python Generic ODE Model + +[![pypi version](https://img.shields.io/pypi/v/pygom.svg)](https://pypi.python.org/pypi/pygom) +[![licence](https://img.shields.io/pypi/l/pygom?color=green)](https://raw.githubusercontent.com/ukhsa-collaboration/pygom/master/LICENSE.txt) +[![Github actions](https://github.com/ukhsa-collaboration/pygom/workflows/pygom/badge.svg)](https://github.com/ukhsa-collaboration/pygom/actions/) +[![Jupyter Book Badge](https://jupyterbook.org/badge.svg)](http://ukhsa-collaboration.github.io/pygom/md/intro.html) + +A generic framework for Ordinary Differential Equation (ODE) models, especially compartmental type systems. +This package provides a simple interface for users to construct ODE models backed by a comprehensive and easy to use tool–box implementing functions to easily perform common operations such as parameter estimation and solving for deterministic or stochastic time evolution. +With both the algebraic and numeric calculations performed automatically (but still accessible), +the end user is free to focus on model development. +Full documentation for this package is avalible on the [documentation](http://ukhsa-collaboration.github.io/pygom/md/intro.html) page. + +## Installation +The easiest way to install a copy of PyGOM is via PyPI and pip + + pip install pygom + +Alternatively, you can download a local copy of the PyGOM source files from this GitHub repository: + + git clone https://github.com/ukhsa-collaboration/pygom.git + +Please be aware that there may be redundant files within the package as it is under active development. + +> [!NOTE] +> The latest fully reviewed version of PyGOM will be on the `master` branch and we generally recommend +> that users install this version. However, the latest version being prepared for release is hosted on +> the `dev` branch. + +When running the following command line commands, ensure that your current working directory is the one +where the PyGOM source files were downloaded to. This should be found from your home directory: + + cd pygom + +Activate the relevant branch for installation via Git Bash. for example if you want +new release then this is the `dev` branch: + + git checkout dev + +Package dependencies can be found in the file, `requirements.txt`. +An easy way to install these to create a new [conda](https://conda.io/docs) environment in Anaconda Prompt via: + + conda env create -f conda-env.yml + +which you should ensure is active for the installation process using + + conda activate pygom + +Alternatively, you may add dependencies to your own environment through conda: + + conda install --file requirements.txt + +**or** via pip: + + pip install -r requirements.txt + +The final prerequisites, if you are working on a Windows machine, is that you will also need to install: +- [Graphviz](https://graphviz.org/) +- Microsoft Visual C++ 14.0 or greater, which you can get with [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) + +You should now be able to install the PyGOM package via command line: + + pip install . + +and test that installation has completed successfully + + python -m unittest discover --verbose --start-directory tests + +This will run a few test cases and can take some minutes to complete. + +## Documentation + +Documentation must be built locally and all necessary files can be found in the `docs` folder. +Documentation is built from the command line by first installing the additional documentation requirements: + + pip install -r docs/requirements.txt + +and then building the documentation: + + jupyter-book build docs + +The html files will be saved in the local copy of your repository under: + + docs/_build/html + +You can view the documentation by opening the index file in your browser of choice: + + docs/_build/html/index.html + +> [!NOTE] +> Building the documentation involves running many examples in python which can take up to 30 minutes. Subsequent builds with these examples unchanged are much quicker due to caching of the code outputs. + +Please be aware that if the module tests fails, then the documentation for the package will not compile. + +## Contributors + +Thomas Finnie (Thomas.Finnie@ukhsa.gov.uk) + +Edwin Tye + +Hannah Williams + +Jonty Carruthers + +Martin Grunnill + +Joseph Gibson + +## Version +0.1.8 Updated and much better documentation. + +0.1.7 Add Approximate Bayesian Computation (ABC) as a method of fitting to data + +0.1.6 Bugfix scipy API, pickling, print to logging and simulation + +0.1.5 Remove auto-simplification for much faster startup + +0.1.4 Much faster Tau leap for stochastic simulations + +0.1.3 Defaults to python built-in unittest and more in sync with conda diff --git a/README.rst b/README.rst deleted file mode 100644 index b78b4bd3..00000000 --- a/README.rst +++ /dev/null @@ -1,87 +0,0 @@ -=============================== -pygom - ODE modelling in Python -=============================== - -|Build status| |Github actions| |Documentation Status| |pypi version| |licence| |Jupyter Book Badge| - -.. |pypi version| image:: https://img.shields.io/pypi/v/pygom.svg - :target: https://pypi.python.org/pypi/pygom -.. |Documentation Status| image:: https://readthedocs.org/projects/pygom/badge/?version=master - :target: https://pygom.readthedocs.io/en/master/?badge=master -.. |licence| image:: https://img.shields.io/pypi/l/pygom?color=green :alt: PyPI - License - :target: https://raw.githubusercontent.com/PublicHealthEngland/pygom/master/LICENSE.txt -.. |Github actions| image:: https://github.com/PublicHealthEngland/pygom/workflows/pygom/badge.svg - :target: https://github.com/PublicHealthEngland/pygom/actions/ -.. |Jupyter Book Badge| image:: https://jupyterbook.org/badge.svg - :target: https://hwilliams-phe.github.io/pygom/intro.html - -A generic framework for ode models, specifically compartmental type problems. - -This package depends on:: - - dask - matplotlib - enum34 - pandas - python-dateutil - numpy - scipy - sympy - -and they should be installed if not already available. Alternatively, the easier way -to use a minimal (and isolated) setup is to use `conda `_ and -create a new environment via:: - - conda env create -f conda-env.yml - -Installation of this package can be performed via:: - -$ python setup.py install - -and tested via:: - -$ python setup.py test - -A reduced form of the documentation may be found on ReadTheDocs_. - -.. _ReadTheDocs: https://pygom.readthedocs.io/en/master/ - -You may get the full documentation, including the lengthy examples by locally -building the documentation found in the folder:: - -$ doc - -Note that building the documentation can be extremely slow depending on the -setup of the system. Further details can be found at it's own read me:: - -$ doc/README.rst - -Please be aware that if the module tests fails, then the documentation for the -package will not compile. - -Please be aware that there may be redundant files within the package as it is -under active development. - -Contributors -============ -Thomas Finnie (Thomas.Finnie@phe.gov.uk) - -Edwin Tye - -Hannah Williams - -Jonty Carruthers - -Martin Grunnill - -Version -======= -0.1.7 Add Approximate Bayesian Computation (ABC) as a method of fitting to data - -0.1.6 Bugfix scipy API, pickling, print to logging and simulation - -0.1.5 Remove auto-simplification for much faster startup - -0.1.4 Much faster Tau leap for stochastic simulations - -0.1.3 Defaults to python built-in unittest and more in sync with conda diff --git a/conda-env.yml b/conda-env.yml index 8c4d3582..359ab31a 100644 --- a/conda-env.yml +++ b/conda-env.yml @@ -11,5 +11,5 @@ dependencies: - graphviz - cython - pip - -pip: + - pip: - -r requirements.txt diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 41dbaa98..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyGenericOdeModelDoc.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyGenericOdeModelDoc.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc/README.rst b/doc/README.rst deleted file mode 100644 index a5143c74..00000000 --- a/doc/README.rst +++ /dev/null @@ -1,36 +0,0 @@ -======================= -Documentation for pygom -======================= - -This documentation is written in `sphinx` style. The starting point (about the -package) can be found at:: - - $ doc/_build/html/index.html - -which is the main page in html format. - -If you wish to build the documentation. Go to the document directory and type -the following line in the terminal:: - - doc$ make html - -It is assumed here that the pyGenericOdeModel package has already -been installed, else, the code demonstration will throw out errors -as it cannot find the required modules. Most likely, building the -documentation will require the following packages if not already installed:: - - numpydoc - sphinx - ipython - - -There may be cases that `ipython` require extra packages, install the full -version using `$ pip install ipython[all]` - -============================ -Installation of requirements -============================ - -If you are using `conda` the requirements to build the docs can be installed -by `$ conda install --file requirements.txt` or similarly for those using `pip` -you may `$pip install -r requirements.txt` from the root of the docs directory. \ No newline at end of file diff --git a/doc/doc_to_sort/bvpSimple.rst b/doc/doc_to_sort/bvpSimple.rst deleted file mode 100644 index e5de0d61..00000000 --- a/doc/doc_to_sort/bvpSimple.rst +++ /dev/null @@ -1,187 +0,0 @@ -.. _bvpSimple: - -******************************* -Solving Boundary Value Problems -******************************* - -In addition to finding solutions for an IVP and estimate the unknown parameters, this package also allows you to solve BVP with a little bit of imagination. Here, we are going to show how a BVP can be solved by treating it as a parameter estimation problem. Essentially, a shooting method where the first boundary condition defines the initial condition of an IVP and the second boundary condition is an observation. Two examples, both from MATLAB [1]_, will be shown here. - -Simple model 1 -============== - -We are trying to find the solution to the second order differential equation - -.. math:: - \nabla^{2} y + |y| = 0 - -subject to the boundary conditions :math:`y(0) = 0` and :math:`y(4) = -2`. Convert this into a set of first order ODE - -.. math:: - - \frac{d y_{0}}{dt} &= y_{1} \\ - \frac{d y_{1}}{dt} &= -|y_{0}| - -using an auxiliary variable :math:`y_{1} = \nabla y` and :math:`y_{0} = y`. Setting up the system below - -.. ipython:: - - In [1]: from pygom import Transition, TransitionType, DeterministicOde, SquareLoss - - In [1]: import matplotlib.pyplot as plt - - In [2]: stateList = ['y0', 'y1'] - - In [3]: paramList = [] - - In [4]: ode1 = Transition(origin='y0', - ...: equation='y1', - ...: transition_type=TransitionType.ODE) - - In [5]: ode2 = Transition(origin='y1', - ...: equation='-abs(y0)', - ...: transition_type=TransitionType.ODE) - - In [6]: model = DeterministicOde(stateList, - ...: paramList, - ...: ode=[ode1, ode2]) - - In [7]: model.get_ode_eqn() - -We check that the equations are correct before proceeding to set up our loss function. - -.. ipython:: - - In [1]: import numpy - - In [2]: from scipy.optimize import minimize - - In [3]: initialState = [0.0, 1.0] - - In [4]: t = numpy.linspace(0, 4, 100) - - In [5]: model.initial_values = (initialState, t[0]) - - In [6]: solution = model.integrate(t[1::]) - - In [7]: f = plt.figure() - - @savefig bvp1_random_guess_plot.png - In [8]: model.plot() - - In [9]: plt.close() - -Setting up the second boundary condition :math:`y(4) = -2` is easy, because that -is just a single observation attached to the state :math:`y_{1}`. Enforcing the -first boundary condition requires us to set it as the initial condition. -Because the condition only states that :math:`y(0) = 0`, the starting value of -the other state :math:`y_1` is free. We let our loss object know that it is -free through the targetState input argument. - -.. ipython:: - - In [10]: theta = [0.0] - - In [11]: obj = SquareLoss(theta=theta, - ....: ode=model, - ....: x0=initialState, - ....: t0=t[0], - ....: t=t[-1], - ....: y=[-2], - ....: state_name=['y0'], - ....: target_state=['y1']) - - In [12]: thetaHat = minimize(fun=obj.costIV, x0=[0.0]) - - In [13]: print(thetaHat) - - In [14]: model.initial_values = ([0.0] + thetaHat['x'].tolist(), t[0]) - - In [15]: solution = model.integrate(t[1::]) - - In [16]: f = plt.figure() - - @savefig bvp1_solution_plot.png - In [17]: model.plot() - - In [18]: plt.close() - -We are going to visualize the solution, and also check the boundary condition. The first became our initial condition, so it is always satisfied and only the latter is of concern, which is zero (subject to numerical error) from thetaHat. - -Simple model 2 -============== - -Our second example is different as it involves an actual parameter and also time. We have the Mathieu's Equation - -.. math:: - - \nabla^{2} y + \left(p - 2q \cos(2x)\right)y = 0 - -and the aim is to compute the fourth eigenvalue :math:`q=5`. There are three boundary conditions - -.. math:: - - \nabla y(0) = 0, \quad \nabla y(\pi) = 0, \quad y(0) = 1 - -and we aim to solve it by converting it to a first order ODE and tackle it as an IVP. As our model object does not allow the use of the time component in the equations, we introduce a anxiliary state :math:`\tau` that replaces time :math:`t`. Rewrite the equations using :math:`y_{0} = y, y_{1} = \nabla y` and define our model as - -.. ipython:: - - In [1]: stateList = ['y0', 'y1', 'tau'] - - In [2]: paramList = ['p'] - - In [3]: ode1 = Transition('y0', 'y1', TransitionType.ODE) - - In [4]: ode2 = Transition('y1', '-(p - 2*5*cos(2*tau))*y0', TransitionType.ODE) - - In [5]: ode3 = Transition('tau', '1', TransitionType.ODE) - - In [6]: model = DeterministicOde(stateList, paramList, ode=[ode1, ode2, ode3]) - - In [7]: theta = [1.0, 1.0, 0.0] - - In [8]: p = 15.0 - - In [9]: t = numpy.linspace(0, numpy.pi) - - In [10]: model.parameters = [('p',p)] - - In [11]: model.initial_values = (theta, t[0]) - - In [12]: solution = model.integrate(t[1::]) - - In [13]: f = plt.figure() - - @savefig bvp2_random_guess_plot.png - In [14]: model.plot() - - In [15]: plt.close() - -Now we are ready to setup the estimation. Like before, we setup the second boundary condition by pretending that it is an observation. We have all the initial conditions defined by the first boundary condition - -.. ipython:: - - In [1]: obj = SquareLoss(15.0, model, x0=[1.0, 0.0, 0.0], t0=0.0, t=numpy.pi, y=0.0, state_name='y1') - - In [2]: xhatObj = minimize(obj.cost,[15]) - - In [3]: print(xhatObj) - - In [4]: model.parameters = [('p', xhatObj['x'][0])] - - In [5]: model.initial_values = ([1.0, 0.0, 0.0], t[0]) - - In [5]: solution = model.integrate(t[1::]) - - In [6]: f = plt.figure() - - @savefig bvp2_solution_plot.png - In [7]: model.plot() - - In [8]: plt.close() - -The plot of the solution shows the path that satisfies all boundary condition. The last subplot is time which obvious is redundant here but the :meth:`DeterministicOde.plot` method is not yet able to recognize the time component. Possible speed up can be achieved through the use of derivative information or via root finding method that tackles the gradient directly, instead of the cost function. - -**Reference** - -.. [1] http://uk.mathworks.com/help/matlab/ref/bvp4c.html diff --git a/doc/doc_to_sort/common_models.rst b/doc/doc_to_sort/common_models.rst deleted file mode 100644 index 01dfe8dd..00000000 --- a/doc/doc_to_sort/common_models.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _common_models: - -********************************* -Pre-defined Example common_models -********************************* - -We have defined a set of models :mod:`common_models`, most of them commonly used in epidemiology. They are there as examples and also save time for end users. Most of them are of the compartmental type, and we use standard naming conventions i.e. **S** = Susceptible, **E** = Exposed, **I** = Infectious, **R** = Recovered. Extra state symbol will be introduced when required. - -.. toctree:: - - common_models/SIS.rst - common_models/SIS_Periodic.rst - common_models/SIR.rst - common_models/SIR_Birth_Death.rst - common_models/SEIR.rst - common_models/SEIR_Multiple.rst - common_models/SEIR_Birth_Death.rst - common_models/SEIR_Birth_Death_Periodic.rst - common_models/Legrand_Ebola_SEIHFR.rst - common_models/Lotka_Volterra.rst - common_models/Lotka_Volterra_4State.rst - common_models/FitzHugh.rst - common_models/Lorenz.rst - common_models/vanDelPol.rst - common_models/Robertson.rst - diff --git a/doc/doc_to_sort/common_models/FitzHugh.rst b/doc/doc_to_sort/common_models/FitzHugh.rst deleted file mode 100644 index 517a8a55..00000000 --- a/doc/doc_to_sort/common_models/FitzHugh.rst +++ /dev/null @@ -1,43 +0,0 @@ -:func:`.FitzHugh` ------------------ - -The FitzHugh model [FitzHugh1961]_ without external external stimulus. This is a commonly used model when developing new methodology with regard to ode's, see [Ramsay2007]_ and [Girolami2011]_ and reference therein. - -.. math:: - - \frac{dV}{dt} &= c ( V - \frac{V^{3}}{3} + R) \\ - \frac{dR}{dt} &= -\frac{1}{c}(V - a + bR). - -An example would be - -.. ipython:: - - In [1]: import numpy - - In [1]: from pygom import common_models - - In [1]: import matplotlib.pyplot as plt - - In [1]: ode = common_models.FitzHugh({'a':0.2, 'b':0.2, 'c':3.0}) - - In [1]: t = numpy.linspace(0, 20, 101) - - In [1]: x0 = [1.0, -1.0] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_fh_1.png - In [1]: ode.plot() - - In [1]: plt.close() - - In [1]: fig = plt.figure() - - In [1]: plt.plot(solution[:,0], solution[:,1], 'b') - - @savefig common_models_fh_2.png - In [1]: plt.show() - - In [1]: plt.close() \ No newline at end of file diff --git a/doc/doc_to_sort/common_models/Legrand_Ebola_SEIHFR.rst b/doc/doc_to_sort/common_models/Legrand_Ebola_SEIHFR.rst deleted file mode 100644 index 0b0ab4d9..00000000 --- a/doc/doc_to_sort/common_models/Legrand_Ebola_SEIHFR.rst +++ /dev/null @@ -1,93 +0,0 @@ -:func:`.Legrand_Ebola_SEIHFR` -============================= - -A commonly used model in the literature to model Ebola outbreaks is the SEIHFR model proposed by [Legrand2007]_. There are two extra compartments on top of the standard SEIR, :math:`H` for hospitialization and :math:`F` for funeral. A total of ten parameters (with some describing the inverse) are required for the model, they are: - -================== ============================================ - Symbol Process -================== ============================================ -:math:`\beta_{I}` Transmission rate in community -:math:`\beta_{H}` Transmission rate in hospital -:math:`\beta_{F}` Transmission rate in funeral -:math:`\gamma_{I}` (inverse) Onset to end of infectious -:math:`\gamma_{D}` (inverse) Onset to death -:math:`\gamma_{H}` (inverse) Onset of hospitilization -:math:`\gamma_{F}` (inverse) Death to burial -:math:`\alpha` (inverse) Duration of the incubation period -:math:`\theta` Proportional of cases hospitalized -:math:`\delta` Case--ftality ratio -================== ============================================ - -The **(inverse)** denotes the parameter should be inverted to make epidemiological sense. We use the parameters in their more natural from in :func:`.Legrand_Ebola_SEIHFR` and replace all the :math:`\gamma`'s with :math:`\omega`'s, i.e. :math:`\omega_{i} = \gamma_{i}^{-1}` for :math:`i \in \{I,D,H,F\}`. We also used :math:`\alpha^{-1}` in our model instead of :math:`\alpha` so that reading the parameters directly gives a more intuitive meaning. There arw five additional parameters that is derived. The two derived case fatality ratio as - -.. math:: - - \delta_{1} &= \frac{\delta \gamma_{I}}{\delta \gamma_{I} + (1-\delta)\gamma_{D}} \\ - \delta_{2} &= \frac{\delta \gamma_{IH}}{\delta \gamma_{IH} + (1-\delta)\gamma_{DH}}, - -with an adjusted hospitalization parameter - -.. math:: - - \theta_{1} = \frac{\theta(\gamma_{I}(1-\delta_{1}) + \gamma_{D}\delta_{1})}{\theta(\gamma_{I}(1-\delta_{1}) + \gamma_{D}\delta_{1}) + (1-\theta)\gamma_{H}}, - -and the derived infectious period - -.. math:: - - \gamma_{IH} &= (\gamma_{I}^{-1} - \gamma_{H}^{-1})^{-1} \\ - \gamma_{DH} &= (\gamma_{D}^{-1} - \gamma_{H}^{-1})^{-1}. - -Now we are ready to state the full set of ode's, - -.. math:: - - \frac{dS}{dt} &= -N^{-1} (\beta_{I}SI + \beta_{H}SH + \beta_{F}(t) SF) \\ - \frac{dE}{dt} &= N^{-1} (\beta_{I}SI + \beta_{H}SH + \beta_{F}(t) SF) - \alpha E \\ - \frac{dI}{dt} &= \alpha E - (\gamma_{H} \theta_{1} + \gamma_{I}(1-\theta_{1})(1-\delta_{1}) + \gamma_{D}(1-\theta_{1})\delta_{1})I \\ - \frac{dH}{dt} &= \gamma_{H}\theta_{1}I - (\gamma_{DH}\delta_{2} + \gamma_{IH}(1-\delta_{2}))H \\ - \frac{dF}{dt} &= \gamma_{D}(1-\theta_{1})\delta_{1}I + \gamma_{DH}\delta_{2}H - \gamma_{F}F \\ - \frac{dR}{dt} &= \gamma_{I}(1-\theta_{1})(1-\delta_{1})I + \gamma_{IH}(1-\delta_{2})H + \gamma_{F}F. - -with :math:`\beta_{F}(t) = \beta_{F}` if :math:`t > c` and :math:`0` otherwise. We use a slightly modified version by replacing the delta function with a sigmoid function namely, the logistic function - -.. math:: - - \beta_{F}(t) = \beta_{F} \left(1 - \frac{1}{1 + \exp(-\kappa (t - c))} \right) - -A brief example (from [3]) is given here with a slightly more in depth example in :ref:`estimate2`. - -.. ipython:: - - In [1]: import numpy - - In [1]: from pygom import common_models - - In [1]: x0 = [1.0, 3.0/200000.0, 0.0, 0.0, 0.0, 0.0, 0.0] - - In [1]: t = numpy.linspace(1, 25, 100) - - In [1]: ode = common_models.Legrand_Ebola_SEIHFR([ - ...: ('beta_I',0.588), - ...: ('beta_H',0.794), - ...: ('beta_F',7.653), - ...: ('omega_I',10.0/7.0), - ...: ('omega_D',9.6/7.0), - ...: ('omega_H',5.0/7.0), - ...: ('omega_F',2.0/7.0), - ...: ('alphaInv',7.0/7.0), - ...: ('delta',0.81), - ...: ('theta',0.80), - ...: ('kappa',300.0), - ...: ('interventionTime',7.0) - ...: ]) - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t) - - @savefig common_models_seihfr.png - In [1]: ode.plot() - -Note also that we have again standardized so that the number of susceptible is 1 and equal to the whole population, i.e. :math:`N` does not exist in our set of ode's as defined in :mod:`.common_models`. - diff --git a/doc/doc_to_sort/common_models/Lorenz.rst b/doc/doc_to_sort/common_models/Lorenz.rst deleted file mode 100644 index cc03eac3..00000000 --- a/doc/doc_to_sort/common_models/Lorenz.rst +++ /dev/null @@ -1,37 +0,0 @@ -:func:`.Lorenz` -=============== - -The Lorenz attractor [Lorenz1963]_ defined by the equations - -.. math:: - - \frac{dx}{dt} &= \sigma (y-x) \\ - \frac{dy}{dt} &= x (\rho - z) - y \\ - \frac{dz}{dt} &= xy - \beta z - -A classic example is - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: import matplotlib.pyplot as plt - - In [1]: t = numpy.linspace(0, 100, 20000) - - In [1]: ode = common_models.Lorenz({'beta':8.0/3.0, 'sigma':10.0, 'rho':28.0}) - - In [1]: ode.initial_values = ([1., 1., 1.], t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - In [1]: f = plt.figure() - - In [1]: plt.plot(solution[:,0], solution[:,2]); - - @savefig common_models_Lorenz.png - In [1]: plt.show() - - diff --git a/doc/doc_to_sort/common_models/Lotka_Volterra.rst b/doc/doc_to_sort/common_models/Lotka_Volterra.rst deleted file mode 100644 index fbf65c4b..00000000 --- a/doc/doc_to_sort/common_models/Lotka_Volterra.rst +++ /dev/null @@ -1,91 +0,0 @@ -:func:`.Lotka_Volterra` -======================= - -A standard Lotka-Volterra (preditor and prey) model with two states and four parameters [Lotka1920]_. - -.. math:: - - \frac{dx}{dt} &= \alpha x - cxy \\ - \frac{dy}{dt} &= -\delta y + \gamma xy - -with both birth and death processes. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: import matplotlib.pyplot as plt - - In [1]: x0 = [2.0, 6.0] - - In [1]: ode = common_models.Lotka_Volterra({'alpha':1, 'delta':3, 'c':2, 'gamma':6}) - - In [1]: ode.initial_values = (x0, 0) - - In [1]: t = numpy.linspace(0.1, 100, 10000) - - In [1]: solution = ode.integrate(t) - - @savefig common_models_Lotka_Volterra.png - In [1]: ode.plot() - - In [1]: plt.close() - -Then we generate the graph at `Wolfram Alpha `_ with varying initial conditions. - -.. ipython:: - - In [1]: x1List = numpy.linspace(0.2, 2.0, 5) - - In [1]: x2List = numpy.linspace(0.6, 6.0, 5) - - In [1]: fig = plt.figure() - - In [1]: solutionList = list() - - In [1]: ode = common_models.Lotka_Volterra({'alpha':1, 'delta':3, 'c':2, 'gamma':6}) - - In [1]: for i in range(len(x1List)): - ...: ode.initial_values = ([x1List[i], x2List[i]], 0) - ...: solutionList += [ode.integrate(t)] - - In [1]: for i in range(len(x1List)): plt.plot(solutionList[i][100::,0], solutionList[i][100::,1], 'b') - - In [1]: plt.xlabel('x') - - In [1]: plt.ylabel('y') - - @savefig common_models_Lotka_Volterra_initial_condition.png - In [1]: plt.show() - - In [1]: plt.close() - -We also know that the system has the critical points at :math:`x = \delta / \gamma` and :math:`y=\alpha / c`. If we changes the parameters in such a way that the ration between :math:`x` and :math:`y` remains the same, then we get a figure as below - -.. ipython:: - - In [1]: cList = numpy.linspace(0.1, 2.0, 5) - - In [1]: gammaList = numpy.linspace(0.6, 6.0, 5) - - In [1]: fig = plt.figure() - - In [1]: for i in range(len(x1List)): - ...: ode = common_models.Lotka_Volterra({'alpha':1, 'delta':3, 'c':cList[i], 'gamma':gammaList[i]}) - ...: ode.initial_values = (x0, 0) - ...: solutionList += [ode.integrate(t)] - - In [1]: for i in range(len(cList)): plt.plot(solutionList[i][100::,0], solutionList[i][100::,1]) - - In [1]: plt.xlabel('x') - - In [1]: plt.ylabel('y') - - @savefig common_models_Lotka_Volterra_critical_point.png - In [1]: plt.show() - - In [1]: plt.close() - -where all the cycles goes through the same points. diff --git a/doc/doc_to_sort/common_models/Lotka_Volterra_4State.rst b/doc/doc_to_sort/common_models/Lotka_Volterra_4State.rst deleted file mode 100644 index 33b75b76..00000000 --- a/doc/doc_to_sort/common_models/Lotka_Volterra_4State.rst +++ /dev/null @@ -1,52 +0,0 @@ -:func:`.Lotka_Volterra_4State` -============================== - -The Lotka-Volterra model with four states and three parameters [Lotka1920]_, explained by the following three transitions - -.. math:: - - \frac{da}{dt} &= k_{0} a x \\ - \frac{dx}{dt} &= k_{0} a x - k_{1} x y \\ - \frac{dy}{dt} &= k_{1} x y - k_{2} y \\ - \frac{db}{dt} &= k_{2} y. - -First, we show the deterministic approach. Then we also show the different process path using the parameters from [Press2007]_. Note that although the model is defined in :mod:`common_models`, it is based on outputting an :class:`OperateOdeModel` rather than :class:`SimulateOdeModel`. - -.. ipython:: - - In [1]: import matplotlib.pyplot as plt - - In [1]: from pygom import Transition, TransitionType, ode_utils, SimulateOde - - In [1]: import numpy - - In [1]: stateList = ['a', 'x', 'y', 'b'] - - In [1]: paramList = ['k0', 'k1', 'k2'] - - In [1]: transitionList = [ - ...: Transition(origin='a', destination='x', equation='k0*a*x', transition_type=TransitionType.T), - ...: Transition(origin='x', destination='y', equation='k1*x*y', transition_type=TransitionType.T), - ...: Transition(origin='y', destination='b', equation='k2*y', transition_type=TransitionType.T) - ...: ] - - In [1]: ode = SimulateOde(stateList, paramList, transition=transitionList) - - In [1]: x0 = [150.0, 10.0, 10.0, 0.0] - - In [1]: t = numpy.linspace(0, 15, 100) - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: ode.parameters = [0.01, 0.1, 1.0] - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_Lotka_Volterra_4State.png - In [1]: ode.plot() - - In [1]: simX, simT = ode.simulate_jump(t[1::], 5, full_output=True) - - @savefig common_models_Lotka_Volterra_Sim.png - In [1]: ode.plot(simX, simT) - diff --git a/doc/doc_to_sort/common_models/Robertson.rst b/doc/doc_to_sort/common_models/Robertson.rst deleted file mode 100644 index 0e90755b..00000000 --- a/doc/doc_to_sort/common_models/Robertson.rst +++ /dev/null @@ -1,75 +0,0 @@ -:func:`.Robertson` -================== - -The Robertson problem [Robertson1966]_ - -.. math:: - - \frac{dy_{1}}{dt} &= -0.04 y_{1} + 1 \cdot 10^{4} y_{2} y_{3} \\ - \frac{dy_{2}}{dt} &= 0.04 y_{1} - 1 \cdot 10^{4} y_{2} y_{3} + 3 \cdot 10^{7} y_{2}^{2} \\ - \frac{dy_{3}}{dt} &= 3 \cdot 10^{7} y_{2}^{2}. - -This is a problem that describes an autocatalytic reaction. One of those commonly used to test stiff ode solvers. As the parameters in the literature is fixed, we show here how to define the states in a slightly more compact format - -.. ipython:: - - In [1]: from pygom import DeterministicOde, Transition, TransitionType - - In [1]: import numpy - - In [1]: import matplotlib.pyplot as plt - - In [1]: t = numpy.append(0, 4*numpy.logspace(-6, 6, 1000)) - - In [1]: # note how we define the states - - In [1]: stateList = ['y1:4'] - - In [1]: paramList = [] - - In [1]: transitionList = [ - ...: Transition(origin='y1', destination='y2', equation='0.04*y1', transition_type=TransitionType.T), - ...: Transition(origin='y2', destination='y1', equation='1e4*y2*y3', transition_type=TransitionType.T), - ...: Transition(origin='y2', destination='y3', equation='3e7*y2*y2', transition_type=TransitionType.T) - ...: ] - - In [1]: ode = DeterministicOde(stateList, paramList, transition=transitionList) - - In [1]: ode.initial_values = ([1.0, 0.0, 0.0], t[0]) - - In [1]: solution, output = ode.integrate(t[1::], full_output=True) - - In [1]: f, axarr = plt.subplots(1, 3) - - In [1]: for i in range(3): - ...: axarr[i].plot(t, solution[:,i]) - ...: axarr[i].set_xscale('log') - - In [1]: f.tight_layout(); - - @savefig common_models_Robertson_1.png - In [1]: plt.show() - - In [1]: plt.close() - -To simplify even further, we can use `y` with the corresponding subscript directly instead of `y1,y2,y3`. Again, we do not have any parameters as they are hard coded into our models. - -.. ipython:: - - In [1]: stateList = ['y1:4'] - - In [1]: transitionList = [ - ...: Transition(origin='y[0]', destination='y[1]', equation='0.04*y[0]', transition_type=TransitionType.T), - ...: Transition(origin='y[1]', destination='y[0]', equation='1e4*y[1]*y[2]', transition_type=TransitionType.T), - ...: Transition(origin='y[1]', destination='y[2]', equation='3e7*y[1]*y[1]', transition_type=TransitionType.T) - ...: ] - - In [1]: ode = DeterministicOde(stateList, paramList, transition=transitionList) - - In [1]: ode.initial_values =([1.0, 0.0, 0.0], t[0]) - - In [1]: solution2 = ode.integrate(t[1::]) - - In [1]: numpy.max(solution - solution2) - -and we have the identical solution as shown in the last line above. diff --git a/doc/doc_to_sort/common_models/SEIR.rst b/doc/doc_to_sort/common_models/SEIR.rst deleted file mode 100644 index 0cb5f9cc..00000000 --- a/doc/doc_to_sort/common_models/SEIR.rst +++ /dev/null @@ -1,36 +0,0 @@ -:func:`.SEIR` -============= - -A natural extension to the SIR is the SEIR model. An extra parameter :math:`\alpha`, which is the inverse of the incubation period is introduced. - -.. math:: - - \frac{dS}{dt} &= -\beta SI \\ - - \frac{dE}{dt} &= \beta SI - \alpha E \\ - - \frac{dI}{dt} &= \alpha E - \gamma I \\ - - \frac{dR}{dt} &= \gamma I - -We use the parameters from [Aron1984] here to generate our plots, which does not yield a *nice* and *sensible* epidemic curve as the birth and death processes are missing. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: ode = common_models.SEIR({'beta':1800, 'gamma':100, 'alpha':35.84}) - - In [1]: t = numpy.linspace(0, 50, 1001) - - In [1]: x0 = [0.0658, 0.0007, 0.0002, 0.0] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_seir.png - In [1]: ode.plot() - diff --git a/doc/doc_to_sort/common_models/SEIR_Birth_Death.rst b/doc/doc_to_sort/common_models/SEIR_Birth_Death.rst deleted file mode 100644 index 970231aa..00000000 --- a/doc/doc_to_sort/common_models/SEIR_Birth_Death.rst +++ /dev/null @@ -1,36 +0,0 @@ -:func:`.SEIR_Birth_Death` -========================= - -Extending it to also include birth death process with equal rate :math:`\mu` - -.. math:: - - \frac{dS}{dt} &= \mu - \beta SI - \mu S \\ - \frac{dE}{dt} &= \beta SI - (\mu + \alpha) E \\ - \frac{dI}{dt} &= \alpha E - (\mu + \gamma) I \\ - \frac{dR}{dt} &= \gamma I - -Same parameters value taken from [Aron1984]_ as the SEIR example above is used here. Observe how the introduction of a birth and a death process changes the graph even though the rest of the parameters remains the same. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import matplotlib.pyplot as plt - - In [1]: import numpy - - In [1]: ode = common_models.SEIR_Birth_Death({'beta':1800, 'gamma':100, 'alpha':35.84, 'mu':0.02}) - - In [1]: t = numpy.linspace(0, 50, 1001) - - In [1]: x0 = [0.0658, 0.0007, 0.0002, 0.0] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::], full_output=True) - - @savefig common_models_seir_bd.png - In [1]: ode.plot() - - In [1]: plt.close() \ No newline at end of file diff --git a/doc/doc_to_sort/common_models/SEIR_Birth_Death_Periodic.rst b/doc/doc_to_sort/common_models/SEIR_Birth_Death_Periodic.rst deleted file mode 100644 index 1f40f887..00000000 --- a/doc/doc_to_sort/common_models/SEIR_Birth_Death_Periodic.rst +++ /dev/null @@ -1,69 +0,0 @@ -:func:`.SEIR_Birth_Death_Periodic` -================================== - -Now extending the SEIR to also have periodic contact, as in [Aron1984]_. - -.. math:: - - \frac{dS}{dt} &= \mu - \beta(t)SI - \mu S \\ - \frac{dE}{dt} &= \beta(t)SI - (\mu + \alpha) E \\ - \frac{dI}{dt} &= \alpha E - (\mu + \gamma) I \\ - \frac{dR}{dt} &= \gamma I. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: import matplotlib.pyplot as plt - - In [1]: ode = common_models.SEIR_Birth_Death_Periodic({'beta_0':1800, 'beta_1':0.2, 'gamma':100, 'alpha':35.84, 'mu':0.02}) - - In [1]: t = numpy.linspace(0, 50, 1001) - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: x0 = [0.0658, 0.0007, 0.0002, 0.0] - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_seir_bd_periodic1.png - In [1]: ode.plot() - - In [1]: plt.close() - -The periodicity is obvious when looking at the the plot between states :math:`S` and :math:`E`, in logarithmic scale. - -.. ipython:: - - In [1]: fig = plt.figure(); - - In [1]: plt.plot(numpy.log(solution[:,0]), numpy.log(solution[:,1])); - - In [1]: plt.xlabel('log of S'); - - In [1]: plt.ylabel('log of E'); - - @savefig common_models_seir_bd_periodic2.png - In [1]: plt.show() - - In [1]: plt.close() - -Similarly, we can see the same thing between the states :math:`E` and :math:`I`. - -.. ipython:: - - In [1]: fig = plt.figure(); - - In [1]: plt.plot(numpy.log(solution[:,1]), numpy.log(solution[:,2])); - - In [1]: plt.xlabel('log of E'); - - In [1]: plt.ylabel('log of I'); - - @savefig common_models_seir_bd_periodic3.png - In [1]: plt.show() - - In [1]: plt.close() - diff --git a/doc/doc_to_sort/common_models/SEIR_Multiple.rst b/doc/doc_to_sort/common_models/SEIR_Multiple.rst deleted file mode 100644 index 2c1daa3c..00000000 --- a/doc/doc_to_sort/common_models/SEIR_Multiple.rst +++ /dev/null @@ -1,49 +0,0 @@ -:func:`.SEIR_Multiple` -====================== - -Multiple SEIR coupled together, without any birth death process. - -.. math:: - - \frac{dS_{i}}{dt} &= dN_{i} - dS_{i} - \lambda_{i}S_{i} \\ - \frac{dE_{i}}{dt} &= \lambda_{i}S_{i} - (d+\epsilon)E_{i} \\ - \frac{dI_{i}}{dt} &= \epsilon E_{i} - (d+\gamma) I_{i} \\ - \frac{dR_{i}}{dt} &= \gamma I_{i} - dR_{i} - -where - -.. math:: - - \lambda_{i} = \sum_{j=1}^{n} \beta_{i,j} I_{j} (1\{i\neq j\} p) - -with :math:`n` being the number of patch and :math:`p` the coupled factor. - -.. ipython:: - - In [1]: from pygom import common_models - - In [2]: import numpy - - In [3]: paramEval = {'beta_00':0.0010107,'beta_01':0.0010107,'beta_10':0.0010107, - ...: 'beta_11':0.0010107,'d':0.02,'epsilon':45.6,'gamma':73.0, - ...: 'N_0':10**6,'N_1':10**6,'p':0.01} - - In [4]: x0 = [36139.3224081278, 422.560577637822, 263.883351688369, 963174.233662546] - - In [5]: ode = common_models.SEIR_Multiple(param=paramEval) - - In [6]: t = numpy.linspace(0, 40, 100) - - In [7]: x01 = [] - - In [8]: for s in x0: - ...: x01 += 2*[s] - - In [9]: ode.initial_values = (numpy.array(x01, float),t[0]) - - In [10]: solution, output = ode.integrate(t[1::], full_output=True) - - @savefig common_models_seir_multiple.png - In [11]: ode.plot() - -The initial conditions are those derived by using the stability condition as stated in [Lloyd1996]_ while the notations is taken from [Brauer2008]_. diff --git a/doc/doc_to_sort/common_models/SIR.rst b/doc/doc_to_sort/common_models/SIR.rst deleted file mode 100644 index 77cef848..00000000 --- a/doc/doc_to_sort/common_models/SIR.rst +++ /dev/null @@ -1,47 +0,0 @@ -:func:`.SIR` -============ - -A standard SIR model defined by the equations - -.. math:: - - \frac{dS}{dt} &= -\beta SI \\ - \frac{dI}{dt} &= \beta SI - \gamma I \\ - \frac{dR}{dt} &= \gamma I - -Note that the examples and parameters are taken from [Brauer2008]_, namely Figure 1.4. Hence, the first one below may not appear to make much sense. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) - - In [1]: t = numpy.linspace(0, 730, 1001) - - In [1]: N = 7781984.0 - - In [1]: x0 = [1.0, 10.0/N, 0.0] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_sir.png - In [1]: ode.plot() - -Now we have the more sensible plot, where the initial susceptibles is only a fraction of 1. - -.. ipython:: - - In [1]: x0 = [0.065, 123*(5.0/30.0)/N, 0.0] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_sir_realistic.png - In [1]: ode.plot() - diff --git a/doc/doc_to_sort/common_models/SIR_Birth_Death.rst b/doc/doc_to_sort/common_models/SIR_Birth_Death.rst deleted file mode 100644 index 5ddc9cf9..00000000 --- a/doc/doc_to_sort/common_models/SIR_Birth_Death.rst +++ /dev/null @@ -1,37 +0,0 @@ -:func:`.SIR_Birth_Death` -======================== - -Next, we look at an SIR model with birth death - -.. math:: - - \frac{dS}{dt} &= B -\beta SI - \mu S \\ - \frac{dI}{dt} &= \beta SI - \gamma I - \mu I \\ - \frac{dR}{dt} &= \gamma I - - -Continuing from the example above, but now with a much longer time frame. Note that the birth and death rate are the same. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: B = 126372.0/365.0 - - In [1]: N = 7781984.0 - - In [1]: ode = common_models.SIR_Birth_Death({'beta':3.6, 'gamma':0.2, 'B':B/N, 'mu':B/N}) - - In [1]: t = numpy.linspace(0, 35*365, 10001) - - In [1]: x0 = [0.065, 123.0*(5.0/30.0)/N, 0.0] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_sir_bd.png - In [1]: ode.plot() - diff --git a/doc/doc_to_sort/common_models/SIS.rst b/doc/doc_to_sort/common_models/SIS.rst deleted file mode 100644 index cb1cbe70..00000000 --- a/doc/doc_to_sort/common_models/SIS.rst +++ /dev/null @@ -1,34 +0,0 @@ -:func:`.SIS` -============ - -A standard SIS model without the total population :math:`N`. We assume here that :math:`S + I = N` so we can always normalize to 1. Evidently, the state :math:`S` is not required for understanding the model because it is a deterministic function of state :math:`I`. - -.. math:: - - \frac{dS}{dt} &= -\beta S I + \gamma I \\ - \frac{dI}{dt} &= \beta S I - \gamma I. - -An example would be - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import matplotlib.pyplot as plt - - In [1]: import numpy - - In [1]: ode = common_models.SIS({'beta':0.5,'gamma':0.2}) - - In [1]: t = numpy.linspace(0, 20, 101) - - In [1]: x0 = [1.0, 0.1] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_sis.png - In [1]: ode.plot() - - In [1]: plt.close() \ No newline at end of file diff --git a/doc/doc_to_sort/common_models/SIS_Periodic.rst b/doc/doc_to_sort/common_models/SIS_Periodic.rst deleted file mode 100644 index 513fbe73..00000000 --- a/doc/doc_to_sort/common_models/SIS_Periodic.rst +++ /dev/null @@ -1,33 +0,0 @@ -:func:`.SIS_Periodic` -===================== - -Now we look at an extension of the SIS model by incorporating periodic contact rate. Note how our equation is defined by a single ode for state **I**. - -.. math:: - - \frac{dI}{dt} = (\beta(t)N - \alpha) I - \beta(t)I^{2} - -where :math:`\beta(t) = 2 - 1.8 \cos(5t)`. As the name suggests, it achieves a (stable) periodic solution. Note how the plots have two sub-graphs, where :math:`\tau` is in fact our time component which we have taken out of the original equation when converting it to a automonous system. - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import matplotlib.pyplot as plt - - In [1]: import numpy - - In [1]: ode = common_models.SIS_Periodic({'alpha':1.0}) - - In [1]: t = numpy.linspace(0, 10, 101) - - In [1]: x0 = [0.1,0.] - - In [1]: ode.initial_values = (x0, t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_sis_periodic.png - In [1]: ode.plot() - - In [1]: plt.close() \ No newline at end of file diff --git a/doc/doc_to_sort/common_models/vanDelPol.rst b/doc/doc_to_sort/common_models/vanDelPol.rst deleted file mode 100644 index 0934b43c..00000000 --- a/doc/doc_to_sort/common_models/vanDelPol.rst +++ /dev/null @@ -1,78 +0,0 @@ -:func:`.vanDelPol` -================== - -The van Del Pol oscillator [vanderpol1926]_ - -.. math:: - - \frac{dx}{dt} &= \sigma (y-x) \\ - \frac{dy}{dt} &= x (\rho - z) - y \\ - \frac{dz}{dt} &= xy - \beta z - -A classic example is - -.. ipython:: - - In [1]: from pygom import common_models - - In [1]: import numpy - - In [1]: import matplotlib.pyplot as plt - - In [1]: t = numpy.linspace(0, 20, 1000) - - In [1]: ode = common_models.vanDelPol({'mu':1.0}) - - In [1]: ode.initial_values = ([2.0, 0.0], t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - @savefig common_models_vanDelPol.png - In [1]: ode.plot() - - In [1]: plt.close() - - In [1]: f = plt.figure() - - In [1]: plt.plot(solution[:,0], solution[:,1]); - - @savefig common_models_vanDelPol_yprime_y_1.png - In [1]: plt.show() - - In [1]: plt.close() - -When we change the value, as per `Wolfram `_ - -.. ipython:: - - In [1]: t = numpy.linspace(0, 100, 1000) - - In [1]: ode.parameters = {'mu':1.0} - - In [1]: ode.initial_values = ([0.0, 0.2], t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - In [1]: f = plt.figure() - - In [1]: plt.plot(solution[:,0],solution[:,1]); - - @savefig common_models_vanDelPol_yprime_y_2.png - In [1]: plt.show() - - In [1]: plt.close() - - In [1]: ode.parameters = {'mu':0.2} - - In [1]: ode.initial_values = ([0.0, 0.2], t[0]) - - In [1]: solution = ode.integrate(t[1::]) - - In [1]: f = plt.figure() - - In [1]: plt.plot(solution[:,0], solution[:,1]); - - @savefig common_models_vanDelPol_yprime_y_3.png - In [1]: plt.show() - - In [1]: plt.close() diff --git a/doc/doc_to_sort/epi.rst b/doc/doc_to_sort/epi.rst deleted file mode 100644 index 757c0db5..00000000 --- a/doc/doc_to_sort/epi.rst +++ /dev/null @@ -1,54 +0,0 @@ -.. _epi: - -************************ -Simple Epidemic Analysis -************************ - -A common application of ordinary differential equations is in the field of epidemiology modeling. More concretely, compartmental models that is used to describe disease progression. We demonstrate some of the simple algebraic analysis one may wish to take when given a compartment model. Our use one of the simplest model, an SIR model with birth and death processes, which is an extension of the one in :ref:`sir`. First, we initialize the model below. - -.. ipython:: - - In [1]: from pygom import common_models - - In [2]: ode = common_models.SIR_Birth_Death() - - In [3]: print(ode.get_ode_eqn()) - - -Obtaining the R0 -================ - -The reproduction number, also known as the :math:`R_{0}`, is the single most powerful piece and reduced piece of information available from a compartmental model. In a nutshell, it provides a single number - if the parameters are known - which can the intuitive interpretation where :math:`R_{0} = 1` defines the tipping point of an outbreak. A :math:`R_{0}` value of more than one signifies an potential outbreak where less than one indicates that the disease will stop spreading naturally. - -To obtain the :math:`R_{0}`, we simply have to tell the function which states represent the *disease state*, which in this case is the state **I**. - -.. ipython:: - - In [1]: from pygom.model.epi_analysis import * - - In [2]: print(R0(ode, 'I')) - -Algebraic R0 -============ - -We may also wish to get the :math:`R_{0}` in pure algebraic term. This can be achieved by the following few lines. Note that the result below is slightly different from the one above. The difference is due to the internal working of the functions, where :func:`getR0` computes the disease-free equilibrium value for the states and substitute them back into the equation. - -.. ipython:: - - In [1]: F, V = disease_progression_matrices(ode, 'I') - - In [2]: e = R0_from_matrix(F, V) - - In [3]: print(e) - - -To replicate the output before, we have to find the values where the disease-free equilibrium will be achieved. Substitution can then be performed to retrieve :math:`R_{0}` in pure parameters. - -.. ipython:: - - In [1]: dfe = DFE(ode, ['I']) - - In [2]: print(dfe) - - In [3]: print(e[0].subs(dfe)) - diff --git a/doc/doc_to_sort/epijson.rst b/doc/doc_to_sort/epijson.rst deleted file mode 100644 index e1ce9cf3..00000000 --- a/doc/doc_to_sort/epijson.rst +++ /dev/null @@ -1,42 +0,0 @@ -.. _epijson: - -****************************** -Reading and using EpiJSON data -****************************** - -Epidemiology data is complicated due to the many different stages a patient can go through and whether a modeling technique is applicable depends heavily on the recording of data. EpiJSON is a framework whih tries to captures all the information [Finnie2016]_, in a JSON format as the name suggests. - -This package provides the functionality to process EpiJSON data. Due to the nature of this package, modeling of ode, it processes the data file with this in mind. The output is therefore in the cumulative form as default, shown below, in a :class:`pandas.DataFrame` format. The input can be in a string format, a file or already a :class:`dict`. - -.. ipython:: - - In [1]: from pygom.loss.read_epijson import epijson_to_data_frame - - In [2]: import pkgutil - - In [3]: data = pkgutil.get_data('pygom', 'data/eg1.json') - - In [3]: df = epijson_to_data_frame(data) - - In [4]: print(df) - -Given that the aim of loading the data is usually for model fitting, we allow EpiJSON as input directly to the loss class :class:`pygom.loss.EpijsonLoss` which uses the Poisson loss under the hood. - -.. ipython:: - - In [1]: from pygom.model import common_models - - In [2]: from pygom.loss.epijson_loss import EpijsonLoss - - In [3]: ode = common_models.SIR([0.5, 0.3]) - - In [4]: obj = EpijsonLoss([0.005, 0.03], ode, data, 'Death', 'R', [300, 2, 0]) - - In [5]: print(obj.cost()) - - In [6]: print(obj._df) - -Given an initialized object, all the operations are inherited from :class:`pygom.loss.BaseLoss`. We demonstrated above how to calculate the cost and the rest will not be shown for brevity. The data frame is stored inside of the loss object and can be retrieved for inspection at any time point. - -Rather unfortunately, initial values for the states is still required, but the time is not. When the time is not supplied, then the first time point in the data will be treated as :math:`t0`. The input `Death` indicate which column of the data is used and :math:`R` the corresponding state the data belongs to. - diff --git a/doc/doc_to_sort/estimate1.rst b/doc/doc_to_sort/estimate1.rst deleted file mode 100644 index 4382142c..00000000 --- a/doc/doc_to_sort/estimate1.rst +++ /dev/null @@ -1,115 +0,0 @@ -.. _estimate1: - -******************************* -Example: Parameter Estimation 1 -******************************* - -Estimation under square loss -============================ - -To ease the estimation process when given data, a separate module :mod:`ode_loss` has been constructed for observations coming from a single state. We demonstrate how to do it via two examples, first, a standard SIR model, then the Legrand SEIHFR model from [Legrand2007]_ used for Ebola in :ref:`estimate2`. - -SIR Model ---------- - -We set up an SIR model as seen previously in :ref:`sir`. - -.. ipython:: - - In [176]: from pygom import SquareLoss, common_models - - In [179]: import numpy - - In [180]: import scipy.integrate - - In [184]: import matplotlib.pyplot - - In [185]: # Again, standard SIR model with 2 parameter. See the first script! - - In [191]: # define the parameters - - In [192]: paramEval = [('beta',0.5), ('gamma',1.0/3.0)] - - In [189]: # initialize the model - - In [190]: ode = common_models.SIR(paramEval) - - -and we assume that we have perfect information about the :math:`R` compartment. - -.. ipython:: - - In [196]: x0 = [1, 1.27e-6, 0] - - In [197]: # Time, including the initial time t0 at t=0 - - In [198]: t = numpy.linspace(0, 150, 1000) - - In [200]: # Standard. Find the solution. - - In [201]: solution = scipy.integrate.odeint(ode.ode, x0, t) - - In [202]: y = solution[:,1:3].copy() - -Initialize the class with some initial guess - -.. ipython:: - - In [209]: # our initial guess - - In [210]: theta = [0.2, 0.2] - - In [176]: objSIR = SquareLoss(theta, ode, x0, t[0], t[1::], y[1::,:], ['I','R']) - -Note that we need to provide the initial values, :math:`x_{0}` and :math:`t_{0}` differently to the observations :math:`y` and the corresponding time :math:`t`. Additionally, the state which the observation lies needs to be specified. Either a single state, or multiple states are allowed, as seen above. - -Difference in gradient ----------------------- - -We have provided two different ways of obtaining the gradient, these are explained in :ref:`gradient` in a bit more detail. First, lets see how similar the output of the two methods are - -.. ipython:: - - In [22]: objSIR.sensitivity() - - In [25]: objSIR.adjoint() - -and the time required to obtain the gradient for the SIR model under :math:`\theta = (0.2,0.2)`, previously entered. - -.. ipython:: - - In [22]: %timeit objSIR.sensitivity() - - In [25]: %timeit objSIR.adjoint() - -Obviously, the amount of time taken for both method is dependent on the number of observations as well as the number of states. The effect on the adjoint method as the number of observations differs can be quite evident. This is because the adjoint method is under a discretization which loops in Python where as the forward sensitivity equations are solved simply via an integration. As the number of observation gets larger, the affect of the Python loop becomes more obvious. - -Difference in gradient is larger when there are less observations. This is because the adjoint method use interpolations on the output of the ode between each consecutive time points. Given solution over the same length of time, fewer discretization naturally leads to a less accurate interpolation. Note that the interpolation is currently performed using univaraite spline, due to the limitation of python packages. Ideally, one would prefer to use an (adaptive) Hermite or Chebyshev interpolation. Note how we ran the two gradient functions once before timing it, that is because we only find the properties (Jacobian, gradient) of the ode during runtime. - -Optimized result ----------------- - -Then standard optimization procedures with some suitable initial guess should yield the correct result. It is important to set the boundaries for compartmental models as we know that all the parameters are strictly positive. We put a less restrictive inequality here for demonstration purpose. - -.. ipython:: - - In [211]: # what we think the bounds are - - In [212]: boxBounds = [(0.0,2.0),(0.0,2.0)] - -Then using the optimization routines in :mod:`scipy.optimize`, for example, the *SLSQP* method with the gradient obtained by forward sensitivity. - -.. ipython:: - - In [208]: from scipy.optimize import minimize - - In [213]: res = minimize(fun=objSIR.cost, - .....: jac=objSIR.sensitivity, - .....: x0=theta, - .....: bounds=boxBounds, - .....: method='SLSQP') - - In [214]: print(res) - -Other methods available in :func:`scipy.optimize.minimize` can also be used, such as the *L-BFGS-B* and *TNC*. We can also use methods that accepts the exact Hessian such as *trust-ncg* but that should not be necessary most of the time. - diff --git a/doc/doc_to_sort/estimate2.rst b/doc/doc_to_sort/estimate2.rst deleted file mode 100644 index 10d27b23..00000000 --- a/doc/doc_to_sort/estimate2.rst +++ /dev/null @@ -1,285 +0,0 @@ -.. _estimate2: - -******************************* -Example: Parameter Estimation 2 -******************************* - -Continuing from the :ref:`estimate1`, we show why estimating the parameters for ode's are hard. This is especially true if there is a lack of data or when there are too much flexibility in the model. Note that for reproducibility purposes, only deterministic models are used here and a fixed seed whenever a stochastic algorithm is needed. - -Standard SEIR model -=================== - -We demonstrate the estimation on the recent Ebola outbreak in West Africa. We use the number of deaths in Guinea and its corresponding time the data was recorded. These data are publicly available and they can be obtained easily on the internet such as https://github.com/cmrivers/ebola. It is stated out here for simplicity. - -.. ipython:: - - In [34]: # the number of deaths and cases in Guinea - - In [35]: yDeath = [29.0, 59.0, 60.0, 62.0, 66.0, 70.0, 70.0, 80.0, 83.0, 86.0, 95.0, 101.0, 106.0, 108.0, - ....: 122.0, 129.0, 136.0, 141.0, 143.0, 149.0, 155.0, 157.0, 158.0, 157.0, 171.0, 174.0, - ....: 186.0, 193.0, 208.0, 215.0, 226.0, 264.0, 267.0, 270.0, 303.0, 305.0, 307.0, 309.0, - ....: 304.0, 310.0, 310.0, 314.0, 319.0, 339.0, 346.0, 358.0, 363.0, 367.0, 373.0, 377.0, - ....: 380.0, 394.0, 396.0, 406.0, 430.0, 494.0, 517.0, 557.0, 568.0, 595.0, 601.0, 632.0, - ....: 635.0, 648.0, 710.0, 739.0, 768.0, 778.0, 843.0, 862.0, 904.0, 926.0, 997.0] - - In [35]: yCase = [49.0, 86.0, 86.0, 86.0, 103.0, 112.0, 112.0, 122.0, 127.0, 143.0, 151.0, 158.0, - ....: 159.0, 168.0, 197.0, 203.0, 208.0, 218.0, 224.0, 226.0, 231.0, 235.0, 236.0, - ....: 233.0, 248.0, 258.0, 281.0, 291.0, 328.0, 344.0, 351.0, 398.0, 390.0, 390.0, - ....: 413.0, 412.0, 408.0, 409.0, 406.0, 411.0, 410.0, 415.0, 427.0, 460.0, 472.0, - ....: 485.0, 495.0, 495.0, 506.0, 510.0, 519.0, 543.0, 579.0, 607.0, 648.0, 771.0, - ....: 812.0, 861.0, 899.0, 936.0, 942.0, 1008.0, 1022.0, 1074.0, 1157.0, 1199.0, 1298.0, - ....: 1350.0, 1472.0, 1519.0, 1540.0, 1553.0, 1906.0] - - In [36]: # the corresponding time - - In [37]: t = [0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 13.0, 16.0, 18.0, 20.0, 23.0, 25.0, 26.0, 29.0, - ....: 32.0, 35.0, 40.0, 42.0, 44.0, 46.0, 49.0, 51.0, 62.0, 66.0, 67.0, 71.0, 73.0, 80.0, 86.0, 88.0, - ....: 90.0, 100.0, 102.0, 106.0, 108.0, 112.0, 114.0, 117.0, 120.0, 123.0, 126.0, 129.0, 132.0, 135.0, - ....: 137.0, 140.0, 142.0, 144.0, 147.0, 149.0, 151.0, 157.0, 162.0, 167.0, 169.0, 172.0, 175.0, 176.0, - ....: 181.0, 183.0, 185.0, 190.0, 193.0, 197.0, 199.0, 204.0, 206.0, 211.0, 213.0, 218.0] - -Simple estimation ------------------ - -First ,we are going to fit a standard **SEIR** model to the data. Details of the models can be found in :mod:`common_models` Defining the model as usual with some random guess on what the parameters might be, here, we choose the values to be the mid point of our feasible region (defined by our box constraints later) - -.. ipython:: - - In [1]: from pygom import SquareLoss, common_models - - In [1]: import numpy, scipy.optimize - - In [1]: import matplotlib.pyplot as plt - - In [1]: theta = numpy.array([5.0, 5.0, 5.0]) - - In [2]: ode = common_models.SEIR(theta) - - In [3]: population = 1175e4 - - In [4]: y = numpy.reshape(numpy.append(numpy.array(yCase), numpy.array(yDeath)), (len(yCase),2), 'F')/population - - In [5]: x0 = [1., 0., 49.0/population, 29.0/population] - - In [6]: t0 = t[0] - - In [7]: objLegrand = SquareLoss(theta, ode, x0, t0, t[1::], y[1::,:], ['I','R'], numpy.sqrt([population]*2)) - -Then we optimize, first, assuming that the initial conditions are accurate. Some relatively large bounds are used for this particular problem. - -.. ipython:: - - In [8]: boxBounds = [ (0.0,10.0), (0.0,10.0), (0.0,10.0) ] - - In [9]: res = scipy.optimize.minimize(fun=objLegrand.cost, - ...: jac=objLegrand.sensitivity, - ...: x0=theta, - ...: bounds=boxBounds, - ...: method='l-bfgs-b') - - In [10]: print(res) - - In [11]: f = plt.figure() - - @savefig ebola_seir_straight.png - In [12]: objLegrand.plot() - - In [13]: plt.close() - -We can see from our visual confirmation that the estimated parameters are not exactly ideal. This is confirmed by the information returned from the :func:`scipy.optimize.minimize` routine, and probably caused by the poor starting point. An attempt to find a more suitable value can be done by some form of parameter space exploration. Given that the evaluation of the objective function is not expensive here, we have plenty of options to choose from. To reduce the number of packages required to build this documentation, routines from :mod:`scipy.optimize` remains our preferred option. - -Improved initial guess ----------------------- - -.. ipython:: - - In [8]: resDE = scipy.optimize.differential_evolution(objLegrand.cost, bounds=boxBounds, polish=False, seed=20921391) - - In [9]: print(objLegrand.sensitivity(resDE['x'])) - - In [10]: f = plt.figure() - - @savefig ebola_seir_de.png - In [11]: objLegrand.plot() - - In [12]: plt.close() - -Looking at the output of the estimates (below this paragraph), we can see our inference on Ebola is wrong when compared to the *known* values (from field observation) even though the graphs looks *``reasonable"*. Namely, :math:`\gamma^{-1}` the third element in the vector below, our time from infectious to death, is within the expected range but :math:`\alpha^{-1}` (second element), the incubation period, is a lot higher than expected. - -.. ipython:: - - In [1]: 1/resDE['x'] - -Multimodal surface ------------------- - -A reason for this type of behavior is that we simply lack the information/data to make proper inference. Without data on the state :math:`E`, the parameters :math:`\beta,\alpha` for the two states :math:`I` and :math:`E` are dependent only on observations on :math:`I`. Hence, some other random combination of :math:`\beta,\alpha` that is capable of generating realization close to observations in :math:`I` is feasible. In such cases, the only requirement is that there exist some :math:`\gamma` in the feasible region that can compensate for the ill suited :math:`\beta,\alpha`. For example, we know (obtained elsewhere and not shown here) that there is another set of parameters capable of generating a similar looking curves as before. Note the reversal of magnitude in :math:`\beta` and :math:`\alpha`. - -.. ipython:: - - In [11]: objLegrand.cost([3.26106524e+00, 2.24798702e-04, 1.23660721e-02]) - - In [12]: ## objLegrand.cost([ 0.02701867, 9.00004776, 0.01031861]) # similar graph - - @savefig ebola_seir_prior.png - In [13]: objLegrand.plot() - - In [14]: plt.close() - -With initial values as parameters ---------------------------------- - -Obviously, the assumption that the whole population being susceptible is an overestimate. We now try to estimate the initial conditions of the ode as well. Given previous estimates of the parameters :math:`\hat{\beta}, \hat{\alpha}, \hat{\gamma}` it is appropriate to start our initial guess there. - -Furthermore, given that we now estimate the initial values for all the states, we can use the first time point as our observation. So our time begins at :math:`t = -1` where our observations include the previous initial condition, i.e. 49 and 29 for the number of cases and death at :math:`t = 0` respectively. The following code block demonstrates how we would do that; feel free to try it out yourself to see the much improved result. - -.. ipython:: - :verbatim: - - In [1]: thetaIV = theta.tolist() + x0 - - In [2]: thetaIV[3] -= 1e-8 # to make sure that the initial guess satisfy the constraints - - In [3]: boxBoundsIV = boxBounds + [(0.,1.), (0.,1.), (0.,1.), (0.,1.)] - - In [4]: objLegrand = SquareLoss(theta, ode, x0, -1, t, y, ['I','R'], numpy.sqrt([population]*2)) - - In [5]: resDEIV = scipy.optimize.differential_evolution(objLegrand.costIV, bounds=boxBoundsIV, polish=False, seed=20921391) - - In [6]: print(resDEIV) - - In [7]: f = plt.figure() - - In [8]: objLegrand.plot() - - In [9]: plt.close() - - -Legrand Ebola SEIHFR Model -========================== - -Next, we demonstrate the estimation on a model that is widely used in the recent Ebola outbreak in west Africa. Again, the model has been defined in :mod:`.common_models` already. - -.. ipython:: - - In [1]: ode = common_models.Legrand_Ebola_SEIHFR() - - In [27]: # initial guess from the paper that studied the outbreak in Congo - - In [28]: theta = numpy.array([0.588,0.794,7.653, ### the beta - ....: 10.0,9.6,5.0,2.0, ### the omega - ....: 7.0,0.81,0.80, ### alpha, delta, theta - ....: 100.,1.0]) ### kappa,intervention time - - In [29]: # initial conditions, note that we have a 0.0 at the end because the model is a non-automonous ode which we have converted the time component out - - In [30]: x0 = numpy.array([population, 0.0, 49.0, 0.0, 0.0, 29.0, 0.0])/population - - In [30]: ode.parameters = theta - - In [31]: ode.initial_values = (x0, t[0]) - - In [32]: objLegrand = SquareLoss(theta, ode, x0, t[0], t[1::], y[1::,:], ['I','R'], numpy.sqrt([population]*2)) - -Now, it is important to set additional constraints accurately because a simply box constraint is much larger than the feasible set. Namely, :math:`\omega_{I}, \omega_{D}` are the time taken from onset until end of infectious/death, which has to be bigger than :math:`\omega_{H}`, onset to hospitalization given the nature of the disease. Therefore, we create extra inequality constraints in addition to the box constraints - -.. ipython:: - - In [549]: boxBounds = [ - .....: (0.001, 100.), # \beta_I - .....: (0.001, 100.), # \beta_H - .....: (0.001, 100.), # \beta_F - .....: (0.001, 100.), # \omega_I - .....: (0.001, 100.), # \omega_D - .....: (0.001, 100.), # \omega_H - .....: (0.001, 100.), # \omega_F - .....: (0.001, 100.), # \alpha^{-1} - .....: (0.0001, 1.), # \delta - .....: (0.0001, 1.), # \theta - .....: (0.001, 1000.), # \kappa - .....: (0.,218.) # intervention tine - .....: ] - - In [550]: cons = ({'type': 'ineq', 'fun' : lambda x: numpy.array([x[3]-x[5], x[4]-x[5]])}) - -We can now try to find the optimal values, but because this is a difficult problem that can take a very long time without guarantee on the quality of solution - -.. ipython:: - :okexcept: - :okwarning: - - In [213]: res = scipy.optimize.minimize(fun=objLegrand.cost, - .....: jac=objLegrand.sensitivity, - .....: x0=theta, - .....: constraints=cons, - .....: bounds=boxBounds, - .....: method='SLSQP') - - In [214]: print(res) - - In [215]: f = plt.figure() - - @savefig ebola_legrand_runtime.png - In [216]: objLegrand.plot() - - In [217]: plt.close() - -Evidently, the estimated parameters are very much unrealistic given that a lot of them are near the boundaries. It is also known from other sources that some of the epidemiology properties of Ebola, with incubation period of around 2 weeks and a mortality rate of around 80 percent. - -As the estimate does not appear to provide anything sensible, we also provide a set of values previously obtained (that looks semi-reasonable) here plot the epidemic curve with the observations layered on top - -.. ipython:: - :okexcept: - :okwarning: - - In [1]: theta = numpy.array([3.96915071e-02, 1.72302620e+01, 1.99749990e+01, - ...: 2.67759445e+01, 4.99999990e+01, 5.56122691e+00, - ...: 4.99999990e+01, 8.51599523e+00, 9.99999000e-01, - ...: 1.00000000e-06, 3.85807562e+00, 1.88385318e+00]) - - In [2]: print(objLegrand.cost(theta)) - - In [2]: solution = ode.integrate(t[1::]) - - In [3]: f, axarr = plt.subplots(2,3) - - In [4]: axarr[0,0].plot(t, solution[:,0]); - - In [5]: axarr[0,0].set_title('Susceptible'); - - In [6]: axarr[0,1].plot(t, solution[:,1]); - - In [7]: axarr[0,1].set_title('Exposed'); - - In [8]: axarr[0,2].plot(t, solution[:,2]); - - In [9]: axarr[0,2].plot(t, y[:,0], 'r'); - - In [10]: axarr[0,2].set_title('Infectious'); - - In [11]: axarr[1,0].plot(t, solution[:,3]); - - In [12]: axarr[1,0].set_title('Hospitalised'); - - In [13]: axarr[1,1].plot(t, solution[:,4]); - - In [14]: axarr[1,1].set_title('Awaiting Burial'); - - In [15]: axarr[1,2].plot(t, solution[:,5]); - - In [16]: axarr[1,2].plot(t, y[:,1], 'r'); - - In [17]: axarr[1,2].set_title('Removed'); - - In [18]: f.text(0.5, 0.04, 'Days from outbreak', ha='center'); - - In [19]: f.text(0.01, 0.5, 'Population', va='center', rotation='vertical'); - - In [20]: f.tight_layout(); - - @savefig ebola_seihfr_straight_prior.png - In [21]: plt.show() - - In [22]: plt.close() - - diff --git a/doc/doc_to_sort/faq.rst b/doc/doc_to_sort/faq.rst deleted file mode 100644 index a57c2675..00000000 --- a/doc/doc_to_sort/faq.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. _faq: - -************************ -Frequent asked questions -************************ - -Code runs slowly -================ - -This is because the package is not optimized for speed. Although the some of the main functions are lambdified using :mod:`sympy` or compiled against :mod:`cython` when available, there are many more optimization that can be done. One example is the lines: - -.. python: - - J = self.Jacobian(state,t) - G = self.Grad(state,t) - A = numpy.dot(J,S) + G - -in :func:`.DeterministicOde.evalSensitivity`. The first two operations can be inlined into the third and the third line itself can be rewritten as: - -.. python: - - G += numpy.dot(J,S) - -and save the explicit copy operation by :mod:`numpy` when making A. If desired, we could have also made used of the :mod:`numexpr` package that provides further speed up on elementwise operations in place of numpy. - -Why not compile the numeric computation form sympy against Theano -================================================================= - -Setup of the package has been simplified as much as possible. If you look closely enough, you will realize that the current code generation only uses :mod:`cython` and not :mod:`f2py`. This is because we are not prepared to do all the system checks, i.e. does a fortran compiler exist, is gcc installed, was python built as a shared library etc. We are very much aware of the benefit, especially considering the possibility of GPU computation in :mod:`theano`. - -Why not use mpmath library throughout? -====================================== - -This is because we have a fair number of operations that depends on :mod:`scipy`. Obviously, we can solve ode using :mod:`mpmath` and do standard linear algebra. Unfortunately, optimization and statistics packages and routine are mostly based on :mod:`numpy`. - -Computing the gradient using :class:`.SquareLoss` is slow -========================================================= - -It will always be slow on the first operation. This is due to the design where the initialization of the class is fast and only find derivative information/compile function during runtime. After the first calculation, things should be significantly faster. - -**Why some of my code is not a fortran object?** - -When we detec either a :math:`\exp` or a :math:`\log` in the equations, we automatically force the compile to use mpmath to ensure that we obtain the highest precision. To turn this on/off will be considered as a feature in the future. - -Can you not convert a non-autonumous system to an autonomous system for me automatically -======================================================================================== - -Although we can do that, it is not, and will not be implemented. This is to ensure that the end user such as yourself are fully aware of the equations being defined. - -Getting the sensitivities from :class:`.SquareLoss` did not get a speed up when I used a restricted set of parameters -===================================================================================================================== - -This is because we currently evaluate the full set of sensitivities before extracting them out. Speeding this up for a restrictive set is being considered. A main reason that stopped us from implementing is that we find the symbolic gradient of the ode before compiling it. Which means that one function call to the compiled file will return the full set of sensitivities and we would only be extracting the appropriate elements from the matrix. This only amounts to a small speed up. The best method would be to compile only the necessary elements of the gradient matrix, but this would require much more work both within the code, and later on when variables are being added/deleted as all these compilation are perfromed in runtime. - -Why do not have the option to obtain gradient via complex differencing -====================================================================== - -It is currently not implemented. Feature under consideration. - - diff --git a/doc/doc_to_sort/fh.rst b/doc/doc_to_sort/fh.rst deleted file mode 100644 index 065f3285..00000000 --- a/doc/doc_to_sort/fh.rst +++ /dev/null @@ -1,133 +0,0 @@ -.. _fh: - -****************** -Example: Fitz Hugh -****************** - -Defining the model -================== - -We are going to investigate another classic model here, the FitzHugh-Nagumo, or simply FitzHugh here. The model has already been defined in :mod:`common_models` so we can load it easily - -.. ipython:: - - In [1]: from pygom import SquareLoss, common_models - - In [2]: import numpy - - In [3]: import scipy.integrate, scipy.optimize - - In [4]: import math,time,copy - - In [5]: import matplotlib.pyplot as plt - - In [1]: x0 = [-1.0, 1.0] - - In [2]: t0 = 0 - - In [3]: # params - - In [4]: paramEval = [('a',0.2), ('b',0.2), ('c',3.0)] - - In [5]: ode = common_models.FitzHugh(paramEval) - - In [5]: ode.initial_values = (x0, t0) - -Define a set of time points and lets see how the two states :math:`V` and :math:`R` are suppose to behave. - -.. ipython:: - - In [6]: t = numpy.linspace(1, 20, 30).astype('float64') - - In [7]: solution = ode.integrate(t) - - @savefig fh_plot.png - In [8]: ode.plot() - -Estimate the parameters -======================= - -Obtaining the correct parameters for the FitzHugh model is well known to be difficult, this is because the surface is multimodal. Although this has been shown many times in the literature, so we will omit the details. Regardless, we give it a go with some initial guess. with some luck, we will be able to recover the original parameters. First, we try it out with only one target state - -.. ipython:: - - In [26]: theta = [0.5, 0.5, 0.5] - - In [27]: objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,1], 'R') - - In [28]: boxBounds = [ - ....: (0.0,5.0), - ....: (0.0,5.0), - ....: (0.0,5.0) - ....: ] - - In [29]: res = scipy.optimize.minimize(fun=objFH.cost, - ....: jac=objFH.sensitivity, - ....: x0=theta, - ....: bounds=boxBounds, - ....: method='L-BFGS-B') - - In [30]: print(res) - -Then we try the same again but with both state as our target. Now we won't look at the iterations because they are pretty pointless. - -.. ipython:: - - In [30]: objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,:], ['V','R']) - - In [31]: res = scipy.optimize.minimize(fun=objFH.cost, - ....: jac=objFH.sensitivity, - ....: x0=theta, - ....: bounds=boxBounds, - ....: method='L-BFGS-B') - - In [32]: print(res) - -Note how the estimates are the same, unlike other models. - -Estimate initial value -====================== - -We can further assume that we have no idea about the initial values for :math:`V` and :math:`R` as well. We also provide guesstimate to set off the optimization. The input vector :math:`\theta` must have the parameters first, then the initial values, along with the corresponding bounds. - -First, only a single target state, i.e. we only have observations for one of states which is :math:`R` in this case - -.. ipython:: - - In [35]: objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,1], 'R') - - In [35]: boxBounds = [ - ....: (0.0,5.0), - ....: (0.0,5.0), - ....: (0.0,5.0), - ....: (None,None), - ....: (None,None) - ....: ] - - In [36]: res = scipy.optimize.minimize(fun=objFH.costIV, - ....: jac=objFH.sensitivityIV, - ....: x0=theta + [-0.5,0.5], - ....: bounds=boxBounds, - ....: method='L-BFGS-B') - - In [37]: print(res) - -then both state as target at the same time - -.. ipython:: - - In [38]: objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,:], ['V','R']) - - In [38]: res = scipy.optimize.minimize(fun=objFH.costIV, - ....: jac=objFH.sensitivityIV, - ....: x0=theta + [-0.5, 0.5], - ....: bounds=boxBounds, - ....: method='L-BFGS-B') - - In [39]: print(res) - -See the difference between the two estimate with the latter, both state were used, yielding superior estimates. Note that only the forward sensitivity method is implemented when estimating the initial value, and it is assumed that the starting condition for all the states are unknown. - -The choice of algorithm here is the **L-BFGS-B** which is a better choice because the parameter space of the FitzHugh is rough (i.e. large second derivative) as well as being multimodal. This means that the Hessian is not guaranteed to be positive definite and approximation using :math:`J^{\top}J` is poor, with :math:`J` being the Jacobian of the objective function. - - diff --git a/doc/doc_to_sort/gradient.rst b/doc/doc_to_sort/gradient.rst deleted file mode 100644 index 121bb6c3..00000000 --- a/doc/doc_to_sort/gradient.rst +++ /dev/null @@ -1,302 +0,0 @@ -.. _gradient: - -************************************* -Gradient estimation under square loss -************************************* - -Assuming that we have a set of :math:`N` observations :math:`y_{i}` at specific time points :math:`t_{i}`, :math:`i = 1,\ldots,N`, we may wish to test out a set of ode to see whether it fits to the data. The most natural way to test such *fit* is to minimize the sum of squares between our observations :math:`y` and see whether the resulting solution of the ode and the estimationed parameters makes sense. - -We assume that this estimation process will be tackled through a non-linear optimization point of view. However, it should be noted that such estimates can also be performed via MCMC or from a global optimization perspective. A key element in non-linear optimization is the gradient, which is the focus of this page. - -Multiple ways of obtaining the gradient have been implemented. All of them serve a certain purpose and may not be a viable/appropriate options depending on the type of ode. More generally, let :math:`d,p` be the number of states and paramters respectively. Then finite difference methods have a run order of :math:`O(p+1)` of the original ode, forward sensitivity require an integration of an ode of size :math:`(d+1)p` rather than :math:`d`. The adjoint method require two run of size :math:`d` in principle, but actual run time is dependent on the number of observations. - -For the details of the classes and methods, please refer to :ref:`mod`. - -Notation -======== - -We introduce the notations that will be used in the rest of the page, some of which may be slightly unconventional but necessary due to the complexity of the problem. Let :math:`x \in \mathbb{R}^{d}` and :math:`\theta \in \mathbb{R}^{p}` be the states and parameters respectively. The term *state* or *simulation* are used interchangeably, even though strictly speaking a state is :math:`x` whereas :math:`x(t)` is the simulation. An ode is defined as - -.. math:: - - f(x,\theta) = \dot{x} = \frac{\partial x}{\partial t} - -and usually comes with a set of initial conditions :math:`(x_0,t_0)` where :math:`t_0 \le t_{i} \forall i`. Let :math:`g(x,\theta)` be a function that maps the set of states to the observations, :math:`g : \mathbb{R}^{d} \rightarrow \mathbb{R}^{m}`. For compartmental problems, which is our focus, :math:`\nabla_{\theta}g(x,\theta)` is usually zero and :math:`\nabla_{x}g(x,\theta)` is an identity function for some or all of the states :math:`x`. Denote :math:`l(x_{0},\theta,x)` as our cost function :math:`l : \mathbb{R}^{m} \rightarrow \mathbb{R}` and :math:`L(x_{0},\theta,x)` be the sum of :math:`l(\cdot)`. Both :math:`x` and :math:`x_{0}` are usually dropped for simplicity. We will be dealing exclusively with square loss here, which means that - -.. math:: - - L(\theta) = \sum_{i=1}^{N} \left\| y_{i} - g(x(t_{i})) \right\|^{2} = \mathbf{e}^{\top} \mathbf{e} - -where :math:`\mathbf{e}` is the residual vector, with elements - -.. math:: - - e_{i} = y_{i} - x(t_{i}). - - -Model setup -=========== - -Again, we demonstrate the functionalities of our classes using an SIR model. - -.. ipython:: - - In [1]: from pygom import SquareLoss, common_models - - In [2]: import copy,time,numpy - - In [2]: ode = common_models.SIR() - - In [3]: paramEval = [('beta',0.5), ('gamma',1.0/3.0) ] - - In [7]: # the initial state, normalized to zero one - - In [8]: x0 = [1., 1.27e-6, 0.] - - In [5]: # initial time - - In [6]: t0 = 0 - - In [5]: ode.parameters = paramEval - - In [6]: ode.initial_values = (x0, t0) - - In [9]: # set the time sequence that we would like to observe - - In [10]: t = numpy.linspace(1, 150, 100) - - In [11]: numStep = len(t) - - In [11]: solution = ode.integrate(t) - - In [12]: y = solution[1::,2].copy() - - In [13]: y += numpy.random.normal(0, 0.1, y.shape) - -Now we have set up the model along with some observations, obtaining the gradient only requires the end user to put the appropriate information it into the class :class:`SquareLoss`. Given the initial guess :math:`\theta` - -.. ipython:: - - In [210]: theta = [0.2, 0.2] - -We initialize the :class:`SquareLoss` simply as - -.. ipython:: - - In [20]: objSIR = SquareLoss(theta, ode, x0, t0, t, y, 'R') - -where the we also have to specify the state our observations are from. Now, we demonstrate the different methods in obtaining the gradient and mathematics behind it. - -Forward sensitivity -=================== - -The forward sensitivity equations are derived by differentiating the states implicitly, which yields - -.. math:: - - \frac{d\dot{x}}{d\theta} = \frac{\partial f}{\partial x}\frac{dx}{d\theta} + \frac{\partial f}{\partial \theta}. - -So finding the sensitivies :math:`\frac{dx}{d\theta}` simply require another integration of a :math:`p` coupled ode of :math:`d` dimension, each with the same Jacobian as the original ode. This integration is performed along with the original ode because of possible non-linearity. - -A direct call to the method :meth:`sensitivity ` computed the gradient - -.. ipython:: - - In [33]: gradSens = objSIR.sensitivity() - -whereas :meth:`.jac` will allow the end user to obtain the Jacobian (of the objective function) and the residuals, the information required to get the gradient as we see next. - -.. ipython:: - - In [33]: objJac, output = objSIR.jac(full_output=True) - - -Gradient -======== - -Just the sensitivities alone are not enough to obtain the gradient, but we are :math:`90\%` there. Differentiating the loss function - -.. math:: - - \frac{dL}{d\theta} &= \nabla_{\theta} \sum_{i=1}^{N}\frac{dl}{dg} \\ - &= \sum_{i=1}^{N} \frac{\partial l}{\partial x}\frac{dx}{d\theta} + \frac{\partial l}{\partial \theta} \\ - &= \sum_{i=1}^{N} \frac{\partial l}{\partial g}\frac{\partial g}{\partial x}\frac{dx}{d\theta} + \frac{\partial l}{\partial g}\frac{\partial g}{\partial \theta} - -via chain rule. When :math:`\frac{\partial g}{\partial \theta} = 0`, the total gradient simplifies to - -.. math:: - - \frac{dL}{d\theta} = \sum_{i=1}^{N} \frac{\partial l}{\partial g}\frac{\partial g}{\partial x}\frac{dx}{d\theta} - -Obviously, the time indicies are dropped above but all the terms above are evaluated only at the observed time points. More concretely, this means that - -.. math:: - - \frac{\partial l(x(j),\theta)}{\partial g} = \left\{ \begin{array}{ll} -2(y_{i} - x(j)) & , \; j = t_{i} \\ 0 & \; \text{otherwise} \end{array} \right. - -When :math:`g(\cdot)` is an identity function (which is assumed to be the case in :class:`SquareLoss`) - -.. math:: - - \frac{\partial g(x(t_{i}),\theta)}{\partial x} = I_{d} - -then the gradient simplifies even further as it is simply - -.. math:: - - \frac{dL}{d\theta} = -2\mathbf{e}^{\top}\mathbf{S} - -where :math:`\mathbf{e}` is the vector of residuals and :math:`\mathbf{S} = \left[\mathbf{s}_{1},\mathbf{s}_{2},\ldots,\mathbf{s}_{n}\right]` with elements - -.. math:: - - \mathbf{s}_{i} = \frac{dx}{d\theta}(t_{i}), - -the solution of the forward sensitivies at time :math:`t_{i}`, obtained from solving the coupled ode as mentioned previously. - -Jacobian -======== - -Now note how the gradient simplifies to :math:`-2\mathbf{e}^{\top}\mathbf{S}`. Recall that a standard result in non-linear programming states that the gradient of a sum of sqaures objective function :math:`L(\theta,y,x)` is - -.. math:: - - \nabla_{\theta} L(\theta,y,x) = -2(\mathbf{J}^{T} \left[\mathbf{y} - \mathbf{f}(x,\boldsymbol{\theta}) \right] )^{\top} - -with :math:`f(x,\theta)` our non-linear function and :math:`J` our Jacobian with elements - -.. math:: - - J_{i} = \frac{\partial f(x_{i},\boldsymbol{\theta})}{\partial \boldsymbol{\theta}}. - -This is exactly what we have seen previously, substituting in reveals that :math:`J = \mathbf{S}`. Hence, the Jacobian is (a necessary)by product when we wish to obtain the gradient. In fact, this is exactly how we proceed in :func:`sensitivity ` where it makes an internal call to :func:`jac ` to obtain the Jacobian first. This allows the end user to have more options when choosing which type of algorithms to use, i.e. Gauss-Newton or Levenberg-Marquardt. - -To check that the output is in fact the same - -.. ipython:: - - In [1]: objJac.transpose().dot(-2*output['resid']) - gradSens - -Adjoint -======= - -When the number of parameters increases, the number of sensitivies also increases. The time required scales directly with the number of parameters. We describe another method which does not depend on the number of parameters, but rather, the number of states and observations. - -The full derivations will not be shown here, but we aim to provide enough information to work out the steps performed in the our code. Let write our optimization problem as - -.. math:: - - min_{\theta} \quad & \int_{t_{0}}^{T} l(x_{0},\theta,x(t)) dt \\ - s.t. \quad & \dot{x} = f(x,\theta) - -which is identical to the original problem but in a continuous setting. Now write the constrained problem in the Lagrangian form - -.. math:: - - min_{\theta} \; L(\theta) + \int_{t_{0}}^{T} \lambda^{\top}(\dot{x} - f(x,\theta)) - -with Lagrangian multiplier :math:`\lambda \ge 0`. After some algebraic manipulation, it can be shown that the total derivative of the Lagrangian function is - -.. math:: - - \frac{dL}{d\theta} = \int_{t_{0}}^{T} \left(\frac{\partial l}{\partial \theta} - \lambda^{\top}\frac{\partial f}{\partial \theta} \right) dt. - -Using previously defined loss functions (the identity), the first term is zero and evaluating :math:`\frac{\partial f}{\partial \theta}` is trivial. What remains is the calculation of :math:`\lambda(t)` for :math:`t \in \left[t_{0},T\right]`. - -Although this still seem to be ill-posed problem when Looking at the Lagrangian function, one can actually obtain the *adjoint equation*, after certain assumptions and - -.. math:: - - \frac{d\lambda^{\top}}{dt} = \frac{\partial l}{\partial x} - \lambda^{\top}\frac{\partial f}{\partial \theta}. - -which is again an integration. An unfortunate situation arise here for non-linear systems because we use the minus Jacobian in the adjoint equation. So if the eigenvalues of the Jacobian indicate that our original ode is stable, such as -1, the minus eigenvalues (now 1) implies that the adjoint equation is not stable. Therefore, one must integrate backward in time to solve the adjoint equation and it cannot be solved simultaneously as the ode, unlike the forward sensitivity equations. - -Given a non-linearity ode, we must store information about the states between :math:`t_{0}` and :math:`T` in order to perform the integration. There are two options, both require storing many evaluated :math:`x(j)` within the interval :math:`\left[t_{0},T\right]`. Unfortunately, only one is available; interpolation over all states and integrate using the interpolating functions. The alternative of using observed :math:`x(j)'s` at fixed points is not competitive because we are unable to use fortran routines for the integration - -The method of choice here to perform the adjoint calcuation is to run a forward integration, then perform an interpolation using splines with explicit knots at the observed time points. - -.. ipython:: - - In [326]: odeSIRAdjoint, outputAdjoint = objSIR.adjoint(full_output=True) - -This is because evaluating the Jacobian may be expensive and Runge-kutta method suffers as the complexity increases. In non-linear model such as those found in epidemiology, each element of the Jacobian may be the result of a complicated equation where linear step method will shine as it makes as little function evaluation as possible. -Note that derivations in the literature, the initial condition when evaluating the adjoint equation is :math:`\lambda(T)=0`. But in our code we used :math:`\lambda(T) = -2(y(T)-x(T))`. Recall that we have observation :math:`y(T)` and simulation :math:`x(T)`, so that the adjoint equation evaluated at time :math:`T` - -.. math:: - - \frac{\partial \lambda^{\top}}{\partial t} \Big|_{T} = -2(y-f(x,\theta))\Big|_{T} - \lambda(T)\frac{\partial f}{\partial \theta}\Big|_{T} - -with the second term equal to zero. Integration under step size :math:`h` implies that :math:`\lambda(T) \approx \lim_{h \to 0} \lambda(T-h) = -2(y(T)-x(T))`. - -Time Comparison -=============== - -A simple time comparison between the different methods reveals that the forward sensitivity method dominates the others by a wide margin. It will be tempting to conclude that it is the best and should be the default at all times but that is not true, due to the complexity of each method mentioned previously. We leave it to the end user to find out the best method for their specific problem. - -.. ipython:: - - In [319]: %timeit gradSens = objSIR.sensitivity() - - In [326]: %timeit odeSIRAdjoint,outputAdjoint = objSIR.adjoint(full_output=True) - - -Hessian -======= - -The Hessian is defined by - -.. math:: - - \frac{\partial^{2} l}{\partial \theta^{2}} = \left( \frac{\partial l}{\partial x} \otimes I_{p} \right) \frac{\partial^{2} x}{\partial \theta^{2}} + \frac{\partial x}{\partial \theta}^{\top}\frac{\partial^{2} l}{\partial x^{2}}\frac{\partial x}{\partial \theta} - -where :math:`\otimes` is the Kronecker product. Note that :math:`\nabla_{\theta} x` is the sensitivity and the second order sensitivities can be found again via the forward method, which involve another set of ode's, namely the forward-forward sensitivities - -.. math:: - - \frac{\partial}{\partial t}\left(\frac{\partial^{2} x}{\partial \theta^{2}}\right) = \left( \frac{\partial f}{\partial x} \otimes I_{p} \right) \frac{\partial^{2} x}{\partial \theta^{2}} + \left( I_{d} \otimes \frac{\partial x}{\partial \theta}^{\top} \right) \frac{\partial^{2} f}{\partial x^{2}} \frac{\partial x}{\partial \theta}. - -From before, we know that - -.. math:: - - \frac{\partial l}{\partial x} = (-2y+2x) \quad and \quad \frac{\partial^{2} l}{\partial x^{2}} = 2I_{d} - -so our Hessian reduces to - -.. math:: - - \frac{\partial^{2} l}{\partial \theta^{2}} = \left( \left(-2y+2x\right) \otimes I_{p} \right) \frac{\partial^{2} x}{\partial \theta^{2}} + 2S^{\top}S, - -where the second term is a good approximation to the Hessian as mentioned previously. This is the only implementation in place so far even though obtaining the estimate this way is relatively slow. - -Just to demonstate how it works, lets look at the Hessian at the optimal point. First, we obtain the optimal value - -.. ipython:: - - In [211]: import scipy.linalg,scipy.optimize - - In [212]: boxBounds = [(0.0, 2.0), (0.0, 2.0)] - - In [213]: res = scipy.optimize.minimize(fun=objSIR.cost, - .....: jac=objSIR.sensitivity, - .....: x0=theta, - .....: bounds=boxBounds, - .....: method='L-BFGS-B') - -Then compare again the least square estimate of the covariance matrix against our version - -.. ipython:: - - In [211]: resLS, cov_x, infodict, mesg, ier = scipy.optimize.leastsq(func=objSIR.residual, x0=res['x'], full_output=True) - - In [212]: HJTJ, outputHJTJ = objSIR.hessian(full_output=True) - - In [311]: print(scipy.linalg.inv(HJTJ)) - - In [312]: print(cov_x) - -also note the difference between the Hessian and the approximation using the Jacobian, which is in fact what the least squares routine uses. - -.. ipython:: - - In [313]: print(scipy.linalg.inv(outputHJTJ['JTJ'])) diff --git a/doc/doc_to_sort/initialGuess.rst b/doc/doc_to_sort/initialGuess.rst deleted file mode 100644 index 97e6a037..00000000 --- a/doc/doc_to_sort/initialGuess.rst +++ /dev/null @@ -1,47 +0,0 @@ -.. _initialGuess: - -******************************************* -Obtaining good initial value for parameters -******************************************* - -Function Interpolation -====================== - -When we want to fit the model to data, one of the necessary steps is to supply the optimization procedure a good set of initial guess for the parameters :math:`\theta`. This may be a challenge when we do have a good understanding of the process we are trying to model i.e. infectious disease may all follow the same SIR process but with vastly different incubation period. - -A method to obtain such initial guess based on the collocation is available in this package. A restriction is that data must be present for all states. We demonstrate this using the FitzHugh-Nagumo model. - - -.. ipython:: - - In [1]: from pygom import SquareLoss, common_models, get_init - - In [2]: import numpy - - In [3]: x0 = [-1.0, 1.0] - - In [4]: t0 = 0 - - In [5]: # params - - In [6]: paramEval = [('a',0.2), ('b',0.2), ('c',3.0)] - - In [7]: ode = common_models.FitzHugh(paramEval) - - In [8]: ode.initial_values = (x0, t0) - - In [8]: t = numpy.linspace(1, 20, 30).astype('float64') - - In [9]: solution = ode.integrate(t) - -Below, we try to find the initial guess without supplying any further information. The underlying method fits a cubic spline against the observation and tries to minimize the difference between the first derivative of the spline and the function of the ode. Varying degree of smoothness penalty is applied to the spline and the best set of parameters is the ones that yields the smallest total error, combining both the fit of the spline against data and the spline against the ode. - -.. ipython:: - - In [10]: theta, sInfo = get_init(solution[1::,:], t, ode, theta=None, full_output=True) - - In [11]: print(theta) - - In [12]: print(sInfo) - -As seen above, we have obtained a very good guess of the parameters, in fact almost the same as the generating process. The information regarding the smoothing factor shows that the amount of penalty used is small, which is expected given that we use the solution of the ode as observations. diff --git a/doc/doc_to_sort/mod/common_models.rst b/doc/doc_to_sort/mod/common_models.rst deleted file mode 100644 index e193a655..00000000 --- a/doc/doc_to_sort/mod/common_models.rst +++ /dev/null @@ -1,8 +0,0 @@ - -common_models -============= - -.. automodule:: pygom.model.common_models - :members: - :noindex: - diff --git a/doc/doc_to_sort/mod/confidence_interval.rst b/doc/doc_to_sort/mod/confidence_interval.rst deleted file mode 100644 index f0af3c3c..00000000 --- a/doc/doc_to_sort/mod/confidence_interval.rst +++ /dev/null @@ -1,7 +0,0 @@ - -loss_type -========= - -.. automodule:: pygom.loss.loss_type - :members: - :noindex: diff --git a/doc/doc_to_sort/mod/deterministic.rst b/doc/doc_to_sort/mod/deterministic.rst deleted file mode 100644 index fe10281e..00000000 --- a/doc/doc_to_sort/mod/deterministic.rst +++ /dev/null @@ -1,7 +0,0 @@ -deterministic -============= - -.. automodule:: pygom.model.deterministic - :members: - :noindex: - \ No newline at end of file diff --git a/doc/doc_to_sort/mod/epi_analysis.rst b/doc/doc_to_sort/mod/epi_analysis.rst deleted file mode 100644 index 751d846b..00000000 --- a/doc/doc_to_sort/mod/epi_analysis.rst +++ /dev/null @@ -1,7 +0,0 @@ -epi_analysis -============ - -.. automodule:: pygom.model.epi_analysis - :members: - :noindex: - \ No newline at end of file diff --git a/doc/doc_to_sort/mod/get_init.rst b/doc/doc_to_sort/mod/get_init.rst deleted file mode 100644 index df85fa99..00000000 --- a/doc/doc_to_sort/mod/get_init.rst +++ /dev/null @@ -1,7 +0,0 @@ -get_init -======== - -.. automodule:: pygom.loss.get_init - :members: - :noindex: - \ No newline at end of file diff --git a/doc/doc_to_sort/mod/index.rst b/doc/doc_to_sort/mod/index.rst deleted file mode 100644 index 5c5362ab..00000000 --- a/doc/doc_to_sort/mod/index.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _mod: - - -******************* -Code documentations -******************* - -===== -model -===== - -.. toctree:: - - common_models - transition - deterministic - simulate - epi_analysis - odeutils - -==== -loss -==== - -.. toctree:: - - odeloss - losstype - confidence_interval - get_init diff --git a/doc/doc_to_sort/mod/losstype.rst b/doc/doc_to_sort/mod/losstype.rst deleted file mode 100644 index 00cbf46c..00000000 --- a/doc/doc_to_sort/mod/losstype.rst +++ /dev/null @@ -1,7 +0,0 @@ - -confidence_interval -=================== - -.. automodule:: pygom.loss.confidence_interval - :members: - :noindex: diff --git a/doc/doc_to_sort/mod/odeloss.rst b/doc/doc_to_sort/mod/odeloss.rst deleted file mode 100644 index 65ceea3a..00000000 --- a/doc/doc_to_sort/mod/odeloss.rst +++ /dev/null @@ -1,17 +0,0 @@ -ode_loss -======== - -These are basically the interfaces for :class:`pygom.loss.BaseLoss` - -.. automodule:: pygom.loss.ode_loss - :members: - :noindex: - -calculations -============ - -The base class which contains has all the calculation implemented - -.. automodule:: pygom.loss.base_loss - :members: - :noindex: diff --git a/doc/doc_to_sort/mod/odeutils.rst b/doc/doc_to_sort/mod/odeutils.rst deleted file mode 100644 index 87d7b550..00000000 --- a/doc/doc_to_sort/mod/odeutils.rst +++ /dev/null @@ -1,7 +0,0 @@ - -ode_utils -========= - -.. automodule:: pygom.model.ode_utils - :members: - :noindex: diff --git a/doc/doc_to_sort/mod/simulate.rst b/doc/doc_to_sort/mod/simulate.rst deleted file mode 100644 index 7aaa9d01..00000000 --- a/doc/doc_to_sort/mod/simulate.rst +++ /dev/null @@ -1,8 +0,0 @@ - -stochastic -========== - -.. automodule:: pygom.model.simulate - :members: - :noindex: - diff --git a/doc/doc_to_sort/mod/transition.rst b/doc/doc_to_sort/mod/transition.rst deleted file mode 100644 index 2901c1e2..00000000 --- a/doc/doc_to_sort/mod/transition.rst +++ /dev/null @@ -1,8 +0,0 @@ - -transition -========== - -.. automodule:: pygom.model.transition - :members: - :noindex: - diff --git a/doc/doc_to_sort/profile.rst b/doc/doc_to_sort/profile.rst deleted file mode 100644 index dd8f0d77..00000000 --- a/doc/doc_to_sort/profile.rst +++ /dev/null @@ -1,433 +0,0 @@ -.. _profile: - -******************************************* -Confidence Interval of Estimated Parameters -******************************************* - -After obtaining the *best* fit, it is natural to report both the point estimate and the confidence level at the :math:`\alpha` level. The easiest way to do this is by invoking the normality argument and use Fisher information of the likelihood. As explained previously at the bottom of :ref:`gradient`, we can find the Hessian, :math:`\mathbf{H}`, or the approximated Hessian for the estimated parameters. The Cramer--Rao inequality, we know that - -.. math:: - Var(\hat{\theta}) \ge \frac{1}{I(\theta)}, - -where :math:`I(\theta)` is the Fisher information, which is the Hessian subject to regularity condition. Given the Hessian, computing the confidence intervals is trivial. Note that this is also known as the asymptotic confidence interval where the normality comes from invoking the CLT. There are other ways of obtaining a confidence intervals, we will the ones implemented in the package. First, we will set up a SIR model as seen in :ref:`sir` which will be used throughout this page. - -.. ipython:: - - In [1]: from pygom import NormalLoss, common_models - - In [2]: from pygom.utilR import qchisq - - In [3]: import numpy - - In [4]: import scipy.integrate - - In [5]: import matplotlib.pyplot as plt - - In [6]: import copy - - In [7]: ode = common_models.SIR([('beta', 0.5), ('gamma', 1.0/3.0)]) - -and we assume that we only have observed realization from the :math:`R` compartment - -.. ipython:: - - In [1]: x0 = [1, 1.27e-6, 0] - - In [2]: t = numpy.linspace(0, 150, 100).astype('float64') - - In [3]: ode.initial_values = (x0, t[0]) - - In [4]: solution = ode.integrate(t[1::]) - - In [5]: theta = [0.2, 0.2] - - In [6]: targetState = ['R'] - - In [7]: targetStateIndex = numpy.array(ode.get_state_index(targetState)) - - In [8]: y = solution[1::,targetStateIndex] + numpy.random.normal(0, 0.01, (len(solution[1::,targetStateIndex]), 1)) - - In [9]: yObv = y.copy() - - In [10]: objSIR = NormalLoss(theta, ode, x0, t[0], t[1::], y, targetState) - - In [11]: boxBounds = [(1e-8, 2.0), (1e-8, 2.0)] - - In [12]: boxBoundsArray = numpy.array(boxBounds) - - In [13]: xhat = objSIR.fit(theta, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1]) - -Asymptotic -========== - -When the estimate is obtained say, under a square loss or a normal assumption, the corresponding likelihood can be written down easily. In such a case, likelihood ratio test under a Chi--squared distribution is - -.. math:: - - 2 (\mathcal{L}(\hat{\boldsymbol{\theta}}) - \mathcal{L}(\boldsymbol{\theta})) \le \chi_{1 - \alpha}^{2}(k) - -where :math:`1-\alpha` is the size of the confidence region and :math:`k` is the degree of freedom. The corresponding asymptotic confidence interval for parameter :math:`j` can be derived as - -.. math:: - - \hat{\theta}_{j} \pm \sqrt{\chi_{1 - \alpha}^{2}(k) H_{i,i}}. - -A pointwise confidence interval is obtained when :math:`k = 1`. We assume in our package that a pointwise confidence interval is desired. This can be obtained simply by - -.. ipython:: - - In [1]: from pygom import confidence_interval as ci - - In [2]: alpha = 0.05 - - In [3]: xL, xU = ci.asymptotic(objSIR, alpha, xhat, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1]) - - In [4]: print(xL) - - In [5]: print(xU) - -Note that the set of bounds here is only used for check the validity of :math:`\hat{\mathbf{x}}` and not used in the calculation of the confidence intervals. Therefore the resulting output can be outside of the box constraints. - -Profile Likelihood -================== - -Another approach to calculate the confidence interval is to tackle one parameter at a time, treating the rest of them as nuisance parameters, hence the term *profile*. Let :math:`\mathcal{L}(\boldsymbol{\theta})` be our log--likelihood with parameter :math:`\boldsymbol{\theta}`. Element :math:`\theta_{j}` is our parameter of interest and :math:`\boldsymbol{\theta}_{-j}` represents the complement such that :math:`\boldsymbol{\theta} = \theta_{j} \cup \boldsymbol{\theta}_{-j}`. For simply models such as linear regression with only regression coefficients :math:`\boldsymbol{\beta}`, then :math:`\boldsymbol{\theta} = \boldsymbol{\beta}`. - -To shorten the notation, let - -.. math:: \mathcal{L}(\boldsymbol{\theta}_{-j} \mid \theta_{j}) = \max \mathcal{L}(\boldsymbol{\theta}_{-j} \mid \theta_{j}) - :label: nuisanceOptim - -which is the maxima of :math:`\boldsymbol{\theta}_{-j}` given :math:`\theta_{j}`. :math:`\hat{\boldsymbol{\theta}}` denotes the MLE of the parameters as usual. The profile--likelihood based confidence interval for :math:`\theta_{j}` is defined as - -.. math:: - - \theta_{j}^{U} &= \sup \left\{ \mathcal{L}(\hat{\boldsymbol{\theta}}) - \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j}) \le \frac{1}{2} \chi_{1 - \alpha}^{2}(1) \right\} \\ - \theta_{j}^{L} &= \inf \left\{ \mathcal{L}(\hat{\boldsymbol{\theta}}) - \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j}) \le \frac{1}{2} \chi_{1 - \alpha}^{2}(1) \right\} - -where again we have made use of the normal approximation, but without imposing symmetry. The set of equations above automatically implies that the interval width is :math:`\theta_{j}^{U} - \theta_{j}^{L}` and - -.. math:: - - \mathcal{L}(\hat{\boldsymbol{\theta}}) - \frac{1}{2} \chi_{1-\alpha}^{2}(1) - \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j}) = 0. - -As mentioned previously, :math:`\boldsymbol{\theta}_{-j}` is the maximizer of the nuisance parameters, which has a gradient of zero. Combining this with the equation above yields a non--linear system of equations of size :math:`p`, - -.. math:: g(\boldsymbol{\theta}) = \left[ \begin{array}{c} \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j}) - c \\ \frac{\partial \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j})}{\partial \boldsymbol{\theta}_{-j}} \end{array} \right] = 0 - :label: obj - -where :math:`c = \mathcal{L}(\hat{\boldsymbol{\theta}}) + \frac{1}{2} \chi_{1-\alpha}^{2}(1)`. Solving this set of system of equations only need simple Newton like steps, possibly with correction terms as per [Venzon1988]_. We provide a function to obtain such estimate - -.. ipython:: - :verbatim: - - In [1]: xLProfile, xUProfile, xLProfileList, xUProfileList = ci.profile(objSIR, alpha, xhat, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1], full_output=True) - -but unfortunately this is not accurate most of the time due to the complicated surface at locations not around :math:`\hat{\theta}`. This is a common scenario for non--linear least square problems because the Hessian is not guaranteed to be a PSD everywhere. Therefore, a safeguard is in place to obtain the :math:`\theta_{j}^{U},\theta_{j}^{L}` by iteratively by updating :math:`\theta_{j}` and find the solution to :eq:`nuisanceOptim`. - -Furthermore, we also provide the functions necessary to obtain the estimates such as the four below. - -.. ipython:: - - In [1]: i = 0 - - In [1]: funcF = ci._profileF(xhat, i, 0.05, objSIR) - - In [2]: funcG = ci._profileG(xhat, i, 0.05, objSIR) - - In [3]: funcGC = ci._profileGSecondOrderCorrection(xhat, i, alpha, objSIR) - - In [4]: funcH = ci._profileH(xhat, i, 0.05, objSIR) - -Where :math:`i` is the index of the parameter of interest. :func:`_profileF` is the squared norm of :eq:`obj`, which easy the optimization process for solvers which requires a converted form from system of equations to non-linear least squares. :func:`_profileG` is the systems of equations :eq:`obj`, :func:`_profileH` is the derivative of :eq:`obj` - -.. math:: - \nabla g(\boldsymbol{\theta}) = \left[ \begin{array}{c} \frac{\partial \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j})}{\partial \theta_{j}} \\ \frac{\partial^{2} \mathcal{L}(\boldsymbol{\theta} \mid \theta_{j})}{\partial \boldsymbol{\beta}_{-j} \partial \theta_{j}} \end{array} \right] - -and :func:`_profileGSecondOrderCorrection` has the second order correction [Venzon1988]_. - -Geometric profile likelihood -============================ - -Due to the difficulty in obtain a profile likelihood via the standard Newton like steps, we also provide a way to generate a similar result using the geometric structure of the likelihood surface. We follow the method in [Moolgavkar1987]_, which involves solving a set of differential equations - -.. math:: - \frac{d\beta_{j}}{dt} &= k g^{-1/2} \\ - \frac{d\boldsymbol{\beta}_{-j}}{dt} &= \frac{d\boldsymbol{\beta}_{-j}}{d\beta_{j}} \frac{d\beta_{j}}{dt}, - -where :math:`k = \Phi(1-\alpha)` is the quantile we want to obtain under a normal distribution, and - -.. math:: - - g = J_{\beta_{j}}^{\top} I^{\boldsymbol{\beta}} J_{\beta_{j}}, \quad J_{\beta_{j}} = \left( \begin{array}{c} 1 \\ \frac{d\boldsymbol{\beta}_{-j}}{d\beta_{j}} \end{array} \right). - -Here, :math:`J_{\beta_{j}}` is the Jacobian between :math:`\beta_{j}` and :math:`\boldsymbol{\beta}_{-j}` with the term - -.. math:: - - \frac{d\boldsymbol{\beta}_{-j}}{d\beta_{j}} = -\left( \frac{\partial^{2} \mathcal{L}}{\partial \boldsymbol{\beta}_{-j}\partial \boldsymbol{\beta}_{-j}^{\top} } \right)^{-1} \frac{\partial^{2} \mathcal{L}}{\partial \beta_{j} \partial \beta_{-j}^{\top}} - -and hence the first element is :math:`1` (identity transformation). :math:`I^{\boldsymbol{\beta}}` is the Fisher information of :math:`\boldsymbol{\beta}`, which is - -.. math:: - - I^{\boldsymbol{\beta}} = \frac{\partial \boldsymbol{\theta}}{\partial \boldsymbol{\beta}^{\top}} \Sigma^{\boldsymbol{\theta}(\boldsymbol{\beta})} \frac{\partial \boldsymbol{\theta}}{\partial \boldsymbol{\beta}}. - -It is simply :math:`\Sigma^{\boldsymbol{\beta}}` if :math:`\boldsymbol{\theta} = \boldsymbol{\beta}`. Different Fisher information can be used for :math:`\Sigma^{\boldsymbol{\beta}}` such as the expected or observed, at :math:`\hat{\boldsymbol{\beta}}` or :math:`\boldsymbol{\beta}`. After some trivial algebraic manipulation, we can show that our ode boils downs to - -.. math:: - - \left[ \begin{array}{c} \frac{d\beta_{j}}{dt} \\ \frac{d\boldsymbol{\beta_{-j}}}{dt} \end{array} \right] = k \left[ \begin{array}{c} 1 \\ -A^{-1}w \end{array} \right] \left( v - w^{\top}A^{-1}w \right)^{-1/2} - -where the symbols on the RHS above correspond to partitions in the Fisher information - -.. math:: - - I^{\boldsymbol{\beta}} = \left[ \begin{array}{cc} v & w^{\top} \\ w & A \end{array} \right]. - -The integration is perform from :math:`t = 0` to :math:`1` and is all handled internally via :func:`geometric` - -.. ipython:: - - In [1]: xLGeometric, xUGeometric, xLList, xUList = ci.geometric(objSIR, alpha, xhat, full_output=True) - - In [2]: print(xLGeometric) - - In [3]: print(xUGeometric) - -Bootstrap -========= - -This is perhaps the favorite method to estimate confidence interval for a lot of people. Although there are many ways to implement bootstrap, semi-parametric is the only logical choice (even though the underlying assumptions may be violated at times). As we have only implemented OLS type loss functions in this package, the parametric approach seem to be inappropriate when there is no self--efficiency guarantee. Non-parametric approach requires at least a conditional independence assumption, something easily violated by our **ode**. Block bootstrap is an option but we are also aware that the errors of an **ode** can be rather rigid, and consistently over/under estimate at certain periods of time. - -When we say semi-parametric, we mean the exchange of errors between the observations. Let our raw error be - -.. math:: - - \varepsilon_{i} = y_{i} - \hat{y}_{i} - -where :math:`\hat{y}_{i}` will be the prediction under :math:`\hat{\boldsymbol{\theta}}` under our model. Then we construct a new set of observations via - -.. math:: - - y_{i}^{\ast} = \hat{y}_{i} + \varepsilon^{\ast}, \quad \varepsilon^{\ast} \sim \mathcal{F} - -with :math:`\mathcal{F}` being the empirical distribution of the raw errors. A new set of parameters :math:`\theta^{\ast}` are then found for the bootstrapped samples, and we obtain the :math:`\alpha` confidence interval by taking the :math:`\alpha/2` quantiles. Invoke the correspond python function yields our bootstrap estimates. Unlike :func:`asymptotic`, the bounds here are used when estimating the parameters of each bootstrap samples. An error may be returned if estimation failed for any of the bootstrap samples. - -.. ipython:: - - In [1]: xLBootstrap, xUBootstrap, setX = ci.bootstrap(objSIR, alpha, xhat, iteration=10, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1], full_output=True) - - In [2]: print(xLBootstrap) - - In [3]: print(xUBootstrap) - -The additional information here can be used to compute the bias, tail effects and test against the normality assumption. If desired, a simultaneous confidence interval can also be approximated empirically. Note however that because we are using a semi--parameter method here, if the model specification is wrong then the resulting estimates for the bias is also wrong. The confidence interval still has the normal approximation guarantee if number of sample is large. - -In this case, because the error in the observation is extremely small, the confidence interval is narrow. - -.. ipython:: - - In [1]: import pylab as P - - In [2]: f = plt.figure() - - In [3]: n, bins, patches = P.hist(setX[:,0], 50) - - In [4]: P.xlabel(r'Estimates of $\beta$'); - - In [5]: P.ylabel('Frequency'); - - In [6]: P.title('Estimates under a semi-parametric bootstrap scheme'); - - @savefig bootstrapCIHist.png - In [7]: P.show() - - In [8]: P.close() - -Comparison Between Methods -========================== - -Although we have shown the numerical values for the confidence interval obtained using different method, it may be hard to comprehend how they vary. As they say, a picture says a million word, and given that this particular model only has two parameters, we can obtain inspect and compare the methods visually via a contour plot. The code to perform this is shown below but the code block will not be run to save time and space. - -.. ipython :: - :verbatim: - - In [1]: niter = 1000 - - In [2]: randNum = numpy.random.rand(niter,2)*2.0 - - In [3]: target = [objSIR.cost(randNum[i,:]) for i in range(niter)] - - In [4]: z = numpy.array(target) - - In [5]: x = randNum[:,0] - - In [6]: y = randNum[:,1] - - In [7]: from scipy.interpolate import griddata - - In [8]: xi = numpy.linspace(0.0, 2.0, 100) - - In [9]: yi = numpy.linspace(0.0, 2.0, 100) - - In [10]: zi = griddata((x, y), numpy.log(z), (xi[None,:], yi[:,None]), method='cubic') - - In [11]: fig = plt.figure() - - In [12]: CS = plt.contour(xi, yi, zi, linewidth=0.5) - - In [13]: plt.clabel(CS, fontsize=10, inline=1); - - In [14]: l0 = plt.scatter(xhat[0], xhat[1], marker='o', c='k', s=30) - - In [15]: l1 = plt.scatter(numpy.append(xL[0], xU[0]), numpy.append(xL[1], xU[1]), marker='x', c='m', s=30) - - In [16]: l2 = plt.scatter(numpy.append(xLBootstrap[0], xUBootstrap[0]), numpy.append(xLBootstrap[1], xUBootstrap[1]), marker='x', c='g', s=30) - - In [17]: l3 = plt.scatter(numpy.append(xLGeometric[0], xUGeometric[0]), numpy.append(xLGeometric[1], xUGeometric[1]), marker='x', c='r', s=30) - - In [19]: plt.legend((l0, l1, l2, l3), ('MLE', 'Asymptotic', 'Bootstrap', 'Geometric'), loc='upper left'); - - In [20]: plt.ylabel(r'Estimates of $\gamma$'); - - In [21]: plt.xlabel(r'Estimates of $\beta$'); - - In [22]: plt.title('Location of the confidence intervals on the likelihood surface'); - - In [23]: plt.tight_layout(); - - In [24]: plt.show() - - In [25]: plt.close() - -In the plot above, the bootstrap confidence interval were so close to the MLE, it is impossible to distinguish the two on such a coarse scale. - -Furthermore, because the geometric confidence interval is the result of an integration, we can trace the path that lead to the final output that was shown previously. Again, we are space conscious (and time constrained) so the code block below will not be run. - -.. ipython:: - :verbatim: - - In [1]: fig = plt.figure() - - In [2]: CS = plt.contour(xi, yi, zi, linewidth=0.5) - - In [3]: plt.clabel(CS, fontsize=10, inline=1) - - In [4]: l1 = plt.scatter(xLList[0][:,0], xLList[0][:,1], marker='o', c='m', s=10); - - In [5]: l2 = plt.scatter(xUList[0][:,0], xUList[0][:,1], marker='x', c='m', s=10); - - In [6]: plt.legend((l1, l2), ('Lower CI path', 'Upper CI path'), loc='upper left'); - - In [7]: plt.ylabel(r'Estimates of $\gamma$'); - - In [8]: plt.xlabel(r'Estimates of $\beta$'); - - In [9]: plt.title('Integration path of the geometric confidence intervals on the likelihood surface'); - - In [10]: plt.tight_layout(); - - In [11]: plt.show() - - In [12]: plt.close() - - -Profile Likelihood Surface -========================== - -To investigate why it was hard to find the profile likelihood confidence interval, we can simply look at the surface (which is simply a line as we are profiling). We find solution of :eq:`nuisanceOptim` for each :math:`\boldsymbol{\theta}_{-j}` at various points of :math:`\boldsymbol{\theta}`. Equivalently, we can minimize the original loss function as defined previously, and this is the approach below. We focus out attention to the parameter :math:`\beta` of our SIR model. The results are not shown here but the existence of a solution to :eq:`obj` is evident by simply *eyeballing* the plots. - -.. ipython:: - :verbatim: - - In [1]: numIter = 100 - - In [2]: x2 = numpy.linspace(0.0, 2.0, numIter) - - In [3]: funcOut = numpy.linspace(0.0, 2.0, numIter) - - In [4]: ode.parameters = [('beta',0.5), ('gamma',1.0/3.0)] - - In [5]: for i in range(numIter): - ...: paramEval = [('beta',x2[i]), ('gamma',x2[i])] - ...: ode2 = copy.deepcopy(ode) - ...: ode2.parameters = paramEval - ...: ode2.initial_values = (x0, t[0]) - ...: objSIR2 = NormalLoss(x2[i], ode2, x0, t[0], t[1::], yObv.copy(), targetState, target_param='gamma') - ...: res = scipy.optimize.minimize(fun=objSIR2.cost, - ...: jac=objSIR2.gradient, - ...: x0=x2[i], - ...: bounds=[(0,2)], - ...: method='L-BFGS-B') - ...: funcOut[i] = res['fun'] - - In [10]: fig = plt.figure() - - In [10]: plt.plot(x2, objSIR.cost(xhat) - funcOut) - - In [11]: l1 = plt.axhline(-0.5*qchisq(1 - alpha, df=1), 0, 2, color='r') - - In [12]: plt.ylabel(r'$\mathcal{L}(\hat{\theta}) - \mathcal{L}(\theta \mid \beta)$'); - - In [13]: plt.xlabel(r'Fixed value of $\beta$'); - - In [14]: plt.title('Difference in objective function between MLE\n and the maximization of the nuisance parameters given the\n parameter of interest, beta in this case'); - - In [15]: plt.tight_layout(); - - In [16]: plt.legend((l1,), (r'$-0.5\mathcal{X}_{1 - \alpha}^{2}(1)$',), loc='lower right'); - - @savefig profileLLMaximizerGivenBeta.png - In [17]: plt.show() # @savefig profileLLMaximizerGivenBeta.png - - In [18]: plt.close() - -Both the upper and lower confidence interval can be found in the profiling procedure, but the part between of :math:`\beta \in \left[0,\hat{\beta}\right]` is not convex, with :math:`\hat{\beta}` being the MLE. This non--quadratic profile likelihood is due to the non-identifiability of the model given data [Raue2009]_. For this particular case, we can fix it simply by introducing additional observations in the form of the :math:`I` state. We encourage the users to try it out for themselves to confirm. - -.. ipython:: - :verbatim: - - In [1]: targetState = ['I', 'R'] - - In [2]: targetStateIndex = numpy.array(ode.get_state_index(targetState)) - - In [3]: y = solution[1::,targetStateIndex] + numpy.random.normal(0, 0.01, (len(solution[1::,targetStateIndex]), 1)) - - In [4]: objSIR = NormalLoss(theta, ode, x0, t[0], t[1::], y.copy(), targetState) - - In [5]: xhat = objSIR.fit(theta, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1]) - - In [6]: for i in range(numIter): - ...: paramEval = [('beta', x2[i]), ('gamma', x2[i])] - ...: ode2 = copy.deepcopy(ode) - ...: ode2.parameters = paramEval - ...: ode2.initial_values = (x0, t[0]) - ...: objSIR2 = NormalLoss(x2[i], ode2, x0, t[0], t[1::], y.copy(), targetState, target_param='gamma') - ...: res = scipy.optimize.minimize(fun=objSIR2.cost, - ...: jac=objSIR2.gradient, - ...: x0=x2[i], - ...: bounds=[(0,2)], - ...: method='L-BFGS-B') - ...: funcOut[i] = res['fun'] - - In [10]: fig = plt.figure() - - In [10]: plt.plot(x2, objSIR.cost(xhat) - funcOut); - - In [11]: l1 = plt.axhline(-0.5*qchisq(1 - alpha, df=1), 0, 2, color='r') - - In [12]: plt.ylabel(r'$\mathcal{L}(\hat{\theta}) - \mathcal{L}(\theta \mid \beta)$'); - - In [13]: plt.xlabel(r'Fixed value of $\beta$'); - - In [14]: plt.title('Profile likelihood curve for the parameter of\n interest with more observation'); - - In [15]: plt.tight_layout(); - - In [16]: plt.legend((l1,), (r'$-0.5\mathcal{X}_{1 - \alpha}^{2}(1)$',), loc='lower right'); - - @savefig profileLLMaximizerGivenBetaMoreObs.png - In [17]: plt.show() # @savefig profileLLMaximizerGivenBetaMoreObs.png - - In [18]: plt.close() diff --git a/doc/doc_to_sort/ref.rst b/doc/doc_to_sort/ref.rst deleted file mode 100644 index c1f0f93e..00000000 --- a/doc/doc_to_sort/ref.rst +++ /dev/null @@ -1,76 +0,0 @@ -.. _ref: - -********** -References -********** - -.. [Aron1984] Seasonality and period-doubling bifurcations in an epidemic model, - Joan L. Aron and Ira B. Schwartz, Journal of Theoretical Biology, Volume 110, - Issue 4, page 665-679, 1984 - -.. [Brauer2008] Mathematical Epidemiology, Lecture Notes in Mathematics, - Fred Brauer, Springer 2008 - -.. [Cao2006] Efficient step size selection for the tau-leaping simulation - method, Yang Cao et el., The Journal of Chemical Physics, Volume 124, - Issue 4, page 044109, 2006 - -.. [Finnie2016] EpiJSON: A unified data-format for epidemiology, - Thomas Finnie et al., Epidemics, Volume 15, page 20-26, 2016 - -.. [FitzHugh1961] Impulses and Physiological States in Theoretical Models of - Nerve Membrane, Richard FitzHugh, Biophysical Journal, Volume 1, Issue 6, - page 445-466, 1961 - -.. [Gillespie1977] Exact stochastic simulation of coupled chemical reactions, - Danial T. Gillespie, The Journal of Physical Chemistry, Volume 81, - Issue 25, page 2340-2361, 1977 - -.. [Girolami2011] Riemann manifold Langevin and Hamiltonian Monte Carlo methods, - Mark Girolami and Ben Calderhead, Journal of the Royal Statistical Society - Series B, Volume 73, Issue 2, page 123-214, 2011. - -.. [Hethcote1973] Asymptotic behavior in a deterministic epidemic model, - Herbert W. Hethcote, Bulletin of Mathematical Biology, Volume 35, - page 607-614, 1973 - -.. [Legrand2007] Understanding the dynamics of Ebola epidemics, - J. Legrand et al. Epidemiology and Infection, Volume 135, Issue 4, - page 610-621, 2007 - -.. [Lloyd1996] Spatial Heterogeneity in Epidemic Models, A.L. Lloyd and - R.M. May, Journal of Theoretical Biology, Volume 179, - Issue 1, page 1-11, 1996 - -.. [Lorenz1963] Deterministic Nonperiodic Flow, Edward N. Lorenz, Journal of - the Atmospheric Sciences, Volume 20, Issue 2, page 130-141, 1963 - -.. [Lotka1920] Analytical Note on Certain Rhythmic Relations in Organic Systems, - Alfred J. Lotka, Proceedings of the National Academy of Sciences of the - United States of America, Volume 7, Issue 7, page 410-415, 1920 - -.. [Moolgavkar1987] Confidence Regions for Parameters of the Proportional - Hazards Model: A Simulation Study, S.H. Moolgavkar and D.J. Venzon, - Scandianvia Journal of Statistics, Volume 14, page 43-56, 1987 - -.. [Press2007] Numerical Recipes 3rd Edition: The Art of Scientific Computing, - W.H. Press et al., Cambridge University Press, 2007 - -.. [Ramsay2007] Parameter estimation for differential equations: a generalized - smoothing approach, Journal of the Royal Statistical Society Series B, - James O. Ramsay et al., Volume 69, Issue 5, page 741-796, 2007 - -.. [Raue2009] Structural and Practical Identifiability Analysis of Partially - Observed Dynamical Models by Exploiting the Profile Likelihood, - A. Raue et al., Bioinformatics, Volume 25, Issue 15, page 1923-1929, 2009 - -.. [Robertson1966] The solution of a set of reaction rate equations, - H.H. Robertson, Academic Press, page 178-182, 1966 - -.. [vanderpol1926] On Relaxed Oscillations, Balthasar van der Pol, The London, - Edinburgh, and Dublin Philosophical Magazine and Journal of Science, - Volume 2, Issue 11, page 978-992, 1926 - -.. [Venzon1988] A Method for Computing Profile-Likelihood-Based Confidence - Intervals, D.J. Venzon and S.H. Moolgavkar, Journal of the Royal Statistical - Society Series C (Applied Statistics), Volume 37, Issue 1, page 87-94, 1988 diff --git a/doc/doc_to_sort/stochastic.rst b/doc/doc_to_sort/stochastic.rst deleted file mode 100644 index 98f380b9..00000000 --- a/doc/doc_to_sort/stochastic.rst +++ /dev/null @@ -1,269 +0,0 @@ -.. _stochastic: - -******************************** -Stochastic representation of ode -******************************** - -There are multiple interpretation of stochasticity of a deterministic ode. We have implemented two of the most common interpretation; when the parameters are realizations of some underlying distribution, and when we have a so called chemical master equation where each transition represent a jump. Again, we use the standard SIR example as previously seen in ref:`sir`. - -.. ipython:: - - In [1]: from pygom import SimulateOde, Transition, TransitionType - - In [1]: import matplotlib.pyplot as plt - - In [1]: import numpy as np - - In [1]: x0 = [1, 1.27e-6, 0] - - In [1]: t = np.linspace(0, 150, 100) - - In [1]: stateList = ['S', 'I', 'R'] - - In [1]: paramList = ['beta', 'gamma'] - - In [1]: transitionList = [ - ...: Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T), - ...: Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) - ...: ] - - In [1]: odeS = SimulateOde(stateList, paramList, transition=transitionList) - - In [1]: odeS.parameters = [0.5, 1.0/3.0] - - In [1]: odeS.initial_values = (x0, t[0]) - - In [1]: solutionReference = odeS.integrate(t[1::], full_output=False) - - -Stochastic Parameter -==================== - -In our first scenario, we assume that the parameters follow some underlying distribution. Given that both :math:`\beta` and :math:`\gamma` in our SIR model has to be non-negative, it seemed natural to use a Gamma distribution. We make use of the familiar syntax from `R `_ to define our distribution. Unfortunately, we have to define it via a tuple, where the first is the function handle (name) while the second the parameters. Note that the parameters can be defined as either a dictionary or as the same sequence as `R `_, which is the shape then the rate in the Gamma case. - -.. ipython:: - - In [1]: from pygom.utilR import rgamma - - In [1]: d = dict() - - In [1]: d['beta'] = (rgamma,{'shape':100.0, 'rate':200.0}) - - In [1]: d['gamma'] = (rgamma,(100.0, 300.0)) - - In [1]: odeS.parameters = d - - In [1]: Ymean, Yall = odeS.simulate_param(t[1::], 10, full_output=True) - -Note that a message is printed above where it is trying to connect to an mpi backend, as our module has the capability to compute in parallel using the IPython. We have simulated a total of 10 different solutions using different parameters, the plots can be seen below - -.. ipython:: - - In [1]: f, axarr = plt.subplots(1,3) - - In [1]: for solution in Yall: - ...: axarr[0].plot(t, solution[:,0]) - ...: axarr[1].plot(t, solution[:,1]) - ...: axarr[2].plot(t, solution[:,2]) - - @savefig stochastic_param_all.png - In [1]: plt.show() - - In [1]: plt.close() - -We then see how the expected results, using the sample average of the simulations - -.. math:: - - \tilde{x}(T) = \mathbb{E}\left[ \int_{t_{0}}^{T} f(\theta,x,t) dt \right] - -differs from the reference solution - -.. math:: - - \hat{x}(T) = \int_{t_{0}}^{T} f(\mathbb{E}\left[ \theta \right],x,t) dt - -.. ipython:: - - In [1]: f, axarr = plt.subplots(1,3) - - In [1]: for i in range(3): axarr[i].plot(t, Ymean[:,i] - solutionReference[:,i]) - - @savefig stochastic_param_compare.png - In [1]: plt.show() - - In [1]: plt.close() - -The difference is relatively large especially for the :math:`S` state. We can decrease this difference as we increase the number of simulation, and more sophisticated sampling method for the generation of random variables can also decrease the difference. - -In addition to using the built-in functions to represent stochasticity, we can also use standard frozen distributions from scipy. Note that it must be a frozen distribution as that is the only for the parameters of the distributions to propagate through the model. - -.. ipython:: - - In [1]: import scipy.stats as st - - In [1]: d = dict() - - In [1]: d['beta'] = st.gamma(a=100.0, scale=1.0/200.0) - - In [1]: d['gamma'] = st.gamma(a=100.0, scale=1.0/300.0) - - In [1]: odeS.parameters = d - - -Obviously, there may be scenarios where only some of the parameters are stochastic. Let's say that the :math:`\gamma` parameter is fixed at :math:`1/3`, then simply replace the distribution information with a scalar. A quick visual inspection at the resulting plot suggests that the system of ODE potentially has less variation when compared to the case where both parameters are stochastic. - -.. ipython:: - - In [1]: d['gamma'] = 1.0/3.0 - - In [1]: odeS.parameters = d - - In [1]: YmeanSingle, YallSingle = odeS.simulate_param(t[1::], 5, full_output=True) - - In [1]: f, axarr = plt.subplots(1,3) - - In [1]: for solution in YallSingle: - ...: axarr[0].plot(t,solution[:,0]) - ...: axarr[1].plot(t,solution[:,1]) - ...: axarr[2].plot(t,solution[:,2]) - - @savefig stochastic_param_single.png - In [1]: plt.show() - - In [1]: plt.close() - -Continuous Markov Representation -================================ - -Another common method of introducing stochasticity into a set of ode is by assuming each movement in the system is a result of a jump process. More concretely, the probabilty of a move for transition :math:`j` is governed by an exponential distribution such that - -.. math:: - - \Pr(\text{process $j$ jump within time } \tau) = \lambda_{j} e^{-\lambda_{j} \tau}, - -where :math:`\lambda_{j}` is the rate of transition for process :math:`j` and :math:`\tau` the time elapsed after current time :math:`t`. - -A couple of the commmon implementation for the jump process have been implemented where two of them are used during a normal simulation; the first reaction method [Gillespie1977]_ and the :math:`\tau`-Leap method [Cao2006]_. The two changes interactively depending on the size of the states. - -.. ipython:: - - In [1]: x0 = [2362206.0, 3.0, 0.0] - - In [1]: stateList = ['S', 'I', 'R'] - - In [1]: paramList = ['beta', 'gamma', 'N'] - - In [1]: transitionList = [ - ...: Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), - ...: Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) - ...: ] - - In [1]: odeS = SimulateOde(stateList, paramList, transition=transitionList) - - In [1]: odeS.parameters = [0.5, 1.0/3.0, x0[0]] - - In [1]: odeS.initial_values = (x0, t[0]) - - In [1]: solutionReference = odeS.integrate(t[1::]) - - In [1]: simX, simT = odeS.simulate_jump(t[1:10], 10, full_output=True) - - In [1]: f, axarr = plt.subplots(1, 3) - - In [1]: for solution in simX: - ...: axarr[0].plot(t[:9], solution[:,0]) - ...: axarr[1].plot(t[:9], solution[:,1]) - ...: axarr[2].plot(t[:9], solution[:,2]) - - @savefig stochastic_process.png - In [1]: plt.show() - - In [1]: plt.close() - -Above, we see ten different simulation, again using the SIR model but without standardization of the initial conditions. We restrict our time frame to be only the first 10 time points so that the individual changes can be seen more clearly above. If we use the same time frame as the one used previously for the deterministic system (as shown below), the trajectories are smoothed out and we no longer observe the *jumps*. Looking at the raw trajectories of the ODE below, it is obvious that the mean from a jump process is very different to the deterministic solution. The reason behind this is that the jump process above was able to fully remove all the initial infected individuals before any new ones. - -.. ipython:: - - In [1]: simX,simT = odeS.simulate_jump(t, 5, full_output=True) - - In [1]: simMean = np.mean(simX, axis=0) - - In [1]: f, axarr = plt.subplots(1,3) - - In [1]: for solution in simX: - ...: axarr[0].plot(t, solution[:,0]) - ...: axarr[1].plot(t, solution[:,1]) - ...: axarr[2].plot(t, solution[:,2]) - - @savefig stochastic_process_compare_large_n_curves.png - In [1]: plt.show() - - In [1]: plt.close() - - -Repeatable Simulation -===================== - -One of the possible use of compartmental models is to generate forecasts. Although most of the time the requirement would be to have (at least point-wise) convergence in the limit, reproducibility is also important. For both types of interpretation explained above, we have given the package the capability to repeat the simulations by setting a seed. When the assumption is that the parameters follows some sort of distribution, we simply set the seed which governs the global state of the random number generator. - -.. ipython:: - - In [1]: x0 = [2362206.0, 3.0, 0.0] - - In [1]: odeS = SimulateOde(stateList, paramList, transition=transitionList) - - In [1]: d = {'beta': st.gamma(a=100.0, scale=1.0/200.0), 'gamma': st.gamma(a=100.0, scale=1.0/300.0), 'N': x0[0]} - - In [1]: odeS.parameters = d - - In [1]: odeS.initial_values = (x0, t[0]) - - In [1]: Ymean, Yall = odeS.simulate_param(t[1::], 10, full_output=True) - - In [1]: np.random.seed(1) - - In [1]: Ymean1, Yall1 = odeS.simulate_param(t[1::], 10, full_output=True) - - In [1]: np.random.seed(1) - - In [1]: Ymean2, Yall2 = odeS.simulate_param(t[1::], 10, full_output=True) - - In [1]: sim_diff = [np.linalg.norm(Yall[i] - yi) for i, yi in enumerate(Yall1)] - - In [1]: sim_diff12 = [np.linalg.norm(Yall2[i] - yi) for i, yi in enumerate(Yall1)] - - In [1]: print("Different in the simulations and the mean: (%s, %s) " % (np.sum(sim_diff), np.sum(np.abs(Ymean1 - Ymean)))) - - In [1]: print("Different in the simulations and the mean using same seed: (%s, %s) " % (np.sum(sim_diff12), np.sum(np.abs(Ymean2 - Ymean1)))) - -In the alternative interpretation, setting the global seed is insufficient. Unlike simulation based on the parameters, where we can pre-generate all the parameter values and send them off to individual processes in the parallel backend, this is prohibitive here. In a nutshell, the seed does not propagate when using a parallel backend because each *integration* requires an unknown number of random samples. Therefore, we have an additional flag **parallel** in the function signature. By ensuring that the computation runs in serial, we can make use of the global seed and generate identical runs. - -.. ipython:: - - In [1]: x0 = [2362206.0, 3.0, 0.0] - - In [1]: odeS = SimulateOde(stateList, paramList, transition=transitionList) - - In [1]: odeS.parameters = [0.5, 1.0/3.0, x0[0]] - - In [1]: odeS.initial_values = (x0, t[0]) - - In [1]: simX, simT = odeS.simulate_jump(t[1:10], 10, parallel=False, full_output=True) - - In [1]: np.random.seed(1) - - In [1]: simX1, simT1 = odeS.simulate_jump(t[1:10], 10, parallel=False, full_output=True) - - In [1]: np.random.seed(1) - - In [1]: simX2, simT2 = odeS.simulate_jump(t[1:10], 10, parallel=False, full_output=True) - - In [1]: sim_diff = [np.linalg.norm(simX[i] - x1) for i, x1 in enumerate(simX1)] - - In [1]: sim_diff12 = [np.linalg.norm(simX2[i] - x1) for i, x1 in enumerate(simX1)] - - In [1]: print("Difference in simulation: %s" % np.sum(np.abs(sim_diff))) - - In [1]: print("Difference in simulation using same seed: %s" % np.sum(np.abs(sim_diff12))) - diff --git a/doc/doc_to_sort/transition.rst b/doc/doc_to_sort/transition.rst deleted file mode 100644 index a36959db..00000000 --- a/doc/doc_to_sort/transition.rst +++ /dev/null @@ -1,183 +0,0 @@ -.. _transition: - -***************** -Transition Object -***************** - -The most important part of setting up the model is to correctly define the set odes, which is based solely on the classes defined in :mod:`transition`. All transitions that gets fed into the ode system needs to be defined as a transition object, :class:`Transition`. It takes a total of four input arguments - -#. The origin state -#. Equation that describe the process -#. The type of transition -#. The destination state - -where the first three are mandatory. To demonstrate, we go back to the SIR model defined previously in the section :ref:`sir`. Recall that the set of odes are - -.. math:: - - \frac{\partial S}{\partial t} &= -\beta SI \\ - \frac{\partial I}{\partial t} &= \beta SI - \gamma I \\ - \frac{\partial R}{\partial t} &= \gamma I. - -We can simply define the set of ode, as seen previously, via - -.. ipython:: - - In [1]: from pygom import Transition, TransitionType, common_models - - In [2]: ode1 = Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.ODE) - - In [3]: ode2 = Transition(origin='I', equation='beta*S*I - gamma*I', transition_type=TransitionType.ODE) - - In [4]: ode3 = Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE) - -Note that we need to state explicitly the type of equation we are inputting, which is simply of type **ODE** in this case. We can confirm this has been entered correctly by putting it into :class:`DeterministicOde` - -.. ipython:: - - In [1]: from pygom import DeterministicOde - - In [2]: stateList = ['S', 'I', 'R'] - - In [3]: paramList = ['beta', 'gamma'] - - In [4]: model = DeterministicOde(stateList, - ...: paramList, - ...: ode=[ode1, ode2, ode3]) - -and check it - -.. ipython:: - - In [1]: model.get_ode_eqn() - -An alternative print function :func:`print_ode` is also available which may be more suitable in other situation. The default prints the formula in a rendered format and another which prints out the latex format which can be used directly in a latex document. The latter is useful as it saves typing out the formula twice, once in the code and another in documents. - -.. ipython:: - - In [1]: model.print_ode(False) - - In [2]: model.print_ode(True) - -Now we are going to show the different ways of defining the same set of odes. - -.. _defining-eqn: - -Defining the equations -====================== - -Recognizing that the set of odes defining the SIR model is the result of two transitions, - -.. math:: - - S \rightarrow I &= \beta SI \\ - I \rightarrow R &= \gamma I - -where :math:`S \rightarrow I` denotes a transition from state :math:`S` to state :math:`I`. Therefore, we can simply define our model by these two transition, but now these two transition needs to be inputted via the ``transition`` argument instead of the ``ode`` argument. Note that we are initializing the model using a different class, because the stochastic implementation has more operation on transitions. - -.. ipython:: - - In [600]: from pygom import SimulateOde - - In [601]: t1 = Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T) - - In [602]: t2 = Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) - - In [603]: modelTrans = SimulateOde(stateList, - .....: paramList, - .....: transition=[t1, t2]) - - In [604]: modelTrans.get_ode_eqn() - -We can see that the resulting ode is exactly the same, as expected. The transition matrix that defines this process can easily be visualized using graphviz. Because only certain renderer permit the use of sub and superscript, operators such as :math:`**` are left as they are in the equation. - -.. ipython:: - - In [1]: import matplotlib.pyplot as plt - - In [2]: f = plt.figure() - - In [3]: modelTrans.get_transition_matrix() - - @savefig sir_transition_graph.png - In [4]: dot = modelTrans.get_transition_graph() - -If we put in via the wrong argument like below (not run), then an error will appear. - -.. ipython:: - - In [1]: # modelTrans = DeterministicOde(stateList, paramList, ode=[t1, t2]) - -because :class:`TranstionType` was defined explicitly as a transition instead of an ode. The same can be observed when the wrong :class:`TransitionType` is used for any of the input argument. - -This though, only encourages us to define the transitions carefully. We can also pretend that the set of odes are in fact just a set of birth process - -.. ipython:: - - In [619]: birth1 = Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.B) - - In [620]: birth2 = Transition(origin='I', equation='beta*S*I - gamma*I', transition_type=TransitionType.B) - - In [621]: birth3 = Transition(origin='R', equation='gamma*I', transition_type=TransitionType.B) - - In [622]: modelBirth = DeterministicOde(stateList, - .....: paramList, - .....: birth_death=[birth1, birth2, birth3]) - - In [623]: modelBirth.get_ode_eqn() - -which will yield the same set result. Alternatively, we can use the negative of the equation but set it to be a death process. For example, we multiply the equations for state :math:`S` and :math:`R` with a negative sign and set the transition type to be a death process instead. - -.. ipython:: - - In [624]: death1 = Transition(origin='S', equation='beta*S*I', transition_type=TransitionType.D) - - In [625]: birth2 = Transition(origin='I', equation='beta*S*I - gamma*I', transition_type=TransitionType.B) - - In [626]: death3 = Transition(origin='R', equation='-gamma*I', transition_type=TransitionType.D) - - In [627]: modelBD = DeterministicOde(stateList, - .....: paramList, - .....: birth_death=[death1, birth2, death3]) - - In [628]: modelBD.get_ode_eqn() - - -We can see that all the above ways yield the same set of ode at the end. - -Model Addition -============== - -Because we allow the separation of transitions between states and birth/death processes, the birth/death processes can be added later on. - -.. ipython:: - - In [1]: modelBD2 = modelTrans - - In [1]: modelBD2.param_list = paramList + ['mu', 'B'] - - In [1]: birthDeathList = [Transition(origin='S', equation='B', transition_type=TransitionType.B), - ...: Transition(origin='S', equation='mu*S', transition_type=TransitionType.D), - ...: Transition(origin='I', equation='mu*I', transition_type=TransitionType.D)] - - In [1]: modelBD2.birth_death_list = birthDeathList - - In [1]: modelBD2.get_ode_eqn() - -So modeling can be done in stages. Start with a standard closed system and extend it with additional flows that interact with the environment. - -.. _transition-type: - -Transition type -=============== - -There are currently four different type of transitions allowed, which is defined in an enum class also located in :mod:`transition`. The four types are B, D, ODE and T, where they represent different type of process with explanation in their corresponding value. - -.. ipython:: - - In [1]: from pygom import transition - - In [2]: for i in transition.TransitionType: - ...: print(str(i) + " = " + i.value) - -Each birth process are added to the origin state while each death process are deducted from the state, i.e. added to the state after multiplying with a negative sign. An ode type is also added to the state and we forbid the number of input ode to be greater than the number of state inputted. diff --git a/doc/doc_to_sort/unroll/unrollBD.rst b/doc/doc_to_sort/unroll/unrollBD.rst deleted file mode 100644 index b8be3a88..00000000 --- a/doc/doc_to_sort/unroll/unrollBD.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. _unrollBD: - -ODE With Birth and Death Process -================================ - -We follow on from the SIR model of :ref:`unrollSimple` but with additional birth and death processes. - -.. math:: - - \frac{dS}{dt} &= -\beta SI + B - \mu S\\ - \frac{dI}{dt} &= \beta SI - \gamma I - \mu I\\ - \frac{dR}{dt} &= \gamma I. - -which consists of two transitions and three birth and death process - -.. graphviz:: - - digraph SIR_Model { - rankdir=LR; - size="8" - node [shape = circle]; - S -> I [ label = "βSI" ]; - I -> R [ label = "γI" ]; - B [height=0 margin=0 shape=plaintext width=0]; - B -> S; - "S**2*μ" [height=0 margin=0 shape=plaintext width=0]; - S -> "S**2*μ"; - "I*μ" [height=0 margin=0 shape=plaintext width=0]; - I -> "I*μ"; - } - -Let's define this in terms of ODEs, and unroll it back to the individual processes. - -.. ipython:: - - In [1]: from pygom import Transition, TransitionType, SimulateOde, common_models - - In [1]: import matplotlib.pyplot as plt - - In [1]: stateList = ['S', 'I', 'R'] - - In [1]: paramList = ['beta', 'gamma', 'B', 'mu'] - - In [1]: odeList = [ - ...: Transition(origin='S', - ...: equation='-beta*S*I + B - mu*S', - ...: transition_type=TransitionType.ODE), - ...: Transition(origin='I', - ...: equation='beta*S*I - gamma*I - mu*I', - ...: transition_type=TransitionType.ODE), - ...: Transition(origin='R', - ...: equation='gamma*I', - ...: transition_type=TransitionType.ODE) - ...: ] - - In [1]: ode = SimulateOde(stateList, paramList, ode=odeList) - - In [1]: ode2 = ode.get_unrolled_obj() - - In [1]: f = plt.figure() - - @savefig sir_unrolled_transition_graph.png - In [1]: ode2.get_transition_graph() - - In [1]: plt.close() - diff --git a/doc/doc_to_sort/unroll/unrollHard.rst b/doc/doc_to_sort/unroll/unrollHard.rst deleted file mode 100644 index 2361cf4d..00000000 --- a/doc/doc_to_sort/unroll/unrollHard.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _unrollHard: - -Hard Problem -============ - -Now we turn to a harder problem that does not have a one to one mapping between all the transitions and the terms in the ODEs. We use the model in :func:`Influenza_SLIARN`, defined by - -.. math:: - \frac{dS}{dt} &= -S \beta (I + \delta A) \\ - \frac{dL}{dt} &= S \beta (I + \delta A) - \kappa L \\ - \frac{dI}{dt} &= p \kappa L - \alpha I \\ - \frac{dA}{dt} &= (1 - p) \kappa L - \eta A \\ - \frac{dR}{dt} &= f \alpha I + \eta A \\ - \frac{dN}{dt} &= -(1 - f) \alpha I. - -The outflow of state **L**, :math:`\kappa L`, is composed of two transitions, one to **I** and the other to **A** but the ode of **L** only reflects the total flow going out of the state. Same can be said for state **I**, where the flow :math:`\alpha I` goes to both **R** and **N**. Graphically, it is a rather simple process as shown below. - -.. graphviz:: - - digraph SLIARD_Model { - labelloc = "t"; - label = "Original transitions"; - rankdir=LR; - size="8" - node [shape = circle]; - S -> L [ label = "-Sβ(I + δA)/N" ]; - L -> I [ label = "κLp" ]; - L -> A [ label = "κL(1-p)" ]; - I -> R [ label = "αIf" ]; - I -> D [ label = "αI(1-f)" ]; - A -> R [ label = "ηA" ]; - } - -We slightly change the model by introducing a new state **D** to convert it into a closed system. The combination of state **D** and **N** is a constant, the total population. So we can remove **N** and this new system consist of six transitions. We define them explicitly as ODEs and unroll them into transitions. - -.. ipython:: - - In [1]: from pygom import SimulateOde, Transition, TransitionType - - In [1]: stateList = ['S', 'L', 'I', 'A', 'R', 'D'] - - In [2]: paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon', 'N'] - - In [3]: odeList = [ - ...: Transition(origin='S', equation='- beta*S/N*(I + delta*A)', transition_type=TransitionType.ODE), - ...: Transition(origin='L', equation='beta*S/N*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE), - ...: Transition(origin='I', equation='p*kappa*L - alpha*I', transition_type=TransitionType.ODE), - ...: Transition(origin='A', equation='(1 - p)*kappa * L - epsilon*A', transition_type=TransitionType.ODE), - ...: Transition(origin='R', equation='f*alpha*I + epsilon*A', transition_type=TransitionType.ODE), - ...: Transition(origin='D', equation='(1 - f)*alpha*I', transition_type=TransitionType.ODE) ] - - In [4]: ode = SimulateOde(stateList, paramList, ode=odeList) - - In [5]: ode.get_transition_matrix() - - In [6]: ode2 = ode.get_unrolled_obj() - - In [7]: ode2.get_transition_matrix() - - In [8]: ode2.get_ode_eqn() - -After unrolling the odes, we have the following transition graph - -.. ipython:: - - @savefig sir_unrolled_transition_graph_hard.png - In [1]: ode2.get_transition_graph() - - In [2]: plt.close() - - In [3]: print(sum(ode.get_ode_eqn() - ode2.get_ode_eqn()).simplify()) # difference - -which is exactly the same apart from slightly weird arrangement of symbols in some of the equations. The last line with a value of zero also reaffirms the result. diff --git a/doc/doc_to_sort/unroll/unrollSimple.rst b/doc/doc_to_sort/unroll/unrollSimple.rst deleted file mode 100644 index 21d3948a..00000000 --- a/doc/doc_to_sort/unroll/unrollSimple.rst +++ /dev/null @@ -1,54 +0,0 @@ -.. _unrollSimple: - -Simple Problem -============== - -For a simple problem, we consider the SIR model defined by - -.. math:: - - \frac{dS}{dt} &= -\beta SI \\ - \frac{dI}{dt} &= \beta SI - \gamma I \\ - \frac{dR}{dt} &= \gamma I. - -which consists of two transitions - -.. graphviz:: - - digraph SIR_Model { - rankdir=LR; - size="8" - node [shape = circle]; - S -> I [ label = "βSI" ]; - I -> R [ label = "γI" ]; - } - -Let's define this using the code block below - -.. ipython:: - - In [1]: from pygom import SimulateOde, Transition, TransitionType - - In [2]: ode1 = Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.ODE) - - In [3]: ode2 = Transition(origin='I', equation='beta*S*I - gamma*I', transition_type=TransitionType.ODE) - - In [4]: ode3 = Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE) - - In [6]: stateList = ['S', 'I', 'R'] - - In [7]: paramList = ['beta', 'gamma'] - - In [8]: ode = SimulateOde(stateList, - ...: paramList, - ...: ode=[ode1, ode2, ode3]) - - In [9]: ode.get_transition_matrix() - -and the last line shows that the transition matrix is empty. This is the expected result because :class:`SimulateOdeModel` was not initialized using transitions. We populate the transition matrix below and demonstrate the difference. - -.. ipython:: - - In [1]: ode = ode.get_unrolled_obj() - - In [2]: ode.get_transition_matrix() diff --git a/doc/doc_to_sort/unrollOde.rst b/doc/doc_to_sort/unrollOde.rst deleted file mode 100644 index 09b44cef..00000000 --- a/doc/doc_to_sort/unrollOde.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _unrollOde: - -**************************** -Convert ODE into transitions -**************************** - -As seen previously in :ref:`transition`, we can define the model via the transitions or explicitly as ODEs. There are times when we all just want to test out some model in a paper and the only available information are the ODEs themselves. Even though we know that the ODEs come from some underlying transitions, breaking them down can be a time consuming process. We provide the functionalities to do this automatically. - -.. toctree:: - - unroll/unrollSimple.rst - unroll/unrollBD.rst - unroll/unrollHard.rst diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index 597a35c2..00000000 --- a/doc/make.bat +++ /dev/null @@ -1,113 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation -set SPHINXBUILD=sphinx-build -set BUILDDIR=_build -set SPHINXOPTS= -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pyGenericOdeModelDoc.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pyGenericOdeModelDoc.ghc - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -:end diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index d6e1e29a..00000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -dask[complete]>=0.13.0 -graphviz>=0.4.9 -matplotlib>=1.0.0 -numpy>=1.6.0 -pandas>=0.15.0 -python-dateutil>=2.0.0 -scipy>=0.10.0 -sympy>=1.0.0 -numpydoc>=0.6.0 -#sphinx>=1.4.1 -#sphinx_rtd_theme>=0.2.0 -#ipython>=7.1.1 -jupyter-book diff --git a/doc/source/_static/.gitignore b/doc/source/_static/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index dc804650..00000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,264 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is execfile() with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os -import warnings - -#slight hack for graphvis on windows to ensure conda path is correct -#if sys.platform == 'win32': -# os.environ['PATH'] += os.pathsep + os.environ['CONDA_PREFIX'] + r'\Library\bin\graphviz' - -import sphinx -if sphinx.__version__ < '1.4.1': - raise RuntimeError("Sphinx 1.4.1 or newer required") - -import pygom - -needs_sphinx = '1.4.1' - -# 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. -sys.path.append(os.path.abspath('.')) -sys.path.append(os.path.abspath('sphinxext')) -#sys.path.append(os.path.abspath('../pygom')) - -# -- 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.mathjax', # 'sphinx.ext.imgmath', - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.graphviz',# 'matplotlib.sphinxext.only_directives', - 'matplotlib.sphinxext.plot_directive', - 'numpydoc', - 'IPython.sphinxext.ipython_console_highlighting', - 'IPython.sphinxext.ipython_directive', - 'nbsphinx' - ] - -# the mapping for code in other packages -intersphinx_mapping = {'matplotlib': ('http://matplotlib.org/', None), - 'numpy': ('https://docs.scipy.org/doc/numpy/', None), - 'python': ('https://docs.python.org/2', None), - 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', None), - 'sympy': ('http://docs.sympy.org/latest/', None)} - -numpydoc_show_class_members = False - - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'PyGOM Documentation' -copyright = '2015-2019, Public Health England' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = pygom.__version__ -# The full version, including alpha/beta/rc tags. -release = pygom.__version__ - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -#Set the directory to save figures in -ipython_savefig_dir = 'savefig' -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -#['alabaster',sphinx_rtd_theme','classic','sphinxdoc','scrolls','agogo', -# 'traditional','nature','haiku','pyramid','bizstyle'] -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' -if not on_rtd: # only import and set the theme if we're building docs locally - import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - exclude_patterns = ['doc_to_sort.*'] -else: - # RTD will time out if we try to build the whole of the documentation so - # ignore some of the longer bits and perhaps add them later - # // TODO: speed up runtime for longer examples for readthedocs - exclude_patterns = ['common_models/*.rst', -# 'bvpSimple.rst', - 'epi.rst', -# 'estimate1.rst', - 'estimate2.rst', - 'gradient.rst', - 'epijson.rst', - 'fh.rst', -# 'getting_started.rst', - 'initialGuess.rst', - 'profile.rst', - 'sir.rst', -# 'stochastic.rst', -# 'transition.rst' - ] - -# html_theme = 'sphinx_rtd_theme' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_use_modindex = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'PyGOM Documentation' - -html_add_permalinks = '' - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'PyGOM.tex', 'PyGOM Documentation', - 'Edwin Tye', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -latex_preamble = '\\usepackage{amsmath,amssymb}' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_use_modindex = True - -# latex_encodings = 'utf-8' -warnings.filterwarnings("ignore", category=UserWarning, - message='Matplotlib is currently using agg, which is a' - ' non-GUI backend, so cannot show the figure.') diff --git a/doc/source/getting_started.rst b/doc/source/getting_started.rst deleted file mode 100644 index cf58249b..00000000 --- a/doc/source/getting_started.rst +++ /dev/null @@ -1,87 +0,0 @@ -.. _getting_started: - -*************** -Getting started -*************** - -.. _package-purpose: - -What this package does -====================== - -The purpose of this package is to allow the end user to easily define a set of -ordinary differential equations (ODE) and obtain information about the ODE by -invoking the the appropriate methods. Here, we define the set of ODE's -as - -.. math:: - \frac{\partial \mathbf{x}}{\partial t} = f(\mathbf{x},\boldsymbol{\theta}) - -where :math:`\mathbf{x} = \left(x_{1},x_{2},\ldots,x_{n}\right)` is the state -vector with :math:`d` state and :math:`\boldsymbol{\theta}` the parameters of -:math:`p` dimension. Currently, this package allows the user to find the -algebraic expression of the ODE, Jacobian, gradient and forward sensitivity of -the ODE. A numerical output is given when all the state and parameter values -are provided. Note that the only important class is :file:`DeterministicOde` -where all the functionality described previously are exposed. - -The current plan is to extend the functionality to include - -* Solving the ode analytically when it is linear - -* Analysis of the system via eigenvalues during the integration - -* Detection of DAE - - -.. _installing-docdir: - -Obtaining the package -===================== - -The location of the package is current on GitHub and can be pulled via https -from:: - - https://github.com/PublicHealthEngland/pygom.git - -The package is currently as follows:: - - pygom/ - bin/ - doc/ - pygom/ - loss/ - tests/ - model/ - tests/ - sbml_translate/ - utilR/ - LICENSE.txt - README.rst - requirements.txt - setup.py - -with files in each of the three main folders not shown. You can install the -package via command line:: - - python setup.py install - -or locally on a user level:: - - python setup.py install --user - -Please note that there are current redundant file are kept for development -purposes for the time being. - -.. _testing-the-package: - -Testing the package -=================== - -Testing can be performed prior or after the installation. Some standard test -files can be found in their respective folder and they can be run in the command -line:: - - python setup.py test - -which can be performed prior to installing the package if desired. diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index e4625e13..00000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,63 +0,0 @@ -##################################### -Welcome to the documentation of pygom -##################################### - -PyGOM (Python Generic ODE Model) is a Python package that aims to facilitate the application of ordinary differential equations (ODEs) in the real world, -with a focus in epidemiology. -This package helps the user define their ODE system in an intuitive manner and provides convenience functions - -making use of various algebraic and numerical libraries in the backend - that can be used in a straight forward fashion. - -This is an open source project hosted on `Github `_. - -A manuscript containing a shortened motivation and use is hosted on `arxXiv `_. - -# // TODO Insert intro text - -################## -User Documentation -################## - -.. toctree:: - :maxdepth: 5 - - getting_started.rst - #sir.rst - #notebooks/sir.ipynb - #transition.rst - #stochastic.rst - #unrollOde.rst - #epi.rst - #epijson.rst - #bvpSimple.rst - #gradient.rst - #fh.rst - #estimate1.rst - #estimate2.rst - #initialGuess.rst - #profile.rst - #common_models.rst - -########################## -Code Documentation and FAQ -########################## - -.. toctree:: - :maxdepth: 5 - - #faq.rst - #mod/index.rst - -########## -References -########## - -.. toctree:: - - #ref.rst - -################## -Indices and tables -################## - -* :ref:`genindex` -* :ref:`modindex` diff --git a/doc/source/sir.rst b/doc/source/sir.rst deleted file mode 100644 index 86ed2b22..00000000 --- a/doc/source/sir.rst +++ /dev/null @@ -1,281 +0,0 @@ -.. _sir: - -***************************** -Motivating Example: SIR Model -***************************** - -Defining the model -================== - -First, we are going to go through an SIR model to show the functionality of the package. The SIR model is defined by the following equations - -.. math:: - - \frac{dS}{dt} &= -\beta SI \\ - \frac{dI}{dt} &= \beta SI- \gamma I \\ - \frac{dR}{dt} &= \gamma I. - -We can set this up as follows - -.. ipython:: - - In [32]: # first we import the classes require to define the transitions - - In [33]: from pygom import Transition, TransitionType - - In [34]: # define our state - - In [35]: stateList = ['S', 'I', 'R'] - - In [36]: # and the set of parameters, which only has two - - In [37]: paramList = ['beta', 'gamma'] - - In [38]: # then the set of ode - - In [38]: odeList = [ - ....: Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.ODE), - ....: Transition(origin='I', equation='beta*S*I - gamma*I', transition_type=TransitionType.ODE), - ....: Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE) - ....: ] - -Here, we have invoke a class from :mod:`Transition` to define the transition object. We proceed here and ignore the details for now. The details of defining a transition object will be covered later in :ref:`transition`. Both the set of states and parameters should be defined when constructing the object, even though not explicitly enforced, to help clarify what we are trying to model. Similarly, this holds for the rest, such as the derived parameters and transitions, where we force the end user to input the different type of transition/process via the corret argument. See :ref:`defining-eqn` for an example when the input is wrong. - -.. ipython:: - - In [39]: # now we import the ode module - - In [40]: from pygom import DeterministicOde - - In [41]: # initialize the model - - In [42]: model = DeterministicOde(stateList, - ....: paramList, - ....: ode=odeList) - -That is all the information required to define a simple SIR model. We can verify the equations by - -.. ipython:: - - In [40]: model.get_ode_eqn() - -where we can see the equations corresponding to their respective :math:`S,I` and :math:`R` state. The set of ode is in the standard :math:`S,I,R` sequence because of how the states are defined initially. We can change them around - -.. ipython:: - - In [59]: # now we are going to define in a different order. note that the output ode changed with the input state - - In [60]: stateList = ['R', 'S', 'I'] - - In [61]: model = DeterministicOde(stateList, - ....: paramList, - ....: ode=odeList) - - In [62]: model.get_ode_eqn() - -and find that the set of ode's still comes out in the correct order with respect to how the states are ordered. In addition to showing the ode in English, we can also display it as either symbols or latex code which save some extra typing when porting the equations to a proper document. - -.. ipython:: - - In [1]: model.print_ode() - - In [2]: model.print_ode(True) - -The SIR model above was defined as a set of explicit ODEs. An alternative way is to define the model using a series of transitions between the states. We have provided the capability to obtain a *best guess* transition matrix when only the ODEs are available. See the section :ref:`unrollOde` for more information, and in particular :ref:`unrollSimple` for the continuing demonstration of the SIR model. - - -Model information -================= - -The most obvious thing information we wish to know about an ode is whether it is linear - -.. ipython:: - - In [65]: model.linear_ode() - -which we know is not for an SIR. So we may want to have a look at the Jacobian say, it is as simple as - -.. ipython:: - - In [64]: model.get_jacobian_eqn() - -or maybe we want to know the gradient (of the ode) - -.. ipython:: - - In [65]: model.get_grad_eqn() - -Invoking the functions that computes :math:`f(x)` (or the derivatives) like below will output an error (not run) - -.. ipython:: - - In [66]: # model.ode() - - In [67]: # model.jacobian() - -This is because the some of the functions are used to solve the ode numerically and expect input values of both state and time. But just invoking the two methods above without defining the parameter value, such as the second line below, will also throws an error. - -.. ipython:: - - In [77]: initialState = [0, 1, 1.27e-6] - - In [78]: # model.ode(state=initialState, t=1) - -It is important to note at this point that the numeric values of the states need to be set in the correct order against the list of states, which can be found by - -.. ipython:: - - In [79]: model.state_list - -There is currently no mechanism to set the numeric values of the states along with the state. This is because of implementation issue with external package, such as solving an initial value problem. - -Initial value problem -===================== - -Setting the parameters will allow us to evaluate - -.. ipython:: - - In [80]: # define the parameters - - In [81]: paramEval = [ - ....: ('beta',0.5), - ....: ('gamma',1.0/3.0) - ....: ] - - In [82]: model.parameters = paramEval - - In [83]: model.ode(initialState, 1) - -Now we are well equipped with solving an initial value problem, using standard numerical integrator such as :func:`odeint ` from :mod:`scipy.integrate`. We also used :mod:`matplotlib.pyplot` for plotting and :func:`linspace ` to create the time vector. - -.. ipython:: - - In [96]: import scipy.integrate - - In [97]: import numpy - - In [98]: t = numpy.linspace(0, 150, 100) - - In [99]: solution = scipy.integrate.odeint(model.ode, initialState, t) - - In [100]: import matplotlib.pyplot as plt - - In [101]: plt.figure(); - - In [102]: plt.plot(t, solution[:,0], label='R'); - - In [103]: plt.plot(t, solution[:,1], label='S'); - - In [104]: plt.plot(t, solution[:,2], label='I'); - - In [105]: plt.xlabel('Time'); - - In [106]: plt.ylabel('Population proportion'); - - In [107]: plt.title('Standard SIR model'); - - In [108]: plt.legend(loc=0); - - @savefig sir_plot.png - In [109]: plt.show(); - - In [110]: plt.close() - -Where a nice standard SIR progression can be observed in the figure above. Alternatively, we can also integrate and plot via the **ode** object which we have initialized. - -.. ipython:: - - In [1]: model.initial_values = (initialState, t[0]) - - In [2]: model.parameters = paramEval - - In [3]: solution = model.integrate(t[1::]) - - In [4]: model.plot() - -The plot is not shown as it is identical to the one above without the axis labels. Obviously, we can solve the ode above using the Jacobian as well. Unfortunately, it does not help because the number of times the Jacobian was evaluated was zero, as expected given that our set of equations are not stiff. - -.. ipython:: - - In [583]: %timeit solution1, output1 = scipy.integrate.odeint(model.ode, initialState, t, full_output=True) - - In [584]: %timeit solution2, output2 = scipy.integrate.odeint(model.ode, initialState, t, Dfun=model.jacobian, mu=None, ml=None, full_output=True) - - In [584]: %timeit solution3, output3 = model.integrate(t, full_output=True) - -It is important to note that we return our Jacobian as a dense square matrix. Hence, the two argument (mu,ml) for the ode solver was set to ``None`` to let it know the output explicitly. - -Solving the forward sensitivity equation -======================================== - -Likewise, the sensitivity equations are also solved as an initial value problem. Let us redefine the model in the standard SIR order and we solve it with the sensitivity all set at zero, i.e. we do not wish to infer the initial value of the states - -.. ipython:: - - In [452]: stateList = ['S', 'I', 'R'] - - In [453]: model = DeterministicOde(stateList, - .....: paramList, - .....: ode=odeList) - - In [454]: initialState = [1, 1.27e-6, 0] - - In [455]: paramEval = [ - .....: ('beta', 0.5), - .....: ('gamma', 1.0/3.0) - .....: ] - - In [456]: model.parameters = paramEval - - In [457]: solution = scipy.integrate.odeint(model.ode_and_sensitivity, numpy.append(initialState, numpy.zeros(6)), t) - - In [458]: f,axarr = plt.subplots(3,3); - - In [459]: # f.text(0.5,0.975,'SIR with forward sensitivity solved via ode',fontsize=16,horizontalalignment='center',verticalalignment='top'); - - In [460]: axarr[0,0].plot(t, solution[:,0]); - - In [461]: axarr[0,0].set_title('S'); - - In [462]: axarr[0,1].plot(t, solution[:,1]); - - In [463]: axarr[0,1].set_title('I'); - - In [464]: axarr[0,2].plot(t, solution[:,2]); - - In [465]: axarr[0,2].set_title('R'); - - In [466]: axarr[1,0].plot(t, solution[:,3]); - - In [467]: axarr[1,0].set_title(r'state S parameter $\beta$'); - - In [468]: axarr[2,0].plot(t, solution[:,4]); - - In [469]: axarr[2,0].set_title(r'state S parameter $\gamma$'); - - In [470]: axarr[1,1].plot(t, solution[:,5]); - - In [471]: axarr[1,1].set_title(r'state I parameter $\beta$'); - - In [472]: axarr[2,1].plot(t, solution[:,6]); - - In [473]: axarr[2,1].set_title(r'state I parameter $\gamma$'); - - In [474]: axarr[1,2].plot(t, solution[:,7]); - - In [475]: axarr[1,2].set_title(r'state R parameter $\beta$'); - - In [476]: axarr[2,2].plot(t, solution[:,8]); - - In [477]: axarr[2,2].set_title(r'state R parameter $\gamma$'); - - In [478]: plt.tight_layout(); - - @savefig sir_sensitivity_plot.png - In [480]: plt.show(); - - In [481]: plt.close() - -This concludes the introductory example and we will be moving on to look at parameter estimation next in :ref:`estimate1` and the most important part in terms of setting up the ode object; defining the equations in various different ways in :ref:`transition`. - diff --git a/docs/_config.yml b/docs/_config.yml index 3b1d7024..84aebe0b 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -14,6 +14,7 @@ only_build_toc_files: true # this could avoid the issue of execution timing out # See https://jupyterbook.org/content/execute.html execute: + allow_errors: true execute_notebooks: cache timeout: -1 diff --git a/docs/_toc.yml b/docs/_toc.yml index 08486baa..2ab98058 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -4,47 +4,65 @@ format: jb-book root: md/intro parts: - - caption: User documentation + - caption: Getting started chapters: - - file: md/getting_started - - file: notebooks/sir - - file: notebooks/transition - - file: notebooks/stochastic - - file: md/unrollOde - sections: - - file: notebooks/unroll/unrollSimple - - file: notebooks/unroll/unrollBD - - file: notebooks/unroll/unrollHard - - file: notebooks/epi - - file: notebooks/epijson + - file: md/installation + - file: md/building_doc + - caption: PyGOM workflow + chapters: + - file: notebooks/model_spec + - file: notebooks/insights + sections: + - file: notebooks/extract_info + #- file: notebooks/epi + - file: notebooks/unroll/unrollSimple + - file: md/solving + sections: + - file: notebooks/model_params + - file: notebooks/model_solver + - file: notebooks/time_dependent_params + #- file: notebooks/transition + # - file: md/unrollOde + # sections: + # - file: notebooks/unroll/unrollSimple + # - file: notebooks/unroll/unrollBD + # - file: notebooks/unroll/unrollHard - file: md/parameter_fitting sections: + - file: notebooks/paramfit/params_via_abc + - file: notebooks/paramfit/params_via_optimization - file: notebooks/paramfit/bvpSimple - - file: notebooks/paramfit/gradient - - file: notebooks/paramfit/fh - - file: notebooks/paramfit/estimate1 - - file: notebooks/paramfit/estimate2 - - file: notebooks/paramfit/initialGuess - - file: notebooks/paramfit/profile + - file: notebooks/epijson + # - file: notebooks/paramfit/gradient + # - file: notebooks/paramfit/fh + # - file: notebooks/paramfit/estimate1 + # - file: notebooks/paramfit/estimate2 + # - file: notebooks/paramfit/initialGuess + # - file: notebooks/paramfit/profile + #- caption: Appendix + # chapters: + # - file: notebooks/paramfit/gradient + # - file: notebooks/paramfit/profile - caption: Common biological compartmental models chapters: - file: md/common_models sections: - file: notebooks/common_models/SIS + - file: notebooks/common_models/SIR + - file: notebooks/common_models/SEIR - file: notebooks/common_models/SIS_Periodic - - file: notebooks/common_models/SIR - file: notebooks/common_models/SIR_Birth_Death - - file: notebooks/common_models/SEIR - - file: notebooks/common_models/SEIR_Multiple - - file: notebooks/common_models/SEIR_Birth_Death - - file: notebooks/common_models/SEIR_Birth_Death_Periodic + - file: notebooks/common_models/SEIR_Multiple + - file: notebooks/common_models/SEIR_Birth_Death_Periodic_Waning_Intro + #- file: notebooks/common_models/SEIR_Birth_Death + #- file: notebooks/common_models/SEIR_Birth_Death_Periodic - file: notebooks/common_models/Legrand_Ebola_SEIHFR - file: notebooks/common_models/Lotka_Volterra - - file: notebooks/common_models/Lotka_Volterra_4State + #- file: notebooks/common_models/Lotka_Volterra_4State - file: notebooks/common_models/FitzHugh - - file: notebooks/common_models/Lorenz - - file: notebooks/common_models/vanDelPol - - file: notebooks/common_models/Robertson + #- file: notebooks/common_models/Lorenz + #- file: notebooks/common_models/vanDelPol + #- file: notebooks/common_models/Robertson - caption: Frequently asked questions chapters: - file: md/faq diff --git a/docs/bib/ref.bib b/docs/bib/ref.bib index b7509dd4..86fd6ec2 100644 --- a/docs/bib/ref.bib +++ b/docs/bib/ref.bib @@ -60,16 +60,15 @@ @article{FitzHugh1961 volume = {1}, year = {1961}, } -@inproceedings{Gillespie1977, - abstract = {There are two formalisms for mathematically describing the time behavior of a spatially homogeneous chemical system: The deterministic approach regards the time evolution as a continuous, wholly predictable process which is governed by a set of coupled, ordinary differential equations (the "reaction-rate equations"); the stochastic approach regards the time evolution as a kind of random-walk process which is governed by a single differential-difference equation (the "master equation"). Fairly simple kinetic theory arguments show that the stochastic formulation of chemical kinetics has a firmer physical basis than the deterministic formulation, but unfortunately the stochastic master equation is often mathematically intractable. There is, however, a way to make exact numerical calculations within the framework of the stochastic formulation without having to deal with the master equation directly. It is a relatively simple digital computer algorithm which uses a rigorously derived Monte Carlo procedure to numerically simulate the time evolution of the given chemical system. Like the master equation, this "stochastic simulation algorithm" correctly accounts for the inherent fluctuations and correlations that are necessarily ignored in the deterministic formulation. In addition, unlike most procedures for numerically solving the deterministic reaction-rate equations, this algorithm never approximates infinitesimal time increments dt by finite time steps Δt. The feasibility and utility of the simulation algorithm are demonstrated by applying it to several well-known model chemical systems, including the Lotka model, the Brusselator, and the Oregonator.}, - author = {Daniel T. Gillespie}, - doi = {10.1021/j100540a008}, - issn = {00223654}, - issue = {25}, - journal = {Journal of Physical Chemistry}, - title = {Exact stochastic simulation of coupled chemical reactions}, - volume = {81}, - year = {1977}, +@article{Gillespie1977, + title={Exact stochastic simulation of coupled chemical reactions}, + author={Gillespie, Daniel T}, + journal={The journal of physical chemistry}, + volume={81}, + number={25}, + pages={2340--2361}, + year={1977}, + publisher={ACS Publications} } @article{Girolami2011, abstract = {The paper proposes Metropolis adjusted Langevin and Hamiltonian Monte Carlo sampling methods defined on the Riemann manifold to resolve the shortcomings of existing Monte Carlo algorithms when sampling from target densities that may be high dimensional and exhibit strong correlations. The methods provide fully automated adaptation mechanisms that circumvent the costly pilot runs that are required to tune proposal densities for Metropolis-Hastings or indeed Hamiltonian Monte Carlo and Metropolis adjusted Langevin algorithms. This allows for highly efficient sampling even in very high dimensions where different scalings may be required for the transient and stationary phases of the Markov chain. The methodology proposed exploits the Riemann geometry of the parameter space of statistical models and thus automatically adapts to the local structure when simulating paths across this manifold, providing highly efficient convergence and exploration of the target density. The performance of these Riemann manifold Monte Carlo methods is rigorously assessed by performing inference on logistic regression models, log-Gaussian Cox point processes, stochastic volatility models and Bayesian estimation of dynamic systems described by non-linear differential equations. Substantial improvements in the time-normalized effective sample size are reported when compared with alternative sampling approaches. MATLAB code that is available from allows replication of all the results reported. © 2011 Royal Statistical Society.}, @@ -155,6 +154,7 @@ @book{Press2007 author = {William H Press and Saul a Teukolsky and William T Vetterling and Brian P Flannery}, issn = {00361445}, journal = {Sample page from NUMBERICAL RECIPES IN C}, + publisher = {Cambridge University Press}, title = {Numerical Recipes 3rd Edition: The Art of Scientific Computing}, volume = {1}, year = {2007}, @@ -262,4 +262,14 @@ @book{ruby author = {Flanagan, David and Matsumoto, Yukihiro}, year = {2008}, publisher = {O'Reilly Media} -} \ No newline at end of file +} +@article{fitzhugh1961impulses, + title={Impulses and physiological states in theoretical models of nerve membrane}, + author={FitzHugh, Richard}, + journal={Biophysical journal}, + volume={1}, + number={6}, + pages={445--466}, + year={1961}, + publisher={Elsevier} +} diff --git a/docs/md/building_doc.md b/docs/md/building_doc.md new file mode 100644 index 00000000..f37d5d96 --- /dev/null +++ b/docs/md/building_doc.md @@ -0,0 +1,22 @@ +# Building the documentation locally + +The documentation, which you are currently reading, may be built locally. +First, install additional packages required specifically for the documentation: + +```bash +pip install -r docs/requirements.txt +``` + +Then, build the documentation from command line: + +```bash +jupyter-book build docs +``` + +The generated HTML files will be saved in the local copy of your repository under: + + pygom/docs/_build/html + +You can view the documentation by opening the index file in your browser of choice: + + pygom/docs/_build/html/index.html \ No newline at end of file diff --git a/docs/md/common_models.md b/docs/md/common_models.md index 08965ee7..f29a1c1e 100644 --- a/docs/md/common_models.md +++ b/docs/md/common_models.md @@ -1,41 +1,5 @@ # Pre-defined examples - common epi models -We have defined a set of models {mod}`common_models`, most of them commonly used in epidemiology. They are there -as examples and also to save time for users. Most of them are of the -compartmental type, and we use standard naming conventions i.e. **S** = -Susceptible, **E** = Exposed, **I** = Infectious, **R** = Recovered. - -#TODO is R recovered, removed or dead? - -Extra state symbol will be introduced when required. - -{doc}`../notebooks/common_models/SIS` - -{doc}`../notebooks/common_models/SIS_Periodic` - -{doc}`../notebooks/common_models/SIR` - -{doc}`../notebooks/common_models/SIR_Birth_Death` - -{doc}`../notebooks/common_models/SEIR` - -{doc}`../notebooks/common_models/SEIR_Multiple` - -{doc}`../notebooks/common_models/SEIR_Birth_Death` - -{doc}`../notebooks/common_models/SEIR_Birth_Death_Periodic` - -{doc}`../notebooks/common_models/Legrand_Ebola_SEIHFR` - -{doc}`../notebooks/common_models/Lotka_Volterra` - -{doc}`../notebooks/common_models/Lotka_Volterra_4State` - -{doc}`../notebooks/common_models/FitzHugh` - -{doc}`../notebooks/common_models/Lorenz` - -{doc}`../notebooks/common_models/vanDelPol` - -{doc}`../notebooks/common_models/Robertson` - +We have defined a set of models in the module {mod}`common_models`. +Most of these draw from commonly used models in epidemiology and are included primarily to save time for users, but also to serve as examples. +We also include a few models from outside of epidemiology which are commonly used for tasks such as testing numerical solvers. \ No newline at end of file diff --git a/docs/md/faq.md b/docs/md/faq.md index a22e19d8..f9bb00bd 100644 --- a/docs/md/faq.md +++ b/docs/md/faq.md @@ -1,76 +1,60 @@ -# Frequent asked questions {#faq} +# Frequently asked questions -## Code runs slowly +```{warning} +These FAQ's are not particularly up to date and so might not be as frequently asked. +``` -This is because the package is not optimized for speed. Although the -some of the main functions are lambdified using -`sympy`{.interpreted-text role="mod"} or compiled against -`cython`{.interpreted-text role="mod"} when available, there are many -more optimization that can be done. One example is the lines: +## Why does code run slowly? -in `.DeterministicOde.evalSensitivity`{.interpreted-text role="func"}. -The first two operations can be inlined into the third and the third -line itself can be rewritten as: +This is because the package is not optimized for speed. +Although some of the main functions are lambdified using {mod}`sympy` or compiled against {mod}`cython` when available, there are many more optimizations that can be done. -and save the explicit copy operation by `numpy`{.interpreted-text -role="mod"} when making A. If desired, we could have also made used of -the `numexpr`{.interpreted-text role="mod"} package that provides -further speed up on elementwise operations in place of numpy. + -## Why not compile the numeric computation form sympy against Theano +## Why not compile the numeric computation form sympy against Theano? -Setup of the package has been simplified as much as possible. If you -look closely enough, you will realize that the current code generation -only uses `cython`{.interpreted-text role="mod"} and not -`f2py`{.interpreted-text role="mod"}. This is because we are not -prepared to do all the system checks, i.e. does a fortran compiler -exist, is gcc installed, was python built as a shared library etc. We -are very much aware of the benefit, especially considering the -possibility of GPU computation in `theano`{.interpreted-text -role="mod"}. +Setup of the package has been simplified as much as possible. +If you look closely enough, you will realize that the current code generation only uses {mod}`cython` and not {mod}`f2py`. +This is because we are not prepared to do all the system checks, i.e. does a fortran compiler exist, is gcc installed, was python built as a shared library etc. +We are very much aware of the benefit, especially considering the possibility of GPU computation in {mod}`theano`. ## Why not use mpmath library throughout? -This is because we have a fair number of operations that depends on -`scipy`{.interpreted-text role="mod"}. Obviously, we can solve ode using -`mpmath`{.interpreted-text role="mod"} and do standard linear algebra. -Unfortunately, optimization and statistics packages and routine are -mostly based on `numpy`{.interpreted-text role="mod"}. +This is because we have a fair number of operations that depends on {mod}`scipy`. +Obviously, we can solve ode using {mod}`mpmath` and do standard linear algebra. +Unfortunately, optimization and statistics packages and routine are mostly based on {mod}`numpy`. -## Computing the gradient using `.SquareLoss`{.interpreted-text role="class"} is slow +## Why is computing the gradient using {class}`.SquareLoss` slow? -It will always be slow on the first operation. This is due to the design -where the initialization of the class is fast and only find derivative -information/compile function during runtime. After the first -calculation, things should be significantly faster. +It will always be slow on the first operation. +This is due to the design where the initialization of the class is fast and only finds derivative information/compile function during runtime. After the first calculation, things should be significantly faster. -**Why some of my code is not a fortran object?** +## Why is some of my code not a fortran object? -When we detec either a $\exp$ or a $\log$ in the equations, we -automatically force the compile to use mpmath to ensure that we obtain -the highest precision. To turn this on/off will be considered as a -feature in the future. +The following answer may be intended for a different question: -## Can you not convert a non-autonumous system to an autonomous system for me automatically +When we detect either a $\exp$ or a $\log$ in the equations, we automatically force the compile to use {mod}`mpmath` to ensure that we obtain +the highest precision. +To turn this on/off will be considered as a feature in the future. -Although we can do that, it is not, and will not be implemented. This is -to ensure that the end user such as yourself are fully aware of the -equations being defined. +## Can you not convert a non-autonumous system to an autonomous system for me automatically? -## Getting the sensitivities from `.SquareLoss`{.interpreted-text role="class"} did not get a speed up when I used a restricted set of parameters +Although we can do that, it is not, and will not be implemented. +This is to ensure that the end user is fully aware of the equations being defined. -This is because we currently evaluate the full set of sensitivities -before extracting them out. Speeding this up for a restrictive set is -being considered. A main reason that stopped us from implementing is -that we find the symbolic gradient of the ode before compiling it. Which -means that one function call to the compiled file will return the full -set of sensitivities and we would only be extracting the appropriate -elements from the matrix. This only amounts to a small speed up. The -best method would be to compile only the necessary elements of the -gradient matrix, but this would require much more work both within the -code, and later on when variables are being added/deleted as all these -compilation are perfromed in runtime. +## Getting the sensitivities from {class}`.SquareLoss` did not get a speed up when I used a restricted set of parameters -## Why do not have the option to obtain gradient via complex differencing +This is because we currently evaluate the full set of sensitivities before extracting them out. +Speeding this up for a restrictive set is being considered. +A main reason that stopped us from implementing is that we find the symbolic gradient of the ode before compiling it. +Which means that one function call to the compiled file will return the full set of sensitivities and we would only be extracting the appropriate elements from the matrix. +This only amounts to a small speed up. +The best method would be to compile only the necessary elements of the gradient matrix, but this would require much more work both within the +code, and later on when variables are being added/deleted as all these compilation are performed in runtime. -It is currently not implemented. Feature under consideration. +## Why do not have the option to obtain gradient via complex differencing? + +It is currently not implemented. Feature under consideration. \ No newline at end of file diff --git a/docs/md/getting_started.md b/docs/md/getting_started.md deleted file mode 100644 index 561ec3e1..00000000 --- a/docs/md/getting_started.md +++ /dev/null @@ -1,93 +0,0 @@ -# Getting started - -## What does this package do? - -The purpose of this package is to allow the end user to easily define a -set of ordinary differential equations (ODEs) and obtain information -about the ODEs by invoking the the appropriate methods. Here, we define -the set of ODEs as - -$$\frac{d \mathbf{x}}{d t} = f(\mathbf{x},\boldsymbol{\theta})$$ - -where $\mathbf{x} = \left(x_{1},x_{2},\ldots,x_{n}\right)$ is the state -vector with $d$ state and $\boldsymbol{\theta}$ the parameters of $p$ -dimension. Currently, this package allows the user to find the algebraic -expression of the ODE, Jacobian, gradient and forward sensitivity of the -ODE. A numerical output is given when all the state and parameter values -are provided. Note that the only important class is -{class}`.DeterministicOde` where all the -functionality described previously are exposed. - -Plans for further development can be found, and proposed, on the repository's [issue board](https://github.com/ukhsa-collaboration/pygom/issues). - -## Installing the package - -PyGOM can be downloaded from the GitHub repository. - -https://github.com/PublicHealthEngland/pygom.git - -You will need to create an environment, for example using conda. - - conda env create -f conda-env.yml - -Alternatively, add dependencies to your own environment. - - pip install -r requirements.txt - -If you are working on a Windows machine you will also need to install: -- [Graphviz](https://graphviz.org/) -- [Visual C++](https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0) -- [Visual C++ Build Tools](https://go.microsoft.com/fwlink/?LinkId=691126) - -You can install the package via command line: - - python setup.py install - -or locally on a user level: - - python setup.py install --user - -```{note} -The latest fully reviewed version of PyGOM will be on master branch. We recommend that users install the version from this branch. -``` - -Alternatively the latest release can be installed from [PyPI](https://pypi.org/project/pygom/): - - pip install pygom - -Please note that there are some redundant files that are being kept for -development purposes. - -## Testing the package - -Test files can be run from the command line prior to or after installation. - - python setup.py test - -## Building the documentation locally - -Install additional packages: - - pip install -r docs/requirements.txt - -Build the documentation: - - jupyter-book build docs/ - -The html files will be saved in the local copy of your repository under: - - pygom/docs/_build/html - - -## Using this documentation -This documentation is built using [JupyterBook](https://jupyterbook.org/en/stable/intro.html). To use the contents of a notebook as a starting point for trialing or developing your own models and analyses, you can download any of the examples within this documentation by using the download icon on the desired page (located at the top right). - -![download file](../images/download.png) - -## Contributing to PyGOM - -Please see the [contribution guidance](../../CONTRIBUTING.md) which outlines: -- required information for raising issues; -- the process by which code contributions should be incorporated; -- what is required by pull requests to PyGOM, including how to add to the documentation; -- how we will acknowledge your contributions. \ No newline at end of file diff --git a/docs/md/installation.md b/docs/md/installation.md new file mode 100644 index 00000000..694438ba --- /dev/null +++ b/docs/md/installation.md @@ -0,0 +1,76 @@ +# Installation + +Installation instructions may be found on the [GitHub project README](https://github.com/ukhsa-collaboration/pygom/), but we include them here also. + +## From source + +Source code for PyGOM can be downloaded from the GitHub repository: https://github.com/ukhsa-collaboration/pygom + +```bash +git clone https://github.com/ukhsa-collaboration/pygom.git +``` + +Please be aware that there may be redundant files within the package as it is under active development. + +```{note} +The latest fully reviewed version of PyGOM will be on the master branch and we recommend that users install the version from there. +``` + +Activate the relevant branch for installation via Git Bash: + +```bash +git activate relevant-branch-name +``` + +Package dependencies can be found in the file `requirements.txt`. +An easy way to install these is to create a new [conda](https://conda.io/docs) environment via: + +```bash +conda env create -f conda-env.yml +``` + +which you should ensure is active for the installation process using: + +```bash +conda activate pygom +``` + +Alternatively, you may add dependencies to your own environment. + +```bash +pip install -r requirements.txt +``` + +The final prerequisite, if you are working on a Windows machine, is that you will also need to install: +- [Graphviz](https://graphviz.org/) +- Microsoft Visual C++ 14.0 or greater, which you can get with [Microsoft C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) + +You you should be able to install the PyGOM package via command line: + +```bash +python setup.py install +``` + +If you anticipate making your own frequent changes to the PyGOM source files, it might be more convenient to install in develop mode instead: + +```bash +python setup.py develop +``` + +## From PyPI + +Alternatively, the latest release can be installed from [PyPI](https://pypi.org/project/pygom/): + +```bash +pip install pygom +``` + +# Testing the package + +Test files should then be run from the command line to check that installation has completed successfully + +```bash +python setup.py test +``` + +This can take some minutes to complete. diff --git a/docs/md/intro.md b/docs/md/intro.md index 3f273853..ebbbb55c 100644 --- a/docs/md/intro.md +++ b/docs/md/intro.md @@ -1,17 +1,33 @@ # Welcome to the documentation for PyGOM -PyGOM (Python Generic ODE Model) is a Python package that aims to facilitate the application of ordinary differential equations (ODEs) in the real world, -with a focus in epidemiology. -This package helps the user define their ODE system in an intuitive manner and provides convenience functions - -making use of various algebraic and numerical libraries in the backend - that can be used in a straight forward fashion. +## What does this package do? -This is an open source project hosted on [Github](https://github.com/PublicHealthEngland/pygom). +PyGOM (Python Generic ODE Model) is a Python package which provides a simple interface for users to construct Ordinary Differential Equation (ODE) models, with a focus on compartmental models and epidemiology. +This is backed by a comprehensive and easy to use tool–box implementing functions to easily perform common operations such as parameter estimation and solving for deterministic or stochastic time evolution. +The package source is freely available (hosted on [GitHub](https://github.com/ukhsa-collaboration/pygom)) and organized in a way that permits easy extension. With both the algebraic and numeric calculations performed automatically (but still accessible), the end user is freed to focus on model development. -A manuscript containing a shortened motivation and use is hosted on [arxXiv](https://arxiv.org/abs/1803.06934). +## What is new in this release? -#TODO insert intro text +The main objective of the current release (0.1.8) is to provide more comprehensive documentation on how to use PyGOM. +The code underlying PyGOM's functionality is largely unchanged since the previous release, barring a few minor bug fixes. +The only significant changes which previous users should be aware of are: +- A move away from the {class}`DeterministicOde` class for deterministic simulations and instead employing {class}`SimulateOde` as our do-all class for deterministic or stochastic simulations as well as parameter fitting. +- Running simulations with random parameters does not require a special simulation function. Instead, PyGOM now recognises the parameter types handed to it (fixed or random) and acts accordingly. This means that stochastic simulations can now be performed with random parameters. +Both these changes are outlined in more detail in the {doc}`Producing forecasts ` section. -```{tableofcontents} -``` +## Using this documentation +This documentation is built using [JupyterBook](https://jupyterbook.org/en/stable/intro.html). +Instructions on how to build the documentation locally and where to find it can be found {doc}`here `. +To use the contents of a notebook as a starting point for trialling or developing your own models and analyses, you can download any of the examples within this documentation by using the download icon on the desired page (located at the top right). + +![download file](../images/download.png) + +## Contributing to PyGOM + +Please see the [contribution guidance](https://github.com/ukhsa-collaboration/pygom/blob/master/CONTRIBUTING.md) which outlines: +- Required information for raising issues +- The process by which code contributions should be incorporated +- What is required by pull requests to PyGOM, including how to add to the documentation +- How we will acknowledge your contributions diff --git a/docs/md/parameter_fitting.md b/docs/md/parameter_fitting.md index 4b252c67..52b6d038 100644 --- a/docs/md/parameter_fitting.md +++ b/docs/md/parameter_fitting.md @@ -1,17 +1,6 @@ # Parameter fitting -The following notebooks will demonstrate how to use the parameter fitting options within PyGOM. - -{doc}`../notebooks/paramfit/bvpSimple` - -{doc}`../notebooks/paramfit/gradient` - -{doc}`../notebooks/paramfit/fh` - -{doc}`../notebooks/paramfit/estimate1` - -{doc}`../notebooks/paramfit/estimate2` - -{doc}`../notebooks/paramfit/initialGuess` - -{doc}`../notebooks/paramfit/profile` \ No newline at end of file +As well as producing forecasts, another key activity in infectious disease modelling is inference of epidemic parameters from case data. +In this chapter we outline how PyGOM may be used to assist these endeavours. +In {doc}`the first section <../notebooks/paramfit/params_via_abc>`, we present a more up to date method which uses Approximate Bayesian Computation (ABC) and {doc}`then <../notebooks/paramfit/params_via_optimization>` a more classical approach via Maximum Likelihood Estimation (MLE). +We also demonstrate PyGOM's ability to solve the less epidemiologically related task of {doc}`boundary value problems <../notebooks/paramfit/bvpSimple>` \ No newline at end of file diff --git a/docs/md/solving.md b/docs/md/solving.md new file mode 100644 index 00000000..8ad3ed93 --- /dev/null +++ b/docs/md/solving.md @@ -0,0 +1,10 @@ +# Producing forecasts + +An exercise central to the study of infectious diseases (and indeed ODE models in general) is performing simulations to understand the likely evolution of the system in time. +PyGOM allows the user to easily obtain numerical solutions for both the deterministic and stochastic time evolution of their model. +Furthermore, users may specify model parameters to take either fixed values or to be drawn randomly from a probability distribution. + +In this chapter, we will use an SIR model as our example system to introduce + +- How to prescribe parameters in {doc}`Parameterisation <../notebooks/model_params>` +- How to obtain solutions and process the model output in {doc}`Finding ODE solutions <../notebooks/model_solver>` \ No newline at end of file diff --git a/docs/md/unrollOde.md b/docs/md/unrollOde.md index 5b53d60c..19b2a56a 100644 --- a/docs/md/unrollOde.md +++ b/docs/md/unrollOde.md @@ -1,16 +1,11 @@ # Converting equations into transitions -As seen previously in {doc}`transition`, we can -define the model via the transitions or explicitly as ODEs. There are -times when we all just want to test out some model in a paper and the -only available information are the ODEs themselves. Even though we know -that the ODEs come from some underlying transitions, breaking them down -can be a time consuming process. We provide the functionalities to do -this automatically. - +As seen previously in {doc}`transition`, we can define a model via transitions or explicitly as ODEs. +There may be times when importing a model from elsewhere and the only available information are the ODEs themselves. +If it is known that the ODEs come from some underlying transitions, we provide the functionality to do this automatically. +Of course there is some interpretation... +Here we demostrate usage of this feature via examples of increasing complexity: {doc}`../notebooks/unroll/unrollSimple` - {doc}`../notebooks/unroll/unrollBD` - {doc}`../notebooks/unroll/unrollHard` diff --git a/docs/notebooks/common_models/FitzHugh.ipynb b/docs/notebooks/common_models/FitzHugh.ipynb index 9d694ea3..1e9fdc8a 100644 --- a/docs/notebooks/common_models/FitzHugh.ipynb +++ b/docs/notebooks/common_models/FitzHugh.ipynb @@ -6,19 +6,19 @@ "source": [ "# FitzHugh\n", "\n", - "{func}`.FitzHugh` - the {cite:t}`FitzHugh1961` model without external stimulus\n", + "{func}`.FitzHugh` - the {cite:t}`FitzHugh1961` model without external stimulus.\n", "\n", - "This is a commonly used model when developing new methodology\n", - "with regards to ODEs, see {cite:p}`Ramsay2007` and {cite}`Girolami2011`.\n", - "\n", - "#TODO why common model?\n", + "The FitzHugh model is commonly used to test ODE software {cite:p}`Ramsay2007` {cite}`Girolami2011`, the model itself describes the excitation state of a neuron membrane as an excitation spike passes. PyGOM also includes other functions which are commonly used to test numerical integrators such as:\n", + "{func}`.vanDerPol` - the Van der Pol oscillator {cite}`vanderPol1926` and\n", + "{func}`.Robertson` - the Robertson reaction {cite}`Robertson1966`.\n", + "The FitzHugh model equations are as follows:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dV}{dt} &= c ( V - \\frac{V^{3}}{3} + R) \\\\\n", - "\\frac{dR}{dt} &= -\\frac{1}{c}(V - a + bR).\n", + "\\frac{\\mathrm{d} V}{\\mathrm{d} t} &= c ( V - \\frac{V^{3}}{3} + R) \\\\\n", + "\\frac{\\mathrm{d} R}{\\mathrm{d} t} &= -\\frac{1}{c}(V - a + bR).\n", "\\end{aligned}$$\n", "\n", - "An example of using this model follows.\n" + "We solve for the deterministic time evolution of the system:" ] }, { @@ -28,41 +28,31 @@ "metadata": {}, "outputs": [], "source": [ - "import numpy\n", - "\n", + "import numpy as np\n", "from pygom import common_models\n", - "\n", "import matplotlib.pyplot as plt\n", "\n", "ode = common_models.FitzHugh({'a':0.2, 'b':0.2, 'c':3.0})\n", "\n", - "t = numpy.linspace(0, 20, 101)\n", - "\n", + "t = np.linspace(0, 20, 101)\n", "x0 = [1.0, -1.0]\n", - "\n", "ode.initial_values = (x0, t[0])\n", "\n", - "solution = ode.integrate(t[1::])" + "solution = ode.solve_determ(t[1::])" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "ccee969d", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [], + "cell_type": "markdown", + "id": "a9061aff", + "metadata": {}, "source": [ - "ode.plot()" + "Plotting the function reveals frequent sharp transitions, which makes it an appropriate system to test ODE solving methods." ] }, { "cell_type": "code", "execution_count": null, - "id": "98a5e32e", + "id": "ccee969d", "metadata": { "tags": [ "hide-input" @@ -70,10 +60,7 @@ }, "outputs": [], "source": [ - "fig = plt.figure()\n", - "\n", - "plt.plot(solution[:,0], solution[:,1], 'b')\n", - "plt.show()\n" + "ode.plot()" ] } ], diff --git a/docs/notebooks/common_models/Legrand_Ebola_SEIHFR.ipynb b/docs/notebooks/common_models/Legrand_Ebola_SEIHFR.ipynb index 7affc240..82cbc0db 100644 --- a/docs/notebooks/common_models/Legrand_Ebola_SEIHFR.ipynb +++ b/docs/notebooks/common_models/Legrand_Ebola_SEIHFR.ipynb @@ -4,13 +4,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# `Legrand_Ebola_SEIHFR`\n", + "# Legrand Ebola SEIHFR\n", "\n", "{func}`Legrand_Ebola_SEIHFR`\n", "\n", - "A commonly used model in the literature to capture the dynamics of Ebola outbreaks is the\n", - "SEIHFR model proposed by {cite}`Legrand2007`. There are two extra\n", - "compartments on top of the SEIR: $H$ for hospitializations and\n", + "A commonly used model in the literature to capture the dynamics of Ebola outbreaks is the SEIHFR model proposed by Legrand _et al_ {cite}`legrand2007utd`.\n", + "There are two extra compartments on top of the SEIR: $H$ for hospitializations and\n", "$F$ for funerals. A total of ten parameters (with some describing the\n", "inverse) are required for the model.\n", "\n", @@ -33,7 +32,7 @@ "$\\omega$'s, i.e. $\\omega_{i} = \\gamma_{i}^{-1}$ for $i \\in \\{I,D,H,F\\}$.\n", "We also used $\\alpha^{-1}$ in our model instead of $\\alpha$ so that\n", "reading the parameters directly gives a more intuitive meaning. There\n", - "arw five additional parameters that is derived. The two derived case\n", + "are five additional parameters that is derived. The two derived case\n", "fatality ratio as\n", "\n", "$$\\begin{aligned}\n", @@ -69,8 +68,7 @@ "\n", "$$\\beta_{F}(t) = \\beta_{F} \\left(1 - \\frac{1}{1 + \\exp(-\\kappa (t - c))} \\right)$$\n", "\n", - "A brief example is given here with a slightly more in depth\n", - "example in {doc}`estimate2`.\n", + "A brief example is given here:\n", "\n" ] }, @@ -89,8 +87,18 @@ "\n", "t = numpy.linspace(1, 25, 100)\n", "\n", - "ode = common_models.Legrand_Ebola_SEIHFR([('beta_I',0.588), ('beta_H',0.794), ('beta_F',7.653), ('omega_I',10.0/7.0), ('omega_D',9.6/7.0),\n", - "('omega_H',5.0/7.0), ('omega_F',2.0/7.0), ('alphaInv',7.0/7.0), ('delta',0.81), ('theta',0.80), ('kappa',300.0), ('interventionTime',7.0)])\n", + "ode = common_models.Legrand_Ebola_SEIHFR([('beta_I',0.588),\n", + " ('beta_H',0.794),\n", + " ('beta_F',7.653),\n", + " ('omega_I',10.0/7.0),\n", + " ('omega_D',9.6/7.0),\n", + " ('omega_H',5.0/7.0),\n", + " ('omega_F',2.0/7.0),\n", + " ('alphaInv',7.0/7.0),\n", + " ('delta',0.81),\n", + " ('theta',0.80),\n", + " ('kappa',300.0),\n", + " ('interventionTime',7.0)])\n", "\n", "ode.initial_values = (x0, t[0])\n", "\n", @@ -108,7 +116,7 @@ "```{note}\n", "We have standardized the states so that the number of\n", "susceptible is 1 and equal to the whole population, i.e. $N$ does not\n", - "exist in our set of ODEs as defined in {mod}`common_models`.\n", + "exist in our set of ODEs.\n", "```" ] } diff --git a/docs/notebooks/common_models/Lotka_Volterra.ipynb b/docs/notebooks/common_models/Lotka_Volterra.ipynb index ddf146b7..d38a2228 100644 --- a/docs/notebooks/common_models/Lotka_Volterra.ipynb +++ b/docs/notebooks/common_models/Lotka_Volterra.ipynb @@ -6,14 +6,16 @@ "source": [ "# Lotka Volterra\n", "\n", - "{func}`.Lotka_Volterra` - the standard predator and prey model with two states and four parameters {cite}`Lotka1920`\n", + "The model {func}`.Lotka_Volterra` is a basic predator and prey model {cite}`Lotka1920`.\n", + "This is more commonly expressed in terms of predator and prey population area densities, $x$ and $y$ respectively, though we define the model in terms of absolute numbers, $X$ and $Y$, in a given area, $A$.\n", + "This decision to define in terms of population numbers, rather than densities, permits us to perform stochastic simulations.\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dx}{dt} &= \\alpha x - cxy \\\\\n", - "\\frac{dy}{dt} &= -\\delta y + \\gamma xy\n", + "\\frac{\\mathrm{d} X}{\\mathrm{d} t} &= \\alpha X - \\frac{\\beta X Y}{A} \\\\\n", + "\\frac{\\mathrm{d} Y}{\\mathrm{d} t} &= -\\gamma Y + \\frac{\\delta X Y}{A}\n", "\\end{aligned}$$\n", "\n", - "with both birth and death processes." + "We first solve this model for the deterministic case:" ] }, { @@ -24,128 +26,117 @@ "outputs": [], "source": [ "from pygom import common_models\n", - "\n", - "import numpy\n", - "\n", + "import numpy as np\n", "import matplotlib.pyplot as plt\n", + "import math\n", "\n", - "x0 = [2.0, 6.0]\n", + "# population density of predators and prey per square m\n", + "x0 = [1, 0.5]\n", "\n", - "ode = common_models.Lotka_Volterra({'alpha':1, 'delta':3, 'c':2, 'gamma':6})\n", + "# total area we wish to consider\n", + "area=200\n", "\n", - "ode.initial_values = (x0, 0)\n", + "# total animal populations\n", + "x0 = [x * area for x in x0]\n", "\n", - "t = numpy.linspace(0.1, 100, 10000)\n", + "ode = common_models.Lotka_Volterra({'alpha':0.1,\n", + " 'beta':0.2,\n", + " 'gamma':0.3,\n", + " 'delta':0.25,\n", + " 'A':area})\n", "\n", - "solution = ode.integrate(t)\n", + "tmax=200 # maximum time over which to run solver\n", + "dt=0.1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", "\n", - "ode.plot()\n" + "ode.initial_values = (x0, t[0])\n", + "\n", + "solution = ode.solve_determ(t[1::])" ] }, { "cell_type": "markdown", - "id": "1943441d", + "id": "4d951b55", "metadata": {}, "source": [ - "Then we can generate the graph at [Wolfram\n", - "Alpha](http://www.wolframalpha.com/input/?i=lotka-volterra+equations)\n", - "with varying initial conditions.\n" + "We see that the predator and prey populations show periodic behaviour with a phase shift between them." ] }, { - "cell_type": "markdown", - "id": "b5c82937", - "metadata": {}, + "cell_type": "code", + "execution_count": null, + "id": "004de679", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], "source": [ - "x1List = numpy.linspace(0.2, 2.0, 5)\n", + "f, ax = plt.subplots(figsize=(10, 2))\n", "\n", - "x2List = numpy.linspace(0.6, 6.0, 5)\n", - "\n", - "fig = plt.figure()\n" + "ax.set_xlabel(\"Time\")\n", + "ax.set_ylabel(\"Population number\")\n", + "ax.plot(t, solution[:,0], label=\"prey\")\n", + "ax.plot(t, solution[:,1], label=\"predator\")\n", + "ax.legend(loc=\"upper right\")\n", + "plt.show()" ] }, { "cell_type": "markdown", - "id": "5a492117", + "id": "5918419c", "metadata": {}, "source": [ - "\n", - "solutionList = list()\n", - "\n" + "We can also see how the system evolves stochastically" ] }, { "cell_type": "code", "execution_count": null, - "id": "f2a1d859", + "id": "9858cacf", "metadata": {}, "outputs": [], "source": [ - "ode = common_models.Lotka_Volterra({'alpha':1, 'delta':3, 'c':2, 'gamma':6})\n", - "\n", - "for i in range(len(x1List)): \n", - " ode.initial_values = ([x1List[i], x2List[i]], 0)\n", + "np.random.seed(1)\n", "\n", - "solutionList += [ode.integrate(t)]\n", + "n_sim=1\n", + "solution, simT = ode.solve_stochast(t, n_sim, full_output=True)\n", "\n", - "for i in range(len(x1List)):\n", - " plt.plot(solutionList[i][100::,0], solutionList[i][100::,1], 'b')\n", + "f, ax = plt.subplots(figsize=(10, 2))\n", "\n", - "plt.xlabel('x')\n", - "\n", - "plt.ylabel('y')\n", + "y=np.dstack(solution)\n", "\n", + "ax.set_xlabel(\"Time\")\n", + "ax.set_ylabel(\"Population number\")\n", + "ax.plot(t, y[:,0], label=\"prey\")\n", + "ax.plot(t, y[:,1], label=\"predator\")\n", + "ax.legend(loc=\"upper right\")\n", "plt.show()" ] }, { "cell_type": "markdown", - "id": "c628f283", + "id": "39ce9a40", "metadata": {}, "source": [ - "We also know that the system has the critical points at\n", - "$x = \\delta / \\gamma$ and $y=\\alpha / c$. If we changes the parameters\n", - "in such a way that the ration between $x$ and $y$ remains the same, then\n", - "we get a figure as below.\n" + "This appears to be unstable, since the populations undergo increasingly extreme peaks and troughs.\n", + "This can be confirmed by examining a phase diagram, whereby the trajectory in state space spirals outwards." ] }, { "cell_type": "code", "execution_count": null, - "id": "837940dd", + "id": "b7717689", "metadata": {}, "outputs": [], "source": [ - "cList = numpy.linspace(0.1, 2.0, 5)\n", - "\n", - "gammaList = numpy.linspace(0.6, 6.0, 5)\n", - "\n", - "fig = plt.figure()\n", - "\n", - "for i in range(len(x1List)): \n", - " ode = common_models.Lotka_Volterra({'alpha':1, 'delta':3, 'c':cList[i], 'gamma':gammaList[i]})\n", - "\n", - "ode.initial_values = (x0, 0) \n", - "solutionList += [ode.integrate(t)]\n", - "\n", - "for i in range(len(cList)):\n", - " plt.plot(solutionList[i][100::,0], solutionList[i][100::,1])\n", - "\n", - "plt.xlabel('x')\n", - "\n", - "plt.ylabel('y')\n", - "\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "id": "f05ce4a3", - "metadata": {}, - "source": [ - "\n", - "\n", - "where all the cycles goes through the same points." + "f, ax = plt.subplots(figsize=(10, 6))\n", + "ax.plot(y[:,0], y[:,1])\n", + "ax.set_xlabel(\"Prey population\")\n", + "ax.set_ylabel(\"Predator population\")\n", + "plt.show()" ] } ], @@ -156,8 +147,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/common_models/SEIR.ipynb b/docs/notebooks/common_models/SEIR.ipynb index 3875aa0b..f01627de 100644 --- a/docs/notebooks/common_models/SEIR.ipynb +++ b/docs/notebooks/common_models/SEIR.ipynb @@ -7,49 +7,140 @@ "# SEIR\n", "{func}`.SEIR`\n", "\n", - "A natural extension to the SIR is the SEIR model. An extra parameter\n", - "$\\alpha$, which is the inverse of the incubation period is introduced.\n", + "A Susceptible-Exposed-Infectious-Recovered (SEIR) model is a more realistic extension of the standard SIR model in which individuals do not become instantly infectious upon exposure, but undergo an incubation period, the timescale of which is governed by the parameter, $\\alpha$:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -\\beta SI \\\\\n", - "\\end{aligned}$$$$\\begin{aligned}\n", - "\\frac{dE}{dt} &= \\beta SI - \\alpha E \\\\\n", - "\\end{aligned}$$$$\\begin{aligned}\n", - "\\frac{dI}{dt} &= \\alpha E - \\gamma I \\\\\n", - "\\end{aligned}$$$$\\frac{dR}{dt} &= \\gamma I$$\n", - "\n", - "We use the parameters from {cite:t}`Aron1984` here to generate our plots,\n", - "which does not yield a *nice* and *sensible* epidemic curve as the birth\n", - "and death processes are missing.\n", - "\n" + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= - \\frac{\\beta SI}{N} \\\\\n", + "\\frac{\\mathrm{d}E}{\\mathrm{d}t} &= \\frac{\\beta SI}{N} - \\alpha E \\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\alpha E - \\gamma I \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= \\gamma I\n", + "\\end{aligned}$$\n", + "\n", + "We use the flu-like parameters of the SIR model demonstration with an incubation period of 2 days." ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "id": "bd15619d", "metadata": {}, + "outputs": [], "source": [ "from pygom import common_models\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import random\n", + "import math\n", + "\n", + "#####################\n", + "# Set up PyGOM object\n", + "#####################\n", + "\n", + "# Parameters\n", + "n_pop=1e4\n", + "gamma=1/4\n", + "alpha=1/2\n", + "R0=1.3\n", + "beta=R0*gamma\n", "\n", - "import numpy\n", + "ode = common_models.SEIR({'beta':beta, 'gamma':gamma, 'alpha':alpha, 'N':n_pop})\n", "\n", - "ode = common_models.SEIR({'beta':1800, 'gamma':100, 'alpha':35.84})\n", + "# Time range and increments\n", + "tmax=365 # maximum time over which to run solver\n", + "dt=0.1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", "\n", - "t = numpy.linspace(0, 50, 1001)\n", + "# Initial conditions\n", + "i0=1\n", + "x0=[n_pop-i0, 0, i0, 0]\n", + "ode.initial_values = (x0, t[0])\n", "\n", - "Ix0 = [0.0658, 0.0007, 0.0002, 0.0]\n", + "# Deterministic evolution\n", + "solution=ode.solve_determ(t[1::])" + ] + }, + { + "cell_type": "markdown", + "id": "abe9b989", + "metadata": {}, + "source": [ + "We also run an SIR model with the same parameters to compare the outputs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "282ebfbd", + "metadata": {}, + "outputs": [], + "source": [ + "ode = common_models.SIR({'beta':beta, 'gamma':gamma, 'N':n_pop})\n", "\n", + "x0=[n_pop-i0, i0, 0]\n", "ode.initial_values = (x0, t[0])\n", "\n", - "solution = ode.integrate(t[1::])\n", + "solution2=ode.solve_determ(t[1::])" + ] + }, + { + "cell_type": "markdown", + "id": "2fab3cb6", + "metadata": {}, + "source": [ + "We see that the SEIR model changes the profile of the epidemic as compared with an SIR model, but the overall final sizes are the same." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0403f7c2", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "# Plot\n", + "\n", + "f, axarr = plt.subplots(1,4, layout='constrained', figsize=(10, 4))\n", "\n", - "ode.plot()" + "# Plot colours\n", + "colours=[\"C1\", \"C3\", \"C0\", \"C2\"]\n", + "stateList=[\"S\", \"E\", \"I\", \"R\"]\n", + "\n", + "for i in range(0, 4):\n", + " axarr[i].plot(t, solution[:,i], color=colours[i])\n", + " if i in [0,2,3]:\n", + " if i in [2,3]:\n", + " axarr[i].plot(t, solution2[:,i-1], color=colours[i], linestyle=\"dashed\")\n", + " else:\n", + " axarr[i].plot(t, solution2[:,i], color=colours[i], linestyle=\"dashed\")\n", + " axarr[i].set_ylabel(stateList[i], rotation=0)\n", + " axarr[i].set_xlabel('Time')\n", + "\n", + "plt.show()" ] } ], "metadata": { + "kernelspec": { + "display_name": "pygom_development", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" } }, "nbformat": 4, diff --git a/docs/notebooks/common_models/SEIR_Birth_Death_Periodic_Waning_Intro.ipynb b/docs/notebooks/common_models/SEIR_Birth_Death_Periodic_Waning_Intro.ipynb new file mode 100644 index 00000000..eaf90f5a --- /dev/null +++ b/docs/notebooks/common_models/SEIR_Birth_Death_Periodic_Waning_Intro.ipynb @@ -0,0 +1,127 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e5455073", + "metadata": {}, + "source": [ + "# SEIR, birth, death, periodic, waning and introductions\n", + "{func}`.SEIR_Birth_Death_Periodic_Waning_Intro`\n", + "\n", + "This model includes relatively more detail than the other pre-defined models provided and may serve as a template for more complex models.\n", + "\n", + "In addition to the processes of births, deaths and seasonal driving, we have included (i) immune waning, which transitions recovered individuals back to susceptible at a rate $w$ and (ii) an external force of infection, which allows individuals to be infected from outside the population (analogous to case importation) at a rate $\\epsilon$.\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= - \\frac{\\beta(t) SI}{N} + w R + \\mu N - \\epsilon S - \\mu S\\\\\n", + "\\frac{\\mathrm{d}E}{\\mathrm{d}t} &= \\frac{\\beta(t) SI}{N} + \\epsilon S - \\alpha E - \\mu E \\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\alpha E - \\gamma I - \\mu I \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= \\gamma I - w R - \\mu R \\\\\n", + "\\beta(t) &= \\beta_0 \\left(1+\\delta \\cos \\left(\\frac{2 \\pi t}{P} \\right) \\right)\n", + "\\end{aligned}$$\n", + "\n", + "We solve this set of equations deterministically:" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "e7321259", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import common_models\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math\n", + "\n", + "# Set up PyGOM object\n", + "n_pop=1e5\n", + "mu=0.01/365\n", + "alpha=1/2\n", + "gamma=1/4\n", + "epsilon=100/(365*n_pop) # approximately 100*n_sus*365/(365*n_pop)=100*frac_sus~30 infections from external sources per year\n", + "w=1/(2*365) # waning rate, immunity lasts ~ 2 years.\n", + "beta0=1\n", + "delta=0.2\n", + "period=365\n", + "\n", + "ode = common_models.SEIR_Birth_Death_Periodic_Waning_Intro({'mu':mu,\n", + " 'alpha':alpha,\n", + " 'gamma':gamma,\n", + " 'epsilon':epsilon,\n", + " 'w':w,\n", + " 'beta0':beta0,\n", + " 'delta':delta,\n", + " 'period':period,\n", + " 'N':n_pop})\n", + "\n", + "# Time range and increments\n", + "tmax=365*20 # maximum time over which to run solver\n", + "dt=0.1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", + "\n", + "# Initial conditions\n", + "x0 = [n_pop, 0, 0, 0, t[0]]\n", + "\n", + "ode.initial_values = (x0, t[0])\n", + "\n", + "solution=ode.solve_determ(t[1::])" + ] + }, + { + "cell_type": "markdown", + "id": "5eefb897", + "metadata": {}, + "source": [ + "Plotting the infection prevalence reveals that the system eventually reaches a state of annual epidemics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30368b0d", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "f, ax = plt.subplots(figsize=(10, 2))\n", + "\n", + "ax.set_xlabel(\"Time\")\n", + "ax.set_ylabel(\"Infection prevalence\")\n", + "ax.plot(t[30000:]/365, solution[30000:,2])\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/common_models/SEIR_Multiple.ipynb b/docs/notebooks/common_models/SEIR_Multiple.ipynb index b9ff28df..ced9c1d6 100644 --- a/docs/notebooks/common_models/SEIR_Multiple.ipynb +++ b/docs/notebooks/common_models/SEIR_Multiple.ipynb @@ -10,10 +10,10 @@ "Multiple SEIR coupled together, without any birth death process.\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS_{i}}{dt} &= dN_{i} - dS_{i} - \\lambda_{i}S_{i} \\\\\n", - "\\frac{dE_{i}}{dt} &= \\lambda_{i}S_{i} - (d+\\epsilon)E_{i} \\\\\n", - "\\frac{dI_{i}}{dt} &= \\epsilon E_{i} - (d+\\gamma) I_{i} \\\\\n", - "\\frac{dR_{i}}{dt} &= \\gamma I_{i} - dR_{i}\n", + "\\frac{\\mathrm{d} S_{i}}{\\mathrm{d} t} &= dN_{i} - dS_{i} - \\lambda_{i}S_{i} \\\\\n", + "\\frac{\\mathrm{d} E_{i}}{\\mathrm{d} t} &= \\lambda_{i}S_{i} - (d+\\epsilon)E_{i} \\\\\n", + "\\frac{\\mathrm{d} I_{i}}{\\mathrm{d} t} &= \\epsilon E_{i} - (d+\\gamma) I_{i} \\\\\n", + "\\frac{\\mathrm{d} R_{i}}{\\mathrm{d}t} &= \\gamma I_{i} - dR_{i}\n", "\\end{aligned}$$\n", "\n", "where\n", diff --git a/docs/notebooks/common_models/SIR.ipynb b/docs/notebooks/common_models/SIR.ipynb index 73dceb7e..6d98dfd9 100644 --- a/docs/notebooks/common_models/SIR.ipynb +++ b/docs/notebooks/common_models/SIR.ipynb @@ -8,19 +8,15 @@ "\n", "{func}`.SIR`\n", "\n", - "A standard SIR model defined by the following equations.\n", + "The standard Susceptible-Infected-Recovered (SIR) model, which features heavily throughout this documentation, is defined by the following equations:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -\\beta SI \\\\\n", - "\\frac{dI}{dt} &= \\beta SI - \\gamma I \\\\\n", - "\\frac{dR}{dt} &= \\gamma I\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= - \\frac{\\beta SI}{N} \\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\frac{\\beta SI}{N} - \\gamma I \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= \\gamma I\n", "\\end{aligned}$$\n", "\n", - "Note that the examples and parameters are taken from {cite:t}`Brauer2008`,\n", - "namely Figure 1.4. Hence, the first example below may not appear to make\n", - "much sense.\n", - "\n", - "#TODO don't understand\n" + "We solve deterministically for flu-like parameters:" ] }, { @@ -31,22 +27,36 @@ "outputs": [], "source": [ "from pygom import common_models\n", - "\n", - "import numpy\n", - "\n", - "ode = common_models.SIR({'beta':3.6, 'gamma':0.2})\n", - "\n", - "t = numpy.linspace(0, 730, 1001)\n", - "\n", - "N = 7781984.0\n", - "\n", - "x0 = [1.0, 10.0/N, 0.0]\n", - "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import random\n", + "import math\n", + "\n", + "#####################\n", + "# Set up PyGOM object\n", + "#####################\n", + "\n", + "# Parameters\n", + "n_pop=1e4\n", + "gamma=1/4\n", + "R0=1.3\n", + "beta=R0*gamma\n", + "\n", + "ode = common_models.SIR({'beta':beta, 'gamma':gamma, 'N':n_pop})\n", + "\n", + "# Time range and increments\n", + "tmax=365 # maximum time over which to run solver\n", + "dt=0.1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", + "\n", + "# Initial conditions\n", + "i0=1\n", + "x0=[n_pop-i0, i0, 0]\n", "ode.initial_values = (x0, t[0])\n", "\n", - "solution = ode.integrate(t[1::])\n", - "\n", - "ode.plot()\n" + "# Deterministic evolution\n", + "solution=ode.solve_determ(t[1::])" ] }, { @@ -54,25 +64,32 @@ "id": "2b5252ff", "metadata": {}, "source": [ - "\n", - "Now we have the more sensible plot, where the initial susceptible population is\n", - "only a fraction of 1.\n" + "Plotting the result recovers the familiar epidemic trajectory:" ] }, { "cell_type": "code", "execution_count": null, "id": "bd78eb6c", - "metadata": {}, + "metadata": { + "tags": [ + "hide-input" + ] + }, "outputs": [], "source": [ - "x0 = [0.065, 123*(5.0/30.0)/N, 0.0]\n", + "f, axarr = plt.subplots(1,3, layout='constrained', figsize=(10, 4))\n", "\n", - "ode.initial_values = (x0, t[0])\n", + "# Plot colours\n", + "colours=[\"C1\", \"C0\", \"C2\"]\n", + "stateList=[\"S\", \"I\", \"R\"]\n", "\n", - "solution = ode.integrate(t[1::])\n", + "for i in range(0, 3):\n", + " axarr[i].plot(t, solution[:,i], color=colours[i])\n", + " axarr[i].set_ylabel(stateList[i], rotation=0)\n", + " axarr[i].set_xlabel('Time')\n", "\n", - "ode.plot()" + "plt.show()" ] } ], @@ -83,8 +100,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/common_models/SIR_Birth_Death.ipynb b/docs/notebooks/common_models/SIR_Birth_Death.ipynb index e93b3599..b0123894 100644 --- a/docs/notebooks/common_models/SIR_Birth_Death.ipynb +++ b/docs/notebooks/common_models/SIR_Birth_Death.ipynb @@ -7,16 +7,19 @@ "# SIR, birth and death \n", "{func}`.SIR_Birth_Death`\n", "\n", - "Next, we look at an SIR model with birth and death processes, where populations are added (birth) or removed (death).\n", + "Here we consider an SIR model in which individuals may be removed by death from each compartment at a uniform rate per person, $\\gamma$.\n", + "The population is replenished via births into the susceptible compartment at the same rate, thus conserving the total population by design.\n", + "For deterministic evolution, the population size remains constant whereas for stochastic evolution, the size fluctuates around this value.\n", + "The equations are as follows:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= B -\\beta SI - \\mu S \\\\\n", - "\\frac{dI}{dt} &= \\beta SI - \\gamma I - \\mu I \\\\\n", - "\\frac{dR}{dt} &= \\gamma I\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= \\mu N - \\frac{\\beta SI}{N} - \\mu S \\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\frac{\\beta SI}{N} - \\gamma I - \\mu I \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= \\gamma I - \\mu R\n", "\\end{aligned}$$\n", "\n", - "Continuing from the example above, but now with a much longer time\n", - "frame. Note that the birth and death rate are the same to maintain a constant population.\n" + "As an example, we study stochastic evolution of this system with measles-like parameters in 3 differently sized populations.\n", + "This provides a demonstration of threshold population sizes in order to support endemic circulation of certain pathogens." ] }, { @@ -27,30 +30,134 @@ "outputs": [], "source": [ "from pygom import common_models\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math\n", "\n", - "import numpy\n", + "#####################\n", + "# Set up PyGOM object\n", + "#####################\n", "\n", - "B = 126372.0/365.0\n", + "# Parameters\n", + "n_pop=1e4\n", + "mu=0.01/365 # birth/death rate 1% per year\n", + "gamma=1/20 \n", + "R0=15\n", + "beta=R0*gamma\n", "\n", - "N = 7781984.0\n", + "ode = common_models.SIR_Birth_Death({'beta':beta, 'gamma':gamma, 'mu':mu, 'N':n_pop})\n", "\n", - "ode = common_models.SIR_Birth_Death({'beta':3.6, 'gamma':0.2, 'B':B/N, 'mu':B/N})\n", + "# Time range and increments\n", + "tmax=365*10 # maximum time over which to run solver\n", + "dt=1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", "\n", - "t = numpy.linspace(0, 35*365, 10001)\n", + "# Initial conditions (endemic equilibrium derived from stationary point)\n", + "def sir_bd_endemic_eq(mu, beta, gamma, n_pop):\n", + " s0=math.floor((gamma+mu)*n_pop/beta)\n", + " i0=math.floor(mu*(n_pop-s0)*n_pop/(beta*s0))\n", + " r0=n_pop-(s0+i0)\n", + " return [s0, i0, r0]\n", "\n", - "x0 = [0.065, 123.0*(5.0/30.0)/N, 0.0]\n", + "x0=sir_bd_endemic_eq(mu, beta, gamma, n_pop)\n", + "ode.initial_values = (x0, t[0])\n", + "\n", + "##########\n", + "# Simulate\n", + "##########\n", + "n_sim=10\n", + "np.random.seed(1)\n", + "\n", + "solution, simT = ode.solve_stochast(t, n_sim, full_output=True)\n", + "y=np.dstack(solution)\n", "\n", + "############################\n", + "# try larger population size\n", + "############################\n", + "n_pop=1e5\n", + "ode = common_models.SIR_Birth_Death({'beta':beta, 'gamma':gamma, 'mu':mu, 'N':n_pop}) # update parameter\n", + "x0=sir_bd_endemic_eq(mu, beta, gamma, n_pop) # recalculate IC's\n", "ode.initial_values = (x0, t[0])\n", + "solution_2, simT_2 = ode.solve_stochast(t, n_sim, full_output=True) # simulate\n", + "y_2=np.dstack(solution_2)\n", "\n", - "solution = ode.integrate(t[1::])\n", + "#################################\n", + "# try even larger population size\n", + "#################################\n", + "n_pop=1e6\n", + "ode = common_models.SIR_Birth_Death({'beta':beta, 'gamma':gamma, 'mu':mu, 'N':n_pop}) # update parameter\n", + "x0=sir_bd_endemic_eq(mu, beta, gamma, n_pop) # recalculate IC's\n", + "ode.initial_values = (x0, t[0])\n", + "solution_3, simT_3 = ode.solve_stochast(t, n_sim, full_output=True) # simulate\n", + "y_3=np.dstack(solution_3)" + ] + }, + { + "cell_type": "markdown", + "id": "bbc9ac4f", + "metadata": {}, + "source": [ + "Plotting the results, we see that for populations of sizes 10,000 and 100,000, the infected population is critically close to zero, such that stochastic fluctuations eventually lead to disease extinction.\n", + "This is of course signified by the infected class reaching zero, but also by the recovered and susceptible classes undergoing stable linear growth due to population turnover.\n", + "When the population size is 1,000,000, we see that the infected subset, of typical size 500, is able to persist for the full 10 years of the simulation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f5389b0", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "f, axarr = plt.subplots(3,3, layout='constrained', figsize=(10, 5))\n", + "\n", + "for i in range(0,3):\n", + " # Plot individual trajectories\n", + " for j in range(0, n_sim):\n", + " axarr[0][i].plot(t/365, y[:,i,j], alpha=0.4, color=\"C0\")\n", + " axarr[1][i].plot(t/365, y_2[:,i,j], alpha=0.4, color=\"C1\")\n", + " axarr[2][i].plot(t/365, y_3[:,i,j], alpha=0.4, color=\"C2\")\n", + "\n", + "# Add titles\n", + "stateList = ['S', 'I', 'R']\n", + "for idx, state in enumerate(stateList):\n", + " axarr[0][idx].set_ylabel(state, rotation=0)\n", + " axarr[1][idx].set_ylabel(state, rotation=0)\n", + " axarr[2][idx].set_ylabel(state, rotation=0)\n", + " axarr[0][idx].set_xlabel('Time (years)')\n", + " axarr[1][idx].set_xlabel('Time (years)')\n", + " axarr[2][idx].set_xlabel('Time (years)')\n", "\n", - "ode.plot()" + "axarr[0][1].set_title(\"Population size = 10,000\")\n", + "axarr[1][1].set_title(\"Population size = 100,000\")\n", + "axarr[2][1].set_title(\"Population size = 1,000,000\")\n", + "\n", + "plt.show()" ] } ], "metadata": { + "kernelspec": { + "display_name": "pygom_development", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" } }, "nbformat": 4, diff --git a/docs/notebooks/common_models/SIS.ipynb b/docs/notebooks/common_models/SIS.ipynb index cb09e523..cd9237ee 100644 --- a/docs/notebooks/common_models/SIS.ipynb +++ b/docs/notebooks/common_models/SIS.ipynb @@ -7,17 +7,14 @@ "# SIS\n", "{func}`.SIS`\n", "\n", - "A standard SIS model without the total population $N$. We assume here\n", - "that $S + I = N$ so we can always normalize to 1. The state\n", - "$S$ is not required for understanding the model because it is a\n", - "deterministic function of state $I$.\n", + "Perhaps the simplest epidemic model is a Susceptible-Infected-Susceptible (SIS) system, in which susceptible individuals may be infected and then do not have any immunity upon recovery.\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -\\beta S I + \\gamma I \\\\\n", - "\\frac{dI}{dt} &= \\beta S I - \\gamma I.\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= -\\frac{\\beta S I}{N} + \\gamma I \\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\frac{\\beta S I}{N} - \\gamma I.\n", "\\end{aligned}$$\n", "\n", - "An example of an implementation is given below.\n" + "We see how this evolves deterministically:" ] }, { @@ -28,28 +25,80 @@ "outputs": [], "source": [ "from pygom import common_models\n", - "\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math\n", "\n", - "import numpy\n", + "# Set up PyGOM object\n", + "n_pop=1e4\n", "\n", - "ode = common_models.SIS({'beta':0.5,'gamma':0.2})\n", + "ode = common_models.SIS({'beta':0.5, 'gamma':0.2, 'N':n_pop})\n", "\n", - "t = numpy.linspace(0, 20, 101)\n", + "# Initial conditions\n", + "i0=10\n", + "x0 = [n_pop-i0, i0]\n", "\n", - "x0 = [1.0, 0.1]\n", + "# Time range and increments\n", + "tmax=50 # maximum time over which to run solver\n", + "dt=0.1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", "\n", "ode.initial_values = (x0, t[0])\n", + "solution=ode.solve_determ(t[1::])" + ] + }, + { + "cell_type": "markdown", + "id": "b272c27d", + "metadata": {}, + "source": [ + "After sufficiently long time, the system reaches an equilibrium state:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2bce7cd0", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 4))\n", "\n", - "solution = ode.integrate(t[1::])\n", + "# Plot colours\n", + "colours=[\"C1\", \"C0\"]\n", + "stateList=[\"S\", \"I\"]\n", "\n", - "ode.plot()\n" + "for i in range(0, 2):\n", + " axarr[i].plot(t, solution[:,i], color=colours[i])\n", + " axarr[i].set_ylabel(stateList[i], rotation=0)\n", + " axarr[i].set_xlabel('Time')\n", + "\n", + "plt.show()" ] } ], "metadata": { + "kernelspec": { + "display_name": "pygom_development", + "language": "python", + "name": "python3" + }, "language_info": { - "name": "python" + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" } }, "nbformat": 4, diff --git a/docs/notebooks/common_models/SIS_Periodic.ipynb b/docs/notebooks/common_models/SIS_Periodic.ipynb index c19fe77d..622cfc6b 100644 --- a/docs/notebooks/common_models/SIS_Periodic.ipynb +++ b/docs/notebooks/common_models/SIS_Periodic.ipynb @@ -7,17 +7,30 @@ "# SIS, periodic\n", "{func}`.SIS_Periodic`\n", "\n", - "Now we look at an extension of the SIS model by incorporating a periodic\n", - "contact rate. Note how our equation is defined by a single ODE for state\n", - "**I**.\n", + "This is an extension of the SIS model which incorporates a periodic infection rate, $\\beta(t)$.\n", + "This could be used to mimic seasonal variation in infectivity due to yearly contact rate patterns or climate drivers, for example.\n", + "We define $\\beta(t)$ as follows:\n", "\n", - "$$\\frac{dI}{dt} = (\\beta(t)N - \\alpha) I - \\beta(t)I^{2}$$\n", + "$$\\begin{aligned}\n", + "\\beta(t) &= \\beta_0 \\left(1+\\delta \\cos \\left(\\frac{2 \\pi t}{P} \\right) \\right)\n", + "\\end{aligned}$$\n", "\n", - "where $\\beta(t) = 2 - 1.8 \\cos(5t)$. As the name suggests, it achieves a\n", - "(stable) periodic solution. Note how the plots have two sub-graphs,\n", - "where $\\tau$ is in fact our time component which we have taken out of\n", - "the original equation when converting it to a autonomous system.\n", - "\n" + "where $\\beta_0$ is the baseline infection rate, $\\delta$ is the magnitude of oscillations from the baseline ($-1<\\delta<1$ so that $\\beta>0$) and $P$ is the period of oscillations.\n", + "\n", + "Also, note how we can use $I+S=N$ to eliminate the equation for $S$:\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= (\\beta(t)N - \\alpha) I - \\beta(t)I^{2} \\\\\n", + "\\end{aligned}$$\n", + "\n", + "In Heathcote's classical model, $\\gamma=1$ and:\n", + "\n", + "$$\\begin{aligned}\n", + "\\beta(t) &= 2 - 1.8 \\cos(5t) \\\\\n", + "&= 2\\left(1 - 0.9 \\cos \\left( \\frac{2 \\pi t}{ \\frac{2 \\pi}{5} } \\right) \\right)\n", + "\\end{aligned}$$\n", + "\n", + "so that $\\beta_0=2$, $\\delta=0.9$ and $P=\\frac{2 \\pi}{5}$." ] }, { @@ -28,22 +41,54 @@ "outputs": [], "source": [ "from pygom import common_models\n", - "\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math\n", "\n", - "import numpy\n", + "# Set up PyGOM object\n", + "n_pop=1e4\n", "\n", - "ode = common_models.SIS_Periodic({'alpha':1.0})\n", + "ode = common_models.SIS_Periodic({'gamma':1, 'beta0':2, 'delta':0.9, 'period':(2*math.pi/5), 'N':n_pop})\n", "\n", - "t = numpy.linspace(0, 10, 101)\n", + "# Time range and increments\n", + "tmax=10 # maximum time over which to run solver\n", + "dt=0.01 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", "\n", - "x0 = [0.1,0.]\n", + "# Initial conditions\n", + "i0=0.1*n_pop\n", + "x0 = [i0, t[0]]\n", "\n", "ode.initial_values = (x0, t[0])\n", + "solution=ode.solve_determ(t[1::])" + ] + }, + { + "cell_type": "markdown", + "id": "5eefb897", + "metadata": {}, + "source": [ + "We plot the infected trajectory which shows periodic evolution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "510dd216", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "f, ax = plt.subplots(figsize=(10, 4))\n", "\n", - "solution = ode.integrate(t[1::])\n", - "\n", - "ode.plot()" + "ax.set_xlabel(\"Time\")\n", + "ax.set_ylabel(\"I\", rotation=0)\n", + "ax.plot(t, solution[:,0])\n", + "plt.show()" ] } ], @@ -54,8 +99,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/epi.ipynb b/docs/notebooks/epi.ipynb index 8b47d848..9e57058c 100644 --- a/docs/notebooks/epi.ipynb +++ b/docs/notebooks/epi.ipynb @@ -6,15 +6,9 @@ "source": [ "# Epidemic Analysis\n", "\n", - "A common application of ODEs is in the field\n", - "of epidemiology modeling, where compartmental models are\n", - "used to describe disease progression through a population. \n", "We demonstrate some of the simpler algebraic analysis that you may wish to undertake on a compartmental model.\n", "\n", - "We revisit the SIR model with birth and death\n", - "processes, which is an extension of the one in {doc}`sir`. \n", - "\n", - "First, we initialize the model, this time by importing it from {mod}`.common_models`, rather than constructing it ourselves." + "First, we initialize an SIR model, this time by importing it from {mod}`.common_models`, rather than constructing it ourselves:" ] }, { @@ -22,20 +16,45 @@ "execution_count": 1, "id": "8c84ea26", "metadata": {}, + "outputs": [], + "source": [ + "from pygom import common_models\n", + "\n", + "ode = common_models.SIR_Birth_Death()" + ] + }, + { + "cell_type": "markdown", + "id": "8432a422", + "metadata": {}, + "source": [ + "We can verify" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f7610d25", + "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Matrix([[B - I*S*beta - S*mu], [I*S*beta - I*gamma - I*mu], [I*gamma]])\n" - ] + "data": { + "text/latex": [ + "$\\displaystyle \\left[\\begin{matrix}B - I S \\beta - S \\mu\\\\I S \\beta - I \\gamma - I \\mu\\\\I \\gamma\\end{matrix}\\right]$" + ], + "text/plain": [ + "Matrix([\n", + "[ B - I*S*beta - S*mu],\n", + "[I*S*beta - I*gamma - I*mu],\n", + "[ I*gamma]])" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "from pygom import common_models\n", - "\n", - "ode = common_models.SIR_Birth_Death()\n", - "\n", "ode.get_ode_eqn()" ] }, @@ -44,18 +63,9 @@ "id": "ea8c4b15", "metadata": {}, "source": [ - "\n", "## Obtaining the reproduction number (R0)\n", "\n", - "The reproduction number, also known as the $R_{0}$, is the single most\n", - "powerful piece and reduced piece of information available from an epidemiological\n", - "compartmental model. This value represents the number of the disease-naive population who can be infected by a single member of the infectious population. When the parameter values are known, $R_{0}$ provides a single number which can then lead to an interpretation of the system, where $R_{0} = 1$ defines the tipping point of an outbreak. An $R_{0}$ value of\n", - "more than one signifies growth of cases (a potential outbreak), and an $R_{0}$ of less than one\n", - "indicates that the disease will stop spreading naturally.\n", - "\n", - "#TODO reference\n", - "\n", - "To obtain the $R_{0}$, we need have to tell the {func}`.R0` function which states\n", + "To obtain $R_{0}$, we need have to tell the {func}`.R0` function which states\n", "represent the *disease state*, which in this case is the state **I**.\n", "\n", "#TODO is this the disease state, or the infectious state?" @@ -105,19 +115,15 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "id": "717c6868", "metadata": {}, "outputs": [ { - "ename": "NameError", - "evalue": "name 'disease_progression_matrices' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m F, V \u001b[39m=\u001b[39m disease_progression_matrices(ode, \u001b[39m'\u001b[39m\u001b[39mI\u001b[39m\u001b[39m'\u001b[39m)\n\u001b[0;32m 3\u001b[0m e \u001b[39m=\u001b[39m R0_from_matrix(F, V)\n\u001b[0;32m 5\u001b[0m \u001b[39mprint\u001b[39m(e)\n", - "\u001b[1;31mNameError\u001b[0m: name 'disease_progression_matrices' is not defined" + "name": "stdout", + "output_type": "stream", + "text": [ + "[S*beta/(gamma + mu)]\n" ] } ], @@ -126,7 +132,7 @@ "\n", "e = R0_from_matrix(F, V)\n", "\n", - "print(e)\n" + "print(e)" ] }, { @@ -174,7 +180,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.15" + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/epijson.ipynb b/docs/notebooks/epijson.ipynb index 882abe8b..73ddd29e 100644 --- a/docs/notebooks/epijson.ipynb +++ b/docs/notebooks/epijson.ipynb @@ -6,20 +6,10 @@ "source": [ "# Reading and using EpiJSON data\n", "\n", - "Epidemiology data is complicated due to the many different stages a\n", - "patient can go through and whether a modeling technique is applicable\n", - "depends heavily on the recording of data. [EpiJSON](https://github.com/Hackout2/EpiJSON) is a framework which\n", - "tries to captures all the information in a JSON format {cite}`Finnie2016`.\n", - "\n", - "PyGOM provides the functionality to process EpiJSON data. Due to\n", - "the nature of this package, modeling of ODEs, data files are processed with this in mind. The output is therefore in the cumulative form as\n", - "default, shown below, in a [`pandas.DataFrame`](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) format. \n", - "\n", - "#TODO unsure what this means\n", - "\n", - "\n", - "The input can be\n", - "in a string format, a file or already a `dict`." + "[EpiJSON](https://github.com/Hackout2/EpiJSON) is a framework which tries to capture epidemiological information in a JSON format {cite}`Finnie2016`.\n", + "PyGOM provides the functionality to process EpiJSON data with a view to preparing it for its various modelling features previously discussed in this guide.\n", + "The input can be in a string format, a file or already a `dict`.\n", + "The output is in the cumulative form as default, shown below, in a [`pandas.DataFrame`](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) format. " ] }, { @@ -30,13 +20,10 @@ "outputs": [], "source": [ "from pygom.loss.read_epijson import epijson_to_data_frame\n", - "\n", "import pkgutil\n", "\n", "data = pkgutil.get_data('pygom', 'data/eg1.json')\n", - "\n", "df = epijson_to_data_frame(data)\n", - "\n", "print(df)" ] }, @@ -62,7 +49,7 @@ "\n", "from pygom.loss.epijson_loss import EpijsonLoss\n", "\n", - "ode = common_models.SIR([0.5, 0.3])\n", + "ode = common_models.SIR_norm([0.5, 0.3])\n", "\n", "obj = EpijsonLoss([0.005, 0.03], ode, data, 'Death', 'R', [300, 2, 0])\n", "\n", @@ -84,18 +71,14 @@ "id": "a5ac54c8", "metadata": {}, "source": [ - "Given an initialized object, all the operations are inherited from\n", - "{class}`.BaseLoss`. We demonstrated above how to calculate the cost\n", - "and the rest will not be shown for brevity. The data frame is stored\n", - "inside of the loss object and can be retrieved for inspection at any\n", - "time point.\n", + "Given an initialized object, all the operations are inherited from {class}`.BaseLoss`.\n", + "We demonstrated above how to calculate the cost and the rest will not be shown for brevity.\n", + "The data frame is stored inside of the loss object and can be retrieved for inspection at any time point.\n", "\n", "```{note}\n", - "Initial values for the states are required,\n", - "but the time is not. When the time is not supplied, then the first time\n", - "point in the data will be treated as $t0$. The input Death indicates which column of the data is used\n", - "and $R$ the corresponding state the data belongs to.\n", + "Initial values for the states are required, but the time is not.\n", + "When the time is not supplied, then the first time point in the data will be treated as $t0$.\n", + "The input Death indicates which column of the data is used and $R$ the corresponding state the data belongs to.\n", "```" ] }, diff --git a/docs/notebooks/extract_info.ipynb b/docs/notebooks/extract_info.ipynb new file mode 100644 index 00000000..84875e30 --- /dev/null +++ b/docs/notebooks/extract_info.ipynb @@ -0,0 +1,229 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e69f436b", + "metadata": {}, + "source": [ + "# Extracting model information\n", + "\n", + "In the study of ODE systems, there are many calculations which are frequently performed and PyGOM has some functionality to provide assistance.\n", + "We will again use the SIR model as our example system, but this time we will make use of the PyGOM `common_models` module, where many predefined models are stored.\n", + "This means we avoid having to build the model from scratch again, saving time and lines of code.\n", + "Here we initialise a `SIR` model:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d499587e", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import common_models\n", + "ode = common_models.SIR()" + ] + }, + { + "cell_type": "markdown", + "id": "5defac16", + "metadata": {}, + "source": [ + "## Verification\n", + "\n", + "As seen previously, the {func}`.get_ode_eqn` function allows us to verify that our ODE equations are as we'd expect:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a2be3c1", + "metadata": {}, + "outputs": [], + "source": [ + "ode.get_ode_eqn()" + ] + }, + { + "cell_type": "markdown", + "id": "d9f4249d", + "metadata": {}, + "source": [ + "```{tip}\n", + "In addition to showing the Python equation form of the ODEs, we can also display them as either symbols or latex code, which can save some extra typing when porting the equations to another document.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2089ef15", + "metadata": {}, + "outputs": [], + "source": [ + "ode.print_ode()\n", + "ode.print_ode(True)" + ] + }, + { + "cell_type": "markdown", + "id": "d9d71015", + "metadata": {}, + "source": [ + "We can check the model definition in terms of a transition matrix:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ea90388", + "metadata": {}, + "outputs": [], + "source": [ + "ode.get_transition_matrix()" + ] + }, + { + "cell_type": "markdown", + "id": "9c7b5c60", + "metadata": {}, + "source": [ + "where only the upper off diagonal triangle is necessary to fully define the system.\n", + "\n", + "We can even inspect the transitions graphically:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e04194ea", + "metadata": {}, + "outputs": [], + "source": [ + "ode.get_transition_graph();" + ] + }, + { + "cell_type": "markdown", + "id": "f77cfefa", + "metadata": {}, + "source": [ + "## Algebraic insights\n", + "\n", + "We briefly outline some of the algebraic results which can be quickly accessed by PyGOM. Firstly, we can check if our system is linear:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d55ef11", + "metadata": {}, + "outputs": [], + "source": [ + "ode.linear_ode()" + ] + }, + { + "cell_type": "markdown", + "id": "c3fa0e62", + "metadata": {}, + "source": [ + "For stability analysis and speeding up numerical integrators, it may be useful to know the Jacobian, Hessian (where three 2D arrays are returned, rather than one 3D array) or gradient which PyGOM has functions for respectively:\n", + "\n", + "```{warning}\n", + "In different contexts it can be useful to know the derivatives with respect to the state variables or the parameters. Make sure you know which one you require and check that the PyGOM function you are using provides it.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9c6ec971", + "metadata": {}, + "outputs": [], + "source": [ + "ode.get_jacobian_eqn()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a8b4ff6", + "metadata": {}, + "outputs": [], + "source": [ + "ode.get_hessian_eqn()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e1c7dfb", + "metadata": {}, + "outputs": [], + "source": [ + "ode.get_grad_eqn()" + ] + }, + { + "cell_type": "markdown", + "id": "3f572e7c", + "metadata": {}, + "source": [ + "## Epidemiology specific insights\n", + "\n", + "Under development are functions to obtain numeric and algebraic expressions for the basic reproduction number, $R_0$.\n", + "Currently, these can be obtained in two steps, first by finding the next generation matrix and then calculating $R_0$ from this, assuming in the initial conditions that $S(0)=N$.\n", + "We must specify which state represents the *infectious state*, which in this case is the state **I**." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d099d92b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[S*beta/(N*gamma)]\n" + ] + } + ], + "source": [ + "from pygom.model.epi_analysis import *\n", + "\n", + "F, V = disease_progression_matrices(ode, 'I')\n", + "e = R0_from_matrix(F, V)\n", + "print(e)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/insights.ipynb b/docs/notebooks/insights.ipynb new file mode 100644 index 00000000..e9a43f3b --- /dev/null +++ b/docs/notebooks/insights.ipynb @@ -0,0 +1,41 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e395ad9b", + "metadata": {}, + "source": [ + "# ODE Insights\n", + "\n", + "Now that our SIR model is encapsulated in the {class}`.SimulateOde` class, it is ready to be studied using PyGOM's various functionalities.\n", + "Before moving on to more complex methods such as parameter fitting and simulation, we can take advantage of several useful features of PyGOM which provide us with more analytical insights - the sort we might commonly find ourselves calculating, requiring pen and paper to do so." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/model_params.ipynb b/docs/notebooks/model_params.ipynb new file mode 100644 index 00000000..7ddbbf50 --- /dev/null +++ b/docs/notebooks/model_params.ipynb @@ -0,0 +1,152 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e395ad9b", + "metadata": {}, + "source": [ + "# Parameterisation\n", + "\n", + "Until now, we have only dealt with parameters when it was necessary to inform PyGOM which of our symbols refer to states and which to parameters.\n", + "However, before PyGOM can find numerical solutions to the equations, it must be fed numerical parameter values.\n", + "PyGOM's ODE solvers accept parameters in two forms: fixed, where they remain constant, or random, where they are drawn from a given distribution.\n", + "We demonstrate these features on our model system, the SIR compartmental model.\n", + "We start, as always, by encapsulating our ODE system in a PyGOM object, in this case loading a previously defined model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1679a48a", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import common_models\n", + "ode = common_models.SIR()" + ] + }, + { + "cell_type": "markdown", + "id": "404cea05", + "metadata": {}, + "source": [ + "## Fixed parameters\n", + "\n", + "Defining fixed parameters for $\\beta$, $\\gamma$ and $N$ is simply done via a list of tuples as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc1bd57c", + "metadata": {}, + "outputs": [], + "source": [ + "fixed_param_set=[('beta', 0.3), ('gamma', 0.25), ('N', 1e4)]\n", + "ode.parameters=fixed_param_set" + ] + }, + { + "cell_type": "markdown", + "id": "b7f1018f", + "metadata": {}, + "source": [ + "\n", + "\n", + "## Random parameters\n", + "\n", + "Instead, imagine that we have some prior uncertainty on the values of our model parameters.\n", + "We may wish to reflect this by running model simulations over a variety of parameter values drawn randomly from a probability distribution.\n", + "A suitable choice of distribution for $\\gamma$ and $\\beta$ is a gamma distribution, since it ensures that both parameters are positive as required.\n", + "In this example, we'll keep the total population, $N$, fixed, showing that a mixture of parameter types (fixed and random) is possible.\n", + "\n", + "To define our random distributions, we make use of the familiar syntax from [R](http://www.r-project.org/).\n", + "Slightly cumbersomely, we have to define it via a tuple, where the first item is the function handle (name) and the second the parameters. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52734403", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom.utilR import rgamma\n", + "random_param_set = dict() # container for random param set\n", + "random_param_set['gamma'] = (rgamma,{'shape':100, 'rate':400})\n", + "random_param_set['beta'] = (rgamma,{'shape':100, 'rate':333.33})\n", + "random_param_set['N'] = 1e4" + ] + }, + { + "cell_type": "markdown", + "id": "a4c4ca97", + "metadata": {}, + "source": [ + "The values of the shape and rate parameters mean that $\\gamma$ and $\\beta$ have means of 0.25 and 0.3 and standard deviations of 0.025 and 0.03 respectively.\n", + "When changing parameters, it is a good idea to define a new {class}`.SimulateOde` object, since there may be some calculated variables leftover from the previous parameter set.\n", + "We do not need to inform PyGOM that the parameters are random and define them in the same way as before:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24447ca7", + "metadata": {}, + "outputs": [], + "source": [ + "ode = common_models.SIR()\n", + "ode.parameters=random_param_set" + ] + }, + { + "cell_type": "markdown", + "id": "b05c629f", + "metadata": {}, + "source": [ + "" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/model_solve.ipynb b/docs/notebooks/model_solve.ipynb new file mode 100644 index 00000000..7ad3babf --- /dev/null +++ b/docs/notebooks/model_solve.ipynb @@ -0,0 +1,516 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "efbf9af8", + "metadata": { + "tags": [ + "remove-input" + ] + }, + "outputs": [], + "source": [ + "# Reload all previous stuff, not sure how to do this without redoing everything...\n", + "stateList = ['S', 'I', 'R']\n", + "paramList = ['beta', 'gamma']\n", + "from pygom import Transition, TransitionType\n", + "odeList = [\n", + " Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='I',equation='beta*S*I - gamma*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE) \n", + "]\n", + "transList = [\n", + " Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T),\n", + " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "133de424", + "metadata": {}, + "source": [ + "# Solving the model\n", + "\n", + "We will now find deterministic solutions to the SIR model.\n", + "First we must import the relevant class" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06b092c7", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import DeterministicOde" + ] + }, + { + "cell_type": "markdown", + "id": "46f1fc79", + "metadata": {}, + "source": [ + "Now we initialize the class, which constructs our ODE system from all the information we have provided.\n", + "For now, let's use both approaches:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2d00708", + "metadata": {}, + "outputs": [], + "source": [ + "model = DeterministicOde(stateList, paramList, ode=odeList)\n", + "model2 = DeterministicOde(stateList, paramList, transition=transList)" + ] + }, + { + "cell_type": "markdown", + "id": "db3a166f", + "metadata": {}, + "source": [ + "We can verify the model equations are what we'd expect by using the `get_ode_eqn()` function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "39171530", + "metadata": {}, + "outputs": [], + "source": [ + "print(model.get_ode_eqn())\n", + "print(model2.get_ode_eqn())" + ] + }, + { + "cell_type": "markdown", + "id": "bc3f2c5c", + "metadata": {}, + "source": [ + "where we can see that building the model via equations or transitions results in the same equations corresponding to their respective $S$, $I$ and $R$ state.\n", + "From now on, we proceed with just `model`, safe in the knowledge that they are the same." + ] + }, + { + "cell_type": "markdown", + "id": "0d06bdf9", + "metadata": {}, + "source": [ + "```{tip}\n", + "In addition to showing the equation form of the ODEs, we can also display them as either symbols or latex code, which can save some extra typing when porting the equations to another document.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83ea4dcb", + "metadata": {}, + "outputs": [], + "source": [ + "model.print_ode()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c05b408", + "metadata": {}, + "outputs": [], + "source": [ + "model.print_ode(True)" + ] + }, + { + "cell_type": "markdown", + "id": "3e7b28f3", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "id": "bdcecb64", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "id": "7b7f8220", + "metadata": {}, + "source": [ + "## Initial value problem\n", + "\n", + "We can calculate the time evolution of the system given the values of the initial conditions and parameters." + ] + }, + { + "cell_type": "markdown", + "id": "f6f00b34", + "metadata": {}, + "source": [ + "1. Define the model parameters. We can call `parameters` to check what is required" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c163aa2f", + "metadata": {}, + "outputs": [], + "source": [ + "model.parameters" + ] + }, + { + "cell_type": "markdown", + "id": "9f56e201", + "metadata": {}, + "source": [ + "we then pass them to the class via a list of tuples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "696476fb", + "metadata": {}, + "outputs": [], + "source": [ + "paramEval = [('beta',0.5), ('gamma',1.0/3.0)]\n", + "model.parameters = paramEval" + ] + }, + { + "cell_type": "markdown", + "id": "f1a505b5", + "metadata": {}, + "source": [ + "and can verify that this was successful" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a94733b2", + "metadata": {}, + "outputs": [], + "source": [ + "model.parameters" + ] + }, + { + "cell_type": "markdown", + "id": "e80ac7f8", + "metadata": {}, + "source": [ + "2. Provide initial conditions for the states." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b45e43c", + "metadata": {}, + "outputs": [], + "source": [ + "i0=1e-6\n", + "initialState = [1-i0, i0, 0]\n", + "\n", + "model.ode(state=initialState, t=1)" + ] + }, + { + "cell_type": "markdown", + "id": "22c4063f", + "metadata": {}, + "source": [ + "```{note}\n", + "Fractional SIR models are subject to the constraint $S(t)+I(t)+R(t)=1$. It is up to the user to ensure that the initial conditions adhere to any constraints.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "105524d4", + "metadata": {}, + "source": [ + "\n", + "3. Implement an ODE solver.\n", + "\n", + "We are well equipped to solve an initial value problem, using the standard numerical integrator such as `odeint ` from `scipy.integrate`. We also used `matplotlib.pyplot` for plotting and `linspace ` to create the time vector." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c9e662c", + "metadata": {}, + "outputs": [], + "source": [ + "import scipy.integrate\n", + "import numpy\n", + "\n", + "t = numpy.linspace(0, 150, 100)\n", + "\n", + "solution = scipy.integrate.odeint(model.ode, initialState, t)" + ] + }, + { + "cell_type": "markdown", + "id": "75ccb76e", + "metadata": {}, + "source": [ + "We can plot our solution to observe a standard SIR shape." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5badfc50", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "plt.figure()\n", + "plt.plot(t, solution[:,0], label='S')\n", + "plt.plot(t, solution[:,1], label='I')\n", + "plt.plot(t, solution[:,2], label='R')\n", + "plt.xlabel('Time')\n", + "plt.ylabel('Population proportion')\n", + "plt.title('Standard SIR model')\n", + "plt.legend(loc=0)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "2caa261e", + "metadata": {}, + "source": [ + "Alternatively, we can integrate and plot via the **ode** object which we initialized earlier." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b71d2931", + "metadata": {}, + "outputs": [], + "source": [ + "model.initial_values = (initialState, t[0])\n", + "\n", + "model.parameters = paramEval\n", + "\n", + "solution = model.integrate(t[1::])\n", + "\n", + "model.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "58b41bf9", + "metadata": {}, + "source": [ + "We could solve the ODEs above using the Jacobian as well. Unfortunately, it does not help because the number of times the Jacobian was evaluated was zero, as expected given that our set of equations are not stiff." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e887ac3e", + "metadata": {}, + "outputs": [], + "source": [ + "#TODO what does this show?\n", + "%timeit solution1, output1 = scipy.integrate.odeint(model.ode, initialState, t, full_output=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d3c7ddd", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "%timeit solution2, output2 = scipy.integrate.odeint(model.ode, initialState, t, Dfun=model.jacobian, mu=None, ml=None, full_output=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2de91b9e", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "%timeit solution3, output3 = model.integrate(t, full_output=True)" + ] + }, + { + "cell_type": "markdown", + "id": "f4707964", + "metadata": {}, + "source": [ + "It is important to note that we return our Jacobian as a dense square matrix. Hence, the two argument (mu,ml) for the ODE solver was set to `None` to let it know the output explicitly." + ] + }, + { + "cell_type": "markdown", + "id": "a0e384cc", + "metadata": {}, + "source": [ + "## Solving the forward sensitivity equation\n", + "\n", + "The sensitivity equations are also solved as an initial value problem. Let us redefine the model in the standard SIR order and we solve it with the sensitivity all set at zero, i.e. we do not wish to infer the initial value of the states." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b637cee", + "metadata": {}, + "outputs": [], + "source": [ + "stateList = ['S', 'I', 'R']\n", + "\n", + "model = DeterministicOde(stateList, paramList, ode=odeList)\n", + "\n", + "initialState = [1, 1.27e-6, 0]\n", + "\n", + "paramEval = [('beta', 0.5), ('gamma', 1.0/3.0)]\n", + "\n", + "model.parameters = paramEval\n", + "\n", + "solution = scipy.integrate.odeint(model.ode_and_sensitivity, numpy.append(initialState, numpy.zeros(6)), t)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b63ba62", + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [], + "source": [ + "{\n", + " \"tags\": [\n", + " \"hide-input\",\n", + " ]\n", + "}\n", + "f,axarr = plt.subplots(3,3);\n", + "\n", + "f.text(0.5,0.975,'SIR with forward sensitivity solved via ode',fontsize=16,horizontalalignment='center',verticalalignment='top')\n", + "\n", + "axarr[0,0].plot(t, solution[:,0])\n", + "\n", + "axarr[0,0].set_title('S')\n", + "\n", + "axarr[0,1].plot(t, solution[:,1])\n", + "\n", + "axarr[0,1].set_title('I')\n", + "\n", + "axarr[0,2].plot(t, solution[:,2]);\n", + "\n", + "axarr[0,2].set_title('R')\n", + "\n", + "axarr[1,0].plot(t, solution[:,3])\n", + "\n", + "axarr[1,0].set_title(r'state S parameter $beta$')\n", + "\n", + "axarr[2,0].plot(t, solution[:,4])\n", + "\n", + "axarr[2,0].set_title(r'state S parameter $gamma$')\n", + "\n", + "axarr[1,1].plot(t, solution[:,5])\n", + "\n", + "axarr[1,1].set_title(r'state I parameter $beta$')\n", + "\n", + "axarr[2,1].plot(t, solution[:,6])\n", + "\n", + "axarr[2,1].set_title(r'state I parameter $gamma$')\n", + "\n", + "axarr[1,2].plot(t, solution[:,7])\n", + "\n", + "axarr[1,2].set_title(r'state R parameter $beta$')\n", + "\n", + "axarr[2,2].plot(t, solution[:,8])\n", + "\n", + "axarr[2,2].set_title(r'state R parameter $gamma$')\n", + "\n", + "plt.tight_layout()\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "2f64d869", + "metadata": {}, + "source": [ + "This concludes the introductory example and we will be moving on to look at parameter estimation next in {doc}`estimate1` and the most important part in terms of setting up the ODE object; defining the equations in various different ways in {doc}`transition`." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.15" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/model_solver.ipynb b/docs/notebooks/model_solver.ipynb new file mode 100644 index 00000000..2c018cd2 --- /dev/null +++ b/docs/notebooks/model_solver.ipynb @@ -0,0 +1,827 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Finding ODE solutions\n", + "\n", + "PyGOM allows the user to evaluate both the **deterministic** and **stochastic** time evolution of their ODE system using the class methods {func}`solve_determ` and {func}`solve_stochast` respectively.\n", + "These methods work with both fixed and random parameters as introduced in the {doc}`previous section <../notebooks/model_params>`.\n", + "\n", + "We begin by defining the series of ODEs and parameters which define our SIR system.\n", + "This we do from scratch rather than loading in a previously defined model in order to present a more comprehensive example of the workflow." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1679a48a", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import SimulateOde, Transition, TransitionType\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import random\n", + "\n", + "###################\n", + "# ODE specification\n", + "###################\n", + "\n", + "# Define SIR model\n", + "stateList = ['S', 'I', 'R']\n", + "paramList = ['beta', 'gamma', 'N']\n", + "transitionList = [Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T),\n", + " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)]\n", + "\n", + "n_pop=1e4 # Total population is fixed\n", + "\n", + "############\n", + "# Parameters\n", + "############\n", + "\n", + "beta_mn=0.35 # Infectivity, beta. Gives the actual value for fixed params and mean for random distribution.\n", + "gamma_mn=0.25 # Recovery rate, gamma.\n", + "\n", + "#######\n", + "# Fixed\n", + "#######\n", + "fixed_param_set=[('beta', beta_mn), ('gamma', gamma_mn), ('N', n_pop)]\n", + "\n", + "########\n", + "# Random\n", + "########\n", + "\n", + "# Recovery rate, gamma\n", + "gamma_var=(gamma_mn/10)**2 # Set the standard deviation to be 1/10th of the mean value\n", + "gamma_shape=(gamma_mn**2)/gamma_var\n", + "gamma_rate=gamma_mn/gamma_var\n", + "\n", + "# Infectivity parameter, beta\n", + "beta_var=(beta_mn/10)**2 # Set the standard deviation to be 1/10th of the mean value\n", + "beta_shape=(beta_mn**2)/beta_var\n", + "beta_rate=beta_mn/beta_var\n", + "\n", + "from pygom.utilR import rgamma\n", + "random_param_set = dict() # container for random param set\n", + "random_param_set['gamma'] = (rgamma,{'shape':gamma_shape, 'rate':gamma_rate})\n", + "random_param_set['beta'] = (rgamma,{'shape':beta_shape, 'rate':beta_rate})\n", + "random_param_set['N'] = n_pop" + ] + }, + { + "cell_type": "markdown", + "id": "fa186a81", + "metadata": {}, + "source": [ + "Since this notebook will involve stochastic processes, we set the random number generator seed to make outputs reproducible." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5dc7996d", + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(1)" + ] + }, + { + "cell_type": "markdown", + "id": "e976c853", + "metadata": {}, + "source": [ + "In order to determine the time evolution of the system, we must supply initial conditions as well as the desired time points for the numerical solver.\n", + "Timesteps should be sufficiently short to reduce numerical integration errors, but not too short such that the computational time costs become too large." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9e31cc4f", + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "\n", + "# Initial conditions\n", + "i0=10\n", + "x0 = [n_pop-i0, i0, 0]\n", + "\n", + "# Time range and increments\n", + "tmax=200 # maximum time over which to run solver\n", + "dt=0.1 # timestep\n", + "n_timestep=math.ceil(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated" + ] + }, + { + "cell_type": "markdown", + "id": "ecd39e70", + "metadata": {}, + "source": [ + "## Deterministic evolution\n", + "\n", + "To solve for the deterministic time evolution of the system, PyGOM uses {func}`scipy.integrate.odeint` which is wrapped by the member function {func}`solve_determ`.\n", + "We begin with the simple (and likely familiar) case of fixed parameters.\n", + "\n", + "### Fixed parameters\n", + "\n", + "First, we initialise a {class}`SimulateOde` object with our fixed parameters, `fixed_param_set`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "657a7646", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up pygom object (D_F suffix implies Deterministic_Fixed)\n", + "ode_D_F = SimulateOde(stateList, paramList, transition=transitionList)\n", + "ode_D_F.initial_values = (x0, t[0]) # (initial state conditions, initial timepoint)\n", + "ode_D_F.parameters=fixed_param_set" + ] + }, + { + "cell_type": "markdown", + "id": "801dbfd6", + "metadata": {}, + "source": [ + "The solution is then found via `solve_determ`, specifying the required time steps (not including the initial one)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f612095", + "metadata": {}, + "outputs": [], + "source": [ + "solution_D_F = ode_D_F.solve_determ(t[1::])" + ] + }, + { + "cell_type": "markdown", + "id": "a4d12509", + "metadata": {}, + "source": [ + "Plotting the output yields the familiar result, where infecteds initially increase in number exponentially until critical depletion of susceptibles results in epidemic decline." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2668b8ad", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "f, axarr = plt.subplots(1,3, layout='constrained', figsize=(10, 2.5))\n", + "\n", + "# Plot colours\n", + "colours=[\"C1\", \"C0\", \"C2\"]\n", + "\n", + "for i in range(0, 3):\n", + " axarr[i].plot(t, solution_D_F[:,i], color=colours[i])\n", + "\n", + "for idx, state in enumerate(stateList):\n", + " axarr[idx].set_ylabel(state, rotation=0)\n", + " axarr[idx].set_xlabel('Time')\n", + "\n", + "axarr[1].set_title(\"Deterministic simulation with fixed parameters\")\n", + "\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "id": "0e516f09", + "metadata": {}, + "source": [ + "### Random parameters\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "id": "bb53913b", + "metadata": {}, + "source": [ + "We now solve the same system, but for 1000 repetitions using randomly drawn parameters for each simulation.\n", + "This time we initialise the parameters with`random_param_set`, but still use {func}`solve_determ` to find solutions as before" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7f1ee87", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up pygom object\n", + "ode_D_R = SimulateOde(stateList, paramList, transition=transitionList)\n", + "ode_D_R.initial_values = (x0, t[0])\n", + "ode_D_R.parameters=random_param_set\n", + "\n", + "n_param_draws=1000 # number of parameters to draw\n", + "Ymean, solution_D_R = ode_D_R.solve_determ(t[1::], n_param_draws, full_output=True)" + ] + }, + { + "cell_type": "markdown", + "id": "2221479d", + "metadata": {}, + "source": [ + "```{note}\n", + "A message may be printed above where PyGOM is trying to connect to an\n", + "mpi backend, as our module has the capability to compute in parallel\n", + "using the IPython.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "9bb7c942", + "metadata": {}, + "source": [ + "Here we visualise the output in 2 ways, first by viewing 50 randomly selected trajectories and secondly by viewing the confidence intervals (here 95% and 50%) and median calculated over the full 1000 solutions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8849566b", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "y_D_R=np.dstack(solution_D_R) # unpack the data\n", + "\n", + "#########################\n", + "# Individual trajectories\n", + "#########################\n", + "\n", + "# Select 50 simulations to plot\n", + "i_rand=random.sample(range(n_param_draws), 50)\n", + "\n", + "######################\n", + "# Confidence intervals\n", + "######################\n", + "\n", + "# Calculate 95%, 50% CIs and median.\n", + "y_D_R_lolo=np.percentile(y_D_R, 2.5, axis=2)\n", + "y_D_R_lo=np.percentile(y_D_R, 25, axis=2)\n", + "y_D_R_hi=np.percentile(y_D_R, 75, axis=2)\n", + "y_D_R_hihi=np.percentile(y_D_R, 97.5, axis=2)\n", + "y_D_R_md=np.percentile(y_D_R, 50, axis=2)\n", + "\n", + "f, axarr = plt.subplots(2,3, layout='constrained', figsize=(10, 5))\n", + "\n", + "# Plot colours\n", + "colours=[\"C1\", \"C0\", \"C2\"]\n", + "\n", + "for i in range(0,3):\n", + " # Plot individual trajectories\n", + " for j in i_rand:\n", + " axarr[0][i].plot(t, y_D_R[:,i,j], color=colours[i], alpha=0.2)\n", + "\n", + " # Plot CI's\n", + " axarr[1][i].fill_between(t, y_D_R_lolo[:,i], y_D_R_hihi[:,i], alpha=0.2, facecolor=colours[i])\n", + " axarr[1][i].fill_between(t, y_D_R_lo[:,i], y_D_R_hi[:,i], alpha=0.4, facecolor=colours[i])\n", + " axarr[1][i].plot(t, y_D_R_md[:,i], color=colours[i])\n", + "\n", + "# Add titles\n", + "for idx, state in enumerate(stateList):\n", + " axarr[0][idx].set_ylabel(state, rotation=0)\n", + " axarr[1][idx].set_ylabel(state, rotation=0)\n", + " axarr[0][idx].set_xlabel('Time')\n", + " axarr[1][idx].set_xlabel('Time')\n", + "\n", + "axarr[0][1].set_title(\"50 deterministic simulations, each with randomly drawn parameters\")\n", + "axarr[1][1].set_title(\"Median (line), 50% CI (dark shaded) and 95% CI (light shaded) over 1000 simulations\")\n", + "\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "id": "39d66f12", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "id": "2f01a3d9", + "metadata": {}, + "source": [ + "## Stochastic evolution\n", + "\n", + "The approximation that numbers of individuals in each state may be treated as a continuum break down when their sizes are small.\n", + "In this regime, transitions between states do not represent continuous flows but are instead stochastic events that occur at rates governed by the current state of the system. The simplifying assumption that waiting times for these events to occur are exponentially distributed (memoryless), allows for quicker evaluation of the dynamics.\n", + "\n", + "Two common algorithms have been implemented for use during simulation; the reaction method {cite}`Gillespie1977` and the $\\tau$-Leap method\n", + "{cite}`Cao2006`.\n", + "The two change interactively depending on the size of the states.\n", + "\n", + "### Fixed parameters\n", + "\n", + "As previously, we define a model and pass our fixed parameters `fixed_param_set`.\n", + "However, this time we employ the function `solve_stochast` to allow for stochastic time evolution:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "118a869b", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up pygom object\n", + "ode_S_F = SimulateOde(stateList, paramList, transition=transitionList)\n", + "ode_S_F.initial_values = (x0, t[0])\n", + "\n", + "n_sim=1000 # number of simulations\n", + "ode_S_F.parameters = fixed_param_set\n", + "solution_S_F, simT = ode_S_F.solve_stochast(t, n_sim, full_output=True)" + ] + }, + { + "cell_type": "markdown", + "id": "920d3a0b", + "metadata": {}, + "source": [ + "Before we inspect the epidemic time series, we plot the distribution of final epidemic sizes." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a3698023", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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uXPnKjo6WiEhIb94T1oAAACgspUp5L7++utavny5hg4dWt71AAAAANetTPfJzc3N5T60AAAA8FplCrmjR4/WqlWryrsWAAAAoFyUabnCzz//rCVLlmjTpk1q3bq1/Pz83PbPnz+/XIoDAAAAyqJMIXffvn1q27atJOnAgQNu+/gQGgAAADytTCF369at5V0HAAAAUG7KtCYXAAAA8GZlmsnt3r37Ly5L2LJlS5kLAgAAAK5XmUJuwXrcApcuXdLevXt14MABDR8+vDzqAgAAAMqsTCH35ZdfLrI9Pj5eP/7443UVBAAAAFyvcl2TO2TIEC1btqw8TwkAAACUWrmG3O3bt6tatWrleUoAAACg1Mq0XGHAgAFuj40xOn36tD799FPNmjWrXAoDAAAAyqpMIdfhcLg9rlKlipo2baq5c+cqLi6uXAoDAAAAyqpMITcpKam86wAAAADKTZlCboFdu3bp8OHDstlsatGihdq1a1dedQEAAABlVqaQm5GRoUceeUTbtm1TzZo1ZYxRVlaWunfvruTkZNWrV6+86wQAAABKrEx3V5g0aZKys7N18OBB/fDDD8rMzNSBAweUnZ2tJ554orxrBAAAAEqlTDO5GzZs0KZNm9S8eXNXW4sWLfTaa6/xwTMAAAB4XJlmcvPz8+Xn51eo3c/PT/n5+dddFAAAAHA9yhRy7777bk2ePFnffvutq+2bb77R7373O/Xo0aPcigMAAADKokzLFRYuXKj+/fsrPDxcYWFhstlsOnHihFq1aqWVK1eWd40AAACWFz59faG2Y8/38UAl1lCmkBsWFqbdu3crJSVFn3/+uYwxatGihe65557yrg8AAAAotVItV9iyZYtatGih7OxsSVLPnj01adIkPfHEE+rQoYNatmypjz76qEIKBQAAAEqqVDO5CxYs0OOPP66goKBC+xwOh8aMGaP58+frzjvvLLcCAQAAivpTPvBLSjWT+9lnn6lXr17F7o+Li9OuXbuuuygAAADgepQq5H733XdF3jqsgK+vr86cOXPdRQEAAADXo1Qh95ZbbtH+/fuL3b9v3z6FhIRcd1EAAADA9ShVyL3vvvv07LPP6ueffy607+LFi5o9e7b69u1bbsUBAAAAZVGqD54988wzWrNmjZo0aaKJEyeqadOmstlsOnz4sF577TXl5eVp5syZFVUrAAAAUCKlCrnB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0qRJqlu3rqpXr65+/frp1KlTbn0yMzM1dOhQORwOORwODR06VOfOnavgZ+fdEhMT1aFDBwUGBqp+/fp64IEHdOTIEbc+jH/FWrx4sVq3bu26oXrnzp3173//27Wf8a88iYmJstlsmjJliquN8a9Y8fHxstlsbpvT6XTtZ/wr3jfffKMhQ4aoTp06CggIUNu2bbVr1y7Xfq96DQwqTXJysvHz8zNLly41hw4dMpMnTzbVq1c3x48f93RpN5T333/fzJw507zzzjtGklm7dq3b/ueff94EBgaad955x+zfv98MHDjQhISEmOzsbFefsWPHmltuucWkpKSY3bt3m+7du5s2bdqYy5cvu/r06tXLREVFmbS0NJOWlmaioqJM3759K+tpeqV7773XJCUlmQMHDpi9e/eaPn36mIYNG5off/zR1Yfxr1jr1q0z69evN0eOHDFHjhwxTz/9tPHz8zMHDhwwxjD+leWTTz4x4eHhpnXr1mby5Mmudsa/Ys2ePdu0bNnSnD592rVlZGS49jP+FeuHH34wjRo1MiNGjDAff/yxOXr0qNm0aZP56quvXH286TUg5Faijh07mrFjx7q1NWvWzEyfPt1DFd34rg25+fn5xul0mueff97V9vPPPxuHw2Fef/11Y4wx586dM35+fiY5OdnV55tvvjFVqlQxGzZsMMYYc+jQISPJ7Nixw9Vn+/btRpL5/PPPK/hZ3TgyMjKMJJOammqMYfw9pVatWuYvf/kL419Jzp8/byIjI01KSoqJjY11hVzGv+LNnj3btGnTpsh9jH/Fe+qpp0zXrl2L3e9trwHLFSpJbm6udu3apbi4OLf2uLg4paWleagq6zl69KjS09Pdxtlutys2NtY1zrt27dKlS5fc+oSGhioqKsrVZ/v27XI4HOrUqZOrzx133CGHw8HrdZWsrCxJUu3atSUx/pUtLy9PycnJunDhgjp37sz4V5IJEyaoT58+uueee9zaGf/K8eWXXyo0NFQRERF65JFH9PXXX0ti/CvDunXrFB0drd/85jeqX7++2rVrp6VLl7r2e9trQMitJN9//73y8vIUHBzs1h4cHKz09HQPVWU9BWP5S+Ocnp6uqlWrqlatWr/Yp379+oXOX79+fV6v/58xRk8++aS6du2qqKgoSYx/Zdm/f79q1Kghu92usWPHau3atWrRogXjXwmSk5O1e/duJSYmFtrH+Fe8Tp066c0339QHH3ygpUuXKj09XTExMTp79izjXwm+/vprLV68WJGRkfrggw80duxYPfHEE3rzzTcled97wBJf63sjsdlsbo+NMYXacP3KMs7X9imqP6/X/5k4caL27dun//znP4X2Mf4Vq2nTptq7d6/OnTund955R8OHD1dqaqprP+NfMU6ePKnJkydr48aNqlatWrH9GP+K07t3b9d/t2rVSp07d9att96qFStW6I477pDE+Fek/Px8RUdHKyEhQZLUrl07HTx4UIsXL9awYcNc/bzlNWAmt5LUrVtXPj4+hf4FkpGRUehfPCi7gk/Z/tI4O51O5ebmKjMz8xf7fPfdd4XOf+bMGV4vSZMmTdK6deu0detWNWjQwNXO+FeOqlWr6rbbblN0dLQSExPVpk0bvfLKK4x/Bdu1a5cyMjLUvn17+fr6ytfXV6mpqfrf//1f+fr6usaG8a881atXV6tWrfTll1/y818JQkJC1KJFC7e25s2b68SJE5K873cAIbeSVK1aVe3bt1dKSopbe0pKimJiYjxUlfVERETI6XS6jXNubq5SU1Nd49y+fXv5+fm59Tl9+rQOHDjg6tO5c2dlZWXpk08+cfX5+OOPlZWVdVO/XsYYTZw4UWvWrNGWLVsUERHhtp/x9wxjjHJychj/CtajRw/t379fe/fudW3R0dEaPHiw9u7dq8aNGzP+lSwnJ0eHDx9WSEgIP/+VoEuXLoVuG/nFF1+oUaNGkrzwd0CJP6KG61ZwC7E33njDHDp0yEyZMsVUr17dHDt2zNOl3VDOnz9v9uzZY/bs2WMkmfnz55s9e/a4bsX2/PPPG4fDYdasWWP2799vHn300SJvX9KgQQOzadMms3v3bnP33XcXefuS1q1bm+3bt5vt27ebVq1a3fS3kBk3bpxxOBxm27Ztbrfw+emnn1x9GP+KNWPGDPPhhx+ao0ePmn379pmnn37aVKlSxWzcuNEYw/hXtqvvrmAM41/Rpk6darZt22a+/vprs2PHDtO3b18TGBjo+j3K+FesTz75xPj6+po//elP5ssvvzRvvfWWCQgIMCtXrnT18abXgJBbyV577TXTqFEjU7VqVXP77be7br2Ektu6dauRVGgbPny4MebKLUxmz55tnE6nsdvt5q677jL79+93O8fFixfNxIkTTe3atY2/v7/p27evOXHihFufs2fPmsGDB5vAwEATGBhoBg8ebDIzMyvpWXqnosZdkklKSnL1Yfwr1mOPPeb6f0i9evVMjx49XAHXGMa/sl0bchn/ilVwz1U/Pz8TGhpqBgwYYA4ePOjaz/hXvH/9618mKirK2O1206xZM7NkyRK3/d70GtiMMabk874AAACA92NNLgAAACyHkAsAAADLIeQCAADAcgi5AAAAsBxCLgAAACyHkAsAAADLIeQCAADAcgi5AAAAsBxCLgB4SLdu3TRlypRyPWd8fLzatm1bpmOPHTsmm82mvXv3lmtNAOAJvp4uAACsbMSIEVqxYkWh9i+//FJr1qyRn5+fB6oqWlhYmE6fPq26det6uhQAuG6EXACoYL169VJSUpJbW7169eTj4+Ohiorm4+Mjp9Pp6TIAoFywXAEAKpjdbpfT6XTbfHx8Ci1XCA8PV0JCgh577DEFBgaqYcOGWrJkidu5nnrqKTVp0kQBAQFq3LixZs2apUuXLpW4lszMTA0ePFj16tWTv7+/IiMjXQH82uUKI0aMkM1mK7Rt27ZNkpSbm6tp06bplltuUfXq1dWpUyfXPgDwNEIuAHiRl156SdHR0dqzZ4/Gjx+vcePG6fPPP3ftDwwM1PLly3Xo0CG98sorWrp0qV5++eUSn3/WrFk6dOiQ/v3vf+vw4cNavHhxscsTXnnlFZ0+fdq1TZ48WfXr11ezZs0kSSNHjtR///tfJScna9++ffrNb36jXr166csvv7y+QQCAcsByBQCoYO+9955q1Kjhety7d2/9/e9/L7Lvfffdp/Hjx0u6Mmv78ssva9u2ba5g+cwzz7j6hoeHa+rUqXr77bc1bdq0EtVy4sQJtWvXTtHR0a5zFMfhcMjhcEiS1qxZo9dff12bNm2S0+nU//t//0+rV6/WqVOnFBoaKkn6/e9/rw0bNigpKUkJCQklqgcAKgohFwAqWPfu3bV48WLX4+rVqxfbt3Xr1q7/ttlscjqdysjIcLX94x//0IIFC/TVV1/pxx9/1OXLlxUUFFTiWsaNG6eHHnpIu3fvVlxcnB544AHFxMT84jF79uzRsGHD9Nprr6lr166SpN27d8sYoyZNmrj1zcnJUZ06dUpcDwBUFEIuAFSw6tWr67bbbitR32vvtmCz2ZSfny9J2rFjhx555BHNmTNH9957rxwOh5KTk/XSSy+VuJbevXvr+PHjWr9+vTZt2qQePXpowoQJevHFF4vsn56ern79+mnUqFEaNWqUqz0/P18+Pj7atWtXoQ/QXT1rDQCeQsgFgBvEf//7XzVq1EgzZ850tR0/frzU56lXr55GjBihESNG6M4779Qf/vCHIkPuzz//rP79+6tZs2aaP3++27527dopLy9PGRkZuvPOO0v/ZACgghFyAeAGcdttt+nEiRNKTk5Whw4dtH79eq1du7ZU53j22WfVvn17tWzZUjk5OXrvvffUvHnzIvuOGTNGJ0+e1ObNm3XmzBlXe+3atdWkSRMNHjxYw4YN00svvaR27drp+++/15YtW9SqVSvdd9991/VcAeB6cXcFALhB9O/fX7/73e80ceJEtW3bVmlpaZo1a1apzlG1alXNmDFDrVu31l133SUfHx8lJycX2Tc1NVWnT59WixYtFBIS4trS0tIkSUlJSRo2bJimTp2qpk2bql+/fvr4448VFhZ23c8VAK6XzRhjPF0EAAAAUJ6YyQUAAIDlEHIBAABgOYRcAAAAWA4hFwAAAJZDyAUAAIDlEHIBAABgOYRcAAAAWA4hFwAAAJZDyAUAAIDlEHIBAABgOYRcAAAAWM7/B4YpDqNG2d+zAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "y_S_F=np.dstack(solution_S_F) # unpack the data\n", + "final_size_S_F=y_S_F[-1, 2, :]\n", + "\n", + "plt.figure(figsize=(8, 4))\n", + "plt.title(\"Epidemic final size distribution\")\n", + "plt.xlabel(\"Final size\")\n", + "plt.ylabel(\"Count\")\n", + "plt.hist(final_size_S_F, bins=100, color=\"C0\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "39f93f66", + "metadata": {}, + "source": [ + "We see that 28 of the 1000 simulations (2.8%) have final sizes very close to zero.\n", + "In these cases, the chain of infections reaches stochastic extinction before an epidemic is able to take off, as can be seen when plotting a selection of these failed epidemics." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08572965", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "# Plot failed epidemics\n", + "i_success_S_F=np.where(final_size_S_F>2000)\n", + "y_fail_S_F=np.delete(y_S_F, obj=i_success_S_F, axis=2) \n", + "f, ax = plt.subplots(figsize=(8, 4))\n", + "\n", + "ax.set_title(\"Stochastically extinct epidemic trajectories\")\n", + "ax.set_xlabel(\"Time\")\n", + "ax.set_ylabel(\"Infected count\")\n", + "for i in range(min(y_fail_S_F.shape[2], 3)):\n", + " ax.plot(t[0:300], y_fail_S_F[0:300,1,i], color=\"C0\", alpha=0.5)" + ] + }, + { + "cell_type": "markdown", + "id": "e8c41b94", + "metadata": {}, + "source": [ + "\n", + "We proceed to eliminate these when plotting our simulation outputs, since we'd like to compare the output here with our deterministic results (which, by definition, do not exhibit stochastic extinction):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f82a87ea", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "# Delete failed epidemics\n", + "i_fail_S_F=np.where(final_size_S_F<2000)\n", + "y_success_S_F=np.delete(y_S_F, obj=i_fail_S_F, axis=2) \n", + "\n", + "#########################\n", + "# Individual trajectories\n", + "#########################\n", + "\n", + "# Select 50 simulations to plot\n", + "i_rand=random.sample(range(y_success_S_F.shape[2]), 50)\n", + "\n", + "######################\n", + "# Confidence intervals\n", + "######################\n", + "\n", + "# Calculate 95%, 50% CIs and median.\n", + "y_S_F_lolo=np.percentile(y_success_S_F, 2.5, axis=2)\n", + "y_S_F_lo=np.percentile(y_success_S_F, 25, axis=2)\n", + "y_S_F_hi=np.percentile(y_success_S_F, 75, axis=2)\n", + "y_S_F_hihi=np.percentile(y_success_S_F, 97.5, axis=2)\n", + "y_S_F_md=np.percentile(y_success_S_F, 50, axis=2)\n", + "\n", + "\n", + "f, axarr = plt.subplots(2,3, layout='constrained', figsize=(10, 5))\n", + "\n", + "# Plot colours\n", + "colours=[\"C1\", \"C0\", \"C2\"]\n", + "\n", + "for i in range(0,3):\n", + " # Plot individual trajectories\n", + " for j in i_rand:\n", + " axarr[0][i].plot(t, y_success_S_F[:,i,j], color=colours[i], alpha=0.2)\n", + "\n", + " # Plot CI's\n", + " axarr[1][i].fill_between(t, y_S_F_lolo[:,i], y_S_F_hihi[:,i], alpha=0.2, facecolor=colours[i])\n", + " axarr[1][i].fill_between(t, y_S_F_lo[:,i], y_S_F_hi[:,i], alpha=0.4, facecolor=colours[i])\n", + " axarr[1][i].plot(t, y_S_F_md[:,i], color=colours[i])\n", + "\n", + "# Add titles\n", + "for idx, state in enumerate(stateList):\n", + " axarr[0][idx].set_ylabel(state, rotation=0)\n", + " axarr[1][idx].set_ylabel(state, rotation=0)\n", + " axarr[0][idx].set_xlabel('Time')\n", + " axarr[1][idx].set_xlabel('Time')\n", + "\n", + "axarr[0][1].set_title(\"50 stochastic simulations with shared parameters\")\n", + "axarr[1][1].set_title(\"Median (line), 50% CI (dark shaded) and 95% CI (light shaded) over 1000 simulations\")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "e2b6b36b", + "metadata": {}, + "source": [ + "### Random parameters\n", + "\n", + "Finally, we explore a scenario where we wish to solve for a stochastic system with parameters drawn randomly from some distributions.\n", + "Using the random parameter set, `random_param_set`, defined previously" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0c270ea", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up pygom object\n", + "ode_S_R = SimulateOde(stateList, paramList, transition=transitionList)\n", + "ode_S_R.initial_values = (x0, t[0])\n", + "\n", + "# In this case n_sim and n_param_draw mean the same thing since we have new parameter set per simulation\n", + "ode_S_R.parameters = random_param_set\n", + "solution_S_R, simT = ode_S_R.solve_stochast(t, n_sim, full_output=True)" + ] + }, + { + "cell_type": "markdown", + "id": "035eac47", + "metadata": {}, + "source": [ + "Again, we begin our analysis by inspecting the final size distribution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91cb77b0", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "y_S_R=np.dstack(solution_S_R)\n", + "\n", + "final_size_S_R=y_S_R[-1, 2, :]\n", + "plt.figure(figsize=(8, 4))\n", + "plt.title(\"Epidemic final size distribution\")\n", + "plt.xlabel(\"Final size\")\n", + "plt.ylabel(\"Count\")\n", + "plt.hist(final_size_S_R, bins=100)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "c54b61c9", + "metadata": {}, + "source": [ + "We see that the final size distribution is much more spread out, owing to increased variation in the parameters.\n", + "The threshold value separating failed and successful epidemics is less clear cut in this case and we judge this by eye to be 2000.\n", + "Again, eliminating the failed epidemics we plot the model output" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a072686d", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "# Delete failed epidemics\n", + "i_fail_S_R=np.where(final_size_S_R<2000)\n", + "y_success_S_R=np.delete(y_S_R, obj=i_fail_S_R, axis=2) \n", + "\n", + "#########################\n", + "# Individual trajectories\n", + "#########################\n", + "\n", + "# Select 50 simulations to plot\n", + "i_rand=random.sample(range(y_success_S_R.shape[2]), 50)\n", + "\n", + "######################\n", + "# Confidence intervals\n", + "######################\n", + "\n", + "# Calculate 95%, 50% CIs and median.\n", + "y_S_R_lolo=np.percentile(y_success_S_R, 2.5, axis=2)\n", + "y_S_R_lo=np.percentile(y_success_S_R, 25, axis=2)\n", + "y_S_R_hi=np.percentile(y_success_S_R, 75, axis=2)\n", + "y_S_R_hihi=np.percentile(y_success_S_R, 97.5, axis=2)\n", + "y_S_R_md=np.percentile(y_success_S_R, 50, axis=2)\n", + "\n", + "f, axarr = plt.subplots(2,3, layout='constrained', figsize=(10, 5))\n", + "\n", + "# Plot colours\n", + "colours=[\"C1\", \"C0\", \"C2\"]\n", + "\n", + "for i in range(0,3):\n", + " # Plot individual trajectories\n", + " for j in i_rand:\n", + " axarr[0][i].plot(t, y_success_S_R[:,i,j], color=colours[i], alpha=0.2)\n", + "\n", + " # Plot CI's\n", + " axarr[1][i].fill_between(t, y_S_R_lolo[:,i], y_S_R_hihi[:,i], alpha=0.2, facecolor=colours[i])\n", + " axarr[1][i].fill_between(t, y_S_R_lo[:,i], y_S_R_hi[:,i], alpha=0.4, facecolor=colours[i])\n", + " axarr[1][i].plot(t, y_S_R_md[:,i], color=colours[i])\n", + "\n", + "# Add titles\n", + "for idx, state in enumerate(stateList):\n", + " axarr[0][idx].set_ylabel(state, rotation=0)\n", + " axarr[1][idx].set_ylabel(state, rotation=0)\n", + " axarr[0][idx].set_xlabel('Time')\n", + " axarr[1][idx].set_xlabel('Time')\n", + "\n", + "axarr[0][1].set_title(\"50 stochastic simulations, each with randomly drawn parameters\")\n", + "axarr[1][1].set_title(\"Median (line), 50% CI (dark shaded) and 95% CI (light shaded) over 1000 simulations\")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "57d2bc06", + "metadata": {}, + "source": [ + "## Summary\n", + "\n", + "With two possible simulation methods and two possible parameter types, we have explored the four total model configurations.\n", + "We plot these results side by side for the infected compartment to provide an illustration of their key qualitative differences." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2b69ea71", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [], + "source": [ + "ymax=1250\n", + "\n", + "fig, axarr2 = plt.subplots(2,2, layout='constrained', figsize=(10, 6))\n", + "\n", + "axarr2[0][0].plot(t, solution_D_F[:,1], color=\"C0\")\n", + "axarr2[0][0].set_ylim(bottom=0, top=ymax)\n", + "\n", + "i_rand=random.sample(range(n_param_draws), 50)\n", + "\n", + "for i in i_rand:\n", + " axarr2[0][1].plot(t, y_S_F[:,1,i], color=\"C0\", alpha=0.3)\n", + " axarr2[1][0].plot(t, y_D_R[:,1,i], color=\"C0\", alpha=0.3)\n", + " axarr2[1][1].plot(t, y_S_R[:,1,i], color=\"C0\", alpha=0.3)\n", + "\n", + "axarr2[0][0].set_title(\"Deterministic with fixed params\")\n", + "axarr2[0][1].set_title(\"Stochastic with fixed params\")\n", + "axarr2[1][0].set_title(\"Deterministic with random params\")\n", + "axarr2[1][1].set_title(\"Stochastic with random params\")\n", + "\n", + "axarr2[0][0].set_xlabel(\"Time\")\n", + "axarr2[0][1].set_xlabel(\"Time\")\n", + "axarr2[1][0].set_xlabel(\"Time\")\n", + "axarr2[1][1].set_xlabel(\"Time\")\n", + "\n", + "axarr2[0][1].set_ylim(bottom=0, top=ymax)\n", + "axarr2[1][0].set_ylim(bottom=0, top=ymax)\n", + "axarr2[1][1].set_ylim(bottom=0, top=ymax)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "e1fe54a8", + "metadata": {}, + "source": [ + "" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/model_spec.ipynb b/docs/notebooks/model_spec.ipynb new file mode 100644 index 00000000..1d08ef2f --- /dev/null +++ b/docs/notebooks/model_spec.ipynb @@ -0,0 +1,334 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5d9ccebd", + "metadata": {}, + "source": [ + "# Defining an ODE system\n", + "\n", + "The starting point, when using PyGOM to study an ODE system, is to encapsulate the relevant information into a class {class}`.SimulateOde`.\n", + "Once defined as an instance of this class, the ODE system is ready for the application of PyGOM's various features such as simulation and parameter fitting.\n", + "\n", + "## Equations vs Transitions\n", + "\n", + "Firstly, we outline the two main ways we might think about defining our ODE system.\n", + "Typically, we may already know the set of equations which describes the rates of change of the dependent variables:\n", + "\n", + "$$\\frac{\\mathrm{d} \\mathbf{y}}{\\mathrm{d} t} = f(\\mathbf{y},\\boldsymbol{\\theta}, t)$$\n", + "\n", + "where $\\mathbf{y} = \\left(y_{1},\\ldots,y_{n}\\right)$ is a vector of the dependent variables, $\\boldsymbol{\\theta} = \\left(\\theta_{1},\\ldots, \\theta_{p}\\right)$ is the set of parameters and $f$ is a vector function giving the rates of change of each dependent variable.\n", + "Typically, as we have used here, rates of change are with respect to time, $t$, though other variables such as position are also common.\n", + "\n", + "Compartmental models, whereby the dependent variables represent categories or states, have another interpretation in which we may instead consider transitions between the different groups:\n", + "\n", + "$$\\begin{aligned}\n", + "y_i \\rightarrow y_j = f_{i,j}(\\mathbf{y},\\boldsymbol{\\theta}) \\\\\n", + "\\end{aligned}$$\n", + "\n", + "where $i, j = \\{1,\\ldots, n\\}$ and $f_{i,j}$ are functions governing the rate at which members of group $i$ transition to group $j$.\n", + "Since flows are symmetric ($f_{i,j}=-f_{j,i}$) and a group cannot flow into itself ($f_{i,i}=0$), we need only specify rates for one half of the transition matrix ($i>j$ or $j>i$).\n", + "\n", + "PyGOM allows the user flexibility in choosing which of these perspectives to use, or indeed combine, in order to build their models.\n", + "If given transitions, PyGOM will automatically convert these into equations and, {doc}`as we'll see later `, it can also attempt to reverse engineer transitions from equations.\n", + "\n", + "## Example: SIR model\n", + "\n", + "Here we use a Susceptible-Infected-Recovered epidemic model (an SIR model, for short) to demonstrate the two different ways PyGOM supports model specification.\n", + "Since we will frequently rely on the SIR model in examples throughout this tutorial, we take a moment here to outline its key features.\n", + "\n", + "```{warning}\n", + "There is some ambiguity in the naming of the Recovered class which is also commonly referred to as Removed.\n", + "In the latter sense, there is no distinction made between those who can no longer be infected due to infection acquired immunity and infection induced death.\n", + "However, for more complex models, the recovered class may become susceptible again due to the effects of immune waning and deaths versus recoveries are typically important to distinguish in real world applications.\n", + "Therefore, in this tutorial, the Recovered class will be reserved solely for those who survive infection.\n", + "```\n", + "\n", + "The assumptions of the SIR model can be stated as:\n", + "1) An average member of the population makes contact sufficient to transmit or receive infection with $c$ others per unit time. Each of these events carries a probability, $p$, of transmission such that each individual has an average of $cp = \\beta$ infectious contacts per unit time. This fixed contact rate reflects what is referred to as *standard* incidence, as opposed to *mass-action* incidence, where contacts per person are proportional to the total population size, $N$.\n", + "2) The population interacts heterogeneously as if a well mixed continuum.\n", + "For instance, a susceptible does not have contacts with other individuals, but with the entire population on average.\n", + "3) The infective class recovers at a rate, $\\gamma$.\n", + "4) No births, deaths (natural or from disease) or migration mean there is no entry into or departure from the population: $S(t)+I(t)+R(t)=N$.\n", + "\n", + "Under these assumptions, the rates of change of the population in each compartment (**S**usceptible, **I**nfected and **R**ecovered) are given by the following equations:\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d} S}{\\mathrm{d} t} &= -\\frac{\\beta SI}{N} \\\\\n", + "\\frac{\\mathrm{d} I}{\\mathrm{d} t} &= \\frac{\\beta SI}{N} - \\gamma I \\\\\n", + "\\frac{\\mathrm{d} R}{\\mathrm{d} t} &= \\gamma I.\n", + "\\end{aligned}$$\n", + "\n", + "However, it is equally valid to view this system as the result of two transitions; infection, which takes subjects from susceptible to infected and recovery, which takes them from infected to recovered:\n", + "\n", + "$$\\begin{aligned}\n", + "S \\rightarrow I &= \\frac{\\beta SI}{N} \\\\\n", + "I \\rightarrow R &= \\gamma I\n", + "\\end{aligned}$$\n", + "\n", + "where the left hand side of each equation indicates the transition and the right hand side the rate at which it occurs.\n", + "One advantage of specifying our system using the transition approach is that many will find transitions a more intuitive language when thinking about compartmental models.\n", + "Perhaps more beneficial, though, is that when building models with transitions using PyGOM, it enables the computer to do our book-keeping when converting transitions to ODE equations.\n", + "This reduces the error of, for example, including a flow out of one state, but forgetting to include it in the recipient state.\n", + "For example, in the case above, when indicating infections with $-\\frac{\\beta SI}{N}$ in the $S$ equation, we had to remember to include the opposite sign in the $I$ equation.\n", + "\n", + "## Defining the model with PyGOM\n", + "\n", + "Defining the system is handled by feeding {class}`.Transition` objects into the central class, {class}`.SimulateOde`.\n", + "An instance of the {class}`.Transition` class takes one of four types, which are specified by the `transition_type` argument, letting {class}`.SimulateOde` know which type of information it is being given.\n", + "This type could be `Transition` or `ODE`, as we've just been discussing, or one of two other available options, namely `Birth` and `Death` processes.\n", + "The {class}`.Transition` class accepts 3 or 4 parameters depending on which type is being defined, as summarised in the below table:\n", + "\n", + "| | Transition | Equation | Birth | Death |\n", + "|:---------------:|:-------------------------------:|:---------------------------------:|:--------------------------------------:|:--------------------------------------:|\n", + "| transition_type | T | ODE | B | D |\n", + "| origin | State transition is from, $y_i$ | State equation pertains to, $y_i$ | State birth process populates, $y_i$ | State death process depletes, $y_i$ |\n", + "| destination | State transition is to, $y_j$ | n/a | n/a | n/a |\n", + "| equation | $f_{i,j}$ | $\\frac{dy_i}{dt}$ | $\\frac{dy_i}{dt}$ due to birth process | $\\frac{dy_i}{dt}$ due to death process |\n", + "\n", + "```{note}\n", + "Arguably, the state which the birth process populates could be defined as a destination rather than an origin, but this is not the convention adopted here.\n", + "\n", + "Furthermore, the {class}`.Transition` class may have been better named.\n", + "One of the four possible input types is also called \"transition\", which would incorrectly imply that it has a special place within the class, given that it shares its name.\n", + "```\n", + "\n", + "Let's see how this is implemented for our example SIR system.\n", + "We import the relevant modules and then define our transitions:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "4c80a36a", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import Transition, TransitionType\n", + "\n", + "# Define SIR model through a list of ODEs\n", + "odeList = [\n", + " Transition(transition_type=TransitionType.ODE, origin='S', equation='-beta*S*I/N'),\n", + " Transition(transition_type=TransitionType.ODE, origin='I', equation='beta*S*I/N - gamma*I'),\n", + " Transition(transition_type=TransitionType.ODE, origin='R', equation='gamma*I') \n", + "]\n", + "\n", + "# Define SIR model through a list of transitions\n", + "transList = [\n", + " Transition(transition_type=TransitionType.T, origin='S', destination='I', equation='beta*S*I/N'),\n", + " Transition(transition_type=TransitionType.T, origin='I', destination='R', equation='gamma*I')\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "bc7ee766", + "metadata": {}, + "source": [ + "We now initialise two {class}`.SimulateOde` objects using these different approaches.\n", + "In addition to the ODE or transition information, we must specify which variables are parameters and which refer to states:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "511317c9", + "metadata": {}, + "outputs": [], + "source": [ + "stateList = ['S', 'I', 'R']\n", + "paramList = ['beta', 'gamma', 'N']" + ] + }, + { + "cell_type": "markdown", + "id": "b6a2bec7", + "metadata": {}, + "source": [ + "We import the relevant module and define the model in two different ways:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "aceb211a", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import SimulateOde\n", + "model_ode = SimulateOde(state=stateList, param=paramList, ode=odeList) # model defined via equations\n", + "model_tra = SimulateOde(state=stateList, param=paramList, transition=transList) # model defined via transitions" + ] + }, + { + "cell_type": "markdown", + "id": "8e38d76b", + "metadata": {}, + "source": [ + "We can use the {func}`.get_ode_eqn` function to verify that the models are equivalent:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "d0fb6c20", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\left[\\begin{matrix}- \\frac{I S \\beta}{N}\\\\- I \\gamma + \\frac{I S \\beta}{N}\\\\I \\gamma\\end{matrix}\\right]$" + ], + "text/plain": [ + "Matrix([\n", + "[ -I*S*beta/N],\n", + "[-I*gamma + I*S*beta/N],\n", + "[ I*gamma]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model_ode.get_ode_eqn()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4e8ec9a3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\left[\\begin{matrix}- \\frac{I S \\beta}{N}\\\\- I \\gamma + \\frac{I S \\beta}{N}\\\\I \\gamma\\end{matrix}\\right]$" + ], + "text/plain": [ + "Matrix([\n", + "[ -I*S*beta/N],\n", + "[-I*gamma + I*S*beta/N],\n", + "[ I*gamma]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model_tra.get_ode_eqn()" + ] + }, + { + "cell_type": "markdown", + "id": "205dec3d", + "metadata": {}, + "source": [ + "## Modifying models\n", + "\n", + "Once an instance of {class}`.SimulateOde` has been defined it may be modified.\n", + "For example, let's say we wish to add birth and death processes to the the previously defined SIR model of `model_ode`.\n", + "Time dependent parameters can be complicated in PyGOM, so here we will assume that birth and death rates cancel out so that $N$ remains a constant parameter.\n", + "If we assume that the birth rate is proportional to the total population, $\\mu N$, then balance can be achieved with a death rate from each compartment also proportional to $\\mu$ giving a total death rate of $\\mu (S+I+R)=\\mu N$\n", + "We must update the parameters of the class to reflect any additions:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0923151d", + "metadata": {}, + "outputs": [], + "source": [ + "model_ode.param_list = model_ode.param_list + ['mu']" + ] + }, + { + "cell_type": "markdown", + "id": "f9236e77", + "metadata": {}, + "source": [ + "We then include the additional processes, where we assume that all new births enter the population as susceptibles:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9b1546f8", + "metadata": {}, + "outputs": [], + "source": [ + "birthDeathList = [Transition(origin='S', equation='mu*N', transition_type=TransitionType.B), \n", + " Transition(origin='S', equation='mu*S', transition_type=TransitionType.D), \n", + " Transition(origin='I', equation='mu*I', transition_type=TransitionType.D), \n", + " Transition(origin='R', equation='mu*R', transition_type=TransitionType.D)]\n", + "\n", + "model_ode.birth_death_list = birthDeathList" + ] + }, + { + "cell_type": "markdown", + "id": "3685b2e1", + "metadata": {}, + "source": [ + "We can again use {func}`.get_ode_eqn` to verify that the equations are updated correctly:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6cc2ba1a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\left[\\begin{matrix}- \\frac{I S \\beta}{N} + N \\mu - S \\mu\\\\- I \\gamma - I \\mu + \\frac{I S \\beta}{N}\\\\I \\gamma - R \\mu\\end{matrix}\\right]$" + ], + "text/plain": [ + "Matrix([\n", + "[ -I*S*beta/N + N*mu - S*mu],\n", + "[-I*gamma - I*mu + I*S*beta/N],\n", + "[ I*gamma - R*mu]])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model_ode.get_ode_eqn()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/paramfit/bvpSimple.ipynb b/docs/notebooks/paramfit/bvpSimple.ipynb index 062c54f7..732badc2 100644 --- a/docs/notebooks/paramfit/bvpSimple.ipynb +++ b/docs/notebooks/paramfit/bvpSimple.ipynb @@ -6,259 +6,179 @@ "source": [ "# Solving Boundary Value Problems\n", "\n", - "In addition to finding solutions for an initial value problem (IVP) and estimating the unknown\n", - "parameters, this package also allows you to solve boundary value problems (BVP) with a little bit\n", - "of imagination. Here, we are going to show how a BVP can be solved by\n", - "treating it as a parameter estimation problem. Essentially, a shooting\n", - "method where the first boundary condition defines the initial condition\n", - "of an IVP and the second boundary condition is an observation. Two\n", - "examples, both from the [bvp4c implementation in MATLAB](https://uk.mathworks.com/help/matlab/ref/bvp4c.html), are demonstrated here.\n", - "\n", - "\n", - "```{note}\n", - "These examples are general and not specific to disease scenarios.\n", - "```" + "In addition to finding solutions for an initial value problem (IVP) and estimating unknown parameters, PyGOM also allows users to solve boundary value problems (BVPs) with a little bit of imagination.\n", + "Here, we show how a BVP can be solved by treating it as a parameter estimation problem.\n", + "Essentially, this is done via a shooting method where the first boundary condition defines the initial condition of an IVP and the second boundary condition is an observation.\n", + "We use projectile motion as our example system, which we note is not relevant to disease modelling scenarios, but then BVPs are not commonly useful in this domain anyway." ] }, { "cell_type": "markdown", - "id": "1cfce26c", + "id": "1908ca0b", "metadata": {}, "source": [ + "## Problem\n", "\n", - "## Simple model 1\n", - "\n", - "We are trying to find the solution to the second order differential\n", - "equation\n", + "Imagine launching a ball straight up into the air from a starting height $y(t=0)=0$. Ignoring air resistance, the ball will be pulled back to it's starting position under gravity.\n", "\n", - "$$\\nabla^{2} y + |y| = 0$$\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}^2 y}{\\mathrm{d} t^2}=-g\n", + "\\end{aligned}$$\n", "\n", - "subject to the boundary conditions $y(0) = 0$ and $y(4) = -2$. Convert\n", - "this into a set of first order ODEs\n", + "where $g$ is acceleration due to gravity. Reducing this equation to two first order ODEs in terms of position and velocity, $v$, yields:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{d y_{0}}{dt} &= y_{1} \\\\\n", - "\\frac{d y_{1}}{dt} &= -|y_{0}|\n", + "\\frac{\\mathrm{d} y}{\\mathrm{d} t}&=v\\\\\n", + "\\frac{\\mathrm{d} v}{\\mathrm{d} t}&=-g\n", "\\end{aligned}$$\n", "\n", - "using an auxiliary variable $y_{1} = \\nabla y$ and $y_{0} = y$. \n", - "Here we set up the system." + "Let's suppose that the ball lands 3 seconds later (i.e. $y(t=3)=0$).\n", + "We will now solve two related BVPs in which the initial speed is unknown and later, the parameter $g$.\n", + "\n", + "## Unknown initial conditions\n", + "\n", + "First, assuming we know that the acceleration due to gravity is $g=10ms^{-2}$, we must estimate the initial velocity ($v(t=0)$) required to ensure that the ball lands 3 seconds later.\n", + "This could be trivially solved via a quick analytical solution of the above equations resulting in $v(0)=15ms^{-1}$.\n", + "Here we focus on demonstrating PyGOM's functionality, so this value will instead serve as a target we hope to reproduce.\n", + "Another artefact of PyGOM, which will soon require changing, is that model parameters are automatically treated as unknowns.\n", + "For this example, it means that we must specify parameters (in this case $g$) numerically in our equations:" ] }, { "cell_type": "code", "execution_count": null, - "id": "594a9de8", + "id": "f244ed16", "metadata": {}, "outputs": [], "source": [ - "from pygom import Transition, TransitionType, DeterministicOde, SquareLoss\n", - "\n", - "import matplotlib.pyplot as plt\n", - "\n", - "stateList = ['y0', 'y1']\n", - "\n", - "paramList = []\n", - "\n", - "ode1 = Transition(origin='y0', equation='y1', transition_type=TransitionType.ODE)\n", + "from pygom import Transition, TransitionType, SimulateOde\n", "\n", - "ode2 = Transition(origin='y1', equation='-abs(y0)', transition_type=TransitionType.ODE)\n", + "stateList = ['y', 'v']\n", + "paramList=[]\n", "\n", - "model = DeterministicOde(stateList, paramList, ode=[ode1, ode2])\n", + "ode1 = Transition(transition_type=TransitionType.ODE, origin='y', equation='v')\n", + "ode2 = Transition(transition_type=TransitionType.ODE, origin='v', equation='-10') # -g replaced explicitly by -10\n", "\n", - "model.get_ode_eqn()" + "model = SimulateOde(stateList, paramList, ode=[ode1, ode2])" ] }, { "cell_type": "markdown", - "id": "9456e756", + "id": "9aa96bec", "metadata": {}, "source": [ - "We check that the equations are correct before proceeding to set up our\n", - "loss function. The loss function enables us to optimize the parameter choice.\n", - "\n", - "#TODO add some ref/notes for loss functions" + "We first plot an example trajectory.\n", + "Given we know that that the ball will land in 3 seconds if launched with speed $15ms^{-1}$, let's try a faster launch of $20ms^{-1}$ and the ball should still be in the air." ] }, { "cell_type": "code", "execution_count": null, - "id": "9ae19c03", + "id": "46ea09e8", "metadata": {}, "outputs": [], "source": [ - "import numpy\n", - "\n", - "from scipy.optimize import minimize\n", + "import numpy as np\n", + "t = np.linspace(0, 3, 100) # Time-points at which to find solutions\n", "\n", - "initialState = [0.0, 1.0]\n", + "theta = [0.0, 20.0] # Initial position and velocity\n", + "model.initial_values = (theta, t[0]) # Initial position, velocity and t[0]\n", + "solution = model.solve_determ(t[1::]) # Solve for subsequent timepoints\n", "\n", - "t = numpy.linspace(0, 4, 100)\n", - "\n", - "model.initial_values = (initialState, t[0])\n", + "import matplotlib.pyplot as plt\n", "\n", - "solution = model.integrate(t[1::])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3952c813", - "metadata": { - "tags": [ - "hide" - ] - }, - "outputs": [], - "source": [ - "f = plt.figure()\n", - "model.plot()\n", - "plt.close()" + "f, axarr = plt.subplots(layout='constrained')\n", + "axarr.plot(t, solution[:,0])\n", + "axarr.set_title(\"Height, y\")\n", + "axarr.set_xlabel(\"Time\");" ] }, { "cell_type": "markdown", - "id": "1a6de472", + "id": "5c225208", "metadata": {}, "source": [ - "\n", - "Setting up the second boundary condition $y(4) = -2$ is easy, because\n", - "that is only a single observation attached to the state $y_{1}$.\n", - "Enforcing the first boundary condition requires us to set it as the\n", - "initial condition. Because the condition only states that $y(0) = 0$,\n", - "the starting value of the other state $y_1$ is free. We let our loss\n", - "object know that it is free through the `targetState` input argument.\n", - "\n", - "#TODO unsure what this means" + "Let's now use PyGOM to solve for the initial condition that satisfies the BVP, using $20ms^{-1}$ as our initial guess.\n", + "It is admittedly a bit inefficient that we have to specify this initial guess twice both in the `theta` parameter and also the initial condition.\n", + "We let the solver know which variable we are solving the initial condition for by specifying the `target_state`:" ] }, { "cell_type": "code", "execution_count": null, - "id": "aaf5a503", + "id": "f73ab2a2", "metadata": {}, "outputs": [], "source": [ - "theta = [0.0]\n", - "\n", - "obj = SquareLoss(theta=theta, ode=model, x0=initialState, t0=t[0], \n", - " t=t[-1], y=[-2], state_name=['y0'], target_state=['y1'])\n", - "\n", - "thetaHat = minimize(fun=obj.costIV, x0=[0.0])\n", + "from scipy.optimize import minimize\n", + "from pygom import SquareLoss\n", "\n", - "print(thetaHat)\n", + "theta = [20.0]\n", "\n", - "model.initial_values = ([0.0] + thetaHat['x'].tolist(), t[0])\n", + "initialState = [0.0, 20.0]\n", "\n", - "solution = model.integrate(t[1::])" + "obj = SquareLoss(theta=theta,\n", + " ode=model,\n", + " t0=t[0], x0=initialState,\n", + " t=t[-1], y=[0],\n", + " state_name=['y'], target_state=['v'])\n" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "bffe9f2f", + "cell_type": "markdown", + "id": "4734f011", "metadata": {}, - "outputs": [], "source": [ - "f = plt.figure()\n", - "model.plot()\n", - "plt.close()" + "And we use the {func}`costIV` function to let the solver know we are considering an initial value problem:" ] }, { - "cell_type": "markdown", - "id": "472ff583", + "cell_type": "code", + "execution_count": null, + "id": "b70c7c06", "metadata": {}, + "outputs": [], "source": [ - "\n", - "We are going to visualize the solution, and also check the boundary\n", - "condition. The first became our initial condition, so it is always\n", - "satisfied and only the latter is of concern, which is zero (subject to\n", - "numerical error) from thetahat.\n", - "\n", - "#TODO what is thetahat?" + "thetaHat = minimize(fun=obj.costIV, x0=theta)\n", + "print(thetaHat)" ] }, { "cell_type": "markdown", - "id": "85032ca8", + "id": "b603595e", "metadata": {}, "source": [ - "\n", - "## Simple model 2\n", - "\n", - "Our second example is different as it involves an actual parameter and\n", - "also time. We have the Mathieu's Equation\n", - "\n", - "#TODO add ref\n", - "\n", - "$$\\nabla^{2} y + \\left(p - 2q \\cos(2x)\\right)y = 0$$\n", - "\n", - "and the aim is to compute the fourth eigenvalue $q=5$. There are three\n", - "boundary conditions\n", - "\n", - "$$\\nabla y(0) = 0, \\quad \\nabla y(\\pi) = 0, \\quad y(0) = 1$$\n", - "\n", - "and we aim to solve it by converting it to a first order ODE and tackle\n", - "it as an IVP. As our model object does not allow the use of the time\n", - "component in the equations, we introduce a anxiliary state $\\tau$ that\n", - "replaces time $t$. Rewrite the equations using\n", - "$y_{0} = y, y_{1} = \\nabla y$ and define our model as" + "We see that the target value of $15ms^{-1}$ and when plotting the trajectory below we see that the ball lands after precisely 3 seconds." ] }, { "cell_type": "code", "execution_count": null, - "id": "afcf4558", + "id": "cc728465", "metadata": {}, "outputs": [], "source": [ - "stateList = ['y0', 'y1', 'tau']\n", - "\n", - "IparamList = ['p']\n", - "\n", - "ode1 = Transition('y0', 'y1', TransitionType.ODE)\n", - "\n", - "ode2 = Transition('y1', '-(p - 2*5*cos(2*tau))*y0', TransitionType.ODE)\n", - "\n", - "ode3 = Transition('tau', '1', TransitionType.ODE)\n", - "\n", - "model = DeterministicOde(stateList, paramList, ode=[ode1, ode2, ode3])\n", - "\n", - "theta = [1.0, 1.0, 0.0]\n", - "\n", - "p = 15.0\n", - "\n", - "t = numpy.linspace(0, numpy.pi)\n", - "\n", - "model.parameters = [('p',p)]\n", + "model.initial_values = ([0.0] + thetaHat['x'].tolist(), t[0])\n", "\n", - "model.initial_values = (theta, t[0])\n", + "solution = model.integrate(t[1::])\n", "\n", - "solution = model.integrate(t[1::])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c75eea5c", - "metadata": {}, - "outputs": [], - "source": [ - "f = plt.figure()\n", - "model.plot()\n", - "plt.close()" + "f, axarr = plt.subplots(layout='constrained')\n", + "axarr.plot(t, solution[:,0])\n", + "axarr.set_title(\"Height, y\")\n", + "axarr.set_xlabel(\"Time\");" ] }, { "cell_type": "markdown", - "id": "1e1407cf", + "id": "85032ca8", "metadata": {}, "source": [ + "## Unknown parameters\n", "\n", - "Now we are ready to setup the estimation. Like before, we set up the\n", - "second boundary condition by pretending that it is an observation. We\n", - "have all the initial conditions defined by the first boundary condition." + "Now we consider the case where initial conditions are known, but we wish to estimate the unknown parameter $g$ which satisfies the BVP.\n", + "Like before, we set up the second boundary condition by pretending that it is an observation.\n", + "This time we omit the `target_state` argument to let the solver know that our initial conditions are fixed.\n", + "We declare $g$ as a model parameter and then solve as before." ] }, { @@ -268,32 +188,27 @@ "metadata": {}, "outputs": [], "source": [ - "obj = SquareLoss(15.0, model, x0=[1.0, 0.0, 0.0], t0=0.0, \n", - " t=numpy.pi, y=0.0, state_name='y1')\n", + "stateList = ['y', 'v']\n", + "paramList = ['g']\n", "\n", - "xhatObj = minimize(obj.cost,[15])\n", + "ode1 = Transition(transition_type=TransitionType.ODE, origin='y', equation='v')\n", + "ode2 = Transition(transition_type=TransitionType.ODE, origin='v', equation='-g')\n", "\n", - "print(xhatObj)\n", + "model = SimulateOde(stateList, paramList, ode=[ode1, ode2])\n", "\n", - "model.parameters = [('p', xhatObj['x'][0])]\n", + "model.parameters = [('g', 5.0)]\n", + "theta = [5.0]\n", + "initialState = [0.0, 15.0]\n", "\n", - "model.initial_values = ([1.0, 0.0, 0.0], t[0])\n", + "t = np.linspace(0, 3, 100)\n", "\n", - "solution = model.integrate(t[1::])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "653c998f", - "metadata": {}, - "outputs": [], - "source": [ - "f = plt.figure()\n", - "\n", - "model.plot()\n", + "obj = SquareLoss(theta=theta,\n", + " ode=model,\n", + " t0=t[0], x0=initialState,\n", + " t=t[-1], y=[0],\n", + " state_name=['y'])\n", "\n", - "plt.close()" + "thetaHat = minimize(fun=obj.cost, x0=theta)" ] }, { @@ -301,33 +216,18 @@ "id": "f3719cf8", "metadata": {}, "source": [ - "\n", - "The plot of the solution shows the path that satisfies all boundary\n", - "condition. The last subplot is time, which is redundant here but\n", - "the `DeterministicOde.plot` method is not yet able to recognize the time\n", - "component. Possible speed up can be achieved through the use of\n", - "derivative information or via the root finding method that tackles the\n", - "gradient directly, instead of the cost function.\n", - "\n", - "#TODO add meth/fun/class refs for root finding method, derivative" + "We see that the result of $g=10ms^{-2}$ is recovered:" ] }, { - "cell_type": "markdown", - "id": "cb79c4f6", + "cell_type": "code", + "execution_count": null, + "id": "1be53116", "metadata": {}, + "outputs": [], "source": [ - "\n", - "**Reference**\n", - "\n", - "[1] " + "print(thetaHat)" ] - }, - { - "cell_type": "markdown", - "id": "ef9004bd", - "metadata": {}, - "source": [] } ], "metadata": { @@ -337,8 +237,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/paramfit/ebola_estimate.ipynb b/docs/notebooks/paramfit/ebola_estimate.ipynb new file mode 100644 index 00000000..64087a71 --- /dev/null +++ b/docs/notebooks/paramfit/ebola_estimate.ipynb @@ -0,0 +1,763 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a6b66278", + "metadata": {}, + "source": [ + "# Parameter Estimation: Example 2\n", + "\n", + "Continuing from the example in {doc}`.estimate1`, we show why estimating the parameters\n", + "for ODE's can be difficult. This is especially true if there is a lack of data\n", + "or when there are too much flexibility in the model. \n", + "\n", + "```{note}\n", + "For reproducibility purposes, only deterministic models are used here. If a stochastic algorithm is required we use a fixed seed.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "8897e924", + "metadata": {}, + "source": [ + "\n", + "## SEIR model\n", + "\n", + "We demonstrate the estimation on data collected from an Ebola outbreak in West\n", + "Africa. We use the number of deaths in Guinea and its corresponding time\n", + "the data was recorded. These data are publicly available and they can be\n", + "obtained [here](https://github.com/cmrivers/ebola). \n", + "\n", + "We provide the data here for reproducibility and ease." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6826d12d", + "metadata": {}, + "outputs": [], + "source": [ + "# the number of deaths and cases in Guinea\n", + "\n", + "yDeath = [29.0, 59.0, 60.0, 62.0, 66.0, 70.0, 70.0, 80.0, 83.0, 86.0, 95.0, 101.0, 106.0, 108.0, 122.0, 129.0, 136.0, 141.0, 143.0, 149.0, 155.0, 157.0, 158.0,\n", + "157.0, 171.0, 174.0, 186.0, 193.0, 208.0, 215.0, 226.0, 264.0,\n", + "267.0, 270.0, 303.0, 305.0, 307.0, 309.0, 304.0, 310.0, 310.0,\n", + "314.0, 319.0, 339.0, 346.0, 358.0, 363.0, 367.0, 373.0, 377.0,\n", + "380.0, 394.0, 396.0, 406.0, 430.0, 494.0, 517.0, 557.0, 568.0, 595.0,\n", + "601.0, 632.0, 635.0, 648.0, 710.0, 739.0, 768.0, 778.0, 843.0,\n", + "862.0, 904.0, 926.0, 997.0]\n", + "\n", + "yCase = [49.0, 86.0, 86.0, 86.0, 103.0, 112.0, 112.0, 122.0, 127.0, 143.0, 151.0, 158.0, 159.0, 168.0, 197.0, 203.0, 208.0, 218.0, 224.0, 226.0, 231.0,\n", + "235.0, 236.0, 233.0, 248.0, 258.0, 281.0, 291.0, 328.0, 344.0,\n", + "351.0, 398.0, 390.0, 390.0, 413.0, 412.0, 408.0, 409.0, 406.0,\n", + "411.0, 410.0, 415.0, 427.0, 460.0, 472.0, 485.0, 495.0, 495.0,\n", + "506.0, 510.0, 519.0, 543.0, 579.0, 607.0, 648.0, 771.0, 812.0,\n", + "861.0, 899.0, 936.0, 942.0, 1008.0, 1022.0, 1074.0, 1157.0, 1199.0,\n", + "1298.0, 1350.0, 1472.0, 1519.0, 1540.0, 1553.0, 1906.0]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "1d9b4bfb", + "metadata": {}, + "outputs": [], + "source": [ + "# the corresponding time\n", + "\n", + "t = [0.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 9.0, 10.0, 13.0, 16.0, 18.0, 20.0, 23.0, 25.0, 26.0, 29.0, 32.0, 35.0, 40.0, 42.0, 44.0, 46.0, 49.0, 51.0, 62.0, 66.0, 67.0,\n", + "71.0, 73.0, 80.0, 86.0, 88.0, 90.0, 100.0, 102.0, 106.0, 108.0,\n", + "112.0, 114.0, 117.0, 120.0, 123.0, 126.0, 129.0, 132.0, 135.0, 137.0, 140.0, 142.0, 144.0, 147.0, 149.0, 151.0, 157.0, 162.0, 167.0,\n", + "169.0, 172.0, 175.0, 176.0, 181.0, 183.0, 185.0, 190.0, 193.0,\n", + "197.0, 199.0, 204.0, 206.0, 211.0, 213.0, 218.0]" + ] + }, + { + "cell_type": "markdown", + "id": "fe8c48cf", + "metadata": {}, + "source": [ + "### Simple estimation\n", + "\n", + "First, we are going to fit a standard **SEIR** model to the data.\n", + "Details of the models can be found in {doc}`common_models` Defining the model\n", + "as usual with an approximation of what the parameters might be, here,\n", + "we choose the values to be the mid point of our feasible region (defined\n", + "by our box constraints later).\n", + "\n", + "Let's see what the data looks like:" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "937db857", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy\n", + "population = 1175e4\n", + "y = numpy.reshape(numpy.append(numpy.array(yCase), numpy.array(yDeath)),\n", + " (len(yCase),2), 'F')#/population\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 4))\n", + "\n", + "axarr[0].scatter(t, y[:,0])\n", + "axarr[1].scatter(t, y[:,1])\n", + "axarr[0].set_yscale('log')\n", + "axarr[1].set_yscale('log')" + ] + }, + { + "cell_type": "markdown", + "id": "07b101f6", + "metadata": {}, + "source": [ + "Let's set up model" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "5dfa5094", + "metadata": {}, + "outputs": [], + "source": [ + "# Define SIR model\n", + "from pygom import SimulateOde, Transition, TransitionType\n", + "stateList = ['S', 'E', 'I', 'R']\n", + "paramList = ['beta', 'alpha', 'gamma']\n", + "\n", + "transitionList = [Transition(origin='S', destination='E', equation='beta*S*I', transition_type=TransitionType.T),\n", + " Transition(origin='E', destination='I', equation='alpha*E', transition_type=TransitionType.T),\n", + " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)]\n", + "\n", + "ode_obj = SimulateOde(stateList, paramList, transition=transitionList)\n", + "\n", + "theta = numpy.array([5.0, 5.0, 5.0])\n", + "ode_obj.parameters=theta\n", + "\n", + "from pygom import SquareLoss\n", + "\n", + "x0 = [1., 0., 49.0/population, 29.0/population]\n", + "\n", + "objLegrand = SquareLoss(theta, ode_obj,\n", + " t0=t[0], x0=x0,\n", + " t=t[1::], y=y[1::,:],\n", + " state_name=['I','R'],\n", + " state_weight=numpy.sqrt(population*2)) " + ] + }, + { + "cell_type": "markdown", + "id": "fdc428cc", + "metadata": {}, + "source": [ + "Now let's param" + ] + }, + { + "cell_type": "markdown", + "id": "288f8273", + "metadata": {}, + "source": [ + "\n", + "Then we optimize, first, assuming that the initial conditions are\n", + "accurate. Some relatively large bounds are used for this particular\n", + "problem.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "fc31ee5f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL\n", + " success: True\n", + " status: 0\n", + " fun: 9.045332633285773e-07\n", + " x: [ 4.919e+00 5.000e+00 5.079e+00]\n", + " nit: 10\n", + " jac: [ 9.551e-06 1.237e-08 -9.238e-06]\n", + " nfev: 11\n", + " njev: 11\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n" + ] + } + ], + "source": [ + "import scipy.optimize\n", + "\n", + "boxBounds = [ (0.0,10.0), (0.0,10.0), (0.0,10.0)]\n", + "\n", + "res = scipy.optimize.minimize(fun=objLegrand.cost, jac=objLegrand.sensitivity, x0=theta, bounds=boxBounds, method='l-bfgs-b')\n", + "\n", + "print(res)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "d3e42fe2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAn4AAAHWCAYAAADpd4R+AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAACPX0lEQVR4nOzdeVxU5f4H8M8wzLAJoyyyKCKSgYYrXhXN7WYoZmrLVW9dNG9545YpmpmkXpcyrVu2uaVppnXDn+HSYhYtoia5IJq7uIIIKojDpjPDzPP748joxCIgw2GYz/t1z4uZc5455zunO4/fc57lKIQQAkRERETU6DnIHQARERER1Q8mfkRERER2gokfERERkZ1g4kdERERkJ5j4EREREdkJJn5EREREdoKJHxEREZGdYOJHREREZCeY+BERERHZCSZ+RHfYs2cPHnvsMbRq1QpOTk7w9fVFZGQkXn75ZblDIyKqU2vWrIFCoah02b59u9whkhU4yh0AUUPx3XffYdiwYejfvz/efvtt+Pv7Izs7G/v370dCQgLeffdduUMkIqpzn376KcLCwsqtb9++vQzRkLUp+KxeIkm/fv2QlZWFEydOwNHR8prIZDLBwYE3yImo8VizZg3GjRuHffv2oVu3bnKHQ/WE/5IR3ZKXlwdvb+9ySR8AJn1ERNQo8F8zolsiIyOxZ88eTJw4EXv27IHBYJA7JCIiqzMajSgtLbVYjEaj3GGRlbCpl+iWvLw8jBgxArt27QIAqFQq/OUvf8Gjjz6KCRMmoEmTJjJHSERUd8qaeiuiVCpRWlpazxFRfeAdP6JbvLy8sHPnTuzbtw8LFy7E8OHDcerUKcTHx6NDhw7Izc2VO0SiBm/Hjh149NFHERAQAIVCgc2bN1v9mFlZWfjHP/4BLy8vuLq6onPnzkhNTbX6cRuLtWvXYt++fRbLnj175A6LrISjeon+pFu3buaOzgaDAa+++iree+89vP3223j77bdljo6oYSsuLkanTp0wbtw4PPHEE1Y/Xn5+Pnr37o0BAwbg+++/R/PmzXHmzBk0bdrU6sduLNq1a8fBHXaEd/yIqqBSqTB79mwAwJEjR2SOhqjhi46OxhtvvIHHH3+8wu16vR7Tpk1DixYt4Obmhh49etzTfHFvvfUWAgMD8emnn6J79+5o3bo1HnroIYSEhNR6n0SNGRM/oluys7MrXH/8+HEAQEBAQH2GQ9QojRs3Dr/99hsSEhLwxx9/4G9/+xsGDx6M9PT0Wu3v66+/Rrdu3fC3v/0NzZs3R5cuXbBy5co6jpqo8WBTL9EtgwYNQsuWLfHoo48iLCwMJpMJBw8exLvvvosmTZpg0qRJcodIZNPOnDmDL7/8EhcvXjRfSE2dOhXbtm3Dp59+ijfffLPG+zx79iyWLVuGKVOm4LXXXsPevXsxceJEODk5YcyYMXX9FRqlI0eOVDiQIyQkBD4+PjJERNbExI/olpkzZ2LLli147733kJ2dDZ1OB39/fwwcOBDx8fFo166d3CES2bQDBw5ACIH777/fYr1Op4OXlxcA4Pz58wgODq5yPy+++CIWL14MQJpcvVu3buaksUuXLjh69CiWLVvGxK+aKhvZu3LlSjz33HP1HA1ZGxM/oltGjhyJkSNHyh0GUaNlMpmgVCqRmpoKpVJpsa1suqQWLVqYu1dUplmzZubX/v7+5R4t1q5dOyQmJtZR1I3XM888g2eeeUbuMKieMfEjIqJ60aVLFxiNRly5cgV9+vSpsIxKparwubGV6d27N06ePGmx7tSpUwgKCrqnWIkaKyZ+RERUZ4qKinD69Gnz+3PnzuHgwYPw9PTE/fffj6effhpjxozBu+++iy5duiA3Nxe//PILOnTogCFDhtT4eJMnT0avXr3w5ptvYuTIkdi7dy9WrFiBFStW1OXXImo0+OQOIiKqM9u3b8eAAQPKrR87dizWrFkDg8GAN954A2vXrkVWVha8vLwQGRmJuXPnokOHDrU65rfffov4+Hikp6cjODgYU6ZMwfjx4+/1qxA1Skz8iIiIiOwE5/EjIiIishNM/IiIiIjsBAd3WIHJZMKlS5fg7u4OhUIhdzhEdkkIgcLCQgQEBMDBgde41sQ6j0h+1a3zmPhZwaVLlxAYGCh3GEQEIDMzEy1btpQ7jEaNdR5Rw3G3Oo+JnxW4u7sDkE6+h4eHzNEQ2aeCggIEBgaaf49kPazziORX3TqPiZ8VlDV1eHh4sBIkkhmbHq2PdR5Rw3G3Oo8dX4iIiIjsBBM/IiIiIjvBxI+IiIjITjDxk9Hnv19AzKo9SEy9KHcoRERWt3LHWcSs2oNtR7LlDoXIbjHxk9G53GLsTM/FycuFcodCRGR1py4XYmd6Lk5fKZI7FCK7xcRPRt5NnAAAuYU6mSMhIrI+b/dbdV6RXuZIiOxXrRK/pUuXIjg4GM7OzoiIiMDOnTurLL9kyRK0a9cOLi4uCA0Nxdq1ay22GwwGzJs3DyEhIXB2dkanTp2wbds2izKFhYWIi4tDUFAQXFxc0KtXL+zbt8+izOXLl/HMM88gICAArq6uGDx4MNLT083bz58/D4VCUeGyYcMGc7nWrVuX2z59+vTanKoqeTdRAwByi1kJElHjZ77YLeLFLpFcapz4rV+/HnFxcZgxYwbS0tLQp08fREdHIyMjo8Lyy5YtQ3x8PObMmYOjR49i7ty5ePHFF/HNN9+Yy8ycORMff/wxPvroIxw7dgyxsbF47LHHkJaWZi7z3HPPISkpCevWrcPhw4cRFRWFgQMHIisrC4D0qJIRI0bg7Nmz2LJlC9LS0hAUFISBAweiuLgYABAYGIjs7GyLZe7cuXBzc0N0dLRF3PPmzbMoN3PmzJqeqrviHT8isifmi10mfkTyETXUvXt3ERsba7EuLCxMTJ8+vcLykZGRYurUqRbrJk2aJHr37m1+7+/vLxYvXmxRZvjw4eLpp58WQghRUlIilEql+Pbbby3KdOrUScyYMUMIIcTJkycFAHHkyBHz9tLSUuHp6SlWrlxZ6ffp3Lmz+Oc//2mxLigoSLz33nuVfuZutFqtACC0Wm2V5f7IvC6CXv1WdJ+fVOtjEVHFqvs7pHtX3XO9K/2qCHr1WzHw3e31FBmR/aju77BGd/z0ej1SU1MRFRVlsT4qKgq7d++u8DM6nQ7Ozs4W61xcXLB3714YDIYqy+zatQsAUFpaCqPRWGUZnU66gryzjFKphFqtNpf5s9TUVBw8eBDPPvtsuW1vvfUWvLy80LlzZ8yfPx96fd03x3q7S1e/eUV6mEyizvdPRNSQsKmXSH41Svxyc3NhNBrh6+trsd7X1xc5OTkVfmbQoEH45JNPkJqaCiEE9u/fj9WrV8NgMCA3N9dcZtGiRUhPT4fJZEJSUhK2bNmC7GxpyL+7uzsiIyPx+uuv49KlSzAajfj888+xZ88ec5mwsDAEBQUhPj4e+fn50Ov1WLhwIXJycsxl/mzVqlVo164devXqZbF+0qRJSEhIwK+//ooJEybg/fffxwsvvFDpedHpdCgoKLBYqsPTTUr8Sk0CBTcN1foMEZGt8rrV1JtfYoDBaJI5GiL7VKvBHX9+DpwQotJnw82aNQvR0dHo2bMnVCoVhg8fjmeeeQaAdEcOAD744AO0bdsWYWFhUKvVmDBhAsaNG2feDgDr1q2DEAItWrSAk5MTPvzwQzz11FPmMiqVComJiTh16hQ8PT3h6uqK7du3Izo62mI/ZW7cuIH//e9/Fd7tmzx5Mvr164eOHTviueeew/Lly7Fq1Srk5eVV+B0XLFgAjUZjXgIDA+9+EgE4OSrh4Sw9LplXwETU2DVzVcPh1j8V+RzURiSLGiV+3t7eUCqV5e7uXblypdxdwDIuLi5YvXo1SkpKcP78eWRkZKB169Zwd3eHt7c3AMDHxwebN29GcXExLly4gBMnTqBJkyYIDg427yckJATJyckoKipCZmamuan4zjIRERE4ePAgrl+/juzsbGzbtg15eXkWZcp89dVXKCkpwZgxY+76vXv27AkAOH36dIXb4+PjodVqzUtmZuZd91nmdtMHK0EiatyUDgp4ukl13lVe7BLJokaJn1qtRkREBJKSkizWJyUllWsu/TOVSoWWLVtCqVQiISEBQ4cOhYOD5eGdnZ3RokULlJaWIjExEcOHDy+3Hzc3N/j7+yM/Px8//PBDhWU0Gg18fHyQnp6O/fv3V1hm1apVGDZsGHx8fO76vctGF/v7+1e43cnJCR4eHhZLdbHPCxHZk7KRvXm82CWShWNNPzBlyhTExMSgW7duiIyMxIoVK5CRkYHY2FgA0t2vrKws81x9p06dwt69e9GjRw/k5+dj0aJFOHLkCD777DPzPvfs2YOsrCx07twZWVlZmDNnDkwmE6ZNm2Yu88MPP0AIgdDQUJw+fRqvvPIKQkNDMW7cOHOZDRs2wMfHB61atcLhw4cxadIkjBgxotxglNOnT2PHjh3YunVrue+XkpKC33//HQMGDIBGo8G+ffswefJkDBs2DK1atarp6bqrsgEenNKFiOyBdLFbyItdIpnUOPEbNWoU8vLyzPPchYeHY+vWrQgKCgIAZGdnW8zpZzQa8e677+LkyZNQqVQYMGAAdu/ejdatW5vL3Lx5EzNnzsTZs2fRpEkTDBkyBOvWrUPTpk3NZbRaLeLj43Hx4kV4enriiSeewPz586FSqcxlsrOzMWXKFFy+fBn+/v4YM2YMZs2aVe47rF69Gi1atCiXEALS3bv169dj7ty50Ol0CAoKwvjx4y2S0LrEpl4isiecy49IXgohBOcRqWMFBQXQaDTQarV3bfb96Od0vJt0CqO6BeKtJzvWU4REjV9Nfod0b2pyrt/cehwrdpzFcw8GY+bQ9vUUIVHjV93fIZ/VK7PmHtIdvyuFN2WOhIjI+nyacHAHkZyY+MnMx52VIBHZD/PFbgHrPCI5MPGTWXN36UkjrASJyB7wjh+RvJj4yazsjl9esR5GPraNiBq5sjrvSgG7txDJgYmfzLzc1FAoAKNJ4Bpnsieie7Rjxw48+uijCAgIgEKhwObNm6ssv337digUinLLiRMnrBJfWStHwc1S3DQYrXIMIqocEz+ZOSod4HXrmb1XOZcfEd2j4uJidOrUCYsXL67R506ePIns7Gzz0rZtW6vE5+HiCLWj9E8P6zyi+lfjefyo7nk3cUJukR5XCm+iPTjtBBHVXnR0NKKjo2v8uebNm1vMnWotCoUCPk2ckHX9Bq4W6RDo6Wr1YxLRbbzj1wA097g1wINXv0Qkky5dusDf3x8PPfQQfv311yrL6nQ6FBQUWCw1cbufH+s8ovrGxK8BaF42pQsTPyKqZ/7+/lixYgUSExOxceNGhIaG4qGHHsKOHTsq/cyCBQug0WjMS2BgYI2O6cv5S4lkw6beBqCsErzMUW5EVM9CQ0MRGhpqfh8ZGYnMzEy888476Nu3b4WfiY+Px5QpU8zvCwoKapT8+d5q5WCdR1T/eMevAfC7VQnmaFkJEpH8evbsifT09Eq3Ozk5wcPDw2KpCV9zncdWDqL6xsSvASjr43eZTb1E1ACkpaXB39/favv3Nfdr5sUuUX1jU28DUHbH7zLv+BHRPSoqKsLp06fN78+dO4eDBw/C09MTrVq1Qnx8PLKysrB27VoAwPvvv4/WrVvjgQcegF6vx+eff47ExEQkJiZaLUa2chDJh4lfA+CnkSrBq0U6GE0CSgeFzBERka3av38/BgwYYH5f1hdv7NixWLNmDbKzs5GRkWHertfrMXXqVGRlZcHFxQUPPPAAvvvuOwwZMsRqMfpp2K+ZSC5M/BoALzc1HG49vSOvSGdu+iUiqqn+/ftDiMof/7hmzRqL99OmTcO0adOsHJWlsjqu4GYpbuiNcFEr6/X4RPaMffwaAEelg3leq8uc14qIGjl3J0e43kr2eNePqH4x8WsgzKPcWAkSUSOnUChY5xHJhIlfA3F7eoMbMkdCRGR9HOBBJA8mfg1EwK0BHtmsBInIDvizziOSBRO/BsK/qQsAVoJEZB/8m5YlfmzlIKpPTPwaiNtXv6wEiajx89NIF7uXrvNil6g+MfFrIPw1vONHRPajrHtLTgEvdonqU60Sv6VLlyI4OBjOzs6IiIjAzp07qyy/ZMkStGvXDi4uLggNDTXPGF/GYDBg3rx5CAkJgbOzMzp16oRt27ZZlCksLERcXByCgoLg4uKCXr16Yd++fRZlLl++jGeeeQYBAQFwdXXF4MGDyz1vsn///lAoFBbL6NGjLcrk5+cjJiYGGo0GGo0GMTExuH79eg3PUs3c2d+lqjm4iIgaA/PFLu/4EdWrGid+69evR1xcHGbMmIG0tDT06dMH0dHRFjPB32nZsmWIj4/HnDlzcPToUcydOxcvvvgivvnmG3OZmTNn4uOPP8ZHH32EY8eOITY2Fo899hjS0tLMZZ577jkkJSVh3bp1OHz4MKKiojBw4EBkZWUBAIQQGDFiBM6ePYstW7YgLS0NQUFBGDhwIIqLiy1iGj9+PLKzs83Lxx9/bLH9qaeewsGDB7Ft2zZs27YNBw8eRExMTE1PVY34ejhDoQD0pSbkFeuteiwiIrmVXezmFetx02CUORoiOyJqqHv37iI2NtZiXVhYmJg+fXqF5SMjI8XUqVMt1k2aNEn07t3b/N7f318sXrzYoszw4cPF008/LYQQoqSkRCiVSvHtt99alOnUqZOYMWOGEEKIkydPCgDiyJEj5u2lpaXC09NTrFy50ryuX79+YtKkSZV+v2PHjgkA4vfffzevS0lJEQDEiRMnKv3cnbRarQAgtFpttcqX6fZGkgh69Vtx+OL1Gn2OiMqr7e+Qaq4259pkMonQmVtF0KvfinNXi6wYHZF9qO7vsEZ3/PR6PVJTUxEVFWWxPioqCrt3767wMzqdDs7Olo8gc3Fxwd69e2EwGKoss2vXLgBAaWkpjEZjlWV0OumJF3eWUSqVUKvV5jJlvvjiC3h7e+OBBx7A1KlTUVhYaN6WkpICjUaDHj16mNf17NkTGo2myu9YUFBgsdRG2RVw1nX2eSGixk2hUCCgbIAHB7UR1ZsaJX65ubkwGo3w9fW1WO/r64ucnJwKPzNo0CB88sknSE1NhRAC+/fvx+rVq2EwGJCbm2sus2jRIqSnp8NkMiEpKQlbtmxBdnY2AMDd3R2RkZF4/fXXcenSJRiNRnz++efYs2ePuUxYWBiCgoIQHx+P/Px86PV6LFy4EDk5OeYyAPD000/jyy+/xPbt2zFr1iwkJibi8ccfN2/PyclB8+bNy32P5s2bV/odFyxYYO4PqNFoEBgYWIOzeluLpmWj3FgJElHjF3CrzsvKZ51HVF9qNbhDoVBYvBdClFtXZtasWYiOjkbPnj2hUqkwfPhwPPPMMwCkO3IA8MEHH6Bt27YICwuDWq3GhAkTMG7cOPN2AFi3bh2EEGjRogWcnJzw4Ycf4qmnnjKXUalUSExMxKlTp+Dp6QlXV1ds374d0dHRFvsZP348Bg4ciPDwcIwePRpfffUVfvrpJxw4cKDS73e37xgfHw+tVmteMjMzq3EWy2vBSpCI7Ii5zuPFLlG9qVHi5+3tDaVSWe7O15UrV8rdBSzj4uKC1atXo6SkBOfPn0dGRgZat24Nd3d3eHt7AwB8fHywefNmFBcX48KFCzhx4gSaNGmC4OBg835CQkKQnJyMoqIiZGZmmpuK7ywTERGBgwcP4vr168jOzsa2bduQl5dnUebPunbtCpVKZR796+fnh8uXL5crd/Xq1Uq/o5OTEzw8PCyW2mjRjJUgEdmPls14sUtU32qU+KnVakRERCApKclifVJSEnr16lXlZ1UqFVq2bAmlUomEhAQMHToUDg6Wh3d2dkaLFi1QWlqKxMREDB8+vNx+3Nzc4O/vj/z8fPzwww8VltFoNPDx8UF6ejr2799fYZkyR48ehcFggL+/PwAgMjISWq0We/fuNZfZs2cPtFrtXb/jveLVLxHZE17sEtU/x5p+YMqUKYiJiUG3bt0QGRmJFStWICMjA7GxsQCkZs+srCzzXH2nTp3C3r170aNHD+Tn52PRokU4cuQIPvvsM/M+9+zZg6ysLHTu3BlZWVmYM2cOTCYTpk2bZi7zww8/QAiB0NBQnD59Gq+88gpCQ0Mxbtw4c5kNGzbAx8cHrVq1wuHDhzFp0iSMGDHCPBjlzJkz+OKLLzBkyBB4e3vj2LFjePnll9GlSxf07t0bANCuXTsMHjwY48ePN0/z8q9//QtDhw5FaGhoTU9XjZRVghd59UtEdoAXu0T1r8aJ36hRo5CXl4d58+YhOzsb4eHh2Lp1K4KCggAA2dnZFnP6GY1GvPvuuzh58iRUKhUGDBiA3bt3o3Xr1uYyN2/exMyZM3H27Fk0adIEQ4YMwbp169C0aVNzGa1Wi/j4eFy8eBGenp544oknMH/+fKhUKnOZ7OxsTJkyBZcvX4a/vz/GjBmDWbNmmber1Wr8/PPP+OCDD1BUVITAwEA88sgjmD17tkU/wC+++AITJ040J4zDhg3D4sWLa3qqaqxlM1cAwLViPUr0pXBV1/g/DxGRzSi72M2+fhMmk4CDQ8X9qImo7iiE4GMi6lpBQQE0Gg20Wm2N+/t1mP0DCnWl+GlKX9zX3N1KERI1fvfyO6Saqe25LjWaEDprG4wmgT2vPQRfD+e7f4iIKlTd3yGf1dvAlF0BZ7K5l4gaOUelA/xuJXuZ10pkjobIPjDxa2ACPaXm3ow8VoJE1Pi1KqvzmPgR1Qsmfg1M0K1K8AITPyKyA0FerPOI6hMTvwamrBLMuFYscyRERNbXyot3/IjqExO/BqaVlxsAXv0SkX0I8pTqvPN5vNglqg9M/BqYoDv6u5hMHHBNRI2buZWDF7tE9YKJXwPTopkLlA4K6EpNuFKokzscIiKrKmvqzSvWo0hXKnM0RI0fE78GRqV0MM9mf4FNH0TUyHk4q9DMVZqIn3UekfUx8WuAzKPc2NmZiOxAWd9mNvcSWR8TvwaoFefyIyI70poXu0T1holfA8Q7fkRUWzt27MCjjz6KgIAAKBQKbN68+a6fSU5ORkREBJydndGmTRssX77c+oHegfOXEtUfJn4NUCvPsmYP9nchopopLi5Gp06dsHjx4mqVP3fuHIYMGYI+ffogLS0Nr732GiZOnIjExEQrR3qbuamX85cSWZ2j3AFQebzjR0S1FR0djejo6GqXX758OVq1aoX3338fANCuXTvs378f77zzDp544gkrRWmJT+8gqj+849cAlfXxu15igPaGQeZoiKgxS0lJQVRUlMW6QYMGYf/+/TAY6qf+KWvqvXT9BvSlpno5JpG9YuLXALk5OcLH3QkAcD6XTR9EZD05OTnw9fW1WOfr64vS0lLk5uZW+BmdToeCggKL5V74uDvBRaWESQCZ+bzrR2RNTPwaqGBvqc/L2dwimSMhosZOoVBYvBdCVLi+zIIFC6DRaMxLYGDgPR+/jc+tOu8qL3aJrImJXwMV4tMEACtBIrIuPz8/5OTkWKy7cuUKHB0d4eXlVeFn4uPjodVqzUtmZuY9x9HmVp135iovdomsiYM7GqiQW1e/rASJyJoiIyPxzTffWKz78ccf0a1bN6hUqgo/4+TkBCcnpzqNI8R8x491HpE18Y5fA8U7fkRUG0VFRTh48CAOHjwIQJqu5eDBg8jIyAAg3a0bM2aMuXxsbCwuXLiAKVOm4Pjx41i9ejVWrVqFqVOn1mvcbVjnEdUL3vFroMyJX24xjCYBpUPFfW2IiO60f/9+DBgwwPx+ypQpAICxY8dizZo1yM7ONieBABAcHIytW7di8uTJWLJkCQICAvDhhx/W21QuZdjKQVQ/mPg1UC2auUDt6AB9qQkX80sQdGuCUyKiqvTv3988OKMia9asKbeuX79+OHDggBWjurs23k2gUAD5JQbkFung3aRum5KJSFKrpt6lS5ciODgYzs7OiIiIwM6dO6ssv2TJErRr1w4uLi4IDQ3F2rVrLbYbDAbMmzcPISEhcHZ2RqdOnbBt2zaLMoWFhYiLi0NQUBBcXFzQq1cv7Nu3z6LM5cuX8cwzzyAgIACurq4YPHgw0tPTzduvXbuGl156CaGhoXB1dUWrVq0wceJEaLVai/20bt0aCoXCYpk+fXptTlWtKR0UaNtcuut3IqewXo9NRFTfXNRK83x+J1nnEVlNjRO/9evXIy4uDjNmzEBaWhr69OmD6Ohoi6aDOy1btgzx8fGYM2cOjh49irlz5+LFF1+06Ew8c+ZMfPzxx/joo49w7NgxxMbG4rHHHkNaWpq5zHPPPYekpCSsW7cOhw8fRlRUFAYOHIisrCwA0vQDI0aMwNmzZ7FlyxakpaUhKCgIAwcORHGx1Gfk0qVLuHTpEt555x0cPnwYa9aswbZt2/Dss8+Wi3vevHnIzs42LzNnzqzpqbpnYX4eAIDj2fc2RxYRkS1gnUdUD0QNde/eXcTGxlqsCwsLE9OnT6+wfGRkpJg6darFukmTJonevXub3/v7+4vFixdblBk+fLh4+umnhRBClJSUCKVSKb799luLMp06dRIzZswQQghx8uRJAUAcOXLEvL20tFR4enqKlStXVvp9/u///k+o1WphMBjM64KCgsR7771X6WfuRqvVCgBCq9XWeh9CCLFyxxkR9Oq34vm1++9pP0T2qK5+h3R3dXWu30s6KYJe/VZMWX+wjiIjsh/V/R3W6I6fXq9Hampqucf7REVFYffu3RV+RqfTwdnZ2WKdi4sL9u7da34cUGVldu3aBQAoLS2F0WissoxOpwMAizJKpRJqtdpcpiJarRYeHh5wdLTs7vjWW2/By8sLnTt3xvz586HX6yvdh7W085eufk/k8OqXiBo/1nlE1lejxC83NxdGo7HCx/v8eQLQMoMGDcInn3yC1NRUCCGwf/9+rF69GgaDwfw4oEGDBmHRokVIT0+HyWRCUlIStmzZguzsbACAu7s7IiMj8frrr+PSpUswGo34/PPPsWfPHnOZsLAwBAUFIT4+Hvn5+dDr9Vi4cCFycnLMZf4sLy8Pr7/+Op5//nmL9ZMmTUJCQgJ+/fVXTJgwAe+//z5eeOGFSs9LXT++qEyYnzsA4MK1EhTrSutkn0REDVW7W0296ZeLUGrkM3uJrKFWgzsqerxPZY/2mTVrFqKjo9GzZ0+oVCoMHz4czzzzDADpjhwAfPDBB2jbti3CwsKgVqsxYcIEjBs3zrwdANatWwchBFq0aAEnJyd8+OGHeOqpp8xlVCoVEhMTcerUKXh6esLV1RXbt29HdHS0xX7KFBQU4JFHHkH79u0xe/Zsi22TJ09Gv3790LFjRzz33HNYvnw5Vq1ahby8vAq/Y10/vqiMVxMnNHd3ghDAycvs7ExEjVvLZi5wUyuhN5pwls8pJ7KKGiV+3t7eUCqVFT7e5893Acu4uLhg9erVKCkpwfnz55GRkYHWrVvD3d0d3t7eAAAfHx9s3rwZxcXFuHDhAk6cOIEmTZogODjYvJ+QkBAkJyejqKgImZmZ5qbiO8tERETg4MGDuH79OrKzs7Ft2zbk5eVZlAGkEcKDBw9GkyZNsGnTpkpnpy/Ts2dPAMDp06cr3G6NxxeVCStr+shm4kdEjZuDg8Jc53GAB5F11CjxU6vViIiIQFJSksX6pKQk9OrVq8rPqlQqtGzZEkqlEgkJCRg6dCgcHCwP7+zsjBYtWqC0tBSJiYkYPnx4uf24ubnB398f+fn5+OGHHyoso9Fo4OPjg/T0dOzfv9+iTEFBAaKioqBWq/H111+X6zdYkbLRxf7+/hVud3JygoeHh8VSV9rdau5lJUhE9qCsiwunsSKyjhpP4DxlyhTExMSgW7duiIyMxIoVK5CRkYHY2FgA0t2vrKws81x9p06dwt69e9GjRw/k5+dj0aJFOHLkCD777DPzPvfs2YOsrCx07twZWVlZmDNnDkwmE6ZNm2Yu88MPP0AIgdDQUJw+fRqvvPIKQkNDMW7cOHOZDRs2wMfHB61atcLhw4cxadIkjBgxwjwYpbCwEFFRUSgpKcHnn39u0R/Px8cHSqUSKSkp+P333zFgwABoNBrs27cPkydPxrBhw9CqVatanOJ7E+ZfVgky8SOixo93/Iisq8aJ36hRo5CXl2ee5y48PBxbt25FUFAQAJR7HJDRaMS7776LkydPQqVSYcCAAdi9ezdat25tLnPz5k3MnDkTZ8+eRZMmTTBkyBCsW7cOTZs2NZfRarWIj4/HxYsX4enpiSeeeALz58+3aKbNzs7GlClTcPnyZfj7+2PMmDGYNWuWeXtqair27NkDALjvvvssvte5c+fQunVrODk5Yf369Zg7dy50Oh2CgoIwfvx4iyS0PrW7o6m3qr6URESNQVkrB7u3EFmHQogqnu1DtVJQUACNRmOeKuZe6EtNeGD2NhiMAjunDUDgrZntiahqdfk7pKrV5bkuvGlAhzk/AgDSZj2MZm7qugiRqNGr7u+wVqN6qf6oHR0Q4sNHtxGRfXB3ViHQ0wUAcJxdXIjqHBM/G9De3NzLSpCIGr+yR7exuZeo7jHxswFlAzx49UtE9oBP8CCyHiZ+NoBXv0RkT25PY8U6j6iuMfGzAe0DpMTvXF4xtDcMMkdDRGRdZXXeyZxC3DQYZY6GqHFh4mcDvJs4oZWnK4QA0jLy5Q6HiMiqWnm6wruJGnqjCUeytHKHQ9SoMPGzEd2CmgEAUi8w8SOixk2hUCDiVp23n3UeUZ1i4mcjIlrfqgTPsxIkosbPnPixziOqU0z8bES3IE8AwMHM6zAYTTJHQ0RkXRG36rwDGfngcwaI6g4TPxvRtnkTeDg74obByNG9RNTohbfwgNrRAdeK9TibWyx3OESNBhM/G+HgoEBXc5+XazJHQ0RkXU6OSnRqqQEApLK5l6jOMPGzId3Y2ZmI7EhZcy8vdonqDhM/G1JWCaaeZ58XImr8OJsBUd1j4mdDOgc2haODAjkFN5F1/Ybc4RARWVXZyN4zV4uRX6yXORqixoGJnw1xUSvxwK0Z7XkFTESNXTM3NUJ83ACwziOqK0z8bIy5zws7OxORHehm7ufHOo+oLjDxszFlTR97z7GzMxE1fmWT1+89lydzJESNAxM/G9OzjScUCuDk5UJcLrgpdzhERFbVK8QLgDR5vbbEIHM0RLaPiZ+N8WrihI4tpLmtkk9dlTkaImqIli5diuDgYDg7OyMiIgI7d+6stOz27duhUCjKLSdOnKjHiCvXspkr7mveBCYB/HYmV+5wiGweEz8b1O9+HwBM/IiovPXr1yMuLg4zZsxAWloa+vTpg+joaGRkZFT5uZMnTyI7O9u8tG3btp4ivjtznXeSdR7RvWLiZ4P6hUqV4K70XJTyub1EdIdFixbh2WefxXPPPYd27drh/fffR2BgIJYtW1bl55o3bw4/Pz/zolQq6yniu7vzYpdzmBLdm1olfjVpRgCAJUuWoF27dnBxcUFoaCjWrl1rsd1gMGDevHkICQmBs7MzOnXqhG3btlmUKSwsRFxcHIKCguDi4oJevXph3759FmUuX76MZ555BgEBAXB1dcXgwYORnp5uUUan0+Gll16Ct7c33NzcMGzYMFy8eNGiTH5+PmJiYqDRaKDRaBATE4Pr16/X8CxZT6eWTeHh7AjtDQMOXdTKHQ4RNRB6vR6pqamIioqyWB8VFYXdu3dX+dkuXbrA398fDz30EH799Vdrhllj3YM94axyQE7BTZy6XCR3OEQ2rcaJX02bEZYtW4b4+HjMmTMHR48exdy5c/Hiiy/im2++MZeZOXMmPv74Y3z00Uc4duwYYmNj8dhjjyEtLc1c5rnnnkNSUhLWrVuHw4cPIyoqCgMHDkRWVhYAQAiBESNG4OzZs9iyZQvS0tIQFBSEgQMHorj49gO+4+LisGnTJiQkJGDXrl0oKirC0KFDYTQazWWeeuopHDx4ENu2bcO2bdtw8OBBxMTE1PRUWY2j0gF92rK5l4gs5ebmwmg0wtfX12K9r68vcnJyKvyMv78/VqxYgcTERGzcuBGhoaF46KGHsGPHjkqPo9PpUFBQYLFYk7NKiZ5tpEEeyaeuWPVYRI2eqKHu3buL2NhYi3VhYWFi+vTpFZaPjIwUU6dOtVg3adIk0bt3b/N7f39/sXjxYosyw4cPF08//bQQQoiSkhKhVCrFt99+a1GmU6dOYsaMGUIIIU6ePCkAiCNHjpi3l5aWCk9PT7Fy5UohhBDXr18XKpVKJCQkmMtkZWUJBwcHsW3bNiGEEMeOHRMAxO+//24uk5KSIgCIEydOVHFmbtNqtQKA0Gq11SpfG+v3ZoigV78V0e/vsNoxiGxZffwOG5qsrCwBQOzevdti/RtvvCFCQ0OrvZ+hQ4eKRx99tNLts2fPFgDKLdY816t3nRVBr34rnlz2m9WOQWTLqlvn1eiOX22aEXQ6HZydnS3Wubi4YO/evTAYDFWW2bVrFwCgtLQURqOxyjI6nQ4ALMoolUqo1WpzmdTUVBgMBov4AwICEB4ebo4/JSUFGo0GPXr0MJfp2bMnNBrNXZtK6tPA9r5QOihwLLsAF/KK7/4BImr0vL29oVQqy93du3LlSrm7gFXp2bNnuW4yd4qPj4dWqzUvmZmZtY65uqIe8AMgTeR8hVNZEdVajRK/2jQjDBo0CJ988glSU1MhhMD+/fuxevVqGAwG5ObmmsssWrQI6enpMJlMSEpKwpYtW5CdnQ0AcHd3R2RkJF5//XVcunQJRqMRn3/+Ofbs2WMuExYWhqCgIMTHxyM/Px96vR4LFy5ETk6OuUxOTg7UajWaNWtWafw5OTlo3rx5ue/RvHnzSr9jfTd7AICnmxo920gz2m89XHFcRGRf1Go1IiIikJSUZLE+KSkJvXr1qvZ+0tLS4O/vX+l2JycneHh4WCzW1qKpCzoHNoUQwLajrPOIaqtWgzsUCoXFeyFEuXVlZs2ahejoaPTs2RMqlQrDhw/HM888AwDmUWMffPAB2rZti7CwMKjVakyYMAHjxo2zGFW2bt06CCHQokULODk54cMPP8RTTz1lLqNSqZCYmIhTp07B09MTrq6u2L59O6Kjo+86Ou3P8Vf0Xar6jgsWLDAPBNFoNAgMDKzyeHVlSAepYv7+SHa9HI+IGr4pU6bgk08+werVq3H8+HFMnjwZGRkZiI2NBSDdrRszZoy5/Pvvv4/NmzcjPT0dR48eRXx8PBITEzFhwgS5vkKlHrlV5209zDqPqLZqlPjVphnBxcUFq1evRklJCc6fP4+MjAy0bt0a7u7u8Pb2BgD4+Phg8+bNKC4uxoULF3DixAk0adIEwcHB5v2EhIQgOTkZRUVFyMzMNDcV31kmIiICBw8exPXr15GdnY1t27YhLy/PXMbPzw96vR75+ZbPfLwzfj8/P1y+fLnc97h69Wql31GOZg8AGPSAHxwUwB8Xtci8VlIvxySihm3UqFF4//33MW/ePHTu3Bk7duzA1q1bERQUBADIzs62GIyn1+sxdepUdOzYEX369MGuXbvw3Xff4fHHH5frK1RqcLjU3Lv33DVcLdTJHA2RbapR4ncvzQgqlQotW7aEUqlEQkIChg4dCgcHy8M7OzujRYsWKC0tRWJiIoYPH15uP25ubvD390d+fj5++OGHCstoNBr4+PggPT0d+/fvN5eJiIiASqWyiD87OxtHjhwxxx8ZGQmtVou9e/eay+zZswdarbbS7yhHswcAeDdxQo9gaaQbr4CJqMwLL7yA8+fPQ6fTITU1FX379jVvW7NmDbZv325+P23aNJw+fRo3btzAtWvXsHPnTgwZMkSGqO8u0NMVnVpqYGJzL1GtOdb0A1OmTEFMTAy6deuGyMhIrFixolwzQlZWlnmuvlOnTmHv3r3o0aMH8vPzsWjRIhw5cgSfffaZeZ979uxBVlYWOnfujKysLMyZMwcmkwnTpk0zl/nhhx8ghEBoaChOnz6NV155BaGhoRg3bpy5zIYNG+Dj44NWrVrh8OHDmDRpEkaMGGEezKHRaPDss8/i5ZdfhpeXFzw9PTF16lR06NABAwcOBAC0a9cOgwcPxvjx4/Hxxx8DAP71r39h6NChCA0NrenpsrqhnfyRcjYPX6VexL/6tqm0OZqIqDEY2jEAhy5q8dX+TMT0DJI7HCKbU+M+fjVtRjAajXj33XfRqVMnPPzww7h58yZ2796N1q1bm8vcvHkTM2fORPv27fHYY4+hRYsW2LVrF5o2bWouo9Vq8eKLLyIsLAxjxozBgw8+iB9//BEqlcpcJjs7GzExMQgLC8PEiRMRExODL7/80iL+9957DyNGjMDIkSPRu3dvuLq64ptvvrHoB/jFF1+gQ4cOiIqKQlRUFDp27Ih169bV9FTVi0c7BcBFpUT6lSLsO59/9w8QEdmwx7q2gEqpwKGLWhzJ4gT2RDWlEILPv6lrBQUF0Gg00Gq19dLs++pXf2D9/kyM6ByA90d3sfrxiGxBff8O7Vl9n+uXvkzDN4cu4akerfDmYx2sfjwiW1Dd3yGf1dsIPN2zFQBg65EcXCvWyxwNEZF1PdVdqvO2pGWhSFcqczREtoWJXyPQsWVThLfwgL7UhMTUi3f/ABGRDevZxhNtfNxQrDdiy8EsucMhsilM/BqJp7pLfSy/3JsBtt4TUWOmUCjMd/3+t4d1HlFNMPFrJIZ1DkATJ0eczS1Gypk8ucMhIrKqJ7q2hNrRAUcvFeDQRQ7yIKouJn6NRBMnR4zoEgAAWL7jrMzREBFZVzM3NYbeepLHx8lnZI6GyHYw8WtE/tUnBEoHBXacuoq0DE7tQkSNW2z/ECgUwPdHcnAyp1DucIhsAhO/RqSVlyse79ICAPDhz+kyR0NEZF33+7pjSLh01+/DX1jnEVUHE79G5sUB98FBAfx68ioOZV6XOxwiIqua8Nf7AEiPrTx1mXf9iO6GiV8j09rbDY91aQkAeHPrcY52I6JGrZ2/B6LD/SAEsGDrcbnDIWrwmPg1Qi9H3Q8nRwfsOXcN3x3OljscIiKremVQKBwdFPj15FX8cuKy3OEQNWhM/BqhgKYuiO0XAgCY8/VR5PNpHkTUiLXxaYJxvVsDAGZsOoLCmwZ5AyJqwJj4NVIvDAhB2+ZNkFukx7xvj8kdDhGRVU15OBRBXq7I1t7Ewu9PyB0OUYPFxK+RcnJU4u0nO8JBAWxKy8KvJ67IHRIRkdW4qJVY8HgHAMAXezI4kT1RJZj4NWJdWjXDP3sHAwBe23SYTb5E1Kj1CvHG3289ym36xj9QwCZfonKY+DVyL0eFovWt5o9/f5EKg9Ekd0hERFYTPyQMARpnXMgrwaQv02A0cWYDojsx8WvkXNRKfBzTDW5qJX4/ew2zvz7KKV6IqNHycFZheUwEnFUO+PXkVby1jf39iO7ExM8OhPq544PRXaBQAP/bk4G1KRfkDomIyGo6tmyKd/7WCQCwYsdZbNifKXNERA0HEz87MbC9L14dHAYAmPPNUXy5N0PmiIiIrGdoxwBMfKgtAGD6xsPYlHZR5oiIGgYmfnbk+b5tMDYyCEIA8RsP45OdZ+UOiYjIauIeaouR3VrCaBKY8n+H8PnvbO0gYuJnRxQKBeYMe8A8ufMb3x3Hgu+Pc8AHETVKDg4KLHy8I57p1RpCADM3H8F7SadQyjqP7BgTPzujUCgwPToMrwwKBQB8nHwWTyzbjdNXimSOjIio7jk4KDD70fZ4ob90wfvBz+kY+XEKzucWyxwZkTyY+NmpFwfch4/+3gUaFxX+uKjFIx/uxOpd52Di1AdE1MgoFApMGxyGd//WCe5OjjiQcR1DPtyJL/Zc4CwHZHdqlfgtXboUwcHBcHZ2RkREBHbu3Fll+SVLlqBdu3ZwcXFBaGgo1q5da7HdYDBg3rx5CAkJgbOzMzp16oRt27ZZlCksLERcXByCgoLg4uKCXr16Yd++fRZlioqKMGHCBLRs2RIuLi5o164dli1bZt5+/vx5KBSKCpcNGzaYy7Vu3brc9unTp9fmVDVoj3YKwA9xfdH3fh/oSk2Y9+0xxKzegwt5vBImosbniYiW+D6uD3q28USJ3ogZm45g3Jp9uJhfIndoRPVH1FBCQoJQqVRi5cqV4tixY2LSpEnCzc1NXLhwocLyS5cuFe7u7iIhIUGcOXNGfPnll6JJkybi66+/NpeZNm2aCAgIEN999504c+aMWLp0qXB2dhYHDhwwlxk5cqRo3769SE5OFunp6WL27NnCw8NDXLx40VzmueeeEyEhIeLXX38V586dEx9//LFQKpVi8+bNQgghSktLRXZ2tsUyd+5c4ebmJgoLC837CQoKEvPmzbMod+f2u9FqtQKA0Gq11f6MnEwmk1ibcl6EzfxeBL36rWgT/52YnnhInM8tkjs0olqztd+hLbO1c200msTKHWdE2xlbRdCr34r7XvtOzNp8WGReK5Y7NKJaq+7vUCFEze5z9+jRA127drW4k9auXTuMGDECCxYsKFe+V69e6N27N/773/+a18XFxWH//v3YtWsXACAgIAAzZszAiy++aC4zYsQINGnSBJ9//jlu3LgBd3d3bNmyBY888oi5TOfOnTF06FC88cYbAIDw8HCMGjUKs2bNMpeJiIjAkCFD8Prrr1f4fbp06YKuXbti1apV5nWtW7dGXFwc4uLianJqzAoKCqDRaKDVauHh4VGrfcjhXG4x5nx9FMmnrgIAFArg4Xa++Hv3VujT1huOSvYMINthq79DW2Sr5/rU5ULM/eYofjstPdfXQQEMDvfD6L+0Qu/7vKF0UMgcIVH1Vfd3WKN/yfV6PVJTUxEVFWWxPioqCrt3767wMzqdDs7OzhbrXFxcsHfvXhgMhirLlCWGpaWlMBqNVZYBgAcffBBff/01srKyIITAr7/+ilOnTmHQoEEVxpaamoqDBw/i2WefLbftrbfegpeXFzp37oz58+dDr6/8Obc6nQ4FBQUWiy0K9nbDZ//sjg2xkeh3vw+EAH48dhnj1uxDzwW/IH7jYfx64gpuGoxyh0pEdM/u93XHF8/1xP+e64EH7/OGSQBbD+dgzOq96L3wF8zafATJp65CV8o6jxqPGiV+ubm5MBqN8PX1tVjv6+uLnJycCj8zaNAgfPLJJ0hNTYUQAvv378fq1athMBiQm5trLrNo0SKkp6fDZDIhKSkJW7ZsQXZ2NgDA3d0dkZGReP3113Hp0iUYjUZ8/vnn2LNnj7kMAHz44Ydo3749WrZsCbVajcGDB2Pp0qV48MEHK4xt1apVaNeuHXr16mWxftKkSUhISMCvv/6KCRMm4P3338cLL7xQ6XlZsGABNBqNeQkMDLz7yWzA/tLaE5/9szuSJvfFuN6t4emmRm6RDl/uzcC4NfvQed6P+Mcne7Dox5PYcjALR7K0KNaVyh02Ed1S037YycnJiIiIgLOzM9q0aYPly5fXU6QNQ6/7vPH5cz3w/aQ+GBMZBI2LCjkFN7Hu9wsYu3ovOs9NQsyqPViUdIp1Htm8GjX1Xrp0CS1atMDu3bsRGRlpXj9//nysW7cOJ06UfybijRs38OKLL2LdunUQQsDX1xf/+Mc/8Pbbb+Py5cto3rw5rl69ivHjx+Obb76BQqFASEgIBg4ciE8//RQlJVKn2zNnzuCf//wnduzYAaVSia5du+L+++/HgQMHcOzYMQDAO++8g5UrV+Kdd95BUFAQduzYgfj4eGzatAkDBw4sF5e/vz9mzZqFl19+ucrvnZiYiCeffBK5ubnw8vIqt12n00Gn05nfFxQUIDAw0OaaPSqjLzUh5Wweko7l4KdjV5BTcLPCcv4aZ7TxcUMb7yYI8XFDG58mCGneBP4eznBgkwnVM1ttfrxX69evR0xMDJYuXYrevXvj448/xieffIJjx46hVatW5cqfO3cO4eHhGD9+PJ5//nn89ttveOGFF/Dll1/iiSeeqNYxG9u51pUasft0Hn48dhk/Hb+Mq4W6Csv5a5wR4nNHfefTBG183OCvcYZCwTqP6ld1f4c1Svz0ej1cXV2xYcMGPPbYY+b1kyZNwsGDB5GcnFzpZw0GAy5fvgx/f3+sWLECr776Kq5fvw4Hh9s3HW/evIm8vDwEBARg+vTp+Pbbb3H06FGL/RQXF6OgoAD+/v4YNWoUioqK8N133+HGjRvQaDTYtGmTRT/A5557DhcvXiw3SnjdunV49tlnkZWVBR8fnyq/d1ZWFlq2bInff/8dPXr0uOt5amyV4J2EEDh9pQgpZ/Nw7FIBzl4txpmrRcgrrrwp3MnRAd5NnODVRA1PNzU8XdXwcFHB3dkRTZwc0eTWXxeVEi5qJdRKBziplHBydJAWlbROpVTAUekARwcFHB0UUDooWLlSpRrz77AqNe2H/eqrr+Lrr7/G8ePHzetiY2Nx6NAhpKSkVOuYjflcm0wCp64UIuVMHk5kF+LM1SKczS3GtSrqPGfVrTrP7Vad5+YEDxdHuJvrOxXcnJRwVTvCWeUAJ8db9Z3KwaL+Uzk4QKlUsM6jaqnu79CxJjtVq9WIiIhAUlKSReKXlJSE4cOHV/lZlUqFli1bAgASEhIwdOhQi6QPAJydndGiRQsYDAYkJiZi5MiR5fbj5uYGNzc35Ofn44cffsDbb78NQEosDQZDuX0qlUqYTOVnaV+1ahWGDRt216QPANLS0gAA/v7+dy3b2CkUCrT1dUdbX3eL9ddL9DhztRhnb1WKZ65Ify/kFUNXakLW9RvIun6jzuNxdFDAwUEBpUKqFB0U0oStDgrpNXBr3a330vQ80sAVBW69vuO7matUxe0/ZRXtndXtnXWvAhVXxPZcP1v7H6eIoKZ4Y0QHqx7DFpX1w/7z9FNV9cNOSUkp12970KBBWLVqFQwGA1QqVbnPVNTK0Vg5OCgQ5ueBMD/Lf0jzi/U4m1uEM1eKcSa3yHwRnJFXgpsGEy7m38DF/IZb55Wr11jn3RNr13l97/dGfHS7OtlXjRI/AJgyZQpiYmLQrVs3REZGYsWKFcjIyEBsbCwAID4+HllZWea5+k6dOoW9e/eiR48eyM/Px6JFi3DkyBF89tln5n3u2bMHWVlZ6Ny5M7KysjBnzhyYTCZMmzbNXOaHH36AEAKhoaE4ffo0XnnlFYSGhmLcuHEAAA8PD/Tr1w+vvPIKXFxcEBQUhOTkZKxduxaLFi2y+A6nT5/Gjh07sHXr1nLfLyUlBb///jsGDBgAjUaDffv2YfLkyRg2bFiFzSQkaeqqRkSQGhFBzSzWlxpNuHT9JnKLdbhWpMe1Yj2ulehRcMOAYl0pCm+WouBmKUr0pSjRG6ErNUFXaoTOYDK/1pdKrytSahIAJ522Oz7uTnKH0CDVph92Tk5OheVLS0uRm5tb4QXvggULMHfu3LoL3AY1c1Mjws0TEUGeFusNRhMuXb+BvGK9uc7LK9aj4KZU5xX9qc67abhdx5nrv1IT9Kzz6A4hPm51tq8aJ36jRo1CXl4e5s2bh+zsbISHh2Pr1q0ICgoCAGRnZyMjI8Nc3mg04t1338XJkyehUqkwYMAA7N69G61btzaXuXnzJmbOnImzZ8+iSZMmGDJkCNatW4emTZuay2i1WsTHx+PixYvw9PTEE088gfnz51tcjSYkJCA+Ph5PP/00rl27hqCgIMyfP9+clJZZvXo1WrRoUe4qFwCcnJywfv16zJ07FzqdDkFBQRg/frxFEkrV56h0QCsvV7Tycr2n/QghYDQJlJYtRtOtvwJGIWA0CpiE9FoIqbxUP0rv7/xrEgICgNTJQdzaP8zryno/3C7zp1gg7nxT0ctKvsM9fP+77t2+NHNVyx1Cg/bnuw9CiCrvSFRUvqL1ZeLj4zFlyhTz+7J+zQSolA4I8nJDkNe9/UNdUZ1nMErr7rXOK6uLWOfZDu8mdXexW+N5/OjuGnN/FyJbYY+/w9r0w+7bty+6dOmCDz74wLxu06ZNGDlyJEpKSips6v0zezzXRA2NVebxIyKihuvOfth3SkpKKjdtVZnIyMhy5X/88Ud069atWkkfEdkWJn5ERI3IlClT8Mknn2D16tU4fvw4Jk+eXK4f9pgxY8zlY2NjceHCBUyZMgXHjx/H6tWrsWrVKkydOlWur0BEVlTjPn5ERNRw1bQfdnBwMLZu3YrJkydjyZIlCAgIwIcffljtOfyIyLawj58VaLVaNG3aFJmZmezvQiSTsgEH169fh0ajkTucRo11HpH8qlvn8Y6fFRQWFgIAR7kRNQCFhYVM/KyMdR5Rw3G3Oo93/KzAZDLh0qVLcHd3r3Q6hLLM3BavkG05dsC247fl2IH6jV8IgcLCQgQEBJSb2J3qFuu8hs2W47fl2IGGWefxjp8VODg4mJ9ScjceHh42+X9mwLZjB2w7fluOHai/+Hmnr36wzrMNthy/LccONKw6j5fBRERERHaCiR8RERGRnWDiJxMnJyfMnj0bTk6298xRW44dsO34bTl2wPbjp9qz5f/2thw7YNvx23LsQMOMn4M7iIiIiOwE7/gRERER2QkmfkRERER2gokfERERkZ1g4kdERERkJ5j4yWDp0qUIDg6Gs7MzIiIisHPnTrlDKmfOnDlQKBQWi5+fn3m7EAJz5sxBQEAAXFxc0L9/fxw9elS2eHfs2IFHH30UAQEBUCgU2Lx5s8X26sSr0+nw0ksvwdvbG25ubhg2bBguXrwoe+zPPPNMuf8WPXv2bBCxL1iwAH/5y1/g7u6O5s2bY8SIETh58qRFmYZ87ql+sM6re6zzWOfVFhO/erZ+/XrExcVhxowZSEtLQ58+fRAdHY2MjAy5QyvngQceQHZ2tnk5fPiwedvbb7+NRYsWYfHixdi3bx/8/Pzw8MMPm5/ZWd+Ki4vRqVMnLF68uMLt1Yk3Li4OmzZtQkJCAnbt2oWioiIMHToURqNR1tgBYPDgwRb/LbZu3WqxXa7Yk5OT8eKLL+L3339HUlISSktLERUVheLiYnOZhnzuyfpY51kH6zzWebUmqF51795dxMbGWqwLCwsT06dPlymiis2ePVt06tSpwm0mk0n4+fmJhQsXmtfdvHlTaDQasXz58nqKsHIAxKZNm8zvqxPv9evXhUqlEgkJCeYyWVlZwsHBQWzbtk222IUQYuzYsWL48OGVfqahxC6EEFeuXBEARHJyshDCts49WQfrPOtjncc6ryZ4x68e6fV6pKamIioqymJ9VFQUdu/eLVNUlUtPT0dAQACCg4MxevRonD17FgBw7tw55OTkWHwPJycn9OvXr0F+j+rEm5qaCoPBYFEmICAA4eHhDeI7bd++Hc2bN8f999+P8ePH48qVK+ZtDSl2rVYLAPD09ATQOM491R7rPHk0ht8d6zzrYeJXj3Jzc2E0GuHr62ux3tfXFzk5OTJFVbEePXpg7dq1+OGHH7By5Urk5OSgV69eyMvLM8dqC98DQLXizcnJgVqtRrNmzSotI5fo6Gh88cUX+OWXX/Duu+9i3759+Otf/wqdTgeg4cQuhMCUKVPw4IMPIjw83BxbWSyVxdZQ4qe6xzpPHrb+u2OdZ12OVj8ClaNQKCzeCyHKrZNbdHS0+XWHDh0QGRmJkJAQfPbZZ+ZOtrbwPe5Um3gbwncaNWqU+XV4eDi6deuGoKAgfPfdd3j88ccr/Vx9xz5hwgT88ccf2LVrV7lttnruqW7YQl3BOq/6ZayNdZ518Y5fPfL29oZSqSyX0V+5cqXc1UFD4+bmhg4dOiA9Pd080s1Wvkd14vXz84Ner0d+fn6lZRoKf39/BAUFIT09HUDDiP2ll17C119/jV9//RUtW7Y0r29s555qhnWePBrb7451Xt1i4leP1Go1IiIikJSUZLE+KSkJvXr1kimq6tHpdDh+/Dj8/f0RHBwMPz8/i++h1+uRnJzcIL9HdeKNiIiASqWyKJOdnY0jR440uO+Ul5eHzMxM+Pv7A5A3diEEJkyYgI0bN+KXX35BcHCwxfbGdu6pZljnyaOx/e5Y59X9l6B6lJCQIFQqlVi1apU4duyYiIuLE25ubuL8+fNyh2bh5ZdfFtu3bxdnz54Vv//+uxg6dKhwd3c3x7lw4UKh0WjExo0bxeHDh8Xf//534e/vLwoKCmSJt7CwUKSlpYm0tDQBQCxatEikpaWJCxcuVDve2NhY0bJlS/HTTz+JAwcOiL/+9a+iU6dOorS0VLbYCwsLxcsvvyx2794tzp07J3799VcRGRkpWrRo0SBi//e//y00Go3Yvn27yM7ONi8lJSXmMg353JP1sc6zDtZ5rPNqi4mfDJYsWSKCgoKEWq0WXbt2NQ8Db0hGjRol/P39hUqlEgEBAeLxxx8XR48eNW83mUxi9uzZws/PTzg5OYm+ffuKw4cPyxbvr7/+KgCUW8aOHVvteG/cuCEmTJggPD09hYuLixg6dKjIyMiQNfaSkhIRFRUlfHx8hEqlEq1atRJjx44tF5dcsVcUNwDx6aefmss05HNP9YN1Xt1jncc6r7YUt74IERERETVy7ONHREREZCeY+BERERHZCSZ+RERERHaCiR8RERGRnWDiR0RERGQnmPgRERER2QkmfkRERER2gokf2a05c+agc+fOcodBRFQvWOcRAHACZ2qUFApFldvHjh2LxYsXQ6fTwcvLq56iIiKyDtZ5VF1M/KhRysnJMb9ev349/vOf/+DkyZPmdS4uLtBoNHKERkRU51jnUXWxqZcaJT8/P/Oi0WigUCjKrftzs8czzzyDESNG4M0334Svry+aNm2KuXPnorS0FK+88go8PT3RsmVLrF692uJYWVlZGDVqFJo1awYvLy8MHz4c58+fr98vTER2jXUeVRcTP6I7/PLLL7h06RJ27NiBRYsWYc6cORg6dCiaNWuGPXv2IDY2FrGxscjMzAQAlJSUYMCAAWjSpAl27NiBXbt2oUmTJhg8eDD0er3M34aIqGqs8+wPEz+iO3h6euLDDz9EaGgo/vnPfyI0NBQlJSV47bXX0LZtW8THx0OtVuO3334DACQkJMDBwQGffPIJOnTogHbt2uHTTz9FRkYGtm/fLu+XISK6C9Z59sdR7gCIGpIHHngADg63r4d8fX0RHh5ufq9UKuHl5YUrV64AAFJTU3H69Gm4u7tb7OfmzZs4c+ZM/QRNRFRLrPPsDxM/ojuoVCqL9wqFosJ1JpMJAGAymRAREYEvvvii3L58fHysFygRUR1gnWd/mPgR3YOuXbti/fr1aN68OTw8POQOh4jIqljn2T728SO6B08//TS8vb0xfPhw7Ny5E+fOnUNycjImTZqEixcvyh0eEVGdYp1n+5j4Ed0DV1dX7NixA61atcLjjz+Odu3a4Z///Cdu3LjBq2EianRY59k+TuBMREREZCd4x4+IiIjITjDxIyIiIrITTPyIiIiI7AQTPyIiIiI7wcSPiIiIyE4w8SMiIiKyE0z8iIiIiOwEEz8iIiIiO8HEj4iIiMhOMPEjIiIishNM/IiIiIjsBBM/IiIiIjvBxI+IiIjITjDxIyIiIrITTPyIiIiI7AQTPyIiIiI7wcSPiIiIyE4w8SOqwJo1a6BQKLB//365QyEisoqyeq5scXR0hL+/P0aPHo309HS5wyMrcZQ7ACIiIpLPp59+irCwMNy8eRO//fYb5s+fj19//RUnTpxAs2bN5A6P6hgTPyIiIjsWHh6Obt26AQD69+8Po9GI2bNnY/PmzRg3bpzM0VFdY1MvERERmZUlgZcvX5Y5ErIGJn5ERERkdu7cOQDA/fffL3MkZA1s6iUiIrJjRqMRpaWl5j5+b7zxBvr27Ythw4bJHRpZARM/IiIiO9azZ0+L9+3atcOWLVvg6MgUoTFiUy8REZEdW7t2Lfbt24dffvkFzz//PI4fP46///3vcodFVsJ0noiIyI61a9fOPKBjwIABMBqN+OSTT/DVV1/hySeflDk6qmu840dERERmb7/9Npo1a4b//Oc/MJlMcodDdYyJHxEREZk1a9YM8fHxOH78OP73v//JHQ7VMSZ+REREZOGll15Cq1atMG/ePBiNRrnDoTqkEEIIuYMgIiIiIuvjHT8iIiIiO8HEj4iIiMhOMPEjIiIishNM/IiIiIjsBBM/IiIiIjvBxI+IiIjITjDxIyIiIrITfFavFZhMJly6dAnu7u5QKBRyh0Nkl4QQKCwsREBAABwceI1rTazziORX3TqPiZ8VXLp0CYGBgXKHQUQAMjMz0bJlS7nDaNRY5xE1HHer85j4WYG7uzsA6eR7eHjIHA2RfSooKEBgYKD590jWwzqPSH7VrfOY+FlBWVOHh4cHK0EimbHp0fpY5xE1HHer89jxhYiIiMhOMPEjIiIishNs6iUi25GXB6SlAZ06AT4+ckdDZFVCCBhNAqUmy78mIWAyCZgEpNdCQAhA3HovcOvvrfUmcWt/uF2u7L10nDuPabmtfEzViLuW37emRHWCaSSauqoR7O1WJ/ti4kdEtmP7duDJJ4GICGD/frmjIbJgNAlka2/g0vWbyC/RQ1tikP7eMKBYV4pivREl+lIU64y4oTfihsEIXakR+lITDEYBXakJ+lIjDEYBvdEEo8l+Ehuq2tCO/lj8VNc62RcTPyKyHYcOSX87dZI3DrJbBTcNyMgrQea1EmTcsWReK0HW9RswGOsnWXNQAEoHBRRQQKEAHBR3/AWgUEid/B1u/S1bh1vly7r/l40DUNxac+e4gDuHCNR2kBTHVtUNLzd1ne2LiR8R2Q4mflSPtCUGpJzNw/7z13Aw8zpOXy3C9RJDlZ9RKRUIaOoCTzc1mrmq0dRFBQ8XFdydHeHm5Ag3tRKuake4qJVwUSnh5OgAtaMDVErpr9rRAWql9N5RqYCjgwJKBwUcHaT3SoUCDg7Mpqj2mPgRke1g4kdWJITAycuF+P5wDrafvILDWVpU1Nrq3USNQE9XtLq13Pna18MZSiZm1IAx8SMi23D9OnDhgvS6Y0dZQ6HG5XqJHl+lXsSG/Rdx8nKhxbYQHzdEhnihS2AztPP3QCsvVzRx4j+dZLv4/14isg1//CH9bdUKaNZM3lioUcjR3sSSX0/jq9SLuGEwAgDUjg7o29YbUQ/4oW9bH/hpnGWOkqhuMfEjIttQ1szLu310j/SlJqz+7Rw+/DkdJXop4Wvn74Gne7TCo50CoHFRyRwhkfVYbQLnpUuXIjg4GM7OzoiIiMDOnTurLJ+cnIyIiAg4OzujTZs2WL58ebkyiYmJaN++PZycnNC+fXts2rSpxsfduHEjBg0aBG9vbygUChw8eLDcPvr37y+NgrpjGT16dM1OABHVLfbvozqwM/0qBn+wAwu/P4ESvRFdWzXF/57rga0TH8Q/egYx6aNGzyqJ3/r16xEXF4cZM2YgLS0Nffr0QXR0NDIyMiosf+7cOQwZMgR9+vRBWloaXnvtNUycOBGJiYnmMikpKRg1ahRiYmJw6NAhxMTEYOTIkdizZ0+NjltcXIzevXtj4cKFVX6H8ePHIzs727x8/PHH93hWiOieMPGje5BfrMe/P09FzKq9OHu1GN5N1Hjnb53wVWwv9LrPm890JruhEFaY+rpHjx7o2rUrli1bZl7Xrl07jBgxAgsWLChX/tVXX8XXX3+N48ePm9fFxsbi0KFDSElJAQCMGjUKBQUF+P77781lBg8ejGbNmuHLL7+s8XHPnz+P4OBgpKWloXPnzhbb+vfvj86dO+P999+v1fcvKCiARqOBVqvlA8uJ6kJpKeDuDty8CZw8Cdx//10/wt9h/Wno5/rU5UI899l+ZFwrgdJBgTGRQZj88P3wcObdPWo8qvs7rPM7fnq9HqmpqYiKirJYHxUVhd27d1f4mZSUlHLlBw0ahP3798NgMFRZpmyftTluVb744gt4e3vjgQcewNSpU1FYWFhpWZ1Oh4KCAouFiOpQerqU9Lm6AiEhckdDNiTp2GU8tuQ3ZFwrQctmLtjyYm/MfvQBJn1kt+p8cEdubi6MRiN8fX0t1vv6+iInJ6fCz+Tk5FRYvrS0FLm5ufD396+0TNk+a3Pcyjz99NMIDg6Gn58fjhw5gvj4eBw6dAhJSUkVll+wYAHmzp1bo2MQUQ2UNfN26AAolfLGQjbjm0OXMCkhDSYB9GzjiaVPR8CzDp+AQGSLrDaq98/9JYQQVfahqKj8n9dXZ581PW5Fxo8fb34dHh6Otm3bolu3bjhw4AC6di3/rLz4+HhMmTLF/L6goACBgYE1OiYRVYH9+6iGfjiag7j1B2ESwN8iWuLNxztApbTaeEYim1HniZ+3tzeUSmW5u2xXrlwpdzeujJ+fX4XlHR0d4eXlVWWZsn3W5rjV1bVrV6hUKqSnp1eY+Dk5OcHJyemejkFEVSibw4+JH1XD9pNX8NL/0mA0CTzepQXeeqIjH3NGdEudX/6o1WpERESUaxZNSkpCr169KvxMZGRkufI//vgjunXrBpVKVWWZsn3W5rjVdfToURgMBvj7+9/TfoiolnjHj6rp9JVCvPDFAeiNJjzSwR9vP8mkj+hOVmnqnTJlCmJiYtCtWzdERkZixYoVyMjIQGxsLACpaTQrKwtr164FII3gXbx4MaZMmYLx48cjJSUFq1atMo/WBYBJkyahb9++eOuttzB8+HBs2bIFP/30E3bt2lXt4wLAtWvXkJGRgUuXLgEATp48CUC6o+jn54czZ87giy++wJAhQ+Dt7Y1jx47h5ZdfRpcuXdC7d29rnC4iqkpeHpCVJb3m5M1UhRJ9Kf79+QGU6I2IbOOF90Z1hiObd4ksCStZsmSJCAoKEmq1WnTt2lUkJyebt40dO1b069fPovz27dtFly5dhFqtFq1btxbLli0rt88NGzaI0NBQoVKpRFhYmEhMTKzRcYUQ4tNPPxUAyi2zZ88WQgiRkZEh+vbtKzw9PYVarRYhISFi4sSJIi8vr9rfXavVCgBCq9VW+zNEVImffxYCEKJNmxp9jL/D+tMQzrXJZBKT16eJoFe/Fd3eSBJXCm7KFguRHKr7O7TKPH72rqHPaUVkU957D5gyBXjsMWDjxmp/jL/D+tMQzvX/7cvEtMQ/4KAA/je+J3q28ZIlDiK5yDaPHxFRnWL/PrqLi/klmPPNUQDAy1GhTPqIqsDEj4gaNiZ+dBeztxxFid6IbkHN8O9+nOCbqCpM/Iio4TIYgGPHpNcc2EEVSD51FT+fuAJHBwUWPtGBI3iJ7oKJHxE1XCdOAHq99Jze1q3ljoYamFKjCW98K10YjO3VGvc1d5c5IqKGj4kfETVcZc28HTsCDqyuyNKXezOQfqUIzVxVmPhQW7nDIbIJrEmJqOFi/z6qhL7UhCW/ngEATHn4fmhcVDJHRGQbmPgRUcPFxI8qsflgFnIKbsLXwwkj/8JnoxNVFxM/Imq4mPhRBUwmgeXJ0t2+5x5sAydHpcwREdkOJn5E1LCYTEByMhAdDVy5IvXtCw+XOypqQH48dhlnrxbDw9kRf+/RSu5wiGyKVZ7VS0RUI6WlUrKXmAhs2gTk5EjrlUrg9dcBNzd546MGQwiBZbfu9o2JbI0mTvxnjKgm+IshInl9/jkQFwfk5d1ep9EAf/sbMH06EMIJeem2lLN5OJR5HU6ODnimd2u5wyGyOUz8iEg+WVnAv/4F3LgBeHkBI0YATz4J/PWvgFotd3TUAK1LuQAA+Fu3lvBu4iRzNES2h4kfEcnnP/+Rkr5evaSmXkdWSVS5vCIdfjp+GQDwj55BMkdDZJs4uIOI5HH4MPDpp9Lrd95h0kd3tfngJRiMAh1bahDm5yF3OEQ2iYkfEclj+nRACKlpNzJS7miogRNCYMP+TADA37px3j6i2mLiR0T1b8cOYOtW6S7fm2/KHQ3ZgMNZWpzIKYSTowOGdQqQOxwim8XEj4jqlxBAfLz0+rnngLaN4xmrS5cuRXBwMJydnREREYGdO3dWWT45ORkRERFwdnZGmzZtsHz58nJlEhMT0b59ezg5OaF9+/bYtGlTjY+7ceNGDBo0CN7e3lAoFDh48GC5feh0Orz00kvw9vaGm5sbhg0bhosXL9bsBFjZloOXAABRD/jx8WxE94CJHxHVr+++A3bvBlxcgFmz5I6mTqxfvx5xcXGYMWMG0tLS0KdPH0RHRyMjI6PC8ufOncOQIUPQp08fpKWl4bXXXsPEiRORmJhoLpOSkoJRo0YhJiYGhw4dQkxMDEaOHIk9e/bU6LjFxcXo3bs3Fi5cWGn8cXFx2LRpExISErBr1y4UFRVh6NChMBqNdXB27p0QAtuOSHM7Du3oL3M0RDZOUJ3TarUCgNBqtXKHQtSwlJYKER4uBCDEq69a9VD1+Tvs3r27iI2NtVgXFhYmpk+fXmH5adOmibCwMIt1zz//vOjZs6f5/ciRI8XgwYMtygwaNEiMHj26Vsc9d+6cACDS0tIs1l+/fl2oVCqRkJBgXpeVlSUcHBzEtm3bKoz/z6x9rg9m5IugV78V7WZ9L27oS61yDCJbV93fIe/4EVH9+fJL4MgRoGlT4NVX5Y6mTuj1eqSmpiIqKspifVRUFHbv3l3hZ1JSUsqVHzRoEPbv3w+DwVBlmbJ91ua4FUlNTYXBYLDYT0BAAMLDwyvdj06nQ0FBgcViTVuPZAMABoQ1h7OKz+UluhdM/Iiofuj10rx9gJT0NWsmbzx1JDc3F0ajEb6+vhbrfX19kVP26Lk/ycnJqbB8aWkpcnNzqyxTts/aHLeyWNRqNZr96b9HVftZsGABNBqNeQkMtN4oWyEEvj8sxTEknM28RPeKiR8R1Y+VK4Fz5wB/f2DiRLmjqXMKhcLivRCi3Lq7lf/z+urss6bHra6q9hMfHw+tVmteMjMz7/l4lTmWXYCMayVwcnRA/1Afqx2HyF4w8SMi6ysqAl5/XXo9axbg6ipvPHXI29sbSqWy3N2xK1eulLsbV8bPz6/C8o6OjvDy8qqyTNk+a3PcymLR6/XIz8+v9n6cnJzg4eFhsVjL9pNXAQB92vrAzYmTfBPdKyZ+RGR9ixcDly8DISHSFC6NiFqtRkREBJKSkizWJyUloVevXhV+JjIyslz5H3/8Ed26dYNKpaqyTNk+a3PcikREREClUlnsJzs7G0eOHKnRfqxlV7rU9N33fm+ZIyFqHHj5RETWVVQkPZINAGbPBlSNbw62KVOmICYmBt26dUNkZCRWrFiBjIwMxMbGApCaRrOysrB27VoAQGxsLBYvXowpU6Zg/PjxSElJwapVq/Dll1+a9zlp0iT07dsXb731FoYPH44tW7bgp59+wq5du6p9XAC4du0aMjIycOmSNA/eyZMnAUh3+vz8/KDRaPDss8/i5ZdfhpeXFzw9PTF16lR06NABAwcOtPq5q8oNvRGpF6Q7kb3vY+JHVCesPr7YDnE6F6I7LFwoTd/Stq0QBkO9Hba+f4dLliwRQUFBQq1Wi65du4rk5GTztrFjx4p+/fpZlN++fbvo0qWLUKvVonXr1mLZsmXl9rlhwwYRGhoqVCqVCAsLE4mJiTU6rhBCfPrppwJAuWX27NnmMjdu3BATJkwQnp6ewsXFRQwdOlRkZGRU+7tb61wnn7wigl79VvR88ydhMpnqdN9EjU11f4cKIW71KKY6U1BQAI1GA61Wa9W+L0QNXlER0Lo1kJcHfPYZMGZMvR2av8P6Y61zvWDrcXy84yz+FtES//1bpzrbL1FjVN3fIfv4EZH1fPSRlPTddx/w1FNyR0M2Zuet/n0PtmUzL1FdYeJHRNaRnw+8/bb0es4cwJFdiqn68op0OJYtTQzdK4SJH1FdYeJHRNbxzjvA9etAeDgwerTc0ZCN2X0mDwAQ5ucOH3cnmaMhajyY+BFR3bt8GXj/fen1G28ASj5mi2qmbBqXBzmal6hOMfEjorq3YAFQUgJ07w4MGyZ3NGRjhBDYdZr9+4iswWqJ39KlSxEcHAxnZ2dERERg586dVZZPTk5GREQEnJ2d0aZNGyxfvrxcmcTERLRv3x5OTk5o3749Nm3aVOPjbty4EYMGDYK3tzcUCgUOHjxYbh86nQ4vvfQSvL294ebmhmHDhuHixYs1OwFE9iojA1i2THo9fz5QB48PI/uSca0EWddvQKVUoHuwp9zhEDUqVkn81q9fj7i4OMyYMQNpaWno06cPoqOjkZGRUWH5c+fOYciQIejTpw/S0tLw2muvYeLEiUhMTDSXSUlJwahRoxATE4NDhw4hJiYGI0eOxJ49e2p03OLiYvTu3RsLFy6sNP64uDhs2rQJCQkJ2LVrF4qKijB06FAYjcY6ODtEjdy8eYBeDwwYADz0kNzRkA06mHkdAPBAgAauag4KIqpT1phEsHv37iI2NtZiXVhYmJg+fXqF5adNmybCwsIs1j3//POiZ8+e5vcjR44UgwcPtigzaNAgMXr06Fod99y5cwKASEtLs1h//fp1oVKpREJCgnldVlaWcHBwENu2basw/j/jBM5kt7ZsEcLBQZqwefduWUPh77D+1PW5nvP1ERH06rdi9pYjdbI/IntQ3d9hnd/x0+v1SE1NRVRUlMX6qKgo7N69u8LPpKSklCs/aNAg7N+/HwaDocoyZfuszXErkpqaCoPBYLGfgIAAhIeHV7ofnU6HgoICi4XI7iQnAyNHAiaT9DzeyEi5IyIbdejWHb9OgRp5AyGS282bwIQJQE5One2yzhO/3NxcGI1G+Pr6Wqz39fVFTiWB5+TkVFi+tLQUubm5VZYp22dtjltZLGq1Gs2aNav2fhYsWACNRmNeAgMDq308okbhwAHg0UcBnQ4YPvx2Hz+iGjIYTTh6Sbp47tSyqbzBEMntlVeAJUuAhx+WLqrrgNUGdyj+1KFbCFFu3d3K/3l9dfZZ0+NWV1X7iY+Ph1arNS+ZmZn3fDwim3HpEjBkCFBYCPTvDyQkcLJmqrWTOYXQlZrg4eyI1l5ucodDJJ8tW4DFi6XX//0v4FA3KVudJ37e3t5QKpXl7o5duXKl3N24Mn5+fhWWd3R0hJeXV5VlyvZZm+NWFoter0d+fn619+Pk5AQPDw+Lhcgu6PXA3/4mzdvXoYNUUTk7yx0V2bBDF68DADoFNoWDA0eEk526eBH45z+l1y+/DAweXGe7rvPET61WIyIiAklJSRbrk5KS0KtXrwo/ExkZWa78jz/+iG7dukGlUlVZpmyftTluRSIiIqBSqSz2k52djSNHjtRoP0R24ZVXgN27AY0G2LgR4EUP3aOy/n0dW7J/H9kpoxF4+mng2jUgIgJ488063b1V2mOmTJmCmJgYdOvWDZGRkVixYgUyMjIQGxsLQGoazcrKwtq1awEAsbGxWLx4MaZMmYLx48cjJSUFq1atwpdffmne56RJk9C3b1+89dZbGD58OLZs2YKffvoJu3btqvZxAeDatWvIyMjApUuXAAAnT54EIN3p8/Pzg0ajwbPPPouXX34ZXl5e8PT0xNSpU9GhQwcMHDjQGqeLyDZ9+SXw4YfS63XrgPvukzceahQOZWoBsH8f2bH584EdO4AmTaSuM2p13e7fWsOKlyxZIoKCgoRarRZdu3YVycnJ5m1jx44V/fr1syi/fft20aVLF6FWq0Xr1q3FsmXLyu1zw4YNIjQ0VKhUKhEWFiYSExNrdFwhhPj0008FgHLL7NmzzWVu3LghJkyYIDw9PYWLi4sYOnSoyMjIqPZ35zQS1OgdPiyEq6s0bcuMGXJHUyH+DutPXZ3ropsGETz9WxH06rfisvZGHUVHZEN27rw9Jda6dTX6aHV/hwohbo2ioDpTUFAAjUYDrVbL/n7U+Gi1wF/+AqSnSyPNvv++QT6Ll7/D+lNX53rP2TyMWvE7/DXOSInn5N9kZ7KzgR49gMxMICYGuNUqWl3V/R3yWb1EVDOTJklJX6tWwP/+1yCTPrJNZQM72L+P7M61a0BUlJT0tW0rTeFiJUz8iKj6Tp6U+vMBUh8/b29546FGxdy/L7CpvIEQ1aecHGDQIODIESAgANi2DXB3t9rhmPgRUfW98YY0ieiwYQBHuVMdK7vj15kDO8he7NsHdOsG7N8PeHkBSUlAmzZWPSQTPyKqnlOnpKZdAPjPf+SNhRqd/GI9LubfAACEs6mX7MG6dUCfPkBWFtCuHZCSArRvb/XDMvEjoqqVlgIffAD07i3d7Xv0UWluKaI6dCKnEAAQ6OkCD2eVzNEQWVFpKTB1KjBmjPSYy0cfBX7/XerbVw/4XCUiqpzBAIwaBWzaJL0PDQUWLZI3JmqUTuRIz+cN8+MIbGrEiouBkSOBrVul97NmAXPm1Nnj2KqDiR8RVay0VJo9ftMmaQLRDz4AnnuOz+ElqziRLd3xa+dnvU7tRLK6dg0YOlRq0nVxAT77THrkZT1jDU5E5RmNUjPEhg2ASiUlf0OGyB0VNWJld/xCecePGiOdDnjkEalJt1kz4LvvgMhIWUJh4kdEloxGYNw4aboWR0cgMZFJH1mVySRw6nIRACCUd/yoMXrppdtJ344dQHi4bKFwcAcR3VZUBPzzn9JoM6USWL9e6nhMZEVZ12/ghsEItdIBrb1c5Q6HqG6tWAGsXAkoFNLMCDImfQDv+BFRmb17pSTvyhWpo/H//gc8/rjcUZEdOH1VutvX2tsVjkrej6BGJCUFmDBBej1/PjB4sLzxgHf8iAiQmh4GDpSSvjZtpD59I0fKHRXZiTNXpMTvvuZNZI6EqA5lZwNPPCHNjvDEE8D06XJHBIB3/Ijoxx+BESOAGzeA/v2Br7+26uOCiP7szK07fiE+TPyokdDppBG72dnSpMyffio19TYAvONHZM+++UZq3r1xQxrAsXUrkz6qd6d5x48aC4MBWLwYuO8+4LffAI0G2Ly5QdWrvONHZK82bZImZzYYpL58X34pzddHVM/OXC0GwDt+ZONOnQL+8Q/p+bsA4O8PrF1bb0/kqC7e8SOyR4mJUjOEwQCMHi2N3mXSRzK4VqzHtWI9AKCNj5vM0RDVghDAxx8DXbpISV/TptJdv7Nnpb7TDQzv+BHZmytXgLFjpfn6YmKA1av5NA6STVkzb4umLnBV8/+HZGMKC6W7fF9/Lb3/61+BNWuAwEBZw6oK7/gR2Zv586XnRXbrJnU4ZtJHMiob2MH+fWRz8vKAhx6Skj61WnqOeVJSg076AN7xI7IvFy4Ay5dLrxcskCZpJpIRB3aQTcrKAqKigGPHAC8vaWBc9+5yR1UtTPyI7MXly8BzzwF6vXSV2gD7npD9KUv8OLCDbEZuLtCvH3DmDNCihTQlVvv2ckdVbWzqJWrshJD68bVrB/z0E6BSAQsXyh0VEQA29ZKN0eulWRDOnAFatwZ27bKppA9g4kfUuKWnS52Nn30WyM8HOncGdu+W+vcRyUxXasSl6zcAAMHeHNFLDZwQQGwssHMn4OEhNe+2bi13VDXGxI+osfruO6BDB2D7dsDFBfjvf6WpBpj0UQNxMf8GTAJwUyvh3YTTCVEDt2iRNCDOwUGaAqtdO7kjqhX28SNqjPR64KWXpMcGDRwIrFgBBAfLHRWRhQt50sTNQV5uUDSQx1kRVejbb4FXXpFeL1oEDB4sbzz3gIkfUWO0ciVw7pw0c/yWLYCrq9wREZVzPrcEANDam///pAbsjz+Av/9daur917+AiRPljuiesKmXqLEpLgZef116PWsWkz5qsO6840fU4OTnA++8A/TsCRQVAf37S0/ksPG707zjR9TYfPSRNHVLmzbSoA6iBup83q07fl68OKEG4sYNadaDZcuAq1dvr+/fH/jqK2lWBBvHO35EjUl+PvDWW9LruXP5/N16tHTpUgQHB8PZ2RkRERHYuXNnleWTk5MREREBZ2dntGnTBsvLJta+Q2JiItq3bw8nJye0b98emzZtqvFxhRCYM2cOAgIC4OLigv79++Po0aMWZfr37w+FQmGxjB49uhZnoWbK7vi18uQdP5KZENITONq3B+bNu530tW4tTYf1yy/SRM2NABM/osbkv/8Frl8HwsOlPilUL9avX4+4uDjMmDEDaWlp6NOnD6Kjo5GRkVFh+XPnzmHIkCHo06cP0tLS8Nprr2HixIlITEw0l0lJScGoUaMQExODQ4cOISYmBiNHjsSePXtqdNy3334bixYtwuLFi7Fv3z74+fnh4YcfRmFhoUVM48ePR3Z2tnn5+OOP6/gsWTKaBLJuTeXSinf8SE5nzgBDhwLDhwPnzwMtW0qjdouKpL7S48bZfPOuBUF1TqvVCgBCq9XKHQrZk+xsIVxdhQCE2LxZ7mhkV5+/w+7du4vY2FiLdWFhYWL69OkVlp82bZoICwuzWPf888+Lnj17mt+PHDlSDB482KLMoEGDxOjRo6t9XJPJJPz8/MTChQvN22/evCk0Go1Yvny5eV2/fv3EpEmTqvFNK1abc30xv0QEvfqtuO+170Sp0VTrYxPVml4vxIwZQjg5SfWmSiXE9OlCFBXJHVmtVPd3yDt+RI3F/PlASYnUEXnYMLmjsRt6vR6pqamIioqyWB8VFYXdu3dX+JmUlJRy5QcNGoT9+/fDYDBUWaZsn9U57rlz55CTk2NRxsnJCf369SsX2xdffAFvb2888MADmDp1ark7gnfS6XQoKCiwWGoq85rUvy+gqQuUDo3obgrZBq0WGDJEqjd1OuDhh4HDh6VnmLs17q4HHNxBZOuMRuCLL4Cyprk332xczRINXG5uLoxGI3x9fS3W+/r6Iicnp8LP5OTkVFi+tLQUubm58Pf3r7RM2T6rc9yyvxWVuXDhgvn9008/jeDgYPj5+eHIkSOIj4/HoUOHkJSUVGH8CxYswNy5cyvcVl0ZtxK/Vp5s5qV6lpEhJX1Hj0pJ3qefAk8+aTf1ptXu+LGjM5GVCQFs3gx06gSMHQsYDMAjjwADBsgdmV368wTEQogqJyWuqPyf11dnn3VRZvz48Rg4cCDCw8MxevRofPXVV/jpp59w4MCBCmOPj4+HVqs1L5mZmZV+z8pcvJX4tWzGxI/qgckE7NgBPP880LGjlPT5+0vr/vY3u0n6ACslfuzoTGRlv/4KREYCjz0mVWDNmkmjeTdskDsyu+Pt7Q2lUlnu7t6VK1fK3Wkr4+fnV2F5R0dHeN0aOVhZmbJ9Vue4fn5+AFCj2ACga9euUKlUSE9Pr3C7k5MTPDw8LJaaysyXBnYEerrU+LNENWI0AlFRQL9+0lOMtFop+fv9d6BrV7mjq3/W6GDIjs4c3EFWcuOGEI89JnVEBqTBHDNmCJGfL3dkDU59D+7497//bbGuXbt2VdZ57dq1s1gXGxtbrs6Ljo62KDN48OBydV5Vxy2r89566y3zdp1OV67O+7PDhw8LACI5ObnSMneqzbl+YulvIujVb8XXB7Oq/RmiWlm3TqovnZ2FGDdOiJ9+EqK0VO6o6lx1f4d1nvjpdDqhVCrFxo0bLdZPnDhR9O3bt8LP9OnTR0ycONFi3caNG4Wjo6PQ6/VCCCECAwPFokWLLMosWrRItGrVqtrHPXPmjAAgDhw4YFFm2LBhYsyYMeb3/fr1E97e3sLLy0u0b99evPzyy6KgoKC6p4CJH1mHwXA76VOphJgwQRrJSxWqz99hQkKCUKlUYtWqVeLYsWMiLi5OuLm5ifPnzwshhJg+fbqIiYkxlz979qxwdXUVkydPFseOHROrVq0SKpVKfPXVV+Yyv/32m1AqlWLhwoXi+PHjYuHChcLR0VH8/vvv1T6uEEIsXLhQaDQasXHjRnH48GHx97//Xfj7+5vrtNOnT4u5c+eKffv2iXPnzonvvvtOhIWFiS5duojSav7jWJtz3fPNn0TQq9+KAxeuVfszRDWm1wsREiLVm2++KXc0VlXd32GdD+6wx47OOp0OOp3O/L42I9yI7urFF4FNmwAnJ+D779mXrwEZNWoU8vLyMG/ePGRnZyM8PBxbt25FUFAQACA7O9uiy0lwcDC2bt2KyZMnY8mSJQgICMCHH36IJ554wlymV69eSEhIwMyZMzFr1iyEhIRg/fr16NGjR7WPCwDTpk3DjRs38MILLyA/Px89evTAjz/+CHd3dwCAWq3Gzz//jA8++ABFRUUIDAzEI488gtmzZ0OpVFrlfBmMJlwuuAkAaNGUTb1kRatXS/P0NW9u88/YrStWG9Vr6x2dy4SHh6Nt27bo1q0bDhw4gK4V9AeoixFuRFX63/+kvikODkBCApO+BuiFF17ACy+8UOG2NWvWlFvXr1+/SgdPlHnyySfx5JNP1vq4gFTfzZkzB3PmzKlwe2BgIJKTk6s8Rl3L0d6ESQBqpQO8mzjV67HJDggB/PwzsGiRdJEMAPHxjX6aluqq88Ed9tjRuS5GuBFV6uxZIDZWev2f/wAjRsgaDtG9KntiR0BTZzhwDj+qKwYDsGaNNNPBww9LSZ9CATz1FPDvf8sdXYNR54mfWq1GREREuWbRpKQk9OrVq8LPREZGliv/448/olu3blDdeiByZWXK9lmd45Y1395ZRq/XIzk5udLYAODo0aMwGAzw9/evcHtdjHAjqtDWrcBf/woUFgK9ewMzZsgdEdE9y7o1ordFMzbzUh0xmaTHVI4bJ03E7OYGvPQScOqUNM+pE+8sm1mjgyE7OnNwB92jI0eEePLJ26N3g4KEuOP/x3R3/B3Wn5qe6w9+OiWCXv1WvLLhoJUjI7sxd65UV6rVQixcKMQ1+xs0JNuo3jJLliwRQUFBQq1Wi65du1pMCzB27FjRr18/i/Lbt28XXbp0EWq1WrRu3VosW7as3D43bNggQkNDhUqlEmFhYSIxMbFGxxVCmt5g9uzZws/PTzg5OYm+ffuKw4cPm7dnZGSIvn37Ck9PT6FWq0VISIiYOHGiyMvLq/Z35z84VCNGoxAHDgjxzjtC/POfQoSH3074lEohpk4VorBQ7ihtDn+H9aem53rahkMi6NVvxXtJJ60cGdmFzZtv15mrVskdjWyq+ztUCHFrFAXVmYKCAmg0Gmi1Wjb7kqXLl4Ht24HkZOD6dekZkb/9Jq2/k0oFREcD8+ZJ/VWoxvg7rD81Pdcxq/ZgZ3ou/vtkR/ytW2A9REiN1rFjQI8eQFERMGEC8NFHckckm+r+DvmsXiJrO3VKeqLGV18BBw9WXMbNTerLFxEBtGsndUxu1qxewySqL9laaSqXAE7lQvciPx8YPlxK+vr3l0bx0l0x8SOqa0IABw4AW7ZIyx9/WG7v1EmajiUoSBpx1qED8OCDgFotT7xE9UgIgexbo3r9NM4yR0M2q6hIGq17+rRUl/7f/0ktJXRXTPyI6tL168Do0cAPP9xep1QCAwdKDwIfNgzw8ZEtPCK5FepKUaw3AgD8mfhRTQghPV931Spg/Xop+XNxATZvZr1aA0z8iOrK2bPA0KHA8eOAszMwZIjUDPHII8Ct+SiJ7F32damZV+Oigqua/wRRNVy9CqxdKyV8x4/fXn/ffcCHHwKdO8sWmi3ir47oXmVmSk268+ZJFVSLFsA33wBdusgdGVGDk62Vmnl5t48qJQSQnQ1kZUkJ3yefADelCwa4uEitJ88+C/TpI3WXoRph4keNX1klcviw1N/u1Cnp0WdubtKdOG9vaWnSRKpcTCbAw0NaNBppxO2hQ1KzgpMT4OgI5OQA585JI8oOHbp9rC5dpKSvRQv5vi9RA1Y2sIOJH5VTUgJ89pk0SOP0acttERHA+PFSVxqNRp74GgkmfmS7fv9dWh58UKoUFAqguBg4cuR2klf299o168WhUAC9egGPPSY9Wo3PgySqVFni56fhiF67ZjIB6elAWtrtC/Lt24G8PGm7gwPg6ysNhnvlFWlAHO/u1QkmfmR7Ll8Gpk2TmgDKuLpKgyiKiqQ7fH/m4ADcfz/QsSPQvr30vrBQSghzc6WlqEjaDwAUFABarbRoNNKdPG9vad49vV7qSBwcDLRpIzU3NG9eP9+dyMbl3GrqDeAdP/tx4wZw4oQ0nVVamjTrQVkryp+1aQNMniw9eo0X0VbBxI9sh9EILF8uPa9Wq5Wu/vr0AVJTpTt9ZXx9pSlSOnaUlg4dpLnxXHiHgUhuZXf8fJn4NV5GozSzwdq1wN69wPnzFV+Qu7hId/Q6dwZCQ4HwcOnOnlJZ3xHbFSZ+1PAZjVLlMWGCdKUIAF27AsuWAd27S/3yMjOl9RoN774RNWBXCnQAAD8PJn6NSlYWsHu39CSir76S3t/J01NK8rp0kervLl2kZI9JXr1j4kcNg04HrFghNQWUNb3m5Ul/r127fbXYtCkwfz7w/PO3KwxnZ6BtW7kiJ6IauFx4644fE7/GIT1d6tv8yy+W6z09gZgYYMQIqXuNjw/76DUQTPxIfsnJUsVx4kTlZZRK4B//AN5+m3f0iGzUTYMR10sMAABfDyeZo6F7UlAgtbrMmSO1ujg4SHf0IiOlx08OHSrNgkANDhM/ko9eD8ycCbzzjnRHz9cX+Pe/AX9/y2lWvLykhY/jIbJpVwulZl61owM0Lvw9y0YIqV90fr40NZXRCLRqBfj5SQlcURGwc6e0HZC2X7wo9dU7c0aaRPnSpdv7e/hh4OOPpQFv1OAx8SN5nDwpPWexrM/ec88B//2v1JRLRI3S5YJbU7l4OEPBZj/rO38e2LQJ+PlnKXG7ckWazaC4uOLBFioV0LKl1D9Pr7/7/oOCgLlzgTFj2IxrQ5j4Uf1bvRp46SVpsk5PT+kxPCNGyB0VEVlZTkFZ/z42AVqFENLduI0bpYSv7MK6Mo6Ot+/yZWUBBoM0MT0g3b0LCZFeKxRSueBgaQkNlWZK4IW6TWLiR/VDCKkv33//C2zdKq176CFpuH9AgLyxEVG9uHxrRG9zDuyoO0IA+/ffTvZOnry9zcFBmvJq+HAgLEzqTqPRSE8pcneXplMpu1NXWio132ZkSAMx7r+fd/EaKSZ+VPfK+o9cuyYtf/wBvP++NHEnIFVGr78OTJ8uvSYiu3Cl7I6fOxO/WiktBY4elUbSnjol/f3559vTWQGAWg0MHAg8/jgwbJiUxFWHo6PUz69VK+vETg0GEz+qOZMJ+L//k+bWK0vu/rwYDOU/5+ICPPMMMGmS1FRARHblMpt6a+/nn4EXXpASvj9zcwOGDJGSvSFDpOeME1WCiR9ZEgLIzpYep3PihNQ5uLhYGtVVNrp20yZg376770utlso3bw6MGgX861/SeyKySyP/EojwFhr0bMN6oNqys4GXXwa+/FJ67+4OPPCANHdp27bSRMgPPcQnE1G1MfGzJwaD1Bfk4EEpqTt1Crh+XZqDqWwpKJDu2N2Nu7v0LMWAAGmARkWLqyv7iBCRWa8Qb/QK8ZY7DNtgNAJLl0pTXhUUSN1iXnxR6iaj0cgdHdkwJn6NVUkJsGcPcPasNEorNVWal+nOZ9pWxsFB6gjcvr00qsvDQ0rgrl2TnqTh7S1dgfr5Wf97EBHZg8JC6WL85Elp+fpr6SIdAP7yF2my5IgIWUOkxoGJX2OUkCA91zYvr/w2b2+gRw9pKH5oqNQM6+x8e3FxAe67j80GRETWYjIBKSlAYqI06O3UKcsJkcs0bQosWACMH89n2lKdYeLX2Hz3nfRoM6NRegJGx47SvEthYcCAAUB4OEfSEhHJ4dgxYN064IsvLEfilmneXLogv/9+qcXl6aelKViI6hATv8ZAp5P67u3aBcybJyV9MTHSRMmO/E9MRCQbIYDPPwfee+/2lFaA1E96xAhp6pWyZK9ZM9nCJPvBrMCWmExS34+9e6Wh/Tt2SP3uioulbWUGD5aehsGkj4io/hmNUh/rrVuBb76R5jIFpDp5yBDpwnzoUKl7DVE9Y2bQ0JWWSs23K1dKiV5hYcXlmjcHevcG+veX+oOo+AB0IqI6YTAAy5dLgy30eqmVRaer/PWVK9KMCWWcnIBZs4Dnn5f6WRPJiIlfQ5WZCXz6qZTwXbx4e72rK9C1K/Dgg1ITQVCQ9PgdX19OnUJEVBsmkzT7waVLwNWr0gW2Xi/dkVMqgXffvftzb/+sWTOp9WXIEOkvEz5qIJj4NSR79gCbN0sVTFKS1DcEkCY9fvZZ4KmnpIk72YRLRFRzBoM0IXJGhrRkZgLHjwM//ADk5FT9WU9PabYEDw/pDp6TkzRJfUWv3d2lgXSsq6kB4v8rG4rFi6VHmd3ZV69/fynhe/JJ9gUhIqqO/HzpIvrgQSmpO35cSury84Gioso/5+QEtGwpdZvx8JASOZ1Omtg+JASYP1+aKYHIxjHxk9P//gf8+KPUtLB1q7QuOlpqxh01SqpsiIioaqWlwPvvS91jjh2ruqxKBQQGAq1aSX+DgoB+/YA+faTkj6iRY+Inp337gM8+u/1+zBhgzRr21SMiqq4TJ4CxY6XZDsrcd5/0tIv27aXJ6lu1kvrcNW0qNdlyLlOyY0z85PToo9KzbgHp8WejRjHpIyKqiBDS3bzkZOmiOS9Par7dv19qjtVogLfeAh57TGquJaIKWe2yZ+nSpQgODoazszMiIiKwc+fOKssnJycjIiICzs7OaNOmDZYvX16uTGJiItq3bw8nJye0b98emzZtqvFxhRCYM2cOAgIC4OLigv79++Po0aMWZXQ6HV566SV4e3vDzc0Nw4YNw8U7R9bWlb/+FXjlFWmJiZH6lBARkaSoSBrw9q9/Sc2y4eHAiy9KLSPffCNNWn/zJhAVBRw+LE2XwqSPqGrCChISEoRKpRIrV64Ux44dE5MmTRJubm7iwoULFZY/e/ascHV1FZMmTRLHjh0TK1euFCqVSnz11VfmMrt37xZKpVK8+eab4vjx4+LNN98Ujo6O4vfff6/RcRcuXCjc3d1FYmKiOHz4sBg1apTw9/cXBQUF5jKxsbGiRYsWIikpSRw4cEAMGDBAdOrUSZSWllbr+2u1WgFAaLXamp46Iqoj/B3Wnzo511lZQixbJsRLLwnx5JNCREYKoVYLId3rkxYXFyEGDhRi9mwhVqwQYsMGIXbvFsJkqrPvQmSrqvs7VAhRNmdI3enRowe6du2KZcuWmde1a9cOI0aMwIIFC8qVf/XVV/H111/j+PHj5nWxsbE4dOgQUlJSAACjRo1CQUEBvv/+e3OZwYMHo1mzZvjyyy+rdVwhBAICAhAXF4dXX30VgHR3z9fXF2+99Raef/55aLVa+Pj4YN26dRg1ahQA4NKlSwgMDMTWrVsxaNCgu37/goICaDQaaLVaeHh4VFpuxY4zSNiXiRZNXRCgcYGvxhnN3Z3g3cQJnm5qNHNVQeOqgoezCk6ODlCwGZio2qr7O6R7V+tzfe6c1FT7449Sf2eDoXyZNm2ARx6R5sPr358zHBBVorq/wzrv46fX65Gamorp06dbrI+KisLu3bsr/ExKSgqioqIs1g0aNAirVq2CwWCASqVCSkoKJk+eXK7M+++/X+3jnjt3Djk5ORbHcnJyQr9+/bB79248//zzSE1NhcFgsCgTEBCA8PBw7N69u1qJX3WdvVpsXu5GrXRAE2dHuKqVcFUr4aJ2hIvKAc4qJZwcHaB2VEKtdIDaUQGV0gEqpQMclQo4Oijg6OAApYPi9qJQQKGA+b1CoYACgINCAQeF9BfS/8zbFIpbCxQW3RDLktE7U9Ky7Yo71v45Z60ohb17Xmu7iS9z9rrl3USNiCBPucOgmjp8WBqMcf48sG0b8Msvltt79AAGDJD6Pvv5AR07Ss+w5Q+IqM7UeeKXm5sLo9EIX19fi/W+vr7IqWSCzJycnArLl5aWIjc3F/7+/pWWKdtndY5b9reiMhcuXDCXUavVaPanh2VXFb9Op4NOpzO/LygoqLDcn8UNvB/DOgXgYv4NZGtv4nLhTVwt1CGvSIf8EgOuFetRcNMAIQC90YRrxXpcu3uOSNTo9b3fB2v/2V3uMKim3nwTSEi4/V6hkJ5E1KYNMHGiNJUVEVmV1Ub1/rlZUghRZVNlReX/vL46+6yrMn9WVZkFCxZg7ty5VX6+In4aZ/hpqm62MJkEivWlKLxZimJdKYr1RhTrSnFDb0SJwQidwYibpSYYSk3QG03Ql5pQajRBbxQoNZpQahIwmgRKTaZbfwWEAExCWl/2Wlqk71m2TuBWxxrc/u8hvb/92uLvn9ebT57ldxJ/XlG2vg46HdR5vwVqkNo2byJ3CFQbHTtKT8to0UJK+EaPlubRI6J6U+eJn7e3N5RKZbm7Y1euXCl3p62Mn59fheUdHR3h5eVVZZmyfVbnuH5+fgCku3r+d8zA/ucyer0e+fn5Fnf9rly5gl69elUYf3x8PKZMmWJ+X1BQgMDAwArL1pSDgwLuziq4O6vqZH9EZB1Lly7Ff//7X2RnZ+OBBx7A+++/jz59+lRaPjk5GVOmTMHRo0cREBCAadOmITY21qJMYmIiZs2ahTNnziAkJATz58/HY489VqPjCiEwd+5crFixAvn5+ejRoweWLFmCBx54wFxGp9Nh6tSp+PLLL3Hjxg089NBDWLp0KVq2bFlHZ+eW+HhpISLZ1Pl0Lmq1GhEREUhKSrJYn5SUVGniFBkZWa78jz/+iG7dukGlUlVZpmyf1TlucHAw/Pz8LMro9XokJyeby0REREClUlmUyc7OxpEjRyqN38nJCR4eHhYLEdmP9evXIy4uDjNmzEBaWhr69OmD6OhoZGRkVFj+3LlzGDJkCPr06YO0tDS89tprmDhxIhITE81lUlJSMGrUKMTExODQoUOIiYnByJEjsWfPnhod9+2338aiRYuwePFi7Nu3D35+fnj44YdRWFhoLhMXF4dNmzYhISEBu3btQlFREYYOHQqj0WiFs0VEsrLGkOKyaVVWrVoljh07JuLi4oSbm5s4f/68EEKI6dOni5iYGHP5sulcJk+eLI4dOyZWrVpVbjqX3377TSiVSrFw4UJx/PhxsXDhwkqnc6nsuEJI07loNBqxceNGcfjwYfH3v/+9wulcWrZsKX766Sdx4MAB8de//pXTuRDZmPr8HXbv3l3ExsZarAsLCxPTp0+vsPy0adNEWFiYxbrnn39e9OzZ0/x+5MiRYvDgwRZlBg0aJEaPHl3t45pMJuHn5ycWLlxo3n7z5k2h0WjE8uXLhRBCXL9+XahUKpGQkGAuk5WVJRwcHMS2bdvu+t2FYJ1H1BBU93dolcRPCCGWLFkigoKChFqtFl27dhXJycnmbWPHjhX9+vWzKL99+3bRpUsXoVarRevWrcWyZcvK7XPDhg0iNDRUqFQqERYWJhITE2t0XCGkinD27NnCz89PODk5ib59+4rDhw9blLlx44aYMGGC8PT0FC4uLmLo0KEiIyOj2t+dlSCR/Orrd6jT6YRSqRQbN260WD9x4kTRt2/fCj/Tp08fMXHiRIt1GzduFI6OjkKv1wshhAgMDBSLFi2yKLNo0SLRqlWrah/3zJkzAoA4cOCARZlhw4aJMWPGCCGE+PnnnwUAce3aNYsyHTt2FP/5z38qjP/mzZtCq9Wal8zMTNZ5RDKrbp1ntcEdL7zwAl544YUKt61Zs6bcun79+uHAgQNV7vPJJ5/Ek08+WevjAtLAjjlz5mDOnDmVlnF2dsZHH32Ejz76qMpjERHZ40wGtR3QRkTy47N6rUDcGp5a3WldiKjulf3+RN3PUV8he5rJ4M8D2rRaLVq1asU6j0hG1a3zmPhZQVmn6boa2UtEtVdYWAiNRmO1/dvjTAZOTk5wcnIyvy/7B4d1HpH87lbnMfGzgoCAAGRmZsLd3b3SK+ayKV8yMzNtbhSwLccO2Hb8thw7UL/xCyFQWFiIgIAAqx7nzhkF7pxqJSkpCcOHD6/wM5GRkfjmm28s1lU2k8GdTyyqbCaDyo5750wGXbp0AXB7JoO33noLgOVMBiNHjgRweyaDt99+u1rngHVew2bL8dty7EADrfOs2dGQKmfLA0BsOXYhbDt+W45dCNuPvzL2PpNBddjyf3tbjl0I247flmMXomHGzzt+RET3aNSoUcjLy8O8efOQnZ2N8PBwbN26FUG3nkqRnZ1tMbdecHAwtm7dismTJ2PJkiUICAjAhx9+iCeeeMJcplevXkhISMDMmTMxa9YshISEYP369ejRo0e1jwsA06ZNw40bN/DCCy+YJ3D+8ccf4e7ubi7z3nvvwdHRESNHjjRP4LxmzRoolUprnjYikoFCiHrq+UwWCgoKoNFooNVqbe72tS3HDth2/LYcO2D78VPt2fJ/e1uOHbDt+G05dqBhxl/nT+6g6nFycsLs2bMtOkjbCluOHbDt+G05dsD246fas+X/9rYcO2Db8dty7EDDjJ93/IiIiIjsBO/4EREREdkJJn5EREREdoKJHxEREZGdYOIng6VLlyI4OBjOzs6IiIjAzp075Q6pnDlz5kChUFgsZU8BAKSJIufMmYOAgAC4uLigf//+OHr0qGzx7tixA48++igCAgKgUCiwefNmi+3ViVen0+Gll16Ct7c33NzcMGzYMFy8eFH22J955ply/y169uzZIGJfsGAB/vKXv8Dd3R3NmzfHiBEjcPLkSYsyDfncU/1gnVf3WOexzqstJn71bP369YiLi8OMGTOQlpaGPn36IDo62mKOr4bigQceQHZ2tnk5fPiwedvbb7+NRYsWYfHixdi3bx/8/Pzw8MMPmx9XV9+Ki4vRqVMnLF68uMLt1Yk3Li4OmzZtQkJCAnbt2oWioiIMHToURqNR1tgBYPDgwRb/LbZu3WqxXa7Yk5OT8eKLL+L3339HUlISSktLERUVheLiYnOZhnzuyfpY51kH6zzWebUm18zR9qp79+4iNjbWYl1YWJiYPn26TBFVbPbs2aJTp04VbjOZTMLPz08sXLjQvO7mzZtCo9GI5cuX11OElQMgNm3aZH5fnXivX78uVCqVSEhIMJfJysoSDg4OYtu2bbLFLoQQY8eOFcOHD6/0Mw0ldiGEuHLligAgkpOThRC2de7JOljnWR/rPNZ5NcE7fvVIr9cjNTUVUVFRFuujoqKwe/dumaKqXHp6OgICAhAcHIzRo0fj7NmzAIBz584hJyfH4ns4OTmhX79+DfJ7VCfe1NRUGAwGizIBAQEIDw9vEN9p+/btaN68Oe6//36MHz8eV65cMW9rSLFrtVoAgKenJ4DGce6p9ljnyaMx/O5Y51kPE796lJubC6PRCF9fX4v1vr6+yMnJkSmqivXo0QNr167FDz/8gJUrVyInJwe9evVCXl6eOVZb+B4AqhVvTk4O1Go1mjVrVmkZuURHR+OLL77AL7/8gnfffRf79u3DX//6V+h0OgANJ3YhBKZMmYIHH3wQ4eHh5tjKYqkstoYSP9U91nnysPXfHes86+KzemWgUCgs3gshyq2TW3R0tPl1hw4dEBkZiZCQEHz22WfmTra28D3uVJt4G8J3GjVqlPl1eHg4unXrhqCgIHz33Xd4/PHHK/1cfcc+YcIE/PHHH9i1a1e5bbZ67qlu2EJdwTqv+mWsjXWedfGOXz3y9vaGUqksl9FfuXKl3NVBQ+Pm5oYOHTogPT3dPNLNVr5HdeL18/ODXq9Hfn5+pWUaCn9/fwQFBSE9PR1Aw4j9pZdewtdff41ff/0VLVu2NK9vbOeeaoZ1njwa2++OdV7dYuJXj9RqNSIiIpCUlGSxPikpCb169ZIpqurR6XQ4fvw4/P39ERwcDD8/P4vvodfrkZyc3CC/R3XijYiIgEqlsiiTnZ2NI0eONLjvlJeXh8zMTPj7+wOQN3YhBCZMmICNGzfil19+QXBwsMX2xnbuqWZY58mjsf3uWOfV/ZegepSQkCBUKpVYtWqVOHbsmIiLixNubm7i/Pnzcodm4eWXXxbbt28XZ8/+f3t379LWHsdx/BO9USzaaFLrQ8VORUTFYqcugg7SIaC4SHGIOKVQ6FA66ODDIk4OopuYqVCX/gXFh9hKHTSDOAh6tVof6FghtkXyvcslV2vpFase9fd+wYHk5HDyORm+fE5OHv62jx8/Wjgctry8vHTOwcFBCwQC9vbtW1taWrKnT59aSUmJff361ZO8+/v7lkgkLJFImCQbGhqyRCJhnz59OnXeaDRqZWVl9u7dO1tcXLTGxkarra21w8NDz7Lv7+/by5cvbW5uztbX121qasoeP35s9+7duxLZnz17ZoFAwKanp213dze9JJPJ9DZX+bXHxWPmXQxmHjPvrCh+HhgdHbX79+9bVlaW1dXVpb8GfpW0tbVZSUmJ+f1+Ky0ttdbWVlteXk4/nkqlrLe314qLiy07O9vq6+ttaWnJs7xTU1Mm6cQSiUROnffg4MCeP39uwWDQcnJyLBwO2+bmpqfZk8mkNTU1WWFhofn9fisvL7dIJHIil1fZf5VbksVisfQ2V/m1x+Vg5p0/Zh4z76x8/x4IAAAAbjg+4wcAAOAIih8AAIAjKH4AAACOoPgBAAA4guIHAADgCIofAACAIyh+AAAAjqD4AQAAOILiB2f19fXp4cOHXscAgEvBzIMk8c8duJF8Pt9vH49EIhoZGdH3798VCoUuKRUAXAxmHk6L4ocbaW9vL317YmJCPT09WllZSa/LyclRIBDwIhoAnDtmHk6LS724kYqLi9NLIBCQz+c7se7nyx4dHR1qaWnRwMCAioqKlJ+fr/7+fh0eHurVq1cKBoMqKyvT+Pj4sefa3t5WW1ubCgoKFAqF1NzcrI2Njcs9YABOY+bhtCh+wBGTk5Pa2dlRPB7X0NCQ+vr6FA6HVVBQoPn5eUWjUUWjUW1tbUmSksmkGhoalJubq3g8rvfv3ys3N1dPnjzRjx8/PD4aAPg9Zp57KH7AEcFgUMPDw6qoqFBnZ6cqKiqUTCbV3d2tBw8eqKurS1lZWfrw4YMk6c2bN8rIyNDY2JhqampUWVmpWCymzc1NTU9Pe3swAPA/mHnu+cvrAMBVUlVVpYyM/86HioqKVF1dnb6fmZmpUCikL1++SJIWFha0urqqvLy8Y/v59u2b1tbWLic0AJwRM889FD/gCL/ff+y+z+f75bpUKiVJSqVSevTokV6/fn1iX4WFhRcXFADOATPPPRQ/4A/U1dVpYmJCd+/e1e3bt72OAwAXipl3/fEZP+APtLe3686dO2pubtbs7KzW19c1MzOjFy9e6PPnz17HA4Bzxcy7/ih+wB+4deuW4vG4ysvL1draqsrKSnV2durg4ICzYQA3DjPv+uMHnAEAABzBO34AAACOoPgBAAA4guIHAADgCIofAACAIyh+AAAAjqD4AQAAOILiBwAA4AiKHwAAgCMofgAAAI6g+AEAADiC4gcAAOAIih8AAIAj/gHSJurNadbeFwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f = plt.figure()\n", + "\n", + "objLegrand.plot()\n", + "\n", + "plt.close()\n" + ] + }, + { + "cell_type": "markdown", + "id": "ef3374aa", + "metadata": {}, + "source": [ + "\n", + "We can see from our visual confirmation that the estimated parameters\n", + "are not exactly ideal. This is confirmed by the information returned\n", + "from the `scipy.optimize.minimize` routine, and probably caused by the\n", + "poor starting point. An attempt to find a more suitable value can be\n", + "done by some form of parameter space exploration. Given that the\n", + "evaluation of the objective function is not expensive here, we have\n", + "plenty of options to choose from. To reduce the number of packages\n", + "required to build this documentation, routines from `scipy.optimize`\n", + "remain our preferred option." + ] + }, + { + "cell_type": "markdown", + "id": "be511db4", + "metadata": {}, + "source": [ + "\n", + "### Improved initial guess" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "38badab5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 3.11038452e-09 7.85178078e-06 -3.60499243e-08]\n" + ] + } + ], + "source": [ + "resDE = scipy.optimize.differential_evolution(objLegrand.cost,\n", + "bounds=boxBounds, polish=False, seed=20921391)\n", + "\n", + "print(objLegrand.sensitivity(resDE['x']))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9f68ff44", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f = plt.figure()\n", + "\n", + "objLegrand.plot()\n", + "\n", + "plt.close()" + ] + }, + { + "cell_type": "markdown", + "id": "d06e8bdf", + "metadata": {}, + "source": [ + "\n", + "Looking at the output of the estimates (below this paragraph), we can\n", + "see our inference on Ebola is wrong when compared to the *known* values\n", + "(from field observations) even though the graphs looks *\\`\\`reasonable\"*.\n", + "Namely, $\\gamma^{-1}$, the third parameter in the vector below, our time\n", + "from infectiousness to death, is within the expected range but $\\alpha^{-1}$\n", + "(second parameter), the incubation period, is a lot higher than expected.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "3f01c604", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([7.13160861e-01, 1.88609866e+03, 8.00526800e+01])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "1/resDE['x']" + ] + }, + { + "cell_type": "markdown", + "id": "4bc57a74", + "metadata": {}, + "source": [ + "\n", + "### Multimodal surface\n", + "\n", + "A reason for this type of behavior is that we simply lack the\n", + "information/data to make proper inference. Without data on the state\n", + "$E$, the parameters $\\beta,\\alpha$ for the two states $I$ and $E$ are\n", + "dependent only on observations on $I$. Hence, some other random\n", + "combination of $\\beta,\\alpha$ that is capable of generating realizations\n", + "close to observations in $I$ is feasible. In such cases, the only\n", + "requirement is that there exist some $\\gamma$ in the feasible region\n", + "that can compensate for the ill suited $\\beta,\\alpha$. For example, we\n", + "know (obtained elsewhere and not shown here) that there is another set\n", + "of parameters capable of generating a similar looking curves as before.\n", + "Note the reversal of magnitude in $\\beta$ and $\\alpha$.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "f4797fe3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1.90984074647533e-08" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "objLegrand.cost([3.26106524e+00, 2.24798702e-04, 1.23660721e-02])\n", + "\n", + "# objLegrand.cost([ 0.02701867, 9.00004776, 0.01031861])\n", + "# similar graph\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "0573ccf8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "objLegrand.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "ce36ae9e", + "metadata": {}, + "source": [ + "### With initial values as parameters\n", + "\n", + "The assumption that the whole population being susceptible is\n", + "an overestimate, therefore we want to estimate the initial conditions of the\n", + "ODEs as well. Given previous estimates of the parameters\n", + "$\\hat{\\beta}, \\hat{\\alpha}, \\hat{\\gamma}$ it is appropriate to start our\n", + "initial guess there.\n", + "\n", + "Furthermore, given that we now estimate the initial values for all the\n", + "states, we can use the first time point as our observation. So our time\n", + "begins at $t = -1$ where our observations include the previous initial\n", + "condition, i.e. 49 and 29 for the number of cases and death at $t = 0$\n", + "respectively. The following code block demonstrates how we would do\n", + "that; feel free to try it out yourself to see the much improved result.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "fe0f36b4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[5.0, 5.0, 5.0, 0.99999999, 0.0, 4.170212765957447e-06, 2.468085106382979e-06]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "thetaIV = theta.tolist() + x0\n", + "\n", + "thetaIV[3] -= 1e-8 # to make sure that the initial guess satisfies the constraints\n", + "\n", + "thetaIV\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2a07dc02", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: Optimization terminated successfully.\n", + " success: True\n", + " fun: 6.267485095752834\n", + " x: [ 3.850e+00 2.211e-02 4.114e+00 6.482e-01\n", + " 2.643e-06 4.215e-06 1.967e-05]\n", + " nit: 99\n", + " nfev: 10500\n", + " population: [[ 3.850e+00 2.211e-02 ... 4.215e-06 1.967e-05]\n", + " [ 4.083e+00 6.271e+00 ... 8.164e-06 1.845e-05]\n", + " ...\n", + " [ 4.550e+00 7.734e+00 ... 5.920e-06 1.729e-05]\n", + " [ 4.326e+00 3.862e-03 ... 8.806e-06 1.406e-05]]\n", + " population_energies: [ 6.267e+00 6.619e+00 ... 6.721e+00 6.385e+00]\n" + ] + } + ], + "source": [ + "objLegrand = SquareLoss(theta, ode_obj,\n", + " t0=t[0], x0=x0,\n", + " t=t[1::], y=y[1::,:],\n", + " state_name=['I','R'],\n", + " state_weight=numpy.sqrt(population*2)) \n", + "\n", + "boxBoundsIV = boxBounds + [(0.,1.), (0.,1.), (0.,1.), (0.,1.)]\n", + "\n", + "resDEIV = scipy.optimize.differential_evolution(objLegrand.costIV, bounds=boxBoundsIV, polish=False, seed=20921391)\n", + "\n", + "print(resDEIV)" + ] + }, + { + "cell_type": "markdown", + "id": "3331a258", + "metadata": {}, + "source": [ + "objLegrand.plot()\n" + ] + }, + { + "cell_type": "markdown", + "id": "2408c495", + "metadata": {}, + "source": [ + "## Legrand Ebola SEIHFR Model\n", + "\n", + "Next, we demonstrate the estimation on a model that has been widely used in\n", + "the 2014 Ebola outbreak in west Africa {citets}`Legrand`. This model has been\n", + "defined in {mod}`.common_models`.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "4f726a4a", + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'delta' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[21], line 9\u001b[0m\n\u001b[0;32m 2\u001b[0m ode \u001b[38;5;241m=\u001b[39m common_models\u001b[38;5;241m.\u001b[39mLegrand_Ebola_SEIHFR()\n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# initial guess from the paper that studied the outbreak in Congo\u001b[39;00m\n\u001b[0;32m 6\u001b[0m theta \u001b[38;5;241m=\u001b[39m numpy\u001b[38;5;241m.\u001b[39marray([\u001b[38;5;241m0.588\u001b[39m,\u001b[38;5;241m0.794\u001b[39m,\u001b[38;5;241m7.653\u001b[39m, \u001b[38;5;66;03m# the beta \u001b[39;00m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;241m10.0\u001b[39m,\u001b[38;5;241m9.6\u001b[39m,\u001b[38;5;241m5.0\u001b[39m,\u001b[38;5;241m2.0\u001b[39m, \u001b[38;5;66;03m# the omega\u001b[39;00m\n\u001b[0;32m 8\u001b[0m \u001b[38;5;241m7.0\u001b[39m,\u001b[38;5;241m0.81\u001b[39m,\u001b[38;5;241m0.80\u001b[39m, \u001b[38;5;66;03m# alpha,\u001b[39;00m\n\u001b[1;32m----> 9\u001b[0m \u001b[43mdelta\u001b[49m, \n\u001b[0;32m 10\u001b[0m theta,\n\u001b[0;32m 11\u001b[0m \u001b[38;5;241m100.\u001b[39m,\u001b[38;5;241m1.0\u001b[39m]) \u001b[38;5;66;03m# kappa,intervention time\u001b[39;00m\n\u001b[0;32m 13\u001b[0m \u001b[38;5;66;03m# initial conditions, note that we have a 0.0 at the end because the model is a non-automonous ODE which we have converted the time component out of\u001b[39;00m\n\u001b[0;32m 15\u001b[0m x0 \u001b[38;5;241m=\u001b[39m numpy\u001b[38;5;241m.\u001b[39marray([population, \u001b[38;5;241m0.0\u001b[39m, \u001b[38;5;241m49.0\u001b[39m, \u001b[38;5;241m0.0\u001b[39m, \u001b[38;5;241m0.0\u001b[39m, \u001b[38;5;241m29.0\u001b[39m, \u001b[38;5;241m0.0\u001b[39m])\u001b[38;5;241m/\u001b[39mpopulation\n", + "\u001b[1;31mNameError\u001b[0m: name 'delta' is not defined" + ] + } + ], + "source": [ + "from pygom import common_models\n", + "ode = common_models.Legrand_Ebola_SEIHFR()\n", + "\n", + "# initial guess from the paper that studied the outbreak in Congo\n", + "\n", + "theta = numpy.array([0.588,0.794,7.653, # the beta \n", + " 10.0,9.6,5.0,2.0, # the omega\n", + " 7.0,0.81,0.80, # alpha,\n", + " delta, \n", + " theta,\n", + " 100.,1.0]) # kappa,intervention time\n", + "\n", + "# initial conditions, note that we have a 0.0 at the end because the model is a non-automonous ODE which we have converted the time component out of\n", + "\n", + "x0 = numpy.array([population, 0.0, 49.0, 0.0, 0.0, 29.0, 0.0])/population\n", + "\n", + "ode.parameters = theta\n", + "\n", + "ode.initial_values = (x0, t[0])\n", + "\n", + "objLegrand = SquareLoss(theta, ode, x0, t[0], t[1::], y[1::,:], \n", + " ['I','R'], numpy.sqrt([population]*2))" + ] + }, + { + "cell_type": "markdown", + "id": "71d2d4b6", + "metadata": {}, + "source": [ + "Now, it is important to set additional constraints accurately because a\n", + "simple box constraint is much larger than the feasible set. Namely,\n", + "$\\omega_{I}, \\omega_{D}$ are the time taken from onset until end of\n", + "infectious/death, which has to be bigger than $\\omega_{H}$, onset to\n", + "hospitalization given the nature of the disease. Therefore, we create\n", + "extra inequality constraints in addition to the box constraints" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d928c542", + "metadata": {}, + "outputs": [], + "source": [ + "boxBounds = [(0.001, 100.), #beta_I \n", + " (0.001, 100.), # beta_H\n", + " (0.001, 100.), # beta_F \n", + " (0.001, 100.), # omega_I \n", + " (0.001, 100.), # omega_D \n", + " (0.001, 100.), # omega_H \n", + " (0.001, 100.), # omega_F\n", + " (0.001, 100.), # alpha^{-1} \n", + " (0.0001, 1.), # delta \n", + " (0.0001, 1.), # theta .….: (0.001, 1000.), # kappa\n", + " (0.,218.) # intervention time \n", + " ]\n", + "\n", + "cons = ({'type': 'ineq', 'fun' : lambda x: numpy.array([x[3]-x[5], x[4]-x[5]])})" + ] + }, + { + "cell_type": "markdown", + "id": "df3e4a0a", + "metadata": {}, + "source": [ + "We can now try to find the optimal values, but because this is a\n", + "difficult problem that can take a very long time without guarantee on\n", + "the quality of solution." + ] + }, + { + "cell_type": "markdown", + "id": "e20c8987", + "metadata": {}, + "source": [ + "res = scipy.optimize.minimize(fun=objLegrand.cost, jac=objLegrand.sensitivity, \n", + " x0=theta, constraints=cons, bounds=boxBounds, method='SLSQP')\n", + "\n", + "print(res)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "b9e7a7d7", + "metadata": {}, + "source": [ + "objLegrand.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "1d0c6889", + "metadata": {}, + "source": [ + "The estimated parameters are very much unrealistic given that\n", + "a lot of them are near the boundaries. It is also known from other\n", + "sources that some of the epidemiology properties of Ebola, with\n", + "incubation period of around 2 weeks and a mortality rate of around 80\n", + "percent.\n", + "\n", + "As the estimate does not appear to provide anything sensible, we also\n", + "provide a set of values previously obtained (that looks semi-reasonable)\n", + "here plot the epidemic curve with the observations layered on top.\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "b383ece7", + "metadata": {}, + "source": [ + "theta = numpy.array([3.96915071e-02, 1.72302620e+01, 1.99749990e+01, 2.67759445e+01, \n", + " 4.99999990e+01, 5.56122691e+00, 4.99999990e+01, 8.51599523e+00, \n", + " 9.99999000e-01, 1.00000000e-06, 3.85807562e+00, 1.88385318e+00])\n", + "\n", + "print(objLegrand.cost(theta))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f9232353", + "metadata": { + "tags": [ + "hide-input" + ], + "vscode": { + "languageId": "javascript" + } + }, + "outputs": [], + "source": [ + "solution = ode.integrate(t[1::])\n", + "\n", + "f, axarr = plt.subplots(2,3)\n", + "\n", + "axarr[0,0].plot(t, solution[:,0]);\n", + "\n", + "axarr[0,0].set_title('Susceptible');\n", + "\n", + "axarr[0,1].plot(t, solution[:,1]);\n", + "\n", + "axarr[0,1].set_title('Exposed');\n", + "\n", + "axarr[0,2].plot(t, solution[:,2]);\n", + "\n", + " axarr[0,2].plot(t, y[:,0], 'r');\n", + "\n", + "axarr[0,2].set_title('Infectious');\n", + "\n", + "axarr[1,0].plot(t, solution[:,3]);\n", + "\n", + "axarr[1,0].set_title('Hospitalised');\n", + "\n", + "axarr[1,1].plot(t, solution[:,4]);\n", + "\n", + "axarr[1,1].set_title('Awaiting Burial');\n", + "\n", + "axarr[1,2].plot(t, solution[:,5]);\n", + "\n", + "axarr[1,2].plot(t, y[:,1], 'r');\n", + "\n", + "axarr[1,2].set_title('Removed');\n", + "\n", + "f.text(0.5, 0.04, 'Days from outbreak', ha='center');\n", + "\n", + "f.text(0.01, 0.5, 'Population', va='center', rotation='vertical');\n", + "\n", + "f.tight_layout();\n", + "\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/paramfit/estimate1.ipynb b/docs/notebooks/paramfit/estimate1.ipynb deleted file mode 100644 index 68946810..00000000 --- a/docs/notebooks/paramfit/estimate1.ipynb +++ /dev/null @@ -1,290 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Parameter Estimation: Example 1\n", - "\n", - "## Estimation under square loss\n", - "\n", - "To ease the estimation process when given data, a separate module\n", - "{mod}`ode_loss` has been constructed for observations coming from a single\n", - "state. We demonstrate how to do parametre fitting using two models; first, a the\n", - "SIR model, followed by the Legrand SEIHFR model from {citets}`Legrand2007` [\\[Legrand2007\\]]() used \n", - "for Ebola in the next page {doc}`.estimate2`.\n", - "\n", - "### SIR Model\n", - "\n", - "We set up an SIR model as seen previously in {doc}`.sir`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "efea520f", - "metadata": {}, - "outputs": [], - "source": [ - "from pygom import SquareLoss, common_models\n", - "\n", - "import numpy\n", - "\n", - "import scipy.integrate\n", - "\n", - "import matplotlib.pyplot\n", - "\n", - "# define the parameters\n", - "paramEval = [('beta',0.5), ('gamma',1.0/3.0)]" - ] - }, - { - "cell_type": "markdown", - "id": "fbfac95a", - "metadata": {}, - "source": [ - "Initialize the model using the preloaded common model {obj}`.SIR`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f09342a5", - "metadata": {}, - "outputs": [], - "source": [ - "ode = common_models.SIR(paramEval)" - ] - }, - { - "cell_type": "markdown", - "id": "3fb03842", - "metadata": {}, - "source": [ - "We assume that we have perfect information about the $R$\n", - "compartment." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2cb19871", - "metadata": {}, - "outputs": [], - "source": [ - "x0 = [1, 1.27e-6, 0]\n", - "\n", - "# time, including the initial time t0 at t=0\n", - "\n", - "t = numpy.linspace(0, 150, 1000)\n", - "\n", - "# determine the solution.\n", - "\n", - "solution = scipy.integrate.odeint(ode.ode, x0, t)\n", - "\n", - "#TODO why use scipy?\n", - "\n", - "y = solution[:,1:3].copy()" - ] - }, - { - "cell_type": "markdown", - "id": "2a5c30e7", - "metadata": {}, - "source": [ - "\n", - "Initialize the class with some initial guess\n" - ] - }, - { - "cell_type": "markdown", - "id": "857371e4", - "metadata": {}, - "source": [ - "# our initial guess\n", - "\n", - "theta = [0.2, 0.2]\n", - "\n", - "objSIR = SquareLoss(theta, ode, x0, t[0], t[1::], y[1::,:], ['I','R'])\n" - ] - }, - { - "cell_type": "markdown", - "id": "cabcb9ba", - "metadata": {}, - "source": [ - "\n", - "Note that we need to provide the initial values, $x_{0}$ and $t_{0}$\n", - "differently to the observations $y$ and the corresponding time $t$.\n", - "Additionally, the state which the observation lines needs to be\n", - "specified. Either a single state, or multiple states are allowed, as\n", - "seen above.\n" - ] - }, - { - "cell_type": "markdown", - "id": "140a5020", - "metadata": {}, - "source": [ - "\n", - "### Difference in gradient\n", - "\n", - "We have provided two different ways of obtaining the gradient, these are\n", - "explained in {doc}`.gradient` in a bit more detail. First, lets see how\n", - "similar the outputs of the two methods are." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "de043dc5", - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "objSIR.sensitivity()\n", - "\n", - "objSIR.adjoint()\n" - ] - }, - { - "cell_type": "markdown", - "id": "c47c6356", - "metadata": {}, - "source": [ - "\n", - "and the time required to obtain the gradient for the SIR model under\n", - "$\\theta = (0.2,0.2)$, previously entered.\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "c74c5449", - "metadata": {}, - "source": [ - "%timeit objSIR.sensitivity()\n" - ] - }, - { - "cell_type": "markdown", - "id": "20856aa8", - "metadata": {}, - "source": [ - "%timeit objSIR.adjoint()" - ] - }, - { - "cell_type": "markdown", - "id": "3a86770d", - "metadata": {}, - "source": [ - "The amount of time taken for both method is dependent on the\n", - "number of observations as well as the number of states. The effect on\n", - "the adjoint method as the number of observations differs can be quite\n", - "evident. This is because the adjoint method is under a discretization\n", - "which loops in Python where as the forward sensitivity equations are\n", - "solved via an integration. As the number of observation gets\n", - "larger, the affect of the Python loop becomes more obvious.\n", - "\n", - "The difference in gradient is larger when there are less observations. This\n", - "is because the adjoint method use interpolations on the output of the\n", - "ode between each consecutive time points. Given solutions over the same\n", - "length of time, fewer discretizations leads to a less accurate\n", - "interpolation. Note that the interpolation is currently performed using a\n", - "univariate spline, due to the limitation of Python packages. Ideally,\n", - "one would prefer to use an (adaptive) Hermite or Chebyshev\n", - "interpolation. \n", - "\n", - "#TODO add refs\n", - "\n", - "Note how we ran the two gradient functions once before\n", - "timing it, that is because we only find the properties (Jacobian,\n", - "gradient) of the ODEs during runtime.\n" - ] - }, - { - "cell_type": "markdown", - "id": "543ec840", - "metadata": {}, - "source": [ - "\n", - "### Optimized result\n", - "\n", - "Then standard optimization procedures with some suitable initial guess\n", - "should yield the correct result. It is important to set the boundaries\n", - "for compartmental models as we know that all the parameters are strictly\n", - "positive. We put a less restrictive inequality here for demonstration\n", - "purpose.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ff093f77", - "metadata": {}, - "outputs": [], - "source": [ - "# what we think the bounds are\n", - "\n", - "boxBounds = [(0.0,2.0),(0.0,2.0)]" - ] - }, - { - "cell_type": "markdown", - "id": "7590328f", - "metadata": {}, - "source": [ - "Then using the optimization routines in `scipy.optimize`, for example,\n", - "the *SLSQP* method with the gradient obtained by forward sensitivity.\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "83eca0ba", - "metadata": {}, - "outputs": [], - "source": [ - "from scipy.optimize import minimize\n", - "\n", - "res = minimize(fun=objSIR.cost, jac=objSIR.sensitivity, x0=theta, \n", - " bounds=boxBounds, method='SLSQP')\n", - "\n", - "print(res)\n" - ] - }, - { - "cell_type": "markdown", - "id": "404ddd1c", - "metadata": {}, - "source": [ - "Other methods available in `scipy.optimize.minimize` can also be used,\n", - "such as the *L-BFGS-B* and *TNC*. We can also use methods that accepts\n", - "the exact Hessian such as *trust-ncg* but that should not be necessary\n", - "most of the time.\n", - "\n", - "#TODO add doc refs for scipy" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.9.15 ('sphinx-doc')", - "language": "python", - "name": "python3" - }, - "language_info": { - "name": "python", - "version": "3.9.15" - }, - "vscode": { - "interpreter": { - "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/notebooks/paramfit/estimate2.ipynb b/docs/notebooks/paramfit/estimate2.ipynb index ce6d24f5..6027866c 100644 --- a/docs/notebooks/paramfit/estimate2.ipynb +++ b/docs/notebooks/paramfit/estimate2.ipynb @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "6826d12d", "metadata": {}, "outputs": [], @@ -59,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "1d9b4bfb", "metadata": {}, "outputs": [], @@ -70,7 +70,7 @@ "71.0, 73.0, 80.0, 86.0, 88.0, 90.0, 100.0, 102.0, 106.0, 108.0,\n", "112.0, 114.0, 117.0, 120.0, 123.0, 126.0, 129.0, 132.0, 135.0, 137.0, 140.0, 142.0, 144.0, 147.0, 149.0, 151.0, 157.0, 162.0, 167.0,\n", "169.0, 172.0, 175.0, 176.0, 181.0, 183.0, 185.0, 190.0, 193.0,\n", - "197.0, 199.0, 204.0, 206.0, 211.0, 213.0, 218.0]\n" + "197.0, 199.0, 204.0, 206.0, 211.0, 213.0, 218.0]" ] }, { @@ -84,36 +84,90 @@ "Details of the models can be found in {doc}`common_models` Defining the model\n", "as usual with an approximation of what the parameters might be, here,\n", "we choose the values to be the mid point of our feasible region (defined\n", - "by our box constraints later).\n" + "by our box constraints later).\n", + "\n", + "Let's see what the data looks like:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, + "id": "937db857", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy\n", + "population = 1175e4\n", + "y = numpy.reshape(numpy.append(numpy.array(yCase), numpy.array(yDeath)),\n", + " (len(yCase),2), 'F')#/population\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 4))\n", + "\n", + "axarr[0].scatter(t, y[:,0])\n", + "axarr[1].scatter(t, y[:,1])\n", + "axarr[0].set_yscale('log')\n", + "axarr[1].set_yscale('log')" + ] + }, + { + "cell_type": "markdown", + "id": "07b101f6", + "metadata": {}, + "source": [ + "Let's set up model" + ] + }, + { + "cell_type": "code", + "execution_count": 10, "id": "5dfa5094", "metadata": {}, "outputs": [], "source": [ - "from pygom import SquareLoss, common_models\n", + "# Define SIR model\n", + "from pygom import SimulateOde, Transition, TransitionType\n", + "stateList = ['S', 'E', 'I', 'R']\n", + "paramList = ['beta', 'alpha', 'gamma']\n", "\n", - "import numpy, scipy.optimize\n", + "transitionList = [Transition(origin='S', destination='E', equation='beta*S*I', transition_type=TransitionType.T),\n", + " Transition(origin='E', destination='I', equation='alpha*E', transition_type=TransitionType.T),\n", + " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)]\n", "\n", - "import matplotlib.pyplot as plt\n", + "ode_obj = SimulateOde(stateList, paramList, transition=transitionList)\n", "\n", "theta = numpy.array([5.0, 5.0, 5.0])\n", + "ode_obj.parameters=theta\n", "\n", - "ode = common_models.SEIR(theta)\n", - "\n", - "population = 1175e4\n", - "\n", - "y = numpy.reshape(numpy.append(numpy.array(yCase), numpy.array(yDeath)), \n", - " (len(yCase),2), 'F')/population\n", + "from pygom import SquareLoss\n", "\n", "x0 = [1., 0., 49.0/population, 29.0/population]\n", "\n", - "t0 = t[0]\n", - "\n", - "objLegrand = SquareLoss(theta, ode, x0, t0, t[1::], y[1::,:], ['I','R'], numpy.sqrt([population\\]*2))\n" + "objLegrand = SquareLoss(theta, ode_obj,\n", + " t0=t[0], x0=x0,\n", + " t=t[1::], y=y[1::,:],\n", + " state_name=['I','R'],\n", + " state_weight=numpy.sqrt(population*2)) " + ] + }, + { + "cell_type": "markdown", + "id": "fdc428cc", + "metadata": {}, + "source": [ + "Now let's param" ] }, { @@ -129,11 +183,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "fc31ee5f", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL\n", + " success: True\n", + " status: 0\n", + " fun: 9.045332633285773e-07\n", + " x: [ 4.919e+00 5.000e+00 5.079e+00]\n", + " nit: 10\n", + " jac: [ 9.551e-06 1.237e-08 -9.238e-06]\n", + " nfev: 11\n", + " njev: 11\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n" + ] + } + ], "source": [ + "import scipy.optimize\n", "\n", "boxBounds = [ (0.0,10.0), (0.0,10.0), (0.0,10.0)]\n", "\n", @@ -144,10 +216,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "d3e42fe2", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "f = plt.figure()\n", "\n", @@ -184,10 +276,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "38badab5", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 3.11038452e-09 7.85178078e-06 -3.60499243e-08]\n" + ] + } + ], "source": [ "resDE = scipy.optimize.differential_evolution(objLegrand.cost,\n", "bounds=boxBounds, polish=False, seed=20921391)\n", @@ -197,16 +297,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "9f68ff44", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "f = plt.figure()\n", "\n", "objLegrand.plot()\n", "\n", - "plt.close()\n" + "plt.close()" ] }, { @@ -225,10 +345,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "3f01c604", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "array([7.13160861e-01, 1.88609866e+03, 8.00526800e+01])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "1/resDE['x']" ] @@ -257,10 +388,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "f4797fe3", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "1.90984074647533e-08" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "objLegrand.cost([3.26106524e+00, 2.24798702e-04, 1.23660721e-02])\n", "\n", @@ -270,12 +412,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "0573ccf8", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "\n", "objLegrand.plot()" ] }, @@ -303,22 +455,67 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "fe0f36b4", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[5.0, 5.0, 5.0, 0.99999999, 0.0, 4.170212765957447e-06, 2.468085106382979e-06]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "thetaIV = theta.tolist() + x0\n", "\n", "thetaIV[3] -= 1e-8 # to make sure that the initial guess satisfies the constraints\n", "\n", - "boxBoundsIV = boxBounds + [(0.,1.), (0.,1.), (0.,1.), (0.,1.)]\n", + "thetaIV\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2a07dc02", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: Optimization terminated successfully.\n", + " success: True\n", + " fun: 6.267485095752834\n", + " x: [ 3.850e+00 2.211e-02 4.114e+00 6.482e-01\n", + " 2.643e-06 4.215e-06 1.967e-05]\n", + " nit: 99\n", + " nfev: 10500\n", + " population: [[ 3.850e+00 2.211e-02 ... 4.215e-06 1.967e-05]\n", + " [ 4.083e+00 6.271e+00 ... 8.164e-06 1.845e-05]\n", + " ...\n", + " [ 4.550e+00 7.734e+00 ... 5.920e-06 1.729e-05]\n", + " [ 4.326e+00 3.862e-03 ... 8.806e-06 1.406e-05]]\n", + " population_energies: [ 6.267e+00 6.619e+00 ... 6.721e+00 6.385e+00]\n" + ] + } + ], + "source": [ + "objLegrand = SquareLoss(theta, ode_obj,\n", + " t0=t[0], x0=x0,\n", + " t=t[1::], y=y[1::,:],\n", + " state_name=['I','R'],\n", + " state_weight=numpy.sqrt(population*2)) \n", "\n", - "objLegrand = SquareLoss(theta, ode, x0, -1, t, y, ['I','R'], numpy.sqrt([population]*2))\n", + "boxBoundsIV = boxBounds + [(0.,1.), (0.,1.), (0.,1.), (0.,1.)]\n", "\n", "resDEIV = scipy.optimize.differential_evolution(objLegrand.costIV, bounds=boxBoundsIV, polish=False, seed=20921391)\n", "\n", - "print(resDEIV)\n" + "print(resDEIV)" ] }, { @@ -344,11 +541,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "id": "4f726a4a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'delta' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[21], line 9\u001b[0m\n\u001b[0;32m 2\u001b[0m ode \u001b[38;5;241m=\u001b[39m common_models\u001b[38;5;241m.\u001b[39mLegrand_Ebola_SEIHFR()\n\u001b[0;32m 4\u001b[0m \u001b[38;5;66;03m# initial guess from the paper that studied the outbreak in Congo\u001b[39;00m\n\u001b[0;32m 6\u001b[0m theta \u001b[38;5;241m=\u001b[39m numpy\u001b[38;5;241m.\u001b[39marray([\u001b[38;5;241m0.588\u001b[39m,\u001b[38;5;241m0.794\u001b[39m,\u001b[38;5;241m7.653\u001b[39m, \u001b[38;5;66;03m# the beta \u001b[39;00m\n\u001b[0;32m 7\u001b[0m \u001b[38;5;241m10.0\u001b[39m,\u001b[38;5;241m9.6\u001b[39m,\u001b[38;5;241m5.0\u001b[39m,\u001b[38;5;241m2.0\u001b[39m, \u001b[38;5;66;03m# the omega\u001b[39;00m\n\u001b[0;32m 8\u001b[0m \u001b[38;5;241m7.0\u001b[39m,\u001b[38;5;241m0.81\u001b[39m,\u001b[38;5;241m0.80\u001b[39m, \u001b[38;5;66;03m# alpha,\u001b[39;00m\n\u001b[1;32m----> 9\u001b[0m \u001b[43mdelta\u001b[49m, \n\u001b[0;32m 10\u001b[0m theta,\n\u001b[0;32m 11\u001b[0m \u001b[38;5;241m100.\u001b[39m,\u001b[38;5;241m1.0\u001b[39m]) \u001b[38;5;66;03m# kappa,intervention time\u001b[39;00m\n\u001b[0;32m 13\u001b[0m \u001b[38;5;66;03m# initial conditions, note that we have a 0.0 at the end because the model is a non-automonous ODE which we have converted the time component out of\u001b[39;00m\n\u001b[0;32m 15\u001b[0m x0 \u001b[38;5;241m=\u001b[39m numpy\u001b[38;5;241m.\u001b[39marray([population, \u001b[38;5;241m0.0\u001b[39m, \u001b[38;5;241m49.0\u001b[39m, \u001b[38;5;241m0.0\u001b[39m, \u001b[38;5;241m0.0\u001b[39m, \u001b[38;5;241m29.0\u001b[39m, \u001b[38;5;241m0.0\u001b[39m])\u001b[38;5;241m/\u001b[39mpopulation\n", + "\u001b[1;31mNameError\u001b[0m: name 'delta' is not defined" + ] + } + ], "source": [ + "from pygom import common_models\n", "ode = common_models.Legrand_Ebola_SEIHFR()\n", "\n", "# initial guess from the paper that studied the outbreak in Congo\n", @@ -530,8 +740,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/paramfit/fh.ipynb b/docs/notebooks/paramfit/fh.ipynb index 3b30551b..254d1a26 100644 --- a/docs/notebooks/paramfit/fh.ipynb +++ b/docs/notebooks/paramfit/fh.ipynb @@ -4,77 +4,65 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Parameter Estimation: FitzHugh Example\n", + "# Parameter Estimation via hill climbing\n", "\n", - "## Defining the model\n", + "## FitzHugh-Nagumo model\n", "\n", - "We are going to investigate another classic model here, the\n", - "FitzHugh-Nagumo, or simply FitzHugh here. The model has already been\n", - "defined in {mod}`common_models` so we can load it rather than define by scratch.\n", + "Here we demonstrate parameter estimation applied to the classic model of FitzHugh-Nagumo {cite}`fitzhugh1961impulses`.\n", "\n", - "#TODO ref for FH-N" + "$$\\begin{aligned}\n", + "\\frac{dV}{dt} &= c ( V - \\frac{V^{3}}{3} + R) \\\\\n", + "\\frac{dR}{dt} &= -\\frac{1}{c}(V - a + bR).\n", + "\\end{aligned}$$\n", + "\n", + "The difficulty in inferring the correct parameters makes this is a commonly used model when developing new methodology with regards to ODEs {cite}`Ramsay2007` {cite}`Girolami2011`.\n", + "This is due to the likelihood landscape for parameters being rough (i.e. large second derivative) as well as multimodal.\n", + "\n", + "The model has been defined in {mod}`common_models` so we can load it rather than define by scratch." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "a74b67ba", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "from pygom import SquareLoss, common_models\n", - "\n", - "import numpy\n", - "\n", - "import scipy.integrate, scipy.optimize\n", - "\n", - "import math,time,copy\n", - "\n", - "import matplotlib.pyplot as plt\n", - "\n", - "x0 = \\[-1.0, 1.0\\]\n", - "\n", - "t0 = 0\n", + "from pygom import common_models\n", "\n", "# params\n", "paramEval = [('a',0.2), ('b',0.2), ('c',3.0)]\n", "\n", + "# set up ode\n", "ode = common_models.FitzHugh(paramEval)\n", "\n", - "ode.initial_values = (x0, t0)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "id": "100b72c6", - "metadata": {}, - "source": [ - "Define a set of time points and we can see how the two states $V$ and $R$\n", - "are suppose to behave.\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e8291f05", - "metadata": {}, - "outputs": [], - "source": [ - "t = numpy.linspace(1, 20, 30).astype('float64')\n", + "# set time steps\n", + "import numpy\n", + "t = numpy.linspace(0, 20, 100).astype('float64')\n", "\n", - "solution = ode.integrate(t)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d2fccb37", - "metadata": {}, - "outputs": [], - "source": [ - "ode.plot()" + "# set initial conditions\n", + "x0 = [-1.0, 1.0]\n", + "ode.initial_values = (x0, t[0])\n", + "\n", + "# solve and plot\n", + "solution = ode.integrate(t[1::])\n", + "\n", + "import matplotlib.pyplot as plt\n", + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 2.5))\n", + "\n", + "axarr[0].plot(t, solution[:,0])\n", + "axarr[1].plot(t, solution[:,1]);" ] }, { @@ -83,36 +71,55 @@ "metadata": {}, "source": [ "\n", - "## Estimate the parameters\n", + "## Estimating the parameters\n", "\n", - "Obtaining the correct parameters for the FitzHugh model is well known to\n", - "be difficult, because of its multimodal surface. Although this\n", - "has been shown many times in the literature, so we will omit the\n", - "details. For further details see {citets}'FitzHugh`.\n", + "Now we use optimisation algorithms to find the parameters by minimising the loss function.\n", "\n", - "#TODO ref?\n", - "\n", - "We will give the fitting a go with an initial guess which will enable us to recover the original parameters. First, we try the fitting process with only one target state.\n", - "\n" + "Let's assume we only know the $R$ state:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "97050c8b", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH\n", + " success: True\n", + " status: 0\n", + " fun: 1.38065348108425e-12\n", + " x: [ 2.000e-01 2.000e-01 3.000e+00]\n", + " nit: 18\n", + " jac: [ 1.479e-05 7.406e-08 9.735e-06]\n", + " nfev: 21\n", + " njev: 21\n", + " hess_inv: <3x3 LbfgsInvHessProduct with dtype=float64>\n" + ] + } + ], "source": [ - "theta = [0.5, 0.5, 0.5]\n", + "from pygom import SquareLoss\n", + "import scipy.optimize\n", "\n", - "objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,1], 'R')\n", + "theta = [0.5, 0.5, 0.5] # initial guess for params\n", "\n", - "boxBounds = [(0.0,5.0), (0.0,5.0), (0.0,5.0)]\n", + "objFH = SquareLoss(theta, # initial parameter guess\n", + " ode, # PyGOM ode object\n", + " t0=t[0], x0=x0, # initial time and conditions\n", + " t=t[1::], y=solution[1::,1], # time steps and solution\n", + " state_name='R') # name of param in solution\n", "\n", - "res = scipy.optimize.minimize(fun=objFH.cost, jac=objFH.sensitivity, \n", - " x0=theta, bounds=boxBounds,\n", - " method='L-BFGS-B')\n", + "boxBounds = [(0.0,5.0), (0.0,5.0), (0.0,5.0)] # min and max parameter estimate bounds\n", "\n", + "res = scipy.optimize.minimize(fun=objFH.cost,\n", + " jac=objFH.sensitivity, \n", + " x0=theta,\n", + " bounds=boxBounds,\n", + " method='L-BFGS-B')\n", "print(res)" ] }, @@ -121,31 +128,7 @@ "id": "f2cbc5b1", "metadata": {}, "source": [ - "Then we try the same again but with both states as our target. " - ] - }, - { - "cell_type": "markdown", - "id": "fa53fd4a", - "metadata": {}, - "source": [ - "objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,:], ['V','R'])\n", - "\n", - "res = scipy.optimize.minimize(fun=objFH.cost, jac=objFH.sensitivity, x0=theta,\n", - " bounds=boxBounds, method='L-BFGS-B')\n", - "print(res)\n" - ] - }, - { - "cell_type": "markdown", - "id": "d94fcdab", - "metadata": {}, - "source": [ - "\n", - "Note how the estimates are the same, unlike other models.\n", - "\n", - "#TODO why is this?\n", - "\n" + "We see this is a good fit." ] }, { @@ -155,23 +138,42 @@ "source": [ "## Estimating initial value\n", "\n", - "We can further assume that we have no idea about the initial values for\n", - "$V$ and $R$ as well. We also provide a guesstimate to set off the\n", - "optimization. The input vector $\\theta$ must have the parameters first,\n", - "then the initial values, along with the corresponding bounds.\n", + "We can extend this example to the case where the initial values of $V$ and $R$ are unknown.\n", + "We also provide a guesstimate to set off the optimization.\n", + "The input vector $\\theta$ must have the parameters first, then the initial values, along with the corresponding bounds.\n", + "We must also use the `costIV` and `sensitibityIV` options to let the solver know Initial Values.\n", "\n", - "First, only a single target state, i.e. we only have observations for\n", - "one of states which is $R$ in this case" + "First, only a single target state, i.e. we only have observations for one of states which is $R$ in this case" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "138e3689", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH\n", + " success: True\n", + " status: 0\n", + " fun: 0.7339990203493604\n", + " x: [ 0.000e+00 6.052e-01 8.512e-01 -7.159e-01 9.061e-01]\n", + " nit: 20\n", + " jac: [ 4.341e+00 3.166e-04 -2.071e-04 -1.664e-05 -5.012e-05]\n", + " nfev: 25\n", + " njev: 25\n", + " hess_inv: <5x5 LbfgsInvHessProduct with dtype=float64>\n" + ] + } + ], "source": [ - "objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,1], 'R')\n", + "objFH = SquareLoss(theta, ode,\n", + " t0=t[0], x0=x0,\n", + " t=t[1::], y=solution[1::,1],\n", + " state_name='R')\n", "\n", "boxBounds = [(0.0,5.0), \n", " (0.0,5.0),\n", @@ -181,30 +183,105 @@ "\n", "res = scipy.optimize.minimize(fun=objFH.costIV,\n", " jac=objFH.sensitivityIV,\n", - " x0=theta + [-0.5,0.5],\n", + " x0=theta + [-1.0,1.0],\n", " bounds=boxBounds, \n", " method='L-BFGS-B')\n", - "\n", "print(res)" ] }, { "cell_type": "markdown", - "id": "af2b3afa", + "id": "636b28df", "metadata": {}, "source": [ + "We see not so good from values and also when we plot: We fit well to the data which we know." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "a515c219", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA/MAAAEFCAYAAACvqLeOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAC1eElEQVR4nOzdd3hUZfbA8e+dmfRKekhC6L333qUjiCI27O7a1r7uuu666urPLeqqa6+o2KVKE5TeIRA6oZNOem9T7u+PdyYUA6TMzJ2ZvJ/nycNkksycwGXmnvue9xxFVVUVSZIkSZIkSZIkSZLchk7rACRJkiRJkiRJkiRJahiZzEuSJEmSJEmSJEmSm5HJvCRJkiRJkiRJkiS5GZnMS5IkSZIkSZIkSZKbkcm8JEmSJEmSJEmSJLkZmcxLkiRJkiRJkiRJkpuRybwkSZIkSZIkSZIkuRmD1gFcicViITMzk6CgIBRF0TocSZIkSdKUqqqUlpbSsmVLdDrPuR4v3+8lSZIk6bz6vt+7dDKfmZlJQkKC1mFIkiRJkktJS0sjPj5e6zDsRr7fS5IkSdJvXe393qWT+aCgIED8EsHBwRpHI0mSJEnaKikpISEhofb90VPI93tJkiRJOq++7/cunczbSu2Cg4Plm7skSZIkWXlaKbp8v5ckSZKk37ra+73nbLiTJEmSJEmSJEmSpGZCJvOSJEmSJEmSJEmS5GZkMi9JkiRJkiRJkiRJbkYm85IkSZIkSZIkSZLkZmQyL0mSJEmSJEmSJEluxqHJ/CuvvMKAAQMICgoiKiqKmTNnkpKS4sinlCRJkiRJkiRJkiSP59DRdBs2bOChhx5iwIABmEwmnn32WSZMmMDhw4cJCAhw5FNrpspo5k8L9pNdXEV0sC9RQT5EBfvQNTaEoe3C0ek8a5yQ1LypqsrpvHLiWvjhY9BrHY4kSVKDVBnN7DlbyPbTBew5W0i/xBY8Oq6DfK+WJEmS3IJDk/lVq1Zd9Plnn31GVFQUSUlJjBw50pFPrZkfk9JZkpxZ59faRwVyz/A2XNcnDl8vmfhI7u/5pYf4fNtZvPU6esSH0D+xBX0TWzCyQyR+3vIYl9zb+pQc9pwtJKu4iuySKrKLqwjx8+LGAQlc26ulfB13Yydyyvj70oPsOl1IjdlSe//mE3lkFFXyz1k9MOjlTkRJkiTJtTk0mb9UcXExAGFhYXV+vbq6murq6trPS0pKnBKXvZjMFj7ceAqA2wa3onV4ADml1WQVV7H+aA4ncsp4ZuEBXv05hdsGJ3L3sDaE+HtpHLUkNc7CPel8vu0sADVmC0lnC0k6WwhAWIA3dw5tze1DEgn199YyTElqlBM5Zdz52a46v7b7bCEvLz/Cjf3juW1wIonhnllp5qkOZhRz+6c7KSivASA62IchbcOJDfXjw42n+DEpnZJKI2/d3EdesJEkSZJcmqKqquqMJ1JVlRkzZlBYWMimTZvq/J7nn3+eF1544Tf3FxcXExwc7OgQm2zpvkwe+WYvYQHebPnT2ItWJkurjHy3K43Ptpwho6gSgCAfA3cPb8Pdw9sQ4ieTesl9HM0uYeY7W6gyWnhkXAdm9YljtzWZ33gst/YY9/fWc8vAVtw7oi0xIb4aRy1J9fe/X4/z2ppjdIgKZEbvlsSE+BET7MvBzGLmbz9LeqE4xnUKXNurJX8Y14F2kYEOj6ukpISQkBC3eV+sL2f9XjtPF3DPvF2UVpvoERfCGzf1pm1EAIoiyurXHD7HQ1/vocZkYUjbcD68vR9BvvL9WZIkSXKu+r4vOi2Zf+ihh1i+fDmbN28mPj6+zu+pa2U+ISHBLU5aVFVlylubOZJVwhPXdOSRcR3q/D6T2cLKg9m8s+4ER7NLAQj2NXDviLbcPbwNgT5OLZaQpAYrrTJy7dtbOJ1XzsiOkXx25wD0F+wvNZktrDiYzXvrT3IkS1TXeBt03DYokQdGtyMyyEer0CWp3qb9bxMHM0r41/U9mDOg1UVfM1tUNhzL4fOtZ9lwLBcQSf2M3nE8PLa9Q5N6mcw33rqjOdw/P4lqk4WBbcL45I7+dSbq207mc98XuymrNtG3VSg/3j9U7qGXJEmSnMqlkvk//OEPLF68mI0bN9KmTZt6/5w7nbSsT8nhzs924e+tZ+ufx161tNhiUVl5MJs3fjnG8ZwyQJQmPzi6HbcNTpSlfZJLUlWVB+bvYdWhbFqG+LLskRGEBdR9rKuqyoZjubyz7gS7zojyez8vPXcMbc3vR7alxWV+TpK0llZQwYh/r0OnwK5nxxMeePkLUAczinnz1+OsOXwOEEn9rL7xPDquAwlh/naPzZ3eFxvC0b/X2qPn+N0XSZgsKmM7R/HurX2v+D57IL2Ymz/aTlm1ic/uHMCYzlF2j0mSnOVcSRVbTuRhsqioqorZAmEBXozvEi17Q0ge41xJFYv2ZrB8fxbtIgP467SuRFzh/dvVuUQyr6oqf/jDH1i0aBHr16+nQ4e6V6svx51OWuZ8sI0dpwu4d3gb/jqta71/zmxRWbY/kzd/Oc6pvHIAYkN8eXRcB27oFy9fZCWX8vnWM/x96SG89Ao/3D+U3gmhV/0ZVVXZdDyP19YcY19aESC2mPx+lKhG8feW1SiSa/lk82n+sewwA9uE8f3vh9TrZw5mFPPGL8f45UgOAF56hVsHJfLQmPZ2rUZxp/fFhnDk75VZVMnkNzdRXGlkeq+WvH5jL7zq8d76j2WH+WTzacZ0iuSzuwbaNSZJcpafD2Xz1A/7KK0y/eZr1/WJ4/Ube9VuM5Ekd6OqKqsOZvPd7jQ2HsvFckFWGxbgzYszujG1R6xbHuP1fV90aKb40EMPMX/+fL7++muCgoLIzs4mOzubyspKRz6t0yWdLWTH6QK89Ar3jKh/5QGAXqcwo3ccqx8fyb+v70nLEF+yiqv488IDTPjvRlYdzMJJOyEk6aoW7kkH4OmJneuVyAMoisLIjpEsfnAoH9/eny6xwZRWm3h19TFG/ns9X2w7Q43JcvUHkiQn+flQNgCTusXU+2e6x4Xw8R0DWPzQMIa1D8doVpm39Qwj/72ON3455qhQpaswW1Qe+zaZ4kojPeNDeG12/RJ5gNsGJwKw/lguZ/PLHRmmJNmd0Wzh5eWH+f2XSZRWmWgfFciYTpGM6xzF+C5R6HUKi/ZmMG/rGa1DlaRGsVhUnl18kAe+2sP6FJHI909swd+mdaVzTBAF5TU8/PVeHvxqD7ml1Vd/QDfl0GT+vffeo7i4mNGjRxMbG1v78d133znyaZ3u/Q0nAZjZO47YEL9GPYZBr+PGAQmsfWo0z03rSliAN6fyyrl//h6ue3cr20/l2zNkSWqUM/kVAIzoGNHgn1UUhfFdo1n+h+G8eVNvWoX5k1dWzXNLDjH+9Q38tC9TXriSNJdXVs2uMwUATOgW3eCf750Qylf3DuarewfRKyGUSqO5tmu6O9i4cSPTp0+nZcuWKIrC4sWLr/ozGzZsoF+/fvj6+tK2bVvef/99xwdaT2+vPcHOMwUEeOt566Y+eBvqf9rTJiKAUR0jUVWYv/2sA6OUJPvKKq7k5g+389Gm0wDcO7wNKx8dwWd3DeSTOwfw8R0DeGZyZwBeWn6EHfIcU3IzZovKnxbs5+sdqSgK/H5UW9Y9NZofHxjKPcPbsPTh4Tw6rgMGncLKg9nMfGcL5dW/rU7xBA5N5lVVrfPjzjvvdOTTOtXJ3DLWHD5XeyA1la+XnruHt2HDH0fzyLgO+HvrSU4r4qYPt3P3vF0cP1dqh6glqeGKK4wUVxoBSGjR+L3AOms1yi9PjOIfM7oREehDakEFf/hmLzPf2SIvXEma+uXwOVQVesSFEN+E43xY+wgWPziUD+f24+Gx7e0YoWOVl5fTq1cv3n777Xp9/+nTp5kyZQojRoxg7969/OUvf+GRRx5hwYIFDo706nafKeDNX0VVxD9mdqd1RMNHCN4+RKzOf787ncoas13jkyRHyCmpYta7W9l9tpAgXwPv39aPv07r+puKlHuGt2FG75aYLSoPfb2HrGLPqpqVPJfJbOHJ75P5ISkdnQJvzOnNM5O70OaC13hvg47Hr+nIkoeH0TLEl4yiSr7Zmaph1I4jN2Q30W7rCs7gNuG0jwqy2+MG+XrxxDUdWf/H0cwdnIhBp7D2aA4T39jIMwsPkFNaZbfnkqT6SC0Qq/IRgT4E2GHqgrdBx9whrdnwx9E8Pr4j/t569qUXc9OH27ln3i5O5MgLV5Lz2UrsJzZiVf5SiqIwoVsMUUHuM5Zx8uTJvPTSS8yaNate3//+++/TqlUr3njjDbp06cK9997L3XffzauvvurgSK+suMLIo98mY1HFvuBZfeueonM1oztFEd/Cj+JKI0v3Zdg5Skmyryqjmd99mURWcRVtIwNY9ofhTOpe93YhRVH456yedIkNJq+shvvn76HaJC9YSa7NaLbw2HfJLE7ORK9T+N/NfZnRO+6y39+tZUjthLGPNp3yyGNcJvNNlF0s9mC0jrB/12KAqCBf/jGzO6sfH8nEbtFYVPhmZyqj/7Oet349LlcKJKc5WyD2jCaG2/dYD/Ax8Oj4Dmz44xhuG9wKvU7h16M5THxjE88tOehWJcqSeyutMrLlhKgMmdiA/fLN2bZt25gwYcJF902cOJHdu3djNBov+3PV1dWUlJRc9GEvqqryzKL9ZBRVkhjuz4szujX6sfQ6hbnWvfOfbz0rtwJJLktVVZ5ddJDktCJC/Lz49I4BJIZfuRrFz1vPB7f1I8TPi31pRbz163EnRStJjfPSssMs25+Fl17h3Vv7MrVn7FV/5rq+ccQE+3KupJpFezzvoqxM5psou0SUJUUHO3blpW1kIB/M7c8P9w+hV0IoFTVmXl9zjHGvrWdJcoY8wZAc7qx1v3yiA8ZtAUQG+fDSzB6sfnwk47tEY7aofLHtLKP+s44PN570yKupkmtZl5JLjdlC28gA2kc5bla8J8nOziY6+uIqhujoaEwmE3l5eZf9uVdeeYWQkJDaj4SEBLvFZDSr+HsbMOgU3rqpT52z5Bvixv4J+Bh0HM4qYU9qoZ2ilCT7+mTzaRbsSUevE0lOfbeVtAr35/+u6wHANzvTZENayWX9fCibz7eJ/iVv39K33hfdfQx67rU2KH9vw0lMZs86xmUy30TZxaLcPTbEOWWUA1qHsfjBobx1cx/iQv3ILK7i0W+Tuf69reyVJxmSA6Vak3lHzM6+ULvIQD6+oz9f3zuIrrHBlFaZ+L8VR5n4343W/czywpXkGOdL7GPccoyNVi79u7L9H73S3+EzzzxDcXFx7UdaWprd4vE26Hh1di9WPTaSXvWcunElLQK8ubZXSwC+2CYb4UmuZ11KDv+34ggAf5vahWHtG9akdmK3aKKCfCgor+HXI+ccEaIkNUlGUSVP/7gfgN+NbNvg6rmbB7aihb8XZ/MrWHEw2xEhakYm802UZU3mHb0yfyFFUbi2V0t+fXIUT00Qe433pBZx3btbeeqHfR49fkHSjm3PvL3L7C9naPsIfvrDcP59fU8ig3w4k1/BvV/s5vZPd8pGkJLdVRnNrD8qZsTLEvv6i4mJITv74hOjnJwcDAYD4eHhl/05Hx8fgoODL/qwN3tWV9w+pDUAKw5kkVcm32Ml15FZVMkj3+zFosJNAxK4Y2jrBj+GQa/jhn6ir8R3u+13YU2S7MFktvDoN3sprjTSKz6EpyZ0avBjBPgYuHOoWJ1/d90Jj1oYksl8E50rsa3MN24kXVP4eul5eGwH1j01uvZF+MekdMa+up6PN53C6GFlJJK2nJ3Mg9iveuOABNY9NZr7R7XDW69j0/E8Jr25iX8sO0xp1eX35EpSQ+w6U0B5jZmYYF96xoVoHY7bGDJkCGvWrLnovtWrV9O/f3+8vJpW3u5QqgqFZ6CiQNy+ih7xIfSMD8FoVlnlYas6kvtSVZW/LDpAaZWJ3gmhvDije6Orim7sL7a6bDyWKzvbSy7lrV+Pi+kMPgb+d3PfBo0YvdAdQxMJ8NZzNLuUdSk5do5SOzKZb4Iqo5nCCpFMxDhxZf5S0cG+vDq7F4seHEqv+BBKq028tPwIk9/cxNYTl9+zKEn1VW0yk2l9c28V1vDxTk0V6GPgz5M7X7Sf/pPNpxn72gYW75U9I6SmSy8Ux3e3lsHodM23xL6srIzk5GSSk5MBMXouOTmZ1FQx0ueZZ57h9ttvr/3++++/n7Nnz/LEE09w5MgRPv30Uz755BOeeuopLcK/ssoiOLQYljwMr3eFN3vBv9vAKwnw3nD49lZImgfmui8STukhGi2tPJjltJAl6UqWJGeyPiUXb72OV2f3bHSSA9A6IoBBbcKwqPDj7nQ7RilJjbf1ZB7/W3cCgJdn9aBVExaUQv29udXa0PSddSc95tyx6fOlmjHbqryfl55gP+3/Kvu0asGiB4fxY1I6/1p1lBM5Zdzy8Q5m9G7Js1O6EKXhBQfJvaUXVqKq4O+tJyLQW7M4WkcE8PEd/VmfksPzSw9xJr+Cx75L5uudqfxjRnc6xdhvPKTUvOSUiNLpqGAfjSPR1u7duxkzZkzt50888QQAd9xxB/PmzSMrK6s2sQdo06YNK1as4PHHH+edd96hZcuWvPXWW1x//fVOj/2yTDWw7iXY9g5YTOfv13mBxQg1pXDugPg4ugy2vAVj/wpdZ4LufHI0uXsM/1x5lO2nCigoryEsQLvXQknKK6vmhZ8OAfDIuPZiPLKqwtmtsOsjOHdIXJiymMSfPkHQfRb0vgVatK7zMecMSGDH6QK+253GQ2PaN+sLm5L2qoxm/rRgP6oKc/on1PYuwWKBgpOQtU985B2DoFiI7w9x/SCiI+j0dT7mvcPbMG/LGZLOFrIvvZjeduirojXtM1A3ZtsvHxPi6zLNknTWsuSJ3WN4bXUKX24/y5LkTNYeyeHJCR2ZO6Q1evniLDWQrfldqzB/lzjWR3eK4ufHw/lo4yneXneCnacLmPrWJu4b2ZZHxnbAz7vuF3FJupycUvF6HulGM+EdYfTo0VdcrZg3b95v7hs1ahR79uxxYFRNkJsCC+6FbNE4iYiO0H68+EgcBqhQlCZK7s8dgO3viZPEH++C2Ddh4svQejgAieEBdGsZzKHMEtYczmbOgFaa/VqS9PzSQxRWGOkSG8zvh8XB3vmw433IPlD3D5Rlw4Z/iY/WI6Dv7dBtFujPpwKTu8fy9yWHSC+sZNup/AY30pMke3p3/UnSCiqJCfblb9O7grESNr0ujvPqOsaZJn0m/vQOgi7TYfzzEHTxtJWoYF8mdY9h6b5MftqX6RHJvCyzbwLbyryWJfaXE+LnxYszurP0oeG1pffP/3SY697dwqHMYq3Dk9yMbb98Kwd3sm8IH4PoGfHLE6O4pms0JovKe+tPMuGNDaz3oL1QknPkWBuHRgY175V5j6GqsPMj+GCkSOT9wmDOfHh4F0x6BdqPAy9f8PKDyI7QcQKMeBIe2Quj/wLegZCVDJ9Phz1f1D6srdR+xQG5b17SzupD2Szbn4Vep/C/UeD1zgBY8pBI5A2+0PcOmLsI7v4Z7l0Lv98I138CbccACpzZBAvvgy9nQtn590s/bz0z+ojVz+92yUZ4knbO5JXz/oaTADw3vSuBZ36BdwbBxn+LRN7gB3H9of89MOVVGPoIJA4HrwBRbbXva3i7P2x/H8ymix57mnU2/fL9WVgs7l9qL1fmm+DClXlX1SM+hIUPDuPrnan8e9VR9qcXc+3bW7h3RBseG9dRrmBK9VI7Y96Jze/qK76FPx/d3p/Vh7L5+9JDpBVUcudnu5jWM5bnr+1GRKBMzqSrsyXzUTKZd3+mGvh+LhxbJT5vNxZmvAvBsVf/WZ8gGP0nGHAP/PwX2P8dLP0DVBbCsEeZ3D2G//ycwpYTeRRXGAnxd+Emf5JHKqky8rclBwH4d7c02i9/HowVEBwHA+8Tibx/2G9/MLYX9LhBVKIkfw1b3xJJ/fsjYPY8SBwCwJz+rZi/PZVVh7LlMS5pQlVVnlt6iBqThWvbqEw++DikrBRfDI6Dif8HnaddVFVSy2KGtJ3i9TtzD6z6EyTPh6n/hYQBAIzsGEmQj4Hskir2pBbSv3Ud/1/ciFyZb4JsN0jmQXQEnzs4kV+fGMWUHjGYLSofbDjFxDc2ygZ5Ur2kFpQD0Crc+c3v6mtCtxjWPDGKe4a3QafAsv1ZXPO6bJAn1U+eTOY9h8EbAiJB7wOT/gm3LqhfIn+hgAi47gMY9pj4fM1zsOY52kYE0DkmCJNFZY2cxy1p4J21JzhXUsXTwWuYdfxPIpFvNw4e3AbDH687kb9QaIK4YHXfOojsLMrv502FrW+DqtI9LpguscHUmCwsTs5wzi8lSRdYdTCbjcdyaa3P57WyP6GkrASdAYY9Cg/thG4z607kQeyVTxwC9/4C0/4LvqGiYuWzyXDkJ0BMA7umqyi/X7bf/RuaymS+CWqTeRcss69LVLAv797aj49u709siC+pBRXc8vEO/rr4AGXVpqs/gNRsnc13vTL7ugT6GPjbtK4seWg4XWKDKaww8th3ydzz+W4yi+SoHaluqqqSa0vm3eT1XLqKSf+E362HwQ9c1MSuQRQFrnkBrnlRfL7lTfjpESZ1iwJg5QH3PwmU3EtaQQWfbznF/xk+4cGaz1BQRZnxLd+DbwNHakZ2hHt/he43gGqG1c/CiqdQgDn9z487liRnKq828eKyw8SQz+LAf+JVmg5h7eD+LeK12Cewfg+k00P/u+EPSWL/vMUIP9wpJpoA03pZS+0PZGF281J7mcw3QXaJe6zMX+qartGsfnwktw0WzXvmb09l4n83svm4XKWXfstiUc/PmHfxZN6mR3wISx8expPXdMRbr2Pt0Rwm/ncj3+9Ok6v00m8UVRipMVsANJ3WINmRTyBEd7XPYw17FK59GxQd7PmC24wLANh0PI/SqrrH2EmSI/xr1VEeU77hFsNaVBRx0Wrqa5dfpbwan0C4/mOY/B9AgV0fw5Y3md6rJToFDmQUk2Z9/5ckZ/jf2hOYi7P4we//CK3OgBZt4M5lENW5cQ8YEAE3zIOec8Rkhx/vhgM/Mrx9JCF+XuSWVrPrTIFdfwdnk8l8E7jbyvyFgny9eGlmD76+dxDxLfzIKKrktk928OyiA1TUyFV66bzcsmqqTRb0OoW4Fn5ah1NvXnodfxjXgeWPDKdPq1BKq008/eN+7vsiqXYVVpLg/H75UH8vfAyyj4hUh75zYfqbAITv/A+zWxynxmxh7VHZbFNyjj2phVgOLuJ+gygVVmZ9JCpPmjphRlFg0O9EY0iAX/5O+OmfGNw2HICVB2UFiuQc6YUVLNm8l6+9XyZBzYLQVnDHTxDcsmkPrDfAzPeg962iCmXhfXgf+oGJ3Wyl9pl2iF47MplvJJPZQm6ZOAGMdbOV+QsNbR/Bz4+N5PYhiQB8tSOVqW9tJjmtSNvAJJdhK7FvGeqLl979XjI6RAfx4/1DeXpSJ7z0Cr8cOcfENzbKElmpVq7cLy/VR9/boc9cFFReMP6XGPJZIV9HJCdQVZV5i1fxH68PxB1D/wA9Z9v3SQY/AIMfFLcXP8AdcWK/vJzcIDnL/1Yf5gP9v2ivy0QNjheJfGiCfR5cpxcVVn1vB9UCi37PbZGnAFh5IBuTtTrPHbnfmbmLyCurwWxR0esUwt28W3aAj4EXZ3Rn/j2DiAn25XReOde/t5U3fznu1ge3ZB9n863N79ykxL4uep3Cg6Pbs/RhsZe+oLyGB77aw1M/7KNc9oto9mwz5qOa+Yx5qR6m/AdieuJvKuJd7zfZkpIlX0Mkh1u95ziP5r1AgFJNTcIwGPe8Y55owktif7G5hmv2PU57XQbJaUVkyJ4zkoMdO1dK4oE36ak7jcmnBcodS6FFa/s+iU4H096EXrcAKj12/pH2fmXkl9ew/ZT7ltrLZL6RbPvlo4N80OuaWOLkIoZ3iGDVYyOY1jMWs0Xlv78c48YPtpFeKPdLNWfnZ8y7bif7+uoSG8ySh4bx0Jh26BTR3Gfa/zZzMKNY69AkDckZ81K9efnBjV+g+obQV3eCJ/mSdSmy1F5ynGqjEf8VD9FOl0WJTzTeN33R+D3yV6PTw6yPIH4AuupiPvd7Ex9qWHVQrs5LjrV4yY/8Xi+2kBhmvAXh7RzzRDodTHsdorqhlOfyfsAH6LCw/ID7ltrLZL6RsovFVcpoNy6xr0uovzdv39KXN2/qTZCvgT2pRUx9azOrD8kX8ubKlWfMN4a3QccfJ3bm6/sGExsiKlGue3cLH208hcXNO5pKjZNTIsvspQYIa4Ny3YcA3GX4mYztCzQOSPJke374DyPMO6nBgPfN80VDL0fy8oObv4XAGOLM6Txh+EFuS5McKvlEKjenv4xeUSnpfCN0vdaxT+jlB7PngZc/7cuSeEi/mJUHszG6aTWyTOYbydb8zp33y1/JjN5xrHhkBL0SQimuNPK7L5N44adDVJvMWocmOZm7dbKvr8Ftw1n56AgmdovGaFZ5ecUR7v1iN8UVsjt1c2PrfyJX5qV66zSJnB6/A2BaxptUlZdoHJDkiaoKM+lx7H8A7O/6NL6tBzrniQMiYPobANyrX4EldUftea8k2ZOqqhQueJIEXS4FXjEEz3zNOU8c2RGmvg7AY14L6VS5ny0n3HOql0zmGynLVmbvhp3s6yshzJ8ffj+E+0a0AeCzLWeY/f42uXeqmakts/eQlfkLhfp78/5t/XhpZne8DWKE3bS3N8my+2Ymx/p6LmfMSw0ROf15sogkTskl66eXtA5H8kBp3/+RQCo4orSn58wnnPvknSZDz5vQKyr/8fqAX/afce7zS83C4bVfMaZyNRZVwTzzffANdt6T974Zet+KHgtver/Nxr1HnPfcdiST+UY65+Er8zbeBh3PTu3KJ3f0J9Tfi/3pxUz/32a2nnTPq1dSw5RWGSkorwHcuwHelSiKwm2DE1n4wFASwvxIK6hk1ntb+W5XqtahSU5i62Yf6ebNTCXnUrwDWN/2SQASUj6B3GMaRyR5kupTW+iQtQyAtCEv4u3t5fwgJv+Tcu8I2umyCN7+b+c/v+TR1MpC4jc/A8C22NuI7DbG+UFM+Q8VIe2JUQrpefS/btn4WybzjZRV7Pkr8xca1yWaZX8YTvc40Ql87ic7+WTzaVRV7jH2ZLb98mEB3gT5anAi4UTd40JY9vAIxnWOosZk4U8LDvDMwv3UmNzvhV1qGFsDvKhgmcxLDdNm2Gx+NffBoJqwLH8S5HuiZA8WM2ULHwPgJ/14Ro+drE0cfi2onChKkaeWLaQwZbM2cUge6cyS/yNELeGkGkeXW/6pTRDeAXjPeheAmazj8M5ftYmjCWQy30jnSmwr834aR+I88S38+fH+oVzXJw6zReUfyw7z+HfJVBnlPnpPdb6TvWeuyl8qxN+Lj27vzx8ndkJR4Judadz+6Q4KrdUJkuepqDFRZh0tJhvgSQ01oE04b3rdS5Xqhe7MRjgom+FJTWfc8THhZccoVv0xjv4b3gbtTtcj+s1grc849IqKbunDYJZ9ZaSmU4vSaHl0HgB7Oz1OWHCgZrEYEgexK3QKAOEbnwWLe+U1MplvBFVVa1fmY5rJyryNr5ee12/sxd+nd0WvU1icnMmtH++oLcWWPEtt8zsP3C9/OTqdwkNj2vPJHf0J8Naz/VQBM9/dwomcMq1DkxzAVmLv56Un0MdB454kj6XXKXTr3pN3TDPEHT8/C1WyGZ7UBOV5WH79BwAfed3GtCE9NQ4Izgz4G3lqMCHlp2HP51qHI3mAnKV/x4cadqpdGDVtrtbhUDP6b5SofsRVpmDZ86XW4TSITOYbobjSSLW19LY5lmUqisJdw9rw5T0DCfY1kHS2kFnvbuF0XrnWoUl2Ziuzby4r8xca2zmahQ8OI76FH2fzK7ju3S1sPJardViSnV1YYq8oisbRSO5oUvdYPjRPI5UYKMuGTU7qxix5JNOvL+NjKuWQJZH4ax7UdFXeZlyfjrxpmgWAZd0/obpU44gkt5Z9kMhTCwHY1/lJIl1gYXRA9868q8wBwLzmeago0DagBtD+FcIN2VblwwK88fXSaxyNdoa2i2Dhg0OJb+HHmfwKZr27hd1n3Ofgl64utUBcoGmOyTxAp5ggFj80jP6JLSitMnH3vF0sSc7QOizJjmwz5mXzO6mxhrQNx9vXnxdrbhV37PwQyuSFP6kRSjJR9opVwXd972VWv0SNAxISwwPYFzWT05ZodBW5sPVtrUOS3FjxT39Bh8oKyyCmTp6mdTiAaPid13kuRy0JeFUXwrqXtQ6p3mQy3wjZzWAsXX21jwpi0YPD6BUfQmGFkVs+3sHPh7K1Dkuyk/Nl9gEaR6KdiEAfvrpvENN7tcRkUXn022TmbTmtdViSneSU2sbSyWReahxvg47xXaL5xdKXTP8uYKyArW9qHZbkhsyb30SvGtlh6czQcTNcYlXeZkKPeP5tukl8svV/UHpO24Ak93RqPSEZGzCqeg52eoyWoa7Te2xizwSeN90BgLr7U8jar3FE9eM6rxJuJLuZjKWrr8ggH7793RCu6RpNjcnCg1/tYem+TK3DkppIVVXOWVctm/ux7mPQ8+ac3twxRKySPP/TYV5fnSKnOXgA2575qKDmfYxLTTOpewyg8LrxenHHzo+hLEfTmCQ3U5aDmjQPgC8MN3J933ht47nE5B6xrLQMJNnSHozlsEGj7uOS+7JYqFzxLABfmcdz48RRGgd0sREdIjhg6MFP5sEoqgV+fUHrkOpFJvONkN3MxtLVh5+3nvdu7cssa6f7R7/dy/e707QOS2qCsmpT7Vi28EBvjaPRnk6n8Py13Xh8fEcA3lp7gueWHMJikQm9O7PtmY+UneylJhjZIRI/Lz0/lnahIrIPmCph8xtahyW5EXXbOxjMVSRb2tF1+LUut42zXWQgnaKD+T/jzeKOpM8h77i2QUnu5dhK/PIOUqr6cazTA7SOcK2qT18vPWM6R/Ef0xws6OHEL5CepHVYVyWT+UaQK/N1M+h1vDq7F7cMaoWqwtM/7ueLbWe0DktqpLwyMaHA31uPv7fs8g2i+eOj4zvwj5ndURT4cvtZnv/pkFyhd2MymZfswc9bz5jOkYDCsvA7xZ27P4FSue1MqoeKAsw7PgLgA67ntsGttY3nMib3iGGn2oVk/yGgmuGX57UOSXIjVRv+C8CX5mu445r+GkdTtyk9YklVo1mlt1YNuEEFikzmG8G2Z765jaWrD51O4eWZ3blneBsAnltyiM/k/mK3lF8mkpwI2RjsN+YOTuTVG3qhKPDFtrO8vPyITOjdVI719VzOmJeaalL3WADeS0tEjR8Ipiq5Oi/Vz44PMJjKOWxJJKb/DEL8vbSOqE5Teohj/Jni61EVHRxdBpl7NY5KcgtpO/HN2kWNqudk61voFBOkdUR1Gt0pEl8vHf+qmIaq6OH4apdfnZfJfCPYVuZj5Mp8nRRF4a9Tu/DwmPYAvPDTYRbtTdc4KqmhbCvzssS+btf3i+f/rusBwMebT/Oq3EPvluSeeclexnaOwseg43R+Bak9HxV37v4USmQPGekKqkowb3sXgHfM13HPiLYaB3R5HaICaRcZwBFzS9Ljpog75QUrqR5qNommoEvMw7h+zACNo7k8f28DozpGclaN4XDERHHnhn9pG9RVyGS+EWpX5mUyf1mKovDkhI7cPUys0P/xh/2sOyqbAbmT/HKR5IQHyBXLy7l5YCtenNENgHfWneStX09oHJHUEEazhYIKcdFKdrOXmirQR5wEAvxY2B4SBoO5WiY70pXt+hh9TQnHLXF4db+W+BauOwpWURQmWytQPuNaceeRpZB/UsOoJJdXcAqvY8sB+DVsDkPahmsc0JXZKlD+WTFdVKAc/xky9mgc1eXJZL6BKmvMFFcaAZnMX41thf66PnGYLCoPfJUk59C7kXzrynyEXJm/otuHtOavU7sA8N9fjvHtzlSNI5LqK7+sBlUFvU4hzF8e51LTTe0pTgKXH8xGHfUncefe+VBZpF1Qkusy1WDe9h4A75hmcN+o9hoHdHWTe8QA8NWZYExtx4NqEaPqJOkyzFveRkFlnbkX14wajaIoWod0ReO6RONt0LEpP4Ti9teJOzf8W9ugrkAm8w1kW5X399YT5CObgl2NTqfw7xt6MqZTJFVGC3fP28XR7BKtw5LqIc+6Z16W2V/dvSPa8ui4DgD8dfFBtp7M0zgiqT5sM+YjAr3R6Vz75EJyD2M7R+Ft0HEqt5yUgH4Q1VWM8dr7pdahSa7o6DL0FTnkqKEUtplGt5YhWkd0VV1jg0kM96faZGFn3FxxZ/LXcu68VLfyfNTkrwD4zvs6pvdqqXFAVxfoY2C0tcpqYeBNoOjg2EqX7Q8hk/kGyiquBMSqvKtfWXIVXnod797aj36JLSipMnHPvN0UlNdoHZZ0FedX5mX5cX08Nr4D1/ZqKapQ5u/hVG6Z1iFJV5FTIvfLS/YV5OvFyA7iJHDFwXMw+AHxhR0fgtmkYWSSKzJZO9h/Yx7L3aM6ahxN/VxYav9VdgLE9RfbSXa8r3FkkitSd32MwVzFAUtrug+dirfBPVJPW5XV/BPeqN1vEHdufFXDiC7PPf5GXcg52cm+Ufy89Xx6xwBah/uTUVTJo9/uxSznc7u08yvzMpmvD0URVSi9E0IprjRy7+e7Ka4wah2WdAW5ZbZkXh7jkv1M7SnKkFccyIIes8E/HIpTIWW5xpFJLuXcYQxpWzGpOraGTGNkhwitI6q3KdZS+7VHc6ke/Ii4c9cnUCUrL6ULGCsxbf8AgM/U6dzioiMX62IrtT+VW86pLr8Xdx5dDoVnNI2rLjKZb6As2cm+0UL8vXh/bj/8vPRsOp7Hf9cc0zok6QryrdUTEQGyzL6+fL30fHh7P+JC/TiVV84DXyVhNFu0Dku6DNvKvJwxL9nTuC7ReOt1nMgp41iBCfrdJb6wXa5cSuepuz4BYLWlP1OH93Oras8ecSHEt/Cj0mhmrdofwjtAdTEkzdM6NMmVHPgRr6p80tUI/HpfT5gbnU9eWGq/OD0I2o4BVNj5kbaB1cGhyfzGjRuZPn06LVu2RFEUFi9e7Mincwo5xqhpOscE88/rxTivt9edYM1hucfKVeXLlflGiQry5eM7+hPgrWfryXx50cqF2fbMy5V5yZ6Cfb0YYV1lXXEgCwbcCzoDpG512T2XkpNVl2JO/gaAH3WTmNU3XuOAGkZRFKZaO34vO3AOhllX57e/C6ZqDSOTXEn1jk8BmG8az10jXL+546VqG5oeyEIddL+4c8+XUO1a2ygdmsyXl5fTq1cv3n77bUc+jVPlyQ7fTTajdxx3Dm0NwBPfJXM6r1zbgKTfMJktFFpLxGUDvIbrEhvMf2b3AuD9DSflFAcXlWO9OBspt01JdmYbbbTiQBYEx0K3WeILcnVeAtj/HQZTOSctsbTqO5FAN2yoPK2naGT269FzVHS+HoJioTQLDi3SODLJJZw7hM+5PRhVPRmtZ9E+KkjriBrswlL7o0GDIaydqEDZ943WoV3Eocn85MmTeemll5g1a5Yjn8ap8qwnf7IpWNM8O7UL/RNbUFpt4oH5SdSYZCmyK7E1KNQp0EKO7GqUKT1iub5vPBYVHv8+mdIquX/e1ZyvtJKv55J9je8ajZde4di5Mk7klJ5vhHdwAZRmaxucpC1VpWbbhwB8ab6G262LG+6me1wwrcL8qTJa+PV4MfS/R3zBun1Aat5Mu+YBsMbSj+tG9NY0lsYK9DEwquMFDU0HWffO7/gALK6Tt7jUnvnq6mpKSkou+nA1+eUymbcH0eG+L2EB3hzNLuXDjSe1Dkm6gK0CJSzAG70c2dVoz1/blfgWfqQVVPLiT4e1Dke6hC2Zl3vmJXsL8fNihLWr/fL92RDXFxIGg8UIuz/VODpJU2e34l2QQoXqQ3ab62gbGah1RI2iKArTbGXI+7Og7+1iO0n6Tsg+oHF0kqaMlVj2fQvAL36TGNUxSuOAGm/ahaX2vW4Gn2DIPw4n12oc2Xkulcy/8sorhISE1H4kJCRoHdJv1JbZB8nVyqaKCvbluWldAXhr7Qk5ysuF2C5ahQfIJKcpgny9eP3G3igK/JCUzqqDWVqHJFmpqipX5iWHmtxddPxefiBT3DHYuudy96dglpU6zZVtHN1i8zBuHN5N42iaxraneF1KDmXe4dB5mviCXJ1v3g4vwdtYQroaQYch17r1otBFpfaFQJ/bxBd2vKdpXBdyqWT+mWeeobi4uPYjLS1N65AuIvYRy9nb9jSjd0tGdoykxmThmYUHsMhxdS7BNmNe7pdvuoFtwrh/VDsAnll4gBzreEtJW0UVRmqskwbkyrzkCBO6xeCt13HsXBkp2aUi0QmIgvJcOLZK6/AkLZTnoxz9CYBfAqe59YolQNfYYNpEBFBtsvDrkXMwwFpqv/97OaauGSvbKi7m/GAZy40DWmkcTdNcVGp/IAsG3gcocOIXyDuubXBWLpXM+/j4EBwcfNGHKymoqEFV5T5ie1IUhZdndsfPS8+O0wV8v9u1LuA0V3LGvH09Pr4jXWODKaww8tLyI1qHI3G++V2ovxc+Br3G0UieKMTPi5HWk8Bl+zNB7wW9bxFf3POlhpFJWlEP/oheNXHA0pqhw8a49YolXFxq/9O+LGg9AiI6grEc9n+ncXSSJnKPEXhuJ2ZVoajjbI84j7Qd48v2Z6G2aAMdJ4kv7PhAw6jOc6lk3tXllcp9xI6QEObPkxM6AvB/K47UjouStFM7Y16uzNuFt0HHv2/oCcDSfZkcSC/WOCJJlthf2bvvvkubNm3w9fWlX79+bNq06bLfu379ehRF+c3H0aNHnRixa5rey5boZKKqqthXDHBiDRRnaBiZpIWKXfMBWMooZvdzva2kjWErtd94LJeSahP0v1t8YfenoMpqy+ameudnAKy19OHakf01jsY+xnWJxseg43ReOYcyS85vmdr3jUuMqXNoMl9WVkZycjLJyckAnD59muTkZFJTUx35tA5jW62UJfb2d+fQ1vSIC6GkysQLslGY5uTUBvvrHhfCdX3iAHHRSpUnOZqyXTSUJfa/9d133/HYY4/x7LPPsnfvXkaMGMHkyZOv+t6dkpJCVlZW7UeHDh2cFLHrGt8lGl8vHWfyKziYUQLh7SBxGKgWSP5a6/AkZ8o5SkDefoyqHmOXWYT4e2kdkV10ig6ifVQgNWYLaw6dg143g8EPcg5D6natw5OcyVSNxfq6tjl4Kn1btdA4IPsI9DEwvks0IC7M0mYUhLWFmjI4vFjb4HBwMr9792769OlDnz59AHjiiSfo06cPzz33nCOf1mHOlx7L1Up7M+h1vDKrB3qdwvL9WSSdLdQ6pGbNtjIfHiCPdXt6ckJHvPU6tp3KZ31KrtbhNGs5tSvzcsb8pV5//XXuuece7r33Xrp06cIbb7xBQkIC77135YY/UVFRxMTE1H7o9XL7QoCPgXGdxUngsv3WRni21fm9X7rUeCPJsar3iCRnvaUX04f20jga+1EUhak9znf8xi8UelwvvrhbNsJrTixHluNnLCJbbUGn4dehKJ5TxWyrslq2PwuLCvSZK77gAlumHJrMjx49GlVVf/Mxb948Rz6tw9iagsnVSsfoHhfCDX3jAXhn3QmNo2ne8uWeeYeIb+HPncNaA/DKyiOYZcNHzeSUyDL7utTU1JCUlMSECRMuun/ChAls3br1ij/bp08fYmNjGTduHOvWrbvi97rDKFp7uegk0KJCl2vBJwSKzsKZjRpHJzmFxYxp7zcAbAuaQN9WodrGY2e2PcWbjudSXGE8P3P+8BIoz9MwMsmZirZ9DsASxjCjb6LG0djX6E5RBPoYyCiqZG9aoeh/oughbTvkpmgam9wz3wCyzN7xHhjdDp0Ca4/mcDBD7ivWSp7sZu8wD41uT4ifF8fOlbEgKV3rcJotWWZft7y8PMxmM9HR0RfdHx0dTXZ2dp0/Exsby4cffsiCBQtYuHAhnTp1Yty4cWzcePlE1R1G0drLb04Cvf2hxw3ii3u+0DY4ySnU0xsJqM6hSA0gccgsj1qxBOgQHUSn6CCMZpVVh7Igri+07APmGkj+SuvwJGcoyyUkU7zmV3WdTYCPQeOA7MvXS8+EruJ9cWlyJgTFQAfrRe+92q7Oe9bftIPlenqZfUUBpO+C9N2QsRsy9kBV0cXf49cCYnuJF+nY3hA/AELi7BZC64gAru3VksXJmbyz7gTv3dbPbo8t1Y+qqrVz5iM98cKVxQJZe8VxXp4rPspyoboEAiIhNAFCrB/xAyAg3K5PH+LvxcNj2vPyiiO8tiaF6b1a4ucty5GdrbbMPliW2dfl0mRDVdXLJiCdOnWiU6dOtZ8PGTKEtLQ0Xn31VUaOHFnnzzzzzDM88cQTtZ+XlJR4bELv66Xnmq7RLNqbwU/7suiXGCZK7Xd/Akd+Eu+9/mFahyk5UOHWzwkDVqhDmdGvjdbhOMS1vVvyn59TWLovkzkDWkHfOyBzLyR/A0MfAQ+7gCFdrHzPDwRgYZ+lLdeMGK51OA4xvXdLFu7NYPmBLP42rSuGvnPh2ErY9y2MfQ4M2uSHMplvAI8ts09Pgm1vi3Io1Xzl760shFPrxYdN4jDofSt0nQE+gU0O58Ex7VmcnMmqQ9kcP1dKh+igJj+mVH/lNWaqjGIfp8dcuDJVw6kNkLJCzHcuzarfzyk6SBgMnSZDpykQ0d4u4dw+NJHPt50hvbCST7ec5qEx9nlcqf5kN/u6RUREoNfrf7MKn5OT85vV+isZPHgw8+fPv+zXfXx88PFpPn/303vFsuiCk0B9y94Q0wOyD4iZ3LbuyJLnqS4l8NRKAHLbXkeoh442vraXSOa3nswnp6SKqG7Xwco/Qe4RyEoWi0CSxyrf/TUBwM6g8dzX0rVGi9vL8PYRhPp7kVdWw47TBQzrMAECoqA8R5xbdr1Wk7hkmX0D2MrsPWK10mIRyfsnE+HjsXBooUjkwzuITqRTX4PfbYCnTlzwcRx+tx6mvQH97hQr9ChwdgsseRBe6wRLHoK8pu137xgdxKRuMagqvLv+pB1+WakhbPvl/bz0+Hu7+fU+s1GMx3mzF3w9G5I+E4m8dyB0nAwD7oPRf4Gpr8Osj2HCyzDoAeg8DSI7i47TqVthzd/g7X7w4Wjx/8ZylYteV+Fj0PPENWIc4xfbzmAyyyZYzpZTIsrsZTJ/MW9vb/r168eaNWsuun/NmjUMHTq03o+zd+9eYmNj7R2e2xrePpIQPy9yS6vZcTpf3Nn3DvHnni/kCC8PVrlvEd5qFacsMQwdNUnrcBwmIcyfPq1CUVXRHwK/UOg8VXwx+RtNY5McS80/SVTJAcyqQouBN2kdjsN46XVM7n5+3Ch6L7F3HjQttXfzM3Xn8phu9gWnYcnDcHaz+FznBT1mw+AHILbnlX82MOriq6vF6WLO4t6voPA07J0vXrT73g6j/yz2lDTCw2Pbs+pQNkuSM3hsfAcSwwMa9ThSw3nEfnmLRVygWvcyFJwS9wXGQJdpYpW99Qgw1COJK0qFlFViRf/MZlEy+P3tEN4ehj0KPefU73HqMK1nS15efoRzJdWsS8nlmq71X/WUmqa82kR5jbggI8vsf+uJJ55g7ty59O/fnyFDhvDhhx+SmprK/feL1eNnnnmGjIwMvvhC7Pd+4403aN26Nd26daOmpob58+ezYMECFixYoOWv4VK8DTomd4/h211p/LQvi6HtIsS++Z+fhZxDkL3feoFc8jTF27/AD1jvN567Wnv2dooZvVqyN7WIJfsyuXt4G5HoHFoIB36ACS9pVoYsOVbW5i9pCWylJxMGXSWPcHPTe8Xyzc5UVh7M5sUZ3fHuMxe2vAEnfoGSTAhu6fSY5Mp8Pamq6v5l9hYL7PwI3hsmEnmvABjxFDx+EK577+qJfF1C4mHkH+GRvXDXSug4SazwJ30Gb/aGX16AqoZ3Ke4eF8KYTpFYVHh/g1yddya372SffxI+GQ8L7hGJvH8ETP43PLZfVJy0H1//BDy0FQz6Hdy+GJ48CiOfBt9QyD8BS/8A/+sPR1c0Kkxvg47r+4npDd/uvPL8bsm+bPvl/b31BHpYkx57mDNnDm+88QYvvvgivXv3ZuPGjaxYsYLERNGdOCsr66KZ8zU1NTz11FP07NmTESNGsHnzZpYvX86sWbO0+hVc0rSe4iRv5cEsakwW0YOmk3Wldv/3GkYmOUxxOjEFuwDw73ezxzW+u9TUni3RKbAvrYiz+eXQdoy4kF5ZAMdXax2e5AiqitehHwBIjZtKsK+XxgE51qA24UQF+VBcaWTT8Vyx/bLVUFHJqVGzR5nM11NxpRGTdYyUW65YFqXBF9fCiqfAWC5WJh/YAuP+1ujV84soCiQOhVu+E0l9/EAwVcLm1+G9oRfvsa+nh8eKfcQ/JqWTVVzZ9BilerHNmI90x+P84EL4YBRkJIF3EIx5Fh5NhkG/b/QKeq2ACBj7rLj4NeFlCIqF4lT49mb45hbxf6yB5gwQDb/WpeTIY9yJZIn91T344IOcOXOG6upqkpKSLmpkN2/ePNavX1/7+dNPP82JEyeorKykoKCATZs2MWXKFA2idm1D2oUTGeRDUYWRjcdyxZ09bhR/HlzQ5O07kuvJ2irKy3daujBx2ECNo3G8yCAfhrWPAKwdv/UG6Gk9xvfJUntPVHlmF5E16VSoPnQcdbPW4TicXqcwtecFpfYAfS+YOW9x/rZJmczXk63EPsjXgI/BzTpPZybDx+PgzCbw8ofJ/4Hbl0KYgzqqJg6Fe1bDTV9Di9ZQnAZfzIDlT0J1Wb0fpl9iGANbh2E0qyxJznRMrNJv1K7MB7hRomOsgmVPwI93QU2paFr30A4Y9TT42LmBok8QDH0Y/pAEwx4DnQFSlsM7A2HzGw06IW8XGcjANmFYVPhhtxxT5yy1neyDZIm95Dx6ncJ06+r84uQMcWeHa8A3RPTyOLNZw+gkR7AcEFtNTsdMoEWAG14gb4Rre4ljfMm+TFRVPb+n+NjPUJ6vYWSSI6RtmAfANq9B9O/omRNJLjXdeoyvPnyOihqTaADuHQRFZ8W0JCeTyXw92fYRu13zu+O/wGdToOwcRHUTq/GDfgc6B//TK4pofHL/Fhhwr7hv18fw/jBI3V7vh5nRR/yHWXGgnt3HpSZzuz3zJVnwyTVizBPA8CfgzuV2HZlYJ+8AuOYFuH+zmOhgrIBf/i4uXJXU/3i9eaB48/tuVxoWi2yC5Qy2ZD4y2M1ezyW3N9P6nvbLkXOUVZtExVDXGeKLB2SpvSepyT1FXMURzKpC/FDPbQp2qYndY/A26DiRU8aRrFKI6iJGGVuMcPBHrcOT7MlsIip1OQBVXa73+G0kNn0SQmkV5k9FjZk1h8+J88GZ78BDuyDO+SO1ZTJfT7aVebfaL7/nC/j6RlFW32YU3L0Swto6NwafQLFPee5iMbe78AzMmyr27teje+/EbjHoFNifXkxqfoXDw5UubPToBsd64Rn4bJJoHuUfDrcugPF/F6V9zhLVRVw8uPZt0YfizCZ4f7hohlIPk7vHEuxrIKOokk0n8hwcrASQUyrL7CVt9IgLoW1EAFVGCz8ftI7/s5XaH14qqowkj3B6gxjNuEfXncE9u2gcjfME+3oxtlMUAEv2WStQbKvzyV9rFJXkCJl7VxJqKSJfDWLAuOu1DsdpFEVhZm9rldVe6zHedQZEdtQkHpnM11OedSUnIshNVis3/kc06FLNYtTcrT+KUj6ttBsDD2yFbrPAYhJ79xc/CMYr7xOOCPRhcNtwAFYclKvzznC+0aOLH+u5x+DTySKhb9Ea7lsLHcZrE4uiiD1Tv98A0T2gIg/mXw9r/g5m0xV/1NdLz6y+shGeM+WWiNfzaNnJXnIyRVGY0VtUDdWW2icOg+A4qC6B4z9rGJ1kT77HlgCQ13oqel3zWLG0mWFNdJbtyxIVZ91vEJOTspLh3GFtg5PsJm+buGC1L3gsUaF23tLo4mb0Ea/jG4/n1W5P1YpM5uvJ1hTMLfYRb/0frH1J3B75R5j5nmuMA/ENhhs+FeNJFB3s+xo+nXTVxmG2RhOy1N458svdoAolax98NhlKM8U8+LtWiYReaxEd4N5fzm8t2fKGqI65ykSHm6yl9msOnyO3VNs3hebgnFyZlzRkS3S2nMgTVSI6HXS3rmrJrvYeoSD1CIk1JzCpOjqNvkXrcJxuTOcognxExVlSaiEEhEPHieKLshGeRzBVV9A2fyMAgf3naByN87WLDKRnfAhmi8qy/drmJzKZrye3KbNP+hxW/1XcHvs3GPtXsWroKhQFhv4B5i4CvzBxlfajsSI5uwxZau9c+a6+Zz5zL8ybLla/Y3vDnSsgOFbrqM7z8hVbS2bPEw0nT/4Kn04UM+svo3NMML0TQjFZVBbskY3wHC2nRDbAk7TTOiKA3gmhWFT4aZ/1JNDW8fv4aqgs1C44yS5Orf8CgP3efWhrHenYnPh66ZnYXUxKqi1D7mXtG3BwoSYdvyX7Orx5CYFUcI4w+gybqHU4mphprbJaZDvGNSKT+XrKLbWWHrtymf3BBfDTo+L2sEdhxJPaxnMlbUfD79aLkuTyHPhs6mXH18lSe+cxW1QKKly4CiX/JMy/AaqLodUQuGOpuOLvirpdB3etEDN2cw7DR+MgPemy325rhPdjkkzmHa22m71sgCdpxLbfcomt1D66O0R2AXON2DsvuS1VVQk/Y20K1mmGxtFox5boLNufRbXJDO2vER2/S9IhfafG0UlNVbXPOqkhcjxeBif2KXIh03u1RK9TSE4r4kxeuWZxyGS+nvJcfVzXsZ9h4e8AFfrfDeNfcK0V+bq0SIS7louZ9zWlIkk7uKDOb5Wl9s5RUF6DqopDp4W/l9bhXKz0HMyfZV2R7wW3/qBtH4j6aNkH7vtVnKiX54jmj0dX1Pmtk3vEolPgRE4Z2cWyCZajVBnNFFcaAVlmL2lnmvUkcH96Madyy8SLbs/Z4osHftA2OKlJThzaTRvLWWpUPd3GNb8Se5sh7cKJCfaluNLIuqM5omqtyzTxxcuc60nuoaSsjC7FYpRm5KDmV2JvExnkw7D2EcAFPVA0IJP5erLtI450xZX5zL3w/R2isVyP2TDlNddP5G18Q+C2BdB1phhb8uM9sP3933ybLLV3Dttx3sLfG4PehV4eqkrgqxvON7u79Uf7z493lJB4uHsVdJgApkr47jY48NvxPMG+XnSPExcntp2SXe0dxdaTwNugI8TPxS5YSc1GRKAPw2tPAjPFnT2syfyZzVCsbdmm1HgZm0XH9pTAgYS0iNQ4Gu3odUrteOGFe6zHs603xKFFV20OK7mufesXEqRUkquE07bvGK3D0dR1fc53tVfrMaXLEVzobN215dnK7F1tz3xpNnxzi0gS2o8Xze4cPUPe3gw+ojHegPsAFVb9CTa/cdG3yFJ753DJTvamapEAZ+8H/wi4bSEERmkdVcP4BMFN30DPOWLCxIJ7Yc+Xv/m2IdZjfNvJfGdH2GzUzpgP9Gk2M3El12SbOb8k2XoSGNoKEgYDKhxeom1wUqNUG00kZq8CwNCz+YzqupxZfcSklnUpORSW14gtln5hUJ4LZzdrG5zUaOqhRQBktZyAotNrHI22JnSNwc9Lz5n8CvalF2sSg5tlfdoorzZRaTQDLjZ721gJ394iOnpHdBIJsd5NV5p0epjyHxj1Z/H5L3//TUIvS+0dz+W2k6gqLHscTm8QM9xv/QHC22kdVePoDTDzfeh3F6DC0od/U4UyuJ01mT8lk3lHybV1spf75SWN2U4Cz+ZXsCe1SNzZbab48/BijaKSmmLXjs20IZNqvOg48katw9Fcp5ggusYGYzSrLDuQJc5Ru1r7CNRRoSa5vrScQnpXbAOg5bCbNY5GewE+BiZ0iwYuaPboZDKZrwfbaqWvl44Abxe5AqWqYo58RhL4tYCbv3H9/cNXoygw5hkY/Yz4/JKEXpbaO57LdbLf8T4kfyVGGd74BcT11TqiptHpYNp/YcjD4vNLqlAGtA5Dr1NIK6gkvVAe445Q2/xO7peXNBbgY2CyteP3QtsUC1uik7ZDltq7oeIkkaCeaTEUvZ+bn5PZyay+1o7ftmPcVmp/ZCmYajSKSmqs5PULCVYqKdBHENF5hNbhuISZ1pnzP+3LxGh2/qQGmczXQ+4FY+lcpixz02uiSY7OIJIcd12trMvoP9eZ0F9Yar/myDmNgvNsLjWC8dR6+PlZcXvCS9BhvKbh2I2iiN/nwiqUHR8AEOhjoGe8dd+8LLV3CDmWTnIls/qKMuSf9mVSZTRDcEtrqT0i2ZHcRnGFkQ4F6wAI7D1L42hcx7W9WqJTYE+qteN34lAx5aWqGE6u1To8qQFUVcX7mHhdKmg1yf229TrIiPYRhAd4U1ptIiW71OnPL/8V6qG29NgVEhyA42tg7T/E7cn/hjYjtY3HES5N6K3Jjq1r5L60Io0C82y1K/MBGq/MF5yGH+4U+8t73gSDH9Q2HnuzVaGM+pP4fOXTsEfMJa7dNy9L7R0ix1ZmL1fmJRcwpF04sSG+lFSZ+PVIjrjTVmp/aLFWYUmNsHn7Vjoq6ZjQ03Jg8x1Jd6moYF+GdxCNABftzRDbKrtdJ74ou9q7lb2nzzHEuAOAOFliX8ug1/HxHf3Z/dfxtY2MnUkm8/VgS3AiXaH0uCgVFt4nbve/Gwbco208jjT6zxcnO/t/oIf1P8mBDG2aTHg6Wzf7CC0Tneoy+PZWqCwUo92mv+E+0xkaavQz50vulz4C+39giHXf/PaT+Zp1RvVkcsa85Er0OoXrrCWataX2Xa4Vf6Zth5JMjSKTGqpk70IAMlsMRPFroXE0rmWW9RhfbGv2aCu1T1kBNXJLmbs4tHERwUolxYYI/NoO1Tocl9KnVQuCfbXpWyaT+XpwmdJjU7UYQVdZCC37wqR/ahuPM4x+Bgb+XtxefD99qncBcDqvvHZWtGQ/eVqvzKsqLHkIcg5BQBTM+Qq8/LSJxRlsJff97wZUWPR7BlZtw0uvkFlcRWqBPMmxN1lmL7kaW6n9+mO5YnRiSBwkDBJfPCxL7d1BVnElXYs3AhDUV5bYX2pCt2j8vW3NHgshvj+EtIKaMji+WuvwpHqoMVkIPbMCgPJ2U2SJvQuR/xL14DLJ/M/PQuYe8A2FGz8XI908naKIixY9ZoPFRNCSu5kcchaAg3J13u5sK/OabSnZ8YHo4qwzwJwvxUmtp1MUmPIa9LoZVDM+i+/lpmixQif3zdtf7Wg6WWYvuYj2UYH0SgjFbFFZus+6Et91pvhTdrV3C2u3J9FLdwoLOlr0uU7rcFyOv7eBSdZmjwv2ZIj3ve7Wix4HZVd7d7DpSAaj1N0ARA++SeNopAvJZL4eXKLD9/4fYNdH4vasj8Q82uZCp4MZ70L7a8BUyWvGl+mgpLNfo3mOnkzTOfPpu2H1X8XtCS9Bq8HOj0ErOh1c+zZ0ngbmap4tfpH2SrrcN29nJrOl9oKVLLOXXMkN1o7fC5Iu6Wqfuh1K5DhWV1e6V8zdzg3rC4GRGkfjmm64tNmjLZk/vkZsr5NcWsqOFQQrFZQZwtAnDtE6HOkCMpmvh1ytV+Zzj8FPj4rbI/8IHSdoE4eWDN6ia3/CIPwtZXzm/W/Onj2ldVQepaLGREWNGdBgZb6iQDS8sxjFftFB9zv3+V2B3gDXfwzxA/E1lzLP+98cP3Fc7pu3o/zyGlQVdAqEB8hkXnId03q2xEuvcDirhCNZJaIqKX4goMqu9i4uJbuUPhWbAQiSq/KXNbhtOHGhfpRWmfj5UDbE9IQWrcFUBSfWaB2edAUVNSbCU38GoKr9ZFli72Lkv0Y9aFpmb6wUSY6xHNqMOt/hvTny9oebv6UyqDXxSh63n/mzbJxiR5lFost3gLeeAG+9857YYoFFv4fiNAhrCzPe9tyGd1fj5Qe3fIclrD3xSh6v1fyD05nZWkflMWz75SMCfdDrmukxJrmkFgHejOscDVzQCE92tXcLa3buZ4CSAoB/z5naBuPCdDqF6/uJ1fkfk9LF+7yt2aPsDeHS1hzKZKwielaF979e42ikS8lkvh40LT3++S/WZmCRorxe58QkyxX5h2G++TsK1UC6qieo+eFekQxKTZZmbbbWKjwAxZnJ9Jb/igY4Bl9RfeHr/LEeLsU/DN3cBRTpWtBFl4rfwjvALJs92kPtWDpZYi+5oFnWUvtFezMxmS0XlNpvg1J5Uc8VWSwqFfuXolNUClv0hJB4rUNyabZS+80n8sgoqjzfG+L4arF4Jbmkwzt+IVIpoUofhNJ6hNbhSJeQyfxV1JgstV3Tnb4yf2gR7P4UUGDWhxAU7dznd1GBLTvzvP9fqFYNeB9fLubQS01m65zeKsyJ3ePPboW1L4nbU16FmB7Oe25X1qI1K3v9jzLVl9j8HbDij6LTv9QktuZ30bKTveSCRneKIizAm7yyajYezxWJYfwARKn9T1qHJ9Vh99lCBldvASCwtyyxv5pW4f4MahOGqsLCpHSI6wvB8aKr/cm1Wocn1aGoooboDLENoqbdBLHtVXIpMpm/CluzJINOIcTPifMDC8/AUus++eGPQ7uxzntud5A4lKeNvxO3t74FSfM0DccTnE/m/Z3zhOX58OM9oFqg503Qd65zntdNtO81jEeMD2NBgaTPYOeHWofk9mrH0jlrZd5igT1fgtnknOeT3Jq3QcfM3mJ1/vtdl8ycl8m8S/p59xGG6A4D4NV9hsbRuIfZ/RMA+HFPOipAV1lq78pWHshigm4nAMGyJ4RLksn8VeSVihL7sABvdM7aY2k2iiSnulg0wBnzF+c8rxvpERfCEstwlrS4Q9yx/CnR9VdqNKcm86oKix+A0kwIbw9TX3P8c7qZXvGhbKQf/zRaR8Cs+jOc+FXboNzcOWuZfaSzVuY3vw5LH4Zv5sjKCqle5gwQic4vR86Jfj1dpokvnNksGoVKLsNktmA8vAIvxUxZaCcIb6d1SG5hSo8YAqwz53edKTy/nSRlJZhqtA1O+o19uzYQr+Rh1PlCu3FahyPVQSbzV5FXrkHzu7X/gIzdYu/wDZ+A3okVAW6iV0IoAK+UXSv2XFmM8N1cKM7QNC53Ztszn+CMZH7bO3D8Z9D7wOx54BPo+Od0M94GHa3C/PnQPI2ctrNEBcMPd4npFlKj1K7MO2PG/NltsO5lcbvbdc23qaPUIJ1igugVH4LJorJ4b4ZoChrdHVQzHFuldXjSBbafKmCYSSwi+PWQq/L15e9tYGrPWAB+2J0mFq0CY8QC1ukNGkcnXSi7uIq4bLGIYGwzVjSillyOTOavIs+6xzLCGSd/IFbetrwpbl/7dvOaJ98AXWOD0SmQXVpNzrjXxclOeQ58d6tsotIIqqo6b2U+PQl+eV7cnvR/cp/8FbSJCAAUfmn/F0gYLE52vpkjV+gaKdfWAM/Rr+cVBbDAtoVkDvS+1bHPJ3mUG62r89/tShOjKTtbV+ePLNMwKulSPyefYqRuPwD6rtM1jsa92Ertlx/IotxogS7Wv7/Di7ULSvqNZfszmagTXez9e8kSe1clk/mryLN1sg9wQsOHshxYZJ2v3f+e8/uIpN8I8DHQPkqs5h7IMcFNX4FfGGTuhZ8ekyWtDZRfXkNFjRlFgbgWDmyAV1kEP94lKim6zhDHuXRZIpmHkwVGcYyHtIKCU7DwPrCYNY7O/dga4EUFO7DM3raFpCTj/BYSuSovNcD0Xi3x9dJxPKeMvWlF5xOdk79CTbmmsUmC0Wyh7PBq/JQaqgLi5UXpBuqf2ILW4f5U1JhZcSDr/Pnu0eVyeosLSUraSUddBmbFAB0maB2OdBkymb+K/DInrcxbLCKRL8+BqK4w8WXHPp8H6BEXCsD+9GJo0VqUayt62P8tbH9Xy9Dcjm1VPjbYFx+Dg8Yfqir89AgUnYXQRJj+lkxyrqK1NZk/k1cOAREioTf4wolfYP0rGkfnXiwWldxSJ5TZb39XlEPrfeCGz8AnyHHPJXmkYF8vpnS/oAw5upt4jzNVif/7kuY2n8hjmGkHAN7dp8v3sgZSFIUbrDPnf9idDq2Ggn8EVBaK/hCS5s7ml9M6dx0A5sSR4BeqbUDSZclk/irybMm8o2fMb3tbXHU3+MENn4KXE8eDuame8WIe+f70InFH21HnL4Ks/psYeybVi1P2y+/+FA4vAZ1BJDnyjeGq2lqT+dN51tW42J7iIgjAxv+IVQypXgorajBZRMWOw3qgZCTBGuuozIkvi38vSWoEWxnyT/uyqDCaLyi1l13tXcGK5DTG6fYAoLM1KZQa5Pp+8egU2HmmgJMFVeebPR6RXe1dwfIDWUzUiy723t1lpbArk8n8VaQXiv3XMSEOTK4zkuDXF8TtSa9AVBfHPZcH6WFN5g9kFIt9hQCD7oceN4pmQT/cCaXntAvQjaTmO3i/fPZBWPWMuD3+BYjv55jn8TBtIkUyn1pQgclsEXf2miOOc4CFv4e84xpF515sJfZhAd54Gxzw1ldZJF5zLEYxTmzAvfZ/DqnZGNw2jMRwf8qqTaw4kH1+RN2x1bLjt8aqTWbyj6ynhVKG0SdM9DORGiw2xI/RnaIA0R/iojGMchuZ5nYm76e37hQqCnSeqnU40hXIZP4qbCtithUyu6sqhh/vBotJvJD1u9Mxz+OBusYGY9Ap5JXVkFUsGluhKDD9DYjsAmXnxN+tnPF8VQ5tflddJpIcczV0mAhDHrL/c3io6CBffL10mCxq7YVFACa8JMoSa0rh21uhulS7IN1EjiNL7FUVljwERaliC8m1/5Nlt1KTKIrCbGsZ8ve70iB+AARGiyaYZzZqHF3ztvFYHiOsJfaGLpNBb9A4Ivd1k7XZ44KkdGoShoNvKJTnQtpObQNr5lLzK2iVux4AU9xACIzSNiDpimQyfwXFFUbyy8UV8NaOSOZVVTRrKzwjGltdK/cQN4Svl56O0WI/6v704vNf8A6AOV+CdyCc3QxrX9QoQvdRm8yHOyCZX/FHyD8OQS1h5nvyGG8AnU6hdfglpfYgxlXOngdBsZCXAksfkU0fryKnxDZj3gHJ/M4P4egy0HnBbLmFRLKPC8uQT+VXQKcp4guy1F5Ty/ZlcI0+CQClsyyxb4qxnaOICvIhv7yGNSkF0HGS+MJROblBS8sPZDFRtxsAr26yxN7VOTyZf/fdd2nTpg2+vr7069ePTZs2Ofop7eZ0vjh5jgryIdDHAVde93wOhxZa9xB/Cn4t7P8cHu43++ZtIjrAjHfE7S1vypOfq3DYnvnkr2Hf16Do4IZPICDcvo/fDLS1ltqfyruki3VQNMz+XLx+HFoIuz7WIDr3cX5l3s6d7DP2wOq/itsT/gFxcguJZB+xIX6M7BgJwHe7087vKT66QpYha6TKaCbjyHbilTzMBj9oN0brkNyaQa9jdn9RgfLtrtTz5dxHfpIXqDW0cd9RBumOiE9kib3Lc2gy/9133/HYY4/x7LPPsnfvXkaMGMHkyZNJTU115NPazem8MuD8eCi7OncYVv5J3B77N0gYYP/naAY6x4iV+VO5dYzr6TYThjwsbi9+UIz0kn6j2mQmy7pqadcy+3OHYdkT4vbov0DiUPs9djNiW5k/c2kyD9BqkOhBAKInQUaSEyNzL7Wd7IPtuDJfVSxGLZprRIMyWy8DSbKTmwe2AuDH3dYyZJ8QMfUmfZfGkTVP61NyGGERJeC6DuNls2I7mNNfHOObjueRHj5UTGwpOgvnDmocWfOUml9By3MbMSgWTJFdIayN1iFJV+HQZP7111/nnnvu4d5776VLly688cYbJCQk8N5779X5/dXV1ZSUlFz0oaXT1gTRtjJmNzUV4gTQVAXtxsHQR+z7+M1IXAuRfGYWV9b9DeOfh4RBUF0CP9wFpmrnBecmMgorUVXw99YTHmCnqQ3VZfDDHWCqhHZjYcST9nncZqjNpR3tLzXkIZFIWozw/Z1itI/0G5lF1mam9poxr6qw9A/nt0nNeFtuIZHs7sIy5J+PFkDHieILstpME8v2ny8/liX29tEq3J/h7SMA+DY5X5wXAxyRpfZaWH4giwl6cYwbuk7XOBqpPhyWzNfU1JCUlMSECRMuun/ChAls3Vr3yLBXXnmFkJCQ2o+EhARHhVcvp60dvu2+Mr/yacg9CoExcN0HoJOtCxqrZag4Mc8ovEwyr/c6v4UhKxnWPOe84NzEhc3vFHskI6oKy5+AvGNiT/esj+Qx3gRXTeYVRWwpadEailNh0QNgsTgvQDdxPEdUWrWPCrTPA25/zzpq0bZPXm6TkuzPS69jjrVJ2Dc7Uy8otV8uy5CdrMpo5sTR/XTWpaEq+vMXVqQmu2mgOMZ/SErD3Mla1i33zWvi1/2nGanbLz6RF6zcgsPOsPPy8jCbzURHR190f3R0NNnZ2XX+zDPPPENxcXHtR1pamqPCq5fzZfZ2OvkDsYd475eAArM+hMBI+z12MxQfKlbm88trqDJeZg9hSDzMfF/c3vG+XNG4hN072e/5AvZ/B4peXEgJiLDP4zZTtmQ+s7jy8se4Xyjc+AXofeDYStj2P+cF6AaqjGbOWHugdIi2w+t56g5Y8zdxe+LLEN+/6Y8pSZcxZ0ACigJbT+ZzJnSI+H9eeBpyjmgdWrOy8Vguw83WLuuth8sLeHZ0TddowgK8OVdSzUalvzh/OHdQbo90stT8CsKzN+On1GAObgUxPbQOSaoHhy+XXbrSp6rqZVf/fHx8CA4OvuhDK6qq1pbZ221l/sI9xGP+Am1H2edxm7FgPwMB3nrgfBltnTpNgqF/ELcXPyRKYyXAzjPmsw+I7vUA4/4m98nbQViAN8G+BlQVzlr/reoU2wsm/0vc/uUFOdrnAidyylBVaOHvRWRgE/fMl+dZ58mboNt1MPB3dolRki4nvoU/o62N8L5Ozoe2o8UXUpZrF1QztOpgNhP1oleBLLG3Lx+Dnuv7xgEwf18JtB4mviBL7Z3qwhJ7fddpcuuYm3BYMh8REYFer//NKnxOTs5vVutdUW5pNeU1ZnSKnZKc6lL4/vYL9hA/1fTHlFAUhZahogFNZlHVlb953N/FrN7qYuv++RonROj67DaWrrIQvrvNOk9+Agx91A7RSYqiXFBqX3blb+53J3S/AVQz/Hg3VBQ4PkA3cOxcKQAdooOatpXEYoYF90BpJoR38Oh58g2dRLNhwwb69euHr68vbdu25f3333dSpM3DLYMSAfgxKR1jx8nizqMymXeWGpOFPUdS6KccF3d0nqJtQB5ozgDRCG9dSg5FidYtDLLU3ql+3p/GON0e8Ym8YOU2HJbMe3t7069fP9asWXPR/WvWrGHoUNdfrbONgUoI88fb0MS/JlWFnx49P2tb7iG2q/PJ/BVW5uH8/nnfUMjcA7++4Pjg3ECqPcbSWSyw8Pei4iG0lewFYWfnk/krrMyDSCyn/RfC2kJxGix5SO6rBY6dExdBOkUHNe2B1v8TTq0HL3+Y8yX4NPHxXFRDJ9GcPn2aKVOmMGLECPbu3ctf/vIXHnnkERYsWODkyD3XmE6RxAT7UlBew1pLP0CBzL1QnKF1aM3C1pN5DDbuRKeoqC37iO17kl21jwpkcNswLCp8V9pT3Jm2E0rPaRtYM5FWUIF/9g5ClXIsfuHQarDWIUn15NCz7SeeeIKPP/6YTz/9lCNHjvD444+TmprK/fe7/vgeW7Mpu5TY7/oYDi4Q86Bnz5N7iO3MlsxnXC2ZB5Fo2ubPb3sbjq12YGSuT1XV2hnzTapA2fgfOP6zGCkzZz74h9kpQgnO9+246so8gG8w3PAZ6L0hZYVo1NbM2VbmOzZlv/zRFbDx3+L29DchqosdInNNDZ1E8/7779OqVSveeOMNunTpwr333svdd9/Nq6++etnncLXpNa7OoNdxo7UR3mf7yiFhoPhCygoNo2o+Vh3MZkJtF3s5d9tR5g5uDcDH+2uwtOwLqHI7iZOsOpjNRJ3YRqLrPBl0eo0jkurLocn8nDlzeOONN3jxxRfp3bs3GzduZMWKFSQmJjryae3Cbsl82i4x/xnEmLRWg5r2eNJvxNk62tcnmQfRDdi2z3Xx/VCS5aDIXF9BeQ3lNWYUBeJCGzkv9/gaWP+KuD31dbF3W7Kr1hHiQstlO9pfqmVvmPCyuL3muWY/f/58Mt/IlfTcY7DQ+pox4D7oeaOdInM9jZlEs23btt98/8SJE9m9ezdGo7HOn3G16TXu4KYBCegU2H6qgPz4a8SdstTe4UxmC5sPnWGYzjr3vLMc1+UoE7pFExnkQ25pNSktrH2l5L55p1h1MIsJeuu5gjzG3YrD62AffPBBzpw5Q3V1NUlJSYwcOdLRT2kXp2wz5puSzJeeg+/nivnPXabDkIftFJ10obgW9Syzv9A1/xBdOivyYeF9Yi9sM2QrsY8J9sXXqxFXYQvPwIJ7ARX63w19brVrfJLQtnZl/ipl9hcaeJ943bEYRY+IqmIHRefayqtNpFtHVzYqma8qgW9vgZpSaDUUJr1i5whdS2Mm0WRnZ9f5/SaTiby8vDp/xtWm17iDlqF+jOkUBcB3pdYu02c2QWWRdkE1AztPF9Crahc+igk1rB1EdtI6JI/lpddxs7UC5aOcruLO0xvlMe5gOSVVmNKTiFUKsHj5n2+yKbkFuan1Mpo8ls5UAz/cAaVZENEJZr7nsY2StNYypBHJvJevKEX2ChAnQ5tec1B0rq1J++Wry+CbW6CqCOL6waR/2jc4qZZtZT6vrJqSqrpXOn9DUeDat8XWkqKzsPSRZrl/3jZfPjLIhxYB3g37YYsFFv1e9DsJjoMbPxe9N5qBhkyiudz313W/jStNr3Entw0WlY3vH1SwhHcUUxVO/KJxVJ5t5cHs2g7fShfZ4dvRbhrYCp0CC9MCqAltLy5Iy2PcoVYfPne+xL7DNeIcWXIbMpmvg8lsqU1y2kQ2cmV+9bOQug18guGmrz22UZIrqG2AV1yFxdKAZCWiA0y1JvHrX4EzWxwQnWtr9H55W5KTcwgCouDGL8HQxJFf0mUF+XoRYR2pdqa+pfYg5s/f8Jno13F4MSR95pD4XNmx7Cbsl9/4b7EnWe8jGt4FRtk5OtfTmEk0MTExdX6/wWAgPDzcYbE2R6M6RtIqzJ+SKhNHQ62VjrLjt8NYLCq/HkxjjG6vuEN2+Ha4lqF+jOsiXmt2+FgbZh/5ScOIPN/PB7Nqk3m6XKttMFKDyWS+DhlFlRjNKj4GHbHBjbg6tfcr2PmhuD3rI4hob98ApYvEhPiiKGJ0TH55A8fN9b4Zet0MqkWUi5fnOyZIF5Xa2GR+/SviBFLvDTd9BSFxDohOulDb2o72DUjmAeL7i7GMACv/DNkH7RyZa0tp7H75w0vO94KY9l9RfdIMNGYSzZAhQ37z/atXr6Z///54eTWPSgZn0ekU5lpX5z/KsTZhPL4GTNUaRuW59qQW0r5iL8FKJWpgNMT11zqkZsF2jL+b3VncceIXMF5l/LDUKMUVRnJP7aedLgtV5y1GC0tuRSbzdTh1QfM7na6B5VTpu2HZ4+L26Geg0yQ7RyddykuvIzpIXHRpUKm9zZRXxczo0kxY/ECzKkVuVDJ/cOHFXb1tXZUlh2rT2GQeRL+ODhPAXA0/3Cm2SDQTjWp+l7FHjFoEGHR/s+sFcbVJNM888wy333577ffff//9nD17lieeeIIjR47w6aef8sknn/DUU09p9St4tNn94/Ex6FicG02NXxTUlMHpTVqH5ZFWXtjFvtMUOXLVSYa3jyAx3J/t1a2o8LUd4xu0Dssj/Xr0HOMUsSqvtBstJuJIbkW+KtXhdG4jO9kXpcE3N4sT5k5TYOTTDohOqkvLhna0v5BPIMz+TJTSHv8Ztr1j5+hcV1qB+Puq9575rH2w+EFxe8jD0PsWB0UmXap1U5J5nQ5mvg9BsWL/94qnms1FqwYn88Xp8M1NYKqE9tecnwrQjFxtEk1WVtZFM+fbtGnDihUrWL9+Pb179+Yf//gHb731Ftdff71Wv4JHC/X3ZmbvOFR07PC2zoI+KsuQ7U1VVVYfzOSa2g7fssTeWXQ6hdsGJaKiY606QNwpt5M4xM+Hspmk3yk+kce4W5LJfB0aNZauulScAJbnQHQPUV4vr+A6TVwLkYw2amUeRGf7Sf8nbv/yPKR7/iivGpOFzGLx91WvlfniDPjaluSMh2tedHCE0oWatDIPEBAO138Cig72fQN759sxOtdUXGHkXIkoP+5Qnz3z1WXidbzsHER1hRs+Bb3BwVG6pitNopk3bx7r16+/6PtHjRrFnj17qK6u5vTp07Wr+JJjzB0iLqx8lmcttU9ZKXqZSHZzJKuUiOKDRCtFqN6B0GaE1iE1Kzf0ExUo35T2FHccXdFsJw85SmWNmePHDtNDdwZV0YmFSMntyGyzDg1O5i1mWHAfnDsomoHd/I1Y7ZWcpkkr8zb974GuM0Tn1B/v8vhRKBlFlagq+HnpiQi8SpfvqmL4arbYihDZWSSFukaMspMa7cJkXm3sqnrrYTDmWXF7xVMev3/+WI5YlW8Z4kuw71X2blvMYkxl9gEIiIRbvpPlhpLL6h4XQr/EFmw2d6VaHyAuQGV4/kVoZ1p9+IIu9h0nyiavTtYiwJsZvVuyw9KFCl0gVORB2k6tw/IoG47lMtpi/TttNRgCI7UNSGoUmczXwZbMt61vJ/tf/g7HVooy7Zu/gdAEB0Yn1SUutBHj6S6lKDD9rfOjvJY85NGlyLby48Rw/yuOnMJshO/vEJ3rA6Ph1h9El3TJqcS/E5RWmRre6PFCw58QlRWmKjE+s7rUfkG6GNsx3uFqJfaqCiv/dL5z/U3fiNcBSXJhtw9JpAYvNqq9xR2yDNmuVl+wX57OU7UNppm6Y2hrTBhYbewt7pDHuF39fCibiXrrfnnZxd5tyWT+ElVGc+3qbr1mzO/6BLb+T9ye+a7oHC053flZ803sduoXCrPniS7tR5d59P75pLOFAPRp1eLy36Sq8NNjcGodeAWI1UqZ5GjC10tfe5yfzW9kqT2I7T/XfSjmpuefgJ8e9diLVraxdJ1irpLMb3oVdn0EKHDd+5AwwPHBSVITTe4eS0SgD0ur+og7ji7XNiAPkl5YgencYdHhWy87fGulW8sQBrYJY6XZem595CePfb9ythqThT1HjjFASRF3yAtWbksm85c4Yz1JDvHzooX/VcoyDy+F5U+K26P/Aj1ucHB00uW0tMfKvE1cP5ho3T+/5jk4u63pj+mCdp0pAGBA6ysk8xv+DcnzxT7r2fOgZR/nBCfVKTpYlHnmlDRxDFVA+Pn58wcXwO5P7BCd6zl2TnTt7xB1hQuze76AtS+J25P/Bd1nOSEySWo6b4OOmwcmsN7SGxMG0dwy95jWYXmENYfPMUln6/A9FnwaONpSspu7h7Vmo6UnVXiLqslzh7QOySNsP5XPYONOdIqKGttbLtS4MZnMX+LCTvZXLD0+s0XMJUeFfnfCKNm5Xku2Mvv88hqqjHZokDLgXuh+A6hmsX++LLfpj+lCKmvMHMwoBmBA67C6v2nHh7DeelFj6mvQUa5MaC3KOoIxp9QOM6VbDYLxL4jbq56BtF1Nf0wXYyuzv+zKfMpKUZkAYvvBoN87KTJJso9bByVSqQtgi7mruCNFrs7bw+pD55hs6/Aty481Nb5LNGGhLdhk7iHukKX2diEuWIljXOkiu9i7M5nMX+JUfZrfnTt0wQi6qTDlNbHfWtJMsJ+BQB/RdbpJTfBsFEXMUI/oBKVZsOAej+qiui+9CKNZJTrYh/gWfr/9huRvYOUfxe1Rf4L+dzs3QKlOkUFiZT7XHsk8wJCHoMt0MNfA93Oh9Jx9HtcF5JVVk19eg6JA+7pW5s9ugx/uAtUCvW+Fcc85P0hJaqKYEF+m9oxltcVahixL7ZusqKKGc2cO00WXiqroodNkrUNq1gx6HbcPSWS1pR8Aqkzmm0xVVbYdPsVQnbXKQV6wcmsymb/EVTvZF6XC/BuguhgSBsMNnzTb0UWuRFGU2o72dim1BzGR4MYvwMsfTm84X4rrAXZbS+z7tw77bQXKkWWi+R/AoAdg9DNOjk66nChrMp9T2sTeEDaKAjPfO3/R6vvbwdSE5nouxLYqn9DCH3/vS16j03aJ6QymSrEXdvqb8oKs5LbuGd6GNWaR6JC+C0qztQ3Iza09msM1inXFss0I8L9M9ZrkNHMGJLBJ1x+zqqBkH4DCM1qH5NYOZZbQtWwHPooJS3gHiOykdUhSE8hk/hJXTOZLMuHz6efHc938DXjVsaopacKu++ZtojrDtdYGh5tfhwM/2u+xNbTrjGh+NyDxkv3yJ9eJbQWqWaxWTvw/meS4kCjbnnl7rcyD2At609fgEwJp22HVn+332BqyNb/reGkn+4w9MP96qCmF1iNg9uegv0p/FElyYT3jQ0ls3Za9lvbijpQV2gbk5lYfOscka4dvukzXNhgJgFB/b8b27cpOSxdxh6xAaZI1h88xWb8DAF1XuSrv7mQyf4Eak4XDmSVAHXssS7NFIl94Blq0htsWyqu1LsaWzGc0taP9pXrcAEMfEbeXPASZe+37+E5mtqjssXay73/hfvnTG+HbW0TJdZdrxZg+nXyJcCV2L7O3iWgP11u7ue/+RDSFc3PHckTzu47RF5TYZ+2HL68TlVWthorpDN7+GkUoSfZz97A2rLZ2/DYflmXIjVVlNJNy/Ch9dCdQUaCz3EvsKu4c2ppVFjFppPrAYm2DcXObD59hjC5ZfNJ1ppahSHYgz9QvsD+9iEqjmbAAb9pHXnACWJYLn18rxjiFJMAdP0FInHaBSnWyy6z5yxn/vCjHNVXBN7e4dRljSnYppdUmAn0MdLZdtDrxqyg7NlaIGeTXfyy3j7gguzbAu1THiTDmWXF7+ZNwdqv9n8OJUi4dS3fuEHwxA6qKIH4g3Po9eF+hN4okuZEJ3WLYFzhMfHJ6A1SVaBuQm9pyIo+RZrFiScIgCIrRNiCpVsfoIAoTrgHAO3OXR/V4caaMokpizm3CVzFiDm0NMT20DklqIpnMX2DbyXwABrcNQ6ezlhZXFIgTwLwUCGopEnk5vsEl2X3P/IV0epHgRnQU2yy+vRWMdq4AcJLdZ8V++T6tQjHodXBstWjoaKqCjpNgzldg8NE4Sqkutj3z+WXVmC0OmLU74klRlWGuEcdEbor9n8MJSquM7E8vAkQJMum74bMpUFkALfvCbT/KUVOSR9HrFMYOH85JSyx61YR6fI3WIbmlC7vYK7L82OXMGjOIZEs7FFQqDy7VOhy39OuRc0zRbwdA3/06uZXSA8hk/gLbT4tkfkjbcHFHaTbMmwo5hyAwGu5cBmFtNIxQupK4UFEua5du9nXxDYGbvxV/ZuyGpQ+DxeKY53Kg2v3yrcPEvrNvbxGTGTpPgxu/BC9fjSOULicswBtFAYsK+eUOWJ3X6WDWhxA/QKxgz7/BLVc/tpzIx2hWaR3uT5vinaKyqqpI/F5zF4r/w5LkYW4ckMA6ZSAAubsXahyN+zFbVPYcOcYA5ai4Q5bYu5xRHSNJ8h8OQN5Oz+hh5GwbD55hjG6f+KTrDG2DkexCJvNW1SYzu61JzuC24VBwCj6ZADmHITBGrMiHt9M4SulKbCvzWUVVWByxagniGJg9DxQ9HPgBfv4LqA56LgdQVZVdp8XK/GTzWtG93GKEbteJ38vgrW2A0hUZ9DrCA6xN8EockMyDaOp587cQ1haKU+Hr2VBd5pjncpANx3IAuD/6CHx9IxjLoe0YuH0J+LW4yk9LknsK9vWCzlMBCEpdCyYHvUZ4qH3pRfSr2oZeUbHE9oYWiVqHJF1CURRaDr4RgNjCXdSUFmgckXsprTLid3Yd/ko1xuBWENtb65AkO5DJvNW+tGKqTRYiAr1pr56FTydB0VnR7O6en+XYBjcQHeyLToEas4U8R6xa2rQbCzPeEbd3vAebXnXcc9lZRlEl2SWVPGZYSIetT4PFBD1vglkfy47ebqK2CV6ZA4/xgAi49UfwD4esffDDnWA2Oe757EhVVdYdzeVG/TrmnH72fEPHW76Te+Qljzfhmqlkqy3wUytITVqpdThu5dcj55isEyX2OtnF3mWNHT6E47TCgJl9a7/VOhy3suFYLhMUUWLv1X2mLLH3EDKZt7Ltl78pNhtl3hQoOwdR3eDun0VCL7k8L72O6GDbvnkH72fvfTNMfEXcXvsS7PrEsc9nJ0mncviX4SMeM1jL04Y/IeaMy2Z3bsO2bz7XUSvzNuHt4JbvweAHJ9bAgnvAbHTsc9pBSlYRd1d8wr+9PkJRLdDnNrjhM9kHQmoWWkUEkhI6CoDMrd9pHI172XHoJEN1h8QnXeR+eVflY9BTmDgJgJqDS1DdqDpSaxsOpjJWZ53I1G2mprFI9iOTeavtp/KZodvM4xlPQFWx6HZ813LZydTNOGTW/OUMeRBGPCVuL38SDi5w/HM2RVUxXdbfxxzDeizoYOrrMP7vcvycm4lyxsq8TXx/uPFz0HnB4cVihd5U4/jnbayqYvx+vI3fGawziEc+Dde+LS9WSc1KwrCbAOhYtJH0fNnVvj7SCytok78eL8WMKaIrRHbUOiTpCjqPuQWAfjVJbD2aqnE07sFotmA8toYApZrqgDjRDFbyCPIsHqiqMTI6/V3e9H4XvaVGdPS+fbHcW+mGnJrMA4z9K/S7C1BhwX2wd75znrehsg/Ah6PpWLqTCtWH5GHvwoB7tI5KagRbmX1OiZOmKXScCDd9BXpvOLpM9Flwxb24Bafg42tILNhMlerFxp7/grHPyjJCqdlp2+8aSnXBhCll/LpqkdbhuIV1R3OYrtsGgKHnLI2jka4mOLE3BT5x+CpGdv/yg9bhuIVdZwoYYxYjZ716yC72nkQm81UlVHwxh9/rlgCgDnscbvpa7q10U7ZZ8+mFTkrmFQWmvga9bgHVDEsegs1vuFZTvL1fwcfjoeAU6WoEc2r+RuIQebLirmwr8w6ZNX85HSfCzd+AwReOrYTvbnOt0YwHF8KHoyEvhWy1BbNr/k7rUbdrHZUkaUNvoKzNRAAMKcspLHfhahoXsf3g8fMl9t3k+6PLUxQM3UQn9tY5v3IkS1agXM36Q2mM0+0BQCdL7D1K807ms/bDx+MJS/+VatWLL2KfRbnmeTFTXHJLcY6cNX85Oj3MfBeGPiI+/+XvsPqv2o+tM1bC0j/AkgfBVEVezAimVb9MeUQPwgPl/mF3FWXtC5HrzGQeoP140UTO4AfHV4uxncUZzo3hUtWlsOgB+PEuqCqmMKwX11a/RHlED1qF+2sbmyRpKGbQbADGKzv4cttpjaNxbeXVJsLOrsKgWKiK6C4nF7mJ4D7iostY3V4+XndE42hcX8Xh1QQqVVT6xYotdJLHaJ7JvMUCW96Ej8ZCXgoFujBurPkbht43aR2Z1ESxIdYy+2InJvMgVugn/AOu+Yf4fNvbsOj3UFPh3DhszmyB94fDni8ABcY8y3/C/0ERQWL0ouS2IrVYmbdpOxpu+1HMac/YDR+OgjObnR8HQPpueH8E7PsaFB2MfJp/xf6XHFowumOUNjFJkotQ2o7GaAgkWiliz9Y1VBnNWofksjafyGOiIkrsfXrdoHE0Ur3F9cPoH02QUknRoTWk5mt0vuUGTuWW0b98PQD6btfKEnsP0/yS+eJ0+OJaWPMcWIyYO05hcvU/2ae2Z0g7meS4O1s3e4fN4L6aYY/AzPetc+i/F8lOZrLznr+qGH56DOZNgfwTEBgDcxdSOeRJlh8Us7dn9o5zXjyS3Z0vs6/Spotv6+Hwu/UQ3R3Kc+Hza2H7e87bWlKeD8seh0+ugcLTEJIAdy5HHfMX1h4rBGBM50jnxCJJrsrgg76z6Pg9tGYrPySlaxyQ69px4AhDdIcBUGT5sfvQ6fDqJqYOTFR28v7GkxoH5Lo2HjrLBF0SAN69b9Q4Gsnemlcyf2o9vDsUzmwCrwC49n/sGPgW58yBRAf70FqWZbq9qGCR6OSX12C2aLRvvffNMHcRBMVC3jH4eBxseh0sDlwZsVjgwI/wzmBI+kzc1/cOeGgHtBvL6sPZlFWbSAjzo3+ibOzozmwr81VGC2XVGs1+D2sL96yGHrNFr4hVf4ZvboJ8B55MmU2w4wP4Xx/Y/SmoFuhxI9y/GRKHcjirhJzSavy89AxsE+a4OCTJTei6ikRnkm4nH204icms8dYvF2SxqHgfW45eUSkN7wlhbbQOSWqIbtcBMFG/iyW7z5Bd7EK9XFxI6f6f8FeqKfGLh7h+Wocj2VnzSubDrPug4vrB/Zug7+1sP1UAwJC24Siy7MTthQd4oyhgtqgUaNn0p+0oeGArdJkOFhP8+gJ8Ph3Sk+z7PBaLaP713hAxB7w0UyRad/wE174FfqEALNwj9jZf1ycenU4e5+7M39tAoI8YtaZJqb2NdwDM+ggm/RN0Bji2Ct4ZJKqequzYjMhUDclfw/vDYOXTovokujvcuRyu/6j2GF+fkgvAsPbh+Bhk3xNJov14VIMfrXS5BBUd4af9mVpH5HL2ZxQz2iS2Cvn1ma1xNFKDtRoMgTGEKBUMUPfx8aZTWkfkckqrjHTN+xkAc7cbZIm9B2peyXxoAty1Au7+ubbBiS2Zl/uIPYNBryM84HwZsqb8w+DGL8Wca68AOLsFPh4LX14HZ7c27bGrSs4nOD/eBblHwScExjwrLiK0GVn7rTmlVWw6LhKdWX1kib0nqJ01r2UyD+KkYPAD4phrNw4sRtGP5H/9YNu7UJbT+McuPQfrXoH/doPFD4hj3K+FmB7xuw2i3P8C61PEc43uJPfLSxIA3gEo7ccBMFG/k7fXntCuYs1F7dh3kIHKUQAM3a/TOBqpwXR66Cq62k/T7+CrHalyesMldhw6wQhlHwAtBt6scTSSIzSvZB4gpjvovQAorjSyN03ssZT75T2HJqO7LkdRoO9ceHAr9L5V7KU/uRY+mwyfToLt70POkfrtN64ph0OLxFiw/7QXCU7OYZHEj34GHtsPo54GL7+LfmxpciYWFfq2CqV1hBy56AkiXOkYB4jsBLctgFu+h/D2UJ4DPz8Dr3USF6+Sv4GKgis/htkEabtgw3/gs6kiid/wT7EvP6gljHsOHtkLA+4FveGiH00vrCDprHgtH91J7peXpFpdRKn9VMMuTuaWs/JglsYBuRbLoaXoFJX8Fr3Fgo/kfqyl9pMMSZiNVXy29Yy28biYwt0L8FbMZPt1gKjOWocjOYDh6t/iuVYcyMJoVukUHUSrMLlf3lNEBvlAFuRq1QSvLi1ai/F1o54Wc+iTv4LUbeIDICBKrDQGtxTJuJe/mOldkiH23eemQFEqcEHSH94Bes6BgffVlhrXZYG1xH5W33hH/XaSk9VesCpxof2BiiLm0bcdA3u/EJUjGUni4tXJteJ7fEPF/4UWieAXBpWFUJEvEv3iNKi+pDw/fiAMvl8kJNaLsHWZvz0ViypK7ONbyNdySarVcSLovGhnyaCDks7ba4OY0j1WbrcCsoor6V++DnTg21t2sXdbCYMgqCWBpZmM0O1n3hY/fjeybe12tObMYlFpk70CgOrOsvLEUzXrI32RbR9x3zi5X96DXNjt2+W0aA3T34CRf4T938HpjZC6XaxkHlp49Z8PTYTus6D79WLf8FWO28OZJRzJKsFbr2Naz1i7/AqS9qKCrLPmy1zogpWNwVusng+4VzTEO7hANGfMS4GqIshKFh918Q2FNiPECLy2Y+o177nKaObbXakA3DGktX1+B0nyFH6h0H4cHFvFLO8d/Cs7njVHzjGxW4zWkWluZ/IBZuiOYUEhoM/1WocjNZZOB91mwvZ3uck/iV/L+vHltrM8MPrq7x+e7sixFPpaDoMCscNu1TocyUGabTKfVlDBzjMFKIoc1eVpbB3tXaYEuS4hcTDiCfFhqhYzs9O2i+ZeNRVgrARjBQRGQURHUcYc0QkCIhrUvGTRXjGOaFyXKEL9vR3120hOZuto71LVJ3UJbyeqUUY9LbaJFJ6ForNQeEYc635horeEfxgERkNkZ7EHsgGWJmdSVGEkvoUf47pEO+b3kCR31v16OLaKOX47+Vf1LP639jgTukY3+0UM877vAMgM6UN8cEuNo5GapNt1sP1dRrMLH+7ko02nuH1IIgHNfHU+d/s3dFNUTvj2oH1Ea63DkRyk2R7li/aKVflh7SKICfHVOBrJnmyrlprNmm8ogw+0HiY+7MhktrA4WXQvliX2nsWl+kLUl3cARHcVH3aiqirzrPsj5w5ORC9LhyXptzpNBoMvYVVp9PNOIylDYX1KLmM6N99mkdVGEz3zV4ECSs+btA5Haqq4/hAcj1dJOteHpPB1cQ++kKvzxKUtA6Ck/QyNI5Ecqfk1wEOcANqS+etkd2+PU9vp2xVLkJ1oy8l8ckuraeHvxaiOsimYJ4l0lW72Gks6W8jhrBJ8DDpu7C+bV0lSnXyCoMMEAJ6MOwTAW2uPo9an8aqHOrJnM+2VdKrwJnbIHK3DkZrKVmoP3B+xH4APN56krNqkYVDayj97iA7mE5hUHa1G3KJ1OJIDNctkPjmtiNN55fh56ZnUXe4b8zTny+xdcM+8E31hXbGc3qsl3oZm+V/dY8ljXLCtys/sHUeLALmNRJIuq/ssAAaVr8fHoLA3tYiNx/M0Dko71UlfA3A0eBg6/1Btg5Hsw9rVPiF3A53CDRRWGPm8GXe2z9o8H4B93n2IiJYLl56sWZ7h21blJ3WPafb7aTzRhWX2zXXlITmtiF+P5qDXKdw1rI3W4Uh2ZjvGCyuM1JgsGkejjXMlVaw6mA3AHUNbaxuMJLm6DhPBKwB9SRpPdy8H4LXVKc3zPdJsokPuzwCYut+ocTCS3cT1g5AElJoyXugqRjB+tOkUpVVGjQPTgKoSdXoxAHltrtU2FsnhHJrMv/zyywwdOhR/f39CQ0Md+VT1VmOysHSf2EcsS+w9k60EudpkoaSqeZZY/XfNMUAc423kbHmPE+rnhcG6PzyvmW4n+Wr7WUwWlYGtw+jaMljrcCTJtXn7i73zwC0Bu/D31rM/vZg1h89pHJjz5SSvJEwtIl8NpuOwmVqHI9mLotSW2g8sX0fbyACKKozM23JG07C0YDy1mShTJmWqLy2HyAtWns6hyXxNTQ2zZ8/mgQcecOTTNMj6lByKKoxEBfkwrH2E1uFIDuDrpSfIV1Rc5DbDMuSks4VsOJaLXqfwyNgOWocjOYBOp9RetHKrJnh2UmU08/VO6zg6uSovSfXTXYxf8zv2E3cNbQXA62uOYbE0r9X58l1fAbAzYDTBAf4aRyPZVfcbANClrOTJkWIb7UebTlHSzFbnC7d+BsAvumF0S5RjiT2dQ5P5F154gccff5wePXo48mkaxFZiP6N3S9n52IPVdvt2l472dvTGL2JVfna/eFqFyxMVTxXVjJvgzdt6hryyGmJDfJnQTY6jk6R6aT8OfEKgNJMH2uQR5GvgaHYpyw5kaR2Z81SV0PLcWgAquszWOBjJ7mJ7iRGn5mom63bQPiqQkioTn20+o3VkzlNdRujpFQCkJl6HTuY6Hs+l9sxXV1dTUlJy0Yc9FVcY+fVIDiBHdXm62n3zzSzR2Xm6gE3H8/DSKzw0pr3W4UgOdH5lvnlVn+SVVfPO2hMAPDWhE156l3obkyTXZfCBLtMACDyxhN+NaAvAG2uOYTI3j94bxoOL8VGrOWFpSff+o7UOR7I3RYGeYjqBbv/3PDpOVCd+vOkUheU1WkbmPIcX422p5KQllta9x2odjeQELnUW9MorrxASElL7kZBg31FDSakFmFWVzjFBdImVeyw9WXPt9m3bKz+7fwIJYXJV3pNFWi9YNbeV+f+uOUZptYkecSGy74kkNVQ30dWew0u4a2gCYQHenMorZ6G1atHTle0UJfa/eI2mY0yQxtFIDtHzRkCBs5uZmmCka2wwpdUm3ll3QuvInKJ695cALLSMZKQcS9wsNDiZf/7551EU5Yofu3fvblQwzzzzDMXFxbUfaWlpjXqcyxnbOZrtz4zj1dm97Pq4kutpjiXIW0/mse1UPt56nVyVbwaimuGe+ZTsUr6x7pX/27SusnzQAQoLC5k7d27tRfW5c+dSVFR0xZ+58847f3MeMHjwYOcELDVM21HgFwbluQRmbOaBUe0AePOX454/GaM4ndCcHQCUdJyFosjXD48UEg+thwOgO/gDf5rcGYAvtp0lvbBCy8gcL/8kPhnbMasKKdFTCfWXI1ubgwYn8w8//DBHjhy54kf37t0bFYyPjw/BwcEXfdhbZJAP3eNC7P64kmtpbmX2ZovKv1YeBeCmgQnEhfppHJHkaJHNrC+Eqqq8tPwwFhUmd49hYJswrUPySLfccgvJycmsWrWKVatWkZyczNy5c6/6c5MmTSIrK6v2Y8WKFU6IVmowvVdtIzySv2HukESignzIKKrk6x1ntY3NwdS9X6Ggst3ShT49emodjuRIvW4Sf+7/jpHtwxnSNpwas4X/rjmubVyOlvw1AJssPenVtavGwUjO0uAh6xEREUREyC7wkmurLbNvJonOZ1tOsy+9mCBfAw/LVflmobb6pJmMplufksum43l463X82brSItnXkSNHWLVqFdu3b2fQoEEAfPTRRwwZMoSUlBQ6dep02Z/18fEhJibGWaFKTdH7Ztj1ERxdhu+0Mh4d34FnFx3kzV+PM6tfPMG+XlpHaH8WM6bdn+MF/GAZx4vtwrWOSHKkLtfC8ich7xhKVjJ/ntyZGe9sYeHedO4b2YbOMR641dZiRk3+GgX4wTyK+ztFaR2R5CQO3TOfmppKcnIyqampmM1mkpOTSU5OpqyszJFPK0nNqjlYWkEFr60We+X/MqULUcG+GkckOYPtGM8t8fxj3Gi28NLywwDcOaw1ieEBGkfkmbZt20ZISEhtIg8wePBgQkJC2Lp16xV/dv369URFRdGxY0fuu+8+cnJyrvj9jm54K11By76i47epCg4tYk7/BNpHBVJYYeS99Se1js4xTq7FqyyDIjWAgsRJBPg0eC1Lcie+wdB5qri9/zt6JYQypUcMqgr/WZWibWyOcmo9SmkmRWoAe/0G062lB16wkOrk0GT+ueeeo0+fPvz973+nrKyMPn360KdPn0bvqZek+mou+4lVVeWZhQeoNJoZ3DaMmwbYt2mk5LpsF21yy6pRVc+eE/3BhpOczC0nLMCbh8fKyhNHyc7OJirqt6s5UVFRZGdnX/bnJk+ezFdffcXatWt57bXX2LVrF2PHjqW6+vKvv45ueCtdgaJA71vE7eSvMeh1/HmSqHb5ZPNpMooqNQzOQXaLudsLzCMZ1lk2zmwWelpL7Q/8CGYjT03ohF6n8OvRHHaeLtA2NkdIFs0dl5iHMrhTnOwp04w4NJmfN28eqqr+5mP06NGOfFpJqu30XVplospo1jgax/khKZ3NJ/LwMej456yesqFPMxIRKBrbGM0qRRVGjaNxnP3pRbzxi9jn+OyULp5ZAuxgDWlcW9driKqqV3xtmTNnDlOnTqV79+5Mnz6dlStXcuzYMZYvX37Zn3F0w1vpKnrOAUUHaTsg/yTjukQxqE0YNSYLr/3sYSuXJZmox1YB8LV5LKM7yQ7fzUK7sRAQCRV5cHItbSMDmWNd8PjnyiOedRG8LBeO/ASIEvvRssS+WXGp0XSSZC/BvgZ8DOLw9tR98zmlVby0TJQeP35NR1pHyNLj5sTHoCfUXyS2nlqBUllj5rHvkjFZVKb0iGFWX7mi1hj1bVwbExPDuXPnfvPzubm5REdH1/v5YmNjSUxM5PjxyzebckbDW+kKgmKg3ThxO/lrFEXh2aldAFiUnMHBjGINg7OzvV+hqGZ2WDpTFdKedpGBWkckOYPeAN1vELf3fQvAY+M64OelZ09qEcv2Z2kYnJ3t+RzMNSRb2nGYtozsIHubNScymZc8kqIoHj1rXlVVnlt8iJIqE93jgrl3eButQ5I04OkjGF9ZeYRTueVEBfnw8swesvKkkSIiIujcufMVP3x9fRkyZAjFxcXs3Lmz9md37NhBcXExQ4cOrffz5efnk5aWRmxsrCN+Hcleet8s/tz3LVgs9IwPZUbvlqgq/N8KD1m5tJhFogN8YxrLqE6R8nWkObF1tT+6DMrziQr25YHRYhzjP1ce9YzKTbMJdn8KwOemCfRp1UKOpGtmZDIveSzbeDpPTHQ+33qGVYeyMegU/nV9Twx6+V+5ObId4+c8sAneupQcvtgmRmW9OrsXLQLkyYmjdenShUmTJnHfffexfft2tm/fzn333ce0adMu6mTfuXNnFi1aBEBZWRlPPfUU27Zt48yZM6xfv57p06cTERHBddddp9WvItVHp6ngEwIl6XBmIwBPTeiEt17H1pP5rEu5chNDt3ByLRSnUUIgKy0DGd1Rltg3Ky17Q2xvMNfU7in/3ci2xIX6kVFUyYcbT2kanl0cWwklGZToQllhGSSP8WZIZgCSx/LUJnhJZwt5afkRQHSv79YyROOIJK3Ehohk3tMaVhWU1/D0j/sBuHNoa0bKkxOn+eqrr+jRowcTJkxgwoQJ9OzZky+//PKi70lJSaG4WJRh6/V6Dhw4wIwZM+jYsSN33HEHHTt2ZNu2bQQFBWnxK0j15eULPWwz58V86oQwf+4a1hqAl5YdocZk0Sg4O0maB8APphFY9D4MbS/Lj5ud/neLP5PmgcWCr5e+drzpe+tPkl3s5hfDd34IwLfm0VTjLffLN0MymZc8VpQHjqfLL6vmoa/2YLKoTO0ZW3vSJTVPieH+AJzNr9A4Evsxmi384Zs95JZW0yEqUM6Ud7KwsDDmz59fOy5u/vz5hIaGXvQ9qqpy5513AuDn58fPP/9MTk4ONTU1nD17lnnz5snu9O6il7Wr/eGlUCXGAz40tj0RgT6cyivn0y2nNQyuiUqyIGUlAN+Yx9A/MYxAOZKu+el+PXgHQcHJ2gqUaT1jGdC6BZVGM/9adVTjAJsg5yic3oiq6JhXPZaIQG85kq4Zksm85LFso7s8pQGe2aLyyLd7yS6pom1kAP+6Xnavb+5aWeetpxV4TjL/0rLDbDmRj7+3nv/d0gdfL73WIUmS54rvD+EdwFQJhxYCEOzrVXsR7a1fj7vvyuWez0E1k+LTnRNqvOxi31z5BEKvOeK2dW+5oig8N60bigKL9mawJ7VQwwCbYNdHAKSEjCCTCEZ1jJIj6ZohmcxLHisy0LPK7P+75lhtkvPBbf3kCoNEqzDrynxBucaR2MfXO1L53LpP/r9zetM5Rq4wSJJDKQr0vV3c3vkxWJvezeoTR99WoVTUmHll5RENA2wkYyXsFInOB5VjARglk/nmq99d4s+jy6FUTOzoER/CDX3jAXjxp8NYLG7W8LGqGJK/AeDTmvEA8oJVMyWTecljRQZ7TjK/cE86b6/7//buPC7Kan/g+GfYd8SNRQV3UEFT3HDfcimvluVaLi1etbyldW9561dZ95ZL271li5ZbWbapXctyS0TNXdHcNxBIREDZERiY8/vjgVFkQFCWmeH7fr3mxTBznmfO4TBz5jznnO85D8C8USG08pa1qAICCjvzV9JzLT4q776oq7z6v+MAPH9va4a086nhHAlRS3R8FOyc4coxiN0LgI2NjjdGBqPTwf+OxLMv6moNZ7KC/vgWspPJcfHjf3ld8PFwIlDazdrLJxgadwVDPkTeiAHyj6GBuDrYciQule8PxdVgBu/A0W9An4XeqyXfXWuOjQ76tJLOfG0knXlhtW5s22WhUwQL7TyXZAwG9tc+zRl5j+y1LTR1XOxxL5yhYclT7eOuZTOjMBbE8Pa+zBzQsqazJETt4VIX2o/W7u9fbHw4uJEn47v6A/Da+hPkF1hIMDyDAfZ8BEBE3YcpwJa+rWVLulrPGAhvpbZlIdqOMLPvbQ3AvF9PczXTQgZ/DAY48DkAkT5jAB2d/L3wdLGv2XyJGiGdeWG1irbtupqVZzlfQm5x/FIa0788RL5BMaKDH3OGSjAwcYNOp8PfwoPgJWfmMnnZfq5l5RHSyJO3H+4gX7qFqG5d/6r9PPUTpMcbH/7H4EA8ne05nZDBqr0xNZS5Cjq3GZLPgqMHH6aGATL9WADtHgCnOpAWq21ZWGhKj6a08fUgNVvPm79YyJKSs79q/+MO7nyR3R2Q//HaTDrzwmrVc3XA1kaHUlqH3tLEXcvmsRUHyMoroEeLerw9ur0ENhElGCPaW+DIfNp1PZOW7icqOYtGdZxZMikUZwcJeCdEtfMJAf8e2jTkwu3cALxcHfj7kEAA3tl8lstpFrAN5p5FAKS3e5TjyQpbGx09W8mWdLWevTPcU7h7Q2EgPAA7WxveelBbUrL28CV2X0iuoQyWk1Kw4x0A8js/wbZo7T0pW9LVXtKZF1bLxkZHfTcHwPIi2idn5jJ5+X6SMnIJ8nHn04mhONpJJ0eU1KRw3bylTbO/nlfAEysOcPJyOvXdHFn1ZDd8PZ1rOltC1F5dp2o/Dy6H/BsXwCd09aejfx0yc/N55cfjKGXGgcLiI+HiTrCxY4v7AwCE+nvh4STTjwU3AuGd3QhXLxgf7ujvxSPdtCUl//fjcXLzzTgGTVQ4xB8GO2cO+Y4nO6+ABu6OsiVdLSadeWHViqbaW9Je88mZuUz4bC9RSdpo5crHu8oXEVGqgLra9nQxVy0non1evoHpqw5xMCYFDyc7vnyiK83qu9Z0toSo3dr8Bdx9ISsRTv7P+LCtjY4FD7XH3lbH1lOJ/HIsoQYzeRu7tVF5gh9ifbQ2k61fkEw/FoUatIZWg0EZYPcHxZ76x5Ag6rs5EpWUxeKIqBrKYDnseFf7GTqZLTHaEtJ+EhOiVpPOvLBqRUHwLCWifVFH/uyVTLw9tNFKbw+nms6WMGNF29PFWsjIfF6+gWdWRxJxNglne1uWP9aVNr4yoiBEjbO1vxEkbP+SYk+19nZnRj8tMOVr64+Tmm2GS9dS4+DEOgCyO89gzwUtAv+9bbxrMlfC3PSarf088jVk3Lgw5elszyvD2wCwKPw8UUmZNZG7ssXuhZhdYGMPPZ5h+9kkQKbY13bSmRdWrUFRZ94CptknZ+byyGf7jB35b/4aJqOV4raK1szHpVw3+31yc/QFTF91iI0nEnCwtWHJpFBCA7xqOltCiCKdJmsdhT/3a1PWb/J0/xa0bOhGcmYeb24ww0Bhez8BVQDN+rAj3Ye8AgMB9Vxo2dCtpnMmzElAD2jSHQryYO/HxZ4a0cGP3q3qk5dv4O/fH6XA3NrUwrXy3DOeuAIvzidmYmujo5fEhKjVpDMvrNqNkXnznmZf1JE/cyVDOvKiQnw9nbCz0ZGXbyAh3Xz/z7Pz8nly5UG2nU7Eyd6Gzyd3prfsiSuEeXH3hnYPaveLpqwXcrSzZcFDIeh08P2hP9l1zowChaXHw8Gl2v2ez7LlZCIAg9p4y/RjUVLR6PyBZXA91fiwTqdj/kPtcXO043BsKp/vNKPp9vFH4PwW0NlAz1nGUflQfy88nWUpZm0mnXlh1Rp4FK2ZN9+R+bhr2Tz8yW5jR3711O7SkRflZmdrQyMvLXCcuU61z8jRM3nZfnadT8bVwZYVj3WlT2vpyAthlno+o/08vgaSzhZ7KjSgLpO6BwAwZ+0fZOToqzt3pkUshPwc8O9BQbMBbDt9BdA680KU0GowNGwLeRnG/dqLNKrjbJxu/+7ms5y9klETOSxpZ+Fa+eCHoF4Ltp/WLlj1lS3paj3pzAurZu5r5k9dTmfUJ7u5eDWbxl7OfPPXMJo3kCmBomKM6+bNcK/55MxcHvl8HwcupuDuZMeXT3aje/N6NZ0tIURpfEIgaDigYMfCEk//Y2gQjb2c+TPlOnPXn6z+/N3q6gWI/FK7P/BVDselkpKtx9PZns5NZRmPMMFGG90GtOUZ+uJbLo7p3IT+gQ3IKzDw/HdH0RcYqj+PN7tyEk79pN3v9Rw5+gJ2F8aE6C/r5Ws96cwLq1bUmU82w878vqirjFm8x7j93JoZPWREXtwRcw2CF52cxaiPd/PHn2l4udizemp3OvnLl2shzF7fF7Wfx34oMTrv5mjH+2PvwUYHaw7/yYY/LtdABm+yfR4Y8rXR1oAwtp7SRuX7BzbA3la+5opSBD8EdfwhOxkiVxV7qmi6vaezPccupfHJ9gulnKQaKAWbXgIUtB0J3m2JOJvEdX0Bfp5OtPF1r7m8CbMgn3LCqhXtW30lPYccvfnsG7rxeAKTlu0nIyefLk29+HZamEStF3esKAhejBl15g/HpjDq49+JvZZNk7rO/DCjB8GNPGs6W0KI8vBtX+bofJemdXmqMLr9S+uOcTnteok01SLhuHbBAWDA/wGw9aTWmR8oU+xFWWztoEfhkpLdH0BB8SUj3h5OvD6iHQAf/HaO45fSqjuHmnObtb3lbR1g0OsAxgto94X4SkwIIZ15Yd28PRyp7+ZIvkHV3AfxTZRSfLL9AtNXHSI338CgNg358oluErxE3BX/wr3mY81kr/nNJxIYv2QvKdl6Qhp5snZGT1rI8hEhLEsZo/MAzw5qRfvGnqRd1/P374/WzG4a4W8CSgva59uBqKRMLiRlYWejk7XE4vbueQRcG0BqLBxcXuLpkff4MbSdD/kGxd9WR5KZm1+9+SvQw6aXtfvdpkPdZuToC4yzT+5v71u9+RFmSTrzwqrpdDo6+dcBIDI2tUbzkpdv4IUf/mDBxtMATAoL4NNHQ3Gyt63RfAnLZy7T7JVSfBpxgWmFF6v6Bzbgm792N24RKYSwILcZnbe3teE/Y+/B2d6W389fZemu6OrNX9wBOPML6Gyhv9bh+e2UFhSse/N6eDjJRXJxGw4u0O+f2v3tb0H2tWJP63Q65o0KwdfTiejkLF5aewylqvGi1YGlcPUcuNSHPn/Xsnkmiey8AhrVceaeJnWqLy/CbElnXli9joVrdA/HptRYHlKy8nh06T6+P/QnNjp4fUQ73hgZjJ2s5xOVwL9wmn1Ktp70GoounaMvYPa3R5j/62mUggnd/PlsUmdcHe1qJD9CiErQ9wXtZymj880buPHK8LYALNx0msjqameVgi2vavfvmQD1WwEYRywHtZGgYKKcOk3WIttfT9F2RbiFl6sDiyZ0xNZGx/qj8azeH1c9+cq+psWDABjwMjhpy9Q2HNOm2N/fXqbYC430JITVq+mR+RPxaYz4aBf7o6/h7mjHsildmNyjaY3kRVgnN0c76rk6ADUT0T4hLYexi/fw45F4bG10vDGyHW8+IBerhLB4vh1ujM6H/9tkkvFdmzC0nQ/6AsWMVYdJqo6As5FfQuxusHcxLgdIycrjYIx2MUHWy4tys7WDIW9q9w98ZvKiVWhAXV4YEgjA3J9OcDI+verzFbEQclK1Cw0dJwFwPa+A34qm2IfIFHuhkW9awuqFNPbE1kZHQnpOtQfpWRf5Jw99spu4a9dpUteZNU/1oJ9sIyKqQNHofHVPtT8Uc40Ri3Zx9M806rjY8+XjXZkU1lRGDISwFv3+CTobOPk/OL+1xNM6nY63R7enRQNXEtJzmPn1YfKrciuvzETYrAW7o/9LUKcJANvPJlJgUAT5uNOkcOmREOXSYgC0HqbtilD0v3WLqb2bMyCoIXn5Bp7++nDVrp9POqNdWADtQoOtNsNt+5lEsvMKaOzlTPvGElBWaKQzL6yei4MdQT7a1h2HY1Kr5TX1BQbmrj/B7G+PkqM30Ld1A36a2YvW3rKFiKgaAYVfXmOqaWReKcWyXdGMXbyXxIxcWjV0439P96RHy/rV8vpCiGriEwzdZmj3NzxfYk9uAHcnexZP7Iybox37oq8x/9fTVZefX1+EnDTwvedGvrgR4XugTLEXd2Lwv8HGHs5tMnnRysZGx7ujOxjXzz//3ZGqCfpYoId107QLC62HahcaCv1cNMVeotiLm0hnXtQKRXtbV8d6vstp1xm/ZC8rdl8E4JkBLVk2pQt1XByq/LVF7VWdQfAyc/OZuTqSN34+Sb5BcX97X9Y93ZOAeq5V/tpCiBrQ/yXwaAQpF2HH2yaTtGzoxjujOwDw+a5o1h+Nr/x8nN0EJ9ZqQe9GfGAcsYy9ms1vp7Xgd6M6Na781xXWr35L6DZNu7/pZSgoOfKurZ/vhIOtDZtOXGHBpiq4aBWxEOIjtTXy979nfPh6XgHbCgM8ShR7cTPpzItaoWPhuvmqDoIXfjqR+/67k4MxKbg72vHZpM48NzgQWxu5giqqln9hRzr2WtVuT3cmIYMRi3ax4Y/L2NnoeO0vbVk0viNuEuhOCOvl6AbDCoOD/f5fSDxlMtnQYB+e6tcCgBd/+IM//kytvDzkZmozAwDCntLW8xdaueciSkHf1g1kG0xx5/r8A5zrQtJp2PmOySShAV4seDgEgMURUazeH1t5rx+778brDv8PeDYyPhV+JpHr+gKa1HUmpJFMsRc3SGde1ApFI/PH49PJzS+o9PPrCwzM++UUj604QEq2nuBGHvz8TC/ubStBeET1qOqReaUUX+6NYcSiXUQlZeHj4cS308J4rGczme4nRG3QZjgE3qdN//15NhhMr4t/fnAgfVs34Lq+gCnLDxCVlFk5r7/t35AWB3UCoN9Lxoczc/P57oAWYXxKz6aV81qidnKuA8MWaPcjFkD0TpPJHuzYmGcHajsovPLjcXadS777187NgLVTQRmg/TgIHlXs6aJlJPeH+EmbK4qRzryoFQLqueDlYk9evqHSo5DGXs1m7OI9LN4RBcCUHk1ZM6OHTDkW1SqgMABefGoO+koOPpWancf0VYd45cfj5OYb6BfYgA3P9CI0wKtSX0cIYeaGLQR7V4jdA0dWmUxia6Pjo0c60b6xJ9ey8pi4dD9X0nPu7nVP/QT7PtHuD39f2x+80NrDf5KRm0/z+q70bdXg7l5HiPZj4J5HtU71michy3RHfdagVjxwjx/5BsWMrw5x7krG3b3ur3MgNQY8/eG+4lvkZefl89tpiWIvTJPOvKgVdDqdcb/5ytqiTinFmkN/ct8HOzkcm4q7kx2fPtqJuSPa4WhnWymvIUR5NXR3xNHOhgKD4lJK5e3asC/qKvf9dyebTlzB3lbH/93fhmWTu1DPzbHSXkMIYSHqNNHWzwNs/CdcOWkymZujHcundKFZfVcupV5n0tL9pGXr7+w1E47D2sK1zN1mQMuBxqcMBsWK3y8C2qi8jSxpE5XhvoVQPxAyE2DddJOzUHQ6HQsebk+Xpl5k5OQzadl+Libf4TK3Yz8UXhzTwajFxj3li6zYfZEcvYGAei4EN/K4s9cQVks686LWMO43H5d61+dKy9Yzc3Ukz39/lMzcfLo09eKXZ3ozNFiumIqaodPpKnWqfW5+AfN+OcW4z/YSn5ZD03ourJ3Rkyd7N5cvzELUZt2mQ9PekJcJq8dCZpLJZPXcHPni8a40dHfkzJUMnlh5gOy8Cm7nlZUMq8eDPgua99Mijt8k4lwSUclZuDvaSeA7UXkcXGH0crBzgvNbYM+HJpM52tmyeGJnWjZ043JaDmOX7Kn4spJzW7ULBgC9ZkNAj2JPJ2bk8NG284A2G0Cm2ItbSWde1BpFI/OHY+4uCN7Oc0kM/e8OYwCwfwwJ5Ju/hsm+tqLGFU21j7nLzvypy+mMXPQ7i3dEoRSM6dyYn5/pTYjsayuEsLWDMV+AVzNIjYVvH4X8XJNJm9R14YsnuuLhZMfBmBQe+XwfKVl55Xud/Dz4bhKkxWqv9fByY/T6IkWj8mO6NJEgnKJyebeDofO1+7+9AdE7TCar6+rA6qndae3txpX0XMYu2cv5xHJ26GN2a+8fgx7ajYIBJfe4f3fTWbLyCujQpA4jOzQycRJR20lnXtQaHZrUQaeDS6nXSbyD9XuZufn8c+0xJi7dz+W0HJrVd2XNjB483b+lRKsXZsG/rhanYX/0tTs6Pr/AwMfbzzNy0e+cTsignqsDSyaGsvDhDvJFWQhxg0tdmPAdOHpC3F746VlQpvfcDvLxYMXjXfF0ticyNpWHPt3Nnym3ueCoFPz6AsT8Dg7uMP4b7TVvcj4xk4izSeh0MDmsaSUVTIibhE7ROtmGfPhqtLY1ogkN3B1ZPbU7QT7uJGXkMm7J3tuvoY8/Al+Phfzr0GowPLgYbIov0Tx+KY3vDmnBHV8d3lZmxQmTpDMvag03RzsCvd0BOFzBdfO/n09myPs7jFuQTOnRlA3P9KJDkzqVnEsh7tyIe/zQ6eCno/HsuXC1QseeupzOgx/vZuHGM+QVGBjUxptNs/swuJ1PFeVWCGHRGrTWpiLrbOHoatj1XqlJO/l78cP0MPw8nYhKymLUx7s5dbmUYLT5efC/p+HQckAHD30ODYNKJFu6Sws6OzDIG/96MjNOVAGdDh74GFoPhfwc+GaCtr7dhHpujnw9tTttfT1Izszl4U/3EH460fR5E0/BqlGQmw4BPbWZLnYOxZIopXjj55MoBSM6+EnAWVEq6cyLWqWjcd18+abap2Tl8eIPf/DI5/u4lHqdxl7OrJ7anbkj2uHiICOVwrzc06QOj3TzB+DldcfKtQ1jXr6B97ac5S8f7uLYpTQ8nOx4++H2fDYplPoS5E4IUZaWA29s5fXbG7Dh76VOuW/l7c6ap3oQ6O1OYkYuYz7dw+YTCcUTZV+DLx+EI19pFwmGvw+BQ0uca+muaFbv10Ysn+jVrFKLJEQx9s4wdhWEjNZG6Nc8CQeXmUxa19WBr6d2o0OTOqRd1/PYigO8vek0+UU7zCgFB5bCZwMg+yr4ddRmndg7lzjXxuMJ7I++hqOdDS8OK3kxS4gi0pkXtYoxon1MapnplFJ8fzCOAe9u59uD2heGR7r5s2lWH8Ja1KvqbApxx/4xJIgG7o5EJWfxyfYLZaaNOJvEfR/s5IPfzpFvUAxp583W5/oyunMTCbIjhCifrlNv7Pt+4DNYfh+k/Wkyqa+nM99NC6Nr07pk5Obz1y8P8bfVkVzNzIXk8/D5IIjZpU2tn/AddH6sxDlW7Y3hXz9rUfSfHdhK2mRR9Wzt4cEl0OVJQMHPs7Vb+uUSSeu4OPDdtO5M7B4AwEfhF3h06T6SL1+Erx6GDc+BPlsLIvnIGnAqGZ0+R1/AW7+eAmBan+Y0qlOysy9EEZ1SpSxyMgPp6el4enqSlpaGh4dsxSDu3vnEDAa9twMnext+mtmLVoXT7m92KCaFBRtPG9cdB3q78+aDwXRuWrdEWiHM0c9/xDPz60gcbG34dVZvWjRwK/b8haRM/v3zScLPaFGo67k68MbIYO4L8ZFOvJmz1nbRWstVq5zdBGunQk4auNSDUUug5SCTSXP0Bby/9Syf7YjCTWUy1Xk70+x+xkGfru2zPeFb8G5b4rjvDsbxwg9/ADC9bwteHBoon1mi+igF2/4FO9/Vfrdz0i5m9ZwNriUvKq0/Gs9/1myjd8F+ZtuvoQ6ZKFtHdIPmartC2JQcU90ffY2X1x3jXGIm3h6OhP+9n8wEraXK2y5KZ17UKgaDovfCcC6lavtwDwv24en+LQn0cefX4wks2xXNkcKt65ztbZk1qBWP92qGva1MYhGWQynFYysOsP1MEmHN6/H11G5cSc/lcGwKO88l8/3BOPINCjsbHVN6NOVvA1vh6Wxf09kW5WCt7aK1lqvWSbmoRaC/fFT73TsYQh6G4Iegjn/xtGmXSNryHq7Hv8IFrU0+ZRvI750/oG+ndrRs6IZOp0NfYCAqKYsdZ5N469dTKAWP9WzKq8PbSkde1IzonVqnPm6f9ruDG7ToD+5+4O4D7r5w7QKc3QgJx4yHHTM05f90z9AzrCeP9WxGA/cbS9lSsvKY9+spvjuozWqp5+rAh+M70qNl/WotmjAfNd6Zv3jxIv/617/Ytm0bCQkJ+Pn58eijj/Lyyy/j4OBw+xMgjbuoGheSMnl74xk23rRWr46LPanZegAc7GwY2cGPZwe1orGXBNURlinuWjb3vh9Bjt5AfTdHkjOLr2Md1KYhL93Xhua3jNoL82at7aK1lqtW0ufA5pfh8BdQcNM2dN4hgIKcdG30Pjdd+x1IdmnJ/PQh/JjfjXy0UcjmDVxxtrfl3JVM8orWHAMTuvnz5gPB0pEXNUspOL9V69QXXbwySYehcReOefbnhdhunEm6sZuSo50N7k72eDjZkZyZS3pOPgDju/ozZ2gQni5ykb02q/HO/MaNG/n2228ZP348LVu25Pjx40ydOpWJEyfyzjvvlOsc0riLqnT2SgYfhZ/np6PxGBTUd3NkYvcAHunuL4G/hFX4NOIC8389DYCNTtsiKjTAi2HBPnK130JZa7toreWq1a6nwMn1cOx7uLiLoo57MU17Q89noeUgrmXr2XryChtPJLDrXHKxDrybox1BPu4MaNOQ6X1ayBZdwnwoBVHbIfkcZMRr6+gzLmtLTVoPgZb3GqfgGwyKLaeu8HH4eY7+mVbiVIHe7rw1KpjQAFnWKcygM2/K22+/zSeffEJUVFS50kvjLqpD7NVsYq9l06WZF452trc/QAgLYTAoNp9MwMPZng6N6+Aqe8VbPGttF621XKJQ2iWIPwwOrtre9E4e4FzX5DpjgIwcPb+fTwZ0tPX1oLGXs3TghVVJy9aTnqMnIyefzNx8DEoRGuAlyzqFUXnbxWr9ZpeWlkbduqVfbcrNzSU398ZU0PT0UvYgFaIS+ddzkT1qhVWysdExNNi3prMhLMibb77Jhg0bOHLkCA4ODqSmpt72GKUUr7/+OkuWLCElJYVu3brx0Ucf0a5du6rPsLAMno20Wzm5O9nLZ5ewap4u9jKNXlSKarv8c+HCBT788EOmT59eapp58+bh6elpvDVp0qS6sieEEELUenl5eYwePZoZM2aU+5iFCxfy3nvvsWjRIg4cOICPjw/33nsvGRkZVZhTIYQQQlS4Mz937lx0Ol2Zt4MHDxY7Jj4+nqFDhzJ69GiefPLJUs/9z3/+k7S0NOMtLi6u4iUSQgghxB15/fXXmT17NiEhIeVKr5TiP//5Dy+//DKjRo0iODiYlStXkp2dzddff13FuRVCCCFqtwpPs585cybjxo0rM03Tpk2N9+Pj4+nfvz9hYWEsWbKkzOMcHR1xdJTAY0IIIYQliI6OJiEhgcGDBxsfc3R0pG/fvuzevZtp06aZPE6W1QkhhBB3r8Kd+fr161O/fvmiIF+6dIn+/fsTGhrK8uXLsbGRoA5CCCGEtUhI0Lb49Pb2Lva4t7c3MTExpR43b948Xn/99SrNmxBCCGHtqqx3HR8fT79+/WjSpAnvvPMOSUlJJCQkGBt+IYQQQlS9O1keV1G37vmtlCpzH3BZVieEEELcvSqLZr9582bOnz/P+fPnady4cbHnqnE3PCGEEKJWq+jyuIrw8fEBtBF6X98b0ccTExNLjNbfTJbVCSGEEHevyjrzU6ZMYcqUKXd1jqJOv6ylE0IIIW60hxW5KF6R5XEV1axZM3x8fNiyZQsdO3YEtIj4ERERLFiwoNznkfZeCCGEuKG87X217jNfUUXb2sgWdUIIIcQNGRkZeHp6Vvp5Y2NjuXbtGrGxsRQUFHDkyBEAWrZsiZubGwBBQUHMmzePBx98EJ1Ox6xZs3jrrbdo1aoVrVq14q233sLFxYUJEyZUqDwg7b0QQghxs9u192bdmffz8yMuLg53d/cy195VRHp6Ok2aNCEuLg4PD49KOWdNsaaygJTHnFlTWcC6ymNNZQEpz+0opcjIyMDPz68SclfSq6++ysqVK42/F422h4eH069fPwDOnDlDWlqaMc0LL7zA9evXeeqpp0hJSaFbt25s3rwZd3f3cr9uZbf38n9kvqypLCDlMWfWVBawrvJYU1mgaspT3vberDvzNjY2JdbbVxYPDw+r+OcB6yoLSHnMmTWVBayrPNZUFpDylKUqRuSLrFixghUrVpSZ5tYpfzqdjrlz5zJ37tw7ft2qau/l/8h8WVNZQMpjzqypLGBd5bGmskDll6c87b3sFSeEEEIIIYQQQlgY6cwLIYQQQgghhBAWptZ15h0dHXnttdesYkscayoLSHnMmTWVBayrPNZUFpDyiMphbX93ayqPNZUFpDzmzJrKAtZVHmsqC9RseXRKNn0XQgghhBBCCCEsSq0bmRdCCCGEEEIIISyddOaFEEIIIYQQQggLI515IYQQQgghhBDCwkhnXgghhBBCCCGEsDDSmRdCCCGEEEIIISyMVXbmP/74Y5o1a4aTkxOhoaHs3LmzzPQRERGEhobi5ORE8+bN+fTTT6spp6WbN28eXbp0wd3dnYYNG/LAAw9w5syZMo/Zvn07Op2uxO306dPVlOvSzZ07t0S+fHx8yjzGHOulSNOmTU3+rZ9++mmT6c2pbnbs2MFf/vIX/Pz80Ol0/Pjjj8WeV0oxd+5c/Pz8cHZ2pl+/fpw4ceK2512zZg1t27bF0dGRtm3bsm7duioqQXFllUev1/Piiy8SEhKCq6srfn5+TJo0ifj4+DLPuWLFCpP1lZOTU2NlAZgyZUqJPHXv3v225zXHugFM/o11Oh1vv/12qeesqbopz2eypb13LJ01tPVgXe29tPXmVS/W1N5bU1sP0t5Le1959WN1nflvv/2WWbNm8fLLLxMZGUnv3r0ZNmwYsbGxJtNHR0dz33330bt3byIjI3nppZd45plnWLNmTTXnvLiIiAiefvpp9u7dy5YtW8jPz2fw4MFkZWXd9tgzZ85w+fJl461Vq1bVkOPba9euXbF8HTt2rNS05lovRQ4cOFCsLFu2bAFg9OjRZR5nDnWTlZVFhw4dWLRokcnnFy5cyHvvvceiRYs4cOAAPj4+3HvvvWRkZJR6zj179jB27FgmTpzI0aNHmThxImPGjGHfvn1VVQyjssqTnZ3N4cOHeeWVVzh8+DBr167l7NmzjBgx4rbn9fDwKFZXly9fxsnJqSqKYHS7ugEYOnRosTz98ssvZZ7TXOsGKPH3XbZsGTqdjoceeqjM89ZE3ZTnM9nS3juWzFraerC+9l7aevOpF2tq762prQdp76W9r8T6UVama9euavr06cUeCwoKUnPmzDGZ/oUXXlBBQUHFHps2bZrq3r17leXxTiQmJipARURElJomPDxcASolJaX6MlZOr732murQoUO501tKvRR59tlnVYsWLZTBYDD5vLnWDaDWrVtn/N1gMCgfHx81f/5842M5OTnK09NTffrpp6WeZ8yYMWro0KHFHhsyZIgaN25cpee5LLeWx5T9+/crQMXExJSaZvny5crT07NyM1dBpsoyefJkNXLkyAqdx5LqZuTIkWrAgAFlpjGHulGq5Geypb93LI21tvVKWXZ7L229edaLUtbV3ltTW6+UtPelMZf6Mff23qpG5vPy8jh06BCDBw8u9vjgwYPZvXu3yWP27NlTIv2QIUM4ePAger2+yvJaUWlpaQDUrVv3tmk7duyIr68vAwcOJDw8vKqzVm7nzp3Dz8+PZs2aMW7cOKKiokpNayn1Atr/3apVq3j88cfR6XRlpjXXuikSHR1NQkJCsb+9o6Mjffv2LfU9BKXXV1nH1JS0tDR0Oh116tQpM11mZiYBAQE0btyY4cOHExkZWT0ZvI3t27fTsGFDWrduzdSpU0lMTCwzvaXUzZUrV9iwYQNPPPHEbdOaQ93c+plcG9475sKa23qw/PZe2nrzrJdbWftnlqW39SDtPZhH/Zh7e29Vnfnk5GQKCgrw9vYu9ri3tzcJCQkmj0lISDCZPj8/n+Tk5CrLa0UopXjuuefo1asXwcHBpabz9fVlyZIlrFmzhrVr1xIYGMjAgQPZsWNHNebWtG7duvHFF1+wadMmPvvsMxISEujRowdXr141md4S6qXIjz/+SGpqKlOmTCk1jTnXzc2K3icVeQ8VHVfRY2pCTk4Oc+bMYcKECXh4eJSaLigoiBUrVrB+/XpWr16Nk5MTPXv25Ny5c9WY25KGDRvGV199xbZt23j33Xc5cOAAAwYMIDc3t9RjLKVuVq5cibu7O6NGjSoznTnUjanPZGt/75gTa23rwfLbe2nrzbNeTLHmzyxLb+tB2nswj/qxhPbe7q6ONlO3XjFVSpV5FdVUelOP15SZM2fyxx9/sGvXrjLTBQYGEhgYaPw9LCyMuLg43nnnHfr06VPV2SzTsGHDjPdDQkIICwujRYsWrFy5kueee87kMeZeL0WWLl3KsGHD8PPzKzWNOdeNKRV9D93pMdVJr9czbtw4DAYDH3/8cZlpu3fvXizQTM+ePenUqRMffvghH3zwQVVntVRjx4413g8ODqZz584EBASwYcOGMhtFc68bgGXLlvHII4/cdi2cOdRNWZ/J1vjeMVfW1taD5bf30tabZ72Uxdo+s6yhrQdp78E86scS2nurGpmvX78+tra2Ja5wJCYmlrgSUsTHx8dkejs7O+rVq1dleS2vv/3tb6xfv57w8HAaN25c4eO7d+9uFlcYb+Xq6kpISEipeTP3eikSExPD1q1befLJJyt8rDnWTVHU4Yq8h4qOq+gx1Umv1zNmzBiio6PZsmVLmVfqTbGxsaFLly5mV1++vr4EBASUmS9zrxuAnTt3cubMmTt6H1V33ZT2mWyt7x1zZI1tPVhney9tvXnWC1jnZ5a1tvUg7T1Ie18aq+rMOzg4EBoaaow2WmTLli306NHD5DFhYWEl0m/evJnOnTtjb29fZXm9HaUUM2fOZO3atWzbto1mzZrd0XkiIyPx9fWt5NzdvdzcXE6dOlVq3sy1Xm61fPlyGjZsyP3331/hY82xbpo1a4aPj0+xv31eXh4RERGlvoeg9Poq65jqUtS4nzt3jq1bt97RF0SlFEeOHDG7+rp69SpxcXFl5suc66bI0qVLCQ0NpUOHDhU+trrq5nafydb43jFX1tTWg3W399LWm2e9gPV9ZllzWw/S3oO092Vl2Kp88803yt7eXi1dulSdPHlSzZo1S7m6uqqLFy8qpZSaM2eOmjhxojF9VFSUcnFxUbNnz1YnT55US5cuVfb29uqHH36oqSIopZSaMWOG8vT0VNu3b1eXL1823rKzs41pbi3L+++/r9atW6fOnj2rjh8/rubMmaMAtWbNmpooQjHPP/+82r59u4qKilJ79+5Vw4cPV+7u7hZXLzcrKChQ/v7+6sUXXyzxnDnXTUZGhoqMjFSRkZEKUO+9956KjIw0RnydP3++8vT0VGvXrlXHjh1T48ePV76+vio9Pd14jokTJxaLGv37778rW1tbNX/+fHXq1Ck1f/58ZWdnp/bu3Vuj5dHr9WrEiBGqcePG6siRI8XeS7m5uaWWZ+7cuWrjxo3qwoULKjIyUj322GPKzs5O7du3r8bKkpGRoZ5//nm1e/duFR0drcLDw1VYWJhq1KiRRdZNkbS0NOXi4qI++eQTk+cwl7opz2eypb13LJm1tPVKWVd7L229edWLNbX31tTW36480t5rpL0vH6vrzCul1EcffaQCAgKUg4OD6tSpU7HtXSZPnqz69u1bLP327dtVx44dlYODg2ratGmp/2TVCTB5W758uTHNrWVZsGCBatGihXJyclJeXl6qV69easOGDdWfeRPGjh2rfH19lb29vfLz81OjRo1SJ06cMD5vKfVys02bNilAnTlzpsRz5lw3RVvn3HqbPHmyUkrbcuO1115TPj4+ytHRUfXp00cdO3as2Dn69u1rTF/k+++/V4GBgcre3l4FBQVV25eXssoTHR1d6nspPDy81PLMmjVL+fv7KwcHB9WgQQM1ePBgtXv37hotS3Z2tho8eLBq0KCBsre3V/7+/mry5MkqNja22DkspW6KLF68WDk7O6vU1FST5zCXuinPZ7KlvXcsnTW09UpZV3svbb151Ys1tffW1NbfrjzS3mukvS8fXWGmhRBCCCGEEEIIYSGsas28EEIIIYQQQghRG0hnXgghhBBCCCGEsDDSmRdCCCGEEEIIISyMdOaFEEIIIYQQQggLI515IYQQQgghhBDCwkhnXgghhBBCCCGEsDDSmRdCCCGEEEIIISyMdOaFEEIIIYQQQggLI515IYQQQgghhBDCwkhnXgghhBBCCCGEsDDSmRdCCCGEEEIIISzM/wPaHri0rSz6CgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pars=res.x\n", + "\n", + "ode_est = common_models.FitzHugh([('a', pars[0]), ('b', pars[1]), ('c', pars[2])])\n", "\n", - "Then we can find both states as target at the same time.\n" + "x0_est = [pars[3], pars[4]]\n", + "ode_est.initial_values = (x0_est, t[0])\n", + "\n", + "solution_est = ode_est.integrate(t[1::])\n", + "\n", + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 2.5))\n", + "\n", + "axarr[0].plot(t, solution[:,0], color='C0')\n", + "axarr[0].plot(t, solution_est[:,0], color='C1')\n", + "axarr[1].plot(t, solution[:,1], color='C0')\n", + "axarr[1].plot(t, solution_est[:,1], color='C1');" + ] + }, + { + "cell_type": "markdown", + "id": "af2b3afa", + "metadata": {}, + "source": [ + "Assume we know both states:" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "869a5561", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH\n", + " success: True\n", + " status: 0\n", + " fun: 3.9102434290500006e-10\n", + " x: [ 2.000e-01 2.000e-01 3.000e+00 -1.000e+00 1.000e+00]\n", + " nit: 50\n", + " jac: [ 5.228e-04 8.604e-05 2.292e-04 -1.938e-04 1.487e-04]\n", + " nfev: 67\n", + " njev: 67\n", + " hess_inv: <5x5 LbfgsInvHessProduct with dtype=float64>\n" + ] + } + ], "source": [ - "objFH = SquareLoss(theta, ode, x0, t0, t, solution[1::,:], ['V','R'])\n", + "objFH = SquareLoss(theta, ode,\n", + " t0=t[0], x0=x0,\n", + " t=t[1::], y=solution[1::,:],\n", + " state_name=['V','R'])\n", "\n", "res = scipy.optimize.minimize(fun=objFH.costIV, \n", " jac=objFH.sensitivityIV, \n", @@ -212,7 +289,31 @@ " bounds=boxBounds, \n", " method='L-BFGS-B')\n", "\n", - "print(res)\n" + "print(res)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d2413973", + "metadata": {}, + "outputs": [], + "source": [ + "pars=res.x\n", + "\n", + "ode_est = common_models.FitzHugh([('a', pars[0]), ('b', pars[1]), ('c', pars[2])])\n", + "\n", + "x0_est = [pars[3], pars[4]]\n", + "ode_est.initial_values = (x0_est, t[0])\n", + "\n", + "solution_est = ode_est.integrate(t[1::])\n", + "\n", + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 2.5))\n", + "\n", + "axarr[0].plot(t, solution[:,0], color='C0')\n", + "axarr[0].plot(t, solution_est[:,0], color='C1')\n", + "axarr[1].plot(t, solution[:,1], color='C0')\n", + "axarr[1].plot(t, solution_est[:,1], color='C1')" ] }, { @@ -220,20 +321,108 @@ "id": "3c045544", "metadata": {}, "source": [ - "\n", "See the difference between the two estimates with the latter method; both states\n", - "were used, yielding superior estimates. Note that only the forward\n", + "were used, yielding superior estimates.\n", + "Note that only the forward\n", "sensitivity method is implemented when estimating the initial value, and\n", "it is assumed that the starting condition for all the states are\n", "unknown.\n", "\n", "The choice of algorithm here is the **L-BFGS-B** which is a better\n", - "choice because the parameter space of the FitzHugh is rough (i.e. large\n", - "second derivative) as well as being multimodal. This means that the\n", + "choice because the parameter space of the FitzHugh is rough. This means that the\n", "Hessian is not guaranteed to be positive definite and approximation\n", "using $J^{\\top}J$ is poor, with $J$ being the Jacobian of the objective\n", "function." ] + }, + { + "cell_type": "markdown", + "id": "886bf54a", + "metadata": {}, + "source": [ + "## Obtaining good initial values for parameters via Function Interpolation\n", + "\n", + "When we want to fit the model to data, one of the necessary steps is to supply the optimization procedure a good set of initial guess for the parameters $\\theta$.\n", + "This may be a challenge when we do have a good understanding of the process we are trying to model.\n", + "\n", + "A method to obtain such initial guess based on the collocation is available in this package.\n", + "A restriction is that data must be present for all states.\n", + "Demonstrate with previous example." + ] + }, + { + "cell_type": "markdown", + "id": "5150a1d6", + "metadata": {}, + "source": [ + "Below, we try to find the initial guess without supplying any further\n", + "information. The underlying method fits a cubic spline against the\n", + "observation and tries to minimize the difference between the first\n", + "derivative of the spline and the function of the ode. Varying degree of\n", + "smoothness penalty is applied to the spline and the best set of\n", + "parameters is the ones that yields the smallest total error, combining\n", + "both the fit of the spline against data and the spline against the ode.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "fb377637", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.20048258 0.19918548 2.98409032]\n" + ] + } + ], + "source": [ + "from pygom import get_init\n", + "\n", + "theta, sInfo = get_init(solution[1::,:], t[1::], ode, theta=None, full_output=True)\n", + "\n", + "print(theta)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "ab55101a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: Solution found.\n", + " success: True\n", + " status: 0\n", + " fun: 0.06821816133192726\n", + " x: 9.734744556902422e-05\n", + " nit: 30\n", + " nfev: 30\n" + ] + } + ], + "source": [ + "print(sInfo)" + ] + }, + { + "cell_type": "markdown", + "id": "f6b7bf0c", + "metadata": {}, + "source": [ + "\n", + "As seen above, we have obtained a very good guess of the parameters, in\n", + "fact almost the same as the generating process. The information\n", + "regarding the smoothing factor shows that the amount of penalty used is\n", + "small, which is expected given that we use the solution of the ode as\n", + "observations." + ] } ], "metadata": { @@ -243,8 +432,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/paramfit/generate_synth_data.ipynb b/docs/notebooks/paramfit/generate_synth_data.ipynb new file mode 100644 index 00000000..7faef9e8 --- /dev/null +++ b/docs/notebooks/paramfit/generate_synth_data.ipynb @@ -0,0 +1,108 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 44, + "id": "14b112be", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "##########################################\n", + "# Code to generate synthetic epidemic data\n", + "# for notebook parameter fitting example\n", + "##########################################\n", + "\n", + "import numpy as np\n", + "from pygom import common_models\n", + "\n", + "# Initial conditions and total population\n", + "i0=5 # initial number of infected individuals\n", + "n_pop=1e4 # total population size\n", + "x0 = [n_pop-i0, 0, i0, 0] # [s0, e0, i0, r0]\n", + "# x0 = [n_pop-i0, i0, 0] # [s0, i0, r0]\n", + "\n", + "# Params\n", + "paramEval=[('beta', 0.35), ('alpha', 0.5), ('gamma', 0.25), ('N', n_pop)]\n", + "# paramEval=[('beta', 0.35), ('gamma', 0.25), ('N', n_pop)]\n", + "\n", + "# Time range and increments\n", + "tmax=200 # maximum time over which to run solver\n", + "dt=1 # timestep\n", + "n_timestep=int(tmax/dt)+1 # number of time points\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", + "\n", + "initEval=(x0, t[0])\n", + "\n", + "# Set up pygom object\n", + "ode = common_models.SEIR_N_stochastic(param=paramEval, init=initEval)\n", + "# ode = common_models.SIR_N_stochastic(param=paramEval, init=initEval)\n", + "\n", + "# Simulate\n", + "np.random.seed(123)\n", + "sol, simT = ode.solve_stochast(t, iteration=1, full_output=True)\n", + "\n", + "# Process output\n", + "sol_inf=sol[0][:,2] # infecteds\n", + "sol_rec=sol[0][:,3] # infecteds\n", + "\n", + "# Strip down data to just points where infecteds are non zero\n", + "epi=sol_inf>0 # time points where infecteds are non zero\n", + "sol_inf=sol_inf[epi]\n", + "sol_rec=sol_rec[epi]\n", + "t=t[epi]\n", + "\n", + "# save result\n", + "out = np.vstack((t, sol_inf, sol_rec))\n", + "out=np.transpose(out)\n", + "np.savetxt('seir_epi_data.txt', out, fmt='%f')\n", + "\n", + "\n", + "import matplotlib.pyplot as plt\n", + "f, axarr = plt.subplots(layout='constrained')\n", + "axarr.scatter(t, sol_inf)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/paramfit/gradient.ipynb b/docs/notebooks/paramfit/gradient.ipynb index 90369963..be41e055 100644 --- a/docs/notebooks/paramfit/gradient.ipynb +++ b/docs/notebooks/paramfit/gradient.ipynb @@ -77,7 +77,7 @@ "\n", "import copy, time, numpy\n", "\n", - "Iode = common_models.SIR()\n", + "ode = common_models.SIR()\n", "\n", "paramEval = [('beta',0.5), ('gamma',1.0/3.0) ]\n", "\n", diff --git a/docs/notebooks/paramfit/mle_ci_theory.ipynb b/docs/notebooks/paramfit/mle_ci_theory.ipynb new file mode 100644 index 00000000..dc3d264c --- /dev/null +++ b/docs/notebooks/paramfit/mle_ci_theory.ipynb @@ -0,0 +1,483 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "57f2bb3f", + "metadata": {}, + "source": [ + "# Confidence Interval of Estimated Parameters\n", + "\n", + "The easiest way to do this is by invoking the normality argument and use Fisher information of the likelihood.\n", + "As explained previously at the bottom of {ref}`gradient:hessian`, we can find the Hessian, $\\mathbf{H}$, or the approximated Hessian for the estimated parameters.\n", + "From the Cramer--Rao inequality, we know that\n", + "\n", + "$$Var(\\hat{\\theta}) \\ge \\frac{1}{I(\\theta)},$$\n", + "\n", + "where $I(\\theta)$ is the Fisher information, which is the Hessian subject to regularity condition.\n", + "Given the Hessian, computing the confidence intervals is trivial.\n", + "Note that this is also known as the asymptotic confidence interval where the normality comes from invoking the CLT.\n", + "There are other ways of obtaining a confidence intervals, we will the ones implemented in the package." + ] + }, + { + "cell_type": "markdown", + "id": "f4d8f8c5", + "metadata": {}, + "source": [ + "## Asymptotic\n", + "\n", + "When the estimate is obtained say, under a square loss or a normal\n", + "assumption, the corresponding likelihood can be written down. In\n", + "such a case, the likelihood ratio test under a Chi--squared distribution is\n", + "\n", + "$$2 (\\mathcal{L}(\\hat{\\boldsymbol{\\theta}}) - \\mathcal{L}(\\boldsymbol{\\theta})) \\le \\chi_{1 - \\alpha}^{2}(k)$$\n", + "\n", + "where $1-\\alpha$ is the size of the confidence region and $k$ is the\n", + "degree of freedom. The corresponding asymptotic confidence interval for\n", + "parameter $j$ can be derived as\n", + "\n", + "$$\\hat{\\theta}_{j} \\pm \\sqrt{\\chi_{1 - \\alpha}^{2}(k) H_{i,i}}.$$\n", + "\n", + "A point-wise confidence interval is obtained when $k = 1$. We assume in\n", + "our package that a point-wise confidence interval is desired. This can be\n", + "obtained with the following steps.\n" + ] + }, + { + "cell_type": "markdown", + "id": "19e92acb", + "metadata": {}, + "source": [ + "\n", + "## Profile Likelihood\n", + "\n", + "Another approach to calculate the confidence interval is to tackle one\n", + "parameter at a time, treating the rest of them as nuisance parameters,\n", + "hence the term *profile*. Let $\\mathcal{L}(\\boldsymbol{\\theta})$ be our\n", + "log--likelihood with parameter $\\boldsymbol{\\theta}$. Element\n", + "$\\theta_{j}$ is our parameter of interest and $\\boldsymbol{\\theta}_{-j}$\n", + "represents the complement such that\n", + "$\\boldsymbol{\\theta} = \\theta_{j} \\cup \\boldsymbol{\\theta}_{-j}$. For\n", + "simply models such as linear regression with only regression\n", + "coefficients $\\boldsymbol{\\beta}$, then\n", + "$\\boldsymbol{\\theta} = \\boldsymbol{\\beta}$.\n", + "\n", + "To shorten the notation, let\n", + "\n", + "$$\\mathcal{L}(\\boldsymbol{\\theta}_{-j} \\mid \\theta_{j}) = \\max \\mathcal{L}(\\boldsymbol{\\theta}_{-j} \\mid \\theta_{j})$$\n", + "\n", + "which is the maxima of $\\boldsymbol{\\theta}_{-j}$ given $\\theta_{j}$.\n", + "$\\hat{\\boldsymbol{\\theta}}$ denotes the MLE of the parameters as usual.\n", + "The profile--likelihood based confidence interval for $\\theta_{j}$ is\n", + "defined as\n", + "\n", + "$$\\begin{aligned}\n", + "\\theta_{j}^{U} &= \\sup \\left\\{ \\mathcal{L}(\\hat{\\boldsymbol{\\theta}}) - \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j}) \\le \\frac{1}{2} \\chi_{1 - \\alpha}^{2}(1) \\right\\} \\\\\n", + "\\theta_{j}^{L} &= \\inf \\left\\{ \\mathcal{L}(\\hat{\\boldsymbol{\\theta}}) - \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j}) \\le \\frac{1}{2} \\chi_{1 - \\alpha}^{2}(1) \\right\\}\n", + "\\end{aligned}$$\n", + "\n", + "where again we have made use of the normal approximation, but without\n", + "imposing symmetry. The set of equations above automatically implies that\n", + "the interval width is $\\theta_{j}^{U} - \\theta_{j}^{L}$ and\n", + "\n", + "$$\\mathcal{L}(\\hat{\\boldsymbol{\\theta}}) - \\frac{1}{2} \\chi_{1-\\alpha}^{2}(1) - \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j}) = 0.$$\n", + "\n", + "As mentioned previously, $\\boldsymbol{\\theta}_{-j}$ is the maximizer of\n", + "the nuisance parameters, which has a gradient of zero. Combining this\n", + "with the equation above yields a non-linear system of equations of size\n", + "$p$,\n", + "\n", + "$$\\begin{aligned}\n", + "g(\\boldsymbol{\\theta}) = \\left[ \\begin{array}{c} \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j}) - c \\\\ \\frac{\\partial \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j})}{\\partial \\boldsymbol{\\theta}_{-j}} \\end{array} \\right] = 0\n", + "\\end{aligned}$$\n", + "\n", + "where\n", + "$c = \\mathcal{L}(\\hat{\\boldsymbol{\\theta}}) + \\frac{1}{2} \\chi_{1-\\alpha}^{2}(1)$.\n", + "Solving this set of system of equations only need simple Newton like\n", + "steps, possibly with correction terms as per {cite:t}`Venzon1988`. We\n", + "provide a function to obtain such estimate, {func}`ci.profile`" + ] + }, + { + "cell_type": "markdown", + "id": "ecd49905", + "metadata": {}, + "source": [ + "but unfortunately this is not accurate most of the time due to the\n", + "complicated surface at locations not around $\\hat{\\theta}$. This is a\n", + "common scenario for non--linear least square problems because the\n", + "Hessian is not guaranteed to be a PSD everywhere. Therefore, a safeguard\n", + "is in place to obtain the $\\theta_{j}^{U},\\theta_{j}^{L}$ by iteratively updating $\\theta_{j}$ and find the solution to `nuisanceOptim`.\n", + "\n", + "#TODO what is nuisance optim?\n", + "\n", + "Furthermore, we also provide the functions necessary to obtain the\n", + "estimates such as the four below." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e58e47ee", + "metadata": {}, + "outputs": [], + "source": [ + "i = 0\n", + "\n", + "funcF = ci._profileF(xhat, i, 0.05, objSIR)\n", + "\n", + "funcG = ci._profileG(xhat, i, 0.05, objSIR)\n", + "\n", + "funcGC = ci._profileGSecondOrderCorrection(xhat, i, alpha, objSIR)\n", + "\n", + "funcH = ci._profileH(xhat, i, 0.05, objSIR)" + ] + }, + { + "cell_type": "markdown", + "id": "f2428994", + "metadata": {}, + "source": [ + "Where $i$ is the index of the parameter of interest. {func}`_profileF` is the\n", + "squared norm of {obj}`obj`, which easy the optimization process for solvers\n", + "which requires a converted form from system of equations to non-linear\n", + "least squares. {func}`_profileG` is the system of equations of {obj}`obj`,\n", + "and {func}`_profileH` is the derivative of {obj}`obj`.\n", + "\n", + "$$\\begin{aligned}\n", + "\\nabla g(\\boldsymbol{\\theta}) = \\left[ \\begin{array}{c} \\frac{\\partial \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j})}{\\partial \\theta_{j}} \\\\ \\frac{\\partial^{2} \\mathcal{L}(\\boldsymbol{\\theta} \\mid \\theta_{j})}{\\partial \\boldsymbol{\\beta}_{-j} \\partial \\theta_{j}} \\end{array} \\right]\n", + "\\end{aligned}$$\n", + "\n", + "{func}`_profileGSecondOrderCorrection` is the second order correction {cite}Venzon1988.\n", + "\n", + "## Geometric profile likelihood\n", + "\n", + "Due to the difficulty in obtain a profile likelihood via the standard\n", + "Newton like steps, we also provide a way to generate a similar result\n", + "using the geometric structure of the likelihood surface. We follow the\n", + "method in {cite:t}`Moolgavkar1987`, which involves solving a set of\n", + "differential equations\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{d\\beta_{j}}{dt} &= k g^{-1/2} \\\\\n", + "\\frac{d\\boldsymbol{\\beta}_{-j}}{dt} &= \\frac{d\\boldsymbol{\\beta}_{-j}}{d\\beta_{j}} \\frac{d\\beta_{j}}{dt},\n", + "\\end{aligned}$$\n", + "\n", + "where $k = \\Phi(1-\\alpha)$ is the quantile we want to obtain under a\n", + "normal distribution, and\n", + "\n", + "$$\\begin{aligned}\n", + "g = J_{\\beta_{j}}^{\\top} I^{\\boldsymbol{\\beta}} J_{\\beta_{j}}, \\quad J_{\\beta_{j}} = \\left( \\begin{array}{c} 1 \\\\ \\frac{d\\boldsymbol{\\beta}_{-j}}{d\\beta_{j}} \\end{array} \\right).\n", + "\\end{aligned}$$\n", + "\n", + "Here, $J_{\\beta_{j}}$ is the Jacobian between $\\beta_{j}$ and\n", + "$\\boldsymbol{\\beta}_{-j}$ with the term\n", + "\n", + "$$\\frac{d\\boldsymbol{\\beta}_{-j}}{d\\beta_{j}} = -\\left( \\frac{\\partial^{2} \\mathcal{L}}{\\partial \\boldsymbol{\\beta}_{-j}\\partial \\boldsymbol{\\beta}_{-j}^{\\top} } \\right)^{-1} \\frac{\\partial^{2} \\mathcal{L}}{\\partial \\beta_{j} \\partial \\beta_{-j}^{\\top}}$$\n", + "\n", + "and hence the first element is $1$ (identity transformation).\n", + "$I^{\\boldsymbol{\\beta}}$ is the Fisher information of\n", + "$\\boldsymbol{\\beta}$, which is\n", + "\n", + "$$I^{\\boldsymbol{\\beta}} = \\frac{\\partial \\boldsymbol{\\theta}}{\\partial \\boldsymbol{\\beta}^{\\top}} \\Sigma^{\\boldsymbol{\\theta}(\\boldsymbol{\\beta})} \\frac{\\partial \\boldsymbol{\\theta}}{\\partial \\boldsymbol{\\beta}}.$$\n", + "\n", + "It is simply $\\Sigma^{\\boldsymbol{\\beta}}$ if\n", + "$\\boldsymbol{\\theta} = \\boldsymbol{\\beta}$. Different Fisher information\n", + "can be used for $\\Sigma^{\\boldsymbol{\\beta}}$ such as the expected or\n", + "observed, at $\\hat{\\boldsymbol{\\beta}}$ or $\\boldsymbol{\\beta}$. After\n", + "some trivial algebraic manipulation, we can show that our ODE boils\n", + "downs to\n", + "\n", + "$$\\begin{aligned}\n", + "\\left[ \\begin{array}{c} \\frac{d\\beta_{j}}{dt} \\\\ \\frac{d\\boldsymbol{\\beta_{-j}}}{dt} \\end{array} \\right] = k \\left[ \\begin{array}{c} 1 \\\\ -A^{-1}w \\end{array} \\right] \\left( v - w^{\\top}A^{-1}w \\right)^{-1/2}\n", + "\\end{aligned}$$\n", + "\n", + "where the symbols on the RHS above correspond to partitions in the\n", + "Fisher information\n", + "\n", + "$$\\begin{aligned}\n", + "I^{\\boldsymbol{\\beta}} = \\left[ \\begin{array}{cc} v & w^{\\top} \\\\ w & A \\end{array} \\right].\n", + "\\end{aligned}$$\n", + "\n", + "The integration is perform from $t = 0$ to $1$ and is all handled\n", + "internally via {class}`geometric`." + ] + }, + { + "cell_type": "markdown", + "id": "75d6f904", + "metadata": {}, + "source": [ + "\n", + "## Bootstrap\n", + "\n", + "This is perhaps the favorite method to estimate confidence intervals for\n", + "a lot of people. Although there are many ways to implement bootstrap,\n", + "semi-parametric is the only logical choice (even though the underlying\n", + "assumptions may be violated at times). As we have only implemented OLS\n", + "type loss functions in this package, the parametric approach seem to be\n", + "inappropriate when there is no self-efficiency guarantee.\n", + "Non-parametric approaches requires at least a conditional independence\n", + "assumption, something easily violated by our **ODE**. Block bootstrap is\n", + "an option but we are also aware that the errors of an **ODE** can be\n", + "rather rigid, and consistently over/under estimate at certain periods of\n", + "time.\n", + "\n", + "#TODO refs for bootstrap?\n", + "\n", + "When we say semi-parametric, we mean the exchange of errors between the\n", + "observations. Let our raw error be\n", + "\n", + "$$\\varepsilon_{i} = y_{i} - \\hat{y}_{i}$$\n", + "\n", + "where $\\hat{y}_{i}$ will be the prediction under\n", + "$\\hat{\\boldsymbol{\\theta}}$ under our model. Then we construct a new set\n", + "of observations via\n", + "\n", + "$$y_{i}^{\\ast} = \\hat{y}_{i} + \\varepsilon^{\\ast}, \\quad \\varepsilon^{\\ast} \\sim \\mathcal{F}$$\n", + "\n", + "with $\\mathcal{F}$ being the empirical distribution of the raw errors. A\n", + "new set of parameters $\\theta^{\\ast}$ are then found for the\n", + "bootstrapped samples, and we obtain the $\\alpha$ confidence interval by\n", + "taking the $\\alpha/2$ quantiles. Invoking the corresponding python function\n", + "yields our bootstrap estimates. Unlike {func}`asymptotic`, the bounds here are\n", + "used when estimating the parameters of each bootstrap samples. An error\n", + "may be returned if estimation failed for any of the bootstrap samples." + ] + }, + { + "cell_type": "markdown", + "id": "0a8e31f0", + "metadata": {}, + "source": [ + "The additional information here can be used to compute the bias, tail\n", + "effects and test against the normality assumption. If desired, a\n", + "simultaneous confidence interval can also be approximated empirically.\n", + "Note however that because we are using a semi-parameter method here, if\n", + "the model specification is wrong then the resulting estimates for the\n", + "bias is also wrong. The confidence interval still has the normal\n", + "approximation guarantee if the number of samples is large.\n", + "\n", + "In this case, because the error in the observation is extremely small,\n", + "the confidence interval is narrow." + ] + }, + { + "cell_type": "markdown", + "id": "9edc8b6b", + "metadata": {}, + "source": [ + "\n", + "\n", + "\n", + "## Comparison Between Methods\n", + "\n", + "Although we have shown the numerical values for the confidence interval\n", + "obtained using different methods, it can be hard to comprehend how they\n", + "vary. As they say, a picture says a million word, and given that this\n", + "particular model only has two parameters, we can obtain inspect and\n", + "compare the methods visually via a contour plot. The code to perform\n", + "this is shown below but the code block will not be run to save time and\n", + "space.\n", + "\n", + "In the plot above, the bootstrap confidence interval were so close to\n", + "the MLE, it is impossible to distinguish the two on such a coarse scale.\n", + "\n", + "Furthermore, because the geometric confidence interval is the result of\n", + "an integration, we can trace the path that lead to the final output that\n", + "was shown previously. Again, we are space conscious (and time\n", + "constrained) so the code block below will not be run." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "6cef48a9", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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rERERKQWa1XJULCGlYiIiNRirSoZCv4UIiIiIrVYq0qGggkrERERsVaVDBoTViIionqOtapk6FjDSkREVM+xVpUMHX8iERER1XOsVSVDx4SViIionildr5odm81aVTJoLAkgIiKqR+T1qkVPiuCzxQcJwQkwkhrBSGYEmZdMsY21qmRImLASERHVI2XVq7be0xqm9qasVSWDxJ9ORERE9UhZ9arWftasVSWDxYSViIiojuLcqlRXMGElIiKqgzi3KtUlrGElIiKqgzi3KtUl/DlFRERUB3FuVapLmLASERHVAZxbleoylgQQERHVcpxbleo6JqxERES1HOdWpbqOP7OIiIhqEXVTVXFuVarrmLASERHVEmVNVcV6VarrmLASERHVEqUv/efeyEXRkyIA4NyqVKdJhBCipoOoSVlZWbC1tUVmZiZsbGxqOhwiIqJyZUZlKupUASDgdABsu9oiPy1fMbdqblIu61XrEOYq7GElIiIyWNpMVcW5Vaku4ywBREREBohTVRH9gwkrERGRAeJUVUT/4E8yIiIiA8Spqoj+wYSViIjIAHBpVaKysSSAiIiohrFelah8TFiJiIhqGOtVicrHn2lERETViEurEmmPCSsREVE14dKqRLphwkpERFRNuLQqkW4M7pMQHh4OT09PyGQydOjQASdPniy3/datW+Hn5wcLCws4OztjwoQJSE9Pr6ZoiYiIylb68r+RuVGZl/79jvnB/4Q/bLvawv+EP/yO+bEEgOj/GVTCumPHDsyePRuLFi1CdHQ0evTogf79+yMxMVFt+1OnTmHcuHGYOHEi4uLisHPnTly4cAGTJk2q5siJiIiUqbv8H909GvGvxiu149KqRBUzqIR11apVmDhxIiZNmgQfHx989tlncHNzw5o1a9S2P3v2LJo2bYpZs2bB09MT3bt3x+TJk3Hx4sVqjpyIiEiZusv/xbnFMJbx0j+RtgzmE5Kfn49Lly4hKChIaXtQUBCioqLU3qdr1664c+cODh48CCEE7t+/j127dmHgwIFlPk5eXh6ysrKU/hEREembupH/vtt84X/Sn5f+ibRkMAlrWloaioqK4OTkpLTdyckJKSkpau/TtWtXbN26FaNHj4aZmRkaN24MOzs7rF69uszHCQsLg62treKfm5ubXp8HERHVT5quVFWcU8xL/0RaMpiEVU4ikSj9LYRQ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g0lY5SQSidLfQgiVbeps374dS5cuxY4dO+Do6Fhmu3fffReZmZmKf0lJSZWOmdTLOpeFS90vaZSsOgU7of3p9pyyioiIiFQYzLRWDRs2hLGxsUpvampqqkqva2k7duzAxIkTsXPnTrz44ovltpVKpZBKpZWOl8qnSb2qRTsLNBrWCA79HZioEhERUZkMpofVzMwMHTp0QEREhNL2iIgIdO3atcz7bd++HePHj8e2bdswcODAqg6TNKBJvar9S/boGNsRnks9mawSERFRuQymhxUA5s6di+DgYAQGBqJLly746quvkJiYiClTpgB4djn/7t272Lx5M4Bnyeq4cePw+eefo3PnzoreWXNzc9ja2tbY86iPss5l4enfT3E3/C6yz3IRACIiItIfg0pYR48ejfT0dCxbtgzJyclo06YNDh48CA8PDwBAcnKy0pys69atQ2FhIaZPn47p06crtoeEhGDTpk3VHX69pc10VU7BThxURURERFoxqHlYawLnNqscbWYAaLaqGS//ExERaYm5ioH1sFLtommyyhIAIiIiqgyDGXRFtQuTVSIiIqouTFhJK9rOrcpklYiIiCqLJQGkkaxzWbg69yqyo8qfAcC6izVcp7rCooUF61WJiIhIL5iwUoU0nQWAl/+JiIioKjBhpXKxVpWIiIhqGmtYqUyaJqusVSUiIqKqxB5WUpF1LgtX511F9uny61U5tyoRERFVByaspKDpwCqAK1YRERFR9WHCSgA0H1hl0c4Crb5qxV5VIiIiqjZMWIkDq4iIiMigcdBVPceBVURERGTo2MNaT3FgFREREdUWTFjrGQ6sIiIiotqGCWs9woFVREREVBsxYa0nOLCKiIiIaisOuqoHOLCKiIiIajP2sNZxmiSrHFhFREREhowJax2l6SwAHFhFREREho4Jax2j6SwAHFhFREREtQUT1jpE01kAOLCKiIiIahMmrHUEZwEgIiKiuoqzBNQBnAWAiIiI6jL2sNZiXF6ViIiI6gMmrLWUpvWqnAWAiIiIajsmrLWQJiUAnAWAiIiI6gomrLWMJskqB1YRERFRXcJBV7WIJskqB1YRERFRXcMe1lpAk8FVHFhFREREdRUTVgOnyeAqlgAQERFRXcaSAAMWP47JKhERERETVgOVvD4ZqVuYrBIRERGxJMAAaVIGwPlViYiIqL5gwmpAOLiKiIiI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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig = plt.figure()\n", + "\n", + "#CS = plt.contour(xi, yi, zi, linewidth=0.5)\n", + "\n", + "#plt.clabel(CS, fontsize=10, inline=1)\n", + "\n", + "l1 = plt.scatter(xLList[0][:,0], xLList[0][:,1], marker='o', c='m', s=10);\n", + "\n", + "l2 = plt.scatter(xUList[0][:,0], xUList[0][:,1], marker='x', c='m', s=10);\n", + "\n", + "plt.legend((l1, l2), ('Lower CI path', 'Upper CI path'), loc='upper left');\n", + "\n", + "plt.ylabel(r'Estimates of $gamma$');\n", + "\n", + "plt.xlabel(r'Estimates of $beta$');\n", + "\n", + "plt.title('Integration path of the geometric confidence intervals on the likelihood surface');\n", + "\n", + "plt.tight_layout();\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "2b357c75", + "metadata": {}, + "source": [ + "\n", + "## Profile Likelihood Surface\n", + "\n", + "To investigate why it was hard to find the profile likelihood confidence\n", + "interval, we can look at the surface (which is a line as\n", + "we are profiling). We find the solution of {func}`nuisanceOptim` for each\n", + "$\\boldsymbol{\\theta}_{-j}$ at various points of $\\boldsymbol{\\theta}$.\n", + "Equivalently, we can minimize the original loss function as defined\n", + "previously, and this is the approach below. We focus out attention to\n", + "the parameter $\\beta$ of our SIR model. The results are not shown here\n", + "but the existence of a solution to {obj}`obj` is evident by *eyeballing* the plots." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "dc31f543", + "metadata": {}, + "outputs": [], + "source": [ + "numIter = 100\n", + "\n", + "x2 = numpy.linspace(0.0, 2.0, numIter)\n", + "\n", + "funcOut = numpy.linspace(0.0, 2.0, numIter)\n", + "\n", + "ode.parameters = [('beta',0.5), ('gamma',1.0/3.0)]\n", + "\n", + "for i in range(numIter):\n", + " paramEval = [('beta',x2[i]), ('gamma',x2[i])]\n", + " ode2 = copy.deepcopy(ode) \n", + " ode2.parameters = paramEval\n", + " ode2.initial_values = (x0, t[0])\n", + " objSIR2 = NormalLoss(x2[i], ode2, x0, t[0], t[1::], yObv.copy(), targetState, target_param='gamma')\n", + " res = scipy.optimize.minimize(fun=objSIR2.cost, jac=objSIR2.gradient, x0=x2[i], bounds=[(0,2)], method='L-BFGS-B')\n", + " funcOut[i] = res['fun']\n", + "\n", + "fig = plt.figure()\n", + "\n", + "plt.plot(x2, objSIR.cost(xhat) - funcOut)\n", + "\n", + "l1 = plt.axhline(-0.5*qchisq(1 - alpha, df=1), 0, 2, color='r')\n", + "\n", + "plt.ylabel(r'\\$mathcal{L}(hat{theta}) - mathcal{L}(theta mid beta)$');\n", + "\n", + "plt.xlabel(r'Fixed value of $beta$');\n", + "\n", + "plt.title('Difference in objective function between MLEn and the maximization of the nuisance parameters given then parameter of interest, beta in this case');\n", + "\n", + "plt.tight_layout();\n", + "\n", + "plt.legend((l1,), (r'$-0.5mathcal{X}_{1 - alpha}^{2}(1)$',), loc='lower right');\n", + "\n", + "plt.show() " + ] + }, + { + "cell_type": "markdown", + "id": "99c84d17", + "metadata": {}, + "source": [ + "\n", + "\n", + "Both the upper and lower confidence interval can be found in the\n", + "profiling procedure, but the part between of\n", + "$\\beta \\in \\left[0,\\hat{\\beta}\\right]$ is not convex, with $\\hat{\\beta}$\n", + "being the MLE. This non--quadratic profile likelihood is due to the\n", + "non-identifiability of the model given data {cite}`Raue2009`. For this\n", + "particular case, we can fix it simply by introducing additional\n", + "observations in the form of the $I$ state. We encourage the users to try\n", + "it out for themselves to confirm." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67ae8521", + "metadata": {}, + "outputs": [], + "source": [ + "targetState = \\['I', 'R'\\]\n", + "\n", + "targetStateIndex = numpy.array(ode.get_state_index(targetState))\n", + "\n", + "y = solution[1::,targetStateIndex] + numpy.random.normal(0, 0.01, (len(solution[1::,targetStateIndex]), 1))\n", + "\n", + "objSIR = NormalLoss(theta, ode, x0, t[0], t[1::], y.copy(), targetState)\n", + "\n", + "xhat = objSIR.fit(theta, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1])\n", + "\n", + "for i in range(numIter): \n", + " paramEval = [('beta', x2[i]), ('gamma', x2[i])] \n", + " ode2 = copy.deepcopy(ode)\n", + " ode2.parameters = paramEval\n", + " ode2.initial_values = (x0, t[0]) \n", + " objSIR2 = NormalLoss(x2[i], ode2, x0, t[0], t[1::], y.copy(), targetState, target_param='gamma')\n", + " res = scipy.optimize.minimize(fun=objSIR2.cost, jac=objSIR2.gradient, x0=x2[i], bounds=[(0,2)], method='L-BFGS-B')\n", + " funcOut[i] = res['fun']\n", + "\n", + "fig = plt.figure()\n", + "\n", + "plt.plot(x2, objSIR.cost(xhat) - funcOut);\n", + "\n", + "l1 = plt.axhline(-0.5*qchisq(1 - alpha, df=1), 0, 2, color='r')\n", + "\n", + "plt.ylabel(r'$mathcal{L}(hat{theta}) - mathcal{L}(theta mid beta)$');\n", + "\n", + "plt.xlabel(r'Fixed value of $beta$');\n", + "\n", + "plt.title('Profile likelihood curve for the parameter of interest with more observations');\n", + "\n", + "plt.tight_layout();\n", + "\n", + "plt.legend((l1,), (r'$-0.5mathcal{X}_{1 - alpha}^{2}(1)$',), loc='lower right');\n", + "\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/paramfit/params_via_abc.ipynb b/docs/notebooks/paramfit/params_via_abc.ipynb new file mode 100644 index 00000000..0e54b10d --- /dev/null +++ b/docs/notebooks/paramfit/params_via_abc.ipynb @@ -0,0 +1,483 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cad1d1d4", + "metadata": {}, + "source": [ + "# Parameter Estimation: Approximate Bayesian Computation" + ] + }, + { + "cell_type": "markdown", + "id": "05daf2f1", + "metadata": {}, + "source": [ + "Here we demonstrate how PyGOM uses Approximate Bayesian Computation (ABC) to estimate posterior distributions for parameters given a candidate model and some data.\n", + "As an example, we use synthetic data produced by PyGOM's {doc}`solve_stochast <../model_solver>` function, the result of a stochastic epidemic simulation of an SEIR model with parameters:\n", + "\n", + "$\\beta=0.35,\\quad \\alpha=0.5,\\quad \\gamma=0.25,\\quad n_{\\text{pop}}=10^4,\\quad I(t=0)=5$\n", + "\n", + "Loading in the data file:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de300402", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "out = np.loadtxt('seir_epi_data.txt')\n", + "t=out[:,0]\n", + "sol_i_r=out[:,1:3]" + ] + }, + { + "cell_type": "markdown", + "id": "0ba66de0", + "metadata": {}, + "source": [ + "We inspect the time series of the daily infected and removed populations:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7660a673", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "plt.rcParams['figure.figsize'] = [10, 4]\n", + "f, axarr = plt.subplots(1,2, layout='constrained')\n", + "axarr[0].scatter(t, sol_i_r[:,0])\n", + "axarr[1].scatter(t, sol_i_r[:,1])\n", + "axarr[0].set_title('I')\n", + "axarr[1].set_title('R')\n", + "axarr[0].set_xlabel('Time')\n", + "axarr[1].set_xlabel('Time');" + ] + }, + { + "cell_type": "markdown", + "id": "b6a77aab", + "metadata": {}, + "source": [ + "```{note}\n", + "We typically do not have access to information regarding the total infected population. More commonly reported is the number of new cases in a given time period (or infection times).\n", + "Furthermore, we are unlikely to know the removed population, unless, for example, the disease results in death with high probability.\n", + "Nevertheless, the purpose of this chapter is to demonstrate model fitting given a data set and so these departures from reality do not undermine the key messages.\n", + "```\n", + "\n", + "In the next sections, we are going to use PyGOM to obtain estimates for unknown values $\\beta$, $\\alpha$ and $\\gamma$ (assuming that the total population, $N$, and initial number of infecteds, $I(t=0)$, are known).\n", + "\n", + "```{note}\n", + "Again, it is rather unrealistic to know $I(t=0)$ or indeed $N$, but we proceed in this way for the sake of simplicity in our example.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "31ebefaa", + "metadata": {}, + "source": [ + "## Fitting an SEIR model (with Infected and Removed known)\n", + "\n", + "To obtain parameter estimates from data, we must provide a candidate model and specify the unknown parameters which we are interested in. Information regarding the candidate model is contained in {func}`abc.create_loss`, which requires:\n", + "1) A {class}`.SimulateOde` object which describes the system of ODEs.\n", + "2) The loss function, which describes how we assume observations are distributed about the mean value predicted by the {class}`SimulateOde` object.\n", + "3) `abc.Parameter` which indicates which parameters we are interested in and their prior distributions.\n", + "4) The data to which we are fitting the parameters.\n", + "\n", + "We start by specifying the ODE system. In this first example, we are going to assume (correctly) that the underlying process is an SEIR model.\n", + "We need to let the model know the value of $N$, however, a feature of PyGOM is that we must pass values for all parameters.\n", + "This usually acts to ensure that we do not under-specify the set of parameters when running simulations, however, in this case it requires us to overspecify what we actually know.\n", + "Thus, even though the other parameters ($\\beta$, $\\alpha$ and $\\gamma$) are unknown, the model expects some values and so for now we can just pass some initial guess (in this case the half way points of our prior distributions defined below), which will be overrode later when we specify ABC parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "160c27ec", + "metadata": {}, + "outputs": [], + "source": [ + "# Set up pygom object from common models\n", + "from pygom import common_models\n", + "\n", + "n_pop=1e4\n", + "paramEval=[('beta', 0.5), ('alpha', 1), ('gamma', 0.5), ('N', n_pop)]\n", + "\n", + "ode_SEIR = common_models.SEIR_N(param=paramEval)" + ] + }, + { + "cell_type": "markdown", + "id": "da9675c6", + "metadata": {}, + "source": [ + "The {class}`Parameter` class is used to specify the parameters we wish to infer and their prior probability distributions.\n", + "We can choose from any of the distributions included in PyGOM, here taking uniform distributions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42291b82", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import approximate_bayesian_computation as abc\n", + "\n", + "parameters = [abc.Parameter('beta', 'unif', 0, 1, logscale=False),\n", + " abc.Parameter('alpha', 'unif', 0, 2, logscale=False),\n", + " abc.Parameter('gamma', 'unif', 0, 1, logscale=False)]" + ] + }, + { + "cell_type": "markdown", + "id": "11aa81ca", + "metadata": {}, + "source": [ + "Finally, we must specify how observations are produced from the underlying model.\n", + "If we assume that each data point is the result of a random draw from a Poisson distribution with mean equal to the SEIR model output at that timepoint, we can use the option `PoissonLoss` as our loss function when calling `create_loss` below.\n", + "Now we combine everything together, including the initial conditions which we are assuming to be known." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd353fe2", + "metadata": {}, + "outputs": [], + "source": [ + "i0=5\n", + "x0=[n_pop-i0, 0, i0, 0]\n", + "\n", + "from pygom import PoissonLoss\n", + "\n", + "objSEIR = abc.create_loss(\"PoissonLoss\", # Loss function\n", + " parameters, # Unknown parameters and prior distributions\n", + " ode_SEIR, # Model\n", + " x0, t[0], # Initial conditions and timepoints\n", + " t[1:], sol_i_r[1:,:], # Data timepoints and I, R values\n", + " ['I', 'R']) # Names of compartments in data\n", + "\n", + "abcSEIR = abc.ABC(objSEIR, parameters)" + ] + }, + { + "cell_type": "markdown", + "id": "4009b7ba", + "metadata": {}, + "source": [ + "A sequential Monte Carlo method (ABC-SMC) is used for parameter inference. This approach considers a series of generations, with each generation using a smaller threshold than the previous. The first generation is equivalent to the standard ABC algorithm, in the sense that parameters are sampled from prior distributions. In subsequent generations, candidate parameters are proposed by perturbing weighted samples from the previous generation. Here, we use a multivariate normal distribution with optimal local covariance matrix to perform the perturbation.\n", + "\n", + "The ABC-SMC method requires a couple of additional arguments to `get_posterior_sample`:\n", + "- G - the number of generations.\n", + "- q - a quantile (0 < q < 1). Whilst it is possible to specify a list of tolerances to use in each generation, it is difficult to know what these should be. When specifying q, the tolerance for the current generation is set to the q-th quantile of the distances from the previous generation. Larger values of q will result in smaller reductions in thresholds but a higher acceptance rate.\n", + "\n", + "We run for 6 generations on our data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3c235ba", + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(1)\n", + "\n", + "abcSEIR.get_posterior_sample(N=250, tol=np.inf, G=6, q=0.25, progress=True)" + ] + }, + { + "cell_type": "markdown", + "id": "c950e11a", + "metadata": {}, + "source": [ + "If we want to run the method for a few more generations, there is no need to start from the beginning.\n", + "Instead, we can use {func}`continue_posterior_sample` along with the `next_tol` attribute to set the tolerance.\n", + "Let's perform 2 additional iterations:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52063687", + "metadata": {}, + "outputs": [], + "source": [ + "abcSEIR.continue_posterior_sample(N=250, tol=abcSEIR.next_tol, G=2, q=0.25, progress=True)" + ] + }, + { + "cell_type": "markdown", + "id": "83092942", + "metadata": {}, + "source": [ + "There are built in methods to plot the posterior distribution and the corresponding fit to the data:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e4dfa76f", + "metadata": {}, + "outputs": [], + "source": [ + "abcSEIR.plot_posterior_histograms();\n", + "abcSEIR.plot_pointwise_predictions();" + ] + }, + { + "cell_type": "markdown", + "id": "614572bc", + "metadata": {}, + "source": [ + "The posterior draws are contained within `abcSIR.res`.\n", + "This can be useful if output needs to be saved, or for calculation credible intervals.\n", + "We see here that the 95% credible intervals are consistent with the true parameter values." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0cea2db3", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'beta={np.median(abcSEIR.res[:,0]):.3f} ({np.quantile(abcSEIR.res[:,0], 0.025):.3f}, {np.quantile(abcSEIR.res[:,0], 0.975):.3f})')\n", + "print(f'alpha={np.median(abcSEIR.res[:,1]):.3f} ({np.quantile(abcSEIR.res[:,1], 0.025):.3f}, {np.quantile(abcSEIR.res[:,1], 0.975):.3f})')\n", + "print(f'gamma={np.median(abcSEIR.res[:,2]):.3f} ({np.quantile(abcSEIR.res[:,2], 0.025):.3f}, {np.quantile(abcSEIR.res[:,2], 0.975):.3f})')" + ] + }, + { + "cell_type": "markdown", + "id": "5c7611b2", + "metadata": {}, + "source": [ + "## Fitting an SEIR model (with only Infected known)\n", + "\n", + "We now fit the same model, but assume we only have access to data concerning the infected component.\n", + "All that changes code-wise is that we omit the recovered time series when inputting the data and specify that we only have information for the infected population in the last argument of `create_loss`.\n", + "We do this and run the ABC algorithm for 8 generations." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6132aacd", + "metadata": {}, + "outputs": [], + "source": [ + "objSEIR2 = abc.create_loss(\"PoissonLoss\",\n", + " parameters,\n", + " ode_SEIR,\n", + " x0, t[0],\n", + " t[1:], sol_i_r[1:,0], # now we only pass one column of epi data\n", + " ['I']) # now we only have information regarding the infected compartment\n", + "\n", + "abcSEIR2 = abc.ABC(objSEIR2, parameters)\n", + "\n", + "abcSEIR2.get_posterior_sample(N=250, tol=np.inf, G=8, q=0.25, progress=True)\n", + "abcSEIR2.plot_posterior_histograms();\n", + "abcSEIR2.plot_pointwise_predictions();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9fb499c", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'beta={np.median(abcSEIR2.res[:,0]):.3f} ({np.quantile(abcSEIR2.res[:,0], 0.025):.3f}, {np.quantile(abcSEIR2.res[:,0], 0.975):.3f})')\n", + "print(f'alpha={np.median(abcSEIR2.res[:,1]):.3f} ({np.quantile(abcSEIR2.res[:,1], 0.025):.3f}, {np.quantile(abcSEIR2.res[:,1], 0.975):.3f})')\n", + "print(f'gamma={np.median(abcSEIR2.res[:,2]):.3f} ({np.quantile(abcSEIR2.res[:,2], 0.025):.3f}, {np.quantile(abcSEIR2.res[:,2], 0.975):.3f})')" + ] + }, + { + "cell_type": "markdown", + "id": "c6542afd", + "metadata": {}, + "source": [ + "We still see estimates in agreement with the true parameter values, even though we have reduced the amount of data made available to the ABC algorithm.\n", + "\n", + "## Fitting an SIR model (with only Infected known)\n", + "\n", + "Of course, we may not know the underlying mechanisms and might instead attempt to fit an SIR model to the infected data.\n", + "We follow similar steps as before, but now specifying an SIR model:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d328eee8", + "metadata": {}, + "outputs": [], + "source": [ + "parameters = [abc.Parameter('beta', 'unif', 0, 1, logscale=False),\n", + " abc.Parameter('gamma', 'unif', 0, 1, logscale=False)]\n", + "\n", + "# Params\n", + "paramEval=[('beta', 0), ('gamma', 0), ('N', n_pop)]\n", + "\n", + "# Initial conditions now doen't require E0\n", + "x0=[n_pop-i0, i0, 0]\n", + "\n", + "# Set up pygom object\n", + "ode_SIR = common_models.SIR(param=paramEval)\n", + "\n", + "objSIR = abc.create_loss(\"PoissonLoss\", parameters, ode_SIR, x0, t[0], t[1:], sol_i_r[1:,0], ['I'])\n", + "abcSIR = abc.ABC(objSIR, parameters)\n", + "\n", + "abcSIR.get_posterior_sample(N=250, tol=np.inf, G=8, q=0.25, progress=True)\n", + "\n", + "abcSIR.plot_posterior_histograms();\n", + "abcSIR.plot_pointwise_predictions();" + ] + }, + { + "cell_type": "markdown", + "id": "4f3d6704", + "metadata": {}, + "source": [ + "Although we see smaller credible intervals, this actually reflects the restriction in model fitting, rather than increased precision.\n", + "We see that our inappropriate model choice here results in poorer parameter estimates:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9bb60c9", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'beta={np.median(abcSEIR.res[:,0]):.3f} ({np.quantile(abcSEIR.res[:,0], 0.025):.3f}, {np.quantile(abcSEIR.res[:,0], 0.975):.3f})')\n", + "print(f'gamma={np.median(abcSEIR.res[:,1]):.3f} ({np.quantile(abcSEIR.res[:,1], 0.025):.3f}, {np.quantile(abcSEIR.res[:,1], 0.975):.3f})')" + ] + }, + { + "cell_type": "markdown", + "id": "68de3e94", + "metadata": {}, + "source": [ + "## Initial conditions\n", + "\n", + "In addition to inferring model parameters, the ABC methods can be used to estimate initial conditions, after all, it is unlikely that $I(t=0)$ is known with certainty.\n", + "To do this, the state that we wish to estimate the initial condition for should be included in the `parameters`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85dc7fa9", + "metadata": {}, + "outputs": [], + "source": [ + "parameters = [abc.Parameter('beta', 'unif', 0, 1, logscale=False),\n", + " abc.Parameter('alpha', 'unif', 0, 2, logscale=False),\n", + " abc.Parameter('gamma', 'unif', 0, 1, logscale=False),\n", + " abc.Parameter('I', 'unif', 0, 20, logscale=False)]" + ] + }, + { + "cell_type": "markdown", + "id": "061f2654", + "metadata": {}, + "source": [ + "The remaining code is the same as before.\n", + "Again, we still need to pass variables even if they are unknown - in this case the initial number of infected individuals." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ca613e08", + "metadata": {}, + "outputs": [], + "source": [ + "i0=5\n", + "x0=[n_pop-i0, 0, i0, 0]\n", + "\n", + "objSEIR3 = abc.create_loss(\"PoissonLoss\",\n", + " parameters,\n", + " ode_SEIR,\n", + " x0, t[0],\n", + " t[1:], sol_i_r[1:,0], # now we only pass one column of epi data\n", + " ['I']) # now we only have information regarding the infected compartment\n", + "\n", + "abcSEIR3 = abc.ABC(objSEIR3, parameters)" + ] + }, + { + "cell_type": "markdown", + "id": "ca183311", + "metadata": {}, + "source": [ + "We run the algorithm for 8 generations:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ba62e53", + "metadata": {}, + "outputs": [], + "source": [ + "abcSEIR3.get_posterior_sample(N=250, tol=np.inf, G=8, q=0.25, progress=True)\n", + "\n", + "abcSEIR3.plot_posterior_histograms();\n", + "abcSEIR3.plot_pointwise_predictions();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b22e6715", + "metadata": {}, + "outputs": [], + "source": [ + "print(f'beta={np.median(abcSEIR3.res[:,0]):.3f} ({np.quantile(abcSEIR3.res[:,0], 0.025):.3f}, {np.quantile(abcSEIR3.res[:,0], 0.975):.3f})')\n", + "print(f'alpha={np.median(abcSEIR3.res[:,1]):.3f} ({np.quantile(abcSEIR3.res[:,1], 0.025):.3f}, {np.quantile(abcSEIR3.res[:,1], 0.975):.3f})')\n", + "print(f'gamma={np.median(abcSEIR3.res[:,2]):.3f} ({np.quantile(abcSEIR3.res[:,2], 0.025):.3f}, {np.quantile(abcSEIR3.res[:,2], 0.975):.3f})')\n", + "print(f'I0={np.median(abcSEIR3.res[:,3]):.3f} ({np.quantile(abcSEIR3.res[:,3], 0.025):.3f}, {np.quantile(abcSEIR3.res[:,3], 0.975):.3f})')" + ] + }, + { + "cell_type": "markdown", + "id": "c76a2d1b", + "metadata": {}, + "source": [ + "Whilst credible intervals are consistent with our parameters, they are wider than before.\n", + "This is because with increased numbers of parameters there are more ways for our model to fit the data." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/paramfit/params_via_optimization.ipynb b/docs/notebooks/paramfit/params_via_optimization.ipynb new file mode 100644 index 00000000..3d24e6e6 --- /dev/null +++ b/docs/notebooks/paramfit/params_via_optimization.ipynb @@ -0,0 +1,380 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parameter Estimation: Maximum likelihood\n", + "\n", + "In the previous section, we outlined how to use Markov Chain Monte Carlo methods to estimate the posterior probability distribution of parameters.\n", + "These methods have generally replaced techniques which infer the maximum likelihood estimates (MLE) of parameter values, with confidence levels provided after making assumptions about the local likelihood landscape.\n", + "PyGOM has the capability to estimate parameters in this way and although perhaps outdated, including these methods could still be practical if trying to reproduce work from older publications, for example.\n", + "\n", + "## Example: SEIR model (with I and R known)\n", + "\n", + "We now solve the same problem as in the previous section, this time via minimisation of the cost function.\n", + "As a reminder: We have data from an SEIR system where the time series of $I$ and $R$ are known and we wish to estimate parameters $\\beta$, $\\alpha$ and $\\gamma$ with true values 0.35, 0.5 and 0.25 respectively.\n", + "We assume that the total population, $N=10,000$ and the initial number infecteds, $i_0=5$, are both known.\n", + "\n", + "We start by loading the data again:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "efea520f", + "metadata": {}, + "outputs": [], + "source": [ + "# Import data\n", + "import numpy as np\n", + "\n", + "out = np.loadtxt('seir_epi_data.txt')\n", + "t=out[:,0]\n", + "sol_i_r=out[:,1:3]" + ] + }, + { + "cell_type": "markdown", + "id": "2a5c30e7", + "metadata": {}, + "source": [ + "The syntax for setting up the solver is similar to the approach via ABC.\n", + "We first form our candidate SEIR model.\n", + "Currently, PyGOM requires us to provide numerical values for all model parameters, including the unknown ones we are trying to estimate.\n", + "These values are used to perform an additional check before performing the MLE to verify that the function provided is integrable.\n", + "This step will be likely removed for later versions, but for now it's probably best to input initial guesses as parameter values.\n", + "For the current example, this means specifying $\\beta$, $\\alpha$ and $\\gamma$ from our initial guess `theta`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "857371e4", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import common_models\n", + "\n", + "n_pop=1e4 # known population size\n", + "theta = [0.4, 0.3, 0.3] # initial guess for [beta, alpha, gamma]\n", + "\n", + "paramEval=[('beta', theta[0]), ('alpha', theta[1]), ('gamma', theta[2]), ('N', n_pop)]\n", + "ode_SEIR = common_models.SEIR_N(param=paramEval)" + ] + }, + { + "cell_type": "markdown", + "id": "80c83797", + "metadata": {}, + "source": [ + "We pass all other required information, including initial conditions, `x0`, to build an object of class {class}`.PoissonLoss`" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "88ad9325", + "metadata": {}, + "outputs": [], + "source": [ + "i0=5\n", + "x0=[n_pop-i0, 0, i0, 0] # initial conditions\n", + "\n", + "from pygom import PoissonLoss\n", + "\n", + "objSEIR = PoissonLoss(theta, ode_SEIR,\n", + " t0=t[0], x0=x0,\n", + " t=t[1:], y=sol_i_r[1:,:],\n", + " target_param=['beta', 'alpha', 'gamma'],\n", + " state_name= ['I', 'R'])" + ] + }, + { + "cell_type": "markdown", + "id": "cabcb9ba", + "metadata": {}, + "source": [ + "```{note}\n", + "It is a good idea to check that value of $R_0$ corresponding to the initial guess is greater than 1.\n", + "For instance, here $\\frac{\\beta}{\\gamma}=\\frac{0.4}{0.3}=1.33$.\n", + "This is important because if $R_0<1$ then the resulting model output will be an exponential decay - essentially, a failed epidemic which will differ substantially from the data.\n", + "If the optimization algorithm proceeds by attempting new sets of parameters in the neighbourhood of the initial ones, these are also likely to result in similarly bad model fits and the algorithm may not find a way out.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "140a5020", + "metadata": {}, + "source": [ + "## Gradient calculations\n", + "\n", + "How the parameter optimizer will navigate parameter space will depend on the gradient of the cost function with respect to the parameters.\n", + "PyGOM can calculate the gradient in two different ways.\n", + "First, let's compare the outputs of the two methods when evaluated at the initial condition, `theta`:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "de043dc5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-3473286.37537513 -648419.19492934 3962185.98738807]\n", + "[-3439949.96665268 -651037.898083 3920356.1433702 ]\n" + ] + } + ], + "source": [ + "print(objSEIR.sensitivity())\n", + "print(objSEIR.adjoint())" + ] + }, + { + "cell_type": "markdown", + "id": "c47c6356", + "metadata": {}, + "source": [ + "Also, let's compare the times each method takes:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "c74c5449", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "57 ms ± 6.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%timeit objSEIR.sensitivity()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "20856aa8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "440 ms ± 81.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit objSEIR.adjoint()" + ] + }, + { + "cell_type": "markdown", + "id": "3a86770d", + "metadata": {}, + "source": [ + "```{note}\n", + "Note how we ran the two gradient functions once before timing it, that is because we only find the properties (Jacobian, gradient) of the ODEs during runtime.\n", + "\n", + "The amount of time taken for both methods is dependent on the number of observations as well as the number of states.\n", + "The effect on the adjoint method as the number of observations differs can be quite evident.\n", + "This is because the adjoint method is under a discretization which loops in Python where as the forward sensitivity equations are solved via an integration.\n", + "As the number of observation gets larger, the affect of the Python loop becomes more obvious.\n", + "\n", + "The difference in gradient is larger when there are less observations.\n", + "This is because the adjoint method use interpolations on the output of the ode between each consecutive time points.\n", + "Given solutions over the same length of time, fewer discretizations leads to a less accurate interpolation.\n", + "Note that the interpolation is currently performed using a univariate spline, due to the limitation of Python packages.\n", + "Ideally, one would prefer to use an (adaptive) Hermite or Chebyshev interpolation.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "543ec840", + "metadata": {}, + "source": [ + "## Optimised result\n", + "\n", + "We now employ optimisation procedures which should progress from the initial guess (if the initial guess is sensible enough) to the parameter set which minimises our cost function.\n", + "It is particularly important to set the boundaries for the parameters here, since we know that they are required to be positive." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ff093f77", + "metadata": {}, + "outputs": [], + "source": [ + "boxBounds = [(0.0,2.0), (0.0,2.0), (0.0,2.0)]" + ] + }, + { + "cell_type": "markdown", + "id": "7590328f", + "metadata": {}, + "source": [ + "Now we use the *SLSQP* optimization routine of `scipy.optimize` with gradient obtained by forward sensitivity.\n", + "\n", + "We could, of course, use other methods available in `scipy.optimize.minimize`, such as *L-BFGS-B* and *TNC*.\n", + "We can also use methods that accepts the exact Hessian such as *trust-ncg* but that should not be necessary most of the time." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "83eca0ba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " message: Optimization terminated successfully\n", + " success: True\n", + " status: 0\n", + " fun: 1651.128217170814\n", + " x: [ 3.537e-01 5.384e-01 2.559e-01]\n", + " nit: 17\n", + " jac: [-4.531e+00 -3.594e-01 4.575e+00]\n", + " nfev: 29\n", + " njev: 17\n" + ] + } + ], + "source": [ + "from scipy.optimize import minimize\n", + "\n", + "res = minimize(fun=objSEIR.cost,\n", + " jac=objSEIR.sensitivity,\n", + " x0=theta, \n", + " bounds=boxBounds,\n", + " method='SLSQP')\n", + "\n", + "print(res)" + ] + }, + { + "cell_type": "markdown", + "id": "912700fc", + "metadata": {}, + "source": [ + "We see that parameter values are in agreement with the underlying model and there is visual agreement with data when plotted below" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c826a9db", + "metadata": { + "tags": [ + "hide-input" + ] + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA/MAAAEFCAYAAACvqLeOAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAACMtElEQVR4nOzdd3hTddvA8e9JmqY7XbRpoexVaNmrbGXLEFBRGYIiuOB9EHGgPooLFBcqTkRBEHHiIygoewhlVMrelN090p2kyXn/CATKBtuGtvfnus7V03PunNyH0fQ+v6WoqqoihBBCCCGEEEKIckPj6gSEEEIIIYQQQghxY6SYF0IIIYQQQgghyhkp5oUQQgghhBBCiHJGinkhhBBCCCGEEKKckWJeCCGEEEIIIYQoZ6SYF0IIIYQQQgghyhkp5oUQQgghhBBCiHLGzdUJlAa73c6ZM2fw9fVFURRXpyOEEEKUGFVVycnJITw8HI2m8j6Tl896IYQQFdX1ftZXyGL+zJkzREREuDoNIYQQotScPHmSatWquToNl5HPeiGEEBXdtT7rK2Qx7+vrCzhu3s/Pz8XZCCGEECUnOzubiIgI52ddZSWf9UIIISqq6/2sr5DF/Lnudn5+fvIBL4QQokKq7F3L5bNeCCFERXetz/oSHWz36aef0qRJE+cHa0xMDEuXLnWeV1WVKVOmEB4ejqenJ127dmXPnj3FrmE2mxk/fjzBwcF4e3szYMAATp06VZJpCiGEEEIIIYQQ5VqJFvPVqlXjzTffZNu2bWzbto3bb7+dO++801mwT58+nffee4+ZM2eydetWjEYjPXr0ICcnx3mNCRMmsGjRIhYuXMiGDRvIzc2lX79+2Gy2kkxVCCGEEBeYMmUKiqIU24xGo/N8ST2Qz8zMZMSIERgMBgwGAyNGjCArK6ssblEIIYSoUEq0mO/fvz933HEH9evXp379+rzxxhv4+PgQGxuLqqrMmDGDF154gcGDBxMVFcXcuXPJz89nwYIFAJhMJmbPns27775L9+7dad68OfPnz2fXrl2sWLGiJFMVQgghxEUaN25MYmKic9u1a5fzXEk9kB86dCjx8fEsW7aMZcuWER8fz4gRI8r0PoUQQoiKoNTWtLHZbCxcuJC8vDxiYmJISEggKSmJnj17OmP0ej1dunRh48aNAMTFxWG1WovFhIeHExUV5Yy5HLPZTHZ2drFNCCGEEDfGzc0No9Ho3KpUqQJQYg/k9+3bx7Jly/jyyy+JiYkhJiaGWbNmsWTJEg4cOOCy+xZCCCHKoxIv5nft2oWPjw96vZ5HH32URYsW0ahRI5KSkgAIDQ0tFh8aGuo8l5SUhLu7OwEBAVeMuZxp06Y5u+sZDAZZqkYIIYS4CYcOHSI8PJxatWpx3333cfToUYASeyC/adMmDAYDbdu2dca0a9cOg8Fw1Yf2IA/uhRBCiIuV+Gz2DRo0ID4+nqysLH7++WdGjhzJ2rVrnecvnpFPVdVrztJ3rZjJkyczceJE5/fnpvIXQty4zUfT+d+OM4ztVJuawd6uTkcIUUbatm3LN998Q/369UlOTub111+nffv27Nmz56oP5I8fPw5c3wP5pKQkQkJCLnnvkJCQqz60B8eD+1deeeWm708IIUQFZyuCokKwWaDIDDYzFFnOfjVf5tjZrzYrdlsRRVYLtiIrdpsV9ewx1WZFtRWh2s/vY7Oi2ovAXnzfVrUtxjueLdNbLvFi3t3dnbp16wLQqlUrtm7dygcffMCzzzpuLCkpibCwMGd8SkqK85cDo9GIxWIhMzOz2C8DKSkptG/f/orvqdfr0ev1JX0rQlQ6v+9MZML327HaVP7ak8ScB9sQVdXg6rSEEGWgT58+zv3o6GhiYmKoU6cOc+fOpV27dkDJPJC/XPz1XEce3AshRAVhLYRCk2MzZ0NhFhRmgzUfLPlgzQNLPqolD2thLtaCXIoKc7GdPYYlH01RPm62QsemmtHarWiw33RKGsD9X95WnMmG8Y5/eZEbVOrrzKuqitlsplatWhiNRpYvX07z5s0BsFgsrF27lrfeeguAli1botPpWL58OUOGDAEgMTGR3bt3M3369NJOVYhKbdnuJMZ99w+qCr56N9JyLdz3RSyv3tmYQc2rVvo1rYWobLy9vYmOjubQoUMMHDgQ+PcP5I1GI8nJyZe8V2pq6iWt/heTB/dCCHGLsRZCfhrkpZ39mg55qah5aVhyUrHlZ2EvcBTtGnM2GmsOOks2WtV6XZdXcBTYN1Nk21QFM+5YcMOCDgtumFUdFnSYzx1THV+L0GJFiw0tRWgpUrXYFS02xQ27oj27uTm/que+as7ua3Sg0RIc0ZCWN5Hrv1Gixfzzzz9Pnz59iIiIICcnh4ULF7JmzRqWLVuGoihMmDCBqVOnUq9ePerVq8fUqVPx8vJi6NChABgMBkaPHs1TTz1FUFAQgYGBTJo0iejoaLp3716SqQohLvLNpmOoKtzdshr/7duIR+ZvI/ZoBhN/2MEP207y+fBWGLx0rk5TCFFGzGYz+/bto1OnTiX2QD4mJgaTycSWLVto06YNAJs3b8ZkMl21B54QQogyZMmD7ETIOVPsq910Glt2IuSloSlIR2vNvezLFeBaj17tqkIOnuTgRbbqTQ6e5Kt68tFTgMf5fVWPVesB7t4o7t646b3ReXij8/TBrvPC7uaF4qZH1epR3BybVqfH3d0ddzctejcN7m4a9G4a9Dot7loNep0GL62GQJ0Gd60WvU7jPO6u1aDVKOWmEatEi/nk5GRGjBhBYmIiBoOBJk2asGzZMnr06AHAM888Q0FBAY8//jiZmZm0bduWv/76C19fX+c13n//fdzc3BgyZAgFBQV069aNOXPmoNVqSzJVIcQFbHaVHSezAHi4Uy0MepjX14vVG/5h/Z4EOG5lza/bubNLOzBGg/bmi/rFO87w8m97mDoomt5Rxmu/QAhRJiZNmkT//v2pXr06KSkpvP7662RnZzNy5MgSeyAfGRlJ7969GTNmDJ9//jkAY8eOpV+/fjRo0MBl9y6EEJWJzVJI+pnDmE4fIi/5MJbUBNxzThJgOUOwNQlv9fJFuoZLZ0+3qloy8CVD9SNd9SUdAxmqLxmqL/laX6w6X2w6X2x6P1S9H3gY0Hj6o/f0xdvTHW+9G97ubni5a8/uawnz1OHnocPP0w0/Dx0eOqkDr0RRVVV1dRIlLTs7G4PBgMlkws/Pz9XpCHHL25+UTf8Zq+nrHs/7kQdQjqx0TCByOe4+UKMDNLsfGva74cL+rk83Enc8E38vHcuf7EIVX+k2K8SNKK3PuPvuu49169aRlpZGlSpVaNeuHa+99hqNGjUCHMPmXnnlFT7//HPnA/mPP/6YqKgo5zUKCwt5+umnWbBggfOB/CeffFJsbHtGRgb/93//x2+//QbAgAEDmDlzJv7+/jeUr3zWCyHEldntKikpp0lP2EXB6b2Quh8P02GqFB6nipqBRrl6CZirepCsBpCkBpLE2a9qIClqAHlu/pj1QVg9AnHz9Cc8wItqAZ5EBJ79GuBFmL8Hejcpwm/W9X7GSTEvRGVnK2LzrzOpuvMjqilp54/rDRDaGIu7gVUH0ghWTDT3SkVbmHk+xscInSdBywdBe+2OPhl5Flq+vpxzP3X6Rofx8bAWJXxDQlRs8hnnIH8OQggBRTY7p9KyMB2LR5u8E03ybkg9QKj5GEHKlZfwzFP1JGqMZLqHYfatjiawJla/Glh8qmHzDUfraXB0TXfT4OPhaCH389Dh4+GGVlM+uqCXZ9f7GVfqE+AJIW5hSbvg18dpm7QTFMjVBeHTZgRE3w0hjUGjwR2Y/dlGth7L5LXekYyolQv7foO4uZCbBH9Mgi2zYMBHUL3tVd9uzYEUVBVC/fSk5Vr4fVci/XcnSXd7IYQQQojrYMot4MS+LWQe3Ij11HbC8vdTj1PUVGzFA8/W24lKCCn6GuT41kETGol/RGOCqzckKKQqdbUXd5oX5Y0U80JURqoKf38Aq14DexHZig8fWO6k/eBn6dakxiXhtzcMZeuxTFYeSKNuaB1+TOvH06PHE3b4B1g9FdIOwNe9odNT0OW5K7bSr9yfAsCQVhHY7CqfrDnCf/+3m5jaQTK5nhBCCCHExQqzMR/bTML2lVgSNlHbvJ9o5YKhkGeL9mzFl6O6uiR61serWjS1IlsQXqcJYZ6+hF3+yqICkGJeiMrGkgf/Gwd7fgHAWr8v3Xb1JVX159Fal28h7xYZwlvL9vP34TT+PpyG1aYS6OXOi/3GQPQ9sPRZ2LkQ1r0Np7bBPXPA07/YNaw2O+sOpAJwe8MQIsP8+HNPEkdS83jt9728c0/T0rxrIYQQQohb2rG0POKPJ+NxZhtBKRsJT48lLP8Aeuw0PBekQC5eHPdshC2sOcYGbQmu1wa/gOo0UxSauTB/UfakmBeiMinIxD7/bjSnt4HGDfq8xWbDnaTu3EK1AM8rTkZXL8SHagGenMoscB7bcPjs+HpPfxj8OdTrAb+Nh6OrYXZPGPYjBJxv5d96LIMccxFB3u40reaPRqMw/e4m3P3ZJn6KO8WApuF0rl+lNO9eCCGEEOKWoKoq2QVF7EvKZnv8NuwH/qRR/jZ6avbjpZiLxZ60V2GfLhJdzfZExfSkSu1mNNbI5HJCinkhKo/cFJg3CE3ybjJVHza1+JA7Wt/F9pWHAGhePeCKL1UUhYHNqjJz9WHualGNX7afYn9SDinZhYT4eTiCou+G4Hqw4D5Ht/s5fWHkbxBYG4Dle5MB6NogBM3ZiVNa1ghkZExN5mw8xhu/76ND3WCZVEUIIYQQFVKiqYAVe5P5a08ShSfi6GLfTE/NNh7TnHYEnK3Ps7UBHPVtxamAtmSHdaR5dGN6GH3LzdrnouxIMS9EZVCQCd8MhJQ9pKj+DLdM5sRmL/wapPHV3wkAtK555WIe4Mke9bm/bXWq+ntyMDmHXadNbDicxuAW1c4HhTWFMSth7gBIPwRf94VRSyjyr8XiHYkA9Llosrsnu9dn0fbTHEjO4ed/TtE9MpQtCRl0iwxBJxOzCCGEEKKcMuVb2XgkjfiTWWw6nIo+cSv9tJt4SxtHuCbDuWi7DS0ZIW3wbdwLjwbd8QtpTDONRrrMi2uSYl6Iis6SBwvuhZQ9ZLsFMSTveY6pYWC1M3z2ZgCiqxoY0iriqpfRahSq+nsC0KleMLtOm1h/6KJiHsAvHEb9Dt8MgNT9MG8QW7p+R1qumUBvd7o0KN6V3uClY9xtdXnjj328tXQ/b/y+D1OBlUc612byHZEl9+cghBBCCFGKbHaVvWey2X4yk3UHU1l7MJVq9jMM0q7nY83fROhTnbF2Ny/Uej3QRvZHW68HVS6aa0iI6yHFvBAVmd0OP4+Bk5ux6w0Mz3+WY2oY0wZH8+rivRRYbQT76PnigZZ46K5/7FXHesF8suYI6w+loarqpd2+fENh5GLH2PnMBKovHYEvk+nfpMZlW9tHxNRgzsZjnM46PyZ/4daTPNmj/g3lJYQQQghR1lJyCvlx2ykWbD7B6awCDORyp/ZvftRuoJnuiDPO7u6DptGd0OhONLW6gM7DhVmLikCKeSEqslWvwoHfUbV6Pq82jZ17/GlSzcB9rSPw1Gn5Yt1RXh8URZjB84Yu27JGAJ46LWm5ZvYn5RAZ5ndpkE8IjPgF++xeVMs7woe6jwhotuiy1/PQaXnrriZM/3M/A5qGM2fjMU5lFrBkZyJ3t6x22dcIIYQQQriCqqqcyizgnxOZ/LU3mT93J1FkV2msHOMp/XL6af7GXbU4ghUt1O0GTe5F0+AOcPdybfKiQpFiXoiKauePsOF9AL4zPs1be/wB+E+3eo4J7ZpXZWDzqjd1ab2blna1A1l9IJUlO89cvpgH1IBa/NTgPfrHPcRt2h2oB2ZAjdcuG9uxXjAd63UEwFxk5+0/DzA/9rgU80IIIYS4Zew+beLVJXvZkpABgI4i7tBs5jHfVURa9zmCVCA0GpoPg6i7HA0cQpQCKeaFqIhS9sPi/wNgU9gDPH+kEVqNwrTB0XSLDC2Rt7i3dXVWH0jlqw3HGBlT8/ys9mclZxfy1A872HBYwzrNI8x0/whl44eOSfKi777qtYe0imDGioPEn8xi92kTUVUNJZKzEEIIIcSNsttVNh1NZ8HmE/yxOxFVhSBNHhP913Kn5Q98ijLAimPZ30YDoc0YiGgLMvu8KGUyVbQQFY0lD34cCdZ81Fpd+U9KXwDeuqvJNSe5uxG9GofSoro/BVYb7684dMn5ST/uYMPhNNzdNNS7fST2Dk86Tiz+D6RdGn+hKr56ejV2zHq/aLtjuZZtxzLo99F64o5nltg9CCGEEEJcTfzJLAZ98jfDvtzM77sSqaJmMjvsV7Z6T2BY/nxHIe8bBre9AE/uhbtnQ/V2UsiLMiHFvBAVzdJnHbPI+4TyT6u3SMmzYfDUcWez8BJ9G0VRnLPN/7DtJIdTcpzn1h1MZf2hNHRahSXjO/Kf7vXQdPsv1OwEllz4cRRYC65wZYc+UWEAbDiUBsAna46w+3Q2M1dd/UGAEEIIIcS/kWsu4qe4U4yes5VBn/zNjlMmarqb+L7aT8R6PUm3zB/QWPMcXenvmg0TdkGXZxwTAAtRhqSbvRAVyf7fYfs8QIG7vmTxLhsAPRqFlsqa7a1rBtKjUSjL9yYza10Cb93dBLtd5c2l+wF4IKYm9UN9HcEaLdz1JXzWEZJ3w/KX4Y7pV7x2+zpBKAocSM7hWFoefx92FPUbDqeRXWjFz0NX4vcjhBBCiMoru9DK1xuO8dXfCZgKrAAEks174avokv0bSlqhI7B6DHScCPV6SAu8cClpmReioshNhd8c4+RpPx57jU4s3Z0IQJ8oY6m97djOtQH4bccZTAVWFm0/zd7EbHw93Bh3W93iwb5GGPSZY3/L55Cw7orXDfB2p8nZsfLT/9yPucgOgNWmsnJfcsnfiBBCCCEqJVVV+WNXIt3eXcv7Kw5iKrASGaTlu/pr2Ob7FF0zfkApKoSIdjByCTy0DOr3lEJeuJwU80JUBKoKSyZAfhqENIbbX2T7yUySs8346N3oWC+41N66VY0A6of6UGC1MXv9Ud74wzGT6+Nd6xLg7X7pC+p2h5YPOvb/9wSYcy6NOatTvSoA/LErCQAPneNH1tKz3wshhBBC3Kx8SxELt5zgrk838vi3/5CaY6ZOkCeL2h/nD80EYk584ehOH9YMhv3sKOJrdXJ12kI4STEvREWw93+wf4ljFtXBn4ObnsU7HK3y3SJD0LtpS+2tFUVheLsaAHy46jAZeRYaGn0Z3bHWlV/U8zXwrw5ZJ+CvF68Y1umihxATutcHYM3BVHLNRf8+eSGEEEJUSsfT8+j/0Qae+2UX/5zIQqdVeLN1Pst9X6H5P5NRchIdv6vc/TWMXQP1uktLvLjlSDEvRHmXnwF/PO3Y7zgRjNEkmgr4bssJgJteS/5GDGpeFS93xwMDjQLT726Cu9tVfrzofeHOjx37cXPg8IrLhjWvHuC8rqdOy6j2NakZ5IWlyM6CzcdRVbUkb0MIIYQQlUDc8QwGfbKRI6l5hPrpmdLdyM7mi7lv18NokuLB3Re6T4EntkLUYCnixS1LinkhyrvlL0FeCgQ3gM6TAHh/+UHMRXZa1wyga/0qpZ6Cr4eOe1pWA+CRLnVoUs3/2i+q1RnaPOLY/994KMi6JMTdTUNM7SAAOtQNxkOnZVBzx/tM/WM/D3y1hbRcc0ncghBCCCEqgQ2H0hj+5RYy8ixEh/ux/LZTjIq7G8/dCxwBzYfD//0DHZ8EnYdrkxXiGkq0mJ82bRqtW7fG19eXkJAQBg4cyIEDB4rFjBo1CkVRim3t2rUrFmM2mxk/fjzBwcF4e3szYMAATp06VZKpClExnNp2dvZ6YMCH4KZn92kTP8U5/r881ycSpYyeJj/fN5KfH4vhmV4Nrv9F3V+GwNqQcwZWvHzZkIc71aZeiA+PdHFMtPf4bXWY0L0e7m4a1h9K45XFe0sifSGEEEJUYAUWGws2n+ChuVspsNq4q7aNX33fwu/P/0BBBoQ0gof+dPQc9AlxdbpCXJcSLebXrl3LE088QWxsLMuXL6eoqIiePXuSl5dXLK53794kJiY6tz/++KPY+QkTJrBo0SIWLlzIhg0byM3NpV+/fthstpJMV4jyzW6D359y7DcbxhZbfQbM3EC/jzZgVx0z2LesEVBm6ejdtLSsEXhjDw/cvWHATMd+3Fw4FXdJSEydIJZP7ELrmoEA6LQaJnSvz/djHQ8Bf995hhPp+f86fyGEEEJUTPNij9Nm6gqeX7QLS5GN16tt4Z20x9AeXw86L+jxKjyyDqq3u/bFhLiFlOg688uWLSv2/ddff01ISAhxcXF07tzZeVyv12M0Xn6pLJPJxOzZs5k3bx7du3cHYP78+URERLBixQp69epVkikLccs4nVXApiPpDGwWjtv1rAn/zzeQGA96P+g+hXe/PcDOUyYUBdrUDOSl/o1KPecSUbMDNLkPdi6E35+EMasda9JfQ/PqAXSuX4V1B1OZtf4orw2MKoNkhRBCCFGe/C/+NP/9dTcALf1z+cBzNtXSNjtOVm8PAz929BIUohwq1THzJpMJgMDAwGLH16xZQ0hICPXr12fMmDGkpKQ4z8XFxWG1WunZs6fzWHh4OFFRUWzcuPGy72M2m8nOzi62CVHevPy/3Uz6cQd/7rmONdTzM2DlK479257H4hFM/MksAH57oiPfPxJDmMGz9JItaT1fA70BEnfAtq+u+2WPnu16/8O2kzJ2XgghhBDFbDycxtM/7gTgnUZH+UmdRLXMzeDmCb3fhFG/SyEvyrVSK+ZVVWXixIl07NiRqKjzLWZ9+vTh22+/ZdWqVbz77rts3bqV22+/HbPZ8Yt4UlIS7u7uBAQU7x4cGhpKUtLl15aeNm0aBoPBuUVERJTWbQlRanaecjz82p90HQ+jVr0OBZmO8V2tx7D7jAlzkZ0ALx1RVf1KOdNS4BMC3f7r2F/5GuSmXD3+rJjaQTSN8MdcZOe7zSdKMUEhhBBClBdpuWYm/biDoV9uRmvLZ16V+dx99EUUczZUbQWPboB2j4FG5gIX5Vup/QseN24cO3fu5Lvvvit2/N5776Vv375ERUXRv39/li5dysGDB/n999+vej1VVa84Fnfy5MmYTCbndvLkyRK7DyHKQmaehZQcxwOto2l5Vw8+E3++9fqOt0HrRtyxTIAbH7N+K2n1EIQ1BbPJMUP/dVAUhXtbOR7erT+cVprZCSGEEKIcOJGez50z/+anuFM0VE6wxm8KnXL+ABTo9BQ8tAyC67o6TSFKRKkU8+PHj+e3335j9erVVKtW7aqxYWFh1KhRg0OHDgFgNBqxWCxkZmYWi0tJSSE0NPSy19Dr9fj5+RXbhChPDibnOPcTUq9SzKsqLJsMqBB1N9TsCMDWYxkAtK5ZdhPelTiNFvq+Byiw4zs4fvlhNReLqeNYui7+RBaFVpkkU4iSMm3aNBRFYcKECc5jqqoyZcoUwsPD8fT0pGvXruzZs6fY665nRZrMzExGjBjh7FE3YsQIsrKyyuCuhBAV2bG0PO79YhOnswoYa9jCH14vE2o5Ab5h8MD/oNtLoNW5Ok0hSkyJFvOqqjJu3Dh++eUXVq1aRa1ata75mvT0dE6ePElYWBgALVu2RKfTsXz5cmdMYmIiu3fvpn379iWZrhC3jGLFfFoeqqpePvDAUjixEdw8oIdjzLyqqsQddzz8alUz8PKvKy+qtYIWDzj2lz0Hdvs1X1IzyAujnwcWm51/jmdeM14IcW1bt27liy++oEmTJsWOT58+nffee4+ZM2eydetWjEYjPXr0ICfn/M+w61mRZujQocTHx7Ns2TKWLVtGfHw8I0aMKLP7E0JUPOm5ZobP3kyaKZcPfOfzvHkGGpsZ6naHR/+G2l1cnaIQJa5Ei/knnniC+fPns2DBAnx9fUlKSiIpKYmCggIAcnNzmTRpEps2beLYsWOsWbOG/v37ExwczKBBgwAwGAyMHj2ap556ipUrV7J9+3aGDx9OdHS0c3Z7ISqaAxcU8wVWG8nZl5nMzVYEK6Y49ts9BgZHr5eEtDzS8yzo3TTlc7z8xW7/r2OG/sQdsPP7a4YrikK72o6HGLFH00s7OyEqvNzcXIYNG8asWbOKzV+jqiozZszghRdeYPDgwURFRTF37lzy8/NZsGABcH5FmnfffZfu3bvTvHlz5s+fz65du1ixYgUA+/btY9myZXz55ZfExMQQExPDrFmzWLJkCQcOHHDJPQshyjdzkY1H5sVhzTzNIq83uNN6dtnrLs/C0B/BO8i1CQpRSkq0mP/0008xmUx07dqVsLAw5/b9945fyLVaLbt27eLOO++kfv36jBw5kvr167Np0yZ8fX2d13n//fcZOHAgQ4YMoUOHDnh5ebF48WK02msvVyVEeXQwKbfY90fTzn+vqipWmx3i50PaAfAMhI5Psu1YBhMWbuf9FY4hKk0j/NG7VYD/Iz5VoNNEx/7KV8Fy7TXkz3W13yTFvBD/2hNPPEHfvn0veYCekJBAUlJSsdVm9Ho9Xbp0ca42cz0r0mzatAmDwUDbtm2dMe3atcNgMFxx1RqQlWuEEJd3KjOfsd/EYT4Rx2KP/xJlPwAeBrj/e7jteZnkTlRoJbrO/BW7Bp/l6enJn3/+ec3reHh48NFHH/HRRx+VVGpC3LJUVXW2zIcZPEg0FZKQlkf7OsEAvLl0Pws27OMfw+voALo8Ax4G3lq2ka3Hzncrb1WjHI+Xv1jbx2DrV2A6AZtmOu75KtrVPjtu/mQWBRYbnu4V4KGGEC6wcOFC/vnnH7Zu3XrJuXMrylw8f01oaCjHjx93xlxrRZqkpCRCQkIuuX5ISMgVV60Bxxj+V1555cZuSAhRoX235QSvLN7DbbZNfOb+KZ5YoEok3L9AlpwTlYI8qhLCxVJyzJgKrGg1Ct0iHb/gnpsEL9FUwFd/JzBS+QNdQSr414BWD1FotbHjpGMpu6YR/kQEejK4xdUnmyxXdB7QY4pjf8MMyLnyL/gA1QO9CDd4YLWp/HNCxs0LcTNOnjzJf/7zH+bPn4+Hh8cV4y5eMeNqq81cKeZy8de6jqxcI4S40JoDKTy/aCej7b/wqfsHeCoWqNsDRv8lhbyoNKSYF8LFDiQ5WuVrBnnR0OgY855wdnm62esT8LNl8ajbYgDUbi+Bm57dp01YbHaCffT8+nh71j9zO3VDfFxzA6Wl8WCo1hqsebDq9auGOsbNO1rnN8gSdULclLi4OFJSUmjZsiVubm64ubmxdu1aPvzwQ9zc3Jwt8he3nl+42sz1rEhjNBpJTk6+5P1TU1OvuGoNyMo1QojzjqfnMfG7rbzt9jlP635wHGz7GNy/EDzkZ4OoPKSYF8LFzs1k38DoS61gb8BRzGflW/huywnGuf2Kj1LIDntt9gc5xrCe617fqkZA+V1X/loUBXpNdexvnw9Ju64a3qVBFQD+3J10zSE/QohLdevWjV27dhEfH+/cWrVqxbBhw4iPj6d27doYjcZiq81YLBbWrl3rXG3melakiYmJwWQysWXLFmfM5s2bMZlMsmqNEOKaCq02Jsz7m/dsb3G3dh2qooW+70KfN0FboiOIhbjlyb94IVzsXMt8/dDzxfyJjHxmrjqMvyWJ4R4rAXiz6H46HkgjMtyfbWfXlW9VnteVvx4RbRwt9Ht+cczkP/znK4be3jAEdzcNR9PyOJicSwOj7xVjhRCX8vX1JSoqqtgxb29vgoKCnMcnTJjA1KlTqVevHvXq1WPq1Kl4eXkxdOhQoPiKNEFBQQQGBjJp0qRiK9JERkbSu3dvxowZw+effw7A2LFj6devHw0aNCjDOxZClEcz/reRlzOepZn2KKqbJ8qQuVC/l6vTEsIlpGVeCBfbcSoLgIZGP4x+HnjoNBTZVb7ckMA4t1/RUURSUFs22Ruzcl8ydrvKtrPrqbcu7+vKX49u/wWNGxxeAcf+vmKYr4eOzvUckwYu3Z1YVtkJUak888wzTJgwgccff5xWrVpx+vRp/vrrrxtekebbb78lOjqanj170rNnT5o0acK8efNccUtCiHJkTexWhux8mGaao1jd/VFGLpZCXlRqiloB+6NmZ2djMBgwmUwypk7c0tJyzbR63bH28j//7UGgtzu9Z6xjf1IONZQkVuufRoON9HuX0HJuNooC3z7clqGzNuOp07JzSk902krwTG7Jk7DtK4hoCw/96eiCfxk/x53iqR930CDUlz+f7FzGSQpRNuQzzkH+HISoXJatWUuz1SMxKpmY3I0YxiyGKvVdnZYQpeJ6P+MqQRUgxK1r81FHd/mGRl8Cvd0B6Bbp6C7+da1VaLBB3R4ERXaicbgfqgqPzIsDoFmEf+Uo5AE6PwNunnByMxy88vKW3SND0WkVDiTncDgltwwTFEIIIURpWbhkKS1XD8eoZJLoXgOvx1ZKIS8EUswL4VKbjjpmXj83EzvA070asuuJGtRO/MNx4LbnAXihbyQBXjpyCosAaF3Rx8tfyC8M2o517K96Dez2y4YZvHS0r+Poav/nnqsvZyeEEEKIW9++uLX02vowVZRskr3qEzp+JbqACrQcrxD/ghTzQrhQ7NmW+Zg6QcWO6zdMB9UODftB1RYAtK8TzMqnunJ/mwhqBnkxoFl4mefrUh0mgN4Aybth95UnwutS3zGr/fYTWWWTlxBCCCFKhTlhExGL7yNAyeW4RySh4/9C41vF1WkJccuQYl4IF0nNMXM4JRdFgba1LpjILmk37Fnk2O86udhrAr3dmTa4CWuevo26IZVstnavQOjwf4791W+AzXrZsKiqBgD2njGVVWZCCCGEKGFFxzejzhuMD/lsVyLxf+QP8KxEvRKFuA5SzAvhIrFH0wGINPrh7+V+/sSaaY6vjQeDMeoyr6zE2j0G3iGQmQD/fHPZkMgwx0OOM6ZCMvIsZZmdEEIIIUpA0r6NmOcMxMOezyZbIzIHfYchoBKs4CPEDZJiXggXUFWVFfuSgeLj5UnaDfuXAAp0fc41yd3K3L2h89OO/bXTwZJ/SYivh46aQV4A7JHWeSGEEKJcyT/+D97f3423mk8ckZgGzef2JrVcnZYQtyQp5oUoY3a7yuu/7+N/8WcA6B4Zcv7k+nccXxsPhCoNyj658qDlKPCvDrlJsOXzy4Y0Dnd0td9zJrsMExNCCCHEv5K0G/WbO/Elj51KQ4yP/UbvFnVcnZUQtywp5oUoYx+sPMTsDQkAvNg3kvZ1HbOvk3oA9vzq2D/X+iwu5eYOXR0z/LNhBhRkXRLSuKpjPU4p5oUQQohyIv0I5q8H4G3LJt5eB/O931M1NOTarxOiEpNiXogytnR3IgAv9WvEw51qnz+x7h1AdcxgH9rYNcmVF02GQJVIKMyCjR9dcvp8y7x0sxdCCCFueTlJmOfcid6czl57DVa0/JTWDWu6OishbnlSzAtRhopsdhLS8gDo2Tj0/In0I7D7J8d+50kuyKyc0Wjh9hcc+5s/g7y0Yqcbhzta5hPS8sgzF5V1dkIIIYS4XgVZFH49EH3OSY7ZQ3k/9E3G3dHK1VkJUS5IMS9EGTqekY/VpuLlriXc4Hn+xPr3HOvK1+sJ4c1dl2B50rAfhDUFSy78PaPYqWAfPaF+elQVXvx1N13fXs3q/SmuyVMIIYQQl2ctIGfO3Xhk7CNF9Wda8FTef7gnHjqtqzMTolyQYl6IMnQoOReAOlV80GgUx8HM47BzoWO/8zMuyqwcUhS47UXH/pYvISep2OlzXe0XbT/NsfR8vttyoqwzFEIIIcSV2IpImzMU3+StZKtevBH4BtPH3ImP3s3VmQlRbkgxL0QZOpySA0C9EJ/zBze8D/YiqH0bRLR2UWblVL0eUK0NFBU4ejdcoFXNAADnLwXbjmeiqmqZpyiEEEKIi6gqhb88TvDpVRSqOmYaX2faY/dh8NS5OjMhypUSLeanTZtG69at8fX1JSQkhIEDB3LgwIFiMaqqMmXKFMLDw/H09KRr167s2bOnWIzZbGb8+PEEBwfj7e3NgAEDOHXqVEmmKoRLHEpxtMzXDT1bzJtOwfb5jv0u0ip/wxTl/Nj5uK8df55nPdShFl+NasXap7uid9OQkWfh6Nn5CoQQQgjhQitexmPP9xSpGqb7PcfTYx/Ey11a5IW4USVazK9du5YnnniC2NhYli9fTlFRET179iQv7/wv0NOnT+e9995j5syZbN26FaPRSI8ePcjJyXHGTJgwgUWLFrFw4UI2bNhAbm4u/fr1w2azlWS6QpSaK7UAn+tmXy/E13Hg7w/AboUaHaFG+7JKr2Kp1QVqdgKbBda97TzsodNye8NQgnz0NI3wB2DbsQwXJSmEEEIIALZ95fj9B3jWOpb+94xGp5XOwkLcjBL9n7Ns2TJGjRpF48aNadq0KV9//TUnTpwgLi4OcBQ4M2bM4IUXXmDw4MFERUUxd+5c8vPzWbBgAQAmk4nZs2fz7rvv0r17d5o3b878+fPZtWsXK1asKMl0hSgVH648RNupK9l6UeFos6scST1XzPs4xnjHzXWc7CLryt80RYHbzrbOb58PGQmXhLQ+2+V+27HMssxMCCGEEBc6vAL1d8eqPe9Y70HXchjNqwe4OCkhyq9SfQxmMjnWeA4MDAQgISGBpKQkevbs6YzR6/V06dKFjRs3AhAXF4fVai0WEx4eTlRUlDPmYmazmezs7GKbEK7y+85EUnLMPDovjtNZBc7jpzMLMBfZcXfTEBHo5Vgf3WZ2jPmu1cWFGVcANWKgTjfH3ANrp19yulVNx8+gbcelmBdCCCFcInkv/DAKRbXxk60z893v4ZneDV2dlRDlWqkV86qqMnHiRDp27EhUVBQASUmO2aZDQ0OLxYaGhjrPJSUl4e7uTkBAwBVjLjZt2jQMBoNzi4iIKOnbEeK6nTE5Cvj0PAtj5m6jwOIYHnLo7OR3dar4oC1Id3QzA+jyrKN1Wfw751rndy6EtEPFTrWoHoCiONadT80xuyA5IYQQohLLSYYFQ8CSw1a1EZOtD/NM70gCvd1dnZkQ5VqpFfPjxo1j586dfPfdd5ecUy4qXFRVveTYxa4WM3nyZEwmk3M7efLkzScuxL+QXWglp7AIgEBvd/YmZvPOX45JIM9NflcvxAc2zQRrvmNN+brdXJZvhVKtJTS4A1Q7rJlW7JTBU0eDUMc8BXHHZdy8EEIIUWYs+fDdfWA6SbIugofNE2hULYh7W0vjmxD/VqkU8+PHj+e3335j9erVVKtWzXncaDQCXNLCnpKS4mytNxqNWCwWMjMzrxhzMb1ej5+fX7FNCFdIzCoEwN9Lx7tDmgLw1d8JbDuW4RyvHR1QBFtmOV7Q+RlplS9Jtz3v+Lr7F0guvkrGuaXqtiRIV3shhBCiTNjtsOgROPMPhTp/huQ+SY7iw2sDo9Bq5PcfIf6tEi3mVVVl3Lhx/PLLL6xatYpatWoVO1+rVi2MRiPLly93HrNYLKxdu5b27R0zebds2RKdTlcsJjExkd27dztjhLhVnTk7Rj7c4MltDUIY3KIqqgr3fhHLin3JAPTO+xUsuRAaDQ36uDDbCsgYDY0GAiqsnlrsVJtaQQBsTkgv+7yEEEKIymjlK7DvN+wadx7I/w/HVSMv9m1Ek2r+rs5MiAqhRIv5J554gvnz57NgwQJ8fX1JSkoiKSmJggJHgaMoChMmTGDq1KksWrSI3bt3M2rUKLy8vBg6dCgABoOB0aNH89RTT7Fy5Uq2b9/O8OHDiY6Opnv37iWZrhAl7tyEd+H+ngC81K8RwT56bHYVXw83pverQcTBeY7gzpOkVb40dJ0MKLB/CZzZ7jzcrrZjEry9idlk5VtclJwQQghRSez8Af6eAcBzRWPZYmvAXS2q8WCHmi5NS4iKxK0kL/bpp58C0LVr12LHv/76a0aNGgXAM888Q0FBAY8//jiZmZm0bduWv/76C19fX2f8+++/j5ubG0OGDKGgoIBu3boxZ84ctFptSaYrRIk71zJf1d8DAH8vd755qA2rD6QwpFUEVf75EMwmqNIQIge4MtWKK6QhNBkCO793tM4P+9Fx2NeDOlW8OZKax5aEDHo2Nro4USGEEKKCOrMdfhsPwOf2O/nB0p4OdYN4Y1DUNefJEkJcvxIt5lVVvWaMoihMmTKFKVOmXDHGw8ODjz76iI8++qgEsxOi9J0r5sPOtswDNAr3o1G4H5hzIPZjx8HOT4OmVFeGrNy6PAu7foJDf8HJLRDRBoB2tYM4kppH7FEp5oUQQohSkZsKC4dDUSFr1ea8ZbmH2xuG8MmwFnjopGFOiJIk1YQQJeiMyTEBXvgFxbzT1tlQkAlBdaHxoDLOrJIJqgPNHEN3WP2G83BMHce4+U1HZdy8EEIIUeKKLPDDA5B9ihNKOOPMT9CuThU+G95SCnkhSoEU80KUoIu72TtZ8mDj2Z4mnZ4CjXyglbouz4BGB0fXwLENALQ9Owne/iQZNy+EEEKUuGXPwYmN5CtePFj4JP6BQXw8tAXublJyCFEa5H+WECXEZldJulLLfNwcyE+DgJoQfU+Z51Yp+VeHliMd+6veAFWliq+euiE+qCpsTpD15oW40KeffkqTJk2cS7zGxMSwdOlS53lVVZkyZQrh4eF4enrStWtX9uwpvgSk2Wxm/PjxBAcH4+3tzYABAzh16lSxmMzMTEaMGIHBYMBgMDBixAiysrLK4haFEKUpbg5sm42Kwjjz45xxq86sB1oR4O3u6syEqLCkmBeihKTmmCmyq2g1CiG+F7TMWwvg7w8c+x0nglbnmgQro05PgVYPJzbCkVXA+VntNx2RrvZCXKhatWq8+eabbNu2jW3btnH77bdz5513Ogv26dOn89577zFz5ky2bt2K0WikR48e5OTkOK8xYcIEFi1axMKFC9mwYQO5ubn069cPm83mjBk6dCjx8fEsW7aMZcuWER8fz4gRI8r8foUQJehELPw+CYD3bfewyt6Cl/o3oqHRz8WJCVGxSTEvRAk5tyyd0c8DreaCmVr/mQe5yWCIgKb3uyi7SsovHFqPduyvdrTOx9QOBiBWxs0LUUz//v254447qF+/PvXr1+eNN97Ax8eH2NhYVFVlxowZvPDCCwwePJioqCjmzp1Lfn4+CxYsAMBkMjF79mzeffddunfvTvPmzZk/fz67du1ixYoVAOzbt49ly5bx5ZdfEhMTQ0xMDLNmzWLJkiUcOHDAlbcvhLhZuSmoPzwAdivLaceH1jvp3djIfa0jXJ2ZEBWeFPNClJDz4+Uv6GJfZIYN7zv2Oz4JbtLVrMx1fBJ0XnA6Dg4uo+3Zlvn9STlk5Mm4eSEux2azsXDhQvLy8oiJiSEhIYGkpCR69uzpjNHr9XTp0oWNGzcCEBcXh9VqLRYTHh5OVFSUM2bTpk0YDAbatm3rjGnXrh0Gg8EZcyVms5ns7OximxDCxew21J9Go+Qmc9Belf8UjiUyzMCbd0XLEnRClAEp5oUoIeeXpbugi/32+ZBzBnzDoflwF2VWyfmEQJuxjv3VbxDspaNeiA8AWxKkdV6IC+3atQsfHx/0ej2PPvooixYtolGjRiQlJQEQGhpaLD40NNR5LikpCXd3dwICAq4aExIScsn7hoSEOGOuZNq0ac5x9gaDgYgIafUTwuXWTkc5to48Vc//2Z7ksR5N+N8THfD3ksYLIcqCFPNClJDEiye/K7Jc0Co/Adz0rklMQIf/gLsvJO2Cfb85l6iLPSqT4AlxoQYNGhAfH09sbCyPPfYYI0eOZO/evc7zF7e0qap6zda3i2MuF38915k8eTImk8m5nTx58npuSQhRWo6sQl37FgAvWEfz0MDejO9WT2auF6IMyf82IUrIuTHzzmJ+50IwnQTvEGjxgAszE3gFQszjjv0102hXyx+QSfCEuJi7uzt169alVatWTJs2jaZNm/LBBx9gNBoBLmk9T0lJcbbWG41GLBYLmZmZV41JTk6+5H1TU1MvafW/mF6vd860f24TQrhIdiL2n8agoLKg6Ha8Wg9liIyRF6LMSTEvRAlQVZUdJ7MAqBXkDbYiWP+u42SH/4DO88ovFmWj3ePg4Q+p++lUuBaAA8k5pOeaXZuXELcwVVUxm83UqlULo9HI8uXLnecsFgtr166lffv2ALRs2RKdTlcsJjExkd27dztjYmJiMJlMbNmyxRmzefNmTCaTM0YIcYuzFcFPD6EpSGOvvQYLgx7n5f6NXJ2VEJWSFPNClIA9Z7JJyTHj5a6lVc0A2PUjZB4Dr2Bo9aCr0xMAnv7QfjwAvrHvEBniBcAWWW9eCACef/551q9fz7Fjx9i1axcvvPACa9asYdiwYSiKwoQJE5g6dSqLFi1i9+7djBo1Ci8vL4YOHQqAwWBg9OjRPPXUU6xcuZLt27czfPhwoqOj6d69OwCRkZH07t2bMWPGEBsbS2xsLGPGjKFfv340aNDAlbcvhLheq1+HExvJUT0ZX/Qf3rinDXo3rauzEqJScnN1AkJUBCv3pQDQqV4wHlpg/TuOE+3Hgbu36xITxbV9FGI/gYyjPFJ9MxNSotlyLIM+0WGuzkwIl0tOTmbEiBEkJiZiMBho0qQJy5Yto0ePHgA888wzFBQU8Pjjj5OZmUnbtm3566+/8PX1dV7j/fffx83NjSFDhlBQUEC3bt2YM2cOWu35X/S//fZb/u///s856/2AAQOYOXNm2d6sEOKm5O/+Ha+z8wE9ax1Dr84diK5mcHFWQlReiqqq6vUGjxo1iqysLH799ddSTOnfy87OxmAwYDKZZEydKBN3ztzAjlMmpt/VhCEem+Hn0eAZABN2gd732hcQZWfjR/DXi+R6htM88006NAhjzoNtXJ2VENftRj/jRo0axdy5cwHQarWEh4fTt29fpk6desnM8+WJfNYLUbbM6ccxz+yAn5rDnKKebGrwLB/c1xwPnbTKC1HSrvczTrrZC/EvpeQUsuOUCYCuDYJg3duOEzFPSCF/K2o1GnyM+BSc4V7tao6n57s6IyFKXe/evUlMTOTYsWN8+eWXLF68mMcff9zVaQkhyosiC5lzhuGn5rCHOtQe9j6fj2glhbwQLibFvBD/0pr9qQA0rWYg5ORfkLofPAzn1zYXtxZ3L+j0FADj3H4lJSOLIpvdxUkJUbr0ej1Go5Fq1arRs2dP7r33Xv766y9XpyWEKCeyl7yAMWcXJtWLMz0+pXNkNVenJIRAinkh/rVV+x3j5W9vUOV8q3zbxxwFvbg1tRyJ6lcNo5LJvcoK57KCQlQGR48eZdmyZeh0OlenIoQoB9S9v+EX/wUAs4OfoXt7GZomxK1Cinkh/qXtJx1rKt+h3w7Ju8HdF9o96uKsxFW56VG6PA3AY27/43hSqosTEqJ0LVmyBB8fHzw9PalTpw579+7l2WefdXVaQohbXUYC1l8cQ3Jm2/sy6P6xKIri4qSEEOdIMS/Ev5CaYyY524yiqNTe87HjYNuxjsnvxK2t2TBS3cKoomTjFf+1q7MRolTddtttxMfHs3nzZsaPH0+vXr0YP368q9MSQtzKisxYFj6Ae1EOcfZ60O1lagXLCj1C3EqkmBfiBiVnF7LuoKMld88Zx8R3Dxh2oU3e6WiVjxnnyvTE9dLqiK0+BoBGR7+CwmwXJyRE6fH29qZu3bo0adKEDz/8ELPZzCuvvOLqtIQQtzD1zxdwT9lJhurDFyH/ZVSn+q5OSQhxESnmhbhBk37cwQNfbWH1/hT2nMlGg51H7AsdJ2MeB69A1yYorltu/cEctofjZct2rD8vRCXx8ssv884773DmzBlXpyKEuBXt/hll6ywAnrU/wXP3dUerke71QtxqSrSYX7duHf379yc8PBxFUS5Zj37UqFEoilJsa9euXbEYs9nM+PHjCQ4OxtvbmwEDBnDq1KmSTFOIm2a3q/xz3DFGfunuRPaeyaafZhPhlmPg4Q/tZKmn8qRGsC/vFd3t+ObvDyEn2bUJCVFGunbtSuPGjZk6daqrUxFC3GrSDqP+5hiG83HRABp3uVu61wtxiyrRYj4vL4+mTZsyc+bMK8acW+v23PbHH38UOz9hwgQWLVrEwoUL2bBhA7m5ufTr1w+bzVaSqQpxU05m5pNncfxbXLU/lb2nMpjg9rPjZPvx4OnvuuTEDasZ7M0f9rbE2+uANQ/WvunqlIQoMxMnTmTWrFmcPHnS1akIIW4V1gL4cSSKJY/N9ob85DuSR7vUcXVWQogrcLuR4Dlz5lz1fJ8+fejTp89VY86tdXs5JpOJ2bNnM2/ePLp37w7A/PnziYiIYMWKFfTq1etG0hWixO1LzHHup+WauU27htq6JOyeQWjaygz25Y3RzwO9m5ap1qH8oH8N4uY6lhWsIuMCRcVxpc/uoUOHMnTo0LJNRghxa1v6DCTvJk31Y7xlPNPuj8ZDp3V1VkKIKyjzMfNr1qwhJCSE+vXrM2bMGFJSUpzn4uLisFqt9OzZ03ksPDycqKgoNm7ceMVrms1msrOzi21ClIZ9ief/beko4j9uvwCg6TQR9D6uSkvcJI1GoUaQF1vUSNKqdgPVBiumuDotIYQQouztWAj/fIMdhf+zjqNbm6Z0iwx1dVZCiKso02K+T58+fPvtt6xatYp3332XrVu3cvvtt2M2mwFISkrC3d2dgIDiy3qFhoaSlJR0xetOmzYNg8Hg3CIiIkr1PkTltT/JUcw3CvPjXu1qqilpZGmDoPVoF2cmblaNIMc4wA01x4OihQO/w/ErPzwUQgghKpyU/aiLnwTgA+tgCqt1ZMqARi5OSghxLWVazN9777307duXqKgo+vfvz9KlSzl48CC///77VV+nqiqKcuUZNCdPnozJZHJuMv5PlJZz3eyf6FSVcW6/AvBPjYdA5+nCrMS/cW5Sn+WpBmg50nHwrxdBVV2YlRBCCFFGLHkULRyBUpTPelsUP3rdx6fDW6J3k+71QtzqXLo0XVhYGDVq1ODQoUMAGI1GLBYLmZmZxeJSUlIIDb1yNx+9Xo+fn1+xTYiSlmsu4kRGPgBdc5ZgVDI5pQbj2fZBF2cm/o07osNQFPh9ZyIbI8aAzhtOx8GeRa5OTQghhChdqop98ZO4ZRwkWfXnDY+JfPtIB0L9PFydmRDiOri0mE9PT+fkyZOEhYUB0LJlS3Q6HcuXL3fGJCYmsnv3btq3b++qNIUA4MDZLvY1fFW8t3wIQEG7icQ0qOrKtMS/1CzCn1HtawLw9NIkzO0cy/Gw8hUoMrsuMSGEEKK0bZ+HZtf32FSF55Qn+XhsL1mGTohypESL+dzcXOLj44mPjwcgISGB+Ph4Tpw4QW5uLpMmTWLTpk0cO3aMNWvW0L9/f4KDgxk0aBAABoOB0aNH89RTT7Fy5Uq2b9/O8OHDiY6Ods5uL4SrnOti/7j3KshLhYBa1Os51sVZiZLwdK8GRAR6cjqrgC8svcEnFDKPwdbZrk5NCCGEKB1Ju7D//jQA7xTdS9/+d1OnikzmK0R5UqLF/LZt22jevDnNmzcHHGvYNm/enJdeegmtVsuuXbu48847qV+/PiNHjqR+/fps2rQJX19f5zXef/99Bg4cyJAhQ+jQoQNeXl4sXrwYrVbG7QjX2peYjYFc7sz5wXGg63Og1bk2KVEivNzdmNjDsRzdHwdz4bbnHSfWTYeCLNclJoQQQpSGwmzUH0aisRWyytaMPbVGcVcL6WkoRHlzQ+vMX0vXrl1RrzJp1J9//nnNa3h4ePDRRx/x0UcflWRqQvxru0+beNztf3jYciCkMUTf4+qURAnqXK8K4Hhok1L3bkKCP4G0A7D+Hej5uouzE0IIIUqIqsLi/6BkHOG0GsQLjOOHwU2vOtm0EOLW5NIx80KUF2m5ZtJOH2GU9i/HgR6vgEZ6i1QkQT56oqo6Js/8+2gW9HzNcSL2M0g/4rrEhBBCiJK09UvY8wtWtIy3jGd0z5ZEBHq5OishxE2QYl6I67DmQCoT3X5Er1ihZieoK3M4VEQd6zpa59cfSoN6PR1/z3Yr/Pm8izMTQgghSsCZ7ahnP9PetN5HUdXWzklghRDljxTzQlyHAzs2MkizwfFNj1dAuqJVSJ3rBQOOYl4F6DUNNG5wcBkcWuHS3IQQQoh/pSCLgm9HoNgs/GVryTf05c3BTXDTSjkgRHkl/3uFuAZLkZ3Oxz9Go6hk1eoHVVu6OiVRSlrWDMBDpyE1x8yB5ByoUh/aPuo4+edksFldm6AQQghxM1SV7IVj8cw7yUl7FWb6TWTh2PY0CvdzdWZCiH9BinkhruFg7BI6KfEUocWv76uuTkeUIr2blra1ggBYfzDNcbDz0+AVDGkHYcssF2YnhBBC3JyC9R/hd/xPzKobX1edwg8T+tCyRoCr0xJC/EtSzAtxNXY7gRsdM5lvDrwTTXAdFyckSlv7Oo5iPu54puOApz90e8mxv+ZNyEtzTWJCCCHETVBPxOK+agoAH7s/yH9G3IuHTibxFaIikGJeiKuwx39LeP4BslVPzO0nuTodUQaiqxoA2JNoOn+w+XAIawpmE6yY4prEhBBCiBuVm0r+tyPQYuMPezu6P/ACBi+dq7MSQpQQKeaFuBJzDkXLXwHgC+Uu2jdt6OKERFk4N37wZEYBpvyzY+Q1WujztmN/+zw4sdlF2QlReqZNm0br1q3x9fUlJCSEgQMHcuDAgWIxqqoyZcoUwsPD8fT0pGvXruzZs6dYjNlsZvz48QQHB+Pt7c2AAQM4depUsZjMzExGjBiBwWDAYDAwYsQIsrKySvsWhahc7Dayvx2JtzmFw/ZwTD3eo0mEdK0XoiKRYl6IK1n/Hu4FqSTYQ8ls/JB0Sask/L3cqRbgCVzUOl+9raOFHuD3iWArckF2QpSetWvX8sQTTxAbG8vy5cspKiqiZ8+e5OXlOWOmT5/Oe++9x8yZM9m6dStGo5EePXqQk5PjjJkwYQKLFi1i4cKFbNiwgdzcXPr164fNZnPGDB06lPj4eJYtW8ayZcuIj49nxIgRZXq/QlR05hVv4Jf4N/mqnu9rv8F9HRu5OiUhRAlzc3UCQtySMo+hbvoYBXijaDhjWtZ0dUaiDDUO9+NUZgF7z2TTvk7w+RPdX4X9v0Pybtj8GbQf57okhShhy5YtK/b9119/TUhICHFxcXTu3BlVVZkxYwYvvPACgwcPBmDu3LmEhoayYMECHnnkEUwmE7Nnz2bevHl0794dgPnz5xMREcGKFSvo1asX+/btY9myZcTGxtK2bVsAZs2aRUxMDAcOHKBBgwZle+NCVEQH/0K/8V0A3vV4nCfvH4Aiy+oKUeFIy7wQl7P8JRSbmQ22xuzz7UDrmoGuzkiUocbhZ8fNn8kufsI7CHqcXdFgzTQwnS7jzIQoOyaTo2dKYKDj519CQgJJSUn07NnTGaPX6+nSpQsbN24EIC4uDqvVWiwmPDycqKgoZ8ymTZswGAzOQh6gXbt2GAwGZ8zlmM1msrOzi21CiMvIPI71p4cBmGfrQe/7/w8fvbTfCVERSTEvxMWO/Q17/4cdDa8VjWBQi2poNPI0uzJpfHbc/J4zpktPNhsOEW3BkutYe16ICkhVVSZOnEjHjh2JiooCICkpCYDQ0NBisaGhoc5zSUlJuLu7ExAQcNWYkJCQS94zJCTEGXM506ZNc46xNxgMRERE3PwNClFBFRbkk/zVfegsJuLtdTjV+kVpkBCiApNiXogL2Ypg2bMAfGe7nQNqdQa1qOripERZO9cyfzgllwKLrfhJjQb6vgeKFvb+Dw4td0GGQpSucePGsXPnTr777rtLzl3cVVdV1Wt237045nLx17rO5MmTMZlMzu3kyZPXug0hKpVCq41VMx4iNGcvmaoPXxpf4sk+0a5OSwhRiqSYF+JCW7+EpF2Y3fx413o3TasZqFPFx9VZiTIW6qcn2Mcduwr7ky7TldcYBe0ec+wvmQjm3LJNUIhSNH78eH777TdWr15NtWrVnMeNRiPAJa3nKSkpztZ6o9GIxWIhMzPzqjHJycmXvG9qauolrf4X0uv1+Pn5FduEEOctmTeDO8xLsaOwL+ZdPnrsTpm8V4gKTop5Ic7JSYJVrwPwpf4BMvBjYHNpla+MFEWh0ZXGzZ/TdTL4VwfTCVj5ahlmJ0TpUFWVcePG8csvv7Bq1Spq1apV7HytWrUwGo0sX36+N4rFYmHt2rW0b98egJYtW6LT6YrFJCYmsnv3bmdMTEwMJpOJLVu2OGM2b96MyWRyxgghbszGTRu44/hbAJyMeoL2ve+TCe+EqASkmBfinD9fAEsOhSHNeTe9HVqNQv+m4a7OSrhI1Nlx81sSMi4foPeB/h849rd8ASdiyygzIUrHE088wfz581mwYAG+vr4kJSWRlJREQUEB4HjINWHCBKZOncqiRYvYvXs3o0aNwsvLi6FDhwJgMBgYPXo0Tz31FCtXrmT79u0MHz6c6Oho5+z2kZGR9O7dmzFjxhAbG0tsbCxjxoyhX79+MpO9EDchOSWF8D8fxksxc9SvDTUGywNmISoLKeaFADi6Fnb/hKpo+MTrMexo6FK/CsE+eldnJlykV2NHl+Jlu5PIyLNcPqjO7Y4J8VDht/FgLSy7BIUoYZ9++ikmk4muXbsSFhbm3L7//ntnzDPPPMOECRN4/PHHadWqFadPn+avv/7C19fXGfP+++8zcOBAhgwZQocOHfDy8mLx4sVotee7+3777bdER0fTs2dPevbsSZMmTZg3b16Z3q8QFYHNZuP0V8OpSSKpmmCqjp4PGulaL0Rloaiqqro6iZKWnZ2NwWDAZDLJmDpxbUUW+LQ9pB9iblEPXi56EIBPhrXgjugwFycnXEVVVfrP3MDu09k8f0dDxnauc/nAgkz4uC3kJkOnp6DbS2WbqKh05DPOQf4chIBtX0+i1fFZFKo6Uof8RkRjGaoiREVwvZ9x0jIvxKaPIP0Q6Rh4t2gIzSL8eWNQFH2ijK7OTLiQoigMb1sDgG83n8Buv8JzT88AuOMdx/6GGZC4o2wSFEIIUakdXruAVsdnARDf7BUp5IWohKSYF5Vb2mFYOx2A1y1Dseh8+fHRGIa1rSETxwgGNAvH18ON4+n5/H0k7cqBjQZA5ABQbbDoMSgyl12SQgghKp2MhHjCVz8JwKqAe2g78HEXZySEcIUSLebXrVtH//79CQ8PR1EUfv3112LnVVVlypQphIeH4+npSdeuXdmzZ0+xGLPZzPjx4wkODsbb25sBAwZw6tSpkkxTCAe73THOuaiQxOAYFtk70jwiAJ1WnnEJBy93N+5q4Via66e4a/wc6vsueAVDyh5Y/UYZZCeEEKIyOnn6DOb59+FFIf9om9B27ExpgBCikirRqiUvL4+mTZsyc+bMy56fPn067733HjNnzmTr1q0YjUZ69OhBTk6OM2bChAksWrSIhQsXsmHDBnJzc+nXrx82m60kUxUC4r6CExtB582X/v8BFFrXDHB1VuIW06+JY96ENQdSKbLZAceDyUv4hJyf3f7vD+HY32WVohBCiEpi/sYjHPviPsJsiZxSq2AYMR9vTw9XpyWEcJESLeb79OnD66+/zuDBgy85p6oqM2bM4IUXXmDw4MFERUUxd+5c8vPzWbBgAQAmk4nZs2fz7rvv0r17d5o3b878+fPZtWsXK1asKMlURWWXdRKWv+zY7/YSy884Pghb1gx0YVLiVtS8egD+XjpMBVb+OZHFqv3J1HthKV9tSLg0OLIfND87u/2vj0LhFdaoF0IIIW7Q/+JPk/vHy3RSdlCo6OG+b6lTs4ar0xJCuFCZ9SdOSEggKSmJnj17Oo/p9Xq6dOnCxo0bAYiLi8NqtRaLCQ8PJyoqyhlzOWazmezs7GKbEFekqrDkSbDkQkRbkhuO4ERGPhoFWlT3d3V24haj1Sjc1iAEgJX7knlr6QGK7Crv/HWAlJzLLEXX+03wrwFZJ2DZ5DLOVgghREW042QWm37+kEfdFgOgv+szqkW2dXFWQghXK7NiPikpCYDQ0NBix0NDQ53nkpKScHd3JyAg4IoxlzNt2jQMBoNzi4iIKOHsRYWy83s4vBy07jDgI7adcDz8aWj0w9dD5+LkxK3o9oaOYv6bTcc5kOwYFpRvsfHBikOXBut9YdBngALx82Hf4jLMVAghREWTlmvm87lzeVXjmLne3mkSStSlvWCFEJVPmc/0dfEEHaqqXnPSjmvFTJ48GZPJ5NxOnjxZIrmKCsh0isLfJgGQ2+4pqNKAbcczAGS8vLiizvWroNUoFFgdc3fE1A4CYOHWkxxJzb30BTXaQ4f/OPb/N87RSi+EEELcIJtdZdq8xUy1voW7YsMaORDN7S+6Oi0hxC2izIp5o9GxZvfFLewpKSnO1nqj0YjFYiEzM/OKMZej1+vx8/MrtglxCbsd2y+P4WHLId5em4W6QQBsOpIOyHh5cWUGT53zYY+7VsOM+5rRPTIUm13li7VHL/+i216Aqi2hMAt+Gg02a9klLIQQokL4bOkWxiU+j7+SR0FoC3SDPwOZuV4IcVaZFfO1atXCaDSyfPly5zGLxcLatWtp3749AC1btkSn0xWLSUxMZPfu3c4YIW7a5k/RHl9HvqrnSesTrDiYwbG0PPYn5aDVKHSqG+zqDMUtbEDTqgDc2zqCUD8PHupQE4CV+5Ox2y8zu72bO9z9FegNcGoLrHqtDLMVQghR3q3Ze5JWm/+PWppk8ryq4jnie9B5ujotIcQtxK0kL5abm8vhw4ed3yckJBAfH09gYCDVq1dnwoQJTJ06lXr16lGvXj2mTp2Kl5cXQ4cOBcBgMDB69GieeuopgoKCCAwMZNKkSURHR9O9e/eSTFVUIjNWHOTo7i18kDMFBXijaBgJahgnjmXy/TbHkIyY2kEEeLu7NlFxS7u/TQSRYb5EVzUA0KpmIL56N9JyLew8baJZhP+lLwqoCXfOhB9GwN8fQM1OUK9HmeYthBCi/DmVkUfOD4/TVbOfQo033qN+diyBKoQQFyjRYn7btm3cdtttzu8nTpwIwMiRI5kzZw7PPPMMBQUFPP7442RmZtK2bVv++usvfH19na95//33cXNzY8iQIRQUFNCtWzfmzJmDVqstyVRFJWHKtzJr9X5+0r6JorHwt6Yl39q6odMqWG0qX653dJHuE210cabiVqcoCs2rn59Xwd1NQ+f6Vfh9VyKr9iVfvpgHaDQA2oyFLV/Aokfg0Q3gF142SQshhCh3zEU21nz5LMNZhw0NmnvnQkikq9MSQtyCFFVVL9M/tHzLzs7GYDBgMplk/Hwlt2DzCXIXP8dYt99JU/3obX6LXF0A97WuzpyNxwDQKLD5+e5U8dW7NllR7vwcd4qnftxB43A/fv+/TlcOtBbC7B6QtBOqtYFRS8BN/r2JmyOfcQ7y5yAqqkVfvcWgE1MByLjtLQK7POrijIQQZe16P+PKfDZ7IcrSyU0/MdbtdwCes44hDQMd61bhjugwZ0zrmoFSyIub0rVBFRQF9pzJJsl0mTXnz9F5wD1zwOPs+Pmlz5RZjkIIIcqP2D8X0P/4mwAcb/iwFPJCiKuSYl5UWGeOHeDRzLcBSGw4ijW0AqBbZAgtqvtj8HSsKX9hYS/EjQjy0dP8bPf6lfuTrxFcB+6aDSgQNwe2fV3a6QkhhCgnrDY73//yC003/gc3xc6e4D7UGPK2q9MSQtzipJgXFVORGc1PozAo+RzWNSDs7rd5uX8jejQKpX/TcNy0Gl64I5LejY0MblHV1dmKcqx7I8eymbPWHaXAYrt6cL0e0O2/jv0/noYTm0s5OyGEELe6fEsRT3/6Ez13jMdTsbDXuw0Nxs4FjfyaLoS4OvkpISok9a8XMebuJUv15mDnmeDmzoiYmsx6oBU+ese8j0NaR/DZiJb4euhcnK0oz4a3q4HRz4Nj6fm8v+LgtV/QcSI0uhPsVscs99mJpZ+kEEKIW5LNrjJl3jImpU4mQMkl0z+ayP/7BTd3Gf4nhLg2KeZFxbNnEcqWLwB41v4Endu0cHFCoiLz89DxxqAoAL5cf5TtJzKv/gJFgTs/gZBGkJsM390HlrwyyFQIIcSt5r1f1vHY8YlUU9Io9KtFwJhfUfS+136hEEIgxbyoaJJ2w69PAPBJ0QA8Gt/hbIkXorR0iwxlYLNw7CqMW7Cd9Fyz85ylyE7s0XTMRRd0wdf7wH3fglcQJMbDT6PBfo0u+kIIISqUP7fuof/OJ6ilSSbfKxyP0UvAO9jVaQkhyhEp5kWFsXTzTjJm3wXWPGJpwrtF9zC4RTVXpyUqiVcGRFEr2JvTWQU89u0/nMzIZ/2hVPp+uJ77vojl2Z92Fn9BYG24fyFo9XBwKSx9FireSqFCCCEu41RiMlV/H0FDzUlydcF4Pfw7GOR3FiHEjZFiXlQIFnMhIUvHEmhN4gRGHikcR6CvFx3qBLk6NVFJGLx0zHqgJT56N7YkZNBp+mpGzN7CoZRcAH7bcYZjaRd1p49oA4O/ABTYOgs2fVz2iQshhChTRQXZ5Hw1iCiOkK34oR+92PGAVwghbpD0Pxbln6qS/v04WrKPbNWTBy1PYcKHh8/OWi9EWakb4svHw1ow+eedpOdZ0Gk13NksnGPpefx9OJ0v1h9l6qDo4i9qPBBMr8FfLzo2Q1VoPMgl+QshhChl5hySP+1PpHUP2aoXeff+iJ+xkauzEpWYzWbDarW6Oo1KR6fTodVq//V1pJgX5V/sp4Qd/RGbqjA37CWU/Aa4p+dzb+sIV2cmKqEu9auwcXK3Ysc2H03n78Pp/BR3ignd6xHi61H8RTHjIPMYbP0Sfh4Del+o273skhZCCFH6CrPJ+WogVbPjyVa92N71a7pEtnN1VqKSUlWVpKQksrKyXJ1KpeXv74/RaERRlJu+hhTzonzbswj1z+dRgKlFQ+nWfQiP1AzEVGCliq8s6yJuDW1qBdKiuj//nMhi9voEJt8RWTxAUaDPdMhLg72/wsLhMGIR1IhxSb5CCCFKWKEJy9zB+KbEYVK9mF37fSbe1tvVWYlK7FwhHxISgpeX178qKMWNUVWV/Px8UlJSAAgLC7vpa0kxL8qvhPXwy1gUVOYXdWORfiCTawXiptVIIS9uKYqi8MRtdRk9dxtzNh5jVIeahBk8iwdptDB4lmOZusPLYcEQGLkYwpu5JGchhBAlJD8D67y7cU+MI0v15jnv13jnvrtdnZWoxGw2m7OQDwqS+aVcwdPT8XtgSkoKISEhN93lXgYUi/IpaRcsHAo2C7sNXXip6EF6NjbKGHlxy7q9YQhtagZiLrLz3l8HLx/k5g73zoMaHcGcDfMGQcr+sk1UCCFEyclJwvbVHejOFvJP6l/hpbFDZdlc4VLnxsh7eXm5OJPK7dyf/7+Zs0AqH1H+ZB6H+XeBOZuc0DbclzYaOxruiL75LipClDZFUXjujoYA/PzPKeZuPMav209jKrjoB7jOE+7/DsJbQEEGzO0HyXtdkLGojNatW0f//v0JDw9HURR+/fXXYudVVWXKlCmEh4fj6elJ165d2bNnT7EYs9nM+PHjCQ4OxtvbmwEDBnDq1KliMZmZmYwYMQKDwYDBYGDEiBEyblNUPBlHsc/uiTZtH8mqP4/qXuflsUMJ9/e89muFKAPStd61SuLPX4p5Ub5kn4F5AyE3GWtQQ/qnjSPX5kavxqF0qhfs6uyEuKoW1QO4I9qIXYWXf9vDhO/jeWTeNuz2i9aX9/CD4T+DsQnkpcKcvpC4wzVJi0olLy+Ppk2bMnPmzMuenz59Ou+99x4zZ85k69atGI1GevToQU5OjjNmwoQJLFq0iIULF7JhwwZyc3Pp168fNpvNGTN06FDi4+NZtmwZy5YtIz4+nhEjRpT6/QlRZpL3oM7ujSbrOMftITykeZ1XHr6HmsHers5MCFGBSB8fUX5kJ8Kcfo4n3YbqPGybzLE8NxoafXlvSDN5uijKhZf6NUZRFPLMRcQeTSf2aAbfbT3BsLY1igd6BcLI3xy9UE7Hwdz+MHwRVGvpmsRFpdCnTx/69Olz2XOqqjJjxgxeeOEFBg8eDMDcuXMJDQ1lwYIFPPLII5hMJmbPns28efPo3t2xIsP8+fOJiIhgxYoV9OrVi3379rFs2TJiY2Np27YtALNmzSImJoYDBw7QoEGDy76/2WzGbDY7v8/Ozi7JWxei5CSsR/1+GEqhiX32CB5TXuSDh3rTwOjr6syEqLC6du1Ks2bNmDFjhqtTKVPSMi/Kh5wkRzGTcQTVEMGrQW+xNklHgJeOWQ+0wlvGnolywmjw4OOhLZjzYBue6eXodj/tj/2cySq4JHZ3hobC+3+GiHZQaIJv7oTjm8o6ZSEASEhIICkpiZ49ezqP6fV6unTpwsaNGwGIi4vDarUWiwkPDycqKsoZs2nTJgwGg7OQB2jXrh0Gg8EZcznTpk1zdss3GAxERMjyo+IWtGMh6rxBKIUmttnrM9L+Mm+N7EHTCH9XZyaEOGvNmjUoilIhhndJMS9KnKqqFNnsJXfBnGTUOf0h/RDpbiGMd3+NOXtV3DQKnwxrSUSgTN4hyqeR7WvSoro/ueYiRs/dRkpOofPcou2n6PfRBqb8edLR5b5mJ7DkOIaZ7FvsuqRFpZWUlARAaGhoseOhoaHOc0lJSbi7uxMQEHDVmJCQkEuuHxIS4oy5nMmTJ2MymZzbyZMn/9X9CFGiVBXWvAWLHkGxW1lia8so2wtMH9GFtrVltnAhROmQYl6UqAKLjWFfbqbz9NUcTsm59guuJeskhV/2QUk/yBk1kIF5k1ly0h2Al/s3IqaOfECK8kurUXh3SDOCffTsS8zmns82cTIjH1VV+XJ9AgCLd5yhUOMJQ3+A+n2gqBC+HwFbZrk4e1FZXTykSVXVaw5zujjmcvHXuo5er8fPz6/YJsStQLUWcGTWA7BmKgCfFfXnNf0kZj3Uia4NLn1wJcStSFVV8i1FLtlUVb12ghfIy8vjgQcewMfHh7CwMN59991i5+fPn0+rVq3w9fXFaDQydOhQ55rux44d47bbbgMgICAARVEYNWoUAMuWLaNjx474+/sTFBREv379OHLkyL//wy1FZdo3ecqUKbzyyivFjl34tF5VVV555RW++OILMjMzadu2LR9//DGNGzcuyzTFTVJVlWd+3snGI+kAjPkmjl8f74DBS3dzF0w9QMFXA/AsSOK0GsSjminc36s9AV7u1A72pk2twJJLXggXqRXszc+PxTBi9haOp+fz6Pw4XhnQmD1nHOOB8yw21h9Ko0ejULh3PvzxFMTNgT8mgekUdHsZNPJcVpQ+o9EIOFrWw8LOrx6SkpLibK03Go1YLBYyMzOLtc6npKTQvn17Z0xycvIl109NTb2k1V+IW51qOs3pL+6hTt4eilQNU2wPkt5wGL8PjCLYR+/q9IS4bgVWG41e+tMl77331V54uV9/Wfr000+zevVqFi1ahNFo5PnnnycuLo5mzZoBYLFYeO2112jQoAEpKSk8+eSTjBo1ij/++IOIiAh+/vln7rrrLg4cOICfn59zzfe8vDwmTpxIdHQ0eXl5vPTSSwwaNIj4+Hg0t+jvWmU+0Lhx48asWLHC+b1Wq3Xun5sld86cOdSvX5/XX3+dHj16cODAAXx9ZdKQW93n646yeMcZ3DQKgd7uJKTlMX7hdr4e1Rqt5gYnpzsVh/mbwXhasjhkr8oXNd7mm/t6EODtXjrJC+FCNYK8+eGRGHp/sI49Z7J5dH4cAG4ahSK7ytJdiY5iXusG/WaAXzVY/Tr8PYNjR/ahv+tTwqpILxVRumrVqoXRaGT58uU0b94ccPzCtHbtWt566y0AWrZsiU6nY/ny5QwZMgSAxMREdu/ezfTp0wGIiYnBZDKxZcsW2rRpA8DmzZsxmUzOgl+I8sB+bBO584dRrSidLNWbtdFv8VSfe+V3FSFKUW5uLrNnz+abb76hR48egGMy1mrVqjljHnroIed+7dq1+fDDD2nTpg25ubn4+PgQGOhoEAwJCcHf398Ze9dddxV7r9mzZxMSEsLevXuJiooqxbu6eWVezLu5uTmf7l/oembJFbeuIpudmasOA/DygMa0qO7P3Z9uYt3BVOZuPMZDHWtd/8UOr0T9fgR6ax7x9josipzBtCEdcdPemk/EhCgJRoMHL/VrxMQfdpCWawHgmd4NmPrHfpbvS8ZcZEPvpgVFgS5Ps2CflXsS36Fm0p/s/uh2Vnb4mOG9Orr4LkR5l5uby+HDh53fJyQkEB8fT2BgINWrV2fChAlMnTqVevXqUa9ePaZOnYqXlxdDhw4FwGAwMHr0aJ566imCgoIIDAxk0qRJREdHO2e3j4yMpHfv3owZM4bPP/8cgLFjx9KvX78rzmQvxC1FVbFt/Qr1j2fwo4j99giO3P45d3bt4OrMhLhpnjote1/t5bL3vl5HjhzBYrEQExPjPBYYGFjs82P79u1MmTKF+Ph4MjIysNsdc3mdOHGCRo0aXfXa//3vf4mNjSUtLa3Y627VYr7Mq6NDhw4RHh5OrVq1uO+++zh69ChwfbPkXonZbCY7O7vYJsrW/qQccs1F+Hq4MaxNdRqHG3ixXyQAb/95gBPp+dd3oS2z4Nt7UKx5rLNFM1p9iRfukUJeVA6DmlfltgZVAGho9OXhjrUJ8dWTU1jExsPpzrgVe5N5/lhTRlifx6T4EaU5Rt/YoXDsb1elLiqIbdu20bx5c2fL+8SJE2nevDkvvfQSAM888wwTJkzg8ccfp1WrVpw+fZq//vqrWO+5999/n4EDBzJkyBA6dOiAl5cXixcvLtYT79tvvyU6OpqePXvSs2dPmjRpwrx588r2ZoW4GeYc7D8/jPaPibhRxFJ7Gw4P+IW+UsiLck5RFLzc3Vyy3cjy0tcaX5+Xl0fPnj3x8fFh/vz5bN26lUWLFgGO3mRX079/f9LT05k1axabN29m8+bN1/U6VyrTCqlt27Z88803/Pnnn8yaNYukpCTat29Penr6dc2SeyWyXI3rbT2WAUCrGgFoznapv791ddrVDqTAauPZn3de/T+fzQq/P+UYB6zaOBLWl4etk2hUMwx3NynkReWgKArT727K8HbVefOuJmg0Cr2jHD2ZfttxBoDsQisv/LoLgKYd+6KOWcMeew0CVBPqNwMg9jPHrMpC3ISuXbuiquol25w5cwDHv9EpU6aQmJhIYWEha9euvaS1wsPDg48++oj09HTy8/NZvHjxJZ/LgYGBzJ8/3/kAfv78+cW6OgpxS0rcgf3zLmh2/0SRquFt230o93xDv1b1XZ2ZEJVG3bp10el0xMbGOo9lZmZy8OBBAPbv309aWhpvvvkmnTp1omHDhs7J785xd3cMhbHZbM5j6enp7Nu3jxdffJFu3boRGRlJZmZmGdzRv1OmVVKfPn246667nN3tfv/9d8DRnf6cm5klV5arcb1txxz/2FvVPD8pnUaj8NZdTfDQadh0NJ0Nh9Mu/+KCTJh/F2z9ElCg28u87TkRCzrayXIuopKp4qvn9YHRNDu7JvHgFo4xYEt2niHRVMBHKw+RnG2mVrA3T/aoj394HZ4xvMNiWzsUexEsexa+Hw75GS68CyGEqEBUFbbMQv2yO5qMI5xWgxhhe5nWw1+jd3TYtV8vhCgxPj4+jB49mqeffpqVK1eye/duRo0a5Zygrnr16ri7u/PRRx9x9OhRfvvtN1577bVi16hRowaKorBkyRJSU1PJzc0lICCAoKAgvvjiCw4fPsyqVauYOHGiK27xhri0ydPb25vo6GgOHTpUbJbcC104S+6VyHI1rqWqarGW+QvVCPLm3laOFpn5sccvffGZePjiNkhYCzpvuO9b7B2eZPPZ60kxLyq7ZhH+tK0ViNWm8vrv+5i70fH/6KX+jfA4O8asSS0j463jWV79SdDoYP8S+LwznNjsytSFEKL8yz7jaHD4YxKKzcJyWwvuVt9i/KjhsuycEC7y9ttv07lzZwYMGED37t3p2LEjLVu2BKBKlSrMmTOHH3/8kUaNGvHmm2/yzjvvFHt91apVeeWVV3juuecIDQ1l3LhxaDQaFi5cSFxcHFFRUTz55JO8/fbbrri9G1LmE+BdyGw2s2/fPjp16nRds+SKW9OpzAJScszotApNz7YmXmhYuxrM3XScFftSSDIVYjR4OJ5yb/0S/nwebBYwVIf7F4AxmgOJ2WTmW/Fy19KkmqHsb0iIW8yjXeuwOSGD33cmAtC+ThBd61dxnm9VI5Dvtpzk08Ie9Hj4TvjpIcg4Cl/3gS7PQqeJoL3JJSKFEKIyUlXY+QMsfRoKTRTizlvWe/nd806+HNWaJtX8XZ2hEJWWj48P8+bNKzbXytNPP+3cv//++7n//vuLvebi4b7//e9/+e9//1vsWPfu3dm7d+9VX3erKdOW+UmTJrF27VoSEhLYvHkzd999N9nZ2YwcORJFUZyz5C5atMjZZeLCWXLFrelcq3x0VYOzpfBC9UN9aVMrEJtd5bstJ0hKSSb/2xGO8fE2CzS4Ax5ZC8ZoAGKPOib6alUzEJ1MfCcEXetXoaHx/ARjk/tEFht+1Prs8JZdp00UVmkCY9dC9D2g2mDNVPiyGyTvveS6QgghLiM7EX4YAYvGQqGJeHtt+prfYHPIvfw6rqMU8kKIW0aZVkqnTp3i/vvvp0GDBgwePBh3d3diY2OpUaMGcH2z5Ipbh6qqFFptbD56tov9BePlLzasbXUAtq35DevMDngdXoyqcYNeU1Hv/Ra8zr/277OzdrerfeXrCVGZKIrCkz0cEyzd07Ia0Rf1WIkI9KSKrx6rTWXnKRN4+MHgWY7Nwx8Sdzi63a97G2xFLrgDIYQoB+w2x6o6H7eBfYspQss71nsYUvQqd9zWhV+f6EC4v6ersxRCCKcy7Wa/cOHCq54/N0vulClTyiYhcdO2Hsvgpf/tYV/i+WUALx4vf6HeDfx402s+99n/AOCUGsxP1V/l/9oO5YkF/xB3PJMJ3euTmmNmxb5kADrXq3LF6wlR2fRqbGTjc7cT6udxyTlFUWhdM4A/diUxZ2MCh1Jy6BEZSkiTIVCrMyyeAAeXwqrXyY//GY87P0BTo23Z34QQQtyqknbD4v/A6W0A7FTr8pzlITJ8G/LdsBa0vMrvOEII4SouHTMvyp8im51Xl+zlm03FJ7Or6u9JTJ0rTFZ3Ihb9r49zn/0IAGfq3EvvPT0oOOhN4Z8HWLrbMenh84t2OV/yn271iKoq4+WFuNDVWoRa1wzkj11Jzm3GikN881AbIsOMcP93bFz0MY12TMU/Yx983ZOE6ndR6963wVsmmRRCVGJ56bD6DYj7GlQ7BYoX0yz3MN/Wg5i6VfjmvuYE++hdnaUQQlyWFPPiuhVabYz/bjvL9zpazu9rHcGTPerjo3fDQ6dFq7loCcG8dFjxMmw/OzmFbxgM+Ijwej1o9uVmNhxO47O1jgK/d2MjGw6nkWsu4pUBjRnZvmYZ3pkQ5d/dLatxOCWXrHwrexOzSUjLY8jnm5jzYGuaVvPn2cONyDO/y/Pu33G3Zi21TvyM9YOV6Lq/CC1HyQR5QojKpcgCW2fBmrfAbALgD1sbXrE+QKY2mMl3NGB0x1poLv7dRgghbiFSzIvrYrerjJ0Xx7qDqbi7aZh5f3N6NjZeKdhRwK942bGGPECz4dDrdfB0dFN7rGsd57rzrWoE8MmwFmQVWMnKt1C7ik9Z3JIQFYqvh443BjkmkTTlWxk9dyvbjmfy8NxtPNypNiczCgj0Dqbn0z/z0cLv6X70LSItJxwTUW7+HLpPgYZ9QZFfXIUQFZjdDnt+QV09FSXD0aCw116DV4tGEGtvRN/oMJ7sUY+6ITJfkxDi1ifFvLgu8zcfZ93BVDx1Wr5+sPWV138/tgH++i+c+cfxfUhj6PceVG9XLKx9nSA61g1m9xkTb97VBI1GIdDbnUBv91K+EyEqPoOXjnmj23LvF5vYecrE238eAGBU+5r4eegYM+x+hn5encaJPzNR9wsB6Yfg+2FQPcZR1F/0/1UIIco9VYWDyyj86xU80vehAKmqH+8U3cuPti70aBzG0u71iQzzc3WmQghx3aSYF9d0KjOft5buB+C5Pg0vX8in7IMVU+DgMsf37j5w2/PQ5hHQXvrPTFEU5j7UBqvNftnl7IQQ/46nu5bPR7RkwMy/Sc0x4+Wu5YEYx8ohHjotnz3Qhvu+sLMorSMTPJfykOZ3NCc2wVe9oFYX6Poc1Gjv4rsQQoh/x2It4mTsz/hs+ZDQnN14ANmqF18U9WWRe3+6t6nDktbVaRQuRbwQovyRYl5cVYHFxlM/7CDPYqN1zQBGtKtRPCD9CKx/F3Z8B6odFC20ehC6PAs+IVe9tlajoNVIIS9EaQkzePLFiJZM/GEHw9pWx9/rfM+XED8Pfnw0hlFfb+X103fxZ2BfFjZcizb+W0hY69hqdoLOkxzFvXS/F0KUI2qRhfilX2KI+5g6nAIgX9Xzjb0XB+o8SO/Wjfi/BiG4u5XpKs1CCFGipJgXV3ThuFtPnZa3znaHByD1AKx7B3b/5CjiASL7Q7eXIbie65IWQhTTvHoAqyd1vey5IB89345py+3vrGFrBiyoMpER/zcJ1r8H2+fDsfWOLTQaYp6AqLvATYbCCCFuXZbsVBL++pSgfd/Q3JYKQA6erPcfSF6zMdzbOpoAGdInhPgX8vPzGTFiBMuXLycnJ4fMzEyaNWvGhAkTmDBhQpnmIo8jxSXiT2Yx6ccddH1nNduOZ+Ln4ca80W2oHewNJ2Lh+xHwcVvY9YOjkK/XEx5eCffOl0JeiHLGz0PH/3Vz/L/9YOUhcj3Dof8M+L/t0GYs6LwgeRf8+ijMiIa10yE70bVJCyHERU7sjWX7zOHY32tEg93vEmxLJU31Y0ONJ3CftI87JnzGPV1bSiEvRDk3atQoFEXh0UcfveTc448/jqIojBo1qlj8wIEDr3i9mjVroijKJdubb755xdfMnTuX9evXs3HjRhITEzEYDGzdupWxY8c6YxRF4ddff72ZW7wh0jIviok/mcWQzzdhKXK0tlf19+TL4U2IzFgBsz6BM9vPBzfs5+iCG97cRdkKIUrC/W2q8/Xfx0hIy2PKb3t49c7GePlHwB1vQ9fJjvWXN38BuUmO9ZjXvAkN+jiG1NS+HTSXPhc+mprLy7/tIclUiKLAsLY1ZMlJIUTJKsgie+t3ZG/8iuqFB6l+9vB+anG41jCiez1ER+MVJuwVQpRbERERLFy4kPfffx9PT08ACgsL+e6776hevfo1Xn2pV199lTFjxhQ75ut75RUtjhw5QmRkJFFRUc5jVapUueH3LQlSzAunlOxCHpm3DUuRnfZ1gpjUUkPT1N/QfjcW8hxd1dDqoem90PYxCG3k2oSFECVCp9XwXJ+GPDIvjp/iTrHpSDrvDmnqmOzSKxA6PQUx42HPIkdhf2IT7F/i2PyqOrrfNxkCoVGgKOw6ZWLU11tIz7M43+P13/dye8MQIgK9XHinQohyr8iMaddSUjctoHrKavyw4AdYVC3xPp3QtH2EZu170dBN5uQR4oaoKljzXfPeOq8bmpunRYsWHD16lF9++YVhw4YB8MsvvxAREUHt2rVv+O19fX0xGq+w5PZFunbtytq1awFH63uXLl1Ys2YNNWvWdHazr1mzJgCDBg0CoEaNGhw7duyG87oeUswLDiXnsHDrSf7YlUhBdgbj/HcxQdmC22+x54N8jNDmYWj5IHgHuy5ZIUSp6NXYyKwHWjHltz2czirg4bnbWPR4e+qFnn0y7ebueJDX9F7H6hXbvoYdCyH7NGz8EDZ+SJZPHdbpu/JBSlPSrcFEVfVjcp9IPlp1iNijGbzz1wE+uE968gghbkxOXh4n4/5As2cR1VNWY1DzMZw9t98ewSa/PjTv/yhtGtRxaZ5ClGvWfJga7pr3fv4MuHvf0EsefPBBvv76a2cx/9VXX/HQQw+xZs2aUkjwvF9++YXnnnuO3bt388svv+DufunQna1btxISEsLXX39N79690WpL7+GiFPOV3L7EbIZ9upqYom1M0W7kNo943AuL4BSgaKBeL2gxwjEuXqtzdbpCiFLUo1EoHeoG8eDXW9mckMGYb7bx6xMdis2CD5BnqIeu55touk3h2/lfEnLsN27XbMc/9wgDco8wQAtHPOpTrdFg9N4GDHdE0m/m3/wv/gwPd6xNdDXDFTIQQghIzi5k3c4j5O1fjjF5He0ssTRS8pznE9VAtnp1xq3ZEJq2uY0HA6THjxCVzYgRI5g8eTLHjh1DURT+/vtvFi5ceFPF/LPPPsuLL75Y7NiSJUvo2rXrJbGBgYF4eXnh7u5+xdb8c13u/f39r7vF/2ZJMV+JrDmQQkqOmUHNq6LLSyZv9+9krPiOjcoOPNyt5wOrREL03dBsKPi56AmdEMIlvNzd+GRYCwbM/Jtj6fl0ems1XRpUoUejUFpUD+DzdUf4dvMJfNzdqBrgyf6kOmiUJ+lVx5M2BRu43bqW6tlx1LEehPVvwvo3ifKrxnxjS75MacCEbzW8PKgVneu7ZmyZEOLWYymyczApm13/bMSy/08a5sYySDmIm3J2tRwF0ghgt6ErOXX7U69VNwaE+bs0ZyEqHJ2Xo4XcVe99g4KDg+nbty9z585FVVX69u1LcPDN9R5++umni02aB1C1atWbulZZk2K+kliz7wzvz/uJLsoOEpbGU992GG+gA4ACNkN1tNF3O4r40MYuzlYI4UpBPnq+HNmKh+du43RWAUt2JrJkZ/EZ7HPMRexPysHdTcPM+5vTs7ERuP3syWQ49CccWAZHVkH2KTpyio7uYM7X8c+8enxvaIlXg9uJ6dyDYMOVJ5kRQlQsOYVW9iXmsPd0FqkJu/BMjKVm7nZaK/u4X8lyBJ2dUzPdsyZ51W/D0HQAwQ270FUj4+CFKDWKcsNd3V3toYceYty4cQB8/PHHN32d4OBg6tatW1JplSkp5isQq82OqcDRwu7rrqBP2wvH1pN3cA0tj/3N/9wLHIE2x5ft9rps0LSi/5CHqBnZ5oYmnhBCVGyRYX6sf+Y24k9lsXxvMiv2JnMoJZe6IT68OqAxnu5a/j6cRqd6VWga4V/8xb6h0OIBx2YtgIR1cGAp9oPL0OckEqPdS0zuXoibR36cB3kRbfGu1wmqtYbwFuDhd105motsuGs1KPKzS4hbjt2uEncik6W7kkjKLsBWmIdb6h5Cc/bQSnOAfpr9BCvZjuCzxbtZ0ZMW3Ba/6D74RvUhKLAWMhe9EOJKevfujcXimGy3V69eLs6mOJ1Oh81mK/X3kWK+HNt+IpONR9IBSDh1muzDsTQoOkgzzRFaaQ6iPzu+7NwztjzFG7fanVhua87fmlY0j2zAsEahBMqaq0KIy9BoFFpUD6BF9QCe7d0QU74VXw83NBpH8dy8esC1L6LzhPq9oH4vNKoK6YfJ3LOCrL0rCUjejD/ZcHKtYwNUFDK8alMY2pwqkR3J8GvEuswgAgy+dKwbjKe7FkuRnS83HOWjlYepHujFawOjaFMrsDT/KIQQ15CaY2bjkTRij6ZzLCkNTeoBalgO0UQ5wj2ao9RTTjm6zV8w/Y5Voyc7uDlutTri16Az+og2VNV5uu4mhBDlilarZd++fc79KzGZTMTHxxc7FhgY6FzGLicnh6SkpGLnvby88PO7vsaFy6lZsyYrV66kQ4cO6PV6AgKu43emmyDFfHmUm8qu7RtZ8udyGisJNFMOU1uTBArFPiRzVE+22huwyd6I0/6tePWR+wn286If0M9VuQshyi2D17+cBFNRILgeAV3qEdDlMbLyCnly9k/4J8fSXHOY5sphIjSpBOUfgYQjkPATRmCQquWwGs6f1OS0Rx12FVUnLt9IAQYOJOcw5PNN3N2yGpP7NCTIR18i9yqEuLqsfAvbDidyYN9OMo7vxC/7EA2UU4xVTlBDSUGjqMV+JwGweFSBqi1wr9kWanREF96cIDdpUBBC3LzrKbjXrFlD8+bFV9MZOXIkc+bMAeCll17ipZdeKnb+kUce4bPPPrvpvN59910mTpzIrFmzqFq1aqktTaeoqqqWypVdKDs7G4PBgMlk+ldPVFzlp7hTWIts3BepQ8k4CulHIPUAasoeSN6Lkpdy2dcV+tVEX701VG3BMa/G/JEWgtmmoWvDEJpV83e2pgkhxK0i31LEF+uOcibLMQzIx5pO1by96BL/oa5lH400x/G/YBbrC1ncfEjWRbA1N4ij9jCSdBH0va0Tt7WPcfQIAAqtNj5fe5Tj6Y5rtKsdxF0tq6Etxz8Py/tnXEmRP4fSl2su4nhSOqkn95N75iD2tCPos48RUHiScDWJcNIdRftlFHkEooQ1QVutpWP4THhzx6S6MixGCJcrLCwkISGBWrVq4eHh4ep0Kq2r/T1c72ectMy7UpEZss+w/+A+9DknqaUkcfzQLholHqSGkoSy1Fws/NzHn11VOK6GkORRh1btOqOr7hhn6uF1vptpLeCJsrsTIYS4KV7ubkzoXv+io7ejqirH0vPB0w2sKahJu8g4GocmeTeeGfvR557AvSiXiKJ9RGiBc73rVr+HulpB8Q2jyK8a29K9cMv1w0Otwmk1mM/jg/kxtjYDWtW97Fj7VjUDaGg8/6GpqiqxRzNQVZXWtQLRaTWl9mchRJlSVXJzsjhx8jg5ycexZJzEbjqNW+4Z9PmJ+JpTqKKm0ljJvfzrz/73KdR4UWioi0e1aDzCoyC0EYQ0ws0npOzuRQghKikp5q/DznX/o3pka/yrXH2ZtkKrDXORHYM7kJ8Oealnt3TIOQOm05B9GkynIPsMnG1hb3jBNWqAcyIYm6qQ6xnOCcLYlhvEPrU6B+wRHFSrUS0kmG8fbovOT56mCSEqHkVRqBV8bsaPCBT/CIIa3nE+oMgMGUch7RCkH8KeeojEI7vwzk1wtOTnnMEt5wwdgY4Xf9KlQ+YyH1JVA6mqP6kYSFEDSFUNxOFPk4YN6Ny8MSa3QN5Zm8zGhEwAfD3cqBXszYWPAJpXD2BC93r4e0lX4ZvxySef8Pbbb5OYmEjjxo2ZMWMGnTp1cnVa5VORGXNuBtmZaeRkpVFgSseck4otJwXy0tAWpOFuTsfTkolPUSYG1YQPFhpd7Zpn/7HnKV5k6CMo8K2JElgbz7B6BEVE4mmsj4dXEB7S2i6EEC5xyxbzt8oHfLYpg8YrR6JdpXLKrTqWgPoEVwnFjkJyRhY6u4VQL5XszFQKslIIxARX6BJ6OYWqjkQ1iNMEk2A3ckw1UqVGI7I8qzN7jx2r2fFXpFHggZiafNG1Dh5u2mKTUAkhRKXjpoeQSMeG4xloVeCLtYf5bOlWqimpVFNSqe+RyYiGWoKKkiDrJPas42gsuQQojq0+py+99pGzG/CNqiFb702O4kua3ZusZB+y8CZL9SVL9SYz0Zc3txvo2rQuzetVJ7RKCOh9Qe8H7j6g0aCqKhl5FhnPf5Hvv/+eCRMm8Mknn9ChQwc+//xz+vTpw969e52TElVYdjvYLGDNB2s+loJs8nNzKMzPwZKfQ1FhDtaCPGzmHOzmPOyWfBRLLljyUax56Ky56Ipy0Bdl42nLxcueiwcW9ECVs9v1yseDLG0g2e6hFHqGUuRTFbeAahiMNalStTY+VWrg7eGPtxTsQghxy7kli/lb6QM+PfE46drq1LIfp1rRCUg9AamOc/4XxHkDFzbX2FSFDHzJxEAGBnJ1gXgG1yDe5M12kzeJahBn1EDq16zBSwMaE6QozFq6H3c3DZPua46iwLGF8ZwxFXBbgxD6NQmjXqisxSyEEFcztktdbmsYysnMfBQcs/FfOHGfRlWhMAtykiE3CXJTICcJcpMhN4Ws1JNkp57GYMvAQC5uip1AcggkhxpX6mGvAvFnt4uYNV5k2T3J1/gS9N94GS98gffee4/Ro0fz8MMPAzBjxgz+/PNPPv30U6ZNm1amuZxJ2Efivo1QZEG1Wc5+NaPYLGCznv1qQbFZ0dgtYLegsVvRnP1esVvRqlY0Z79qz31VrbipVtzUorP7Reiw4kbx5Yrcz27/ll1VyMGLXMWbgv9v795jojjfPYB/Z5fZZUFYbsKyUpGf9RbhRwu2VtN6S0okpWJtLLamxWNrQr0Uo23UNlZsmmraxJM0VmtTNTY1wTRHTRNNGzxy0XpsDWCrtIdiXcULyNF6QRfYhX3PH5S1K1ctMu8M30+yEd4d1ufh2Zknz+4wawqFW41EsyUKHms0REgMlCFDERQeC2t4HEKiHIhzDENERCRCAPR87iEREclIygvgTZw4EWlpadi6dat/bdy4cZg9e3afGvzDuCjOpUsX8b8/FeHi+Rr8ebUBJgVwRNvRDAuqr3rRaglD5sQUjHv0Xyi9KHCgphn/47oOb1vnX29EiIql0x/Fc/+OR7ydH8FCRCSl1hbA/SfQdB1o+utf//ftaz73dTRcqUNT43WYvI0IgxthaIKqBA5rN0UoWt9x9cu780a48JvH40FISAi++eYbvPDCC/71/Px8nDx5EqWlpZ1+pqWlBS0td68lc+vWLTzyyCP98nv46b/+E0+eKvhHj/GgWkQQmmDFHQSjBcFoNgXDowTDY7LBaw5BW5ANbWYbfGoohGoDLKHwWcIBmx1qSBRs4VEItUcjPDIGERHRCLNZeOYeEfWo48JrI0aMgM3GWUQrTU1NOHfunLEugOfxeFBeXo7Vq1cHrGdkZODYsWNd/kxXDb6/DRuWgGEv/AeA9qsvmxQFwWr7FZeavW2wmE3+5pkzEsiZ2n4V2D9ve+ATAqcv30RJ9f8hMkTFm9Me5We7ExHJLsgKhMe337phAuD46+vrdzworm7Af/92Bbdu34bN58aj4T5MSQzG404brDzN3u/q1atoa2tDXFxcwHpcXFynz/rtsGHDBqxfv/6hxGONSkCVJQU+RUWboqLNpMJnUtFmssCnqBBmFT6TBT6TCmGyQJhVCLMFwmQBzBYgyAKY2tdMQVYIswpTkBUIav9eCbJCMaswqdb2W5AF5iALgkPDYA8NQbhNRbyVfz5HRANDVdvPWHO73RzmNeR2uwHcrceDkG6Yl63BdyXEEvhr6xjq7zXEGoQh1vZtR8SEIuvfPImNiMioIkMtmJOWgDlpCVqHohv3fqKAEKLLTxkAgDVr1mDFihX+7zveme8PqdPnAtPn9stjERHJzmw2IyIiAg0N7RfjDgkJ6fbYS/1PCAG3242GhgZERETAbO56luwL6Yb5DrI0eCIiIupfMTExMJvNnV6kb2ho6PRifger1QqrlWc3EBH1B4ej/byyjoGeBl5ERIS/Dg9KumGeDZ6IiMjYLBYL0tPTUVRUFPA380VFRcjOztYwMiKiwUFRFMTHxyM2NhZer1frcAYdVVX/0TvyHaQb5tngiYiIjG/FihV49dVXMWHCBEyaNAlffPEFamtrkZeXp3VoRESDhtls7pehkrQh3TAPsMETEREZXU5ODq5du4YPPvgAdXV1SE5OxsGDB5GYmKh1aERERLog5TDPBk9ERGR8ixcvxuLFi7UOg4iISJekHOYBNngiIiIiIiKi7kg7zP8TQggAD+fz5omIiLTU0ds6et1gxV5PRERG1ddeb8hhvrGxEQD48XRERGRYjY2NsNvtWoehGfZ6IiIyut56vSIM+NK+z+fD5cuXERYW1u1n09+Pjs+tv3DhAsLDw/shQm0wD7kwD/kYJRfmIZf+zkMIgcbGRjidTphMpn6IUJ/Y67vGPOTCPOTCPORilDwA7Xq9Id+ZN5lMSEhI6PfHDQ8P1/0TDWAesmEe8jFKLsxDLv2Zx2B+R74De33PmIdcmIdcmIdcjJIHMPC9fvC+pE9ERERERESkUxzmiYiIiIiIiHSGw3wfWK1WrFu3DlarVetQ/hHmIRfmIR+j5MI85GKUPIzOKHViHnJhHnJhHnIxSh6AdrkY8gJ4REREREREREbGd+aJiIiIiIiIdIbDPBEREREREZHOcJgnIiIiIiIi0hkO80REREREREQ6w2G+F1u2bEFSUhKCg4ORnp6OI0eOaB1SjzZs2IAnnngCYWFhiI2NxezZs1FdXR2wzYIFC6AoSsDtqaee0ijirhUUFHSK0eFw+O8XQqCgoABOpxM2mw3Tpk1DVVWVhhF3b8SIEZ1yURQFS5YsASBvPcrKyvD888/D6XRCURTs378/4P6+1KClpQXLli1DTEwMQkNDMWvWLFy8eHEAs+g5D6/Xi1WrViElJQWhoaFwOp147bXXcPny5YDHmDZtWqcazZs3T5o8gL49j2SvB4Au9xVFUfDJJ5/4t5GhHn051uplHyH2eq0Ypdezz2t/DGOvv0uGmhih1+ulz3OY78GePXuwfPlyvPfee6isrMQzzzyDzMxM1NbWah1at0pLS7FkyRIcP34cRUVFaG1tRUZGBu7cuROw3cyZM1FXV+e/HTx4UKOIuzd+/PiAGE+dOuW/7+OPP8amTZuwefNmnDhxAg6HA88++ywaGxs1jLhrJ06cCMijqKgIADB37lz/NjLW486dO0hNTcXmzZu7vL8vNVi+fDn27duHwsJCHD16FLdv30ZWVhba2toGKo0e83C73aioqMDatWtRUVGBvXv34vfff8esWbM6bbto0aKAGm3btm0gwvfrrR5A788j2esBICD+uro67NixA4qi4MUXXwzYTut69OVYq5d9ZLBjr9eWEXo9+7z2xzD2+rtkqIkRer1u+rygbj355JMiLy8vYG3s2LFi9erVGkV0/xoaGgQAUVpa6l/Lzc0V2dnZ2gXVB+vWrROpqald3ufz+YTD4RAbN270rzU3Nwu73S4+//zzAYrwweXn54uRI0cKn88nhNBHPQCIffv2+b/vSw1u3LghVFUVhYWF/m0uXbokTCaT+O677wYs9r+7N4+u/PTTTwKAOH/+vH9t6tSpIj8//+EGdx+6yqO355Fe65GdnS1mzJgRsCZbPYTofKzV6z4yGLHXa8eovZ59XttjGHu9XDUxSq+Xtc/znflueDwelJeXIyMjI2A9IyMDx44d0yiq+3fz5k0AQFRUVMB6SUkJYmNjMXr0aCxatAgNDQ1ahNejmpoaOJ1OJCUlYd68eTh79iwAwOVyob6+PqA2VqsVU6dOlb42Ho8HX3/9NRYuXAhFUfzreqjH3/WlBuXl5fB6vQHbOJ1OJCcnS12nmzdvQlEUREREBKzv3r0bMTExGD9+PN5++23p3hkCen4e6bEeV65cwYEDB/D66693uk+2etx7rDXyPmIk7PXaM1qvZ5/XxzGMvV4eeun1svb5oH55FAO6evUq2traEBcXF7AeFxeH+vp6jaK6P0IIrFixAk8//TSSk5P965mZmZg7dy4SExPhcrmwdu1azJgxA+Xl5bBarRpGfNfEiRPx1VdfYfTo0bhy5Qo+/PBDTJ48GVVVVf7ff1e1OX/+vBbh9tn+/ftx48YNLFiwwL+mh3rcqy81qK+vh8ViQWRkZKdtZN2HmpubsXr1arzyyisIDw/3r8+fPx9JSUlwOBw4ffo01qxZg59//tl/KqUMense6bEeu3btQlhYGObMmROwLls9ujrWGnUfMRr2em0Zsdezz8u//7DXy0UPvV7mPs9hvhd/f1UVaC/mvWuyWrp0KX755RccPXo0YD0nJ8f/dXJyMiZMmIDExEQcOHCg046klczMTP/XKSkpmDRpEkaOHIldu3b5L/Shx9ps374dmZmZcDqd/jU91KM7D1IDWevk9Xoxb948+Hw+bNmyJeC+RYsW+b9OTk7GqFGjMGHCBFRUVCAtLW2gQ+3Sgz6PZK0HAOzYsQPz589HcHBwwLps9ejuWAsYax8xMj32kw7s9XJhn5e7Ruz18tFDr5e5z/M0+27ExMTAbDZ3etWkoaGh0yswMlq2bBm+/fZbFBcXIyEhocdt4+PjkZiYiJqamgGK7v6FhoYiJSUFNTU1/ivd6q0258+fx6FDh/DGG2/0uJ0e6tGXGjgcDng8Hly/fr3bbWTh9Xrx0ksvweVyoaioKOCV+q6kpaVBVVWpa3Tv80hP9QCAI0eOoLq6utf9BdC2Ht0da422jxgVe71c9N7r2ec7byMT9nr5aqKHXi97n+cw3w2LxYL09PROp3IUFRVh8uTJGkXVOyEEli5dir179+Lw4cNISkrq9WeuXbuGCxcuID4+fgAifDAtLS347bffEB8f7z/l5u+18Xg8KC0tlbo2O3fuRGxsLJ577rket9NDPfpSg/T0dKiqGrBNXV0dTp8+LVWdOpp7TU0NDh06hOjo6F5/pqqqCl6vV+oa3fs80ks9Omzfvh3p6elITU3tdVst6tHbsdZI+4iRsdfLRe+9nn1e3mMYe718NQHk7vW66fP9chk9gyosLBSqqort27eLX3/9VSxfvlyEhoaKc+fOaR1at958801ht9tFSUmJqKur89/cbrcQQojGxkaxcuVKcezYMeFyuURxcbGYNGmSGDZsmLh165bG0d+1cuVKUVJSIs6ePSuOHz8usrKyRFhYmP93v3HjRmG328XevXvFqVOnxMsvvyzi4+OlyuHv2traxPDhw8WqVasC1mWuR2Njo6isrBSVlZUCgNi0aZOorKz0X/m1LzXIy8sTCQkJ4tChQ6KiokLMmDFDpKamitbWViny8Hq9YtasWSIhIUGcPHkyYJ9paWkRQghx5swZsX79enHixAnhcrnEgQMHxNixY8Xjjz8uTR59fR7JXo8ON2/eFCEhIWLr1q2dfl6WevR2rBVCP/vIYMderx0j9Xr2eW2PYez1ctXECL1eL32ew3wvPvvsM5GYmCgsFotIS0sL+NgXGQHo8rZz504hhBBut1tkZGSIoUOHClVVxfDhw0Vubq6ora3VNvB75OTkiPj4eKGqqnA6nWLOnDmiqqrKf7/P5xPr1q0TDodDWK1WMWXKFHHq1CkNI+7Z999/LwCI6urqgHWZ61FcXNzlcyk3N1cI0bcaNDU1iaVLl4qoqChhs9lEVlbWgOfWUx4ul6vbfaa4uFgIIURtba2YMmWKiIqKEhaLRYwcOVK89dZb4tq1a9Lk0dfnkez16LBt2zZhs9nEjRs3Ov28LPXo7VgrhH72EWKv14qRej37vLbHMPb6u2SoiRF6vV76vPJXsERERERERESkE/ybeSIiIiIiIiKd4TBPREREREREpDMc5omIiIiIiIh0hsM8ERERERERkc5wmCciIiIiIiLSGQ7zRERERERERDrDYZ6IiIiIiIhIZzjMExEREREREekMh3ki6lVBQQEee+wxrcMgIiKih4S9nkh/FCGE0DoIItKOoig93p+bm4vNmzejpaUF0dHRAxQVERER9Rf2eiJj4jBPNMjV19f7v96zZw/ef/99VFdX+9dsNhvsdrsWoREREVE/YK8nMiaeZk80yDkcDv/NbrdDUZROa/eeerdgwQLMnj0bH330EeLi4hAREYH169ejtbUV77zzDqKiopCQkIAdO3YE/F+XLl1CTk4OIiMjER0djezsbJw7d25gEyYiIhpk2OuJjInDPBE9kMOHD+Py5csoKyvDpk2bUFBQgKysLERGRuLHH39EXl4e8vLycOHCBQCA2+3G9OnTMWTIEJSVleHo0aMYMmQIZs6cCY/Ho3E2REREdC/2eiK5cZgnogcSFRWFTz/9FGPGjMHChQsxZswYuN1uvPvuuxg1ahTWrFkDi8WCH374AQBQWFgIk8mEL7/8EikpKRg3bhx27tyJ2tpalJSUaJsMERERdcJeTyS3IK0DICJ9Gj9+PEymu68HxsXFITk52f+92WxGdHQ0GhoaAADl5eU4c+YMwsLCAh6nubkZf/zxx8AETURERH3GXk8kNw7zRPRAVFUN+F5RlC7XfD4fAMDn8yE9PR27d+/u9FhDhw59eIESERHRA2GvJ5Ibh3kiGhBpaWnYs2cPYmNjER4ernU4RERE1M/Y64kGFv9mnogGxPz58xETE4Ps7GwcOXIELpcLpaWlyM/Px8WLF7UOj4iIiP4h9nqigcVhnogGREhICMrKyjB8+HDMmTMH48aNw8KFC9HU1MRX74mIiAyAvZ5oYClCCKF1EERERERERETUd3xnnoiIiIiIiEhnOMwTERERERER6QyHeSIiIiIiIiKd4TBPREREREREpDMc5omIiIiIiIh0hsM8ERERERERkc5wmCciIiIiIiLSGQ7zRERERERERDrDYZ6IiIiIiIhIZzjMExEREREREekMh3kiIiIiIiIinfl/7Hi69POMlIwAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pars=res.x\n", + "\n", + "ode_est = common_models.SEIR_N([('beta', pars[0]), ('alpha', pars[1]), ('gamma', pars[2]), ('N', n_pop)])\n", + "ode_est.initial_values = (x0, t[0])\n", + "solution = ode_est.integrate(t[1::])\n", + "\n", + "import matplotlib.pyplot as plt\n", + "f, axarr = plt.subplots(1,2, layout='constrained', figsize=(10, 2.5))\n", + "\n", + "axarr[0].plot(t, sol_i_r[:,0], color='C0', label=\"data\")\n", + "axarr[0].plot(t, solution[:,2], color='C1', label=\"MLE fit\")\n", + "axarr[1].plot(t, sol_i_r[:,1], color='C0', label=\"data\")\n", + "axarr[1].plot(t, solution[:,3], color='C1', label=\"MLE fit\")\n", + "axarr[1].legend(loc=\"lower right\")\n", + "axarr[0].set_xlabel('Time')\n", + "axarr[1].set_xlabel('Time')\n", + "axarr[0].set_ylabel('I', rotation=0)\n", + "axarr[1].set_ylabel('R', rotation=0)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "f79d99fc", + "metadata": {}, + "source": [ + "## Confidence intervals of estimated parameters\n", + "\n", + "Point estimates of parameters found via MLE provide the *best* fit, but are incomplete without some measure of their uncertainty.\n", + "With the ABC method of the previous section, credible intervals fall out as part of the fitting process, since the output is parameter probability distributions.\n", + "For parameter estimates found via optimisation, we need to make some assumptions about the shape of the likelihood function in the neighbourhood of the MLE to obtain confidence levels.\n", + "\n", + "```{warning}\n", + "PyGOM has built in functions using different methods to solve this problem; these are, however, under development.\n", + "The location and names of the relevant code can be found below and they should be carefully inspected before being employed.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1ab2d9b6", + "metadata": {}, + "outputs": [], + "source": [ + "#from pygom import confidence_interval as ci\n", + "\n", + "## Different methods for CIs:\n", + "# ci.asymptotic\n", + "# ci.profile\n", + "# ci.bootstrap\n", + "# ci.geometric" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/paramfit/profile.ipynb b/docs/notebooks/paramfit/profile.ipynb index 8e8d3def..00f54623 100644 --- a/docs/notebooks/paramfit/profile.ipynb +++ b/docs/notebooks/paramfit/profile.ipynb @@ -30,9 +30,11 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 1, "id": "efed1abf", "metadata": {}, + "outputs": [], "source": [ "from pygom import NormalLoss, common_models\n", "\n", @@ -61,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "b8425085", "metadata": {}, "outputs": [], @@ -119,9 +121,20 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 3, "id": "9f93e2ba", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.30563305 0.15211495]\n", + "[0.69392383 0.51349773]\n" + ] + } + ], "source": [ "from pygom import confidence_interval as ci\n", "\n", @@ -129,14 +142,7 @@ "\n", "xL, xU = ci.asymptotic(objSIR, alpha, xhat, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1])\n", "\n", - "print(xL)" - ] - }, - { - "cell_type": "markdown", - "id": "7eae33a2", - "metadata": {}, - "source": [ + "print(xL)\n", "print(xU)" ] }, @@ -210,7 +216,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "7dab2b66", "metadata": {}, "outputs": [], @@ -237,7 +243,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "e58e47ee", "metadata": {}, "outputs": [], @@ -324,20 +330,24 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 6, "id": "eb9240d7", "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.21802959 0.04961695]\n", + "[1.26151364 1.06296231]\n" + ] + } + ], "source": [ "xLGeometric, xUGeometric, xLList, xUList = ci.geometric(objSIR, alpha, xhat, full_output=True)\n", "\n", - "print(xLGeometric)" - ] - }, - { - "cell_type": "markdown", - "id": "f09236cc", - "metadata": {}, - "source": [ + "print(xLGeometric)\n", "print(xUGeometric)" ] }, @@ -384,20 +394,31 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": 7, "id": "d33c189c", "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:root:Number of iterations (10) is low. Consider using more.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.49842726 0.33142003]\n", + "[0.50466089 0.33727478]\n" + ] + } + ], "source": [ "xLBootstrap, xUBootstrap, setX = ci.bootstrap(objSIR, alpha, xhat, iteration=10, lb=boxBoundsArray[:,0], ub=boxBoundsArray[:,1], full_output=True)\n", "\n", - "print(xLBootstrap)" - ] - }, - { - "cell_type": "markdown", - "id": "90e0585e", - "metadata": {}, - "source": [ + "print(xLBootstrap)\n", "print(xUBootstrap)" ] }, @@ -420,14 +441,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "c585db79", "metadata": { "vscode": { "languageId": "javascript" } }, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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CDI15s779u2Lvn37lrq+nZ0d7OzslPVt27bhn3/+wejRo1X1dDodnJ2dK6yfRERE9Hip1tcgrVmzBk899RTc3NxU5Tdv3oSbmxsaNGiAAQMGICkpyUg9JCIiourIqEeQHoRer8fu3bvx1Vdfqcq9vLwQGRmJ1q1bIysrC4sXL0bnzp2RkpKCZs2aFdlWTk4OcnJylPWsrKxK7TsRERFVbdX2CFJkZCRq166NwYMHq8o7duyIF154AT4+PujatSs2bdqE5s2bY+nSpcW2FR4erpy+s7OzQ8OGDSu590RERFSVVcuAJCL4/PPPERwcDHNz8xLr1qhRA0888QTOnTtXbJ3Q0FBkZmYqS1paWkV3mYiIiKqRanmKLSEhAefPn8fYsWPvW1dEkJycjNatWxdbx8LCAhYWFhXZRSIiIqrGjBqQbt68ifPnzyvrFy9eRHJyMuzt7dGoUSOEhobi8uXLWLdunWq7NWvWwN/fH61atTJoMywsDB07dkSzZs2QlZWFJUuWIDk5GZ988kmlj4eIiIgeDUYNSCdPnkTPnj2V9WnTpgEAQkJCEBkZCb1ej9TUVNU2mZmZiImJweLFi4ts8/r163j55ZeRnp4OOzs7+Pr64vDhw+jQoUPlDYSIiIgeKToREWN3oqrJysqCnZ0dMjMzYWtra+zuUCVyn/HNfev8/n7/h9ATIiJ6UBX5+V0tL9ImIiIiqkwMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGkYNSIcPH8bAgQPh6uoKnU6Hbdu2lVg/Pj4eOp3OYDlz5oyqXkxMDLy9vWFhYQFvb29s3bq1EkdBREREjxqjBqTs7Gz4+Phg2bJlZdru7Nmz0Ov1ytKsWTPlscTERAwbNgzBwcFISUlBcHAwhg4diuPHj1d094mIiOgRZWrMnfft2xd9+/Yt83aOjo6o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EPLz85Gfn4+DBw9i8uTJGD58eEX3kYiIiOihKtddbO+99x4uXbqEwMBAmJrebaKgoAAjR47kNUhERERU7ZUrIJmbmyM6Ohrz5s1DSkoKrKys0Lp1a7i5uVV0/4iIiIgeunIFpELNmzdH8+bNK6ovRERERFVCuQJSfn4+IiMjceDAAWRkZKCgoED1+MGDByukc0RERETGUK6ANHnyZERGRqJ///5o1aoVdDpdRfeLiIiIyGjKFZA2btyITZs2oV+/fhXdHyIiIiKjK9dt/ubm5mjatGlF94WIiIioSihXQHr99dexePFiiEhF94eIiIjI6Mp1iu3IkSM4dOgQdu/ejZYtW8LMzEz1+JYtWyqkc0RERETGUK6AVLt2bTz99NMV3RciIiKiKqFcAWnt2rUV3Q8iIiKiKqNc1yABQF5eHvbv349Vq1bhxo0bAIA///wTN2/erLDOERERERlDuY4gXbp0CX369EFqaipycnLQq1cv2NjY4IMPPsDt27excuXKiu4nERER0UNTriNIkydPRvv27fHPP//AyspKKX/66adx4MCBCuscERERkTGU+y627777Dubm5qpyNzc3XL58uUI6RkRERGQs5TqCVFBQgPz8fIPyP/74AzY2Ng/cKSIiIiJjKldA6tWrFyIiIpR1nU6HmzdvYvbs2fz5ESIiIqr2ynWK7eOPP0bPnj3h7e2N27dvY8SIETh37hzq1q2LqKioiu4jERER0UNVroDk6uqK5ORkREVF4dSpUygoKMDYsWPx/PPPqy7aJiIiIqqOyhWQAMDKygpjxozBmDFjKrI/REREREZXroC0bt26Eh8fOXJkuTpDREREVBWUKyBNnjxZtX7nzh3cunUL5ubmqFmzJgMSERERVWvluovtn3/+US03b97E2bNn0aVLF16kTURERNVeuX+LTatZs2Z4//33DY4uleTw4cMYOHAgXF1dodPpsG3btvtuk5CQAD8/P1haWqJx48ZF/qxJTEwMvL29YWFhAW9vb2zdurUsQyEiIqLHXIUFJAAwMTHBn3/+Wer62dnZ8PHxwbJly0pV/+LFi+jXrx+6du2KpKQkvP3223jttdcQExOj1ElMTMSwYcMQHByMlJQUBAcHY+jQoTh+/HiZx0NERESPJ52ISFk32rFjh2pdRKDX67Fs2TI0bNgQu3fvLntHdDps3boVgwcPLrbOW2+9hR07duD06dNK2bhx45CSkoLExEQAwLBhw5CVlaXqQ58+fVCnTp1Sn/7LysqCnZ0dMjMzYWtrW+axUPXhPuOb+9b5/f3+D6EnRET0oCry87tcF2lrQ4xOp0O9evXw5JNP4qOPPnqgDpUkMTERQUFBqrLevXtjzZo1uHPnDszMzJCYmIipU6ca1Ln3m7+JiIiISlKugFRQUFDR/SiV9PR0ODk5qcqcnJyQl5eHq1evwsXFpdg66enpxbabk5ODnJwcZT0rK6tiO05ERETVSrm/KNJYdDqdar3wDOG95UXV0ZbdKzw8HGFhYRXYy5JVx9M6j2qfK6qdihp7dZznqoZzSI+a6vicro591ipXQJo2bVqp6y5atKg8uyiSs7OzwZGgjIwMmJqawsHBocQ62qNK9woNDVWNKSsrCw0bNqywfhMREVH1Uq6AlJSUhFOnTiEvLw+enp4AgF9//RUmJiZo166dUq+kozblERAQgJ07d6rK9u3bh/bt28PMzEypExcXp7oOad++fejUqVOx7VpYWMDCwqJC+0pERETVV7kC0sCBA2FjY4MvvvgCderUAXD3yyNHjx6Nrl274vXXXy9VOzdv3sT58+eV9YsXLyI5ORn29vZo1KgRQkNDcfnyZeWnTcaNG4dly5Zh2rRpeOmll5CYmIg1a9ao7k6bPHkyunXrhgULFmDQoEHYvn079u/fjyNHjpRnqERERPQYKtf3IH300UcIDw9XwhEA1KlTB++9916Z7mI7efIkfH194evrC+DuqTtfX1/MmjULAKDX65GamqrU9/DwQGxsLOLj49G2bVvMmzcPS5YswbPPPqvU6dSpEzZu3Ii1a9eiTZs2iIyMRHR0NPz9/cszVCIiInoMlesIUlZWFv766y+0bNlSVZ6RkYEbN26Uup0ePXqgpK9hioyMNCjr3r07Tp06VWK7Q4YMwZAhQ0rdDyIiIqJ7lesI0tNPP43Ro0fj66+/xh9//IE//vgDX3/9NcaOHYtnnnmmovtIRERE9FCV6wjSypUrMX36dLzwwgu4c+fO3YZMTTF27FgsXLiwQjtIRERE9LCVKyDVrFkTy5cvx8KFC3HhwgWICJo2bQpra+uK7h8RERHRQ/dAP1ar1+uh1+vRvHlzWFtbl3g9EREREVF1Ua6AdO3aNQQGBqJ58+bo168f9Ho9AODFF18s9S3+RERERFVVuQLS1KlTYWZmhtTUVNSsWVMpHzZsGPbs2VNhnSMiIiIyhnJdg7Rv3z7s3bsXDRo0UJU3a9YMly5dqpCOERERERlLuY4gZWdnq44cFbp69Sp/soOIiIiqvXIFpG7duik//wHc/c21goICLFy4ED179qywzhEREREZQ7lOsS1cuBA9evTAyZMnkZubizfffBM///wz/v77b3z33XcV3UciIiKih6pcR5C8vb3x448/okOHDujVqxeys7PxzDPPICkpCU2aNKnoPhIRERE9VGU+gnTnzh0EBQVh1apVCAsLq4w+ERERERlVmY8gmZmZ4aeffoJOp6uM/hAREREZXblOsY0cORJr1qyp6L4QERERVQnlukg7NzcXn332GeLi4tC+fXuD32BbtGhRhXSOiIiIyBjKFJB+++03uLu746effkK7du0AAL/++quqDk+9ERERUXVXpoDUrFkz6PV6HDp0CMDdnxZZsmQJnJycKqVzRERERMZQpmuQRES1vnv3bmRnZ1doh4iIiIiMrVwXaRfSBiYiIiKiR0GZApJOpzO4xojXHBEREdGjpkzXIIkIRo0apfwg7e3btzFu3DiDu9i2bNlScT0kIiIiesjKFJBCQkJU6y+88EKFdoaIiIioKihTQFq7dm1l9YOIiIioynigi7SJiIiIHkUMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBoMSEREREQaDEhEREREGgxIRERERBpGD0jLly+Hh4cHLC0t4efnh2+//bbYuqNGjYJOpzNYWrZsqdSJjIwsss7t27cfxnCIiIjoEWDUgBQdHY0pU6Zg5syZSEpKQteuXdG3b1+kpqYWWX/x4sXQ6/XKkpaWBnt7e/z3v/9V1bO1tVXV0+v1sLS0fBhDIiIiokeAUQPSokWLMHbsWLz44oto0aIFIiIi0LBhQ6xYsaLI+nZ2dnB2dlaWkydP4p9//sHo0aNV9XQ6naqes7PzwxgOERERPSKMFpByc3Pxww8/ICgoSFUeFBSEo0ePlqqNNWvW4KmnnoKbm5uq/ObNm3Bzc0ODBg0wYMAAJCUlVVi/iYiI6NFnaqwdX716Ffn5+XByclKVOzk5IT09/b7b6/V67N69G1999ZWq3MvLC5GRkWjdujWysrKwePFidO7cGSkpKWjWrFmRbeXk5CAnJ0dZz8rKKseIiIiI6FFh9Iu0dTqdal1EDMqKEhkZidq1a2Pw4MGq8o4dO+KFF16Aj48Punbtik2bNqF58+ZYunRpsW2Fh4fDzs5OWRo2bFiusRAREdGjwWgBqW7dujAxMTE4WpSRkWFwVElLRPD5558jODgY5ubmJdatUaMGnnjiCZw7d67YOqGhocjMzFSWtLS00g+EiIiIHjlGC0jm5ubw8/NDXFycqjwuLg6dOnUqcduEhAScP38eY8eOve9+RATJyclwcXEpto6FhQVsbW1VCxERET2+jHYNEgBMmzYNwcHBaN++PQICArB69WqkpqZi3LhxAO4e2bl8+TLWrVun2m7NmjXw9/dHq1atDNoMCwtDx44d0axZM2RlZWHJkiVITk7GJ5988lDGRERERNWfUQPSsGHDcO3aNcydOxd6vR6tWrVCbGyscleaXq83+E6kzMxMxMTEYPHixUW2ef36dbz88stIT0+HnZ0dfH19cfjwYXTo0KHSx0NERESPBqMGJACYMGECJkyYUORjkZGRBmV2dna4detWse19/PHH+Pjjjyuqe0RERPQYMvpdbERERERVDQMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZEGAxIRERGRBgMSERERkQYDEhEREZGG0QPS8uXL4eHhAUtLS/j5+eHbb78ttm58fDx0Op3BcubMGVW9mJgYeHt7w8LCAt7e3ti6dWtlD4OIiIgeIUYNSNHR0ZgyZQpmzpyJpKQkdO3aFX379kVqamqJ2509exZ6vV5ZmjVrpjyWmJiIYcOGITg4GCkpKQgODsbQoUNx/Pjxyh4OERERPSKMGpAWLVqEsWPH4sUXX0SLFi0QERGBhg0bYsWKFSVu5+joCGdnZ2UxMTFRHouIiECvXr0QGhoKLy8vhIaGIjAwEBEREZU8GiIiInpUGC0g5ebm4ocffkBQUJCqPCgoCEePHi1xW19fX7i4uCAwMBCHDh1SPZaYmGjQZu/eve/bJhEREVEhU2Pt+OrVq8jPz4eTk5Oq3MnJCenp6UVu4+LigtWrV8PPzw85OTlYv349AgMDER8fj27dugEA0tPTy9QmAOTk5CAnJ0dZz8rKKu+wiIiI6BFgtIBUSKfTqdZFxKCskKenJzw9PZX1gIAApKWl4cMPP1QCUlnbBIDw8HCEhYWVp/tERET0CDLaKba6devCxMTE4MhORkaGwRGgknTs2BHnzp1T1p2dncvcZmhoKDIzM5UlLS2t1PsnIiKiR4/RApK5uTn8/PwQFxenKo+Li0OnTp1K3U5SUhJcXFyU9YCAAIM29+3bV2KbFhYWsLW1VS1ERET0+DLqKbZp06YhODgY7du3R0BAAFavXo3U1FSMGzcOwN0jO5cvX8a6desA3L1Dzd3dHS1btkRubi42bNiAmJgYxMTEKG1OnjwZ3bp1w4IFCzBo0CBs374d+/fvx5EjR4wyRiIiIqp+jBqQhg0bhmvXrmHu3LnQ6/Vo1aoVYmNj4ebmBgDQ6/Wq70TKzc3F9OnTcfnyZVhZWaFly5b45ptv0K9fP6VOp06dsHHjRrzzzjt499130aRJE0RHR8Pf3/+hj4+IiIiqJ6NfpD1hwgRMmDChyMciIyNV62+++SbefPPN+7Y5ZMgQDBkypCK6R0RERI8ho//UCBEREVFVw4BEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKTBgERERESkwYBEREREpMGARERERKRh9IC0fPlyeHh4wNLSEn5+fvj222+Lrbtlyxb06tUL9erVg62tLQICArB3715VncjISOh0OoPl9u3blT0UIiIiekQYNSBFR0djypQpmDlzJpKSktC1a1f07dsXqampRdY/fPgwevXqhdjYWPzwww/o2bMnBg4ciKSkJFU9W1tb6PV61WJpafkwhkRERESPAFNj7nzRokUYO3YsXnzxRQBAREQE9u7dixUrViA8PNygfkREhGp9/vz52L59O3bu3AlfX1+lXKfTwdnZuVL7TkRERI8uox1Bys3NxQ8//ICgoCBVeVBQEI4ePVqqNgoKCnDjxg3Y29urym/evAk3Nzc0aNAAAwYMMDjCRERERFQSowWkq1evIj8/H05OTqpyJycnpKenl6qNjz76CNnZ2Rg6dKhS5uXlhcjISOzYsQNRUVGwtLRE586dce7cuWLbycnJQVZWlmohIiKix5dRT7EBd0+H3UtEDMqKEhUVhTlz5mD79u1wdHRUyjt27IiOHTsq6507d0a7du2wdOlSLFmypMi2wsPDERYWVs4REBER0aPGaEeQ6tatCxMTE4OjRRkZGQZHlbSio6MxduxYbNq0CU899VSJdWvUqIEnnniixCNIoaGhyMzMVJa0tLTSD4SIiIgeOUYLSObm5vDz80NcXJyqPC4uDp06dSp2u6ioKIwaNQpfffUV+vfvf9/9iAiSk5Ph4uJSbB0LCwvY2tqqFiIiInp8GfUU27Rp0xAcHIz27dsjICAAq1evRmpqKsaNGwfg7pGdy5cvY926dQDuhqORI0di8eLF6Nixo3L0ycrKCnZ2dgCAsLAwdOzYEc2aNUNWVhaWLFmC5ORkfPLJJ8YZJBEREVU7Rg1Iw4YNw7Vr1zB37lzo9Xq0atUKsbGxcHNzAwDo9XrVdyKtWrUKeXl5mDhxIiZOnKiUh4SEIDIyEgBw/fp1vPzyy0hPT4ednR18fX1x+PBhdOjQ4aGOjYiIiKovo1+kPWHCBEyYMKHIxwpDT6H4+Pj7tvfxxx/j448/roCeERER0ePK6D81QkRERFTVMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkwIBERERFpMCARERERaTAgEREREWkYPSAtX74cHh4esLS0hJ+fH7799tsS6yckJMDPzw+WlpZo3Lgx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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import pylab as P\n", "\n", @@ -473,16 +505,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "6cef48a9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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rERERKQWa1XJULCGlYiIiNRirSoZCv4UIiIiIrVYq0qGggkrERERsVaVDBoTViIionqOtapk6FjDSkREVM+xVpUMHX8iERER1XOsVSVDx4SViIionildr5odm81aVTJoLAkgIiKqR+T1qkVPiuCzxQcJwQkwkhrBSGYEmZdMsY21qmRImLASERHVI2XVq7be0xqm9qasVSWDxJ9ORERE9UhZ9arWftasVSWDxYSViIiojuLcqlRXMGElIiKqgzi3KtUlrGElIiKqgzi3KtUl/DlFRERUB3FuVapLmLASERHVAZxbleoylgQQERHVcpxbleo6JqxERES1HOdWpbqOP7OIiIhqEXVTVXFuVarrmLASERHVEmVNVcV6VarrmLASERHVEqUv/efeyEXRkyIA4NyqVKdJhBCipoOoSVlZWbC1tUVmZiZsbGxqOhwiIqJyZUZlKupUASDgdABsu9oiPy1fMbdqblIu61XrEOYq7GElIiIyWNpMVcW5Vaku4ywBREREBohTVRH9gwkrERGRAeJUVUT/4E8yIiIiA8Spqoj+wYSViIjIAHBpVaKysSSAiIiohrFelah8TFiJiIhqGOtVicrHn2lERETViEurEmmPCSsREVE14dKqRLphwkpERFRNuLQqkW4M7pMQHh4OT09PyGQydOjQASdPniy3/datW+Hn5wcLCws4OztjwoQJSE9Pr6ZoiYiIylb68r+RuVGZl/79jvnB/4Q/bLvawv+EP/yO+bEEgOj/GVTCumPHDsyePRuLFi1CdHQ0evTogf79+yMxMVFt+1OnTmHcuHGYOHEi4uLisHPnTly4cAGTJk2q5siJiIiUqbv8H909GvGvxiu149KqRBUzqIR11apVmDhxIiZNmgQfHx989tlncHNzw5o1a9S2P3v2LJo2bYpZs2bB09MT3bt3x+TJk3Hx4sVqjpyIiEiZusv/xbnFMJbx0j+RtgzmE5Kfn49Lly4hKChIaXtQUBCioqLU3qdr1664c+cODh48CCEE7t+/j127dmHgwIFlPk5eXh6ysrKU/hEREembupH/vtt84X/Sn5f+ibRkMAlrWloaioqK4OTkpLTdyckJKSkpau/TtWtXbN26FaNHj4aZmRkaN24MOzs7rF69uszHCQsLg62treKfm5ubXp8HERHVT5quVFWcU8xL/0RaMpiEVU4ikSj9LYRQ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g0lY5SQSidLfQgiVbeps374dS5cuxY4dO+Do6Fhmu3fffReZmZmKf0lJSZWOmdTLOpeFS90vaZSsOgU7of3p9pyyioiIiFQYzLRWDRs2hLGxsUpvampqqkqva2k7duzAxIkTsXPnTrz44ovltpVKpZBKpZWOl8qnSb2qRTsLNBrWCA79HZioEhERUZkMpofVzMwMHTp0QEREhNL2iIgIdO3atcz7bd++HePHj8e2bdswcODAqg6TNKBJvar9S/boGNsRnks9mawSERFRuQymhxUA5s6di+DgYAQGBqJLly746quvkJiYiClTpgB4djn/7t272Lx5M4Bnyeq4cePw+eefo3PnzoreWXNzc9ja2tbY86iPss5l4enfT3E3/C6yz3IRACIiItIfg0pYR48ejfT0dCxbtgzJyclo06YNDh48CA8PDwBAcnKy0pys69atQ2FhIaZPn47p06crtoeEhGDTpk3VHX69pc10VU7BThxURURERFoxqHlYawLnNqscbWYAaLaqGS//ExERaYm5ioH1sFLtommyyhIAIiIiqgyDGXRFtQuTVSIiIqouTFhJK9rOrcpklYiIiCqLJQGkkaxzWbg69yqyo8qfAcC6izVcp7rCooUF61WJiIhIL5iwUoU0nQWAl/+JiIioKjBhpXKxVpWIiIhqGmtYqUyaJqusVSUiIqKqxB5WUpF1LgtX511F9uny61U5tyoRERFVByaspKDpwCqAK1YRERFR9WHCSgA0H1hl0c4Crb5qxV5VIiIiqjZMWIkDq4iIiMigcdBVPceBVURERGTo2MNaT3FgFREREdUWTFjrGQ6sIiIiotqGCWs9woFVREREVBsxYa0nOLCKiIiIaisOuqoHOLCKiIiIajP2sNZxmiSrHFhFREREhowJax2l6SwAHFhFREREho4Jax2j6SwAHFhFREREtQUT1jpE01kAOLCKiIiIahMmrHUEZwEgIiKiuoqzBNQBnAWAiIiI6jL2sNZiXF6ViIiI6gMmrLWUpvWqnAWAiIiIajsmrLWQJiUAnAWAiIiI6gomrLWMJskqB1YRERFRXcJBV7WIJskqB1YRERFRXcMe1lpAk8FVHFhFREREdRUTVgOnyeAqlgAQERFRXcaSAAMWP47JKhERERETVgOVvD4ZqVuYrBIRERGxJMAAaVIGwPlViYiIqL5gwmpAOLiKiIiI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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "fig = plt.figure()\n", "\n", - "CS = plt.contour(xi, yi, zi, linewidth=0.5)\n", + "#CS = plt.contour(xi, yi, zi, linewidth=0.5)\n", "\n", - "plt.clabel(CS, fontsize=10, inline=1)\n", + "#plt.clabel(CS, fontsize=10, inline=1)\n", "\n", "l1 = plt.scatter(xLList[0][:,0], xLList[0][:,1], marker='o', c='m', s=10);\n", "\n", @@ -521,7 +564,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "dc31f543", "metadata": {}, "outputs": [], @@ -580,9 +623,11 @@ ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "id": "67ae8521", "metadata": {}, + "outputs": [], "source": [ "targetState = \\['I', 'R'\\]\n", "\n", @@ -630,8 +675,16 @@ "name": "python3" }, "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", "name": "python", - "version": "3.9.15" + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/paramfit/seir_epi_data.txt b/docs/notebooks/paramfit/seir_epi_data.txt new file mode 100644 index 00000000..31ba102b --- /dev/null +++ b/docs/notebooks/paramfit/seir_epi_data.txt @@ -0,0 +1,201 @@ +0.000000 5.000000 0.000000 +1.000000 4.000000 1.000000 +2.000000 3.000000 2.000000 +3.000000 4.000000 2.000000 +4.000000 3.000000 4.000000 +5.000000 5.000000 4.000000 +6.000000 4.000000 6.000000 +7.000000 3.000000 7.000000 +8.000000 3.000000 8.000000 +9.000000 2.000000 9.000000 +10.000000 4.000000 9.000000 +11.000000 5.000000 9.000000 +12.000000 7.000000 9.000000 +13.000000 5.000000 13.000000 +14.000000 9.000000 14.000000 +15.000000 5.000000 19.000000 +16.000000 6.000000 21.000000 +17.000000 8.000000 24.000000 +18.000000 8.000000 27.000000 +19.000000 12.000000 28.000000 +20.000000 12.000000 31.000000 +21.000000 13.000000 32.000000 +22.000000 13.000000 36.000000 +23.000000 12.000000 40.000000 +24.000000 13.000000 44.000000 +25.000000 17.000000 47.000000 +26.000000 15.000000 53.000000 +27.000000 16.000000 55.000000 +28.000000 20.000000 59.000000 +29.000000 21.000000 66.000000 +30.000000 25.000000 71.000000 +31.000000 26.000000 80.000000 +32.000000 29.000000 84.000000 +33.000000 34.000000 91.000000 +34.000000 37.000000 99.000000 +35.000000 39.000000 110.000000 +36.000000 39.000000 117.000000 +37.000000 53.000000 124.000000 +38.000000 57.000000 131.000000 +39.000000 53.000000 146.000000 +40.000000 48.000000 160.000000 +41.000000 40.000000 174.000000 +42.000000 41.000000 182.000000 +43.000000 34.000000 201.000000 +44.000000 39.000000 203.000000 +45.000000 37.000000 213.000000 +46.000000 40.000000 225.000000 +47.000000 53.000000 233.000000 +48.000000 56.000000 245.000000 +49.000000 58.000000 261.000000 +50.000000 58.000000 279.000000 +51.000000 62.000000 289.000000 +52.000000 66.000000 302.000000 +53.000000 76.000000 314.000000 +54.000000 73.000000 336.000000 +55.000000 82.000000 352.000000 +56.000000 91.000000 383.000000 +57.000000 85.000000 405.000000 +58.000000 96.000000 425.000000 +59.000000 85.000000 460.000000 +60.000000 95.000000 473.000000 +61.000000 109.000000 494.000000 +62.000000 110.000000 513.000000 +63.000000 119.000000 534.000000 +64.000000 128.000000 562.000000 +65.000000 139.000000 590.000000 +66.000000 157.000000 629.000000 +67.000000 146.000000 672.000000 +68.000000 163.000000 709.000000 +69.000000 174.000000 756.000000 +70.000000 202.000000 808.000000 +71.000000 198.000000 863.000000 +72.000000 193.000000 915.000000 +73.000000 195.000000 933.000000 +74.000000 215.000000 974.000000 +75.000000 218.000000 1031.000000 +76.000000 231.000000 1089.000000 +77.000000 250.000000 1149.000000 +78.000000 228.000000 1226.000000 +79.000000 231.000000 1302.000000 +80.000000 238.000000 1365.000000 +81.000000 227.000000 1403.000000 +82.000000 225.000000 1476.000000 +83.000000 239.000000 1547.000000 +84.000000 238.000000 1619.000000 +85.000000 252.000000 1686.000000 +86.000000 253.000000 1721.000000 +87.000000 259.000000 1793.000000 +88.000000 269.000000 1872.000000 +89.000000 272.000000 1946.000000 +90.000000 279.000000 1978.000000 +91.000000 274.000000 2060.000000 +92.000000 278.000000 2133.000000 +93.000000 293.000000 2205.000000 +94.000000 296.000000 2242.000000 +95.000000 293.000000 2326.000000 +96.000000 291.000000 2414.000000 +97.000000 280.000000 2470.000000 +98.000000 283.000000 2539.000000 +99.000000 271.000000 2631.000000 +100.000000 265.000000 2713.000000 +101.000000 257.000000 2802.000000 +102.000000 262.000000 2834.000000 +103.000000 268.000000 2918.000000 +104.000000 270.000000 2988.000000 +105.000000 279.000000 3023.000000 +106.000000 290.000000 3100.000000 +107.000000 285.000000 3168.000000 +108.000000 280.000000 3221.000000 +109.000000 274.000000 3289.000000 +110.000000 276.000000 3382.000000 +111.000000 268.000000 3472.000000 +112.000000 256.000000 3522.000000 +113.000000 267.000000 3579.000000 +114.000000 257.000000 3659.000000 +115.000000 255.000000 3699.000000 +116.000000 248.000000 3782.000000 +117.000000 235.000000 3829.000000 +118.000000 225.000000 3904.000000 +119.000000 208.000000 3973.000000 +120.000000 210.000000 4006.000000 +121.000000 196.000000 4072.000000 +122.000000 183.000000 4126.000000 +123.000000 170.000000 4158.000000 +124.000000 147.000000 4222.000000 +125.000000 142.000000 4244.000000 +126.000000 130.000000 4297.000000 +127.000000 113.000000 4344.000000 +128.000000 105.000000 4365.000000 +129.000000 94.000000 4400.000000 +130.000000 101.000000 4427.000000 +131.000000 95.000000 4445.000000 +132.000000 84.000000 4478.000000 +133.000000 79.000000 4500.000000 +134.000000 75.000000 4532.000000 +135.000000 75.000000 4544.000000 +136.000000 77.000000 4568.000000 +137.000000 70.000000 4589.000000 +138.000000 64.000000 4601.000000 +139.000000 64.000000 4620.000000 +140.000000 59.000000 4632.000000 +141.000000 56.000000 4650.000000 +142.000000 51.000000 4666.000000 +143.000000 59.000000 4672.000000 +144.000000 49.000000 4689.000000 +145.000000 42.000000 4705.000000 +146.000000 48.000000 4708.000000 +147.000000 53.000000 4712.000000 +148.000000 52.000000 4729.000000 +149.000000 38.000000 4751.000000 +150.000000 38.000000 4761.000000 +151.000000 35.000000 4777.000000 +152.000000 31.000000 4785.000000 +153.000000 38.000000 4788.000000 +154.000000 37.000000 4804.000000 +155.000000 33.000000 4810.000000 +156.000000 30.000000 4819.000000 +157.000000 24.000000 4829.000000 +158.000000 22.000000 4835.000000 +159.000000 18.000000 4842.000000 +160.000000 17.000000 4851.000000 +161.000000 16.000000 4852.000000 +162.000000 18.000000 4854.000000 +163.000000 17.000000 4856.000000 +164.000000 20.000000 4859.000000 +165.000000 20.000000 4863.000000 +166.000000 21.000000 4866.000000 +167.000000 24.000000 4869.000000 +168.000000 24.000000 4877.000000 +169.000000 18.000000 4886.000000 +170.000000 16.000000 4890.000000 +171.000000 15.000000 4892.000000 +172.000000 12.000000 4896.000000 +173.000000 12.000000 4899.000000 +174.000000 12.000000 4903.000000 +175.000000 11.000000 4905.000000 +176.000000 12.000000 4906.000000 +177.000000 11.000000 4910.000000 +178.000000 11.000000 4912.000000 +179.000000 13.000000 4917.000000 +180.000000 11.000000 4922.000000 +181.000000 9.000000 4926.000000 +182.000000 6.000000 4929.000000 +183.000000 6.000000 4929.000000 +184.000000 9.000000 4930.000000 +185.000000 9.000000 4932.000000 +186.000000 7.000000 4934.000000 +187.000000 7.000000 4936.000000 +188.000000 7.000000 4937.000000 +189.000000 7.000000 4941.000000 +190.000000 5.000000 4944.000000 +191.000000 5.000000 4944.000000 +192.000000 7.000000 4944.000000 +193.000000 6.000000 4945.000000 +194.000000 6.000000 4946.000000 +195.000000 6.000000 4946.000000 +196.000000 4.000000 4948.000000 +197.000000 3.000000 4949.000000 +198.000000 2.000000 4951.000000 +199.000000 2.000000 4951.000000 +200.000000 3.000000 4951.000000 diff --git a/docs/notebooks/sir.ipynb b/docs/notebooks/sir.ipynb index f90e3e31..0611b915 100644 --- a/docs/notebooks/sir.ipynb +++ b/docs/notebooks/sir.ipynb @@ -4,19 +4,35 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Motivating Example: SIR Model\n", + "# Defining an ODE system\n", "\n", - "## Defining the model\n", + "There are 2 ways to encapsulate an ODE system.\n", "\n", - "First, we are going to go through an SIR model to show the functionality\n", - "of the package. The SIR model is defined by the following equations\n", + "We first demonstrate how to encapsulate the relevant equations in a class which will eventually be used to solve them.\n", + "\n", + "One useful feature of PyGom is the ability to define the system in a variety of intuitive ways.\n", + "\n", + "In compartmental models, where the states represent counts of certain categories, the changes in these quantities\n", + "\n", + "## Example: SIR model\n", + "\n", + "Here we use a Susceptible-Infected-Removed epidemic model (an SIR model, for short) to demonstrate the different ways to specify a system.\n", + "The rates of change of each compartment are defined by the following equations\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d} S}{\\mathrm{d} t} &= -\\beta SI \\\\\n", + "\\frac{\\mathrm{d} I}{\\mathrm{d} t} &= \\beta SI- \\gamma I \\\\\n", + "\\frac{\\mathrm{d} R}{\\mathrm{d} t} &= \\gamma I.\n", + "\\end{aligned}$$\n", + "\n", + "However, it is also true that this is the result of two transitions:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -\\beta SI \\\\\n", - "\\frac{dI}{dt} &= \\beta SI- \\gamma I \\\\\n", - "\\frac{dR}{dt} &= \\gamma I.\n", + "S \\rightarrow I &= \\beta SI \\\\\n", + "I \\rightarrow R &= \\gamma I\n", "\\end{aligned}$$\n", "\n", + "\n", "We can set this up as follows:" ] }, @@ -25,12 +41,12 @@ "id": "586834ab", "metadata": {}, "source": [ - "1. import the classes required to define the transitions" + "1. Import the classes required to define the transitions" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "4c80a36a", "metadata": {}, "outputs": [], @@ -43,12 +59,12 @@ "id": "0ec4c9d0", "metadata": {}, "source": [ - "2. define our states, in this case the population states of **S**usceptible, **I**nfected and **R**emoved" + "2. Define our states, in this case the population states of **S**usceptible, **I**nfected and **R**emoved" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3ce016f2", "metadata": {}, "outputs": [], @@ -61,12 +77,12 @@ "id": "021a1927", "metadata": {}, "source": [ - "3. define the set of parameters for our model, here there are only two" + "3. Define the set of parameters for our model" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "441e2287", "metadata": {}, "outputs": [], @@ -79,33 +95,43 @@ "id": "dfd736b2", "metadata": {}, "source": [ - "4. specify the transitions of the modelled states; this will form our ODE system" + "4. \n", + " i. Specify the transitions of the modelled states; this will form our ODE system" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "b5f80ab0", "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'Transition' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[1;32mIn[4], line 2\u001b[0m\n\u001b[0;32m 1\u001b[0m odeList \u001b[39m=\u001b[39m [\n\u001b[1;32m----> 2\u001b[0m Transition(origin\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mS\u001b[39m\u001b[39m'\u001b[39m, equation\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39m-beta*S*I\u001b[39m\u001b[39m'\u001b[39m, transition_type\u001b[39m=\u001b[39mTransitionType\u001b[39m.\u001b[39mODE),\n\u001b[0;32m 3\u001b[0m Transition(origin\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mI\u001b[39m\u001b[39m'\u001b[39m,equation\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mbeta*S*I - gamma*I\u001b[39m\u001b[39m'\u001b[39m, transition_type\u001b[39m=\u001b[39mTransitionType\u001b[39m.\u001b[39mODE),\n\u001b[0;32m 4\u001b[0m Transition(origin\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mR\u001b[39m\u001b[39m'\u001b[39m, equation\u001b[39m=\u001b[39m\u001b[39m'\u001b[39m\u001b[39mgamma*I\u001b[39m\u001b[39m'\u001b[39m, transition_type\u001b[39m=\u001b[39mTransitionType\u001b[39m.\u001b[39mODE) \n\u001b[0;32m 5\u001b[0m ]\n", - "\u001b[1;31mNameError\u001b[0m: name 'Transition' is not defined" - ] - } - ], + "outputs": [], "source": [ "odeList = [\n", " Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.ODE),\n", " Transition(origin='I',equation='beta*S*I - gamma*I', transition_type=TransitionType.ODE),\n", " Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE) \n", - " ]" + "]" + ] + }, + { + "cell_type": "markdown", + "id": "18c7fbac", + "metadata": {}, + "source": [ + "ii. Specify the transitions of the modelled states; this will form our ODE system" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2761de1", + "metadata": {}, + "outputs": [], + "source": [ + "odeList2 = [\n", + " Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T),\n", + " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)\n", + "]" ] }, { @@ -124,7 +150,7 @@ "metadata": {}, "source": [ "\n", - "5. import the ode module" + "5. Depending on if we want to run deterministic or stochastic solver, we create a class. For this case let's try depterministic. We import the relevant class." ] }, { @@ -142,7 +168,7 @@ "id": "477d6f84", "metadata": {}, "source": [ - "6. initialize the model, which constructs our ODE system from all the information we have provided" + "6. And then initialize the model, which constructs our ODE system from all the information we have provided" ] }, { diff --git a/docs/notebooks/stochastic.ipynb b/docs/notebooks/stochastic.ipynb deleted file mode 100644 index f037f47b..00000000 --- a/docs/notebooks/stochastic.ipynb +++ /dev/null @@ -1,617 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Stochastic representation of ODEs\n", - "\n", - "There are multiple interpretations of the stochasticity of a deterministic\n", - "ODE. We have implemented two of the most common interpretations; when the\n", - "parameters are realizations of some underlying distribution, and when we\n", - "have a so called chemical master equation where each transition\n", - "represent a jump. Again, we use the standard SIR example as previously\n", - "seen in {doc}`sir`." - ] - }, - { - "cell_type": "markdown", - "id": "d945f972", - "metadata": {}, - "source": [ - "#TODO add comment about using a density or frequency formulation (use of population size) - currently unexplained" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "id": "3f44792d", - "metadata": {}, - "outputs": [], - "source": [ - "from pygom import SimulateOde, Transition, TransitionType\n", - "\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import numpy as np\n", - "\n", - "# initial conditions\n", - "Ix0 = [1, 1.27e-6, 0]\n", - "\n", - "# time period\n", - "t = np.linspace(0, 150, 100)\n", - "\n", - "stateList = ['S', 'I', 'R']\n", - "\n", - "paramList = ['beta', 'gamma']\n", - "\n", - "transitionList = [Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T), \n", - " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)]\n", - "\n", - "# create the ODEs\n", - "odeS = SimulateOde(stateList, paramList, transition=transitionList)\n", - "\n", - "# assign parameter values\n", - "odeS.parameters = [0.5, 1.0/3.0]\n", - "\n", - "# assign initial values\n", - "odeS.initial_values = (Ix0, t[0])\n", - "\n", - "# solve deterministic solution\n", - "solutionReference = odeS.integrate(t[1::], full_output=False)" - ] - }, - { - "cell_type": "markdown", - "id": "0e516f09", - "metadata": {}, - "source": [ - "\n", - "## Stochastic Parameters\n", - "\n", - "In our first implementation, we assume that the parameters follow some\n", - "underlying distribution. Given that both $\\beta$ and $\\gamma$ in our SIR\n", - "model has to be non-negative, it seems natural to use a Gamma\n", - "distribution. We make use of the familiar syntax from\n", - "[R](http://www.r-project.org/) to define our distribution.\n", - "Unfortunately, we have to define it via a tuple, where the first item is the\n", - "function handle (name) and the second the parameters. \n", - "\n", - "```{note}\n", - "The parameters can be defined as either a dictionary or as the same sequence\n", - "as [R](http://www.r-project.org/) (without specifying the arguments), which for the [Gamma distribution](https://stat.ethz.ch/R-manual/R-devel/library/stats/html/GammaDist.html) is the shape followed by the rate.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "a3e9bc81", - "metadata": {}, - "outputs": [], - "source": [ - "from pygom.utilR import rgamma\n", - "\n", - "d = dict()\n", - "\n", - "# E(X) = 0.5 = shape * scale = shape / rate \n", - "d['beta'] = (rgamma,{'shape':100.0, 'rate':200.0})\n", - "\n", - "# E(X) = 1.0/3.0 = shape / rate\n", - "d['gamma'] = (rgamma,(100.0, 300.0))\n", - "\n", - "odeS.parameters = d\n", - "\n", - "Ymean, Yall = odeS.simulate_param(t[1::], 10, full_output=True)" - ] - }, - { - "cell_type": "markdown", - "id": "2221479d", - "metadata": {}, - "source": [ - "```{note}\n", - "Note that a message may be printed above where PyGOM is trying to connect to an\n", - "mpi backend, as our module has the capability to compute in parallel\n", - "using the IPython. We have simulated a total of 10 different solutions\n", - "using different parameters, the plots can be seen below.\n", - "```\n" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "id": "8849566b", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoYAAAHrCAYAAABSCFxgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOydeZgcdZ3/X1V99/Tc95VM7gNCEgKEU0ACURAFUTlUNCuoSLzy28Moh8dKXEVEd9nFZWHBa2VFBFYggJGISCCQA3Lfk0nmvmf67q6q3x9V1T1Hd0/33Mf39Tz9dE93ddW3k6mpd3+O90fSNE1DIBAIBAKBQDDjkSd6AQKBQCAQCASCyYEQhgKBQCAQCAQCQAhDgUAgEAgEAoGBEIYCgUAgEAgEAkAIQ4FAIBAIBAKBgRCGAoFAIBAIBAJACEOBQCAQCAQCgYEQhgKBQCAQCAQCQAhDgUAgEAgEAoGBEIYCgUAgEAgEAkAIwxnBnj17+NjHPsbs2bNxOp1UVlZy5ZVX8q//+q8TvTSBYNry+OOPI0kS77zzzkQvRSCYUpjnjnmzWq1UVlby2c9+lvr6+ole3rTHOtELEIwtb7zxBpdffjmzZs3i9ttvp6ysjFOnTvHmm2/y05/+lC9/+csTvUSBQCAQCAbx3e9+lzlz5hAMBnnzzTd5/PHHef3119m7dy9Op3OilzdtEcJwmvP973+f3Nxc3n77bfLy8vq91tLSMjGLEggEAoFgCD74wQ9yzjnnAHDbbbdRVFTEv/zLv/Dcc8/xiU98YoJXN30RqeRpzrFjxzjjjDMGiUKAkpKS8V+QQCAQCATD4JJLLgH065pg7BDCcJoze/ZsduzYwd69eyd6KQKBQCAQDJva2loA8vPzJ3Yh0xwhDKc5f//3f4/f72fFihVceOGF/NM//RMvv/wykUhkopcmEAgEAkFSuru7aWtr4/Tp0/z+97/nO9/5Dg6Hgw996EMTvbRpjRCG05wrr7ySbdu28eEPf5h3332XH/7wh6xdu5bKykqee+65iV6eQCAQCAQJWbNmDcXFxVRXV/Oxj32MrKwsnnvuOaqqqiZ6adMaIQxnAOeeey5PP/00nZ2dbN++nY0bN9Lb28vHPvYx9u/fP9HLEwgEAoFgEA899BCvvPIKTz31FFdffTVtbW04HI6JXta0RwjDGYTdbufcc8/lvvvu4z/+4z+IRCL87ne/m+hlCQQCgUAwiPPOO481a9Zwww038Nxzz3HmmWdyyy234PV6J3pp0xohDGcopgVAY2PjBK9EIBAIBILUWCwWNm3aRENDA//2b/820cuZ1ghhOM159dVX0TRt0PMvvPACAIsWLRrvJQkEAoFAkDGXXXYZ5513Hg8++CDBYHCilzNtEQbX05wvf/nL+P1+rr/+ehYvXkw4HOaNN97gySefpKamhnXr1k30EgUCgUAgSIt/+Id/4OMf/ziPP/44X/ziFyd6OdMSETGc5tx///1cfvnlvPDCC2zYsIENGzawfft2vvSlL/HWW28lNL4WCAQCgWAy8tGPfpR58+Zx//33oyjKRC9nWiJpifKMAoFAIBAIBIIZh4gYCgQCgUAgEAgAIQwFAoFAIBAIBAZCGAoEAoFAIBAIACEMBQKBQCAQCAQGQhgKBAKBQCAQCAAhDAUCgUAgEAgEBlPC4FpVVRoaGsjOzkaSpIlejkCApmn09vZSUVGBLE+f71fiXBNMNqbiuSbOI8FkI5PzaEoIw4aGBqqrqyd6GQLBIE6dOkVVVdVEL2PUEOeaYLIylc41cR4JJivpnEdTQhhmZ2cD+gfKycmZ4NUIBNDT00N1dXXsd3O6IM41wWRjKp5r4jwSTDYyOY+mhDA0Q/E5OTniJBNMKqZbmkica4LJylQ618R5JJispHMeTY2CDYFAIBAIBALBmCOEoUAgEAgEAoEAEMJQIBAIBAKBQGAghKFAIBAIBAKBABDCUCAQCAQCgUBgIIShQCAQCKY1Dz30EDU1NTidTlavXs327dtTbv/ggw+yaNEiXC4X1dXVfP3rXycYDI7TagWCiUUIQ4FAIBBMW5588kk2bNjAvffey86dO1m+fDlr166lpaUl4fa/+c1v+MY3vsG9997LgQMHePTRR3nyySf55je/Oc4rFwgmBiEMBQKBQDBteeCBB7j99ttZt24dS5cu5eGHH8btdvPYY48l3P6NN97goosu4pZbbqGmpoarrrqKm2++ecgoo0AwXRDCUCAQCATTknA4zI4dO1izZk3sOVmWWbNmDdu2bUv4ngsvvJAdO3bEhODx48d54YUXuPrqq5MeJxQK0dPT0+8mEExVpsTkE4FAIBAIMqWtrQ1FUSgtLe33fGlpKQcPHkz4nltuuYW2tjYuvvhiNE0jGo3yxS9+MWUqedOmTXznO98Z1bULBBOFiBgKBAKBQGCwdetW7rvvPv793/+dnTt38vTTT/P888/zve99L+l7Nm7cSHd3d+x26tSpcVyxQDC6iIihQCAQCKYlRUVFWCwWmpub+z3f3NxMWVlZwvfcfffdfPrTn+a2224DYNmyZfh8Pj7/+c/zrW99C1keHE9xOBw4HI7R/wACwQSQccTwtdde49prr6WiogJJknjmmWeGfM/WrVs5++yzcTgczJ8/n8cff3wYSxUIBAKBIH3sdjurVq1iy5YtsedUVWXLli1ccMEFCd/j9/sHiT+LxQKApmljt1iBYJKQsTD0+XwsX76chx56KK3tT5w4wTXXXMPll1/O7t27+drXvsZtt93GSy+9lPFiBQKBQCDIhA0bNvDII4/wxBNPcODAAe644w58Ph/r1q0D4NZbb2Xjxo2x7a+99lr+4z/+g9/+9recOHGCV155hbvvvptrr702JhAFgulMxqnkD37wg3zwgx9Me/uHH36YOXPm8OMf/xiAJUuW8Prrr/OTn/yEtWvXZnr4QZw6eRwlGh78giTpd7IViywBEhbZChYJSZaRLVYsVisSMhaLFatxwssWCatsMd4rxb45SkhIxj4FAsHUQ9M0cQ7PQG688UZaW1u55557aGpqYsWKFWzevDnWkFJXV9cvQnjXXXchSRJ33XUX9fX1FBcXc+211/L9739/oj6CYJzQNA00DQ0NtIER4sHR4skYQJYksFhtI9rHmNcYbtu2rZ9VAMDatWv52te+lvQ9oVCIUCgU+zlV6/91R/ZTb6ka8ToHImkqMioSGhIaMvrPsvG8RdMfWzQVi6piUVSsUbBEJBwRFWc0iisaxRWO4AlHyAmFyQ2GyAqF0CSNqKQRkqP4bWFC9ggRZ5ioK4LqCqO5I+BSsFtt2C127BY7TosTp9WJ0+LEZXXhtrnJsmXhsXnItmeTY88h15FLvjMft9UtLoACQR+2P/sUb//f09x4z30UzaqZ6OUIxpn169ezfv36hK9t3bq1389Wq5V7772Xe++9dxxWJhguQZ+XzoZ6ulub8ba34evuItDbQ8jnJRzwEw4GiYZCRCNhlEgUJRpBjUZRVQVVUdE0FU1V0VQNTVMn+uOMGhULl3Dz9340on2MuTBsampKaBXQ09NDIBDA5XINes9kaP3XJBklUaZ9hHrLqkTJ83sp9HZT2ttBRVc7ud4IktcOmh27WoBFcaJGnUQ1Cb8lSKezkw53A21Zp2l3N6DKSspjOCwOCp2FFLmLKHWXUp5VToWngursampyaqjwVGCVRd+RYOZw4PWtBHt7qNv7rhCGAsEUpLulmRO73uHUvvdoPHqY3vbWiV7StGVSqoONGzeyYcOG2M89PT1UV1cn3PbR/ALCoY5+z6mKHt81w8IAqqagKQoaGqqqokUjqIqKEg0TDYeIRiNEAwHCAR+hYIBgwEcg0Es4GgaLBFYZm1UiXwOLEiJil4i6ZSIuiYhHIpQDoSyJkMVGADd+3HjJplvNpy1SSQdF9NidRC1W2rLzaMvO41D5bAByA37mtNazsLmOAn8vWEJg7wbAAZRpFqo7l2Jvuhh7JB+1IIKvtIWOkpO0uxvoifTQE+qhO9xNSAkRUkI0+Bpo8DUk/Dezy3bm5s1lccFizig8g7OKz2Jh/kIhFgXTkmg4TEe9bh/S29E+wasRCATpokSjHNr2V3a/9Ecajxwa9Lonv4Dc0nKyC4vIysvHlZ2D0+PB7nJjc7qw2R1Y7XasdjuyxYJssSJbLciyjGTe0MvLJEnqU4IWLyHrGwwaOhM38Zm6RF3zmTLmSqCsrCyhVUBOTk7CaCFk1vq/YtWFI15jKrqam9j3lz+xe/MfCfq8dNnsfHD9Bqqz8/Fu3Ur3M88RqasDwFaWTfEaP8G8ZjrzbLQWOgg7ZHBARLWw+cT7eb7pas5eNovFiwrZEwjxTrePbpeb3bMWsHvWAs72RfjQkWbK2lvpkHpplXsISVEiji4iji58gDWcjfNIGXPfez9nl3hYtLqMpZdWkJXnwB/x0xHsoC3QRlugjWZ/Mw3eBuq99dT11lHXU0dICXGw4yAHOw7yzNFnAPDYPKwqXcVFlRdxWdVllHvKx/TfVSAYL9pP16EqepS9t71tglcjEAiGQtM0jr7zJn/5xX/R3aLrB0mSqVy8lNlnraRy0RJK5szD4c6a4JVOTyRtBP33kiTxhz/8geuuuy7pNv/0T//ECy+8wJ49e2LP3XLLLXR0dLB58+a0jtPT00Nubi7d3d3k5OQMd7kjwtfVyeb/eJDa3TuwWK3c8K3vUb10GZqi0PPCC7T88EdEW1uRnE6q7/kCWZ1/QDv1Ju35Nk4urKTL4QWgwVvKv7/7dwS0WWy6fhnvW1LCqx29PNXcwcttPZiVDh/wZPGtHhvZ77XT2tJCvdxJndxKo6VLL4wFJNWK21eNy1+BRbKy8LxSVn2whrxSd9LPoWoq9b31HO48zP6O/exr28d7re/RG+ntt90ZhWdw9ZyruWbuNRS6Csfk33QqMxl+J8eC6fi59rz6Mi8//DMAKhcv5abv/HCCVyTIhKn4OzkV1zxZCAf8vPLIQxz8218AcOfmcfYHP8yZl19JVl7+BK9u6pLJ72TGwtDr9XL06FEAVq5cyQMPPMDll19OQUEBs2bNYuPGjdTX1/OLX/wC0O1qzjzzTO68807+7u/+jj//+c985Stf4fnnn0+7K3mynGSqqvB/D/yAo29vw5GVxboHHo79okY7O2n4f3+P7403kJxOZv3XI7ilvfDiN9CiAdrmLeRQjYVQpJWw4uTHO77A0a55fOWKBXx9zQIkSaIuEOLf6lr4dWM7igZ5Vgs/WVzNFWEr3jca8O9qwa8GOWpt4qC7iZ6wLjZtkhNXx1wcoSJkWeKMSytZ/eG5OFzpBYQVVeFQ5yG2NWzjtdOvsbt1N6pRjGuVrayZtYZPL/00ZxWfNTb/sFOQyfI7OdpMx8/158d/zq4X/w+AnOISbv+3xyZ4RYJMmIq/k1NxzZMBb0c7T33/btpP1yFbLJz74RtYfd0nsDmdE720Kc+YCsOtW7dy+eWXD3r+M5/5DI8//jif/exnqa2t7dfptXXrVr7+9a+zf/9+qqqquPvuu/nsZz+b9jEn00kWDYf5zd1/T2vtcc64dA0f+NLXYq+poRCnv/xlfK/9FWtJCXOefQar7zj85hPgbyM0/2L2LvHQ1f0OiubiX7Z/kWPdc/jC++byjQ8ujtUvHPQF+MqBOt7rDQDwrbnlrJ9VgtIZovvFEwT2tKGiUlvQyQ7LCbp79XrEAkc1Ul01smYlK8/B+z+9mFlnZB7taw+088rJV3ju2HPsaYtHeleXreZLK77E2aVnj+BfcHowmX4nR5Pp+Lme/PY3OH1gLwCyxcLXfvWHWA2RYPIzFX8np+KaJxpvRzv/+92NdDY24Mkv4ENf+waVi5dO9LKmDWMqDCeCyXaSNRw+wP/c/Q8A3Py9H1GxcEnsNdXv58QNHyN84gTZV66h8mc/Q2p6Dx77IER8KOd/gXdLG+nsfAOFfP5h6wa6w7l844OL+eKl82L7iaga3z5az6P1ek3UhppS/nGOXvcXONBO51NHUH0RVJfEwWU9bNvzNpqmkZudT27XGQRa9QvfOVfXcO6H5iDLwyuKPdhxkF/u/yUvnHiBqBoF4IpZV/D/zvl/VGcnbgiaCUy238nRYrp9Lk3T+Ld1NxIO+GPPffHnvxQpqSnEVPydnIprnkii4TBPfvufaDp2hJziEj5xz33kliQeWSgYHpn8ToqvzcOgYuESzrj0CgC2P/v7fq/JbjeVP74fbDZ6X/kTvtf/BuXL4YZHALC8+Z8sL/gCnqxFWOjk+5f/DllS+OHmg7x5PN4xaZMlvr+wiu/MrwDggdpmHq5rAcC1pJDSr56NrcqDHNA4Y1cun1r7cXJycuju7aTVs4NZ5+mh93deqOXl/9qHEhmeT9PigsV8/+Lv8/z1z3PDghuQJZktdVv46LMf5bG9j6Goqa1zBIKJpKe1mXDAj8VqxZ2bB0Bvm7C5EAgmE68+/p80HTuC05PNx+8WonCiEcJwmJz74RsAOL5zO97O/nY5zqVLKfjkJwFo/elPdducxdfA8psBDcsf/55lS36CxeLBpb3H1y7Yj6rBV/5nF52+/lNcvlBdwrfm6pHC7x5r4LUOvUnEkmOn+PNn4VyUjxZRcT7fyWevuYWKigoCgQD7Wl5j5fVFyBaJYztbeP7f3yUaGb6Iq/BU8O0Lv83vr/0955WdR1AJ8pMdP+HvXvo7GryJbXEEgommxxCBOcWl5Bbrfqq9HaIzWSCYLNTu3sF7WzaDJHHNl/+evFIhCicaIQyHSWHVLCoWLkFTVfZt/dPg12+/DcntJrh3L15zgPva+8BdBK0HcB99i/nz9HT0WXn/y5llKi29IR545fCgfX15dim3lBegAl/cX0tjSBePst1C4aeW4liQhxZRCT5Vyyevv4nq6mqCwSB/3f0i7/vsbKwOC6cOdPLSI/tQlJE5vM/Pn89/XfVffPfC75Jly2Jny04+8cdP8Lf6v41ovwLBWBAO6HW6dpcbT6Feb9vbLrwMBYLJQDQcZst/PwzA2R/8MDUrVk3wigQghOGIWHaF3lW959WX0dT+gstaWEjBpz4FQMcTeoc27gK4+Gv6478+QEXZx/B4FqNEu/mHi3Rh9eu3TrK/YfAIwPsWVHGWx0VHROGbh+tjz0s2mcJPLcFa6kbtjeD93+N88uZbKC8vJxAI8OpbL3DlbYuwWGVq32vj9SePjPhzS5LE9Quu56lrn+LMwjPpDnXzpS1f4n8O/s+I9y0QjCaRoCkMXWQXFAHgFRFDgWBSsOOFZ+lqaiQrv4ALP/7JiV6OwEAIwxGw6IKLsTocdDc30Xbq5KDX82++CSQJ/9tvEz6lT17gnL8DVwF0nkDe9ywLFtwFgOp7lo+ucKFqcN8LBwbty2mR+emSWVgleLGtmxdau2KvyQ4rRZ85A8lpJXKql9DfWrj55pvJycmhra2Ndw68xpWfWwoS7H2tnn1/rR+0/+FQlV3F4x98nOvnX4+qqdz31n08uONBpkA/k2CGEDaEoc3pJLtQF4bC5FogmHgiwSDv/PEPALzvls/icCf33xWML0IYjgCbw0nVkjMBqNv77uDXy8vJuuACALqfeVZ/0p4FF9ypP37rYfLzzicnZwWqGubTy97GIku8frSNPae7B+1vicfF+ll6ndTdR+oJ9YlSWguc5F+vdzX3vlqHs1vixhtvRJZl9u/fT7d2mtXXzgHgr08eob3eOyr/Bg6Lg+9c+B2+svIrADy691F++PYPhThMg4ceeoiamhqcTierV69m+/btSbfdt28fN9xwAzU1NUiSxIMPPphy3z/4wQ+QJImvfe1ro7voKUYslex04RHCUCCYNOx59WWCvT3klpax+KJLJ3o5gj4IYThCZp25HICTe3YnfD33+usB6H7mmXi6+ezPgGSBhp1IbYeZPet2AHran+T65bqNxsN/OZZwf1+dXUq5w0Z9KMIvG/rXSrmXl+BaXgwqdD57lIryCt7//vcD8OKLLzL/wnxmLytEiaq88t/7h92pPBBJkrj9rNu5+/y7AfjVgV/xs10/G5V9T1eefPJJNmzYwL333svOnTtZvnw5a9eupaWlJeH2fr+fuXPn8oMf/ICystTF2W+//TY///nPOessYUgeCQYBXRiKVLJAMDlQolHe+T89WnjutR9FtlgmeEWCvghhOEJmL1sBwOn9e1Gi0UGvZ6+5Ajkri0h9PcG9uskunmJYcKX++N3/obj4SlyuWUSj3dy8XBeEL+5t5GS7b9D+XBaZDTV61PDB2mZ8Sv9O47wPzUVyWIic9uLf0cyFF15IdXU1kUiEzZs3c/mnFuPMstF+2suOzbWj849g8IlFn+CeC+4B4L/2/BdP7HtiVPc/nXjggQe4/fbbWbduHUuXLuXhhx/G7Xbz2GOJp3Kce+65/OhHP+Kmm25KOUfc6/XyyU9+kkceeYT8fOHVF0slu1w4PR4AQn5/qrcIBIIxpvbdnfS2t+LKyeWMS9dM9HIEAxDCcIQUz6rBlZ1DJBSk8eihQa/LLhdZF14IgO9vfTp3l9+s37/3v0galJd9VN8+8AqXLChC1eCpHacTHvOmskJqXHbaIlF+PSBqaMm2k3PFLAC6X6qFqMaHPvQhZFnm4MGD1Def5H03LwRg50t1dLeO7kXy4ws/ztdXfR2AH7/zY7bUbRnV/U8HwuEwO3bsYM2a+B9EWZZZs2YN27ZtG9G+77zzTq655pp++05FKBSip6en3206EWs+cbqwOV1APL0sEAgmhv2v/RmAJRdfhtVun+DVCAYihOEIkWSZaiOdXLdncJ0hQNZFFwHgfb2PMFz4AXDmQk89nHqLsrKPANDR+QafOFu/gD29sx5VHVyrZ5Ml7qguAeCx+jaUAfV8ngsrsBQ4Ub0RfG81Ulpayvnnnw/AK6+8wtyVRVQtzkeJqrz+vyPvUh7IujPWceOiG9HQ2PjXjRzuHGzBM5Npa2tDURRKS0v7PV9aWkpTU9Ow9/vb3/6WnTt3smnTprTfs2nTJnJzc2O36urpNc0mXmPoxO7SzytViRKNRCZyWQLBjCXo83Jsx1sALH3f+yd4NYJECGE4ClQu0uc5Np84mvD1rIsvBiCwezdKr25Qjc0JC67SHx95BZdrFrk5KwGVpfnbyXZaqe8K8OaJxJ5rHyvLJ9dqoTYQZkt7/yiPZJXJuVy/wPf+5TRqWOGSSy7B6XTS2trKnj17eN9NC5Flido97dQf7hzhv0B/JEniG+d9g/PLzycQDbBh6wa84dFpdhEk5tSpU3z1q1/l17/+Nc4MBs5v3LiR7u7u2O2U2T0/TQgH4z6GdiNiCPQbkScQCMaPw2++jhKJUFQ9m5KauRO9HEEChDAcBYpn1wDQVjfYsgbAXlWJvaYGFAX/W2/FX5hvpPuO6gbZZWXXAdDRtpkPnaVPO/n9jsTWMlkWC7eUFwDw6OnBxfTus0uw5Dv0qOHbTbhcLi42BOqrr75KTrGTpRfr4/beevb4qHcRW2UrP3zfDyl1l3Ky5yTf3fbdUd3/VKaoqAiLxUJzc3O/55ubm4dsLEnGjh07aGlp4eyzz8ZqtWK1WvnLX/7Cz372M6xWK4qSeOqNw+EgJyen3206EeljVyNbLFhtduP54EQuSyCYsRx+U8+cLbnkciRJmuDVCBIhhOEoUDSrBtDnsob8gxtGIB419PatM5ynz1um6T3obaaoSP+5p+ddPrIsC4A/HWgmmmRayWcr9S7L1zp7Y9NQTCSLTPalVQD4tjWiqRrnnXceWVlZdHd3s3fvXs65ugaLTabxWDd1+zoG7X+k5Dvz+fFlP8YiWXix9kWeP/78qB9jKmK321m1ahVbtsTrL1VVZcuWLVxg2BtlyhVXXMGePXvYvXt37HbOOefwyU9+kt27d2OZoV1/8cknerTQZtybkUSBQDB+RIJBTu/fA8C8VasneDWCZAhhOAq4PNkxj7RkUUP3eecCEHi3Tx2ipxjKV+iPj23B6SwnK2shoDLLs588t43uQISddV0J9znb5WB1bhYa8Ifmwdu4V5YiOS1E2wIEj3Rit9tZvVo/Gf/2t7/hzrWz7NJKgFHvUDZZXrycLyz/AgDff/P7NPmGX0M3ndiwYQOPPPIITzzxBAcOHOCOO+7A5/Oxbt06AG699VY2btwY2z4cDscEXzgcpr6+nt27d3P0qF6+kJ2dzZlnntnvlpWVRWFhIWeeeeaEfMbJQLiPXQ3EBaJoQBEIxp+6fe+hRKPkFJdQUFk10csRJEEIw1GiuHo2AG2nahO+7jIuzqHDR1BDofgLpm2NkU4uLNSNPrs6/8plC4sB2HKgf8qxLzeU6pYkv28eHPGTHRayVukNDr43GgDd9sRms9HS0sLRo0dZfsUsZItE49Fumk4MNtUeDW5fdjtnFZ1Fb6SX77/5fWF+Ddx4443cf//93HPPPaxYsYLdu3ezefPmWENKXV0djY2Nse0bGhpYuXIlK1eupLGxkfvvv5+VK1dy2223TdRHmBLEJ58YwtC4j4gaQ4Fg3DmxewcAc1asEmnkSYwQhqNE0Wx9qkjrydqEr1vLy7EUFkI0SujgwfgLc96n39fptYeFBfrP7R2vccVivfN4y8HEpscA15bkYZMk9nmDHPAOjoJ4LtDrCIOHO4l2hXC5XKxapQ8q3759O558BwvP1cXI7lfq0vy0mWGVrXznwu9gla1sPb2Vl06+NCbHmWqsX7+ekydPEgqFeOutt2LRXICtW7fy+OOPx36uqalB07RBt61btybd/9atW4eckDLdiQxIJdtFKlkgmBA0TaN29zsA1Kw4Z4JXI0iFEIajRLFRZ9haV5vwdUmScJ55BgCBPXvjL1ScDZIMPaehp4G8vFVYLG7C4VbOqerAKkscbfEmNLsGyLdZeX9hNgDPtw6O+FmLXNjn5IAG/t26wDznHP2kPHr0KF1dXay4Uvc9PL6rld6OsSnKn58/n9uW6dGtH27/Ib5I4s8jEIwWmqbFu5IHRAzDovlEIBhXupob6W5pRrZYmXWmmMo0mRHCcJQwhWFbXW3SVKnrzGUA8QkoAA4PlOiCkdPvIMsO8nJ14RYN7uLs2Xqq+G9HE9vWAKwtygXg5fbEqeCss/WIoH9nM5qmUVRUFItA7dy5k8JKD5UL89A0OPC3hvQ+8DC4fdntVGdX0xpo5ZH3Hhmz4wgEANFIODaG0kwlC5NrgWBiaDh0AICyeQv6WUcJJh9CGI4S+RVVyBYL4YAfb0diEReLGO7d0/+Far0xhdPbAcjJPRuA7u5dnD+3EIDtSfwMAa4szEEC3usN0BQabNzrWlYEVploS4BIve4naEYNd+3ahaqqLL1ETzkfeKMRNUkX9EixW+z847n/CMAv9v+Cup6xSV0LBNDfksbm1McImqnkiEglCwTjSsNhXRhWLFoywSsRDIUQhqOExWol2+hM7m5N3CxiNqCEjx1H9fVJpVaZwlCvv8iLCcOdrJ6jexW+daIjaSSy2G5jZY4bgD+1Dx5pJjutuJbq+/HvbgVg8eLFuFwuent7qa2tZd6KEpxZNrydIU6OgXWNyaVVl3JRxUVE1Ag/2/WzMTuOQGBGBa0OB7Ks2/XEUsmi+UQgGFcaD+u19RULFk/wSgRDIYThKJJTrKdse1sTN4tYi4uxlpSAphE83GdMnCkMG3aBEiEn5yxAIhg8zRllYayyRGN3kNOdyaMcVxbqxsQvtyVOJ7uW6R3Ogf3taJqG1Wpl6VJ9Yst7772HxSaz6ALdXPnQm40J9zEaSJLE11d9HQmJl2pfYm/b3qHfJBAMA1P89U1bieYTgWD8Cfn9tJ7SrdzKFwphONkRwnAUySnWu4i7kwhDAPs8fQRQ+ERt/MnC+eDKh2gQmvditWbj8SzSt/PvYVmVXkP4dm3ySJ4pDP/a6SWSYL6yc1E+WGWUjiCRRj1auWyZXvN44MABIpEIi8/XhWHte+2EAtF0PvKwWFSwiGvnXQvAgzsfHLPjCGY2ZirZFIMgagwFgomg6ehh0DRyikvx5BdM9HIEQyCE4SiSa0QMe5KkkgEcc0xheDz+pCRBmdGl1bxP31csnbyD82r0E2n7ieTCcKnHRYHNQkBV2d07OE0m2y04F+qNLIF9er3irFmzyMnJIRQKceTIEQorPeSXZ6FEVY7vak3nIw+bO1fciVW28lbjW7zT9M6YHkswMxnoYQh9fAxFV7JAMG7E6gtFtHBKIIThKJJWxHCuLgxDx0/0f6FET+vSop9AuTkr9X317OZcQximihjKksQFeR4A/tbZm3Ab1xl6I0twnz5bWZbl2FSM/fv3I0lSzNPwyNtjO6GkwlPBR+d/FICH3314TI8lmJlEBljVgEglCwQTQdMxvXSqfMGiCV6JIB2EMBxFTGGYKmJon1MDQPj48f4vlBidWkbEMDtb72D2eg9xVpWeJj7e5sMbSp7ivcgUhl3ehK+7lhSABJEmP9EuffrKkiX6cY8cOUI0GmWBIQxPH+zE3xNOuJ/R4rZlt+lRw6a32NG8Y0yPJZh5xOYkO52x52KzkkXziUAwbpj+viWz507sQgRpYZ3oBUwn4qnkVjRVRZIH626HETEMnzqFFokg2Wz6C6WGl6ERMXS75yJJdhTFS7atjbIcJ009QfY39HDenMQ1Ghfl60bX73T7CKkqjgHHl9027NXZhOt6CR3uxHpeGZWVlXg8HrxeL7W1tcyfP5/iWdm01vVSu6eNpRdVjPjfJRnlnnKum38dTx1+ikf3PMqq0lVjdizBzCOWSna5Y8/ZRY2hQDCuhPw+etv00qQiw+93sqBpGqrXS7S1FaW9HaW7G6WnF9XrRfX7UQMBtFAILRxCDYchEkWLRtEUBZQomqKCoqBpKigqaJr+WAM0rf8N0OhT/59sMuwIR8Y6Fi6g/NvfHtE+hDAcRTwFhUiyjKpE8XZ1kF1QNGgba2kpktuN5vcTPnUax1x9lB7FRojd2wT+DmR3AVlZ8/F69+P1HuDMygKaeoLsqe9OKgwXuh0U2ay0RaLs6vFzvhFB7ItzYT7hul6CRzrJOq8MWZZZtGgRO3bs4ODBg8yfP585y4torevlxO7WMRWGAOvOWMfTR57mr/V/5VDHIRYViFSDYHSINZ+IVLJAMGG01endyJ7CIpyewdek8ULp7SWwaxfBffsIHj5M+PgJIqdP97eOEwBCGI4qssVCdmExPa3N9LS0JBSGkizjqKkhuH8/4RPH48LQkQ15s6CrDlr2Q83FZHsW4/Xup9d7iGWVH+BPB5rZW5/YjgZ0K5gL8jz8X2sXb3X5EgpDx8J8+FMdwSOdaIqGZJFYvHhxTBheffXVzF1RzPb/O8GpA52Eg1HszrH7NZmVM4urZl/F5trNPLb3Mf7lff8yZscSzCzidjXxVLJoPhEIxhczjVxcPXvcjx2pr6f7j8/T++ctBN/bkzQaJ3s8WAsLseTlIefkYMn2ILlcyC43ssuJZLMj2W36vdUCFqt+L8tIFgvIFpD06zuSrDeUmj+D/jNS/4NKfX4e8FLS7dLAkpub0faJEMJwlMkpNoRhazOVi5cm3MY+Zw7B/fsJHT9O9hVXxF8oOcMQhgeg5mI8Hr2Dy+s9wLKqTwCwJ4UwBDgn183/tXaxszfxtyB7VTaSy4oWiBI+3Ytjdg5z5szBZrPh9Xppbm6mrKKMnGIXPa0BTu3vYN7ZJcP4l0ifdWeuY3PtZl6ufZmvr/o6ZVllY3o8wcwgLOxqBIIJp80QhkWz54zbMf07d9H+85/jfe21fmLQNnsWruXLcS5ajH3eXOyzZmErL0d2iRF9fRHNJ6NMrM6wLbndi92IEoYHdSb3b0CJC8ODnFmpfws41urFl6IBZVVOFgA7uv0JJ6VIsoRzQR4AoSOdAFitVubM0dd09OhRJEliznI92nnivbakxxotlhYu5ZzSc4hqUZ489OSYH08wM4gksqsxLgCqEiUaGTw+UiAQjC5tp2qB8YkYRhoaOP3lr3Dyllvw/uUvoGm4V6+m7NvfZv5ftjL/pZeo/OEPKfzc35F92WU45s4VojABQhiOMtlFpmVNis7k2TUARE6d6v+CaVnTqo8OMoVhIFBHgUuhNMeBpsH+xsFj70zO9LiwSRJtkSingom7ih3z8gAIHY9HH+fPnw/AsWPHAKg5U7e2qdvfgZbAMHu0+dTSTwHwu8O/IxAV0RzByIl3JQ/2MdRfF53JAsFYomlarMZwrBtPejZv5viHP0LvK6+AxULux25g7osvMPuJx8m/6UZspaVjevzphBCGo4wnXzeR9nd3Jd3GVlEO6N9u+lFotPJ36JFEu70Qu70E0PD5DrO0XLetOdiU2KcQwGmRWerRa6p29iS+8Dnm6NHHUF0vWlQFYN68eQDU1dURCoUon5eH1WEh0BOmrT6x/c1oclnVZVR6KukOdfP88efH/HiC6U/c4DpeYyhbLFjtDiAeURTMDB566CFqampwOp2sXr2a7du3J932sssuQ5KkQbdrrrlmHFc89eltbyXk9yFbLBRUVo3JMTRNo/Vn/0r9176O6vXiWrGCOU8/TcU//zOOOeOXvp5OCGE4yrhz8wDwd3Ul3cZWoXf6Rpqb9bZ3kwJDGHqbIKzXCHqyFgDg8x1jYaluR3OkObkwhHg6OZkwtBa7kD02iKqET+v7KiwsJD8/H1VVOXHiBBabTNUiXeTWGZNSxhKLbOHmxTcD8OShJxOmwQWCTIiGda/OvsIQ+nYmiwaUmcKTTz7Jhg0buPfee9m5cyfLly9n7dq1tLQkHkbw9NNP09jYGLvt3bsXi8XCxz/+8XFe+dSmo6EegLzScixW26jvX9M0mjdtou3f/x2Awts+x+xf/RLnooWjfqyZhBCGo4w7VxdTvhQRQ2txMVitoChE+/5hcuWDM09/3Fmr78+ti0V/4AQLYsIwdQTv7Bzdt21nT+IGFEmS4lHDE4PTyccN8+1ZS3VbnLp9ySeujCYfmfcR7LKdgx0Hea/tvXE5pmD6Eg3rNYRWm73f86ZQFA0oM4cHHniA22+/nXXr1rF06VIefvhh3G43jz32WMLtCwoKKCsri91eeeUV3G63EIYZ0t3cCEBe+djYnnU8+iidv/glSBKl99xNyd//PZJV9NSOFCEMR5ksM2LY3ZU06iVZLNjK9M7bQenkgv7pZLe7Rt+f/wQLS3X7mSMtqSOGZxsRwz3eANEk9YExYdinztBsQKmtrQVgljFCr+lYN+Fg8oaX0SLPmccH5nwAgCcPiiYUwchQInqNrcXWP1IRs6wRNYYzgnA4zI4dO1izZk3sOVmWWbNmDdu2bUtrH48++ig33XQTWVlZCV8PhUL09PT0uwmgs0kXhvll5aO+794/v0rL/T8GoHTjRgpuuWXUjzFTEcJwlHHn5QF6GisSSp6qspWbdYaN/V8oMGoiOvSondut/+z3n2BesS4M27xhOnzJx9XVuOxkWWRCqsbRQOI12A1hGD7Zg6bo4nH2bL1rrKWlBZ/PR26xi5wiJ6qq0XCkK+nxRpMbF90IwMsnX6Y7lNqaRyBIRdQQhgMjhsLkembR1taGoiiUDmg+KC0tpalp6Jnw27dvZ+/evdx2221Jt9m0aRO5ubmxW3V19YjXPR3oMoRhbunoCsNoWxuN3/oWAPm33ELBrZ8e1f3PdIQwHGVsDmesuD2tOsNkEcNOM2KoC8NAoBa3XaYqX7+opaozlCWJMzz6dvu9iYWhrdSN5LSghVUizXrKOSsri5ISvavajBpWGnWG9YeTf5bRZFnRMhbmLySkhHjhxAvjckzB9MS0o7HaBwhD4WUoyIBHH32UZcuWcd555yXdZuPGjXR3d8dupwY6TsxQupr061v+KAvDxnvuRensxLFoESXf+KdR3bdACMNRR5KkWANKqjpDW6UhDBsHCMP8/hFDp7MSSbKhqmGCwcZYA8rhltR1hksNYbi3N/HFT5Il7NX6vsJ1cZE5MJ1cudAQhoc6Ux5vtJAkiY8u+CgAvz/8e9GEIhg2iiEMB6aSbQ69xjBVRF8wfSgqKsJisdDc3N9CrLm5mbKy1Gb6Pp+P3/72t3zuc59LuZ3D4SAnJ6ffbaajqSrdzXpENq9s9GoMvX/9K94//xlsNip++EPkAV/8BCNnWMIwk7b/SCTCd7/7XebNm4fT6WT58uVs3rx52AueCsTrDJOLKWt5EsuaATWGkmTB5dJTvP7ACRaU6Onko0N0Jp9pCMN93uRRkbgwjNfD1NTUAHFhaHYmt53qJeQfH0PgD839EHbZzqHOQ+xv3z8uxxRMP5QkqWSrQ4/oR8PJyzEE0we73c6qVavYsmVL7DlVVdmyZQsXXHBByvf+7ne/IxQK8alPfWqslznt8HZ2EI2EkS0WcopHZ3qWFo3S/C/62NSCT31KdB+PERkLw0zb/u+66y5+/vOf86//+q/s37+fL37xi1x//fXs2rVrxIufrJh1hqm9DJOlko2IYfcpiOoXrqxYneHxWGfy4SE6k81U8l5vIGnUzT5L/1YbPhUXmWadYWtrKz6fj6w8B3mlbjSNcaszzHXkcsVsfVTgM0efGZdjCqYfZleyxT4wYmj4GIZC474mwcSwYcMGHnnkEZ544gkOHDjAHXfcgc/nY926dQDceuutbNy4cdD7Hn30Ua677joKCwvHe8lTHjONnFNcgmyxjMo+u595hvDRY1hycyn64hdGZZ+CwWQsDDNt+//lL3/JN7/5Ta6++mrmzp3LHXfcwdVXX82Pf/zjES9+shLzMuxO3jxhCsNoQ2N/4eYpBZsbNFUXh/RvQJlvRAyPt6UWhouznMhAeyRKczhxR7EZMYy2BlCNaKDb7aa4uBggVidTuVD/PONVZwhw3bzrAHix9kXCiojsCDJDVRVURf+9HxQxNFJPps+hYPpz4403cv/993PPPfewYsUKdu/ezebNm2MNKXV1dTQ29m8EPHToEK+//vqQaWRBYsyO5NFKI2uqSvt/PQpA4Re+gCU3d1T2KxhMRsJwOG3/oVAI5wCDWZfLxeuvv570OFO99T8rnRpDI5Ws+v2ofQWkJEF+jf64o38Dit9/gjmFul1Cc08IfxLBB+CyyMx36//ue5Okky1ZNqxFRiF+n6ih2VFnCsMKQxg2Hk3+eUab1eWrKXGX0B3q5i+n/zJuxxVMD5Q+c5AHC0P9vBCp5JnF+vXrOXnyJKFQiLfeeovVq1fHXtu6dSuPP/54v+0XLVqEpmlceeWV47zS6UGX6WE4So0n3q1/IVxbi5ydTd4nPjEq+xQkJiNhOJy2/7Vr1/LAAw9w5MgRVFXllVdeibnKJ2Oqt/67cvKA1DWGstOJxUhPDEon5xqjg3pO6/szagwDgZPkum3kufXU2Mn21D5sZxij8fanUWcYqhssDOvq6gAoN2Yrt57yEgkpjAcW2cK1c68F4Nmjz47LMQXTh2gfYTi4+USkkgWCsaa7aXSFYYeRlcy/8RNYPIn9JAWjw5h3Jf/0pz9lwYIFLF68GLvdzvr161m3bh2ynPzQU731PyuNGkMAa6lekBtta+v/Qk6lft+tjxNyuXShFgw2omkqs42o4cn2xJNNTBZl6cLwsC9596W9Sk9NR/rMQ541axYADQ0NRKNRsgucePIdaKpGc+34RW8/PP/DAPyt/m90BMdn+opgeqAY0UDZYhlU3yRSyQLB2NPTpvcd5JSMvPEkdPwE/nfeAYuFfNEINOZkJAyH0/ZfXFzMM888g8/n4+TJkxw8eBCPx8PcuXOTHmeqt/67+0w/SYW1qAiAaGtr/xdyDWHYowtDu70ESbKiaRFC4RZqCvWRd7VDRAwXmsLQn8Jou8roTO4jDAsKCnC73SiKEovsls/T6znGM508N3cuSwuXEtWivFT70rgdVzD1icasagZbWZg+o0IYCgRjR2+7HvDIKSwe8b66n9OzRp6LL45NDROMHRkJw5G0/TudTiorK4lGo/z+97/nIx/5yPBWPAVIp/kEwFqknzDR1gERw1wjdd6tp5Jl2YrDoYfjg4HT1KQZMTSF4RFfCDVJZ7KtPAskUHvDKD16lEWSpEHp5DIjndx0bHynkXxo7ocA+OPxP47rcQVTm7hVjW3QayKVLBCMLUo0Equxzy4sGtG+NFWl+7nnAMi9bvrqhslExtOmN2zYwGc+8xnOOecczjvvPB588MFBbf+VlZVs2rQJgLfeeov6+npWrFhBfX093/72t1FVlX/8x38c3U8yicjK1b3/Qn4f0XB40OQFE2uxKQwHRAxz+kcMAVzOSoLBUwSD9dQU6d+YattSRwxrnA7skkRAVTkdDDPL5Ri0jWy3YC12E23xE27w4sopAPQ6w0OHDlFfr6+hfL4eMWw63o2qasiylPLYo8UH53yQ+9+5n/da3+NUzymqc6ZWvalgYjAbSywJzr14Klk0nwgEY4G3owM0DYvNhitnZN3D/nfeIdrQiOzx4Ln88lFa4TDRNAj1QKATgt0Q6oWwT79Fg8YtBEpYv6kKqNH4vaYaNy3+GC3+HJpxj/6473HjPyRZm3FfOBcu+X8j+pgZC8Mbb7yR1tZW7rnnHpqamlixYsWgtv++9YPBYJC77rqL48eP4/F4uPrqq/nlL39JnlGHNx1xZGUhW6yoShR/Txc5RYlrLGKp5IE1hmYqufu0/gshSThdVdAFgeBpZhe+D4DaISKGVllintvBAV+Qw/5QQmEIYK/0EG3xEzndi2uxLgwrK/U1mMKwsNKDzWkhHFTobPRRWOkZ8t9hNChyFXF++fm80fAGz594ni8u/+K4HFcwtYmNw0sQMYwbXIuIoUAwFvS268GO7IIiJGlkQYSeF1/U97X2KuQBDidjgqpA22Fo2gtth3R3kK466GkAX4su+CYz1eePvzAEve1//fr1CV/bunVrv58vvfRS9u+fWdMrJEnC6fHg7+4i6PUmF4bFSYShGTGMBsHfAVmFOJ16p3IwcJqaWXoqubE7SDCi4LQlNw9dmOXUhaEvyJrCxLWatkoP7GrpV2dYYfgsdnd309vbS3Z2NiWzs6k/1EXziZ5xE4YAV8+5mjca3uDFEy/yhbO+MOI/NILpT7KpJwA2u0glCwRjiVlf6BmhMbimaXi36nZl2WNpG9RxHA6+AMf+DKfegnBqn2CsLnDmgiMb7Flg94DNCVYnWB0g28BiBYsdZCtIFpAtIMn6PZL+WJJ1izpJ1p8D/efYYwY835ck18GckftGDksYCobGkaULw5Av+S9Y0lSy1QFZxeBr1S1rsgpxOXWxGAw2kO+2keO00hOMUtfhj81PTsRCdxqdyYbIizTE1+pwOCguLqa1tZWGhgYWLVpEaU2uIQy7WXrx6M2+HIr3z3o/9m12jncf53DnYRYVLBq3YwumJlFDGKZuPpnk3/wFgimKKQyzR9h4Ejp8mGhjI5LTSdb554/G0uJEQ7DnKdjx33D67f6v2bKg7EwoXgyF8yF/th6w8ZRCVhHYXKO7lkmGEIZjhNOji61gKmGYLJUM+i+hr1W3rClfjtMQhoHgaSRJoqYoi/dOd3OizZdaGKbTmVyhRyCV7jCKN4zFo19MKysraW1tpb6+XheGc/SI43ha1gBk27O5pOoSttRt4cUTLwphKBgSxRyHJ1LJAsG4E0slj7DxxPvqVgCyzj9/9NLIqgK7fw2v3ge9hp+yZIGai2DhB6DmEig9w4jszUzG3MdwpuLMSl8Yan4/qm9AvWDM5Fqv8YulkoMNaJpKdYFuWXO6M7l5NfQRhr5g0pnJssOKpVDfLtIUb2gZWGdoCsOOBh/hYPKpK2PBB+Z8AIDNtZuTfg6BwCSaoivZbD4RqWSBYGwYrYih1yhN81x22QhXZNByEP7rCnjuy7oozK6ANd+GDQfgM/8HF9wJ5WfNaFEIQhiOGTFh6E0uDOWsLGS3LvCSdiYb85IdjlIkyYKmhQmHW6nK00PZ9UMIwxqXHRnwKiqtKUbo2cv0qGGkMS5Q+wpDTdPIynXoRtcatJ7sTbifseLSqktxWV3Ue+vZ175vXI8tmHrEhGGCrmRbHx9D8SVDIBh9ettMYTj8iKHS3U3g3XcB8Fx26cgX9e6T8PP3QcMuvT5w7X3w1d1w8dchu3TIt88khDAcIxyGMExVYwhgSdaAYkYMjeknfb0MA8HTVOXrwvB0Z2rLGocsU+XUL47HA8kjJLZyQxg2xYVhaWkpFouFYDBIR4c+eaS0ZmLSyS6ri8uqLgNg84nN43pswdQjnVSypqqoyvhGvgWCmcBopJL9O3eCpmGfM2dkptaaBq9ugj98HpQQzLsCvvSWHh20JnbqmOkIYThGxGoMU0QMIUUDyoDpJ0CszjAYqKfSEIb1XakjhgBzDZua4/4UwrBssDC0WCwxGyJzAkrJBNUZAqytWQvASydfEpEeQUqiKbqSzeYTEOlkgWC0iYRDBHr160N20fBTyf533gHAfc6qkS1o6w/gLz/QH1/y/+CTT0HO6Mxvnq4IYThGpFNjCCmmn2Qbv7i9TfF9OvRvTaFwM5V56dUYAsx1G8IwnYhhsw9NiYsu07YmJgxn6Y0u451KBrio8iLcVjdNvibebX133I8vmDooKUbiWaxWJEn/0yc6kwWC0cVr1BdaHY7YdXA4xIXhOcNfzNv/FReFazfBFfeALGTPUIh/oTEi3VRyLGI4MJXsMWoevC3xfTr050LBpljEsDsQoTcYSXmMmDBMETG05DuR7BaIakT7TFQpL9cFqikMiw1h2NsRJOhNfdzRxml1cln1ZQC8cvKVcT22YGoRrzEcnEqWJCnemSwihgLBqOLt1MuOsgsKh+05q/p8BPfp/sfDFoYnt8GL/6Q/vvwuuOBLw9vPDEQIwzEi/YihUWM4MJVsCsOITx+7AzjMiGGoGY/DSp5bv+gNlU6OpZJTRAwlWcJWpkch+6aTTWHY0NCApmk43DZyi3VR2lI3/unkq2quAnRhKNLJgmTERuIliBhC37F4QhgKBKOJ35iR7DZGww6HwLvvQjSKtaIcm9EEmdkOuuCpdfoYujOuh/f9/bDXMhMRwnCMcKYbMUzmZejw6G7qEIsamsIwGNLTy2YDylCdyWbEsDYQQk0hpmLp5D6dySUlJciyTDAYpKurC4Di2UY6uW4C0skVejq50dfI3ra943780eShhx6ipqYGp9PJ6tWr2b59e9Jt9+3bxw033EBNTQ2SJPHggw8O2mbTpk2ce+65+pSakhKuu+46Dh06NIafYPKixEbiJRaGNiNiGBHCUCAYVXxdnQBk5eYNex/+d3YAI4gWvnyXbkdTMBc+8lCCqSGCVAhhOEY40mw+sRTo36qUzs7BL3qMUXpGnWEslWwIw8o8szM5tTCsctixSRJBVaMhlDz9G2tAaY6nkq1WKyUl+joGppMnos7QaXVyaZVuXfDyyZfH/fijxZNPPsmGDRu499572blzJ8uXL2ft2rW0tLQk3N7v9zN37lx+8IMfUJakQ+8vf/kLd955J2+++SavvPIKkUiEq666Ct9Aj8wZQCofQ+gz/USkkgWCUSUWMcwbQcRw7x4AXMuXZ/7mE3+FXb/UH3/kIX1knSAjhDAcI/pOPkmV8rTmpxKGhgDwNgPgcOo/h8OtaJpCVb6e+h0qlWyVJWa79MjJiRR1htYSI5Xc3N8CZ2CdodmA0jIBwhDgyhp9ZuZUTic/8MAD3H777axbt46lS5fy8MMP43a7eeyxxxJuf+655/KjH/2Im266CYcjscXC5s2b+exnP8sZZ5zB8uXLefzxx6mrq2PHjh1j+VEmJYqZSk7gYwh9U8mi+UQgGE1GGjHUNC1WX+g644zM3qyqerQQ4Jy/g9kXDmsNMx0xEm+MMFPJmqoSDgRwGEbWA7GkFIZGxNAQhnZbESCjaVHC4fZYxHCoVDLodYZH/SGOBUJcQuIRerZSt7GWIGpYQbbr7u/l5eXs2rWLpiY9Utm3ASXgDePyJL74jhUXV14cM7ve37GfMwoz/OMxwYTDYXbs2MHGjRtjz8myzJo1a9i2bduoHae7uxuAgoKCpNuEQiFCfaJmPT3jXzc6FkRjqeTEEUORShYIxoaRRgyjLS0o7e1gseBYvDizN+9/Bhp362VYl31zWMcfDqoaIRxpJxLuIBLtJhrtQYl6iSo+VCWAogRR1ZB+08JoahRVi6BpCpoWNe4VQEPTVEDV7zVNfw4NNBWMn+Joxjbx5z2eRSxe9N0RfR4hDMcIq92BxWpFiUYJ+bxDCkPV70cNhZD7RoOyjYihkUrWTa5LCIWaCIWaqMrXheNQJtcAc1zxOsNkWDx25Cwbqi9CtMWPvUoXgGbq0hSGDreNnGIXPa0B2k55qV6SXHiMBS6ri4srL+aVk6/wSu0rU04YtrW1oShKzCPSpLS0lIMHD47KMVRV5Wtf+xoXXXQRZ555ZtLtNm3axHe+851ROeZkwkwlJ28+EalkgWAsiEUM8/KG9f7gPn2ylWPu3MzmI6sK/Pmf9ccXfgU8IxvHNxBN0wgGT9HTuxef9zA+/3ECgTqCwQYikfZRPdbIGHkWTQjDMUKSJBxZHvzdXQR9XnKKSxJuJ2dng9UK0ShKVxdyX7GQxLLGFIYVebMBqO8KDrmeWUYquS6QOnVmK3UTOt5NpDkuDE0B09vbi8/nIysri+Jqz4QJQ4CrZl+lC8OTr/DVs786bFuE6cqdd97J3r17ef3111Nut3HjRjZs2BD7uaenh+rq6rFe3pgTaz5Jmko2x+KJVLJAMJr4jIhh1jC7koN7dWHozDSNfHgzdBzTx92NkjVNONxBW9ufae/4C52dbxKJdCTdVpIs2Gz5WK152KzZWKweLJYsLBYXFosLWXboN8mOJFuRJRuSbENCRpIMb1VJNn6WAcn4WTIeS8ZjYj/HHsceSdhseSP+3EIYjiFOUximaECRJAlLfh5KaxtKZye2hMIwbnJtNqAEQ81UGF3Jbd4Q4aiK3Zq8ZHS2ETE8GUwdIbGawrAlHoV0OBwUFBTQ0dFBU1MT8+bNo6gqm2M7W2k7PTF1hpdUXYJdtlPXW8fhzsMsKlg0IesYDkVFRVgsFpqbm/s939zcnLSxJBPWr1/PH//4R1577TWqqqpSbutwOJLWLE5lTME3ZCpZRAwFglFD0zT8hnuFe4QRw4yF4bZ/1+9XrQNH4nKpdNA0jfaOv1Bf/z+0t79qpHh1JMmOx7OIbM8S3Flzcblm4XJW4XCUYrMVxIzzpzpCGI4hZmfykJY1efkxYdiP7EQRQ9PLsIkqtw27VSYcVWnuCVJdkDhdDTDbmJd8MhBG07SkETazzjA6oAGlrKysvzCs1j9b66nUn22syLJlcVHlRbx66lX+VPenKSUM7XY7q1atYsuWLVx33XWAnvrdsmUL69evH/Z+NU3jy1/+Mn/4wx/YunUrc+bMGaUVTz2UIVPJwsdQIBhtgj5vbP74cH0MA/uHIQwbdsPJ10G2wnmfH9ZxNU2jvX0rx47fj9cbL+nxeJZSXLSGgoKLyMlZhixPvy/SAxHCcAxJ1+TarDOMdgwIU5sRw96+EcO4MJQkifJcJyfb/TQNIQyrDWHoVVQ6IgqF9sT/9baS+Gi8vpSVlbF///5YlKu4Wv9G1tXkIxpWsBqNKuPJlbOv1IXhyT9x54o7x/34I2HDhg185jOf4ZxzzuG8887jwQcfxOfzsW7dOgBuvfVWKisr2bRpE6A3rOzfvz/2uL6+nt27d+PxeJg/fz6gp49/85vf8Oyzz5KdnR2rCc3NzcXlck3Ap5w4okP4GMZTyUIYCgSjhd+oL3RkZSWN1qci2taG0toGkoRzcQZf9nf+Qr9f+hHIzdwQOxhq4uDBu2hvfxUAiyWLiopPUFlxE1lZ8zPe31RHCMMxJFNhqHR29X/BtKvxt4MSAYut31g8gLIcXRg2dqeuM3RaZModNhpDEU4GQ0mFoTXWmRxCDSnIDl3wDWxAcefacWXbCPRGaK/3UTonJ+Xxx4JLqy/FKls52nWU493HmZs7d9zXMFxuvPFGWltbueeee2hqamLFihVs3rw5Vs9ZV1eH3GemZ0NDAytXroz9fP/993P//fdz6aWXsnXrVgD+4z/+A4DLLrus37H++7//m89+9rNj+nkmG7GIYYKReCBSyQLBWOAz0sjDrS8MHT0GgK26GjlJw+YgoiHY+3v98cpPZ3zMtvat7Nv3daLRHiTJTnX1Z6iZfQc2W27G+5ouCGE4hqQ7L9mSnwcksKxxF4JkAU0BXyvkVMSFYViP3JXn6l1bTd1DW9bMdtppDEWoC4Q5Oyex6acly4bssaF6I0RbBzegtLa2EolEsNlsFFVnc2p/B22neydEGObYc1hdvpq/1f+NP538E58/a3gphIli/fr1SVPHptgzqampGdKzcap6Oo4F0fBQEUPhYygQjDa+bv0aNtz6wtCxowA45s1L/02HX4JgF2SXw5z3ZXS8ulP/zZEj3wc0srOXsXTpj/BkLchoH9OR6VEpOUlxpjv9JJmXoSwP8jJ02PWfw2F9hF5Zrp4iHCpiCPEGlFSWNQBWYxZytDUuNnNycnC5XGiaRqsx17l4gusMAa6cpZtd/+nknyZsDYLJR9qTT0QqWSAYNWKNJ8OMGIaP6RFDx/wMhOF7T+r3Z30C5PRLmmprH+bIkX8GNCoqbuKcVf8rRKGBEIZjSLqp5Nj0k65EJtdmnaFhcm3XvZmi0V4UJdgnYpiOMDQaUIJDWNaYE1D6dCZLkhSLGppj2wqr9M/XfnrihOHlsy5HlmQOdBzgVO+pCVuHYHJh2tUkm3wiUskCwejj7x6Zh6GZSnbMT7OuL9QLR4zRqGfdmPZxTp/+NceO/wiAOXO+xuJF/4wsj++ghsmMEIZjiN1lCKxg6jRvrPkk0fSTrCL93q9HCK3W7FhXVDjcSpkhDNOKGPbpTE6FtdjoTG7p35lsCkOzAaWoUk8zt9d70dSJSWMWOAs4p1QftL7l5JYJWYNg8qHEIoai+UQgGC9GXGNoRAzt89IUhke3gBKGgnlQsjStt7R3vM7hI7qp/5w5X2XunC8LH9wBCGE4htiNTtBwYAhhmJek+QQgy3Bv9+nCUJKkWNQwHG7NMGJoeBkOkUqORQxb+697oDDMK3UhWyUiIYWe9qGPP1asmb0GgFfqXpmwNQgmD5qqokR1ywxLslSyQwhDgWC0MSOG7mHMSY52duqj8ADH3DSttg5v1u8XfbCP4XNyQqFW9u37OpqmUFZ2PXNqvpzxOmcCQhiOIWbEMBRIPbIu5bxkd6F+72uN79cQhqE+EcOW3iBRRU15nFlGxLAhFCGsJt82VmPYHkBT4pHAkhK9vtEUhrJFpqBcb2Jpr5+4dPIVs64A4L3W92jyNQ2xtWC6E41GYo+TTT6x2UUqWSAYbQK9+qx1V07mHb1mfaGtsjK9jmQlqjeegC4Mh0DTNA4c/CcikQ48niUsWfx9ESlMghCGY4jdqQusyBARQ2ufruRBnaWxVHJ8FqPDrj8XDrVRlOXAKkuoGrR6U1/kiu1WnLKEBjSGIkm3s+Q6kGwyKBrRjvjaTWHo8/nwGg01RUadYdsE1hmWuEtYUbwCgC11Ip0801HCfYSh6EoWCMaNmDDMztylwqwvtKfbeHJ6OwQ6wJkH1ecPuXlT09O0t/8FWbZzxtIfzwij6uEihOEYYndnFjHUwmE0/4Bt3YYwNFLJAHZHPJUsyxKlOenVGUqSRKVDvyCeStGAIskS1hKzzjAuDO12OwUF+lzkWANKpdGAMoERQ9DNrgFeOSnSyTMdsyNZkmVkS+IuRZFKFghGn0CvPiLVlZ35SLrQcaPxZG6awvCI8bd+wVVgSe28F416OXrMaDap+Soez9SZlDURCGE4hjiMVHJ4CGEouVxI5oVqYJ1hrMYwcSoZ4l6GjV1D1/mZE1BSCUOIp5MjrakbUCZDZzLEheHO5p20BdqG2FownRmq8QREKlkgGG2UaDR2rRtOxDBysg4Ae01Nem+ofV2/n3vZ0Jue/A/C4VZcrtnMmrUu47XNNIQwHENsRvOJEomgRJOnbiVJ6lNnOGAsXoJUst1MJRtehqWGMGzuGVoYVhnC8PRQljVpdybrwrC7LUA4GB3y+GNFuaecZUXL0NBEd/IMxzS3TmZVA327kkUqWSAYDYJePVqIJOHISjxAIRXhU7rdmL26auiNQ15o2Kk/rrk49abhNk6dehyABfO/KVLIaSCE4Rhi1hhCOp3JeQAoXd39X4g1n7SBUX/oMLuSQ3o6tyRb/0Vv6R06+pFpxDDa1n/dZp2hmUp2Zdtx59hBg46G/vOVxxuRThbA0ObWIGoMBYLRxqwvdHqykTMwmgbQFIWIIQxts2YN/YZTb4IahbxZkD879aZ1j6GqQXJyllNUdEVG65qpCGE4hlis1lg6a0hhmKOH3pWeAcLQTCVHAxDWhdfAVLJZY9iSVsRQv1ieDiaPYAJYi8xUcqBfQ0xfYaganc2FlRPfmQxx25q3m9+mPdA+xNaC6Uo6qeS4MAyJUYICwSgQazzxZF5fGG1uRotEwGrFVlY29BtO/FW/r0k9Ai8S6eJ0/a/0TWvuFF3IaSKE4RhjNqAMVWdoydWFodrTM2AHWWDVhZ9pch33MWxD07SxiRgawlALRFF9cRFZUFCA1WolGo3SadjrFBjp5ImOGFZnV7OkYAmqporu5BlMLJWcRsQQ4lNSBNOXhx56iJqaGpxOJ6tXr2b79u0pt+/q6uLOO++kvLwch8PBwoULeeGFF8ZptVOToNF44hxG40m4zogWVlYgWVM3kgDx+sIh0sj1DU+iKD48nsUUFb4/43XNVIQwHGNMk+uhOpNlM2LYPSBiKEl9OpP1KJhZY6hpEaLR7ljEMJMaw8ZQmGiKaSWy3YIlz6jD6pNOlmWZ4mJdmMY6kyuMBpSGiY0YAqytWQvAyydfnuCVCCYKs57XYk1PGIp08vTmySefZMOGDdx7773s3LmT5cuXs3bt2tjfr4GEw2GuvPJKamtreeqppzh06BCPPPIIlZWV47zyqUXAO3yrmvApo/GkOo00ctgPDbv0xymEoaapNNT/FoDqqs+KaGEGCGE4xtidxhSRoVLJhlO80t0z+EWzAcXoTLZYHFituoFoKNxKaY4u4NIRhqUOGzZJIqpBU3iIdLJZZ9iaus4wnkr2TXha7qqaqwB4u+ltOoIdQ2wtmI7E5iTbkkceZIsVSdL//AnLmunNAw88wO233866detYunQpDz/8MG63m8ceeyzh9o899hgdHR0888wzXHTRRdTU1HDppZeyfPnycV751CLQY6aSh9GRbEQM7bOqh9648V3QFMguh7zk23d0vkEgWIfF4qG09JqM1zSTEcJwjLG704sYJq0xhEHzkqFPOjnUSnG2HjHsCUYJRpTUx5EkKhxmnWF66eRIkgYUszO5oDwLSYKgN4K/Z2KjL33TyX86+acJXYtgYohFDFOkkiVJitcZilTytCUcDrNjxw7WrFkTe06WZdasWcO2bdsSvue5557jggsu4M4776S0tJQzzzyT++67D0VJ/rc1FArR09PT7zbTCBhdya6c4UQMjVRyOhHD+h36feWq1JvV/waA8rLrsVjSmKQiiCGE4RhjdiYP2XySrMYQEptc2/Vu5XC4lRynFadN/69s6Rk6+lGVZp1hzLJmiIih1W4h1zDE7qif2DpD6JNOrhXp5JlILGKYIpUM/RtQBNOTtrY2FEWJ2WyZlJaW0tSUeHzm8ePHeeqpp1AUhRdeeIG7776bH//4x/zzP/9z0uNs2rSJ3Nzc2K26Oo3I1zQj2KcrOVMidUYqOZ2IYUwYnp18f5Ee2tr+DEBF5U0Zr2emI4ThGGNP0+Q6XmM4dCoZ+ngZRjqQpPj0k5be9E2uh4wYxlLJib0M29vbiUZ178LCCiOdPInqDN9ufluYXc9AFON30jJEEXsiL0M1GOT4hz9C3d/93YSXRQgmBlVVKSkp4T//8z9ZtWoVN954I9/61rd4+OGHk75n48aNdHd3x26njAjYTGK44/A0TesTMcxEGCaPGLa2vYymRcjKWkC2Z3FG6xEIYTjmONLtSjaGjg9qPoEkJtdmxFB/zuxMbk4jYlhpWNbUD2VZYwrDjiCaEr9IZmdn43Q60TSN1lZdrBZMktF4AFXZVSwrWoaqqSJqOAOJ1xgOFTHUX+8bMQzs3k3o8GF8b2wjdPDg2C1SMC4UFRVhsVhiZS8mzc3NlCWxRSkvL2fhwoVY+oxTXLJkCU1NTYSTNCo5HA5ycnL63WYacWGYWcRQ7e5GNTqa7UMJQ18bdJ3UH1esTLpZS4veQV5SImoLh4MQhmOMLd1Ucp4hDNNNJdt0YRgxhWEGncmVRsSwPpQ6YmjJcSDZZFA0op3x/UqSFEsnm8LQbECZaMsakw/UfACAl2pfmuCVCMabdLqSIe5z2DdiGNi9O/a49xVRozrVsdvtrFq1ii1b4vZVqqqyZcsWLrjggoTvueiiizh69GjMpxXg8OHDlJeXY08xTWemY04+ybT5JNLQAICloADZ5Uq9cb0x7aRoIThzE+8v0klHx98AKC25OqO1CHSGJQwz9YR68MEHWbRoES6Xi+rqar7+9a8TDA4tYKYD6c5LNptP1FQRw36pZCNiGNE7bzPxMqx0GMJwiIihJEtYC9ObgGJa1nQ0+NBS2OCMF1fVXIWExM6WnTT5EtcSCaYn8VTyUBHDwankwK7dsce9fxLCcDqwYcMGHnnkEZ544gkOHDjAHXfcgc/nY906fWburbfeysaNG2Pb33HHHXR0dPDVr36Vw4cP8/zzz3Pfffdx5513TtRHmBIEeofXfBIxaj1t5eVDb2yOwatIXl/Y2roFTYvi8SwmK2teRmsR6GQsDDP1hPrNb37DN77xDe69914OHDjAo48+ypNPPsk3v/nNES9+KmD6GA4VMTRrDFW/X3eA74s5Fi8Qt18ZmErOZPpJLJUcCg9ZR5XuaLycYhcWq0w0otLTnvqzjgdlWWWcXar/8XjxxIsTvBrBeJKOXQ0Mbj7RNK1fxDB0+DBhoyheMHW58cYbuf/++7nnnntYsWIFu3fvZvPmzbFa6bq6OhobG2PbV1dX89JLL/H2229z1lln8ZWvfIWvfvWrfOMb35iojzDpUVWFoE8vI8q0+SRi/NvbKtIQhs179fvys5Ju0t6+FYDioiszWocgTsbCMFNPqDfeeIOLLrqIW265hZqaGq666ipuvvnmIaOM04V0m08sfb5lDUonuwr0e39n7CmbTX8uEhOG6UcMK4yIoU9R6YmmtrcxLWuGEoayLJFfrn/W9knQmQxw9Rw9jSCE4cwiHbsaYJBdTfhELUp3N5LDgfuccwDwbt06dgsVjBvr16/n5MmThEIh3nrrLVavXh17bevWrTz++OP9tr/gggt48803CQaDHDt2jG9+85v9ag4F/Ql6vWAEGTIVhlFDGFrL0hGG+/T70jMSvqyqUTo69akohYWXZrQOQZw0Zs/EMT2h+obdh/KEuvDCC/nVr37F9u3bOe+88zh+/DgvvPACn/70p5MeJxQKEQrFBc5U9oSKjcQLpo6iSRYLcnY2am8vSncP1sLC+ItuQxiGeyEaBqu9TyrZbD5Jv8bQbZEpsFnoiCjUhyLkpoisJBOG5vSTrq4uQqEQDoeDwgoPbae8dDT4mLuieMh1jDVXzb6KTW9t4kDHAY53HWdu3tyJXpJgHIimbVfTP5VsRgudZ56Ja+VK/O+8Q/jU6bFbqEAwTTAbTxzurCHdAAYSaUwzlRz2QccJ/XFJYmHY3bOLaLQXmy2fnJzkUcXxJKqoeENRfGGFQDhKIKwSiiqEoyphRSWiaEQVlaiqoagaUVVDVTVUTUPVQNU0tH6P9XsT86GG/qA0x8lHVoxsSk9G/4OpPKEOJungu+WWW2hra+Piiy9G0zSi0Shf/OIXU6aSN23axHe+851MljZpifkY+lNHDEGPGqq9vagDTa6deSDJoKl6Ojm7LGZXoyg+FCWQ0fQT0OsMOyIBTgfDLPUkL/iNCcMBXoZZWVl4PB68Xi+tra1UVVVRMIksawDynHlcWHkhr51+jedPPM+XV355opckGAfUtGsM+6eSA3veA8C1YjlWIyIeTVIiIxAI4oxkTnIslVyeuEs8RstBQIOsEvAkDjy0t/8FgIKCi5GksY/w9gQjHGn2cqLNx6kOPw1dAVp6Q7R5Q3T6wnQFIvjDqbNyo805s/PHVxgOh61bt3Lffffx7//+76xevZqjR4/y1a9+le9973vcfffdCd+zceNGNmzYEPu5p6dnyhqGmqnk0BA1hgBybg7U1w9OJcuyLg4DHeDXhaHF4kGS7GhamHC4g2KPfiHrCUYJRRUc1tQnRaXTxh5vgIbQEJY1hjBUukOoYQXZHt9vcXExXq+XlpaWfsJwsnQmA1wz5xpdGB5/nvUr1ot5mTOAzGsM9YhhtEm3NLHPmo0lP09/boDNiUAgGEysvjBrGMKwyRSGQ0QMzfrCJGlkgI721wAoLBibNHJdu5/XjrSy/UQHu091UdcxdMDHxG6RcdktuGwWHDYZu0XGbpWxWWRsFgmrLGORpdhNlnQHEIskIUkgG/eSJCGB/pj4zwBIMKcwa8SfMyNhOBxPqLvvvptPf/rT3HbbbQAsW7YMn8/H5z//eb71rW8hy4PLHB0OBw6HI5OlTVpizSdDpJKhr5dhIsuaAl0YGg0okiRhtxcQCjURibSTk12B3SITVlTavGEq81K3/VfEOpNTW9bIbiuSy4oWiBJtD2Ivj//SlZSUcOLEiT4zk/XO5K4mP0pUxWKdeDeky2ddTpYti3pvPbtadsUaUgTTl3TtaiwD7GqUDv3cshTkYzNKJUTEUCAYmpBfDwY4sjITJZqiEG02JmgNJQxb9uv3SYRhJNJFr1ffpqDg4ozWkYrmniBP7TjNs7vrOdw8OBtWluNkbnEWswvdVOa5KMlxUpztoMBtJ89tI8dpw+O0YrNM/PUwXTIShn09oa677jog7gm1fv36hO/x+/2DxJ9ZxDsTJgvEmk/SSSXnpjC5jjWg9O9MDoWaCIfbkSSJ4mwH9V0BWntDQwrDuJfhEJY1koStyEX4VC/RNv8gYQjxBhRPvgO700I4qNDV7I8JxYnEZXWxZtYanj32LM8de04IwxlA+jWG/VPJUUMYWgsLsRrlMpHWVjRVRUrwBVYgEOiEYhHDzP7mR1tbQVHAasVaVJR64yEaT7q6dwAabvdcHI6R17gfb/Xysy1H+ON7jUQNCzaLLLFqdj4XzSti1ex8llXmkutO/XdmKpJxKnnDhg185jOf4ZxzzuG8887jwQcfHOQJVVlZyaZNmwC49tpreeCBB1i5cmUslXz33Xdz7bXXzoguL3PyiapEiUYiWFN0SpqdycrAGkNIbFlj69+AUtRHGA5FpUNfR8MQEUPQ08m6MEzdmSxJEgUVWTQd76GjwTcphCHAtfOu5dljz/Jy7ctsXL0Rh2V6RKMFiYnVGA7Zldy/+SQWMczPj1+kIhGUri6sBQVjtFqBYOpjppIzjRhGGow0ckkJUio9oGlDppK7ut4GIC/3nIzWMBBvKMr9Lx3il2+eRDEE4bk1+Xx8VTVrzyiblkJwIBkLwxtvvJHW1lbuuecempqaWLFixSBPqL4RwrvuugtJkrjrrruor6+nuLiYa6+9lu9///uj9ykmMTanM/Y4HPBjtSV2awew5Jom10lSydBvLJ7N3n/6SbFHv9ClIwyrzHnJQ0w/geQNKGZnstfrxe/343a7Kajw0HS8h/YGLwsoHbSvieDcsnMpyyqjydfEq3Wv8oE5H5joJQnGkLhdTfo1hmo4jOrT02HWggIkmw1LYSFKezvR5mYhDAWCFISMc8fhzkwYRo36QutQHoa+Ngh0ApI+9SQBMWGYd15Ga+jLO7UdfOV/dtHQrTdxXrG4hK+uWcBZVXnD3udUZFjNJ+vXr0+aOt46wPfLarVy7733cu+99w7nUFMeWbZgcziJhIKE/X7cOcmFoZyTYiyeK1+/9yc3uS7OTl8YVhgRw6ZQBEXTsKRoyogJw/b+Hc9Op5Pc3Fy6u7tpbW1l9uzZk7IBRZZkPjzvw/zne//JM0efEcJwmpNuKtkW8zEMx6KFWK0xs3lraYkuDFtaYMmSsVuwQDDFCQ4zlRyzqhnKw7D9iH6fVw22wWVSiuKnt1ePKOblnZvRGkx+ua2W7/zffqKqxqwCN/ddv4yLFwyR3p6miMKZccCMGg7VgJKyxtCMGAbiJtcDU8kxYegd2rKm1GHDIkFUg9ZwNOW2cS/DwXWSg0fjTT5hCHDdvOsAeKPhDTEib5qjDMPHMNqun0PW/PxY57qtWP/djogGFIEgJbGIYcbCMM2O5DZDGBYuSPhyd/cuNC2Kw1GO05mZVYumaTzwymHufnYfUVXj2uUVvPjVS2asKAQhDMcF08swEkodyTNTyQlrDBM0n9js+nPDiRhaJIkye3p1htYiXdiqviiqv3+zykBhWGDMTO5uCxAZZ/+mVFTnVLOqdBUaGs8de26ilyMYQ9KvMYw3nygd+hcuS5+UcczLsFkIQ4EgFcPtSjbtoKylQ5QdmRHDomTCUJ+hnJd3TsaWZA+9epSfbdH3v+HKhfzsphVkOcbcyW9SI4ThOGAzrHciQ0QMZWOUkNqbwCA6RfNJJKI/l0mNIUC5w5yZnLozWXZYkbONi+iAdPJAYejOsePKtoEGnY2TK2p4/fzrAXj6yNOomjrBqxGMFVGjxtA6xASGvjWGSmfcqib2unGxEpY1AkFqhptKjra2AmAtHqKLuO2ofl84P+HLPb17AMjJWZ7R8X/3zinuf/kwAHdds4SvXLFAeN0ihOG4YItFDFOneC05pjDsHfxiguaTpDWG3vSEYYXRgNKYSQNKis5k035oMtYZAlxVcxXZtmzqvfW81fjWRC9HMEaYqWQ5Ax/DaLthVVMQH0VpLTG8DIXJtUCQkmE3n6QrDIeIGPb0GMIwe1nax95b3823/qDXJX7psnncdokYmWoihOE4YNYYRoKphaEZMVQSCcNEqWSb/lwk0ommaZT0SSWn4xFZkWbEEMBmCMPIAGFYVFSEJEkEAgG8Xv1bo5lOnmzC0GV1cc3cawB46vBTE7wawVgxvFSyGTEcnEqOtIqIoUCQipiPoSf9iKGmaXFhaJxrCVEi0FmrP04QMQyFmgmHWwCZ7OylaR3bG4qy/jc7CSsqa5aU8g9rF6W97smCpmkEFZXuSJTWcIT6YJjaQIjTaVjQDcXMTqSPEzaHIQzTjRh6vYNNdc2IYbALVBVkGbtRY6iqIRTFT5FHP04wog/tznamvjBWxLwMhxaGySKGNpuNgoIC2tvbaWlpITs7O9aAMllmJvflYws/xm8P/ZY/1/2ZtkAbRa6ZW2A8XYmlktP1MYyEiXaaEcN4KtlmppJFjaFAkBRNVQkF9MbETCKGak8PmuEhai1O8Xe48ySoUbC5Ibti0Ms9PfqMc0/WAiwWd1rHvv+lQ9S2+6nMc3H/x8+a8PSxqmk0hSKcDoapD0VoCkVoDUdpj0Tpikbpiij0RhV6FRWfohBQVAJq4uDP+blZPHN24shqughhOA7YY13JQ0QMzQHkmobq82HpO5DcjBhqqi4O3QXIsgtZdqCqISKRTlyuKrIdVnpDUVp7Q2kIw0xSyfpnGCgMQU8nt7e309zczLx58yZtxBBgUcEizio+i/da3+P3h3/PF5Z/YaKXJBhl4qnkDGoM282IYZ9UspHeUtrb0aJRpCH2JxDMREIBv25ATWZdyWa0UM7NRU41AtdMIxfOgwQTiMz6wuyc9NLI757q4olttQD8yw1nkee2p73m0SCkquzpDbCjx8ee3gAHfUGO+YNJhV662CUJmyzhGIUpTeIv3TiQdirZ4UCy29HCYdTe3v7C0GoHezaEe3XLGneBPq7OVkAo1Egk0oHLVUVxtiMmDOcWpz5JKwzh2JBGKrlvxFDTtH7fsEpLSzlw4ECfzmT9W6O3M0TIH8ExyZzib1p0E++1vsfvDv+Ozy37HFZZnAbTifTtavQLghIOo/gGN5+Y9lGgl3dY8/MRCAT9MdPIVrtjyCh9X+L1hUNkbYawqumN1ReeNeQxNU3jnmf3omlw3YqKcbOkaQ5FeKGtm5fbunmzy0dAHdz8aJGg0mGn0mmj3GGn2GalyG4l32Ylx2oh12rBY5Fx97k5ZRmHLGGTpFGNeoor4jiQbvMJ6FFDpb0dpbeXQaeYO18Xhv52/dsTYDeEYdjoTC7KdnC8zUdLWibX+oWxKRQhqmpY5RQm14UukEALKajeCJbs+LesgZ3JDpcVT74Db2eIjgYf5fPzhlzLeLK2Zi33v3M/zf5mXj31KlfOvnKilyQYRcwaw6EuUra+Poad8aknJpLNhpyVherzoXZ3gxCGAsEggr5hWtUY14shG086T+j3xjWvL5qm0WMYW2fnnDnkMV/a18y7p7tx2y1865r06hGHi6pp/Km9h8fr29ja0UtfKVhgs3BOThYrctwszXKxMMtJtdOOLcU1eDwRwnAcSNeuBsBiCMOEncmuAuiqS+hlGAkbljUZeBkW261YDZPrlnAk1qWcCMkqY8lzoHSGiLYFkgpDVVWRZZmCCg/ezhDtk1AY2i12blhwA4/seYRfH/i1EIbTCE3TYjWGaTefRMJEEzSfAMi5Oag+X2LTeYFAEIsYjllHstl4kjd70EvhcKth1ybjyUrdQKKoGj9++RAAn7t4TuxaOdqomsZzLV3cX9vEUX/8Orwqx80Hi3K5ojCHxVnOCa9rTIXoSh4HYhHDIVLJEK8zVHpSWNb0mX5is+lRjEhEf870MmxLw7LGIkmUOYaXTu5LQUEBVquVaDRKZ6e+jsJKw7KmfvI1oADcuOhGrJKVHc072Ne+b6KXIxglVEWJ1TsNVWNo2tUARH2DI4YAltw8IMmYSoFAELOqGTMPw86T+n1+zaCXvF5d6LndNVgszpS7eXFvI0davOQ4rWNmTbO318+Hdh7hi/tPctQfItdq4UvVJbyxegnPr1rI+tmlLPG4JrUoBCEMxwWzK3mo5hMgVleoehNFDI1UVr+xeMb0EzOV7NEvdukIQ4ink+tH4GUoyzLFxsk9cDRe+yRsQAEozSpl7Zy1APxy/y8neDWC0UKJxr/gWNOsMQRQZKnfnGST2JjKLhExFAgSEfQbEcNMU8mGMLSlsqpRFeg+pT/OHxwx9Pp0YThUtBDg0df1lPS6i+aQ6xrdundF0/jZyWY+sOMwO3v8ZFlk/nFOGTsuWMo98yuY6x6b6ORYIYThOGB2JadbYwhJIoYJhGEsYhg2hWFm009My5rGNCxrknkZQvLReB0NvrQ8FSeCTy/9NAAvnXhpQuYnP/TQQ9TU1OB0Olm9ejXbt29Puu2+ffu44YYbqKmpQZIkHnzwwRHvczqiRONzv4dKJVus1pgllCpJWLKzB32TtxhCUaSSBYLEhLzDnHrSkkbEsLcRlDDIVsgZPAPZZ0QMszypheHOuk521XVht8h86vzBAnMk9EYVbn3vBPcdbySqwTXFuby+ejEbasrwWC2jeqzxQgjDcSDdrmTo62WYpjC0948YmnUTbd70TC7NiOFIUskQF4bNxpSI/DI3kgRBXwR/z8gNN8eCMwrP4Nyyc4lqUZ7Y98S4HvvJJ59kw4YN3HvvvezcuZPly5ezdu3amLAeiN/vZ+7cufzgBz+grKxsVPY5HTE7kpGk/j6gSTC9DBVZittF9SEWMUw0v1wgEAx/TnI6qWQzjZxbDfJgkRWLGHoWpjzWf/+tFoAPr6gY1drCllCED+88wpaOHlyyxAOLq/mvM2ood4yvBc5oI4ThOJCuwTX0mX6SKmIY7Io9Ze8z/QTiEcO0U8kxy5oMUsntAbQBnkulhhmwKUKsdgu5JbrZaEf95EwnA3zuzM8B8Psjv6cz2DnE1qPHAw88wO233866detYunQpDz/8MG63m8ceeyzh9ueeey4/+tGPuOmmm3Ak8fzKdJ/TEVMYWq22tOp4zHSyKsvInsEXNkuuHjFURcRQIEhIMNZ8klnEMJKOMOwy6wsHR/k0TcHn02cop0old/nDbN7bCMBnL6zJaI2paA5FuGH3UQ74gpTYrTy9cgG3lBdO+vrBdBDCcBzIpPkk5bzkVKnkPnY1oAvDdFK45WYqOY2IoSXfqZstRTWU7v7C0xSG7e3tRIyL82SegGJyYcWFLClYQiAa4NcHfj0uxwyHw+zYsYM1a9bEnpNlmTVr1rBt27Zx3WcoFKKnp6ffbSqjpDkOzyTmZShJWBKkwmRRYygQpCTefJJ+xFDx+tD8+rSUtCKGCTqS/f6TqGoIWXbhcs1Kuov/e6+RiKKxtDyHMytzk26XCd6owi3vHeOIP0Slw8ZzZy9gZU56U1emAkIYjgMxu5pMIobpCkMzlWzUGBZm6Re6iKLRHRha7GUiDCVZwlqYeAKKx+PB7XajaRqtxjfBgkr9Qts+STuTASRJ4rZltwHw6wO/pjs09gKgra0NRVFiYtqktLSUpqbh1ToOd5+bNm0iNzc3dquurh7W8ScLSppWNSZmKlmVJeQEc17jqeSpLZgFgrEinkpOP2KotOnXCMntRk4lKE2rmkQdybHGkwVIUnIp8/TO0wB89OzBNYrDQdE0vrDvJPu8QYpsVn6/cj41rqnVXDIUQhiOA3YjYphWV3KqiKEzT7/v15Wsi8VotBtVjeK0Wchx6jYd6aSTK41aiOawbnI9FNYi/VvRQGEoSVJMlJh1hqZlTfskTiUDrJm9hgX5C/BGvDOuQ3njxo10d3fHbqdOnZroJY2IdMfhmcQihsmEYY4hDEUqWSBISMzg2p1+xCzaoV/DrIWFqTdMkUr2+fSJKFkp6guPt3rZVdeFRZb48IrBc5aHw09PNsdqCn9x1pxpJwpBCMNxwdanK3mo9G6sKznNiKHVmgfoNQ2RaBcQTye39g5dN1hkmFwrhsn1UMRmJrcObkAZLAyNzuRGH+oI50COJbIkc8fyOwD41YFf0dWnhnMsKCoqwmKxxP6dTJqbm5M2lozVPh0OBzk5Of1uU5m+NYbpYE5HUSQpcY1hnhCGAkEqwgE9JWzPwOBa6WgHBvuGDiKWSq4Z9JLffxyALHdyT8Ln39NrCy+eX0RJdmqfw3R4s8vL/Sf0DMy/LKrm7JzMGm6mCkIYjgOmMETTiIZTR/FiPoYphWEXGLMWZdmK1apfvAZa1qRrcl1qTz+dbE1hWTNQGOYWubDaZZSISneLf8h9TyRXzLqCxQWL8UV8PLLnkTE9lt1uZ9WqVWzZsiX2nKqqbNmyhQsuuGDS7HMqknmNoZlKlrGkTCULYSgQJCKWSs4kYthuTBpKFTGMhqC3QX+cIGJoCkN3CmH4ygH9WnT1suF94e53PEXlqwfqUIGPl+XzibIhRO0URgjDccCcyQpDN6CkjhjmGQ806FMLZzfH4kUyH4sHmVnW2JKkkqG/MNQ0DUmWKCifGulkWZL52tlfA+B/Dv4PDd6GMT3ehg0beOSRR3jiiSc4cOAAd9xxBz6fj3Xr1gFw6623snHjxtj24XCY3bt3s3v3bsLhMPX19ezevZujR4+mvc+ZgFljOKxUcoIaKdPHUO3qnrR+nALBRBKLGLrSF4axiGFhCnHVU6/fW13g7i8gNU3D768FkgvDhq4A753uRpLg/YtLE26TCT+pbeJkMEyFw8Z9C6pGvL/JjBCG44Aky1jTbEBJGTG0OsBmhK4TdCaHhzEWD+KWNY3pWNYU6xFDpTOIFlX7vVZcXIwkSfj9fryG6amZTp7MnckmF1ZcyOqy1UTUCD/d+dMxPdaNN97I/fffzz333MOKFSvYvXs3mzdvjonruro6GhsbY9s3NDSwcuVKVq5cSWNjI/fffz8rV67ktttuS3ufM4GMU8l9upIT1RjKxkg8LRJBCww961wgmElomkbYr58XjgyEYSximJ9CGHYbwjC3EgZYwITDLSiKD0my4HIlbpj7kxEtXDUrf8TehYd9Qf7jlG7Fdt+CKrKnqHF1uqT3tVowYuxOF9FQaMgGFDNiqIVCqOEwsn2AUaYrHyK+hGPx4qnkzMbimZ3J9WlEDGWPDclhQQspRNsD2ErjNRY2m43CwkLa2tpoamoiOzs7LgxPT35hKEkSXz/n69z8x5t54cQL3Lz4ZlaUrBiz461fv57169cnfG3r1q39fq6pqUkrYpVqnzOBkXUlD64XkrPcYLVCNIrS04OcQbpMIJju6HXzeoDAMZwaw3QihokmnhhpZKezCllObCb98j5dGF51xsi/GN93vIGoBlcV5vCB4tGxvJnMiIjhOBGzrBlKGHo8sW9HmXsZ9je5zngsXjqWNZIUixqm14BippInvzAEfRrK9QuuB2DT9k2omjrEOwSTieH7GCauMZQkSYzFEwiSEDa8CCUpnhVLh1jEsCBFjWG3bjOTSBj6/frc42RpZH84yvYT+jGuWDIyYbi9y8vmth5k4K55o9PZPNkRwnCcSNfkWpLlmK9TYmGYp98HuuL7HiAMMx2LZ47vSWdeMqSemWx2wJreeYVV+sW2py1IOBgdtP1k5Csrv4LH5mF/+35eqn1popcjyAAzlWzJsMYwmY8h9GlAEcJQIOhHKNaR7Mpo4ofSoYu2tCKGuYmEYeqO5LdrOwkrKpV5LuYWjaxz+AdGF/It5YUszBp5Z/NUQKSSx4m+ljVDIedko3q9GZhcJ44YpptKrnSkPxYPwFpsNKAkiBgOFIYuj52sXDu+7jDt9T7K503+MHyhq5AN52wgrIS5cvaVE70cQQbEhWFmqeRkzSeAiBgKBEkYTuMJQLQjja7k7uSp5HhH8pyEb33jaBsAF84b2Yi6nd0+3ujyYpXg6zUzp1ZbCMNxIjYvOTh0AbvFk02UxsTTFvpa1pj7jjWf9B+L1+4N693BQ5wY5UbzSVM4gqJpWIbYPpZKThExbG9vJxwOY7fbKazKxtfdTnu9d0oIQ4CPL/z4RC9BMAwyrjG09W0+SRxZkA0vQzEvWSDoT8hIJWdSX6gpCkqnYXCdysewx3CGyB3cAez3pU4lv24Iw4sXFKW9rkT8W53ecPLR0nwqnYlrGacjIpU8TthjEcOho3hmA4rqTWDxkiBiGGs+iXQB8bF4YUWlJzB0+rbEbsNimFy3hofe3vQyjLYO9ibMzs4mKysLTdNoadFPqqIq/Y9G2xRoQBFMbWI1hummkg0BmczHEPqmksVYPIGgL8OyqunujvnwWvLykm/Yk7jGUFXDBIL6a253zaC3dfjC7G/Uz9UL5g0xWSUFx/0hXmzTvwzeOWvmRAtBCMNxw4wYhtOIGJqRC9U7vOYTp81CtjEWr9Wbxhi+PibX6aSTTWGo+qMovsF1icnqDKdCZ7JgapNpKtmMjicbiQdiLJ5AkAyz+cThcqX9HqVd70i25OYiJYvsh/3xa9yAGsNgsAFQkWUndnvJoLduO9aOpsGi0uwRTTv5RUMbGnBFQQ6LZkhtoYkQhuNEJjWGFo8ZMUwgpGLNJ8mFIcS9DNMZiweZdSbLdguWXH3/qdLJMWFoWtbUe9Em8Wg8wdQn01SybPw+qrKM5Ez8x1/O1n9/E35REwhmMMOJGKY19cRsPLFng7N/+VEgoM9zd7mqE5ZJvV2r7//8ucOfTBJSVf63Sd/PZyqHH3WcqghhOE7EawzTaD4xIhdKbyJhmChiqJ8AiuJDUfRUdaYNKGZnckOancnWEiOdnGDU3UBhmF/qxmKViYQUetqH/vwCwXDJ1K7GYqS0VJs1aS2u+UVNSfRFTSCYwQynxlDpNDqSU9UXmlY1CTqSA0FTGM5K+NZddfq1cVXN8IXhC63ddEQUKhw23l8wtefHDwchDMcJ065mKINrAEssQpFKGHbEnrJas5Ek3Yk9Eh1oWZOZl2G6nck2ozM5kqAzuby8HNCFoaIoyBaZggqzzlBEXQRjR6Z2NRZFAUBNsb35RU1N9EVNMGV46KGHqKmpwel0snr1arZv355028cffxxJkvrdnEkiyjOZuF3NGEUME3QkB42IodM5uCklEFbY16DXF549Ky/tNQ3k1w16uvuW8kKs8vC7mqcqQhiOE2bzSTQduxozYpiyxrAr9pQkSViteQBEwqZlTWbTT+Jj8dKMGBYnb0ApKCjAbrcTjUZpN+pJiow6w7ZT4uIqGDsyrTGUInqEUbEk/1MY+6KWyD5KMCV48skn2bBhA/feey87d+5k+fLlrF27NtYgl4icnBwaGxtjt5MnT47jiqcG8VRyBjWGxtQTS0F+8o26k3sY9k0lD+S9011EVY3SHAeVeemvqS9NoQh/69KvU58oS7HGaYwQhuNEZs0n5rzkBCLKmaffB7ugz4g0u93sTB7gZZhmjWEslZy2MEzuZSjLciyd3NCgWw4UVeufqe2UuLgKxo5MawwthjBU5eR/Ck2XAMXrhWgIjv4JIqIkYirxwAMPcPvtt7Nu3TqWLl3Kww8/jNvt5rHHHkv6HkmSKCsri91SzRwPhUL09PT0u80E4s0nmUcMrammnvQaVjXZgyeNBIJ1QOJU8g4zjTw7f9j+hc+1dKIB5+ZkMcs1shnLUxUhDMcJWyxiOHQEL3UqOU+/V8IQiYuyQWPxjFRy61ilkksMYdgRQIsOHhtnppMbGxsBKK7WP1OriBgKxpBM7WrksC4klRQXkVgq2dsLv/kE/OoG+NuDI1uoYNwIh8Ps2LGDNWvWxJ6TZZk1a9awbdu2pO/zer3Mnj2b6upqPvKRj7Bv376k227atInc3NzYrbp6cDRrOhJPJWcyJ9kch5ciGter16eTXTbopVjE0Dn433jnSf36d/as4Uf6/tDcBcB1pXnD3sdURwjDccKcsJCWj2GqVLLdA7Jx0UtjXnL6zSeGyXUogqoN3TksZ9uQHBZQIdqevM7QFIaFVR6QwNcVIpBmFFMgyJSMU8lh/fxQUgQXTH9Dtb0Zjm/VnzwsRiVOFdra2lAUZVDEr7S0NNYgN5BFixbx2GOP8eyzz/KrX/0KVVW58MILOX36dMLtN27cSHd3d+x26tSpUf8ck5HhRAyVri5gCA/DmDAs7/d0JNJNNKpHYwemkjVNY2edvu+zZw9PGNYGQuzq9SMDHy5Jsb5pjhCG44TNaQrDdGoMU6SSJal/Otncf2z6yYAaw970hGGp3YYMRNM0uZYkCWtJ8nRyRYWeAmhqakJVVexOK7lGXaKoMxSMFZmmkiXji5pC8i9DsVRyMIKmGQqycTcEha/hdOWCCy7g1ltvZcWKFVx66aU8/fTTFBcX8/Of/zzh9g6Hg5ycnH63mcCwDK67jKkn+elEDPuL+UBATyPb7cVYLP1rCBu7g3T4wlhkiaXlw/v3f7FVP6cvyvdQbE/vb8h0RAjDccKWUcTQNLhOIqASTj8xI4bGWLxYxFAfizcUVlmiNJZOTq/O0GYIvUiCBpTCwkKsVivhcLhPA4p+gW0VdYaCMSIaydDHMGAIwxT+muYXNTQJLacGCueDpsLJN0a0VsH4UFRUhMViobm5ud/zzc3NsVroobDZbKxcuZKjR4+OxRKnLPFUcvqNHtGhIoaqAj6jKWhAxDBuVTM4jby3Xhd1C0o8OG2WtNfTl5fb9X2sLZoao1vHimEJw0za/i+77LJBbf+SJHHNNdcMe9FTkZiPYToG19lD+KbFTK674vsfkEo27WrCikpPcOgIIMTTyY1p1hnGGlBaBkcMLRbLoAaU4llGZ7KYgCIYI9QMawylgP67q6HF6hMHIme5wQgUKp55UHOJ/sOJ10a2WMG4YLfbWbVqFVu2bIk9p6oqW7Zs4YILLkhrH4qisGfPnliJjEAnnKGPoaZpKF26+EoqDH2t+hcvSYas4n4vpaov3GvY1JxZOTxR1xGJsr1bH0N7VeHMiPgmI2NhmGnb/9NPP92v5X/v3r1YLBY+/vGPj3jxUwnbMGYla34/muGz1o9UY/HC8bF4Hod+cczcyzDNiKFhch1JYHINUFmpWw0M7ExurRMRQ8HYkHGNoT/+uxsNJ/5CJEkSsnEuqe5qmPM+/QUhDKcMGzZs4JFHHuGJJ57gwIED3HHHHfh8PtatWwfArbfeysaNG2Pbf/e73+Xll1/m+PHj7Ny5k0996lOcPHmS2267baI+wqRD07R4xDDNVLLq84F5jiZLJZtp5KwSkPtH/vRxeOB0Drax2WdEDM+sGJ6o+3N7D4oGi7OcM7Yb2SS9r9V96Nv2D/Dwww/z/PPP89hjj/GNb3xj0PYFA9zNf/vb3+J2u2ecMDSbT9LqSs6Kf/tSvV4suQO+AaWoMTQNrkGPGnpDUVp7Q8wrTjwHti8VhmVNfTDNiKFZY9jiR1M1pAFGoKYwrK/XPalKZunCsKvFTzgQxe7K+NdPIEhJNNMaQ3882h0Nh3AkMeqV7aAGQXWWxyOGzXsh2APOmR1dmArceOONtLa2cs8999DU1MSKFSvYvHlzrCGlrq4OuY9lUWdnJ7fffjtNTU3k5+ezatUq3njjDZYuXTpRH2HSEQkFY5Zp6TafmI0nksOBnMz7MEl9IUAoJgwH29jsG2HE8OV2/f0zPY0MGQpDs+2/7zerdNr++/Loo49y0003kZWVPPQcCoUI9RFQ08ETKmZXEw6hqSpSCt80yW5HcjjQQiGU3gTCMFHE0PAxDIfjE1GKPHZOtPkyjhimbXJd4AKLhBZRUbpCWAv6TwYwhWFjYyPRaBRXth1PvgNvZ4jWU71ULpyZ5qGCsSPTiKEWDCKrKqosJ40Y6vuLEEVCsZWApxhcBfr0oa46KDtzVNYuGFvWr1/P+vXrE762devWfj//5Cc/4Sc/+ck4rGrqYqaRJVnG6kgvwqZ0dgEpooUA3sQdyQDBUGJh2NoboqkniCTBkmE0niiaxmsdeiZrzQxPI0OGqeThtP33Zfv27ezdu3fIcPx09ISy9TlxUl2ATGLeab4UXoZ9agzjzSfx5+Im1+lOP8nM5FqySPEGlATp5IKCApxOJ4qixEoNSmbrJ51IJwvGgkxrDFW/H4vReJL0vAz2IMv6a6olT38uzzDX7aob9loFgqlMqI9VTbpm0mZHclpWNZ7BEUMzlewYIAz3Nehp5DlFWWQ5Ms9E7fUG6IoqeCwyK7PT77CeroxrV/Kjjz7KsmXLOO+881JuNx09oaw2e+xxWg0onhRjuFLUGKpqAEXR02PxecnppYYrjYhhuqlkAGupHvmNNg8WhpIkxWxrzHRysZFObjkphKFg9Mk0laz6/ciaKQyTfIFqO4Js07dRQ0bNb57xZbV76v9tEgiGQ3gYc5JH4mEYjfbGPAydjv6v7W/Unz+jYnhpYDNaeFG+Z0bORh5IRsJwJG3/Pp+P3/72t3zuc58b8jjT0ROqb7g9PS9Dw+Q6kTBMUGNosXiQJP1iONDkujXtiKFhch2OoKRhcQPxCShDNaDEhOFs0YAiGDuUDO1q1EAaEcO2Q1hs+nQfxfQWzZut34uIoWCGEms8cWYwJzmWSs5LvlGSGsNgUB+WYLXmYrX2r5k/3KRfTxaXZae9lr78tVN//yX5w3v/dCMjYTiStv/f/e53hEIhPvWpTw1vpdOAuGVN+p3Jqtc3+MUEqWRJkrDZ9OcHWtakOxavxG7DKoGiQXO6dYamMGxOsE7iwtCcGBBrQGnWG1AEgtEk4xpDnx9Z1UVfcmF4GNluRAxNCymRShbMcCKG1dNwzK1TRgyT1Bgmqy8EONysn5cLSoZushxIUFFjNjXvE8IQGEYqOdO2f5NHH32U6667jsLCFIOzpzm2DCKG8XnJ6aWSoa+XYRcAxRmOxbNIEqX2DC1rSvt0JieIMpr1oW1tbQQCAb0BpcAQrCJqKBhlMq4xDASwmKnkSJLzpKcxFjGMnY+5RipZCEPBDCUcNIVhBhHDTFLJnoERw8TCUFE1jrbqwnDRMCKG7/T4CKoaZXYbC9wz26bGJOMqzUzb/gEOHTrE66+/zssvvzw6q56ixCKGwTQihlnmvOQEzScJUsnQdyyeMf0kO7NUMkCl0059KEJ9KMw5DG1aai10giyhhY3O5Pz+nclZWVkUFBTQ0dHB6dOnWbBgAaWzc/B2tNJc20PlItGZLBgdNE3LqMZQi0bRwuGhU8neZmSrvk08lSwihoKZTXg4qWRDGCYdh6cq4E089SRmVePoLwxPtvsIR1WcNpnq/MwbR97q0qOFF+Rlpd1EM1nQVA3VH0H1RvR7fxTJYcG5YGTX1WEZyWXS9g/6QPJ0xrJNd2JehsmK3PsQSyUnmpccixh2gaqCIcTtNt2yZmAquc0bQtO0tH7pYybXwXQ7k2WsxS6izX4izf5BwhD0qGFHRwenTp1iwYIFlMzJ4dguXRgKBKOFqigxX7V0hKFqpMKGFIa+VmS7ETE0a37N5pNAB4S84Mg8hSUQTGXCxvljy0AYRjuHSCX720FTAGnQ1BOzxtDp7C8YzTTy/BIP8jAaR8w08nl5k/Mc1hSVaGuASLOPSEsApT1AtCOI0h1G6Q3DgHGe9jk5EyMMBcPD5syk+cScl5wolZxnPNAg1BP72WbvP/2kyKN3QkcUje5AhDy3naEwTa4b0hyLB2Ary9KFYZMP1+KCQa9XV1fz7rvvxrrLS2v0ZqLmE0IYCkYPJRr/MmNNo8ZQNew2huxK9rZgMbuSTfsoZ65+C3brncklS0awcoFg6mFexzJLJRvj8JJFDM1oobsQLP3liVljONCq5kizfo1cWJp5GjmqarzTowvD1bnpjfUba7SIQuh4N8Hj3YRrewjXeyGqJn+DBLLLiuy2Ibut2EpH/jmEMBxH4qnkdOxqUsxLtjrA5oaIX68zNIXhgHnJDquFXJeN7kCE1t5QWsKw0plZjSGArcxN4F2INiVuQDHrDOvr61EUheJZ2UgS+LpCeDtDePJFXYdg5JiNJ5BmxNAQhhZj7FbCiKGqgL8N2dif0jeCnzsLgnv0dLIQhoIZRjgwjBrDoSKGPkMYekoGvZSsxvDQCIThAV8An6KSY5VZlDU42zVeaBGVwP52/O+1EjzUOUgISg4LtrIsrMUurEUurAVOLHkOrLkOZI8NyTK6zoNCGI4jNiOVHEkrlWz6GCYQhqDXGUb8icfiReJNKUUee0wYLkjjxKmMjcXLQBga31AiTYkta4qLi3E4HIRCIVpaWigvL6egwkN7vZeW2h48+cUJ3ycQZIJiNJ4gSSknC5mYwtBq/FFNKAz97aCpyIbO7OcrmjcLmveIOkPBjGQ4qeQhm0+8rfr9gDSypimEQnpTykAPwyNGKnlhaeap4LeMNPI5OVlYJqC+MNodwvtGA77tTWh9XDosuXYcC/JxzMnFPisba6Fr0MjZsUQIw3HEHIuXXsQwhcE16HWGvQ0JTa77CsPibAfHWn1pW9aYXob1GaaSASKtfjRFHfTtRZZlqqqqOHbsGCdPnqS8vJzSmmza670013Yzd6UQhoKRY0YMrVZbWvW0mlljaKSsEqaSjdSWJVsvf+gXwc8TncmCmUs4aDSfpBkxVAMBNOPalzSVnCRiGA63o2lRQMZuj78WVVSOt5lWNZlHDGP1heOcRla8YXr/fArvW426PxxgyXXgPrsE17IibOUT2wgjhOE4Yh2Gj6HiS5yejXsZxkWgPdaV3FcY6sdM2+TaiBi2hqOEVBVHGpEXS74DyWFBCylE2wIJaxxqampiwvD888+ndE4u+//WKOoMBaOGMoypJwBWqxVQiSSKGBoXKjmvAOiN+xhCvGvS2zz4fQLBNCeWSk4zYmhGC7FakbOSCDGzxnBAxDAU0s8xu70IWY7LlvquABFFw26VqcxLP3JpssOMGI6TMNQ0Dd/2Jro318YihPY5OWRfUoVzccG4RgVTIYThOGL6GKbVlZxl+hgmSSX37Uw29x+LGHbEnjMbUNKNGBbaLDhliaCq0RSKMNs1dP2fJEnYSt2E63qJNPkSCsPZs/VJESdPnkTTNErnGA0otT0oiopllGskBDOPjKee+PULm9VmAzVENNEXNjNiWFAC9KIFg2jhMJLdHo9qmBczgWAGYWa+0haG3UbjSW5u8miYL3Eq2RSGDkd/b8Pjbbqwm1OYlXFHcms4Qn0oggSsGIf5yEpvmI7fHSZ0WA/c2MqzyL1mDs75k8+yTVyNx5GYwXU6qeTsIVLJCbwMbX3sakx7oJhlTW96qWFJkmJ1hqcymJkcSycnqTOsqKjAarXi9/tpbW2loDwLh9tKNKzSfjqJ+BUIMkCJmVtnGDE05pgnrDE0RJ+cH78gxaL4WYYwNC9mAsEMwjS4tqWZSo51JOemmGdsnksDUsnJhOGJVkMYFmUe8dvVo5//890OPFZLxu/PhPCpXlr+dZcuCq0yudfMpWT9ykkpCkEIw3ElPhIvg1nJPl9iD8gEqWQzYqiqIVRVP2nN6SfpRgwBqpzDaEAxhWFj4tS31WqNdSfX1tYiyRKlc/Q/EI1Hu9M+jkCQjPg4vHSnnhjCMJW/qJFKlnLLkIwaYdUUhh4jqiGEoWAGknEquScNYRhLJQ8UhnrjicNR1u/5E2bEsDhzYbi7Vz//V+SMbbQwcLCDlp+/h9ITxlriovTLK8i+pBLJMjnSxokQwnAcsZqp5AxqDIlE0BJtn2AsnsXiRpYN70JzLN6wpp/oEZfTmUQMy01hmDz6V1NTA+jpZIDyeYYwPCaEoWDkDLvG0BSGkUQRw3hqy/yyFhOGZrrL16YbzQsEM4hMR+L1TSUnJRYxTJxKdg6MGLYNP2K424gYjmUaObC3jfZf7IeoinNRPiVfWjEqPoNjjRCG40hGEUO3G4w6jIR1hrGIYVfsKUmSYunk2Fg8zzCEoWlZk0lnsiEMle4wii9xpNEUhidOnEBV1ZgwbDrWJSbjCEZMPGKYoTB0mhHDRMLQaCzxlGDJMk3njfPRFIaaok9AEQhmEJFAhl3JPXqjoSU3J8kGap8awzRTyYYwnJuhMNQ0LRYxXDlGwjB4pJP2/zkIqoZreTGFty5Fdk6Ntg4hDMeRWI1hGhFDSZZjnVtKojrDBM0n0KcBxZh+UmJEDDt8IRQ1PfFlppIziRjKTiuWQkP4NiSOGlZWVmKz2fD7/TQ3N1MyJwdZlvB1h+ltH1osCwSpiNUY2tL746v5TR82/fc2cSo5XvMUixiawtBii5+HogFFMINQopHY+WZ3pieszBpDOVnEMNgFquHlN7D5JGwKw3gqORhRqO/Sz+FMI4anQxE6IgpWCZZ6Mu9mHopIs4/2Xx4ARcO1rIiCGxeNugn1QDRNo6vZT9so1OwLYTiO2DKwqwH6XIgS1O0laD4BsNn0500vw0KPA1nSxym2p1lnaKaSM6kxBLCXD11naEYNjx8/js1uoaha/4winSwYKbFUcqYRQ5d+YUvVfEJWSfyLWt8IvmhAEcxAwn0aKM0vVkOhmBHDnCTC0DzXnHlg7T+ly6wxtDvikcTadv06k+uyUZA19FSvvrxrpJGXZLlwjrJgU/0R2n6xHy2s4Jibq4vCMbKhUVWN04c6ee23h/nlXdv49b1v8tazx0a8XyEMx5F4xDC96FisMznhvOTBNYYQjxiGI+36PmSJQiOd3JJmOrnaGU8lZ5LitVXo6w0niRgCzJs3D4Bjx/Rf3oqF+nobDncmfY9AkA4Z29WYkxvcSYShMQ4PGBAx7PPFJ0s0oAhmHhHTHN5mS7vZa8gawyTm1oriJxrVr4HOPhHDvh3JmZpB7/Pq6z8ze3SjhZqm0fH7IyjtQSx5Dgo+uQTJOvoyq7cjyJvPHuMX33yDZ3+yiz1bT9PbHkS2SiBJIy7NmhoJ72mCNUNhaHoZJpyXnEQY2m2F+jH6mFyXZDto7Q3R0hsEUhT+GpQ7bEhAUNVoi0Qptqd3oTWFYaQhiSk3MHfuXADq6uqIRCJULsxj9yt11B/uSusYAkEyopl2JRsRQ5tLjwQOSiX7O0AzmkrcRcieATWGAJ5i6sscKJ0vUK3dMKHTCgSC8SJs1hdmMg6vuwtIUWOYtCNZTyNbLG4slvjYuxPtw288MYXhGaOcRvbvaCa4rx0sEoWfXoolK71rZ7p0Nvl458VajrzdgmaUhjncVuauKGbOimKqFuVjc4zcekcIw3HETCWn05UM8c7khPOSzeaTiB+iIbDqojPRWLySbAf7gJae9I5rl2VK7TaawhFOByNpC0N7hXGBbfWjhhVk++Bf0OLiYrKzs+nt7aWuro6q+bORJOhuDeDtDOHJH9pQWyBIRMZdycbFzZZlCsMBEUPzS5cjFyzW+JjKPtOIejw2DhZmQ/QvZHW8TmHhJSP5CALBlCDTjmQAtdtsPkkWMUzdkexwlPb74nWqQz9/ZxVk3jwyFsIw2h2i67njAORcORt7Zeazm5MR8IZ589njHHi9ATMYWLkwjzMvrWLOWUVYbKMblRSp5HEk0xrDeCo5gTB05ALGSdJ3+ond6EoOx7skS4yxeOmmkqFvnWEGDSjZduQsG2gQaUocNZQkifnz5wNw+PBhHC4rRdW6AG44ItLJguGjDtPg2mYIvkHC0KzfNb6ExaYR+eLn4zHn4djjEyd+KrrrBTOCcIZTTyCeSpZzhhcxdNj7dyTXDVMYdkWi1If0L5FLs9Krj0yH7j8eRwsr2Gdlk/2+qlHZp6ZpHHqrid/c+xb7/6qLwpqzivj4xnO4bsPZzF9VMuqiEIQwHFf6jsTT0vA9i6eSE9QYynLKecn9IoY5w/EyzLwzWZIkbMa3pEh98jrDhQsXArow1DSNyoV5ADMunfzQQw9RU1OD0+lk9erVbN++PeX2v/vd71i8eDFOp5Nly5bxwgsv9Hvd6/Wyfv16qqqqcLlcLF26lIcffngsP8KkIpqhXY3ZlWw3IvODUsnmeWUKQ0//0o7Ozrfo0E4jqRqyJtHds4uOjtdH8hEEgimBWWNoc6UvymLNJ7l5iTdIOg4vsbl1TBgWZiYM93t1UVvltJGbpoPBUAQPdxLY0wYS5F03f1SaTcKBKC8/uo8//fd+gr4IhZUerv9/Z3PNl86iZHYScT1KCGE4jpgRQ0jSATmAWCo5UVcyDDEWLx4xNE2u9RrD9KgyvAxPZ+BlCGCvMhpQTiUZ5YdeZ2ixWOjs7KStrY1KowHl9KGZEzF88skn2bBhA/feey87d+5k+fLlrF27lpaWxLYnb7zxBjfffDOf+9zn2LVrF9dddx3XXXcde/fujW2zYcMGNm/ezK9+9SsOHDjA1772NdavX89zzz03Xh9rQok3n2RWY2j36OeZEo2iKkp8AzMSb9TzxmsM9fOxpXUzAGUtISq69deamp8Z9voFgqlCpqlkTVFi412T1hj69YZJsgr7PR0K6X8THX06kqOKSkOXfj3LNGK43ze6aWRN1eh6Xk8hey6swF4x8hRyV7Ofp/7lHY6+04IkS6z+8Bw+/s1zqFiQN+J9p4MQhuOI1R5vqU9vLJ5xIUo2LzlBA0riVHJmXckA1a7MI4YA9ir9IhtO4aXkcDhitjWHDx+mYkEesizR0xqgpy2Q0fGmKg888AC3334769ati0X23G43jz32WMLtf/rTn/KBD3yAf/iHf2DJkiV873vf4+yzz+bf/u3fYtu88cYbfOYzn+Gyyy6jpqaGz3/+8yxfvnzISOR0IfMaQyPq0edC1S9qaJ5XxhcweYDBtc+rp5HzuiMUdOjv8/YeGN7iBYIpRKz5xJGZVQ2AJVkq2Wc4ALiL+j0dCrcax4oLw8buIIqqYbfKsbGv6bK3d3SFof/dVqLNfiSnlZwrZo14f80nenjqh+/Q2eQnK8/BR//+bM65eg6WMfZB7IsQhuOIJMux8VvpCEOLEcnoW9PUjwQm13YjYhiNdqEZHZXFZo1hms0nELesOZWpMDTqBaOtftRQNOl2Zjr50KFD2F1WSufqfyxOHZj+EyTC4TA7duxgzZo1sedkWWbNmjVs27Yt4Xu2bdvWb3uAtWvX9tv+wgsv5LnnnqO+vh5N03j11Vc5fPgwV111VdK1hEIhenp6+t2mKspwawz7+Kr1q/+N1Rjq59nA5hOvTxeGHp+Cp0P/vfX5j6GqmZ0zAsFUIxxLJac59cSsL3S7kZJ9cTOtobL6C8OwKQzt8efNNHJ1vgs5w7TtaEYMtahKz8u1AGRfVoXsHlkXcsORLp59cBchX5SS2dl8fOM5lM1N7iSiaRq9vb3U1tayc+dOtmzZMiqBANGVPM7YHA6i4RCRYDoRQ6OmKVFXMiSsMTQNrjVNIRrtwWbLi0UMW3tDaJqWlqWGKQzrAuG03wNgybZjybWjdIeJ1PtwJPmlXrRoES+++CJ1dXV4vV6qlxTQeLSbU/s7OOOSyrSONVVpa2tDURRKS/sXU5eWlnLw4MGE72lqakq4fVNTU+znf/3Xf+Xzn/88VVVVWK1WZFnmkUce4X3ve1/StWzatInvfOc7I/g0kwczlWxNI2KoKQqacQ5asrKwOhxEQ6HEEcMBNYaqz0s43GaUa0hk+aPIahSrpYKo0ovPd4zs7CWj9rkEgsmGGdjIdE6ynJdqTrKRSnYnFoYOezxiONzGE1XTOOLT174ka+TC0L+7FaUzhOyx4bmwYkT7ajnZwx8fepdISKFqcT4f/OIy7ANG6Pn9furq6qirq/v/7P15eCR3efWNf2rpXfs2Gmk0o9kXz4a3wWZxTAxjdpMADm/AeRzC+4TgAJnEP2IC5gckMYT9AQc/mDiGBGLC5kBsDMbBxsb72GN79lXSjDTapZZ6766q949vVfWiXqp7FmnkOtelSzOt2npG1d9T577PuRkaGmJkZIR4PL/KtmzZMi6//PIzuhaXGJ5nqD4fzEK62PitAsjlXMlQtJQsy15UtZ5MZpZUahKPp8nuMUxpOuF4mqZg5ZR4ixjOajrhjEZTFU26nmX1aOEJUqdmSxLDpqYmuru7GRwc5MCBA/RsWsfTPz/BqUNT6LpR9VOgC0EMn3zySX72s5+xYsUKfvvb3/KhD32Irq6uOWqjhVtuuYVdu3bZf5+ZmaGnp+d8XfJZhVVKlh3kGOrx7IOZHAjg8QpimKcYFvYY2mawKBGzjBwI9KAoMdCj1Pl7mY6+RCRywCWGLhY1LMXQ8Ti8SlNPMilImtOvChTDZNJSDLOmlFqJ4clEirhu4JMlVgSqm5ZSCEM3mP3tSQDqX9NdNJ7NKWbG4/z86y+QTmh0r2vizX+xFdU83ujoKPv37+fw4cMMDQ3N2VeSJJqammhpaaG5uZnOzs4521QLlxieZ9iRNYnKxNAuXRVzJUOZsXjNZDKzpqKxCr9HoTHgIRxPMzqbdEQMg4pMm0dlPJ3hZCJVFTH0LqsnsU8Qw3LYtGkTg4OD7N+/n0vedym+oEoylmG0b6asfH6ho62tDUVRGBkZyXt9ZGSk5E3d2dlZdvt4PM7HP/5xfvrTn/LmN78ZgK1bt7Jnzx6++MUvliSGPp8Pn29xZEdqVbiSDbNHCklC8vvtB7a8jNHCHsOcgOto9AgAodA6CI5BOEqdp5tpXiISKa76unCxWGATQ6eK4XSFqSeW8URSsusaYuqJpglhxOebSwx7qiSGh0y1cE3Qh3KGYfSJg5NkRuNIPoXQjqU1HycVz3DfP79IIpKmfXk9b/qLrWhGhuefeY7du3fnVYVArB/Lly+nu7ubpUuX0t7ejsdhX7VTuMTwPMMOuXaiGFpuyVKu5JJj8VqJxwfynMkd9T5BDGeSrFtS7+hae/xextMZBhIpttQ7vwGtPsPUQGVi+OCDD9LX10csFmXZhmaOPTdG/96JRU0MvV4vl1xyCQ899BDXXXcdALqu89BDD3HTTTcV3eeKK67goYce4qMf/aj92oMPPsgVV1wBQDqdJp1OI8v5bcOKoqA7iEZaDLB6DJ2Ukq3+QjkQEDFLVu9vykGPYSSS7S8MrYPgAQifpF4SSodLDF0sdqQS1U0+0WYqEUPLeNIiothMWGqhLAfypp6cOkNiuC545vmFkccGAQi9cimyvzYqZRgGv/n3g0wORQk2enndn67jscd/y9NPP03CbHWRZZk1a9awYcMG1qxZQ0Mp885ZhEsMzzOqmZdciysZslmGqYIswyOjkaoia5YHvDw/G+NkvAYDigTadJJMOInaWFyRam5upquri6GhIfbv30/vlh6OPTdG30vj7HjbqqrOeaFh165d/Mmf/AmXXnopl19+OV/96leJRqPceOONANxwww10d3dz2223AfCRj3yEq666ii996Uu8+c1v5p577uHZZ5/lW9/6FgANDQ1cddVV3HzzzQQCAVasWMEjjzzCd7/7Xb785S/P2/s8n6hmVrJFDCVzTrI1rjJTtJTcBGRdyRgGkRlB/kKhtRAQhq86TSxcs5EDVfXlunBxocE2n/gdupLtOckVomqC+VE12f7C9rz7qdZSskUM159hsHV6NEbyeBgkqLui9t7CA787zdHdo0gy9Fyl8S/fucPuGWxtbeWyyy5j69atBIPVT3c5E7jE8DzDJoYOzCeKlWMYjWLoOlKBGpQ1n0znn8OMrEmf4fSTWp3Jsk/BszREeihKqn8GdWt7yW23bt3K0NAQL7zwAu/9o+0gwfjJCJGpBHXNZy+VfqHh+uuvZ2xsjFtvvZXh4WG2b9/OAw88YBtMBgYG8tS/K6+8ku9///t84hOf4OMf/zhr167l3nvvZfPmzfY299xzD7fccgt//Md/zOTkJCtWrOAf/uEf+PM///Pz/v7mA7X0GMrmB242fD7nd902n4gHLSkQAFnG0DWiMVFKrqtbby9moZQHkEmnJ0mlJ/B583ulXLhYLLDWL6el5Mrj8CpF1WTXkEgyw1RM3OvLmqszkBw+S8Qw+tRpAPwbWlCbamvFCY/FefQ/D5NRohgr+3nsafFv0N7eztVXX82GDRvmVIDOF1xieJ5h9xg6KiWb0rlhoMdidinLhq0Y5ke8FJ2XbE4/GQ47VwxtZ3KVxBDAu6LBJobBMsRw8+bN/PKXv2RwcJBIIkznygaGj8/Q99IEm1+7uN3JN910U8nS8cMPPzzntXe96128613vKnm8zs5O/vVf//VsXd4FB9uV7KDH0JqTLJuKh1pYSjaMbCnZ7HmSJAm5ro60FkbTRXtHINAryl+AEp/B7+8kkRwiET/pEkMXixbpRJXmE3scXoUew4Jw65QZbp1rPBmaFudu8KvU+5331umGwZGYWUo+A2JopDWiu8V1hV5ZW2+hVUKeVYaIthzDiGj4fD6uueYaLr74YhSldiPL2YCbY3ieoVahGEo+H5hlsaLO5CI5hpDNMkylJ+zXOhssxbCKUnKNiiGAzxzZk+wvn4tXV1fH2rVrAXjhhRfo3SoW074Xx6s+p4uXN6oJuDbMco1sKh4WMbRLyekYaObvvXWfIdo79GYxD9njaUFRfHYpmdgkfr94mEkkBs/szbhwsYCRMluhHJeSbVdydeHWdik5RzEcNIlhd/MZOJL9tRvu4vsnMBIZlCYf/rXNlXcogn2PDXJo6FkijYcx0Fi1ahUf+tCHuOyyy+adFIJLDM87bMUwWVkxlCQJJVSmz9BakBLTkGMwyI7FyyqGFjGsSjEMZImhYRiO9wPwLhcfAOmhKHpKK7vttm3bAEEMezaLG+3kwUlS8dIB2S5cFMIOuHbSY2gSQykoiGG299e8L62HLVkFb8jeTwnVoTWJP/t9plpg9UXFJlxi6OJlAbuU7JAY6vac5FI9hsXDre1Sco5iODhlEsOm6lQ/q79wdcCHegZxaLHnxTUFL+6oaSZyLJLkvl/+F/GQ+Iy4+uqree9733teTCVO4RLD8wzrCcuJKxmy85K1oophk/hu6NkMKMBbZCzekkZx3pEqpp9Y85Kjms5kujy5K4TS7ENu8IJulJ2bDCLsOhQKMTs7y/jMIE1LgugZgxOuauiiClQTV6PHLMXQNJ9YiqF1X+b2F+Y0vct1dWiN4iHJ5zMDx81SMvEp/H7RiB5PzM0bc+FiscCalexx7EoWxFCur1ExzAm3tkrJ3U3V9RcejYl7e+0ZlJG1SIrEYbGuBrd3VNi6yP6axl3/97vE1TEkQ+IP/+CdXHXVVfPWS1gKC+tqXgawe5kclJIhZ9pCMWKo+sBjqhl500/m9hguabCIYQJdd6b++RWZTq9YZPvjzgklCLXTt1L0kySPh8tuq6oqF198MQDPPPMMay4RN9yx50arOqeLlzeyxNCJ+SQbVwNFFMOC/kILcl0dmllK9vnNzMmgW0p28fKBrmt2y4XjUrJZ8aroSi7oMcyGW2cJo1VK7qqSGB4z+wtXB8+gjPzCGOjgWVaHp6PKqSu6zo/+8yeMzw6CIXPNq9/Clq2bK+84D3CJ4XlG1v3ojGjZ2WmlImvsRSmXGFqKYbbHsKPehyRBRjeYjDnvGew1y8l9tfQZrnJGDAEuueQSJEnixIkTNK8UPRYD+yZJJdxysgtnqKrH0MoIM0vJdlxNynxgK3AkW5BDIfQm8Wef11QM7R5Dt5S8kHH77bfT29uL3+9nx44djmfK3nPPPUiSZGeOvtyRO5zBaY6hNSvZStqYg4o9hnMVw+qJobju1YHaiWHMrGLVohb+5je/4cChfWDAqtDlvOr1l9R8HecaLjE8z7CesBwrhlYpuYp5yV6veOrS9TiaJpQRjyLTGqrembzCvImqVQwhSwxTAzMYFUrRTU1NrFu3DoADx/fQ2BFAy+iceMEtJ7twBrvHsIpSsmQubHbAdWGPoXV/mZDrQmhNhYqhqXLEJ+1SciIxWHVfrotzhx/84Afs2rWLT33qUzz33HNs27aNnTt3MjpavirR19fH3/zN3/Ca17zmPF3pwoflSJZk2dlDWCaTDZSvFHCd02NoGJotbnhzSsl2j2GVUTXHzDVsdY3h1tpMitSAKIkHtlSXOHDgwAEeffRRAOrD63j9H15R0zWcL7jE8DwjuwA5I2dKfYWxeJZakRNZoyghZFkofbl9hp1m0PTIjHNiaCuGVYZcA6htAeR6L2gGyQpTUABe9apXAfDiiy/Ss00Q4sNPDZfbxYULG1UFXBe6kgsDrksohrnmE5+voJSspfBLolSmaVEymcpKuYvzgy9/+ct84AMf4MYbb2TTpk3ccccdBINB7rrrrpL7aJrGH//xH/PpT3+aVasWd+B+NUjZxpOAoxB3LafaNSdyDUDXIGauUzmKoRjQoAOS3R6V0XSGzfWrmh7DmYzGWEo8ONZaSo7vnwBDDHAoNbShGKampvjpT38KQCDazbrVm1i6emFP9nKJ4XmGrRg6Np+YC00V008kScLjESpG7lg825lcFTGsXTGUJAmfeQMkj01X3H758uUsX74cTdOYUfoBOHlgkuh09ed28fJDNaVku8cwWKAYphz0GJqKod8ihp4gqOLeUpIx+95zy8kLA6lUit27d+fNC5dlmWuuuYYnnnii5H6f+cxn6Ojo4P3vf3/FcySTSWZmZvK+FivStvGkOkeyFAwiFbs341OAqa5bD1lAKiVURI+nGVkWfcPDMwl0AzyKRHudc3J21Owv7PCq1Ku1xcHE94nrCWxurbBlFrqu89Of/pRUKoUn3UBodiWXvmllTec/n3CJ4XlG1nzilBhaPYalSskmMYzlh1xb5eS8PsOG6p3JK85AMYScPsNjztSTV7/61QC8uG8PrSv9GAYcfnqkpnO7eHmhGvOJEStQDL3i99yefGIrhk35+9V7Mcyec9uVLEl5fYYBt89wQWF8fBxN0+ypQhaWLFnC8HDxisRjjz3Gv/zLv3DnnXc6Osdtt91GY2Oj/dXT03PG171QYbVBOXckm8aTUnEslvHE3whKljhaxDDXeDI0Lc69tDGAXEVUzHGrv7BGtVCPpe01zH+R8zLyk08+ycDAAIqsUj+9nqWrmhe8WgguMTzvyOYYOiwl11k9hiWeQHOiMnLhLWJAsRTDkSp6DC3FcDiVJq7pFbaeC/8ac27zyRl0B7mEa9eupbu7m3Q6TaZVLKwHnzzt9mu5KAvDMKrrMbRyDEuVkhPm/ebP/xDX6sU5pLSCquY00gezLR2WASXuEsMLErOzs7zvfe/jzjvvpK3NGQm45ZZbCIfD9tfJkyfP8VXOH1JJa+qJQ8XQXLtKGk/sMnLhnGSLGGZfH5wWSn+1UTWW8WRNjf2FicNToBuoS4J42pydOxwO85vf/AaAhugaFC3AK96wvKbzn2+4xPA8w+OvzpXsWDEsIIYeSzEsMv2kmlJys6rQoIpfk36HKmcu1BY/ansAdEgcna64vSRJ/P7v/z4Ax4cOgC/J5FCUYYeKo4uXJ3Qt+9BRXY9h/qxku5ScLEEMQ0JRVKPe/APmpANkDShuluFCQFtbG4qiMDKSX3kYGRmhs7NzzvbHjh2jr6+Pt771raiqiqqqfPe73+VnP/sZqqpy7NixOfv4fD4aGhryvhYrsophdVNP5EpRNYGWvJfLKYbVOpKtDMNVNTqSE4fE+upf31JhyyweeOAB0uk0bU2dKOF2Gtr8rNx6YYzJrIkYVmv7n56e5kMf+hBLly7F5/Oxbt067r///pou+EKHp8ocQ+spq2RcTRHzCWSfstI5imE25No5MZQkiV6/1WdYWznZv06Q1+ThqQpbCqxatYpVq1ah6zp69ykA9v7WVV9clIZVRoYqR+JZcTWFI/ES5oOIL38xSwfEvaPMFvQp5UXWCGKYTLrGqYUAr9fLJZdcwkMPPWS/pus6Dz30EFdcMdcdumHDBl566SX27Nljf73tbW/j6quvZs+ePYu6TOwEKXtOcnXh1kqpcGuLGBYohmnbkZwlU6fDVlRNdcrf8XjtGYaGbgjFEPCvdzYC78SJExw4cABJkmiIrENC4qLXdtc0KWU+UDUxrNb2n0qleP3rX09fXx8/+tGPOHToEHfeeSfd3d1nfPEXImzziYOReAByXZnJJ1BSMfR6zo5iCNnImr4aDCiQfcpKHJ50XBK+9tprkSSJidggSe8kR58bJT5bGzF1sfiRySWGjgKurbgacU/MUQztUnL+YpbxRMU5pgs+4HMia7xm5loy6Qa0LxTs2rWLO++8k+985zscOHCAD37wg0SjUW688UYAbrjhBm655RYA/H4/mzdvzvtqamqivr6ezZs34/V6y51q0aPaHkO90pzkeIVSsidLDK2otc5G58TQMAxOmKLGqhqIYXoogh5NI3kVfCsqK8GGYfDggw8CcNH6rcyeAkWV2Xjl0qrPPV+o/AlagFzbP8Add9zBfffdx1133cXf/u3fztn+rrvuYnJykscffxyP+STf29t7Zld9AcPqMcykkhi6jlRhFI4dV1PJlVxgPvF4S/cYTsfSxFMaAa8zd9aZRNYA+FY2gCqjhVNkRmJ4OkMV9+no6OCVr3wlTzzxBPGWY3hHGtn36BCXvqm3pmtwsbhhOZIlWUaWK/9eF5aS5yiGVim5UDFUxQOaPFnQbxvMKobW+K5UyiWGCwXXX389Y2Nj3HrrrQwPD7N9+3YeeOAB25AyMDCw4MaSLVRUOyfZMp/Ilcwnwcql5NNhy3zinBiOpTLENB0ZWO6vntRbZWTfmiYktfLvyP79+xkaGsLj8VCfWMkIk6y+uJ1A3YXzQFHVnVCL7f9nP/sZV1xxBR/60IdYsmQJmzdv5h//8R/RtNKBx4vZ+m81uUOOA7IMys5KhjLmE6uUnCWMDQGVkEkGLUneCVaaT1knYrUphpJHwW86seL7JypsncVVV11FY2MjaeJE6o/z4m9OkqlyZrOLlwd0y3jioIwMOcTQiquZMxKveI9hRhKKoTyZzns929IxhdfbDohxXq5pauHgpptuor+/n2QyyVNPPcWOHTvsnz388MPcfffdJfe9++67uffee8/9RV4AqHpOckXzibl2zSGGVik5qyTaimGD8x7DE2alq9vvxVsD+a+mjKzrOo888ggAr9zxSgZeEO9906u6qj7vfKKqf6VabP/Hjx/nRz/6EZqmcf/99/PJT36SL33pS/z93/99yfMsZuu/1WMIzpzJFjHUI5Hii4ylGCbCIijUhLeI+USSJJaaTbunq3AmWyOEjsarK0HnXaZp8Y/vc04M/X4/b3/72wFIBE8znRrm0JNu35aLubBKyaoDRzKAEcuflazmjqrUNUiZCn0BMUwjXpemNfTcB7uclg5rfJeYPFTigc6FiwsU1SqGetgkhpXMJxVcyYm0xkRU3HPVKIZWpcuqfFUDPaWROinuef+aporbHzlyhNHRUbxeL0uCa0nFM9S1+OhaW3nfhYRzrp3ruk5HRwff+ta3uOSSS7j++uv5u7/7O+64446S+yxm678ky9ksQwd9hvZTlqbZi1ke7MkMRrZhHuyQ3VQqv6/PcnNZg8idwOrLGEzUFlkD4N/UAhKkByNkpp0TzFWrVtlP9rONB3nqVwfQa7wGF4sX1Uw9MQxjTlyNxysWGl3T0KI5bRmFpWRd3GNyREKPRrM/yFHuFSWAoogWELfP0MViQyperWJolpIrmU9yXMmGYdiihlVKHjXzd32qTFPQ2QMgZHvjV9bgSE71zYBuoDT5UFrKk1HDMPjtb38LwGWXXUbf80JpXL+j84IxnVioihhWa/sHWLp0KevWrUNRsn0/GzduZHh4mFSJUupit/6rdtmqMkGS/H4wm+mLTj9RPOA1yWPevGRxkxlGKk+16DKftE5XQc7aPCqNqoJB7QYUpc6L12zcje91rhoCvP71r6e7exmGrDGoP8eLj/bXdA0uFi+sHkPZSbh1Mgnmw5IctHoMs2pCZtb8/VT9oOarDNYkIWVWqPg2Cnp9LdUw6fYZulhkqHXySUnFsIj5JJMJYxiiPcRSDK32p6WNfkej+CxYpeTeGohhwpzY5VvdVPGcJ0+eZHBwEEVR2L7lEgb2ife1fkdxbrSQURUxrNb2D2L+7dGjR9H1rMpz+PBhli5d+rJ1d3kKw3TLQJIke75kNQYUoVoIk4clyUNWMRyqQjGUJMnOfzpWY58hQGCzWU7eO15hy3yoqsr1178bvzeA5onxwP/8jGSNRhgXixNWuLVaRYYhgGwuborHIyaYAJmIeR8VqIWGodvEUJ6VihPD+DSA3WeYSo5V90ZcuFjgSCWzs5KdwM4xLNljOLeUbK1ZqlqPLJtDFmaqdyTDmZWSkzYxrDytxIrt27p1K6NH4hi6QfvyepodmC0XGqouJVdj+wf44Ac/yOTkJB/5yEc4fPgw9913H//4j//Ihz70obP3Li4w2FmGDqef2AaUUiHXwQqRNTnOZKs3Y6gK8wlk85+O16gYgkkMJSHPV1NOBmhoaOC973svkqGQkKf4l299h3Q6XXlHFy8LZMfhOc8wlDweJFNhlCQpe1/OmsSwMKomM4NhiD5eOVpCMUyGQcu4iqGLRYtqFUOr0lU0rkbX7IepYnOSizuSqwu3rrWUrCcypAfFPe5b3VR225mZGfbv3w/A5ZdfztHd4r5ffXF7VedcKKiaGF5//fV88Ytf5NZbb2X79u3s2bNnju3/9OnT9vY9PT388pe/5JlnnmHr1q18+MMf5iMf+UjRaJuXC6rOMrQiayIVFMN48cgaS+WA7CihahRDyBLDM1EM1SYfvpXiySu2p3olZVlPN6+95FrQZUanBvnud/6NeLy69+FiccIqJVcz9UQyy8gWbANKxHzAKlAMU6bDX0rKSBkpPynA35T9cyKcjaxxewxdLDKkLPOJrzIxNAwDPSz6cosSw/g0YPbAB7Ku37OVYTiVzjCdEQ9zy6tUDJN9M2CA2upHbSxPKp977jl0Xaenp4em+lYGD08DsOaSjqrOuVBQdY4hCNv/TTfdVPRnDz/88JzXrrjiCp588slaTrUokZ2X7IxkZecllyCGlgRfkGVo9WYkc0rJua5kwzAc92pYBpTjZ0AMAYKv6CB5PEzs+VHqr1pWVa8IwFVvuZS+FyYYSD/DyVMDfPvb3+aP/uiPaG+/MJ/MXJwdaCmLGFb+8NdjVoZhvvLg8fmIA+mYaeIqdCSbD1hq0gvo6JEc84migq9RKIbxKbw+M7Im5ZaSXSwupKuIqzGSSQxTzS+aY2iVkX2Nol/eRKrM1JNaHMlLvCohxVlur30NfaIE7u0tX0bWdZ3nn38eEKaT48+P2WXkxvZg2X0XKtxEz3lANeYTALnBGotXqpRsEcN8U0c2y3BuKTmW0piJZ3AKK7Lm2BlE1oBZTlYkMiMx0qejlXcogCxL7HzPK2ma3Ias+ZiYmOBb3/oWzz33nJsZ9zJGxlQMnfUY5kfVWLBDrqPFp55Yi5WSNh3M0YL7MdAkvscn8XlFBcVVDF0sNlQzK9nqL0SWkUNFeu0qhFt7imYYVkMMazeeJPvEA6Kvt7z5ta+vj3A4jM/nY+PGjRzfI679Qi0jg0sM5wWeKomhpRiWLCWXIobm01auYuj3KLSGhKpSTWSNFXI9mdaYTDsnlIWQAyqBTeJ6o0/XlknYtaaJLTvW0jzxCgJGC+l0mp/97Gd897vfZWzMVWhejtDMhIOq5iQXUQwB0rHiU0+s+AxVEyqAXhg6n5Nl6CqGLhYr7FKyA8XQdiTX1xevDpUah2dH1WRfr6XHsN8khiuqLCMbGZ3UKXF/eysQQ0st3LJlC+gyg+aklJVbXWLoogrYY/Ec9xiapeSZKomhuTilChanpeYA8mqmn4QUhW6fWHSPRM9MNQztEDMjY8+Poidrm2Tyqneupb6hntDIRaxq246qqpw4cYJ//ud/5uc//zlTU1OVD+Ji0cAOuHZSSjZVbylYQjGMm4SvsJRs9hiqhuj5nTONKDfk2h2L52IRwtB1W9BwphjWOg4vv5Sc0XTGImK9XFKh3y8XAwnxwLjcX51imBqKQEZHDqmobaWJaCKR4MCBAwBs376dkwcm0TI6DW1+mpdemGVkcInhvKBqxbCS+cSe01rYY2gRw/x4mK7G2gwo60Lig+Bw7MyIoW91I2pbACOpEdtT28LpC6i87oYNSEjM7m3gTa95N+vXr8cwDHbv3s3/+T//h//8z//k+PHjeVFJLhYntLRzxdAeh+cvoRjGzRaHEoqhR7IU/IJWiCLTTzKZWTTNNUi5WBzIpFJ2BqgjxdBcs0qPwys+9cTq5/V6xNo2FkliGKDKEm2hKoih2WNYrfHE7i9c3lC2D/7QoUNkMhlaW1vp7u6m70Wx1vZuaau6f34hwSWG8wC1SvOJXFcprqZ8KblQMbSyDE/VSAwPnaFiKEkSITP0M/rEUM29gcs3tXLxtSsAePYnp3n9a97KjTfeyOrVqzEMg/379/Pd736Xr3zlK9x///0cO3bMjbhZpLAVQwfZqKV7DMW+maQ5YaiEYuhRmsRxChXDvOkndciyuF/c6ScuFgusOclIkqN7rbJiWKKUbCqGVo/hiDn1pKPeh1zFFBFLMVzhr8GRTOX+wn379gGwefNmMKDvJZMYbm0rt9uCR02uZBdnhmpdyXZcTUVXcj4x9NnEMF8xXNZsEsPJ6ojheksxPENiCBC6ZAkzD/aTHo6RPDyFf31L5Z2KYMdbVzJyIszgoWnuu/0F3vm3l/K+972P4eFhnn32Wfbu3cvs7CxPP/00Tz/9NIqi0N3dTU9PD11dXSxZsoSWlhbkGoaru1g4sBXDKnIM5RKlZKu5fo75xFQxPGoLaYqZT7JB85Ik4fW2kUicIp2eAFZU8W5cuFiYsI0nPj+Sg89MfTbbY1gUFjHMiaqBnFKyxyKG4rwdVRhPMrrBYLJ6xdAwDFIns4phKcTjcY4ePQrARRddxNjJWeKzaTx+5YKbjVwIlxjOA7KTT5yWkk3F0In5xDDsCQ5WKVnTYmQyUVRVuMJ6WkTvw8mpIrOXy2B98OwohgBy0EPo8qVEHhtk9pFTNRNDWZG59v/dwo//aTfTIzF+9rU9XLfrFXR2dvKWt7yFa6+9lmPHjnHw4EGOHj3K7OwsAwMDDAwM2MdQFIWWlhaam5tpamqioaGB+vp66urq6O7uxu8wyNXF/CGrGDooJcfy5yRbsHqmMskEeJk7J9larHytpCnfYwjYxLDwwcyFiwsVlmLodRpubSuGJYihbT7Jfv7retIe42qNdh01ieGSBudl5MFkCs0AnyyxxMHnQvaaU+izaZDB011XcruDBw+i6zodHR10dHTw7C/6AFi2vhlFvbCFBpcYzgPsXqaEM4JlmU/0UuYTa/i4oUEibMdmKEoIWQ6g63FSqfEsMWw2ieFkdcTQKiWPpDJMpzM0ec7s16fu1d1EHh8ieTxMsn8G34raZmL7Qx7ectM2fvql55gcivJfX9nDWz+8jVCjD1VVWb9+vd1/OD4+bs+0PH36NKOjo2QyGcbGxoo6mv/sz/6MZcuWndH7dHHukXUlOyklW67k/OZwS8lPJVOCGJZQDL3+DqKU7zGE4qkALlxcyEhVOyfZVgwrlJIDWWJoB8lLKqoq9rNKyUuqUAxPmmXkZT4vchX9fumTYp31LAkhe0tnH1qTTi666CJxvv3iupdvqk3kWEhwieE8IFtKdqgYmv0ZJQOuPX7w1kEqIlRDkxhmy1knSaXGCAZFOaunRSglU7E0kWSGOp+zX4N6VTiTB5NpDkcTXN5U+mnKCdQmH8GLO4g9O8LML/to+8CWmht2G9sDvP2j2/npl59nYjDCT76wm7f+5XaalmQXf0mSaG9vp729nYsvvhgQ4aThcJiJiQmmpqYIh8PMzMwwOztLJBKhoVRvjIsFBS1TjSu5eI+hpYKkzbDsXMXQMAzSaUH4fCGRUVgurgayjfO5OaIuXFzIyC0lO0EtiqFlPPF4WpAkobyN2Iqhc2JYs/HEJIbenhLXDKRSKY4fPw7Axo0bSSUyDB8TuYc9LjF0UQuqHYlnEUMrE6oogi0mMZyE1tX2yz6bGGYXp3q/h6agh+lYmpOTMTYudU5+1oX8ghjGkmdMDAEarllO7PlRoRoemca/rrnyTiXQ3BniD/7mYn7+f/YwM57gh7c9wzV/ehEryzQCy7JMc3Mzzc21n9fF/COTcj4SzzDjaub0GFoPbFZOZ475RMxJFq/76kXc0lximDWfQK75yyWGLhYHrKkn3oCzLEHNUgzrShFDM1YsTzG0omqyr43MZs0nTpGNqjn7xPDYsWNomkZzczPt7e30vTSBrhs0tAcu2GknubiwC+EXKLLE0OnkE5MYRqMYmRLh0lVmGZ5pOflQ9OxEcKhNfuqu6AIg/IsTGNqZTS9p6gjyh/+/S1m6upFUQuP+f36RR/7jEOka8xJdXBjImOYTZ5NPzB7DOXE15n2ZMX8Hc4ihpRYqShC1TjxEaNFSpWSz5FzC/OXCxYWKlD31xBkxtKZ1FVUMDSOHGObOSc43nkBuj6FzxdAKt15exdQTQzdIDZr9jWWI4aFDhwBYv349kiRly8gbL3y1EFxiOC+we5kc9hgqdVllrmQ52XriKjn9pIAYmuXkk1PVEbwNJjE8EDlzA4qF+qt7kAIq6dNRIk8OnfHxgg1e3v5Xr2Dr60Rv4N5HBvn+p58UMyzdsXmLEtkcwypKycH8J3u7lKybfUW+7MKQzogykUdtQjbvRyMWw9ByHjisxS0RBl2zpzZY+YcuXFzosBVDp6VkSzEs1pKTnAHdFDqKlZJzx+HVUkquQTHMjMUwkhqSV0btKK786brO4cOHAUEMAU6Z006WbVwclSeXGM4DrGBQp4qh5PHYi1jJcnLJLMPiIde1KoYX1Ylr3xeJnzWSpYQ8NF7bC8DMr/rRws5K7GWPqcq85t3reOuHt1Hf4icymeQX//clfvKF3Qzsn3AJ4iJDVTmGMYsYFnclpw0FPEFQsuqjpRiqniwxhIJysjUrGSARdhVDF4sOVSuGM2UCri3jiRoAT/Z4WcVQkMVEWmM6Ju7valzJlvmkmh5Dawyep6sOqURe4uDgILFYDL/fz/Lly4nNpJg6LaoH3WtdYuiiRqi2K9m5WmeVk6sei1cqy9CMrDlVZWTNuqAfVYKpjMZQ8uyFRYcu68TbU4+R1Jj80WEM/ewQt+WbWnnPp3ZwyRtXoHpkho/P8PP/8wI/+Ptn2PvbQZLx2uc+u1g40NJV9BjGSs1KthRDeW5UTXpabONpQvZ6kUwCmhc6r3jAay6AsUm3x9DFooNtPnEaVzNbJuC6iPEE5s5JHjP7C72qTGPAWexMXNMZTYnP9p4qFMP0kFlGLhNTY2UXrlq1CkVRGDwsHhpbu+vw1zmPxVnIcInhPMBWDBPOlTHbmTwTLr5ByZDrUj2GZim5ypBrvyKz1swz3Bc5e6O+JFmi+V3rQJVJHpkm8sSZl5QteHwKr3z7at7791ew9XXLUL0yE4MRHvn+If715se4/5svcvCJ08RmUmftnC7OLzK1jMQrKCV7ckvJvnyFI5NDDCEnQqog5Fqzy8nT9sKWyYTRdfd3y8WFj3SVOYZWhau4YjjXeAI5E4a8+eHWnQ1+x6kVVrB1SJFpVktHzhQiNZRVDEvh2LFjAKxeLUyeg4enAehe3+T4PAsdrit5HmApE7qWQcukHU1rsJp3S08/KTUvubhimBtybRhGVTExF9UFOBBNsC8S5w1tjZV3cAhPR5CmN69k+r+OEb7/BN5l9TVnGxZDqNHHa969jsvevJKDT5xm/+9OM3U6yokXxjnxgvj3aekK0bWmiSUrG+hY0UBTZ7CqEUwu5gdaqoq4GrOULJXKMdSVORmG6QJiqNTVoU1M5N2Pw+EEU2GVjcDg0Cm6ui9GklQMI0MqNYHfv7SWt+bCxYKB1f7kpJSsJ5MYZr5oecWwYOpJOr+UnM0wdF5GPmVlGPq9jtc2QzdID4mScCnFMB6PMzg4CMCaNWsAGDIVw+4zSNRYaHAVw3mAx5/9BXeqGloBoVq4th7DZDLfeLGsOYAsQSylMRaprqfP6jPcexYVQwuhVy4lsKUNNIOJf9tPZvrsmVws+EMetl+znPfcejnv/rvLuPRNvbT1iA+CyaEoe387yEPfOcB/fOYpTh2crHA0FwsBtbiS5/QYmsQwU66UrDaJfa1pRCYxTGV0/uJ7uxnXBNm857cvktGzzkrXgOJiMcDqMXSiGNr98JI0R50HikbVQDbg2lugGFYzDu9UQjwoLvNVYTyZTGAkNVBl1BKRM8ePH8cwDNra2mhsbCQaTjI1HAOJC34MXi5cxXAeoKgeZEVF1zKkkwn8dZXzAO0sw9nqiKHPjKsxjBSZzDQej3iq8akKXU0BTk3F6RuP0VHv/KbbbBLD/eeAGEqSRPM715EZi5MejjL+7b20/++tKPXVZVE5PVd7Tz3tPfXseNsq4rMpho5Oc/pomNH+GcZPRug4i4qli3MHK+C6qsknpUrJxtxScjozLbYx7x97frlpPvmPpwd4bmCaqF/sNzs1xr/+7gTb/K0kUyOuAcXFokDannxSWTG0+wvr64vPVS4xJzltPkR5rDnJsyYxrCLD0DKe9FRhPLH6Cz1LQ0hKcZXRKiNbauHpo6K1q7WrDn9ocfQXgqsYzhss1TDl0IBS0XwSMkOco/m9hLLsw2O5u5IjeT9b2SZG5J0YLwjqrYBNJjE8EU8RyZz9fEDZp9D6vy5CafKRGY8z9u2X0M5D/1+g3svqV3Tw6net5Q/+5hI+8JXXLqqbfTEjOxKv/P+XkUqBaVSZYz4xiaFmyGjeAmI4p5Scrxj+9rC473q6RERSkxThvpeGs5E1LjF0sQhQjfnEarMo2l8IRc0nmhZH00SrhxVwPTZjhVtXoxha4/Ccf36nrfzCrlDJbaxpJ6tWrQLg9LFpALrWnL2WqoUAlxjOE6wnrkyV009Kmk9CQhkkMQ1avlvY5+sAIFWSGFbnTG71qnSZN9xL50A1BDEur+3PtiDXe8mMxBi94wXSo9Vd55miVFyBi4UHO66mgmJoqYVQ2pUMkJYLiaEoe9nmE1Pl12cjaLrB0yfEItfe0QlAExH2DoaRFHcsnovFg2wp2YFiOFPGkQxl5yTLshdFEffYaA1TT2pRDCsZT6anp5menkaSJFasEONlLcWw0yWGLs4G7GgMpyHXlvmklGIYaAZzruTccrKY7ZpMjua93tsqiGHfeMEEBwd4RYMow+2ZOXdkzdMWoOPPt6K0+tEmE4zevof43sWjvNx+++309vbi9/vZsWMHTz/9dNntf/jDH7Jhwwb8fj9btmzh/vvvn7PNgQMHeNvb3kZjYyOhUIjLLruMgYGBc/UWFgzsHkNveYXAJoYejx05Y0FRVaxngbScv/AVKobZUvIsB07PMJvMUO9TaWsX91q3L4GmG0zExD3mRta4WAzIlpKdKIZlHMlQYk6yVUZusU0jo1YpuQbzSU8VPYZpM4vQW4IY9vX1AdDV1YXP5yOVyDBu5h4uXd3k+DwXAlxiOE+wmndTSaelZPFEopUKuJaVbJ9hQTnZ57WI4XDe6yvbLcWwemK4vV4Qw+dnz62Kp7YG6PjgNrwrGzCSGhP/foDJHx5Gj529DMX5wA9+8AN27drFpz71KZ577jm2bdvGzp07GR0dLbr9448/znve8x7e//738/zzz3Pddddx3XXXsXfvXnubY8eO8epXv5oNGzbw8MMP8+KLL/LJT34Sv8NoiQsZ2RzDCoqhFW5dZNarJEl4VLEYlSaGoh8qt5T85HGxmF3a24xsLnLLA0Ll6J8273O3lOxiESCVrEUxLEEMiymG5tSTvHF4s9WVklO6zmkzY3eZwwxDbTaFHkmDBOqS4saTEydOANDb2wvASN8Mhm5Q1+KjvmVxfca6xHCekFUMnZaSrYWoBDGEbDm5kBhaimEqn3SstBTDiSh6lYHSlmL4/DlUDC0odV7a/2wLdVctAwliu0cY/uKzRJ4cwsjo5/z85wJf/vKX+cAHPsCNN97Ipk2buOOOOwgGg9x1111Ft//a177Gtddey80338zGjRv57Gc/y8UXX8w3vvENe5u/+7u/401vehP/9E//xCte8QpWr17N2972Njo6Os7X25oX6JqGoYvfg0o9hnqJcGsLHkXcB2kp+0Gv62k0TSgDqioe0Owcw9kITx4Xi9mOVa22+tGuivvi4KjIULMWPBcuLmRUoxja4/DqS5SSLVdyrmJoZxiK15KZ7NQTp6Xk08k0BuCXJdq9zvy16WEhjqitAWTv3NxDwzBsxXDlypXiPGYZebGpheASw3mD7YB0aj6xFqJScTWQJYaRfGLoNXsMkwU9hsuaA6iyRDKjc3qmuliYrfVBJEQvx1jq3Kt3kiLT9MaVtP/vragdQfRYhul7jzH8xWeZfWwQPXHhTDBJpVLs3r2ba665xn5NlmWuueYannjiiaL7PPHEE3nbA+zcudPeXtd17rvvPtatW8fOnTvp6Ohgx44d3HvvvWWvJZlMMjMzk/d1ocEqI0PluBojXloxBPDIJjEkqzRYc5JBwuMRxFAxS8laJMIzfWIxe+WqVtth2WAIteTAiEkM3VKyiwschmFUZz6xxuGVUgyLxNUUZhjaU08UmaagMyOJ1V/Y7XOeYWiVkT1LixtPpqenCYfDyLJMT08PAMPHLWK4uPoLwSWG8wZbMXQ4L1lpNEvJpQKuobJiWEAMVUVmuRl0XW2fYYOqsCYonuDOZZ9hIXy9jSz5yCtoettq5HoP2nSS8H8f5/Q/PMXkDw4RPzCBkV7YKuL4+DiaprFkyZK815csWcLw8HDRfYaHh8tuPzo6SiQS4XOf+xzXXnstv/rVr3jHO97BH/zBH/DII4+UvJbbbruNxsZG+8v60LuQkElliWFlxdCak1y8XOSRhcs+lxhaU09UtQFJEkRPNkvJiekw4XgaRZbYtLTBJoZqcprupgDhpNjONZ+4uNChZTLomrg/HJWSTcXQulfyf5iGpPkQmhNXU6gYWmXk9nqfY5J3Mifc2iksxdDTWZwY9vf3A7B06VJ8Ph+GbjByQlx/56rFRwzdHMN5gj1lwan5xArUnZkpPamkIjGc27+2si3E8fEox8ejvGpNm9PLB0Q5+UgsyZ7ZGK8/ixNQKkFSZOqu7CJ02RKiz40S+d0gmdE4sedHiT0/iuSR8a1qxLuyEd/yBjzddcg+52ORLkToZin17W9/O3/1V38FwPbt23n88ce54447uOqqq4rud8stt7Br1y777zMzMxccObQyDGVFRZbL/z9b5hMpWEIxlDKAStrIfjRm+wuzv+OW+SRpKvjLW4J4VTm7yCXCrFseYE+/2C6Vnqh6wpALFwsJudWtXAd/KejmHPGiiqGlFiJBoMl+OdtjaBLDmSwxdIpBK9zaX0VUTQXF8OTJkwC2G3lqJEYqnkH1yLR0l463uVDhEsN5giXFZxwqhpb5hHQaI5FAKlYKs7MM8xvdLfNJKjWOrmeQ5ex/uxVZc3ysuixDgFc0hPjP4Sl2h89vjIwFyaNQt2Mpocs7SZ2cJfb8KIl9E2gzKRKHpkgcMj98JFBb/KhLQqhtftQWP0qTH6XRh1LvQQ56zms0TVtbG4qiMDKSr+COjIzQ2dlZdJ/Ozs6y27e1taGqKps2bcrbZuPGjTz22GMlr8Xn8+HzOf/QXYiwxuE5mpNs9xiWUAxJAX4xFs9ENqomq2zYD2rm4rfKvI/wN5lbGGxpk3j0iCCGhpEhk5nJI5cuXFxIsMrIqseLrFR+0C6rGFrGE3+jME5a57AUQ6uUHKk+qsaak+xUMTQ03Y5CK6UYWskOy5cvB7DVwvYV9SjK4iu8usRwnmD3GDolhqEgyDLoOtrMTPEeqTrTZFCgGHq9rUiSgmFopNLj+H1Z8rF2iVi4joxUTwwvbxQ30TMzUTK6gTpPuX+SJOFb3oBveQPG21aTGYmRODJNsi9M+uQs2kyKzESCzESJf2sZ5KAHOaAiB1Qkv4rsU5B8Cg2vW456lh1nXq+XSy65hIceeojrrrsOEIrfQw89xE033VR0nyuuuIKHHnqIj370o/ZrDz74IFdccYV9zMsuu4xDhw7l7Xf48GH7KXexoqpxeOVKyYZhEkNI69kP+3Ra9BJZUTWQXeykqEkMTYc/qhe89ZCaZWNDhozhIakF8SkxUqkJlxi6uGCRqsJ4Ajk9ho3l5iQXjMOzFEM73Fp8ZlejGFpRNd0OiWFmLA6ageRTUJrnnicWizE2ZgbYm9WUkRNmfuHKxXk/u8RwnuCtspQsSRJKfT1aOCxmUBb0mwElS8mSJOP1tpNMDpNMjhQQQ7HAHR4p07tYAhtCfhpVhXBGY28kzvaG4irM+YQkSXg6Q3g6Q9S/phsQUQTpkSiZsbj4mkqgTSfRZpLo0QzooEfSIq6gAHWv6j4n17lr1y7+5E/+hEsvvZTLL7+cr371q0SjUW688UYAbrjhBrq7u7ntttsA+MhHPsJVV13Fl770Jd785jdzzz338Oyzz/Ktb33LPubNN9/M9ddfz2tf+1quvvpqHnjgAX7+85/z8MMPn5P3sFBgR9V4Ky8EejnzSSqK1+oxzBnok86YiqGaqxiKBypPIo5k6Kxqz8k+CzRDapY19eK6ZlN1+AIxUukJQqxy/sZcuFhAyBpPKvcXQu5IvGLEsPic5GyPoYirqTaqBrKl5G6HU09y+wuLtXpYZeTW1lZCIfEAOGwqhktWLs6RqS4xnCdkXcnO3cByYyNaOFw6y7AEMQTRZ5hMDs+ZfrK2I5suH46laXTo/AJQJInLGkP8emKGp8KRBUEMi0Gp94pZy2ua5/zM0HT0aBotkkaPZzDiGfSkhpHU0JMaSsPZn9EMcP311zM2Nsatt97K8PAw27dv54EHHrANJgMDA8g580WvvPJKvv/97/OJT3yCj3/846xdu5Z7772XzZs329u84x3v4I477uC2227jwx/+MOvXr+fHP/4xr371q8/Je1goyE49qfy7a9hzkossbskZVIsY5jBDq8dQzesxNBVDDAKZFKvziGEThAfoMbMMpxIh2gKuAcXFhQ1LMfQ6VgzNuJpiPYYl5iTP6TG0iKHDcGvDMKouJadHrDJy8fXLIoZWGTmd1Jg0x+ctcRVDF2cT1ZaSQfQ1pQGtVGRN7rxkw4Ccpx/LgFI4L7ne76Gr0c9QOMHh0Vku681/gquEHRYxnI7yvy8szwIgjCxKgw+lilT9s4WbbrqpZOm4mMr3rne9i3e9611lj/mnf/qn/Omf/unZuLwLBppdSnagGEbLlJKTs3gkkxjmjKosnHoCIPl8oKqQyRBMJ7KlZLAXO39mhu6mNmZTYmF0I2tcXMioJqoGKimGc0vJup6080I9HksxNKeeOCwlj6czJHUDCVjqVDG0iGFHcWJY2F84NjCDYUCoyUddkdLzYsDi65q8QFDtSDzIiaypNC85k4BUfs+gzywfF04/gTMrJ7+ySSglT4YjGEZ1IdkuXJwNWD2Gjswnliu5WCk5MYNXFu7u3PsyU6THUJIkCInf/SVymtZQDim1FrvYJOuW1DGTspzJbsj1fKKaEZQ/+clPuPTSS2lqaiIUCrF9+3b+7d/+7Txe7cJDNty6cilZT6UwzHvIarvIQ7EMQ7OMLEkeVFWsSZYr2Wkp2SojL/F68MrO6E16xAy3XjLXeKJpGkNDQwAsW7ZMXFO/WCc7VpTIZ1wEcInhPMG6uaoihk2CGOrhEsTQGwKP+ctdUE72+7sASCSG5uy27gwMKNvqA/hlicm0xqFYdSHZLlycDWRdyU56DMu4kpPhbI5hjpKfzkwD4FGb8jZP+8Ux1oTI702yymPxKdYtqbcVw8JS8oFInFuPDPLRAwNEMhouzh2qHUHZ0tLC3/3d3/HEE0/w4osvcuONN3LjjTfyy1/+8jxf+cKB1Q/vpJSs5+TtynVFiGFsrmKYsuckNyNJkpg1HhUPfU5LyVYZudthVI2e0tAmTSW0SCl5dHSUTCaDz+ejtdVUMftExa6jd3H2F4JLDOcNHjMipKpSclMTAJnp6dIblYis8ftKE8MzUQy9ssyORnHjPzpZPbF04eJMUZUrOV6hlFyMGNqKYX4/UdwrFsgVhQJKDjFc3Z6rGGaJ4WNTs1zz7CG+dWqMe4Yn+cSRwYrX7qJ2VDuC8vd+7/d4xzvewcaNG1m9ejUf+chH2Lp1a9nop8WOahRDqw9erqtDKhZtE5/bY2gZTyxH8mQ0haYbSBL5inwZ1ORINkAOqSh1c/c5deqUOF53t93z7SqGLs4Zqp18AsJ8AmUUQyhpQLEUw2RRxdAihrURu6taxP6/mbzwxqm5uPBhuZJVB65kw46rKV5KtohhKq+UPC2On1NKBoiq4h7uVgvUPpsYTrK8NUgkbRLDHMXwy30jaAa8whwtec/wJPeNTVe8fhfVo5YRlLkwDIOHHnqIQ4cO8drXvrboNothtGQl1KIYyqXG4cWsUnKWGFqtFp6CcXitIS+qw6zAmh3JRcrIkCWGVhk5EU0THhMEuWO5qxi6OMuwbi6ncTUAqqkYamUVQ2tecn6JxCaGqRF0PX+u8NqOOiQJxiNJxiNJqsXVJjF8YjpCUl/Y4+hcLD5YrmRFdR5wXbTHMDmLRzJ7DPNKyaZiqOYrhjOKUP1bpVTe63bfVGyS5S1BZmzziVDxX5yN8fh0BFWCf9ncy03LRf7oF04UH4fo4sxQywhKgHA4TF1dHV6vlze/+c18/etf5/Wvf33RbRfDaMlKsO4JR4qhSQyVYsYTyPYY5pSSbcWwINy6re7chVtbwdbqkuLGk8FBoeRbxHBsQLyvhjY//jrnCR4XGlxiOE+oyZXshBhaIdeRfPex19uGJKki5DqVTxpDPpWVreKJad9Q9U+6G0J+lnhV4rrBM+HqZi67cHGm0GownxQvJWcVw4z5wKbrKTTNVBUKFMMpSSw+zUYBMbQWu/gknQ1+EhmxOCaSQjH81kmh5r+to5kuv5e/WN6BKsHBaIKjbp/ugkF9fT179uzhmWee4R/+4R/YtWtXyUzQW265hXA4bH9ZESeLCXYp2dE4PIsYllAM7VJybo9hwZxkM9y6o8F5huGpKuckZ2zFcO7nQTweZ3xcPMx1d4s829F+s79wxeJVC8ElhvMG66krk0xiOFTZrFKyNl2mlFy/VHyfzX8SliTFdiYX6zO8qFsce+9gmWOXgCRJOeXk6vsUXbg4E2RSZo+hk4Brq5RczHySW0o2H9jSGetBSbKdkiDKi+OGIKINWoHKnqMYyrJEnani69o0yUya+8fFPfZn3aIfuNmj8ppmcez7Rqu//1yURy0jKEGUm9esWcP27dv567/+a975znfagfOF8Pl8NDQ05H0tNlRTSrZ7DIv9OxhG0RxDy5xVqBi2V6MYmqXkLqelZGsUXsfcUrLlRm5ubraDrcfM/sL2RdxfCC4xnDd4cubTplPOyreOSsn1ZrmkQDGE8s7kLd3iBt43VNvCdHWL2P/B8cXXW+NiYUPL1OBKLhpwPYunIK7G7i9UG5CkbBP9VCzNjCIWyEAqnn+coHAvWuWy9oYOdEO4lndPjxDTdFo8Sl4g/FvamwD4b7fP8KwjdwSlBWsEpTVS0gl0XSeZrL7VZrGgqriacophOgbWw1SwmGIo7h+rx9DpOLyEpjOeFm1SThRDPaWhTYtzFCslW8TQUgsBxk5axpPFR/xzURMxrCYP6u6770aSpLwvv8OAzMUM1euzA6idRtbYimE580md+QQ8e3rOj2xncnLuzzZ3WYphbcTudS31qBIcjiU45pbDXJxHZCefVM7rN8rNSk5MZ0fimfdkNtw6v79waDpOxCMWSClW0D5hLXbJGcikWN5SRyQtFIffTQqyeEVTHXJOxM21bY0oErwUidMff/mSj3OFXbt2ceedd/Kd73yHAwcO8MEPfnDOCMpbbrnF3v62227jwQcf5Pjx4xw4cIAvfelL/Nu//Rvvfe975+stzDuqUwytcOsixNDqL5Q94M1G2aTtqSe1EcPTSfE5EJBlmtQiTugC5DmSQ3MVRosYLl0qqnCJaJqZcfFv0LasSATPIkLVk0+sPKg77riDHTt28NWvfpWdO3dy6NAhOjo6iu7T0NDAoUOH7L8Xm0f4coMkSXh8ftKJuGNiaPUY6tEoRiqFVKx0ZimGs8UUQ/MXvFgp2SSGA5OxqkfjATR6VF7dVM/DU7PcPxbmL1e45N/F+YGWsnoMy6sEhmHk5BgWH4mXG1dj6HqO8aQpb9PB6ThRkxjOCZz3NwISYEB8ip6WILNT9TR4IzwZTgIqVzTlLyytXpXLGkI8GY7yu+kIKwKLc6LCfKHaEZTRaJS/+Iu/4NSpUwQCATZs2MC///u/c/3118/XW5h3VKcYOhyHl8MFUqn8HsNqiWHWeOJxxDEylvGkxMQTixh2dQlBZfxkjvGkCJFcTKhaMaw2DwoECers7LS/Ct1hhXg5WP8h15kcr7ClgNLQYN9IJeclWz2G0VEo6F30lYmsaQx66GkRN/y+07WVk9/YLsjlL8bdPikX5w8ZhyPxjERC9DcBUokeQ0sxBEEOM0XmJEO+YqjPFPTVyoqYlwwisqYlyEyqjgwKu6PiI/dVTXMVh8sahar4rGvgOie46aab6O/vJ5lM8tRTT7Fjxw77Zw8//DB33323/fe///u/58iRI8TjcSYnJ3n88cdf1qQQckbiOTCfZBVDZ+PwIFcxzCeGTsfhZfsLq3MkFxuFF41GCZuVOUsxHBsQcW7tPYu7vxCqJIa15kFFIhFWrFhBT08Pb3/729m3b1/Z87wcrP+Q40x2qBhKimI385bsMwx1ABLoGYjlT1qwewyTc4kh5JaTayN217Y1IgHPzcQ4nUxV3N6Fi7MBzewrquRKttRCADlQZHFLzqBKOpIsHr6S8VhOuHVT3qaDU1liWPQhLceAsqI1xGyynhOsJmHItHgU1ofmnv9SmxjGyr4PFy7mA5aA4S2mthdAc6QY5s5JTpExjV7eM1QMnU49saNq2kv3F7a2ttqtb1Z/YdtylxjmoZY8qPXr13PXXXfxX//1X/z7v/87uq5z5ZVX2sGRxfBysP4DeM2RWk4VQ8iZl1yqz1BRs9NPCvoMs9NPik9Z2LJMHHvPyWnH15OLJT4Pl5uL209HajuGCxfVwunkE8uRLPn9xacxJGaQJPCaikgqHi85Dm8onKsYFiGGOZE1PS0BZlJ1HGE9ADsa8/sLLVzSIO6dw7EE0+nMnJ+7cDGfSMWdE0PdSY9hboZhWrwmSQqq2kg8pTGbFPeAU2I4VKViaJWSi0XVFJaRIVtKbneJ4Znjiiuu4IYbbmD79u1cddVV/OQnP6G9vZ3/+3//b8l9Xg7Wf8jeYKl4FcTQkTPZNKAUOJP9fuGuymRmbSUkF5csF9EBz/ZNYZglt2rxzk5xjP8cnqz5GC5cVINsjmH5BSEbVVNkYTMMSIh7IntfZhXDwlLy4HTCsWIY9KpkaGaAFQBsriu+sLZ5VVaZvYW7Z1zV0MXCQrbH0EEp2VYMy5SSrXYLsv2FqtqEJMn2oAWfKlPvc2aFqEYxNDI6mQlRqSvWY1hIDFOJDFMj4p50S8kFqDUPKhcej4dXvOIVHD16tJpTL0rYC1DC+SKgNDnIMrSdyfkqrqqG8JiOr3h8YM5u23qaUGWJ0dkkp6ack9VcvLW9CZ8scTCaYF+ktmO4cFENMg5H4pV1JGcSoIvjeM3+w1Q8bvcYFpaSh6bjRLzi/jWSSfTCGJMcxRBEQ71FDC8qQQwBLmkU53b7DF0sJGiZNFpGKHhWpascyiqG9ji8XMUwf07y6Kwgbe31Psdm1ew4vMqKYWYiDrqB5FNQGuZuf/q0qLZZ/YUTpyJgQKjRS7DI9osNVRHDs5EHpWkaL730kv0P/nKG5e5KV6MYNjYBTrMM55b3g4HlAMQTc8vzfo9iB13v7p9yfE25aPKovKFVHOM/h2s7hgsX1cCalVypx1CLCrIlh4rMRU1kg6y9QXO2cSJedBxeKqMzNpskrmYjp+aUk3MUQwCfr4NBRK/0xrrSistlZjn52RmXGLpYOMgd3epMMTRzDMsphrkZhma4deGcZKfGE8MwqlIMM+a8Y7U9MId4RqNR2/BqCV7jp4Tx5OXQXwg1lJKrzYP6zGc+w69+9SuOHz/Oc889x3vf+176+/v5sz/7s7P3Li5QnFEp2VGW4VxiGLCIYWyuYghw6QqznNw/6fiaCvHunHJyTHNnJ7s4t8g4HImnl1MMkyax8zdk78tYLCfHsMne1FIzPB4V2Wyun1NOLlAM03VLyUge/Eac5WXCd7eZodf7InG3FcPFgoElXigeD4pavrRrpNMYVixUXZG8vyLmk6xiWFuG4UxGI2quNUsdKIbpsdKOZMsv0dLSYhtPbGLYvbjzCy1UnWNYbR7U1NQUH/jABxgeHqa5uZlLLrmExx9/nE2bNp29d3GBwuu3Ssk1mE+c9BiWI4aJ0sTwXx47wbN9tat9r2ttoMfv5WQixU9Hpvjjrtaaj+XCRSXYI/Eq9RiWVQzNBy1fIz4jawrLeOb2GI6YM1yXNPhQ6hvQwzOliaG5CEaD7aBBDwNIUunqyrqgHxmYTGuMpDJ0Ohzt5cLFuUQqLoiU10GGoRaJ2H8uOvmkmGJoTT0pUAwdG0/McOsWj0JQqax3ZUYtxXAuMbTKyLntcZbxpO1l0F8INRBDEHlQN910U9GfFQ4Z/8pXvsJXvvKVWk6z6JHb5O4UjhTDEuYTyCGGRXoMAS4xFcNDI7OE42kaA9UvTIokcWN3G585NsS/nBrj/1na4oaauzhnsIihx1t+EXFEDP0NeMhRDAPT4tg5ruSRGbFoLan3ozQ0kKZyKXnG2wDxFCs4TiYTRVWLXAMQUGRWB30ciSXZH4m7xNDFgoA99cSRI9mckxwMIhVTF4sphqmCDEN7TrKzQQmnEmYZ2WmGoaUYts99P5ZiaLW76ZrOxJD47FjsE08suLOS5xG2YlhVj6EDxdBJKTlePAKoo8HPqvYQhgFPHJsouo0TvGdpCwFZYn80wWNTkco7uHBRIzKm8UP1VSKGZim5GDG0Ssm+bCk5mYja2WqeooqhP5srWhhyXVBKHjXnLC+nn3S6/H21yTSnuOYtFwsFqSqmnpQdhwflFUPLfGI+fHU0VKcYdjlxJBtGXo9hIQqNJ9OjcbS0jupTaCyy/WKESwznEd5gDTmGTuJqGkxjz+ww6FrejyximEgMoevFQ6hfs0bkID52dMzxdRWi2aPynqWihPzl/uIZly5cnA1kUmIR8VQihuZM4+JzkrM9hj7TlZxOZtspVDWXGGYXLcUmhgUKfoFi2G8aZJbTTyRW/r6yXMsHou7McRcLA1ZUjaNSsnkvFDWe6BrEp8Wfg9kWo9KKodOpJ84VQ302jZHUQAa1Nf/9JJNJJibEg1vWeGKWkbtDdvj9YodLDOcRNSmGzaLUq02V6QGs6wRJFvEbkdH8c3rbkWU/oBedmQzw6rXtADx6ZNzxdRXDTcs78EoST0xHedxVDV2cI6RNYlgprsaRYuhvtFWRVGoaAEWpQ5azSoSlGHY2+G3ziT5bSjGcIpLOMGoGVndxiuHp/OD5QriKoYuFBmuNcuJItkvJjUWIYSIMmKaqQHP2+KaKXuucZFsxdNB6YZWR1ZYAkppPgawovvr6eupM48z4SdN4suzl0V8ILjGcV+TmpTmF2ipunMxUmRBqRYV6M7F9Jn/KiSRJBAIiNqNUn+ErV7WgyBL9EzFOTtYetNvl9/KepeJ6P3/itOuydHHWYRhGtpR8NnoMfQ34TEUxY0XVFIRb55aSlQZrElGJHkND43hYLHohPUKIGBMz5RX0Tea4vKOxBEnddfW7mH9UNQ7PLCUrxeYkW2NafQ2gZElcKkcx1HXDDriudhzesjKOfwsZixi2le4vzDWeTJiO5NaXSX8huMRwXlGTK7nFXHDS6bkqRS4axZQTwnNHD1bqM6z3e7h4eRNw5qrhR1YsISDLPBWO8l+j02d0LBcuCmFF1YCTUnKZuJqcUrJ1X2q61V/YlLepRQxFKdmMq5ktIIYeP3gEAT0eFup+q3m8mWi+il+IpT4PzaqCZsBht5zsYgEgbZlPHIRbly0l28aTrFqo6xky1uhJbyvT8TRpTYgIbY5Lyc4VQ9uR3DGXGFqKYe7Y3/FBSzF0iaGL8wBPwAq4dq7KyT6frXhkJso0sTeUI4ZiAkMsfqLk7q8xy8kPHZjrbK4GXX4vf7miA4DPHhtycw1dnFVYjmQ4Q8Uw13xiEkfNEAtC4Zxkq8ewM8d8ohcqhmD3UB2NiPO2IxakWKJ8j6EkSWww3ZgHXWLoYgGgulKyaT4pVkouYjyx5pGDuNesMnJz0INXrUxRdMPgtG0+qSLDsEhUTaFiGJ9NEQuLz5iWruJJAgsJg5HByhs5gEsM5xHZkXjV9RIprWLBKdtn2LhMfJ+Z+4sSCq4CIBY9VnL3N1wknpgePTpOxBxmXis+2NPBMr+HwWSa244X72t04aIWWGVkWVGRFaXstuVLydkeQ0sxNAyxvZqjGEaSGft+6MgtJRdT783F73hcLCxLVWEES6cqu/3XBsUCfMQlhi4WANJVlZLNOclFS8nFomqsqSfNyLJadX/heCpD2jCQgU5vdVNPcqHruq0YWsRwwlQLG9oDeP01pfudNxyfPs6bf/JmPvw/Hyatpc/oWC4xnEfkmk+MKnqJVNOAUlYxtIhheG65OBhaA0A0drzk7uuX1LOyLUQqo/PwofKlr0oIKDL/tE70Nd55apzHpsqUwF24qALppDNHMjhUDP0Ndu+vIZnKQu7UE7OMXOdTqfOp2VJyoSsZICTc/cdSoiy2wly0DL1yePw6s8/wSCxZYUsXLs49UrW4kssqhllHcnYcnjn1JJKdk+wEp8z+wk6fB7WCa9hIa2hhsye5oMdwcnKSTCaDqqq0mC1bE4NmfuEFMPHkn1/4ZzRDQ0LCo5xZ/qlLDOcRuU9f6aRzZcBWDCfLLDB2Kbm0YphIDKJpxdVKSZLYeZF4anpg75nHzbyutYH3mvE1f3lggLHUmT3RuHAB2aiaShmGUKnHcFp89zVm70vFGn3XZG82UpCvZvVR6YU5hgDBNgzguCbKW+vqxeLikaYrXqutGMZcxdDF/CNbSnYScG2Wkov2GJpiRm4p2R6HV5BhWO8s3Hqoiv7C9HgCDJACKnIof3urjLxkyRJ7epsVVdPavbDLyAcnD/LLvl8iIfGhV3zojI/nEsN5hOr1IUniv6CqyJoWM7JmspxiaBLDIqVkj6cFVW0CDGKxvpKHuHazIIa/OThKIq2V3M4p/v9rulgb9HE6meYDe/tI665L2cWZIeMwqgaclpKziqGkmmpk3tSTbFQNkBNwXbzHcMzTwiwqMrC1RfTaBtVp9Aq/++tCgnieiCdJuc5kF/OMmkrJZc0nOeHWpmLo9dQ2J9lyJDvpL8zkTDwpnMZVWEaGHMVwgUfV3P787QBcu/Ja1jWvO+PjucRwHiFJEt5g9X2Gaou4gTITk6U3ahSlWyIjkMkvR0mSRChk9hnGSvcZblvWSHdTgGhK45f7zlw1rFMV7tq8kjpF5slwlA8f6EdzI2xcnAHsUnIF4wlUYT4xFz/FJx6G8hXDbFQN5CiGs7Nz20FCrRwLipaOHr+XFW3iYa3OE2NstnyuZ6fXQ50ioxlwIl48iN6Fi/OFbCnZeY5hUWJYdOqJlWFolZKrC7e2FMNuJ45kq7+wTFSN5UjWNZ1JcxRe67KFqxgemDjAw6ceRpZkPrjtg2flmC4xnGdY9v/aFMMyxDDYCqp5E8/MNXyEgpX7DCVJ4p2XiIXth8/OdTfXgrUhP9+6qBdVgp+OTnPzoZMuOXRRM5yWko1MBsMyqoQKSsmGkWc+sZR8tSgxzC8l2+Uyw0CPFJC9YBvHzczQVUEfAV8Lmi4+cgcnypuwJElyDSguFgzsWcmOegzNgOui5hOz/SknrmbO1JMaFcNuJ4rhuGU8mdtOUhhVMz0aR8uIUXgNrZXf93zhzpfuBGBn705WNq48K8d0ieE8w3YmVxVybSqG5YihJEFD8ZBrgGCosjMZsInh746Nn1HYdS5e19rANzauQAK+f3qS/3dfH3E3xsZFDbDiaiophlZ/IRRRDFNRMMxWCX+DreQrfvGamhNwPTprZhia/U+y14tk3sNauMCAEmqjLyDuwZUBQTbjmjjWaLiyO3+tWU4+7PYZuphnpK0ew0D5HEPDMGyHfnnzyVzF0GsqhqOzVo/h2c8wTOeUkvMuKx5nxiS0FjG0HMmtXQt3FN7x6eP8uv/XAHxgywfO2nFdYjjPqCnkulncVGUVQ8hxJs9V+0LB1QBEy5SSAXpagrxqTSuGAT/cfXZUQ4DrljTzrYt68UoS942FectzhznhOjBdVIl00lmPoVVGxuNBLtzWKiNLCnjEwuf1B7OKoZpVN4otWkqjGVlTOL882Eq/XxDDFQFxzjRNAEzNVm7NcBVDFwsFTkvJRiwGGRHnVLbHsJgr2Vtbj+GQ1WNYYU6yYRhZxbCglGyphY2NjfjN92gTwwXsSL57390YGLyu53WsbV571o7rEsN5Ri0h1/ZYvIrE0OwznJ47+i5oEsNY7DiGUd5Y8keXiUkp33uy/6yYUCy8taOJe7atps2jsi+S4HXPHOLbp8bc0rILx7DH4VWaemISQ6WoI9lU+vwNQmkHvEEfik+o2Lkj8YotWkpTE1CMGLZliaHf3F4W9+5srHIElBtZ42KhwOlIPNuEpaq2km7DMLKu5EARV7KnhWRGIxwXCqATYpjSdUZTgoh2+8srhnokjZHQQAK1tTgxzJ14YhlPFqojeSw2xn8f/28Abtx841k9tksM5xmWYpisqsfQVAynpsrnHzb3iu9TfXN+FAgsQ5b96Hqy5MxkC2/c3Mmy5gAT0RQ/OouqIcCVzXU8eNk6rmgKEdd1PnFkkGueOcSD42F3trKLirB6DJ2WkqXC/kLIIYZN9ku++myYrarOJYYdRYlhYSm5lYHAUgBWmGKGxyOyDeOJyqMmVwfFOY7Hk+694GLeoOua/QBWKa7GnpPc0DDH9UsqAroZUxYs4kr2ttr3l1eRaQxULg2fTqYxAJ8s0eYpH0BtGU+UZj+SJ5/6jI6KB7V8YmiVkhemYvj9g98nrafZ3r6d7R3bz+qxXWI4z8j2GFahGJoB12ja3L6mXDSbjahFiKEkKdTVrQdgdnZ/+fMpMu9/tTjWtx89jnaWY2aW+rz8ePsaPrduGU2qwoFogve9dILff+YQ/zY0TiRz9lRKF4sLaTuuxqFiWMyRHJ8W3wNN9ku+OjFFRSKALIsFJ5bKn3pioZRiGFbqmDLVxuW6WGQCfjFqUstUJoYr/D4UCWKazrCb++linpBOZBXrSuYT3cmcZMVnt2zoeopMRqiMXm+r3arRXu+bSyyLYNB2JHsrbp8eF2tsMUdyoWKYSmSYnRAtHAuxlBzPxPnPQ/8JwP+66H+d9eO7xHCeYRHDdBU9hpLXm81PKzcWr8UkhpPFZyLX1W0EIBI5UPGc7760h6agh76JGD8+y6ohgCxJ/K/uNp545UY+2NNOUJHZH01w86FTbP7dXt6/9wT3nJ5gOOkukC6yqLaULAeLZRhOi+85iqHX3EwysgqjFbwb9CrU+bLqRKkew37zd7U9NUEoIVSRhqBYeCS9QhsI4JEluwR9zC0nu5gnpBJmMLyioHjKq3iW8aRiuLVJ4tJpsX5JkoKqNtr3WNUZhk6iasz+wkLjSe4oPIsYWjE1oUYv/rozmyJyLnDf8fuYSc3QXdfN7/X83lk/vksM5xlWmG41rmTIqoZaubF4Vil5dgjScxvY601iOOuAGIZ8KjddLSJuvvTgIWKpM5ufXArNHpVPrelm9xWb+NTqLtYEfSR0g/vGwnz04Em2P76PVz65n7/Y3883B0b5zcQM/fGk25f4MoWlGFYaiWdPPSlWSi6iGHqszfTsIlLKLVlKMew38wdXxE/bi2Jrgygt++Rp0g6c+KuCLjF0Mb/ITj3xV1TltLCDcOtgW/bYOXOSJUlmzHb9V5lh6CjcurjxZHp6mnQ6jaIoOaPwFq7xxDAMvnfgewC8Z8N7UOTyM+JrwcKeCv0yQC2uZDDH4vX3lw+5DraCtx5SszDdD+3r835cV7cBgEjkoKNzvu+KFdz9eB+npuJ867fH+eg1Z56wXgrNHpUPLu/gz3va2RuJc/9YmIcmZ3hpNk5fPEVfPMVPRrJqqSoJV1qXz8MSn4d2r0qzqtLkUWhSFepVhZAiE1QUgoqMX5bwyzI+WcIry3gkCVXCUfnCxcKBFVfjtJRcfOqJ1WOY7SX0BAwMwMhkFxwrqqZQzShNDAWZW5EYgpgoPbfUL2EAqPfOMjKTYFlz+fiP1UEfv55wiaGL+UPazjAs/7sKuaXkIpNCLMUwlONIto0nBVE1DdVmGDpXDEs5ktvb21EUQbImTi1cYvjM8DMcnT5KQA3wjrXvOCfncInhPKOWHEMAtU08dWXGy/QqSZJQDUdeEn2GJYhhMjlMKjVpz6osBZ+q8LFrN/CX//E8//ybY7xpy1LWLTm3o4IkSWJLfZAt9UE+tmop4XSG52Zi7JmNsT+S4GA0Tn88RcowGEikGEic2ZQIVQKPJCFLEqok8dNXrGFT3cINN325I1NlXI3TUrLq10kDejq74JSa4WoTw4J+X+t3cXniNESFguL3i7F4jb4ZTocdEMOAqxi6mF9Ya5OzcXhOSslZYpguEVXjdE7yKfMeW1YpqkbTyZg9g4Xh1kWNJ0ML15H8n4dFb+FbVr2FBm+Rf+ezAJcYzjOypeTqwqPVdtHEnhmtEHvR0iuIYZE+Q1WtIxBYTjw+QCRygJaWV1U871u2LuXe5wd56OAoN//wBX70wSvxKOevI6HRo3J1awNXt2ZvCM0wGE6mOZlIMZxMM5pKM5bKMJXWmM5kCGc0ZjM6UU0jpunEdZ24ZpDQdQoL0BkDMoYB5k9c/XBhwx6JV6GUrJVTDIuUkhVfmjSgJbJlmtES+WpKU4keQ7uUPAQx8SDn9YrvIU+coakw9JZ/GLOcycfibpahi/lBOpktJVdCdk5y49wfFiGG2TnJ4j4odY+VwqDZx9tVQTHMTCVBN5A8MkpDPom0FMOODvHQZhiGXUpuWWCK4Xh8nIf6HwLg+vXXn7PzuMRwnuE1c9WSsWhV+6nmL3FmbKz8hmUia0AYUOLxAWYdEkNJkviHd2zh6a88wgunwvzj/Qf41FsvquLKzz4USaLb73XUZ5ILwzDIGCILK2UYZAyDtC6+6wjCuazKY7o4v8iknZWSjXI9hkUUQ8mTBgMyiexDz1iJMpfSKPYrJIZ9eaVkkWeoqo3ohoosZRidHgbKj7BabYZcD8RTpHQdr+y2hbs4v0iZ946TcXjZOcnFSslmdSs4t5TssaeeVNtjaJaSKyiGmbGsI7lwikmhYhidTpGMZZBkiZbOhaUY/vTIT8kYGba1b2N9y/rKO9QI91NmnuE3S1vJWJWKoUUMKymGdmRNcWdyQ/1mAGZmXnR87s5GP1981zYA/vV3ffzw2ZOO911IkCQJjywRUhWaPSrtXg9dfi/LAz56Az5WB/34zuFCfPvtt9Pb24vf72fHjh08/fTTZbf/4Q9/yIYNG/D7/WzZsoX777+/5LZ//ud/jiRJfPWrXz3LV72wkDlHiqGkiAUqFc0uIoXj8CwU6zHUDMPufxKlZPEAJ0kSGXP6yXTkdNlrBljiVQkpMjrQFz+zNgkXLmqBlbHrK9aGUQB7TnKVpWRbMSzRrlEMMxmNWdPAVVExLNFfmE6nmTANnJZiODEk1MKmjgCKZ+FQJN3Q+fGRHwPw7vXvPqfnWjjv+mUKX0hI1VUrhk5LyZZiWCKypqFhOwAzM3uqOv/Oizr5y9cJl/Lf/uQlHthbeZFzkcUPfvADdu3axac+9Smee+45tm3bxs6dO+2n10I8/vjjvOc97+H9738/zz//PNdddx3XXXcde/funbPtT3/6U5588km6urrO9duYd2RH4p1JXM1c8wmyeFBLRrLNBqVGdSnNTeIckQhGWpS2hpJpMgZ4MOhMTkA0pxdYEQtjJDZS9ppBEMlsn6FbTnZx/mG1OXkrzEmGSqXkYuPwxH3h9bah6QbjEefmk0FTLWzxKISU8s7cUo7k8fFxDMMgEAhQXy9UzoXqSH7y9JMMRgap99TzhhVvOKfnconhPMN6CktGqy0lm8SwUim5ZZX4PtUH+tyg6IaGrYBEIjFIMll5TFcu/uqadbzzkmVousFN33/+nOQbLlZ8+ctf5gMf+AA33ngjmzZt4o477iAYDHLXXXcV3f5rX/sa1157LTfffDMbN27ks5/9LBdffDHf+MY38rYbHBzkL//yL/ne976Hp0Lm2GJApsqAa6elZB2xfXI2e8+UjKvJUUeshfGkqe4tUw0UdIhk7y2vVygTyZSz+22VPQHFVQxdnH/YxDDowHwSngayKnoeivYYZonhRDSJbgjPZGuocguPZTypNCMZchTD9uKO5I6ODjuRwsowbOlaeGVkgDetehN+1Zk5p1a4xHCeYRHDTCqJlnEe3uwxZW9teho9VWbBaFoukua1pIisKYCq1lEXErEz1aqGsizx+T/cynXbu8joBn/9wxe47f4DpDKV89lezkilUuzevZtrrrnGfk2WZa655hqeeOKJovs88cQTedsD7Ny5M297Xdd53/vex80338xFFznr+0wmk8zMzOR9XUjIOM0xjJjEsK5I71ORUrKmz5o/SmMYBmlNZzIq7rNCYigpSjZw3iwnD5jTInr8Zht3NPsAFwp0AmBolaefQA4xdBVDF/MAq83J50QxNMdCWoasPFiqeSg3xzBLDK0ycmvIh+rA0DiUtDIMKz8Ap0sohmVH4S0gxXA6Mc1DA8J08odr//Ccn88lhvOM3KewavoM5cZGJDOiIzNaRjWUFWgVJV/GDhfdpKFxOwDh8B7H57egyBJffvd2Pvh7qwH4v789zh9+83FePDVd9bFeLhgfH0fTtLwPIxAfTsPDw0X3GR4errj95z//eVRV5cMf/rDja7nttttobGy0v3p6eqp4J/OPtNO4mlmzxFVf8GGvpSFtqvWmYmgYBhltGoBUVJBPq4ysyhLNwbnnKuwzPGlF1ZjmMpIzkBaLU2OdIIZ+ecpRULxVSj4edyNrXJx/pMw2J2+FHkPDMOzIJmsakA1dh3h+KdkwDFLpLDEsNoe8HE45NJ7oyQz6rNjWUxBVU+hI1jWdqdNiHV5IUTX3nbiPtJ5mY8tGNrZuPOfnc4nhPEOWFbt3IxmNON5PkqRsn+FYhZJUuxlEPX6o6I8bG14BQLhKxdCCLEt87NoN3PHei2kMeHhpMMzbb/8du36wh6Ojzt+Ti9qxe/duvva1r3H33XdXFdJ9yy23EA6H7a+TJy8sI5FdSq5kPpkVv4dyfYFimMjJHjR7DDUtimEINSKTUEhGo3kxGrI899+3kBhaGYY9oTpQzIXLLCc3hMT0k0bfDEPTlVXAlbZi6BJDF+cftvmkgmJoxGJg9tjOIYaJaTDMSlJAGE00LYKui/sklxg6jaqxMwwrJEdY/YVynQc5kB/EUqgYhsfiaBkd1afQ0Lpw8mv/6+h/AfD2NW8/L+dzieECgC9Ua5+h5Uyu0GfYLoKsKymGMzMvouu1zyK+dvNSfvVXr+W67V0YBvzk+UGu+fIjvPfbT3Hv84PMJtw5xwBtbW0oimI/rVoYGRmhs7Oz6D6dnZ1lt3/00UcZHR1l+fLlqKqKqqr09/fz13/91/T29pa8Fp/PR0NDQ97XhQRr8omnUo+hNcO1rkAxtMrIvgahrpOd36pnZIyMTDIWZXSmfIxGYZah1WO4POCDkLhPrXKyz2uFXIc5Ha4cbL/KVAxHUhkimbl9wi5cnEtkzSfliZKlFkoeD1LhtpbxxNcAqiByVhlZUepQFH/VUTWDDkvJpRzJsViMWfNzod0UWSYGzf7CpaE5sTbzhSNTRzgweQBVVnnTyjedl3O6xHABwOozTJwrZ3JbecUwFFyNqjah63FmZ1+q6hoKsaTBz1f/6BX87KZX8fpNS5AkeOzoOB/9wR4u/uyDvOdbT/K1Xx/h0SNjds/Wyw1er5dLLrmEhx56yH5N13UeeughrrjiiqL7XHHFFXnbAzz44IP29u973/t48cUX2bNnj/3V1dXFzTffzC9/+ctz92bmEVomg64JolROMTQ0zTafKHMUw2nxPcd4YhPDlFhwEnmKYfGm76xiKBZHq5Tc4/dCnbhPLcXQ6xN/b/LNMDRdmRg2eVRaPULpOOGWk12cZ2TNJ+UVQ4sYyk2Nc6sWRTIMk3Z/YW3j8CzFsKdCKblSf2FjYyN+M7w721+4cMrIPzv2MwBe2/1amv3N5+WcbsD1AoBFDFPnKuTaGoU3dhgM0/aVA0mSaW5+JWNjDzA5+TiNjRdXdR3FsHVZE3fecCknJ2P88NmT/PdLpzk+FuWJ4xM8cXzC3q6tzsuqtjqWtQToagywpNFPW8hLc8hLU9BDvd9DnU8l5FUcNSRfKNi1axd/8id/wqWXXsrll1/OV7/6VaLRKDfeeCMAN9xwA93d3dx2220AfOQjH+Gqq67iS1/6Em9+85u55557ePbZZ/nWt74FQGtrK62trXnn8Hg8dHZ2sn79uQtCnU9YZWQo70rWc5T4OaVk23iSLX1ZobtGRhwzGY0wOivUxFKLVm7IdUrXOW2qGT1+b45iKBYin1eUrRq8s+yddnbPrw76mAhnOBZLsqW+sgnAxVzcfvvtfOELX2B4eJht27bx9a9/ncsvv7zotnfeeSff/e537TioSy65hH/8x38suf1ihtO4mpL9hVDRkQwwYqrySxoqO27Tuph2BQ5KyaZiWNhfWNZ40rUwjCearnHf8fsAeNuat52387rEcAHAKiUnai4lV1AMW9eAJEMyDJERqJ9brmxpvlIQw6nHWbnypqquoxx6WoLsesN6/ur16+ifiPHokTGe7Z/ihZPT9E3EGI+kGI9M8nRf5WN5FAm/quDzyHgVGa8qoyoyqizhUWRkWUKVJRRJQpJAliRkWXwH8V2SxJg7SZLM79bRJfvPubT5k2/ZRE/L2V+Ir7/+esbGxrj11lsZHh5m+/btPPDAA/aH1MDAAHJOuPaVV17J97//fT7xiU/w8Y9/nLVr13LvvfeyefPms35tFwqsMrIkyShq6Y8yq4wseb3IhcpiMcUwNWXumO39HZsV+1UuJU8xlEyjA35ZosOr5iiG4gHO623BMGRkSWciPAwUbyY3MjqxPaMYKZ0VHomncQ0otcLKDb3jjjvYsWMHX/3qV9m5cyeHDh2yjQe5ePjhh3nPe97DlVdeid/v5/Of/zxveMMb2LdvH93d3fPwDuYPTl3JWUdy09wfliWG4rUR05XshBieTqbQAa8k0eYtT2Nyp57kwiKGuf//C21G8tPDTzMWH6PR18hru1973s7rEsMFADvL8FyVklWfCLqePA5jh4oTw5YrAQiHn0fT4ijK2W28lSSJ3rYQvW0h3ndFLwCRZIbjYxFOjEc5NRVnOJxgZCbBRDTFVCxFOJZmJpEmrYmQ4bRmkNYyzJ7HtfGj16w7Z8e+6aabuOmm4iT84YcfnvPau971Lt71rnc5Pn5fX1+NV3ZhwHYk+3xlDTdapITxBHKIYVblsErJkpFt8RidEQpCqYkMqqnWZianshmGfq+4rgLFUJIUDLkZyZhgJlbcha7HM0z8+36Sx8Ri27HSC+t8rgGlRuTmhgLccccd3Hfffdx111387d/+7Zztv/e97+X9/dvf/jY//vGPeeihh7jhhhvmbJ9MJkkms/83F1rsUznYI/EqEsNpIKue58GBYjhahWJ4KpHtL5TL3PuGYTjKMARIJzVmzG0XSlTNfx//bwB2rtiJRzl/ubQuMVwAOPOQawdBuW3rBTEcPwyrrprz40CgF5+vk2RymOnwblpbXl3VtdSCOp/K1mVNbF3WVHa7VEYnmswQT2skMzqJtEYqo5PWdFKaTkYz0HSDjC6+G4aBZlh/BgPxXdMN7DkW5uuAuQ05f85Ou1jaeG6DRF3UjkxSLCQVMwxNxVApNJ5A0QzDtFlKlqU6IEUyEmF0Vvy8pGLYYjotJyezjmSrxFVnEsOckGvV046emiCemDv9xDAMJv5tP8njYSSvgm9lA8unxXs4Mua6/KuFlRt6yy232K9Vyg0tRCwWI51O02L+Pxfitttu49Of/vRZud6FBC2TtueRVxqJV7aUbGcYFiGGnjZ03bB7DJc46DE8lXTmSNZnUhgpHWRQW7Kf5YZhzFEMJ4eiYECgwUugvnJo9rlGPBPn1/2/BuAtq99yXs/tEsMFAH+oNsXQYzpS06eLqw55WLIJDv8ChoubSyRJoqX5Sk4P/4TJyUfPCzF0Cq8q41W9nJ+2WxcXCtL21JPyH+Ka5Uguqxg2ZY+bFq+pciMwJhRDyzFZYtFSTcKQmZzIN54AhMxSck7IdcC/hGjqIJnMOLpu5EXgJA5MkjweBlWm/c+34u2qY+OvjgGzHE+myERSqHXzv3BdKCiXG3rw4EFHx/jYxz5GV1fXnJB5C7fccgu7du2y/z4zM3PBZYIWQyqeNUc5dSUX7zEsPw5vMpYioxtIErTVOR+HV4kYpi21sCWApGZbc8LhMMlkElmWaWsTiqU1I7l1gUw8efjkw8QyMbrrutnevv28nnvxdPNfwKi1lOxZKvLQ9EjEHsVVEp1bxffTL5TcpLX19wAYG/s1hmGU3M6Fi4UAq8ew4jg8u5RcRjHMIYYps5Ts8YjXEtEI4xFr6kkJV3KLWPC0iclsuLWtGJqEJEcxrA+Jh7p6dZrxaLYEaWgG4V+Iueb1r+nGazbB0C5B/wAAi51JREFUb35dLwCzHomTj15YWZMXOj73uc9xzz338NOf/tR2rxbiQo99KgXLeKL6fMgV5hHb4/CKEsO5ruRUSpSXvd4223jSGvLhcWAydBpuXWpGsqUWtra2opr9yQvNeHL/ifsBeNPKN1WVTXs24BLDBQCvXUqurkwkB4N2o2/69OnyGy81ieHofjHtoQhaW1+LJHmJx/uIxY5VdS0uXJxvZJLOxuFZD01KsXF4lmKYV0q2iKFQAWfDM2i2mlF8IVJbxbZ6JEK/ObquJ1BQSo5miWHAJ8hio2+GwamsKhPfN05mLI4cUqm/apn9elBV6DJzFg/sHUWLvDyjnmpBLbmhFr74xS/yuc99jl/96lds3br1XF7mgkRV4/AsxbDoODxTLQ9ljR655pPRGedlZMj2GC6rlGFoGU/aHRhPrAzDBWA8CSfDPDb4GABvXPnG837+mojh7bffTm9vL36/nx07dvD000872u+ee+5BkiSuu+66Wk67aFFrKRnA09UFQHpwqPyGTb0iXFRLCQNKEahqPS0tIhdvbOzBqq/FhYvzibTZY1hRMSw19QQgZjqQg9neMavH0OcXJaaIuX9ryFsyMkluaABTeTgZt+YkF5SSE2HIiJ9lswzDDOZkGcZ2C/ISunwpsj+/02dNo1jc+nwQfXZub6KL4qglNxTgn/7pn/jsZz/LAw88wKWXXno+LnXBwanxBECfdtJj2G6/lE5nFcPhKownAIMOewztDMMSxhOrvcAwjAU1I/mhgYfI6BnWNK1hbfPa837+qomhZfv/1Kc+xXPPPce2bdvYuXOnzcBLoa+vj7/5m7/hNa95Tc0Xu1jhC4pfxGpmJVvwdJvEcKgCMZRlR+Xk9rY3ADA27hJDFwsbVv9Tpd4nPWKaT4qVki23ZCCXGAqy6A+IRSxulqJLhVuDOaKypYWUqjKSEaO/lvtNwhpoBtlUNkzlxO8TbSBN/mk75FqbTZE4Is4dvHhuhMrqoDj/QEgmtnvEbfeoArt27eLOO+/kO9/5DgcOHOCDH/zgnNzQXHPK5z//eT75yU9y11130dvby/DwMMPDw0QiLy/zT9JhhiGU6TE0jGwbRUg8bGlaDE0zj51TSnZCDA3DcNxjaCmGpTIMLcUwNpMiEUkjSdCyAHoMc8vI84GqiWGu7X/Tpk3ccccdBINB7rrrrpL7aJrGH//xH/PpT3+aVatWndEFL0bUOhIPchTDSsQQsuXk4RdLbtLW9vuAxMzMC8Tjp6q+HhcuzhdSCZMY+is0xduKYZG+r7jVFC+IoWEYNjEMmL2BqZjYv9KoLqW1lZEWsfAFZJlWj9mTJUnZcvKsUCp8PlHCbPaF7VJybM8o6OBdXj9nIQMRcg0wUKeQGYuTPvXyIilnguuvv54vfvGL3HrrrWzfvp09e/bMyQ09ndOO881vfpNUKsU73/lOli5dan998YtfnK+3MC+wegx9FaaeQE5cTWGOYXIWNLOP1lQMk0nxgCTLfhQllJNhWLmUPJ7OENcNZKDLV7qUbKQ1tGnToJajGGqaxpg5FML6/7fUwsaOIB5v+V7Kc43x+DjPDD8DwLUrr52Xa6jKlVyr7f8zn/kMHR0dvP/97+fRRx+teJ7FnAlVDNZNl4xV/0FfFTG0FcPSxNDna6el+Uomp37H6eGfsGrlh6u+JhcuzgccK4azJRRDw5jjlsxkZjEMMWYvGBKqnmYS0EqLltrczLD5kbo84M1vGK/vhJlBiIgEAb9fEMNG3yynR8XnW2yPWKyCF+e7Zy1YM5NPNnuAONHdI3h7ipTHXRRFNbmhiz0D1CmcTj0xDKO0Ymj1F3rrwCuOk0pl54ZLklRVhuGAmRO61OfBK5fWttLjCTBACqjIoSyBnJiYQNd1vF4vjea1TpxaOMHWv+7/Nbqhs7l1Mz318+Nsr0oxLGf7Hx4uHpny2GOP8S//8i/ceeedjs9z22230djYaH8tBtt/OfhCYsFKxePoulbVvmqtimGZ8yxd+ocAnD79EwxDr+p6XLg4X7AVw0oxGmYpWS40nyRnQTeNWGYp2ep7UpQQwQZBFo1kHAyjpCPZgtLaynCrUER6Cktc9YJkMitUKVVtAsQ2M9HTaDNJ0oMRkCCwOX+0oQVLMez3GGhA/KUxDN0gk9bY8+sBfv71F3jkPw4xeHiq7HW6cOEUtvmkgmJoJBIYZkqAXBhwbfcXtmWPm8qfGz4yaxHDyorhnDioEsiWkQN5D2m5wdbWdCk7qmYB9Bc+0PcAMH9qIZxjV/Ls7Czve9/7uPPOO+2sICe45ZZbCIfD9tfJk4s7niH3pkvF4mW2nIuqFMO29eKpLRUR7uQSaG9/A4pSRyJxkunpZ6q6HhcuzhcsxdDjL79oZc0nBR/6VhlZ9ecoGVZDfCt+MxBbwsCnJysrhi0tDLeKkvFcYmi6X2fFA7QkSajmzORE8jSJQ6YTelk9Sgnn8zK/F68kkQJGGz3o0QzhfeP8x2ee5nc/OsrAvgn2PjLIvV95nhd/47aBuDhzVDsnGVVFDhVsazuSs8aTVDKrGEJ2HF6lhy8gGyAfqEQMLeNJFTOS55kYjsZGeW7kOQDesOIN83YdVRHDam3/x44do6+vj7e+9a2oqoqqqnz3u9/lZz/7GaqqcuxY8UiUxZoJVQqK6kE1IzeqLSdbxFAbH0fPKb+XOBEsu0z8eeDJ0pspAZYseTMAg4Pfr+p6XLg4X0jbi5ZT80mBYlg0dDfrlFRUj70gBvRExTJXrmK4vCQxzPaxBf1CRfRJE8zuF+cNrC8d465IEr1mOXlonXgvh350hJmxOKFGL1e8YzVrLu0AAx79wWH2P+bgYdGFizJIOh2Hl1NGnpO5Z8U05RDDpFlK9vrayWg64xHnc5KdKobpElE1haPwdE1n8rRVSp5fYvhg/4MYGGxr38bSuqXzdh1VEcNqbf8bNmzgpZdeYs+ePfbX2972Nq6++mr27Nmz6EvE1cAKuU5UaUBRmpqQTMXRkWq4/JXiexliCLCs+70AjI79gnh8sKprcuHifKBq80lhKdkihjmO5OyYLkEWA+ZDqV+rTAzV1hZOt1UqJWdbboJB8VDX6p8mfWxanGd98ZFrFtaY5eShZeI9N8Qy+EIqf3DzJVy8cwVveP9FXPLGFQA89qMjzE4myh7PhYtySDl8+NKmpgHnUTWppCCLPm8HY5EkhgGqLNEaqjzRx5pFXrmUbFYUSmQYWorh9EgcPWPg8Sk0tM7vCNRf9f0KgJ29O+f1OqouJVdj+/f7/WzevDnvq6mpifr6ejZv3oy3wiirlxP8Zp9hwlQ3nEKSJHsCSlXE8ORTZTerr99ES/OrMAyNk6furuqaXLg4Hzhj84ntSM6qdKmcbDUAf50ghgEtTmeFudlKcwvDLaZiWFjmshTDmaxi6DMja9b4wkgpHTnkwVNBsbD6DA+roBsG9YrE69+5lgZzsoMkSVz+1lV0rmokndB4+HvFM0tduHACp65kbUrcS0pLEcW7SCk5t8fwdDhrPMkdDVkKA4WThYrAMIyccOvstScSCaZN97SlGFpl5JauEJKD858rjERHeG5UlJFfv+L183YdUAMxrNb278IZ/KaaUS0xhJwsw0EHyl73pSApED4J4fJ9SMuX/xkAQ0M/IJWarPq6XLg4l3BiPjE0Dd1U4ecEXJdRDD1eoRiqZsZoUE9UVDPSLc1MmY33lcwnAH4zsmaZX5ThfGubKi5Ma8wswxdGZpnIiBzDFj3fICbLEq+7YQOyIjGwb4Kho9Nlj+nCRSnYpeRgebduZkr0yKrNzohhrit52CSGSys8eIF4GDrloJSshZMYKR1kCTVHBbTUwoaGBoIm2R03Y5/als1vGfnXA78GYFv7NjpD5SfynGvUZD656aab6O/vJ5lM8tRTT7Fjxw77Zw8//DB33313yX3vvvtu7r333lpOu6gRMDPW4rPVE0Pvil4AUv39lTf21UHnFvHnCuXklpbXUF9/EZoWpa/v9qqvy4WLcwlbMSxTStZzAonnEkMz3LpEjyGA7hOLR6snU3LqiYXB+iYAQvEYTWpBFppFDOOT9vQTK8uwyT8NgH9VU9njA6w1FcOThsaoSQyTR6bnbNfcGWLDFeKcu3/RV/G4LlwUg60YVuoxnBTEUGku0gpRzJWctBTDDjvgvZIiDzCaypAyDBQJusrMSc6MmsaTVj9Szn1bOPEEFg4xtMrI82k6seDOSl4gsHqZ4rPhqvf1rhA9Rak+B8QQYMWV4vuJ35bdTJIk1qz+GACnBr9HLObw+C5cnAdkFcPSi5bVXyj5fMiFrSsF4daQP78VIK2KY7coxeeL52LIdEd3jY1gFE4xCjSDYrqazT5Dn5ll6PWLRdW7qkh/VgGsUvJsUCazWmyfPB7G0ObGSl28cwWSLDGwb5LR/sWdBevi3MAa01q5x9AkhsVKyZF884mup7NjJ73tVSmGA+a4yS6fF7WMup4eNcvIHfmfDcWI4cQpIca0Lpu/TNDR2CjPjz4PwBt6XWLowkTALCXHZ6v/APf29gKQchrKuvr3xfejvxYhv2XQ0vIqWltei2GkOXzkM+4YLhcLBtYcV09ZxdDMMCw6J3luKdme3+oR6kZcEYtVPRUc/8BJQyxUnROjZMbH838oSXMia6xSsuadYUpJ55W8SiGERF1CkED51R3IIRUjpZE6ObfS0NgeYO1loo/qJTe+xkUNsMyQVg98KVg9hk5KydbDlySpeDzNnDbDrTsby5NPqCHDsAIxjEdSRMPimPMZbv3r/l9jYLC1feu8l5HBJYYLBlYpOVFLKdkkhumBAQzNQUB276tEdtvMIIwdrLj5mrUfR5K8TEw8zPDwT6u+PhcuzjYMwyCdEAtKOTVDM6cmKXVl5iTnlZLzFcOoJBS6kFGZGPZbasb4KBlz5FYeCvoMPZ4WMDwgGbzkc9bDe+iZ0zTPivOMNOr4VjcBkChSTgbYctUyAI7uHiUZq6x6unBhwTAMklGhuPuK3T85yFil5JaCUrKWySrz5lhIq7/Q621DkmRbMexyohg6jaopohjquj6HGFpl5Ib2AF5/VYPgzioe7H8QWBhlZHCJ4YJBoEGUhWpRDD1LO5G8Xox0mrQT448nAL2vFn8++uuKm9eF1tqj8Q4f+Szx+OIOHHex8JFJJu2pPGWJYan5rTCnlKzrSTIZ8WBm9RhOaWIB8qZjc/cvgLVoLR0fJWM2uedhTsi1jCcjzn3EO8pUBeI2MjLCz379H9Snxf4/euwJnuMYOjrJI8WnnSxZ2UBLV4hMWufw0yNFt3HhohhS8TiGaWyqrBiaxLCpQDG0Hr4kWbRTkNNf6BUK4ukqegz7zaiaFZXCrUfnRtVMT0+TSqVQFIXWVvHgN7EA+gvH4+PsHtkNzL8b2YJLDBcI/GdQSpYUBe+K5QCkTvQ522nNNeK7A2IIsHz5B2ho2EYmM8OLL30QTatuQosLF2cTVn8hkoTHV3pBsYN3ixHDmEmmzFKyZTyRJBVVFQr+hCZmrCqpysTQWrSWjo85UgwNTccTEece9Y9zcrL0OUZGRvj2t79NUo/SFBXbTQZC/O7wszyjHiN1ahY9ObdaIEkSm14tUgv2uYHXLqqApRYqqorqLT/1R5ssEVdjhVsHWkAWhiwrqsbn60DTDUZMBXypg1Jyn6nKW0HvRa8lmkaPioesXMXQUgvb29tRFHEtC8F48j8D/4OBwebWzXTVdc3bdeTCJYYLBGfiSgbw2AaUPmc7WMSw/3FIVDa8yLLKls3fwONpJRI5wN59H0HXUzVdqwsXZwo7eNfvnztpIQfVKIa2I9nTah9zOCkWECNRPnjeMIwcYjhCuqxiKIhh+nQUNSaUCykwzsmp4sQwk8nwk5/8hHQ6jSfVwGZttXhvS8Qi8pI6wHFGSPUVv4/X7+hEViUmTkXszDYXLiohYZWRQ3Vl7zHDMMiY95laWEqeNVXq+mzfnDUOz+ttZzySRNMNFFmivb7ynOR+U5XvLVNKtvoLlSYfsjebDlDOkTyfE09+1S/cyK/vXRhqIbjEcMEg60quzT3oswwoTiJrAFrXQPsG0FJw8D5Hu/j9XWzZcjuy7GV8/CH27vsrdL1y75ULF2cbTqJqoAwxTMfBKg/bxNDqL8zGagwlxEekloihZTIlzzOezhDXdSTDYMnkOJnRIophQ7f4PiOUu2T/DJ64OFdrYJKTk8VV+EcffZSRkREUyUvD9CauXCMWtiFD5pWvehUAv/McJHy4CBkF/CEPKy4SBPTIM2452YUzJMyop0plZD0SgbRQ6JRC80nEnPRTlyVjtmLo7ciGW9f7UCpkeMY1ndNJcZ4VZRTDUo7k4WFxLdb4Xi2tMzUkHvjaeuaHGE4lpnh2+FkAXr/cJYYuChAwJyykE3Ey6eqbxKt2JksSbP5D8ee9P3Z8nuamy9iy5ZtIkpexsQd4/vk/ccOvXZx3WKVkT6V8NZsYFkTBWI5kWQWfuPesqSceryCKibTGaFLG8uGXC58fMNXCJYaGN5Mp3mPYKIwghEWPbqp/Bk8ihxgWUQyj0SiPP/44AMGpVci6l1e+YglBRSZtGKx85atoq28mKWV4cv/ukte39jKxMB95dsRNFnDhCE6NJ1YZWQoGkf0FbR3WCMg8xTBbSq6mv9ByJNcpMi0epeR2mZHijuRCYjh5OoquG/iCKvUt8zMK7zcnf4NmaGxs2UhPw8IZEewSwwUCXzCIJIv/jsSZRNacOOF8p4v+QHw/9huITjjera3199i29VsoSh3T4Wd46uk3MzFRPhPRhYuzCeeKYYkeQ6spPtAiHpKYG249HE5gSDJJWSwa5dR8e0yXKu7hoj2GNjEcBF0n1T+LJy6UvFb/ZNEew6eeeop0Ok1TfSu+RDsdvQ00tQXtoOtjiRS//3sifurF2DGmx4o/pPVuaUP1ysyMJxjpczMNXVSGVUp2ajwpGlUTmVtKTiStHM+ltmJYbX9hudJ22iKGS7LEMB6P26PwrFLymBnx1NZTX/Z45xJ2GXmBmE4suMRwgUCS5TMyoHhXi76j9OAgWsRhH1HbGli6DQwN9t9b1flaW1/DpZf8kGBwFanUKHteuJGXXrqJWKyvugt34aIGOBmHB6CFp4EixNAK3TUjNADSNjEUZG0oLM6R8YoFptx9aS1ay80SV3FX8lLhztTTZE4PooWTeYph/0T+fZtIJHj66afFz6U1SEis3Cq2XxcSZPVQNMGGiy+iU25Bk3R+9+tHi16fx6ewcptwgR7dXbzk7MJFLpwSQzuqphgxtBTDuiwxTCatHM+lDNsZhmfPkZweEeVhdclc40ljY2N2FN6AIIbt81RGDifDPHX6KQCuWXHNvFxDKbjEcAEha0Cpnhiqzc2o5pNQ8vBh5ztuebf4vvtfK4ZdF6Kubh2XX/Yzli27AZAZHfsFTzz5el7a+5dMTj5ux4m4cHG2kY47JIalegwtt2Te/Nb8HsOhabFo4RfBt+WJoVi0VjaJe1iPROwZzTYUFeqFYSR1RPQZBpp6AAWPrDEbGyGVyd4zL730EolEgtaWVqInxMLZu1WQ1vXmzOTD0QSSJHH5MjHm8sWje0kmi/f9rr5YvNcTe8bccrKLikjmmE/KofzUE0sxFGuTpiWzU098nQyapWQnU0/6E5UdyXosjT4rWrE8RYhhrvFk7KTpSO6Zn4knj5x6hIyeYU3TGlY2rpyXaygFlxguIJypM9m3YT0AyUOHnO+0/f8RYdfDL8HJp6o+p6IEWL/uU1x++c9pbb0a0BkdvZ/n97yP3/3u1Rw8dCtjY79y+xBdnFVkXck1lpKLKIZ2icsrFg+r/0kNioUxPlNZMVzdWIdkKhJFy8lNoo8o1T8tzrWiGb85Gq/FN2EvlADPPy9GZK1athEtbVDX7LPdk5ZieDgmyOu6rRtp0AMktTQvvvhi0WtcvqkV1SPKyZYb04WLUrDNJ5V6DMtNPSlQDC21UJYDqGoDg1Pi931Zs5NSsqkYlnEkW2VkpcmH7MsGVhf2F+q6wbjp0G+fJ2L4YN/CCrXOhUsMFxAC9bWXkgH86wQxTBysghgGW2DLu8Sfn/5WTecFqK/bwPZt3+byy/6b7u7/B0WpI5kaYXDwe7z40gd59LHLePzxq3nxxT/n6LEvMjT0QyYnf0c0epxMZtZVMFxUBSelZMMwsophY4H5xBrTlUMMUzn5agBDZv+T3zSGxWdKxzqdyOl/8rQLZa5cn2Fq2Azn7qnH7xdu5dbAFH3jQmUcHh5maGgIWZbxRsTxere02b1Q601ieDSWRDMM/Kua2KSJYz/91NNF7yePT2G56U4+/nyRa3PhIgeOS8mWYthcEFVjGHMUQ7uM7O9EkiROmcSwu6m8iQyyk4XKKYbF+gthLjEMj8bIJDUUj0zTksqk9GxjNjXL74Z+Byy8/kKA+ZsB42IOsoph5VzBYqhJMQS4/APw/L/B/v+CqT5o7q3p/AD19RvZsP6zrFv7CSYnH2di4hEmp54gFjtKPDFAPDEA4w/O2U+WvahqE6ragKrWoypBZCWAogSQZT+y7EWWPEiyB1lSkSQPkqTkfSHJSEiijwtJ/BnJNheU/LsNac4f29uuweNpqvnfw8W5gWU+KTsnORoDM2KmpGIYyhLDpO2WNBVDs8ewvrmJWSBq9isWIprRGE2J8/QGvIQ7Okj19xfPMmxchmEopMLiur3L6/GPCWLYFpigb0IQwz179gCwfv16Tr8gXluxJTu6r8fvJSBLxHWRn7iy2ceG0AqeSR5jbHyMoaEhuru755x+1fY2ju8Z4/ieMXa8bVXR9+PCBVRRSi41Di8xDRmzHaNAMfT5OkmkNcYjguxVUgx1w7ANXuV6DIv1F2YyGUbNe9EihuMns/mFsnL+9bFHTj1CWk+zsnElq5tWn/fzV4JLDBcQzmReMoB/vakYHj6Moeu2y7kilm6DVb8Hxx+GR74A191e0/lzIcs+2tqupq3tagDS6TCzs/uIRA8Ri50gHh8gkRgimRxB0yLoeopUatRWbRYK6i/7b5cYLkA4UQwttVDy+ZALt4vml5IzmQiaJhYVr9dUDM2ybnNbmyCG08XbIfrMBavFo9DkUYl2mMcslmXYuIy00Qu6ghRQUVsDBGaF0tfqn6R/Ioau6+zduxeANb0befI348iqRPe6bKlOliTWBv28GIlzKBpnVdBHw6o2eve1c0wZYc+ePUWJ4YotbciyxORQlOnRGE0dlZUaFy9POHYlW1NPmpvyf2CFW/sbwSMU7kQOMbTur6BXoSnoKXuOwWSapG7gkSS6fWXCre2ompD92tjYGJqm4fP5aDbL3aP9oirXsWJ+y8jXLL9m3hzR5eASwwUE/xmYT0BE1kheL0YsRvrkSbzmNBRHuPoTghi+8B/wml3QenafYjyeRlparqSl5co5P9O0OOn0FOn0NOn0NJoWRdNiZLQoupZA15Piy0hj6Gnx3dAwjAyGoWMYGTAMDDQMwxwLZhgY6IBhm2oMcstrZV7PgaqGcLHwYCmGvjI5hmWnnkTyzSeWWqgodfb/+WnTfLKks4MBIDpVfB7xiVh+iUu1SslFFcMeUrp4gPP21CPJEn6/IIbtgQl2j0cZGBggEong9/uRZxuAcbrWNOHx5We3rQtZxDDBG9vBu7KRtS8u5Zgywt69e9m5cyeqmv8R7w95WLq2icFDU/S9OM72a5YXfU8uXCQdu5LNHsNCxTBSzJEspv74c4wn3U2BiuTouH2PeVHLBGEXKyWfPi3OuXTpUvs8Y5Yjefn5J4bRdJTHBh8DYGfvzvN+fidwieECwpm4kgEkVcW3Zg2J/ftJHDxUHTHsuQzWXQuHH4BffQL+6Pt2yfVcQzFLxn7/wpgT6WLhI20HXFdWDMsSQ1MxzJa4RBl5NpFmNinKw8u6lvAMpRVDq79wpUUMTedjZqTIlJHGZaT0DYAghgCBgDCktAUn6O+Psn//fkCUkQcPiraSnk0tcw61qS4AI1PsjwoC61vZSJfeQtDwEYvHOXz4MJs2bZqz38qtbS4xdFERlvmkUsB1Zly4+a0HIhuz+f2FAMmEdZ8t5dSQSQwdGE+OmSarVcEyM5JnU2JGspRfSs4lhgCGbjBqEsOOFQ0Vz3228cjJR0jpKVY0rGBd87rzfn4ncM0nCwhBs0G+VC+TE/gvEgtBYu9L1e98zadB9sCh++HAz2u+BhcuzjWyAdcOFMNC44mWyQZcm6O6kgXGEyt4tzHgobVDxNdEp6aKmjqywbuixOUxF6D00NDci2pcRsoQi4F3qSifBYLiAa7NP8nQ9Cz7DxwAYOP6jQweFirl8k2tcw610TSgHIiY7un2AGqdl9WaeE9WOboQvWYW4tDRMIlo9VOWXCx+GIbhqJRsGEZpYlhEMcyGW3dW5Ug+bt5jq8oZT06b/YWtgbwZyYXEMDwWJ50QxpOWpee/leLB/qwbeSGWkcElhgsKoSahCkSnao92CWzfDkDMjLqoCh0b4NUfFX++/2aIjtd8HS5cnEukHOQYlgy3jk0AhjApBQXhSiWFumEphlaZq6spYN+XmXSKZKwgmxA4YWUYmouWp8skhuaClAtdD5IxROnY2yDUQJ93CbLsR5F1VvkHiMzO4vP58BstZFI6wQYvrd1zWxo21Yn3fiyWJK7pSJKEb2WjTQwPHz5cNNOwsT1AS1cIQzfo3+t84pGLlw/SiTiGLpzz5YihNj2dnZPcWvDwUkwxzFHms6XkyuTsmFlKXh0snXeYHhb3pmdp9l7Rdd12JFvE0OovbFt2/o0nsXSMRwdFCP1CdCNbcInhAkKdafePzYTRNa2mYwRe8QoAEi/txahh5jKv+RtoWyee9n78ftBruw4XLs4lkjGhZnhr6TG0jCfBVpCFsmA7ku0MQ6EYdjX6Ub1efCGx2BTrM+wrKCV7ukRLRGZ0FCOVyts2ZeYHqtIQSmIAAEmSCAaEargxJF5bt24dpw+LBaxnY0tRZaHDq9LiUdCBI2apzdfbQKtRT4MaIpPJcOTIkaL/NtYElb4X3Yc/F3NhqYWyoqL6ypRvTbVQaWxE9haYQgoUQ2EwFNv7fVnF0Ekp2eoxdKIYejqzxHB8fJxMJoPH46HVJK52GXke+gsfOfUISS3J8vrlbGjZcN7P7xQuMVxACDQ0IEkyGAaxGsvJ3t5elMZGjGSSxMGD1R/A44d3fxc8QWFG+eXfVT0RxYWLcw2r/8nK/iyGiuHWuVE1c0rJ5kSGJqFQWKphZCpfYYtpOkNJ8QBmmU+U1lYknw8Mg3RBn2FqQJA9r3QIJrNzzQPBXnGMkCg/r1+/npMHBAnt2VgkOBhBKDeGxKK63ywne1c2IiGxKi3eR6Vy8sC+CTTNnVDkIh+54dblyp1WVqfa0T73hzOmYt4glDrx8GUgSV48nhZOTQmjSHdTeWKY0nVOms7/1WV6DG3FMIcYWmXkzs5OZDOlY6zfNJ7MQ3/hAyceAITpZKGWkcElhgsKsqwQNBex6HRxB2QlSLJsl5PjtZSTATo2wtu+Lv781Dfh4dtccuhiwUDXNLuka80XL4bSiuHccGurxOW1SslT2VIyQJ0Zc1F4Xx43lbpmVaHVK7x8kiRl+wwH8/sMUyfFouSVD8FUlhhaimFzcBIDiWVLVzBmbrts41zjiYVNdVafobgOT2cIya+yMiUW6iNHjhQtJ3f0NhCo95BKaJw+Ml3y+C5ennCaYWj1FyptbXN/GD4lvjeI1olEYhAAv38pGR17TnJPBcWwP55CB0KKTIe3uF/W0HTSo6YjOaeUPDgoztllqvh6nvHk/CqGkVRkwbuRLbjEcIEh1CQWoMiZ9Bma5eSa+gwtbHknvPGfxJ8f+Tzct0s07btwMc+wylzgoP+JIuYTaxpD3dxwa79JDE+aakZPsyhVl+r/PWqWuNYU9D5Z5eRcA4phGDnE8HC+YmgSw0Bglqi3mfG+OBjQ0hUi1FhaJdlo9hnujwoiK8kSvt4GWow6mgINaJpWtJwsyxIrNovSWt+Lbp+hi3xkjSfl47oyYyWMJ7oGs+bvfqNFDAVRDPiXMRxOoBvgVWTa6kr/fkPWeLI64CupsmXG4qAZSD4FpSl7vCHz/rMyPadOR8kkNTw+heal5zeK7Dcnf0NKT9Hb0Ltg3cgWXGK4wGD1GZaKxnACWzF87vkzGzW343/DtZ8DJHj2Lrj7zWIyigsX84hERJArXzCErCglt9MmBOFRWgpKsQUZhoZh2MTQa/YYDkwKYri8xSSGJe5LmxiG8hc31TagZImhNplAj2VANvBIx/MVQ7OUHAjMciLdwMkD4jw9G0qrhQCbzFLyvkjcvtd9q8xysldcwwHT5VwIq5x84qVxdySlizzEzSEL5RR5yCkltxU6kkdBz4CkQL3oMYzbimE3/RPmg1dLALlMLiFk77FyUTW5ZWTJPJ6mabbxxCKGIyfMYOve+ornPdv4Zd8vgYVfRgaXGC44WIphqTBdJwhs34bk85EZGSF17NiZXdArPwjX/zt46+Hkk/DPV8Aj/wSpue5MFy7OByxi6Hecr9aR/4OCUnImM41hiB4mn6+NRFpjZEYsRj0WMbSV/Pz78qhZSnaiGNpq4RIfkpQRD1mmuUuWO83zRziaDNK/X5DaZSX6Cy1sCPlRJJhMa3avo2+VUEh7wk2AKCenixjReja2IKsSM2Nxps1gYBcuIDsXPNjQVHY7+x4rLCXPCBJI/VLb4JWIC8XQH1hG/6Q55rG1smpn3WPl+gtTQ0LhzC0jj46Okslk8Pv9tJjh2yMnxPta0ts49yDnEOFk2J6N/MaVbzyv564FLjFcYCilTFQD2e8neNllAEQee+zML2rjW+CDj8GKV0E6Br/5B/jKZvifv3cVRBfnHdnG+NLN44aukzEVQ7W9YNGaNZviTbdkIiH+7vG0IMs+Tpn9hSGvQrM5qqvUfXnMLiXnL1pFiaHZ2+TtbRF5oVoKZsTPT52KoGkKsmzQ5okTnUwiKxJda5vK/VPgV2TWm6T0pVkz9LurDsmn0JYIUR+qJ5VKcazIA6LXr9pj9k647mQXOYhZxLCwDaMAtmJYWEoOnxTfG7NjGeM5pWRLMbQU+XI4bAa4rw+V7kVMD5opBV3Zh8Xc/kJLoRvpE4rhkt7zazx5aOAhMnqGdc3rFuRs5EK4xHCBIet+rF0xBKh7zasBiD56FoghQHMv/K/74J13iT/HJ+G3X4CvbYM7f1+oiANPQjpxds7nwkUJWJOByimG2vQ0aBpI0txRXTNW75NYtBI5JS7I6S9sCdoLSl0RJV83jJwew8rEMGk5knsbocmcOGKWk48dO04iIcp2F/nFYtu5qhGvv/Jwqq31YnF9MSKuW5JFnqGExJpmcZ6DJRIKere4sTUu5iKrGFYghrYqX/DwFTYVQ7O/EPLvs/4JoRj2tpYnhoZh2MRwXai4YmgYBqkhs5TcPZcYWmXkVCLDpLndkpXnlxj+4sQvgAtDLQSXGC44hGz3Y+2KIUDoNa8BIPbMM+hmGPAZQ5Jg8x/CXz4H77obVv0eIMHgs0JFvGsn3NYN33wV/OhP4X/+AZ7/dzj2GxjZL/pONHfSgoXbb7+d3t5e/H4/O3bs4Omnny67/Q9/+EM2bNiA3+9ny5Yt3H///fbP0uk0H/vYx9iyZQuhUIiuri5uuOEGu/l6MSGrGJbuf7Ka4pXmZiSPJ/sDw8guWg2CvOUqGQAnJ7PE0EIxxXAomSau63gkieX+QmIoFqPM0GkMXcdIa6TNRcm7vAFaVooNJ09gGAZHjhwhFhWL8Oqg6HdctqF8GdnClnqhpFiKIWTLySsyYsE+dOgQWpFs1N6twoAyfCxMIuLemy4EsophU9ntSk49sUrJDeI+0PVMdk5yIKsYVioln06mmdV0VKl0hqE2lcSIZ0CR8mYkW599liN5rH8Ww4C6Zh+hpvKGl7OJ8fg4Tw+Lz/aF7ka24M5KXmCos92PZ6YYeleuRO1aSmboNLGnn6buqqvOxuUJyApc9A7xNTsMh34hMg/7fyf6t0b2iq9S8ITAVw++OvAERGai6gPFB4oXFFWU2mTV/JLFlApJMb9bXxIg5c90tl4r/HPez/NeKP9ed/xvu3n6bOIHP/gBu3bt4o477mDHjh189atfZefOnRw6dIiOjo452z/++OO85z3v4bbbbuMtb3kL3//+97nuuut47rnn2Lx5M7FYjOeee45PfvKTbNu2jampKT7ykY/wtre9jWefffasX/98IhEVJdlyGYaZcaspvkDJiE9BxiRQ9WLBSCTEAmLN6j45ObfMZZnCUvE4qXgMbyBol5F7A148BY3sniUdIMsY6TSZ8XH0mA90A7neI1yTzRYxPM7IyAizs7MkEs1AP0vrhhlD9AA6ga0Yzmb7BC1i2DrsIRAIEI/HGRgYYOXKlXn7NrQGaO0OMTEYpX/fBOt3nP3fdRcXHqwc3UAZxVBPJtHDgkDOuc+sqBpTMUwmRzAMDUny4PW0MzC5B4AVFRTDw2Z/4cqAD69cXMdKW/2FnSEkVTbPl2R0VDxgWYrhsNVfeJ7VwgdOPIBu6Gxt20pPfc95PXetcInhAkMoJy/NMIya3UuSJFH32tcyfc8PmHnwwbNLDHNR3wmX3ii+DEN8IIzsg7GDokw2PSBKd9ExiE0CBqSj4itS8ejzj81/cE6I4Ze//GU+8IEPcOONNwJwxx13cN9993HXXXfxt3/7t3O2/9rXvsa1117LzTffDMBnP/tZHnzwQb7xjW9wxx130NjYyIMPPpi3zze+8Q0uv/xyBgYGWL58+Vl/D/OFrPmknGJYghhaSkawTYS5k43R8AfEImY5knPz1byBIP5QHYlohJmxUdqW99rTRgqNJwCSx4Ons5P00BDpkyfRosLt7F3eIO7pliwxPHr0KAD19euAPQTrT5OSDMc5a5vq/MjASCrDSDLNEp9H9Bn6FUhorF27iheP7OPAgQNziCEId/LEYJQTL4y7xNAF4KyUbE09kbxe5IYCsmVnGFrtGqLn0O/vYjyaJpbSkCVY1lyeGB6yy8ilR+GlSvQXGoZBY2MjDea1nT4m3tPS1U1lz3m2cd/x+wB406o3ndfznglcYrjAYLkfdS1DfHamYo9HOTS86U1M3/MDZn/5K/Rbb507suhsQ5KgqUd8rb927s91DeLTkAxDclY4m9MxSMchkxRfWkrEHGhp0NNiH0MDXQej4AvDDN4u/F6AvNcqxHIU7h9sLb7dGSCVSrF7925uueUW+zVZlrnmmmt44okniu7zxBNPsGvXrrzXdu7cyb333lvyPOFwGEmSaCoMeM5BMpnMC0CemZlx9ibmEXaURqhMuHXF3qdsU/ycHsNJoSj2FDTGN7QvIRGNEDaJodX7VNhfaMHbu4L00BCpvn60uCCZPmsMV+sa8X3iKEdiImewq+tSYvH/xNtwmn5FI5zI0ByqfM+GFIU1QT+HYwlenI3xel+j6DNc1URi/wQrfUt5kX0cPHiQN77xjXMeNldubWf3L/rFFJS0juJxO4xezjAMw1EpOffha46AMZN/n2XbNXrsMnJXUwCvWv53ze4vLDcj2VIMc+aJnzwpiGhPj1DoDN1g2CSGnavPnyO5f6afvRN7USSFa3uLrIkLFC4xXGBQVA/++gYSszNEp6fOiBgGL70UdckSMiMjRH/7W+qvueYsXmkNkBUItYqvlzHGx8fRNI0lS5bkvb5kyZKSJoHh4eGi21s5XYVIJBJ87GMf4z3veY/9xFwMt912G5/+9KerfAfzCydxNXaPYSnFsCHbFB+PZ4mhYRhFS8kADe0djPYdY2ZclKgOmouWFTJdCM+KFfD4EyT7+tGSYoH09pj/F+3rxXsZ7+ckYhFbu/ZV7HlBRvHGGauf5ODwLFesdnavbK0PcDiW4IXZOK9vE58Z/tWNJPZP0DlVh8fjYWZmhqGhIbu0ZqFjRT3BRi+xcIpTh6dYcdHiuz9vv/12vvCFLzA8PMy2bdv4+te/zuWXX15023379nHrrbeye/du+vv7+cpXvsJHP/rR83vB84hkNIpu9qOWKyWnR8R9oBa2vmRS2azQRkHMEtY9Fuhmn91f6MSRLB5a15dQDA3DsBVDT45ieOqUIKLLlon7fGo4RjKWQfXKtPWUj7k6m7DUwld2vZLWwIVzX7mPhgsQVj9TZPLMJhJIskzDm4R8Hb7vvjO+LhcXBtLpNO9+97sxDINvfvObZbe95ZZbCIfD9pf1pL2QkZ2TXJrwVm6KF/2EmUyUTGZaHM/fTTieZjYpJvwUlrkazDzEmbFRDMPgoDltZGOJRcu7QkwzSZ8cQ59Jieb4Zeai1Lgc1ADH9aXouk5LSwsNdW2kI+Ic6cYhDg47V28vaRRqye6ZbL6ob00TAPpAlLVrhEJZLOxakiVWWmHXLyw+d7LVz/upT32K5557jm3btrFz5067B60QsViMVatW8bnPfY7Ozpdfad1SC72BIGqucasAVni7xwxztzE7BBig+u2KSyIvqkb8ji5vKW88MQzD7jEsRQy1cBI9kgZZwmtmGOq6PkcxPH1sGhAxNYpyfmiPYRj8/NjPAXjLqrecl3OeLbjEcAGiwUyRnxkr/sFV1bHe8mYAIg/9D5nJM3M6uzg7aGtrQ1EURkZG8l4fGRkpuRB1dnY62t4ihf39/Tz44INl1UIAn89HQ0ND3tdCh2U+KasY2sG7hcSweFSNqjagqvUcHzfjLBp8BLz5U1UaLWI4OsJQMs1MRrglSwXvent7xbVMiPYEb1cdsnVMWYa2tRxFbLN27VqGjkyTDItFtqH+NAdPz5Z8f4W4uEGQ2OdnYuhmO4TaEUSu92CkdVa3CpJaMrbGJIZ9L4xh6ItrCkpuP++mTZu44447CAaD3HXXXUW3v+yyy/jCF77AH/3RH+HznT/36kJBbGYacJBheFq4jNWlBcRwekB8b+i2zX6xeD8A/kAPfaZiWCmq5nQyTTijoUilp55Y2aCepSEkj7i3JiYmSCQSqKpqV1msMvJS82HpfOD50ef/v/bOOzyO6t7f78z2pl31almSLfeKjY0xNsUm9AABQoAEQiDk5kIaye8m3ATITbmGBEgBAgm5CQRCIPRqmjGmGRs3ZNzkJqv3sqvtu3N+f8xqJVnFsi3bkn3e59Gz0s7szBntnj2f+VaqO6uxG+0sKVxy1M47HEhhOAJxZ+mLvbep4QB7HhjrlClYp01DRCK0//vfh308yeFjNpuZM2cOK1asSD6naRorVqxgwYIF/b5mwYIFvfYHePvtt3vt3yUKd+7cyTvvvEN6+uhxXRwMoSG06xow+aRPUHyXG1l3Oe1u1K2RJRl9RWdKpr7IeJsb2ebv6sZgHTBbsstiKOIpib97i26RMSkpDMePH0/V1lbCXn2RzXXWs+0gLIZTHDasqkJ7LJ7sLasoCpZEoP2YcBqqqtLc3ExT4n/Tk4JJqZgsBvwdERr3DV2QjnS64nmX9gijOVA876EQDofxer29fkYrwUSm8WBuZIBobaIwfG5e7w1dPcDTuhOdAgH9Obu9mF2JOTYuc3CX7uedukW+1G7FMsAcS3YTGtP9XdBlLczLy8No1KPlao9BfOHLu18G4AtFX8BmHLg490hECsMRSJfLqqPx8IWhoiikXXctAG3/fBIRiRz2MSWHz6233sojjzzCY489xrZt2/j2t7+N3+9PZilfe+21vZJTvve97/HGG29w7733sn37dn7+85+zbt06brnlFkAXhZdffjnr1q3jn//8Z7JPaH19PZHj6D3X4nHCAd2qN6gwHCj5ZL/6at3CUF/cuiyG47L6urmS87KpkW2JRWvSINmS5oICMBhQ3foCadmv20KjfTxeXBgVQVFREVXbWol49XHkO+vZUe8jPkTrnUlVmJkoW7O+o7tsjbVUT2YTe/2UlJQA/buTjSYDY6frNxJ7Nh2+p2KkMFg870DxuYfCsmXLcLvdyZ8uF+ZoJDDEdnjRhMWwjyu5qwd4oiRTNNpBNKp7qyyWsexp0oXh+KzBheGWxBybNkAML/QvDPft062TXZUYfK0hvE1BFFUht+ToCMNQLJTsjfzFcV88KuccTqQwHIG4uywTw+BKBkg55xyMmZnEmproeFXGGo4ErrzySu655x7uuOMOZs2axaZNm3jjjTeSC1hlZSV1iS9egFNPPZUnn3ySv/zlL8ycOZNnn32WF198kWnTpgF6eYaXX36Z6upqZs2aRW5ubvLn448/PibXeCQI+btrHFkd/S8sWjiMlrDY9LIYCtHtSt6vuHVXRnLXotW/xVAXhkFvB9sSsXwDxRdComRN4TjUFH3h3N9iuDOkxxIXm1sJdsT0AHmvLijGuGqIxGJUtAy9J3mXO7lnnGGXMIzWdDJp3AQAtm7d2u/rS2bpbvfdG5oQ/WX3SwZkNMbqDsRQXclJYbi/K3k/i2EgWAGA2ZxFvU8lHNMwG9U+Wf/70yUMpw4gDEVc626F148wHJuw2NeW6zWBMwtdmG1HJ9/2ncp36Ix2ku/MZ072nKNyzuFEZiWPQFKydHHQMQyuZNDrTKVddy2N99xL0wP3k3LB+agnYOzMSOOWW25JWvz257333uvz3BVXXMEVV1zR7/5FRUUnxGLelXhisTtQDYZ+9xmwvlqgFWKJlo0pXcWtdYthV9eTPU26qCrJ7GsxtDqcWOwOwgE/WxLia9Ig/VsBzCWzURQVxRLD4OpdemZns95ppDS6jcrP9TGnZUxAVS1YjWGy7M1sqfUe0OXWxUkpDqCplzA0pJgx5TiI1vspUrNRFIX6+npaW1tJ269V4Nhp6RiMKh1NQVpr/aTnH73szSPFocTzHgoWi+W4iUcMJm6qBrMYaqEQ8UQv8j7CcD+LYX9u5JIMB4b9isLvz4GEYbQ+gIhqKFYDxgx9n46ODtrb21EUJWkxrClvByB/wsDXM9y8sPMFAC4efzGqMvrsb4c04oNp5fX8888zd+5cPB4PDoeDWbNm8fjjjx/ygE8EuiyGgY52opHwAfYeGqlf/SrGnBxitXW0PfHPYTmmRHK0CXUeuE9yd+LJfvXVvIn4Qkem3mmHnotWEXFNJGusDSTGUjIyiasqeyJ65vJk58AWQwBDum6lQ/RO/AqFQlTW6bF+47Vy9n2mWzILp2bhdE7Sf3dVU1bVPujxezLXrVtgtnWG8Ma6299ZJuhWQ3VfKFnguj+rodlqZMwUXSzu3tg3DnE0cijxvCc6XV1P7IMkosUSbnjFbkftaVkUAlor9N8TFsNgQP/bbi/qji88gBu5MxZnb1APgZkygDDs6UZWEiKzy1qYm5ubFOo1CYth/sShtZg8XKp8VaytX4uCwiXjLjkq5xxuDloYHmzqf1paGj/96U9ZvXo1ZWVlXH/99Vx//fW8+eabhz344xWLw4HZpn/JD5c7WbVayfzudwFofuihpBtAIhlNDKVPcrROX7T61Fdr7W3JEELrZc2obgsQieturjxP/4tRSlY2LalZRFFwGlTGWAcvQK0Y9DFobbt7Pb97926EEKQbOnELP9W79OsaOzUdl3MKAIUp1ZRVdwx6/J7kWswU2cxowKcdPdzJCUtJqLyNyZMnAwO7k8edpLuTd60/fuIMDzaeNxKJsGnTJjZt2kQkEqGmpoZNmzYlO9Qc73TFGNoGKW7d043c6+Yr2KY3MABILdKP14/FsPQAwrAruSvXYiLD3L9jM1KRKKtT2C1gKyoqgG43srcliLc5pMcXHqXEkxd3vQjAgrwF5DpzB995hHLQwvBgU//POOMMLr30UiZPnsy4ceP43ve+x4wZM/jwww8Pe/DHK4qi9CqNMVy4L/4i1hkz0Do7qfvpTxGaNmzHlkiOBslFa5AahtEa3T1sKijovaF1j/6YpidhhMP1aFoIRTFitRYk3cjF6QO7uVIys2jI0N3QM1x21EFaVmrhOFpIt1pEdq7pta28vByACalQG5lMLKpgTzGTMcaJ05UQhq5qPq/tGHICCsApbn3BXd3eHYtpKXKjmA1onVHGucegKAq1tbW09lO+qnhmJqpRoa3OT0vNaOhZeWAONp63traW2bNnM3v2bOrq6rjnnnuYPXs2N95447G6hKPKUNrhdWckDxBf6MoFk35zFQgmhKGtmF1DTDzpykieMkioRrhC9x70TOrqshgWJUpF1exoB/Qi7mbrkY+ci2rRpBv50tJLj/j5jhQHJQwPN/VfCMGKFSvYsWMHixcvHnC/4yn1/1BJSZSs6RgmiyGAYjCQd9ddKFYr/o9X0zqAmJdIRipdRd8dqWkD7pMUhvt1+NhfGHZZMmy2QlTVxO6mLjfXwIV3U3PyqM/sEoaDxxdG9nlBgOZvJlKxlXjC2qlpGjt36m3wJhTnsy88F4DCaekoioLLNRWAopRqApFY0soyFBZ49AX3kx7CUDGqWEs9ABj2hZOL5pYtW/q83mIzUjhFz04+nqyGt9xyC/v27SMcDrNmzRrmz5+f3Pbee+/x6KOPJv/uitfd/6e/uN/jkeQc8wzseh0w8aRtf6u8IJBwJdts3a7kAwnDMp8e0jFtgDkWaw8Rbw+D2m0x7OjooKWlpVd8YdU2/eanYNLRcSOvqlpFU7CJNGsaS8aMrtqFPTkoYXioqf8dHR04nU7MZjMXXHAB999/P2efffaA+x9Pqf+HStJiOEwJKF1YSorJ/vF/AdB4731433prWI8vkRxJOtv0L3pX2sA1GruF4UD11XoLQ7tdX8S6StX0l5HcRVr+GBoydcHZVR5mIMJ72gHQ/HrB33C5Lgarq6sJBAJYrVbGTDqJveGTASiermdQOx0TURQDTnMnqZZ2PqtuH/Q8PTnFo4vaTb4A/nh3nKF1si6kQ9tbk5nsn3/+eb/HKJ2rf/fsXNfQJ6EpEA2wvmE9L+16iZd2vcT71e/TEjy8Dk2SkUM0FEpm/rvSMwfeb6CuJ/vdfEUizcTjfkClM5aFLxRDVaA4Y/CuJxu8ujCcPcAci+z1Js7vRLXoSWh79ujnzsvLw2azITSRFIZdNztHmmfKnwHg0vGXYjIM3DVmpHNUspJdLhebNm2is7OTFStWcOutt1JSUsIZZ5zR7/633XYbt956a/Jvr9d7wonDrmK6w2kx7MLzla8Q3rmTtif/Re0Pf4Tyu/uOfR9liWQIdFsMBxGGtUOzGPoD+t9dwnB7nb7YlGYPLAxT8vJpqteziafaBv/iD+/RXXKqXXeLhct3YD9pNjt27AD0otZew0S88TgqUQqK9NcZDFbs9nH4/eWMTanis6p2vjx3aN9/hVYz+RYTNeEoGzoCLErTYzGtk9JA0cvWTCyYzmuqSkNDA01NTWTu1zawaEYGBpNKR2OQpkofWWNT+KzpMx79/FHer36fiNa3LuaMzBlcMeEKLiy5EKMqi12MVrwtetKR2WbHYh/4xmfArifJm68iAPx+/WbIZhvDjkY9kbIow4HF2H9FAdATT8oTMYZdJZj2J7xXn1uWom539+7dehzvuHHjAGiq8hHqjGKyGsguOfIdnSq9lXxc+zEKCpdNuOyIn+9IclAWw0NN/VdVlfHjxzNr1ix++MMfcvnll7Ns2bIB9x+NbbqGG3dXyZqG4U8SURSF7P/+b1xnn42IRqn+7vdofeyxE6LciWR042/ThaFzAIuhEIJIjW7NMPcUhpFAoocrPbIlu2OfNE2wvV7PcpySO/D3Ta3ZQcxowhwJkdoxcItJLRQjUp3ImizQ3WHhRFxhV3zhxIkTqdihL5YF5jLMbd2uXXfKLADGeSrYdBCZyYqiJN3JH7R1dzAxOM3dtd4qgsnFsz+rodlqTPZO3vRRBd9f+X2++vpXeafyHSJahGx7NqfknsLC/IWUuEtQUChrKuP2j27nspcvY3Xt8HUUkRxdfC16Rr8rPWPQ/SKVep1Gc5+br0SSVeLmq9Ov3wQ5nRPZUquLual5gyeBbPIFEEC+xUSWpf+br3Ai8cRSrM9VTdOSFsOuQu6VWxJu5ImpR6U/8r+2/wuAhfkLGeMa3Yasg/pvDVfqv6ZphMPDU4bleCUtXw+cb62pPiJJIorRSP7v7sP9pS+BptGw7C6q/+PbRKqrh/1cEslw0WUxdA4QYxhvb0cEdDeUMa+HK7mtQn+0esCuv9afdCWXUNkaIBCJYzaqg7q5PksExWc319FeN/BcCe9qBw2MGTZsk4sACJWXJ1vSdd0s7/1MX4iLrZ9C3WfJ17vdJwEw3rOXbXVefKHogOfan8UJK+F7rb1b21kn62I6+Hkz06dPB6CsrKzfG8KJ8/Ub/c2rK3h330oMioFLx1/KMxc9w9uXv80jX3iEh5c+zEuXvMS7X36X7530PTwWD3s69nDT2zdx99q7icaHPmbJyMCXsBgOJgy1SCQZrmEu7m57hxDQmOjFnamXXOrsTAhDxyS21OoW+cFuvEDv9w1ddTn7EvdFiDXq89CcsBg2NDQQCAQwmUwUJJLOut3IA8cjDxf+qD+ZjXzN5GuO+PmONActow829X/ZsmW8/fbb7Nmzh23btnHvvffy+OOP89WvfnX4ruI4xJOdi2owEg2Hkndxw41iNJL761+R/bOfoZhMdK5axZ4LLqRh2TJZzkYy4tC0OP72dmBgYRit1hcsY2YmqrlHKZn93MiaFiaU6HpitxezLeFGnpjtwjiIdWFTYtHKbqqhtWZgYRjaqddOs05IxTJxIgDhHeXJdnTFxcVoYZX6hEusyLKuX2FY7K5EIc76fW0Dnmt/zkjVhWFZZ5CmSLc4s03ThWF4dwcTCsdhNptpa2vrt0vH+8pygkYf1qiTU+NL+fdF/+YXC3/BpLRJvcuTABm2DG6cfiOvf+l1rpx4JQBPbHuCG9+6kdbQwFZVycjD13xgi2G0shKEQHU6MfTsx+6t1UvVKAZIHw9AZ6cuFJ3OiWxNCMOpeYMLww1JYTiAG3lXOwCmPAcGh25R7HIjFxUVYTQaCfmj1CX6IxdOPfLxhS/vfpnOaCdFKUWcmnfqET/fkeagheHBpv77/X7+8z//k6lTp7Jw4UKee+45nnjiiRMm9f9QUQ0G0vJ0M31LdeURO4+iKKR99RqKn38O+/z5iHCY1sf+wa4lS6n85k20P/cc0QFqVEokR5NAeztCaCiKit3j6XefgTOSe7u49ExJgcHgxGzOSArDSTkD10cEWJuoD5hfX0lrbf/CUAhBaGc7AJZSD+aSEjAY0Hw+tpaVATB58mT2bGoCAdm54DS0QPW65DHs9mKMRg8mNcoYVzWfVgxdYGVZTExNFN5+v4fV0JRpx5RjB00Q39WZrGn42WfdglQIwf0b7+e3G37DrowNAFysXceE1AkHPK/L7OJnp/yMB856AKfJyYbGDVy7/FpqO2uHPHbJsaXblTxw4kkkUSvQXFTU+yahKdGDO30cGC0IEU/GGCrmccn2jlMGEYZCCDYkOvcMJAy7brospd2Zxl3hGaWlpQDs+7wFoQnS8hykZAxePeBwiWtxntj6BABXTbpqVHY62Z9DuoKDSf3/1a9+xc6dOwkGg7S2tvLxxx9z5ZVXHvbATwTSCvSU+yMpDLuwlJZS+OjfGfPII9jnzwdNw//BB9T99GfsWnw6u845h5of/ojmRx7B9847hLZv1912Mi5RcpToykh2eDyoav/B60MtVdPTkqEoCtsS8YWTB3FztUdj7EgExefX7xtQGMZbQsRbQ2BQsJR4UM1mLOPHE7DbqGvSXXWTJk1i90b9hmvcyQWgqNC+D3yJjhKKits9G9DdyWv3Hpzl7Yw0/TpW7udOtk3TLUHBz5uZOXMmoJetiUZ1y+L9G+/nL2V/AeCkxXocYsVnLYQ6h+4WPn3M6fzz/H+S58hjn3cf1y6/lkrvkf8Okxw+Q3El9xSGvdjPjRwMVqJpIVTVSkWbByEgO8VChnPg1oFVoQgNkRhGBab3k5EshCCUsBhax3sACAQCSav3hAn6Dczez/TrKJ45eKzkcLCyaiWVvkpSzClcMv6SI36+o4FMHxvBpOfrAawtNUenIbuiKDgXnYZz0WlE9u2j49VX6Vz5HqEtW4juqyS6rxJee633a0wmDGlpGDweDC4XqsOB6rCjWG2oVguKyYxiNqOYjGAwoBiMKEYDqAZQFRTVAKqq/64ooCj6IqkkB9V9V9rLhdXj90GKDB/UPv3gOvMMDANYpyRHl2R84ZBK1ewnDJsTXSsSwtDXqXf+6Ooy0mUxHEwYrvPqQfGFJhVH0E9rTRVCiD6u1aRFY2xKspSGbcYMNgs9VriwsBCDMFOb6OE6bt4YqJwK9Zuh8hOYegkAbvdsWlpWMs6zl79v6SAUjWM1DZzN2ZMz01w8WNnIqjYfmhDJQty26Rl436kktLONsVeU4na76ejoYNu2bXyqfMojmx8B4CfzfsI1k6/h6dVraa7qZMeaemYuGXpAfYmnhMfOe4xvvf0t9nTs4Ya3buDv5/ydAlfBgV8sOWYMxWIYHkgYdlkMs3RLdFd8ocNRytY63Qp4oMST1e36frNcduz9hHTEGgNo3ggY1WRG8s6dOxFCkJ2djcfjIR7VkoknxTMHvo7hQAjB37f8HYArJ16J3TR4CavRghSGI5j0o2gx3B/z2LFk3nwzmTffTNzrJfjZZ4S2biO8axeRvXuJ1tQQb2tDRKPEGhqINQxvvcWRgvXFF6QwHCEkLYaDlarpTxgKAY2JjN9sXQh2+vRFzOmajDcUpbot0WlhEGHY1WbulLQUVIOBSDCIr7mJlMzerfeCW3UBa+3Rm9U2ayb72nTBOHXqVHZvbEIIyCx06a6uMaf0EYYe9xwAJqftJhKPs7GynQXjhhYvNc/twGVQaYrE2OANMNetB/Kbsh2YcuxE6wMEt7Qwe/Zs3nvvPd766C0esz8GwK1zbk0G0E9ZmMf7T5Wz9aNaZpxV0EcED0aOI4f/O+f/+Mab32Bvx16++dY3+cd5/yDTfmQXa8mhIYToFoYZh28x7LbKT2LLFj3e70CJJx8nCrN3ZdbvTzJEoygFxaQLx2QXoYS1sHpHG9FwHIfbTFbh4KEhh8u6hnWUNZVhVs1cPfnqI3quo4kUhiOY9IKExbC6f8vE0cKQkoJz0SKcixb1el6LRIg3NRFrayfe3o7m86IFAmj+AFowiIhEEJGw/hiNIWIxRDwGcQ0Rj0M8DgiEJkDT9AW862/Q/xb9/K7v1f9gh9m1rToGL8QqOXocKCMZeixaY3pYpry1eg9XxQAZE/UFsFMXhi7nZMqq9EUr32PDbR+4NuGaxKI13+MiPmYsTRV7aNizq5cw1EKxZP1Ca4+iuqHiYlo3b0YRgikTJ/L2X/WYx/GJYtIUngKfPgJVnyRf43bPRlWtuMxe8p11fLiracjC0KyqLE1P4YXGdl5v6kgKQwD77Cw6llcQ2NjI7K/owrCzoRNngZMrZl3B9dOuT+47YV42Hz+3i9ZaP/W7O8hNuO+GSoYtg//7wv9x3RvXUeWr4lvvfItHz32UFPOJV4JspBMO+ImG9BukwV3Jetu5XsJQCGjSLYRdFsOuOeZ0TmRjZTsA0wsGtxh2CcNTBxKG2/WbQ+sE/aYrFosle1h3CcNdG/QQjeKZmSgDtLYcLv5c9mdAb3+XYTvybuujhRSGI5jU3DwUVSUSDNDZ1oIrbWR98FSzGTU/v6/bTiI5AnQeoIahFg4TScQamceP797QkLAWZkwAk5VwuJ5otBVFMeBwTGBDoibbSWMHbpsV0TQ2Jdp0zXM72FM8XheGe3dROr87CzFU3gZxgTHThimz261U7tNj/bIaGgjtqKJuVwcoMOHkRBepwlP0x7oyCHeCxYmqWvB4Tqa19QOmpO3gvR2T+H/nTBrifwvOzXTzQmM7y5vbuX1cbvLG0jYzi443Kojs9RL0NtPsaCbDn8GZypl8f873ex3DYjdROi+bbR/VUfZe9UELQ4BMeyZ/PvvPXLv8Wna27eT7K7/Pw0sfxmwwH/jFkqNGl7XQ6nRhslj73Sfu8xFPZC6bi8Z2b+iohogPVCOkjUMIgderJzWppsnsbNTn7pxB5lhVKEJVKIJB0efY/mjBvjddu3fvJhwO43K5yM/PJx7V2LNRjy8sPTmrzzGGk02Nm1hTtwajYuQb075xRM91tBn96TPHMQajidQcvRZbS+W+YzwaieTYciCLYWTvXtA0VLcbY89uHg2JIs7Zeg/iLjey3V6CwWBlQ6Xu4j2p0DPguT/t8BPSBBkmI+PtFnLG6cKzYc+uXvuFutzIk7vFqxCCzxN9iQsrK9nxnl4/MX+CB2dqYgF2F0BKAYg4VK9NvjYt7TQApqTvYEutl0ZfaMAx7s+StBQsqsLeYIQdge7XGT0WLMW65ea1l56m3KG74lKaU4hFY32OM/0M3fq6Z0MT/vZDqz87xjWGh5c+jMPk4NP6T/nZRz9DE8Nfn1Vy6Awt8URfhwyZGRicPax6XXMsvRSMZsLhOiKRJhTFSHmbvoYVpdsHTTxZnbAWznTZcfTTGSVU3gqawJhlw5TINO7q9z1lyhRUVaVyawuRYAyH20zuOM/QLvwQefizhwH44vgvkufMO8DeowspDEc4WcV6ZmD97p3HeCQSybHlQMkn4Z26SLOMH9877KLLYpgQhj0TTzRNJN1cg1kzuopFn5Hm0jsHFXcLw67MfBHTCG7XRaatR1Hduro6GhsbMQD5VdXsSdzjTZi3X7eo4sX64+53k0+lpS4EYFLabgxKjA/Kh17T1Gk0sChR0/CVxvZe22xzdGvKvIbJiHQNl9tFKBhi8+bNfY6TOcZF7ng3mib4/P2aIZ9/fyamTeS+M+7DqBhZvnc5D2x84JCPJRl+vImyZK6MQRJPdurrkKWouPeGmvX6Y74eF9vRsRHQ4ws3VOru6TljBy803VVaaSA3cnCr7ka2JW66otEo27frcYxd/b93rtOvYfzc7CPqRv60/lM+qv0Io2LkxunHX+k9KQxHOLnj9biJul07jvFIJJJjh9A0Ohr1BKeuPuL7E07EGlkS7d6SJIWhvnj4fPrfTuck9jT76QhGsZrUQTOSV/UQhgAZhUWoBgNBnxdfs25pCe1sQ4RiqC4z5sLuY23cqC+SpdnZhGwF+DQnRpPKuJP2c3WNX6I/7uoWhk7nREymdMyGMOM9e3mvvGnAMfbHJVkeAJ5vaOtVWuox7Vl8aoCcaAYPjPstp8zTXdlr167ttwTVjDP1eOfNq6qJhuMHNYaenJp3KncsuAOARzY/wgs7XzjkY0mGl67yS2l5A2eOhxIF2q1TJvfeUKPXvCRfL8ze4d0EgDtldrI4+2A3XnEheLdVrwxwZlrfhBER0wjtSMQXJtzIu3btIhKJkJKSQn5+PpFgLFmmJhm7ewToqvUJcNmEy0Z9+7v+kMJwhJMzXu+aULerXNYMlJyw+FqbiUXCqAZDso/4/iSFYc/4wlgYmnVXKdlTEULQ0aFbN1Lcs5Nu5Bn5HkwDdDxpjsQoS7TCW5ywwBnNZtLH6DFWXe7kQGJRss/ISForotFo0go3Z/FiavP1BK6SSXYstv1CvMedBSh6BrVXbxKgKCrp6fprZmVuZtWORiKxobtgz8twY1NV9gYjyY4SK/at4OGtf2aFew0A6dssnHTSSZhMJhoaGpI9Z3tSMjsTd6aNsD/G1g8Pr2D1paWXctOMmwD4xepfsKZuzWEdTzI8dJVF62rH2h+hbbq13TK5hzAUoofFUBeG3i6LoWtGstf33KKBheFn3gCt0TgpRpV57r4Ww1B5GyIU12+6Ej2/uwqzT506FVVV2bmugVhEIzXHTnbRkUtuWlm1ko2NG7EYLMnP8fGGFIYjnKyiElSDkaC3A2/T8VkSRiI5EK21ugvTnZ2Lwdh/zlykSxiW9hCGjdv0uD1bKqTkEQzuIxJpRlHMpLhmsDEhDGeP9Qx47vfbdGvhVKeVLEt31nJOiX6e+t3laJF4Mr7Q1qN22vbt2wmFQqSkpFAwdjwNWbqrbayhnxJU9jTI04ta93QnZ2Z+AYC5OZvxhqJ8tGvo7mSH0cAFmXo84bMNbexu381/f/jfABjn6Ncc2taCKaxw0kn6ov7hhx/2OY6qKsw6Wy+ftemdSuIHIU7745ZZt3Be0XnERIwfrPwBu9t3H9bxJIdPt8WwfwuY0DTC23TXrXXylB4v3AOhdjBYIGsqmhbB16lb5euD4wlG46RYjYzP7N9FDPB2i24tPD01BVM/LuD9b7o6OzuTZWpmzZoFwNaP9JupyafmHbEKHtF4lHvX3QvAtVOuJct+ZBNcjhVSGI5wjGYzmWP1eI66ndKdLDkx6epLPJCbq2dGci+LYfWn+mPebFAU2tv1tnMpKdNRVTMf7NRF1vzigeOf3kksWl3dRLrInaBnCFdv20JoWysiomFIsyYtGgCffqqff/bs2ZSvbURTjDj8tdg+f7//kyXdyW8nn0pPW4yqWkmztlDoqua1zQfXx/yybN1S82JDK99Z+UMCsQBzs+dyw1nfxlLiBg06P65lwYIFqKrK3r17qanpG0s4aUEO9hQznW1htq8+vF7qiqLwy9N+yeys2fiiPm5ecTPNwSPTE15yYCLBAJ2JrOSBLIbRyko0vx/FYsEyrqR7Q5cbOXcGGM34fFvQtAhGo4ePKvTkqgXj0lEHiflbkZhjS9P7Wvq0cPdNl32WLsTKysrQNI38/Hyys7NpqemkscKLqipMPCWnzzGGiye3P0mlr5IMWwY3TL/hiJ3nWCOF4Sggt7QrzrD8GI9EIjk2tNV1CcP+SyNF9uwBTcPgdmPoWZy3crX+WKiXlGnv0IWhx3MyFS0BqtuCmAwKp5QMkNCiabzVrJfIOC+jdw22wql6S7n63eV0rtXdq/aZmUlrRV1dHZWVlaiqykknzaHsXV245te8T2DtGr2W5/6UnqM/7nwHonomscFgIz1dT0yZnVXGW1vqD8qdvDjNRZ7FRFtMY2cshxxHDvecfg8m1YRzsS4C/GvqSbE6mT59OgCrVq3qcxyjycBJ5+ru83WvVxCLHnqsIYDFYOEPZ/6BQlchNZ01PLntycM6nuTQ6bLI290ebM7+i0J3xRdaJkxA6Wm13y/xpLX1IwBSU+fzfiJZ6vQJA1vWakORZKjGWel9zx3a2oKIahjTrZgKnAghknG7s2frFvbNq/TxF83MwJ5yZMogNfgb+NOmPwHwndnfwWE6fmvcSmE4CsjtijMs336MRyKRHBu6Fq7UAYRhKFG2wjJhQrcbSQjY1yUM9X7u7e26Bc/jnssHO3X31NyxadjN/bunV7X66Ixr5FpMnJTSu92VOysbd1Y2NsVJeLdu8XDM7Y5/XLtWLzszefJkWvaG8TaHsNiN5Ae2onm9BD8r63vC/Dl62ZqID3a9k3w6M1MXjKfkfoY3FOXDXUNPQjEoCuPRvQ3hlLP5/Zm/J92mC2HrhFSMmTZEOI5/bT2LFi1CURTKy8upru7bC3rqojycqRY628Js+eDwYg0BUq2p/Gnpn/jm9G9y86ybD/t4kkMj6UYeLL5wayLxZPJ+iSdViRjRpDDUQxHsrgVsTMQXLp4wcAmclxIZ86e4HWSa+xaY93+q9w+3zcpCURQqKipoamrCZDIxdepUQv4oOxIW7BlnHLmWi7/59DcEYgFmZM44bnoiD4QUhqOAgil6NmX97p2EOjuP8WgkkqNPW0IYpuX2/8UfSFgQbAkLAgAdVeCr1Yvu5s8hHGkmGKwAFNzuOUlrxqJBFq1Xm9oBOD/Dnew33JMxU2dS7JqBAlhKPRjT9fpqPp+PsjJd+M2bN49N7+gxhVMX5+NepFsvfW+91feEqppsiceW7ozdzIwlqKqVLHs9xe59PP3p0Punv7rnVbbsvhdEjIh5HHFzd6kRRVVwJayGvverSUtJZeZM3RL67rvv9jmW0WRgznlFAKx7rYKQPzrkcQzE2JSxfPek72JQh9YHWjL8tHYlngyWkbxVTzzplZEcaIVafe5RdBqxWCcdXv3vXe2TiWuCkkwHBakD9xB+oVGP8704u29ySrQxoBe1VsBxsu4i/uQTvTvQzJkzsdlsbPmghlhUI2OMk7wJnqFd8EGysnIlb+17C4Ni4I5T7kBVjm/pdHxf3XFCSkYWafljEEKj8vNNx3o4EslRJRoKJYvvDmTRCG5ICMOTegjDykR7udyZYHbQ2qLH9bmcUxCKk9W7dWG4uLT/um0RTeOtZt0SeGGi7Mv+FE6ZQYlTd786etQl/OSTT4jH4xQUFGAIuqjb1YFqVJh+egEp5+jJJN633uy/0sDUL+mPO5ZDRM8kNhpdZGWdC8BpeZ+wYlvjkIpdb2rcxJ0f3YmqeZli0q/34are1kb7SVkY0qxonVH8n9Rx+umno6oqe/bsYefOvvVTpyzMJS3PQcgfZd3rFQccg2Tk0xXDm54/QOJJLEYwkQVsnTa9e8Pe9wGh90dOyaO9fS1CxLBZC1m1R3fpDjS/APYEwpT5ghgUuCjT02e7f61uLbROSsPosdDa2sqOHbr1e/78+cSicTav1Mc+c8mYI5J00h5q5xef/ALQE04mpk0c9nOMNKQwHCUUz9IzBvdu2nCMRyKRHF3a6nWXpdWVgs3VNzg91tamdz0BbAlrF9AjvnABAM3NugUsPeNMPtnTgj8SJ8NpZsoA9QvfaPbSHouTYzb126ILIJtCbEYXwVgnokB3RweDwWTSyaJFi5LiacpC3Q3rOO00VLudWG0dobL+3MkngacQon7Y8Xry6dzcywFYkLcRlTDPrR+82HSlt5LvvvtdIlqEs8acxe9m6mVvXmxoY2+gu4OJYlBJOUsXBL5V1bhtLubP113vb775JvH9YiFVg8ppl5cCsHllNa21/kHHIRn5tBzAYhjauhWtsxM1JQXr5B5tGfes1B9LztSPk3Aje1JP5c0tehWNsyYNHF/4fINuLVyc6iJjv3AOLRLHv14/hmN+LgCrV+tzevz48WRmZrL1wzr8HRGcqRZK5/RfxupwEELw6zW/pjnYTLG7mJtnnxjhDlIYjhKKZujCsKJsg6xnKDmhSC5auf3HFwY3bQLAXFKCMTXhjhKiu+TL2FPRtDAtrR8Aulv21TJdbJ4zNWfAbMkna/VMyK/kpmHoxxIhhCCyXl/Yyr3r2L1BjylcvXo1kUiErKws7CKTmvJ2VKPCSefoiRuq1YrzjDMA8L7xZt8TKwrMvFr/fd3fk0+neuZjtRZgMQSZl7OeJ9fuIxbvPwmlNdTKf674T9rCbUxJn8KyRcuYmeJgaXoKGnB/Ze/SV/bZ2RgzbGj+KL6VVSxevBi73U5zc3MyVrInY6akUTwzA00TrHxiO0KT30mjlXAgkIwxzBhb3O8+/jV6HKH95JNRDD1c/nve0x9LzkAIQXOzHhfbGJlFqz9CmsPMgnH9J3bFNMG/6vQ5dlk/bmT/2npEMIYh3Yp1QiodHR1s2KAbRhYuXEgsEmfDGxUAzDl3LAbT8MuZF3a9wBsVb2BUjPx64a+xGAZu6Xc8IYXhKCF/yjSMJjOdLc20VMm+yZITh/pEmaas4pJ+t/frRm7cBm0Vem214tNpa1tLPN6J2ZyJ2TaZNz7XXVQXzey/x2llMMyqRP3Cq3L7L2UT2tFGrCGApmrs9m1i55qP8Pl8SavG6aefzurn9fp8Uxbm4UqzJl/rOk93C3e88goiEul78DnXgWKAfR9Co550pigqBfm6YDyv+D2qWgMsT1xHT/xRP99+59vs8+4jz5HHg0sexG7SY7y+P1a3qvy7vpXdPfonKwYF9wW6KPB9WIMpAEuW6KVz3n33Xdrb2/ucZ9GVEzBZDNTv6TisVnmSY0vdrh0gBO6s7AH7kAfW6DcHjvnzup9s3avPMdUIRQvxejcRCtVgMDhYXq7fBJ03LWfAwvFvt3RQE46SZjJw4X5uZBHT6PxAF6uuxQUoqsKHH35IPB6nqKiI4uJiNq+qSVoLJ586/L2Ky9vKWbZmGQDfOek7TM+cfoBXHD9IYThKMJktjJk2A4Adn3x0jEcjkRw9anbo2ZB5E6f0uz2QsCLYeyae7HhNfyw5AyxOmltWAJCRfiYf7mzFG4qRnWLh5KL+F8J/1rUigMWpTsba+loJhCbwvq3foJlnphLVwlR+/hkr3nmHaDRKQUEBSnsqTZU+zFYD8y7sbYlxnXEGhswM4s3N+PpJ8iAlDyaep/++7m/Jp/Pzr8ZgcJLjqGN6xlYeem93Lw9CMBbkO+9+h60tW0m1pPLw2Q+TYetOrpnrdrAkLYWYgF/t7l2L0DopDUupB+KC9pd3M3v2bMaOHUs0GuWVV17p46lwpVk55RJdrH/83C7a6qVLeTRSu0NPKsmbMLnf7SISIbBeL0ljT4QYALDtFf2xcAFYXDQ06nMuLe0slm/RLekD3XgBPFqjWwuvzk3Hup94DGxsJN4RQXWZcczJpqWlhfWJMZx++ukEvJFkiMbJFxYPu7WwPdTOd9/9LqF4iIV5C/n61K8P6/FHOlIYjiImn3YGANs+XCndyZITgmgoRGOFbnXLn9h34Yq1tRFMZCTb55/SvWHHcv1x0vloWoSGBn3Rysz8Ai9s0q1bF0zPw9CPG9kXi/NojZ6ocW1e/xnLwc+bidZ0opgNZF4wiczCIqJGM5sSAfqnLzqTT17SW8vNPb8Ym6t3bTXFZMJzuR4z2PbU0/1f/Nxv6I8bnwC/Ph6j0UV+3pX6+EtWsLWug/d2JHo1x0J8f+X3+bT+UxwmB39a+ieK3X1dg3eMz8OgwPLmDj5KWEVBLzrtuWgcGBRCO9oIbmrioosuwmAwsHv37mTcZE+mn15AwaRUYlGNt/+2lXj08DqiSI4+tYkyaAPdeAU3b0YEgxhSU7GUlnZv+PxZ/XHqpQih0digx8NWh07FG4qR5Rr4xmtbZ5BVbT4U4Nq83q5mLRLH+45+0+ValI9iVHnzzTfRNI1x48ZRXFzMmlf2EAnGyCx0MWlB7mFcfV8i8Qi3rrqVms4aCpwF3L347uM+C3l/TqyrHeWMP/kUTFYbHQ311CasKBLJ8Uz97nKEpuFMzyAlo28Qe+fK90DTsEyejLkgEYPoresuujvhXJqb3yUabcVsziJqPJk3E+7Xy+b0H7P4WE0zHbE4pXYL52e6+2wXMQ3vW4mFa3E+BqeZ0lNOI5RbBOi9Wys/CRP0RvBk25lxZv8B/alXXAGqSuCTTwj3k/3LuLMgd5aehPLx/cmnx4z5OopiptSzi2kZ27hr+XY6w35uWXELH9d+jM1o46GlDzEtY1q/553osPLVXH0x/nF5NaEecYqmLDspS/XWd+2v7MFjcnH22WcDeiJKfX1v17WiKiy5bgoWh5GmSh/vPy2L8I8mNC1O3c6EMJwwqd99fG/pXXgcp56KoiYkQ/MuqPtMdyNPuYS2ttWEIw0YjS7+vl4PV7hqXmG/N14A91bon6MLMz0U7meR7/yohnhHBIPHgnNBHjt37qS8vBxVVTn33HOp3dme7Nd92pdLB+2ocrBoQuNnH/4seXP1h7P+gNvS9zvgeEcKw1GEyWJlwvyFAGx5f8UxHo1EcuRJupEHcHP5VujzwLV0SfeTZU/pjwXzwJVDbd2/AcjN/RL/XFNDTBPMK0pjal7fL3x/PM6fq3UL3M2FWf3WLvStqibWHER1mnAu0sVl2J2BZnNAPEahI5/tq+tBgbOunTygm8uUl4crEcfX/NBDfXdQFDjjJ/rvax9JWg2t1jzGjLkWgK9MfJny5louf+nrrKlfg91o509L/sTsrNl9j9eD20pyyTIb2RUIc19Fb7HnWlyAKd+JCMZo/dd25s2dR2lpKfF4nKeffppAINBrf2eqhbO/MRUU2PphLZ+v6lsYWzIyaa7cRyQYxGyzkVE4ts92oWl4l+vW95QLzu/e0GUtLDkTHOlUVT8GgMl5Hp9WdGJUFa6ZX9jvObd2Bnm1qQMFuLWodyZxrCOM7z398+M+p4hwPMIrr+gu63nz5uFJSWPFP7aB0Msm5Y33HMbV90YTGr9Y/QuWVyzHqBi574z7mJA6YdiOP5qQwnCUMfX0swDY9uF7BH3eYzwaieTI0hX/1J8bWQsG8X+kx9u6li5NPKl1Z/LOuY5QqJaWFj0bOT3zSzy5Vi80ff3Con7P92BlI02RGGOsZi7L7usGizYF8K7Uj+G5sATVYqSuro4PEgknlsZq1j6rL2Qzziwgd9zg1oaMW/TyF97lbxAq78faNuFcvQ5j1A/v/jL5dNHY/8RodJPrqOUL0++lJrgdp8nFX77wF+bmzB30nAAek5G7J+iWzAcqG/m4rbtwvmJQSb9qEorFQKTCi/fNCi655BI8Hg9tbW0888wzxGKxXscbOzWdUy7W4w3ff6qcPZuG3plFcuyo2rIZgJzxE1H7KTAeXL+eWGMjqsuF47TT9CfjMdj0T/336ZcTCOxLloJ6fY++zwUzcslKsfY5nhCCX+3WrX0XZXmY7LT12tb+wi5EOI650IVtZiZvvfUWXq+X1NRUzjzzTD74dznepiDOVAunXl7a5/iHSlyL88tPfslzO59DVVR+fdqvOTXv1GE7/mhDCsNRRsGU6WQVjyMWDrNh+cvHejgSyREjGglTvb1LGPaNf/K9+y4iFMJUUIBlQuLOfve70L4PrG6Y+iUq9v0Z0EhNXcCzmxRa/RHyPTbOntK35llVKMKfKhsBuGNcHqb9XFQiptH69A6ICSwTUrHNzCQUCvHcc88Rj8cpzMvD1N5MxL+V1BzBgkvHHfAarRMn4jrnHBCCpt/9vu8OigLn6JmRrH8MqnUXucnkxpB+KQBfzGjFLRxM1H7CzMyZfY8xAOdlergiJxUN+PbWCpoi3V1MjBk2Ui/TF97OD2oQW7xcddVVmM1m9u7dywsvvICm9Y4nPOmcsUxemIsQ8Nb/baFqa+uQxyI5NpSv0W+sxp10cr/bO17X4wZdZ5+Nak7EyW57GdorwZ4OUy5OWAsFVudC/pmI4LjhtP7L3ixv7uDdVh8mReG/inN6bQtsaCS0vRUMCqmXlbL5883J8jQXX3wxu9e1sO2jOhQFllw3GYut/zaWB0s4Hua/3v8vni1/FgWFXy38FeeXnH/gFx7HSGE4ylAUhfmXfhmAjW+8Qng/t45EcrywZ/2nRENBUjKzySruK7LaHn8CAPfFF3d3PFj7Z/1x5tWEtHZqa3U3cmbOf3D/u3oc3/eWlGLcLwtSCMFPdlQT0gQLPA4u7Ce2sOPNCqLVnSg2I6lfGo8Qgueee47m5mZcLhfZzEE15AJxUlI3YzQNrcVb5ne/A0YjnStX4n377b47FC2EGV8BBLzyXbRIgL9u/iu3rH+G3SEVqwpXuVys+lzh+Q0H58a9a0IBEx1WGiIxri3bi79HMWv7jMzueMMXd+FqVPnyl7+Mqqps2bKFl156qVfxa0VROOPqiRTPzCAe1XjtT2VUbG4+qPFIjh6+luakRb70lIV9tsc7O/G+qidtpZyfEEpCdMe7zruJYKyF2tp/AbB8z2KE0EvUzCjw9D1fLM7tO/XEr5sLsxhv77YoRhv8tL+4Sz/X0kJahI+XX9YNH4sWLcIUdrPqX3rZqnkXlVAwqf+kloOlOdjMN974Bm/tewujauS3p/+Wi8ZdNCzHHs1IYTgKKT15AWl5BYT9fta8MEBGo0Qyytn+0XsATDp1UZ9WV8HNm/XC1iYTqV/Rs3TZtxp2vgWKCiffyN6KBxEigsczn7+vS8MbijEh28llc/omgzxa28KKVi8WVeF/Swv6nM+/roHODxL9mi8vxeC28Nprr7Fz506MRiOTMxZSsaEDs+N0AMpXv0tLdeWQrtMybhzpN9wAQMMvf0Xc20+IyBd+CfYM6pu38c1nz+UPG/5AXAgaXeehqjYmpe7hstJXuO35zXxe0zGk8wI4DAb+Nq2IVKOBjb4A39qyj3APS6BrSSH2OdmgQeu/dpAXcHPZZZehKAqfffYZzz77LNFot6VRNaic881pujiMabz+0GZZ43CEsjNhLcybOAVXWt/s+/annkLz+TCXlOA4Ve8exO53oXYDGK1w8o3s3nMvmhZBsczhiU05GFSFH53Tt2WcEIIf7aiiJhyl0Grmu2O7LfZxf5SWx7chohqW8R5iM5w88cQTxGIxxo0bx7Rxc3n9oTK0mKBkdiZzzu0bC3korKlbwxWvXEFZcxkp5hQeXvow5xSdMyzHHu1IYTgKUVSVxV/VS1mse/UFmvbtPcYjkkiGl5C/k70b1wEwaeHpfba3PqoHu7vPPw9jZqZuyXjnTn3j7K/RbmyntlZPQglbr+fvH+tz5LbzJ/fJlNzoDfA/u3Tx8rOSvF5xTwChHa20Pa9bG11nFGCZnMby5ctZv349iqIwKesU9q7WLfdLrj+L8ScvQAiNtx95EE3r3U5uIDK+/R+YxhYSa2yk9sc/Qeznpo3b0/nXKV/j4oJc1kbbsCkm/ufU/+Gnp/2BKZPvBuC84hXMzfqYGx77lMqWoXsSxtmt/GNGCVZV4Z0WL9dv3kswkamsKLpbzz4rEzRB67+2U9jm4YorrsBgMLBt2zYeffRRvD3ErMGocs5N05h0Sg5CE6x6cgcr/7mdWHRo/wvJ0WH7x3rv8IkLTuuzTQuHaXlMn2PpN96oZyPHIrD8x/oOc79BW2QPDQ0vAwoPrDsXUPjaKWMZl+nsc7xHa1t4qbEdowIPTRmLPWGx18JxWh7dQqw5iMFtQT0vm8efeJzOzk6ysrJYfPIXeOWPnxEJxckd7+bsb0xBOcws5GAsyG8+/Q3ffOubNAebGe8Zz5MXPMn83PkHfvEJghSGo5Rxc+ZROv9UhKbxxkO/JxoJH/hFEskoYduH7xGPxUgvKCSjsKjXtuCmTXhf011cqdfq2bl89i+oWgNGG/FFP2Dbdj2bNyPzcv7rFQNCwBVzCjhzYu+SN/uCYb5WtoeQJliansINBb0tJ8GtLTT/YytoAtvMTOxnFfDcc88l28QVuU6iYYP+NXrGNROZfGoeZ1x7A2abjZrtW1j74rNDul7VaiX/3vtQzGY6V66k6f7u8jRr69bylde+wv/ufY6AqjIzFOaZqiq+pNlRFIXs7AsYO/Y/APj61H8x1v4xV//1E6pahy4OT3Y7eGx6CTZV4d1WH5dt2kV9WLcEKqpC6pcn4jglFwR0vLqHnM8NXH3l1VitVmpqanj44Ycp75E8YzConHXdZOZ/sUTPVv6glmeWraNxn0yYGwlUb/ucup07UA2GZKWLnrT+4x/Em5ox5ubivvAC/clPHoSWneDIJLrw22zZeisAFYEz2VCXTXGGgx+f27fkzfKmdn5aroc4/KQ4lzmJvuNaIErz3z4nUuVDtRuJX5zJo089TltbG6mpqZw28zze+NM2woEYOSVuLrh55pDDM/pDCMF7Ve9x6UuX8vjWxxEILiu9jCcveJKxKcNjhTxekMJwFHPm12/C6nTRuHc3b//lAVn0WnJcEA2HWPO8HiIx8wvn93Lrinicul/8AgD3pZdimzoVWnbDaz/Sty/+EVur7yUQ2IvJnMVvPzmb6rYgBak27riodwLL7kCIL23cRXM0xlSnlYenjE2WpxFC4PughpbHt0JcYJuWDksy+Nvf/8aWLVtQVZVsMYPOcgcGo8rZN0xhaqJ0jTsrh7Ou14Xax8/8k93r+/Ya7g/btKnk3KlbPVseepjPfvdzbnzrRm546wa2t27HZXbx3/Nu4x8ZZzA2GoGnvwqbdeE5ruRH5OV9BVUR3DT9H0xJeY1L//QhGyvbhvx/Pz3Nxb9mjsNjNLDBG+AL63awskUXcoqq4Ll4HO7zi0HREwUcL7Vy3blXkZ2dTSAQ4Mknn+T555+ns1PPcFYUhbnnF/HF78zC5jLRWuvn2bvX88HT5YT80cGGIjnCrH5WjwucesZSnGm9C0xHKipofuBBADK/8x0Usxmq1sK7vwZAW3IHW/f+mnC4jrDI5berz8WoKtxzxUxs5t7C7fWmdv5j6z404OrcNG4u1G/Mos1BGv9cRmSfF8VqoG6RyqPP/xOfz0dmZibTss7gg8f3EotoFE5J44vfm3VYySYbGjbwjTe/wXfe/Q41nTVk27N5cMmD/PzUn2Mz2g58gBMMKQxHMa60DC76wU9QVJVtH6xk1eN/leJQMurZsPwV/O1tuLOymbGkd8xP0x/+SHjrNtSUFLJ+9EPwt8BT10DUjxi7kF05IRqblqMoJl6v+jYf7g7jshj563VzcVlNyeN82Objixt2UROOMs5m4YkZJTiN+qIW74zQ8sQ2Ol7bAwKsJ2VSXtLBw4/8mbq6OkwGC+6WaWgNHhweCxf/YDYTTu6dYTll8VlMPX0pQtN49Xd3Ufl52ZCu3Xrx+bRcq/dRNv/5aSY88TFmDFw16Speu/Q1rpp8NeolD8KUS0CLwnM3wIpfomhxJk38JQX5X0NRBFdOfJHLSv7C1/9vBY+8vwdNG9r3wikeJ2/MncBEh5XGSIyryvbw/W2VNEWiKIqCa3EBmd+cjiHFTKwlRPypSr7kXsz82XpWa1lZGX/84x95//33CYX0XsxjpqRx1R3zGT8nC6EJylZW88Ttq1n3egXhgBSIR5vKz8uo/PwzVIOBUy69stc2LRTSQxnCYRynnor70kugvQr+fS1oUcTki9hu20Jz8ztowsRv115FKG7lf780nTljU5PHEULwcGUjN35eQVgTXJDp5jcTxgDgX99A4/0biTUECDkFH5Ts45VVy4nFYuTnFJLSNIPtq/R2eTOXjuGCm2dgshy8pTCmxXhn3ztct/w6rnvjOtY1rMOsmvnGtG/w8iUvs7hg8aH/E49zFDEKlITX68XtdtPR0UFKSsqxHs6Io2zFG7z9lwcAmLzoTM6+8WZM1r41pCTDx/H6mTzW19W0by9P3v4jYuEw593yQ6YsOjO5rf2556n76U8ByPvtb3CfOR/+eTnUfYbmymb70i9Q16IX43275kae2jIDi1Hl718/mVPH6y5ifzzO7yoa+FNlIxoww2njnzNLyDSbEDGNzjV1+FZUogViCBWa5qqsrttEU5Nel88S9+BomYhBs1AyO5Mzr5mE1WmiP+KxGC/f+2v2bPgU1WBk6Y3/ybQzz+6T2BLTYmxo2MDyiuW8WfEmvoiPSz/WuGqVHudnmD2dort+i3lsD3eXFoc3/xvWPKz/nT8HLrgPkTuTqupH2bXrLoSI0R5O4dnyLxIwLOGOi3ov3oMRjGv8anct/5doDeg0qNxYkMk3CzJJNxvRQjE6Xt+L/9N6EICq4J2k8r73M+qbGwCwWq3MmTOHuXPnkpqqn7dqaysfPruT1lq9r7LJYmDSglymnJZHRkHf2DQ49p/JQ2Gkjjng7eDxH3+XztYWZp59HktvvDm5TcTj1Hz/B/jefhvV5aL4hecx28Lwj4uho4p41kS2LJxFU8sKhFB58LPr2dg4kx+ePYHvLOmuKVgZDPOT8mrebdXbLX4tL51lpQVodX46lu8lvKudMFF2ZDSxKbybSDSCqqjk2CYQ2ZOJgoLNZeKsr02maEb/LSkHQgjB9tbtLK9Yzmu7X6MxqJefMqpGLh53Md+a8S1yncPbQm+0cDCfSSkMjxO2rFrBmw/9ASE0UnPzWfKNbzN2xqxjPazjluP1M3ksr8vf3saTP/sR3qYGxs6YzZdu+zmqakAIQcsjf6XpvvsASP/Wt8i6ZA48/03w1eHNyGDbScV0hvYiUHlqx1W8s28+HruJ/7tuLnPGphHWNJ6ua+UP+xqoScTOXZ2bxq9LCzCH4gTWN9D5YQ1xb4QQEfamtrHdUktLu16LTxFGHN4irMFc3Jl2Trt8PMUzMw94TdFImDce/B3ln3wIwLi5p3DW9Tfhs0b5tP5TVteu5qPaj+gId2cS5zpyuaz0Mi7cl47v58sQgQCKxULqV68h/cYbMab2EHebn4VXfwBhL6DA1EvhtB/Q4RBs3fJDAkE96aa2M5s3KpZgcp7NdQsnsbg0c8B2ZT1Z1+Hnv3dWU+YLAmBRFb6Y5eHKnDQWeJzEazrpeKOC8K52AASCfVkdbIjvptXfnjzO2LFjmTZtGhMnTsTpdLFrXQMb3txHS40/uc+CS8dx0jl9Y71G41wbiWOOhIK8+JtfUrWljNTcfL667HeYbXYA4h0d1PzwR/g//BDFZGLMXx/BYa+CV2+FcAdtY4rYPimVQLiKmGbkb59fzdqGufzPF6dy7YIiABrDUR6uauJvNU2ENIFFVfh5SR5fCRnwf1xHcFsLrUon5aY6dprqicT1eWhTPVgaSzDFnCgKTFucz7wvlmB19H/DtT++iI/1DetZXbuaVdWrqOnszoJPtaRy+YTLuXLilWQ7+tYuPZGQwvAEpWpLGa8/cC+drboZvnDaDGaf+0WKZ8/BYBzaJJMMjeH4TD744IP89re/pb6+npkzZ3L//fczb968Afd/5plnuP3226moqKC0tJS7776b88/vLsQqhODOO+/kkUceob29nYULF/LQQw9RWjr0DgHHaq7Vlm/jld/dRWdrC+7sHK75399hc7oIbd1Kw/8uI7BOz1BOvfQcsme2wvaX6EgxUlWcRaM7AkBn1MVfN1/N5uapzB2byj1XzKTZBK80tvNMQyutiazYfIuJX+ZncXpDnODWFgI7W2nTfNSqbVSbW6kVrQj0r0VFM2AL5GHzjyE1w8WsswuZvDAXg2FoUTia0Kj31fH+c49T89ZHoAk0RbCzoJPywk5aUiKggNviZknhEs4rPo95OfNQFf34kepq6u+4A//HemcVxWwm5bzzSLnwAhzz5+vxX946eOtn3W3KAPJOQpt2CZWpAfY2Po0W1603gaiNDY0zqOg8ifEFp3P6pGLmFqViHSSoXxOC5c0d/GFfQ1IgAqSbjCxJd7E41cWsToFnTQOhLS2ggYagSm1mm6OO6mjvLihZWVkUFRUxZswY1JCTyg2dVJQ1c8VtJ/drNRyuz+Rwz7fBGGlrVltdDa/+4Tc07t2N0Wzh6l/fS2ZhESIex/vaazTeex+xhgYUq5X8/3c9ruhbiIoPaPOY2Dcum1aHHhbQHkrhobJv4BdTuO/Ls5hR5OH9Vh/PN7TzZnMHkYScWGCx8tM2A1llzdT7GqlWW6lUm2hXuxOiDDE79s5CLKFMDAaV0pOzmXteEZ5s+4DX4Yv42N2+m/K2cra2bGVz82Z2tu1MzlcAi8HCovxFXFhyIYsLFmMyyLUPpDA8oQl2+lj97JN89tbraInisxaHg6KZcyicOoPscaWkFxRiNMnJcjgc7mfy6aef5tprr+Xhhx9m/vz5/P73v+eZZ55hx44dZGVl9dn/448/ZvHixSxbtowLL7yQJ598krvvvpsNGzYwbdo0AO6++26WLVvGY489RnFxMbfffjubN29m69atWIcYWnA055oWj1O1ZTNl7yxPdmBIyyvggmtuwLijHO/y5QTXJVopmA2kLTWjlFTR5jbRnGYmZNPFjCYUVtfN5anKK1DdGZw8IwfhNrGmw09brLtESq5Q+EpbjNPKGwl2dtCu+GlRfDSrPqJK71IqxqgTazAHezSHkmnZTDo1l8Kp6ag9rGya0PCGvbSGW2kJttASbKEh0EC9v57azlqqOquo8lYRiuuLaqrXxLytaeS29ngvPDbypk9n5uzF5I6bgCcrRy8N0gMhBP7336fp/gcIff558nnFbsd+8lzss2ZhmTwZizuOqfxxlB2v6vGHCWJpY6guyaXK1kxE6c4K1oRCtS+Pfb4iNMM4UlNKyU0vpTi7iLHpLrJcll7XK4RgvTfA0/WtvNzYTkes9/8sw2Rkqs1CiU9jTG2QnOoAOSENRyhItdLAPkMjjWrfrGSL2UxGWiaLzljEpEl9s1qH4zN5JObbYIyENUtoGg17dvH5e2+z+d230eIxbCluLv7BT0gNx+hctYqOl14mVlcHgDHTTsZ5UcLuOto8JprTLEQs+mcxrqm8W3MarzRcyvyZJRQUeSjzB9ngDSTFIMAkf4RzdtVR2FxPq9pJq9KJUHpIDKFgDqdjC+RgiqSSluNgwvwcJp+ai8EhaAu10RpqpTnYTGOwkXp/PfX+eqp91VT6KmkO9l8wvdBVyPzc+SzKX8T83PnYTQOLyxMVKQwleJsa2fTWa2xZtYJAR3uvbYqi4srIJCUjE2daOvYUN1anC4vDgdlqw2S1YjSbMZjMGIxGVIMRg8GAYjCgqiqKqqIoKoqq6PFSioJC4jG5jijdsVS9PFYDu6/2j70aCdjd7n6trYf7mZw/fz4nn3wyDzygx4ZqmsaYMWP4zne+w09+8pM++1955ZX4/X5effXV5HOnnHIKs2bN4uGHH0YIQV5eHj/84Q/50Y/0DN2Ojg6ys7N59NFH+cpXvjKkcQ12Xe+88SKt7S16zUB0qxCahh5kJvQEB9H9vIjH0IT+GI/FiMWjxKNRYvEIsWiYSDyCUBSEAYQRrCrY43E0k0LMAjErRO0KUYcgYoOQwUwYKwHs+HHiEym0RHNpFRn4zFY0ta8VzxKLMa65ifFN1eS01DCg91RTMUXdmMOpWCwuyI4SzmvFn91IQOkkEA3gj/rxR/34Ij58UR/esLeXpWIgjKqRopQiSlNLmZw2mTEdLvxry9m7/lPi0d7JF0aTmZSsbFzpGThT07GlpGB1OLHYHZisVkRdPaF16whv2AgdHShCoAhQSDwajZjSUjHaFIyKF0O8FYMxjmoWKAaNcB74ixU681WiKf3/M4SmEA2ZiYQsxKNWtLgVhBUFKwo2VMWCUGzsto5hq6WQ7eZc9hk9xJWBrajOWBxPNIY7GscSC2OIByEeRGhBjFoMUzzGZfY8vvLlvha54fj+H+75diAGG3PF7u2sW7e6xzOJ+dRzKRb7PS/iIARCQFwIEBpCE8S1GMRixONxtHgkOb+ikQjhaBihClBAGMBkUnEIgSI04maIWRSiNoWoTRBxQtQKYdVMEBsBHPhx0CFSaY1m06ak02m29HutKcEAY1tqmVhfRYa/b3F1NW7GFPFgDqdh1FKIpHnpyKijIXMXTeYafS5FvMkbqAORZcuiNK2USamTmJYxjZmZM8m0Hzis40TnYObR8DQblIw4UjKzWHzN9Zx21bXU7tjGvs2fUbtjC4179xDyd+JtasDb1HCshzni+drdfySrqGRYjxmJRFi/fj233XZb8jlVVVm6dCmrV6/u9zWrV6/m1ltv7fXcOeecw4svvgjA3r17qa+vZ+nSpcntbreb+fPns3r16gGFYTgcJhzuroHZs1Dx/vxea2dd9pwDXt9RQwF6rFWqpuEOdpLm95LpayfH20Kmrx1D14KrgCIUTHErxK3EhUpYieEzddJsbaQl/TOaHdWETQl3VxCoOPAwXCYXabY00q3pZNuzyXZkk+vIZYxrDIUpheQ78zGq+33VLoRIMMC+sk1Ubimjbud2WqoqiUUjtNZU0VpTNfhJM536z+A7JX4SxIGqxA9gckSxZwexZ4SwpoWxuCNYXBEUg8BsD2O2h4GBPw+zEz8AEcxUirFUUkQN+dSTRyPZtJBBWLHSaTTQaTRQbQOwA32TYKZXvA4Mf4/aIzHf9udg5tFTbz/P7yeOkl68+80xUyxKasBHemcHWb52cjuacQf9KIBBGDDHnSgxK7G4iYii0WkM0GZtps1dTrOjhnZbQ7cFMZT46YFRNZJmTSPDlkGmLZNseza5zlzynfkUugopTCnEZXYdpYs/cZHC8DhHVQ0UTJ5GwWTd/SGEINDRTlt9Lb6WZvxtrQQ62gn5O4kEAkRCQaLhELFIhHgkQjweJx6LosXiCC2OpmkITdNtRFocoenWIiFIWpIEgqQhpcddcB/rysg3Vh8RK2ZzczPxeJzs7N7B0NnZ2Wzfvr3f19TX1/e7f319fXJ713MD7dMfy5Yt43/+53+GNG5VCEwiMug+Svcbn7QNdz2nJCyLSuJ3BQ0FgSoEKhqKABUNVWgYhIaqCQyahiGG/hNVMMUF1lgMazSGLRrDEYngikRxhcK4wmFQIK4I4opG2BAjYFbpNEeImaNErVGithCaPYJmjWIyGDGq+k+2wUyBOh6TOhmLwYLFaMFqsGIz2rAardiNdhwmBw6TA5fZRYo5hRRLCm6z+5BjmMw2O6XzT6V0/qkAaFocb1MT7Q11dLa24G9rJejzEg74Cfv9REJBYpGwPjejUeKxGFpctxYJTUPE42jxGCKu/y6ElrAy6T9db03X/Ix3GvF1uvDt7rnQCkyOGEZHDKM1htEWx2CJY7BoGEwaqllDNWmoBg3FKFANAkXVfwoM+xij7gNFoOhvpl7zULHjVT14lRQ6FSd+1UkQOwHFQQgrEcVCGAuZwSPTOu9IzLf9OZh5pKBgFAcu06MMYI3u/Xz3fKLHPOs5x1Qh9HmWmFv6fBMYtDiqJjBqAjWuzy9jVMES07DEYthiMeyRGI5oFFc4TEoojCUWQ1MFUYNG2BAlYI7gz1CIW+No9jDYvGCPY7QoWAwWnAYzqaoTm3EGVuO85Fyym+w4jA6cZidOsxO32Y3b4sZpco5Iz9GJhhSGJxiKouDwpOLwDK1sheT45rbbbutlGfF6vYwZM6bffV++4PqjNawTElU14MnOwZOdc+Cdj0eWHniXkcrBzKMf/8dt/PhoDUwiOQSkMJRIjjIZGRkYDAYaGnq78hsaGsjJ6V8U5OTkDLp/12NDQwO5ubm99pk1a9aAY7FYLFgs/ccOSSTHA0divu2PnEeS4wnZ+UQiOcqYzWbmzJnDihUrks9pmsaKFStYsGBBv69ZsGBBr/0B3n777eT+xcXF5OTk9NrH6/WyZs2aAY8pkZwIHIn5JpEc14hD4IEHHhBjx44VFotFzJs3T6xZs2bAff/yl7+I0047TXg8HuHxeMSSJUsG3b8/Ojo6BCA6OjoOZbgSybBzuJ/Jp556SlgsFvHoo4+KrVu3iptuukl4PB5RX18vhBDia1/7mvjJT36S3P+jjz4SRqNR3HPPPWLbtm3izjvvFCaTSWzevDm5z1133SU8Ho946aWXRFlZmbj44otFcXGxCAaDR+26JJLhZjg+k0divh3pMUskw8nBfCYPWhg+9dRTwmw2i7/97W9iy5Yt4pvf/KbweDyioaGh3/2vvvpq8eCDD4qNGzeKbdu2ia9//evC7XaL6urqIZ9TTjLJSGM4PpP333+/KCwsFGazWcybN0988sknyW2nn366uO6663rt/+9//1tMmDBBmM1mMXXqVPHaa6/12q5pmrj99ttFdna2sFgsYsmSJWLHjh1H/bokkuFkuD6Twz3fjsaYJZLh4mA+kwddx/Bg60HtTzweJzU1lQceeIBrr7223336S/0fM2aMrGMoGTEcr7U1j9frkoxeRuNncjSOWXJ8czCfyYOKMeyqB9WzVtqB6kHtTyAQIBqNkpaWNuA+y5Ytw+12J38Gyu6SSCQSiUQikQwfByUMB6sHNVittJ78+Mc/Ji8vr5e43J/bbruNjo6O5E9V1QGKvUokEolEIpFIDpujWq7mrrvu4qmnnuK9994btHerTP2XSCQSiUQiOfoclDA8lHpQXdxzzz3cddddvPPOO8yYMePgRyqRSCQSiUQiOaIclCv5UOpBAfzmN7/hl7/8JW+88QZz58499NFKJBKJRCKRSI4YB+1KvvXWW7nuuuuYO3cu8+bN4/e//z1+v5/rr9fbZV177bXk5+ezbNkyAO6++27uuOMOnnzySYqKipKxiE6nE6fzQE3gJRKJRCKRSCRHi4MWhldeeSVNTU3ccccd1NfXM2vWLN54441kQkplZSWq2m2IfOihh4hEIlx++eW9jnPnnXfy85///PBGL5FIJBKJRCIZNg4p+eSWW27hlltu6Xfbe++91+vvioqKQzmFRCKRSCQSieQoI3slSyQSiUQikUgAKQwlEolEIpFIJAmkMJRIJBKJRCKRAEe5wPWh0tXO2ev1HuORSCQ6XZ/Fg2w1PuKRc00y0hiNc03OI8lI42Dm0agQhj6fD0D2TJaMOHw+H263+1gPY9iQc00yUhlNc03OI8lIZSjzSBGj4DZM0zRqa2txuVwoitJrm9frZcyYMVRVVZGSknKMRijp4kR5P4QQ+Hw+8vLyepVnGu3IuTZ6OFHej9E41wabR3DivHejhRPh/TiYeTQqLIaqqlJQUDDoPikpKcftGzoaORHej9FivTgY5FwbfZwI78dom2tDmUdwYrx3o4nj/f0Y6jwaHbdfEolEIpFIJJIjjhSGEolEIpFIJBLgOBCGFouFO++8E4vFcqyHIkG+H8cz8r0dWcj3Y/Qi37uRhXw/ejMqkk8kEolEIpFIJEeeUW8xlEgkEolEIpEMD1IYSiQSiUQikUgAKQwlEolEIpFIJAmkMJRIJBKJRCKRAFIYSiQSiUQikUgSjHph+OCDD1JUVITVamX+/PmsXbv2WA/puOT999/noosuIi8vD0VRePHFF3ttF0Jwxx13kJubi81mY+nSpezcubPXPq2trVxzzTWkpKTg8Xi44YYb6OzsPIpXITkc5Fw7Osi5dnwj59HRQc6jQ2dUC8Onn36aW2+9lTvvvJMNGzYwc+ZMzjnnHBobG4/10I47/H4/M2fO5MEHH+x3+29+8xv++Mc/8vDDD7NmzRocDgfnnHMOoVAouc8111zDli1bePvtt3n11Vd5//33uemmm47WJUgOAznXjh5yrh2/yHl09JDz6DAQo5h58+aJm2++Ofl3PB4XeXl5YtmyZcdwVMc/gHjhhReSf2uaJnJycsRvf/vb5HPt7e3CYrGIf/3rX0IIIbZu3SoA8emnnyb3Wb58uVAURdTU1By1sUsODTnXjg1yrh1fyHl0bJDz6OAYtRbDSCTC+vXrWbp0afI5VVVZunQpq1evPoYjO/HYu3cv9fX1vd4Lt9vN/Pnzk+/F6tWr8Xg8zJ07N7nP0qVLUVWVNWvWHPUxS4aOnGsjBznXRi9yHo0c5DwanFErDJubm4nH42RnZ/d6Pjs7m/r6+mM0qhOTrv/3YO9FfX09WVlZvbYbjUbS0tLk+zXCkXNt5CDn2uhFzqORg5xHgzNqhaFEIpFIJBKJZHgZtcIwIyMDg8FAQ0NDr+cbGhrIyck5RqM6Men6fw/2XuTk5PQJsI7FYrS2tsr3a4Qj59rIQc610YucRyMHOY8GZ9QKQ7PZzJw5c1ixYkXyOU3TWLFiBQsWLDiGIzvxKC4uJicnp9d74fV6WbNmTfK9WLBgAe3t7axfvz65z7vvvoumacyfP/+oj1kydORcGznIuTZ6kfNo5CDn0QE41tkvh8NTTz0lLBaLePTRR8XWrVvFTTfdJDwej6ivrz/WQzvu8Pl8YuPGjWLjxo0CEPfdd5/YuHGj2LdvnxBCiLvuukt4PB7x0ksvibKyMnHxxReL4uJiEQwGk8c499xzxezZs8WaNWvEhx9+KEpLS8VVV111rC5JchDIuXb0kHPt+EXOo6OHnEeHzqgWhkIIcf/994vCwkJhNpvFvHnzxCeffHKsh3RcsnLlSgH0+bnuuuuEEHr6/+233y6ys7OFxWIRS5YsETt27Oh1jJaWFnHVVVcJp9MpUlJSxPXXXy98Pt8xuBrJoSDn2tFBzrXjGzmPjg5yHh06ihBCHG0rpUQikUgkEolk5DFqYwwlEolEIpFIJMOLFIYSiUQikUgkEkAKQ4lEIpFIJBJJAikMJRKJRCKRSCSAFIYSiUQikUgkkgRSGEokEolEIpFIACkMJRKJRCKRSCQJpDCUSCQSiUQikQBSGEokEolEIpFIEkhhKJFIJBKJRCIBpDCUSCQSiUQikST4/8xvTpBKncv2AAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "f, axarr = plt.subplots(1,3, layout='constrained')\n", - "\n", - "#TODO tidy up plots\n", - "for solution in Yall: \n", - " axarr[0].plot(t, solution[:,0]) \n", - " axarr[1].plot(t, solution[:,1]) \n", - " axarr[2].plot(t, solution[:,2])\n", - "\n", - "for idx, state in enumerate(stateList):\n", - " axarr[idx].set_title(state)\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "1fd28659", - "metadata": {}, - "source": [ - "\n", - "We then see how the expected results, using the sample average of the\n", - "simulations\n", - "\n", - "$$\\tilde{x}(T) = \\mathbb{E}\\left[ \\int_{t_{0}}^{T} f(\\theta,x,t) dt \\right]$$\n", - "\n", - "differs from the reference solution\n", - "\n", - "$$\\hat{x}(T) = \\int_{t_{0}}^{T} f(\\mathbb{E}\\left[ \\theta \\right],x,t) dt$$ " - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "4e6f4164", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAosAAAHrCAYAAACn9tfQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAACG5klEQVR4nO3de3xU9Zk/8M+ZSWYm9wu5DIFAQNCgIGAQiFKtmm6otUpFKqxblKX4W2usNV2ruIpWu6W1SvFCl9XWWrdSLa2lVi0tjaJVwh1UroKgXMLkSjK5zSUz5/fHzDmTSCaZy7nM5fN+vea16+TMzBmak3nmeb7P8xVEURRBRERERDQIg94nQERERESxi8EiEREREQXFYJGIiIiIgmKwSERERERBMVgkIiIioqAYLBIRERFRUAwWiYiIiCgoBotEREREFBSDRSIiIiIKisEiEREREQXFYJGC+vjjj3HTTTdh7NixsFgsGDVqFL7yla/gmWee0fvUiOLeiy++CEEQsHPnTr1PhShuSdeRdEtJScGoUaNw22234fTp03qfXsJI0fsEKDZt2bIFV111FcaMGYNly5bBarXi5MmT2Lp1K5566incddddep8iERERAODRRx/FuHHj4HA4sHXrVrz44ot4//33sW/fPlgsFr1PL+4xWKRB/fd//zdycnKwY8cO5ObmDvhZU1OTPidFREQ0iK9+9auYMWMGAODb3/42CgoK8NOf/hSvv/46vvnNb+p8dvGPZWga1KeffoqLLrronEARAIqKirQ/ISIiohB96UtfAuD7LKPoMVikQY0dOxa7du3Cvn379D4VIiKisHz22WcAgLy8PH1PJEEwWKRB/ed//id6enowbdo0XHbZZbjvvvvw97//HW63W+9TIyIiGqCjowMtLS04deoU/vjHP+KHP/whzGYzrrvuOr1PLSEwWKRBfeUrX0F9fT2uv/56fPjhh3j88cdRXV2NUaNG4fXXX9f79IiIiGRVVVUoLCxEaWkpbrrpJmRkZOD111/H6NGj9T61hMBgkYK69NJL8dprr+Hs2bPYvn07li9fjs7OTtx00004cOCA3qdHREQEAFizZg02bdqEP/zhD7j22mvR0tICs9ms92klDAaLNCyTyYRLL70UP/7xj/E///M/cLvdWL9+vd6nRUREBACYOXMmqqqqMH/+fLz++uuYPHky/vVf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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "f, axarr = plt.subplots(1,3, layout='constrained')\n", - "\n", - "for i in range(3): \n", - " axarr[i].plot(t, Ymean[:,i] - solutionReference[:,i])\n", - " axarr[i].set_title(stateList[i])\n", - "\n", - "plt.show()\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "id": "ee4d496d", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAoYAAAHrCAYAAABSCFxgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8o6BhiAAAACXBIWXMAAA9hAAAPYQGoP6dpAACu10lEQVR4nOzde3zT9fX48VeSNknvhd5bCqXcr6VcBS+gQ0GcivOCl6nDy75zsjnZnMMLOtlE9xUvP3WiTKZz+tWpyJgylDHxBoJcykXu15ZLb5Te26RN8vvjk0/a0luS5p7zfDzySEg/n+QdaMjJeb/PeWtsNpsNIYQQQggR9rT+HoAQQgghhAgMEhgKIYQQQghAAkMhhBBCCGEngaEQQgghhAAkMBRCCCGEEHYSGAohhBBCCEACQyGEEEIIYSeBoRBCCCGEACQwFEIIIYQQdhIYCiGEEEIIQALDsLBr1y6uu+46+vXrh9FoJCsri0svvZQXX3zR30MTImS98cYbaDQatmzZ4u+hCBFU1PeOeomIiCArK4uf/OQnnDx50t/DC3kR/h6A8K4NGzZw8cUX07dvX+6++27S09MpKiri22+/5YUXXuAXv/iFv4cohBBCtPPEE0/Qv39/Ghsb+fbbb3njjTf4+uuv2b17N0aj0d/DC1kSGIa4P/7xjyQkJPDdd9+RmJjY5melpaX+GZQQQgjRjcsvv5zx48cDcNddd5GcnMzTTz/NqlWruOGGG/w8utAlU8kh7vDhw4wYMaJdUAiQmprq+wEJIYQQbrjwwgsB5XNNeI8EhiGuX79+bN26ld27d/t7KEIIIYTbjh07BkCvXr38O5AQJ4FhiPvNb35DfX09Y8aMYcqUKTz44IN89tlnNDU1+XtoQgghRKeqqqooLy/nxIkTfPjhh/z+97/HYDDwwx/+0N9DC2kSGIa4Sy+9lI0bN3LVVVexY8cO/vSnPzFjxgyysrJYtWqVv4cnhBBCdGj69OmkpKSQnZ3NddddR0xMDKtWraJPnz7+HlpIk8AwDEyYMIEVK1Zw9uxZNm/ezIIFC6ipqeG6665jz549/h6eEEII0c7LL7/M2rVr+eCDD5g1axbl5eUYDAZ/DyvkSWAYRvR6PRMmTODJJ5/klVdeoampiffff9/fwxJCCCHamThxItOnT+faa69l1apVjBw5kptvvpna2lp/Dy2kSWAYptQWAKdPn/bzSIQQQoiu6XQ6Fi9ezKlTp3jppZf8PZyQJoFhiPv888+x2Wzt7l+9ejUAQ4YM8fWQhBBCCJdNmzaNiRMn8vzzz9PY2Ojv4YQsaXAd4n7xi19QX1/PNddcw9ChQzGbzWzYsIH33nuPnJwc5s6d6+8hCiGEEE554IEHuP7663njjTf42c9+5u/hhCTJGIa4Z555hosvvpjVq1czf/585s+fz+bNm/n5z3/Opk2bOmx8LYQQQgSiH/3oRwwYMIBnnnkGi8Xi7+GEJI2to3lGIYQQQggRdiRjKIQQQgghAAkMhRBCCCGEnQSGQgghhBACkMBQCCGEEELYSWAohBBCCCEACQyFEEIIIYRdUDS4tlqtnDp1iri4ODQajb+HIwQ2m42amhoyMzPRakPn+5W810SgCcb3mryPRKBx5X0UFIHhqVOnyM7O9vcwhGinqKiIPn36+HsYHiPvNRGogum9Ju8jEaiceR8FRWAYFxcHKC8oPj7ez6MRAqqrq8nOznb8boYKea+JQBOM7zV5H4lA48r7KCgCQzUVHx8fL28yEVBCbZpI3msiUAXTe03eRyJQOfM+Co4FG0IIIYQQwuskMBRCCBHSXn75ZXJycjAajUyaNInNmzd3eXxlZSX33nsvGRkZGAwGBg8ezOrVq300WiH8KyimkoUQQgh3vPfee8yfP5+lS5cyadIknn/+eWbMmMH+/ftJTU1td7zZbObSSy8lNTWVDz74gKysLI4fP05iYqLvBy+EH0hgKIQQImQ9++yz3H333cydOxeApUuX8sknn7B8+XJ+97vftTt++fLlVFRUsGHDBiIjIwHIycnx5ZCF8CuZShZCCBGSzGYzW7duZfr06Y77tFot06dPZ+PGjR2es2rVKiZPnsy9995LWloaI0eO5Mknn8RisXT6PCaTierq6jYXIYKVBIZCCCFCUnl5ORaLhbS0tDb3p6WlUVxc3OE5R44c4YMPPsBisbB69WoeffRRlixZwh/+8IdOn2fx4sUkJCQ4LtLDUAQzCQyFEEIIO6vVSmpqKq+99hrjxo1jzpw5PPzwwyxdurTTcxYsWEBVVZXjUlRU5MMRC+FZssZQCCFESEpOTkan01FSUtLm/pKSEtLT0zs8JyMjg8jISHQ6neO+YcOGUVxcjNlsRq/XtzvHYDBgMBg8O3gh/EQyhkIIIUKSXq9n3LhxrFu3znGf1Wpl3bp1TJ48ucNzzj//fA4dOoTVanXcd+DAATIyMjoMCoUINRIYCiGECFnz589n2bJlvPnmm+zdu5d77rmHuro6R5XybbfdxoIFCxzH33PPPVRUVHDfffdx4MABPvnkE5588knuvfdef70EIXxKppKFEEKErDlz5lBWVsbChQspLi5mzJgxrFmzxlGQUlhYiFbbkiPJzs7m008/5f7772f06NFkZWVx33338eCDD/rrJQjhUxqbzWbz9yC6U11dTUJCAlVVVbLvpAgIofo7GaqvSwSvYPydDMYxi9Dmyu+ky1PJX375JVdeeSWZmZloNBpWrlzZ7Tnr169n7NixGAwGBg4cyBtvvOHq0wohhBBCCC9zOTCsq6sjLy+Pl19+2anjjx49yhVXXMHFF19MQUEBv/rVr7jrrrv49NNPXR6sEEIIIYTwHpfXGF5++eVcfvnlTh+/dOlS+vfvz5IlSwCl7P/rr7/mueeeY8aMGa4+fTtmUyM2m7XTn2s02la3NY6LVqNRfqbRKBchhBBCiGBgs4HNar/YAJtyrdFARM9aJ3m9+GTjxo1ttiMCmDFjBr/61a86PcdkMmEymRx/7mp7oZNPT6S/9XiPxmi1abCiwYYGq0aLDQ0WdFjQYdVEYNFGYtPpQWdAq4/CEB1HVGwC2qhEiOoFMckQmw4JfaB3f0joC1op+BYiLBVugndugMsWwdjb/D0aIYQ/2GxQfwaqTkBNMdSVKn9uqITGKjDVgLkWzHXQ3Gi/mMBiBkuTcm1tBqul5dpmaQkGO5N9HtzZsxlZrweGxcXFHW5HVF1dTUNDA1FRUe3OWbx4Mb///e+9PTQHrcaGFrUG55z9MG32u9S7G4Cqbh4wIgrSR0GfCdD/IuWij/bkkIUQgWrLcmishPVPw5hbQKvr9hQhRBBraoCTW5VL8W4o2wsVR5XAz+d6Xk8ckO1qFixYwPz58x1/rq6u7nTvydT7v6TG2jZ6bl1o7bhtA1COs1ltWK0WbNiwWq3YrDYsNivW5maaLRaam5swmcyYmsw0NJqoq2+guraOs9U1nKmspOzMWXTNdcRTRy9NLQNjGpic0kRc4yk4ewyaG+DEZuXy7csQGQPDfggT/wf6jPPkX5UQIpBYrXDoP8rt6hNw5HMYOL3rc4QQwafqBOz5J+z/NxRtUjJ8HYlNg7h0iElVZhejeoExAQxxyiUyGiKjIMIIOr0yDazTgy4StBHKRaNVvmBqdPZrrXLBvhROXTKnHtdDXg8M09PTO9yOKD4+vsNsIbi2vVBMXGJPh+gyi9VGQVElqwpO8tLWE9RXWdDVaHho1jDunNJX+aZwajsc/0b5kKgqgp3vKZfci+GyP0D6SJ+PWwjhZcU7oL685c/b3pLAUIhQoX7x2/QKHP6cNtm5uAxlljAjD1KHQ9JA6NWvx+v9/MHrgeHkyZNZvXp1m/vWrl3b6XZEwUCn1TCuXy/G9evFL34wiMdXfc/HO0+z6OM9VDU0Mf/SwZA8EEZfr6wzOLFFmV7a9b6SQXj1Ipi2AC6cL9NMQoQSNVuYPBjKD8C+T5Q1RVGJ/hyVEKKnDv8X1j4GxTtb7us7BYZfBYMug965IVPI6nKFRG1tLQUFBRQUFABKO5qCggIKCwsBZRr4tttaFlz/7Gc/48iRI/z2t79l3759/PnPf+Yf//gH999/v2degZ8lxxp48aZ8HpgxBID/t+4gK7efbDlAo4HsCXDNKzDvOxh2pbKA9PM/KAvUTf5YgyCE8IqD9sDwvJ9DfBZYm6D8oH/HJIRwX105fHAHvHWNEhTq42DyPPhlAdzxbzjvHkgaEDJBIbgRGG7ZsoX8/Hzy8/MBZR/K/Px8Fi5cCMDp06cdQSJA//79+eSTT1i7di15eXksWbKEv/zlLx5pVRMoNBoN9148kF9eMhCAhz7axaHSDgK+3v3hhrfgmteUdQWH/gN/uwoaO6+6FkIECatVWXwOkDsVEvsqt6sKOz9HCBG4ijbD0gtg94fK+r1JP4P7dsCMPyqf5yHK5ankadOm0dUueh3tajJt2jS2b9/u6lMFnfumD+a7Y2fZeOQMj67czTt3T0Jz7rcIjQby5ijfMN6+Tvkgef8ncPN7ymJTIURwqitTMoQardKyKrEvFG6EyiJ/j0wI4ardK2DFT5X3dPJguOZVyBrr71H5hDTb8yCdVsP/Xj8afYSWjUfO8MWBss4P7jMebv1IyRweXgefPeq7gQohPK/mlHIdkwq6CEiwd1KolIyhEEFl+9+V6WNrk7L86+7/hk1QCBIYelyfXtHcPrkfAE/9ex9Waxc9hTLz4dq/KLc3vQJHvvDBCIUQXlFTrFzHZyjXifbAsEoyhkIEjX2rYdUvABuMvwOuf1NpKxNGJDD0gnsvHkicIYJ9xTV8dai864OHXgHj71Ru//NepRu6ECL4VNszhnH2wNCRMZTAUIigcHqnkim0WSH/x3DFs2HZOUQCQy9IjNZz7bg+ALz9rRPb9V36BCT2UzILG17y8uiEEF5Rc1q5VgNDR/FJkX0vUyFEwDLVKOv9mxuU3qM/fCGkKo1dIYGhl9wySflQWLevlNNVDV0fbIiFS+1bAG58CWq7WJsohAhMamCoTiUnKF8OMddCw1n/jEkI4ZzVD0DFYYjvAz9apqwTDlMSGHrJoLQ4JvbvjcVq473vnJhKGj5bWXNoroWvlnh9fEIID6s+J2MYGQUxKcptKUARInAd/hx2/B+gUdb9R/f294j8SgJDL7pxgrLG6JOdp7s/WKOBS+yVydv+Bo1VXhyZEMLj1OITNTCEttPJQojA09QIn/xauT3xbugXvLuyeYoEhl70g2FpRGg1HCyt5XCZEzucDLgEUoZCUx0UvOP9AQohPEdtVxOf2XKfFKAIEdi+W6ZMIcemwyWP+Hs0AUECQy9KiIpk8oAkAD79vrj7EzQa5RsLwOZlyk4KImS9/PLL5OTkYDQamTRpEps3b+7y+Pfff5+hQ4diNBoZNWpUuz3IAfbu3ctVV11FQkICMTExTJgwoc1ORMJLmhpa1hHGpbfcLy1rhAhcphr4+jnl9iWPgDHBv+MJEBIYetnMkcqHxKfflzh3wugbwZCgfIM59qUXRyb86b333mP+/Pk89thjbNu2jby8PGbMmEFpaWmHx2/YsIGbbrqJO++8k+3btzN79mxmz57N7t27HcccPnyYCy64gKFDh7J+/Xp27tzJo48+itFo9NXLCl/qNHJEFBgTW+5XM4ZVJ3w+JCFEN75dCvVnIGkg5N3k79H0yMGSGl74z0H+4UxNQzckMPSyS4enodHAjqJKiqsauz/BEAsjZiu3d6/w6tiE/zz77LPcfffdzJ07l+HDh7N06VKio6NZvnx5h8e/8MILzJw5kwceeIBhw4axaNEixo4dy0svtbQ3evjhh5k1axZ/+tOfyM/PZ8CAAVx11VWkpqb66mWFr9YVya1bXEQrMwbUV/h+TEKIzpnr4ds/K7enLQjKKuTiqkb+vP4Qlz33BZc+9yXP/ecAb2w41uPHlcDQy1LjjIzOUtLT33TX7Fo18kfK9d5VYGny0siEv5jNZrZu3cr06dMd92m1WqZPn87GjRs7PGfjxo1tjgeYMWOG43ir1conn3zC4MGDmTFjBqmpqUyaNImVK1d2ORaTyUR1dXWbi3DDuc2tVWpg2CCBoRABZdc/lPdlYl8YcY2/R+M0m83GFwfKuOvNLUx5ah1/WrOfAyW16HVafjA0lTsu6I+th31TJTD0gSkDkwEXAsN+FyhtLhrOwlHZJi/UlJeXY7FYSEtLa3N/WloaxcUdr0UtLi7u8vjS0lJqa2t56qmnmDlzJp999hnXXHMNP/rRj/jii85/hxYvXkxCQoLjkp2d3cNXF6Y6qkiGVhnDM74djxCiczabMo0MMPF/gmJ3kyaLlfe3FHHZc19y+/LN/GdvCVYbTMzpzdPXjuK7R6bz+k8mcN24Pmh62Jg7+HKnQeiCgcm8sv4w3xwux2azdf+PpouAYVfBltdh90dKF3YhumC1FypdffXV3H///QCMGTOGDRs2sHTpUqZOndrheQsWLGD+/PmOP1dXV0tw6A418FP7FqpaB4Y2W9jupCBEQDn2FZTthcgYZeu7ANZssbJi+0n+37qDnDirbJYRa4jgunF9+PF5/RiYGuvx55TA0AfG9euFPkJLSbWJw2W1DEx1YkPu4VcrgeHBz5TqZK0kd0NFcnIyOp2OkpK2BUklJSWkp6d3eE56enqXxycnJxMREcHw4cPbHDNs2DC+/vrrTsdiMBgwGAzuvAzRmlqRHJXY9n61Ua61GUzVUvUoRCBQ28GNvr79ezZA2Gw2Pt9fypOr93GoVGl3lxyr564Lc7l5Ul/ijZFee26JNnzAGKljQk4vAL455OSUUt/zIDIa6kqh9Hsvjk74ml6vZ9y4caxbt85xn9VqZd26dUye3HFz1cmTJ7c5HmDt2rWO4/V6PRMmTGD//v1tjjlw4AD9+vXz8CsQ7TRWKtetK5JB2f0kMka5LdPJQvifuQ72rFJu593s37F04viZOu544zvueGMLh0pr6RUdyUOzhvLVby/hZ1MHeDUoBMkY+syUAcl8c+gMGw6Xc/uUnO5PiDBAzgVKxvDw55A+yutjFL4zf/58br/9dsaPH8/EiRN5/vnnqaurY+7cuQDcdtttZGVlsXjxYgDuu+8+pk6dypIlS7jiiit499132bJlC6+99prjMR944AHmzJnDRRddxMUXX8yaNWv417/+xfr16/3xEsNLQ6Vy3VH2Ibo3VNUplcm9c305KiHEufZ+rGwi0as/ZE/092jaaLZYWfbVUZ7/zwFMzVYidRrmnt+fey8eSEKUd4PB1iQw9JFJ/ZUppa3Hzzq3zhAg92IlMDzyOZz/Sy+PUPjSnDlzKCsrY+HChRQXFzNmzBjWrFnjKDApLCxE22r5wJQpU3jnnXd45JFHeOihhxg0aBArV65k5MiRjmOuueYali5dyuLFi/nlL3/JkCFD+PDDD7ngggt8/vrCTmcZQ7AHhkWSMRQiEOx8V7nOuymg1vweLqtl/j92sKOoElBqE35/9QgGpHh+DWF3JDD0kZFZCeh1WsprzRw/U09Ockz3Jw24WLk+vkHZzzFSGhWHknnz5jFv3rwOf9ZRlu/666/n+uuv7/Ix77jjDu644w5PDE+4osuMofQyFCIgNJyFI/YuDaOu8+9Y7Gw2G+99V8Tj//qexiYr8cYIFl45gmvHZvW4uthdssbQR4yROkb1URaef3fMyQ+IlKFK+4vmRija5MXRCSF6pMuMobSsESIgHFwLNgukDIOkAf4eDQ1mC7/+xw5+t2IXjU1WLhiYzGf3T/VIy5mekMDQh8bbC1C2Hj/r3AkaDfQ7X7ld1PU+ukIIP7FaobFKud1lxlACQyH8at8nyvXQWf4dB3DibD0/emUDK7afRKfV8ODMofztjomkJ/h/ZlACQx8a309ZZ7jF2cAQoM8E5frEd14YkRCix8w1YFP6SErGUIgA1WyCQ/9Rbg+5wq9D2VZ4ltkvf8Pe09Ukx+p5+65J3DNtAFptYKx5lDWGPjSun5IxPFRay9k6M71i9N2f1DowlAa5QgQedX1hhLHjdcBqL0MJDIXwn2NfgblWWZ6Vme+3YfxnTwnz/m8bjU1WhmXE8/rt48lMjPLbeDoiGUMf6h2jJ9dedFJgrzzqVvoo0BmUPR0rjnhvcEII93S1vhCk+ESIQHD4c+V64HS/bRjx0fYT/M/ft9LYZGXakBQ++NnkgAsKQQJDnxuTnQjAdmcDwwg9ZOQpt09s8cqYhBA90FVFMkCUPWPYIIGhEH6jViPnTvPL0//juyLm/2MHFquNH43NYtlt44kxBOakrQSGPjambyLgQsYQZJ2hEIHM6YyhTCUL4Rd1Z6Bkl3K7/0U+f/oPt57gwRU7sdngtsn9eOa6PCJ1gRt+Be7IQpSaMdxRVInNZnPupD7jleuTkjEUIuB0lzFsPZVstfpiREKI1o59qVynDofYVJ8+9ZrdxTzwwQ5HUPj7q0YETJFJZyQw9LGh6fHoI7RUNTRx7Ey9cyepU8mle8Fq8d7ghBCu6zZjaJ9KtlnAVOWLEQkhWlOnkftP9enTfnvkDL98dztWG8wZn83jV47wa39CZ0lg6GP6CC0jM+MBKChysm1Nr/4QGa00upYCFCECS3cZwwgD6OOU23UynSyEzx37SrnO9V1geKSslv95ayvmZiszRqTxx2tGBnymUCWBoR+MyVba1hQUVjp3glYLqcOU2yW7vTMoIYR7ussYQkvQ2CgZQyF8qu4MnDmk3O57nk+esqq+iTve+I6qhiby+ybywo35RATwmsJzBc9IQ0hetrI1XsEJFz4k0kYo1yXfe2FEQgi3dZcxBDAq73lHECmE8A21aDN5MET18vrTWa02fvXedo6dqScrMYrXbh2PMVLn9ef1JAkM/SCvTyIAe09XY252cjF62kjlWgJDIQKLMxlDNTA0VXt7NEKI1k7Yt5PtM9EnT/fifw/x+f4yDBFaXr11HClxBp88rydJYOgH/ZKiSYiKxNxs5UBJjXMnOTKGMpUsREBxJmNoUNYVy1SyED5WZA8Msyd4/am+PXKGF9YdAODJa0YxMivB68/pDRIY+oFGo2F0H+UXZseJSudOSh2uXFcWyoeLEIHElYyhvHeF8B1LM5zcptz2csawqr6J+98rwGqD68b14dpxfbz6fN4kgaGfqIHhziInPyiie0N8lnK7ZI+XRiWEcJlLawxlKlkInyndA011SsY+ZahXn+rxf33P6apGcpNj+P1VI7z6XN4mgaGfjMpKBGDnSRcyCOovdvl+zw9ICOE6m60lC9hlxlCmkoXwOXVTiKxxXt0fec3uYj7afhKtBpbckBewW905SwJDP1Erkw+U1NBgdrJpdfIg5VotvRdC+FdTvdK4GsAQ1/lxMpUshO+d3qlcZ47x2lNUNzax8J/K2v+fTR1Afl/vVz57mwSGfpIebyQlzoDFamPPaSc/LJIGKtdnpMm1EAHBVGu/oQF9TOfHSVWyEL5XbN8fOX2U157iT2v2UVpjIjc5hl/+YJDXnseXJDD0E41Gw2h7xdIuZ/sZJg1QriVjKERgMNsDQ0McdLXVlVQlC+FbVktLe7f0PK88xc4Tlby9qRCAP1wzMuj6FXZGAkM/GmUvQNl10sksgpoxrDgieyYLEQhM9nZT+tiuj5OpZCF8q/wgNDdAZAz0zvX4w9tsNh5f9T02G1yTn8WUAckefw5/kcDQj0apGcOTlc6dEN8HdAawNilta4QQ/qUGhgZnA0OZShbCJxzTyCO9Unjyz4JTbCusJFqv43eXe7fi2dckMPQjNTA8VFpLvbm5+xO02lbTyYe9ODIhhFPUqWTJGAoRWIp3KNfpoz3+0I1NFv73U6U7yL0XDyQt3ujx5/AnCQz9KDXeSFq8AasN9pxydjpZ1hkKETBMrdYYdkUNDM01sgxECF9QK5K9UHjy92+Pc7KygYwEI3de0N/jj+9vEhj6mZo13Ol0AYpamSyBoRB+p1YZdxcYqsUnrc8RQniPo/DEs4FhdWMTL32ufP7eP31wyBSctCaBoZ+pja53OdvoWgJDIQKHs1PJEXqIjFZuy3SyX7z88svk5ORgNBqZNGkSmzdv7vTYN954A41G0+ZiNIbWdGFIqyuH+nJA4/EdT9745hiV9U0MTI3lR2OzPPrYgUICQz8b1UfJJOx2NjDsbZ9KrpBehkL4nWMquZvAEKRljR+99957zJ8/n8cee4xt27aRl5fHjBkzKC0t7fSc+Ph4Tp8+7bgcP37chyMWPVJm3x0ssS/ooz32sNWNTfzlK+Wz95c/GESELjRDqNB8VUFkZKYylXy4zMkClMS+ynX1SWWDcCGE/5idXGMIUpnsR88++yx33303c+fOZfjw4SxdupTo6GiWL1/e6TkajYb09HTHJS0tzYcjFj1Stk+59nC28M1vjlHd2MzA1FiuGJXh0ccOJBIY+llqvJHUOKUAZe/pmu5PiEsHbSRYm6HmtPcHKITonLpesLupZJDKZD8xm81s3bqV6dOnO+7TarVMnz6djRs3dnpebW0t/fr1Izs7m6uvvprvv/++02NNJhPV1dVtLsKP1IxhyhCPPWSD2cJfNxwD4BeXDESn7aKhfZCTwDAAjLQXoDg1nazVQUIf5bb0MhTCv5ytSgYwylSyP5SXl2OxWNpl/NLS0iguLu7wnCFDhrB8+XL++c9/8ve//x2r1cqUKVM4ceJEh8cvXryYhIQExyU7O9vjr0O4wJEx9Fxg+P7WIirqzGT3jgrpbCFIYBgQXAoMoWU6uarISyMSQjjF2eITkP2Sg8jkyZO57bbbGDNmDFOnTmXFihWkpKTw6quvdnj8ggULqKqqclyKiuT/Zr9yZAw9M5XcbLGyzL628O4Lc0N2baEqwt8DEDAy016A4mwvQzUwlIyhEP7lUsZQppL9ITk5GZ1OR0lJSZv7S0pKSE9Pd+oxIiMjyc/P59ChjrtBGAwGDAZDj8cqPKDhLNTaM8HJgz3ykJ/tKaGoooHeMXquHxf62eDQDnuDhJoxPFhSQ2OTE81vE/sp15VSJSeEXzm7JR60qkqWjKEv6fV6xo0bx7p16xz3Wa1W1q1bx+TJk516DIvFwq5du8jICO0pxJBQdkC5js9qWb7RQ298cwyAWyb1JUofen0LzyWBYQDISDCSFKOn2Wpjf7ETBSiSMRQiMJjt71e9ZAwD2fz581m2bBlvvvkme/fu5Z577qGuro65c+cCcNttt7FgwQLH8U888QSfffYZR44cYdu2bfz4xz/m+PHj3HXXXf56CcJZ5fZpZA9lC3efrGLzsQoitBpumdTPI48Z6GQqOQBoNBqGZ8bz1cFyvj9VTV52YtcnSGAoRGBwq/ik0mvDER2bM2cOZWVlLFy4kOLiYsaMGcOaNWscBSmFhYVotS15krNnz3L33XdTXFxMr169GDduHBs2bGD48OH+egnCWWcOK9fJgzzycG/aK5EvH5VBekJ4NDmXwDBAjMhMsAeGTmQTHMUnJ5R9V7Whn9oWIiC5NJWsFp84MSsgPG7evHnMmzevw5+tX7++zZ+fe+45nnvuOR+MSnicuvlD79weP1RVQxP/2nkKgNsnh0e2EGQqOWAMtxeg7DntxPoj6WUohP81m8DapNx2pipZzSpKYCiE91QcVa7VXcJ64KNtJ2hssjIkLY5x/Xr1+PGChVuBoSt7TjY1NfHEE08wYMAAjEYjeXl5rFmzxu0Bh6oR9sBw3+kaLFZb1wdLL0Mh/E+dRgYnA0P7Mebaro8TQrjHZvNYxtBms/HOZuXz9eZJfdFoQreh9blcDgxd3XPykUce4dVXX+XFF19kz549/OxnP+Oaa65h+/btPR58KMlJiiFar6OhycLRcic+OBLtJfMSGArhH2rhSWQ06JxYlSMZQyG8q7YEmupAo21ZcuWmbYWVHCipxRipZXZ+locGGBxcDgxd3XPyrbfe4qGHHmLWrFnk5uZyzz33MGvWLJYsWdLpc4Tj9kI6rYah6coHx/fO9DOMt/+iVp/y4qiEEJ1SAzxnsoUggaEQ3qZmCxOyIULfo4f6YKuyy82skRkkREX2dGRBxaXA0J09J00mE0Zj20qeqKgovv76606fJ1y3FxqRqSxO3+NMYBhn76clawyF8A9HRbKzgaG9KtlcC1ard8YkRDjz0DRyY5OFj3coSZfrxvfp6aiCjkuBoTt7Ts6YMYNnn32WgwcPYrVaWbt2LStWrOD06c4DmnDdXkgtQHEuY5ipXEvGUAj/cGU7vHOPk3WGQnie2qomqWeFJ59+X0yNqZk+vaI4r3+SBwYWXLxelfzCCy8waNAghg4dil6vZ968ecydO7dNz6hzGQwG4uPj21zCwfAMewFKsQSGQgQ8dc9jg5P/P0UYlG4CINPJQniDhzKG6jTytWP7oNWGT9GJyqXA0J09J1NSUli5ciV1dXUcP36cffv2ERsbS25uz3sMhZrBaXFoNVBea6a0prHrg2UqWQj/cnUqWaORdYZCeJMHAsPSmka+OVQOwDVhVnSicikw7Mmek0ajkaysLJqbm/nwww+5+uqr3RtxCIvS68hJjgGUtjVdUjOGtSVgafbyyIQQ7bg6lQwSGArhLTYbnD2m3O7V3+2H+WTnaaw2GJOd6Pg8DjcuTyW7uufkpk2bWLFiBUeOHOGrr75i5syZWK1Wfvvb33ruVYSQYfbp5L3dNbqOSQGNDmxWJTgUQviWqxlDaBUYhn6nBSF8qrGy5X3Vg1Y1KwuU5Vmzx2R6YFDByeUt8Vzdc7KxsZFHHnmEI0eOEBsby6xZs3jrrbdITEz02IsIJcPS4/hk5+nuA0OtTplOrj6hTCcnhGfKWwi/6UnGUIpPhPAstadvTAroo916iGPldewoqkSn1XDFaAkMXeLKnpNTp05lz5497jxNWBrmKEBxYqop3h4YSgGKEL5nrlOu9S5MN8lUshDeUWnvXtKDbOEnu5Q1+1MGJJESZ/DEqIKS7JUcYIbaA8NDpbWYmi1dHywFKEL4jwSGQgQONWOY4H7f4493Kp+lPxyd4YkRBS0JDANMZoKReGMEzVYbh0q7mW5ytKw56f2BCSHaanIjMFSnnSUwFMKz1MDQzYzhkbJa9p6uRqfVcNnwjrushAsJDAOMRqNxZA33dzed7AgMJWMYjF5++WVycnIwGo1MmjSJzZs3d3n8+++/z9ChQzEajYwaNYrVq1e3+flPfvITNBpNm8vMmTO9+RLCm5oxjJSMoRB+V9WzqeTV9mnk8wcm0yumZ9vpBTsJDAOQumfy/pJuPjzi7IGhTCUHnffee4/58+fz2GOPsW3bNvLy8pgxYwalpaUdHr9hwwZuuukm7rzzTrZv387s2bOZPXs2u3fvbnPczJkzOX36tOPyf//3f754OeHJXK9cuzSVbG+GLYGhEJ5VeVy5Tuzn1umf7FJ2b7tiVHhnC0ECw4A0OM0eGHabMbSvg5Cp5KDz7LPPcvfddzN37lyGDx/O0qVLiY6OZvny5R0e/8ILLzBz5kweeOABhg0bxqJFixg7diwvvfRSm+MMBgPp6emOS69evXzxcsKTY42hCxWQkjEUwjt6MJVcVFHP3tPVaDVwaZhPI4MEhgFJzRge6C4wjLX/AteWeXlEwpPMZjNbt25l+vTpjvu0Wi3Tp09n48aNHZ6zcePGNseDsg/5ucevX7+e1NRUhgwZwj333MOZM2e6HIvJZKK6urrNRTjJrXY1ssZQCI9rrFIuAImuF598+r2SLZzYvze9w3waGSQwDEiD7BnDU1WNVDU0dX5gbKpyba5pyV6IgFdeXo7FYnH0/lSlpaVRXFzc4TnFxcXdHj9z5kz+9re/sW7dOp5++mm++OILLr/8ciyWzqvbFy9eTEJCguOSne1+RV/YaXJnKlkyhkJ4nNqqJjrJtfejnRoYzhwh2UKQwDAgJURFkplgBOBgV+sMDXEQEaXcru14bZoIHzfeeCNXXXUVo0aNYvbs2Xz88cd899137XqLtrZgwQKqqqocl6KiIt8NONg5ik/cmEo2S2AohMf0YBq5rMbEluNnAbhMAkNAAsOANcQ+ndxlo2uNpiVrKIFh0EhOTkan01FS0nYrw5KSEtLTO/6PKT093aXjAXJzc0lOTubQoUOdHmMwGIiPj29zEU6w2VqtMXRlKlmKT4TwOLUi2Y0ehv/dV4LNBqP7JJCZGOXhgQUnCQwD1GB1nWF3lcmx9ulF2S85aOj1esaNG8e6desc91mtVtatW8fkyZM7PGfy5MltjgdYu3Ztp8cDnDhxgjNnzpCREd7NWr2iqQGwKbddKT6RPoZCeF7VCeXajcBw7R4lqTJ9WFo3R4YPCQwD1FBnMobQkjGsk4xhMJk/fz7Lli3jzTffZO/evdxzzz3U1dUxd+5cAG677TYWLFjgOP6+++5jzZo1LFmyhH379vH444+zZcsWx9aUtbW1PPDAA3z77bccO3aMdevWcfXVVzNw4EBmzJjhl9cY0lqv6XVnKlkCQyE8R90WNt61/Y0bmyx8fUgp3pTAsIVbeyUL7xuUqnyAHCypwWazodFoOj5QppKD0pw5cygrK2PhwoUUFxczZswY1qxZ4ygwKSwsRKtt+d42ZcoU3nnnHR555BEeeughBg0axMqVKxk5ciQAOp2OnTt38uabb1JZWUlmZiaXXXYZixYtwmAI3z0/vaap1fpCrc7589TA0GKGZhNEyL+NED3mZmC44XA5jU1WMhOMDMuI88LAgpMEhgFqYGosGg2crW/iTJ2Z5NhOPkBkKjlozZs3z5HxO1dHBSPXX389119/fYfHR0VF8emnn3pyeKIr7hSeQEtgCGCqlcBQCE9Qe/nGZ7l0mmMaeXha58mXMCRTyQHKGKmjb2/lQ6fLdYaSMRTC99zZ9QSU7KIaTJqkZ6QQPWa1tuz+5ULG0Gaz8fk+5XPzBzKN3IYEhgFMnU4+VFrb+UGSMRTC99xpbq2SdYZCeE79GWVpBhqIc77dzN7TNRRXNxIVqWNS/97eG18QksAwgA1KUz50us4YqoGh7H4ihM+4sx2eSg0mzV184RNCOEedRo5NA12k06d9vl/JFp4/MAljpAvrhMOABIYBbLAjMOziAyQmRbmuLVF6qwkhvM+dXU9Ujm3xJDAUosfcLDxZbw8Mpw1J9fSIgp4EhgHMualk+y+1xdSyV6QQwrvUbF+kG4GhXnY/EcJjHIUnzgeGVfVNbLXvdjJtSIo3RhXUJDAMYANSlMrkijoz5bWmjg+KjAJDgnJbClCE8A13i09AMoZCeJIjY+h8RfKXB8uw2mBQaix9ermxHCTESWAYwKL0OrJ7uVKZLAUoQviEY42hOxlDWWMohMe4MZX85QFlTb5kCzsmgWGAG5SqfIgclspkIQKHoypZMoZC+JWLPQxtNhtfHlQCw4sGS2DYEQkMA9xAe2DY5TrDmGTluq7cByMSQvSo+MSRMZQ1hkL0mIsZw/0lNZRUmzBGapmQI21qOiKBYYAboAaGZU4EhvUSGArhE+7ufAKt+hhKxlCIHrHZWjW3znDqFHUaeVJ/aVPTGQkMA5xzGUN7OlwyhkL4hqwxFML/TNUt2ftY55pbf3lA+ZyUaeTOSWAY4NTAsKTaRHVjU8cHRScp13XS5FoIn3AEhu7sfCJrDIXwiBr7unpDvFPN5hubLGw+VgHARYOSvTmyoCaBYYCLN0aSGmcAuihAcUwln/HRqIQIc7LziRD+V1usXMc6t9fxd8cqMDdbSY83OpIuoj0JDINAt9PJ0VJ8IoRPNfVgKln2ShbCM9SMoZN7JH99SPmMPH9gMhqNxlujCnoSGAaBgd0VoKhrDKX4RAjfcBSfyBpDIfxGzRg6GxgeVD4jL5Rp5C5JYBgEBqR008tQnUpuOAuWTtYhCiE8R3Y+EcL/apyfSq6oM/P9qWpAyRiKzklgGAS6nUqO6gXY0+L1Fb4ZlBDhrCdVyepUsmQMheiZWuenkr+xTyMPTY8jxb5uX3RMAsMgoGYMi842YG62tj9Aq4Noe6NOmU4Wwrtstp7tfKJvFRhaO3g/CyGc48gYdh8YbjisFGdKtrB7EhgGgbR4AzF6HRarjcKKuo4PkgIUIXyjuRGwKbfdanDdqhqyqZP3sxCie46MYfdTyRsPq4UnSd4cUUiQwDAIaDSalh1QSjv5IHE0uZZehkJ4lbq+ENzLGEYYQWPfcUHWGQrhPrUquZuM4cnKBo6dqUen1cg2eE6QwDBIOApQOq1Mtn8Lkl6GQniXmuXTGZRlHK7SaFqyhrLOUAj3NDWAqUq53U3GcIN9fWFenwTijJHeHlnQk8AwSAxIUTITnQaGMpUshG84KpLdmEZW6aWXoRA9oq4vjIhSdj7pgrq+cMoAWV/oDAkMg0SuPWN4pKyzqWQ1MJSpZCG8qqkHPQxVkjEUomfUwDAuTcnCd8Jms7HBvr5wygBZX+gMCQyDROupZJvN1v4AaXIthG94JGMovQyF6JFa5yqSj52pp6TahF6nZWy/Xj4YWPCTwDBI9EuKRquBmsZmympN7Q+Itn8TqpM1hkJ4VZM9MHSnIlklGUMheqbGuYrkjfZp5Py+iRgj3VgTHIYkMAwSxkgd2b2VD6LDHVUmq1PJkjEUwrt60txa5cgYyhpDIdxSV6pcd7PrybdHlMDwvFyZRnaWBIZBJDdZ+SA6Ut5BlkGKT4TwDY9kDGX3EyF6pNYeGMakdnqIzWZjowSGLpPAMIh0WYCiTiU3VoLV4rtBCRFuZI2hEP6nFlrGdF5pfKS8jrIaE/oILfl9E30zrhAggWEQybW3rDnSUcuaKPuiWpsVGqt8OCohwoxUJQvhf2pgGNt5xlCdRh4r6wtdIoFhEOnvmEruIGMYoW/pjVZf4cNRCRFmPJoxlDWGQrilVs0Ydh4YbjqifBZO6i/TyK6QwDCIqC1riirqMTdb2x8Qbd/qR3Y/EcJ7ZI2hEP5ls7UqPknp5BAbm44qn4WTcmUbPFdIYBhEUuMMxOh1WG1QWNHROkP7L3+DZAyF8BqPViVLYOgrL7/8Mjk5ORiNRiZNmsTmzZudOu/dd99Fo9Ewe/Zs7w5QOM9cC82Nyu2YjgPDwgqlf2GkTkN+tvQvdIUEhkFEo9E4ClAOd1WAIhlDIbxH+hgGnffee4/58+fz2GOPsW3bNvLy8pgxYwalpaVdnnfs2DF+85vfcOGFF/popMIpakVyZEynX9DUaeS8PolE6WV9oSskMAwyLQUoHQSGUepUsmQMhfAaR8ZQqpKDxbPPPsvdd9/N3LlzGT58OEuXLiU6Oprly5d3eo7FYuGWW27h97//Pbm5uV0+vslkorq6us1FeJGj8KTjbCHApqPK5+DE/jKN7CoJDINMbrLasqajXob2jKFMJQvhPY6MYU+qktU1hlJ84m1ms5mtW7cyffp0x31arZbp06ezcePGTs974oknSE1N5c477+z2ORYvXkxCQoLjkp2d7ZGxi0440cNw8zFl5kwCQ9dJYBhkHBnDjiqTpfhECO+TPoZBpby8HIvFQlpa2x0y0tLSKC4u7vCcr7/+mtdff51ly5Y59RwLFiygqqrKcSkqKurxuEUXHD0MO84Ynq5qoKiiAa0Gxsn+yC6L8PcAhGvUwPBol4GhZAyF8BrpYxjSampquPXWW1m2bBnJyZ03T27NYDBgMBi8PDLh0M1U8nfHzgIwPDOeOGOkr0YVMiQwDDI5ScqHUUWdmcp6M4nR+pYfyhpDIbzPkxnD5kawNINO/iv2luTkZHQ6HSUlJW3uLykpIT09vd3xhw8f5tixY1x55ZWO+6xWpT1YREQE+/fvZ8CAAd4dtOhaN1PJ39nXF07IkWlkd8hUcpCJMUSQHm8EOsgayhpDIbzPk30MQdYZepler2fcuHGsW7fOcZ/VamXdunVMnjy53fFDhw5l165dFBQUOC5XXXUVF198MQUFBbJ+MBA4ehh2Ehgek8CwJ+RrahDqnxxDcXUjR8vryO/bav2ErDEUwvscGcMeTCXrIkFnAItJWWcYJeugvGn+/PncfvvtjB8/nokTJ/L8889TV1fH3LlzAbjtttvIyspi8eLFGI1GRo4c2eb8xMREgHb3Cz+pK1euO9gnuaq+if0lypctCQzdI4FhEOqfEsPGI2fat6xx9DGsUDrDazS+H5wQoc6xxrAHGUNQ1hnWm2SdoQ/MmTOHsrIyFi5cSHFxMWPGjGHNmjWOgpTCwkK0WplACxpdTCVvLazAZlMSKClxsu7THRIYBqHc5E4KUNQ1hjYLNFZBVKJvByZEqLM0gbVZud2TNYagrDOsPyOVyT4yb9485s2b1+HP1q9f3+W5b7zxhucHJNznKD5pHxiqhSfjpRrZbW59RXJ1a6Hnn3+eIUOGEBUVRXZ2Nvfffz+NjY1uDVh00bIm0thSKSnrDIXwPHOr91xPqpJBehkK4Y5mE5jsDcQ7mEreqgaGORIYusvlwNDVrYXeeecdfve73/HYY4+xd+9eXn/9dd577z0eeuihHg8+XPW3N7k+Vl6H1Wpr+0NpWSOE96iFJ9oIiNB3fWx3pJehEK5T19BrI8CY2OZH5mYrO05UAjCun6wvdJfLgaGrWwtt2LCB888/n5tvvpmcnBwuu+wybrrpJqc3MBft9ekVRYRWQ0OTheLqczKvEhgK4T1mD+x6opJehkK4Ti08iU5qt45+96kqTM1WekVHMiDFA+/RMOVSYOjO1kJTpkxh69atjkDwyJEjrF69mlmzZnX6PLLvZNcidVr69lbWN3W6zlAqk4XwvCYP7JOskoyhEK6rVwPDzqeRx/XrjUaKL93mUmDoztZCN998M0888QQXXHABkZGRDBgwgGnTpnU5lSz7Tnavv70Apd2eyWrGUNYYCuF5Zg/0MFQ5MoayxlAIp9XZkx4xSe1+tOW48rkn6wt7xuv1+evXr+fJJ5/kz3/+M9u2bWPFihV88sknLFq0qNNzZN/J7vV3VCbXt/2BmjFsOOvjEQkRBjyaMbQXn0jGUAjn1beaSm7FZrOx9XglIBXJPeVSuxpXtxYCePTRR7n11lu56667ABg1ahR1dXX89Kc/5eGHH+6wd5TsO9m9/o49k8/5UFEb5UpgKITneXKNodogW9YYCuG8uo6nkosqGiivNRGp0zAyK8EPAwsdLmUMXd1aCKC+vr5d8KfT6QAlwhfu6d9pL0MJDIXwmiYP7JOsMsgaQyFcVt/xrifbCpXPvBGZCRgjdb4eVUhxucG1K1sLAVx55ZU8++yz5OfnM2nSJA4dOsSjjz7KlVde6QgQhety7S1ris420GSxEqmzB98SGArhPWYP7XoCLcUnssZQCOfVdTyVvPW48pk3tq9MI/eUy2sM58yZwzPPPMPChQsZM2YMBQUF7bYWOn36tOP4Rx55hF//+tc88sgjDB8+nDvvvJMZM2bw6quveu5VhKG0eANRkTosVhtFFa3WGUq7mqDhaqP4999/n6FDh2I0Ghk1ahSrV6/u9Nif/exnaDQann/+eQ+POsw1eWCfZJVB1hgK4TK140YnGcOx/RJ9PKDQ41bxybx58zh+/Dgmk4lNmzYxadIkx8/Wr1/fZvugiIgIHnvsMQ4dOkRDQwOFhYW8/PLLjk3JhXs0Gk3H08mSMQwKrjaK37BhAzfddBN33nkn27dvZ/bs2cyePZvdu3e3O/ajjz7i22+/JTMz09svI/x4sipZL30MhXBZB2sM683N7CtWMu/jpPCkx2TX8CDWUoDSUWBY6fsBCae52ij+hRdeYObMmTzwwAMMGzaMRYsWMXbsWF566aU2x508eZJf/OIXvP3220RGRnY7DukZ6iJHVbIHG1xLxlAI53WwxnBHURUWq42MBCMZCVF+GljokMAwiOUmd7BnstquxlQFlmY/jEp0x51G8Rs3bmxzPMCMGTPaHG+1Wrn11lt54IEHGDFihFNjkZ6hLvJoxlDdK1kCQyGcYmlumQ1rlTF0TCPL+kKPkMAwiDmmkstaBYbGVmX6jZW+HZBwijuN4ouLi7s9/umnnyYiIoJf/vKXTo9Feoa6yCtVyVJ8IoRTHBs3aFrW0wMFRZUA5PdN9PmQQpHLVckicDh2P2ndy1AXAYYEJWPYcLbdAl0RmrZu3coLL7zAtm3bXNoKSnqGushRleyJPoat1hjabO32fRVCnENdXxjVC7Qtbe+2F1YCMCY70T/jCjGSMQxiamBYUm2iztRq2jgqUbmWApSA5E6j+PT09C6P/+qrrygtLaVv375EREQQERHB8ePH+fWvf01OTo5XXkdY8kbG0NoMzaaeP54Qoa6D9YUnK5XG1hFaaWztKRIYBrHEaD29Y/QAHDvTajpZWtYENHcaxU+ePLnN8QBr1651HH/rrbeyc+dOCgoKHJfMzEweeOABPv30U++9mHDjjapkaMlECiE610EPQzVbOCwjXhpbe4hMJQe53OQYKurMHC2vY0Sm/duStKwJeK42ir/vvvuYOnUqS5Ys4YorruDdd99ly5YtvPbaawAkJSWRlNS24WtkZCTp6ekMGTLEty8ulHmyKlmrUwLMpnqlyXVMUvfnCBHO1B6GrQJDWV/oeRIYBrn+yTFsOX6WI2XSyzCYzJkzh7KyMhYuXEhxcTFjxoxp1yi+9VaSU6ZM4Z133uGRRx7hoYceYtCgQaxcuZKRI0f66yWEJ09mDEHJGjbVS8saIZzRQXPr7faKZFlf6DkSGAa5rnsZSmAYyObNm8e8efM6/Nn69evb3Xf99ddz/fXXO/34x44dc3NkolOeXGMIyjrDulKpTBbCGedkDJssVnafUnqvSmDoObLGMMh12cuwQdYYCuFRnqxKhpZt8aSXoRDdOycw3F9cg7nZSrwxwlGMKXpOAsMg1z9ZWcB+tKwWm82m3CkZQyG8Qw0MPZUxVJtcS8ZQiO6pBZX2wFBdX5iXnehSmy7RNQkMg1y/pGg0GqhubKaizqzcKYGhEJ5ntYDF3lbGYxlD2S9ZCKepGUP7rNjOE5UA5PVJ9M94QpQEhkHOGKkj0743pGOdoQSGQnhe65YyHltjKBlDIZzm2A5PyRjuKKoClIyh8BwJDENArr0AxVGZLH0MhfA8tfAEDUQYPfOYai9DqUoWonuONYa9qTM1c7BU+UKV10caW3uSBIYhoF0BimQMhfA8c6sehp5az+TYL7naM48nRKhqamj5chbdm90nq7DaICPBSGq8h76oCUACw5Dg2DO5zJ51UANDU7WyLkoI0XNNHu5hCGCIV65ljaEQXVNnwLQRYIhn5wllGnm0ZAs9TgLDEJCbYq9MVjOGxlZvlMYqP4xIiBBk9nAPQ5CpZCGc1bpVjUbDzpNqYJjovzGFKAkMQ4CaMTx+ph6L1Qa6yJY2GDKdLIRnOLbDi+36OFc4ppKl+ESILp1TkbzLXpEsGUPPk8AwBGQlRqGP0GK2WDlx1p7VkHWGQniWp7fDA2lwLYSzGlp6GFY1NHHsjPJ+HJkpgaGnSWAYArRaDf2Tzi1Asb9ZGir9MyghQo2nt8ODVg2upfhEiC45mlv35nv7NHJ27yh6xej9OKjQJIFhiGjXskYyhkJ4lqe3w4NWfQwlYyhEl1q1qlHXF47KkmyhN0hgGCI6rUyWwFAIz/BGxlB2PhHCOa22w9vlCAwT/TeeECaBYYhoV5msBoaNlf4ZkBChxhtrDPVSfCKEU1pVJe+SVjVeJYFhiGjJGKotaxKVa8kYCuEZTa0aXHuKOpXc3AiWJs89rhChxh4Y1usSKKyQwhNvksAwRAywrzEsrm6k1tQsU8lCeJo3q5JBsoZCdMVelXys0QAohScJ0ZH+HFHIksAwRCRG60myV2cdLauTwFAIT3NkDD0YGOoiQad80Mk6QyG6YF9jeKBaeb+MyJBsobdIYBhCHJXJ5bUQlajcKe1qhPAMR8bQg1PJIJXJQjjDPpW8q0IJW0ZmxftzNCFNAsMQMsBegHJYMoZCeJ7ZCxlDkN1PhOhOU6OjK8CWMg0AI2R9oddIYBhC1Izh4bJaCQyF8LQmL6wxhFa7n0hgKESH7OsLbRodO8ttAIyQjKHXRPh7AMJz1IzhkbI6MOYodzZWgs0GGo3fxiVESDB7oSoZWu1+IoFhKLBYLJjNZvr164fZbKaxsdHfQwp+VeUQm02TPpHMmgh6x+iJj0T+bluJjIxEp9N55LEkMAwhLb0Ma7EaE5V0sMWsZDo8/WEmRLjxWsZQnUqWNYbBzGazUVxcTGVlJVarlaVLl1JSUkJZWZm/hxb8mi1w/hKsmkgetyZijNRy9OhRf48q4CQmJpKeno6mh4kgCQxDSHavKCJ1GhqbrJyq19JHGwnWJmU6WQJDIXpGLT7x9HvJIBnDUKAGhampqRgMBhoaGsjJyfFYFiesNVZBtQ2zxkizJZneMQZS4gz+HlXAsNls1NfXU1paCkBGRkaPHk8CwxASodPSLymGQ6W1HCmvp09UL6grVSqTE/r4e3hCBDe1XY2nM4Z62RYv2FksFkdQmJSUhMViAcBoNEpg6AmWWojQ0KyJQKPREx8ThdGo9/eoAkpUVBQApaWlpKam9uj3TopPQoza6PpQaeuWNVKAIkSPmb2wVzJIxjAENDUpu9ZER3v4d0MorM0ANFmVkMUYKcF2R9TfP/X30V0SGIaYlpY1UpkshMdYrdDcoNz2Wh9DCQyDXU/XdolOWJUMbDNatBoN+ggJXTriqd8/+dsNMQNTlcBQyRhKYCiER6iFJ+D5jKFMJQvRNXvG0IIWY6ROAnAvk8AwxLRpcm1MVO6UwFCInnEEhhqIiPLsY0uDayG6Zg8Mm9ERJdPIXieBYYgZYM8YlteaMEXaO8M3VvpvQEKEAjWbp48BrYf/25SpZCHa+clPfsLs2bOVP9inki02LUa9hC3eJn/DISbWEEFGghGAMxZ7ZkP2SxaiZ8xeqkgGMNh3cJDAUIiO2SRj6EsSGIYgdZ1hsVkJEGUqWYge8lYPQ5DAUIhu2Oztf6xoMUYEdmBoNpv9PYQek8AwBKnrDIsaJTAUwiMcU8mxnn9sx1RytecfW/iNzWaj3tzsl4vNZnN6nB988AGjRo0iKiqKpKQkpk+fTl2dkiH/7rvvuPTSS0lOTiYhIYGpU6eybdu2NudrNBpeffVVfvjDHxIdHc2wYcPYuHEjhw4dYtq0acTExDBlyhQOHz7sOOfxxx9nzJgxvPrqq2RnZxMdHc0NN9xAVVVVR3+RYGvGarXy6p9fYsCAXKKiosjLy+ODDz7o8rW99dZbjB8/nri4ONLT07n55psdTaCtVit9+vThlVdeaXPO9u3b0Wq1HD9+HIDKykruuusuUlJSiI+P55JLLmHHjh3tXstf/vIX+vfvj9GofO6uWbOGCy64gMTERJKSkvjhD3/Y5u8AYMOGDYwZMwaj0cj48eNZuXIlGo2GgoICxzG7d+/m8ssvJzY2lrS0NG699VbKy8u7fN09JQ2uQ5C6zvBIbaRyh6wxFKJnHPske2MqWdYYhiKTBUb9/j9+ee49T8wgWt/9x/vp06e56aab+NOf/sQ111xDTU0NX331lSOwrKmp4fbbb+fFF1/EZrOxZMkSZs2axcGDB4mLi3M8zqJFi3j22Wd59tlnefDBB7n55pvJzc1lwYIF9O3blzvuuIN58+bx73//23HOoUOH+Mc//sG//vUvqqurufPOO/n5z3/O22+/3XaQNgsa4MkXl7Pyo/+wdOlSBg0axJdffsmPf/xjUlJSmDp1aoevr6mpiUWLFjFkyBBKS0uZP38+P/nJT1i9ejVarZabbrqJd955h3vuucdxzttvv835559Pv379ALj++uuJiori3//+NwkJCbz66qv84Ac/4MCBA/Tu3dvxWj788ENWrFjhaCxdV1fH/PnzGT16NLW1tSxcuJBrrrmGgoICtFot1dXVXHnllcyaNYt33nmH48eP86tf/arN+CsrK7nkkku46667eO6552hoaODBBx/khhtu4L///W+3/77uksAwBA20Zwz3V9n/eSVjKETPNHlzKtn+AWsxQ7MJImSrL+Ebp0+fprm5mR/96EeOQGjUqFGOn19yySVtjn/ttddITEzkiy++4Ic//KHj/rlz53LDDTcA8OCDDzJ58mQeffRRZsyYAcB9993H3Llz2zxWY2Mjf/vb38jKygLgxRdf5IorrmDJkiWkp6e3HGi1YDKZefLF5fxj1b+ZMX0aALm5uXz99de8+uqrnQaGd9xxh+N2bm4u/+///T8mTJhAbW0tsbGx3HLLLSxZsoTCwkL69u2L1Wrl3Xff5ZFHHgHg66+/ZvPmzZSWlmIwKO/LZ555hpUrV/LBBx/w05/+FFCmj//2t7+RkpLieL5rr722zViWL19OSkoKe/bsYeTIkbzzzjtoNBqWLVuG0Whk+PDhnDx5krvvvttxzksvvUR+fj5PPvlkm8fJzs7mwIEDDB48uMPX3VMSGIYgdY3hwRod6IGGDtLzQgjnta5K9jRDS+YFU40EhiHCoINdj033y5Z4zhZo5OXl8YMf/IBRo0YxY8YMLrvsMq677jp69VJ64JaUlPDII4+wfv16SktLsVgs1NfXU1hY2OZxRo8e7bidlpYGtA0w09LSaGxspLq6mvh4ZU1t3759HUEhwOTJk7Farezfv/+cwLCZQ8eKqG9oZM7slmAUlIAsPz+/09e3detWHn/8cXbs2MHZs2exWq0AFBYWMnz4cMaMGcOwYcN45513+N3vfscXX3xBaWkp119/PQA7duygtraWpKSkNo/b0NDQZlq4X79+bYJCgIMHD7Jw4UI2bdpEeXl5m+ceOXIk+/fvZ/To0Y6pZ4CJEye2eYwdO3bw+eefExvbfgnL4cOHJTAUzkuO1ZMYHcnZerU/WhVYmkEn/9xCuMVRleyFwFCrU9YummuVdYYxyZ5/DsHLL7/M//7v/1JcXExeXh4vvvhiuw9i1YoVK3jyySc5dOgQTU1NDBo0iF//+tfceuutTj+fRqMhWh8R0Hsl63Q61q5dy4YNG/jss8948cUXefjhh9m0aRP9+/fn9ttv58yZM7zwwgv069cPg8HA5MmT2xVYREZGOm6rzac7uk8NjlxhszZTW6dk7D9atYr+ffu2+bmayTtXXV0dM2bMYMaMGbz99tukpKRQWFjIjBkz2oz/lltucQSG77zzDjNnznQEgrW1tWRkZLB+/fp2j5+YmOi4HRPT/v+FK6+8kn79+rFs2TIyMzOxWq2MHDnSpeKU2tparrzySp5++ul2P8vIyHD6cVwlkUII0mg0DE6NY+uxxpY7G6sgJqnzk4QQnbNXJVsjo9l+vILBaXHEGSO7OckFhjglMGyUAhRveO+995g/fz5Lly5l0qRJPP/888yYMYP9+/eTmpra7vjevXvz8MMPM3ToUPR6PR9//DFz584lNTXVMT0aKjQaDeeffz7nn38+CxcupF+/fnz00UfMnz+fb775hj//+c/MmjULgKKiIo8VPhQWFnLq1CkyMzMB+Pbbb9FqtQwZMqTNcc1NTQwfnIvBoOf0iRNces70dmf27dvHmTNneOqpp8jOzgZgy5Yt7Y67+eabeeSRR9i6dSsffPABS5cudfxs7NixFBcXExERQU5OjtOv7cyZM+zfv59ly5Zx4YUXAsq0dGtDhgzh73//OyaTyRHcfvfdd22OGTt2LB9++CE5OTlERPguXJOq5BA1MC0WCzpMOvtieSlAEcJ99qnkfx+o4dpXNjJ20Vp+8/4Omi2uZ0A6JAUoXvXss89y9913M3fuXIYPH87SpUuJjo5m+fLlHR4/bdo0rrnmGoYNG8aAAQO47777GD16dLsP92C3adMmnnzySbZs2UJhYSErVqygrKyMYcOGATBo0CDeeust9u7dy6ZNm7jllluIivLMzj9Go5Hbb7+dHTt28NVXX/HLX/6SG264oe00MtDc3ERcbAy//NmdzJ8/nzfffJPDhw+zbds2XnzxRd58880OH79v377o9XpefPFFjhw5wqpVq1i0aFG743JycpgyZQp33nknFouFq666yvGz6dOnM3nyZGbPns1nn33GsWPH2LBhAw8//HCHQaaqV69eJCUl8dprr3Ho0CH++9//Mn/+/DbH3HzzzVitVn7605+yd+9ePv30U5555hmgJcN67733UlFRwU033cR3333H4cOH+fTTT5k7dy4Wewsfb5DAMEQNsq8zrNHYP3CkAEUIt1lMSmB4oMKKVgNNFhsfbD3B618f9cwTSC9DrzGbzWzdupXp06c77tNqtUyfPp2NGzd2e77NZmPdunXs37+fiy66qNPnsFqtWCwWxyUYxMfH8+WXXzJr1iwGDx7MI488wpIlS7j88ssBeP311zl79ixjx47l1ltv5Ze//GWHGVZ3DBw4kB/96EfMmjWLyy67jNGjR/PnP/+53XGWZqW59aO/+w2PPvooixcvZtiwYcycOZNPPvmE/v37d/j4KSkpvPHGG7z//vsMHz6cp556yhF4neuW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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "f, axarr = plt.subplots(1,3, layout='constrained', sharey=False)\n", - "\n", - "for i in range(3): \n", - " axarr[i].plot(t, Ymean[:,i], label='sample average')\n", - " axarr[i].plot(t, solutionReference[:,i], label='reference')\n", - " axarr[i].set_title(stateList[i])\n", - "\n", - "axarr[2].legend()\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "aa230d7f", - "metadata": {}, - "source": [ - "The difference between the deterministic reference and averaged solutions is relatively large, especially for the $S$ state. \n", - "We can decrease this difference as we increase the number of simulations, and also by using more sophisticated sampling methods for the generation of random\n", - "variables." - ] - }, - { - "cell_type": "markdown", - "id": "39d66f12", - "metadata": {}, - "source": [ - "```{tip}\n", - "In addition to using the built-in functions to represent stochasticity,\n", - "we can also use standard frozen distributions from scipy. Note that it\n", - "must be a frozen distribution as that is the only for the parameters of\n", - "the distributions to propagate through the model.\n", - "```\n" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "id": "b8a806bc", - "metadata": {}, - "outputs": [], - "source": [ - "import scipy.stats as st\n", - "\n", - "d = dict()\n", - "\n", - "d['beta'] = st.gamma(a=100.0, scale=1.0/200.0)\n", - "\n", - "d['gamma'] = st.gamma(a=100.0, scale=1.0/300.0)\n", - "\n", - "odeS.parameters = d" - ] - }, - { - "cell_type": "markdown", - "id": "030d6487", - "metadata": {}, - "source": [ - "There may be scenarios where only some of the parameters are\n", - "stochastic. Let's say that the $\\gamma$ parameter is fixed at $1/3$,\n", - "then we can replace the distribution information with a scalar. A quick\n", - "visual inspection at the resulting plot suggests that the system of ODEs\n", - "potentially has less variation when compared to the case where both\n", - "parameters are stochastic." - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "id": "fa0d6ee2", - "metadata": {}, - "outputs": [], - "source": [ - "d['gamma'] = 1.0/3.0\n", - "\n", - "odeS.parameters = d\n", - "\n", - "YmeanSingle, YallSingle = odeS.simulate_param(t[1::], 5, full_output=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "id": "eb4e969a", - "metadata": { - "tags": [ - "hide-input" - ] - }, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "f, axarr = plt.subplots(1,3)\n", - "\n", - "for solution in YallSingle: \n", - " axarr[0].plot(t,solution[:,0]) \n", - " axarr[1].plot(t,solution[:,1]) \n", - " axarr[2].plot(t,solution[:,2])\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "2f01a3d9", - "metadata": {}, - "source": [ - "## Continuous Markov Representation\n", - "\n", - "Another common method of introducing stochasticity into a set of ODEs is\n", - "by assuming each movement in the system is a result of a jump process.\n", - "More concretely, the probabilty of a move for transition $j$ is governed\n", - "by an exponential distribution such that\n", - "\n", - "$$\\Pr(\\text{process $j$ jump within time } \\tau) = \\lambda_{j} e^{-\\lambda_{j} \\tau},$$\n", - "\n", - "where $\\lambda_{j}$ is the rate of transition for process $j$ and $\\tau$\n", - "the time elapsed after current time $t$.\n", - "\n", - "Two of the commmon algorithms for the jump process have been\n", - "implemented for use during simulation; the reaction method [\\[Gillespie1977\\]]() and the $\\tau$-Leap method\n", - "[\\[Cao2006\\]](). The two change interactively depending on the size of the states." - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "id": "a0a0bcbc", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "x0 = [2362206.0, 3.0, 0.0]\n", - "\n", - "stateList = ['S', 'I', 'R']\n", - "\n", - "paramList = ['beta', 'gamma', 'N']\n", - "\n", - "transitionList = [Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T),\n", - " Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)\n", - " ]\n", - "\n", - "odeS = SimulateOde(stateList, paramList, transition=transitionList)\n", - "\n", - "odeS.parameters = [0.5, 1.0/3.0, x0[0]]\n", - "\n", - "odeS.initial_values = (x0, t[0])\n", - "\n", - "solutionReference = odeS.integrate(t[1::])\n", - "\n", - "simX, simT = odeS.simulate_jump(t[1:10], 10, full_output=True)\n", - "\n", - "f, axarr = plt.subplots(1, 3)\n", - "\n", - "for solution in simX: \n", - " axarr[0].plot(t[:9], solution[:,0])\n", - " axarr[1].plot(t[:9], solution[:,1]) \n", - " axarr[2].plot(t[:9], solution[:,2])\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "e18e4fa7", - "metadata": {}, - "source": [ - "Above, we see 10 different simulations, again using the SIR model but\n", - "without standardization of the initial conditions (we include $N$ as a parameter in our model). \n", - "For demonstration purposes, we restrict our time\n", - "frame to be only the first 10 time points so that the individual changes or stochasticity\n", - "can be seen more clearly. If we use the same time frame as the one\n", - "used previously for the deterministic system (as shown below), the\n", - "trajectories are smoothed out and we no longer observe the *jumps*.\n", - "Looking at the raw trajectories of the ODEs below, we see that the\n", - "mean from a jump process is very different to the deterministic\n", - "solution. This occurs because the jump process above was able\n", - "to fully remove all the initial infected individuals before any new\n", - "ones occured." - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "id": "525a069b", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "simX,simT = odeS.simulate_jump(t, 5, full_output=True)\n", - "\n", - "simMean = np.mean(simX, axis=0)\n", - "\n", - "f, axarr = plt.subplots(1,3)\n", - "\n", - "for solution in simX: \n", - " axarr[0].plot(t, solution[:,0]) \n", - " axarr[1].plot(t, solution[:,1]) \n", - " axarr[2].plot(t, solution[:,2])\n", - "\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "fbef64f3", - "metadata": {}, - "source": [ - "\n", - "## Repeatable Simulation\n", - "\n", - "One of the possible uses of compartmental models is to generate\n", - "forecasts. Although most of the time the requirement would be to have\n", - "(at least point-wise) convergence in the limit, reproducibility is also\n", - "important. For both types of interpretation explained above, we have\n", - "given the package the capability to repeat the simulations by setting a\n", - "seed. When the assumption is that the parameters follows some sort of\n", - "distribution, we can set the seed which governs the global state of\n", - "the random number generator." - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "415cab81", - "metadata": {}, - "outputs": [], - "source": [ - "x0 = [2362206.0, 3.0, 0.0]\n", - "\n", - "odeS = SimulateOde(stateList, paramList, transition=transitionList)\n", - "\n", - "d = {'beta': st.gamma(a=100.0, scale=1.0/200.0), 'gamma':st.gamma(a=100.0, scale=1.0/300.0), 'N': x0[0]}\n", - "\n", - "odeS.parameters = d\n", - "\n", - "odeS.initial_values = (x0, t[0])\n", - "\n", - "Ymean, Yall = odeS.simulate_param(t[1::], 10, full_output=True)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "id": "7a51e644", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Different in the simulations and the mean: (81103473.8935847, 52437230.37979218) \n", - "Different in the simulations and the mean using same seed: (0.0, 0.0) \n" - ] - } - ], - "source": [ - "\n", - "np.random.seed(1)\n", - "\n", - "Ymean1, Yall1 = odeS.simulate_param(t[1::], 10, full_output=True)\n", - "\n", - "np.random.seed(1)\n", - "\n", - "Ymean2, Yall2 = odeS.simulate_param(t[1::], 10, full_output=True)\n", - "\n", - "sim_diff = [np.linalg.norm(Yall[i] - yi) for i, yi in enumerate(Yall1)]\n", - "\n", - "sim_diff12 = [np.linalg.norm(Yall2[i] - yi) for i, yi in enumerate(Yall1)]\n", - "\n", - "print(\"Different in the simulations and the mean: (%s, %s) \" %(np.sum(sim_diff), np.sum(np.abs(Ymean1 - Ymean))))\n", - "\n", - "print(\"Different in the simulations and the mean using same seed: (%s, %s) \" % (np.sum(sim_diff12), np.sum(np.abs(Ymean2 - Ymean1))))" - ] - }, - { - "cell_type": "markdown", - "id": "e1fe54a8", - "metadata": {}, - "source": [ - "In the alternative interpretation, setting the global seed is\n", - "insufficient. Unlike simulation based on the parameters, where we can\n", - "pre-generate all the parameter values and send them off to individual\n", - "processes in the parallel backend, this is prohibitive here. In a\n", - "nutshell, the seed does not propagate when using a parallel backend\n", - "because each *integration* requires an unknown number of random samples.\n", - "Therefore, we have an additional flag **parallel** in the function\n", - "signature. By ensuring that the computation runs in serial, we can make\n", - "use of the global seed and generate identical runs." - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "id": "d5a9e235", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Difference in simulation: 2534.4614923250074\n", - "Difference in simulation using same seed: 0.0\n" - ] - } - ], - "source": [ - "x0 = [2362206.0, 3.0, 0.0]\n", - "\n", - "odeS = SimulateOde(stateList, paramList, transition=transitionList)\n", - "\n", - "odeS.parameters = [0.5, 1.0/3.0, x0[0]]\n", - "\n", - "odeS.initial_values = (x0, t[0])\n", - "\n", - "simX, simT = odeS.simulate_jump(t[1:10], 10, parallel=False, full_output=True)\n", - "\n", - "np.random.seed(1)\n", - "\n", - "simX1, simT1 = odeS.simulate_jump(t[1:10], 10, parallel=False, full_output=True)\n", - "\n", - "np.random.seed(1)\n", - "\n", - "simX2, simT2 = odeS.simulate_jump(t[1:10], 10, parallel=False, full_output=True)\n", - "\n", - "sim_diff = [np.linalg.norm(simX[i] - x1) for i, x1 in enumerate(simX1)]\n", - "\n", - "sim_diff12 = [np.linalg.norm(simX2[i] - x1) for i, x1 in enumerate(simX1)]\n", - "\n", - "print(\"Difference in simulation: %s\" %np.sum(np.abs(sim_diff)))\n", - "\n", - "print(\"Difference in simulation using same seed: %s\" %np.sum(np.abs(sim_diff12)))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.9.15 ('sphinx-doc')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.15" - }, - "vscode": { - "interpreter": { - "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" - } - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/notebooks/time_dependent_params.ipynb b/docs/notebooks/time_dependent_params.ipynb new file mode 100644 index 00000000..c0cf2bad --- /dev/null +++ b/docs/notebooks/time_dependent_params.ipynb @@ -0,0 +1,170 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "aeef8af5", + "metadata": {}, + "source": [ + "# Time dependent parameters\n", + "\n", + "PyGOM may also be used to model systems with time dependent parameters.\n", + "Such situations commonly enter epidemic modelling if, for example, the infectivity varies with time due to seasonal effects or interventions.\n", + "As an example, let's consider an SIR model with periodic infectivity ($\\beta(t)$) and add in immune waning too (so we can witness multiple seasons):\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d} S}{\\mathrm{d} t} &= -\\frac{\\beta(t) SI}{N} + w R \\\\\n", + "\\frac{\\mathrm{d} I}{\\mathrm{d} t} &= \\frac{\\beta(t) SI}{N}- \\gamma I \\\\\n", + "\\frac{\\mathrm{d} R}{\\mathrm{d} t} &= \\gamma I - w R \\\\\n", + "\\beta(t) &= \\beta_0 \\left(1+\\delta \\cos \\left(\\frac{2 \\pi t}{P} \\right) \\right)\n", + "\\end{aligned}$$\n", + "\n", + "where $\\beta_0$ is some baseline infection rate, $\\delta$ is the magnitude of oscillations from the baseline ($-1<\\delta<1$ so that $\\beta>0$), $P$ is the oscillation period and $w$ is the waning rate.\n", + "PyGOM cannot handle the time dependence explicitly, instead we must define a dummy variable, $\\tau$, to play the same role.\n", + "We append our set of equations with an extra one:\n", + "\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d} \\tau}{\\mathrm{d} t} &= 1\n", + "\\end{aligned}$$\n", + "\n", + "This takes the place of an extra ``state'' in our system, so we need to treat it as such by:\n", + "\n", + "- Declaring it in our state list\n", + "- Including the equation above in our ode list\n", + "- Providing an initial condition (best set $\\tau_0=0$ if $t_0=0$ so that that $\\tau=t$)\n", + "\n", + "We must also provide the functional form of $\\beta$ which we do by including it as a `derived parameter`.\n", + "In the following we put all of these requirements into code:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1679a48a", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import SimulateOde, Transition, TransitionType\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "# Define SIR model\n", + "stateList = ['S', 'I', 'R', 'tau'] # now we have added tau to the states\n", + "paramList = ['gamma', 'N', 'beta0', 'delta', 'period', 'w']\n", + "derived_param = [('beta', 'beta0*(1+delta*cos(2*3.14*tau/period))')] # beta (with tau instead of t)\n", + "\n", + "odeList=[Transition(origin='S', equation='-beta*S*I/N + w*R', transition_type=TransitionType.ODE),\n", + " Transition(origin='I', equation='beta*S*I/N - gamma*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='R', equation='gamma*I - w*R', transition_type=TransitionType.ODE),\n", + " Transition(origin='tau', equation='1', transition_type=TransitionType.ODE)] # d(tau)/dt = 1\n", + "\n", + "# Set parameter values\n", + "gamma=0.25 # Recovery rate\n", + "n_pop=1e4 # Total population\n", + "beta0=0.3 # Baseline infectivity\n", + "period=365 # Period 1 year\n", + "delta=0.2 # beta varies between 0.8 and 1.2 times beta0\n", + "w=2/(365) # timescale of immune waning of order 0.5 year\n", + "\n", + "params=[('gamma', gamma),\n", + " ('N', n_pop),\n", + " ('beta0', beta0),\n", + " ('delta', delta),\n", + " ('period', period),\n", + " ('w', w)]\n", + "\n", + "# Initial conditions\n", + "i0=1\n", + "x0 = [n_pop-i0, i0, 0, 0] # We specify tau0=0 in [s0, i0, r0, tau0]\n", + "\n", + "# Time range and increments\n", + "tmax=10*365 # run for 10 years\n", + "dt=0.1 # timestep\n", + "n_timestep=int(tmax/dt) # number of iterations\n", + "t = np.linspace(0, tmax, n_timestep) # times at which solution will be evaluated\n", + "\n", + "# Set up pygom object\n", + "ode = SimulateOde(stateList,\n", + " paramList,\n", + " ode=odeList,\n", + " derived_param=derived_param)\n", + "\n", + "ode.initial_values = (x0, t[0]) # (initial state conditions, initial timepoint)\n", + "ode.parameters=params" + ] + }, + { + "cell_type": "markdown", + "id": "1dcdfcc4", + "metadata": {}, + "source": [ + "We may then solve this deterministically and plot the result:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a8057a58", + "metadata": {}, + "outputs": [], + "source": [ + "solution = ode.solve_determ(t[1::])\n", + "\n", + "f, axarr = plt.subplots(2,2, layout='constrained', figsize=(10, 4))\n", + "\n", + "axarr[0][0].plot(t/365, solution[:,0], color='C1')\n", + "axarr[0][1].plot(t/365, solution[:,1], color='C0')\n", + "axarr[1][0].plot(t/365, solution[:,2], color='C2')\n", + "axarr[1][1].plot(t/365, solution[:,3]/365, color='C3')\n", + "axarr[0][0].set_title(\"S\")\n", + "axarr[0][0].set_xlabel(\"Time (years)\")\n", + "axarr[0][1].set_title(\"I\")\n", + "axarr[0][1].set_xlabel(\"Time (years)\")\n", + "axarr[1][0].set_title(\"R\")\n", + "axarr[1][0].set_xlabel(\"Time (years)\")\n", + "axarr[1][1].set_title(\"tau (years)\")\n", + "axarr[1][1].set_xlabel(\"Time (years)\")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "dc691a8f", + "metadata": {}, + "source": [ + "```{warning}\n", + "PyGOM cannot be used to solve time dependent systems stochastically.\n", + "This is because our dummy variable, $\\tau$, representing time will be treated the same as the other state variables and thus also evolves stochastically.\n", + "Mathematically, the equation $\\frac{\\mathrm{d} \\tau}{\\mathrm{d} t} = 1$ implies stochastic evolution according to $\\mathrm{d} \\tau \\sim \\mathrm{Poisson}(\\mathrm{d} t)$.\n", + "Whilst $\\tau$ might vaguely follow a similar trajectory to time, we will likely lose too much precision for most applications.\n", + "```" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.15 ('sphinx-doc')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "4dc1e323c80fe09539c74ad5c5a7c7d8d9ff99e04f7b3dbd3680daf878629d6e" + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/notebooks/transition.ipynb b/docs/notebooks/transition.ipynb index fc65bc5a..42d68d31 100644 --- a/docs/notebooks/transition.ipynb +++ b/docs/notebooks/transition.ipynb @@ -6,7 +6,6 @@ "source": [ "# Model set-up using the transition object\n", "\n", - "\n", "The most important part of setting up the model is to correctly define the set ODEs, which is based solely on the classes defined in `transition`. These transitions describe how members of one state can move into another state. We choose to define the models using transitions because it enables the computer to do our book-keeping, therefore reducing the error of, for example, including a flow out of one state, but forgetting to include it in the recipient state. (This does not apply to birth and death processes.) \n", "\n", "\n", @@ -30,7 +29,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "68d41d64", "metadata": {}, "outputs": [], @@ -57,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "3b0801dd", "metadata": {}, "outputs": [], @@ -158,53 +157,24 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "1e17eb7c", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}0 & I S \\beta & 0\\\\0 & 0 & I \\gamma\\\\0 & 0 & 0\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[0, I*S*beta, 0],\n", - "[0, 0, I*gamma],\n", - "[0, 0, 0]])" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "modelTrans.get_transition_matrix()" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "570ceed5", "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": "\n\n\n\n\n\n\n\n\nS\n\nS\n\n\n\nI\n\nI\n\n\n\nS->I\n\n\nβ*S*I\n\n\n\nR\n\nR\n\n\n\nI->R\n\n\nγ*I\n\n\n\n", - "text/plain": [ - "" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "# TODO why are two images produced? issue #75\n", - "modelTrans.get_transition_graph(show=False)" + "modelTrans.get_transition_graph(show=True)" ] }, { @@ -235,27 +205,10 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "9f24cb0a", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}- I S \\beta\\\\I S \\beta - I \\gamma\\\\I \\gamma\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[ -I*S*beta],\n", - "[I*S*beta - I*gamma],\n", - "[ I*gamma]])" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "birth1 = Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.B)\n", "\n", @@ -278,27 +231,10 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "id": "9a3b3758", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}- I S \\beta\\\\I S \\beta - I \\gamma\\\\I \\gamma\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[ -I*S*beta],\n", - "[I*S*beta - I*gamma],\n", - "[ I*gamma]])" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "death1 = Transition(origin='S', equation='beta*S*I', transition_type=TransitionType.D)\n", "\n", @@ -333,27 +269,10 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "id": "3a6a15ea", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}B - I S \\beta - S \\mu\\\\I S \\beta - I \\gamma - I \\mu\\\\I \\gamma\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[ B - I*S*beta - S*mu],\n", - "[I*S*beta - I*gamma - I*mu],\n", - "[ I*gamma]])" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "modelBD2 = modelTrans\n", "\n", @@ -390,21 +309,10 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "id": "ce5787f8", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "TransitionType.B = Birth process\n", - "TransitionType.D = Death process\n", - "TransitionType.T = Between states\n", - "TransitionType.ODE = ODE _equation\n" - ] - } - ], + "outputs": [], "source": [ "from pygom import transition\n", "\n", diff --git a/docs/notebooks/unroll/unrollBD.ipynb b/docs/notebooks/unroll/unrollBD.ipynb index 54b6f36d..b688db13 100644 --- a/docs/notebooks/unroll/unrollBD.ipynb +++ b/docs/notebooks/unroll/unrollBD.ipynb @@ -10,98 +10,182 @@ "birth and death processes.\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -\\beta SI + B - \\mu S\\\\\n", - "\\frac{dI}{dt} &= \\beta SI - \\gamma I - \\mu I\\\\\n", - "\\frac{dR}{dt} &= \\gamma I\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= -\\beta SI + B - \\mu S\\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\beta SI - \\gamma I - \\mu I\\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= \\gamma I - \\mu R\n", "\\end{aligned}$$\n", "\n", - "which consists of two transitions and three birth and death process.\n", + "which consists of two transitions, one birth process and three death processes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a17b8221", + "metadata": {}, + "outputs": [], + "source": [ + "digraph SIR_Model {rankdir=LR;\n", + " size=\"8\" node \\[shape = circle\\];\n", + " S -\\> I \\[ label = \"βSI\"\\];\n", + " I -\\> R \\[ label = \"γI\" \\];\n", + " B \\[height=0 margin=0 shape=plaintext width=0\\];\n", + " B -\\> S; \"S\\**2*μ\" \\[height=0 margin=0 shape=plaintext width=0\\];\n", + " S -\\> \"S\\**2*μ\"; \"I\\*μ\" \\[height=0 margin=0 shape=plaintext width=0\\];\n", + " I -\\> \"I\\*μ\";\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "416dd324", + "metadata": {}, + "source": [ "\n", - "digraph SIR_Model { \n", - "rankdir=LR; size=\"8\" node \\[shape = circle\\]; S -\\> I \\[ label = \"βSI\"\n", - "\\]; I -\\> R \\[ label = \"γI\" \\]; B \\[height=0 margin=0 shape=plaintext\n", - "width=0\\]; B -\\> S; \"S\\**2*μ\" \\[height=0 margin=0 shape=plaintext\n", - "width=0\\]; S -\\> \"S\\**2*μ\"; \"I\\*μ\" \\[height=0 margin=0 shape=plaintext\n", - "width=0\\]; I -\\> \"I\\*μ\";\n", + "Let's define this in terms of ODEs, and unroll it back to the individual\n", + "processes.\n", "\n", - "}\n", + "We can also assume standard mixing:\n", "\n", - "Let's define this in terms of ODEs, and unroll it back to the individual\n", - "processes." + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= -\\frac{\\beta SI}{N} + B N - \\mu S\\\\\n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= \\frac{\\beta SI}{N} - \\gamma I - \\mu I\\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= \\gamma I - \\mu R \\\\\n", + "\\frac{\\mathrm{d}N}{\\mathrm{d}t} &= (B - \\mu) N\n", + "\\end{aligned}$$\n", + "\n", + "$N=S+I+R$ which means that we can get rid of one equation" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "id": "eed075f5", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}0 & I S \\beta & 0\\\\0 & 0 & I \\gamma\\\\0 & 0 & 0\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[0, I*S*beta, 0],\n", - "[0, 0, I*gamma],\n", - "[0, 0, 0]])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from pygom import Transition, TransitionType, SimulateOde, common_models\n", "\n", "import matplotlib.pyplot as plt\n", "\n", - "stateList = ['S', 'I', 'R']\n", - "\n", + "stateList = ['S', 'I', 'R', 'N']\n", "paramList = ['beta', 'gamma', 'B', 'mu']\n", "\n", "odeList = [Transition(origin='S', equation='-beta*S*I + B - mu*S', transition_type=TransitionType.ODE),\n", " Transition(origin='I', equation='beta*S*I - gamma*I - mu*I', transition_type=TransitionType.ODE),\n", - " Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE)]\n", + " Transition(origin='R', equation='gamma*I - mu*R', transition_type=TransitionType.ODE),\n", + " Transition(origin='N', equation='(B - mu)*N', transition_type=TransitionType.ODE)]\n", "\n", - "ode = SimulateOde(stateList, paramList, ode=odeList)\n", - "\n", - "ode2 = ode.get_unrolled_obj()\n", - "ode2.get_transition_matrix()" + "model = SimulateOde(stateList, paramList, ode=odeList)\n" + ] + }, + { + "cell_type": "markdown", + "id": "73ba18bb", + "metadata": {}, + "source": [ + "The transition matrix is empty" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c6fc68a", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_transition_matrix()" + ] + }, + { + "cell_type": "markdown", + "id": "2d52621b", + "metadata": {}, + "source": [ + "Upon calculation, we get:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "738249fa", + "metadata": {}, + "outputs": [], + "source": [ + "model = model.get_unrolled_obj()\n", + "model.get_transition_matrix()" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "1759120d", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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c+fO5fbbb8fLy6vbX8irqqpYuXIln332GU1NTVx11VXMnj2b0NDQM5qK2pU5Zta0t7djNptpb2/ngw8+wGw24+HhIeeSFBQUUFJSIq+V48gJSUpKIjExkR49euDh4XFSEGo2m1m8eDGPPPKInCzr7e1NUFAQkydP5uabb6Zfv35/+h5ZtmwZ7777LmFhYdx7770MGDCgw+rNlwPHTLWqqioefvhhNm3axPLlyxkwYMCfvg9FgCIIwmXF0e1fWlrKkiVL+M9//kO/fv145513iIqK6nY9Jn/m8OHDLF26lJUrVxITE8OiRYtISUlBrVY7u2ln5MRp2I7iYlarVa4Xc+DAAQ4dOsT+/fupqalBoVDg5+dHTEwMvXv3Ji0tjbS0NOLi4s44odlqtbJlyxZGjRqFWq1Gq9UyY8YM5s6dS69evc44wLPb7SxdupT3338fHx8fHn/8cQYMGNBtXvvz5Th3VVVVPPvssyxbtozly5czceLEMxoyFQGKIAiXDce3uT179vDSSy+xdu1a5s+fz9///ne5TsmlqKmpic2bN/PUU09RWlrKBx98wLhx4y7IDKRzdaoF7gBaWlooLi5m79697N69m6ysLPbu3UtNTQ0uLi7ExcWRkpJCnz596N27N3369CE4OPi8coYcJe8DAgJIS0vj5ZdfJj09Ha1We9b7slqtfPPNN7z66quYTCaeffZZJk+e3KVe+wvBEZwcO3aMxx9/nHXr1vH2229z4403nvFxiwBFEITLhtVq5fvvv+eVV16htraWF198kauuugrgkr9YSJJEcXExjz76KN9++y3vv/8+N998c5c5bkmSaGpqYv/+/ezbt4/9+/ezf/9+srOz5Vk1YWFh9OnTh9TUVIYMGcLgwYNPm9dxvsclSRI//PADEydO7FA99lz2I0kSu3bt4uWXX+4QFLu4uHSZ17+zmUwm1q1bx7PPPktdXR0ffvghV1xxxVkdrwhQBEG4LDi629999128vb155plnSE9P7/a5JmfK8fFtMplYuHAhb775Jp988glXX331RR9ysNlsmEwmjh07xs6dO8nIyGDv3r1kZ2djs9kICAggKSmJ3r1707NnT/r06UN8fDze3t4dqvE6LnYX4iLvCCw64zkc+yovL2fJkiW89NJL9OnThw8//JAePXpcckHK/v37ef/991m1ahUpKSm8+OKLJCUl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jBkzmDt3LgaDAVdX10viveDIASkvL2fNmjV88sknWK1WHnzwQW666SZnN++c2O12GhsbOXr0KIcOHZJvubm5tLS04OrqKvecRkVFER8fT69evdDr9XLvquMmvpx0fSJAEc6LJEm0t7djMpnYvHkzq1atYsuWLVgsFoYOHcq1114rF+ly5oeB1WqlqqqKdevW8cUXX7Bp0yYCAgKYPn06N9xwA1FRUbi7u1+2gYqjPL3VapVvbW1tHDp0iN27d7N//3727dtHaWkpVqsVvV5PYmKiXF10yJAhJ61+3NVJkkRjYyPvv/8+ixYtIjExkWeffZa+ffvKiwt2p+M5kdVqpbW1lU2bNrF06VJ27dpFeno6f//73+ndu7ezm9fpTCYTeXl57N+/nz179pCVlUVubi4NDQ2oVCoiIyPp2bMnPXv2JDk5meTkZLln5cSFJrvzOb8UiQBFOGeObzOff/45H330EdnZ2SQkJHDDDTdw9dVXd9kVUSVJIjs7m48++oj//ve/2Gw2pk6dyq233kq/fv3knJdLmSMgcdwsFgs1NTXs3buXjIwMMjIy2L59O21tbQQEBNCrVy969+5Namoq6enp5zxU0xXZbDb27dvH/fffz549e7jllluYN2+ePITUnb5p2+127HY7WVlZvPrqq/zyyy9ER0dz5513ct111+Hp6ensJl40ra2tlJSUkJWVxf79++VKuHV1dahUKnnYNzU1lX79+pGcnExoaKgcpDiSsR068z1w4npV3en9dbGJAEU4a463wZo1a/jb3/5GQUEBw4cP54477mD06NHd6nWuq6tj+fLlfPDBB5SVlTF69GjuvfdeRowYAVwa+Qin+rMtKytj//79ZGZmkpmZyd69eykqKkKpVBIdHc2QIUMYOnQogwYNIjExEY1Gc0m8FqfjuGB8+OGH/O///i91dXVMmTKF2bNnM2DAALnwXFd7DX5/bnft2sXzzz/PmjVriIqKYt68eUydOrXDopCXu7KyMnbs2EFGRgb79u3jwIEDlJeXA6DX6+nVqxcpKSn07duXfv36kZSUdMovLOfzXrBarezfv5/c3FymT58uFl88DRGgCGdFkiRKS0uZM2cO69atY+rUqTzyyCP07t1bzgvoTn9kjgtTQ0MDn332GR9++CGlpaVcc801/OMf/+j2H+yO3pGsrCy2bt3K9u3b2bJlCxUV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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": "\n\n\n\n\n\n\n\n\nS\n\nS\n\n\n\nI\n\nI\n\n\n\nS->I\n\n\nI*S*β\n\n\n\nS*μ\nS*μ\n\n\n\nS->S*μ\n\n\n\n\n\nR\n\nR\n\n\n\nI->R\n\n\nI*γ\n\n\n\nI*μ\nI*μ\n\n\n\nI->I*μ\n\n\n\n\n\nB\nB\n\n\n\nB->S\n\n\n\n\n\n", - "text/plain": [ - "" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], + "source": [ + "#model.get_transition_graph()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14d00308", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import Transition, TransitionType, SimulateOde, common_models\n", + "\n", + "import matplotlib.pyplot as plt\n", + "\n", + "stateList = ['S', 'I', 'R', 'U']\n", + "paramList = ['beta', 'gamma', 'B', 'mu']\n", + "odeList = [Transition(origin='S', equation='-beta*S*I/(S+I+R) + B*(S+I+R) - mu*S', transition_type=TransitionType.ODE),\n", + " Transition(origin='I', equation='beta*S*I/(S+I+R) - gamma*I - mu*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='R', equation='gamma*I - mu*R', transition_type=TransitionType.ODE),\n", + " Transition(origin='U', equation='(mu-B)*(S+I+R)', transition_type=TransitionType.ODE)]\n", + "\n", + "model = SimulateOde(stateList, paramList, ode=odeList)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9d064b4", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_ode_eqn()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65f1a19a", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "model = model.get_unrolled_obj()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ec11e160", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_transition_matrix()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2be9c993", + "metadata": {}, + "outputs": [], "source": [ - "ode2.get_transition_graph()\n" + "model.get_ode_eqn()" ] } ], @@ -121,7 +205,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.15" + "version": "3.12.2" }, "vscode": { "interpreter": { diff --git a/docs/notebooks/unroll/unrollHard.ipynb b/docs/notebooks/unroll/unrollHard.ipynb index f178daa7..68557980 100644 --- a/docs/notebooks/unroll/unrollHard.ipynb +++ b/docs/notebooks/unroll/unrollHard.ipynb @@ -6,31 +6,50 @@ "source": [ "# Hard Problem\n", "\n", - "Now we turn to a harder problem that does not have a one to one mapping\n", - "between all the transitions and the terms in the ODEs. We use the model\n", - "in {doc}`Influenza_SLIARN`, defined by" - ] - }, - { - "cell_type": "markdown", - "id": "2f468e1e", - "metadata": {}, - "source": [ + "Now we turn to a harder problem that does not have a one to one mapping between all the transitions and the terms in the ODEs.\n", + "\n", + "We use a **S**usceptible, **L**atent, **I**nfective, **A**symptomatic and **R**emoved model.\n", + "\n", + "In this model, **S**usceptible individuals may be infected and enter a **L**atent phase after which they are capable of onward transmission as members of the **I**nfective or **A**symptomatic classes. Those in the **A** class have infectivity reduced by a factor $\\delta$ relative to the **I** class. These states are populated by the outflow of **L**atent individuals, where a fraction $p$ proceed to the **I**nfective group and the remainder instead become **A**symptomatic, both at a rate $\\kappa$. All **A**symptomatics eventually become **R**emoved, whereas a fraction, $1-f$, of **I**nfectives go on to die, thus reducing the total living population, **N**.\n", + "\n", + "The equations are as follows:\n", + "\n", + "under mass action $\\beta(N) \\propto N$\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= -\\beta S (I + \\delta A) \\\\ \n", + "\\frac{\\mathrm{d}L}{\\mathrm{d}t} &= \\beta S (I + \\delta A) - \\kappa L \\\\ \n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= p \\kappa L - \\alpha I \\\\\n", + "\\frac{\\mathrm{d}A}{\\mathrm{d}t} &= (1 - p) \\kappa L - \\eta A \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= f \\alpha I + \\eta A \\\\\n", + "\\frac{\\mathrm{d}N}{\\mathrm{d}t} &= -(1 - f) \\alpha I.\n", + "\\end{aligned}$$\n", + "\n", + "where $N+D=N_0$, assuming we start when deaths are zero.\n", + "\n", + "under standard incidence $\\beta(N) = \\text{const}$\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= -\\beta S \\frac{(I + \\delta A)}{N} \\\\ \n", + "\\frac{\\mathrm{d}L}{\\mathrm{d}t} &= \\beta S \\frac{(I + \\delta A)}{N} - \\kappa L \\\\ \n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= p \\kappa L - \\alpha I \\\\\n", + "\\frac{\\mathrm{d}A}{\\mathrm{d}t} &= (1 - p) \\kappa L - \\eta A \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= f \\alpha I + \\eta A \\\\\n", + "\\frac{\\mathrm{d}N}{\\mathrm{d}t} &= -(1 - f) \\alpha I.\n", + "\\end{aligned}$$\n", + "\n", + "We see the difficulty for finding the transitions:\n", + "\n", + "The outflow of state **L**, $\\kappa L$, is composed of two transitions, one to **I** and the other to **A** but the ode of **L** only reflects the total flow going out of the state.\n", + "\n", + "Also confusing things is the fact that the total number of living individuals **N** is not a distinct category, rather $N=S+L+I+A+R$ and thus it doesn't make sense to think of any of our groups flowing into it since they are a subset of it. We must instead identify how the leave the system, in this case **D**ead, so we replace the last equation with:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -S \\beta (I + \\delta A) \\\\ \n", - "\\frac{dL}{dt} &= S \\beta (I + \\delta A) - \\kappa L \\\\ \n", - "\\frac{dI}{dt} &= p \\kappa L - \\alpha I \\\\\n", - "\\frac{dA}{dt} &= (1 - p) \\kappa L - \\eta A \\\\\n", - "\\frac{dR}{dt} &= f \\alpha I + \\eta A \\\\\n", - "\\frac{dN}{dt} &= -(1 - f) \\alpha I.\n", + "\\frac{\\mathrm{d}D}{\\mathrm{d}t} &= (1 - f) \\alpha I.\n", "\\end{aligned}$$\n", + "and substitute N from the above equations\n", + "\n", + "The combination $S+L+I+A+R+D$ is constant, so all the flows on the LHS must add to zero and we have a closed system.\n", "\n", - "The outflow of state **L**, $\\kappa L$, is composed of two transitions,\n", - "one to **I** and the other to **A** but the ode of **L** only reflects\n", - "the total flow going out of the state. The same can be said for state **I**,\n", - "where the flow $\\alpha I$ goes to both **R** and **N**. Graphically, it\n", - "is a rather simple process as shown below." + "TODO: Is this a necessary condition? If so, we could add a quick error message if sum!=0" ] }, { @@ -47,19 +66,6 @@ "}" ] }, - { - "cell_type": "markdown", - "id": "db8a91f0", - "metadata": {}, - "source": [ - "\n", - "We slightly change the model by introducing a new state **D** to convert\n", - "it into a closed system. The combination of state **D** and **N** is a\n", - "constant, the total population. So we can remove **N** and this new\n", - "system consist of six transitions. We define them explicitly as ODEs and\n", - "unroll them into transitions.\n" - ] - }, { "cell_type": "code", "execution_count": 1, @@ -90,19 +96,16 @@ "from pygom import SimulateOde, Transition, TransitionType\n", "\n", "stateList = ['S', 'L', 'I', 'A', 'R', 'D']\n", - "\n", - "paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon', 'N']\n", - "\n", - "odeList = [Transition(origin='S', equation='- beta*S/N*(I + delta*A)', transition_type=TransitionType.ODE), \n", - " Transition(origin='L', equation='beta*S/N*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE),\n", + "paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon']\n", + "odeList = [Transition(origin='S', equation='- beta*S*(I + delta*A)', transition_type=TransitionType.ODE), \n", + " Transition(origin='L', equation='beta*S*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE),\n", " Transition(origin='I', equation='p*kappa*L - alpha*I', transition_type=TransitionType.ODE),\n", - " Transition(origin='A', equation='(1 - p)*kappa* L - epsilon*A', transition_type=TransitionType.ODE),\n", + " Transition(origin='A', equation='(1 - p)*kappa*L - epsilon*A', transition_type=TransitionType.ODE),\n", " Transition(origin='R', equation='f*alpha*I + epsilon*A', transition_type=TransitionType.ODE), \n", " Transition(origin='D', equation='(1 - f)*alpha*I', transition_type=TransitionType.ODE)]\n", - "\n", - "ode = SimulateOde(stateList, paramList, ode=odeList)\n", - "\n", - "ode.get_transition_matrix()" + "model = SimulateOde(stateList, paramList, ode=odeList)\n", + "#model.get_transition_matrix()\n", + "model.get_ode_eqn()" ] }, { @@ -132,9 +135,8 @@ } ], "source": [ - "ode2 = ode.get_unrolled_obj()\n", - "\n", - "ode2.get_transition_matrix()" + "model = model.get_unrolled_obj()\n", + "model.get_transition_matrix()" ] }, { @@ -164,7 +166,70 @@ } ], "source": [ - "ode2.get_ode_eqn()" + "model.get_ode_eqn()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1369c63a", + "metadata": {}, + "outputs": [], + "source": [ + "# Lets see what happens with standard\n", + "\n", + "#stateList = ['S', 'L', 'I', 'A', 'R', 'N']\n", + "#paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon']\n", + "#odeList = [Transition(origin='S', equation='-beta*S/N*(I + delta*A)', transition_type=TransitionType.ODE), \n", + "# Transition(origin='L', equation='beta*S/N*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE),\n", + "# Transition(origin='I', equation='p*kappa*L - alpha*I', transition_type=TransitionType.ODE),\n", + "# Transition(origin='A', equation='(1 - p)*kappa*L - epsilon*A', transition_type=TransitionType.ODE),\n", + "# Transition(origin='R', equation='f*alpha*I + epsilon*A', transition_type=TransitionType.ODE), \n", + "# Transition(origin='N', equation='-(1 - f)*alpha*I', transition_type=TransitionType.ODE)]\n", + "#model = SimulateOde(stateList, paramList, ode=odeList)\n", + "#model.get_transition_matrix()\n", + "\n", + "stateList = ['S', 'L', 'I', 'A', 'R', 'D']\n", + "paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon', 'tot']\n", + "odeList = [Transition(origin='S', equation='- (beta*S/(tot-D))*(I + delta*A)', transition_type=TransitionType.ODE), \n", + " Transition(origin='L', equation='(beta*S/(tot-D))*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE),\n", + " Transition(origin='I', equation='p*kappa*L - alpha*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='A', equation='(1 - p)*kappa*L - epsilon*A', transition_type=TransitionType.ODE),\n", + " Transition(origin='R', equation='f*alpha*I + epsilon*A', transition_type=TransitionType.ODE), \n", + " Transition(origin='D', equation='(1 - f)*alpha*I', transition_type=TransitionType.ODE)]\n", + "model = SimulateOde(stateList, paramList, ode=odeList)\n", + "model.get_transition_matrix()\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21730a6c", + "metadata": {}, + "outputs": [], + "source": [ + "model = model.get_unrolled_obj()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "712c2776", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_transition_matrix()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24e88360", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_ode_eqn()" ] }, { @@ -193,7 +258,98 @@ }, { "data": { - "image/svg+xml": "\n\n\n\n\n\n\n\n\nS\n\nS\n\n\n\nL\n\nL\n\n\n\nS->L\n\n\nA*S*β*δ/N + I*S*β/N\n\n\n\nI\n\nI\n\n\n\nL->I\n\n\nL*κ*p\n\n\n\nA\n\nA\n\n\n\nL->A\n\n\n-L*κ*p + L*κ\n\n\n\nR\n\nR\n\n\n\nI->R\n\n\nI*α*f\n\n\n\nD\n\nD\n\n\n\nI->D\n\n\n-I*α*f + I*α\n\n\n\nA->R\n\n\nA*ε\n\n\n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "S\n", + "\n", + "S\n", + "\n", + "\n", + "\n", + "L\n", + "\n", + "L\n", + "\n", + "\n", + "\n", + "S->L\n", + "\n", + "\n", + "A*S*β*δ/N + I*S*β/N\n", + "\n", + "\n", + "\n", + "I\n", + "\n", + "I\n", + "\n", + "\n", + "\n", + "L->I\n", + "\n", + "\n", + "L*κ*p\n", + "\n", + "\n", + "\n", + "A\n", + "\n", + "A\n", + "\n", + "\n", + "\n", + "L->A\n", + "\n", + "\n", + "-L*κ*p + L*κ\n", + "\n", + "\n", + "\n", + "R\n", + "\n", + "R\n", + "\n", + "\n", + "\n", + "I->R\n", + "\n", + "\n", + "I*α*f\n", + "\n", + "\n", + "\n", + "D\n", + "\n", + "D\n", + "\n", + "\n", + "\n", + "I->D\n", + "\n", + "\n", + "-I*α*f + I*α\n", + "\n", + "\n", + "\n", + "A->R\n", + "\n", + "\n", + "A*ε\n", + "\n", + "\n", + "\n" + ], "text/plain": [ "" ] @@ -204,7 +360,7 @@ } ], "source": [ - "ode2.get_transition_graph()" + "model.get_transition_graph()" ] }, { diff --git a/docs/notebooks/unroll/unrollSimple.ipynb b/docs/notebooks/unroll/unrollSimple.ipynb index 1aa9646b..7d5894d4 100644 --- a/docs/notebooks/unroll/unrollSimple.ipynb +++ b/docs/notebooks/unroll/unrollSimple.ipynb @@ -4,118 +4,229 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# A simple problem\n", + "# Deducing transitions from equations\n", "\n", - "For a simple problem, where we can clearly distinguish the flows from one compartment to another, we consider the SIR model defined by\n", + "Deducing ODEs from transitions is as simple as adding up all the different flows in and out of each state.\n", + "In this process, information is lost regarding the nature (origin and destination) of the constituent transitions and so the reverse problem, deducing transitions from ODEs, is more difficult.\n", + "PyGOM includes some tools to attempt to distinguish the implied flows between compartments given a set of equations, but given that multiple underlying flow configurations can separately explain an ODE system, this functionality should be used with caution.\n", + "Here we demonstrate how this works in practice for two potentially tricky problems, the first of which is a system where the total population count is not conserved and the second is a system where a flow out of some of the compartments is split between multiple destinations.\n", + "\n", + "## SIR with births and deaths\n", + "\n", + "For our first example, let's consider the SIR model with standard incidence mixing and births and deaths proportional to the total population count, but not necessarily balanced:\n", "\n", "$$\\begin{aligned}\n", - "\\frac{dS}{dt} &= -\\beta SI \\\\\n", - "\\frac{dI}{dt} &= \\beta SI - \\gamma I \\\\\n", - "\\frac{dR}{dt} &= \\gamma I.\n", + "\\frac{\\mathrm{d} S}{\\mathrm{d} t} &= -\\frac{\\beta SI}{N} + B N - \\mu S \\\\\n", + "\\frac{\\mathrm{d} I}{\\mathrm{d} t} &= \\frac{\\beta SI}{N} - \\gamma I - \\mu I \\\\\n", + "\\frac{\\mathrm{d} R}{\\mathrm{d} t} &= \\gamma I - \\mu R \\\\\n", + "\\frac{\\mathrm{d} N}{\\mathrm{d} t} &= (B-\\mu)N\n", "\\end{aligned}$$\n", "\n", - "which consists of two transitions" + "Given that the infection rate, $\\frac{\\beta SI}{N}$, depends on the total population, it is necessary to keep track of $N(t)$ in the final equation. \n", + "Here we encounter an issue when thinking in terms of compartments:\n", + "The total number of living individuals, $N$, is not a distinct category, rather, $S$, $I$ and $R$ are a subset of it.\n", + "Thus, whilst valid to define a system of ODEs as we have done above, PyGOM will run into difficulties as it will interpret $N$ as a compartment.\n", + "One solution could be to define $N$ as a time dependent parameter, however PyGOM does not currently have this functionality.\n", + "\n", + "Instead, we must be careful to ensure that we only pass state equations to PyGOM's transition calculating function, {func}`.get_unrolled_obj()`.\n", + "The implication for the current example is that we eliminate the final equation and substitute $N=S+I+R$ everywhere else.\n", + "\n", + "Let's set up the {class}`.SimulateOde` object as usual:" ] }, { - "cell_type": "markdown", - "id": "336381fa", + "cell_type": "code", + "execution_count": null, + "id": "52daed16", "metadata": {}, + "outputs": [], "source": [ + "from pygom import SimulateOde, Transition, TransitionType\n", + "\n", + "odeList = [\n", + " Transition(transition_type=TransitionType.ODE, origin='S', equation='-beta*S*I/(S+I+R) + B*(S+I+R) - mu*S'),\n", + " Transition(transition_type=TransitionType.ODE, origin='I', equation='beta*S*I/(S+I+R) - gamma*I - mu*I'),\n", + " Transition(transition_type=TransitionType.ODE, origin='R', equation='gamma*I - mu*R') \n", + "]\n", + "\n", + "stateList = ['S', 'I', 'R']\n", + "paramList = ['beta', 'gamma', 'B', 'mu']\n", "\n", - "digraph SIR_Model { \n", - "rankdir=LR; size=\"8\" node \\[shape = circle\\]; S -\\> I \\[ label = \"βSI\"\n", - "\\]; I -\\> R \\[ label = \"γI\" \\];\n", - "}" + "model = SimulateOde(state=stateList, param=paramList, ode=odeList)" ] }, { "cell_type": "markdown", - "id": "160f9040", + "id": "d712e654", "metadata": {}, "source": [ - "We can define this as an ODE, as seen in {doc}`sir`." + "If we now inspect the transition matrix:" ] }, { "cell_type": "code", - "execution_count": 1, - "id": "52daed16", + "execution_count": null, + "id": "16280343", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}0 & 0 & 0\\\\0 & 0 & 0\\\\0 & 0 & 0\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[0, 0, 0],\n", - "[0, 0, 0],\n", - "[0, 0, 0]])" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "from pygom import SimulateOde, Transition, TransitionType\n", - "\n", - "ode1 = Transition(origin='S', equation='-beta*S*I', transition_type=TransitionType.ODE)\n", + "model.get_transition_matrix()" + ] + }, + { + "cell_type": "markdown", + "id": "669529c7", + "metadata": {}, + "source": [ + "we see that it is empty.\n", + "This is because {class}`.SimulateOde` was not initialized using transitions, but by ODEs.\n", + "We can populate the transition matrix by calling an algorithm to extract the flow information:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "768a4cd0", + "metadata": {}, + "outputs": [], + "source": [ + "model = model.get_unrolled_obj()" + ] + }, + { + "cell_type": "markdown", + "id": "5e3c78c4", + "metadata": {}, + "source": [ + "and can verify that the calculated transition matrix now matches what we would expect:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5750fc80", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_transition_matrix()" + ] + }, + { + "cell_type": "markdown", + "id": "a373d4c1", + "metadata": {}, + "source": [ + "Birth and death processes are not between states, rather into and out of the system and so do not appear in the transition matrix.\n", + "We could always get around this by defining another class (perhaps **U**nliving) as a limitless reservoir where births may come from and deaths may flow into.\n", + "Alternatively, we can view the birth and death processes by inspecting a graph of the transitions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8251b87f", + "metadata": {}, + "outputs": [], + "source": [ + "model.get_transition_graph();" + ] + }, + { + "cell_type": "markdown", + "id": "98da24d0", + "metadata": {}, + "source": [ + "## SLIAR epidemic model\n", "\n", - "ode2 = Transition(origin='I', equation='beta*S*I - gamma*I', transition_type=TransitionType.ODE)\n", + "Now we turn to a problem that does not have a one to one mapping between all the transitions and the terms in the ODEs.\n", + "In this model, **S**usceptible individuals may be infected and enter a **L**atent phase.\n", + "The rate at which individuals leave this state is $\\kappa$, after which a fraction, $p$, become **I**nfective and the remaining, $(1-p)$, become **A**symptomatic.\n", + "Both these classes are capable of onward transmission, however, those in the **A** class have infectivity reduced by a factor $\\delta$ relative to the **I** class.\n", + "All **A**symptomatics eventually become **R**emoved at a rate $\\eta$, whereas a fraction, $f$, of the infectives recover, the remaining $(1-f)$ going on to die (both at a rate $\\alpha$).\n", "\n", - "ode3 = Transition(origin='R', equation='gamma*I', transition_type=TransitionType.ODE)\n", + "The equations are as follows:\n", "\n", - "stateList = ['S', 'I', 'R']\n", + "$$\\begin{aligned}\n", + "\\frac{\\mathrm{d}S}{\\mathrm{d}t} &= -\\beta S (I + \\delta A) \\\\ \n", + "\\frac{\\mathrm{d}L}{\\mathrm{d}t} &= \\beta S (I + \\delta A) - \\kappa L \\\\ \n", + "\\frac{\\mathrm{d}I}{\\mathrm{d}t} &= p \\kappa L - \\alpha I \\\\\n", + "\\frac{\\mathrm{d}A}{\\mathrm{d}t} &= (1 - p) \\kappa L - \\eta A \\\\\n", + "\\frac{\\mathrm{d}R}{\\mathrm{d}t} &= f \\alpha I + \\eta A \\\\\n", + "\\end{aligned}$$\n", "\n", - "paramList = ['beta', 'gamma']\n", + "In this case, the potential difficulty comes from the outflows of state **L** and **I**.\n", + "For **L**, this is composed of two transitions, one to **I** and the other to **A** but the ODE of **L** only reflects the total flow going out of the state.\n", + "Similarly for **I**, the outflow, $\\alpha I$, is partitioned as $f \\alpha I$ into state **R** with the rest assumed dead, though not explicitly stated in the equations.\n", "\n", - "ode = SimulateOde(stateList, paramList, ode=[ode1, ode2, ode3])\n", + "We set up the {class}`.SimulateOde` object for this case:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "280c4be4", + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import SimulateOde, Transition, TransitionType\n", "\n", - "ode.get_transition_matrix()" + "stateList = ['S', 'L', 'I', 'A', 'R']\n", + "paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'eta']\n", + "odeList = [Transition(origin='S', equation='- beta*S*(I + delta*A)', transition_type=TransitionType.ODE), \n", + " Transition(origin='L', equation='beta*S*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE),\n", + " Transition(origin='I', equation='p*kappa*L - alpha*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='A', equation='(1 - p)*kappa*L - eta*A', transition_type=TransitionType.ODE),\n", + " Transition(origin='R', equation='f*alpha*I + eta*A', transition_type=TransitionType.ODE)]\n", + "model = SimulateOde(stateList, paramList, ode=odeList)" ] }, { "cell_type": "markdown", - "id": "d712e654", + "id": "690b0785", "metadata": {}, "source": [ - "\n", - "and the last line shows that the transition matrix is empty. This is the\n", - "expected result because {class}`.SimulateOdeModel` was not initialized using\n", - "transitions. We can populate the transition matrix by calling an algorithm to extract the flow information, and can see that the output matches that from {ref}`transition:defining-the-equations`." + "Deducing the transitions and inspecting the resulting transition graph:" ] }, { "cell_type": "code", - "execution_count": 2, - "id": "768a4cd0", + "execution_count": null, + "id": "1b6cb187", "metadata": {}, - "outputs": [ - { - "data": { - "text/latex": [ - "$\\displaystyle \\left[\\begin{matrix}0 & I S \\beta & 0\\\\0 & 0 & I \\gamma\\\\0 & 0 & 0\\end{matrix}\\right]$" - ], - "text/plain": [ - "Matrix([\n", - "[0, I*S*beta, 0],\n", - "[0, 0, I*gamma],\n", - "[0, 0, 0]])" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ode = ode.get_unrolled_obj()\n", - "\n", - "ode.get_transition_matrix()" + "outputs": [], + "source": [ + "model = model.get_unrolled_obj()\n", + "model.get_transition_graph();" + ] + }, + { + "cell_type": "markdown", + "id": "00742616", + "metadata": {}, + "source": [ + "We notice that the **L** outflow has been captured, but the outflow from **I** is assumed to be a full death process of which a fraction are born into the recovered state.\n", + "This appearance of an incorrect, but still consistent, configuration demonstrates the difficulty in performing such reverse engineering.\n", + "One work-around is if we explicitly introduce a dead state, $D$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "59ce2a8a", + "metadata": {}, + "outputs": [], + "source": [ + "stateList = ['S', 'L', 'I', 'A', 'R', 'D']\n", + "paramList = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'eta']\n", + "odeList = [Transition(origin='S', equation='- beta*S*(I + delta*A)', transition_type=TransitionType.ODE), \n", + " Transition(origin='L', equation='beta*S*(I + delta*A) - kappa*L', transition_type=TransitionType.ODE),\n", + " Transition(origin='I', equation='p*kappa*L - alpha*I', transition_type=TransitionType.ODE),\n", + " Transition(origin='A', equation='(1 - p)*kappa*L - eta*A', transition_type=TransitionType.ODE),\n", + " Transition(origin='R', equation='f*alpha*I + eta*A', transition_type=TransitionType.ODE),\n", + " Transition(origin='D', equation='(1-f)*alpha*I', transition_type=TransitionType.ODE)]\n", + "model = SimulateOde(stateList, paramList, ode=odeList)\n", + "model = model.get_unrolled_obj()\n", + "model.get_transition_graph();" ] } ], @@ -135,7 +246,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.15" + "version": "3.9.19" }, "vscode": { "interpreter": { diff --git a/notebooks/ABC loss function tests.ipynb b/notebooks/ABC loss function tests.ipynb new file mode 100644 index 00000000..ffc97d43 --- /dev/null +++ b/notebooks/ABC loss function tests.ipynb @@ -0,0 +1,254 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "e847f075-fdaa-4d6e-961c-02aaf1d7c112", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from unittest import main, TestCase\n", + "\n", + "from pygom import SquareLoss, NormalLoss\n", + "from pygom.model import common_models\n", + "from pygom import approximate_bayesian_computation as pgabc" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "533185c5-3671-4499-aba5-4d18f6a13a60", + "metadata": {}, + "outputs": [], + "source": [ + "class Expando: pass\n", + "self = Expando()\n", + "\n", + "## def setUp(self):\n", + "# define the model and parameters\n", + "self.ode = common_models.SIR({'beta':0.5, 'gamma':1.0/3.0})\n", + "\n", + "# the initial state, normalized to one\n", + "self.x0 = [1, 1.27e-6, 0]\n", + "# set the time sequence that we would like to observe\n", + "self.t = np.linspace(0, 150, 100)\n", + "self.ode.initial_values = (self.x0, self.t[0])\n", + "# find the solution\n", + "self.solution = self.ode.integrate(self.t[1::])\n", + "\n", + "# what the posterior median estimates should be close to\n", + "self.target = np.array([0.5, 1.0/3.0])\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ac7a5ac6-ec89-4308-a0ff-fdddf383c62b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + " y = self.solution[1::, 1:3]\n", + " \n", + " # setting the parameters in the inference\n", + " parameters = [pgabc.Parameter('beta', 'unif', 0, 3, logscale=False),\n", + " pgabc.Parameter('gamma', 'unif', 0, 3, logscale=False)]\n", + " \n", + " # creating the loss and abc objects\n", + " sir_obj = pgabc.create_loss(SquareLoss, parameters, self.ode, self.x0, self.t[0],\n", + " self.t[1::], y, ['I', 'R'])\n", + " sir_abc = pgabc.ABC(sir_obj, parameters)\n", + " \n", + " # getting the posterior sample\n", + " sir_abc.get_posterior_sample(N=100, tol=np.inf, G=10, q=0.5)\n", + " sir_abc.continue_posterior_sample(N=100, tol=sir_abc.next_tol, G=10, q=0.5)\n", + "\n", + " # the estimate for beta must be between 0.485 and 0.515\n", + " # the estimate for gamma must be between 0.32 and 0.3466 \n", + " med_est = np.median(sir_abc.res, axis=0)\n", + " \n", + " np.allclose(med_est, self.target, 1e-2, 1e-2)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1badf36a-9a0c-4f09-a69a-84383a188711", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + " # def test_SIR_abc_NormalLoss(self):\n", + " y = self.solution[1::, 1:3]\n", + " parameters = [pgabc.Parameter('beta', 'unif', 0, 3, logscale=False), \n", + " pgabc.Parameter('gamma', 'unif', 0, 3, logscale=False)]\n", + " sir_obj = pgabc.create_loss(NormalLoss, parameters, self.ode, self.x0, self.t[0],\n", + " self.t[1::], y, ['I', 'R'], sigma=1.0)\n", + " sir_abc = pgabc.ABC(sir_obj, parameters)\n", + " sir_abc.get_posterior_sample(N=100, tol=np.inf, G=10, q=0.5)\n", + " sir_abc.continue_posterior_sample(N=100, tol=sir_abc.next_tol, G=10, q=0.5)\n", + " med_est = np.median(sir_abc.res, axis=0)\n", + " np.allclose(med_est, self.target, 1e-2, 1e-2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e3c926e-a194-45e0-aade-7b6593be15e5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9cbf8b2a-5b64-4604-9a9a-fbe766a6ee04", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> \u001b[0;32m/home/phe.gov.uk/thomas.finnie/git/pygom/pygom/loss/ode_loss.py\u001b[0m(59)\u001b[0;36m_setLossType\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 57 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 58 \u001b[0;31m \u001b[0;32mdef\u001b[0m \u001b[0m_setLossType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m---> 59 \u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_lossObj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mNormal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_y\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_weight\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_spread_param\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 60 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_lossObj\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 61 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> u\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> \u001b[0;32m/home/phe.gov.uk/thomas.finnie/git/pygom/pygom/loss/base_loss.py\u001b[0m(191)\u001b[0;36m__init__\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 189 \u001b[0;31m \u001b[0;31m# TODO: optimal weight in terms of Pareto front from a\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 190 \u001b[0;31m \u001b[0;31m# multiobjective optimization perspective\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m--> 191 \u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_lossObj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_setLossType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 192 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 193 \u001b[0;31m \u001b[0;31m# final check\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> state_name\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['I', 'R']\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> spread_param\n", + "ipdb> u\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> \u001b[0;32m/home/phe.gov.uk/thomas.finnie/git/pygom/pygom/loss/ode_loss.py\u001b[0m(43)\u001b[0;36m__init__\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 41 \u001b[0;31m def __init__(self, theta, ode, x0, t0, t, y, state_name, state_weight=None,\n", + "\u001b[0m\u001b[0;32m 42 \u001b[0;31m sigma=1.0, target_param=None, target_state=None):\n", + "\u001b[0m\u001b[0;32m---> 43 \u001b[0;31m super().__init__(theta=theta, \n", + "\u001b[0m\u001b[0;32m 44 \u001b[0;31m \u001b[0mode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mode\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 45 \u001b[0;31m \u001b[0mx0\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mx0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> sigma\n", + "ipdb> u\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> \u001b[0;32m/home/phe.gov.uk/thomas.finnie/git/pygom/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py\u001b[0m(162)\u001b[0;36mcreate_loss\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 160 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 161 \u001b[0;31m \u001b[0;32melif\u001b[0m \u001b[0mloss_type\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mNormalLoss\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m--> 162 \u001b[0;31m return NormalLoss(theta=theta, \n", + "\u001b[0m\u001b[0;32m 163 \u001b[0;31m \u001b[0mode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mode\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 164 \u001b[0;31m \u001b[0mx0\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mx0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> sigma\n", + "ipdb> q\n" + ] + } + ], + "source": [ + "debug" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/debug_tau_leap.ipynb b/notebooks/debug_tau_leap.ipynb new file mode 100644 index 00000000..5ffe59d3 --- /dev/null +++ b/notebooks/debug_tau_leap.ipynb @@ -0,0 +1,512 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this notebook, we debug the `_test_tau_leap_safety` function (old version written in python).\n", + "Fixing this will help to understand and fix the Cython version.\n", + "\n", + "First load the relevant modules:" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import SimulateOde, Transition, TransitionType\n", + "import numpy as np\n", + "import math" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set up PyGOM object. This will be an SIR model with births and deaths:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 0, 0, 1, 0, 0],\n", + " [1, 1, 0, 0, 1, 0],\n", + " [0, 0, 0, 0, 0, 1]])" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "state = ['S', 'I', 'R']\n", + "param_list = ['beta', 'gamma', 'mu', 'N']\n", + "\n", + "transition = [\n", + " Transition(origin='S',\n", + " destination='I',\n", + " equation='beta*S*I/N',\n", + " transition_type=TransitionType.T),\n", + " Transition(origin='I',\n", + " destination='R',\n", + " equation='gamma*I',\n", + " transition_type=TransitionType.T)\n", + "]\n", + "\n", + "birth_death = [\n", + " Transition(origin='S',\n", + " equation='mu*N',\n", + " transition_type=TransitionType.B),\n", + " Transition(origin='S',\n", + " equation='mu*S',\n", + " transition_type=TransitionType.D),\n", + " Transition(origin='I',\n", + " equation='mu*I',\n", + " transition_type=TransitionType.D),\n", + " Transition(origin='R',\n", + " equation='mu*R',\n", + " transition_type=TransitionType.D)\n", + "]\n", + "\n", + "# initialize the model\n", + "ode = SimulateOde(state,\n", + " param_list,\n", + " birth_death=birth_death,\n", + " transition=transition)\n", + "\n", + "#Params\n", + "n_pop=1e4\n", + "param_set=[('beta', 0.4), ('gamma', 0.25), ('mu', 0.01), ('N', n_pop)]\n", + "ode.parameters=param_set\n", + "\n", + "# Initial conditions\n", + "i0=10\n", + "x0 = [n_pop-i0, i0, 0]\n", + "ode.initial_values = (x0, 0)\n", + "\n", + "# Calculate reactant matrix\n", + "ode._computeReactantMatrix()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Define old python version of function here. I've added a few comments in" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "## Python solution\n", + "\n", + "import scipy.stats as st\n", + "\n", + "def _ppois(q, mu=1.0):\n", + " '''\n", + " A cached and slightly faster and less safe version of the pygom.utilR.ppois\n", + " function\n", + " '''\n", + " return st.poisson._cdf(q, mu=mu)\n", + "\n", + "def _test_tau_leap_safety(x, reactant_mat, rates, tau_scale, epsilon):\n", + " \"\"\"\n", + " Additional safety test on :math:`\\\\tau`-leap, decrease the step size if\n", + " the original is not small enough. Decrease a couple of times and then\n", + " bail out because we don't want to spend too long decreasing the\n", + " step size until we find a suitable one.\n", + "\n", + " Parameters\n", + " ----------\n", + " x: array\n", + " Current populations of the states\n", + " reactant_mat: matrix\n", + " reactant_mat[i,j]=1 if state i involved in transition j and 0 if not\n", + " rates: array\n", + " rates of each of the transitions\n", + " tau_scale: float\n", + " initial value for timestep\n", + " epsilon: float\n", + " threshold value\n", + " \"\"\"\n", + "\n", + " total_rate = sum(rates) \n", + " safe = False # when True, indicates that tau_scale is sufficiently small\n", + " count = 0 # number of attempts to find acceptable tau_scale\n", + "\n", + " # Print output, first some titles\n", + " row=[\"Iteration\", \"tau_scale\", \"max_cdf\"]\n", + " print(\"{: <10} {: <10} {: <10}\".format(*row))\n", + "\n", + " while safe is False:\n", + " cdf_val = 1.0\n", + " for i, r in enumerate(rates):\n", + " xi = x[reactant_mat[:, i]] # reactant_mat[i,j]={0,1} so we only ever look at first 2 states. Seems wrong\n", + " mu=tau_scale*r # Expected number of events\n", + " new_cdf = _ppois(xi, mu=mu).min() # prob(# transitions in jump < size of state)\n", + " if new_cdf < cdf_val:\n", + " cdf_val = new_cdf\n", + "\n", + " max_cdf = 1.0 - cdf_val # prob(# transmissions in jump > size of state)\n", + "\n", + " # Print output\n", + " row=[count, tau_scale, max_cdf]\n", + " print(\"{: <10} {: <10.4g} {: <10.4g}\".format(*row))\n", + "\n", + " # cannot allow it to exceed out epsilon\n", + " if max_cdf > epsilon:\n", + " tau_scale /= (max_cdf / epsilon)\n", + " else:\n", + " safe = True\n", + "\n", + " # Abandon if we're taking too many attempts\n", + " if count > 256:\n", + " print(\"count error\")\n", + " return tau_scale, False\n", + " \n", + " # Abandon if tau_scale gets too small?\n", + " if tau_scale*total_rate <= 1.0:\n", + " print(\"scale error\")\n", + " return tau_scale, False\n", + " \n", + " count += 1\n", + "\n", + " return tau_scale, True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We provide the state of the system to prepare the function inputs:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "x=np.array([100., 1., 0.]) # (S=100, I=1, R=0)\n", + "\n", + "reactant_mat=ode._lambdaMat # Reactant_mat[i,j]=1 if state i involved in transition j and 0 if not\n", + "\n", + "# Rates of transitions at current state x and time t\n", + "t=0 # No time dependence, so this is unimportant, just need to give something to function.\n", + "transition_func=ode.transition_vector\n", + "rates = transition_func(x, t)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, there seems to be an issue with the reactant matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1 0 0 1 0 0]\n", + " [1 1 0 0 1 0]\n", + " [0 0 0 0 0 1]]\n" + ] + } + ], + "source": [ + "print(reactant_mat)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This correctly implies that states 0 and 1 ($S$ and $I$) are involved in infections (column 0).\n", + "It then incorrectly implies that only state 1 ($I$) is involved in recovery (column 1) and that no state is involved in births (column 2).\n", + "In the calculation of the reactant matrix, what is actually calculated is if the state appears as a variable in the equations.\n", + "i.e. $S$ and $I$ appear in infection rate $\\frac{\\beta S I}{N}$, but only $I$ appears in recovery rate $\\gamma I$.\n", + "\n", + "The second issue is that in the function `_test_tau_leap_safety`, we try to find the populations, xi, of the states involved in transition, i, via\n", + "\n", + "```{python}\n", + "xi = x[reactant_mat[:, i]]\n", + "```\n", + "\n", + "However, since reactant_mat only takes values 0 and 1, we are mistakenly recycling our binary indicators as state indices.\n", + "For example, let's look at the last transition, i=5, which should be a death rate from the recovereds:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([100., 100., 1.])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x[reactant_mat[:, 5]]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We should just get $[N_R]$.\n", + "Instead, we get $[N_S, N_S, N_I]$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Perhaps we should instead use:\n", + "\n", + "```{python}\n", + "xi = x[reactant_mat[:, i]==1]\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0.])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x[reactant_mat[:, 5]==1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looks better, let's deifne a fixed version of the `_test_tau_leap_safety` function and compare them later:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def _test_tau_leap_safety_fix(x, reactant_mat, rates, tau_scale, epsilon):\n", + " total_rate = sum(rates) \n", + " safe = False # when True, indicates that tau_scale is sufficiently small\n", + " count = 0 # number of attempts to find acceptable tau_scale\n", + "\n", + " # Print output, first some titles\n", + " row=[\"Iteration\", \"tau_scale\", \"max_cdf\"]\n", + " print(\"{: <10} {: <10} {: <10}\".format(*row))\n", + "\n", + " while safe is False:\n", + " cdf_val = 1.0\n", + " for i, r in enumerate(rates):\n", + " xi = x[reactant_mat[:, i]==1] # Population of each state involved in the transitions\n", + " mu=tau_scale*r # Expected number of events\n", + " new_cdf = _ppois(xi, mu=mu).min() # prob(# transitions in jump < size of state)\n", + "\n", + " if new_cdf < cdf_val:\n", + " cdf_val = new_cdf\n", + "\n", + " max_cdf = 1.0 - cdf_val # prob(# transmissions in jump > size of state)\n", + "\n", + " # Print output\n", + " row=[count, tau_scale, max_cdf]\n", + " print(\"{: <10} {: <10.4g} {: <10.4g}\".format(*row))\n", + "\n", + " # cannot allow it to exceed out epsilon\n", + " if max_cdf > epsilon:\n", + " tau_scale /= (max_cdf / epsilon)\n", + " else:\n", + " safe = True\n", + "\n", + " # Abandon if we're taking too many attempts\n", + " if count > 256:\n", + " print(\"count error\")\n", + " return tau_scale, False\n", + " \n", + " # Abandon if tau_scale gets too small?\n", + " if tau_scale*total_rate <= 1.0:\n", + " print(\"scale error\")\n", + " return tau_scale, False\n", + " \n", + " count += 1\n", + "\n", + " return tau_scale, True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We still have the issue that the `reactant_mat` which is input to the `_test_tau_leap_safety` function is not entirely correct.\n", + "For now, let's manually edit it and see the difference:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1 0 1 1 0 0]\n", + " [1 1 0 0 1 0]\n", + " [0 1 0 0 0 1]]\n" + ] + } + ], + "source": [ + "reactant_mat_fix=reactant_mat\n", + "reactant_mat_fix[2, 1]=1 # add the fact that R is involved in recovery\n", + "reactant_mat_fix[0, 2]=1 # add the fact that S is involved in birth\n", + "print(reactant_mat)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need a value of the parameter epsilon, which dictates how stringent we are with the step size.\n", + "There is usually a preliminary calculation to obtain a first guess for `tau_scale`, for now we supply an overly large value so that the function has to do some work." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "epsilon=0.1\n", + "tau_scale=10 # Set a silly high value, which algorithm should iteratively cut down" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's compare the output of each function" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iteration tau_scale max_cdf \n", + "0 10 1 \n", + "1 1 0.4734 \n", + "2 0.2112 0.05144 \n", + "(0.21122098761337782, True)\n", + "\n", + "\n", + "Iteration tau_scale max_cdf \n", + "0 10 1 \n", + "1 1 1 \n", + "2 0.1 0.9995 \n", + "3 0.01 0.2644 \n", + "scale error\n", + "(0.003783681272942391, False)\n" + ] + } + ], + "source": [ + "y1=_test_tau_leap_safety_fix(x.astype(np.float64, copy=False),\n", + " reactant_mat_fix.astype(np.int64, copy=False),\n", + " rates.astype(np.float64, copy=False),\n", + " tau_scale=float(tau_scale),\n", + " epsilon=float(epsilon))\n", + "\n", + "print(y1)\n", + "print(\"\\n\")\n", + "\n", + "y2=_test_tau_leap_safety(x.astype(np.float64, copy=False),\n", + " reactant_mat.astype(np.int64, copy=False),\n", + " rates.astype(np.float64, copy=False),\n", + " tau_scale=float(tau_scale),\n", + " epsilon=float(epsilon))\n", + "\n", + "print(y2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We see that the old version fails due to the \"scale error\", namely\n", + "\n", + "```{python}\n", + "tau_scale*total_rate <= 1.0:\n", + "```\n", + "\n", + "It is worth pointing out that even if it didn't fail, it would not be returning correct values due to errors described above.\n", + "\n", + "The next question is why is this scale error useful?\n", + "Is it that we don't want the step size getting so small that the probability of nothing happening becomes significant. " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pygom/model/_tau_leap.c b/pygom/model/_tau_leap.c deleted file mode 100644 index b6af6e0a..00000000 --- a/pygom/model/_tau_leap.c +++ /dev/null @@ -1,23997 +0,0 @@ -/* Generated by Cython 0.29.33 */ - -#ifndef PY_SSIZE_T_CLEAN -#define PY_SSIZE_T_CLEAN -#endif /* PY_SSIZE_T_CLEAN */ -#include "Python.h" -#ifndef Py_PYTHON_H - #error Python headers needed to compile C extensions, please install development version of Python. -#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) - #error Cython requires Python 2.6+ or Python 3.3+. -#else -#define CYTHON_ABI "0_29_33" -#define CYTHON_HEX_VERSION 0x001D21F0 -#define CYTHON_FUTURE_DIVISION 0 -#include -#ifndef offsetof - #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) -#endif -#if !defined(WIN32) && !defined(MS_WINDOWS) - #ifndef __stdcall - #define __stdcall - #endif - #ifndef __cdecl - #define __cdecl - #endif - #ifndef __fastcall - #define __fastcall - #endif -#endif -#ifndef DL_IMPORT - #define DL_IMPORT(t) t -#endif -#ifndef DL_EXPORT - #define DL_EXPORT(t) t -#endif -#define __PYX_COMMA , -#ifndef HAVE_LONG_LONG - #if PY_VERSION_HEX >= 0x02070000 - #define HAVE_LONG_LONG - #endif -#endif -#ifndef PY_LONG_LONG - #define PY_LONG_LONG LONG_LONG -#endif -#ifndef Py_HUGE_VAL - #define Py_HUGE_VAL HUGE_VAL -#endif -#ifdef PYPY_VERSION - #define CYTHON_COMPILING_IN_PYPY 1 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #define CYTHON_COMPILING_IN_NOGIL 0 - #undef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 0 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #if PY_VERSION_HEX < 0x03050000 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #undef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #undef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 1 - #undef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 0 - #undef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 0 - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 - #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC - #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 - #endif -#elif defined(PYSTON_VERSION) - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 1 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #define CYTHON_COMPILING_IN_NOGIL 0 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 - #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC - #define CYTHON_UPDATE_DESCRIPTOR_DOC 0 - #endif -#elif defined(PY_NOGIL) - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #define CYTHON_COMPILING_IN_NOGIL 1 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #ifndef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #ifndef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 1 - #endif - #ifndef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 1 - #endif - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#else - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 1 - #define CYTHON_COMPILING_IN_NOGIL 0 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) - #define CYTHON_USE_PYTYPE_LOOKUP 1 - #endif - #if PY_MAJOR_VERSION < 3 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #elif !defined(CYTHON_USE_PYLONG_INTERNALS) - #define CYTHON_USE_PYLONG_INTERNALS 1 - #endif - #ifndef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 1 - #endif - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #elif !defined(CYTHON_USE_UNICODE_WRITER) - #define CYTHON_USE_UNICODE_WRITER 1 - #endif - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #if PY_VERSION_HEX >= 0x030B00A4 - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #elif !defined(CYTHON_FAST_THREAD_STATE) - #define CYTHON_FAST_THREAD_STATE 1 - #endif - #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030A0000) - #endif - #ifndef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) - #endif - #ifndef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) - #endif - #ifndef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) - #endif - #if PY_VERSION_HEX >= 0x030B00A4 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 - #elif !defined(CYTHON_USE_EXC_INFO_STACK) - #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) - #endif - #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC - #define CYTHON_UPDATE_DESCRIPTOR_DOC 1 - #endif -#endif -#if !defined(CYTHON_FAST_PYCCALL) -#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) -#endif -#if CYTHON_USE_PYLONG_INTERNALS - #if PY_MAJOR_VERSION < 3 - #include "longintrepr.h" - #endif - #undef SHIFT - #undef BASE - #undef MASK - #ifdef SIZEOF_VOID_P - enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; - #endif -#endif -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif -#ifndef __has_cpp_attribute - #define __has_cpp_attribute(x) 0 -#endif -#ifndef CYTHON_RESTRICT - #if defined(__GNUC__) - #define CYTHON_RESTRICT __restrict__ - #elif defined(_MSC_VER) && _MSC_VER >= 1400 - #define CYTHON_RESTRICT __restrict - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_RESTRICT restrict - #else - #define CYTHON_RESTRICT - #endif -#endif -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -#endif -#ifndef CYTHON_MAYBE_UNUSED_VAR -# if defined(__cplusplus) - template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } -# else -# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) -# endif -#endif -#ifndef CYTHON_NCP_UNUSED -# if CYTHON_COMPILING_IN_CPYTHON -# define CYTHON_NCP_UNUSED -# else -# define CYTHON_NCP_UNUSED CYTHON_UNUSED -# endif -#endif -#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) -#ifdef _MSC_VER - #ifndef _MSC_STDINT_H_ - #if _MSC_VER < 1300 - typedef unsigned char uint8_t; - typedef unsigned int uint32_t; - #else - typedef unsigned __int8 uint8_t; - typedef unsigned __int32 uint32_t; - #endif - #endif -#else - #include -#endif -#ifndef CYTHON_FALLTHROUGH - #if defined(__cplusplus) && __cplusplus >= 201103L - #if __has_cpp_attribute(fallthrough) - #define CYTHON_FALLTHROUGH [[fallthrough]] - #elif __has_cpp_attribute(clang::fallthrough) - #define CYTHON_FALLTHROUGH [[clang::fallthrough]] - #elif __has_cpp_attribute(gnu::fallthrough) - #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] - #endif - #endif - #ifndef CYTHON_FALLTHROUGH - #if __has_attribute(fallthrough) - #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) - #else - #define CYTHON_FALLTHROUGH - #endif - #endif - #if defined(__clang__ ) && defined(__apple_build_version__) - #if __apple_build_version__ < 7000000 - #undef CYTHON_FALLTHROUGH - #define CYTHON_FALLTHROUGH - #endif - #endif -#endif - -#ifndef CYTHON_INLINE - #if defined(__clang__) - #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) - #elif defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_INLINE inline - #else - #define CYTHON_INLINE - #endif -#endif - -#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) - #define Py_OptimizeFlag 0 -#endif -#define __PYX_BUILD_PY_SSIZE_T "n" -#define CYTHON_FORMAT_SSIZE_T "z" -#if PY_MAJOR_VERSION < 3 - #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) - #define __Pyx_DefaultClassType PyClass_Type -#else - #define __Pyx_BUILTIN_MODULE_NAME "builtins" - #define __Pyx_DefaultClassType PyType_Type -#if PY_VERSION_HEX >= 0x030B00A1 - static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f, - PyObject *code, PyObject *c, PyObject* n, PyObject *v, - PyObject *fv, PyObject *cell, PyObject* fn, - PyObject *name, int fline, PyObject *lnos) { - PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL; - PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL; - const char *fn_cstr=NULL; - const char *name_cstr=NULL; - PyCodeObject* co=NULL; - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - if (!(kwds=PyDict_New())) goto end; - if (!(argcount=PyLong_FromLong(a))) goto end; - if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end; - if (!(posonlyargcount=PyLong_FromLong(0))) goto end; - if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end; - if (!(kwonlyargcount=PyLong_FromLong(k))) goto end; - if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end; - if (!(nlocals=PyLong_FromLong(l))) goto end; - if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end; - if (!(stacksize=PyLong_FromLong(s))) goto end; - if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end; - if (!(flags=PyLong_FromLong(f))) goto end; - if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end; - if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end; - if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end; - if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end; - if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end; - if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too; - if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here - if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too; - Py_XDECREF((PyObject*)co); - co = (PyCodeObject*)call_result; - call_result = NULL; - if (0) { - cleanup_code_too: - Py_XDECREF((PyObject*)co); - co = NULL; - } - end: - Py_XDECREF(kwds); - Py_XDECREF(argcount); - Py_XDECREF(posonlyargcount); - Py_XDECREF(kwonlyargcount); - Py_XDECREF(nlocals); - Py_XDECREF(stacksize); - Py_XDECREF(replace); - Py_XDECREF(call_result); - Py_XDECREF(empty); - if (type) { - PyErr_Restore(type, value, traceback); - } - return co; - } -#else - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#endif - #define __Pyx_DefaultClassType PyType_Type -#endif -#ifndef Py_TPFLAGS_CHECKTYPES - #define Py_TPFLAGS_CHECKTYPES 0 -#endif -#ifndef Py_TPFLAGS_HAVE_INDEX - #define Py_TPFLAGS_HAVE_INDEX 0 -#endif -#ifndef Py_TPFLAGS_HAVE_NEWBUFFER - #define Py_TPFLAGS_HAVE_NEWBUFFER 0 -#endif -#ifndef Py_TPFLAGS_HAVE_FINALIZE - #define Py_TPFLAGS_HAVE_FINALIZE 0 -#endif -#ifndef METH_STACKLESS - #define METH_STACKLESS 0 -#endif -#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) - #ifndef METH_FASTCALL - #define METH_FASTCALL 0x80 - #endif - typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); - typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, - Py_ssize_t nargs, PyObject *kwnames); -#else - #define __Pyx_PyCFunctionFast _PyCFunctionFast - #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords -#endif -#if CYTHON_FAST_PYCCALL -#define __Pyx_PyFastCFunction_Check(func)\ - ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) -#else -#define __Pyx_PyFastCFunction_Check(func) 0 -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) - #define PyObject_Malloc(s) PyMem_Malloc(s) - #define PyObject_Free(p) PyMem_Free(p) - #define PyObject_Realloc(p) PyMem_Realloc(p) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 - #define PyMem_RawMalloc(n) PyMem_Malloc(n) - #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) - #define PyMem_RawFree(p) PyMem_Free(p) -#endif -#if CYTHON_COMPILING_IN_PYSTON - #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) -#else - #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) -#endif -#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#elif PY_VERSION_HEX >= 0x03060000 - #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() -#elif PY_VERSION_HEX >= 0x03000000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#else - #define __Pyx_PyThreadState_Current _PyThreadState_Current -#endif -#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) -#include "pythread.h" -#define Py_tss_NEEDS_INIT 0 -typedef int Py_tss_t; -static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { - *key = PyThread_create_key(); - return 0; -} -static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { - Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); - *key = Py_tss_NEEDS_INIT; - return key; -} -static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { - PyObject_Free(key); -} -static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { - return *key != Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { - PyThread_delete_key(*key); - *key = Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { - return PyThread_set_key_value(*key, value); -} -static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { - return PyThread_get_key_value(*key); -} -#endif -#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) -#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) -#else -#define __Pyx_PyDict_NewPresized(n) PyDict_New() -#endif -#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) -#else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS -#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) -#else -#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) -#endif -#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) - #define CYTHON_PEP393_ENABLED 1 - #if PY_VERSION_HEX >= 0x030C0000 - #define __Pyx_PyUnicode_READY(op) (0) - #else - #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ - 0 : _PyUnicode_Ready((PyObject *)(op))) - #endif - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) - #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) - #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) - #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) - #if PY_VERSION_HEX >= 0x030C0000 - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_LENGTH(u)) - #else - #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000 - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length)) - #else - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) - #endif - #endif -#else - #define CYTHON_PEP393_ENABLED 0 - #define PyUnicode_1BYTE_KIND 1 - #define PyUnicode_2BYTE_KIND 2 - #define PyUnicode_4BYTE_KIND 4 - #define __Pyx_PyUnicode_READY(op) (0) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) - #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) - #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) - #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) -#endif -#if CYTHON_COMPILING_IN_PYPY - #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) -#else - #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ - PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) - #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) - #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) - #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) -#endif -#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) -#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) -#else - #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) -#endif -#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) - #define PyObject_ASCII(o) PyObject_Repr(o) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBaseString_Type PyUnicode_Type - #define PyStringObject PyUnicodeObject - #define PyString_Type PyUnicode_Type - #define PyString_Check PyUnicode_Check - #define PyString_CheckExact PyUnicode_CheckExact -#ifndef PyObject_Unicode - #define PyObject_Unicode PyObject_Str -#endif -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) - #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) -#else - #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) - #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) -#endif -#ifndef PySet_CheckExact - #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) -#endif -#if PY_VERSION_HEX >= 0x030900A4 - #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) - #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) -#else - #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) - #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) -#endif -#if CYTHON_ASSUME_SAFE_MACROS - #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) -#else - #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyIntObject PyLongObject - #define PyInt_Type PyLong_Type - #define PyInt_Check(op) PyLong_Check(op) - #define PyInt_CheckExact(op) PyLong_CheckExact(op) - #define PyInt_FromString PyLong_FromString - #define PyInt_FromUnicode PyLong_FromUnicode - #define PyInt_FromLong PyLong_FromLong - #define PyInt_FromSize_t PyLong_FromSize_t - #define PyInt_FromSsize_t PyLong_FromSsize_t - #define PyInt_AsLong PyLong_AsLong - #define PyInt_AS_LONG PyLong_AS_LONG - #define PyInt_AsSsize_t PyLong_AsSsize_t - #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask - #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask - #define PyNumber_Int PyNumber_Long -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBoolObject PyLongObject -#endif -#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY - #ifndef PyUnicode_InternFromString - #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) - #endif -#endif -#if PY_VERSION_HEX < 0x030200A4 - typedef long Py_hash_t; - #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsHash_t -#else - #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t __Pyx_PyIndex_AsSsize_t -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyMethod_New(func, self, klass) ((self) ? ((void)(klass), PyMethod_New(func, self)) : __Pyx_NewRef(func)) -#else - #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) -#endif -#if CYTHON_USE_ASYNC_SLOTS - #if PY_VERSION_HEX >= 0x030500B1 - #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods - #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) - #else - #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) - #endif -#else - #define __Pyx_PyType_AsAsync(obj) NULL -#endif -#ifndef __Pyx_PyAsyncMethodsStruct - typedef struct { - unaryfunc am_await; - unaryfunc am_aiter; - unaryfunc am_anext; - } __Pyx_PyAsyncMethodsStruct; -#endif - -#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS) - #if !defined(_USE_MATH_DEFINES) - #define _USE_MATH_DEFINES - #endif -#endif -#include -#ifdef NAN -#define __PYX_NAN() ((float) NAN) -#else -static CYTHON_INLINE float __PYX_NAN() { - float value; - memset(&value, 0xFF, sizeof(value)); - return value; -} -#endif -#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) -#define __Pyx_truncl trunc -#else -#define __Pyx_truncl truncl -#endif - -#define __PYX_MARK_ERR_POS(f_index, lineno) \ - { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } -#define __PYX_ERR(f_index, lineno, Ln_error) \ - { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -#define __PYX_HAVE__pygom__model___tau_leap -#define __PYX_HAVE_API__pygom__model___tau_leap -/* Early includes */ -#include -#include -#include "numpy/arrayobject.h" -#include "numpy/ndarrayobject.h" -#include "numpy/ndarraytypes.h" -#include "numpy/arrayscalars.h" -#include "numpy/ufuncobject.h" - - /* NumPy API declarations from "numpy/__init__.pxd" */ - -#include -#include "pythread.h" -#include -#include "pystate.h" -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - -#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) -#define CYTHON_WITHOUT_ASSERTIONS -#endif - -typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; - const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; - -#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) -#define __PYX_DEFAULT_STRING_ENCODING "" -#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString -#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#define __Pyx_uchar_cast(c) ((unsigned char)c) -#define __Pyx_long_cast(x) ((long)x) -#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ - (sizeof(type) < sizeof(Py_ssize_t)) ||\ - (sizeof(type) > sizeof(Py_ssize_t) &&\ - likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX) &&\ - (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ - v == (type)PY_SSIZE_T_MIN))) ||\ - (sizeof(type) == sizeof(Py_ssize_t) &&\ - (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX))) ) -static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { - return (size_t) i < (size_t) limit; -} -#if defined (__cplusplus) && __cplusplus >= 201103L - #include - #define __Pyx_sst_abs(value) std::abs(value) -#elif SIZEOF_INT >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) abs(value) -#elif SIZEOF_LONG >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) labs(value) -#elif defined (_MSC_VER) - #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) -#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define __Pyx_sst_abs(value) llabs(value) -#elif defined (__GNUC__) - #define __Pyx_sst_abs(value) __builtin_llabs(value) -#else - #define __Pyx_sst_abs(value) ((value<0) ? -value : value) -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); -#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) -#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) -#define __Pyx_PyBytes_FromString PyBytes_FromString -#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); -#if PY_MAJOR_VERSION < 3 - #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#else - #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize -#endif -#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) -#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) -#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) -#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) -#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) -static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { - const Py_UNICODE *u_end = u; - while (*u_end++) ; - return (size_t)(u_end - u - 1); -} -#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) -#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode -#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode -#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) -#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); -#define __Pyx_PySequence_Tuple(obj)\ - (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*); -#if CYTHON_ASSUME_SAFE_MACROS -#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) -#else -#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) -#endif -#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) -#if PY_MAJOR_VERSION >= 3 -#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) -#else -#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) -#endif -#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII -static int __Pyx_sys_getdefaultencoding_not_ascii; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - PyObject* ascii_chars_u = NULL; - PyObject* ascii_chars_b = NULL; - const char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - if (strcmp(default_encoding_c, "ascii") == 0) { - __Pyx_sys_getdefaultencoding_not_ascii = 0; - } else { - char ascii_chars[128]; - int c; - for (c = 0; c < 128; c++) { - ascii_chars[c] = c; - } - __Pyx_sys_getdefaultencoding_not_ascii = 1; - ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); - if (!ascii_chars_u) goto bad; - ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); - if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { - PyErr_Format( - PyExc_ValueError, - "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", - default_encoding_c); - goto bad; - } - Py_DECREF(ascii_chars_u); - Py_DECREF(ascii_chars_b); - } - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - Py_XDECREF(ascii_chars_u); - Py_XDECREF(ascii_chars_b); - return -1; -} -#endif -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) -#else -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -static char* __PYX_DEFAULT_STRING_ENCODING; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); - if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; - strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - return -1; -} -#endif -#endif - - -/* Test for GCC > 2.95 */ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) - #define likely(x) __builtin_expect(!!(x), 1) - #define unlikely(x) __builtin_expect(!!(x), 0) -#else /* !__GNUC__ or GCC < 2.95 */ - #define likely(x) (x) - #define unlikely(x) (x) -#endif /* __GNUC__ */ -static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } - -static PyObject *__pyx_m = NULL; -static PyObject *__pyx_d; -static PyObject *__pyx_b; -static PyObject *__pyx_cython_runtime = NULL; -static PyObject *__pyx_empty_tuple; -static PyObject *__pyx_empty_bytes; -static PyObject *__pyx_empty_unicode; -static int __pyx_lineno; -static int __pyx_clineno = 0; -static const char * __pyx_cfilenm= __FILE__; -static const char *__pyx_filename; - -/* Header.proto */ -#if !defined(CYTHON_CCOMPLEX) - #if defined(__cplusplus) - #define CYTHON_CCOMPLEX 1 - #elif defined(_Complex_I) - #define CYTHON_CCOMPLEX 1 - #else - #define CYTHON_CCOMPLEX 0 - #endif -#endif -#if CYTHON_CCOMPLEX - #ifdef __cplusplus - #include - #else - #include - #endif -#endif -#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__) - #undef _Complex_I - #define _Complex_I 1.0fj -#endif - - -static const char *__pyx_f[] = { - "pygom/model/_tau_leap.pyx", - "__init__.pxd", - "stringsource", - "type.pxd", -}; -/* BufferFormatStructs.proto */ -#define IS_UNSIGNED(type) (((type) -1) > 0) -struct __Pyx_StructField_; -#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0) -typedef struct { - const char* name; - struct __Pyx_StructField_* fields; - size_t size; - size_t arraysize[8]; - int ndim; - char typegroup; - char is_unsigned; - int flags; -} __Pyx_TypeInfo; -typedef struct __Pyx_StructField_ { - __Pyx_TypeInfo* type; - const char* name; - size_t offset; -} __Pyx_StructField; -typedef struct { - __Pyx_StructField* field; - size_t parent_offset; -} __Pyx_BufFmt_StackElem; -typedef struct { - __Pyx_StructField root; - __Pyx_BufFmt_StackElem* head; - size_t fmt_offset; - size_t new_count, enc_count; - size_t struct_alignment; - int is_complex; - char enc_type; - char new_packmode; - char enc_packmode; - char is_valid_array; -} __Pyx_BufFmt_Context; - -/* MemviewSliceStruct.proto */ -struct __pyx_memoryview_obj; -typedef struct { - struct __pyx_memoryview_obj *memview; - char *data; - Py_ssize_t shape[8]; - Py_ssize_t strides[8]; - Py_ssize_t suboffsets[8]; -} __Pyx_memviewslice; -#define __Pyx_MemoryView_Len(m) (m.shape[0]) - -/* Atomics.proto */ -#include -#ifndef CYTHON_ATOMICS - #define CYTHON_ATOMICS 1 -#endif -#define __PYX_CYTHON_ATOMICS_ENABLED() CYTHON_ATOMICS -#define __pyx_atomic_int_type int -#if CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 &&\ - (__GNUC_MINOR__ > 1 ||\ - (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 2)))) - #define __pyx_atomic_incr_aligned(value) __sync_fetch_and_add(value, 1) - #define __pyx_atomic_decr_aligned(value) __sync_fetch_and_sub(value, 1) - #ifdef __PYX_DEBUG_ATOMICS - #warning "Using GNU atomics" - #endif -#elif CYTHON_ATOMICS && defined(_MSC_VER) && CYTHON_COMPILING_IN_NOGIL - #include - #undef __pyx_atomic_int_type - #define __pyx_atomic_int_type long - #pragma intrinsic (_InterlockedExchangeAdd) - #define __pyx_atomic_incr_aligned(value) _InterlockedExchangeAdd(value, 1) - #define __pyx_atomic_decr_aligned(value) _InterlockedExchangeAdd(value, -1) - #ifdef __PYX_DEBUG_ATOMICS - #pragma message ("Using MSVC atomics") - #endif -#else - #undef CYTHON_ATOMICS - #define CYTHON_ATOMICS 0 - #ifdef __PYX_DEBUG_ATOMICS - #warning "Not using atomics" - #endif -#endif -typedef volatile __pyx_atomic_int_type __pyx_atomic_int; -#if CYTHON_ATOMICS - #define __pyx_add_acquisition_count(memview)\ - __pyx_atomic_incr_aligned(__pyx_get_slice_count_pointer(memview)) - #define __pyx_sub_acquisition_count(memview)\ - __pyx_atomic_decr_aligned(__pyx_get_slice_count_pointer(memview)) -#else - #define __pyx_add_acquisition_count(memview)\ - __pyx_add_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) - #define __pyx_sub_acquisition_count(memview)\ - __pyx_sub_acquisition_count_locked(__pyx_get_slice_count_pointer(memview), memview->lock) -#endif - -/* ForceInitThreads.proto */ -#ifndef __PYX_FORCE_INIT_THREADS - #define __PYX_FORCE_INIT_THREADS 0 -#endif - -/* NoFastGil.proto */ -#define __Pyx_PyGILState_Ensure PyGILState_Ensure -#define __Pyx_PyGILState_Release PyGILState_Release -#define __Pyx_FastGIL_Remember() -#define __Pyx_FastGIL_Forget() -#define __Pyx_FastGilFuncInit() - - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":689 - * # in Cython to enable them only on the right systems. - * - * ctypedef npy_int8 int8_t # <<<<<<<<<<<<<< - * ctypedef npy_int16 int16_t - * ctypedef npy_int32 int32_t - */ -typedef npy_int8 __pyx_t_5numpy_int8_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":690 - * - * ctypedef npy_int8 int8_t - * ctypedef npy_int16 int16_t # <<<<<<<<<<<<<< - * ctypedef npy_int32 int32_t - * ctypedef npy_int64 int64_t - */ -typedef npy_int16 __pyx_t_5numpy_int16_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":691 - * ctypedef npy_int8 int8_t - * ctypedef npy_int16 int16_t - * ctypedef npy_int32 int32_t # <<<<<<<<<<<<<< - * ctypedef npy_int64 int64_t - * #ctypedef npy_int96 int96_t - */ -typedef npy_int32 __pyx_t_5numpy_int32_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":692 - * ctypedef npy_int16 int16_t - * ctypedef npy_int32 int32_t - * ctypedef npy_int64 int64_t # <<<<<<<<<<<<<< - * #ctypedef npy_int96 int96_t - * #ctypedef npy_int128 int128_t - */ -typedef npy_int64 __pyx_t_5numpy_int64_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":696 - * #ctypedef npy_int128 int128_t - * - * ctypedef npy_uint8 uint8_t # <<<<<<<<<<<<<< - * ctypedef npy_uint16 uint16_t - * ctypedef npy_uint32 uint32_t - */ -typedef npy_uint8 __pyx_t_5numpy_uint8_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":697 - * - * ctypedef npy_uint8 uint8_t - * ctypedef npy_uint16 uint16_t # <<<<<<<<<<<<<< - * ctypedef npy_uint32 uint32_t - * ctypedef npy_uint64 uint64_t - */ -typedef npy_uint16 __pyx_t_5numpy_uint16_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":698 - * ctypedef npy_uint8 uint8_t - * ctypedef npy_uint16 uint16_t - * ctypedef npy_uint32 uint32_t # <<<<<<<<<<<<<< - * ctypedef npy_uint64 uint64_t - * #ctypedef npy_uint96 uint96_t - */ -typedef npy_uint32 __pyx_t_5numpy_uint32_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":699 - * ctypedef npy_uint16 uint16_t - * ctypedef npy_uint32 uint32_t - * ctypedef npy_uint64 uint64_t # <<<<<<<<<<<<<< - * #ctypedef npy_uint96 uint96_t - * #ctypedef npy_uint128 uint128_t - */ -typedef npy_uint64 __pyx_t_5numpy_uint64_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":703 - * #ctypedef npy_uint128 uint128_t - * - * ctypedef npy_float32 float32_t # <<<<<<<<<<<<<< - * ctypedef npy_float64 float64_t - * #ctypedef npy_float80 float80_t - */ -typedef npy_float32 __pyx_t_5numpy_float32_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":704 - * - * ctypedef npy_float32 float32_t - * ctypedef npy_float64 float64_t # <<<<<<<<<<<<<< - * #ctypedef npy_float80 float80_t - * #ctypedef npy_float128 float128_t - */ -typedef npy_float64 __pyx_t_5numpy_float64_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":713 - * # The int types are mapped a bit surprising -- - * # numpy.int corresponds to 'l' and numpy.long to 'q' - * ctypedef npy_long int_t # <<<<<<<<<<<<<< - * ctypedef npy_longlong long_t - * ctypedef npy_longlong longlong_t - */ -typedef npy_long __pyx_t_5numpy_int_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":714 - * # numpy.int corresponds to 'l' and numpy.long to 'q' - * ctypedef npy_long int_t - * ctypedef npy_longlong long_t # <<<<<<<<<<<<<< - * ctypedef npy_longlong longlong_t - * - */ -typedef npy_longlong __pyx_t_5numpy_long_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":715 - * ctypedef npy_long int_t - * ctypedef npy_longlong long_t - * ctypedef npy_longlong longlong_t # <<<<<<<<<<<<<< - * - * ctypedef npy_ulong uint_t - */ -typedef npy_longlong __pyx_t_5numpy_longlong_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":717 - * ctypedef npy_longlong longlong_t - * - * ctypedef npy_ulong uint_t # <<<<<<<<<<<<<< - * ctypedef npy_ulonglong ulong_t - * ctypedef npy_ulonglong ulonglong_t - */ -typedef npy_ulong __pyx_t_5numpy_uint_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":718 - * - * ctypedef npy_ulong uint_t - * ctypedef npy_ulonglong ulong_t # <<<<<<<<<<<<<< - * ctypedef npy_ulonglong ulonglong_t - * - */ -typedef npy_ulonglong __pyx_t_5numpy_ulong_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":719 - * ctypedef npy_ulong uint_t - * ctypedef npy_ulonglong ulong_t - * ctypedef npy_ulonglong ulonglong_t # <<<<<<<<<<<<<< - * - * ctypedef npy_intp intp_t - */ -typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":721 - * ctypedef npy_ulonglong ulonglong_t - * - * ctypedef npy_intp intp_t # <<<<<<<<<<<<<< - * ctypedef npy_uintp uintp_t - * - */ -typedef npy_intp __pyx_t_5numpy_intp_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":722 - * - * ctypedef npy_intp intp_t - * ctypedef npy_uintp uintp_t # <<<<<<<<<<<<<< - * - * ctypedef npy_double float_t - */ -typedef npy_uintp __pyx_t_5numpy_uintp_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":724 - * ctypedef npy_uintp uintp_t - * - * ctypedef npy_double float_t # <<<<<<<<<<<<<< - * ctypedef npy_double double_t - * ctypedef npy_longdouble longdouble_t - */ -typedef npy_double __pyx_t_5numpy_float_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":725 - * - * ctypedef npy_double float_t - * ctypedef npy_double double_t # <<<<<<<<<<<<<< - * ctypedef npy_longdouble longdouble_t - * - */ -typedef npy_double __pyx_t_5numpy_double_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":726 - * ctypedef npy_double float_t - * ctypedef npy_double double_t - * ctypedef npy_longdouble longdouble_t # <<<<<<<<<<<<<< - * - * ctypedef npy_cfloat cfloat_t - */ -typedef npy_longdouble __pyx_t_5numpy_longdouble_t; -/* Declarations.proto */ -#if CYTHON_CCOMPLEX - #ifdef __cplusplus - typedef ::std::complex< float > __pyx_t_float_complex; - #else - typedef float _Complex __pyx_t_float_complex; - #endif -#else - typedef struct { float real, imag; } __pyx_t_float_complex; -#endif -static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float); - -/* Declarations.proto */ -#if CYTHON_CCOMPLEX - #ifdef __cplusplus - typedef ::std::complex< double > __pyx_t_double_complex; - #else - typedef double _Complex __pyx_t_double_complex; - #endif -#else - typedef struct { double real, imag; } __pyx_t_double_complex; -#endif -static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double); - - -/*--- Type declarations ---*/ -struct __pyx_array_obj; -struct __pyx_MemviewEnum_obj; -struct __pyx_memoryview_obj; -struct __pyx_memoryviewslice_obj; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":728 - * ctypedef npy_longdouble longdouble_t - * - * ctypedef npy_cfloat cfloat_t # <<<<<<<<<<<<<< - * ctypedef npy_cdouble cdouble_t - * ctypedef npy_clongdouble clongdouble_t - */ -typedef npy_cfloat __pyx_t_5numpy_cfloat_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":729 - * - * ctypedef npy_cfloat cfloat_t - * ctypedef npy_cdouble cdouble_t # <<<<<<<<<<<<<< - * ctypedef npy_clongdouble clongdouble_t - * - */ -typedef npy_cdouble __pyx_t_5numpy_cdouble_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":730 - * ctypedef npy_cfloat cfloat_t - * ctypedef npy_cdouble cdouble_t - * ctypedef npy_clongdouble clongdouble_t # <<<<<<<<<<<<<< - * - * ctypedef npy_cdouble complex_t - */ -typedef npy_clongdouble __pyx_t_5numpy_clongdouble_t; - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":732 - * ctypedef npy_clongdouble clongdouble_t - * - * ctypedef npy_cdouble complex_t # <<<<<<<<<<<<<< - * - * cdef inline object PyArray_MultiIterNew1(a): - */ -typedef npy_cdouble __pyx_t_5numpy_complex_t; -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_jn; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_jn; -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_yn; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_yn; -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_in; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_in; -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_kn; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_kn; - -/* "scipy/special/cython_special.pxd":8 - * double - * - * cpdef number_t spherical_jn(long n, number_t z, bint derivative=*) nogil # <<<<<<<<<<<<<< - * cpdef number_t spherical_yn(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_in(long n, number_t z, bint derivative=*) nogil - */ -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_jn { - int __pyx_n; - int derivative; -}; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_jn { - int __pyx_n; - int derivative; -}; - -/* "scipy/special/cython_special.pxd":9 - * - * cpdef number_t spherical_jn(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_yn(long n, number_t z, bint derivative=*) nogil # <<<<<<<<<<<<<< - * cpdef number_t spherical_in(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_kn(long n, number_t z, bint derivative=*) nogil - */ -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_yn { - int __pyx_n; - int derivative; -}; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_yn { - int __pyx_n; - int derivative; -}; - -/* "scipy/special/cython_special.pxd":10 - * cpdef number_t spherical_jn(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_yn(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_in(long n, number_t z, bint derivative=*) nogil # <<<<<<<<<<<<<< - * cpdef number_t spherical_kn(long n, number_t z, bint derivative=*) nogil - * - */ -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_in { - int __pyx_n; - int derivative; -}; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_in { - int __pyx_n; - int derivative; -}; - -/* "scipy/special/cython_special.pxd":11 - * cpdef number_t spherical_yn(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_in(long n, number_t z, bint derivative=*) nogil - * cpdef number_t spherical_kn(long n, number_t z, bint derivative=*) nogil # <<<<<<<<<<<<<< - * - * ctypedef fused Dd_number_t: - */ -struct __pyx_fuse_0__pyx_opt_args_5scipy_7special_14cython_special_spherical_kn { - int __pyx_n; - int derivative; -}; -struct __pyx_fuse_1__pyx_opt_args_5scipy_7special_14cython_special_spherical_kn { - int __pyx_n; - int derivative; -}; - -/* "View.MemoryView":106 - * - * @cname("__pyx_array") - * cdef class array: # <<<<<<<<<<<<<< - * - * cdef: - */ -struct __pyx_array_obj { - PyObject_HEAD - struct __pyx_vtabstruct_array *__pyx_vtab; - char *data; - Py_ssize_t len; - char *format; - int ndim; - Py_ssize_t *_shape; - Py_ssize_t *_strides; - Py_ssize_t itemsize; - PyObject *mode; - PyObject *_format; - void (*callback_free_data)(void *); - int free_data; - int dtype_is_object; -}; - - -/* "View.MemoryView":280 - * - * @cname('__pyx_MemviewEnum') - * cdef class Enum(object): # <<<<<<<<<<<<<< - * cdef object name - * def __init__(self, name): - */ -struct __pyx_MemviewEnum_obj { - PyObject_HEAD - PyObject *name; -}; - - -/* "View.MemoryView":331 - * - * @cname('__pyx_memoryview') - * cdef class memoryview(object): # <<<<<<<<<<<<<< - * - * cdef object obj - */ -struct __pyx_memoryview_obj { - PyObject_HEAD - struct __pyx_vtabstruct_memoryview *__pyx_vtab; - PyObject *obj; - PyObject *_size; - PyObject *_array_interface; - PyThread_type_lock lock; - __pyx_atomic_int acquisition_count[2]; - __pyx_atomic_int *acquisition_count_aligned_p; - Py_buffer view; - int flags; - int dtype_is_object; - __Pyx_TypeInfo *typeinfo; -}; - - -/* "View.MemoryView":967 - * - * @cname('__pyx_memoryviewslice') - * cdef class _memoryviewslice(memoryview): # <<<<<<<<<<<<<< - * "Internal class for passing memoryview slices to Python" - * - */ -struct __pyx_memoryviewslice_obj { - struct __pyx_memoryview_obj __pyx_base; - __Pyx_memviewslice from_slice; - PyObject *from_object; - PyObject *(*to_object_func)(char *); - int (*to_dtype_func)(char *, PyObject *); -}; - - - -/* "View.MemoryView":106 - * - * @cname("__pyx_array") - * cdef class array: # <<<<<<<<<<<<<< - * - * cdef: - */ - -struct __pyx_vtabstruct_array { - PyObject *(*get_memview)(struct __pyx_array_obj *); -}; -static struct __pyx_vtabstruct_array *__pyx_vtabptr_array; - - -/* "View.MemoryView":331 - * - * @cname('__pyx_memoryview') - * cdef class memoryview(object): # <<<<<<<<<<<<<< - * - * cdef object obj - */ - -struct __pyx_vtabstruct_memoryview { - char *(*get_item_pointer)(struct __pyx_memoryview_obj *, PyObject *); - PyObject *(*is_slice)(struct __pyx_memoryview_obj *, PyObject *); - PyObject *(*setitem_slice_assignment)(struct __pyx_memoryview_obj *, PyObject *, PyObject *); - PyObject *(*setitem_slice_assign_scalar)(struct __pyx_memoryview_obj *, struct __pyx_memoryview_obj *, PyObject *); - PyObject *(*setitem_indexed)(struct __pyx_memoryview_obj *, PyObject *, PyObject *); - PyObject *(*convert_item_to_object)(struct __pyx_memoryview_obj *, char *); - PyObject *(*assign_item_from_object)(struct __pyx_memoryview_obj *, char *, PyObject *); -}; -static struct __pyx_vtabstruct_memoryview *__pyx_vtabptr_memoryview; - - -/* "View.MemoryView":967 - * - * @cname('__pyx_memoryviewslice') - * cdef class _memoryviewslice(memoryview): # <<<<<<<<<<<<<< - * "Internal class for passing memoryview slices to Python" - * - */ - -struct __pyx_vtabstruct__memoryviewslice { - struct __pyx_vtabstruct_memoryview __pyx_base; -}; -static struct __pyx_vtabstruct__memoryviewslice *__pyx_vtabptr__memoryviewslice; - -/* --- Runtime support code (head) --- */ -/* Refnanny.proto */ -#ifndef CYTHON_REFNANNY - #define CYTHON_REFNANNY 0 -#endif -#if CYTHON_REFNANNY - typedef struct { - void (*INCREF)(void*, PyObject*, int); - void (*DECREF)(void*, PyObject*, int); - void (*GOTREF)(void*, PyObject*, int); - void (*GIVEREF)(void*, PyObject*, int); - void* (*SetupContext)(const char*, int, const char*); - void (*FinishContext)(void**); - } __Pyx_RefNannyAPIStruct; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); - #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; -#ifdef WITH_THREAD - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - if (acquire_gil) {\ - PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - PyGILState_Release(__pyx_gilstate_save);\ - } else {\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - } -#else - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) -#endif - #define __Pyx_RefNannyFinishContext()\ - __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) - #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) - #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) -#else - #define __Pyx_RefNannyDeclarations - #define __Pyx_RefNannySetupContext(name, acquire_gil) - #define __Pyx_RefNannyFinishContext() - #define __Pyx_INCREF(r) Py_INCREF(r) - #define __Pyx_DECREF(r) Py_DECREF(r) - #define __Pyx_GOTREF(r) - #define __Pyx_GIVEREF(r) - #define __Pyx_XINCREF(r) Py_XINCREF(r) - #define __Pyx_XDECREF(r) Py_XDECREF(r) - #define __Pyx_XGOTREF(r) - #define __Pyx_XGIVEREF(r) -#endif -#define __Pyx_XDECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_XDECREF(tmp);\ - } while (0) -#define __Pyx_DECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_DECREF(tmp);\ - } while (0) -#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) -#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) - -/* PyObjectGetAttrStr.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) -#endif - -/* GetBuiltinName.proto */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name); - -/* RaiseArgTupleInvalid.proto */ -static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, - Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); - -/* RaiseDoubleKeywords.proto */ -static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); - -/* ParseKeywords.proto */ -static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ - PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ - const char* function_name); - -/* ArgTypeTest.proto */ -#define __Pyx_ArgTypeTest(obj, type, none_allowed, name, exact)\ - ((likely((Py_TYPE(obj) == type) | (none_allowed && (obj == Py_None)))) ? 1 :\ - __Pyx__ArgTypeTest(obj, type, name, exact)) -static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact); - -/* IsLittleEndian.proto */ -static CYTHON_INLINE int __Pyx_Is_Little_Endian(void); - -/* BufferFormatCheck.proto */ -static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts); -static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, - __Pyx_BufFmt_StackElem* stack, - __Pyx_TypeInfo* type); - -/* BufferGetAndValidate.proto */ -#define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\ - ((obj == Py_None || obj == NULL) ?\ - (__Pyx_ZeroBuffer(buf), 0) :\ - __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)) -static int __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj, - __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack); -static void __Pyx_ZeroBuffer(Py_buffer* buf); -static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info); -static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -/* PyDictVersioning.proto */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) -#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ - (version_var) = __PYX_GET_DICT_VERSION(dict);\ - (cache_var) = (value); -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ - (VAR) = __pyx_dict_cached_value;\ - } else {\ - (VAR) = __pyx_dict_cached_value = (LOOKUP);\ - __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ - }\ -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); -#else -#define __PYX_GET_DICT_VERSION(dict) (0) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); -#endif - -/* GetModuleGlobalName.proto */ -#if CYTHON_USE_DICT_VERSIONS -#define __Pyx_GetModuleGlobalName(var, name) do {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ - (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ - __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} while(0) -#define __Pyx_GetModuleGlobalNameUncached(var, name) do {\ - PY_UINT64_T __pyx_dict_version;\ - PyObject *__pyx_dict_cached_value;\ - (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} while(0) -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); -#else -#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) -#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); -#endif - -/* PyCFunctionFastCall.proto */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); -#else -#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) -#endif - -/* PyFunctionFastCall.proto */ -#if CYTHON_FAST_PYCALL -#define __Pyx_PyFunction_FastCall(func, args, nargs)\ - __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); -#else -#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) -#endif -#define __Pyx_BUILD_ASSERT_EXPR(cond)\ - (sizeof(char [1 - 2*!(cond)]) - 1) -#ifndef Py_MEMBER_SIZE -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) -#endif -#if CYTHON_FAST_PYCALL - static size_t __pyx_pyframe_localsplus_offset = 0; - #include "frameobject.h" -#if PY_VERSION_HEX >= 0x030b00a6 - #ifndef Py_BUILD_CORE - #define Py_BUILD_CORE 1 - #endif - #include "internal/pycore_frame.h" -#endif - #define __Pxy_PyFrame_Initialize_Offsets()\ - ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ - (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) - #define __Pyx_PyFrame_GetLocalsplus(frame)\ - (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) -#endif // CYTHON_FAST_PYCALL -#endif - -/* PyObjectCall.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); -#else -#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) -#endif - -/* PyObjectCall2Args.proto */ -static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2); - -/* PyObjectCallMethO.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); -#endif - -/* PyObjectCallOneArg.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); - -/* MemviewSliceInit.proto */ -#define __Pyx_BUF_MAX_NDIMS %(BUF_MAX_NDIMS)d -#define __Pyx_MEMVIEW_DIRECT 1 -#define __Pyx_MEMVIEW_PTR 2 -#define __Pyx_MEMVIEW_FULL 4 -#define __Pyx_MEMVIEW_CONTIG 8 -#define __Pyx_MEMVIEW_STRIDED 16 -#define __Pyx_MEMVIEW_FOLLOW 32 -#define __Pyx_IS_C_CONTIG 1 -#define __Pyx_IS_F_CONTIG 2 -static int __Pyx_init_memviewslice( - struct __pyx_memoryview_obj *memview, - int ndim, - __Pyx_memviewslice *memviewslice, - int memview_is_new_reference); -static CYTHON_INLINE int __pyx_add_acquisition_count_locked( - __pyx_atomic_int *acquisition_count, PyThread_type_lock lock); -static CYTHON_INLINE int __pyx_sub_acquisition_count_locked( - __pyx_atomic_int *acquisition_count, PyThread_type_lock lock); -#define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p) -#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview)) -#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__) -#define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__) -static CYTHON_INLINE void __Pyx_INC_MEMVIEW(__Pyx_memviewslice *, int, int); -static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW(__Pyx_memviewslice *, int, int); - -/* PyThreadStateGet.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; -#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; -#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type -#else -#define __Pyx_PyThreadState_declare -#define __Pyx_PyThreadState_assign -#define __Pyx_PyErr_Occurred() PyErr_Occurred() -#endif - -/* PyErrFetchRestore.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) -#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) -#else -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#endif -#else -#define __Pyx_PyErr_Clear() PyErr_Clear() -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) -#endif - -/* GetTopmostException.proto */ -#if CYTHON_USE_EXC_INFO_STACK -static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate); -#endif - -/* SaveResetException.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_ExceptionSave(type, value, tb) __Pyx__ExceptionSave(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#define __Pyx_ExceptionReset(type, value, tb) __Pyx__ExceptionReset(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); -#else -#define __Pyx_ExceptionSave(type, value, tb) PyErr_GetExcInfo(type, value, tb) -#define __Pyx_ExceptionReset(type, value, tb) PyErr_SetExcInfo(type, value, tb) -#endif - -/* PyErrExceptionMatches.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err) -static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err); -#else -#define __Pyx_PyErr_ExceptionMatches(err) PyErr_ExceptionMatches(err) -#endif - -/* GetException.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_GetException(type, value, tb) __Pyx__GetException(__pyx_tstate, type, value, tb) -static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#else -static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); -#endif - -/* RaiseException.proto */ -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); - -/* IncludeStringH.proto */ -#include - -/* BytesEquals.proto */ -static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals); - -/* UnicodeEquals.proto */ -static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals); - -/* StrEquals.proto */ -#if PY_MAJOR_VERSION >= 3 -#define __Pyx_PyString_Equals __Pyx_PyUnicode_Equals -#else -#define __Pyx_PyString_Equals __Pyx_PyBytes_Equals -#endif - -/* DivInt[Py_ssize_t].proto */ -static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t, Py_ssize_t); - -/* UnaryNegOverflows.proto */ -#define UNARY_NEG_WOULD_OVERFLOW(x)\ - (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x))) - -static CYTHON_UNUSED int __pyx_array_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ -static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *); /*proto*/ -/* GetAttr.proto */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *, PyObject *); - -/* GetItemInt.proto */ -#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ - (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ - __Pyx_GetItemInt_Generic(o, to_py_func(i)))) -#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck); - -/* ObjectGetItem.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); -#else -#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) -#endif - -/* decode_c_string_utf16.proto */ -static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16(const char *s, Py_ssize_t size, const char *errors) { - int byteorder = 0; - return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); -} -static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16LE(const char *s, Py_ssize_t size, const char *errors) { - int byteorder = -1; - return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); -} -static CYTHON_INLINE PyObject *__Pyx_PyUnicode_DecodeUTF16BE(const char *s, Py_ssize_t size, const char *errors) { - int byteorder = 1; - return PyUnicode_DecodeUTF16(s, size, errors, &byteorder); -} - -/* decode_c_string.proto */ -static CYTHON_INLINE PyObject* __Pyx_decode_c_string( - const char* cstring, Py_ssize_t start, Py_ssize_t stop, - const char* encoding, const char* errors, - PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)); - -/* GetAttr3.proto */ -static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); - -/* RaiseTooManyValuesToUnpack.proto */ -static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); - -/* RaiseNeedMoreValuesToUnpack.proto */ -static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); - -/* RaiseNoneIterError.proto */ -static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); - -/* ExtTypeTest.proto */ -static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); - -/* SwapException.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_ExceptionSwap(type, value, tb) __Pyx__ExceptionSwap(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#else -static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb); -#endif - -/* Import.proto */ -static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); - -/* FastTypeChecks.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); -#else -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) -#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) -#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) -#endif -#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) - -static CYTHON_UNUSED int __pyx_memoryview_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ -/* ListCompAppend.proto */ -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) { - PyListObject* L = (PyListObject*) list; - Py_ssize_t len = Py_SIZE(list); - if (likely(L->allocated > len)) { - Py_INCREF(x); - PyList_SET_ITEM(list, len, x); - __Pyx_SET_SIZE(list, len + 1); - return 0; - } - return PyList_Append(list, x); -} -#else -#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x) -#endif - -/* PyIntBinop.proto */ -#if !CYTHON_COMPILING_IN_PYPY -static PyObject* __Pyx_PyInt_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); -#else -#define __Pyx_PyInt_AddObjC(op1, op2, intval, inplace, zerodivision_check)\ - (inplace ? PyNumber_InPlaceAdd(op1, op2) : PyNumber_Add(op1, op2)) -#endif - -/* ListExtend.proto */ -static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) { -#if CYTHON_COMPILING_IN_CPYTHON - PyObject* none = _PyList_Extend((PyListObject*)L, v); - if (unlikely(!none)) - return -1; - Py_DECREF(none); - return 0; -#else - return PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, v); -#endif -} - -/* ListAppend.proto */ -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { - PyListObject* L = (PyListObject*) list; - Py_ssize_t len = Py_SIZE(list); - if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { - Py_INCREF(x); - PyList_SET_ITEM(list, len, x); - __Pyx_SET_SIZE(list, len + 1); - return 0; - } - return PyList_Append(list, x); -} -#else -#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) -#endif - -/* None.proto */ -static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); - -/* DivInt[long].proto */ -static CYTHON_INLINE long __Pyx_div_long(long, long); - -/* PySequenceContains.proto */ -static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) { - int result = PySequence_Contains(seq, item); - return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); -} - -/* ImportFrom.proto */ -static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); - -/* HasAttr.proto */ -static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *); - -/* PyObject_GenericGetAttrNoDict.proto */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GenericGetAttrNoDict PyObject_GenericGetAttr -#endif - -/* PyObject_GenericGetAttr.proto */ -#if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GenericGetAttr PyObject_GenericGetAttr -#endif - -/* SetVTable.proto */ -static int __Pyx_SetVtable(PyObject *dict, void *vtable); - -/* PyObjectGetAttrStrNoError.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name); - -/* SetupReduce.proto */ -static int __Pyx_setup_reduce(PyObject* type_obj); - -/* TypeImport.proto */ -#ifndef __PYX_HAVE_RT_ImportType_proto -#define __PYX_HAVE_RT_ImportType_proto -enum __Pyx_ImportType_CheckSize { - __Pyx_ImportType_CheckSize_Error = 0, - __Pyx_ImportType_CheckSize_Warn = 1, - __Pyx_ImportType_CheckSize_Ignore = 2 -}; -static PyTypeObject *__Pyx_ImportType(PyObject* module, const char *module_name, const char *class_name, size_t size, enum __Pyx_ImportType_CheckSize check_size); -#endif - -/* CLineInTraceback.proto */ -#ifdef CYTHON_CLINE_IN_TRACEBACK -#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) -#else -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); -#endif - -/* CodeObjectCache.proto */ -typedef struct { - PyCodeObject* code_object; - int code_line; -} __Pyx_CodeObjectCacheEntry; -struct __Pyx_CodeObjectCache { - int count; - int max_count; - __Pyx_CodeObjectCacheEntry* entries; -}; -static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); -static PyCodeObject *__pyx_find_code_object(int code_line); -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); - -/* AddTraceback.proto */ -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename); - -#if PY_MAJOR_VERSION < 3 - static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); - static void __Pyx_ReleaseBuffer(Py_buffer *view); -#else - #define __Pyx_GetBuffer PyObject_GetBuffer - #define __Pyx_ReleaseBuffer PyBuffer_Release -#endif - - -/* BufferStructDeclare.proto */ -typedef struct { - Py_ssize_t shape, strides, suboffsets; -} __Pyx_Buf_DimInfo; -typedef struct { - size_t refcount; - Py_buffer pybuffer; -} __Pyx_Buffer; -typedef struct { - __Pyx_Buffer *rcbuffer; - char *data; - __Pyx_Buf_DimInfo diminfo[8]; -} __Pyx_LocalBuf_ND; - -/* MemviewSliceIsContig.proto */ -static int __pyx_memviewslice_is_contig(const __Pyx_memviewslice mvs, char order, int ndim); - -/* OverlappingSlices.proto */ -static int __pyx_slices_overlap(__Pyx_memviewslice *slice1, - __Pyx_memviewslice *slice2, - int ndim, size_t itemsize); - -/* Capsule.proto */ -static CYTHON_INLINE PyObject *__pyx_capsule_create(void *p, const char *sig); - -/* TypeInfoCompare.proto */ -static int __pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b); - -/* MemviewSliceValidateAndInit.proto */ -static int __Pyx_ValidateAndInit_memviewslice( - int *axes_specs, - int c_or_f_flag, - int buf_flags, - int ndim, - __Pyx_TypeInfo *dtype, - __Pyx_BufFmt_StackElem stack[], - __Pyx_memviewslice *memviewslice, - PyObject *original_obj); - -/* ObjectToMemviewSlice.proto */ -static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_double(PyObject *, int writable_flag); - -/* ObjectToMemviewSlice.proto */ -static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5numpy_int64_t(PyObject *, int writable_flag); - -/* GCCDiagnostics.proto */ -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -#define __Pyx_HAS_GCC_DIAGNOSTIC -#endif - -/* RealImag.proto */ -#if CYTHON_CCOMPLEX - #ifdef __cplusplus - #define __Pyx_CREAL(z) ((z).real()) - #define __Pyx_CIMAG(z) ((z).imag()) - #else - #define __Pyx_CREAL(z) (__real__(z)) - #define __Pyx_CIMAG(z) (__imag__(z)) - #endif -#else - #define __Pyx_CREAL(z) ((z).real) - #define __Pyx_CIMAG(z) ((z).imag) -#endif -#if defined(__cplusplus) && CYTHON_CCOMPLEX\ - && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103) - #define __Pyx_SET_CREAL(z,x) ((z).real(x)) - #define __Pyx_SET_CIMAG(z,y) ((z).imag(y)) -#else - #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x) - #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y) -#endif - -/* Arithmetic.proto */ -#if CYTHON_CCOMPLEX - #define __Pyx_c_eq_float(a, b) ((a)==(b)) - #define __Pyx_c_sum_float(a, b) ((a)+(b)) - #define __Pyx_c_diff_float(a, b) ((a)-(b)) - #define __Pyx_c_prod_float(a, b) ((a)*(b)) - #define __Pyx_c_quot_float(a, b) ((a)/(b)) - #define __Pyx_c_neg_float(a) (-(a)) - #ifdef __cplusplus - #define __Pyx_c_is_zero_float(z) ((z)==(float)0) - #define __Pyx_c_conj_float(z) (::std::conj(z)) - #if 1 - #define __Pyx_c_abs_float(z) (::std::abs(z)) - #define __Pyx_c_pow_float(a, b) (::std::pow(a, b)) - #endif - #else - #define __Pyx_c_is_zero_float(z) ((z)==0) - #define __Pyx_c_conj_float(z) (conjf(z)) - #if 1 - #define __Pyx_c_abs_float(z) (cabsf(z)) - #define __Pyx_c_pow_float(a, b) (cpowf(a, b)) - #endif - #endif -#else - static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex); - static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex); - #if 1 - static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex); - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex); - #endif -#endif - -/* Arithmetic.proto */ -#if CYTHON_CCOMPLEX - #define __Pyx_c_eq_double(a, b) ((a)==(b)) - #define __Pyx_c_sum_double(a, b) ((a)+(b)) - #define __Pyx_c_diff_double(a, b) ((a)-(b)) - #define __Pyx_c_prod_double(a, b) ((a)*(b)) - #define __Pyx_c_quot_double(a, b) ((a)/(b)) - #define __Pyx_c_neg_double(a) (-(a)) - #ifdef __cplusplus - #define __Pyx_c_is_zero_double(z) ((z)==(double)0) - #define __Pyx_c_conj_double(z) (::std::conj(z)) - #if 1 - #define __Pyx_c_abs_double(z) (::std::abs(z)) - #define __Pyx_c_pow_double(a, b) (::std::pow(a, b)) - #endif - #else - #define __Pyx_c_is_zero_double(z) ((z)==0) - #define __Pyx_c_conj_double(z) (conj(z)) - #if 1 - #define __Pyx_c_abs_double(z) (cabs(z)) - #define __Pyx_c_pow_double(a, b) (cpow(a, b)) - #endif - #endif -#else - static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex); - static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex); - #if 1 - static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex); - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex); - #endif -#endif - -/* MemviewSliceCopyTemplate.proto */ -static __Pyx_memviewslice -__pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, - const char *mode, int ndim, - size_t sizeof_dtype, int contig_flag, - int dtype_is_object); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_npy_int64(npy_int64 value); - -/* CIntFromPy.proto */ -static CYTHON_INLINE npy_int64 __Pyx_PyInt_As_npy_int64(PyObject *); - -/* CIntFromPy.proto */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); - -/* CIntFromPy.proto */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); - -/* CIntFromPy.proto */ -static CYTHON_INLINE char __Pyx_PyInt_As_char(PyObject *); - -/* CheckBinaryVersion.proto */ -static int __Pyx_check_binary_version(void); - -/* FunctionImport.proto */ -static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); - -/* InitStrings.proto */ -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); - -static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *__pyx_v_self); /* proto*/ -static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index); /* proto*/ -static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj); /* proto*/ -static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_dst, PyObject *__pyx_v_src); /* proto*/ -static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memoryview_obj *__pyx_v_self, struct __pyx_memoryview_obj *__pyx_v_dst, PyObject *__pyx_v_value); /* proto*/ -static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /* proto*/ -static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp); /* proto*/ -static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value); /* proto*/ -static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp); /* proto*/ -static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value); /* proto*/ - -/* Module declarations from 'cpython.buffer' */ - -/* Module declarations from 'libc.string' */ - -/* Module declarations from 'libc.stdio' */ - -/* Module declarations from '__builtin__' */ - -/* Module declarations from 'cpython.type' */ -static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0; - -/* Module declarations from 'cpython' */ - -/* Module declarations from 'cpython.object' */ - -/* Module declarations from 'cpython.ref' */ - -/* Module declarations from 'cpython.mem' */ - -/* Module declarations from 'numpy' */ - -/* Module declarations from 'numpy' */ -static PyTypeObject *__pyx_ptype_5numpy_dtype = 0; -static PyTypeObject *__pyx_ptype_5numpy_flatiter = 0; -static PyTypeObject *__pyx_ptype_5numpy_broadcast = 0; -static PyTypeObject *__pyx_ptype_5numpy_ndarray = 0; -static PyTypeObject *__pyx_ptype_5numpy_generic = 0; -static PyTypeObject *__pyx_ptype_5numpy_number = 0; -static PyTypeObject *__pyx_ptype_5numpy_integer = 0; -static PyTypeObject *__pyx_ptype_5numpy_signedinteger = 0; -static PyTypeObject *__pyx_ptype_5numpy_unsignedinteger = 0; -static PyTypeObject *__pyx_ptype_5numpy_inexact = 0; -static PyTypeObject *__pyx_ptype_5numpy_floating = 0; -static PyTypeObject *__pyx_ptype_5numpy_complexfloating = 0; -static PyTypeObject *__pyx_ptype_5numpy_flexible = 0; -static PyTypeObject *__pyx_ptype_5numpy_character = 0; -static PyTypeObject *__pyx_ptype_5numpy_ufunc = 0; - -/* Module declarations from 'scipy.special.cython_special' */ -static double (*__pyx_f_5scipy_7special_14cython_special_pdtr)(double, double, int __pyx_skip_dispatch); /*proto*/ - -/* Module declarations from 'libc.math' */ - -/* Module declarations from 'cython.view' */ - -/* Module declarations from 'cython' */ - -/* Module declarations from 'pygom.model._tau_leap' */ -static PyTypeObject *__pyx_array_type = 0; -static PyTypeObject *__pyx_MemviewEnum_type = 0; -static PyTypeObject *__pyx_memoryview_type = 0; -static PyTypeObject *__pyx_memoryviewslice_type = 0; -static PyObject *generic = 0; -static PyObject *strided = 0; -static PyObject *indirect = 0; -static PyObject *contiguous = 0; -static PyObject *indirect_contiguous = 0; -static int __pyx_memoryview_thread_locks_used; -static PyThread_type_lock __pyx_memoryview_thread_locks[8]; -static struct __pyx_array_obj *__pyx_array_new(PyObject *, Py_ssize_t, char *, char *, char *); /*proto*/ -static void *__pyx_align_pointer(void *, size_t); /*proto*/ -static PyObject *__pyx_memoryview_new(PyObject *, int, int, __Pyx_TypeInfo *); /*proto*/ -static CYTHON_INLINE int __pyx_memoryview_check(PyObject *); /*proto*/ -static PyObject *_unellipsify(PyObject *, int); /*proto*/ -static PyObject *assert_direct_dimensions(Py_ssize_t *, int); /*proto*/ -static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_obj *, PyObject *); /*proto*/ -static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *, Py_ssize_t, Py_ssize_t, Py_ssize_t, int, int, int *, Py_ssize_t, Py_ssize_t, Py_ssize_t, int, int, int, int); /*proto*/ -static char *__pyx_pybuffer_index(Py_buffer *, char *, Py_ssize_t, Py_ssize_t); /*proto*/ -static int __pyx_memslice_transpose(__Pyx_memviewslice *); /*proto*/ -static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice, int, PyObject *(*)(char *), int (*)(char *, PyObject *), int); /*proto*/ -static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __pyx_memoryview_obj *, __Pyx_memviewslice *); /*proto*/ -static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *, __Pyx_memviewslice *); /*proto*/ -static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *); /*proto*/ -static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview_obj *, __Pyx_memviewslice *); /*proto*/ -static Py_ssize_t abs_py_ssize_t(Py_ssize_t); /*proto*/ -static char __pyx_get_best_slice_order(__Pyx_memviewslice *, int); /*proto*/ -static void _copy_strided_to_strided(char *, Py_ssize_t *, char *, Py_ssize_t *, Py_ssize_t *, Py_ssize_t *, int, size_t); /*proto*/ -static void copy_strided_to_strided(__Pyx_memviewslice *, __Pyx_memviewslice *, int, size_t); /*proto*/ -static Py_ssize_t __pyx_memoryview_slice_get_size(__Pyx_memviewslice *, int); /*proto*/ -static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *, Py_ssize_t *, Py_ssize_t, int, char); /*proto*/ -static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *, __Pyx_memviewslice *, char, int); /*proto*/ -static int __pyx_memoryview_err_extents(int, Py_ssize_t, Py_ssize_t); /*proto*/ -static int __pyx_memoryview_err_dim(PyObject *, char *, int); /*proto*/ -static int __pyx_memoryview_err(PyObject *, char *); /*proto*/ -static int __pyx_memoryview_copy_contents(__Pyx_memviewslice, __Pyx_memviewslice, int, int, int); /*proto*/ -static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *, int, int); /*proto*/ -static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *, int, int, int); /*proto*/ -static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *, Py_ssize_t *, Py_ssize_t *, int, int); /*proto*/ -static void __pyx_memoryview_refcount_objects_in_slice(char *, Py_ssize_t *, Py_ssize_t *, int, int); /*proto*/ -static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *, int, size_t, void *, int); /*proto*/ -static void __pyx_memoryview__slice_assign_scalar(char *, Py_ssize_t *, Py_ssize_t *, int, size_t, void *); /*proto*/ -static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *, PyObject *); /*proto*/ -static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t = { "float64_t", NULL, sizeof(__pyx_t_5numpy_float64_t), { 0 }, 0, 'R', 0, 0 }; -static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int64_t = { "int64_t", NULL, sizeof(__pyx_t_5numpy_int64_t), { 0 }, 0, IS_UNSIGNED(__pyx_t_5numpy_int64_t) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_5numpy_int64_t), 0 }; -static __Pyx_TypeInfo __Pyx_TypeInfo_double = { "double", NULL, sizeof(double), { 0 }, 0, 'R', 0, 0 }; -#define __Pyx_MODULE_NAME "pygom.model._tau_leap" -extern int __pyx_module_is_main_pygom__model___tau_leap; -int __pyx_module_is_main_pygom__model___tau_leap = 0; - -/* Implementation of 'pygom.model._tau_leap' */ -static PyObject *__pyx_builtin_range; -static PyObject *__pyx_builtin_ImportError; -static PyObject *__pyx_builtin_ValueError; -static PyObject *__pyx_builtin_MemoryError; -static PyObject *__pyx_builtin_enumerate; -static PyObject *__pyx_builtin_TypeError; -static PyObject *__pyx_builtin_Ellipsis; -static PyObject *__pyx_builtin_id; -static PyObject *__pyx_builtin_IndexError; -static const char __pyx_k_O[] = "O"; -static const char __pyx_k_c[] = "c"; -static const char __pyx_k_i[] = "i"; -static const char __pyx_k_j[] = "j"; -static const char __pyx_k_x[] = "x"; -static const char __pyx_k_id[] = "id"; -static const char __pyx_k_mu[] = "mu"; -static const char __pyx_k_np[] = "np"; -static const char __pyx_k_new[] = "__new__"; -static const char __pyx_k_obj[] = "obj"; -static const char __pyx_k_sum[] = "sum"; -static const char __pyx_k_base[] = "base"; -static const char __pyx_k_dict[] = "__dict__"; -static const char __pyx_k_main[] = "__main__"; -static const char __pyx_k_mode[] = "mode"; -static const char __pyx_k_name[] = "name"; -static const char __pyx_k_ndim[] = "ndim"; -static const char __pyx_k_pack[] = "pack"; -static const char __pyx_k_safe[] = "safe"; -static const char __pyx_k_size[] = "size"; -static const char __pyx_k_step[] = "step"; -static const char __pyx_k_stop[] = "stop"; -static const char __pyx_k_test[] = "__test__"; -static const char __pyx_k_ASCII[] = "ASCII"; -static const char __pyx_k_class[] = "__class__"; -static const char __pyx_k_count[] = "count"; -static const char __pyx_k_error[] = "error"; -static const char __pyx_k_flags[] = "flags"; -static const char __pyx_k_numpy[] = "numpy"; -static const char __pyx_k_range[] = "range"; -static const char __pyx_k_rates[] = "rates"; -static const char __pyx_k_shape[] = "shape"; -static const char __pyx_k_start[] = "start"; -static const char __pyx_k_encode[] = "encode"; -static const char __pyx_k_format[] = "format"; -static const char __pyx_k_import[] = "__import__"; -static const char __pyx_k_name_2[] = "__name__"; -static const char __pyx_k_pickle[] = "pickle"; -static const char __pyx_k_reduce[] = "__reduce__"; -static const char __pyx_k_struct[] = "struct"; -static const char __pyx_k_unpack[] = "unpack"; -static const char __pyx_k_update[] = "update"; -static const char __pyx_k_x_view[] = "x_view"; -static const char __pyx_k_cdf_val[] = "cdf_val"; -static const char __pyx_k_epsilon[] = "epsilon"; -static const char __pyx_k_fortran[] = "fortran"; -static const char __pyx_k_max_cdf[] = "max_cdf"; -static const char __pyx_k_memview[] = "memview"; -static const char __pyx_k_n_rates[] = "n_rates"; -static const char __pyx_k_new_cdf[] = "new_cdf"; -static const char __pyx_k_Ellipsis[] = "Ellipsis"; -static const char __pyx_k_getstate[] = "__getstate__"; -static const char __pyx_k_itemsize[] = "itemsize"; -static const char __pyx_k_pyx_type[] = "__pyx_type"; -static const char __pyx_k_setstate[] = "__setstate__"; -static const char __pyx_k_TypeError[] = "TypeError"; -static const char __pyx_k_enumerate[] = "enumerate"; -static const char __pyx_k_pyx_state[] = "__pyx_state"; -static const char __pyx_k_reduce_ex[] = "__reduce_ex__"; -static const char __pyx_k_tau_scale[] = "tau_scale"; -static const char __pyx_k_IndexError[] = "IndexError"; -static const char __pyx_k_ValueError[] = "ValueError"; -static const char __pyx_k_pyx_result[] = "__pyx_result"; -static const char __pyx_k_pyx_vtable[] = "__pyx_vtable__"; -static const char __pyx_k_rates_view[] = "rates_view"; -static const char __pyx_k_total_rate[] = "total_rate"; -static const char __pyx_k_ImportError[] = "ImportError"; -static const char __pyx_k_MemoryError[] = "MemoryError"; -static const char __pyx_k_PickleError[] = "PickleError"; -static const char __pyx_k_n_reactants[] = "n_reactants"; -static const char __pyx_k_pyx_checksum[] = "__pyx_checksum"; -static const char __pyx_k_reactant_mat[] = "reactant_mat"; -static const char __pyx_k_stringsource[] = "stringsource"; -static const char __pyx_k_pyx_getbuffer[] = "__pyx_getbuffer"; -static const char __pyx_k_reduce_cython[] = "__reduce_cython__"; -static const char __pyx_k_View_MemoryView[] = "View.MemoryView"; -static const char __pyx_k_allocate_buffer[] = "allocate_buffer"; -static const char __pyx_k_dtype_is_object[] = "dtype_is_object"; -static const char __pyx_k_pyx_PickleError[] = "__pyx_PickleError"; -static const char __pyx_k_setstate_cython[] = "__setstate_cython__"; -static const char __pyx_k_pyx_unpickle_Enum[] = "__pyx_unpickle_Enum"; -static const char __pyx_k_reactant_mat_view[] = "reactant_mat_view"; -static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; -static const char __pyx_k_strided_and_direct[] = ""; -static const char __pyx_k_strided_and_indirect[] = ""; -static const char __pyx_k_contiguous_and_direct[] = ""; -static const char __pyx_k_pygom_model__tau_leap[] = "pygom.model._tau_leap"; -static const char __pyx_k_MemoryView_of_r_object[] = ""; -static const char __pyx_k_MemoryView_of_r_at_0x_x[] = ""; -static const char __pyx_k_contiguous_and_indirect[] = ""; -static const char __pyx_k_cy_test_tau_leap_safety[] = "_cy_test_tau_leap_safety"; -static const char __pyx_k_Cannot_index_with_type_s[] = "Cannot index with type '%s'"; -static const char __pyx_k_Invalid_shape_in_axis_d_d[] = "Invalid shape in axis %d: %d."; -static const char __pyx_k_pygom_model__tau_leap_pyx[] = "pygom/model/_tau_leap.pyx"; -static const char __pyx_k_itemsize_0_for_cython_array[] = "itemsize <= 0 for cython.array"; -static const char __pyx_k_unable_to_allocate_array_data[] = "unable to allocate array data."; -static const char __pyx_k_strided_and_direct_or_indirect[] = ""; -static const char __pyx_k_numpy_core_multiarray_failed_to[] = "numpy.core.multiarray failed to import"; -static const char __pyx_k_Buffer_view_does_not_expose_stri[] = "Buffer view does not expose strides"; -static const char __pyx_k_Can_only_create_a_buffer_that_is[] = "Can only create a buffer that is contiguous in memory."; -static const char __pyx_k_Cannot_assign_to_read_only_memor[] = "Cannot assign to read-only memoryview"; -static const char __pyx_k_Cannot_create_writable_memory_vi[] = "Cannot create writable memory view from read-only memoryview"; -static const char __pyx_k_Empty_shape_tuple_for_cython_arr[] = "Empty shape tuple for cython.array"; -static const char __pyx_k_Incompatible_checksums_0x_x_vs_0[] = "Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))"; -static const char __pyx_k_Indirect_dimensions_not_supporte[] = "Indirect dimensions not supported"; -static const char __pyx_k_Invalid_mode_expected_c_or_fortr[] = "Invalid mode, expected 'c' or 'fortran', got %s"; -static const char __pyx_k_Out_of_bounds_on_buffer_access_a[] = "Out of bounds on buffer access (axis %d)"; -static const char __pyx_k_Unable_to_convert_item_to_object[] = "Unable to convert item to object"; -static const char __pyx_k_got_differing_extents_in_dimensi[] = "got differing extents in dimension %d (got %d and %d)"; -static const char __pyx_k_no_default___reduce___due_to_non[] = "no default __reduce__ due to non-trivial __cinit__"; -static const char __pyx_k_numpy_core_umath_failed_to_impor[] = "numpy.core.umath failed to import"; -static const char __pyx_k_unable_to_allocate_shape_and_str[] = "unable to allocate shape and strides."; -static PyObject *__pyx_n_s_ASCII; -static PyObject *__pyx_kp_s_Buffer_view_does_not_expose_stri; -static PyObject *__pyx_kp_s_Can_only_create_a_buffer_that_is; -static PyObject *__pyx_kp_s_Cannot_assign_to_read_only_memor; -static PyObject *__pyx_kp_s_Cannot_create_writable_memory_vi; -static PyObject *__pyx_kp_s_Cannot_index_with_type_s; -static PyObject *__pyx_n_s_Ellipsis; -static PyObject *__pyx_kp_s_Empty_shape_tuple_for_cython_arr; -static PyObject *__pyx_n_s_ImportError; -static PyObject *__pyx_kp_s_Incompatible_checksums_0x_x_vs_0; -static PyObject *__pyx_n_s_IndexError; -static PyObject *__pyx_kp_s_Indirect_dimensions_not_supporte; -static PyObject *__pyx_kp_s_Invalid_mode_expected_c_or_fortr; -static PyObject *__pyx_kp_s_Invalid_shape_in_axis_d_d; -static PyObject *__pyx_n_s_MemoryError; -static PyObject *__pyx_kp_s_MemoryView_of_r_at_0x_x; -static PyObject *__pyx_kp_s_MemoryView_of_r_object; -static PyObject *__pyx_n_b_O; -static PyObject *__pyx_kp_s_Out_of_bounds_on_buffer_access_a; -static PyObject *__pyx_n_s_PickleError; -static PyObject *__pyx_n_s_TypeError; -static PyObject *__pyx_kp_s_Unable_to_convert_item_to_object; -static PyObject *__pyx_n_s_ValueError; -static PyObject *__pyx_n_s_View_MemoryView; -static PyObject *__pyx_n_s_allocate_buffer; -static PyObject *__pyx_n_s_base; -static PyObject *__pyx_n_s_c; -static PyObject *__pyx_n_u_c; -static PyObject *__pyx_n_s_cdf_val; -static PyObject *__pyx_n_s_class; -static PyObject *__pyx_n_s_cline_in_traceback; -static PyObject *__pyx_kp_s_contiguous_and_direct; -static PyObject *__pyx_kp_s_contiguous_and_indirect; -static PyObject *__pyx_n_s_count; -static PyObject *__pyx_n_s_cy_test_tau_leap_safety; -static PyObject *__pyx_n_s_dict; -static PyObject *__pyx_n_s_dtype_is_object; -static PyObject *__pyx_n_s_encode; -static PyObject *__pyx_n_s_enumerate; -static PyObject *__pyx_n_s_epsilon; -static PyObject *__pyx_n_s_error; -static PyObject *__pyx_n_s_flags; -static PyObject *__pyx_n_s_format; -static PyObject *__pyx_n_s_fortran; -static PyObject *__pyx_n_u_fortran; -static PyObject *__pyx_n_s_getstate; -static PyObject *__pyx_kp_s_got_differing_extents_in_dimensi; -static PyObject *__pyx_n_s_i; -static PyObject *__pyx_n_s_id; -static PyObject *__pyx_n_s_import; -static PyObject *__pyx_n_s_itemsize; -static PyObject *__pyx_kp_s_itemsize_0_for_cython_array; -static PyObject *__pyx_n_s_j; -static PyObject *__pyx_n_s_main; -static PyObject *__pyx_n_s_max_cdf; -static PyObject *__pyx_n_s_memview; -static PyObject *__pyx_n_s_mode; -static PyObject *__pyx_n_s_mu; -static PyObject *__pyx_n_s_n_rates; -static PyObject *__pyx_n_s_n_reactants; -static PyObject *__pyx_n_s_name; -static PyObject *__pyx_n_s_name_2; -static PyObject *__pyx_n_s_ndim; -static PyObject *__pyx_n_s_new; -static PyObject *__pyx_n_s_new_cdf; -static PyObject *__pyx_kp_s_no_default___reduce___due_to_non; -static PyObject *__pyx_n_s_np; -static PyObject *__pyx_n_s_numpy; -static PyObject *__pyx_kp_s_numpy_core_multiarray_failed_to; -static PyObject *__pyx_kp_s_numpy_core_umath_failed_to_impor; -static PyObject *__pyx_n_s_obj; -static PyObject *__pyx_n_s_pack; -static PyObject *__pyx_n_s_pickle; -static PyObject *__pyx_n_s_pygom_model__tau_leap; -static PyObject *__pyx_kp_s_pygom_model__tau_leap_pyx; -static PyObject *__pyx_n_s_pyx_PickleError; -static PyObject *__pyx_n_s_pyx_checksum; -static PyObject *__pyx_n_s_pyx_getbuffer; -static PyObject *__pyx_n_s_pyx_result; -static PyObject *__pyx_n_s_pyx_state; -static PyObject *__pyx_n_s_pyx_type; -static PyObject *__pyx_n_s_pyx_unpickle_Enum; -static PyObject *__pyx_n_s_pyx_vtable; -static PyObject *__pyx_n_s_range; -static PyObject *__pyx_n_s_rates; -static PyObject *__pyx_n_s_rates_view; -static PyObject *__pyx_n_s_reactant_mat; -static PyObject *__pyx_n_s_reactant_mat_view; -static PyObject *__pyx_n_s_reduce; -static PyObject *__pyx_n_s_reduce_cython; -static PyObject *__pyx_n_s_reduce_ex; -static PyObject *__pyx_n_s_safe; -static PyObject *__pyx_n_s_setstate; -static PyObject *__pyx_n_s_setstate_cython; -static PyObject *__pyx_n_s_shape; -static PyObject *__pyx_n_s_size; -static PyObject *__pyx_n_s_start; -static PyObject *__pyx_n_s_step; -static PyObject *__pyx_n_s_stop; -static PyObject *__pyx_kp_s_strided_and_direct; -static PyObject *__pyx_kp_s_strided_and_direct_or_indirect; -static PyObject *__pyx_kp_s_strided_and_indirect; -static PyObject *__pyx_kp_s_stringsource; -static PyObject *__pyx_n_s_struct; -static PyObject *__pyx_n_s_sum; -static PyObject *__pyx_n_s_tau_scale; -static PyObject *__pyx_n_s_test; -static PyObject *__pyx_n_s_total_rate; -static PyObject *__pyx_kp_s_unable_to_allocate_array_data; -static PyObject *__pyx_kp_s_unable_to_allocate_shape_and_str; -static PyObject *__pyx_n_s_unpack; -static PyObject *__pyx_n_s_update; -static PyObject *__pyx_n_s_x; -static PyObject *__pyx_n_s_x_view; -static PyObject *__pyx_pf_5pygom_5model_9_tau_leap__cy_test_tau_leap_safety(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_x, PyArrayObject *__pyx_v_reactant_mat, PyArrayObject *__pyx_v_rates, double __pyx_v_tau_scale, double __pyx_v_epsilon); /* proto */ -static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, PyObject *__pyx_v_format, PyObject *__pyx_v_mode, int __pyx_v_allocate_buffer); /* proto */ -static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(struct __pyx_array_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ -static void __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(struct __pyx_array_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_5array_7memview___get__(struct __pyx_array_obj *__pyx_v_self); /* proto */ -static Py_ssize_t __pyx_array___pyx_pf_15View_dot_MemoryView_5array_6__len__(struct __pyx_array_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_attr); /* proto */ -static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item); /* proto */ -static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value); /* proto */ -static PyObject *__pyx_pf___pyx_array___reduce_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_array_2__setstate_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ -static int __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum___init__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v_name); /* proto */ -static PyObject *__pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum_2__repr__(struct __pyx_MemviewEnum_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_MemviewEnum___reduce_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_MemviewEnum_2__setstate_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */ -static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj, int __pyx_v_flags, int __pyx_v_dtype_is_object); /* proto */ -static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__dealloc__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4__getitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index); /* proto */ -static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /* proto */ -static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbuffer__(struct __pyx_memoryview_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_10__len__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12__repr__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14__str__(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16is_c_contig(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18is_f_contig(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20copy(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22copy_fortran(struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_memoryview___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_memoryview_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ -static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewslice___dealloc__(struct __pyx_memoryviewslice_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView_16_memoryviewslice_4base___get__(struct __pyx_memoryviewslice_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_memoryviewslice___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self); /* proto */ -static PyObject *__pyx_pf___pyx_memoryviewslice_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */ -static PyObject *__pyx_tp_new_array(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static PyObject *__pyx_tp_new_Enum(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static PyObject *__pyx_tp_new_memoryview(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static PyObject *__pyx_tp_new__memoryviewslice(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/ -static PyObject *__pyx_int_0; -static PyObject *__pyx_int_1; -static PyObject *__pyx_int_112105877; -static PyObject *__pyx_int_136983863; -static PyObject *__pyx_int_184977713; -static PyObject *__pyx_int_neg_1; -static PyObject *__pyx_tuple_; -static PyObject *__pyx_tuple__2; -static PyObject *__pyx_tuple__3; -static PyObject *__pyx_tuple__4; -static PyObject *__pyx_tuple__5; -static PyObject *__pyx_tuple__6; -static PyObject *__pyx_tuple__7; -static PyObject *__pyx_tuple__8; -static PyObject *__pyx_tuple__9; -static PyObject *__pyx_slice__17; -static PyObject *__pyx_tuple__10; -static PyObject *__pyx_tuple__11; -static PyObject *__pyx_tuple__12; -static PyObject *__pyx_tuple__13; -static PyObject *__pyx_tuple__14; -static PyObject *__pyx_tuple__15; -static PyObject *__pyx_tuple__16; -static PyObject *__pyx_tuple__18; -static PyObject *__pyx_tuple__19; -static PyObject *__pyx_tuple__20; -static PyObject *__pyx_tuple__21; -static PyObject *__pyx_tuple__22; -static PyObject *__pyx_tuple__24; -static PyObject *__pyx_tuple__25; -static PyObject *__pyx_tuple__26; -static PyObject *__pyx_tuple__27; -static PyObject *__pyx_tuple__28; -static PyObject *__pyx_tuple__29; -static PyObject *__pyx_codeobj__23; -static PyObject *__pyx_codeobj__30; -/* Late includes */ - -/* "pygom/model/_tau_leap.pyx":11 - * @cython.wraparound(False) # Deactivate negative indexing. - * @cython.cdivision(True) # Deactivate the div 0 error checking - * def _cy_test_tau_leap_safety(np.ndarray[np.float64_t] x, # <<<<<<<<<<<<<< - * np.ndarray[np.int64_t, ndim=2] reactant_mat, - * np.ndarray[np.float64_t] rates, - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_5pygom_5model_9_tau_leap_1_cy_test_tau_leap_safety(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_5pygom_5model_9_tau_leap__cy_test_tau_leap_safety[] = "\n Additional safety test on :math:`\\tau`-leap, decrease the step size if\n the original is not small enough. Decrease a couple of times and then\n bail out because we don't want to spend too long decreasing the\n step size until we find a suitable one.\n "; -static PyMethodDef __pyx_mdef_5pygom_5model_9_tau_leap_1_cy_test_tau_leap_safety = {"_cy_test_tau_leap_safety", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_5pygom_5model_9_tau_leap_1_cy_test_tau_leap_safety, METH_VARARGS|METH_KEYWORDS, __pyx_doc_5pygom_5model_9_tau_leap__cy_test_tau_leap_safety}; -static PyObject *__pyx_pw_5pygom_5model_9_tau_leap_1_cy_test_tau_leap_safety(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyArrayObject *__pyx_v_x = 0; - PyArrayObject *__pyx_v_reactant_mat = 0; - PyArrayObject *__pyx_v_rates = 0; - double __pyx_v_tau_scale; - double __pyx_v_epsilon; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("_cy_test_tau_leap_safety (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_x,&__pyx_n_s_reactant_mat,&__pyx_n_s_rates,&__pyx_n_s_tau_scale,&__pyx_n_s_epsilon,0}; - PyObject* values[5] = {0,0,0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - CYTHON_FALLTHROUGH; - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - CYTHON_FALLTHROUGH; - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_x)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_reactant_mat)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_cy_test_tau_leap_safety", 1, 5, 5, 1); __PYX_ERR(0, 11, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rates)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_cy_test_tau_leap_safety", 1, 5, 5, 2); __PYX_ERR(0, 11, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 3: - if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_tau_scale)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_cy_test_tau_leap_safety", 1, 5, 5, 3); __PYX_ERR(0, 11, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 4: - if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_epsilon)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_cy_test_tau_leap_safety", 1, 5, 5, 4); __PYX_ERR(0, 11, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_cy_test_tau_leap_safety") < 0)) __PYX_ERR(0, 11, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 5) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - } - __pyx_v_x = ((PyArrayObject *)values[0]); - __pyx_v_reactant_mat = ((PyArrayObject *)values[1]); - __pyx_v_rates = ((PyArrayObject *)values[2]); - __pyx_v_tau_scale = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_tau_scale == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 14, __pyx_L3_error) - __pyx_v_epsilon = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_epsilon == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 15, __pyx_L3_error) - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("_cy_test_tau_leap_safety", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 11, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("pygom.model._tau_leap._cy_test_tau_leap_safety", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_x), __pyx_ptype_5numpy_ndarray, 1, "x", 0))) __PYX_ERR(0, 11, __pyx_L1_error) - if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_reactant_mat), __pyx_ptype_5numpy_ndarray, 1, "reactant_mat", 0))) __PYX_ERR(0, 12, __pyx_L1_error) - if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_rates), __pyx_ptype_5numpy_ndarray, 1, "rates", 0))) __PYX_ERR(0, 13, __pyx_L1_error) - __pyx_r = __pyx_pf_5pygom_5model_9_tau_leap__cy_test_tau_leap_safety(__pyx_self, __pyx_v_x, __pyx_v_reactant_mat, __pyx_v_rates, __pyx_v_tau_scale, __pyx_v_epsilon); - - /* function exit code */ - goto __pyx_L0; - __pyx_L1_error:; - __pyx_r = NULL; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_5pygom_5model_9_tau_leap__cy_test_tau_leap_safety(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_x, PyArrayObject *__pyx_v_reactant_mat, PyArrayObject *__pyx_v_rates, double __pyx_v_tau_scale, double __pyx_v_epsilon) { - __Pyx_memviewslice __pyx_v_rates_view = { 0, 0, { 0 }, { 0 }, { 0 } }; - __pyx_t_5numpy_int64_t __pyx_v_n_rates; - __Pyx_memviewslice __pyx_v_x_view = { 0, 0, { 0 }, { 0 }, { 0 } }; - __Pyx_memviewslice __pyx_v_reactant_mat_view = { 0, 0, { 0 }, { 0 }, { 0 } }; - __pyx_t_5numpy_int64_t __pyx_v_n_reactants; - double __pyx_v_mu; - double __pyx_v_max_cdf; - double __pyx_v_new_cdf; - double __pyx_v_total_rate; - int __pyx_v_safe; - int __pyx_v_count; - double __pyx_v_cdf_val; - __pyx_t_5numpy_int64_t __pyx_v_i; - __pyx_t_5numpy_int64_t __pyx_v_j; - __Pyx_LocalBuf_ND __pyx_pybuffernd_rates; - __Pyx_Buffer __pyx_pybuffer_rates; - __Pyx_LocalBuf_ND __pyx_pybuffernd_reactant_mat; - __Pyx_Buffer __pyx_pybuffer_reactant_mat; - __Pyx_LocalBuf_ND __pyx_pybuffernd_x; - __Pyx_Buffer __pyx_pybuffer_x; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice __pyx_t_1 = { 0, 0, { 0 }, { 0 }, { 0 } }; - __Pyx_memviewslice __pyx_t_2 = { 0, 0, { 0 }, { 0 }, { 0 } }; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - double __pyx_t_6; - int __pyx_t_7; - __pyx_t_5numpy_int64_t __pyx_t_8; - __pyx_t_5numpy_int64_t __pyx_t_9; - __pyx_t_5numpy_int64_t __pyx_t_10; - __pyx_t_5numpy_int64_t __pyx_t_11; - __pyx_t_5numpy_int64_t __pyx_t_12; - __pyx_t_5numpy_int64_t __pyx_t_13; - __pyx_t_5numpy_int64_t __pyx_t_14; - __pyx_t_5numpy_int64_t __pyx_t_15; - int __pyx_t_16; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_cy_test_tau_leap_safety", 0); - __pyx_pybuffer_x.pybuffer.buf = NULL; - __pyx_pybuffer_x.refcount = 0; - __pyx_pybuffernd_x.data = NULL; - __pyx_pybuffernd_x.rcbuffer = &__pyx_pybuffer_x; - __pyx_pybuffer_reactant_mat.pybuffer.buf = NULL; - __pyx_pybuffer_reactant_mat.refcount = 0; - __pyx_pybuffernd_reactant_mat.data = NULL; - __pyx_pybuffernd_reactant_mat.rcbuffer = &__pyx_pybuffer_reactant_mat; - __pyx_pybuffer_rates.pybuffer.buf = NULL; - __pyx_pybuffer_rates.refcount = 0; - __pyx_pybuffernd_rates.data = NULL; - __pyx_pybuffernd_rates.rcbuffer = &__pyx_pybuffer_rates; - { - __Pyx_BufFmt_StackElem __pyx_stack[1]; - if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_x.rcbuffer->pybuffer, (PyObject*)__pyx_v_x, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 11, __pyx_L1_error) - } - __pyx_pybuffernd_x.diminfo[0].strides = __pyx_pybuffernd_x.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_x.diminfo[0].shape = __pyx_pybuffernd_x.rcbuffer->pybuffer.shape[0]; - { - __Pyx_BufFmt_StackElem __pyx_stack[1]; - if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer, (PyObject*)__pyx_v_reactant_mat, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int64_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) __PYX_ERR(0, 11, __pyx_L1_error) - } - __pyx_pybuffernd_reactant_mat.diminfo[0].strides = __pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_reactant_mat.diminfo[0].shape = __pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_reactant_mat.diminfo[1].strides = __pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_reactant_mat.diminfo[1].shape = __pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer.shape[1]; - { - __Pyx_BufFmt_StackElem __pyx_stack[1]; - if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_rates.rcbuffer->pybuffer, (PyObject*)__pyx_v_rates, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) __PYX_ERR(0, 11, __pyx_L1_error) - } - __pyx_pybuffernd_rates.diminfo[0].strides = __pyx_pybuffernd_rates.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_rates.diminfo[0].shape = __pyx_pybuffernd_rates.rcbuffer->pybuffer.shape[0]; - - /* "pygom/model/_tau_leap.pyx":23 - * """ - * #view on arrays - * cdef double[:] rates_view = rates # <<<<<<<<<<<<<< - * cdef np.int64_t n_rates = rates.shape[0] - * cdef double[:] x_view = x - */ - __pyx_t_1 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_rates), PyBUF_WRITABLE); if (unlikely(!__pyx_t_1.memview)) __PYX_ERR(0, 23, __pyx_L1_error) - __pyx_v_rates_view = __pyx_t_1; - __pyx_t_1.memview = NULL; - __pyx_t_1.data = NULL; - - /* "pygom/model/_tau_leap.pyx":24 - * #view on arrays - * cdef double[:] rates_view = rates - * cdef np.int64_t n_rates = rates.shape[0] # <<<<<<<<<<<<<< - * cdef double[:] x_view = x - * cdef np.int64_t[:, :] reactant_mat_view = reactant_mat - */ - __pyx_v_n_rates = (__pyx_v_rates->dimensions[0]); - - /* "pygom/model/_tau_leap.pyx":25 - * cdef double[:] rates_view = rates - * cdef np.int64_t n_rates = rates.shape[0] - * cdef double[:] x_view = x # <<<<<<<<<<<<<< - * cdef np.int64_t[:, :] reactant_mat_view = reactant_mat - * cdef np.int64_t n_reactants = reactant_mat.shape[0] - */ - __pyx_t_1 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_x), PyBUF_WRITABLE); if (unlikely(!__pyx_t_1.memview)) __PYX_ERR(0, 25, __pyx_L1_error) - __pyx_v_x_view = __pyx_t_1; - __pyx_t_1.memview = NULL; - __pyx_t_1.data = NULL; - - /* "pygom/model/_tau_leap.pyx":26 - * cdef np.int64_t n_rates = rates.shape[0] - * cdef double[:] x_view = x - * cdef np.int64_t[:, :] reactant_mat_view = reactant_mat # <<<<<<<<<<<<<< - * cdef np.int64_t n_reactants = reactant_mat.shape[0] - * - */ - __pyx_t_2 = __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5numpy_int64_t(((PyObject *)__pyx_v_reactant_mat), PyBUF_WRITABLE); if (unlikely(!__pyx_t_2.memview)) __PYX_ERR(0, 26, __pyx_L1_error) - __pyx_v_reactant_mat_view = __pyx_t_2; - __pyx_t_2.memview = NULL; - __pyx_t_2.data = NULL; - - /* "pygom/model/_tau_leap.pyx":27 - * cdef double[:] x_view = x - * cdef np.int64_t[:, :] reactant_mat_view = reactant_mat - * cdef np.int64_t n_reactants = reactant_mat.shape[0] # <<<<<<<<<<<<<< - * - * cdef double mu, max_cdf, new_cdf - */ - __pyx_v_n_reactants = (__pyx_v_reactant_mat->dimensions[0]); - - /* "pygom/model/_tau_leap.pyx":30 - * - * cdef double mu, max_cdf, new_cdf - * cdef double total_rate = np.sum(rates) # <<<<<<<<<<<<<< - * safe = False - * cdef int count = 0 - */ - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_sum); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_5, function); - } - } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_4, ((PyObject *)__pyx_v_rates)) : __Pyx_PyObject_CallOneArg(__pyx_t_5, ((PyObject *)__pyx_v_rates)); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_6 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_6 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 30, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_total_rate = __pyx_t_6; - - /* "pygom/model/_tau_leap.pyx":31 - * cdef double mu, max_cdf, new_cdf - * cdef double total_rate = np.sum(rates) - * safe = False # <<<<<<<<<<<<<< - * cdef int count = 0 - * while safe is False: - */ - __pyx_v_safe = 0; - - /* "pygom/model/_tau_leap.pyx":32 - * cdef double total_rate = np.sum(rates) - * safe = False - * cdef int count = 0 # <<<<<<<<<<<<<< - * while safe is False: - * cdf_val = 1.0 - */ - __pyx_v_count = 0; - - /* "pygom/model/_tau_leap.pyx":33 - * safe = False - * cdef int count = 0 - * while safe is False: # <<<<<<<<<<<<<< - * cdf_val = 1.0 - * for i in range(n_rates): - */ - while (1) { - __pyx_t_7 = ((__pyx_v_safe == 0) != 0); - if (!__pyx_t_7) break; - - /* "pygom/model/_tau_leap.pyx":34 - * cdef int count = 0 - * while safe is False: - * cdf_val = 1.0 # <<<<<<<<<<<<<< - * for i in range(n_rates): - * #xi = x[reactant_mat[:, i]] - */ - __pyx_v_cdf_val = 1.0; - - /* "pygom/model/_tau_leap.pyx":35 - * while safe is False: - * cdf_val = 1.0 - * for i in range(n_rates): # <<<<<<<<<<<<<< - * #xi = x[reactant_mat[:, i]] - * #new_cdf = _ppois(xi, mu=tau_scale*r).min() - */ - __pyx_t_8 = __pyx_v_n_rates; - __pyx_t_9 = __pyx_t_8; - for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) { - __pyx_v_i = __pyx_t_10; - - /* "pygom/model/_tau_leap.pyx":38 - * #xi = x[reactant_mat[:, i]] - * #new_cdf = _ppois(xi, mu=tau_scale*r).min() - * for j in range(n_reactants): # <<<<<<<<<<<<<< - * if reactant_mat_view[j, i] == 1: - * mu = rates_view[i] * tau_scale - */ - __pyx_t_11 = __pyx_v_n_reactants; - __pyx_t_12 = __pyx_t_11; - for (__pyx_t_13 = 0; __pyx_t_13 < __pyx_t_12; __pyx_t_13+=1) { - __pyx_v_j = __pyx_t_13; - - /* "pygom/model/_tau_leap.pyx":39 - * #new_cdf = _ppois(xi, mu=tau_scale*r).min() - * for j in range(n_reactants): - * if reactant_mat_view[j, i] == 1: # <<<<<<<<<<<<<< - * mu = rates_view[i] * tau_scale - * new_cdf = csc.pdtr(floor(x_view[i]), mu) - */ - __pyx_t_14 = __pyx_v_j; - __pyx_t_15 = __pyx_v_i; - __pyx_t_7 = (((*((__pyx_t_5numpy_int64_t *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_reactant_mat_view.data + __pyx_t_14 * __pyx_v_reactant_mat_view.strides[0]) ) + __pyx_t_15 * __pyx_v_reactant_mat_view.strides[1]) ))) == 1) != 0); - if (__pyx_t_7) { - - /* "pygom/model/_tau_leap.pyx":40 - * for j in range(n_reactants): - * if reactant_mat_view[j, i] == 1: - * mu = rates_view[i] * tau_scale # <<<<<<<<<<<<<< - * new_cdf = csc.pdtr(floor(x_view[i]), mu) - * if new_cdf < cdf_val: - */ - __pyx_t_15 = __pyx_v_i; - __pyx_v_mu = ((*((double *) ( /* dim=0 */ (__pyx_v_rates_view.data + __pyx_t_15 * __pyx_v_rates_view.strides[0]) ))) * __pyx_v_tau_scale); - - /* "pygom/model/_tau_leap.pyx":41 - * if reactant_mat_view[j, i] == 1: - * mu = rates_view[i] * tau_scale - * new_cdf = csc.pdtr(floor(x_view[i]), mu) # <<<<<<<<<<<<<< - * if new_cdf < cdf_val: - * cdf_val = new_cdf - */ - __pyx_t_15 = __pyx_v_i; - __pyx_v_new_cdf = __pyx_f_5scipy_7special_14cython_special_pdtr(floor((*((double *) ( /* dim=0 */ (__pyx_v_x_view.data + __pyx_t_15 * __pyx_v_x_view.strides[0]) )))), __pyx_v_mu, 0); - - /* "pygom/model/_tau_leap.pyx":39 - * #new_cdf = _ppois(xi, mu=tau_scale*r).min() - * for j in range(n_reactants): - * if reactant_mat_view[j, i] == 1: # <<<<<<<<<<<<<< - * mu = rates_view[i] * tau_scale - * new_cdf = csc.pdtr(floor(x_view[i]), mu) - */ - } - - /* "pygom/model/_tau_leap.pyx":42 - * mu = rates_view[i] * tau_scale - * new_cdf = csc.pdtr(floor(x_view[i]), mu) - * if new_cdf < cdf_val: # <<<<<<<<<<<<<< - * cdf_val = new_cdf - * if new_cdf < cdf_val: - */ - __pyx_t_7 = ((__pyx_v_new_cdf < __pyx_v_cdf_val) != 0); - if (__pyx_t_7) { - - /* "pygom/model/_tau_leap.pyx":43 - * new_cdf = csc.pdtr(floor(x_view[i]), mu) - * if new_cdf < cdf_val: - * cdf_val = new_cdf # <<<<<<<<<<<<<< - * if new_cdf < cdf_val: - * cdf_val = new_cdf - */ - __pyx_v_cdf_val = __pyx_v_new_cdf; - - /* "pygom/model/_tau_leap.pyx":42 - * mu = rates_view[i] * tau_scale - * new_cdf = csc.pdtr(floor(x_view[i]), mu) - * if new_cdf < cdf_val: # <<<<<<<<<<<<<< - * cdf_val = new_cdf - * if new_cdf < cdf_val: - */ - } - } - - /* "pygom/model/_tau_leap.pyx":44 - * if new_cdf < cdf_val: - * cdf_val = new_cdf - * if new_cdf < cdf_val: # <<<<<<<<<<<<<< - * cdf_val = new_cdf - * #cdf_val[i * reactant_mat.shape[0] : (i * reactant_mat.shape[0]) + len(rates)] = _ppois(xi, mu=tau_scale*r) - */ - __pyx_t_7 = ((__pyx_v_new_cdf < __pyx_v_cdf_val) != 0); - if (__pyx_t_7) { - - /* "pygom/model/_tau_leap.pyx":45 - * cdf_val = new_cdf - * if new_cdf < cdf_val: - * cdf_val = new_cdf # <<<<<<<<<<<<<< - * #cdf_val[i * reactant_mat.shape[0] : (i * reactant_mat.shape[0]) + len(rates)] = _ppois(xi, mu=tau_scale*r) - * - */ - __pyx_v_cdf_val = __pyx_v_new_cdf; - - /* "pygom/model/_tau_leap.pyx":44 - * if new_cdf < cdf_val: - * cdf_val = new_cdf - * if new_cdf < cdf_val: # <<<<<<<<<<<<<< - * cdf_val = new_cdf - * #cdf_val[i * reactant_mat.shape[0] : (i * reactant_mat.shape[0]) + len(rates)] = _ppois(xi, mu=tau_scale*r) - */ - } - } - - /* "pygom/model/_tau_leap.pyx":49 - * - * # the expected probability that our jump will exceed the value - * max_cdf = 1.0 - cdf_val # <<<<<<<<<<<<<< - * # cannot allow it to exceed out epsilon - * if max_cdf > epsilon: - */ - __pyx_v_max_cdf = (1.0 - __pyx_v_cdf_val); - - /* "pygom/model/_tau_leap.pyx":51 - * max_cdf = 1.0 - cdf_val - * # cannot allow it to exceed out epsilon - * if max_cdf > epsilon: # <<<<<<<<<<<<<< - * tau_scale /= (max_cdf / epsilon) - * else: - */ - __pyx_t_7 = ((__pyx_v_max_cdf > __pyx_v_epsilon) != 0); - if (__pyx_t_7) { - - /* "pygom/model/_tau_leap.pyx":52 - * # cannot allow it to exceed out epsilon - * if max_cdf > epsilon: - * tau_scale /= (max_cdf / epsilon) # <<<<<<<<<<<<<< - * else: - * safe = True - */ - __pyx_v_tau_scale = (__pyx_v_tau_scale / (__pyx_v_max_cdf / __pyx_v_epsilon)); - - /* "pygom/model/_tau_leap.pyx":51 - * max_cdf = 1.0 - cdf_val - * # cannot allow it to exceed out epsilon - * if max_cdf > epsilon: # <<<<<<<<<<<<<< - * tau_scale /= (max_cdf / epsilon) - * else: - */ - goto __pyx_L12; - } - - /* "pygom/model/_tau_leap.pyx":54 - * tau_scale /= (max_cdf / epsilon) - * else: - * safe = True # <<<<<<<<<<<<<< - * - * if tau_scale*total_rate <= 1.0 or count > 256: - */ - /*else*/ { - __pyx_v_safe = 1; - } - __pyx_L12:; - - /* "pygom/model/_tau_leap.pyx":56 - * safe = True - * - * if tau_scale*total_rate <= 1.0 or count > 256: # <<<<<<<<<<<<<< - * return False - * count += 1 - */ - __pyx_t_16 = (((__pyx_v_tau_scale * __pyx_v_total_rate) <= 1.0) != 0); - if (!__pyx_t_16) { - } else { - __pyx_t_7 = __pyx_t_16; - goto __pyx_L14_bool_binop_done; - } - __pyx_t_16 = ((__pyx_v_count > 0x100) != 0); - __pyx_t_7 = __pyx_t_16; - __pyx_L14_bool_binop_done:; - if (__pyx_t_7) { - - /* "pygom/model/_tau_leap.pyx":57 - * - * if tau_scale*total_rate <= 1.0 or count > 256: - * return False # <<<<<<<<<<<<<< - * count += 1 - * - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(Py_False); - __pyx_r = Py_False; - goto __pyx_L0; - - /* "pygom/model/_tau_leap.pyx":56 - * safe = True - * - * if tau_scale*total_rate <= 1.0 or count > 256: # <<<<<<<<<<<<<< - * return False - * count += 1 - */ - } - - /* "pygom/model/_tau_leap.pyx":58 - * if tau_scale*total_rate <= 1.0 or count > 256: - * return False - * count += 1 # <<<<<<<<<<<<<< - * - * return tau_scale, True - */ - __pyx_v_count = (__pyx_v_count + 1); - } - - /* "pygom/model/_tau_leap.pyx":60 - * count += 1 - * - * return tau_scale, True # <<<<<<<<<<<<<< - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PyFloat_FromDouble(__pyx_v_tau_scale); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 60, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); - __Pyx_INCREF(Py_True); - __Pyx_GIVEREF(Py_True); - PyTuple_SET_ITEM(__pyx_t_5, 1, Py_True); - __pyx_t_3 = 0; - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; - goto __pyx_L0; - - /* "pygom/model/_tau_leap.pyx":11 - * @cython.wraparound(False) # Deactivate negative indexing. - * @cython.cdivision(True) # Deactivate the div 0 error checking - * def _cy_test_tau_leap_safety(np.ndarray[np.float64_t] x, # <<<<<<<<<<<<<< - * np.ndarray[np.int64_t, ndim=2] reactant_mat, - * np.ndarray[np.float64_t] rates, - */ - - /* function exit code */ - __pyx_L1_error:; - __PYX_XDEC_MEMVIEW(&__pyx_t_1, 1); - __PYX_XDEC_MEMVIEW(&__pyx_t_2, 1); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); - __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_rates.rcbuffer->pybuffer); - __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer); - __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_x.rcbuffer->pybuffer); - __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} - __Pyx_AddTraceback("pygom.model._tau_leap._cy_test_tau_leap_safety", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - goto __pyx_L2; - __pyx_L0:; - __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_rates.rcbuffer->pybuffer); - __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_reactant_mat.rcbuffer->pybuffer); - __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_x.rcbuffer->pybuffer); - __pyx_L2:; - __PYX_XDEC_MEMVIEW(&__pyx_v_rates_view, 1); - __PYX_XDEC_MEMVIEW(&__pyx_v_x_view, 1); - __PYX_XDEC_MEMVIEW(&__pyx_v_reactant_mat_view, 1); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":734 - * ctypedef npy_cdouble complex_t - * - * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(1, a) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("PyArray_MultiIterNew1", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":735 - * - * cdef inline object PyArray_MultiIterNew1(a): - * return PyArray_MultiIterNew(1, a) # <<<<<<<<<<<<<< - * - * cdef inline object PyArray_MultiIterNew2(a, b): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 735, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":734 - * ctypedef npy_cdouble complex_t - * - * cdef inline object PyArray_MultiIterNew1(a): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(1, a) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":737 - * return PyArray_MultiIterNew(1, a) - * - * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(2, a, b) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("PyArray_MultiIterNew2", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":738 - * - * cdef inline object PyArray_MultiIterNew2(a, b): - * return PyArray_MultiIterNew(2, a, b) # <<<<<<<<<<<<<< - * - * cdef inline object PyArray_MultiIterNew3(a, b, c): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 738, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":737 - * return PyArray_MultiIterNew(1, a) - * - * cdef inline object PyArray_MultiIterNew2(a, b): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(2, a, b) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":740 - * return PyArray_MultiIterNew(2, a, b) - * - * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(3, a, b, c) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("PyArray_MultiIterNew3", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":741 - * - * cdef inline object PyArray_MultiIterNew3(a, b, c): - * return PyArray_MultiIterNew(3, a, b, c) # <<<<<<<<<<<<<< - * - * cdef inline object PyArray_MultiIterNew4(a, b, c, d): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 741, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":740 - * return PyArray_MultiIterNew(2, a, b) - * - * cdef inline object PyArray_MultiIterNew3(a, b, c): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(3, a, b, c) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":743 - * return PyArray_MultiIterNew(3, a, b, c) - * - * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(4, a, b, c, d) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("PyArray_MultiIterNew4", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":744 - * - * cdef inline object PyArray_MultiIterNew4(a, b, c, d): - * return PyArray_MultiIterNew(4, a, b, c, d) # <<<<<<<<<<<<<< - * - * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 744, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":743 - * return PyArray_MultiIterNew(3, a, b, c) - * - * cdef inline object PyArray_MultiIterNew4(a, b, c, d): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(4, a, b, c, d) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":746 - * return PyArray_MultiIterNew(4, a, b, c, d) - * - * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(5, a, b, c, d, e) - * - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("PyArray_MultiIterNew5", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":747 - * - * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): - * return PyArray_MultiIterNew(5, a, b, c, d, e) # <<<<<<<<<<<<<< - * - * cdef inline tuple PyDataType_SHAPE(dtype d): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 747, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":746 - * return PyArray_MultiIterNew(4, a, b, c, d) - * - * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e): # <<<<<<<<<<<<<< - * return PyArray_MultiIterNew(5, a, b, c, d, e) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":749 - * return PyArray_MultiIterNew(5, a, b, c, d, e) - * - * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< - * if PyDataType_HASSUBARRAY(d): - * return d.subarray.shape - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":750 - * - * cdef inline tuple PyDataType_SHAPE(dtype d): - * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< - * return d.subarray.shape - * else: - */ - __pyx_t_1 = (PyDataType_HASSUBARRAY(__pyx_v_d) != 0); - if (__pyx_t_1) { - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":751 - * cdef inline tuple PyDataType_SHAPE(dtype d): - * if PyDataType_HASSUBARRAY(d): - * return d.subarray.shape # <<<<<<<<<<<<<< - * else: - * return () - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape)); - __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape); - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":750 - * - * cdef inline tuple PyDataType_SHAPE(dtype d): - * if PyDataType_HASSUBARRAY(d): # <<<<<<<<<<<<<< - * return d.subarray.shape - * else: - */ - } - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":753 - * return d.subarray.shape - * else: - * return () # <<<<<<<<<<<<<< - * - * - */ - /*else*/ { - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_empty_tuple); - __pyx_r = __pyx_empty_tuple; - goto __pyx_L0; - } - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":749 - * return PyArray_MultiIterNew(5, a, b, c, d, e) - * - * cdef inline tuple PyDataType_SHAPE(dtype d): # <<<<<<<<<<<<<< - * if PyDataType_HASSUBARRAY(d): - * return d.subarray.shape - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":928 - * int _import_umath() except -1 - * - * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< - * Py_INCREF(base) # important to do this before stealing the reference below! - * PyArray_SetBaseObject(arr, base) - */ - -static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("set_array_base", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":929 - * - * cdef inline void set_array_base(ndarray arr, object base): - * Py_INCREF(base) # important to do this before stealing the reference below! # <<<<<<<<<<<<<< - * PyArray_SetBaseObject(arr, base) - * - */ - Py_INCREF(__pyx_v_base); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":930 - * cdef inline void set_array_base(ndarray arr, object base): - * Py_INCREF(base) # important to do this before stealing the reference below! - * PyArray_SetBaseObject(arr, base) # <<<<<<<<<<<<<< - * - * cdef inline object get_array_base(ndarray arr): - */ - (void)(PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base)); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":928 - * int _import_umath() except -1 - * - * cdef inline void set_array_base(ndarray arr, object base): # <<<<<<<<<<<<<< - * Py_INCREF(base) # important to do this before stealing the reference below! - * PyArray_SetBaseObject(arr, base) - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":932 - * PyArray_SetBaseObject(arr, base) - * - * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< - * base = PyArray_BASE(arr) - * if base is NULL: - */ - -static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) { - PyObject *__pyx_v_base; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - __Pyx_RefNannySetupContext("get_array_base", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":933 - * - * cdef inline object get_array_base(ndarray arr): - * base = PyArray_BASE(arr) # <<<<<<<<<<<<<< - * if base is NULL: - * return None - */ - __pyx_v_base = PyArray_BASE(__pyx_v_arr); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":934 - * cdef inline object get_array_base(ndarray arr): - * base = PyArray_BASE(arr) - * if base is NULL: # <<<<<<<<<<<<<< - * return None - * return base - */ - __pyx_t_1 = ((__pyx_v_base == NULL) != 0); - if (__pyx_t_1) { - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":935 - * base = PyArray_BASE(arr) - * if base is NULL: - * return None # <<<<<<<<<<<<<< - * return base - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":934 - * cdef inline object get_array_base(ndarray arr): - * base = PyArray_BASE(arr) - * if base is NULL: # <<<<<<<<<<<<<< - * return None - * return base - */ - } - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":936 - * if base is NULL: - * return None - * return base # <<<<<<<<<<<<<< - * - * # Versions of the import_* functions which are more suitable for - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_base)); - __pyx_r = ((PyObject *)__pyx_v_base); - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":932 - * PyArray_SetBaseObject(arr, base) - * - * cdef inline object get_array_base(ndarray arr): # <<<<<<<<<<<<<< - * base = PyArray_BASE(arr) - * if base is NULL: - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":940 - * # Versions of the import_* functions which are more suitable for - * # Cython code. - * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< - * try: - * __pyx_import_array() - */ - -static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("import_array", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":941 - * # Cython code. - * cdef inline int import_array() except -1: - * try: # <<<<<<<<<<<<<< - * __pyx_import_array() - * except Exception: - */ - { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); - __Pyx_XGOTREF(__pyx_t_1); - __Pyx_XGOTREF(__pyx_t_2); - __Pyx_XGOTREF(__pyx_t_3); - /*try:*/ { - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":942 - * cdef inline int import_array() except -1: - * try: - * __pyx_import_array() # <<<<<<<<<<<<<< - * except Exception: - * raise ImportError("numpy.core.multiarray failed to import") - */ - __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 942, __pyx_L3_error) - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":941 - * # Cython code. - * cdef inline int import_array() except -1: - * try: # <<<<<<<<<<<<<< - * __pyx_import_array() - * except Exception: - */ - } - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - goto __pyx_L8_try_end; - __pyx_L3_error:; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":943 - * try: - * __pyx_import_array() - * except Exception: # <<<<<<<<<<<<<< - * raise ImportError("numpy.core.multiarray failed to import") - * - */ - __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); - if (__pyx_t_4) { - __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 943, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GOTREF(__pyx_t_6); - __Pyx_GOTREF(__pyx_t_7); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":944 - * __pyx_import_array() - * except Exception: - * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< - * - * cdef inline int import_umath() except -1: - */ - __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 944, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_Raise(__pyx_t_8, 0, 0, 0); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __PYX_ERR(1, 944, __pyx_L5_except_error) - } - goto __pyx_L5_except_error; - __pyx_L5_except_error:; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":941 - * # Cython code. - * cdef inline int import_array() except -1: - * try: # <<<<<<<<<<<<<< - * __pyx_import_array() - * except Exception: - */ - __Pyx_XGIVEREF(__pyx_t_1); - __Pyx_XGIVEREF(__pyx_t_2); - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); - goto __pyx_L1_error; - __pyx_L8_try_end:; - } - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":940 - * # Versions of the import_* functions which are more suitable for - * # Cython code. - * cdef inline int import_array() except -1: # <<<<<<<<<<<<<< - * try: - * __pyx_import_array() - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":946 - * raise ImportError("numpy.core.multiarray failed to import") - * - * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< - * try: - * _import_umath() - */ - -static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("import_umath", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":947 - * - * cdef inline int import_umath() except -1: - * try: # <<<<<<<<<<<<<< - * _import_umath() - * except Exception: - */ - { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); - __Pyx_XGOTREF(__pyx_t_1); - __Pyx_XGOTREF(__pyx_t_2); - __Pyx_XGOTREF(__pyx_t_3); - /*try:*/ { - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":948 - * cdef inline int import_umath() except -1: - * try: - * _import_umath() # <<<<<<<<<<<<<< - * except Exception: - * raise ImportError("numpy.core.umath failed to import") - */ - __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 948, __pyx_L3_error) - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":947 - * - * cdef inline int import_umath() except -1: - * try: # <<<<<<<<<<<<<< - * _import_umath() - * except Exception: - */ - } - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - goto __pyx_L8_try_end; - __pyx_L3_error:; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":949 - * try: - * _import_umath() - * except Exception: # <<<<<<<<<<<<<< - * raise ImportError("numpy.core.umath failed to import") - * - */ - __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); - if (__pyx_t_4) { - __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 949, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GOTREF(__pyx_t_6); - __Pyx_GOTREF(__pyx_t_7); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":950 - * _import_umath() - * except Exception: - * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< - * - * cdef inline int import_ufunc() except -1: - */ - __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 950, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_Raise(__pyx_t_8, 0, 0, 0); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __PYX_ERR(1, 950, __pyx_L5_except_error) - } - goto __pyx_L5_except_error; - __pyx_L5_except_error:; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":947 - * - * cdef inline int import_umath() except -1: - * try: # <<<<<<<<<<<<<< - * _import_umath() - * except Exception: - */ - __Pyx_XGIVEREF(__pyx_t_1); - __Pyx_XGIVEREF(__pyx_t_2); - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); - goto __pyx_L1_error; - __pyx_L8_try_end:; - } - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":946 - * raise ImportError("numpy.core.multiarray failed to import") - * - * cdef inline int import_umath() except -1: # <<<<<<<<<<<<<< - * try: - * _import_umath() - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":952 - * raise ImportError("numpy.core.umath failed to import") - * - * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< - * try: - * _import_umath() - */ - -static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("import_ufunc", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":953 - * - * cdef inline int import_ufunc() except -1: - * try: # <<<<<<<<<<<<<< - * _import_umath() - * except Exception: - */ - { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3); - __Pyx_XGOTREF(__pyx_t_1); - __Pyx_XGOTREF(__pyx_t_2); - __Pyx_XGOTREF(__pyx_t_3); - /*try:*/ { - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":954 - * cdef inline int import_ufunc() except -1: - * try: - * _import_umath() # <<<<<<<<<<<<<< - * except Exception: - * raise ImportError("numpy.core.umath failed to import") - */ - __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 954, __pyx_L3_error) - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":953 - * - * cdef inline int import_ufunc() except -1: - * try: # <<<<<<<<<<<<<< - * _import_umath() - * except Exception: - */ - } - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - goto __pyx_L8_try_end; - __pyx_L3_error:; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":955 - * try: - * _import_umath() - * except Exception: # <<<<<<<<<<<<<< - * raise ImportError("numpy.core.umath failed to import") - * - */ - __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0]))); - if (__pyx_t_4) { - __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 955, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GOTREF(__pyx_t_6); - __Pyx_GOTREF(__pyx_t_7); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":956 - * _import_umath() - * except Exception: - * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< - * - * cdef extern from *: - */ - __pyx_t_8 = __Pyx_PyObject_Call(__pyx_builtin_ImportError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 956, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_Raise(__pyx_t_8, 0, 0, 0); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __PYX_ERR(1, 956, __pyx_L5_except_error) - } - goto __pyx_L5_except_error; - __pyx_L5_except_error:; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":953 - * - * cdef inline int import_ufunc() except -1: - * try: # <<<<<<<<<<<<<< - * _import_umath() - * except Exception: - */ - __Pyx_XGIVEREF(__pyx_t_1); - __Pyx_XGIVEREF(__pyx_t_2); - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3); - goto __pyx_L1_error; - __pyx_L8_try_end:; - } - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":952 - * raise ImportError("numpy.core.umath failed to import") - * - * cdef inline int import_ufunc() except -1: # <<<<<<<<<<<<<< - * try: - * _import_umath() - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":966 - * - * - * cdef inline bint is_timedelta64_object(object obj): # <<<<<<<<<<<<<< - * """ - * Cython equivalent of `isinstance(obj, np.timedelta64)` - */ - -static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_obj) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("is_timedelta64_object", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":978 - * bool - * """ - * return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type) # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyTimedeltaArrType_Type)); - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":966 - * - * - * cdef inline bint is_timedelta64_object(object obj): # <<<<<<<<<<<<<< - * """ - * Cython equivalent of `isinstance(obj, np.timedelta64)` - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":981 - * - * - * cdef inline bint is_datetime64_object(object obj): # <<<<<<<<<<<<<< - * """ - * Cython equivalent of `isinstance(obj, np.datetime64)` - */ - -static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_obj) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("is_datetime64_object", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":993 - * bool - * """ - * return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type) # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyDatetimeArrType_Type)); - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":981 - * - * - * cdef inline bint is_datetime64_object(object obj): # <<<<<<<<<<<<<< - * """ - * Cython equivalent of `isinstance(obj, np.datetime64)` - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":996 - * - * - * cdef inline npy_datetime get_datetime64_value(object obj) nogil: # <<<<<<<<<<<<<< - * """ - * returns the int64 value underlying scalar numpy datetime64 object - */ - -static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject *__pyx_v_obj) { - npy_datetime __pyx_r; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1003 - * also needed. That can be found using `get_datetime64_unit`. - * """ - * return (obj).obval # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = ((PyDatetimeScalarObject *)__pyx_v_obj)->obval; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":996 - * - * - * cdef inline npy_datetime get_datetime64_value(object obj) nogil: # <<<<<<<<<<<<<< - * """ - * returns the int64 value underlying scalar numpy datetime64 object - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1006 - * - * - * cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: # <<<<<<<<<<<<<< - * """ - * returns the int64 value underlying scalar numpy timedelta64 object - */ - -static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject *__pyx_v_obj) { - npy_timedelta __pyx_r; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1010 - * returns the int64 value underlying scalar numpy timedelta64 object - * """ - * return (obj).obval # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = ((PyTimedeltaScalarObject *)__pyx_v_obj)->obval; - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1006 - * - * - * cdef inline npy_timedelta get_timedelta64_value(object obj) nogil: # <<<<<<<<<<<<<< - * """ - * returns the int64 value underlying scalar numpy timedelta64 object - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1013 - * - * - * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< - * """ - * returns the unit part of the dtype for a numpy datetime64 object. - */ - -static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObject *__pyx_v_obj) { - NPY_DATETIMEUNIT __pyx_r; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1017 - * returns the unit part of the dtype for a numpy datetime64 object. - * """ - * return (obj).obmeta.base # <<<<<<<<<<<<<< - */ - __pyx_r = ((NPY_DATETIMEUNIT)((PyDatetimeScalarObject *)__pyx_v_obj)->obmeta.base); - goto __pyx_L0; - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":1013 - * - * - * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil: # <<<<<<<<<<<<<< - * """ - * returns the unit part of the dtype for a numpy datetime64 object. - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":123 - * cdef bint dtype_is_object - * - * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, # <<<<<<<<<<<<<< - * mode="c", bint allocate_buffer=True): - * - */ - -/* Python wrapper */ -static int __pyx_array___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_array___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_shape = 0; - Py_ssize_t __pyx_v_itemsize; - PyObject *__pyx_v_format = 0; - PyObject *__pyx_v_mode = 0; - int __pyx_v_allocate_buffer; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_shape,&__pyx_n_s_itemsize,&__pyx_n_s_format,&__pyx_n_s_mode,&__pyx_n_s_allocate_buffer,0}; - PyObject* values[5] = {0,0,0,0,0}; - values[3] = ((PyObject *)__pyx_n_s_c); - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - CYTHON_FALLTHROUGH; - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - CYTHON_FALLTHROUGH; - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_shape)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_itemsize)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 3, 5, 1); __PYX_ERR(2, 123, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_format)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 3, 5, 2); __PYX_ERR(2, 123, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 3: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mode); - if (value) { values[3] = value; kw_args--; } - } - CYTHON_FALLTHROUGH; - case 4: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_allocate_buffer); - if (value) { values[4] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(2, 123, __pyx_L3_error) - } - } else { - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - CYTHON_FALLTHROUGH; - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - CYTHON_FALLTHROUGH; - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - break; - default: goto __pyx_L5_argtuple_error; - } - } - __pyx_v_shape = ((PyObject*)values[0]); - __pyx_v_itemsize = __Pyx_PyIndex_AsSsize_t(values[1]); if (unlikely((__pyx_v_itemsize == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 123, __pyx_L3_error) - __pyx_v_format = values[2]; - __pyx_v_mode = values[3]; - if (values[4]) { - __pyx_v_allocate_buffer = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_allocate_buffer == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 124, __pyx_L3_error) - } else { - - /* "View.MemoryView":124 - * - * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, - * mode="c", bint allocate_buffer=True): # <<<<<<<<<<<<<< - * - * cdef int idx - */ - __pyx_v_allocate_buffer = ((int)1); - } - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 3, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 123, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("View.MemoryView.array.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return -1; - __pyx_L4_argument_unpacking_done:; - if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_shape), (&PyTuple_Type), 1, "shape", 1))) __PYX_ERR(2, 123, __pyx_L1_error) - if (unlikely(((PyObject *)__pyx_v_format) == Py_None)) { - PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "format"); __PYX_ERR(2, 123, __pyx_L1_error) - } - __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(((struct __pyx_array_obj *)__pyx_v_self), __pyx_v_shape, __pyx_v_itemsize, __pyx_v_format, __pyx_v_mode, __pyx_v_allocate_buffer); - - /* "View.MemoryView":123 - * cdef bint dtype_is_object - * - * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, # <<<<<<<<<<<<<< - * mode="c", bint allocate_buffer=True): - * - */ - - /* function exit code */ - goto __pyx_L0; - __pyx_L1_error:; - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array___cinit__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, PyObject *__pyx_v_format, PyObject *__pyx_v_mode, int __pyx_v_allocate_buffer) { - int __pyx_v_idx; - Py_ssize_t __pyx_v_i; - Py_ssize_t __pyx_v_dim; - PyObject **__pyx_v_p; - char __pyx_v_order; - int __pyx_r; - __Pyx_RefNannyDeclarations - Py_ssize_t __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - char *__pyx_t_7; - int __pyx_t_8; - Py_ssize_t __pyx_t_9; - PyObject *__pyx_t_10 = NULL; - Py_ssize_t __pyx_t_11; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__cinit__", 0); - __Pyx_INCREF(__pyx_v_format); - - /* "View.MemoryView":130 - * cdef PyObject **p - * - * self.ndim = len(shape) # <<<<<<<<<<<<<< - * self.itemsize = itemsize - * - */ - if (unlikely(__pyx_v_shape == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(2, 130, __pyx_L1_error) - } - __pyx_t_1 = PyTuple_GET_SIZE(__pyx_v_shape); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(2, 130, __pyx_L1_error) - __pyx_v_self->ndim = ((int)__pyx_t_1); - - /* "View.MemoryView":131 - * - * self.ndim = len(shape) - * self.itemsize = itemsize # <<<<<<<<<<<<<< - * - * if not self.ndim: - */ - __pyx_v_self->itemsize = __pyx_v_itemsize; - - /* "View.MemoryView":133 - * self.itemsize = itemsize - * - * if not self.ndim: # <<<<<<<<<<<<<< - * raise ValueError("Empty shape tuple for cython.array") - * - */ - __pyx_t_2 = ((!(__pyx_v_self->ndim != 0)) != 0); - if (unlikely(__pyx_t_2)) { - - /* "View.MemoryView":134 - * - * if not self.ndim: - * raise ValueError("Empty shape tuple for cython.array") # <<<<<<<<<<<<<< - * - * if itemsize <= 0: - */ - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 134, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 134, __pyx_L1_error) - - /* "View.MemoryView":133 - * self.itemsize = itemsize - * - * if not self.ndim: # <<<<<<<<<<<<<< - * raise ValueError("Empty shape tuple for cython.array") - * - */ - } - - /* "View.MemoryView":136 - * raise ValueError("Empty shape tuple for cython.array") - * - * if itemsize <= 0: # <<<<<<<<<<<<<< - * raise ValueError("itemsize <= 0 for cython.array") - * - */ - __pyx_t_2 = ((__pyx_v_itemsize <= 0) != 0); - if (unlikely(__pyx_t_2)) { - - /* "View.MemoryView":137 - * - * if itemsize <= 0: - * raise ValueError("itemsize <= 0 for cython.array") # <<<<<<<<<<<<<< - * - * if not isinstance(format, bytes): - */ - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 137, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 137, __pyx_L1_error) - - /* "View.MemoryView":136 - * raise ValueError("Empty shape tuple for cython.array") - * - * if itemsize <= 0: # <<<<<<<<<<<<<< - * raise ValueError("itemsize <= 0 for cython.array") - * - */ - } - - /* "View.MemoryView":139 - * raise ValueError("itemsize <= 0 for cython.array") - * - * if not isinstance(format, bytes): # <<<<<<<<<<<<<< - * format = format.encode('ASCII') - * self._format = format # keep a reference to the byte string - */ - __pyx_t_2 = PyBytes_Check(__pyx_v_format); - __pyx_t_4 = ((!(__pyx_t_2 != 0)) != 0); - if (__pyx_t_4) { - - /* "View.MemoryView":140 - * - * if not isinstance(format, bytes): - * format = format.encode('ASCII') # <<<<<<<<<<<<<< - * self._format = format # keep a reference to the byte string - * self.format = self._format - */ - __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_format, __pyx_n_s_encode); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 140, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { - __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5); - if (likely(__pyx_t_6)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); - __Pyx_INCREF(__pyx_t_6); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_5, function); - } - } - __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_n_s_ASCII) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_n_s_ASCII); - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 140, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_DECREF_SET(__pyx_v_format, __pyx_t_3); - __pyx_t_3 = 0; - - /* "View.MemoryView":139 - * raise ValueError("itemsize <= 0 for cython.array") - * - * if not isinstance(format, bytes): # <<<<<<<<<<<<<< - * format = format.encode('ASCII') - * self._format = format # keep a reference to the byte string - */ - } - - /* "View.MemoryView":141 - * if not isinstance(format, bytes): - * format = format.encode('ASCII') - * self._format = format # keep a reference to the byte string # <<<<<<<<<<<<<< - * self.format = self._format - * - */ - if (!(likely(PyBytes_CheckExact(__pyx_v_format))||((__pyx_v_format) == Py_None)||((void)PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_v_format)->tp_name), 0))) __PYX_ERR(2, 141, __pyx_L1_error) - __pyx_t_3 = __pyx_v_format; - __Pyx_INCREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_3); - __Pyx_GOTREF(__pyx_v_self->_format); - __Pyx_DECREF(__pyx_v_self->_format); - __pyx_v_self->_format = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "View.MemoryView":142 - * format = format.encode('ASCII') - * self._format = format # keep a reference to the byte string - * self.format = self._format # <<<<<<<<<<<<<< - * - * - */ - if (unlikely(__pyx_v_self->_format == Py_None)) { - PyErr_SetString(PyExc_TypeError, "expected bytes, NoneType found"); - __PYX_ERR(2, 142, __pyx_L1_error) - } - __pyx_t_7 = __Pyx_PyBytes_AsWritableString(__pyx_v_self->_format); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(2, 142, __pyx_L1_error) - __pyx_v_self->format = __pyx_t_7; - - /* "View.MemoryView":145 - * - * - * self._shape = PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2) # <<<<<<<<<<<<<< - * self._strides = self._shape + self.ndim - * - */ - __pyx_v_self->_shape = ((Py_ssize_t *)PyObject_Malloc((((sizeof(Py_ssize_t)) * __pyx_v_self->ndim) * 2))); - - /* "View.MemoryView":146 - * - * self._shape = PyObject_Malloc(sizeof(Py_ssize_t)*self.ndim*2) - * self._strides = self._shape + self.ndim # <<<<<<<<<<<<<< - * - * if not self._shape: - */ - __pyx_v_self->_strides = (__pyx_v_self->_shape + __pyx_v_self->ndim); - - /* "View.MemoryView":148 - * self._strides = self._shape + self.ndim - * - * if not self._shape: # <<<<<<<<<<<<<< - * raise MemoryError("unable to allocate shape and strides.") - * - */ - __pyx_t_4 = ((!(__pyx_v_self->_shape != 0)) != 0); - if (unlikely(__pyx_t_4)) { - - /* "View.MemoryView":149 - * - * if not self._shape: - * raise MemoryError("unable to allocate shape and strides.") # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_MemoryError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 149, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 149, __pyx_L1_error) - - /* "View.MemoryView":148 - * self._strides = self._shape + self.ndim - * - * if not self._shape: # <<<<<<<<<<<<<< - * raise MemoryError("unable to allocate shape and strides.") - * - */ - } - - /* "View.MemoryView":152 - * - * - * for idx, dim in enumerate(shape): # <<<<<<<<<<<<<< - * if dim <= 0: - * raise ValueError("Invalid shape in axis %d: %d." % (idx, dim)) - */ - __pyx_t_8 = 0; - __pyx_t_3 = __pyx_v_shape; __Pyx_INCREF(__pyx_t_3); __pyx_t_1 = 0; - for (;;) { - if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_3)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_1); __Pyx_INCREF(__pyx_t_5); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(2, 152, __pyx_L1_error) - #else - __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 152, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - #endif - __pyx_t_9 = __Pyx_PyIndex_AsSsize_t(__pyx_t_5); if (unlikely((__pyx_t_9 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 152, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_v_dim = __pyx_t_9; - __pyx_v_idx = __pyx_t_8; - __pyx_t_8 = (__pyx_t_8 + 1); - - /* "View.MemoryView":153 - * - * for idx, dim in enumerate(shape): - * if dim <= 0: # <<<<<<<<<<<<<< - * raise ValueError("Invalid shape in axis %d: %d." % (idx, dim)) - * self._shape[idx] = dim - */ - __pyx_t_4 = ((__pyx_v_dim <= 0) != 0); - if (unlikely(__pyx_t_4)) { - - /* "View.MemoryView":154 - * for idx, dim in enumerate(shape): - * if dim <= 0: - * raise ValueError("Invalid shape in axis %d: %d." % (idx, dim)) # <<<<<<<<<<<<<< - * self._shape[idx] = dim - * - */ - __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_idx); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 154, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = PyInt_FromSsize_t(__pyx_v_dim); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 154, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) __PYX_ERR(2, 154, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_6); - __pyx_t_5 = 0; - __pyx_t_6 = 0; - __pyx_t_6 = __Pyx_PyString_Format(__pyx_kp_s_Invalid_shape_in_axis_d_d, __pyx_t_10); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 154, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_10 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_6); if (unlikely(!__pyx_t_10)) __PYX_ERR(2, 154, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_Raise(__pyx_t_10, 0, 0, 0); - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __PYX_ERR(2, 154, __pyx_L1_error) - - /* "View.MemoryView":153 - * - * for idx, dim in enumerate(shape): - * if dim <= 0: # <<<<<<<<<<<<<< - * raise ValueError("Invalid shape in axis %d: %d." % (idx, dim)) - * self._shape[idx] = dim - */ - } - - /* "View.MemoryView":155 - * if dim <= 0: - * raise ValueError("Invalid shape in axis %d: %d." % (idx, dim)) - * self._shape[idx] = dim # <<<<<<<<<<<<<< - * - * cdef char order - */ - (__pyx_v_self->_shape[__pyx_v_idx]) = __pyx_v_dim; - - /* "View.MemoryView":152 - * - * - * for idx, dim in enumerate(shape): # <<<<<<<<<<<<<< - * if dim <= 0: - * raise ValueError("Invalid shape in axis %d: %d." % (idx, dim)) - */ - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "View.MemoryView":158 - * - * cdef char order - * if mode == 'fortran': # <<<<<<<<<<<<<< - * order = b'F' - * self.mode = u'fortran' - */ - __pyx_t_4 = (__Pyx_PyString_Equals(__pyx_v_mode, __pyx_n_s_fortran, Py_EQ)); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(2, 158, __pyx_L1_error) - if (__pyx_t_4) { - - /* "View.MemoryView":159 - * cdef char order - * if mode == 'fortran': - * order = b'F' # <<<<<<<<<<<<<< - * self.mode = u'fortran' - * elif mode == 'c': - */ - __pyx_v_order = 'F'; - - /* "View.MemoryView":160 - * if mode == 'fortran': - * order = b'F' - * self.mode = u'fortran' # <<<<<<<<<<<<<< - * elif mode == 'c': - * order = b'C' - */ - __Pyx_INCREF(__pyx_n_u_fortran); - __Pyx_GIVEREF(__pyx_n_u_fortran); - __Pyx_GOTREF(__pyx_v_self->mode); - __Pyx_DECREF(__pyx_v_self->mode); - __pyx_v_self->mode = __pyx_n_u_fortran; - - /* "View.MemoryView":158 - * - * cdef char order - * if mode == 'fortran': # <<<<<<<<<<<<<< - * order = b'F' - * self.mode = u'fortran' - */ - goto __pyx_L10; - } - - /* "View.MemoryView":161 - * order = b'F' - * self.mode = u'fortran' - * elif mode == 'c': # <<<<<<<<<<<<<< - * order = b'C' - * self.mode = u'c' - */ - __pyx_t_4 = (__Pyx_PyString_Equals(__pyx_v_mode, __pyx_n_s_c, Py_EQ)); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(2, 161, __pyx_L1_error) - if (likely(__pyx_t_4)) { - - /* "View.MemoryView":162 - * self.mode = u'fortran' - * elif mode == 'c': - * order = b'C' # <<<<<<<<<<<<<< - * self.mode = u'c' - * else: - */ - __pyx_v_order = 'C'; - - /* "View.MemoryView":163 - * elif mode == 'c': - * order = b'C' - * self.mode = u'c' # <<<<<<<<<<<<<< - * else: - * raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode) - */ - __Pyx_INCREF(__pyx_n_u_c); - __Pyx_GIVEREF(__pyx_n_u_c); - __Pyx_GOTREF(__pyx_v_self->mode); - __Pyx_DECREF(__pyx_v_self->mode); - __pyx_v_self->mode = __pyx_n_u_c; - - /* "View.MemoryView":161 - * order = b'F' - * self.mode = u'fortran' - * elif mode == 'c': # <<<<<<<<<<<<<< - * order = b'C' - * self.mode = u'c' - */ - goto __pyx_L10; - } - - /* "View.MemoryView":165 - * self.mode = u'c' - * else: - * raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode) # <<<<<<<<<<<<<< - * - * self.len = fill_contig_strides_array(self._shape, self._strides, - */ - /*else*/ { - __pyx_t_3 = __Pyx_PyString_FormatSafe(__pyx_kp_s_Invalid_mode_expected_c_or_fortr, __pyx_v_mode); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 165, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_10 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(2, 165, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_Raise(__pyx_t_10, 0, 0, 0); - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __PYX_ERR(2, 165, __pyx_L1_error) - } - __pyx_L10:; - - /* "View.MemoryView":167 - * raise ValueError("Invalid mode, expected 'c' or 'fortran', got %s" % mode) - * - * self.len = fill_contig_strides_array(self._shape, self._strides, # <<<<<<<<<<<<<< - * itemsize, self.ndim, order) - * - */ - __pyx_v_self->len = __pyx_fill_contig_strides_array(__pyx_v_self->_shape, __pyx_v_self->_strides, __pyx_v_itemsize, __pyx_v_self->ndim, __pyx_v_order); - - /* "View.MemoryView":170 - * itemsize, self.ndim, order) - * - * self.free_data = allocate_buffer # <<<<<<<<<<<<<< - * self.dtype_is_object = format == b'O' - * if allocate_buffer: - */ - __pyx_v_self->free_data = __pyx_v_allocate_buffer; - - /* "View.MemoryView":171 - * - * self.free_data = allocate_buffer - * self.dtype_is_object = format == b'O' # <<<<<<<<<<<<<< - * if allocate_buffer: - * - */ - __pyx_t_10 = PyObject_RichCompare(__pyx_v_format, __pyx_n_b_O, Py_EQ); __Pyx_XGOTREF(__pyx_t_10); if (unlikely(!__pyx_t_10)) __PYX_ERR(2, 171, __pyx_L1_error) - __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 171, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_v_self->dtype_is_object = __pyx_t_4; - - /* "View.MemoryView":172 - * self.free_data = allocate_buffer - * self.dtype_is_object = format == b'O' - * if allocate_buffer: # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_4 = (__pyx_v_allocate_buffer != 0); - if (__pyx_t_4) { - - /* "View.MemoryView":175 - * - * - * self.data = malloc(self.len) # <<<<<<<<<<<<<< - * if not self.data: - * raise MemoryError("unable to allocate array data.") - */ - __pyx_v_self->data = ((char *)malloc(__pyx_v_self->len)); - - /* "View.MemoryView":176 - * - * self.data = malloc(self.len) - * if not self.data: # <<<<<<<<<<<<<< - * raise MemoryError("unable to allocate array data.") - * - */ - __pyx_t_4 = ((!(__pyx_v_self->data != 0)) != 0); - if (unlikely(__pyx_t_4)) { - - /* "View.MemoryView":177 - * self.data = malloc(self.len) - * if not self.data: - * raise MemoryError("unable to allocate array data.") # <<<<<<<<<<<<<< - * - * if self.dtype_is_object: - */ - __pyx_t_10 = __Pyx_PyObject_Call(__pyx_builtin_MemoryError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_10)) __PYX_ERR(2, 177, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __Pyx_Raise(__pyx_t_10, 0, 0, 0); - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __PYX_ERR(2, 177, __pyx_L1_error) - - /* "View.MemoryView":176 - * - * self.data = malloc(self.len) - * if not self.data: # <<<<<<<<<<<<<< - * raise MemoryError("unable to allocate array data.") - * - */ - } - - /* "View.MemoryView":179 - * raise MemoryError("unable to allocate array data.") - * - * if self.dtype_is_object: # <<<<<<<<<<<<<< - * p = self.data - * for i in range(self.len / itemsize): - */ - __pyx_t_4 = (__pyx_v_self->dtype_is_object != 0); - if (__pyx_t_4) { - - /* "View.MemoryView":180 - * - * if self.dtype_is_object: - * p = self.data # <<<<<<<<<<<<<< - * for i in range(self.len / itemsize): - * p[i] = Py_None - */ - __pyx_v_p = ((PyObject **)__pyx_v_self->data); - - /* "View.MemoryView":181 - * if self.dtype_is_object: - * p = self.data - * for i in range(self.len / itemsize): # <<<<<<<<<<<<<< - * p[i] = Py_None - * Py_INCREF(Py_None) - */ - if (unlikely(__pyx_v_itemsize == 0)) { - PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); - __PYX_ERR(2, 181, __pyx_L1_error) - } - else if (sizeof(Py_ssize_t) == sizeof(long) && (!(((Py_ssize_t)-1) > 0)) && unlikely(__pyx_v_itemsize == (Py_ssize_t)-1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(__pyx_v_self->len))) { - PyErr_SetString(PyExc_OverflowError, "value too large to perform division"); - __PYX_ERR(2, 181, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_div_Py_ssize_t(__pyx_v_self->len, __pyx_v_itemsize); - __pyx_t_9 = __pyx_t_1; - for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_9; __pyx_t_11+=1) { - __pyx_v_i = __pyx_t_11; - - /* "View.MemoryView":182 - * p = self.data - * for i in range(self.len / itemsize): - * p[i] = Py_None # <<<<<<<<<<<<<< - * Py_INCREF(Py_None) - * - */ - (__pyx_v_p[__pyx_v_i]) = Py_None; - - /* "View.MemoryView":183 - * for i in range(self.len / itemsize): - * p[i] = Py_None - * Py_INCREF(Py_None) # <<<<<<<<<<<<<< - * - * @cname('getbuffer') - */ - Py_INCREF(Py_None); - } - - /* "View.MemoryView":179 - * raise MemoryError("unable to allocate array data.") - * - * if self.dtype_is_object: # <<<<<<<<<<<<<< - * p = self.data - * for i in range(self.len / itemsize): - */ - } - - /* "View.MemoryView":172 - * self.free_data = allocate_buffer - * self.dtype_is_object = format == b'O' - * if allocate_buffer: # <<<<<<<<<<<<<< - * - * - */ - } - - /* "View.MemoryView":123 - * cdef bint dtype_is_object - * - * def __cinit__(array self, tuple shape, Py_ssize_t itemsize, format not None, # <<<<<<<<<<<<<< - * mode="c", bint allocate_buffer=True): - * - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_10); - __Pyx_AddTraceback("View.MemoryView.array.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_format); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":186 - * - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): # <<<<<<<<<<<<<< - * cdef int bufmode = -1 - * if self.mode == u"c": - */ - -/* Python wrapper */ -static CYTHON_UNUSED int __pyx_array_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ -static CYTHON_UNUSED int __pyx_array_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); - __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(((struct __pyx_array_obj *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_2__getbuffer__(struct __pyx_array_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { - int __pyx_v_bufmode; - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - char *__pyx_t_4; - Py_ssize_t __pyx_t_5; - int __pyx_t_6; - Py_ssize_t *__pyx_t_7; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - if (__pyx_v_info == NULL) { - PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); - return -1; - } - __Pyx_RefNannySetupContext("__getbuffer__", 0); - __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); - __Pyx_GIVEREF(__pyx_v_info->obj); - - /* "View.MemoryView":187 - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): - * cdef int bufmode = -1 # <<<<<<<<<<<<<< - * if self.mode == u"c": - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - */ - __pyx_v_bufmode = -1; - - /* "View.MemoryView":188 - * def __getbuffer__(self, Py_buffer *info, int flags): - * cdef int bufmode = -1 - * if self.mode == u"c": # <<<<<<<<<<<<<< - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * elif self.mode == u"fortran": - */ - __pyx_t_1 = (__Pyx_PyUnicode_Equals(__pyx_v_self->mode, __pyx_n_u_c, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(2, 188, __pyx_L1_error) - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":189 - * cdef int bufmode = -1 - * if self.mode == u"c": - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS # <<<<<<<<<<<<<< - * elif self.mode == u"fortran": - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - */ - __pyx_v_bufmode = (PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS); - - /* "View.MemoryView":188 - * def __getbuffer__(self, Py_buffer *info, int flags): - * cdef int bufmode = -1 - * if self.mode == u"c": # <<<<<<<<<<<<<< - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * elif self.mode == u"fortran": - */ - goto __pyx_L3; - } - - /* "View.MemoryView":190 - * if self.mode == u"c": - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * elif self.mode == u"fortran": # <<<<<<<<<<<<<< - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * if not (flags & bufmode): - */ - __pyx_t_2 = (__Pyx_PyUnicode_Equals(__pyx_v_self->mode, __pyx_n_u_fortran, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 190, __pyx_L1_error) - __pyx_t_1 = (__pyx_t_2 != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":191 - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * elif self.mode == u"fortran": - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS # <<<<<<<<<<<<<< - * if not (flags & bufmode): - * raise ValueError("Can only create a buffer that is contiguous in memory.") - */ - __pyx_v_bufmode = (PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS); - - /* "View.MemoryView":190 - * if self.mode == u"c": - * bufmode = PyBUF_C_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * elif self.mode == u"fortran": # <<<<<<<<<<<<<< - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * if not (flags & bufmode): - */ - } - __pyx_L3:; - - /* "View.MemoryView":192 - * elif self.mode == u"fortran": - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * if not (flags & bufmode): # <<<<<<<<<<<<<< - * raise ValueError("Can only create a buffer that is contiguous in memory.") - * info.buf = self.data - */ - __pyx_t_1 = ((!((__pyx_v_flags & __pyx_v_bufmode) != 0)) != 0); - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":193 - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * if not (flags & bufmode): - * raise ValueError("Can only create a buffer that is contiguous in memory.") # <<<<<<<<<<<<<< - * info.buf = self.data - * info.len = self.len - */ - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__7, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 193, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 193, __pyx_L1_error) - - /* "View.MemoryView":192 - * elif self.mode == u"fortran": - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * if not (flags & bufmode): # <<<<<<<<<<<<<< - * raise ValueError("Can only create a buffer that is contiguous in memory.") - * info.buf = self.data - */ - } - - /* "View.MemoryView":194 - * if not (flags & bufmode): - * raise ValueError("Can only create a buffer that is contiguous in memory.") - * info.buf = self.data # <<<<<<<<<<<<<< - * info.len = self.len - * info.ndim = self.ndim - */ - __pyx_t_4 = __pyx_v_self->data; - __pyx_v_info->buf = __pyx_t_4; - - /* "View.MemoryView":195 - * raise ValueError("Can only create a buffer that is contiguous in memory.") - * info.buf = self.data - * info.len = self.len # <<<<<<<<<<<<<< - * info.ndim = self.ndim - * info.shape = self._shape - */ - __pyx_t_5 = __pyx_v_self->len; - __pyx_v_info->len = __pyx_t_5; - - /* "View.MemoryView":196 - * info.buf = self.data - * info.len = self.len - * info.ndim = self.ndim # <<<<<<<<<<<<<< - * info.shape = self._shape - * info.strides = self._strides - */ - __pyx_t_6 = __pyx_v_self->ndim; - __pyx_v_info->ndim = __pyx_t_6; - - /* "View.MemoryView":197 - * info.len = self.len - * info.ndim = self.ndim - * info.shape = self._shape # <<<<<<<<<<<<<< - * info.strides = self._strides - * info.suboffsets = NULL - */ - __pyx_t_7 = __pyx_v_self->_shape; - __pyx_v_info->shape = __pyx_t_7; - - /* "View.MemoryView":198 - * info.ndim = self.ndim - * info.shape = self._shape - * info.strides = self._strides # <<<<<<<<<<<<<< - * info.suboffsets = NULL - * info.itemsize = self.itemsize - */ - __pyx_t_7 = __pyx_v_self->_strides; - __pyx_v_info->strides = __pyx_t_7; - - /* "View.MemoryView":199 - * info.shape = self._shape - * info.strides = self._strides - * info.suboffsets = NULL # <<<<<<<<<<<<<< - * info.itemsize = self.itemsize - * info.readonly = 0 - */ - __pyx_v_info->suboffsets = NULL; - - /* "View.MemoryView":200 - * info.strides = self._strides - * info.suboffsets = NULL - * info.itemsize = self.itemsize # <<<<<<<<<<<<<< - * info.readonly = 0 - * - */ - __pyx_t_5 = __pyx_v_self->itemsize; - __pyx_v_info->itemsize = __pyx_t_5; - - /* "View.MemoryView":201 - * info.suboffsets = NULL - * info.itemsize = self.itemsize - * info.readonly = 0 # <<<<<<<<<<<<<< - * - * if flags & PyBUF_FORMAT: - */ - __pyx_v_info->readonly = 0; - - /* "View.MemoryView":203 - * info.readonly = 0 - * - * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< - * info.format = self.format - * else: - */ - __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":204 - * - * if flags & PyBUF_FORMAT: - * info.format = self.format # <<<<<<<<<<<<<< - * else: - * info.format = NULL - */ - __pyx_t_4 = __pyx_v_self->format; - __pyx_v_info->format = __pyx_t_4; - - /* "View.MemoryView":203 - * info.readonly = 0 - * - * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< - * info.format = self.format - * else: - */ - goto __pyx_L5; - } - - /* "View.MemoryView":206 - * info.format = self.format - * else: - * info.format = NULL # <<<<<<<<<<<<<< - * - * info.obj = self - */ - /*else*/ { - __pyx_v_info->format = NULL; - } - __pyx_L5:; - - /* "View.MemoryView":208 - * info.format = NULL - * - * info.obj = self # <<<<<<<<<<<<<< - * - * __pyx_getbuffer = capsule( &__pyx_array_getbuffer, "getbuffer(obj, view, flags)") - */ - __Pyx_INCREF(((PyObject *)__pyx_v_self)); - __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); - __Pyx_GOTREF(__pyx_v_info->obj); - __Pyx_DECREF(__pyx_v_info->obj); - __pyx_v_info->obj = ((PyObject *)__pyx_v_self); - - /* "View.MemoryView":186 - * - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): # <<<<<<<<<<<<<< - * cdef int bufmode = -1 - * if self.mode == u"c": - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.array.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - if (__pyx_v_info->obj != NULL) { - __Pyx_GOTREF(__pyx_v_info->obj); - __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; - } - goto __pyx_L2; - __pyx_L0:; - if (__pyx_v_info->obj == Py_None) { - __Pyx_GOTREF(__pyx_v_info->obj); - __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; - } - __pyx_L2:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":212 - * __pyx_getbuffer = capsule( &__pyx_array_getbuffer, "getbuffer(obj, view, flags)") - * - * def __dealloc__(array self): # <<<<<<<<<<<<<< - * if self.callback_free_data != NULL: - * self.callback_free_data(self.data) - */ - -/* Python wrapper */ -static void __pyx_array___dealloc__(PyObject *__pyx_v_self); /*proto*/ -static void __pyx_array___dealloc__(PyObject *__pyx_v_self) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); - __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(((struct __pyx_array_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -static void __pyx_array___pyx_pf_15View_dot_MemoryView_5array_4__dealloc__(struct __pyx_array_obj *__pyx_v_self) { - __Pyx_RefNannyDeclarations - int __pyx_t_1; - __Pyx_RefNannySetupContext("__dealloc__", 0); - - /* "View.MemoryView":213 - * - * def __dealloc__(array self): - * if self.callback_free_data != NULL: # <<<<<<<<<<<<<< - * self.callback_free_data(self.data) - * elif self.free_data: - */ - __pyx_t_1 = ((__pyx_v_self->callback_free_data != NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":214 - * def __dealloc__(array self): - * if self.callback_free_data != NULL: - * self.callback_free_data(self.data) # <<<<<<<<<<<<<< - * elif self.free_data: - * if self.dtype_is_object: - */ - __pyx_v_self->callback_free_data(__pyx_v_self->data); - - /* "View.MemoryView":213 - * - * def __dealloc__(array self): - * if self.callback_free_data != NULL: # <<<<<<<<<<<<<< - * self.callback_free_data(self.data) - * elif self.free_data: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":215 - * if self.callback_free_data != NULL: - * self.callback_free_data(self.data) - * elif self.free_data: # <<<<<<<<<<<<<< - * if self.dtype_is_object: - * refcount_objects_in_slice(self.data, self._shape, - */ - __pyx_t_1 = (__pyx_v_self->free_data != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":216 - * self.callback_free_data(self.data) - * elif self.free_data: - * if self.dtype_is_object: # <<<<<<<<<<<<<< - * refcount_objects_in_slice(self.data, self._shape, - * self._strides, self.ndim, False) - */ - __pyx_t_1 = (__pyx_v_self->dtype_is_object != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":217 - * elif self.free_data: - * if self.dtype_is_object: - * refcount_objects_in_slice(self.data, self._shape, # <<<<<<<<<<<<<< - * self._strides, self.ndim, False) - * free(self.data) - */ - __pyx_memoryview_refcount_objects_in_slice(__pyx_v_self->data, __pyx_v_self->_shape, __pyx_v_self->_strides, __pyx_v_self->ndim, 0); - - /* "View.MemoryView":216 - * self.callback_free_data(self.data) - * elif self.free_data: - * if self.dtype_is_object: # <<<<<<<<<<<<<< - * refcount_objects_in_slice(self.data, self._shape, - * self._strides, self.ndim, False) - */ - } - - /* "View.MemoryView":219 - * refcount_objects_in_slice(self.data, self._shape, - * self._strides, self.ndim, False) - * free(self.data) # <<<<<<<<<<<<<< - * PyObject_Free(self._shape) - * - */ - free(__pyx_v_self->data); - - /* "View.MemoryView":215 - * if self.callback_free_data != NULL: - * self.callback_free_data(self.data) - * elif self.free_data: # <<<<<<<<<<<<<< - * if self.dtype_is_object: - * refcount_objects_in_slice(self.data, self._shape, - */ - } - __pyx_L3:; - - /* "View.MemoryView":220 - * self._strides, self.ndim, False) - * free(self.data) - * PyObject_Free(self._shape) # <<<<<<<<<<<<<< - * - * @property - */ - PyObject_Free(__pyx_v_self->_shape); - - /* "View.MemoryView":212 - * __pyx_getbuffer = capsule( &__pyx_array_getbuffer, "getbuffer(obj, view, flags)") - * - * def __dealloc__(array self): # <<<<<<<<<<<<<< - * if self.callback_free_data != NULL: - * self.callback_free_data(self.data) - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -/* "View.MemoryView":223 - * - * @property - * def memview(self): # <<<<<<<<<<<<<< - * return self.get_memview() - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_5array_7memview_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_5array_7memview_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_5array_7memview___get__(((struct __pyx_array_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_5array_7memview___get__(struct __pyx_array_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":224 - * @property - * def memview(self): - * return self.get_memview() # <<<<<<<<<<<<<< - * - * @cname('get_memview') - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = ((struct __pyx_vtabstruct_array *)__pyx_v_self->__pyx_vtab)->get_memview(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 224, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "View.MemoryView":223 - * - * @property - * def memview(self): # <<<<<<<<<<<<<< - * return self.get_memview() - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.array.memview.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":227 - * - * @cname('get_memview') - * cdef get_memview(self): # <<<<<<<<<<<<<< - * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE - * return memoryview(self, flags, self.dtype_is_object) - */ - -static PyObject *__pyx_array_get_memview(struct __pyx_array_obj *__pyx_v_self) { - int __pyx_v_flags; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("get_memview", 0); - - /* "View.MemoryView":228 - * @cname('get_memview') - * cdef get_memview(self): - * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE # <<<<<<<<<<<<<< - * return memoryview(self, flags, self.dtype_is_object) - * - */ - __pyx_v_flags = ((PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT) | PyBUF_WRITABLE); - - /* "View.MemoryView":229 - * cdef get_memview(self): - * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE - * return memoryview(self, flags, self.dtype_is_object) # <<<<<<<<<<<<<< - * - * def __len__(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 229, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_self->dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 229, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 229, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(((PyObject *)__pyx_v_self)); - __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); - PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_v_self)); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2); - __pyx_t_1 = 0; - __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryview_type), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 229, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":227 - * - * @cname('get_memview') - * cdef get_memview(self): # <<<<<<<<<<<<<< - * flags = PyBUF_ANY_CONTIGUOUS|PyBUF_FORMAT|PyBUF_WRITABLE - * return memoryview(self, flags, self.dtype_is_object) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.array.get_memview", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":231 - * return memoryview(self, flags, self.dtype_is_object) - * - * def __len__(self): # <<<<<<<<<<<<<< - * return self._shape[0] - * - */ - -/* Python wrapper */ -static Py_ssize_t __pyx_array___len__(PyObject *__pyx_v_self); /*proto*/ -static Py_ssize_t __pyx_array___len__(PyObject *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__len__ (wrapper)", 0); - __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_6__len__(((struct __pyx_array_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static Py_ssize_t __pyx_array___pyx_pf_15View_dot_MemoryView_5array_6__len__(struct __pyx_array_obj *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__len__", 0); - - /* "View.MemoryView":232 - * - * def __len__(self): - * return self._shape[0] # <<<<<<<<<<<<<< - * - * def __getattr__(self, attr): - */ - __pyx_r = (__pyx_v_self->_shape[0]); - goto __pyx_L0; - - /* "View.MemoryView":231 - * return memoryview(self, flags, self.dtype_is_object) - * - * def __len__(self): # <<<<<<<<<<<<<< - * return self._shape[0] - * - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":234 - * return self._shape[0] - * - * def __getattr__(self, attr): # <<<<<<<<<<<<<< - * return getattr(self.memview, attr) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_array___getattr__(PyObject *__pyx_v_self, PyObject *__pyx_v_attr); /*proto*/ -static PyObject *__pyx_array___getattr__(PyObject *__pyx_v_self, PyObject *__pyx_v_attr) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getattr__ (wrapper)", 0); - __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v_attr)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_8__getattr__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_attr) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__getattr__", 0); - - /* "View.MemoryView":235 - * - * def __getattr__(self, attr): - * return getattr(self.memview, attr) # <<<<<<<<<<<<<< - * - * def __getitem__(self, item): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_memview); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 235, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_GetAttr(__pyx_t_1, __pyx_v_attr); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 235, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":234 - * return self._shape[0] - * - * def __getattr__(self, attr): # <<<<<<<<<<<<<< - * return getattr(self.memview, attr) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.array.__getattr__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":237 - * return getattr(self.memview, attr) - * - * def __getitem__(self, item): # <<<<<<<<<<<<<< - * return self.memview[item] - * - */ - -/* Python wrapper */ -static PyObject *__pyx_array___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item); /*proto*/ -static PyObject *__pyx_array___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); - __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v_item)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_array___pyx_pf_15View_dot_MemoryView_5array_10__getitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__getitem__", 0); - - /* "View.MemoryView":238 - * - * def __getitem__(self, item): - * return self.memview[item] # <<<<<<<<<<<<<< - * - * def __setitem__(self, item, value): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_memview); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 238, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_v_item); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 238, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":237 - * return getattr(self.memview, attr) - * - * def __getitem__(self, item): # <<<<<<<<<<<<<< - * return self.memview[item] - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.array.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":240 - * return self.memview[item] - * - * def __setitem__(self, item, value): # <<<<<<<<<<<<<< - * self.memview[item] = value - * - */ - -/* Python wrapper */ -static int __pyx_array___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value); /*proto*/ -static int __pyx_array___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0); - __pyx_r = __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v_item), ((PyObject *)__pyx_v_value)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_array___pyx_pf_15View_dot_MemoryView_5array_12__setitem__(struct __pyx_array_obj *__pyx_v_self, PyObject *__pyx_v_item, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setitem__", 0); - - /* "View.MemoryView":241 - * - * def __setitem__(self, item, value): - * self.memview[item] = value # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_memview); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 241, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (unlikely(PyObject_SetItem(__pyx_t_1, __pyx_v_item, __pyx_v_value) < 0)) __PYX_ERR(2, 241, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "View.MemoryView":240 - * return self.memview[item] - * - * def __setitem__(self, item, value): # <<<<<<<<<<<<<< - * self.memview[item] = value - * - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.array.__setitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_array_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw___pyx_array_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_array___reduce_cython__(((struct __pyx_array_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_array___reduce_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__reduce_cython__", 0); - - /* "(tree fragment)":2 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 2, __pyx_L1_error) - - /* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.array.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":3 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_array_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ -static PyObject *__pyx_pw___pyx_array_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_array_2__setstate_cython__(((struct __pyx_array_obj *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_array_2__setstate_cython__(CYTHON_UNUSED struct __pyx_array_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setstate_cython__", 0); - - /* "(tree fragment)":4 - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 4, __pyx_L1_error) - - /* "(tree fragment)":3 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.array.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":245 - * - * @cname("__pyx_array_new") - * cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, # <<<<<<<<<<<<<< - * char *mode, char *buf): - * cdef array result - */ - -static struct __pyx_array_obj *__pyx_array_new(PyObject *__pyx_v_shape, Py_ssize_t __pyx_v_itemsize, char *__pyx_v_format, char *__pyx_v_mode, char *__pyx_v_buf) { - struct __pyx_array_obj *__pyx_v_result = 0; - struct __pyx_array_obj *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("array_cwrapper", 0); - - /* "View.MemoryView":249 - * cdef array result - * - * if buf == NULL: # <<<<<<<<<<<<<< - * result = array(shape, itemsize, format, mode.decode('ASCII')) - * else: - */ - __pyx_t_1 = ((__pyx_v_buf == NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":250 - * - * if buf == NULL: - * result = array(shape, itemsize, format, mode.decode('ASCII')) # <<<<<<<<<<<<<< - * else: - * result = array(shape, itemsize, format, mode.decode('ASCII'), - */ - __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_itemsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 250, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_format); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 250, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __Pyx_decode_c_string(__pyx_v_mode, 0, strlen(__pyx_v_mode), NULL, NULL, PyUnicode_DecodeASCII); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 250, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyTuple_New(4); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 250, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_INCREF(__pyx_v_shape); - __Pyx_GIVEREF(__pyx_v_shape); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_shape); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_5, 3, __pyx_t_4); - __pyx_t_2 = 0; - __pyx_t_3 = 0; - __pyx_t_4 = 0; - __pyx_t_4 = __Pyx_PyObject_Call(((PyObject *)__pyx_array_type), __pyx_t_5, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 250, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_v_result = ((struct __pyx_array_obj *)__pyx_t_4); - __pyx_t_4 = 0; - - /* "View.MemoryView":249 - * cdef array result - * - * if buf == NULL: # <<<<<<<<<<<<<< - * result = array(shape, itemsize, format, mode.decode('ASCII')) - * else: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":252 - * result = array(shape, itemsize, format, mode.decode('ASCII')) - * else: - * result = array(shape, itemsize, format, mode.decode('ASCII'), # <<<<<<<<<<<<<< - * allocate_buffer=False) - * result.data = buf - */ - /*else*/ { - __pyx_t_4 = PyInt_FromSsize_t(__pyx_v_itemsize); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 252, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = __Pyx_PyBytes_FromString(__pyx_v_format); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 252, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_mode, 0, strlen(__pyx_v_mode), NULL, NULL, PyUnicode_DecodeASCII); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 252, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = PyTuple_New(4); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 252, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_INCREF(__pyx_v_shape); - __Pyx_GIVEREF(__pyx_v_shape); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_shape); - __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_4); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_2, 3, __pyx_t_3); - __pyx_t_4 = 0; - __pyx_t_5 = 0; - __pyx_t_3 = 0; - - /* "View.MemoryView":253 - * else: - * result = array(shape, itemsize, format, mode.decode('ASCII'), - * allocate_buffer=False) # <<<<<<<<<<<<<< - * result.data = buf - * - */ - __pyx_t_3 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 253, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if (PyDict_SetItem(__pyx_t_3, __pyx_n_s_allocate_buffer, Py_False) < 0) __PYX_ERR(2, 253, __pyx_L1_error) - - /* "View.MemoryView":252 - * result = array(shape, itemsize, format, mode.decode('ASCII')) - * else: - * result = array(shape, itemsize, format, mode.decode('ASCII'), # <<<<<<<<<<<<<< - * allocate_buffer=False) - * result.data = buf - */ - __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)__pyx_array_type), __pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 252, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_result = ((struct __pyx_array_obj *)__pyx_t_5); - __pyx_t_5 = 0; - - /* "View.MemoryView":254 - * result = array(shape, itemsize, format, mode.decode('ASCII'), - * allocate_buffer=False) - * result.data = buf # <<<<<<<<<<<<<< - * - * return result - */ - __pyx_v_result->data = __pyx_v_buf; - } - __pyx_L3:; - - /* "View.MemoryView":256 - * result.data = buf - * - * return result # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(((PyObject *)__pyx_r)); - __Pyx_INCREF(((PyObject *)__pyx_v_result)); - __pyx_r = __pyx_v_result; - goto __pyx_L0; - - /* "View.MemoryView":245 - * - * @cname("__pyx_array_new") - * cdef array array_cwrapper(tuple shape, Py_ssize_t itemsize, char *format, # <<<<<<<<<<<<<< - * char *mode, char *buf): - * cdef array result - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.array_cwrapper", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF((PyObject *)__pyx_v_result); - __Pyx_XGIVEREF((PyObject *)__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":282 - * cdef class Enum(object): - * cdef object name - * def __init__(self, name): # <<<<<<<<<<<<<< - * self.name = name - * def __repr__(self): - */ - -/* Python wrapper */ -static int __pyx_MemviewEnum___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_MemviewEnum___init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_name = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__init__ (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_name,0}; - PyObject* values[1] = {0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_name)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(2, 282, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 1) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - } - __pyx_v_name = values[0]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 282, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("View.MemoryView.Enum.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return -1; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum___init__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self), __pyx_v_name); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum___init__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v_name) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__init__", 0); - - /* "View.MemoryView":283 - * cdef object name - * def __init__(self, name): - * self.name = name # <<<<<<<<<<<<<< - * def __repr__(self): - * return self.name - */ - __Pyx_INCREF(__pyx_v_name); - __Pyx_GIVEREF(__pyx_v_name); - __Pyx_GOTREF(__pyx_v_self->name); - __Pyx_DECREF(__pyx_v_self->name); - __pyx_v_self->name = __pyx_v_name; - - /* "View.MemoryView":282 - * cdef class Enum(object): - * cdef object name - * def __init__(self, name): # <<<<<<<<<<<<<< - * self.name = name - * def __repr__(self): - */ - - /* function exit code */ - __pyx_r = 0; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":284 - * def __init__(self, name): - * self.name = name - * def __repr__(self): # <<<<<<<<<<<<<< - * return self.name - * - */ - -/* Python wrapper */ -static PyObject *__pyx_MemviewEnum___repr__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_MemviewEnum___repr__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); - __pyx_r = __pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum_2__repr__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_MemviewEnum___pyx_pf_15View_dot_MemoryView_4Enum_2__repr__(struct __pyx_MemviewEnum_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__repr__", 0); - - /* "View.MemoryView":285 - * self.name = name - * def __repr__(self): - * return self.name # <<<<<<<<<<<<<< - * - * cdef generic = Enum("") - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_self->name); - __pyx_r = __pyx_v_self->name; - goto __pyx_L0; - - /* "View.MemoryView":284 - * def __init__(self, name): - * self.name = name - * def __repr__(self): # <<<<<<<<<<<<<< - * return self.name - * - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * cdef tuple state - * cdef object _dict - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_MemviewEnum_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw___pyx_MemviewEnum_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_MemviewEnum___reduce_cython__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_MemviewEnum___reduce_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self) { - PyObject *__pyx_v_state = 0; - PyObject *__pyx_v__dict = 0; - int __pyx_v_use_setstate; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__reduce_cython__", 0); - - /* "(tree fragment)":5 - * cdef object _dict - * cdef bint use_setstate - * state = (self.name,) # <<<<<<<<<<<<<< - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: - */ - __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_self->name); - __Pyx_GIVEREF(__pyx_v_self->name); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->name); - __pyx_v_state = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "(tree fragment)":6 - * cdef bint use_setstate - * state = (self.name,) - * _dict = getattr(self, '__dict__', None) # <<<<<<<<<<<<<< - * if _dict is not None: - * state += (_dict,) - */ - __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v__dict = __pyx_t_1; - __pyx_t_1 = 0; - - /* "(tree fragment)":7 - * state = (self.name,) - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: # <<<<<<<<<<<<<< - * state += (_dict,) - * use_setstate = True - */ - __pyx_t_2 = (__pyx_v__dict != Py_None); - __pyx_t_3 = (__pyx_t_2 != 0); - if (__pyx_t_3) { - - /* "(tree fragment)":8 - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: - * state += (_dict,) # <<<<<<<<<<<<<< - * use_setstate = True - * else: - */ - __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v__dict); - __Pyx_GIVEREF(__pyx_v__dict); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict); - __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 8, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - - /* "(tree fragment)":9 - * if _dict is not None: - * state += (_dict,) - * use_setstate = True # <<<<<<<<<<<<<< - * else: - * use_setstate = self.name is not None - */ - __pyx_v_use_setstate = 1; - - /* "(tree fragment)":7 - * state = (self.name,) - * _dict = getattr(self, '__dict__', None) - * if _dict is not None: # <<<<<<<<<<<<<< - * state += (_dict,) - * use_setstate = True - */ - goto __pyx_L3; - } - - /* "(tree fragment)":11 - * use_setstate = True - * else: - * use_setstate = self.name is not None # <<<<<<<<<<<<<< - * if use_setstate: - * return __pyx_unpickle_Enum, (type(self), 0xb068931, None), state - */ - /*else*/ { - __pyx_t_3 = (__pyx_v_self->name != Py_None); - __pyx_v_use_setstate = __pyx_t_3; - } - __pyx_L3:; - - /* "(tree fragment)":12 - * else: - * use_setstate = self.name is not None - * if use_setstate: # <<<<<<<<<<<<<< - * return __pyx_unpickle_Enum, (type(self), 0xb068931, None), state - * else: - */ - __pyx_t_3 = (__pyx_v_use_setstate != 0); - if (__pyx_t_3) { - - /* "(tree fragment)":13 - * use_setstate = self.name is not None - * if use_setstate: - * return __pyx_unpickle_Enum, (type(self), 0xb068931, None), state # <<<<<<<<<<<<<< - * else: - * return __pyx_unpickle_Enum, (type(self), 0xb068931, state) - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_Enum); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_INCREF(__pyx_int_184977713); - __Pyx_GIVEREF(__pyx_int_184977713); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_184977713); - __Pyx_INCREF(Py_None); - __Pyx_GIVEREF(Py_None); - PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None); - __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 13, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1); - __Pyx_INCREF(__pyx_v_state); - __Pyx_GIVEREF(__pyx_v_state); - PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state); - __pyx_t_4 = 0; - __pyx_t_1 = 0; - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; - goto __pyx_L0; - - /* "(tree fragment)":12 - * else: - * use_setstate = self.name is not None - * if use_setstate: # <<<<<<<<<<<<<< - * return __pyx_unpickle_Enum, (type(self), 0xb068931, None), state - * else: - */ - } - - /* "(tree fragment)":15 - * return __pyx_unpickle_Enum, (type(self), 0xb068931, None), state - * else: - * return __pyx_unpickle_Enum, (type(self), 0xb068931, state) # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * __pyx_unpickle_Enum__set_state(self, __pyx_state) - */ - /*else*/ { - __Pyx_XDECREF(__pyx_r); - __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_Enum); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self)))); - __Pyx_INCREF(__pyx_int_184977713); - __Pyx_GIVEREF(__pyx_int_184977713); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_184977713); - __Pyx_INCREF(__pyx_v_state); - __Pyx_GIVEREF(__pyx_v_state); - PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state); - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 15, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1); - __pyx_t_5 = 0; - __pyx_t_1 = 0; - __pyx_r = __pyx_t_4; - __pyx_t_4 = 0; - goto __pyx_L0; - } - - /* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * cdef tuple state - * cdef object _dict - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.Enum.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_state); - __Pyx_XDECREF(__pyx_v__dict); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":16 - * else: - * return __pyx_unpickle_Enum, (type(self), 0xb068931, state) - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * __pyx_unpickle_Enum__set_state(self, __pyx_state) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_MemviewEnum_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ -static PyObject *__pyx_pw___pyx_MemviewEnum_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_MemviewEnum_2__setstate_cython__(((struct __pyx_MemviewEnum_obj *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_MemviewEnum_2__setstate_cython__(struct __pyx_MemviewEnum_obj *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setstate_cython__", 0); - - /* "(tree fragment)":17 - * return __pyx_unpickle_Enum, (type(self), 0xb068931, state) - * def __setstate_cython__(self, __pyx_state): - * __pyx_unpickle_Enum__set_state(self, __pyx_state) # <<<<<<<<<<<<<< - */ - if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||((void)PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 17, __pyx_L1_error) - __pyx_t_1 = __pyx_unpickle_Enum__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 17, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":16 - * else: - * return __pyx_unpickle_Enum, (type(self), 0xb068931, state) - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * __pyx_unpickle_Enum__set_state(self, __pyx_state) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.Enum.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":299 - * - * @cname('__pyx_align_pointer') - * cdef void *align_pointer(void *memory, size_t alignment) nogil: # <<<<<<<<<<<<<< - * "Align pointer memory on a given boundary" - * cdef Py_intptr_t aligned_p = memory - */ - -static void *__pyx_align_pointer(void *__pyx_v_memory, size_t __pyx_v_alignment) { - Py_intptr_t __pyx_v_aligned_p; - size_t __pyx_v_offset; - void *__pyx_r; - int __pyx_t_1; - - /* "View.MemoryView":301 - * cdef void *align_pointer(void *memory, size_t alignment) nogil: - * "Align pointer memory on a given boundary" - * cdef Py_intptr_t aligned_p = memory # <<<<<<<<<<<<<< - * cdef size_t offset - * - */ - __pyx_v_aligned_p = ((Py_intptr_t)__pyx_v_memory); - - /* "View.MemoryView":305 - * - * with cython.cdivision(True): - * offset = aligned_p % alignment # <<<<<<<<<<<<<< - * - * if offset > 0: - */ - __pyx_v_offset = (__pyx_v_aligned_p % __pyx_v_alignment); - - /* "View.MemoryView":307 - * offset = aligned_p % alignment - * - * if offset > 0: # <<<<<<<<<<<<<< - * aligned_p += alignment - offset - * - */ - __pyx_t_1 = ((__pyx_v_offset > 0) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":308 - * - * if offset > 0: - * aligned_p += alignment - offset # <<<<<<<<<<<<<< - * - * return aligned_p - */ - __pyx_v_aligned_p = (__pyx_v_aligned_p + (__pyx_v_alignment - __pyx_v_offset)); - - /* "View.MemoryView":307 - * offset = aligned_p % alignment - * - * if offset > 0: # <<<<<<<<<<<<<< - * aligned_p += alignment - offset - * - */ - } - - /* "View.MemoryView":310 - * aligned_p += alignment - offset - * - * return aligned_p # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = ((void *)__pyx_v_aligned_p); - goto __pyx_L0; - - /* "View.MemoryView":299 - * - * @cname('__pyx_align_pointer') - * cdef void *align_pointer(void *memory, size_t alignment) nogil: # <<<<<<<<<<<<<< - * "Align pointer memory on a given boundary" - * cdef Py_intptr_t aligned_p = memory - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":346 - * cdef __Pyx_TypeInfo *typeinfo - * - * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): # <<<<<<<<<<<<<< - * self.obj = obj - * self.flags = flags - */ - -/* Python wrapper */ -static int __pyx_memoryview___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static int __pyx_memoryview___cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_obj = 0; - int __pyx_v_flags; - int __pyx_v_dtype_is_object; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_obj,&__pyx_n_s_flags,&__pyx_n_s_dtype_is_object,0}; - PyObject* values[3] = {0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_obj)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_flags)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 2, 3, 1); __PYX_ERR(2, 346, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (kw_args > 0) { - PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_dtype_is_object); - if (value) { values[2] = value; kw_args--; } - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) __PYX_ERR(2, 346, __pyx_L3_error) - } - } else { - switch (PyTuple_GET_SIZE(__pyx_args)) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - break; - default: goto __pyx_L5_argtuple_error; - } - } - __pyx_v_obj = values[0]; - __pyx_v_flags = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_flags == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 346, __pyx_L3_error) - if (values[2]) { - __pyx_v_dtype_is_object = __Pyx_PyObject_IsTrue(values[2]); if (unlikely((__pyx_v_dtype_is_object == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 346, __pyx_L3_error) - } else { - __pyx_v_dtype_is_object = ((int)0); - } - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 2, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 346, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("View.MemoryView.memoryview.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return -1; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit__(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v_obj, __pyx_v_flags, __pyx_v_dtype_is_object); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview___cinit__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj, int __pyx_v_flags, int __pyx_v_dtype_is_object) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__cinit__", 0); - - /* "View.MemoryView":347 - * - * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): - * self.obj = obj # <<<<<<<<<<<<<< - * self.flags = flags - * if type(self) is memoryview or obj is not None: - */ - __Pyx_INCREF(__pyx_v_obj); - __Pyx_GIVEREF(__pyx_v_obj); - __Pyx_GOTREF(__pyx_v_self->obj); - __Pyx_DECREF(__pyx_v_self->obj); - __pyx_v_self->obj = __pyx_v_obj; - - /* "View.MemoryView":348 - * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): - * self.obj = obj - * self.flags = flags # <<<<<<<<<<<<<< - * if type(self) is memoryview or obj is not None: - * __Pyx_GetBuffer(obj, &self.view, flags) - */ - __pyx_v_self->flags = __pyx_v_flags; - - /* "View.MemoryView":349 - * self.obj = obj - * self.flags = flags - * if type(self) is memoryview or obj is not None: # <<<<<<<<<<<<<< - * __Pyx_GetBuffer(obj, &self.view, flags) - * if self.view.obj == NULL: - */ - __pyx_t_2 = (((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))) == ((PyObject *)__pyx_memoryview_type)); - __pyx_t_3 = (__pyx_t_2 != 0); - if (!__pyx_t_3) { - } else { - __pyx_t_1 = __pyx_t_3; - goto __pyx_L4_bool_binop_done; - } - __pyx_t_3 = (__pyx_v_obj != Py_None); - __pyx_t_2 = (__pyx_t_3 != 0); - __pyx_t_1 = __pyx_t_2; - __pyx_L4_bool_binop_done:; - if (__pyx_t_1) { - - /* "View.MemoryView":350 - * self.flags = flags - * if type(self) is memoryview or obj is not None: - * __Pyx_GetBuffer(obj, &self.view, flags) # <<<<<<<<<<<<<< - * if self.view.obj == NULL: - * (<__pyx_buffer *> &self.view).obj = Py_None - */ - __pyx_t_4 = __Pyx_GetBuffer(__pyx_v_obj, (&__pyx_v_self->view), __pyx_v_flags); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 350, __pyx_L1_error) - - /* "View.MemoryView":351 - * if type(self) is memoryview or obj is not None: - * __Pyx_GetBuffer(obj, &self.view, flags) - * if self.view.obj == NULL: # <<<<<<<<<<<<<< - * (<__pyx_buffer *> &self.view).obj = Py_None - * Py_INCREF(Py_None) - */ - __pyx_t_1 = ((((PyObject *)__pyx_v_self->view.obj) == NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":352 - * __Pyx_GetBuffer(obj, &self.view, flags) - * if self.view.obj == NULL: - * (<__pyx_buffer *> &self.view).obj = Py_None # <<<<<<<<<<<<<< - * Py_INCREF(Py_None) - * - */ - ((Py_buffer *)(&__pyx_v_self->view))->obj = Py_None; - - /* "View.MemoryView":353 - * if self.view.obj == NULL: - * (<__pyx_buffer *> &self.view).obj = Py_None - * Py_INCREF(Py_None) # <<<<<<<<<<<<<< - * - * if not __PYX_CYTHON_ATOMICS_ENABLED(): - */ - Py_INCREF(Py_None); - - /* "View.MemoryView":351 - * if type(self) is memoryview or obj is not None: - * __Pyx_GetBuffer(obj, &self.view, flags) - * if self.view.obj == NULL: # <<<<<<<<<<<<<< - * (<__pyx_buffer *> &self.view).obj = Py_None - * Py_INCREF(Py_None) - */ - } - - /* "View.MemoryView":349 - * self.obj = obj - * self.flags = flags - * if type(self) is memoryview or obj is not None: # <<<<<<<<<<<<<< - * __Pyx_GetBuffer(obj, &self.view, flags) - * if self.view.obj == NULL: - */ - } - - /* "View.MemoryView":355 - * Py_INCREF(Py_None) - * - * if not __PYX_CYTHON_ATOMICS_ENABLED(): # <<<<<<<<<<<<<< - * global __pyx_memoryview_thread_locks_used - * if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED: - */ - __pyx_t_1 = ((!(__PYX_CYTHON_ATOMICS_ENABLED() != 0)) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":357 - * if not __PYX_CYTHON_ATOMICS_ENABLED(): - * global __pyx_memoryview_thread_locks_used - * if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED: # <<<<<<<<<<<<<< - * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] - * __pyx_memoryview_thread_locks_used += 1 - */ - __pyx_t_1 = ((__pyx_memoryview_thread_locks_used < 8) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":358 - * global __pyx_memoryview_thread_locks_used - * if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED: - * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] # <<<<<<<<<<<<<< - * __pyx_memoryview_thread_locks_used += 1 - * if self.lock is NULL: - */ - __pyx_v_self->lock = (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]); - - /* "View.MemoryView":359 - * if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED: - * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] - * __pyx_memoryview_thread_locks_used += 1 # <<<<<<<<<<<<<< - * if self.lock is NULL: - * self.lock = PyThread_allocate_lock() - */ - __pyx_memoryview_thread_locks_used = (__pyx_memoryview_thread_locks_used + 1); - - /* "View.MemoryView":357 - * if not __PYX_CYTHON_ATOMICS_ENABLED(): - * global __pyx_memoryview_thread_locks_used - * if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED: # <<<<<<<<<<<<<< - * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] - * __pyx_memoryview_thread_locks_used += 1 - */ - } - - /* "View.MemoryView":360 - * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] - * __pyx_memoryview_thread_locks_used += 1 - * if self.lock is NULL: # <<<<<<<<<<<<<< - * self.lock = PyThread_allocate_lock() - * if self.lock is NULL: - */ - __pyx_t_1 = ((__pyx_v_self->lock == NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":361 - * __pyx_memoryview_thread_locks_used += 1 - * if self.lock is NULL: - * self.lock = PyThread_allocate_lock() # <<<<<<<<<<<<<< - * if self.lock is NULL: - * raise MemoryError - */ - __pyx_v_self->lock = PyThread_allocate_lock(); - - /* "View.MemoryView":362 - * if self.lock is NULL: - * self.lock = PyThread_allocate_lock() - * if self.lock is NULL: # <<<<<<<<<<<<<< - * raise MemoryError - * - */ - __pyx_t_1 = ((__pyx_v_self->lock == NULL) != 0); - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":363 - * self.lock = PyThread_allocate_lock() - * if self.lock is NULL: - * raise MemoryError # <<<<<<<<<<<<<< - * - * if flags & PyBUF_FORMAT: - */ - PyErr_NoMemory(); __PYX_ERR(2, 363, __pyx_L1_error) - - /* "View.MemoryView":362 - * if self.lock is NULL: - * self.lock = PyThread_allocate_lock() - * if self.lock is NULL: # <<<<<<<<<<<<<< - * raise MemoryError - * - */ - } - - /* "View.MemoryView":360 - * self.lock = __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] - * __pyx_memoryview_thread_locks_used += 1 - * if self.lock is NULL: # <<<<<<<<<<<<<< - * self.lock = PyThread_allocate_lock() - * if self.lock is NULL: - */ - } - - /* "View.MemoryView":355 - * Py_INCREF(Py_None) - * - * if not __PYX_CYTHON_ATOMICS_ENABLED(): # <<<<<<<<<<<<<< - * global __pyx_memoryview_thread_locks_used - * if __pyx_memoryview_thread_locks_used < THREAD_LOCKS_PREALLOCATED: - */ - } - - /* "View.MemoryView":365 - * raise MemoryError - * - * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< - * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') - * else: - */ - __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":366 - * - * if flags & PyBUF_FORMAT: - * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') # <<<<<<<<<<<<<< - * else: - * self.dtype_is_object = dtype_is_object - */ - __pyx_t_2 = (((__pyx_v_self->view.format[0]) == 'O') != 0); - if (__pyx_t_2) { - } else { - __pyx_t_1 = __pyx_t_2; - goto __pyx_L12_bool_binop_done; - } - __pyx_t_2 = (((__pyx_v_self->view.format[1]) == '\x00') != 0); - __pyx_t_1 = __pyx_t_2; - __pyx_L12_bool_binop_done:; - __pyx_v_self->dtype_is_object = __pyx_t_1; - - /* "View.MemoryView":365 - * raise MemoryError - * - * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< - * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') - * else: - */ - goto __pyx_L11; - } - - /* "View.MemoryView":368 - * self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') - * else: - * self.dtype_is_object = dtype_is_object # <<<<<<<<<<<<<< - * - * self.acquisition_count_aligned_p = <__pyx_atomic_int *> align_pointer( - */ - /*else*/ { - __pyx_v_self->dtype_is_object = __pyx_v_dtype_is_object; - } - __pyx_L11:; - - /* "View.MemoryView":370 - * self.dtype_is_object = dtype_is_object - * - * self.acquisition_count_aligned_p = <__pyx_atomic_int *> align_pointer( # <<<<<<<<<<<<<< - * &self.acquisition_count[0], sizeof(__pyx_atomic_int)) - * self.typeinfo = NULL - */ - __pyx_v_self->acquisition_count_aligned_p = ((__pyx_atomic_int *)__pyx_align_pointer(((void *)(&(__pyx_v_self->acquisition_count[0]))), (sizeof(__pyx_atomic_int)))); - - /* "View.MemoryView":372 - * self.acquisition_count_aligned_p = <__pyx_atomic_int *> align_pointer( - * &self.acquisition_count[0], sizeof(__pyx_atomic_int)) - * self.typeinfo = NULL # <<<<<<<<<<<<<< - * - * def __dealloc__(memoryview self): - */ - __pyx_v_self->typeinfo = NULL; - - /* "View.MemoryView":346 - * cdef __Pyx_TypeInfo *typeinfo - * - * def __cinit__(memoryview self, object obj, int flags, bint dtype_is_object=False): # <<<<<<<<<<<<<< - * self.obj = obj - * self.flags = flags - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_AddTraceback("View.MemoryView.memoryview.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":374 - * self.typeinfo = NULL - * - * def __dealloc__(memoryview self): # <<<<<<<<<<<<<< - * if self.obj is not None: - * __Pyx_ReleaseBuffer(&self.view) - */ - -/* Python wrapper */ -static void __pyx_memoryview___dealloc__(PyObject *__pyx_v_self); /*proto*/ -static void __pyx_memoryview___dealloc__(PyObject *__pyx_v_self) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); - __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__dealloc__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -static void __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_2__dealloc__(struct __pyx_memoryview_obj *__pyx_v_self) { - int __pyx_v_i; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - int __pyx_t_5; - PyThread_type_lock __pyx_t_6; - PyThread_type_lock __pyx_t_7; - __Pyx_RefNannySetupContext("__dealloc__", 0); - - /* "View.MemoryView":375 - * - * def __dealloc__(memoryview self): - * if self.obj is not None: # <<<<<<<<<<<<<< - * __Pyx_ReleaseBuffer(&self.view) - * elif (<__pyx_buffer *> &self.view).obj == Py_None: - */ - __pyx_t_1 = (__pyx_v_self->obj != Py_None); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":376 - * def __dealloc__(memoryview self): - * if self.obj is not None: - * __Pyx_ReleaseBuffer(&self.view) # <<<<<<<<<<<<<< - * elif (<__pyx_buffer *> &self.view).obj == Py_None: - * - */ - __Pyx_ReleaseBuffer((&__pyx_v_self->view)); - - /* "View.MemoryView":375 - * - * def __dealloc__(memoryview self): - * if self.obj is not None: # <<<<<<<<<<<<<< - * __Pyx_ReleaseBuffer(&self.view) - * elif (<__pyx_buffer *> &self.view).obj == Py_None: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":377 - * if self.obj is not None: - * __Pyx_ReleaseBuffer(&self.view) - * elif (<__pyx_buffer *> &self.view).obj == Py_None: # <<<<<<<<<<<<<< - * - * (<__pyx_buffer *> &self.view).obj = NULL - */ - __pyx_t_2 = ((((Py_buffer *)(&__pyx_v_self->view))->obj == Py_None) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":379 - * elif (<__pyx_buffer *> &self.view).obj == Py_None: - * - * (<__pyx_buffer *> &self.view).obj = NULL # <<<<<<<<<<<<<< - * Py_DECREF(Py_None) - * - */ - ((Py_buffer *)(&__pyx_v_self->view))->obj = NULL; - - /* "View.MemoryView":380 - * - * (<__pyx_buffer *> &self.view).obj = NULL - * Py_DECREF(Py_None) # <<<<<<<<<<<<<< - * - * cdef int i - */ - Py_DECREF(Py_None); - - /* "View.MemoryView":377 - * if self.obj is not None: - * __Pyx_ReleaseBuffer(&self.view) - * elif (<__pyx_buffer *> &self.view).obj == Py_None: # <<<<<<<<<<<<<< - * - * (<__pyx_buffer *> &self.view).obj = NULL - */ - } - __pyx_L3:; - - /* "View.MemoryView":384 - * cdef int i - * global __pyx_memoryview_thread_locks_used - * if self.lock != NULL: # <<<<<<<<<<<<<< - * for i in range(__pyx_memoryview_thread_locks_used): - * if __pyx_memoryview_thread_locks[i] is self.lock: - */ - __pyx_t_2 = ((__pyx_v_self->lock != NULL) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":385 - * global __pyx_memoryview_thread_locks_used - * if self.lock != NULL: - * for i in range(__pyx_memoryview_thread_locks_used): # <<<<<<<<<<<<<< - * if __pyx_memoryview_thread_locks[i] is self.lock: - * __pyx_memoryview_thread_locks_used -= 1 - */ - __pyx_t_3 = __pyx_memoryview_thread_locks_used; - __pyx_t_4 = __pyx_t_3; - for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { - __pyx_v_i = __pyx_t_5; - - /* "View.MemoryView":386 - * if self.lock != NULL: - * for i in range(__pyx_memoryview_thread_locks_used): - * if __pyx_memoryview_thread_locks[i] is self.lock: # <<<<<<<<<<<<<< - * __pyx_memoryview_thread_locks_used -= 1 - * if i != __pyx_memoryview_thread_locks_used: - */ - __pyx_t_2 = (((__pyx_memoryview_thread_locks[__pyx_v_i]) == __pyx_v_self->lock) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":387 - * for i in range(__pyx_memoryview_thread_locks_used): - * if __pyx_memoryview_thread_locks[i] is self.lock: - * __pyx_memoryview_thread_locks_used -= 1 # <<<<<<<<<<<<<< - * if i != __pyx_memoryview_thread_locks_used: - * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( - */ - __pyx_memoryview_thread_locks_used = (__pyx_memoryview_thread_locks_used - 1); - - /* "View.MemoryView":388 - * if __pyx_memoryview_thread_locks[i] is self.lock: - * __pyx_memoryview_thread_locks_used -= 1 - * if i != __pyx_memoryview_thread_locks_used: # <<<<<<<<<<<<<< - * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( - * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) - */ - __pyx_t_2 = ((__pyx_v_i != __pyx_memoryview_thread_locks_used) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":390 - * if i != __pyx_memoryview_thread_locks_used: - * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( - * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) # <<<<<<<<<<<<<< - * break - * else: - */ - __pyx_t_6 = (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]); - __pyx_t_7 = (__pyx_memoryview_thread_locks[__pyx_v_i]); - - /* "View.MemoryView":389 - * __pyx_memoryview_thread_locks_used -= 1 - * if i != __pyx_memoryview_thread_locks_used: - * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( # <<<<<<<<<<<<<< - * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) - * break - */ - (__pyx_memoryview_thread_locks[__pyx_v_i]) = __pyx_t_6; - (__pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used]) = __pyx_t_7; - - /* "View.MemoryView":388 - * if __pyx_memoryview_thread_locks[i] is self.lock: - * __pyx_memoryview_thread_locks_used -= 1 - * if i != __pyx_memoryview_thread_locks_used: # <<<<<<<<<<<<<< - * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( - * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) - */ - } - - /* "View.MemoryView":391 - * __pyx_memoryview_thread_locks[i], __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used] = ( - * __pyx_memoryview_thread_locks[__pyx_memoryview_thread_locks_used], __pyx_memoryview_thread_locks[i]) - * break # <<<<<<<<<<<<<< - * else: - * PyThread_free_lock(self.lock) - */ - goto __pyx_L6_break; - - /* "View.MemoryView":386 - * if self.lock != NULL: - * for i in range(__pyx_memoryview_thread_locks_used): - * if __pyx_memoryview_thread_locks[i] is self.lock: # <<<<<<<<<<<<<< - * __pyx_memoryview_thread_locks_used -= 1 - * if i != __pyx_memoryview_thread_locks_used: - */ - } - } - /*else*/ { - - /* "View.MemoryView":393 - * break - * else: - * PyThread_free_lock(self.lock) # <<<<<<<<<<<<<< - * - * cdef char *get_item_pointer(memoryview self, object index) except NULL: - */ - PyThread_free_lock(__pyx_v_self->lock); - } - __pyx_L6_break:; - - /* "View.MemoryView":384 - * cdef int i - * global __pyx_memoryview_thread_locks_used - * if self.lock != NULL: # <<<<<<<<<<<<<< - * for i in range(__pyx_memoryview_thread_locks_used): - * if __pyx_memoryview_thread_locks[i] is self.lock: - */ - } - - /* "View.MemoryView":374 - * self.typeinfo = NULL - * - * def __dealloc__(memoryview self): # <<<<<<<<<<<<<< - * if self.obj is not None: - * __Pyx_ReleaseBuffer(&self.view) - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -/* "View.MemoryView":395 - * PyThread_free_lock(self.lock) - * - * cdef char *get_item_pointer(memoryview self, object index) except NULL: # <<<<<<<<<<<<<< - * cdef Py_ssize_t dim - * cdef char *itemp = self.view.buf - */ - -static char *__pyx_memoryview_get_item_pointer(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index) { - Py_ssize_t __pyx_v_dim; - char *__pyx_v_itemp; - PyObject *__pyx_v_idx = NULL; - char *__pyx_r; - __Pyx_RefNannyDeclarations - Py_ssize_t __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - Py_ssize_t __pyx_t_3; - PyObject *(*__pyx_t_4)(PyObject *); - PyObject *__pyx_t_5 = NULL; - Py_ssize_t __pyx_t_6; - char *__pyx_t_7; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("get_item_pointer", 0); - - /* "View.MemoryView":397 - * cdef char *get_item_pointer(memoryview self, object index) except NULL: - * cdef Py_ssize_t dim - * cdef char *itemp = self.view.buf # <<<<<<<<<<<<<< - * - * for dim, idx in enumerate(index): - */ - __pyx_v_itemp = ((char *)__pyx_v_self->view.buf); - - /* "View.MemoryView":399 - * cdef char *itemp = self.view.buf - * - * for dim, idx in enumerate(index): # <<<<<<<<<<<<<< - * itemp = pybuffer_index(&self.view, itemp, idx, dim) - * - */ - __pyx_t_1 = 0; - if (likely(PyList_CheckExact(__pyx_v_index)) || PyTuple_CheckExact(__pyx_v_index)) { - __pyx_t_2 = __pyx_v_index; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0; - __pyx_t_4 = NULL; - } else { - __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 399, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 399, __pyx_L1_error) - } - for (;;) { - if (likely(!__pyx_t_4)) { - if (likely(PyList_CheckExact(__pyx_t_2))) { - if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(2, 399, __pyx_L1_error) - #else - __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 399, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - #endif - } else { - if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(2, 399, __pyx_L1_error) - #else - __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 399, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - #endif - } - } else { - __pyx_t_5 = __pyx_t_4(__pyx_t_2); - if (unlikely(!__pyx_t_5)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(2, 399, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_5); - } - __Pyx_XDECREF_SET(__pyx_v_idx, __pyx_t_5); - __pyx_t_5 = 0; - __pyx_v_dim = __pyx_t_1; - __pyx_t_1 = (__pyx_t_1 + 1); - - /* "View.MemoryView":400 - * - * for dim, idx in enumerate(index): - * itemp = pybuffer_index(&self.view, itemp, idx, dim) # <<<<<<<<<<<<<< - * - * return itemp - */ - __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_v_idx); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 400, __pyx_L1_error) - __pyx_t_7 = __pyx_pybuffer_index((&__pyx_v_self->view), __pyx_v_itemp, __pyx_t_6, __pyx_v_dim); if (unlikely(__pyx_t_7 == ((char *)NULL))) __PYX_ERR(2, 400, __pyx_L1_error) - __pyx_v_itemp = __pyx_t_7; - - /* "View.MemoryView":399 - * cdef char *itemp = self.view.buf - * - * for dim, idx in enumerate(index): # <<<<<<<<<<<<<< - * itemp = pybuffer_index(&self.view, itemp, idx, dim) - * - */ - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "View.MemoryView":402 - * itemp = pybuffer_index(&self.view, itemp, idx, dim) - * - * return itemp # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = __pyx_v_itemp; - goto __pyx_L0; - - /* "View.MemoryView":395 - * PyThread_free_lock(self.lock) - * - * cdef char *get_item_pointer(memoryview self, object index) except NULL: # <<<<<<<<<<<<<< - * cdef Py_ssize_t dim - * cdef char *itemp = self.view.buf - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.memoryview.get_item_pointer", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_idx); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":405 - * - * - * def __getitem__(memoryview self, object index): # <<<<<<<<<<<<<< - * if index is Ellipsis: - * return self - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/ -static PyObject *__pyx_memoryview___getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4__getitem__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((PyObject *)__pyx_v_index)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_4__getitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index) { - PyObject *__pyx_v_have_slices = NULL; - PyObject *__pyx_v_indices = NULL; - char *__pyx_v_itemp; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - char *__pyx_t_6; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__getitem__", 0); - - /* "View.MemoryView":406 - * - * def __getitem__(memoryview self, object index): - * if index is Ellipsis: # <<<<<<<<<<<<<< - * return self - * - */ - __pyx_t_1 = (__pyx_v_index == __pyx_builtin_Ellipsis); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":407 - * def __getitem__(memoryview self, object index): - * if index is Ellipsis: - * return self # <<<<<<<<<<<<<< - * - * have_slices, indices = _unellipsify(index, self.view.ndim) - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_self)); - __pyx_r = ((PyObject *)__pyx_v_self); - goto __pyx_L0; - - /* "View.MemoryView":406 - * - * def __getitem__(memoryview self, object index): - * if index is Ellipsis: # <<<<<<<<<<<<<< - * return self - * - */ - } - - /* "View.MemoryView":409 - * return self - * - * have_slices, indices = _unellipsify(index, self.view.ndim) # <<<<<<<<<<<<<< - * - * cdef char *itemp - */ - __pyx_t_3 = _unellipsify(__pyx_v_index, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 409, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if (likely(__pyx_t_3 != Py_None)) { - PyObject* sequence = __pyx_t_3; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(2, 409, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - #else - __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 409, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 409, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - #endif - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(2, 409, __pyx_L1_error) - } - __pyx_v_have_slices = __pyx_t_4; - __pyx_t_4 = 0; - __pyx_v_indices = __pyx_t_5; - __pyx_t_5 = 0; - - /* "View.MemoryView":412 - * - * cdef char *itemp - * if have_slices: # <<<<<<<<<<<<<< - * return memview_slice(self, indices) - * else: - */ - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_have_slices); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 412, __pyx_L1_error) - if (__pyx_t_2) { - - /* "View.MemoryView":413 - * cdef char *itemp - * if have_slices: - * return memview_slice(self, indices) # <<<<<<<<<<<<<< - * else: - * itemp = self.get_item_pointer(indices) - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = ((PyObject *)__pyx_memview_slice(__pyx_v_self, __pyx_v_indices)); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 413, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "View.MemoryView":412 - * - * cdef char *itemp - * if have_slices: # <<<<<<<<<<<<<< - * return memview_slice(self, indices) - * else: - */ - } - - /* "View.MemoryView":415 - * return memview_slice(self, indices) - * else: - * itemp = self.get_item_pointer(indices) # <<<<<<<<<<<<<< - * return self.convert_item_to_object(itemp) - * - */ - /*else*/ { - __pyx_t_6 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->get_item_pointer(__pyx_v_self, __pyx_v_indices); if (unlikely(__pyx_t_6 == ((char *)NULL))) __PYX_ERR(2, 415, __pyx_L1_error) - __pyx_v_itemp = __pyx_t_6; - - /* "View.MemoryView":416 - * else: - * itemp = self.get_item_pointer(indices) - * return self.convert_item_to_object(itemp) # <<<<<<<<<<<<<< - * - * def __setitem__(memoryview self, object index, object value): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->convert_item_to_object(__pyx_v_self, __pyx_v_itemp); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 416, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - } - - /* "View.MemoryView":405 - * - * - * def __getitem__(memoryview self, object index): # <<<<<<<<<<<<<< - * if index is Ellipsis: - * return self - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.memoryview.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_have_slices); - __Pyx_XDECREF(__pyx_v_indices); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":418 - * return self.convert_item_to_object(itemp) - * - * def __setitem__(memoryview self, object index, object value): # <<<<<<<<<<<<<< - * if self.view.readonly: - * raise TypeError("Cannot assign to read-only memoryview") - */ - -/* Python wrapper */ -static int __pyx_memoryview___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value); /*proto*/ -static int __pyx_memoryview___setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setitem__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((PyObject *)__pyx_v_index), ((PyObject *)__pyx_v_value)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_6__setitem__(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - PyObject *__pyx_v_have_slices = NULL; - PyObject *__pyx_v_obj = NULL; - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setitem__", 0); - __Pyx_INCREF(__pyx_v_index); - - /* "View.MemoryView":419 - * - * def __setitem__(memoryview self, object index, object value): - * if self.view.readonly: # <<<<<<<<<<<<<< - * raise TypeError("Cannot assign to read-only memoryview") - * - */ - __pyx_t_1 = (__pyx_v_self->view.readonly != 0); - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":420 - * def __setitem__(memoryview self, object index, object value): - * if self.view.readonly: - * raise TypeError("Cannot assign to read-only memoryview") # <<<<<<<<<<<<<< - * - * have_slices, index = _unellipsify(index, self.view.ndim) - */ - __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__10, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 420, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_Raise(__pyx_t_2, 0, 0, 0); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __PYX_ERR(2, 420, __pyx_L1_error) - - /* "View.MemoryView":419 - * - * def __setitem__(memoryview self, object index, object value): - * if self.view.readonly: # <<<<<<<<<<<<<< - * raise TypeError("Cannot assign to read-only memoryview") - * - */ - } - - /* "View.MemoryView":422 - * raise TypeError("Cannot assign to read-only memoryview") - * - * have_slices, index = _unellipsify(index, self.view.ndim) # <<<<<<<<<<<<<< - * - * if have_slices: - */ - __pyx_t_2 = _unellipsify(__pyx_v_index, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 422, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (likely(__pyx_t_2 != Py_None)) { - PyObject* sequence = __pyx_t_2; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(2, 422, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_4); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 422, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 422, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - #endif - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(2, 422, __pyx_L1_error) - } - __pyx_v_have_slices = __pyx_t_3; - __pyx_t_3 = 0; - __Pyx_DECREF_SET(__pyx_v_index, __pyx_t_4); - __pyx_t_4 = 0; - - /* "View.MemoryView":424 - * have_slices, index = _unellipsify(index, self.view.ndim) - * - * if have_slices: # <<<<<<<<<<<<<< - * obj = self.is_slice(value) - * if obj: - */ - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_have_slices); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(2, 424, __pyx_L1_error) - if (__pyx_t_1) { - - /* "View.MemoryView":425 - * - * if have_slices: - * obj = self.is_slice(value) # <<<<<<<<<<<<<< - * if obj: - * self.setitem_slice_assignment(self[index], obj) - */ - __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->is_slice(__pyx_v_self, __pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 425, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_v_obj = __pyx_t_2; - __pyx_t_2 = 0; - - /* "View.MemoryView":426 - * if have_slices: - * obj = self.is_slice(value) - * if obj: # <<<<<<<<<<<<<< - * self.setitem_slice_assignment(self[index], obj) - * else: - */ - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_obj); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(2, 426, __pyx_L1_error) - if (__pyx_t_1) { - - /* "View.MemoryView":427 - * obj = self.is_slice(value) - * if obj: - * self.setitem_slice_assignment(self[index], obj) # <<<<<<<<<<<<<< - * else: - * self.setitem_slice_assign_scalar(self[index], value) - */ - __pyx_t_2 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_index); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 427, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->setitem_slice_assignment(__pyx_v_self, __pyx_t_2, __pyx_v_obj); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 427, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "View.MemoryView":426 - * if have_slices: - * obj = self.is_slice(value) - * if obj: # <<<<<<<<<<<<<< - * self.setitem_slice_assignment(self[index], obj) - * else: - */ - goto __pyx_L5; - } - - /* "View.MemoryView":429 - * self.setitem_slice_assignment(self[index], obj) - * else: - * self.setitem_slice_assign_scalar(self[index], value) # <<<<<<<<<<<<<< - * else: - * self.setitem_indexed(index, value) - */ - /*else*/ { - __pyx_t_4 = __Pyx_PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_index); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 429, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_memoryview_type))))) __PYX_ERR(2, 429, __pyx_L1_error) - __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->setitem_slice_assign_scalar(__pyx_v_self, ((struct __pyx_memoryview_obj *)__pyx_t_4), __pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 429, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - } - __pyx_L5:; - - /* "View.MemoryView":424 - * have_slices, index = _unellipsify(index, self.view.ndim) - * - * if have_slices: # <<<<<<<<<<<<<< - * obj = self.is_slice(value) - * if obj: - */ - goto __pyx_L4; - } - - /* "View.MemoryView":431 - * self.setitem_slice_assign_scalar(self[index], value) - * else: - * self.setitem_indexed(index, value) # <<<<<<<<<<<<<< - * - * cdef is_slice(self, obj): - */ - /*else*/ { - __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->setitem_indexed(__pyx_v_self, __pyx_v_index, __pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 431, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - } - __pyx_L4:; - - /* "View.MemoryView":418 - * return self.convert_item_to_object(itemp) - * - * def __setitem__(memoryview self, object index, object value): # <<<<<<<<<<<<<< - * if self.view.readonly: - * raise TypeError("Cannot assign to read-only memoryview") - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("View.MemoryView.memoryview.__setitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_have_slices); - __Pyx_XDECREF(__pyx_v_obj); - __Pyx_XDECREF(__pyx_v_index); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":433 - * self.setitem_indexed(index, value) - * - * cdef is_slice(self, obj): # <<<<<<<<<<<<<< - * if not isinstance(obj, memoryview): - * try: - */ - -static PyObject *__pyx_memoryview_is_slice(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_obj) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - int __pyx_t_9; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("is_slice", 0); - __Pyx_INCREF(__pyx_v_obj); - - /* "View.MemoryView":434 - * - * cdef is_slice(self, obj): - * if not isinstance(obj, memoryview): # <<<<<<<<<<<<<< - * try: - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - */ - __pyx_t_1 = __Pyx_TypeCheck(__pyx_v_obj, __pyx_memoryview_type); - __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":435 - * cdef is_slice(self, obj): - * if not isinstance(obj, memoryview): - * try: # <<<<<<<<<<<<<< - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - * self.dtype_is_object) - */ - { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ExceptionSave(&__pyx_t_3, &__pyx_t_4, &__pyx_t_5); - __Pyx_XGOTREF(__pyx_t_3); - __Pyx_XGOTREF(__pyx_t_4); - __Pyx_XGOTREF(__pyx_t_5); - /*try:*/ { - - /* "View.MemoryView":436 - * if not isinstance(obj, memoryview): - * try: - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, # <<<<<<<<<<<<<< - * self.dtype_is_object) - * except TypeError: - */ - __pyx_t_6 = __Pyx_PyInt_From_int(((__pyx_v_self->flags & (~PyBUF_WRITABLE)) | PyBUF_ANY_CONTIGUOUS)); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 436, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_6); - - /* "View.MemoryView":437 - * try: - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - * self.dtype_is_object) # <<<<<<<<<<<<<< - * except TypeError: - * return None - */ - __pyx_t_7 = __Pyx_PyBool_FromLong(__pyx_v_self->dtype_is_object); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 437, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_7); - - /* "View.MemoryView":436 - * if not isinstance(obj, memoryview): - * try: - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, # <<<<<<<<<<<<<< - * self.dtype_is_object) - * except TypeError: - */ - __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 436, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_INCREF(__pyx_v_obj); - __Pyx_GIVEREF(__pyx_v_obj); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_obj); - __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_6); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_t_7); - __pyx_t_6 = 0; - __pyx_t_7 = 0; - __pyx_t_7 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryview_type), __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 436, __pyx_L4_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __Pyx_DECREF_SET(__pyx_v_obj, __pyx_t_7); - __pyx_t_7 = 0; - - /* "View.MemoryView":435 - * cdef is_slice(self, obj): - * if not isinstance(obj, memoryview): - * try: # <<<<<<<<<<<<<< - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - * self.dtype_is_object) - */ - } - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - goto __pyx_L9_try_end; - __pyx_L4_error:; - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; - - /* "View.MemoryView":438 - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - * self.dtype_is_object) - * except TypeError: # <<<<<<<<<<<<<< - * return None - * - */ - __pyx_t_9 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_TypeError); - if (__pyx_t_9) { - __Pyx_AddTraceback("View.MemoryView.memoryview.is_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_7, &__pyx_t_8, &__pyx_t_6) < 0) __PYX_ERR(2, 438, __pyx_L6_except_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_GOTREF(__pyx_t_8); - __Pyx_GOTREF(__pyx_t_6); - - /* "View.MemoryView":439 - * self.dtype_is_object) - * except TypeError: - * return None # <<<<<<<<<<<<<< - * - * return obj - */ - __Pyx_XDECREF(__pyx_r); - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - goto __pyx_L7_except_return; - } - goto __pyx_L6_except_error; - __pyx_L6_except_error:; - - /* "View.MemoryView":435 - * cdef is_slice(self, obj): - * if not isinstance(obj, memoryview): - * try: # <<<<<<<<<<<<<< - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - * self.dtype_is_object) - */ - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_XGIVEREF(__pyx_t_4); - __Pyx_XGIVEREF(__pyx_t_5); - __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_4, __pyx_t_5); - goto __pyx_L1_error; - __pyx_L7_except_return:; - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_XGIVEREF(__pyx_t_4); - __Pyx_XGIVEREF(__pyx_t_5); - __Pyx_ExceptionReset(__pyx_t_3, __pyx_t_4, __pyx_t_5); - goto __pyx_L0; - __pyx_L9_try_end:; - } - - /* "View.MemoryView":434 - * - * cdef is_slice(self, obj): - * if not isinstance(obj, memoryview): # <<<<<<<<<<<<<< - * try: - * obj = memoryview(obj, self.flags & ~PyBUF_WRITABLE | PyBUF_ANY_CONTIGUOUS, - */ - } - - /* "View.MemoryView":441 - * return None - * - * return obj # <<<<<<<<<<<<<< - * - * cdef setitem_slice_assignment(self, dst, src): - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_obj); - __pyx_r = __pyx_v_obj; - goto __pyx_L0; - - /* "View.MemoryView":433 - * self.setitem_indexed(index, value) - * - * cdef is_slice(self, obj): # <<<<<<<<<<<<<< - * if not isinstance(obj, memoryview): - * try: - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("View.MemoryView.memoryview.is_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_obj); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":443 - * return obj - * - * cdef setitem_slice_assignment(self, dst, src): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice dst_slice - * cdef __Pyx_memviewslice src_slice - */ - -static PyObject *__pyx_memoryview_setitem_slice_assignment(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_dst, PyObject *__pyx_v_src) { - __Pyx_memviewslice __pyx_v_dst_slice; - __Pyx_memviewslice __pyx_v_src_slice; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice *__pyx_t_1; - __Pyx_memviewslice *__pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; - int __pyx_t_5; - int __pyx_t_6; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("setitem_slice_assignment", 0); - - /* "View.MemoryView":447 - * cdef __Pyx_memviewslice src_slice - * - * memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0], # <<<<<<<<<<<<<< - * get_slice_from_memview(dst, &dst_slice)[0], - * src.ndim, dst.ndim, self.dtype_is_object) - */ - if (!(likely(((__pyx_v_src) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_src, __pyx_memoryview_type))))) __PYX_ERR(2, 447, __pyx_L1_error) - __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(((struct __pyx_memoryview_obj *)__pyx_v_src), (&__pyx_v_src_slice)); if (unlikely(__pyx_t_1 == ((__Pyx_memviewslice *)NULL))) __PYX_ERR(2, 447, __pyx_L1_error) - - /* "View.MemoryView":448 - * - * memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0], - * get_slice_from_memview(dst, &dst_slice)[0], # <<<<<<<<<<<<<< - * src.ndim, dst.ndim, self.dtype_is_object) - * - */ - if (!(likely(((__pyx_v_dst) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_dst, __pyx_memoryview_type))))) __PYX_ERR(2, 448, __pyx_L1_error) - __pyx_t_2 = __pyx_memoryview_get_slice_from_memoryview(((struct __pyx_memoryview_obj *)__pyx_v_dst), (&__pyx_v_dst_slice)); if (unlikely(__pyx_t_2 == ((__Pyx_memviewslice *)NULL))) __PYX_ERR(2, 448, __pyx_L1_error) - - /* "View.MemoryView":449 - * memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0], - * get_slice_from_memview(dst, &dst_slice)[0], - * src.ndim, dst.ndim, self.dtype_is_object) # <<<<<<<<<<<<<< - * - * cdef setitem_slice_assign_scalar(self, memoryview dst, value): - */ - __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_src, __pyx_n_s_ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 449, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 449, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_dst, __pyx_n_s_ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 449, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_5 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_5 == (int)-1) && PyErr_Occurred())) __PYX_ERR(2, 449, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "View.MemoryView":447 - * cdef __Pyx_memviewslice src_slice - * - * memoryview_copy_contents(get_slice_from_memview(src, &src_slice)[0], # <<<<<<<<<<<<<< - * get_slice_from_memview(dst, &dst_slice)[0], - * src.ndim, dst.ndim, self.dtype_is_object) - */ - __pyx_t_6 = __pyx_memoryview_copy_contents((__pyx_t_1[0]), (__pyx_t_2[0]), __pyx_t_4, __pyx_t_5, __pyx_v_self->dtype_is_object); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(2, 447, __pyx_L1_error) - - /* "View.MemoryView":443 - * return obj - * - * cdef setitem_slice_assignment(self, dst, src): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice dst_slice - * cdef __Pyx_memviewslice src_slice - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_slice_assignment", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":451 - * src.ndim, dst.ndim, self.dtype_is_object) - * - * cdef setitem_slice_assign_scalar(self, memoryview dst, value): # <<<<<<<<<<<<<< - * cdef int array[128] - * cdef void *tmp = NULL - */ - -static PyObject *__pyx_memoryview_setitem_slice_assign_scalar(struct __pyx_memoryview_obj *__pyx_v_self, struct __pyx_memoryview_obj *__pyx_v_dst, PyObject *__pyx_v_value) { - int __pyx_v_array[0x80]; - void *__pyx_v_tmp; - void *__pyx_v_item; - __Pyx_memviewslice *__pyx_v_dst_slice; - __Pyx_memviewslice __pyx_v_tmp_slice; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice *__pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_t_4; - int __pyx_t_5; - char const *__pyx_t_6; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - PyObject *__pyx_t_9 = NULL; - PyObject *__pyx_t_10 = NULL; - PyObject *__pyx_t_11 = NULL; - PyObject *__pyx_t_12 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("setitem_slice_assign_scalar", 0); - - /* "View.MemoryView":453 - * cdef setitem_slice_assign_scalar(self, memoryview dst, value): - * cdef int array[128] - * cdef void *tmp = NULL # <<<<<<<<<<<<<< - * cdef void *item - * - */ - __pyx_v_tmp = NULL; - - /* "View.MemoryView":458 - * cdef __Pyx_memviewslice *dst_slice - * cdef __Pyx_memviewslice tmp_slice - * dst_slice = get_slice_from_memview(dst, &tmp_slice) # <<<<<<<<<<<<<< - * - * if self.view.itemsize > sizeof(array): - */ - __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_dst, (&__pyx_v_tmp_slice)); if (unlikely(__pyx_t_1 == ((__Pyx_memviewslice *)NULL))) __PYX_ERR(2, 458, __pyx_L1_error) - __pyx_v_dst_slice = __pyx_t_1; - - /* "View.MemoryView":460 - * dst_slice = get_slice_from_memview(dst, &tmp_slice) - * - * if self.view.itemsize > sizeof(array): # <<<<<<<<<<<<<< - * tmp = PyMem_Malloc(self.view.itemsize) - * if tmp == NULL: - */ - __pyx_t_2 = ((((size_t)__pyx_v_self->view.itemsize) > (sizeof(__pyx_v_array))) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":461 - * - * if self.view.itemsize > sizeof(array): - * tmp = PyMem_Malloc(self.view.itemsize) # <<<<<<<<<<<<<< - * if tmp == NULL: - * raise MemoryError - */ - __pyx_v_tmp = PyMem_Malloc(__pyx_v_self->view.itemsize); - - /* "View.MemoryView":462 - * if self.view.itemsize > sizeof(array): - * tmp = PyMem_Malloc(self.view.itemsize) - * if tmp == NULL: # <<<<<<<<<<<<<< - * raise MemoryError - * item = tmp - */ - __pyx_t_2 = ((__pyx_v_tmp == NULL) != 0); - if (unlikely(__pyx_t_2)) { - - /* "View.MemoryView":463 - * tmp = PyMem_Malloc(self.view.itemsize) - * if tmp == NULL: - * raise MemoryError # <<<<<<<<<<<<<< - * item = tmp - * else: - */ - PyErr_NoMemory(); __PYX_ERR(2, 463, __pyx_L1_error) - - /* "View.MemoryView":462 - * if self.view.itemsize > sizeof(array): - * tmp = PyMem_Malloc(self.view.itemsize) - * if tmp == NULL: # <<<<<<<<<<<<<< - * raise MemoryError - * item = tmp - */ - } - - /* "View.MemoryView":464 - * if tmp == NULL: - * raise MemoryError - * item = tmp # <<<<<<<<<<<<<< - * else: - * item = array - */ - __pyx_v_item = __pyx_v_tmp; - - /* "View.MemoryView":460 - * dst_slice = get_slice_from_memview(dst, &tmp_slice) - * - * if self.view.itemsize > sizeof(array): # <<<<<<<<<<<<<< - * tmp = PyMem_Malloc(self.view.itemsize) - * if tmp == NULL: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":466 - * item = tmp - * else: - * item = array # <<<<<<<<<<<<<< - * - * try: - */ - /*else*/ { - __pyx_v_item = ((void *)__pyx_v_array); - } - __pyx_L3:; - - /* "View.MemoryView":468 - * item = array - * - * try: # <<<<<<<<<<<<<< - * if self.dtype_is_object: - * ( item)[0] = value - */ - /*try:*/ { - - /* "View.MemoryView":469 - * - * try: - * if self.dtype_is_object: # <<<<<<<<<<<<<< - * ( item)[0] = value - * else: - */ - __pyx_t_2 = (__pyx_v_self->dtype_is_object != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":470 - * try: - * if self.dtype_is_object: - * ( item)[0] = value # <<<<<<<<<<<<<< - * else: - * self.assign_item_from_object( item, value) - */ - (((PyObject **)__pyx_v_item)[0]) = ((PyObject *)__pyx_v_value); - - /* "View.MemoryView":469 - * - * try: - * if self.dtype_is_object: # <<<<<<<<<<<<<< - * ( item)[0] = value - * else: - */ - goto __pyx_L8; - } - - /* "View.MemoryView":472 - * ( item)[0] = value - * else: - * self.assign_item_from_object( item, value) # <<<<<<<<<<<<<< - * - * - */ - /*else*/ { - __pyx_t_3 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->assign_item_from_object(__pyx_v_self, ((char *)__pyx_v_item), __pyx_v_value); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 472, __pyx_L6_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } - __pyx_L8:; - - /* "View.MemoryView":476 - * - * - * if self.view.suboffsets != NULL: # <<<<<<<<<<<<<< - * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) - * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, - */ - __pyx_t_2 = ((__pyx_v_self->view.suboffsets != NULL) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":477 - * - * if self.view.suboffsets != NULL: - * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) # <<<<<<<<<<<<<< - * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, - * item, self.dtype_is_object) - */ - __pyx_t_3 = assert_direct_dimensions(__pyx_v_self->view.suboffsets, __pyx_v_self->view.ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 477, __pyx_L6_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "View.MemoryView":476 - * - * - * if self.view.suboffsets != NULL: # <<<<<<<<<<<<<< - * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) - * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, - */ - } - - /* "View.MemoryView":478 - * if self.view.suboffsets != NULL: - * assert_direct_dimensions(self.view.suboffsets, self.view.ndim) - * slice_assign_scalar(dst_slice, dst.view.ndim, self.view.itemsize, # <<<<<<<<<<<<<< - * item, self.dtype_is_object) - * finally: - */ - __pyx_memoryview_slice_assign_scalar(__pyx_v_dst_slice, __pyx_v_dst->view.ndim, __pyx_v_self->view.itemsize, __pyx_v_item, __pyx_v_self->dtype_is_object); - } - - /* "View.MemoryView":481 - * item, self.dtype_is_object) - * finally: - * PyMem_Free(tmp) # <<<<<<<<<<<<<< - * - * cdef setitem_indexed(self, index, value): - */ - /*finally:*/ { - /*normal exit:*/{ - PyMem_Free(__pyx_v_tmp); - goto __pyx_L7; - } - __pyx_L6_error:; - /*exception exit:*/{ - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12); - if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9) < 0)) __Pyx_ErrFetch(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9); - __Pyx_XGOTREF(__pyx_t_7); - __Pyx_XGOTREF(__pyx_t_8); - __Pyx_XGOTREF(__pyx_t_9); - __Pyx_XGOTREF(__pyx_t_10); - __Pyx_XGOTREF(__pyx_t_11); - __Pyx_XGOTREF(__pyx_t_12); - __pyx_t_4 = __pyx_lineno; __pyx_t_5 = __pyx_clineno; __pyx_t_6 = __pyx_filename; - { - PyMem_Free(__pyx_v_tmp); - } - if (PY_MAJOR_VERSION >= 3) { - __Pyx_XGIVEREF(__pyx_t_10); - __Pyx_XGIVEREF(__pyx_t_11); - __Pyx_XGIVEREF(__pyx_t_12); - __Pyx_ExceptionReset(__pyx_t_10, __pyx_t_11, __pyx_t_12); - } - __Pyx_XGIVEREF(__pyx_t_7); - __Pyx_XGIVEREF(__pyx_t_8); - __Pyx_XGIVEREF(__pyx_t_9); - __Pyx_ErrRestore(__pyx_t_7, __pyx_t_8, __pyx_t_9); - __pyx_t_7 = 0; __pyx_t_8 = 0; __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; - __pyx_lineno = __pyx_t_4; __pyx_clineno = __pyx_t_5; __pyx_filename = __pyx_t_6; - goto __pyx_L1_error; - } - __pyx_L7:; - } - - /* "View.MemoryView":451 - * src.ndim, dst.ndim, self.dtype_is_object) - * - * cdef setitem_slice_assign_scalar(self, memoryview dst, value): # <<<<<<<<<<<<<< - * cdef int array[128] - * cdef void *tmp = NULL - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_slice_assign_scalar", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":483 - * PyMem_Free(tmp) - * - * cdef setitem_indexed(self, index, value): # <<<<<<<<<<<<<< - * cdef char *itemp = self.get_item_pointer(index) - * self.assign_item_from_object(itemp, value) - */ - -static PyObject *__pyx_memoryview_setitem_indexed(struct __pyx_memoryview_obj *__pyx_v_self, PyObject *__pyx_v_index, PyObject *__pyx_v_value) { - char *__pyx_v_itemp; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - char *__pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("setitem_indexed", 0); - - /* "View.MemoryView":484 - * - * cdef setitem_indexed(self, index, value): - * cdef char *itemp = self.get_item_pointer(index) # <<<<<<<<<<<<<< - * self.assign_item_from_object(itemp, value) - * - */ - __pyx_t_1 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->get_item_pointer(__pyx_v_self, __pyx_v_index); if (unlikely(__pyx_t_1 == ((char *)NULL))) __PYX_ERR(2, 484, __pyx_L1_error) - __pyx_v_itemp = __pyx_t_1; - - /* "View.MemoryView":485 - * cdef setitem_indexed(self, index, value): - * cdef char *itemp = self.get_item_pointer(index) - * self.assign_item_from_object(itemp, value) # <<<<<<<<<<<<<< - * - * cdef convert_item_to_object(self, char *itemp): - */ - __pyx_t_2 = ((struct __pyx_vtabstruct_memoryview *)__pyx_v_self->__pyx_vtab)->assign_item_from_object(__pyx_v_self, __pyx_v_itemp, __pyx_v_value); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 485, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "View.MemoryView":483 - * PyMem_Free(tmp) - * - * cdef setitem_indexed(self, index, value): # <<<<<<<<<<<<<< - * cdef char *itemp = self.get_item_pointer(index) - * self.assign_item_from_object(itemp, value) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.memoryview.setitem_indexed", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":487 - * self.assign_item_from_object(itemp, value) - * - * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< - * """Only used if instantiated manually by the user, or if Cython doesn't - * know how to convert the type""" - */ - -static PyObject *__pyx_memoryview_convert_item_to_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp) { - PyObject *__pyx_v_struct = NULL; - PyObject *__pyx_v_bytesitem = 0; - PyObject *__pyx_v_result = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - int __pyx_t_8; - PyObject *__pyx_t_9 = NULL; - size_t __pyx_t_10; - int __pyx_t_11; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("convert_item_to_object", 0); - - /* "View.MemoryView":490 - * """Only used if instantiated manually by the user, or if Cython doesn't - * know how to convert the type""" - * import struct # <<<<<<<<<<<<<< - * cdef bytes bytesitem - * - */ - __pyx_t_1 = __Pyx_Import(__pyx_n_s_struct, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 490, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_struct = __pyx_t_1; - __pyx_t_1 = 0; - - /* "View.MemoryView":493 - * cdef bytes bytesitem - * - * bytesitem = itemp[:self.view.itemsize] # <<<<<<<<<<<<<< - * try: - * result = struct.unpack(self.view.format, bytesitem) - */ - __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_itemp + 0, __pyx_v_self->view.itemsize - 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 493, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_bytesitem = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":494 - * - * bytesitem = itemp[:self.view.itemsize] - * try: # <<<<<<<<<<<<<< - * result = struct.unpack(self.view.format, bytesitem) - * except struct.error: - */ - { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4); - __Pyx_XGOTREF(__pyx_t_2); - __Pyx_XGOTREF(__pyx_t_3); - __Pyx_XGOTREF(__pyx_t_4); - /*try:*/ { - - /* "View.MemoryView":495 - * bytesitem = itemp[:self.view.itemsize] - * try: - * result = struct.unpack(self.view.format, bytesitem) # <<<<<<<<<<<<<< - * except struct.error: - * raise ValueError("Unable to convert item to object") - */ - __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_unpack); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 495, __pyx_L3_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 495, __pyx_L3_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_7 = NULL; - __pyx_t_8 = 0; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { - __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5); - if (likely(__pyx_t_7)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_5, function); - __pyx_t_8 = 1; - } - } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_5)) { - PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_6, __pyx_v_bytesitem}; - __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 495, __pyx_L3_error) - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) { - PyObject *__pyx_temp[3] = {__pyx_t_7, __pyx_t_6, __pyx_v_bytesitem}; - __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 495, __pyx_L3_error) - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - } else - #endif - { - __pyx_t_9 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 495, __pyx_L3_error) - __Pyx_GOTREF(__pyx_t_9); - if (__pyx_t_7) { - __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL; - } - __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_9, 0+__pyx_t_8, __pyx_t_6); - __Pyx_INCREF(__pyx_v_bytesitem); - __Pyx_GIVEREF(__pyx_v_bytesitem); - PyTuple_SET_ITEM(__pyx_t_9, 1+__pyx_t_8, __pyx_v_bytesitem); - __pyx_t_6 = 0; - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_9, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 495, __pyx_L3_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - } - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_v_result = __pyx_t_1; - __pyx_t_1 = 0; - - /* "View.MemoryView":494 - * - * bytesitem = itemp[:self.view.itemsize] - * try: # <<<<<<<<<<<<<< - * result = struct.unpack(self.view.format, bytesitem) - * except struct.error: - */ - } - - /* "View.MemoryView":499 - * raise ValueError("Unable to convert item to object") - * else: - * if len(self.view.format) == 1: # <<<<<<<<<<<<<< - * return result[0] - * return result - */ - /*else:*/ { - __pyx_t_10 = strlen(__pyx_v_self->view.format); - __pyx_t_11 = ((__pyx_t_10 == 1) != 0); - if (__pyx_t_11) { - - /* "View.MemoryView":500 - * else: - * if len(self.view.format) == 1: - * return result[0] # <<<<<<<<<<<<<< - * return result - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_result, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 500, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L6_except_return; - - /* "View.MemoryView":499 - * raise ValueError("Unable to convert item to object") - * else: - * if len(self.view.format) == 1: # <<<<<<<<<<<<<< - * return result[0] - * return result - */ - } - - /* "View.MemoryView":501 - * if len(self.view.format) == 1: - * return result[0] - * return result # <<<<<<<<<<<<<< - * - * cdef assign_item_from_object(self, char *itemp, object value): - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_result); - __pyx_r = __pyx_v_result; - goto __pyx_L6_except_return; - } - __pyx_L3_error:; - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0; - - /* "View.MemoryView":496 - * try: - * result = struct.unpack(self.view.format, bytesitem) - * except struct.error: # <<<<<<<<<<<<<< - * raise ValueError("Unable to convert item to object") - * else: - */ - __Pyx_ErrFetch(&__pyx_t_1, &__pyx_t_5, &__pyx_t_9); - __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_error); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 496, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_8 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_1, __pyx_t_6); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_ErrRestore(__pyx_t_1, __pyx_t_5, __pyx_t_9); - __pyx_t_1 = 0; __pyx_t_5 = 0; __pyx_t_9 = 0; - if (__pyx_t_8) { - __Pyx_AddTraceback("View.MemoryView.memoryview.convert_item_to_object", __pyx_clineno, __pyx_lineno, __pyx_filename); - if (__Pyx_GetException(&__pyx_t_9, &__pyx_t_5, &__pyx_t_1) < 0) __PYX_ERR(2, 496, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_9); - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GOTREF(__pyx_t_1); - - /* "View.MemoryView":497 - * result = struct.unpack(self.view.format, bytesitem) - * except struct.error: - * raise ValueError("Unable to convert item to object") # <<<<<<<<<<<<<< - * else: - * if len(self.view.format) == 1: - */ - __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__11, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 497, __pyx_L5_except_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_Raise(__pyx_t_6, 0, 0, 0); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - __PYX_ERR(2, 497, __pyx_L5_except_error) - } - goto __pyx_L5_except_error; - __pyx_L5_except_error:; - - /* "View.MemoryView":494 - * - * bytesitem = itemp[:self.view.itemsize] - * try: # <<<<<<<<<<<<<< - * result = struct.unpack(self.view.format, bytesitem) - * except struct.error: - */ - __Pyx_XGIVEREF(__pyx_t_2); - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_XGIVEREF(__pyx_t_4); - __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); - goto __pyx_L1_error; - __pyx_L6_except_return:; - __Pyx_XGIVEREF(__pyx_t_2); - __Pyx_XGIVEREF(__pyx_t_3); - __Pyx_XGIVEREF(__pyx_t_4); - __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4); - goto __pyx_L0; - } - - /* "View.MemoryView":487 - * self.assign_item_from_object(itemp, value) - * - * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< - * """Only used if instantiated manually by the user, or if Cython doesn't - * know how to convert the type""" - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_9); - __Pyx_AddTraceback("View.MemoryView.memoryview.convert_item_to_object", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_struct); - __Pyx_XDECREF(__pyx_v_bytesitem); - __Pyx_XDECREF(__pyx_v_result); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":503 - * return result - * - * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< - * """Only used if instantiated manually by the user, or if Cython doesn't - * know how to convert the type""" - */ - -static PyObject *__pyx_memoryview_assign_item_from_object(struct __pyx_memoryview_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value) { - PyObject *__pyx_v_struct = NULL; - char __pyx_v_c; - PyObject *__pyx_v_bytesvalue = 0; - Py_ssize_t __pyx_v_i; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - int __pyx_t_7; - PyObject *__pyx_t_8 = NULL; - Py_ssize_t __pyx_t_9; - PyObject *__pyx_t_10 = NULL; - char *__pyx_t_11; - char *__pyx_t_12; - char *__pyx_t_13; - char *__pyx_t_14; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("assign_item_from_object", 0); - - /* "View.MemoryView":506 - * """Only used if instantiated manually by the user, or if Cython doesn't - * know how to convert the type""" - * import struct # <<<<<<<<<<<<<< - * cdef char c - * cdef bytes bytesvalue - */ - __pyx_t_1 = __Pyx_Import(__pyx_n_s_struct, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 506, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_struct = __pyx_t_1; - __pyx_t_1 = 0; - - /* "View.MemoryView":511 - * cdef Py_ssize_t i - * - * if isinstance(value, tuple): # <<<<<<<<<<<<<< - * bytesvalue = struct.pack(self.view.format, *value) - * else: - */ - __pyx_t_2 = PyTuple_Check(__pyx_v_value); - __pyx_t_3 = (__pyx_t_2 != 0); - if (__pyx_t_3) { - - /* "View.MemoryView":512 - * - * if isinstance(value, tuple): - * bytesvalue = struct.pack(self.view.format, *value) # <<<<<<<<<<<<<< - * else: - * bytesvalue = struct.pack(self.view.format, value) - */ - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_pack); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 512, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_4 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 512, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 512, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4); - __pyx_t_4 = 0; - __pyx_t_4 = __Pyx_PySequence_Tuple(__pyx_v_value); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 512, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_6 = PyNumber_Add(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 512, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_6, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 512, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||((void)PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(2, 512, __pyx_L1_error) - __pyx_v_bytesvalue = ((PyObject*)__pyx_t_4); - __pyx_t_4 = 0; - - /* "View.MemoryView":511 - * cdef Py_ssize_t i - * - * if isinstance(value, tuple): # <<<<<<<<<<<<<< - * bytesvalue = struct.pack(self.view.format, *value) - * else: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":514 - * bytesvalue = struct.pack(self.view.format, *value) - * else: - * bytesvalue = struct.pack(self.view.format, value) # <<<<<<<<<<<<<< - * - * for i, c in enumerate(bytesvalue): - */ - /*else*/ { - __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_struct, __pyx_n_s_pack); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 514, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_1 = __Pyx_PyBytes_FromString(__pyx_v_self->view.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 514, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = NULL; - __pyx_t_7 = 0; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_6); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_6, function); - __pyx_t_7 = 1; - } - } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_6)) { - PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_1, __pyx_v_value}; - __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 514, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) { - PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_1, __pyx_v_value}; - __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 514, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } else - #endif - { - __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 514, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - if (__pyx_t_5) { - __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL; - } - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_1); - __Pyx_INCREF(__pyx_v_value); - __Pyx_GIVEREF(__pyx_v_value); - PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_v_value); - __pyx_t_1 = 0; - __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 514, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - } - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (!(likely(PyBytes_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||((void)PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "bytes", Py_TYPE(__pyx_t_4)->tp_name), 0))) __PYX_ERR(2, 514, __pyx_L1_error) - __pyx_v_bytesvalue = ((PyObject*)__pyx_t_4); - __pyx_t_4 = 0; - } - __pyx_L3:; - - /* "View.MemoryView":516 - * bytesvalue = struct.pack(self.view.format, value) - * - * for i, c in enumerate(bytesvalue): # <<<<<<<<<<<<<< - * itemp[i] = c - * - */ - __pyx_t_9 = 0; - if (unlikely(__pyx_v_bytesvalue == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' is not iterable"); - __PYX_ERR(2, 516, __pyx_L1_error) - } - __Pyx_INCREF(__pyx_v_bytesvalue); - __pyx_t_10 = __pyx_v_bytesvalue; - __pyx_t_12 = PyBytes_AS_STRING(__pyx_t_10); - __pyx_t_13 = (__pyx_t_12 + PyBytes_GET_SIZE(__pyx_t_10)); - for (__pyx_t_14 = __pyx_t_12; __pyx_t_14 < __pyx_t_13; __pyx_t_14++) { - __pyx_t_11 = __pyx_t_14; - __pyx_v_c = (__pyx_t_11[0]); - - /* "View.MemoryView":517 - * - * for i, c in enumerate(bytesvalue): - * itemp[i] = c # <<<<<<<<<<<<<< - * - * @cname('getbuffer') - */ - __pyx_v_i = __pyx_t_9; - - /* "View.MemoryView":516 - * bytesvalue = struct.pack(self.view.format, value) - * - * for i, c in enumerate(bytesvalue): # <<<<<<<<<<<<<< - * itemp[i] = c - * - */ - __pyx_t_9 = (__pyx_t_9 + 1); - - /* "View.MemoryView":517 - * - * for i, c in enumerate(bytesvalue): - * itemp[i] = c # <<<<<<<<<<<<<< - * - * @cname('getbuffer') - */ - (__pyx_v_itemp[__pyx_v_i]) = __pyx_v_c; - } - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - - /* "View.MemoryView":503 - * return result - * - * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< - * """Only used if instantiated manually by the user, or if Cython doesn't - * know how to convert the type""" - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_XDECREF(__pyx_t_10); - __Pyx_AddTraceback("View.MemoryView.memoryview.assign_item_from_object", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_struct); - __Pyx_XDECREF(__pyx_v_bytesvalue); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":520 - * - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): # <<<<<<<<<<<<<< - * if flags & PyBUF_WRITABLE and self.view.readonly: - * raise ValueError("Cannot create writable memory view from read-only memoryview") - */ - -/* Python wrapper */ -static CYTHON_UNUSED int __pyx_memoryview_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/ -static CYTHON_UNUSED int __pyx_memoryview_getbuffer(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { - int __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbuffer__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static int __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_8__getbuffer__(struct __pyx_memoryview_obj *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - Py_ssize_t *__pyx_t_4; - char *__pyx_t_5; - void *__pyx_t_6; - int __pyx_t_7; - Py_ssize_t __pyx_t_8; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - if (__pyx_v_info == NULL) { - PyErr_SetString(PyExc_BufferError, "PyObject_GetBuffer: view==NULL argument is obsolete"); - return -1; - } - __Pyx_RefNannySetupContext("__getbuffer__", 0); - __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None); - __Pyx_GIVEREF(__pyx_v_info->obj); - - /* "View.MemoryView":521 - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): - * if flags & PyBUF_WRITABLE and self.view.readonly: # <<<<<<<<<<<<<< - * raise ValueError("Cannot create writable memory view from read-only memoryview") - * - */ - __pyx_t_2 = ((__pyx_v_flags & PyBUF_WRITABLE) != 0); - if (__pyx_t_2) { - } else { - __pyx_t_1 = __pyx_t_2; - goto __pyx_L4_bool_binop_done; - } - __pyx_t_2 = (__pyx_v_self->view.readonly != 0); - __pyx_t_1 = __pyx_t_2; - __pyx_L4_bool_binop_done:; - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":522 - * def __getbuffer__(self, Py_buffer *info, int flags): - * if flags & PyBUF_WRITABLE and self.view.readonly: - * raise ValueError("Cannot create writable memory view from read-only memoryview") # <<<<<<<<<<<<<< - * - * if flags & PyBUF_ND: - */ - __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__12, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 522, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 522, __pyx_L1_error) - - /* "View.MemoryView":521 - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): - * if flags & PyBUF_WRITABLE and self.view.readonly: # <<<<<<<<<<<<<< - * raise ValueError("Cannot create writable memory view from read-only memoryview") - * - */ - } - - /* "View.MemoryView":524 - * raise ValueError("Cannot create writable memory view from read-only memoryview") - * - * if flags & PyBUF_ND: # <<<<<<<<<<<<<< - * info.shape = self.view.shape - * else: - */ - __pyx_t_1 = ((__pyx_v_flags & PyBUF_ND) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":525 - * - * if flags & PyBUF_ND: - * info.shape = self.view.shape # <<<<<<<<<<<<<< - * else: - * info.shape = NULL - */ - __pyx_t_4 = __pyx_v_self->view.shape; - __pyx_v_info->shape = __pyx_t_4; - - /* "View.MemoryView":524 - * raise ValueError("Cannot create writable memory view from read-only memoryview") - * - * if flags & PyBUF_ND: # <<<<<<<<<<<<<< - * info.shape = self.view.shape - * else: - */ - goto __pyx_L6; - } - - /* "View.MemoryView":527 - * info.shape = self.view.shape - * else: - * info.shape = NULL # <<<<<<<<<<<<<< - * - * if flags & PyBUF_STRIDES: - */ - /*else*/ { - __pyx_v_info->shape = NULL; - } - __pyx_L6:; - - /* "View.MemoryView":529 - * info.shape = NULL - * - * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< - * info.strides = self.view.strides - * else: - */ - __pyx_t_1 = ((__pyx_v_flags & PyBUF_STRIDES) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":530 - * - * if flags & PyBUF_STRIDES: - * info.strides = self.view.strides # <<<<<<<<<<<<<< - * else: - * info.strides = NULL - */ - __pyx_t_4 = __pyx_v_self->view.strides; - __pyx_v_info->strides = __pyx_t_4; - - /* "View.MemoryView":529 - * info.shape = NULL - * - * if flags & PyBUF_STRIDES: # <<<<<<<<<<<<<< - * info.strides = self.view.strides - * else: - */ - goto __pyx_L7; - } - - /* "View.MemoryView":532 - * info.strides = self.view.strides - * else: - * info.strides = NULL # <<<<<<<<<<<<<< - * - * if flags & PyBUF_INDIRECT: - */ - /*else*/ { - __pyx_v_info->strides = NULL; - } - __pyx_L7:; - - /* "View.MemoryView":534 - * info.strides = NULL - * - * if flags & PyBUF_INDIRECT: # <<<<<<<<<<<<<< - * info.suboffsets = self.view.suboffsets - * else: - */ - __pyx_t_1 = ((__pyx_v_flags & PyBUF_INDIRECT) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":535 - * - * if flags & PyBUF_INDIRECT: - * info.suboffsets = self.view.suboffsets # <<<<<<<<<<<<<< - * else: - * info.suboffsets = NULL - */ - __pyx_t_4 = __pyx_v_self->view.suboffsets; - __pyx_v_info->suboffsets = __pyx_t_4; - - /* "View.MemoryView":534 - * info.strides = NULL - * - * if flags & PyBUF_INDIRECT: # <<<<<<<<<<<<<< - * info.suboffsets = self.view.suboffsets - * else: - */ - goto __pyx_L8; - } - - /* "View.MemoryView":537 - * info.suboffsets = self.view.suboffsets - * else: - * info.suboffsets = NULL # <<<<<<<<<<<<<< - * - * if flags & PyBUF_FORMAT: - */ - /*else*/ { - __pyx_v_info->suboffsets = NULL; - } - __pyx_L8:; - - /* "View.MemoryView":539 - * info.suboffsets = NULL - * - * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< - * info.format = self.view.format - * else: - */ - __pyx_t_1 = ((__pyx_v_flags & PyBUF_FORMAT) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":540 - * - * if flags & PyBUF_FORMAT: - * info.format = self.view.format # <<<<<<<<<<<<<< - * else: - * info.format = NULL - */ - __pyx_t_5 = __pyx_v_self->view.format; - __pyx_v_info->format = __pyx_t_5; - - /* "View.MemoryView":539 - * info.suboffsets = NULL - * - * if flags & PyBUF_FORMAT: # <<<<<<<<<<<<<< - * info.format = self.view.format - * else: - */ - goto __pyx_L9; - } - - /* "View.MemoryView":542 - * info.format = self.view.format - * else: - * info.format = NULL # <<<<<<<<<<<<<< - * - * info.buf = self.view.buf - */ - /*else*/ { - __pyx_v_info->format = NULL; - } - __pyx_L9:; - - /* "View.MemoryView":544 - * info.format = NULL - * - * info.buf = self.view.buf # <<<<<<<<<<<<<< - * info.ndim = self.view.ndim - * info.itemsize = self.view.itemsize - */ - __pyx_t_6 = __pyx_v_self->view.buf; - __pyx_v_info->buf = __pyx_t_6; - - /* "View.MemoryView":545 - * - * info.buf = self.view.buf - * info.ndim = self.view.ndim # <<<<<<<<<<<<<< - * info.itemsize = self.view.itemsize - * info.len = self.view.len - */ - __pyx_t_7 = __pyx_v_self->view.ndim; - __pyx_v_info->ndim = __pyx_t_7; - - /* "View.MemoryView":546 - * info.buf = self.view.buf - * info.ndim = self.view.ndim - * info.itemsize = self.view.itemsize # <<<<<<<<<<<<<< - * info.len = self.view.len - * info.readonly = self.view.readonly - */ - __pyx_t_8 = __pyx_v_self->view.itemsize; - __pyx_v_info->itemsize = __pyx_t_8; - - /* "View.MemoryView":547 - * info.ndim = self.view.ndim - * info.itemsize = self.view.itemsize - * info.len = self.view.len # <<<<<<<<<<<<<< - * info.readonly = self.view.readonly - * info.obj = self - */ - __pyx_t_8 = __pyx_v_self->view.len; - __pyx_v_info->len = __pyx_t_8; - - /* "View.MemoryView":548 - * info.itemsize = self.view.itemsize - * info.len = self.view.len - * info.readonly = self.view.readonly # <<<<<<<<<<<<<< - * info.obj = self - * - */ - __pyx_t_1 = __pyx_v_self->view.readonly; - __pyx_v_info->readonly = __pyx_t_1; - - /* "View.MemoryView":549 - * info.len = self.view.len - * info.readonly = self.view.readonly - * info.obj = self # <<<<<<<<<<<<<< - * - * __pyx_getbuffer = capsule( &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)") - */ - __Pyx_INCREF(((PyObject *)__pyx_v_self)); - __Pyx_GIVEREF(((PyObject *)__pyx_v_self)); - __Pyx_GOTREF(__pyx_v_info->obj); - __Pyx_DECREF(__pyx_v_info->obj); - __pyx_v_info->obj = ((PyObject *)__pyx_v_self); - - /* "View.MemoryView":520 - * - * @cname('getbuffer') - * def __getbuffer__(self, Py_buffer *info, int flags): # <<<<<<<<<<<<<< - * if flags & PyBUF_WRITABLE and self.view.readonly: - * raise ValueError("Cannot create writable memory view from read-only memoryview") - */ - - /* function exit code */ - __pyx_r = 0; - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - if (__pyx_v_info->obj != NULL) { - __Pyx_GOTREF(__pyx_v_info->obj); - __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; - } - goto __pyx_L2; - __pyx_L0:; - if (__pyx_v_info->obj == Py_None) { - __Pyx_GOTREF(__pyx_v_info->obj); - __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = 0; - } - __pyx_L2:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":555 - * - * @property - * def T(self): # <<<<<<<<<<<<<< - * cdef _memoryviewslice result = memoryview_copy(self) - * transpose_memslice(&result.from_slice) - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_1T_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_1T_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_1T___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - struct __pyx_memoryviewslice_obj *__pyx_v_result = 0; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":556 - * @property - * def T(self): - * cdef _memoryviewslice result = memoryview_copy(self) # <<<<<<<<<<<<<< - * transpose_memslice(&result.from_slice) - * return result - */ - __pyx_t_1 = __pyx_memoryview_copy_object(__pyx_v_self); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 556, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_memoryviewslice_type))))) __PYX_ERR(2, 556, __pyx_L1_error) - __pyx_v_result = ((struct __pyx_memoryviewslice_obj *)__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":557 - * def T(self): - * cdef _memoryviewslice result = memoryview_copy(self) - * transpose_memslice(&result.from_slice) # <<<<<<<<<<<<<< - * return result - * - */ - __pyx_t_2 = __pyx_memslice_transpose((&__pyx_v_result->from_slice)); if (unlikely(__pyx_t_2 == ((int)0))) __PYX_ERR(2, 557, __pyx_L1_error) - - /* "View.MemoryView":558 - * cdef _memoryviewslice result = memoryview_copy(self) - * transpose_memslice(&result.from_slice) - * return result # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_result)); - __pyx_r = ((PyObject *)__pyx_v_result); - goto __pyx_L0; - - /* "View.MemoryView":555 - * - * @property - * def T(self): # <<<<<<<<<<<<<< - * cdef _memoryviewslice result = memoryview_copy(self) - * transpose_memslice(&result.from_slice) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.memoryview.T.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF((PyObject *)__pyx_v_result); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":561 - * - * @property - * def base(self): # <<<<<<<<<<<<<< - * return self.obj - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4base_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4base_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4base___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":562 - * @property - * def base(self): - * return self.obj # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_self->obj); - __pyx_r = __pyx_v_self->obj; - goto __pyx_L0; - - /* "View.MemoryView":561 - * - * @property - * def base(self): # <<<<<<<<<<<<<< - * return self.obj - * - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":565 - * - * @property - * def shape(self): # <<<<<<<<<<<<<< - * return tuple([length for length in self.view.shape[:self.view.ndim]]) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_5shape_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_5shape_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_5shape___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - Py_ssize_t __pyx_v_length; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t *__pyx_t_2; - Py_ssize_t *__pyx_t_3; - Py_ssize_t *__pyx_t_4; - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":566 - * @property - * def shape(self): - * return tuple([length for length in self.view.shape[:self.view.ndim]]) # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 566, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = (__pyx_v_self->view.shape + __pyx_v_self->view.ndim); - for (__pyx_t_4 = __pyx_v_self->view.shape; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) { - __pyx_t_2 = __pyx_t_4; - __pyx_v_length = (__pyx_t_2[0]); - __pyx_t_5 = PyInt_FromSsize_t(__pyx_v_length); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 566, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(2, 566, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - } - __pyx_t_5 = PyList_AsTuple(((PyObject*)__pyx_t_1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 566, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; - goto __pyx_L0; - - /* "View.MemoryView":565 - * - * @property - * def shape(self): # <<<<<<<<<<<<<< - * return tuple([length for length in self.view.shape[:self.view.ndim]]) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.memoryview.shape.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":569 - * - * @property - * def strides(self): # <<<<<<<<<<<<<< - * if self.view.strides == NULL: - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_7strides_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_7strides_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_7strides___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - Py_ssize_t __pyx_v_stride; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - Py_ssize_t *__pyx_t_3; - Py_ssize_t *__pyx_t_4; - Py_ssize_t *__pyx_t_5; - PyObject *__pyx_t_6 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":570 - * @property - * def strides(self): - * if self.view.strides == NULL: # <<<<<<<<<<<<<< - * - * raise ValueError("Buffer view does not expose strides") - */ - __pyx_t_1 = ((__pyx_v_self->view.strides == NULL) != 0); - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":572 - * if self.view.strides == NULL: - * - * raise ValueError("Buffer view does not expose strides") # <<<<<<<<<<<<<< - * - * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) - */ - __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__13, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 572, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_Raise(__pyx_t_2, 0, 0, 0); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __PYX_ERR(2, 572, __pyx_L1_error) - - /* "View.MemoryView":570 - * @property - * def strides(self): - * if self.view.strides == NULL: # <<<<<<<<<<<<<< - * - * raise ValueError("Buffer view does not expose strides") - */ - } - - /* "View.MemoryView":574 - * raise ValueError("Buffer view does not expose strides") - * - * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 574, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_4 = (__pyx_v_self->view.strides + __pyx_v_self->view.ndim); - for (__pyx_t_5 = __pyx_v_self->view.strides; __pyx_t_5 < __pyx_t_4; __pyx_t_5++) { - __pyx_t_3 = __pyx_t_5; - __pyx_v_stride = (__pyx_t_3[0]); - __pyx_t_6 = PyInt_FromSsize_t(__pyx_v_stride); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 574, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - if (unlikely(__Pyx_ListComp_Append(__pyx_t_2, (PyObject*)__pyx_t_6))) __PYX_ERR(2, 574, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - } - __pyx_t_6 = PyList_AsTuple(((PyObject*)__pyx_t_2)); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 574, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_6; - __pyx_t_6 = 0; - goto __pyx_L0; - - /* "View.MemoryView":569 - * - * @property - * def strides(self): # <<<<<<<<<<<<<< - * if self.view.strides == NULL: - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("View.MemoryView.memoryview.strides.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":577 - * - * @property - * def suboffsets(self): # <<<<<<<<<<<<<< - * if self.view.suboffsets == NULL: - * return (-1,) * self.view.ndim - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_10suboffsets_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_10suboffsets_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_10suboffsets___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - Py_ssize_t __pyx_v_suboffset; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - Py_ssize_t *__pyx_t_4; - Py_ssize_t *__pyx_t_5; - Py_ssize_t *__pyx_t_6; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":578 - * @property - * def suboffsets(self): - * if self.view.suboffsets == NULL: # <<<<<<<<<<<<<< - * return (-1,) * self.view.ndim - * - */ - __pyx_t_1 = ((__pyx_v_self->view.suboffsets == NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":579 - * def suboffsets(self): - * if self.view.suboffsets == NULL: - * return (-1,) * self.view.ndim # <<<<<<<<<<<<<< - * - * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_self->view.ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 579, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyNumber_Multiply(__pyx_tuple__14, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 579, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "View.MemoryView":578 - * @property - * def suboffsets(self): - * if self.view.suboffsets == NULL: # <<<<<<<<<<<<<< - * return (-1,) * self.view.ndim - * - */ - } - - /* "View.MemoryView":581 - * return (-1,) * self.view.ndim - * - * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 581, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_5 = (__pyx_v_self->view.suboffsets + __pyx_v_self->view.ndim); - for (__pyx_t_6 = __pyx_v_self->view.suboffsets; __pyx_t_6 < __pyx_t_5; __pyx_t_6++) { - __pyx_t_4 = __pyx_t_6; - __pyx_v_suboffset = (__pyx_t_4[0]); - __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_suboffset); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 581, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_t_2))) __PYX_ERR(2, 581, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - } - __pyx_t_2 = PyList_AsTuple(((PyObject*)__pyx_t_3)); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 581, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":577 - * - * @property - * def suboffsets(self): # <<<<<<<<<<<<<< - * if self.view.suboffsets == NULL: - * return (-1,) * self.view.ndim - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview.suboffsets.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":584 - * - * @property - * def ndim(self): # <<<<<<<<<<<<<< - * return self.view.ndim - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4ndim_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4ndim_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4ndim___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":585 - * @property - * def ndim(self): - * return self.view.ndim # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->view.ndim); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 585, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "View.MemoryView":584 - * - * @property - * def ndim(self): # <<<<<<<<<<<<<< - * return self.view.ndim - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.memoryview.ndim.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":588 - * - * @property - * def itemsize(self): # <<<<<<<<<<<<<< - * return self.view.itemsize - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_8itemsize_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_8itemsize_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_8itemsize___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":589 - * @property - * def itemsize(self): - * return self.view.itemsize # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 589, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "View.MemoryView":588 - * - * @property - * def itemsize(self): # <<<<<<<<<<<<<< - * return self.view.itemsize - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.memoryview.itemsize.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":592 - * - * @property - * def nbytes(self): # <<<<<<<<<<<<<< - * return self.size * self.view.itemsize - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_6nbytes_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_6nbytes_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_6nbytes___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":593 - * @property - * def nbytes(self): - * return self.size * self.view.itemsize # <<<<<<<<<<<<<< - * - * @property - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 593, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_self->view.itemsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 593, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyNumber_Multiply(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 593, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_3; - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "View.MemoryView":592 - * - * @property - * def nbytes(self): # <<<<<<<<<<<<<< - * return self.size * self.view.itemsize - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview.nbytes.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":596 - * - * @property - * def size(self): # <<<<<<<<<<<<<< - * if self._size is None: - * result = 1 - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4size_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_10memoryview_4size_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_10memoryview_4size___get__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_v_result = NULL; - PyObject *__pyx_v_length = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - Py_ssize_t *__pyx_t_3; - Py_ssize_t *__pyx_t_4; - Py_ssize_t *__pyx_t_5; - PyObject *__pyx_t_6 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":597 - * @property - * def size(self): - * if self._size is None: # <<<<<<<<<<<<<< - * result = 1 - * - */ - __pyx_t_1 = (__pyx_v_self->_size == Py_None); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":598 - * def size(self): - * if self._size is None: - * result = 1 # <<<<<<<<<<<<<< - * - * for length in self.view.shape[:self.view.ndim]: - */ - __Pyx_INCREF(__pyx_int_1); - __pyx_v_result = __pyx_int_1; - - /* "View.MemoryView":600 - * result = 1 - * - * for length in self.view.shape[:self.view.ndim]: # <<<<<<<<<<<<<< - * result *= length - * - */ - __pyx_t_4 = (__pyx_v_self->view.shape + __pyx_v_self->view.ndim); - for (__pyx_t_5 = __pyx_v_self->view.shape; __pyx_t_5 < __pyx_t_4; __pyx_t_5++) { - __pyx_t_3 = __pyx_t_5; - __pyx_t_6 = PyInt_FromSsize_t((__pyx_t_3[0])); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 600, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_XDECREF_SET(__pyx_v_length, __pyx_t_6); - __pyx_t_6 = 0; - - /* "View.MemoryView":601 - * - * for length in self.view.shape[:self.view.ndim]: - * result *= length # <<<<<<<<<<<<<< - * - * self._size = result - */ - __pyx_t_6 = PyNumber_InPlaceMultiply(__pyx_v_result, __pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 601, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF_SET(__pyx_v_result, __pyx_t_6); - __pyx_t_6 = 0; - } - - /* "View.MemoryView":603 - * result *= length - * - * self._size = result # <<<<<<<<<<<<<< - * - * return self._size - */ - __Pyx_INCREF(__pyx_v_result); - __Pyx_GIVEREF(__pyx_v_result); - __Pyx_GOTREF(__pyx_v_self->_size); - __Pyx_DECREF(__pyx_v_self->_size); - __pyx_v_self->_size = __pyx_v_result; - - /* "View.MemoryView":597 - * @property - * def size(self): - * if self._size is None: # <<<<<<<<<<<<<< - * result = 1 - * - */ - } - - /* "View.MemoryView":605 - * self._size = result - * - * return self._size # <<<<<<<<<<<<<< - * - * def __len__(self): - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_self->_size); - __pyx_r = __pyx_v_self->_size; - goto __pyx_L0; - - /* "View.MemoryView":596 - * - * @property - * def size(self): # <<<<<<<<<<<<<< - * if self._size is None: - * result = 1 - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("View.MemoryView.memoryview.size.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_result); - __Pyx_XDECREF(__pyx_v_length); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":607 - * return self._size - * - * def __len__(self): # <<<<<<<<<<<<<< - * if self.view.ndim >= 1: - * return self.view.shape[0] - */ - -/* Python wrapper */ -static Py_ssize_t __pyx_memoryview___len__(PyObject *__pyx_v_self); /*proto*/ -static Py_ssize_t __pyx_memoryview___len__(PyObject *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__len__ (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_10__len__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static Py_ssize_t __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_10__len__(struct __pyx_memoryview_obj *__pyx_v_self) { - Py_ssize_t __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - __Pyx_RefNannySetupContext("__len__", 0); - - /* "View.MemoryView":608 - * - * def __len__(self): - * if self.view.ndim >= 1: # <<<<<<<<<<<<<< - * return self.view.shape[0] - * - */ - __pyx_t_1 = ((__pyx_v_self->view.ndim >= 1) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":609 - * def __len__(self): - * if self.view.ndim >= 1: - * return self.view.shape[0] # <<<<<<<<<<<<<< - * - * return 0 - */ - __pyx_r = (__pyx_v_self->view.shape[0]); - goto __pyx_L0; - - /* "View.MemoryView":608 - * - * def __len__(self): - * if self.view.ndim >= 1: # <<<<<<<<<<<<<< - * return self.view.shape[0] - * - */ - } - - /* "View.MemoryView":611 - * return self.view.shape[0] - * - * return 0 # <<<<<<<<<<<<<< - * - * def __repr__(self): - */ - __pyx_r = 0; - goto __pyx_L0; - - /* "View.MemoryView":607 - * return self._size - * - * def __len__(self): # <<<<<<<<<<<<<< - * if self.view.ndim >= 1: - * return self.view.shape[0] - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":613 - * return 0 - * - * def __repr__(self): # <<<<<<<<<<<<<< - * return "" % (self.base.__class__.__name__, - * id(self)) - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview___repr__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_memoryview___repr__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12__repr__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_12__repr__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__repr__", 0); - - /* "View.MemoryView":614 - * - * def __repr__(self): - * return "" % (self.base.__class__.__name__, # <<<<<<<<<<<<<< - * id(self)) - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 614, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_class); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 614, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 614, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "View.MemoryView":615 - * def __repr__(self): - * return "" % (self.base.__class__.__name__, - * id(self)) # <<<<<<<<<<<<<< - * - * def __str__(self): - */ - __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 615, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - - /* "View.MemoryView":614 - * - * def __repr__(self): - * return "" % (self.base.__class__.__name__, # <<<<<<<<<<<<<< - * id(self)) - * - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 614, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2); - __pyx_t_1 = 0; - __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyString_Format(__pyx_kp_s_MemoryView_of_r_at_0x_x, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 614, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":613 - * return 0 - * - * def __repr__(self): # <<<<<<<<<<<<<< - * return "" % (self.base.__class__.__name__, - * id(self)) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":617 - * id(self)) - * - * def __str__(self): # <<<<<<<<<<<<<< - * return "" % (self.base.__class__.__name__,) - * - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview___str__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_memoryview___str__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__str__ (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14__str__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_14__str__(struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__str__", 0); - - /* "View.MemoryView":618 - * - * def __str__(self): - * return "" % (self.base.__class__.__name__,) # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 618, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_class); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 618, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_name_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 618, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 618, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1); - __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_PyString_Format(__pyx_kp_s_MemoryView_of_r_object, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 618, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "View.MemoryView":617 - * id(self)) - * - * def __str__(self): # <<<<<<<<<<<<<< - * return "" % (self.base.__class__.__name__,) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.memoryview.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":621 - * - * - * def is_c_contig(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice *mslice - * cdef __Pyx_memviewslice tmp - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview_is_c_contig(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_memoryview_is_c_contig(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("is_c_contig (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16is_c_contig(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_16is_c_contig(struct __pyx_memoryview_obj *__pyx_v_self) { - __Pyx_memviewslice *__pyx_v_mslice; - __Pyx_memviewslice __pyx_v_tmp; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice *__pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("is_c_contig", 0); - - /* "View.MemoryView":624 - * cdef __Pyx_memviewslice *mslice - * cdef __Pyx_memviewslice tmp - * mslice = get_slice_from_memview(self, &tmp) # <<<<<<<<<<<<<< - * return slice_is_contig(mslice[0], 'C', self.view.ndim) - * - */ - __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_self, (&__pyx_v_tmp)); if (unlikely(__pyx_t_1 == ((__Pyx_memviewslice *)NULL))) __PYX_ERR(2, 624, __pyx_L1_error) - __pyx_v_mslice = __pyx_t_1; - - /* "View.MemoryView":625 - * cdef __Pyx_memviewslice tmp - * mslice = get_slice_from_memview(self, &tmp) - * return slice_is_contig(mslice[0], 'C', self.view.ndim) # <<<<<<<<<<<<<< - * - * def is_f_contig(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_memviewslice_is_contig((__pyx_v_mslice[0]), 'C', __pyx_v_self->view.ndim)); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 625, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":621 - * - * - * def is_c_contig(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice *mslice - * cdef __Pyx_memviewslice tmp - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.memoryview.is_c_contig", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":627 - * return slice_is_contig(mslice[0], 'C', self.view.ndim) - * - * def is_f_contig(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice *mslice - * cdef __Pyx_memviewslice tmp - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview_is_f_contig(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_memoryview_is_f_contig(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("is_f_contig (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18is_f_contig(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_18is_f_contig(struct __pyx_memoryview_obj *__pyx_v_self) { - __Pyx_memviewslice *__pyx_v_mslice; - __Pyx_memviewslice __pyx_v_tmp; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice *__pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("is_f_contig", 0); - - /* "View.MemoryView":630 - * cdef __Pyx_memviewslice *mslice - * cdef __Pyx_memviewslice tmp - * mslice = get_slice_from_memview(self, &tmp) # <<<<<<<<<<<<<< - * return slice_is_contig(mslice[0], 'F', self.view.ndim) - * - */ - __pyx_t_1 = __pyx_memoryview_get_slice_from_memoryview(__pyx_v_self, (&__pyx_v_tmp)); if (unlikely(__pyx_t_1 == ((__Pyx_memviewslice *)NULL))) __PYX_ERR(2, 630, __pyx_L1_error) - __pyx_v_mslice = __pyx_t_1; - - /* "View.MemoryView":631 - * cdef __Pyx_memviewslice tmp - * mslice = get_slice_from_memview(self, &tmp) - * return slice_is_contig(mslice[0], 'F', self.view.ndim) # <<<<<<<<<<<<<< - * - * def copy(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_memviewslice_is_contig((__pyx_v_mslice[0]), 'F', __pyx_v_self->view.ndim)); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 631, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":627 - * return slice_is_contig(mslice[0], 'C', self.view.ndim) - * - * def is_f_contig(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice *mslice - * cdef __Pyx_memviewslice tmp - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.memoryview.is_f_contig", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":633 - * return slice_is_contig(mslice[0], 'F', self.view.ndim) - * - * def copy(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice mslice - * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview_copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_memoryview_copy(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("copy (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20copy(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_20copy(struct __pyx_memoryview_obj *__pyx_v_self) { - __Pyx_memviewslice __pyx_v_mslice; - int __pyx_v_flags; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("copy", 0); - - /* "View.MemoryView":635 - * def copy(self): - * cdef __Pyx_memviewslice mslice - * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS # <<<<<<<<<<<<<< - * - * slice_copy(self, &mslice) - */ - __pyx_v_flags = (__pyx_v_self->flags & (~PyBUF_F_CONTIGUOUS)); - - /* "View.MemoryView":637 - * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS - * - * slice_copy(self, &mslice) # <<<<<<<<<<<<<< - * mslice = slice_copy_contig(&mslice, "c", self.view.ndim, - * self.view.itemsize, - */ - __pyx_memoryview_slice_copy(__pyx_v_self, (&__pyx_v_mslice)); - - /* "View.MemoryView":638 - * - * slice_copy(self, &mslice) - * mslice = slice_copy_contig(&mslice, "c", self.view.ndim, # <<<<<<<<<<<<<< - * self.view.itemsize, - * flags|PyBUF_C_CONTIGUOUS, - */ - __pyx_t_1 = __pyx_memoryview_copy_new_contig((&__pyx_v_mslice), ((char *)"c"), __pyx_v_self->view.ndim, __pyx_v_self->view.itemsize, (__pyx_v_flags | PyBUF_C_CONTIGUOUS), __pyx_v_self->dtype_is_object); if (unlikely(PyErr_Occurred())) __PYX_ERR(2, 638, __pyx_L1_error) - __pyx_v_mslice = __pyx_t_1; - - /* "View.MemoryView":643 - * self.dtype_is_object) - * - * return memoryview_copy_from_slice(self, &mslice) # <<<<<<<<<<<<<< - * - * def copy_fortran(self): - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __pyx_memoryview_copy_object_from_slice(__pyx_v_self, (&__pyx_v_mslice)); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 643, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":633 - * return slice_is_contig(mslice[0], 'F', self.view.ndim) - * - * def copy(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice mslice - * cdef int flags = self.flags & ~PyBUF_F_CONTIGUOUS - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.memoryview.copy", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":645 - * return memoryview_copy_from_slice(self, &mslice) - * - * def copy_fortran(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice src, dst - * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS - */ - -/* Python wrapper */ -static PyObject *__pyx_memoryview_copy_fortran(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_memoryview_copy_fortran(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("copy_fortran (wrapper)", 0); - __pyx_r = __pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22copy_fortran(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_memoryview___pyx_pf_15View_dot_MemoryView_10memoryview_22copy_fortran(struct __pyx_memoryview_obj *__pyx_v_self) { - __Pyx_memviewslice __pyx_v_src; - __Pyx_memviewslice __pyx_v_dst; - int __pyx_v_flags; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_memviewslice __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("copy_fortran", 0); - - /* "View.MemoryView":647 - * def copy_fortran(self): - * cdef __Pyx_memviewslice src, dst - * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS # <<<<<<<<<<<<<< - * - * slice_copy(self, &src) - */ - __pyx_v_flags = (__pyx_v_self->flags & (~PyBUF_C_CONTIGUOUS)); - - /* "View.MemoryView":649 - * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS - * - * slice_copy(self, &src) # <<<<<<<<<<<<<< - * dst = slice_copy_contig(&src, "fortran", self.view.ndim, - * self.view.itemsize, - */ - __pyx_memoryview_slice_copy(__pyx_v_self, (&__pyx_v_src)); - - /* "View.MemoryView":650 - * - * slice_copy(self, &src) - * dst = slice_copy_contig(&src, "fortran", self.view.ndim, # <<<<<<<<<<<<<< - * self.view.itemsize, - * flags|PyBUF_F_CONTIGUOUS, - */ - __pyx_t_1 = __pyx_memoryview_copy_new_contig((&__pyx_v_src), ((char *)"fortran"), __pyx_v_self->view.ndim, __pyx_v_self->view.itemsize, (__pyx_v_flags | PyBUF_F_CONTIGUOUS), __pyx_v_self->dtype_is_object); if (unlikely(PyErr_Occurred())) __PYX_ERR(2, 650, __pyx_L1_error) - __pyx_v_dst = __pyx_t_1; - - /* "View.MemoryView":655 - * self.dtype_is_object) - * - * return memoryview_copy_from_slice(self, &dst) # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __pyx_memoryview_copy_object_from_slice(__pyx_v_self, (&__pyx_v_dst)); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 655, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":645 - * return memoryview_copy_from_slice(self, &mslice) - * - * def copy_fortran(self): # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice src, dst - * cdef int flags = self.flags & ~PyBUF_C_CONTIGUOUS - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView.memoryview.copy_fortran", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_memoryview_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw___pyx_memoryview_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_memoryview___reduce_cython__(((struct __pyx_memoryview_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_memoryview___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__reduce_cython__", 0); - - /* "(tree fragment)":2 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__15, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 2, __pyx_L1_error) - - /* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.memoryview.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":3 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_memoryview_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ -static PyObject *__pyx_pw___pyx_memoryview_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_memoryview_2__setstate_cython__(((struct __pyx_memoryview_obj *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_memoryview_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryview_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setstate_cython__", 0); - - /* "(tree fragment)":4 - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__16, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 4, __pyx_L1_error) - - /* "(tree fragment)":3 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.memoryview.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":659 - * - * @cname('__pyx_memoryview_new') - * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): # <<<<<<<<<<<<<< - * cdef memoryview result = memoryview(o, flags, dtype_is_object) - * result.typeinfo = typeinfo - */ - -static PyObject *__pyx_memoryview_new(PyObject *__pyx_v_o, int __pyx_v_flags, int __pyx_v_dtype_is_object, __Pyx_TypeInfo *__pyx_v_typeinfo) { - struct __pyx_memoryview_obj *__pyx_v_result = 0; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("memoryview_cwrapper", 0); - - /* "View.MemoryView":660 - * @cname('__pyx_memoryview_new') - * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): - * cdef memoryview result = memoryview(o, flags, dtype_is_object) # <<<<<<<<<<<<<< - * result.typeinfo = typeinfo - * return result - */ - __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_flags); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 660, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 660, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 660, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_o); - __Pyx_GIVEREF(__pyx_v_o); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_o); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2); - __pyx_t_1 = 0; - __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryview_type), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 660, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_result = ((struct __pyx_memoryview_obj *)__pyx_t_2); - __pyx_t_2 = 0; - - /* "View.MemoryView":661 - * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): - * cdef memoryview result = memoryview(o, flags, dtype_is_object) - * result.typeinfo = typeinfo # <<<<<<<<<<<<<< - * return result - * - */ - __pyx_v_result->typeinfo = __pyx_v_typeinfo; - - /* "View.MemoryView":662 - * cdef memoryview result = memoryview(o, flags, dtype_is_object) - * result.typeinfo = typeinfo - * return result # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_check') - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_result)); - __pyx_r = ((PyObject *)__pyx_v_result); - goto __pyx_L0; - - /* "View.MemoryView":659 - * - * @cname('__pyx_memoryview_new') - * cdef memoryview_cwrapper(object o, int flags, bint dtype_is_object, __Pyx_TypeInfo *typeinfo): # <<<<<<<<<<<<<< - * cdef memoryview result = memoryview(o, flags, dtype_is_object) - * result.typeinfo = typeinfo - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview_cwrapper", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF((PyObject *)__pyx_v_result); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":665 - * - * @cname('__pyx_memoryview_check') - * cdef inline bint memoryview_check(object o): # <<<<<<<<<<<<<< - * return isinstance(o, memoryview) - * - */ - -static CYTHON_INLINE int __pyx_memoryview_check(PyObject *__pyx_v_o) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - __Pyx_RefNannySetupContext("memoryview_check", 0); - - /* "View.MemoryView":666 - * @cname('__pyx_memoryview_check') - * cdef inline bint memoryview_check(object o): - * return isinstance(o, memoryview) # <<<<<<<<<<<<<< - * - * cdef tuple _unellipsify(object index, int ndim): - */ - __pyx_t_1 = __Pyx_TypeCheck(__pyx_v_o, __pyx_memoryview_type); - __pyx_r = __pyx_t_1; - goto __pyx_L0; - - /* "View.MemoryView":665 - * - * @cname('__pyx_memoryview_check') - * cdef inline bint memoryview_check(object o): # <<<<<<<<<<<<<< - * return isinstance(o, memoryview) - * - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":668 - * return isinstance(o, memoryview) - * - * cdef tuple _unellipsify(object index, int ndim): # <<<<<<<<<<<<<< - * """ - * Replace all ellipses with full slices and fill incomplete indices with - */ - -static PyObject *_unellipsify(PyObject *__pyx_v_index, int __pyx_v_ndim) { - PyObject *__pyx_v_tup = NULL; - PyObject *__pyx_v_result = NULL; - int __pyx_v_have_slices; - int __pyx_v_seen_ellipsis; - CYTHON_UNUSED PyObject *__pyx_v_idx = NULL; - PyObject *__pyx_v_item = NULL; - Py_ssize_t __pyx_v_nslices; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - Py_ssize_t __pyx_t_5; - PyObject *(*__pyx_t_6)(PyObject *); - PyObject *__pyx_t_7 = NULL; - Py_ssize_t __pyx_t_8; - int __pyx_t_9; - int __pyx_t_10; - PyObject *__pyx_t_11 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_unellipsify", 0); - - /* "View.MemoryView":673 - * full slices. - * """ - * if not isinstance(index, tuple): # <<<<<<<<<<<<<< - * tup = (index,) - * else: - */ - __pyx_t_1 = PyTuple_Check(__pyx_v_index); - __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":674 - * """ - * if not isinstance(index, tuple): - * tup = (index,) # <<<<<<<<<<<<<< - * else: - * tup = index - */ - __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 674, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_index); - __Pyx_GIVEREF(__pyx_v_index); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_index); - __pyx_v_tup = __pyx_t_3; - __pyx_t_3 = 0; - - /* "View.MemoryView":673 - * full slices. - * """ - * if not isinstance(index, tuple): # <<<<<<<<<<<<<< - * tup = (index,) - * else: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":676 - * tup = (index,) - * else: - * tup = index # <<<<<<<<<<<<<< - * - * result = [] - */ - /*else*/ { - __Pyx_INCREF(__pyx_v_index); - __pyx_v_tup = __pyx_v_index; - } - __pyx_L3:; - - /* "View.MemoryView":678 - * tup = index - * - * result = [] # <<<<<<<<<<<<<< - * have_slices = False - * seen_ellipsis = False - */ - __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 678, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_v_result = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "View.MemoryView":679 - * - * result = [] - * have_slices = False # <<<<<<<<<<<<<< - * seen_ellipsis = False - * for idx, item in enumerate(tup): - */ - __pyx_v_have_slices = 0; - - /* "View.MemoryView":680 - * result = [] - * have_slices = False - * seen_ellipsis = False # <<<<<<<<<<<<<< - * for idx, item in enumerate(tup): - * if item is Ellipsis: - */ - __pyx_v_seen_ellipsis = 0; - - /* "View.MemoryView":681 - * have_slices = False - * seen_ellipsis = False - * for idx, item in enumerate(tup): # <<<<<<<<<<<<<< - * if item is Ellipsis: - * if not seen_ellipsis: - */ - __Pyx_INCREF(__pyx_int_0); - __pyx_t_3 = __pyx_int_0; - if (likely(PyList_CheckExact(__pyx_v_tup)) || PyTuple_CheckExact(__pyx_v_tup)) { - __pyx_t_4 = __pyx_v_tup; __Pyx_INCREF(__pyx_t_4); __pyx_t_5 = 0; - __pyx_t_6 = NULL; - } else { - __pyx_t_5 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_tup); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 681, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 681, __pyx_L1_error) - } - for (;;) { - if (likely(!__pyx_t_6)) { - if (likely(PyList_CheckExact(__pyx_t_4))) { - if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_4)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(2, 681, __pyx_L1_error) - #else - __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 681, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - #endif - } else { - if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_4)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(2, 681, __pyx_L1_error) - #else - __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 681, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - #endif - } - } else { - __pyx_t_7 = __pyx_t_6(__pyx_t_4); - if (unlikely(!__pyx_t_7)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(2, 681, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_7); - } - __Pyx_XDECREF_SET(__pyx_v_item, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_INCREF(__pyx_t_3); - __Pyx_XDECREF_SET(__pyx_v_idx, __pyx_t_3); - __pyx_t_7 = __Pyx_PyInt_AddObjC(__pyx_t_3, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 681, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_3); - __pyx_t_3 = __pyx_t_7; - __pyx_t_7 = 0; - - /* "View.MemoryView":682 - * seen_ellipsis = False - * for idx, item in enumerate(tup): - * if item is Ellipsis: # <<<<<<<<<<<<<< - * if not seen_ellipsis: - * result.extend([slice(None)] * (ndim - len(tup) + 1)) - */ - __pyx_t_2 = (__pyx_v_item == __pyx_builtin_Ellipsis); - __pyx_t_1 = (__pyx_t_2 != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":683 - * for idx, item in enumerate(tup): - * if item is Ellipsis: - * if not seen_ellipsis: # <<<<<<<<<<<<<< - * result.extend([slice(None)] * (ndim - len(tup) + 1)) - * seen_ellipsis = True - */ - __pyx_t_1 = ((!(__pyx_v_seen_ellipsis != 0)) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":684 - * if item is Ellipsis: - * if not seen_ellipsis: - * result.extend([slice(None)] * (ndim - len(tup) + 1)) # <<<<<<<<<<<<<< - * seen_ellipsis = True - * else: - */ - __pyx_t_8 = PyObject_Length(__pyx_v_tup); if (unlikely(__pyx_t_8 == ((Py_ssize_t)-1))) __PYX_ERR(2, 684, __pyx_L1_error) - __pyx_t_7 = PyList_New(1 * ((((__pyx_v_ndim - __pyx_t_8) + 1)<0) ? 0:((__pyx_v_ndim - __pyx_t_8) + 1))); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 684, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - { Py_ssize_t __pyx_temp; - for (__pyx_temp=0; __pyx_temp < ((__pyx_v_ndim - __pyx_t_8) + 1); __pyx_temp++) { - __Pyx_INCREF(__pyx_slice__17); - __Pyx_GIVEREF(__pyx_slice__17); - PyList_SET_ITEM(__pyx_t_7, __pyx_temp, __pyx_slice__17); - } - } - __pyx_t_9 = __Pyx_PyList_Extend(__pyx_v_result, __pyx_t_7); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(2, 684, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - - /* "View.MemoryView":685 - * if not seen_ellipsis: - * result.extend([slice(None)] * (ndim - len(tup) + 1)) - * seen_ellipsis = True # <<<<<<<<<<<<<< - * else: - * result.append(slice(None)) - */ - __pyx_v_seen_ellipsis = 1; - - /* "View.MemoryView":683 - * for idx, item in enumerate(tup): - * if item is Ellipsis: - * if not seen_ellipsis: # <<<<<<<<<<<<<< - * result.extend([slice(None)] * (ndim - len(tup) + 1)) - * seen_ellipsis = True - */ - goto __pyx_L7; - } - - /* "View.MemoryView":687 - * seen_ellipsis = True - * else: - * result.append(slice(None)) # <<<<<<<<<<<<<< - * have_slices = True - * else: - */ - /*else*/ { - __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_result, __pyx_slice__17); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(2, 687, __pyx_L1_error) - } - __pyx_L7:; - - /* "View.MemoryView":688 - * else: - * result.append(slice(None)) - * have_slices = True # <<<<<<<<<<<<<< - * else: - * if not isinstance(item, slice) and not PyIndex_Check(item): - */ - __pyx_v_have_slices = 1; - - /* "View.MemoryView":682 - * seen_ellipsis = False - * for idx, item in enumerate(tup): - * if item is Ellipsis: # <<<<<<<<<<<<<< - * if not seen_ellipsis: - * result.extend([slice(None)] * (ndim - len(tup) + 1)) - */ - goto __pyx_L6; - } - - /* "View.MemoryView":690 - * have_slices = True - * else: - * if not isinstance(item, slice) and not PyIndex_Check(item): # <<<<<<<<<<<<<< - * raise TypeError("Cannot index with type '%s'" % type(item)) - * - */ - /*else*/ { - __pyx_t_2 = PySlice_Check(__pyx_v_item); - __pyx_t_10 = ((!(__pyx_t_2 != 0)) != 0); - if (__pyx_t_10) { - } else { - __pyx_t_1 = __pyx_t_10; - goto __pyx_L9_bool_binop_done; - } - __pyx_t_10 = ((!(PyIndex_Check(__pyx_v_item) != 0)) != 0); - __pyx_t_1 = __pyx_t_10; - __pyx_L9_bool_binop_done:; - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":691 - * else: - * if not isinstance(item, slice) and not PyIndex_Check(item): - * raise TypeError("Cannot index with type '%s'" % type(item)) # <<<<<<<<<<<<<< - * - * have_slices = have_slices or isinstance(item, slice) - */ - __pyx_t_7 = __Pyx_PyString_FormatSafe(__pyx_kp_s_Cannot_index_with_type_s, ((PyObject *)Py_TYPE(__pyx_v_item))); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 691, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_11 = __Pyx_PyObject_CallOneArg(__pyx_builtin_TypeError, __pyx_t_7); if (unlikely(!__pyx_t_11)) __PYX_ERR(2, 691, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_11); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_Raise(__pyx_t_11, 0, 0, 0); - __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0; - __PYX_ERR(2, 691, __pyx_L1_error) - - /* "View.MemoryView":690 - * have_slices = True - * else: - * if not isinstance(item, slice) and not PyIndex_Check(item): # <<<<<<<<<<<<<< - * raise TypeError("Cannot index with type '%s'" % type(item)) - * - */ - } - - /* "View.MemoryView":693 - * raise TypeError("Cannot index with type '%s'" % type(item)) - * - * have_slices = have_slices or isinstance(item, slice) # <<<<<<<<<<<<<< - * result.append(item) - * - */ - __pyx_t_10 = (__pyx_v_have_slices != 0); - if (!__pyx_t_10) { - } else { - __pyx_t_1 = __pyx_t_10; - goto __pyx_L11_bool_binop_done; - } - __pyx_t_10 = PySlice_Check(__pyx_v_item); - __pyx_t_2 = (__pyx_t_10 != 0); - __pyx_t_1 = __pyx_t_2; - __pyx_L11_bool_binop_done:; - __pyx_v_have_slices = __pyx_t_1; - - /* "View.MemoryView":694 - * - * have_slices = have_slices or isinstance(item, slice) - * result.append(item) # <<<<<<<<<<<<<< - * - * nslices = ndim - len(result) - */ - __pyx_t_9 = __Pyx_PyList_Append(__pyx_v_result, __pyx_v_item); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(2, 694, __pyx_L1_error) - } - __pyx_L6:; - - /* "View.MemoryView":681 - * have_slices = False - * seen_ellipsis = False - * for idx, item in enumerate(tup): # <<<<<<<<<<<<<< - * if item is Ellipsis: - * if not seen_ellipsis: - */ - } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "View.MemoryView":696 - * result.append(item) - * - * nslices = ndim - len(result) # <<<<<<<<<<<<<< - * if nslices: - * result.extend([slice(None)] * nslices) - */ - __pyx_t_5 = PyList_GET_SIZE(__pyx_v_result); if (unlikely(__pyx_t_5 == ((Py_ssize_t)-1))) __PYX_ERR(2, 696, __pyx_L1_error) - __pyx_v_nslices = (__pyx_v_ndim - __pyx_t_5); - - /* "View.MemoryView":697 - * - * nslices = ndim - len(result) - * if nslices: # <<<<<<<<<<<<<< - * result.extend([slice(None)] * nslices) - * - */ - __pyx_t_1 = (__pyx_v_nslices != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":698 - * nslices = ndim - len(result) - * if nslices: - * result.extend([slice(None)] * nslices) # <<<<<<<<<<<<<< - * - * return have_slices or nslices, tuple(result) - */ - __pyx_t_3 = PyList_New(1 * ((__pyx_v_nslices<0) ? 0:__pyx_v_nslices)); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 698, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - { Py_ssize_t __pyx_temp; - for (__pyx_temp=0; __pyx_temp < __pyx_v_nslices; __pyx_temp++) { - __Pyx_INCREF(__pyx_slice__17); - __Pyx_GIVEREF(__pyx_slice__17); - PyList_SET_ITEM(__pyx_t_3, __pyx_temp, __pyx_slice__17); - } - } - __pyx_t_9 = __Pyx_PyList_Extend(__pyx_v_result, __pyx_t_3); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(2, 698, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "View.MemoryView":697 - * - * nslices = ndim - len(result) - * if nslices: # <<<<<<<<<<<<<< - * result.extend([slice(None)] * nslices) - * - */ - } - - /* "View.MemoryView":700 - * result.extend([slice(None)] * nslices) - * - * return have_slices or nslices, tuple(result) # <<<<<<<<<<<<<< - * - * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): - */ - __Pyx_XDECREF(__pyx_r); - if (!__pyx_v_have_slices) { - } else { - __pyx_t_4 = __Pyx_PyBool_FromLong(__pyx_v_have_slices); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 700, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = __pyx_t_4; - __pyx_t_4 = 0; - goto __pyx_L14_bool_binop_done; - } - __pyx_t_4 = PyInt_FromSsize_t(__pyx_v_nslices); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 700, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = __pyx_t_4; - __pyx_t_4 = 0; - __pyx_L14_bool_binop_done:; - __pyx_t_4 = PyList_AsTuple(__pyx_v_result); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 700, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(2, 700, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_11); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_4); - PyTuple_SET_ITEM(__pyx_t_11, 1, __pyx_t_4); - __pyx_t_3 = 0; - __pyx_t_4 = 0; - __pyx_r = ((PyObject*)__pyx_t_11); - __pyx_t_11 = 0; - goto __pyx_L0; - - /* "View.MemoryView":668 - * return isinstance(o, memoryview) - * - * cdef tuple _unellipsify(object index, int ndim): # <<<<<<<<<<<<<< - * """ - * Replace all ellipses with full slices and fill incomplete indices with - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_11); - __Pyx_AddTraceback("View.MemoryView._unellipsify", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_tup); - __Pyx_XDECREF(__pyx_v_result); - __Pyx_XDECREF(__pyx_v_idx); - __Pyx_XDECREF(__pyx_v_item); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":702 - * return have_slices or nslices, tuple(result) - * - * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): # <<<<<<<<<<<<<< - * for suboffset in suboffsets[:ndim]: - * if suboffset >= 0: - */ - -static PyObject *assert_direct_dimensions(Py_ssize_t *__pyx_v_suboffsets, int __pyx_v_ndim) { - Py_ssize_t __pyx_v_suboffset; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - Py_ssize_t *__pyx_t_1; - Py_ssize_t *__pyx_t_2; - Py_ssize_t *__pyx_t_3; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("assert_direct_dimensions", 0); - - /* "View.MemoryView":703 - * - * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): - * for suboffset in suboffsets[:ndim]: # <<<<<<<<<<<<<< - * if suboffset >= 0: - * raise ValueError("Indirect dimensions not supported") - */ - __pyx_t_2 = (__pyx_v_suboffsets + __pyx_v_ndim); - for (__pyx_t_3 = __pyx_v_suboffsets; __pyx_t_3 < __pyx_t_2; __pyx_t_3++) { - __pyx_t_1 = __pyx_t_3; - __pyx_v_suboffset = (__pyx_t_1[0]); - - /* "View.MemoryView":704 - * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): - * for suboffset in suboffsets[:ndim]: - * if suboffset >= 0: # <<<<<<<<<<<<<< - * raise ValueError("Indirect dimensions not supported") - * - */ - __pyx_t_4 = ((__pyx_v_suboffset >= 0) != 0); - if (unlikely(__pyx_t_4)) { - - /* "View.MemoryView":705 - * for suboffset in suboffsets[:ndim]: - * if suboffset >= 0: - * raise ValueError("Indirect dimensions not supported") # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__18, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 705, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_Raise(__pyx_t_5, 0, 0, 0); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __PYX_ERR(2, 705, __pyx_L1_error) - - /* "View.MemoryView":704 - * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): - * for suboffset in suboffsets[:ndim]: - * if suboffset >= 0: # <<<<<<<<<<<<<< - * raise ValueError("Indirect dimensions not supported") - * - */ - } - } - - /* "View.MemoryView":702 - * return have_slices or nslices, tuple(result) - * - * cdef assert_direct_dimensions(Py_ssize_t *suboffsets, int ndim): # <<<<<<<<<<<<<< - * for suboffset in suboffsets[:ndim]: - * if suboffset >= 0: - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.assert_direct_dimensions", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":712 - * - * @cname('__pyx_memview_slice') - * cdef memoryview memview_slice(memoryview memview, object indices): # <<<<<<<<<<<<<< - * cdef int new_ndim = 0, suboffset_dim = -1, dim - * cdef bint negative_step - */ - -static struct __pyx_memoryview_obj *__pyx_memview_slice(struct __pyx_memoryview_obj *__pyx_v_memview, PyObject *__pyx_v_indices) { - int __pyx_v_new_ndim; - int __pyx_v_suboffset_dim; - int __pyx_v_dim; - __Pyx_memviewslice __pyx_v_src; - __Pyx_memviewslice __pyx_v_dst; - __Pyx_memviewslice *__pyx_v_p_src; - struct __pyx_memoryviewslice_obj *__pyx_v_memviewsliceobj = 0; - __Pyx_memviewslice *__pyx_v_p_dst; - int *__pyx_v_p_suboffset_dim; - Py_ssize_t __pyx_v_start; - Py_ssize_t __pyx_v_stop; - Py_ssize_t __pyx_v_step; - int __pyx_v_have_start; - int __pyx_v_have_stop; - int __pyx_v_have_step; - PyObject *__pyx_v_index = NULL; - struct __pyx_memoryview_obj *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - struct __pyx_memoryview_obj *__pyx_t_4; - char *__pyx_t_5; - int __pyx_t_6; - Py_ssize_t __pyx_t_7; - PyObject *(*__pyx_t_8)(PyObject *); - PyObject *__pyx_t_9 = NULL; - Py_ssize_t __pyx_t_10; - int __pyx_t_11; - Py_ssize_t __pyx_t_12; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("memview_slice", 0); - - /* "View.MemoryView":713 - * @cname('__pyx_memview_slice') - * cdef memoryview memview_slice(memoryview memview, object indices): - * cdef int new_ndim = 0, suboffset_dim = -1, dim # <<<<<<<<<<<<<< - * cdef bint negative_step - * cdef __Pyx_memviewslice src, dst - */ - __pyx_v_new_ndim = 0; - __pyx_v_suboffset_dim = -1; - - /* "View.MemoryView":720 - * - * - * memset(&dst, 0, sizeof(dst)) # <<<<<<<<<<<<<< - * - * cdef _memoryviewslice memviewsliceobj - */ - (void)(memset((&__pyx_v_dst), 0, (sizeof(__pyx_v_dst)))); - - /* "View.MemoryView":724 - * cdef _memoryviewslice memviewsliceobj - * - * assert memview.view.ndim > 0 # <<<<<<<<<<<<<< - * - * if isinstance(memview, _memoryviewslice): - */ - #ifndef CYTHON_WITHOUT_ASSERTIONS - if (unlikely(!Py_OptimizeFlag)) { - if (unlikely(!((__pyx_v_memview->view.ndim > 0) != 0))) { - PyErr_SetNone(PyExc_AssertionError); - __PYX_ERR(2, 724, __pyx_L1_error) - } - } - #endif - - /* "View.MemoryView":726 - * assert memview.view.ndim > 0 - * - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * memviewsliceobj = memview - * p_src = &memviewsliceobj.from_slice - */ - __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":727 - * - * if isinstance(memview, _memoryviewslice): - * memviewsliceobj = memview # <<<<<<<<<<<<<< - * p_src = &memviewsliceobj.from_slice - * else: - */ - if (!(likely(((((PyObject *)__pyx_v_memview)) == Py_None) || likely(__Pyx_TypeTest(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type))))) __PYX_ERR(2, 727, __pyx_L1_error) - __pyx_t_3 = ((PyObject *)__pyx_v_memview); - __Pyx_INCREF(__pyx_t_3); - __pyx_v_memviewsliceobj = ((struct __pyx_memoryviewslice_obj *)__pyx_t_3); - __pyx_t_3 = 0; - - /* "View.MemoryView":728 - * if isinstance(memview, _memoryviewslice): - * memviewsliceobj = memview - * p_src = &memviewsliceobj.from_slice # <<<<<<<<<<<<<< - * else: - * slice_copy(memview, &src) - */ - __pyx_v_p_src = (&__pyx_v_memviewsliceobj->from_slice); - - /* "View.MemoryView":726 - * assert memview.view.ndim > 0 - * - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * memviewsliceobj = memview - * p_src = &memviewsliceobj.from_slice - */ - goto __pyx_L3; - } - - /* "View.MemoryView":730 - * p_src = &memviewsliceobj.from_slice - * else: - * slice_copy(memview, &src) # <<<<<<<<<<<<<< - * p_src = &src - * - */ - /*else*/ { - __pyx_memoryview_slice_copy(__pyx_v_memview, (&__pyx_v_src)); - - /* "View.MemoryView":731 - * else: - * slice_copy(memview, &src) - * p_src = &src # <<<<<<<<<<<<<< - * - * - */ - __pyx_v_p_src = (&__pyx_v_src); - } - __pyx_L3:; - - /* "View.MemoryView":737 - * - * - * dst.memview = p_src.memview # <<<<<<<<<<<<<< - * dst.data = p_src.data - * - */ - __pyx_t_4 = __pyx_v_p_src->memview; - __pyx_v_dst.memview = __pyx_t_4; - - /* "View.MemoryView":738 - * - * dst.memview = p_src.memview - * dst.data = p_src.data # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_5 = __pyx_v_p_src->data; - __pyx_v_dst.data = __pyx_t_5; - - /* "View.MemoryView":743 - * - * - * cdef __Pyx_memviewslice *p_dst = &dst # <<<<<<<<<<<<<< - * cdef int *p_suboffset_dim = &suboffset_dim - * cdef Py_ssize_t start, stop, step - */ - __pyx_v_p_dst = (&__pyx_v_dst); - - /* "View.MemoryView":744 - * - * cdef __Pyx_memviewslice *p_dst = &dst - * cdef int *p_suboffset_dim = &suboffset_dim # <<<<<<<<<<<<<< - * cdef Py_ssize_t start, stop, step - * cdef bint have_start, have_stop, have_step - */ - __pyx_v_p_suboffset_dim = (&__pyx_v_suboffset_dim); - - /* "View.MemoryView":748 - * cdef bint have_start, have_stop, have_step - * - * for dim, index in enumerate(indices): # <<<<<<<<<<<<<< - * if PyIndex_Check(index): - * slice_memviewslice( - */ - __pyx_t_6 = 0; - if (likely(PyList_CheckExact(__pyx_v_indices)) || PyTuple_CheckExact(__pyx_v_indices)) { - __pyx_t_3 = __pyx_v_indices; __Pyx_INCREF(__pyx_t_3); __pyx_t_7 = 0; - __pyx_t_8 = NULL; - } else { - __pyx_t_7 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_indices); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 748, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_8)) __PYX_ERR(2, 748, __pyx_L1_error) - } - for (;;) { - if (likely(!__pyx_t_8)) { - if (likely(PyList_CheckExact(__pyx_t_3))) { - if (__pyx_t_7 >= PyList_GET_SIZE(__pyx_t_3)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_9 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_7); __Pyx_INCREF(__pyx_t_9); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(2, 748, __pyx_L1_error) - #else - __pyx_t_9 = PySequence_ITEM(__pyx_t_3, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 748, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - #endif - } else { - if (__pyx_t_7 >= PyTuple_GET_SIZE(__pyx_t_3)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_9 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_7); __Pyx_INCREF(__pyx_t_9); __pyx_t_7++; if (unlikely(0 < 0)) __PYX_ERR(2, 748, __pyx_L1_error) - #else - __pyx_t_9 = PySequence_ITEM(__pyx_t_3, __pyx_t_7); __pyx_t_7++; if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 748, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - #endif - } - } else { - __pyx_t_9 = __pyx_t_8(__pyx_t_3); - if (unlikely(!__pyx_t_9)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(2, 748, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_9); - } - __Pyx_XDECREF_SET(__pyx_v_index, __pyx_t_9); - __pyx_t_9 = 0; - __pyx_v_dim = __pyx_t_6; - __pyx_t_6 = (__pyx_t_6 + 1); - - /* "View.MemoryView":749 - * - * for dim, index in enumerate(indices): - * if PyIndex_Check(index): # <<<<<<<<<<<<<< - * slice_memviewslice( - * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], - */ - __pyx_t_2 = (PyIndex_Check(__pyx_v_index) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":753 - * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], - * dim, new_ndim, p_suboffset_dim, - * index, 0, 0, # start, stop, step # <<<<<<<<<<<<<< - * 0, 0, 0, # have_{start,stop,step} - * False) - */ - __pyx_t_10 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_10 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 753, __pyx_L1_error) - - /* "View.MemoryView":750 - * for dim, index in enumerate(indices): - * if PyIndex_Check(index): - * slice_memviewslice( # <<<<<<<<<<<<<< - * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], - * dim, new_ndim, p_suboffset_dim, - */ - __pyx_t_11 = __pyx_memoryview_slice_memviewslice(__pyx_v_p_dst, (__pyx_v_p_src->shape[__pyx_v_dim]), (__pyx_v_p_src->strides[__pyx_v_dim]), (__pyx_v_p_src->suboffsets[__pyx_v_dim]), __pyx_v_dim, __pyx_v_new_ndim, __pyx_v_p_suboffset_dim, __pyx_t_10, 0, 0, 0, 0, 0, 0); if (unlikely(__pyx_t_11 == ((int)-1))) __PYX_ERR(2, 750, __pyx_L1_error) - - /* "View.MemoryView":749 - * - * for dim, index in enumerate(indices): - * if PyIndex_Check(index): # <<<<<<<<<<<<<< - * slice_memviewslice( - * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], - */ - goto __pyx_L6; - } - - /* "View.MemoryView":756 - * 0, 0, 0, # have_{start,stop,step} - * False) - * elif index is None: # <<<<<<<<<<<<<< - * p_dst.shape[new_ndim] = 1 - * p_dst.strides[new_ndim] = 0 - */ - __pyx_t_2 = (__pyx_v_index == Py_None); - __pyx_t_1 = (__pyx_t_2 != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":757 - * False) - * elif index is None: - * p_dst.shape[new_ndim] = 1 # <<<<<<<<<<<<<< - * p_dst.strides[new_ndim] = 0 - * p_dst.suboffsets[new_ndim] = -1 - */ - (__pyx_v_p_dst->shape[__pyx_v_new_ndim]) = 1; - - /* "View.MemoryView":758 - * elif index is None: - * p_dst.shape[new_ndim] = 1 - * p_dst.strides[new_ndim] = 0 # <<<<<<<<<<<<<< - * p_dst.suboffsets[new_ndim] = -1 - * new_ndim += 1 - */ - (__pyx_v_p_dst->strides[__pyx_v_new_ndim]) = 0; - - /* "View.MemoryView":759 - * p_dst.shape[new_ndim] = 1 - * p_dst.strides[new_ndim] = 0 - * p_dst.suboffsets[new_ndim] = -1 # <<<<<<<<<<<<<< - * new_ndim += 1 - * else: - */ - (__pyx_v_p_dst->suboffsets[__pyx_v_new_ndim]) = -1L; - - /* "View.MemoryView":760 - * p_dst.strides[new_ndim] = 0 - * p_dst.suboffsets[new_ndim] = -1 - * new_ndim += 1 # <<<<<<<<<<<<<< - * else: - * start = index.start or 0 - */ - __pyx_v_new_ndim = (__pyx_v_new_ndim + 1); - - /* "View.MemoryView":756 - * 0, 0, 0, # have_{start,stop,step} - * False) - * elif index is None: # <<<<<<<<<<<<<< - * p_dst.shape[new_ndim] = 1 - * p_dst.strides[new_ndim] = 0 - */ - goto __pyx_L6; - } - - /* "View.MemoryView":762 - * new_ndim += 1 - * else: - * start = index.start or 0 # <<<<<<<<<<<<<< - * stop = index.stop or 0 - * step = index.step or 0 - */ - /*else*/ { - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_start); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 762, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(2, 762, __pyx_L1_error) - if (!__pyx_t_1) { - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - } else { - __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_t_9); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 762, __pyx_L1_error) - __pyx_t_10 = __pyx_t_12; - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - goto __pyx_L7_bool_binop_done; - } - __pyx_t_10 = 0; - __pyx_L7_bool_binop_done:; - __pyx_v_start = __pyx_t_10; - - /* "View.MemoryView":763 - * else: - * start = index.start or 0 - * stop = index.stop or 0 # <<<<<<<<<<<<<< - * step = index.step or 0 - * - */ - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_stop); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 763, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(2, 763, __pyx_L1_error) - if (!__pyx_t_1) { - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - } else { - __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_t_9); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 763, __pyx_L1_error) - __pyx_t_10 = __pyx_t_12; - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - goto __pyx_L9_bool_binop_done; - } - __pyx_t_10 = 0; - __pyx_L9_bool_binop_done:; - __pyx_v_stop = __pyx_t_10; - - /* "View.MemoryView":764 - * start = index.start or 0 - * stop = index.stop or 0 - * step = index.step or 0 # <<<<<<<<<<<<<< - * - * have_start = index.start is not None - */ - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_step); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 764, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(2, 764, __pyx_L1_error) - if (!__pyx_t_1) { - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - } else { - __pyx_t_12 = __Pyx_PyIndex_AsSsize_t(__pyx_t_9); if (unlikely((__pyx_t_12 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 764, __pyx_L1_error) - __pyx_t_10 = __pyx_t_12; - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - goto __pyx_L11_bool_binop_done; - } - __pyx_t_10 = 0; - __pyx_L11_bool_binop_done:; - __pyx_v_step = __pyx_t_10; - - /* "View.MemoryView":766 - * step = index.step or 0 - * - * have_start = index.start is not None # <<<<<<<<<<<<<< - * have_stop = index.stop is not None - * have_step = index.step is not None - */ - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_start); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 766, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_1 = (__pyx_t_9 != Py_None); - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - __pyx_v_have_start = __pyx_t_1; - - /* "View.MemoryView":767 - * - * have_start = index.start is not None - * have_stop = index.stop is not None # <<<<<<<<<<<<<< - * have_step = index.step is not None - * - */ - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_stop); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 767, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_1 = (__pyx_t_9 != Py_None); - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - __pyx_v_have_stop = __pyx_t_1; - - /* "View.MemoryView":768 - * have_start = index.start is not None - * have_stop = index.stop is not None - * have_step = index.step is not None # <<<<<<<<<<<<<< - * - * slice_memviewslice( - */ - __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_v_index, __pyx_n_s_step); if (unlikely(!__pyx_t_9)) __PYX_ERR(2, 768, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __pyx_t_1 = (__pyx_t_9 != Py_None); - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - __pyx_v_have_step = __pyx_t_1; - - /* "View.MemoryView":770 - * have_step = index.step is not None - * - * slice_memviewslice( # <<<<<<<<<<<<<< - * p_dst, p_src.shape[dim], p_src.strides[dim], p_src.suboffsets[dim], - * dim, new_ndim, p_suboffset_dim, - */ - __pyx_t_11 = __pyx_memoryview_slice_memviewslice(__pyx_v_p_dst, (__pyx_v_p_src->shape[__pyx_v_dim]), (__pyx_v_p_src->strides[__pyx_v_dim]), (__pyx_v_p_src->suboffsets[__pyx_v_dim]), __pyx_v_dim, __pyx_v_new_ndim, __pyx_v_p_suboffset_dim, __pyx_v_start, __pyx_v_stop, __pyx_v_step, __pyx_v_have_start, __pyx_v_have_stop, __pyx_v_have_step, 1); if (unlikely(__pyx_t_11 == ((int)-1))) __PYX_ERR(2, 770, __pyx_L1_error) - - /* "View.MemoryView":776 - * have_start, have_stop, have_step, - * True) - * new_ndim += 1 # <<<<<<<<<<<<<< - * - * if isinstance(memview, _memoryviewslice): - */ - __pyx_v_new_ndim = (__pyx_v_new_ndim + 1); - } - __pyx_L6:; - - /* "View.MemoryView":748 - * cdef bint have_start, have_stop, have_step - * - * for dim, index in enumerate(indices): # <<<<<<<<<<<<<< - * if PyIndex_Check(index): - * slice_memviewslice( - */ - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "View.MemoryView":778 - * new_ndim += 1 - * - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * return memoryview_fromslice(dst, new_ndim, - * memviewsliceobj.to_object_func, - */ - __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":779 - * - * if isinstance(memview, _memoryviewslice): - * return memoryview_fromslice(dst, new_ndim, # <<<<<<<<<<<<<< - * memviewsliceobj.to_object_func, - * memviewsliceobj.to_dtype_func, - */ - __Pyx_XDECREF(((PyObject *)__pyx_r)); - - /* "View.MemoryView":780 - * if isinstance(memview, _memoryviewslice): - * return memoryview_fromslice(dst, new_ndim, - * memviewsliceobj.to_object_func, # <<<<<<<<<<<<<< - * memviewsliceobj.to_dtype_func, - * memview.dtype_is_object) - */ - if (unlikely(!__pyx_v_memviewsliceobj)) { __Pyx_RaiseUnboundLocalError("memviewsliceobj"); __PYX_ERR(2, 780, __pyx_L1_error) } - - /* "View.MemoryView":781 - * return memoryview_fromslice(dst, new_ndim, - * memviewsliceobj.to_object_func, - * memviewsliceobj.to_dtype_func, # <<<<<<<<<<<<<< - * memview.dtype_is_object) - * else: - */ - if (unlikely(!__pyx_v_memviewsliceobj)) { __Pyx_RaiseUnboundLocalError("memviewsliceobj"); __PYX_ERR(2, 781, __pyx_L1_error) } - - /* "View.MemoryView":779 - * - * if isinstance(memview, _memoryviewslice): - * return memoryview_fromslice(dst, new_ndim, # <<<<<<<<<<<<<< - * memviewsliceobj.to_object_func, - * memviewsliceobj.to_dtype_func, - */ - __pyx_t_3 = __pyx_memoryview_fromslice(__pyx_v_dst, __pyx_v_new_ndim, __pyx_v_memviewsliceobj->to_object_func, __pyx_v_memviewsliceobj->to_dtype_func, __pyx_v_memview->dtype_is_object); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 779, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_memoryview_type))))) __PYX_ERR(2, 779, __pyx_L1_error) - __pyx_r = ((struct __pyx_memoryview_obj *)__pyx_t_3); - __pyx_t_3 = 0; - goto __pyx_L0; - - /* "View.MemoryView":778 - * new_ndim += 1 - * - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * return memoryview_fromslice(dst, new_ndim, - * memviewsliceobj.to_object_func, - */ - } - - /* "View.MemoryView":784 - * memview.dtype_is_object) - * else: - * return memoryview_fromslice(dst, new_ndim, NULL, NULL, # <<<<<<<<<<<<<< - * memview.dtype_is_object) - * - */ - /*else*/ { - __Pyx_XDECREF(((PyObject *)__pyx_r)); - - /* "View.MemoryView":785 - * else: - * return memoryview_fromslice(dst, new_ndim, NULL, NULL, - * memview.dtype_is_object) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_3 = __pyx_memoryview_fromslice(__pyx_v_dst, __pyx_v_new_ndim, NULL, NULL, __pyx_v_memview->dtype_is_object); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 784, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - - /* "View.MemoryView":784 - * memview.dtype_is_object) - * else: - * return memoryview_fromslice(dst, new_ndim, NULL, NULL, # <<<<<<<<<<<<<< - * memview.dtype_is_object) - * - */ - if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_memoryview_type))))) __PYX_ERR(2, 784, __pyx_L1_error) - __pyx_r = ((struct __pyx_memoryview_obj *)__pyx_t_3); - __pyx_t_3 = 0; - goto __pyx_L0; - } - - /* "View.MemoryView":712 - * - * @cname('__pyx_memview_slice') - * cdef memoryview memview_slice(memoryview memview, object indices): # <<<<<<<<<<<<<< - * cdef int new_ndim = 0, suboffset_dim = -1, dim - * cdef bint negative_step - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_9); - __Pyx_AddTraceback("View.MemoryView.memview_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF((PyObject *)__pyx_v_memviewsliceobj); - __Pyx_XDECREF(__pyx_v_index); - __Pyx_XGIVEREF((PyObject *)__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":809 - * - * @cname('__pyx_memoryview_slice_memviewslice') - * cdef int slice_memviewslice( # <<<<<<<<<<<<<< - * __Pyx_memviewslice *dst, - * Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset, - */ - -static int __pyx_memoryview_slice_memviewslice(__Pyx_memviewslice *__pyx_v_dst, Py_ssize_t __pyx_v_shape, Py_ssize_t __pyx_v_stride, Py_ssize_t __pyx_v_suboffset, int __pyx_v_dim, int __pyx_v_new_ndim, int *__pyx_v_suboffset_dim, Py_ssize_t __pyx_v_start, Py_ssize_t __pyx_v_stop, Py_ssize_t __pyx_v_step, int __pyx_v_have_start, int __pyx_v_have_stop, int __pyx_v_have_step, int __pyx_v_is_slice) { - Py_ssize_t __pyx_v_new_shape; - int __pyx_v_negative_step; - int __pyx_r; - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - - /* "View.MemoryView":829 - * cdef bint negative_step - * - * if not is_slice: # <<<<<<<<<<<<<< - * - * if start < 0: - */ - __pyx_t_1 = ((!(__pyx_v_is_slice != 0)) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":831 - * if not is_slice: - * - * if start < 0: # <<<<<<<<<<<<<< - * start += shape - * if not 0 <= start < shape: - */ - __pyx_t_1 = ((__pyx_v_start < 0) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":832 - * - * if start < 0: - * start += shape # <<<<<<<<<<<<<< - * if not 0 <= start < shape: - * _err_dim(IndexError, "Index out of bounds (axis %d)", dim) - */ - __pyx_v_start = (__pyx_v_start + __pyx_v_shape); - - /* "View.MemoryView":831 - * if not is_slice: - * - * if start < 0: # <<<<<<<<<<<<<< - * start += shape - * if not 0 <= start < shape: - */ - } - - /* "View.MemoryView":833 - * if start < 0: - * start += shape - * if not 0 <= start < shape: # <<<<<<<<<<<<<< - * _err_dim(IndexError, "Index out of bounds (axis %d)", dim) - * else: - */ - __pyx_t_1 = (0 <= __pyx_v_start); - if (__pyx_t_1) { - __pyx_t_1 = (__pyx_v_start < __pyx_v_shape); - } - __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":834 - * start += shape - * if not 0 <= start < shape: - * _err_dim(IndexError, "Index out of bounds (axis %d)", dim) # <<<<<<<<<<<<<< - * else: - * - */ - __pyx_t_3 = __pyx_memoryview_err_dim(__pyx_builtin_IndexError, ((char *)"Index out of bounds (axis %d)"), __pyx_v_dim); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(2, 834, __pyx_L1_error) - - /* "View.MemoryView":833 - * if start < 0: - * start += shape - * if not 0 <= start < shape: # <<<<<<<<<<<<<< - * _err_dim(IndexError, "Index out of bounds (axis %d)", dim) - * else: - */ - } - - /* "View.MemoryView":829 - * cdef bint negative_step - * - * if not is_slice: # <<<<<<<<<<<<<< - * - * if start < 0: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":837 - * else: - * - * negative_step = have_step != 0 and step < 0 # <<<<<<<<<<<<<< - * - * if have_step and step == 0: - */ - /*else*/ { - __pyx_t_1 = ((__pyx_v_have_step != 0) != 0); - if (__pyx_t_1) { - } else { - __pyx_t_2 = __pyx_t_1; - goto __pyx_L6_bool_binop_done; - } - __pyx_t_1 = ((__pyx_v_step < 0) != 0); - __pyx_t_2 = __pyx_t_1; - __pyx_L6_bool_binop_done:; - __pyx_v_negative_step = __pyx_t_2; - - /* "View.MemoryView":839 - * negative_step = have_step != 0 and step < 0 - * - * if have_step and step == 0: # <<<<<<<<<<<<<< - * _err_dim(ValueError, "Step may not be zero (axis %d)", dim) - * - */ - __pyx_t_1 = (__pyx_v_have_step != 0); - if (__pyx_t_1) { - } else { - __pyx_t_2 = __pyx_t_1; - goto __pyx_L9_bool_binop_done; - } - __pyx_t_1 = ((__pyx_v_step == 0) != 0); - __pyx_t_2 = __pyx_t_1; - __pyx_L9_bool_binop_done:; - if (__pyx_t_2) { - - /* "View.MemoryView":840 - * - * if have_step and step == 0: - * _err_dim(ValueError, "Step may not be zero (axis %d)", dim) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_3 = __pyx_memoryview_err_dim(__pyx_builtin_ValueError, ((char *)"Step may not be zero (axis %d)"), __pyx_v_dim); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(2, 840, __pyx_L1_error) - - /* "View.MemoryView":839 - * negative_step = have_step != 0 and step < 0 - * - * if have_step and step == 0: # <<<<<<<<<<<<<< - * _err_dim(ValueError, "Step may not be zero (axis %d)", dim) - * - */ - } - - /* "View.MemoryView":843 - * - * - * if have_start: # <<<<<<<<<<<<<< - * if start < 0: - * start += shape - */ - __pyx_t_2 = (__pyx_v_have_start != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":844 - * - * if have_start: - * if start < 0: # <<<<<<<<<<<<<< - * start += shape - * if start < 0: - */ - __pyx_t_2 = ((__pyx_v_start < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":845 - * if have_start: - * if start < 0: - * start += shape # <<<<<<<<<<<<<< - * if start < 0: - * start = 0 - */ - __pyx_v_start = (__pyx_v_start + __pyx_v_shape); - - /* "View.MemoryView":846 - * if start < 0: - * start += shape - * if start < 0: # <<<<<<<<<<<<<< - * start = 0 - * elif start >= shape: - */ - __pyx_t_2 = ((__pyx_v_start < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":847 - * start += shape - * if start < 0: - * start = 0 # <<<<<<<<<<<<<< - * elif start >= shape: - * if negative_step: - */ - __pyx_v_start = 0; - - /* "View.MemoryView":846 - * if start < 0: - * start += shape - * if start < 0: # <<<<<<<<<<<<<< - * start = 0 - * elif start >= shape: - */ - } - - /* "View.MemoryView":844 - * - * if have_start: - * if start < 0: # <<<<<<<<<<<<<< - * start += shape - * if start < 0: - */ - goto __pyx_L12; - } - - /* "View.MemoryView":848 - * if start < 0: - * start = 0 - * elif start >= shape: # <<<<<<<<<<<<<< - * if negative_step: - * start = shape - 1 - */ - __pyx_t_2 = ((__pyx_v_start >= __pyx_v_shape) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":849 - * start = 0 - * elif start >= shape: - * if negative_step: # <<<<<<<<<<<<<< - * start = shape - 1 - * else: - */ - __pyx_t_2 = (__pyx_v_negative_step != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":850 - * elif start >= shape: - * if negative_step: - * start = shape - 1 # <<<<<<<<<<<<<< - * else: - * start = shape - */ - __pyx_v_start = (__pyx_v_shape - 1); - - /* "View.MemoryView":849 - * start = 0 - * elif start >= shape: - * if negative_step: # <<<<<<<<<<<<<< - * start = shape - 1 - * else: - */ - goto __pyx_L14; - } - - /* "View.MemoryView":852 - * start = shape - 1 - * else: - * start = shape # <<<<<<<<<<<<<< - * else: - * if negative_step: - */ - /*else*/ { - __pyx_v_start = __pyx_v_shape; - } - __pyx_L14:; - - /* "View.MemoryView":848 - * if start < 0: - * start = 0 - * elif start >= shape: # <<<<<<<<<<<<<< - * if negative_step: - * start = shape - 1 - */ - } - __pyx_L12:; - - /* "View.MemoryView":843 - * - * - * if have_start: # <<<<<<<<<<<<<< - * if start < 0: - * start += shape - */ - goto __pyx_L11; - } - - /* "View.MemoryView":854 - * start = shape - * else: - * if negative_step: # <<<<<<<<<<<<<< - * start = shape - 1 - * else: - */ - /*else*/ { - __pyx_t_2 = (__pyx_v_negative_step != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":855 - * else: - * if negative_step: - * start = shape - 1 # <<<<<<<<<<<<<< - * else: - * start = 0 - */ - __pyx_v_start = (__pyx_v_shape - 1); - - /* "View.MemoryView":854 - * start = shape - * else: - * if negative_step: # <<<<<<<<<<<<<< - * start = shape - 1 - * else: - */ - goto __pyx_L15; - } - - /* "View.MemoryView":857 - * start = shape - 1 - * else: - * start = 0 # <<<<<<<<<<<<<< - * - * if have_stop: - */ - /*else*/ { - __pyx_v_start = 0; - } - __pyx_L15:; - } - __pyx_L11:; - - /* "View.MemoryView":859 - * start = 0 - * - * if have_stop: # <<<<<<<<<<<<<< - * if stop < 0: - * stop += shape - */ - __pyx_t_2 = (__pyx_v_have_stop != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":860 - * - * if have_stop: - * if stop < 0: # <<<<<<<<<<<<<< - * stop += shape - * if stop < 0: - */ - __pyx_t_2 = ((__pyx_v_stop < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":861 - * if have_stop: - * if stop < 0: - * stop += shape # <<<<<<<<<<<<<< - * if stop < 0: - * stop = 0 - */ - __pyx_v_stop = (__pyx_v_stop + __pyx_v_shape); - - /* "View.MemoryView":862 - * if stop < 0: - * stop += shape - * if stop < 0: # <<<<<<<<<<<<<< - * stop = 0 - * elif stop > shape: - */ - __pyx_t_2 = ((__pyx_v_stop < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":863 - * stop += shape - * if stop < 0: - * stop = 0 # <<<<<<<<<<<<<< - * elif stop > shape: - * stop = shape - */ - __pyx_v_stop = 0; - - /* "View.MemoryView":862 - * if stop < 0: - * stop += shape - * if stop < 0: # <<<<<<<<<<<<<< - * stop = 0 - * elif stop > shape: - */ - } - - /* "View.MemoryView":860 - * - * if have_stop: - * if stop < 0: # <<<<<<<<<<<<<< - * stop += shape - * if stop < 0: - */ - goto __pyx_L17; - } - - /* "View.MemoryView":864 - * if stop < 0: - * stop = 0 - * elif stop > shape: # <<<<<<<<<<<<<< - * stop = shape - * else: - */ - __pyx_t_2 = ((__pyx_v_stop > __pyx_v_shape) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":865 - * stop = 0 - * elif stop > shape: - * stop = shape # <<<<<<<<<<<<<< - * else: - * if negative_step: - */ - __pyx_v_stop = __pyx_v_shape; - - /* "View.MemoryView":864 - * if stop < 0: - * stop = 0 - * elif stop > shape: # <<<<<<<<<<<<<< - * stop = shape - * else: - */ - } - __pyx_L17:; - - /* "View.MemoryView":859 - * start = 0 - * - * if have_stop: # <<<<<<<<<<<<<< - * if stop < 0: - * stop += shape - */ - goto __pyx_L16; - } - - /* "View.MemoryView":867 - * stop = shape - * else: - * if negative_step: # <<<<<<<<<<<<<< - * stop = -1 - * else: - */ - /*else*/ { - __pyx_t_2 = (__pyx_v_negative_step != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":868 - * else: - * if negative_step: - * stop = -1 # <<<<<<<<<<<<<< - * else: - * stop = shape - */ - __pyx_v_stop = -1L; - - /* "View.MemoryView":867 - * stop = shape - * else: - * if negative_step: # <<<<<<<<<<<<<< - * stop = -1 - * else: - */ - goto __pyx_L19; - } - - /* "View.MemoryView":870 - * stop = -1 - * else: - * stop = shape # <<<<<<<<<<<<<< - * - * if not have_step: - */ - /*else*/ { - __pyx_v_stop = __pyx_v_shape; - } - __pyx_L19:; - } - __pyx_L16:; - - /* "View.MemoryView":872 - * stop = shape - * - * if not have_step: # <<<<<<<<<<<<<< - * step = 1 - * - */ - __pyx_t_2 = ((!(__pyx_v_have_step != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":873 - * - * if not have_step: - * step = 1 # <<<<<<<<<<<<<< - * - * - */ - __pyx_v_step = 1; - - /* "View.MemoryView":872 - * stop = shape - * - * if not have_step: # <<<<<<<<<<<<<< - * step = 1 - * - */ - } - - /* "View.MemoryView":877 - * - * with cython.cdivision(True): - * new_shape = (stop - start) // step # <<<<<<<<<<<<<< - * - * if (stop - start) - step * new_shape: - */ - __pyx_v_new_shape = ((__pyx_v_stop - __pyx_v_start) / __pyx_v_step); - - /* "View.MemoryView":879 - * new_shape = (stop - start) // step - * - * if (stop - start) - step * new_shape: # <<<<<<<<<<<<<< - * new_shape += 1 - * - */ - __pyx_t_2 = (((__pyx_v_stop - __pyx_v_start) - (__pyx_v_step * __pyx_v_new_shape)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":880 - * - * if (stop - start) - step * new_shape: - * new_shape += 1 # <<<<<<<<<<<<<< - * - * if new_shape < 0: - */ - __pyx_v_new_shape = (__pyx_v_new_shape + 1); - - /* "View.MemoryView":879 - * new_shape = (stop - start) // step - * - * if (stop - start) - step * new_shape: # <<<<<<<<<<<<<< - * new_shape += 1 - * - */ - } - - /* "View.MemoryView":882 - * new_shape += 1 - * - * if new_shape < 0: # <<<<<<<<<<<<<< - * new_shape = 0 - * - */ - __pyx_t_2 = ((__pyx_v_new_shape < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":883 - * - * if new_shape < 0: - * new_shape = 0 # <<<<<<<<<<<<<< - * - * - */ - __pyx_v_new_shape = 0; - - /* "View.MemoryView":882 - * new_shape += 1 - * - * if new_shape < 0: # <<<<<<<<<<<<<< - * new_shape = 0 - * - */ - } - - /* "View.MemoryView":886 - * - * - * dst.strides[new_ndim] = stride * step # <<<<<<<<<<<<<< - * dst.shape[new_ndim] = new_shape - * dst.suboffsets[new_ndim] = suboffset - */ - (__pyx_v_dst->strides[__pyx_v_new_ndim]) = (__pyx_v_stride * __pyx_v_step); - - /* "View.MemoryView":887 - * - * dst.strides[new_ndim] = stride * step - * dst.shape[new_ndim] = new_shape # <<<<<<<<<<<<<< - * dst.suboffsets[new_ndim] = suboffset - * - */ - (__pyx_v_dst->shape[__pyx_v_new_ndim]) = __pyx_v_new_shape; - - /* "View.MemoryView":888 - * dst.strides[new_ndim] = stride * step - * dst.shape[new_ndim] = new_shape - * dst.suboffsets[new_ndim] = suboffset # <<<<<<<<<<<<<< - * - * - */ - (__pyx_v_dst->suboffsets[__pyx_v_new_ndim]) = __pyx_v_suboffset; - } - __pyx_L3:; - - /* "View.MemoryView":891 - * - * - * if suboffset_dim[0] < 0: # <<<<<<<<<<<<<< - * dst.data += start * stride - * else: - */ - __pyx_t_2 = (((__pyx_v_suboffset_dim[0]) < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":892 - * - * if suboffset_dim[0] < 0: - * dst.data += start * stride # <<<<<<<<<<<<<< - * else: - * dst.suboffsets[suboffset_dim[0]] += start * stride - */ - __pyx_v_dst->data = (__pyx_v_dst->data + (__pyx_v_start * __pyx_v_stride)); - - /* "View.MemoryView":891 - * - * - * if suboffset_dim[0] < 0: # <<<<<<<<<<<<<< - * dst.data += start * stride - * else: - */ - goto __pyx_L23; - } - - /* "View.MemoryView":894 - * dst.data += start * stride - * else: - * dst.suboffsets[suboffset_dim[0]] += start * stride # <<<<<<<<<<<<<< - * - * if suboffset >= 0: - */ - /*else*/ { - __pyx_t_3 = (__pyx_v_suboffset_dim[0]); - (__pyx_v_dst->suboffsets[__pyx_t_3]) = ((__pyx_v_dst->suboffsets[__pyx_t_3]) + (__pyx_v_start * __pyx_v_stride)); - } - __pyx_L23:; - - /* "View.MemoryView":896 - * dst.suboffsets[suboffset_dim[0]] += start * stride - * - * if suboffset >= 0: # <<<<<<<<<<<<<< - * if not is_slice: - * if new_ndim == 0: - */ - __pyx_t_2 = ((__pyx_v_suboffset >= 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":897 - * - * if suboffset >= 0: - * if not is_slice: # <<<<<<<<<<<<<< - * if new_ndim == 0: - * dst.data = ( dst.data)[0] + suboffset - */ - __pyx_t_2 = ((!(__pyx_v_is_slice != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":898 - * if suboffset >= 0: - * if not is_slice: - * if new_ndim == 0: # <<<<<<<<<<<<<< - * dst.data = ( dst.data)[0] + suboffset - * else: - */ - __pyx_t_2 = ((__pyx_v_new_ndim == 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":899 - * if not is_slice: - * if new_ndim == 0: - * dst.data = ( dst.data)[0] + suboffset # <<<<<<<<<<<<<< - * else: - * _err_dim(IndexError, "All dimensions preceding dimension %d " - */ - __pyx_v_dst->data = ((((char **)__pyx_v_dst->data)[0]) + __pyx_v_suboffset); - - /* "View.MemoryView":898 - * if suboffset >= 0: - * if not is_slice: - * if new_ndim == 0: # <<<<<<<<<<<<<< - * dst.data = ( dst.data)[0] + suboffset - * else: - */ - goto __pyx_L26; - } - - /* "View.MemoryView":901 - * dst.data = ( dst.data)[0] + suboffset - * else: - * _err_dim(IndexError, "All dimensions preceding dimension %d " # <<<<<<<<<<<<<< - * "must be indexed and not sliced", dim) - * else: - */ - /*else*/ { - - /* "View.MemoryView":902 - * else: - * _err_dim(IndexError, "All dimensions preceding dimension %d " - * "must be indexed and not sliced", dim) # <<<<<<<<<<<<<< - * else: - * suboffset_dim[0] = new_ndim - */ - __pyx_t_3 = __pyx_memoryview_err_dim(__pyx_builtin_IndexError, ((char *)"All dimensions preceding dimension %d must be indexed and not sliced"), __pyx_v_dim); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(2, 901, __pyx_L1_error) - } - __pyx_L26:; - - /* "View.MemoryView":897 - * - * if suboffset >= 0: - * if not is_slice: # <<<<<<<<<<<<<< - * if new_ndim == 0: - * dst.data = ( dst.data)[0] + suboffset - */ - goto __pyx_L25; - } - - /* "View.MemoryView":904 - * "must be indexed and not sliced", dim) - * else: - * suboffset_dim[0] = new_ndim # <<<<<<<<<<<<<< - * - * return 0 - */ - /*else*/ { - (__pyx_v_suboffset_dim[0]) = __pyx_v_new_ndim; - } - __pyx_L25:; - - /* "View.MemoryView":896 - * dst.suboffsets[suboffset_dim[0]] += start * stride - * - * if suboffset >= 0: # <<<<<<<<<<<<<< - * if not is_slice: - * if new_ndim == 0: - */ - } - - /* "View.MemoryView":906 - * suboffset_dim[0] = new_ndim - * - * return 0 # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = 0; - goto __pyx_L0; - - /* "View.MemoryView":809 - * - * @cname('__pyx_memoryview_slice_memviewslice') - * cdef int slice_memviewslice( # <<<<<<<<<<<<<< - * __Pyx_memviewslice *dst, - * Py_ssize_t shape, Py_ssize_t stride, Py_ssize_t suboffset, - */ - - /* function exit code */ - __pyx_L1_error:; - { - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_AddTraceback("View.MemoryView.slice_memviewslice", __pyx_clineno, __pyx_lineno, __pyx_filename); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - } - __pyx_r = -1; - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":912 - * - * @cname('__pyx_pybuffer_index') - * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, # <<<<<<<<<<<<<< - * Py_ssize_t dim) except NULL: - * cdef Py_ssize_t shape, stride, suboffset = -1 - */ - -static char *__pyx_pybuffer_index(Py_buffer *__pyx_v_view, char *__pyx_v_bufp, Py_ssize_t __pyx_v_index, Py_ssize_t __pyx_v_dim) { - Py_ssize_t __pyx_v_shape; - Py_ssize_t __pyx_v_stride; - Py_ssize_t __pyx_v_suboffset; - Py_ssize_t __pyx_v_itemsize; - char *__pyx_v_resultp; - char *__pyx_r; - __Pyx_RefNannyDeclarations - Py_ssize_t __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("pybuffer_index", 0); - - /* "View.MemoryView":914 - * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, - * Py_ssize_t dim) except NULL: - * cdef Py_ssize_t shape, stride, suboffset = -1 # <<<<<<<<<<<<<< - * cdef Py_ssize_t itemsize = view.itemsize - * cdef char *resultp - */ - __pyx_v_suboffset = -1L; - - /* "View.MemoryView":915 - * Py_ssize_t dim) except NULL: - * cdef Py_ssize_t shape, stride, suboffset = -1 - * cdef Py_ssize_t itemsize = view.itemsize # <<<<<<<<<<<<<< - * cdef char *resultp - * - */ - __pyx_t_1 = __pyx_v_view->itemsize; - __pyx_v_itemsize = __pyx_t_1; - - /* "View.MemoryView":918 - * cdef char *resultp - * - * if view.ndim == 0: # <<<<<<<<<<<<<< - * shape = view.len / itemsize - * stride = itemsize - */ - __pyx_t_2 = ((__pyx_v_view->ndim == 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":919 - * - * if view.ndim == 0: - * shape = view.len / itemsize # <<<<<<<<<<<<<< - * stride = itemsize - * else: - */ - if (unlikely(__pyx_v_itemsize == 0)) { - PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero"); - __PYX_ERR(2, 919, __pyx_L1_error) - } - else if (sizeof(Py_ssize_t) == sizeof(long) && (!(((Py_ssize_t)-1) > 0)) && unlikely(__pyx_v_itemsize == (Py_ssize_t)-1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(__pyx_v_view->len))) { - PyErr_SetString(PyExc_OverflowError, "value too large to perform division"); - __PYX_ERR(2, 919, __pyx_L1_error) - } - __pyx_v_shape = __Pyx_div_Py_ssize_t(__pyx_v_view->len, __pyx_v_itemsize); - - /* "View.MemoryView":920 - * if view.ndim == 0: - * shape = view.len / itemsize - * stride = itemsize # <<<<<<<<<<<<<< - * else: - * shape = view.shape[dim] - */ - __pyx_v_stride = __pyx_v_itemsize; - - /* "View.MemoryView":918 - * cdef char *resultp - * - * if view.ndim == 0: # <<<<<<<<<<<<<< - * shape = view.len / itemsize - * stride = itemsize - */ - goto __pyx_L3; - } - - /* "View.MemoryView":922 - * stride = itemsize - * else: - * shape = view.shape[dim] # <<<<<<<<<<<<<< - * stride = view.strides[dim] - * if view.suboffsets != NULL: - */ - /*else*/ { - __pyx_v_shape = (__pyx_v_view->shape[__pyx_v_dim]); - - /* "View.MemoryView":923 - * else: - * shape = view.shape[dim] - * stride = view.strides[dim] # <<<<<<<<<<<<<< - * if view.suboffsets != NULL: - * suboffset = view.suboffsets[dim] - */ - __pyx_v_stride = (__pyx_v_view->strides[__pyx_v_dim]); - - /* "View.MemoryView":924 - * shape = view.shape[dim] - * stride = view.strides[dim] - * if view.suboffsets != NULL: # <<<<<<<<<<<<<< - * suboffset = view.suboffsets[dim] - * - */ - __pyx_t_2 = ((__pyx_v_view->suboffsets != NULL) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":925 - * stride = view.strides[dim] - * if view.suboffsets != NULL: - * suboffset = view.suboffsets[dim] # <<<<<<<<<<<<<< - * - * if index < 0: - */ - __pyx_v_suboffset = (__pyx_v_view->suboffsets[__pyx_v_dim]); - - /* "View.MemoryView":924 - * shape = view.shape[dim] - * stride = view.strides[dim] - * if view.suboffsets != NULL: # <<<<<<<<<<<<<< - * suboffset = view.suboffsets[dim] - * - */ - } - } - __pyx_L3:; - - /* "View.MemoryView":927 - * suboffset = view.suboffsets[dim] - * - * if index < 0: # <<<<<<<<<<<<<< - * index += view.shape[dim] - * if index < 0: - */ - __pyx_t_2 = ((__pyx_v_index < 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":928 - * - * if index < 0: - * index += view.shape[dim] # <<<<<<<<<<<<<< - * if index < 0: - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - */ - __pyx_v_index = (__pyx_v_index + (__pyx_v_view->shape[__pyx_v_dim])); - - /* "View.MemoryView":929 - * if index < 0: - * index += view.shape[dim] - * if index < 0: # <<<<<<<<<<<<<< - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - */ - __pyx_t_2 = ((__pyx_v_index < 0) != 0); - if (unlikely(__pyx_t_2)) { - - /* "View.MemoryView":930 - * index += view.shape[dim] - * if index < 0: - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) # <<<<<<<<<<<<<< - * - * if index >= shape: - */ - __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_dim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 930, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Out_of_bounds_on_buffer_access_a, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 930, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_IndexError, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 930, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 930, __pyx_L1_error) - - /* "View.MemoryView":929 - * if index < 0: - * index += view.shape[dim] - * if index < 0: # <<<<<<<<<<<<<< - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - */ - } - - /* "View.MemoryView":927 - * suboffset = view.suboffsets[dim] - * - * if index < 0: # <<<<<<<<<<<<<< - * index += view.shape[dim] - * if index < 0: - */ - } - - /* "View.MemoryView":932 - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - * if index >= shape: # <<<<<<<<<<<<<< - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - */ - __pyx_t_2 = ((__pyx_v_index >= __pyx_v_shape) != 0); - if (unlikely(__pyx_t_2)) { - - /* "View.MemoryView":933 - * - * if index >= shape: - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) # <<<<<<<<<<<<<< - * - * resultp = bufp + index * stride - */ - __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_dim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 933, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_Out_of_bounds_on_buffer_access_a, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 933, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_IndexError, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 933, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_3, 0, 0, 0); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __PYX_ERR(2, 933, __pyx_L1_error) - - /* "View.MemoryView":932 - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - * if index >= shape: # <<<<<<<<<<<<<< - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - */ - } - - /* "View.MemoryView":935 - * raise IndexError("Out of bounds on buffer access (axis %d)" % dim) - * - * resultp = bufp + index * stride # <<<<<<<<<<<<<< - * if suboffset >= 0: - * resultp = ( resultp)[0] + suboffset - */ - __pyx_v_resultp = (__pyx_v_bufp + (__pyx_v_index * __pyx_v_stride)); - - /* "View.MemoryView":936 - * - * resultp = bufp + index * stride - * if suboffset >= 0: # <<<<<<<<<<<<<< - * resultp = ( resultp)[0] + suboffset - * - */ - __pyx_t_2 = ((__pyx_v_suboffset >= 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":937 - * resultp = bufp + index * stride - * if suboffset >= 0: - * resultp = ( resultp)[0] + suboffset # <<<<<<<<<<<<<< - * - * return resultp - */ - __pyx_v_resultp = ((((char **)__pyx_v_resultp)[0]) + __pyx_v_suboffset); - - /* "View.MemoryView":936 - * - * resultp = bufp + index * stride - * if suboffset >= 0: # <<<<<<<<<<<<<< - * resultp = ( resultp)[0] + suboffset - * - */ - } - - /* "View.MemoryView":939 - * resultp = ( resultp)[0] + suboffset - * - * return resultp # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = __pyx_v_resultp; - goto __pyx_L0; - - /* "View.MemoryView":912 - * - * @cname('__pyx_pybuffer_index') - * cdef char *pybuffer_index(Py_buffer *view, char *bufp, Py_ssize_t index, # <<<<<<<<<<<<<< - * Py_ssize_t dim) except NULL: - * cdef Py_ssize_t shape, stride, suboffset = -1 - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("View.MemoryView.pybuffer_index", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":945 - * - * @cname('__pyx_memslice_transpose') - * cdef int transpose_memslice(__Pyx_memviewslice *memslice) nogil except 0: # <<<<<<<<<<<<<< - * cdef int ndim = memslice.memview.view.ndim - * - */ - -static int __pyx_memslice_transpose(__Pyx_memviewslice *__pyx_v_memslice) { - int __pyx_v_ndim; - Py_ssize_t *__pyx_v_shape; - Py_ssize_t *__pyx_v_strides; - int __pyx_v_i; - int __pyx_v_j; - int __pyx_r; - int __pyx_t_1; - Py_ssize_t *__pyx_t_2; - long __pyx_t_3; - long __pyx_t_4; - Py_ssize_t __pyx_t_5; - Py_ssize_t __pyx_t_6; - int __pyx_t_7; - int __pyx_t_8; - int __pyx_t_9; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - - /* "View.MemoryView":946 - * @cname('__pyx_memslice_transpose') - * cdef int transpose_memslice(__Pyx_memviewslice *memslice) nogil except 0: - * cdef int ndim = memslice.memview.view.ndim # <<<<<<<<<<<<<< - * - * cdef Py_ssize_t *shape = memslice.shape - */ - __pyx_t_1 = __pyx_v_memslice->memview->view.ndim; - __pyx_v_ndim = __pyx_t_1; - - /* "View.MemoryView":948 - * cdef int ndim = memslice.memview.view.ndim - * - * cdef Py_ssize_t *shape = memslice.shape # <<<<<<<<<<<<<< - * cdef Py_ssize_t *strides = memslice.strides - * - */ - __pyx_t_2 = __pyx_v_memslice->shape; - __pyx_v_shape = __pyx_t_2; - - /* "View.MemoryView":949 - * - * cdef Py_ssize_t *shape = memslice.shape - * cdef Py_ssize_t *strides = memslice.strides # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_2 = __pyx_v_memslice->strides; - __pyx_v_strides = __pyx_t_2; - - /* "View.MemoryView":953 - * - * cdef int i, j - * for i in range(ndim / 2): # <<<<<<<<<<<<<< - * j = ndim - 1 - i - * strides[i], strides[j] = strides[j], strides[i] - */ - __pyx_t_3 = __Pyx_div_long(__pyx_v_ndim, 2); - __pyx_t_4 = __pyx_t_3; - for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_4; __pyx_t_1+=1) { - __pyx_v_i = __pyx_t_1; - - /* "View.MemoryView":954 - * cdef int i, j - * for i in range(ndim / 2): - * j = ndim - 1 - i # <<<<<<<<<<<<<< - * strides[i], strides[j] = strides[j], strides[i] - * shape[i], shape[j] = shape[j], shape[i] - */ - __pyx_v_j = ((__pyx_v_ndim - 1) - __pyx_v_i); - - /* "View.MemoryView":955 - * for i in range(ndim / 2): - * j = ndim - 1 - i - * strides[i], strides[j] = strides[j], strides[i] # <<<<<<<<<<<<<< - * shape[i], shape[j] = shape[j], shape[i] - * - */ - __pyx_t_5 = (__pyx_v_strides[__pyx_v_j]); - __pyx_t_6 = (__pyx_v_strides[__pyx_v_i]); - (__pyx_v_strides[__pyx_v_i]) = __pyx_t_5; - (__pyx_v_strides[__pyx_v_j]) = __pyx_t_6; - - /* "View.MemoryView":956 - * j = ndim - 1 - i - * strides[i], strides[j] = strides[j], strides[i] - * shape[i], shape[j] = shape[j], shape[i] # <<<<<<<<<<<<<< - * - * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: - */ - __pyx_t_6 = (__pyx_v_shape[__pyx_v_j]); - __pyx_t_5 = (__pyx_v_shape[__pyx_v_i]); - (__pyx_v_shape[__pyx_v_i]) = __pyx_t_6; - (__pyx_v_shape[__pyx_v_j]) = __pyx_t_5; - - /* "View.MemoryView":958 - * shape[i], shape[j] = shape[j], shape[i] - * - * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: # <<<<<<<<<<<<<< - * _err(ValueError, "Cannot transpose memoryview with indirect dimensions") - * - */ - __pyx_t_8 = (((__pyx_v_memslice->suboffsets[__pyx_v_i]) >= 0) != 0); - if (!__pyx_t_8) { - } else { - __pyx_t_7 = __pyx_t_8; - goto __pyx_L6_bool_binop_done; - } - __pyx_t_8 = (((__pyx_v_memslice->suboffsets[__pyx_v_j]) >= 0) != 0); - __pyx_t_7 = __pyx_t_8; - __pyx_L6_bool_binop_done:; - if (__pyx_t_7) { - - /* "View.MemoryView":959 - * - * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: - * _err(ValueError, "Cannot transpose memoryview with indirect dimensions") # <<<<<<<<<<<<<< - * - * return 1 - */ - __pyx_t_9 = __pyx_memoryview_err(__pyx_builtin_ValueError, ((char *)"Cannot transpose memoryview with indirect dimensions")); if (unlikely(__pyx_t_9 == ((int)-1))) __PYX_ERR(2, 959, __pyx_L1_error) - - /* "View.MemoryView":958 - * shape[i], shape[j] = shape[j], shape[i] - * - * if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: # <<<<<<<<<<<<<< - * _err(ValueError, "Cannot transpose memoryview with indirect dimensions") - * - */ - } - } - - /* "View.MemoryView":961 - * _err(ValueError, "Cannot transpose memoryview with indirect dimensions") - * - * return 1 # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = 1; - goto __pyx_L0; - - /* "View.MemoryView":945 - * - * @cname('__pyx_memslice_transpose') - * cdef int transpose_memslice(__Pyx_memviewslice *memslice) nogil except 0: # <<<<<<<<<<<<<< - * cdef int ndim = memslice.memview.view.ndim - * - */ - - /* function exit code */ - __pyx_L1_error:; - { - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_AddTraceback("View.MemoryView.transpose_memslice", __pyx_clineno, __pyx_lineno, __pyx_filename); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - } - __pyx_r = 0; - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":978 - * cdef int (*to_dtype_func)(char *, object) except 0 - * - * def __dealloc__(self): # <<<<<<<<<<<<<< - * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) - * - */ - -/* Python wrapper */ -static void __pyx_memoryviewslice___dealloc__(PyObject *__pyx_v_self); /*proto*/ -static void __pyx_memoryviewslice___dealloc__(PyObject *__pyx_v_self) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0); - __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewslice___dealloc__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -static void __pyx_memoryviewslice___pyx_pf_15View_dot_MemoryView_16_memoryviewslice___dealloc__(struct __pyx_memoryviewslice_obj *__pyx_v_self) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__dealloc__", 0); - - /* "View.MemoryView":979 - * - * def __dealloc__(self): - * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) # <<<<<<<<<<<<<< - * - * cdef convert_item_to_object(self, char *itemp): - */ - __PYX_XDEC_MEMVIEW((&__pyx_v_self->from_slice), 1); - - /* "View.MemoryView":978 - * cdef int (*to_dtype_func)(char *, object) except 0 - * - * def __dealloc__(self): # <<<<<<<<<<<<<< - * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) - * - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -/* "View.MemoryView":981 - * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) - * - * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< - * if self.to_object_func != NULL: - * return self.to_object_func(itemp) - */ - -static PyObject *__pyx_memoryviewslice_convert_item_to_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("convert_item_to_object", 0); - - /* "View.MemoryView":982 - * - * cdef convert_item_to_object(self, char *itemp): - * if self.to_object_func != NULL: # <<<<<<<<<<<<<< - * return self.to_object_func(itemp) - * else: - */ - __pyx_t_1 = ((__pyx_v_self->to_object_func != NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":983 - * cdef convert_item_to_object(self, char *itemp): - * if self.to_object_func != NULL: - * return self.to_object_func(itemp) # <<<<<<<<<<<<<< - * else: - * return memoryview.convert_item_to_object(self, itemp) - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __pyx_v_self->to_object_func(__pyx_v_itemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 983, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - - /* "View.MemoryView":982 - * - * cdef convert_item_to_object(self, char *itemp): - * if self.to_object_func != NULL: # <<<<<<<<<<<<<< - * return self.to_object_func(itemp) - * else: - */ - } - - /* "View.MemoryView":985 - * return self.to_object_func(itemp) - * else: - * return memoryview.convert_item_to_object(self, itemp) # <<<<<<<<<<<<<< - * - * cdef assign_item_from_object(self, char *itemp, object value): - */ - /*else*/ { - __Pyx_XDECREF(__pyx_r); - __pyx_t_2 = __pyx_memoryview_convert_item_to_object(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v_itemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 985, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_r = __pyx_t_2; - __pyx_t_2 = 0; - goto __pyx_L0; - } - - /* "View.MemoryView":981 - * __PYX_XDEC_MEMVIEW(&self.from_slice, 1) - * - * cdef convert_item_to_object(self, char *itemp): # <<<<<<<<<<<<<< - * if self.to_object_func != NULL: - * return self.to_object_func(itemp) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_AddTraceback("View.MemoryView._memoryviewslice.convert_item_to_object", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":987 - * return memoryview.convert_item_to_object(self, itemp) - * - * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< - * if self.to_dtype_func != NULL: - * self.to_dtype_func(itemp, value) - */ - -static PyObject *__pyx_memoryviewslice_assign_item_from_object(struct __pyx_memoryviewslice_obj *__pyx_v_self, char *__pyx_v_itemp, PyObject *__pyx_v_value) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("assign_item_from_object", 0); - - /* "View.MemoryView":988 - * - * cdef assign_item_from_object(self, char *itemp, object value): - * if self.to_dtype_func != NULL: # <<<<<<<<<<<<<< - * self.to_dtype_func(itemp, value) - * else: - */ - __pyx_t_1 = ((__pyx_v_self->to_dtype_func != NULL) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":989 - * cdef assign_item_from_object(self, char *itemp, object value): - * if self.to_dtype_func != NULL: - * self.to_dtype_func(itemp, value) # <<<<<<<<<<<<<< - * else: - * memoryview.assign_item_from_object(self, itemp, value) - */ - __pyx_t_2 = __pyx_v_self->to_dtype_func(__pyx_v_itemp, __pyx_v_value); if (unlikely(__pyx_t_2 == ((int)0))) __PYX_ERR(2, 989, __pyx_L1_error) - - /* "View.MemoryView":988 - * - * cdef assign_item_from_object(self, char *itemp, object value): - * if self.to_dtype_func != NULL: # <<<<<<<<<<<<<< - * self.to_dtype_func(itemp, value) - * else: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":991 - * self.to_dtype_func(itemp, value) - * else: - * memoryview.assign_item_from_object(self, itemp, value) # <<<<<<<<<<<<<< - * - * @property - */ - /*else*/ { - __pyx_t_3 = __pyx_memoryview_assign_item_from_object(((struct __pyx_memoryview_obj *)__pyx_v_self), __pyx_v_itemp, __pyx_v_value); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 991, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } - __pyx_L3:; - - /* "View.MemoryView":987 - * return memoryview.convert_item_to_object(self, itemp) - * - * cdef assign_item_from_object(self, char *itemp, object value): # <<<<<<<<<<<<<< - * if self.to_dtype_func != NULL: - * self.to_dtype_func(itemp, value) - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView._memoryviewslice.assign_item_from_object", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":994 - * - * @property - * def base(self): # <<<<<<<<<<<<<< - * return self.from_object - * - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_16_memoryviewslice_4base_1__get__(PyObject *__pyx_v_self); /*proto*/ -static PyObject *__pyx_pw_15View_dot_MemoryView_16_memoryviewslice_4base_1__get__(PyObject *__pyx_v_self) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__ (wrapper)", 0); - __pyx_r = __pyx_pf_15View_dot_MemoryView_16_memoryviewslice_4base___get__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView_16_memoryviewslice_4base___get__(struct __pyx_memoryviewslice_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__get__", 0); - - /* "View.MemoryView":995 - * @property - * def base(self): - * return self.from_object # <<<<<<<<<<<<<< - * - * __pyx_getbuffer = capsule( &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)") - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_self->from_object); - __pyx_r = __pyx_v_self->from_object; - goto __pyx_L0; - - /* "View.MemoryView":994 - * - * @property - * def base(self): # <<<<<<<<<<<<<< - * return self.from_object - * - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_memoryviewslice_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyObject *__pyx_pw___pyx_memoryviewslice_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_memoryviewslice___reduce_cython__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_memoryviewslice___reduce_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__reduce_cython__", 0); - - /* "(tree fragment)":2 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__19, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 2, __pyx_L1_error) - - /* "(tree fragment)":1 - * def __reduce_cython__(self): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView._memoryviewslice.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":3 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - -/* Python wrapper */ -static PyObject *__pyx_pw___pyx_memoryviewslice_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/ -static PyObject *__pyx_pw___pyx_memoryviewslice_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0); - __pyx_r = __pyx_pf___pyx_memoryviewslice_2__setstate_cython__(((struct __pyx_memoryviewslice_obj *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state)); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf___pyx_memoryviewslice_2__setstate_cython__(CYTHON_UNUSED struct __pyx_memoryviewslice_obj *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__setstate_cython__", 0); - - /* "(tree fragment)":4 - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - */ - __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__20, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 4, __pyx_L1_error) - - /* "(tree fragment)":3 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): # <<<<<<<<<<<<<< - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView._memoryviewslice.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":1001 - * - * @cname('__pyx_memoryview_fromslice') - * cdef memoryview_fromslice(__Pyx_memviewslice memviewslice, # <<<<<<<<<<<<<< - * int ndim, - * object (*to_object_func)(char *), - */ - -static PyObject *__pyx_memoryview_fromslice(__Pyx_memviewslice __pyx_v_memviewslice, int __pyx_v_ndim, PyObject *(*__pyx_v_to_object_func)(char *), int (*__pyx_v_to_dtype_func)(char *, PyObject *), int __pyx_v_dtype_is_object) { - struct __pyx_memoryviewslice_obj *__pyx_v_result = 0; - Py_ssize_t __pyx_v_suboffset; - PyObject *__pyx_v_length = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - __Pyx_TypeInfo *__pyx_t_4; - Py_buffer __pyx_t_5; - Py_ssize_t *__pyx_t_6; - Py_ssize_t *__pyx_t_7; - Py_ssize_t *__pyx_t_8; - Py_ssize_t __pyx_t_9; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("memoryview_fromslice", 0); - - /* "View.MemoryView":1009 - * cdef _memoryviewslice result - * - * if memviewslice.memview == Py_None: # <<<<<<<<<<<<<< - * return None - * - */ - __pyx_t_1 = ((((PyObject *)__pyx_v_memviewslice.memview) == Py_None) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1010 - * - * if memviewslice.memview == Py_None: - * return None # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - - /* "View.MemoryView":1009 - * cdef _memoryviewslice result - * - * if memviewslice.memview == Py_None: # <<<<<<<<<<<<<< - * return None - * - */ - } - - /* "View.MemoryView":1015 - * - * - * result = _memoryviewslice(None, 0, dtype_is_object) # <<<<<<<<<<<<<< - * - * result.from_slice = memviewslice - */ - __pyx_t_2 = __Pyx_PyBool_FromLong(__pyx_v_dtype_is_object); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1015, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 1015, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(Py_None); - __Pyx_GIVEREF(Py_None); - PyTuple_SET_ITEM(__pyx_t_3, 0, Py_None); - __Pyx_INCREF(__pyx_int_0); - __Pyx_GIVEREF(__pyx_int_0); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_0); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2); - __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)__pyx_memoryviewslice_type), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1015, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_result = ((struct __pyx_memoryviewslice_obj *)__pyx_t_2); - __pyx_t_2 = 0; - - /* "View.MemoryView":1017 - * result = _memoryviewslice(None, 0, dtype_is_object) - * - * result.from_slice = memviewslice # <<<<<<<<<<<<<< - * __PYX_INC_MEMVIEW(&memviewslice, 1) - * - */ - __pyx_v_result->from_slice = __pyx_v_memviewslice; - - /* "View.MemoryView":1018 - * - * result.from_slice = memviewslice - * __PYX_INC_MEMVIEW(&memviewslice, 1) # <<<<<<<<<<<<<< - * - * result.from_object = ( memviewslice.memview).base - */ - __PYX_INC_MEMVIEW((&__pyx_v_memviewslice), 1); - - /* "View.MemoryView":1020 - * __PYX_INC_MEMVIEW(&memviewslice, 1) - * - * result.from_object = ( memviewslice.memview).base # <<<<<<<<<<<<<< - * result.typeinfo = memviewslice.memview.typeinfo - * - */ - __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_memviewslice.memview), __pyx_n_s_base); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1020, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_GIVEREF(__pyx_t_2); - __Pyx_GOTREF(__pyx_v_result->from_object); - __Pyx_DECREF(__pyx_v_result->from_object); - __pyx_v_result->from_object = __pyx_t_2; - __pyx_t_2 = 0; - - /* "View.MemoryView":1021 - * - * result.from_object = ( memviewslice.memview).base - * result.typeinfo = memviewslice.memview.typeinfo # <<<<<<<<<<<<<< - * - * result.view = memviewslice.memview.view - */ - __pyx_t_4 = __pyx_v_memviewslice.memview->typeinfo; - __pyx_v_result->__pyx_base.typeinfo = __pyx_t_4; - - /* "View.MemoryView":1023 - * result.typeinfo = memviewslice.memview.typeinfo - * - * result.view = memviewslice.memview.view # <<<<<<<<<<<<<< - * result.view.buf = memviewslice.data - * result.view.ndim = ndim - */ - __pyx_t_5 = __pyx_v_memviewslice.memview->view; - __pyx_v_result->__pyx_base.view = __pyx_t_5; - - /* "View.MemoryView":1024 - * - * result.view = memviewslice.memview.view - * result.view.buf = memviewslice.data # <<<<<<<<<<<<<< - * result.view.ndim = ndim - * (<__pyx_buffer *> &result.view).obj = Py_None - */ - __pyx_v_result->__pyx_base.view.buf = ((void *)__pyx_v_memviewslice.data); - - /* "View.MemoryView":1025 - * result.view = memviewslice.memview.view - * result.view.buf = memviewslice.data - * result.view.ndim = ndim # <<<<<<<<<<<<<< - * (<__pyx_buffer *> &result.view).obj = Py_None - * Py_INCREF(Py_None) - */ - __pyx_v_result->__pyx_base.view.ndim = __pyx_v_ndim; - - /* "View.MemoryView":1026 - * result.view.buf = memviewslice.data - * result.view.ndim = ndim - * (<__pyx_buffer *> &result.view).obj = Py_None # <<<<<<<<<<<<<< - * Py_INCREF(Py_None) - * - */ - ((Py_buffer *)(&__pyx_v_result->__pyx_base.view))->obj = Py_None; - - /* "View.MemoryView":1027 - * result.view.ndim = ndim - * (<__pyx_buffer *> &result.view).obj = Py_None - * Py_INCREF(Py_None) # <<<<<<<<<<<<<< - * - * if (memviewslice.memview).flags & PyBUF_WRITABLE: - */ - Py_INCREF(Py_None); - - /* "View.MemoryView":1029 - * Py_INCREF(Py_None) - * - * if (memviewslice.memview).flags & PyBUF_WRITABLE: # <<<<<<<<<<<<<< - * result.flags = PyBUF_RECORDS - * else: - */ - __pyx_t_1 = ((((struct __pyx_memoryview_obj *)__pyx_v_memviewslice.memview)->flags & PyBUF_WRITABLE) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1030 - * - * if (memviewslice.memview).flags & PyBUF_WRITABLE: - * result.flags = PyBUF_RECORDS # <<<<<<<<<<<<<< - * else: - * result.flags = PyBUF_RECORDS_RO - */ - __pyx_v_result->__pyx_base.flags = PyBUF_RECORDS; - - /* "View.MemoryView":1029 - * Py_INCREF(Py_None) - * - * if (memviewslice.memview).flags & PyBUF_WRITABLE: # <<<<<<<<<<<<<< - * result.flags = PyBUF_RECORDS - * else: - */ - goto __pyx_L4; - } - - /* "View.MemoryView":1032 - * result.flags = PyBUF_RECORDS - * else: - * result.flags = PyBUF_RECORDS_RO # <<<<<<<<<<<<<< - * - * result.view.shape = result.from_slice.shape - */ - /*else*/ { - __pyx_v_result->__pyx_base.flags = PyBUF_RECORDS_RO; - } - __pyx_L4:; - - /* "View.MemoryView":1034 - * result.flags = PyBUF_RECORDS_RO - * - * result.view.shape = result.from_slice.shape # <<<<<<<<<<<<<< - * result.view.strides = result.from_slice.strides - * - */ - __pyx_v_result->__pyx_base.view.shape = ((Py_ssize_t *)__pyx_v_result->from_slice.shape); - - /* "View.MemoryView":1035 - * - * result.view.shape = result.from_slice.shape - * result.view.strides = result.from_slice.strides # <<<<<<<<<<<<<< - * - * - */ - __pyx_v_result->__pyx_base.view.strides = ((Py_ssize_t *)__pyx_v_result->from_slice.strides); - - /* "View.MemoryView":1038 - * - * - * result.view.suboffsets = NULL # <<<<<<<<<<<<<< - * for suboffset in result.from_slice.suboffsets[:ndim]: - * if suboffset >= 0: - */ - __pyx_v_result->__pyx_base.view.suboffsets = NULL; - - /* "View.MemoryView":1039 - * - * result.view.suboffsets = NULL - * for suboffset in result.from_slice.suboffsets[:ndim]: # <<<<<<<<<<<<<< - * if suboffset >= 0: - * result.view.suboffsets = result.from_slice.suboffsets - */ - __pyx_t_7 = (__pyx_v_result->from_slice.suboffsets + __pyx_v_ndim); - for (__pyx_t_8 = __pyx_v_result->from_slice.suboffsets; __pyx_t_8 < __pyx_t_7; __pyx_t_8++) { - __pyx_t_6 = __pyx_t_8; - __pyx_v_suboffset = (__pyx_t_6[0]); - - /* "View.MemoryView":1040 - * result.view.suboffsets = NULL - * for suboffset in result.from_slice.suboffsets[:ndim]: - * if suboffset >= 0: # <<<<<<<<<<<<<< - * result.view.suboffsets = result.from_slice.suboffsets - * break - */ - __pyx_t_1 = ((__pyx_v_suboffset >= 0) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1041 - * for suboffset in result.from_slice.suboffsets[:ndim]: - * if suboffset >= 0: - * result.view.suboffsets = result.from_slice.suboffsets # <<<<<<<<<<<<<< - * break - * - */ - __pyx_v_result->__pyx_base.view.suboffsets = ((Py_ssize_t *)__pyx_v_result->from_slice.suboffsets); - - /* "View.MemoryView":1042 - * if suboffset >= 0: - * result.view.suboffsets = result.from_slice.suboffsets - * break # <<<<<<<<<<<<<< - * - * result.view.len = result.view.itemsize - */ - goto __pyx_L6_break; - - /* "View.MemoryView":1040 - * result.view.suboffsets = NULL - * for suboffset in result.from_slice.suboffsets[:ndim]: - * if suboffset >= 0: # <<<<<<<<<<<<<< - * result.view.suboffsets = result.from_slice.suboffsets - * break - */ - } - } - __pyx_L6_break:; - - /* "View.MemoryView":1044 - * break - * - * result.view.len = result.view.itemsize # <<<<<<<<<<<<<< - * for length in result.view.shape[:ndim]: - * result.view.len *= length - */ - __pyx_t_9 = __pyx_v_result->__pyx_base.view.itemsize; - __pyx_v_result->__pyx_base.view.len = __pyx_t_9; - - /* "View.MemoryView":1045 - * - * result.view.len = result.view.itemsize - * for length in result.view.shape[:ndim]: # <<<<<<<<<<<<<< - * result.view.len *= length - * - */ - __pyx_t_7 = (__pyx_v_result->__pyx_base.view.shape + __pyx_v_ndim); - for (__pyx_t_8 = __pyx_v_result->__pyx_base.view.shape; __pyx_t_8 < __pyx_t_7; __pyx_t_8++) { - __pyx_t_6 = __pyx_t_8; - __pyx_t_2 = PyInt_FromSsize_t((__pyx_t_6[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1045, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_XDECREF_SET(__pyx_v_length, __pyx_t_2); - __pyx_t_2 = 0; - - /* "View.MemoryView":1046 - * result.view.len = result.view.itemsize - * for length in result.view.shape[:ndim]: - * result.view.len *= length # <<<<<<<<<<<<<< - * - * result.to_object_func = to_object_func - */ - __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_result->__pyx_base.view.len); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1046, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyNumber_InPlaceMultiply(__pyx_t_2, __pyx_v_length); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 1046, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_9 = __Pyx_PyIndex_AsSsize_t(__pyx_t_3); if (unlikely((__pyx_t_9 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(2, 1046, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_result->__pyx_base.view.len = __pyx_t_9; - } - - /* "View.MemoryView":1048 - * result.view.len *= length - * - * result.to_object_func = to_object_func # <<<<<<<<<<<<<< - * result.to_dtype_func = to_dtype_func - * - */ - __pyx_v_result->to_object_func = __pyx_v_to_object_func; - - /* "View.MemoryView":1049 - * - * result.to_object_func = to_object_func - * result.to_dtype_func = to_dtype_func # <<<<<<<<<<<<<< - * - * return result - */ - __pyx_v_result->to_dtype_func = __pyx_v_to_dtype_func; - - /* "View.MemoryView":1051 - * result.to_dtype_func = to_dtype_func - * - * return result # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_get_slice_from_memoryview') - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(((PyObject *)__pyx_v_result)); - __pyx_r = ((PyObject *)__pyx_v_result); - goto __pyx_L0; - - /* "View.MemoryView":1001 - * - * @cname('__pyx_memoryview_fromslice') - * cdef memoryview_fromslice(__Pyx_memviewslice memviewslice, # <<<<<<<<<<<<<< - * int ndim, - * object (*to_object_func)(char *), - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.memoryview_fromslice", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF((PyObject *)__pyx_v_result); - __Pyx_XDECREF(__pyx_v_length); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":1054 - * - * @cname('__pyx_memoryview_get_slice_from_memoryview') - * cdef __Pyx_memviewslice *get_slice_from_memview(memoryview memview, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *mslice) except NULL: - * cdef _memoryviewslice obj - */ - -static __Pyx_memviewslice *__pyx_memoryview_get_slice_from_memoryview(struct __pyx_memoryview_obj *__pyx_v_memview, __Pyx_memviewslice *__pyx_v_mslice) { - struct __pyx_memoryviewslice_obj *__pyx_v_obj = 0; - __Pyx_memviewslice *__pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("get_slice_from_memview", 0); - - /* "View.MemoryView":1057 - * __Pyx_memviewslice *mslice) except NULL: - * cdef _memoryviewslice obj - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * obj = memview - * return &obj.from_slice - */ - __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1058 - * cdef _memoryviewslice obj - * if isinstance(memview, _memoryviewslice): - * obj = memview # <<<<<<<<<<<<<< - * return &obj.from_slice - * else: - */ - if (!(likely(((((PyObject *)__pyx_v_memview)) == Py_None) || likely(__Pyx_TypeTest(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type))))) __PYX_ERR(2, 1058, __pyx_L1_error) - __pyx_t_3 = ((PyObject *)__pyx_v_memview); - __Pyx_INCREF(__pyx_t_3); - __pyx_v_obj = ((struct __pyx_memoryviewslice_obj *)__pyx_t_3); - __pyx_t_3 = 0; - - /* "View.MemoryView":1059 - * if isinstance(memview, _memoryviewslice): - * obj = memview - * return &obj.from_slice # <<<<<<<<<<<<<< - * else: - * slice_copy(memview, mslice) - */ - __pyx_r = (&__pyx_v_obj->from_slice); - goto __pyx_L0; - - /* "View.MemoryView":1057 - * __Pyx_memviewslice *mslice) except NULL: - * cdef _memoryviewslice obj - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * obj = memview - * return &obj.from_slice - */ - } - - /* "View.MemoryView":1061 - * return &obj.from_slice - * else: - * slice_copy(memview, mslice) # <<<<<<<<<<<<<< - * return mslice - * - */ - /*else*/ { - __pyx_memoryview_slice_copy(__pyx_v_memview, __pyx_v_mslice); - - /* "View.MemoryView":1062 - * else: - * slice_copy(memview, mslice) - * return mslice # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_slice_copy') - */ - __pyx_r = __pyx_v_mslice; - goto __pyx_L0; - } - - /* "View.MemoryView":1054 - * - * @cname('__pyx_memoryview_get_slice_from_memoryview') - * cdef __Pyx_memviewslice *get_slice_from_memview(memoryview memview, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *mslice) except NULL: - * cdef _memoryviewslice obj - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_AddTraceback("View.MemoryView.get_slice_from_memview", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF((PyObject *)__pyx_v_obj); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":1065 - * - * @cname('__pyx_memoryview_slice_copy') - * cdef void slice_copy(memoryview memview, __Pyx_memviewslice *dst): # <<<<<<<<<<<<<< - * cdef int dim - * cdef (Py_ssize_t*) shape, strides, suboffsets - */ - -static void __pyx_memoryview_slice_copy(struct __pyx_memoryview_obj *__pyx_v_memview, __Pyx_memviewslice *__pyx_v_dst) { - int __pyx_v_dim; - Py_ssize_t *__pyx_v_shape; - Py_ssize_t *__pyx_v_strides; - Py_ssize_t *__pyx_v_suboffsets; - __Pyx_RefNannyDeclarations - Py_ssize_t *__pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - Py_ssize_t __pyx_t_5; - __Pyx_RefNannySetupContext("slice_copy", 0); - - /* "View.MemoryView":1069 - * cdef (Py_ssize_t*) shape, strides, suboffsets - * - * shape = memview.view.shape # <<<<<<<<<<<<<< - * strides = memview.view.strides - * suboffsets = memview.view.suboffsets - */ - __pyx_t_1 = __pyx_v_memview->view.shape; - __pyx_v_shape = __pyx_t_1; - - /* "View.MemoryView":1070 - * - * shape = memview.view.shape - * strides = memview.view.strides # <<<<<<<<<<<<<< - * suboffsets = memview.view.suboffsets - * - */ - __pyx_t_1 = __pyx_v_memview->view.strides; - __pyx_v_strides = __pyx_t_1; - - /* "View.MemoryView":1071 - * shape = memview.view.shape - * strides = memview.view.strides - * suboffsets = memview.view.suboffsets # <<<<<<<<<<<<<< - * - * dst.memview = <__pyx_memoryview *> memview - */ - __pyx_t_1 = __pyx_v_memview->view.suboffsets; - __pyx_v_suboffsets = __pyx_t_1; - - /* "View.MemoryView":1073 - * suboffsets = memview.view.suboffsets - * - * dst.memview = <__pyx_memoryview *> memview # <<<<<<<<<<<<<< - * dst.data = memview.view.buf - * - */ - __pyx_v_dst->memview = ((struct __pyx_memoryview_obj *)__pyx_v_memview); - - /* "View.MemoryView":1074 - * - * dst.memview = <__pyx_memoryview *> memview - * dst.data = memview.view.buf # <<<<<<<<<<<<<< - * - * for dim in range(memview.view.ndim): - */ - __pyx_v_dst->data = ((char *)__pyx_v_memview->view.buf); - - /* "View.MemoryView":1076 - * dst.data = memview.view.buf - * - * for dim in range(memview.view.ndim): # <<<<<<<<<<<<<< - * dst.shape[dim] = shape[dim] - * dst.strides[dim] = strides[dim] - */ - __pyx_t_2 = __pyx_v_memview->view.ndim; - __pyx_t_3 = __pyx_t_2; - for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_dim = __pyx_t_4; - - /* "View.MemoryView":1077 - * - * for dim in range(memview.view.ndim): - * dst.shape[dim] = shape[dim] # <<<<<<<<<<<<<< - * dst.strides[dim] = strides[dim] - * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 - */ - (__pyx_v_dst->shape[__pyx_v_dim]) = (__pyx_v_shape[__pyx_v_dim]); - - /* "View.MemoryView":1078 - * for dim in range(memview.view.ndim): - * dst.shape[dim] = shape[dim] - * dst.strides[dim] = strides[dim] # <<<<<<<<<<<<<< - * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 - * - */ - (__pyx_v_dst->strides[__pyx_v_dim]) = (__pyx_v_strides[__pyx_v_dim]); - - /* "View.MemoryView":1079 - * dst.shape[dim] = shape[dim] - * dst.strides[dim] = strides[dim] - * dst.suboffsets[dim] = suboffsets[dim] if suboffsets else -1 # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_copy_object') - */ - if ((__pyx_v_suboffsets != 0)) { - __pyx_t_5 = (__pyx_v_suboffsets[__pyx_v_dim]); - } else { - __pyx_t_5 = -1L; - } - (__pyx_v_dst->suboffsets[__pyx_v_dim]) = __pyx_t_5; - } - - /* "View.MemoryView":1065 - * - * @cname('__pyx_memoryview_slice_copy') - * cdef void slice_copy(memoryview memview, __Pyx_memviewslice *dst): # <<<<<<<<<<<<<< - * cdef int dim - * cdef (Py_ssize_t*) shape, strides, suboffsets - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -/* "View.MemoryView":1082 - * - * @cname('__pyx_memoryview_copy_object') - * cdef memoryview_copy(memoryview memview): # <<<<<<<<<<<<<< - * "Create a new memoryview object" - * cdef __Pyx_memviewslice memviewslice - */ - -static PyObject *__pyx_memoryview_copy_object(struct __pyx_memoryview_obj *__pyx_v_memview) { - __Pyx_memviewslice __pyx_v_memviewslice; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("memoryview_copy", 0); - - /* "View.MemoryView":1085 - * "Create a new memoryview object" - * cdef __Pyx_memviewslice memviewslice - * slice_copy(memview, &memviewslice) # <<<<<<<<<<<<<< - * return memoryview_copy_from_slice(memview, &memviewslice) - * - */ - __pyx_memoryview_slice_copy(__pyx_v_memview, (&__pyx_v_memviewslice)); - - /* "View.MemoryView":1086 - * cdef __Pyx_memviewslice memviewslice - * slice_copy(memview, &memviewslice) - * return memoryview_copy_from_slice(memview, &memviewslice) # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_copy_object_from_slice') - */ - __Pyx_XDECREF(__pyx_r); - __pyx_t_1 = __pyx_memoryview_copy_object_from_slice(__pyx_v_memview, (&__pyx_v_memviewslice)); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1086, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_r = __pyx_t_1; - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "View.MemoryView":1082 - * - * @cname('__pyx_memoryview_copy_object') - * cdef memoryview_copy(memoryview memview): # <<<<<<<<<<<<<< - * "Create a new memoryview object" - * cdef __Pyx_memviewslice memviewslice - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("View.MemoryView.memoryview_copy", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":1089 - * - * @cname('__pyx_memoryview_copy_object_from_slice') - * cdef memoryview_copy_from_slice(memoryview memview, __Pyx_memviewslice *memviewslice): # <<<<<<<<<<<<<< - * """ - * Create a new memoryview object from a given memoryview object and slice. - */ - -static PyObject *__pyx_memoryview_copy_object_from_slice(struct __pyx_memoryview_obj *__pyx_v_memview, __Pyx_memviewslice *__pyx_v_memviewslice) { - PyObject *(*__pyx_v_to_object_func)(char *); - int (*__pyx_v_to_dtype_func)(char *, PyObject *); - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *(*__pyx_t_3)(char *); - int (*__pyx_t_4)(char *, PyObject *); - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("memoryview_copy_from_slice", 0); - - /* "View.MemoryView":1096 - * cdef int (*to_dtype_func)(char *, object) except 0 - * - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * to_object_func = (<_memoryviewslice> memview).to_object_func - * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func - */ - __pyx_t_1 = __Pyx_TypeCheck(((PyObject *)__pyx_v_memview), __pyx_memoryviewslice_type); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1097 - * - * if isinstance(memview, _memoryviewslice): - * to_object_func = (<_memoryviewslice> memview).to_object_func # <<<<<<<<<<<<<< - * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func - * else: - */ - __pyx_t_3 = ((struct __pyx_memoryviewslice_obj *)__pyx_v_memview)->to_object_func; - __pyx_v_to_object_func = __pyx_t_3; - - /* "View.MemoryView":1098 - * if isinstance(memview, _memoryviewslice): - * to_object_func = (<_memoryviewslice> memview).to_object_func - * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func # <<<<<<<<<<<<<< - * else: - * to_object_func = NULL - */ - __pyx_t_4 = ((struct __pyx_memoryviewslice_obj *)__pyx_v_memview)->to_dtype_func; - __pyx_v_to_dtype_func = __pyx_t_4; - - /* "View.MemoryView":1096 - * cdef int (*to_dtype_func)(char *, object) except 0 - * - * if isinstance(memview, _memoryviewslice): # <<<<<<<<<<<<<< - * to_object_func = (<_memoryviewslice> memview).to_object_func - * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func - */ - goto __pyx_L3; - } - - /* "View.MemoryView":1100 - * to_dtype_func = (<_memoryviewslice> memview).to_dtype_func - * else: - * to_object_func = NULL # <<<<<<<<<<<<<< - * to_dtype_func = NULL - * - */ - /*else*/ { - __pyx_v_to_object_func = NULL; - - /* "View.MemoryView":1101 - * else: - * to_object_func = NULL - * to_dtype_func = NULL # <<<<<<<<<<<<<< - * - * return memoryview_fromslice(memviewslice[0], memview.view.ndim, - */ - __pyx_v_to_dtype_func = NULL; - } - __pyx_L3:; - - /* "View.MemoryView":1103 - * to_dtype_func = NULL - * - * return memoryview_fromslice(memviewslice[0], memview.view.ndim, # <<<<<<<<<<<<<< - * to_object_func, to_dtype_func, - * memview.dtype_is_object) - */ - __Pyx_XDECREF(__pyx_r); - - /* "View.MemoryView":1105 - * return memoryview_fromslice(memviewslice[0], memview.view.ndim, - * to_object_func, to_dtype_func, - * memview.dtype_is_object) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_5 = __pyx_memoryview_fromslice((__pyx_v_memviewslice[0]), __pyx_v_memview->view.ndim, __pyx_v_to_object_func, __pyx_v_to_dtype_func, __pyx_v_memview->dtype_is_object); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 1103, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_r = __pyx_t_5; - __pyx_t_5 = 0; - goto __pyx_L0; - - /* "View.MemoryView":1089 - * - * @cname('__pyx_memoryview_copy_object_from_slice') - * cdef memoryview_copy_from_slice(memoryview memview, __Pyx_memviewslice *memviewslice): # <<<<<<<<<<<<<< - * """ - * Create a new memoryview object from a given memoryview object and slice. - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView.memoryview_copy_from_slice", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "View.MemoryView":1111 - * - * - * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: # <<<<<<<<<<<<<< - * if arg < 0: - * return -arg - */ - -static Py_ssize_t abs_py_ssize_t(Py_ssize_t __pyx_v_arg) { - Py_ssize_t __pyx_r; - int __pyx_t_1; - - /* "View.MemoryView":1112 - * - * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: - * if arg < 0: # <<<<<<<<<<<<<< - * return -arg - * else: - */ - __pyx_t_1 = ((__pyx_v_arg < 0) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1113 - * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: - * if arg < 0: - * return -arg # <<<<<<<<<<<<<< - * else: - * return arg - */ - __pyx_r = (-__pyx_v_arg); - goto __pyx_L0; - - /* "View.MemoryView":1112 - * - * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: - * if arg < 0: # <<<<<<<<<<<<<< - * return -arg - * else: - */ - } - - /* "View.MemoryView":1115 - * return -arg - * else: - * return arg # <<<<<<<<<<<<<< - * - * @cname('__pyx_get_best_slice_order') - */ - /*else*/ { - __pyx_r = __pyx_v_arg; - goto __pyx_L0; - } - - /* "View.MemoryView":1111 - * - * - * cdef Py_ssize_t abs_py_ssize_t(Py_ssize_t arg) nogil: # <<<<<<<<<<<<<< - * if arg < 0: - * return -arg - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":1118 - * - * @cname('__pyx_get_best_slice_order') - * cdef char get_best_order(__Pyx_memviewslice *mslice, int ndim) nogil: # <<<<<<<<<<<<<< - * """ - * Figure out the best memory access order for a given slice. - */ - -static char __pyx_get_best_slice_order(__Pyx_memviewslice *__pyx_v_mslice, int __pyx_v_ndim) { - int __pyx_v_i; - Py_ssize_t __pyx_v_c_stride; - Py_ssize_t __pyx_v_f_stride; - char __pyx_r; - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - - /* "View.MemoryView":1123 - * """ - * cdef int i - * cdef Py_ssize_t c_stride = 0 # <<<<<<<<<<<<<< - * cdef Py_ssize_t f_stride = 0 - * - */ - __pyx_v_c_stride = 0; - - /* "View.MemoryView":1124 - * cdef int i - * cdef Py_ssize_t c_stride = 0 - * cdef Py_ssize_t f_stride = 0 # <<<<<<<<<<<<<< - * - * for i in range(ndim - 1, -1, -1): - */ - __pyx_v_f_stride = 0; - - /* "View.MemoryView":1126 - * cdef Py_ssize_t f_stride = 0 - * - * for i in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< - * if mslice.shape[i] > 1: - * c_stride = mslice.strides[i] - */ - for (__pyx_t_1 = (__pyx_v_ndim - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { - __pyx_v_i = __pyx_t_1; - - /* "View.MemoryView":1127 - * - * for i in range(ndim - 1, -1, -1): - * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< - * c_stride = mslice.strides[i] - * break - */ - __pyx_t_2 = (((__pyx_v_mslice->shape[__pyx_v_i]) > 1) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1128 - * for i in range(ndim - 1, -1, -1): - * if mslice.shape[i] > 1: - * c_stride = mslice.strides[i] # <<<<<<<<<<<<<< - * break - * - */ - __pyx_v_c_stride = (__pyx_v_mslice->strides[__pyx_v_i]); - - /* "View.MemoryView":1129 - * if mslice.shape[i] > 1: - * c_stride = mslice.strides[i] - * break # <<<<<<<<<<<<<< - * - * for i in range(ndim): - */ - goto __pyx_L4_break; - - /* "View.MemoryView":1127 - * - * for i in range(ndim - 1, -1, -1): - * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< - * c_stride = mslice.strides[i] - * break - */ - } - } - __pyx_L4_break:; - - /* "View.MemoryView":1131 - * break - * - * for i in range(ndim): # <<<<<<<<<<<<<< - * if mslice.shape[i] > 1: - * f_stride = mslice.strides[i] - */ - __pyx_t_1 = __pyx_v_ndim; - __pyx_t_3 = __pyx_t_1; - for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_i = __pyx_t_4; - - /* "View.MemoryView":1132 - * - * for i in range(ndim): - * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< - * f_stride = mslice.strides[i] - * break - */ - __pyx_t_2 = (((__pyx_v_mslice->shape[__pyx_v_i]) > 1) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1133 - * for i in range(ndim): - * if mslice.shape[i] > 1: - * f_stride = mslice.strides[i] # <<<<<<<<<<<<<< - * break - * - */ - __pyx_v_f_stride = (__pyx_v_mslice->strides[__pyx_v_i]); - - /* "View.MemoryView":1134 - * if mslice.shape[i] > 1: - * f_stride = mslice.strides[i] - * break # <<<<<<<<<<<<<< - * - * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): - */ - goto __pyx_L7_break; - - /* "View.MemoryView":1132 - * - * for i in range(ndim): - * if mslice.shape[i] > 1: # <<<<<<<<<<<<<< - * f_stride = mslice.strides[i] - * break - */ - } - } - __pyx_L7_break:; - - /* "View.MemoryView":1136 - * break - * - * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): # <<<<<<<<<<<<<< - * return 'C' - * else: - */ - __pyx_t_2 = ((abs_py_ssize_t(__pyx_v_c_stride) <= abs_py_ssize_t(__pyx_v_f_stride)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1137 - * - * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): - * return 'C' # <<<<<<<<<<<<<< - * else: - * return 'F' - */ - __pyx_r = 'C'; - goto __pyx_L0; - - /* "View.MemoryView":1136 - * break - * - * if abs_py_ssize_t(c_stride) <= abs_py_ssize_t(f_stride): # <<<<<<<<<<<<<< - * return 'C' - * else: - */ - } - - /* "View.MemoryView":1139 - * return 'C' - * else: - * return 'F' # <<<<<<<<<<<<<< - * - * @cython.cdivision(True) - */ - /*else*/ { - __pyx_r = 'F'; - goto __pyx_L0; - } - - /* "View.MemoryView":1118 - * - * @cname('__pyx_get_best_slice_order') - * cdef char get_best_order(__Pyx_memviewslice *mslice, int ndim) nogil: # <<<<<<<<<<<<<< - * """ - * Figure out the best memory access order for a given slice. - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":1142 - * - * @cython.cdivision(True) - * cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, # <<<<<<<<<<<<<< - * char *dst_data, Py_ssize_t *dst_strides, - * Py_ssize_t *src_shape, Py_ssize_t *dst_shape, - */ - -static void _copy_strided_to_strided(char *__pyx_v_src_data, Py_ssize_t *__pyx_v_src_strides, char *__pyx_v_dst_data, Py_ssize_t *__pyx_v_dst_strides, Py_ssize_t *__pyx_v_src_shape, Py_ssize_t *__pyx_v_dst_shape, int __pyx_v_ndim, size_t __pyx_v_itemsize) { - CYTHON_UNUSED Py_ssize_t __pyx_v_i; - CYTHON_UNUSED Py_ssize_t __pyx_v_src_extent; - Py_ssize_t __pyx_v_dst_extent; - Py_ssize_t __pyx_v_src_stride; - Py_ssize_t __pyx_v_dst_stride; - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - Py_ssize_t __pyx_t_4; - Py_ssize_t __pyx_t_5; - Py_ssize_t __pyx_t_6; - - /* "View.MemoryView":1149 - * - * cdef Py_ssize_t i - * cdef Py_ssize_t src_extent = src_shape[0] # <<<<<<<<<<<<<< - * cdef Py_ssize_t dst_extent = dst_shape[0] - * cdef Py_ssize_t src_stride = src_strides[0] - */ - __pyx_v_src_extent = (__pyx_v_src_shape[0]); - - /* "View.MemoryView":1150 - * cdef Py_ssize_t i - * cdef Py_ssize_t src_extent = src_shape[0] - * cdef Py_ssize_t dst_extent = dst_shape[0] # <<<<<<<<<<<<<< - * cdef Py_ssize_t src_stride = src_strides[0] - * cdef Py_ssize_t dst_stride = dst_strides[0] - */ - __pyx_v_dst_extent = (__pyx_v_dst_shape[0]); - - /* "View.MemoryView":1151 - * cdef Py_ssize_t src_extent = src_shape[0] - * cdef Py_ssize_t dst_extent = dst_shape[0] - * cdef Py_ssize_t src_stride = src_strides[0] # <<<<<<<<<<<<<< - * cdef Py_ssize_t dst_stride = dst_strides[0] - * - */ - __pyx_v_src_stride = (__pyx_v_src_strides[0]); - - /* "View.MemoryView":1152 - * cdef Py_ssize_t dst_extent = dst_shape[0] - * cdef Py_ssize_t src_stride = src_strides[0] - * cdef Py_ssize_t dst_stride = dst_strides[0] # <<<<<<<<<<<<<< - * - * if ndim == 1: - */ - __pyx_v_dst_stride = (__pyx_v_dst_strides[0]); - - /* "View.MemoryView":1154 - * cdef Py_ssize_t dst_stride = dst_strides[0] - * - * if ndim == 1: # <<<<<<<<<<<<<< - * if (src_stride > 0 and dst_stride > 0 and - * src_stride == itemsize == dst_stride): - */ - __pyx_t_1 = ((__pyx_v_ndim == 1) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1155 - * - * if ndim == 1: - * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< - * src_stride == itemsize == dst_stride): - * memcpy(dst_data, src_data, itemsize * dst_extent) - */ - __pyx_t_2 = ((__pyx_v_src_stride > 0) != 0); - if (__pyx_t_2) { - } else { - __pyx_t_1 = __pyx_t_2; - goto __pyx_L5_bool_binop_done; - } - __pyx_t_2 = ((__pyx_v_dst_stride > 0) != 0); - if (__pyx_t_2) { - } else { - __pyx_t_1 = __pyx_t_2; - goto __pyx_L5_bool_binop_done; - } - - /* "View.MemoryView":1156 - * if ndim == 1: - * if (src_stride > 0 and dst_stride > 0 and - * src_stride == itemsize == dst_stride): # <<<<<<<<<<<<<< - * memcpy(dst_data, src_data, itemsize * dst_extent) - * else: - */ - __pyx_t_2 = (((size_t)__pyx_v_src_stride) == __pyx_v_itemsize); - if (__pyx_t_2) { - __pyx_t_2 = (__pyx_v_itemsize == ((size_t)__pyx_v_dst_stride)); - } - __pyx_t_3 = (__pyx_t_2 != 0); - __pyx_t_1 = __pyx_t_3; - __pyx_L5_bool_binop_done:; - - /* "View.MemoryView":1155 - * - * if ndim == 1: - * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< - * src_stride == itemsize == dst_stride): - * memcpy(dst_data, src_data, itemsize * dst_extent) - */ - if (__pyx_t_1) { - - /* "View.MemoryView":1157 - * if (src_stride > 0 and dst_stride > 0 and - * src_stride == itemsize == dst_stride): - * memcpy(dst_data, src_data, itemsize * dst_extent) # <<<<<<<<<<<<<< - * else: - * for i in range(dst_extent): - */ - (void)(memcpy(__pyx_v_dst_data, __pyx_v_src_data, (__pyx_v_itemsize * __pyx_v_dst_extent))); - - /* "View.MemoryView":1155 - * - * if ndim == 1: - * if (src_stride > 0 and dst_stride > 0 and # <<<<<<<<<<<<<< - * src_stride == itemsize == dst_stride): - * memcpy(dst_data, src_data, itemsize * dst_extent) - */ - goto __pyx_L4; - } - - /* "View.MemoryView":1159 - * memcpy(dst_data, src_data, itemsize * dst_extent) - * else: - * for i in range(dst_extent): # <<<<<<<<<<<<<< - * memcpy(dst_data, src_data, itemsize) - * src_data += src_stride - */ - /*else*/ { - __pyx_t_4 = __pyx_v_dst_extent; - __pyx_t_5 = __pyx_t_4; - for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { - __pyx_v_i = __pyx_t_6; - - /* "View.MemoryView":1160 - * else: - * for i in range(dst_extent): - * memcpy(dst_data, src_data, itemsize) # <<<<<<<<<<<<<< - * src_data += src_stride - * dst_data += dst_stride - */ - (void)(memcpy(__pyx_v_dst_data, __pyx_v_src_data, __pyx_v_itemsize)); - - /* "View.MemoryView":1161 - * for i in range(dst_extent): - * memcpy(dst_data, src_data, itemsize) - * src_data += src_stride # <<<<<<<<<<<<<< - * dst_data += dst_stride - * else: - */ - __pyx_v_src_data = (__pyx_v_src_data + __pyx_v_src_stride); - - /* "View.MemoryView":1162 - * memcpy(dst_data, src_data, itemsize) - * src_data += src_stride - * dst_data += dst_stride # <<<<<<<<<<<<<< - * else: - * for i in range(dst_extent): - */ - __pyx_v_dst_data = (__pyx_v_dst_data + __pyx_v_dst_stride); - } - } - __pyx_L4:; - - /* "View.MemoryView":1154 - * cdef Py_ssize_t dst_stride = dst_strides[0] - * - * if ndim == 1: # <<<<<<<<<<<<<< - * if (src_stride > 0 and dst_stride > 0 and - * src_stride == itemsize == dst_stride): - */ - goto __pyx_L3; - } - - /* "View.MemoryView":1164 - * dst_data += dst_stride - * else: - * for i in range(dst_extent): # <<<<<<<<<<<<<< - * _copy_strided_to_strided(src_data, src_strides + 1, - * dst_data, dst_strides + 1, - */ - /*else*/ { - __pyx_t_4 = __pyx_v_dst_extent; - __pyx_t_5 = __pyx_t_4; - for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { - __pyx_v_i = __pyx_t_6; - - /* "View.MemoryView":1165 - * else: - * for i in range(dst_extent): - * _copy_strided_to_strided(src_data, src_strides + 1, # <<<<<<<<<<<<<< - * dst_data, dst_strides + 1, - * src_shape + 1, dst_shape + 1, - */ - _copy_strided_to_strided(__pyx_v_src_data, (__pyx_v_src_strides + 1), __pyx_v_dst_data, (__pyx_v_dst_strides + 1), (__pyx_v_src_shape + 1), (__pyx_v_dst_shape + 1), (__pyx_v_ndim - 1), __pyx_v_itemsize); - - /* "View.MemoryView":1169 - * src_shape + 1, dst_shape + 1, - * ndim - 1, itemsize) - * src_data += src_stride # <<<<<<<<<<<<<< - * dst_data += dst_stride - * - */ - __pyx_v_src_data = (__pyx_v_src_data + __pyx_v_src_stride); - - /* "View.MemoryView":1170 - * ndim - 1, itemsize) - * src_data += src_stride - * dst_data += dst_stride # <<<<<<<<<<<<<< - * - * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, - */ - __pyx_v_dst_data = (__pyx_v_dst_data + __pyx_v_dst_stride); - } - } - __pyx_L3:; - - /* "View.MemoryView":1142 - * - * @cython.cdivision(True) - * cdef void _copy_strided_to_strided(char *src_data, Py_ssize_t *src_strides, # <<<<<<<<<<<<<< - * char *dst_data, Py_ssize_t *dst_strides, - * Py_ssize_t *src_shape, Py_ssize_t *dst_shape, - */ - - /* function exit code */ -} - -/* "View.MemoryView":1172 - * dst_data += dst_stride - * - * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *dst, - * int ndim, size_t itemsize) nogil: - */ - -static void copy_strided_to_strided(__Pyx_memviewslice *__pyx_v_src, __Pyx_memviewslice *__pyx_v_dst, int __pyx_v_ndim, size_t __pyx_v_itemsize) { - - /* "View.MemoryView":1175 - * __Pyx_memviewslice *dst, - * int ndim, size_t itemsize) nogil: - * _copy_strided_to_strided(src.data, src.strides, dst.data, dst.strides, # <<<<<<<<<<<<<< - * src.shape, dst.shape, ndim, itemsize) - * - */ - _copy_strided_to_strided(__pyx_v_src->data, __pyx_v_src->strides, __pyx_v_dst->data, __pyx_v_dst->strides, __pyx_v_src->shape, __pyx_v_dst->shape, __pyx_v_ndim, __pyx_v_itemsize); - - /* "View.MemoryView":1172 - * dst_data += dst_stride - * - * cdef void copy_strided_to_strided(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *dst, - * int ndim, size_t itemsize) nogil: - */ - - /* function exit code */ -} - -/* "View.MemoryView":1179 - * - * @cname('__pyx_memoryview_slice_get_size') - * cdef Py_ssize_t slice_get_size(__Pyx_memviewslice *src, int ndim) nogil: # <<<<<<<<<<<<<< - * "Return the size of the memory occupied by the slice in number of bytes" - * cdef Py_ssize_t shape, size = src.memview.view.itemsize - */ - -static Py_ssize_t __pyx_memoryview_slice_get_size(__Pyx_memviewslice *__pyx_v_src, int __pyx_v_ndim) { - Py_ssize_t __pyx_v_shape; - Py_ssize_t __pyx_v_size; - Py_ssize_t __pyx_r; - Py_ssize_t __pyx_t_1; - Py_ssize_t *__pyx_t_2; - Py_ssize_t *__pyx_t_3; - Py_ssize_t *__pyx_t_4; - - /* "View.MemoryView":1181 - * cdef Py_ssize_t slice_get_size(__Pyx_memviewslice *src, int ndim) nogil: - * "Return the size of the memory occupied by the slice in number of bytes" - * cdef Py_ssize_t shape, size = src.memview.view.itemsize # <<<<<<<<<<<<<< - * - * for shape in src.shape[:ndim]: - */ - __pyx_t_1 = __pyx_v_src->memview->view.itemsize; - __pyx_v_size = __pyx_t_1; - - /* "View.MemoryView":1183 - * cdef Py_ssize_t shape, size = src.memview.view.itemsize - * - * for shape in src.shape[:ndim]: # <<<<<<<<<<<<<< - * size *= shape - * - */ - __pyx_t_3 = (__pyx_v_src->shape + __pyx_v_ndim); - for (__pyx_t_4 = __pyx_v_src->shape; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) { - __pyx_t_2 = __pyx_t_4; - __pyx_v_shape = (__pyx_t_2[0]); - - /* "View.MemoryView":1184 - * - * for shape in src.shape[:ndim]: - * size *= shape # <<<<<<<<<<<<<< - * - * return size - */ - __pyx_v_size = (__pyx_v_size * __pyx_v_shape); - } - - /* "View.MemoryView":1186 - * size *= shape - * - * return size # <<<<<<<<<<<<<< - * - * @cname('__pyx_fill_contig_strides_array') - */ - __pyx_r = __pyx_v_size; - goto __pyx_L0; - - /* "View.MemoryView":1179 - * - * @cname('__pyx_memoryview_slice_get_size') - * cdef Py_ssize_t slice_get_size(__Pyx_memviewslice *src, int ndim) nogil: # <<<<<<<<<<<<<< - * "Return the size of the memory occupied by the slice in number of bytes" - * cdef Py_ssize_t shape, size = src.memview.view.itemsize - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":1189 - * - * @cname('__pyx_fill_contig_strides_array') - * cdef Py_ssize_t fill_contig_strides_array( # <<<<<<<<<<<<<< - * Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride, - * int ndim, char order) nogil: - */ - -static Py_ssize_t __pyx_fill_contig_strides_array(Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, Py_ssize_t __pyx_v_stride, int __pyx_v_ndim, char __pyx_v_order) { - int __pyx_v_idx; - Py_ssize_t __pyx_r; - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - - /* "View.MemoryView":1198 - * cdef int idx - * - * if order == 'F': # <<<<<<<<<<<<<< - * for idx in range(ndim): - * strides[idx] = stride - */ - __pyx_t_1 = ((__pyx_v_order == 'F') != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1199 - * - * if order == 'F': - * for idx in range(ndim): # <<<<<<<<<<<<<< - * strides[idx] = stride - * stride *= shape[idx] - */ - __pyx_t_2 = __pyx_v_ndim; - __pyx_t_3 = __pyx_t_2; - for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_idx = __pyx_t_4; - - /* "View.MemoryView":1200 - * if order == 'F': - * for idx in range(ndim): - * strides[idx] = stride # <<<<<<<<<<<<<< - * stride *= shape[idx] - * else: - */ - (__pyx_v_strides[__pyx_v_idx]) = __pyx_v_stride; - - /* "View.MemoryView":1201 - * for idx in range(ndim): - * strides[idx] = stride - * stride *= shape[idx] # <<<<<<<<<<<<<< - * else: - * for idx in range(ndim - 1, -1, -1): - */ - __pyx_v_stride = (__pyx_v_stride * (__pyx_v_shape[__pyx_v_idx])); - } - - /* "View.MemoryView":1198 - * cdef int idx - * - * if order == 'F': # <<<<<<<<<<<<<< - * for idx in range(ndim): - * strides[idx] = stride - */ - goto __pyx_L3; - } - - /* "View.MemoryView":1203 - * stride *= shape[idx] - * else: - * for idx in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< - * strides[idx] = stride - * stride *= shape[idx] - */ - /*else*/ { - for (__pyx_t_2 = (__pyx_v_ndim - 1); __pyx_t_2 > -1; __pyx_t_2-=1) { - __pyx_v_idx = __pyx_t_2; - - /* "View.MemoryView":1204 - * else: - * for idx in range(ndim - 1, -1, -1): - * strides[idx] = stride # <<<<<<<<<<<<<< - * stride *= shape[idx] - * - */ - (__pyx_v_strides[__pyx_v_idx]) = __pyx_v_stride; - - /* "View.MemoryView":1205 - * for idx in range(ndim - 1, -1, -1): - * strides[idx] = stride - * stride *= shape[idx] # <<<<<<<<<<<<<< - * - * return stride - */ - __pyx_v_stride = (__pyx_v_stride * (__pyx_v_shape[__pyx_v_idx])); - } - } - __pyx_L3:; - - /* "View.MemoryView":1207 - * stride *= shape[idx] - * - * return stride # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_copy_data_to_temp') - */ - __pyx_r = __pyx_v_stride; - goto __pyx_L0; - - /* "View.MemoryView":1189 - * - * @cname('__pyx_fill_contig_strides_array') - * cdef Py_ssize_t fill_contig_strides_array( # <<<<<<<<<<<<<< - * Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t stride, - * int ndim, char order) nogil: - */ - - /* function exit code */ - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":1210 - * - * @cname('__pyx_memoryview_copy_data_to_temp') - * cdef void *copy_data_to_temp(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *tmpslice, - * char order, - */ - -static void *__pyx_memoryview_copy_data_to_temp(__Pyx_memviewslice *__pyx_v_src, __Pyx_memviewslice *__pyx_v_tmpslice, char __pyx_v_order, int __pyx_v_ndim) { - int __pyx_v_i; - void *__pyx_v_result; - size_t __pyx_v_itemsize; - size_t __pyx_v_size; - void *__pyx_r; - Py_ssize_t __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - struct __pyx_memoryview_obj *__pyx_t_4; - int __pyx_t_5; - int __pyx_t_6; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - - /* "View.MemoryView":1221 - * cdef void *result - * - * cdef size_t itemsize = src.memview.view.itemsize # <<<<<<<<<<<<<< - * cdef size_t size = slice_get_size(src, ndim) - * - */ - __pyx_t_1 = __pyx_v_src->memview->view.itemsize; - __pyx_v_itemsize = __pyx_t_1; - - /* "View.MemoryView":1222 - * - * cdef size_t itemsize = src.memview.view.itemsize - * cdef size_t size = slice_get_size(src, ndim) # <<<<<<<<<<<<<< - * - * result = malloc(size) - */ - __pyx_v_size = __pyx_memoryview_slice_get_size(__pyx_v_src, __pyx_v_ndim); - - /* "View.MemoryView":1224 - * cdef size_t size = slice_get_size(src, ndim) - * - * result = malloc(size) # <<<<<<<<<<<<<< - * if not result: - * _err(MemoryError, NULL) - */ - __pyx_v_result = malloc(__pyx_v_size); - - /* "View.MemoryView":1225 - * - * result = malloc(size) - * if not result: # <<<<<<<<<<<<<< - * _err(MemoryError, NULL) - * - */ - __pyx_t_2 = ((!(__pyx_v_result != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1226 - * result = malloc(size) - * if not result: - * _err(MemoryError, NULL) # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_3 = __pyx_memoryview_err(__pyx_builtin_MemoryError, NULL); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(2, 1226, __pyx_L1_error) - - /* "View.MemoryView":1225 - * - * result = malloc(size) - * if not result: # <<<<<<<<<<<<<< - * _err(MemoryError, NULL) - * - */ - } - - /* "View.MemoryView":1229 - * - * - * tmpslice.data = result # <<<<<<<<<<<<<< - * tmpslice.memview = src.memview - * for i in range(ndim): - */ - __pyx_v_tmpslice->data = ((char *)__pyx_v_result); - - /* "View.MemoryView":1230 - * - * tmpslice.data = result - * tmpslice.memview = src.memview # <<<<<<<<<<<<<< - * for i in range(ndim): - * tmpslice.shape[i] = src.shape[i] - */ - __pyx_t_4 = __pyx_v_src->memview; - __pyx_v_tmpslice->memview = __pyx_t_4; - - /* "View.MemoryView":1231 - * tmpslice.data = result - * tmpslice.memview = src.memview - * for i in range(ndim): # <<<<<<<<<<<<<< - * tmpslice.shape[i] = src.shape[i] - * tmpslice.suboffsets[i] = -1 - */ - __pyx_t_3 = __pyx_v_ndim; - __pyx_t_5 = __pyx_t_3; - for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { - __pyx_v_i = __pyx_t_6; - - /* "View.MemoryView":1232 - * tmpslice.memview = src.memview - * for i in range(ndim): - * tmpslice.shape[i] = src.shape[i] # <<<<<<<<<<<<<< - * tmpslice.suboffsets[i] = -1 - * - */ - (__pyx_v_tmpslice->shape[__pyx_v_i]) = (__pyx_v_src->shape[__pyx_v_i]); - - /* "View.MemoryView":1233 - * for i in range(ndim): - * tmpslice.shape[i] = src.shape[i] - * tmpslice.suboffsets[i] = -1 # <<<<<<<<<<<<<< - * - * fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, - */ - (__pyx_v_tmpslice->suboffsets[__pyx_v_i]) = -1L; - } - - /* "View.MemoryView":1235 - * tmpslice.suboffsets[i] = -1 - * - * fill_contig_strides_array(&tmpslice.shape[0], &tmpslice.strides[0], itemsize, # <<<<<<<<<<<<<< - * ndim, order) - * - */ - (void)(__pyx_fill_contig_strides_array((&(__pyx_v_tmpslice->shape[0])), (&(__pyx_v_tmpslice->strides[0])), __pyx_v_itemsize, __pyx_v_ndim, __pyx_v_order)); - - /* "View.MemoryView":1239 - * - * - * for i in range(ndim): # <<<<<<<<<<<<<< - * if tmpslice.shape[i] == 1: - * tmpslice.strides[i] = 0 - */ - __pyx_t_3 = __pyx_v_ndim; - __pyx_t_5 = __pyx_t_3; - for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) { - __pyx_v_i = __pyx_t_6; - - /* "View.MemoryView":1240 - * - * for i in range(ndim): - * if tmpslice.shape[i] == 1: # <<<<<<<<<<<<<< - * tmpslice.strides[i] = 0 - * - */ - __pyx_t_2 = (((__pyx_v_tmpslice->shape[__pyx_v_i]) == 1) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1241 - * for i in range(ndim): - * if tmpslice.shape[i] == 1: - * tmpslice.strides[i] = 0 # <<<<<<<<<<<<<< - * - * if slice_is_contig(src[0], order, ndim): - */ - (__pyx_v_tmpslice->strides[__pyx_v_i]) = 0; - - /* "View.MemoryView":1240 - * - * for i in range(ndim): - * if tmpslice.shape[i] == 1: # <<<<<<<<<<<<<< - * tmpslice.strides[i] = 0 - * - */ - } - } - - /* "View.MemoryView":1243 - * tmpslice.strides[i] = 0 - * - * if slice_is_contig(src[0], order, ndim): # <<<<<<<<<<<<<< - * memcpy(result, src.data, size) - * else: - */ - __pyx_t_2 = (__pyx_memviewslice_is_contig((__pyx_v_src[0]), __pyx_v_order, __pyx_v_ndim) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1244 - * - * if slice_is_contig(src[0], order, ndim): - * memcpy(result, src.data, size) # <<<<<<<<<<<<<< - * else: - * copy_strided_to_strided(src, tmpslice, ndim, itemsize) - */ - (void)(memcpy(__pyx_v_result, __pyx_v_src->data, __pyx_v_size)); - - /* "View.MemoryView":1243 - * tmpslice.strides[i] = 0 - * - * if slice_is_contig(src[0], order, ndim): # <<<<<<<<<<<<<< - * memcpy(result, src.data, size) - * else: - */ - goto __pyx_L9; - } - - /* "View.MemoryView":1246 - * memcpy(result, src.data, size) - * else: - * copy_strided_to_strided(src, tmpslice, ndim, itemsize) # <<<<<<<<<<<<<< - * - * return result - */ - /*else*/ { - copy_strided_to_strided(__pyx_v_src, __pyx_v_tmpslice, __pyx_v_ndim, __pyx_v_itemsize); - } - __pyx_L9:; - - /* "View.MemoryView":1248 - * copy_strided_to_strided(src, tmpslice, ndim, itemsize) - * - * return result # <<<<<<<<<<<<<< - * - * - */ - __pyx_r = __pyx_v_result; - goto __pyx_L0; - - /* "View.MemoryView":1210 - * - * @cname('__pyx_memoryview_copy_data_to_temp') - * cdef void *copy_data_to_temp(__Pyx_memviewslice *src, # <<<<<<<<<<<<<< - * __Pyx_memviewslice *tmpslice, - * char order, - */ - - /* function exit code */ - __pyx_L1_error:; - { - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_AddTraceback("View.MemoryView.copy_data_to_temp", __pyx_clineno, __pyx_lineno, __pyx_filename); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - } - __pyx_r = NULL; - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":1253 - * - * @cname('__pyx_memoryview_err_extents') - * cdef int _err_extents(int i, Py_ssize_t extent1, # <<<<<<<<<<<<<< - * Py_ssize_t extent2) except -1 with gil: - * raise ValueError("got differing extents in dimension %d (got %d and %d)" % - */ - -static int __pyx_memoryview_err_extents(int __pyx_v_i, Py_ssize_t __pyx_v_extent1, Py_ssize_t __pyx_v_extent2) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_RefNannySetupContext("_err_extents", 0); - - /* "View.MemoryView":1256 - * Py_ssize_t extent2) except -1 with gil: - * raise ValueError("got differing extents in dimension %d (got %d and %d)" % - * (i, extent1, extent2)) # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_err_dim') - */ - __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1256, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = PyInt_FromSsize_t(__pyx_v_extent1); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1256, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyInt_FromSsize_t(__pyx_v_extent2); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 1256, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 1256, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3); - __pyx_t_1 = 0; - __pyx_t_2 = 0; - __pyx_t_3 = 0; - - /* "View.MemoryView":1255 - * cdef int _err_extents(int i, Py_ssize_t extent1, - * Py_ssize_t extent2) except -1 with gil: - * raise ValueError("got differing extents in dimension %d (got %d and %d)" % # <<<<<<<<<<<<<< - * (i, extent1, extent2)) - * - */ - __pyx_t_3 = __Pyx_PyString_Format(__pyx_kp_s_got_differing_extents_in_dimensi, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 1255, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 1255, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_Raise(__pyx_t_4, 0, 0, 0); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __PYX_ERR(2, 1255, __pyx_L1_error) - - /* "View.MemoryView":1253 - * - * @cname('__pyx_memoryview_err_extents') - * cdef int _err_extents(int i, Py_ssize_t extent1, # <<<<<<<<<<<<<< - * Py_ssize_t extent2) except -1 with gil: - * raise ValueError("got differing extents in dimension %d (got %d and %d)" % - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("View.MemoryView._err_extents", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __Pyx_RefNannyFinishContext(); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - return __pyx_r; -} - -/* "View.MemoryView":1259 - * - * @cname('__pyx_memoryview_err_dim') - * cdef int _err_dim(object error, char *msg, int dim) except -1 with gil: # <<<<<<<<<<<<<< - * raise error(msg.decode('ascii') % dim) - * - */ - -static int __pyx_memoryview_err_dim(PyObject *__pyx_v_error, char *__pyx_v_msg, int __pyx_v_dim) { - int __pyx_r; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_RefNannySetupContext("_err_dim", 0); - __Pyx_INCREF(__pyx_v_error); - - /* "View.MemoryView":1260 - * @cname('__pyx_memoryview_err_dim') - * cdef int _err_dim(object error, char *msg, int dim) except -1 with gil: - * raise error(msg.decode('ascii') % dim) # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_err') - */ - __pyx_t_2 = __Pyx_decode_c_string(__pyx_v_msg, 0, strlen(__pyx_v_msg), NULL, NULL, PyUnicode_DecodeASCII); if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1260, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_dim); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 1260, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PyUnicode_Format(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 1260, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_INCREF(__pyx_v_error); - __pyx_t_3 = __pyx_v_error; __pyx_t_2 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_2)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_2); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - } - } - __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1260, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_Raise(__pyx_t_1, 0, 0, 0); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __PYX_ERR(2, 1260, __pyx_L1_error) - - /* "View.MemoryView":1259 - * - * @cname('__pyx_memoryview_err_dim') - * cdef int _err_dim(object error, char *msg, int dim) except -1 with gil: # <<<<<<<<<<<<<< - * raise error(msg.decode('ascii') % dim) - * - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_AddTraceback("View.MemoryView._err_dim", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __Pyx_XDECREF(__pyx_v_error); - __Pyx_RefNannyFinishContext(); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - return __pyx_r; -} - -/* "View.MemoryView":1263 - * - * @cname('__pyx_memoryview_err') - * cdef int _err(object error, char *msg) except -1 with gil: # <<<<<<<<<<<<<< - * if msg != NULL: - * raise error(msg.decode('ascii')) - */ - -static int __pyx_memoryview_err(PyObject *__pyx_v_error, char *__pyx_v_msg) { - int __pyx_r; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_RefNannySetupContext("_err", 0); - __Pyx_INCREF(__pyx_v_error); - - /* "View.MemoryView":1264 - * @cname('__pyx_memoryview_err') - * cdef int _err(object error, char *msg) except -1 with gil: - * if msg != NULL: # <<<<<<<<<<<<<< - * raise error(msg.decode('ascii')) - * else: - */ - __pyx_t_1 = ((__pyx_v_msg != NULL) != 0); - if (unlikely(__pyx_t_1)) { - - /* "View.MemoryView":1265 - * cdef int _err(object error, char *msg) except -1 with gil: - * if msg != NULL: - * raise error(msg.decode('ascii')) # <<<<<<<<<<<<<< - * else: - * raise error - */ - __pyx_t_3 = __Pyx_decode_c_string(__pyx_v_msg, 0, strlen(__pyx_v_msg), NULL, NULL, PyUnicode_DecodeASCII); if (unlikely(!__pyx_t_3)) __PYX_ERR(2, 1265, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_error); - __pyx_t_4 = __pyx_v_error; __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_2)) __PYX_ERR(2, 1265, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_Raise(__pyx_t_2, 0, 0, 0); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __PYX_ERR(2, 1265, __pyx_L1_error) - - /* "View.MemoryView":1264 - * @cname('__pyx_memoryview_err') - * cdef int _err(object error, char *msg) except -1 with gil: - * if msg != NULL: # <<<<<<<<<<<<<< - * raise error(msg.decode('ascii')) - * else: - */ - } - - /* "View.MemoryView":1267 - * raise error(msg.decode('ascii')) - * else: - * raise error # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_copy_contents') - */ - /*else*/ { - __Pyx_Raise(__pyx_v_error, 0, 0, 0); - __PYX_ERR(2, 1267, __pyx_L1_error) - } - - /* "View.MemoryView":1263 - * - * @cname('__pyx_memoryview_err') - * cdef int _err(object error, char *msg) except -1 with gil: # <<<<<<<<<<<<<< - * if msg != NULL: - * raise error(msg.decode('ascii')) - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_AddTraceback("View.MemoryView._err", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = -1; - __Pyx_XDECREF(__pyx_v_error); - __Pyx_RefNannyFinishContext(); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - return __pyx_r; -} - -/* "View.MemoryView":1270 - * - * @cname('__pyx_memoryview_copy_contents') - * cdef int memoryview_copy_contents(__Pyx_memviewslice src, # <<<<<<<<<<<<<< - * __Pyx_memviewslice dst, - * int src_ndim, int dst_ndim, - */ - -static int __pyx_memoryview_copy_contents(__Pyx_memviewslice __pyx_v_src, __Pyx_memviewslice __pyx_v_dst, int __pyx_v_src_ndim, int __pyx_v_dst_ndim, int __pyx_v_dtype_is_object) { - void *__pyx_v_tmpdata; - size_t __pyx_v_itemsize; - int __pyx_v_i; - char __pyx_v_order; - int __pyx_v_broadcasting; - int __pyx_v_direct_copy; - __Pyx_memviewslice __pyx_v_tmp; - int __pyx_v_ndim; - int __pyx_r; - Py_ssize_t __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - int __pyx_t_5; - int __pyx_t_6; - void *__pyx_t_7; - int __pyx_t_8; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - - /* "View.MemoryView":1278 - * Check for overlapping memory and verify the shapes. - * """ - * cdef void *tmpdata = NULL # <<<<<<<<<<<<<< - * cdef size_t itemsize = src.memview.view.itemsize - * cdef int i - */ - __pyx_v_tmpdata = NULL; - - /* "View.MemoryView":1279 - * """ - * cdef void *tmpdata = NULL - * cdef size_t itemsize = src.memview.view.itemsize # <<<<<<<<<<<<<< - * cdef int i - * cdef char order = get_best_order(&src, src_ndim) - */ - __pyx_t_1 = __pyx_v_src.memview->view.itemsize; - __pyx_v_itemsize = __pyx_t_1; - - /* "View.MemoryView":1281 - * cdef size_t itemsize = src.memview.view.itemsize - * cdef int i - * cdef char order = get_best_order(&src, src_ndim) # <<<<<<<<<<<<<< - * cdef bint broadcasting = False - * cdef bint direct_copy = False - */ - __pyx_v_order = __pyx_get_best_slice_order((&__pyx_v_src), __pyx_v_src_ndim); - - /* "View.MemoryView":1282 - * cdef int i - * cdef char order = get_best_order(&src, src_ndim) - * cdef bint broadcasting = False # <<<<<<<<<<<<<< - * cdef bint direct_copy = False - * cdef __Pyx_memviewslice tmp - */ - __pyx_v_broadcasting = 0; - - /* "View.MemoryView":1283 - * cdef char order = get_best_order(&src, src_ndim) - * cdef bint broadcasting = False - * cdef bint direct_copy = False # <<<<<<<<<<<<<< - * cdef __Pyx_memviewslice tmp - * - */ - __pyx_v_direct_copy = 0; - - /* "View.MemoryView":1286 - * cdef __Pyx_memviewslice tmp - * - * if src_ndim < dst_ndim: # <<<<<<<<<<<<<< - * broadcast_leading(&src, src_ndim, dst_ndim) - * elif dst_ndim < src_ndim: - */ - __pyx_t_2 = ((__pyx_v_src_ndim < __pyx_v_dst_ndim) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1287 - * - * if src_ndim < dst_ndim: - * broadcast_leading(&src, src_ndim, dst_ndim) # <<<<<<<<<<<<<< - * elif dst_ndim < src_ndim: - * broadcast_leading(&dst, dst_ndim, src_ndim) - */ - __pyx_memoryview_broadcast_leading((&__pyx_v_src), __pyx_v_src_ndim, __pyx_v_dst_ndim); - - /* "View.MemoryView":1286 - * cdef __Pyx_memviewslice tmp - * - * if src_ndim < dst_ndim: # <<<<<<<<<<<<<< - * broadcast_leading(&src, src_ndim, dst_ndim) - * elif dst_ndim < src_ndim: - */ - goto __pyx_L3; - } - - /* "View.MemoryView":1288 - * if src_ndim < dst_ndim: - * broadcast_leading(&src, src_ndim, dst_ndim) - * elif dst_ndim < src_ndim: # <<<<<<<<<<<<<< - * broadcast_leading(&dst, dst_ndim, src_ndim) - * - */ - __pyx_t_2 = ((__pyx_v_dst_ndim < __pyx_v_src_ndim) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1289 - * broadcast_leading(&src, src_ndim, dst_ndim) - * elif dst_ndim < src_ndim: - * broadcast_leading(&dst, dst_ndim, src_ndim) # <<<<<<<<<<<<<< - * - * cdef int ndim = max(src_ndim, dst_ndim) - */ - __pyx_memoryview_broadcast_leading((&__pyx_v_dst), __pyx_v_dst_ndim, __pyx_v_src_ndim); - - /* "View.MemoryView":1288 - * if src_ndim < dst_ndim: - * broadcast_leading(&src, src_ndim, dst_ndim) - * elif dst_ndim < src_ndim: # <<<<<<<<<<<<<< - * broadcast_leading(&dst, dst_ndim, src_ndim) - * - */ - } - __pyx_L3:; - - /* "View.MemoryView":1291 - * broadcast_leading(&dst, dst_ndim, src_ndim) - * - * cdef int ndim = max(src_ndim, dst_ndim) # <<<<<<<<<<<<<< - * - * for i in range(ndim): - */ - __pyx_t_3 = __pyx_v_dst_ndim; - __pyx_t_4 = __pyx_v_src_ndim; - if (((__pyx_t_3 > __pyx_t_4) != 0)) { - __pyx_t_5 = __pyx_t_3; - } else { - __pyx_t_5 = __pyx_t_4; - } - __pyx_v_ndim = __pyx_t_5; - - /* "View.MemoryView":1293 - * cdef int ndim = max(src_ndim, dst_ndim) - * - * for i in range(ndim): # <<<<<<<<<<<<<< - * if src.shape[i] != dst.shape[i]: - * if src.shape[i] == 1: - */ - __pyx_t_5 = __pyx_v_ndim; - __pyx_t_3 = __pyx_t_5; - for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_i = __pyx_t_4; - - /* "View.MemoryView":1294 - * - * for i in range(ndim): - * if src.shape[i] != dst.shape[i]: # <<<<<<<<<<<<<< - * if src.shape[i] == 1: - * broadcasting = True - */ - __pyx_t_2 = (((__pyx_v_src.shape[__pyx_v_i]) != (__pyx_v_dst.shape[__pyx_v_i])) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1295 - * for i in range(ndim): - * if src.shape[i] != dst.shape[i]: - * if src.shape[i] == 1: # <<<<<<<<<<<<<< - * broadcasting = True - * src.strides[i] = 0 - */ - __pyx_t_2 = (((__pyx_v_src.shape[__pyx_v_i]) == 1) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1296 - * if src.shape[i] != dst.shape[i]: - * if src.shape[i] == 1: - * broadcasting = True # <<<<<<<<<<<<<< - * src.strides[i] = 0 - * else: - */ - __pyx_v_broadcasting = 1; - - /* "View.MemoryView":1297 - * if src.shape[i] == 1: - * broadcasting = True - * src.strides[i] = 0 # <<<<<<<<<<<<<< - * else: - * _err_extents(i, dst.shape[i], src.shape[i]) - */ - (__pyx_v_src.strides[__pyx_v_i]) = 0; - - /* "View.MemoryView":1295 - * for i in range(ndim): - * if src.shape[i] != dst.shape[i]: - * if src.shape[i] == 1: # <<<<<<<<<<<<<< - * broadcasting = True - * src.strides[i] = 0 - */ - goto __pyx_L7; - } - - /* "View.MemoryView":1299 - * src.strides[i] = 0 - * else: - * _err_extents(i, dst.shape[i], src.shape[i]) # <<<<<<<<<<<<<< - * - * if src.suboffsets[i] >= 0: - */ - /*else*/ { - __pyx_t_6 = __pyx_memoryview_err_extents(__pyx_v_i, (__pyx_v_dst.shape[__pyx_v_i]), (__pyx_v_src.shape[__pyx_v_i])); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(2, 1299, __pyx_L1_error) - } - __pyx_L7:; - - /* "View.MemoryView":1294 - * - * for i in range(ndim): - * if src.shape[i] != dst.shape[i]: # <<<<<<<<<<<<<< - * if src.shape[i] == 1: - * broadcasting = True - */ - } - - /* "View.MemoryView":1301 - * _err_extents(i, dst.shape[i], src.shape[i]) - * - * if src.suboffsets[i] >= 0: # <<<<<<<<<<<<<< - * _err_dim(ValueError, "Dimension %d is not direct", i) - * - */ - __pyx_t_2 = (((__pyx_v_src.suboffsets[__pyx_v_i]) >= 0) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1302 - * - * if src.suboffsets[i] >= 0: - * _err_dim(ValueError, "Dimension %d is not direct", i) # <<<<<<<<<<<<<< - * - * if slices_overlap(&src, &dst, ndim, itemsize): - */ - __pyx_t_6 = __pyx_memoryview_err_dim(__pyx_builtin_ValueError, ((char *)"Dimension %d is not direct"), __pyx_v_i); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(2, 1302, __pyx_L1_error) - - /* "View.MemoryView":1301 - * _err_extents(i, dst.shape[i], src.shape[i]) - * - * if src.suboffsets[i] >= 0: # <<<<<<<<<<<<<< - * _err_dim(ValueError, "Dimension %d is not direct", i) - * - */ - } - } - - /* "View.MemoryView":1304 - * _err_dim(ValueError, "Dimension %d is not direct", i) - * - * if slices_overlap(&src, &dst, ndim, itemsize): # <<<<<<<<<<<<<< - * - * if not slice_is_contig(src, order, ndim): - */ - __pyx_t_2 = (__pyx_slices_overlap((&__pyx_v_src), (&__pyx_v_dst), __pyx_v_ndim, __pyx_v_itemsize) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1306 - * if slices_overlap(&src, &dst, ndim, itemsize): - * - * if not slice_is_contig(src, order, ndim): # <<<<<<<<<<<<<< - * order = get_best_order(&dst, ndim) - * - */ - __pyx_t_2 = ((!(__pyx_memviewslice_is_contig(__pyx_v_src, __pyx_v_order, __pyx_v_ndim) != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1307 - * - * if not slice_is_contig(src, order, ndim): - * order = get_best_order(&dst, ndim) # <<<<<<<<<<<<<< - * - * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) - */ - __pyx_v_order = __pyx_get_best_slice_order((&__pyx_v_dst), __pyx_v_ndim); - - /* "View.MemoryView":1306 - * if slices_overlap(&src, &dst, ndim, itemsize): - * - * if not slice_is_contig(src, order, ndim): # <<<<<<<<<<<<<< - * order = get_best_order(&dst, ndim) - * - */ - } - - /* "View.MemoryView":1309 - * order = get_best_order(&dst, ndim) - * - * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) # <<<<<<<<<<<<<< - * src = tmp - * - */ - __pyx_t_7 = __pyx_memoryview_copy_data_to_temp((&__pyx_v_src), (&__pyx_v_tmp), __pyx_v_order, __pyx_v_ndim); if (unlikely(__pyx_t_7 == ((void *)NULL))) __PYX_ERR(2, 1309, __pyx_L1_error) - __pyx_v_tmpdata = __pyx_t_7; - - /* "View.MemoryView":1310 - * - * tmpdata = copy_data_to_temp(&src, &tmp, order, ndim) - * src = tmp # <<<<<<<<<<<<<< - * - * if not broadcasting: - */ - __pyx_v_src = __pyx_v_tmp; - - /* "View.MemoryView":1304 - * _err_dim(ValueError, "Dimension %d is not direct", i) - * - * if slices_overlap(&src, &dst, ndim, itemsize): # <<<<<<<<<<<<<< - * - * if not slice_is_contig(src, order, ndim): - */ - } - - /* "View.MemoryView":1312 - * src = tmp - * - * if not broadcasting: # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_2 = ((!(__pyx_v_broadcasting != 0)) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1315 - * - * - * if slice_is_contig(src, 'C', ndim): # <<<<<<<<<<<<<< - * direct_copy = slice_is_contig(dst, 'C', ndim) - * elif slice_is_contig(src, 'F', ndim): - */ - __pyx_t_2 = (__pyx_memviewslice_is_contig(__pyx_v_src, 'C', __pyx_v_ndim) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1316 - * - * if slice_is_contig(src, 'C', ndim): - * direct_copy = slice_is_contig(dst, 'C', ndim) # <<<<<<<<<<<<<< - * elif slice_is_contig(src, 'F', ndim): - * direct_copy = slice_is_contig(dst, 'F', ndim) - */ - __pyx_v_direct_copy = __pyx_memviewslice_is_contig(__pyx_v_dst, 'C', __pyx_v_ndim); - - /* "View.MemoryView":1315 - * - * - * if slice_is_contig(src, 'C', ndim): # <<<<<<<<<<<<<< - * direct_copy = slice_is_contig(dst, 'C', ndim) - * elif slice_is_contig(src, 'F', ndim): - */ - goto __pyx_L12; - } - - /* "View.MemoryView":1317 - * if slice_is_contig(src, 'C', ndim): - * direct_copy = slice_is_contig(dst, 'C', ndim) - * elif slice_is_contig(src, 'F', ndim): # <<<<<<<<<<<<<< - * direct_copy = slice_is_contig(dst, 'F', ndim) - * - */ - __pyx_t_2 = (__pyx_memviewslice_is_contig(__pyx_v_src, 'F', __pyx_v_ndim) != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1318 - * direct_copy = slice_is_contig(dst, 'C', ndim) - * elif slice_is_contig(src, 'F', ndim): - * direct_copy = slice_is_contig(dst, 'F', ndim) # <<<<<<<<<<<<<< - * - * if direct_copy: - */ - __pyx_v_direct_copy = __pyx_memviewslice_is_contig(__pyx_v_dst, 'F', __pyx_v_ndim); - - /* "View.MemoryView":1317 - * if slice_is_contig(src, 'C', ndim): - * direct_copy = slice_is_contig(dst, 'C', ndim) - * elif slice_is_contig(src, 'F', ndim): # <<<<<<<<<<<<<< - * direct_copy = slice_is_contig(dst, 'F', ndim) - * - */ - } - __pyx_L12:; - - /* "View.MemoryView":1320 - * direct_copy = slice_is_contig(dst, 'F', ndim) - * - * if direct_copy: # <<<<<<<<<<<<<< - * - * refcount_copying(&dst, dtype_is_object, ndim, False) - */ - __pyx_t_2 = (__pyx_v_direct_copy != 0); - if (__pyx_t_2) { - - /* "View.MemoryView":1322 - * if direct_copy: - * - * refcount_copying(&dst, dtype_is_object, ndim, False) # <<<<<<<<<<<<<< - * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) - * refcount_copying(&dst, dtype_is_object, ndim, True) - */ - __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 0); - - /* "View.MemoryView":1323 - * - * refcount_copying(&dst, dtype_is_object, ndim, False) - * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) # <<<<<<<<<<<<<< - * refcount_copying(&dst, dtype_is_object, ndim, True) - * free(tmpdata) - */ - (void)(memcpy(__pyx_v_dst.data, __pyx_v_src.data, __pyx_memoryview_slice_get_size((&__pyx_v_src), __pyx_v_ndim))); - - /* "View.MemoryView":1324 - * refcount_copying(&dst, dtype_is_object, ndim, False) - * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) - * refcount_copying(&dst, dtype_is_object, ndim, True) # <<<<<<<<<<<<<< - * free(tmpdata) - * return 0 - */ - __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 1); - - /* "View.MemoryView":1325 - * memcpy(dst.data, src.data, slice_get_size(&src, ndim)) - * refcount_copying(&dst, dtype_is_object, ndim, True) - * free(tmpdata) # <<<<<<<<<<<<<< - * return 0 - * - */ - free(__pyx_v_tmpdata); - - /* "View.MemoryView":1326 - * refcount_copying(&dst, dtype_is_object, ndim, True) - * free(tmpdata) - * return 0 # <<<<<<<<<<<<<< - * - * if order == 'F' == get_best_order(&dst, ndim): - */ - __pyx_r = 0; - goto __pyx_L0; - - /* "View.MemoryView":1320 - * direct_copy = slice_is_contig(dst, 'F', ndim) - * - * if direct_copy: # <<<<<<<<<<<<<< - * - * refcount_copying(&dst, dtype_is_object, ndim, False) - */ - } - - /* "View.MemoryView":1312 - * src = tmp - * - * if not broadcasting: # <<<<<<<<<<<<<< - * - * - */ - } - - /* "View.MemoryView":1328 - * return 0 - * - * if order == 'F' == get_best_order(&dst, ndim): # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_2 = (__pyx_v_order == 'F'); - if (__pyx_t_2) { - __pyx_t_2 = ('F' == __pyx_get_best_slice_order((&__pyx_v_dst), __pyx_v_ndim)); - } - __pyx_t_8 = (__pyx_t_2 != 0); - if (__pyx_t_8) { - - /* "View.MemoryView":1331 - * - * - * transpose_memslice(&src) # <<<<<<<<<<<<<< - * transpose_memslice(&dst) - * - */ - __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_src)); if (unlikely(__pyx_t_5 == ((int)0))) __PYX_ERR(2, 1331, __pyx_L1_error) - - /* "View.MemoryView":1332 - * - * transpose_memslice(&src) - * transpose_memslice(&dst) # <<<<<<<<<<<<<< - * - * refcount_copying(&dst, dtype_is_object, ndim, False) - */ - __pyx_t_5 = __pyx_memslice_transpose((&__pyx_v_dst)); if (unlikely(__pyx_t_5 == ((int)0))) __PYX_ERR(2, 1332, __pyx_L1_error) - - /* "View.MemoryView":1328 - * return 0 - * - * if order == 'F' == get_best_order(&dst, ndim): # <<<<<<<<<<<<<< - * - * - */ - } - - /* "View.MemoryView":1334 - * transpose_memslice(&dst) - * - * refcount_copying(&dst, dtype_is_object, ndim, False) # <<<<<<<<<<<<<< - * copy_strided_to_strided(&src, &dst, ndim, itemsize) - * refcount_copying(&dst, dtype_is_object, ndim, True) - */ - __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 0); - - /* "View.MemoryView":1335 - * - * refcount_copying(&dst, dtype_is_object, ndim, False) - * copy_strided_to_strided(&src, &dst, ndim, itemsize) # <<<<<<<<<<<<<< - * refcount_copying(&dst, dtype_is_object, ndim, True) - * - */ - copy_strided_to_strided((&__pyx_v_src), (&__pyx_v_dst), __pyx_v_ndim, __pyx_v_itemsize); - - /* "View.MemoryView":1336 - * refcount_copying(&dst, dtype_is_object, ndim, False) - * copy_strided_to_strided(&src, &dst, ndim, itemsize) - * refcount_copying(&dst, dtype_is_object, ndim, True) # <<<<<<<<<<<<<< - * - * free(tmpdata) - */ - __pyx_memoryview_refcount_copying((&__pyx_v_dst), __pyx_v_dtype_is_object, __pyx_v_ndim, 1); - - /* "View.MemoryView":1338 - * refcount_copying(&dst, dtype_is_object, ndim, True) - * - * free(tmpdata) # <<<<<<<<<<<<<< - * return 0 - * - */ - free(__pyx_v_tmpdata); - - /* "View.MemoryView":1339 - * - * free(tmpdata) - * return 0 # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_broadcast_leading') - */ - __pyx_r = 0; - goto __pyx_L0; - - /* "View.MemoryView":1270 - * - * @cname('__pyx_memoryview_copy_contents') - * cdef int memoryview_copy_contents(__Pyx_memviewslice src, # <<<<<<<<<<<<<< - * __Pyx_memviewslice dst, - * int src_ndim, int dst_ndim, - */ - - /* function exit code */ - __pyx_L1_error:; - { - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_AddTraceback("View.MemoryView.memoryview_copy_contents", __pyx_clineno, __pyx_lineno, __pyx_filename); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif - } - __pyx_r = -1; - __pyx_L0:; - return __pyx_r; -} - -/* "View.MemoryView":1342 - * - * @cname('__pyx_memoryview_broadcast_leading') - * cdef void broadcast_leading(__Pyx_memviewslice *mslice, # <<<<<<<<<<<<<< - * int ndim, - * int ndim_other) nogil: - */ - -static void __pyx_memoryview_broadcast_leading(__Pyx_memviewslice *__pyx_v_mslice, int __pyx_v_ndim, int __pyx_v_ndim_other) { - int __pyx_v_i; - int __pyx_v_offset; - int __pyx_t_1; - int __pyx_t_2; - int __pyx_t_3; - - /* "View.MemoryView":1346 - * int ndim_other) nogil: - * cdef int i - * cdef int offset = ndim_other - ndim # <<<<<<<<<<<<<< - * - * for i in range(ndim - 1, -1, -1): - */ - __pyx_v_offset = (__pyx_v_ndim_other - __pyx_v_ndim); - - /* "View.MemoryView":1348 - * cdef int offset = ndim_other - ndim - * - * for i in range(ndim - 1, -1, -1): # <<<<<<<<<<<<<< - * mslice.shape[i + offset] = mslice.shape[i] - * mslice.strides[i + offset] = mslice.strides[i] - */ - for (__pyx_t_1 = (__pyx_v_ndim - 1); __pyx_t_1 > -1; __pyx_t_1-=1) { - __pyx_v_i = __pyx_t_1; - - /* "View.MemoryView":1349 - * - * for i in range(ndim - 1, -1, -1): - * mslice.shape[i + offset] = mslice.shape[i] # <<<<<<<<<<<<<< - * mslice.strides[i + offset] = mslice.strides[i] - * mslice.suboffsets[i + offset] = mslice.suboffsets[i] - */ - (__pyx_v_mslice->shape[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->shape[__pyx_v_i]); - - /* "View.MemoryView":1350 - * for i in range(ndim - 1, -1, -1): - * mslice.shape[i + offset] = mslice.shape[i] - * mslice.strides[i + offset] = mslice.strides[i] # <<<<<<<<<<<<<< - * mslice.suboffsets[i + offset] = mslice.suboffsets[i] - * - */ - (__pyx_v_mslice->strides[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->strides[__pyx_v_i]); - - /* "View.MemoryView":1351 - * mslice.shape[i + offset] = mslice.shape[i] - * mslice.strides[i + offset] = mslice.strides[i] - * mslice.suboffsets[i + offset] = mslice.suboffsets[i] # <<<<<<<<<<<<<< - * - * for i in range(offset): - */ - (__pyx_v_mslice->suboffsets[(__pyx_v_i + __pyx_v_offset)]) = (__pyx_v_mslice->suboffsets[__pyx_v_i]); - } - - /* "View.MemoryView":1353 - * mslice.suboffsets[i + offset] = mslice.suboffsets[i] - * - * for i in range(offset): # <<<<<<<<<<<<<< - * mslice.shape[i] = 1 - * mslice.strides[i] = mslice.strides[0] - */ - __pyx_t_1 = __pyx_v_offset; - __pyx_t_2 = __pyx_t_1; - for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { - __pyx_v_i = __pyx_t_3; - - /* "View.MemoryView":1354 - * - * for i in range(offset): - * mslice.shape[i] = 1 # <<<<<<<<<<<<<< - * mslice.strides[i] = mslice.strides[0] - * mslice.suboffsets[i] = -1 - */ - (__pyx_v_mslice->shape[__pyx_v_i]) = 1; - - /* "View.MemoryView":1355 - * for i in range(offset): - * mslice.shape[i] = 1 - * mslice.strides[i] = mslice.strides[0] # <<<<<<<<<<<<<< - * mslice.suboffsets[i] = -1 - * - */ - (__pyx_v_mslice->strides[__pyx_v_i]) = (__pyx_v_mslice->strides[0]); - - /* "View.MemoryView":1356 - * mslice.shape[i] = 1 - * mslice.strides[i] = mslice.strides[0] - * mslice.suboffsets[i] = -1 # <<<<<<<<<<<<<< - * - * - */ - (__pyx_v_mslice->suboffsets[__pyx_v_i]) = -1L; - } - - /* "View.MemoryView":1342 - * - * @cname('__pyx_memoryview_broadcast_leading') - * cdef void broadcast_leading(__Pyx_memviewslice *mslice, # <<<<<<<<<<<<<< - * int ndim, - * int ndim_other) nogil: - */ - - /* function exit code */ -} - -/* "View.MemoryView":1364 - * - * @cname('__pyx_memoryview_refcount_copying') - * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, # <<<<<<<<<<<<<< - * int ndim, bint inc) nogil: - * - */ - -static void __pyx_memoryview_refcount_copying(__Pyx_memviewslice *__pyx_v_dst, int __pyx_v_dtype_is_object, int __pyx_v_ndim, int __pyx_v_inc) { - int __pyx_t_1; - - /* "View.MemoryView":1368 - * - * - * if dtype_is_object: # <<<<<<<<<<<<<< - * refcount_objects_in_slice_with_gil(dst.data, dst.shape, - * dst.strides, ndim, inc) - */ - __pyx_t_1 = (__pyx_v_dtype_is_object != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1369 - * - * if dtype_is_object: - * refcount_objects_in_slice_with_gil(dst.data, dst.shape, # <<<<<<<<<<<<<< - * dst.strides, ndim, inc) - * - */ - __pyx_memoryview_refcount_objects_in_slice_with_gil(__pyx_v_dst->data, __pyx_v_dst->shape, __pyx_v_dst->strides, __pyx_v_ndim, __pyx_v_inc); - - /* "View.MemoryView":1368 - * - * - * if dtype_is_object: # <<<<<<<<<<<<<< - * refcount_objects_in_slice_with_gil(dst.data, dst.shape, - * dst.strides, ndim, inc) - */ - } - - /* "View.MemoryView":1364 - * - * @cname('__pyx_memoryview_refcount_copying') - * cdef void refcount_copying(__Pyx_memviewslice *dst, bint dtype_is_object, # <<<<<<<<<<<<<< - * int ndim, bint inc) nogil: - * - */ - - /* function exit code */ -} - -/* "View.MemoryView":1373 - * - * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') - * cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< - * Py_ssize_t *strides, int ndim, - * bint inc) with gil: - */ - -static void __pyx_memoryview_refcount_objects_in_slice_with_gil(char *__pyx_v_data, Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, int __pyx_v_ndim, int __pyx_v_inc) { - __Pyx_RefNannyDeclarations - #ifdef WITH_THREAD - PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure(); - #endif - __Pyx_RefNannySetupContext("refcount_objects_in_slice_with_gil", 0); - - /* "View.MemoryView":1376 - * Py_ssize_t *strides, int ndim, - * bint inc) with gil: - * refcount_objects_in_slice(data, shape, strides, ndim, inc) # <<<<<<<<<<<<<< - * - * @cname('__pyx_memoryview_refcount_objects_in_slice') - */ - __pyx_memoryview_refcount_objects_in_slice(__pyx_v_data, __pyx_v_shape, __pyx_v_strides, __pyx_v_ndim, __pyx_v_inc); - - /* "View.MemoryView":1373 - * - * @cname('__pyx_memoryview_refcount_objects_in_slice_with_gil') - * cdef void refcount_objects_in_slice_with_gil(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< - * Py_ssize_t *strides, int ndim, - * bint inc) with gil: - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - #ifdef WITH_THREAD - __Pyx_PyGILState_Release(__pyx_gilstate_save); - #endif -} - -/* "View.MemoryView":1379 - * - * @cname('__pyx_memoryview_refcount_objects_in_slice') - * cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< - * Py_ssize_t *strides, int ndim, bint inc): - * cdef Py_ssize_t i - */ - -static void __pyx_memoryview_refcount_objects_in_slice(char *__pyx_v_data, Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, int __pyx_v_ndim, int __pyx_v_inc) { - CYTHON_UNUSED Py_ssize_t __pyx_v_i; - __Pyx_RefNannyDeclarations - Py_ssize_t __pyx_t_1; - Py_ssize_t __pyx_t_2; - Py_ssize_t __pyx_t_3; - int __pyx_t_4; - __Pyx_RefNannySetupContext("refcount_objects_in_slice", 0); - - /* "View.MemoryView":1383 - * cdef Py_ssize_t i - * - * for i in range(shape[0]): # <<<<<<<<<<<<<< - * if ndim == 1: - * if inc: - */ - __pyx_t_1 = (__pyx_v_shape[0]); - __pyx_t_2 = __pyx_t_1; - for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) { - __pyx_v_i = __pyx_t_3; - - /* "View.MemoryView":1384 - * - * for i in range(shape[0]): - * if ndim == 1: # <<<<<<<<<<<<<< - * if inc: - * Py_INCREF(( data)[0]) - */ - __pyx_t_4 = ((__pyx_v_ndim == 1) != 0); - if (__pyx_t_4) { - - /* "View.MemoryView":1385 - * for i in range(shape[0]): - * if ndim == 1: - * if inc: # <<<<<<<<<<<<<< - * Py_INCREF(( data)[0]) - * else: - */ - __pyx_t_4 = (__pyx_v_inc != 0); - if (__pyx_t_4) { - - /* "View.MemoryView":1386 - * if ndim == 1: - * if inc: - * Py_INCREF(( data)[0]) # <<<<<<<<<<<<<< - * else: - * Py_DECREF(( data)[0]) - */ - Py_INCREF((((PyObject **)__pyx_v_data)[0])); - - /* "View.MemoryView":1385 - * for i in range(shape[0]): - * if ndim == 1: - * if inc: # <<<<<<<<<<<<<< - * Py_INCREF(( data)[0]) - * else: - */ - goto __pyx_L6; - } - - /* "View.MemoryView":1388 - * Py_INCREF(( data)[0]) - * else: - * Py_DECREF(( data)[0]) # <<<<<<<<<<<<<< - * else: - * refcount_objects_in_slice(data, shape + 1, strides + 1, - */ - /*else*/ { - Py_DECREF((((PyObject **)__pyx_v_data)[0])); - } - __pyx_L6:; - - /* "View.MemoryView":1384 - * - * for i in range(shape[0]): - * if ndim == 1: # <<<<<<<<<<<<<< - * if inc: - * Py_INCREF(( data)[0]) - */ - goto __pyx_L5; - } - - /* "View.MemoryView":1390 - * Py_DECREF(( data)[0]) - * else: - * refcount_objects_in_slice(data, shape + 1, strides + 1, # <<<<<<<<<<<<<< - * ndim - 1, inc) - * - */ - /*else*/ { - - /* "View.MemoryView":1391 - * else: - * refcount_objects_in_slice(data, shape + 1, strides + 1, - * ndim - 1, inc) # <<<<<<<<<<<<<< - * - * data += strides[0] - */ - __pyx_memoryview_refcount_objects_in_slice(__pyx_v_data, (__pyx_v_shape + 1), (__pyx_v_strides + 1), (__pyx_v_ndim - 1), __pyx_v_inc); - } - __pyx_L5:; - - /* "View.MemoryView":1393 - * ndim - 1, inc) - * - * data += strides[0] # <<<<<<<<<<<<<< - * - * - */ - __pyx_v_data = (__pyx_v_data + (__pyx_v_strides[0])); - } - - /* "View.MemoryView":1379 - * - * @cname('__pyx_memoryview_refcount_objects_in_slice') - * cdef void refcount_objects_in_slice(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< - * Py_ssize_t *strides, int ndim, bint inc): - * cdef Py_ssize_t i - */ - - /* function exit code */ - __Pyx_RefNannyFinishContext(); -} - -/* "View.MemoryView":1399 - * - * @cname('__pyx_memoryview_slice_assign_scalar') - * cdef void slice_assign_scalar(__Pyx_memviewslice *dst, int ndim, # <<<<<<<<<<<<<< - * size_t itemsize, void *item, - * bint dtype_is_object) nogil: - */ - -static void __pyx_memoryview_slice_assign_scalar(__Pyx_memviewslice *__pyx_v_dst, int __pyx_v_ndim, size_t __pyx_v_itemsize, void *__pyx_v_item, int __pyx_v_dtype_is_object) { - - /* "View.MemoryView":1402 - * size_t itemsize, void *item, - * bint dtype_is_object) nogil: - * refcount_copying(dst, dtype_is_object, ndim, False) # <<<<<<<<<<<<<< - * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, - * itemsize, item) - */ - __pyx_memoryview_refcount_copying(__pyx_v_dst, __pyx_v_dtype_is_object, __pyx_v_ndim, 0); - - /* "View.MemoryView":1403 - * bint dtype_is_object) nogil: - * refcount_copying(dst, dtype_is_object, ndim, False) - * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, # <<<<<<<<<<<<<< - * itemsize, item) - * refcount_copying(dst, dtype_is_object, ndim, True) - */ - __pyx_memoryview__slice_assign_scalar(__pyx_v_dst->data, __pyx_v_dst->shape, __pyx_v_dst->strides, __pyx_v_ndim, __pyx_v_itemsize, __pyx_v_item); - - /* "View.MemoryView":1405 - * _slice_assign_scalar(dst.data, dst.shape, dst.strides, ndim, - * itemsize, item) - * refcount_copying(dst, dtype_is_object, ndim, True) # <<<<<<<<<<<<<< - * - * - */ - __pyx_memoryview_refcount_copying(__pyx_v_dst, __pyx_v_dtype_is_object, __pyx_v_ndim, 1); - - /* "View.MemoryView":1399 - * - * @cname('__pyx_memoryview_slice_assign_scalar') - * cdef void slice_assign_scalar(__Pyx_memviewslice *dst, int ndim, # <<<<<<<<<<<<<< - * size_t itemsize, void *item, - * bint dtype_is_object) nogil: - */ - - /* function exit code */ -} - -/* "View.MemoryView":1409 - * - * @cname('__pyx_memoryview__slice_assign_scalar') - * cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< - * Py_ssize_t *strides, int ndim, - * size_t itemsize, void *item) nogil: - */ - -static void __pyx_memoryview__slice_assign_scalar(char *__pyx_v_data, Py_ssize_t *__pyx_v_shape, Py_ssize_t *__pyx_v_strides, int __pyx_v_ndim, size_t __pyx_v_itemsize, void *__pyx_v_item) { - CYTHON_UNUSED Py_ssize_t __pyx_v_i; - Py_ssize_t __pyx_v_stride; - Py_ssize_t __pyx_v_extent; - int __pyx_t_1; - Py_ssize_t __pyx_t_2; - Py_ssize_t __pyx_t_3; - Py_ssize_t __pyx_t_4; - - /* "View.MemoryView":1413 - * size_t itemsize, void *item) nogil: - * cdef Py_ssize_t i - * cdef Py_ssize_t stride = strides[0] # <<<<<<<<<<<<<< - * cdef Py_ssize_t extent = shape[0] - * - */ - __pyx_v_stride = (__pyx_v_strides[0]); - - /* "View.MemoryView":1414 - * cdef Py_ssize_t i - * cdef Py_ssize_t stride = strides[0] - * cdef Py_ssize_t extent = shape[0] # <<<<<<<<<<<<<< - * - * if ndim == 1: - */ - __pyx_v_extent = (__pyx_v_shape[0]); - - /* "View.MemoryView":1416 - * cdef Py_ssize_t extent = shape[0] - * - * if ndim == 1: # <<<<<<<<<<<<<< - * for i in range(extent): - * memcpy(data, item, itemsize) - */ - __pyx_t_1 = ((__pyx_v_ndim == 1) != 0); - if (__pyx_t_1) { - - /* "View.MemoryView":1417 - * - * if ndim == 1: - * for i in range(extent): # <<<<<<<<<<<<<< - * memcpy(data, item, itemsize) - * data += stride - */ - __pyx_t_2 = __pyx_v_extent; - __pyx_t_3 = __pyx_t_2; - for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_i = __pyx_t_4; - - /* "View.MemoryView":1418 - * if ndim == 1: - * for i in range(extent): - * memcpy(data, item, itemsize) # <<<<<<<<<<<<<< - * data += stride - * else: - */ - (void)(memcpy(__pyx_v_data, __pyx_v_item, __pyx_v_itemsize)); - - /* "View.MemoryView":1419 - * for i in range(extent): - * memcpy(data, item, itemsize) - * data += stride # <<<<<<<<<<<<<< - * else: - * for i in range(extent): - */ - __pyx_v_data = (__pyx_v_data + __pyx_v_stride); - } - - /* "View.MemoryView":1416 - * cdef Py_ssize_t extent = shape[0] - * - * if ndim == 1: # <<<<<<<<<<<<<< - * for i in range(extent): - * memcpy(data, item, itemsize) - */ - goto __pyx_L3; - } - - /* "View.MemoryView":1421 - * data += stride - * else: - * for i in range(extent): # <<<<<<<<<<<<<< - * _slice_assign_scalar(data, shape + 1, strides + 1, - * ndim - 1, itemsize, item) - */ - /*else*/ { - __pyx_t_2 = __pyx_v_extent; - __pyx_t_3 = __pyx_t_2; - for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_i = __pyx_t_4; - - /* "View.MemoryView":1422 - * else: - * for i in range(extent): - * _slice_assign_scalar(data, shape + 1, strides + 1, # <<<<<<<<<<<<<< - * ndim - 1, itemsize, item) - * data += stride - */ - __pyx_memoryview__slice_assign_scalar(__pyx_v_data, (__pyx_v_shape + 1), (__pyx_v_strides + 1), (__pyx_v_ndim - 1), __pyx_v_itemsize, __pyx_v_item); - - /* "View.MemoryView":1424 - * _slice_assign_scalar(data, shape + 1, strides + 1, - * ndim - 1, itemsize, item) - * data += stride # <<<<<<<<<<<<<< - * - * - */ - __pyx_v_data = (__pyx_v_data + __pyx_v_stride); - } - } - __pyx_L3:; - - /* "View.MemoryView":1409 - * - * @cname('__pyx_memoryview__slice_assign_scalar') - * cdef void _slice_assign_scalar(char *data, Py_ssize_t *shape, # <<<<<<<<<<<<<< - * Py_ssize_t *strides, int ndim, - * size_t itemsize, void *item) nogil: - */ - - /* function exit code */ -} - -/* "(tree fragment)":1 - * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyMethodDef __pyx_mdef_15View_dot_MemoryView_1__pyx_unpickle_Enum = {"__pyx_unpickle_Enum", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum, METH_VARARGS|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_15View_dot_MemoryView_1__pyx_unpickle_Enum(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v___pyx_type = 0; - long __pyx_v___pyx_checksum; - PyObject *__pyx_v___pyx_state = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__pyx_unpickle_Enum (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pyx_type,&__pyx_n_s_pyx_checksum,&__pyx_n_s_pyx_state,0}; - PyObject* values[3] = {0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_type)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_checksum)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_Enum", 1, 3, 3, 1); __PYX_ERR(2, 1, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_pyx_state)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_Enum", 1, 3, 3, 2); __PYX_ERR(2, 1, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__pyx_unpickle_Enum") < 0)) __PYX_ERR(2, 1, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 3) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - } - __pyx_v___pyx_type = values[0]; - __pyx_v___pyx_checksum = __Pyx_PyInt_As_long(values[1]); if (unlikely((__pyx_v___pyx_checksum == (long)-1) && PyErr_Occurred())) __PYX_ERR(2, 1, __pyx_L3_error) - __pyx_v___pyx_state = values[2]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__pyx_unpickle_Enum", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(2, 1, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("View.MemoryView.__pyx_unpickle_Enum", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(__pyx_self, __pyx_v___pyx_type, __pyx_v___pyx_checksum, __pyx_v___pyx_state); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_15View_dot_MemoryView___pyx_unpickle_Enum(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_v___pyx_PickleError = 0; - PyObject *__pyx_v___pyx_result = 0; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__pyx_unpickle_Enum", 0); - - /* "(tree fragment)":4 - * cdef object __pyx_PickleError - * cdef object __pyx_result - * if __pyx_checksum not in (0xb068931, 0x82a3537, 0x6ae9995): # <<<<<<<<<<<<<< - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) - */ - __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_2 = (__Pyx_PySequence_ContainsTF(__pyx_t_1, __pyx_tuple__21, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_3 = (__pyx_t_2 != 0); - if (__pyx_t_3) { - - /* "(tree fragment)":5 - * cdef object __pyx_result - * if __pyx_checksum not in (0xb068931, 0x82a3537, 0x6ae9995): - * from pickle import PickleError as __pyx_PickleError # <<<<<<<<<<<<<< - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) - * __pyx_result = Enum.__new__(__pyx_type) - */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_n_s_PickleError); - __Pyx_GIVEREF(__pyx_n_s_PickleError); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_PickleError); - __pyx_t_4 = __Pyx_Import(__pyx_n_s_pickle, __pyx_t_1, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_4, __pyx_n_s_PickleError); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 5, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_t_1); - __pyx_v___pyx_PickleError = __pyx_t_1; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "(tree fragment)":6 - * if __pyx_checksum not in (0xb068931, 0x82a3537, 0x6ae9995): - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) # <<<<<<<<<<<<<< - * __pyx_result = Enum.__new__(__pyx_type) - * if __pyx_state is not None: - */ - __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_v___pyx_checksum); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = __Pyx_PyString_Format(__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(2, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_INCREF(__pyx_v___pyx_PickleError); - __pyx_t_1 = __pyx_v___pyx_PickleError; __pyx_t_6 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) { - __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_1); - if (likely(__pyx_t_6)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); - __Pyx_INCREF(__pyx_t_6); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_1, function); - } - } - __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 6, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_Raise(__pyx_t_4, 0, 0, 0); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __PYX_ERR(2, 6, __pyx_L1_error) - - /* "(tree fragment)":4 - * cdef object __pyx_PickleError - * cdef object __pyx_result - * if __pyx_checksum not in (0xb068931, 0x82a3537, 0x6ae9995): # <<<<<<<<<<<<<< - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) - */ - } - - /* "(tree fragment)":7 - * from pickle import PickleError as __pyx_PickleError - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) - * __pyx_result = Enum.__new__(__pyx_type) # <<<<<<<<<<<<<< - * if __pyx_state is not None: - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - */ - __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_MemviewEnum_type), __pyx_n_s_new); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_1, function); - } - } - __pyx_t_4 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_v___pyx_type) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v___pyx_type); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 7, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_v___pyx_result = __pyx_t_4; - __pyx_t_4 = 0; - - /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) - * __pyx_result = Enum.__new__(__pyx_type) - * if __pyx_state is not None: # <<<<<<<<<<<<<< - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - * return __pyx_result - */ - __pyx_t_3 = (__pyx_v___pyx_state != Py_None); - __pyx_t_2 = (__pyx_t_3 != 0); - if (__pyx_t_2) { - - /* "(tree fragment)":9 - * __pyx_result = Enum.__new__(__pyx_type) - * if __pyx_state is not None: - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) # <<<<<<<<<<<<<< - * return __pyx_result - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): - */ - if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||((void)PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(2, 9, __pyx_L1_error) - __pyx_t_4 = __pyx_unpickle_Enum__set_state(((struct __pyx_MemviewEnum_obj *)__pyx_v___pyx_result), ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_4)) __PYX_ERR(2, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "(tree fragment)":8 - * raise __pyx_PickleError("Incompatible checksums (0x%x vs (0xb068931, 0x82a3537, 0x6ae9995) = (name))" % __pyx_checksum) - * __pyx_result = Enum.__new__(__pyx_type) - * if __pyx_state is not None: # <<<<<<<<<<<<<< - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - * return __pyx_result - */ - } - - /* "(tree fragment)":10 - * if __pyx_state is not None: - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - * return __pyx_result # <<<<<<<<<<<<<< - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): - * __pyx_result.name = __pyx_state[0] - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v___pyx_result); - __pyx_r = __pyx_v___pyx_result; - goto __pyx_L0; - - /* "(tree fragment)":1 - * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("View.MemoryView.__pyx_unpickle_Enum", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v___pyx_PickleError); - __Pyx_XDECREF(__pyx_v___pyx_result); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "(tree fragment)":11 - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result.name = __pyx_state[0] - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): - */ - -static PyObject *__pyx_unpickle_Enum__set_state(struct __pyx_MemviewEnum_obj *__pyx_v___pyx_result, PyObject *__pyx_v___pyx_state) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - Py_ssize_t __pyx_t_3; - int __pyx_t_4; - int __pyx_t_5; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__pyx_unpickle_Enum__set_state", 0); - - /* "(tree fragment)":12 - * return __pyx_result - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): - * __pyx_result.name = __pyx_state[0] # <<<<<<<<<<<<<< - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): - * __pyx_result.__dict__.update(__pyx_state[1]) - */ - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(2, 12, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 12, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __Pyx_GOTREF(__pyx_v___pyx_result->name); - __Pyx_DECREF(__pyx_v___pyx_result->name); - __pyx_v___pyx_result->name = __pyx_t_1; - __pyx_t_1 = 0; - - /* "(tree fragment)":13 - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): - * __pyx_result.name = __pyx_state[0] - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< - * __pyx_result.__dict__.update(__pyx_state[1]) - */ - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()"); - __PYX_ERR(2, 13, __pyx_L1_error) - } - __pyx_t_3 = PyTuple_GET_SIZE(__pyx_v___pyx_state); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(2, 13, __pyx_L1_error) - __pyx_t_4 = ((__pyx_t_3 > 1) != 0); - if (__pyx_t_4) { - } else { - __pyx_t_2 = __pyx_t_4; - goto __pyx_L4_bool_binop_done; - } - __pyx_t_4 = __Pyx_HasAttr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(2, 13, __pyx_L1_error) - __pyx_t_5 = (__pyx_t_4 != 0); - __pyx_t_2 = __pyx_t_5; - __pyx_L4_bool_binop_done:; - if (__pyx_t_2) { - - /* "(tree fragment)":14 - * __pyx_result.name = __pyx_state[0] - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): - * __pyx_result.__dict__.update(__pyx_state[1]) # <<<<<<<<<<<<<< - */ - __pyx_t_6 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v___pyx_result), __pyx_n_s_dict); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_update); if (unlikely(!__pyx_t_7)) __PYX_ERR(2, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(__pyx_v___pyx_state == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(2, 14, __pyx_L1_error) - } - __pyx_t_6 = __Pyx_GetItemInt_Tuple(__pyx_v___pyx_state, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(2, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_8 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) { - __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7); - if (likely(__pyx_t_8)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_7, function); - } - } - __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_6); - __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0; - __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 14, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":13 - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): - * __pyx_result.name = __pyx_state[0] - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): # <<<<<<<<<<<<<< - * __pyx_result.__dict__.update(__pyx_state[1]) - */ - } - - /* "(tree fragment)":11 - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result.name = __pyx_state[0] - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): - */ - - /* function exit code */ - __pyx_r = Py_None; __Pyx_INCREF(Py_None); - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_AddTraceback("View.MemoryView.__pyx_unpickle_Enum__set_state", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} -static struct __pyx_vtabstruct_array __pyx_vtable_array; - -static PyObject *__pyx_tp_new_array(PyTypeObject *t, PyObject *a, PyObject *k) { - struct __pyx_array_obj *p; - PyObject *o; - if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { - o = (*t->tp_alloc)(t, 0); - } else { - o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); - } - if (unlikely(!o)) return 0; - p = ((struct __pyx_array_obj *)o); - p->__pyx_vtab = __pyx_vtabptr_array; - p->mode = ((PyObject*)Py_None); Py_INCREF(Py_None); - p->_format = ((PyObject*)Py_None); Py_INCREF(Py_None); - if (unlikely(__pyx_array___cinit__(o, a, k) < 0)) goto bad; - return o; - bad: - Py_DECREF(o); o = 0; - return NULL; -} - -static void __pyx_tp_dealloc_array(PyObject *o) { - struct __pyx_array_obj *p = (struct __pyx_array_obj *)o; - #if CYTHON_USE_TP_FINALIZE - if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && (!PyType_IS_GC(Py_TYPE(o)) || !_PyGC_FINALIZED(o))) { - if (PyObject_CallFinalizerFromDealloc(o)) return; - } - #endif - { - PyObject *etype, *eval, *etb; - PyErr_Fetch(&etype, &eval, &etb); - __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); - __pyx_array___dealloc__(o); - __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); - PyErr_Restore(etype, eval, etb); - } - Py_CLEAR(p->mode); - Py_CLEAR(p->_format); - (*Py_TYPE(o)->tp_free)(o); -} -static PyObject *__pyx_sq_item_array(PyObject *o, Py_ssize_t i) { - PyObject *r; - PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0; - r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x); - Py_DECREF(x); - return r; -} - -static int __pyx_mp_ass_subscript_array(PyObject *o, PyObject *i, PyObject *v) { - if (v) { - return __pyx_array___setitem__(o, i, v); - } - else { - PyErr_Format(PyExc_NotImplementedError, - "Subscript deletion not supported by %.200s", Py_TYPE(o)->tp_name); - return -1; - } -} - -static PyObject *__pyx_tp_getattro_array(PyObject *o, PyObject *n) { - PyObject *v = __Pyx_PyObject_GenericGetAttr(o, n); - if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - v = __pyx_array___getattr__(o, n); - } - return v; -} - -static PyObject *__pyx_getprop___pyx_array_memview(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_5array_7memview_1__get__(o); -} - -static PyMethodDef __pyx_methods_array[] = { - {"__getattr__", (PyCFunction)__pyx_array___getattr__, METH_O|METH_COEXIST, 0}, - {"__reduce_cython__", (PyCFunction)__pyx_pw___pyx_array_1__reduce_cython__, METH_NOARGS, 0}, - {"__setstate_cython__", (PyCFunction)__pyx_pw___pyx_array_3__setstate_cython__, METH_O, 0}, - {0, 0, 0, 0} -}; - -static struct PyGetSetDef __pyx_getsets_array[] = { - {(char *)"memview", __pyx_getprop___pyx_array_memview, 0, (char *)0, 0}, - {0, 0, 0, 0, 0} -}; - -static PySequenceMethods __pyx_tp_as_sequence_array = { - __pyx_array___len__, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - __pyx_sq_item_array, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - 0, /*sq_contains*/ - 0, /*sq_inplace_concat*/ - 0, /*sq_inplace_repeat*/ -}; - -static PyMappingMethods __pyx_tp_as_mapping_array = { - __pyx_array___len__, /*mp_length*/ - __pyx_array___getitem__, /*mp_subscript*/ - __pyx_mp_ass_subscript_array, /*mp_ass_subscript*/ -}; - -static PyBufferProcs __pyx_tp_as_buffer_array = { - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getreadbuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getwritebuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getsegcount*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getcharbuffer*/ - #endif - __pyx_array_getbuffer, /*bf_getbuffer*/ - 0, /*bf_releasebuffer*/ -}; - -static PyTypeObject __pyx_type___pyx_array = { - PyVarObject_HEAD_INIT(0, 0) - "pygom.model._tau_leap.array", /*tp_name*/ - sizeof(struct __pyx_array_obj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_array, /*tp_dealloc*/ - #if PY_VERSION_HEX < 0x030800b4 - 0, /*tp_print*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 - 0, /*tp_vectorcall_offset*/ - #endif - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - #if PY_MAJOR_VERSION < 3 - 0, /*tp_compare*/ - #endif - #if PY_MAJOR_VERSION >= 3 - 0, /*tp_as_async*/ - #endif - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - &__pyx_tp_as_sequence_array, /*tp_as_sequence*/ - &__pyx_tp_as_mapping_array, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - __pyx_tp_getattro_array, /*tp_getattro*/ - 0, /*tp_setattro*/ - &__pyx_tp_as_buffer_array, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_array, /*tp_methods*/ - 0, /*tp_members*/ - __pyx_getsets_array, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_array, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - 0, /*tp_version_tag*/ - #if PY_VERSION_HEX >= 0x030400a1 - 0, /*tp_finalize*/ - #endif - #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) - 0, /*tp_vectorcall*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 - 0, /*tp_print*/ - #endif - #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 - 0, /*tp_pypy_flags*/ - #endif -}; - -static PyObject *__pyx_tp_new_Enum(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) { - struct __pyx_MemviewEnum_obj *p; - PyObject *o; - if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { - o = (*t->tp_alloc)(t, 0); - } else { - o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); - } - if (unlikely(!o)) return 0; - p = ((struct __pyx_MemviewEnum_obj *)o); - p->name = Py_None; Py_INCREF(Py_None); - return o; -} - -static void __pyx_tp_dealloc_Enum(PyObject *o) { - struct __pyx_MemviewEnum_obj *p = (struct __pyx_MemviewEnum_obj *)o; - #if CYTHON_USE_TP_FINALIZE - if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { - if (PyObject_CallFinalizerFromDealloc(o)) return; - } - #endif - PyObject_GC_UnTrack(o); - Py_CLEAR(p->name); - (*Py_TYPE(o)->tp_free)(o); -} - -static int __pyx_tp_traverse_Enum(PyObject *o, visitproc v, void *a) { - int e; - struct __pyx_MemviewEnum_obj *p = (struct __pyx_MemviewEnum_obj *)o; - if (p->name) { - e = (*v)(p->name, a); if (e) return e; - } - return 0; -} - -static int __pyx_tp_clear_Enum(PyObject *o) { - PyObject* tmp; - struct __pyx_MemviewEnum_obj *p = (struct __pyx_MemviewEnum_obj *)o; - tmp = ((PyObject*)p->name); - p->name = Py_None; Py_INCREF(Py_None); - Py_XDECREF(tmp); - return 0; -} - -static PyMethodDef __pyx_methods_Enum[] = { - {"__reduce_cython__", (PyCFunction)__pyx_pw___pyx_MemviewEnum_1__reduce_cython__, METH_NOARGS, 0}, - {"__setstate_cython__", (PyCFunction)__pyx_pw___pyx_MemviewEnum_3__setstate_cython__, METH_O, 0}, - {0, 0, 0, 0} -}; - -static PyTypeObject __pyx_type___pyx_MemviewEnum = { - PyVarObject_HEAD_INIT(0, 0) - "pygom.model._tau_leap.Enum", /*tp_name*/ - sizeof(struct __pyx_MemviewEnum_obj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_Enum, /*tp_dealloc*/ - #if PY_VERSION_HEX < 0x030800b4 - 0, /*tp_print*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 - 0, /*tp_vectorcall_offset*/ - #endif - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - #if PY_MAJOR_VERSION < 3 - 0, /*tp_compare*/ - #endif - #if PY_MAJOR_VERSION >= 3 - 0, /*tp_as_async*/ - #endif - __pyx_MemviewEnum___repr__, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - __pyx_tp_traverse_Enum, /*tp_traverse*/ - __pyx_tp_clear_Enum, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_Enum, /*tp_methods*/ - 0, /*tp_members*/ - 0, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - __pyx_MemviewEnum___init__, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_Enum, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - 0, /*tp_version_tag*/ - #if PY_VERSION_HEX >= 0x030400a1 - 0, /*tp_finalize*/ - #endif - #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) - 0, /*tp_vectorcall*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 - 0, /*tp_print*/ - #endif - #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 - 0, /*tp_pypy_flags*/ - #endif -}; -static struct __pyx_vtabstruct_memoryview __pyx_vtable_memoryview; - -static PyObject *__pyx_tp_new_memoryview(PyTypeObject *t, PyObject *a, PyObject *k) { - struct __pyx_memoryview_obj *p; - PyObject *o; - if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) { - o = (*t->tp_alloc)(t, 0); - } else { - o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0); - } - if (unlikely(!o)) return 0; - p = ((struct __pyx_memoryview_obj *)o); - p->__pyx_vtab = __pyx_vtabptr_memoryview; - p->obj = Py_None; Py_INCREF(Py_None); - p->_size = Py_None; Py_INCREF(Py_None); - p->_array_interface = Py_None; Py_INCREF(Py_None); - p->view.obj = NULL; - if (unlikely(__pyx_memoryview___cinit__(o, a, k) < 0)) goto bad; - return o; - bad: - Py_DECREF(o); o = 0; - return NULL; -} - -static void __pyx_tp_dealloc_memoryview(PyObject *o) { - struct __pyx_memoryview_obj *p = (struct __pyx_memoryview_obj *)o; - #if CYTHON_USE_TP_FINALIZE - if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { - if (PyObject_CallFinalizerFromDealloc(o)) return; - } - #endif - PyObject_GC_UnTrack(o); - { - PyObject *etype, *eval, *etb; - PyErr_Fetch(&etype, &eval, &etb); - __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); - __pyx_memoryview___dealloc__(o); - __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); - PyErr_Restore(etype, eval, etb); - } - Py_CLEAR(p->obj); - Py_CLEAR(p->_size); - Py_CLEAR(p->_array_interface); - (*Py_TYPE(o)->tp_free)(o); -} - -static int __pyx_tp_traverse_memoryview(PyObject *o, visitproc v, void *a) { - int e; - struct __pyx_memoryview_obj *p = (struct __pyx_memoryview_obj *)o; - if (p->obj) { - e = (*v)(p->obj, a); if (e) return e; - } - if (p->_size) { - e = (*v)(p->_size, a); if (e) return e; - } - if (p->_array_interface) { - e = (*v)(p->_array_interface, a); if (e) return e; - } - if (p->view.obj) { - e = (*v)(p->view.obj, a); if (e) return e; - } - return 0; -} - -static int __pyx_tp_clear_memoryview(PyObject *o) { - PyObject* tmp; - struct __pyx_memoryview_obj *p = (struct __pyx_memoryview_obj *)o; - tmp = ((PyObject*)p->obj); - p->obj = Py_None; Py_INCREF(Py_None); - Py_XDECREF(tmp); - tmp = ((PyObject*)p->_size); - p->_size = Py_None; Py_INCREF(Py_None); - Py_XDECREF(tmp); - tmp = ((PyObject*)p->_array_interface); - p->_array_interface = Py_None; Py_INCREF(Py_None); - Py_XDECREF(tmp); - Py_CLEAR(p->view.obj); - return 0; -} -static PyObject *__pyx_sq_item_memoryview(PyObject *o, Py_ssize_t i) { - PyObject *r; - PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0; - r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x); - Py_DECREF(x); - return r; -} - -static int __pyx_mp_ass_subscript_memoryview(PyObject *o, PyObject *i, PyObject *v) { - if (v) { - return __pyx_memoryview___setitem__(o, i, v); - } - else { - PyErr_Format(PyExc_NotImplementedError, - "Subscript deletion not supported by %.200s", Py_TYPE(o)->tp_name); - return -1; - } -} - -static PyObject *__pyx_getprop___pyx_memoryview_T(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_1T_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_base(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_4base_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_shape(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_5shape_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_strides(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_7strides_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_suboffsets(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_10suboffsets_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_ndim(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_4ndim_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_itemsize(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_8itemsize_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_nbytes(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_6nbytes_1__get__(o); -} - -static PyObject *__pyx_getprop___pyx_memoryview_size(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_10memoryview_4size_1__get__(o); -} - -static PyMethodDef __pyx_methods_memoryview[] = { - {"is_c_contig", (PyCFunction)__pyx_memoryview_is_c_contig, METH_NOARGS, 0}, - {"is_f_contig", (PyCFunction)__pyx_memoryview_is_f_contig, METH_NOARGS, 0}, - {"copy", (PyCFunction)__pyx_memoryview_copy, METH_NOARGS, 0}, - {"copy_fortran", (PyCFunction)__pyx_memoryview_copy_fortran, METH_NOARGS, 0}, - {"__reduce_cython__", (PyCFunction)__pyx_pw___pyx_memoryview_1__reduce_cython__, METH_NOARGS, 0}, - {"__setstate_cython__", (PyCFunction)__pyx_pw___pyx_memoryview_3__setstate_cython__, METH_O, 0}, - {0, 0, 0, 0} -}; - -static struct PyGetSetDef __pyx_getsets_memoryview[] = { - {(char *)"T", __pyx_getprop___pyx_memoryview_T, 0, (char *)0, 0}, - {(char *)"base", __pyx_getprop___pyx_memoryview_base, 0, (char *)0, 0}, - {(char *)"shape", __pyx_getprop___pyx_memoryview_shape, 0, (char *)0, 0}, - {(char *)"strides", __pyx_getprop___pyx_memoryview_strides, 0, (char *)0, 0}, - {(char *)"suboffsets", __pyx_getprop___pyx_memoryview_suboffsets, 0, (char *)0, 0}, - {(char *)"ndim", __pyx_getprop___pyx_memoryview_ndim, 0, (char *)0, 0}, - {(char *)"itemsize", __pyx_getprop___pyx_memoryview_itemsize, 0, (char *)0, 0}, - {(char *)"nbytes", __pyx_getprop___pyx_memoryview_nbytes, 0, (char *)0, 0}, - {(char *)"size", __pyx_getprop___pyx_memoryview_size, 0, (char *)0, 0}, - {0, 0, 0, 0, 0} -}; - -static PySequenceMethods __pyx_tp_as_sequence_memoryview = { - __pyx_memoryview___len__, /*sq_length*/ - 0, /*sq_concat*/ - 0, /*sq_repeat*/ - __pyx_sq_item_memoryview, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - 0, /*sq_contains*/ - 0, /*sq_inplace_concat*/ - 0, /*sq_inplace_repeat*/ -}; - -static PyMappingMethods __pyx_tp_as_mapping_memoryview = { - __pyx_memoryview___len__, /*mp_length*/ - __pyx_memoryview___getitem__, /*mp_subscript*/ - __pyx_mp_ass_subscript_memoryview, /*mp_ass_subscript*/ -}; - -static PyBufferProcs __pyx_tp_as_buffer_memoryview = { - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getreadbuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getwritebuffer*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getsegcount*/ - #endif - #if PY_MAJOR_VERSION < 3 - 0, /*bf_getcharbuffer*/ - #endif - __pyx_memoryview_getbuffer, /*bf_getbuffer*/ - 0, /*bf_releasebuffer*/ -}; - -static PyTypeObject __pyx_type___pyx_memoryview = { - PyVarObject_HEAD_INIT(0, 0) - "pygom.model._tau_leap.memoryview", /*tp_name*/ - sizeof(struct __pyx_memoryview_obj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc_memoryview, /*tp_dealloc*/ - #if PY_VERSION_HEX < 0x030800b4 - 0, /*tp_print*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 - 0, /*tp_vectorcall_offset*/ - #endif - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - #if PY_MAJOR_VERSION < 3 - 0, /*tp_compare*/ - #endif - #if PY_MAJOR_VERSION >= 3 - 0, /*tp_as_async*/ - #endif - __pyx_memoryview___repr__, /*tp_repr*/ - 0, /*tp_as_number*/ - &__pyx_tp_as_sequence_memoryview, /*tp_as_sequence*/ - &__pyx_tp_as_mapping_memoryview, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - __pyx_memoryview___str__, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - &__pyx_tp_as_buffer_memoryview, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - __pyx_tp_traverse_memoryview, /*tp_traverse*/ - __pyx_tp_clear_memoryview, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods_memoryview, /*tp_methods*/ - 0, /*tp_members*/ - __pyx_getsets_memoryview, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new_memoryview, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - 0, /*tp_version_tag*/ - #if PY_VERSION_HEX >= 0x030400a1 - 0, /*tp_finalize*/ - #endif - #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) - 0, /*tp_vectorcall*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 - 0, /*tp_print*/ - #endif - #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 - 0, /*tp_pypy_flags*/ - #endif -}; -static struct __pyx_vtabstruct__memoryviewslice __pyx_vtable__memoryviewslice; - -static PyObject *__pyx_tp_new__memoryviewslice(PyTypeObject *t, PyObject *a, PyObject *k) { - struct __pyx_memoryviewslice_obj *p; - PyObject *o = __pyx_tp_new_memoryview(t, a, k); - if (unlikely(!o)) return 0; - p = ((struct __pyx_memoryviewslice_obj *)o); - p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_memoryview*)__pyx_vtabptr__memoryviewslice; - p->from_object = Py_None; Py_INCREF(Py_None); - p->from_slice.memview = NULL; - return o; -} - -static void __pyx_tp_dealloc__memoryviewslice(PyObject *o) { - struct __pyx_memoryviewslice_obj *p = (struct __pyx_memoryviewslice_obj *)o; - #if CYTHON_USE_TP_FINALIZE - if (unlikely(PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE) && Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) { - if (PyObject_CallFinalizerFromDealloc(o)) return; - } - #endif - PyObject_GC_UnTrack(o); - { - PyObject *etype, *eval, *etb; - PyErr_Fetch(&etype, &eval, &etb); - __Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1); - __pyx_memoryviewslice___dealloc__(o); - __Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1); - PyErr_Restore(etype, eval, etb); - } - Py_CLEAR(p->from_object); - PyObject_GC_Track(o); - __pyx_tp_dealloc_memoryview(o); -} - -static int __pyx_tp_traverse__memoryviewslice(PyObject *o, visitproc v, void *a) { - int e; - struct __pyx_memoryviewslice_obj *p = (struct __pyx_memoryviewslice_obj *)o; - e = __pyx_tp_traverse_memoryview(o, v, a); if (e) return e; - if (p->from_object) { - e = (*v)(p->from_object, a); if (e) return e; - } - return 0; -} - -static int __pyx_tp_clear__memoryviewslice(PyObject *o) { - PyObject* tmp; - struct __pyx_memoryviewslice_obj *p = (struct __pyx_memoryviewslice_obj *)o; - __pyx_tp_clear_memoryview(o); - tmp = ((PyObject*)p->from_object); - p->from_object = Py_None; Py_INCREF(Py_None); - Py_XDECREF(tmp); - __PYX_XDEC_MEMVIEW(&p->from_slice, 1); - return 0; -} - -static PyObject *__pyx_getprop___pyx_memoryviewslice_base(PyObject *o, CYTHON_UNUSED void *x) { - return __pyx_pw_15View_dot_MemoryView_16_memoryviewslice_4base_1__get__(o); -} - -static PyMethodDef __pyx_methods__memoryviewslice[] = { - {"__reduce_cython__", (PyCFunction)__pyx_pw___pyx_memoryviewslice_1__reduce_cython__, METH_NOARGS, 0}, - {"__setstate_cython__", (PyCFunction)__pyx_pw___pyx_memoryviewslice_3__setstate_cython__, METH_O, 0}, - {0, 0, 0, 0} -}; - -static struct PyGetSetDef __pyx_getsets__memoryviewslice[] = { - {(char *)"base", __pyx_getprop___pyx_memoryviewslice_base, 0, (char *)0, 0}, - {0, 0, 0, 0, 0} -}; - -static PyTypeObject __pyx_type___pyx_memoryviewslice = { - PyVarObject_HEAD_INIT(0, 0) - "pygom.model._tau_leap._memoryviewslice", /*tp_name*/ - sizeof(struct __pyx_memoryviewslice_obj), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - __pyx_tp_dealloc__memoryviewslice, /*tp_dealloc*/ - #if PY_VERSION_HEX < 0x030800b4 - 0, /*tp_print*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 - 0, /*tp_vectorcall_offset*/ - #endif - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - #if PY_MAJOR_VERSION < 3 - 0, /*tp_compare*/ - #endif - #if PY_MAJOR_VERSION >= 3 - 0, /*tp_as_async*/ - #endif - #if CYTHON_COMPILING_IN_PYPY - __pyx_memoryview___repr__, /*tp_repr*/ - #else - 0, /*tp_repr*/ - #endif - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - #if CYTHON_COMPILING_IN_PYPY - __pyx_memoryview___str__, /*tp_str*/ - #else - 0, /*tp_str*/ - #endif - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - "Internal class for passing memoryview slices to Python", /*tp_doc*/ - __pyx_tp_traverse__memoryviewslice, /*tp_traverse*/ - __pyx_tp_clear__memoryviewslice, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - __pyx_methods__memoryviewslice, /*tp_methods*/ - 0, /*tp_members*/ - __pyx_getsets__memoryviewslice, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - 0, /*tp_init*/ - 0, /*tp_alloc*/ - __pyx_tp_new__memoryviewslice, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ - 0, /*tp_bases*/ - 0, /*tp_mro*/ - 0, /*tp_cache*/ - 0, /*tp_subclasses*/ - 0, /*tp_weaklist*/ - 0, /*tp_del*/ - 0, /*tp_version_tag*/ - #if PY_VERSION_HEX >= 0x030400a1 - 0, /*tp_finalize*/ - #endif - #if PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800) - 0, /*tp_vectorcall*/ - #endif - #if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 - 0, /*tp_print*/ - #endif - #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 - 0, /*tp_pypy_flags*/ - #endif -}; - -static PyMethodDef __pyx_methods[] = { - {0, 0, 0, 0} -}; - -#if PY_MAJOR_VERSION >= 3 -#if CYTHON_PEP489_MULTI_PHASE_INIT -static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ -static int __pyx_pymod_exec__tau_leap(PyObject* module); /*proto*/ -static PyModuleDef_Slot __pyx_moduledef_slots[] = { - {Py_mod_create, (void*)__pyx_pymod_create}, - {Py_mod_exec, (void*)__pyx_pymod_exec__tau_leap}, - {0, NULL} -}; -#endif - -static struct PyModuleDef __pyx_moduledef = { - PyModuleDef_HEAD_INIT, - "_tau_leap", - 0, /* m_doc */ - #if CYTHON_PEP489_MULTI_PHASE_INIT - 0, /* m_size */ - #else - -1, /* m_size */ - #endif - __pyx_methods /* m_methods */, - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_moduledef_slots, /* m_slots */ - #else - NULL, /* m_reload */ - #endif - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; -#endif -#ifndef CYTHON_SMALL_CODE -#if defined(__clang__) - #define CYTHON_SMALL_CODE -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - #define CYTHON_SMALL_CODE __attribute__((cold)) -#else - #define CYTHON_SMALL_CODE -#endif -#endif - -static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_n_s_ASCII, __pyx_k_ASCII, sizeof(__pyx_k_ASCII), 0, 0, 1, 1}, - {&__pyx_kp_s_Buffer_view_does_not_expose_stri, __pyx_k_Buffer_view_does_not_expose_stri, sizeof(__pyx_k_Buffer_view_does_not_expose_stri), 0, 0, 1, 0}, - {&__pyx_kp_s_Can_only_create_a_buffer_that_is, __pyx_k_Can_only_create_a_buffer_that_is, sizeof(__pyx_k_Can_only_create_a_buffer_that_is), 0, 0, 1, 0}, - {&__pyx_kp_s_Cannot_assign_to_read_only_memor, __pyx_k_Cannot_assign_to_read_only_memor, sizeof(__pyx_k_Cannot_assign_to_read_only_memor), 0, 0, 1, 0}, - {&__pyx_kp_s_Cannot_create_writable_memory_vi, __pyx_k_Cannot_create_writable_memory_vi, sizeof(__pyx_k_Cannot_create_writable_memory_vi), 0, 0, 1, 0}, - {&__pyx_kp_s_Cannot_index_with_type_s, __pyx_k_Cannot_index_with_type_s, sizeof(__pyx_k_Cannot_index_with_type_s), 0, 0, 1, 0}, - {&__pyx_n_s_Ellipsis, __pyx_k_Ellipsis, sizeof(__pyx_k_Ellipsis), 0, 0, 1, 1}, - {&__pyx_kp_s_Empty_shape_tuple_for_cython_arr, __pyx_k_Empty_shape_tuple_for_cython_arr, sizeof(__pyx_k_Empty_shape_tuple_for_cython_arr), 0, 0, 1, 0}, - {&__pyx_n_s_ImportError, __pyx_k_ImportError, sizeof(__pyx_k_ImportError), 0, 0, 1, 1}, - {&__pyx_kp_s_Incompatible_checksums_0x_x_vs_0, __pyx_k_Incompatible_checksums_0x_x_vs_0, sizeof(__pyx_k_Incompatible_checksums_0x_x_vs_0), 0, 0, 1, 0}, - {&__pyx_n_s_IndexError, __pyx_k_IndexError, sizeof(__pyx_k_IndexError), 0, 0, 1, 1}, - {&__pyx_kp_s_Indirect_dimensions_not_supporte, __pyx_k_Indirect_dimensions_not_supporte, sizeof(__pyx_k_Indirect_dimensions_not_supporte), 0, 0, 1, 0}, - {&__pyx_kp_s_Invalid_mode_expected_c_or_fortr, __pyx_k_Invalid_mode_expected_c_or_fortr, sizeof(__pyx_k_Invalid_mode_expected_c_or_fortr), 0, 0, 1, 0}, - {&__pyx_kp_s_Invalid_shape_in_axis_d_d, __pyx_k_Invalid_shape_in_axis_d_d, sizeof(__pyx_k_Invalid_shape_in_axis_d_d), 0, 0, 1, 0}, - {&__pyx_n_s_MemoryError, __pyx_k_MemoryError, sizeof(__pyx_k_MemoryError), 0, 0, 1, 1}, - {&__pyx_kp_s_MemoryView_of_r_at_0x_x, __pyx_k_MemoryView_of_r_at_0x_x, sizeof(__pyx_k_MemoryView_of_r_at_0x_x), 0, 0, 1, 0}, - {&__pyx_kp_s_MemoryView_of_r_object, __pyx_k_MemoryView_of_r_object, sizeof(__pyx_k_MemoryView_of_r_object), 0, 0, 1, 0}, - {&__pyx_n_b_O, __pyx_k_O, sizeof(__pyx_k_O), 0, 0, 0, 1}, - {&__pyx_kp_s_Out_of_bounds_on_buffer_access_a, __pyx_k_Out_of_bounds_on_buffer_access_a, sizeof(__pyx_k_Out_of_bounds_on_buffer_access_a), 0, 0, 1, 0}, - {&__pyx_n_s_PickleError, __pyx_k_PickleError, sizeof(__pyx_k_PickleError), 0, 0, 1, 1}, - {&__pyx_n_s_TypeError, __pyx_k_TypeError, sizeof(__pyx_k_TypeError), 0, 0, 1, 1}, - {&__pyx_kp_s_Unable_to_convert_item_to_object, __pyx_k_Unable_to_convert_item_to_object, sizeof(__pyx_k_Unable_to_convert_item_to_object), 0, 0, 1, 0}, - {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1}, - {&__pyx_n_s_View_MemoryView, __pyx_k_View_MemoryView, sizeof(__pyx_k_View_MemoryView), 0, 0, 1, 1}, - {&__pyx_n_s_allocate_buffer, __pyx_k_allocate_buffer, sizeof(__pyx_k_allocate_buffer), 0, 0, 1, 1}, - {&__pyx_n_s_base, __pyx_k_base, sizeof(__pyx_k_base), 0, 0, 1, 1}, - {&__pyx_n_s_c, __pyx_k_c, sizeof(__pyx_k_c), 0, 0, 1, 1}, - {&__pyx_n_u_c, __pyx_k_c, sizeof(__pyx_k_c), 0, 1, 0, 1}, - {&__pyx_n_s_cdf_val, __pyx_k_cdf_val, sizeof(__pyx_k_cdf_val), 0, 0, 1, 1}, - {&__pyx_n_s_class, __pyx_k_class, sizeof(__pyx_k_class), 0, 0, 1, 1}, - {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, - {&__pyx_kp_s_contiguous_and_direct, __pyx_k_contiguous_and_direct, sizeof(__pyx_k_contiguous_and_direct), 0, 0, 1, 0}, - {&__pyx_kp_s_contiguous_and_indirect, __pyx_k_contiguous_and_indirect, sizeof(__pyx_k_contiguous_and_indirect), 0, 0, 1, 0}, - {&__pyx_n_s_count, __pyx_k_count, sizeof(__pyx_k_count), 0, 0, 1, 1}, - {&__pyx_n_s_cy_test_tau_leap_safety, __pyx_k_cy_test_tau_leap_safety, sizeof(__pyx_k_cy_test_tau_leap_safety), 0, 0, 1, 1}, - {&__pyx_n_s_dict, __pyx_k_dict, sizeof(__pyx_k_dict), 0, 0, 1, 1}, - {&__pyx_n_s_dtype_is_object, __pyx_k_dtype_is_object, sizeof(__pyx_k_dtype_is_object), 0, 0, 1, 1}, - {&__pyx_n_s_encode, __pyx_k_encode, sizeof(__pyx_k_encode), 0, 0, 1, 1}, - {&__pyx_n_s_enumerate, __pyx_k_enumerate, sizeof(__pyx_k_enumerate), 0, 0, 1, 1}, - {&__pyx_n_s_epsilon, __pyx_k_epsilon, sizeof(__pyx_k_epsilon), 0, 0, 1, 1}, - {&__pyx_n_s_error, __pyx_k_error, sizeof(__pyx_k_error), 0, 0, 1, 1}, - {&__pyx_n_s_flags, __pyx_k_flags, sizeof(__pyx_k_flags), 0, 0, 1, 1}, - {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1}, - {&__pyx_n_s_fortran, __pyx_k_fortran, sizeof(__pyx_k_fortran), 0, 0, 1, 1}, - {&__pyx_n_u_fortran, __pyx_k_fortran, sizeof(__pyx_k_fortran), 0, 1, 0, 1}, - {&__pyx_n_s_getstate, __pyx_k_getstate, sizeof(__pyx_k_getstate), 0, 0, 1, 1}, - {&__pyx_kp_s_got_differing_extents_in_dimensi, __pyx_k_got_differing_extents_in_dimensi, sizeof(__pyx_k_got_differing_extents_in_dimensi), 0, 0, 1, 0}, - {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1}, - {&__pyx_n_s_id, __pyx_k_id, sizeof(__pyx_k_id), 0, 0, 1, 1}, - {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1}, - {&__pyx_n_s_itemsize, __pyx_k_itemsize, sizeof(__pyx_k_itemsize), 0, 0, 1, 1}, - {&__pyx_kp_s_itemsize_0_for_cython_array, __pyx_k_itemsize_0_for_cython_array, sizeof(__pyx_k_itemsize_0_for_cython_array), 0, 0, 1, 0}, - {&__pyx_n_s_j, __pyx_k_j, sizeof(__pyx_k_j), 0, 0, 1, 1}, - {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, - {&__pyx_n_s_max_cdf, __pyx_k_max_cdf, sizeof(__pyx_k_max_cdf), 0, 0, 1, 1}, - {&__pyx_n_s_memview, __pyx_k_memview, sizeof(__pyx_k_memview), 0, 0, 1, 1}, - {&__pyx_n_s_mode, __pyx_k_mode, sizeof(__pyx_k_mode), 0, 0, 1, 1}, - {&__pyx_n_s_mu, __pyx_k_mu, sizeof(__pyx_k_mu), 0, 0, 1, 1}, - {&__pyx_n_s_n_rates, __pyx_k_n_rates, sizeof(__pyx_k_n_rates), 0, 0, 1, 1}, - {&__pyx_n_s_n_reactants, __pyx_k_n_reactants, sizeof(__pyx_k_n_reactants), 0, 0, 1, 1}, - {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, - {&__pyx_n_s_name_2, __pyx_k_name_2, sizeof(__pyx_k_name_2), 0, 0, 1, 1}, - {&__pyx_n_s_ndim, __pyx_k_ndim, sizeof(__pyx_k_ndim), 0, 0, 1, 1}, - {&__pyx_n_s_new, __pyx_k_new, sizeof(__pyx_k_new), 0, 0, 1, 1}, - {&__pyx_n_s_new_cdf, __pyx_k_new_cdf, sizeof(__pyx_k_new_cdf), 0, 0, 1, 1}, - {&__pyx_kp_s_no_default___reduce___due_to_non, __pyx_k_no_default___reduce___due_to_non, sizeof(__pyx_k_no_default___reduce___due_to_non), 0, 0, 1, 0}, - {&__pyx_n_s_np, __pyx_k_np, sizeof(__pyx_k_np), 0, 0, 1, 1}, - {&__pyx_n_s_numpy, __pyx_k_numpy, sizeof(__pyx_k_numpy), 0, 0, 1, 1}, - {&__pyx_kp_s_numpy_core_multiarray_failed_to, __pyx_k_numpy_core_multiarray_failed_to, sizeof(__pyx_k_numpy_core_multiarray_failed_to), 0, 0, 1, 0}, - {&__pyx_kp_s_numpy_core_umath_failed_to_impor, __pyx_k_numpy_core_umath_failed_to_impor, sizeof(__pyx_k_numpy_core_umath_failed_to_impor), 0, 0, 1, 0}, - {&__pyx_n_s_obj, __pyx_k_obj, sizeof(__pyx_k_obj), 0, 0, 1, 1}, - {&__pyx_n_s_pack, __pyx_k_pack, sizeof(__pyx_k_pack), 0, 0, 1, 1}, - {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1}, - {&__pyx_n_s_pygom_model__tau_leap, __pyx_k_pygom_model__tau_leap, sizeof(__pyx_k_pygom_model__tau_leap), 0, 0, 1, 1}, - {&__pyx_kp_s_pygom_model__tau_leap_pyx, __pyx_k_pygom_model__tau_leap_pyx, sizeof(__pyx_k_pygom_model__tau_leap_pyx), 0, 0, 1, 0}, - {&__pyx_n_s_pyx_PickleError, __pyx_k_pyx_PickleError, sizeof(__pyx_k_pyx_PickleError), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_checksum, __pyx_k_pyx_checksum, sizeof(__pyx_k_pyx_checksum), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_getbuffer, __pyx_k_pyx_getbuffer, sizeof(__pyx_k_pyx_getbuffer), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_result, __pyx_k_pyx_result, sizeof(__pyx_k_pyx_result), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_state, __pyx_k_pyx_state, sizeof(__pyx_k_pyx_state), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_type, __pyx_k_pyx_type, sizeof(__pyx_k_pyx_type), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_unpickle_Enum, __pyx_k_pyx_unpickle_Enum, sizeof(__pyx_k_pyx_unpickle_Enum), 0, 0, 1, 1}, - {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1}, - {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, - {&__pyx_n_s_rates, __pyx_k_rates, sizeof(__pyx_k_rates), 0, 0, 1, 1}, - {&__pyx_n_s_rates_view, __pyx_k_rates_view, sizeof(__pyx_k_rates_view), 0, 0, 1, 1}, - {&__pyx_n_s_reactant_mat, __pyx_k_reactant_mat, sizeof(__pyx_k_reactant_mat), 0, 0, 1, 1}, - {&__pyx_n_s_reactant_mat_view, __pyx_k_reactant_mat_view, sizeof(__pyx_k_reactant_mat_view), 0, 0, 1, 1}, - {&__pyx_n_s_reduce, __pyx_k_reduce, sizeof(__pyx_k_reduce), 0, 0, 1, 1}, - {&__pyx_n_s_reduce_cython, __pyx_k_reduce_cython, sizeof(__pyx_k_reduce_cython), 0, 0, 1, 1}, - {&__pyx_n_s_reduce_ex, __pyx_k_reduce_ex, sizeof(__pyx_k_reduce_ex), 0, 0, 1, 1}, - {&__pyx_n_s_safe, __pyx_k_safe, sizeof(__pyx_k_safe), 0, 0, 1, 1}, - {&__pyx_n_s_setstate, __pyx_k_setstate, sizeof(__pyx_k_setstate), 0, 0, 1, 1}, - {&__pyx_n_s_setstate_cython, __pyx_k_setstate_cython, sizeof(__pyx_k_setstate_cython), 0, 0, 1, 1}, - {&__pyx_n_s_shape, __pyx_k_shape, sizeof(__pyx_k_shape), 0, 0, 1, 1}, - {&__pyx_n_s_size, __pyx_k_size, sizeof(__pyx_k_size), 0, 0, 1, 1}, - {&__pyx_n_s_start, __pyx_k_start, sizeof(__pyx_k_start), 0, 0, 1, 1}, - {&__pyx_n_s_step, __pyx_k_step, sizeof(__pyx_k_step), 0, 0, 1, 1}, - {&__pyx_n_s_stop, __pyx_k_stop, sizeof(__pyx_k_stop), 0, 0, 1, 1}, - {&__pyx_kp_s_strided_and_direct, __pyx_k_strided_and_direct, sizeof(__pyx_k_strided_and_direct), 0, 0, 1, 0}, - {&__pyx_kp_s_strided_and_direct_or_indirect, __pyx_k_strided_and_direct_or_indirect, sizeof(__pyx_k_strided_and_direct_or_indirect), 0, 0, 1, 0}, - {&__pyx_kp_s_strided_and_indirect, __pyx_k_strided_and_indirect, sizeof(__pyx_k_strided_and_indirect), 0, 0, 1, 0}, - {&__pyx_kp_s_stringsource, __pyx_k_stringsource, sizeof(__pyx_k_stringsource), 0, 0, 1, 0}, - {&__pyx_n_s_struct, __pyx_k_struct, sizeof(__pyx_k_struct), 0, 0, 1, 1}, - {&__pyx_n_s_sum, __pyx_k_sum, sizeof(__pyx_k_sum), 0, 0, 1, 1}, - {&__pyx_n_s_tau_scale, __pyx_k_tau_scale, sizeof(__pyx_k_tau_scale), 0, 0, 1, 1}, - {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, - {&__pyx_n_s_total_rate, __pyx_k_total_rate, sizeof(__pyx_k_total_rate), 0, 0, 1, 1}, - {&__pyx_kp_s_unable_to_allocate_array_data, __pyx_k_unable_to_allocate_array_data, sizeof(__pyx_k_unable_to_allocate_array_data), 0, 0, 1, 0}, - {&__pyx_kp_s_unable_to_allocate_shape_and_str, __pyx_k_unable_to_allocate_shape_and_str, sizeof(__pyx_k_unable_to_allocate_shape_and_str), 0, 0, 1, 0}, - {&__pyx_n_s_unpack, __pyx_k_unpack, sizeof(__pyx_k_unpack), 0, 0, 1, 1}, - {&__pyx_n_s_update, __pyx_k_update, sizeof(__pyx_k_update), 0, 0, 1, 1}, - {&__pyx_n_s_x, __pyx_k_x, sizeof(__pyx_k_x), 0, 0, 1, 1}, - {&__pyx_n_s_x_view, __pyx_k_x_view, sizeof(__pyx_k_x_view), 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0} -}; -static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 35, __pyx_L1_error) - __pyx_builtin_ImportError = __Pyx_GetBuiltinName(__pyx_n_s_ImportError); if (!__pyx_builtin_ImportError) __PYX_ERR(1, 944, __pyx_L1_error) - __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) __PYX_ERR(2, 134, __pyx_L1_error) - __pyx_builtin_MemoryError = __Pyx_GetBuiltinName(__pyx_n_s_MemoryError); if (!__pyx_builtin_MemoryError) __PYX_ERR(2, 149, __pyx_L1_error) - __pyx_builtin_enumerate = __Pyx_GetBuiltinName(__pyx_n_s_enumerate); if (!__pyx_builtin_enumerate) __PYX_ERR(2, 152, __pyx_L1_error) - __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) __PYX_ERR(2, 2, __pyx_L1_error) - __pyx_builtin_Ellipsis = __Pyx_GetBuiltinName(__pyx_n_s_Ellipsis); if (!__pyx_builtin_Ellipsis) __PYX_ERR(2, 406, __pyx_L1_error) - __pyx_builtin_id = __Pyx_GetBuiltinName(__pyx_n_s_id); if (!__pyx_builtin_id) __PYX_ERR(2, 615, __pyx_L1_error) - __pyx_builtin_IndexError = __Pyx_GetBuiltinName(__pyx_n_s_IndexError); if (!__pyx_builtin_IndexError) __PYX_ERR(2, 834, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":944 - * __pyx_import_array() - * except Exception: - * raise ImportError("numpy.core.multiarray failed to import") # <<<<<<<<<<<<<< - * - * cdef inline int import_umath() except -1: - */ - __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_numpy_core_multiarray_failed_to); if (unlikely(!__pyx_tuple_)) __PYX_ERR(1, 944, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple_); - __Pyx_GIVEREF(__pyx_tuple_); - - /* "../../anaconda3/envs/pygom_test_3.10/lib/python3.10/site-packages/numpy/__init__.pxd":950 - * _import_umath() - * except Exception: - * raise ImportError("numpy.core.umath failed to import") # <<<<<<<<<<<<<< - * - * cdef inline int import_ufunc() except -1: - */ - __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_numpy_core_umath_failed_to_impor); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(1, 950, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__2); - __Pyx_GIVEREF(__pyx_tuple__2); - - /* "View.MemoryView":134 - * - * if not self.ndim: - * raise ValueError("Empty shape tuple for cython.array") # <<<<<<<<<<<<<< - * - * if itemsize <= 0: - */ - __pyx_tuple__3 = PyTuple_Pack(1, __pyx_kp_s_Empty_shape_tuple_for_cython_arr); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(2, 134, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__3); - __Pyx_GIVEREF(__pyx_tuple__3); - - /* "View.MemoryView":137 - * - * if itemsize <= 0: - * raise ValueError("itemsize <= 0 for cython.array") # <<<<<<<<<<<<<< - * - * if not isinstance(format, bytes): - */ - __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_s_itemsize_0_for_cython_array); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(2, 137, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__4); - __Pyx_GIVEREF(__pyx_tuple__4); - - /* "View.MemoryView":149 - * - * if not self._shape: - * raise MemoryError("unable to allocate shape and strides.") # <<<<<<<<<<<<<< - * - * - */ - __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_unable_to_allocate_shape_and_str); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(2, 149, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__5); - __Pyx_GIVEREF(__pyx_tuple__5); - - /* "View.MemoryView":177 - * self.data = malloc(self.len) - * if not self.data: - * raise MemoryError("unable to allocate array data.") # <<<<<<<<<<<<<< - * - * if self.dtype_is_object: - */ - __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_s_unable_to_allocate_array_data); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(2, 177, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__6); - __Pyx_GIVEREF(__pyx_tuple__6); - - /* "View.MemoryView":193 - * bufmode = PyBUF_F_CONTIGUOUS | PyBUF_ANY_CONTIGUOUS - * if not (flags & bufmode): - * raise ValueError("Can only create a buffer that is contiguous in memory.") # <<<<<<<<<<<<<< - * info.buf = self.data - * info.len = self.len - */ - __pyx_tuple__7 = PyTuple_Pack(1, __pyx_kp_s_Can_only_create_a_buffer_that_is); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(2, 193, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__7); - __Pyx_GIVEREF(__pyx_tuple__7); - - /* "(tree fragment)":2 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - __pyx_tuple__8 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(2, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__8); - __Pyx_GIVEREF(__pyx_tuple__8); - - /* "(tree fragment)":4 - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - */ - __pyx_tuple__9 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__9); - __Pyx_GIVEREF(__pyx_tuple__9); - - /* "View.MemoryView":420 - * def __setitem__(memoryview self, object index, object value): - * if self.view.readonly: - * raise TypeError("Cannot assign to read-only memoryview") # <<<<<<<<<<<<<< - * - * have_slices, index = _unellipsify(index, self.view.ndim) - */ - __pyx_tuple__10 = PyTuple_Pack(1, __pyx_kp_s_Cannot_assign_to_read_only_memor); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(2, 420, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__10); - __Pyx_GIVEREF(__pyx_tuple__10); - - /* "View.MemoryView":497 - * result = struct.unpack(self.view.format, bytesitem) - * except struct.error: - * raise ValueError("Unable to convert item to object") # <<<<<<<<<<<<<< - * else: - * if len(self.view.format) == 1: - */ - __pyx_tuple__11 = PyTuple_Pack(1, __pyx_kp_s_Unable_to_convert_item_to_object); if (unlikely(!__pyx_tuple__11)) __PYX_ERR(2, 497, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__11); - __Pyx_GIVEREF(__pyx_tuple__11); - - /* "View.MemoryView":522 - * def __getbuffer__(self, Py_buffer *info, int flags): - * if flags & PyBUF_WRITABLE and self.view.readonly: - * raise ValueError("Cannot create writable memory view from read-only memoryview") # <<<<<<<<<<<<<< - * - * if flags & PyBUF_ND: - */ - __pyx_tuple__12 = PyTuple_Pack(1, __pyx_kp_s_Cannot_create_writable_memory_vi); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(2, 522, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__12); - __Pyx_GIVEREF(__pyx_tuple__12); - - /* "View.MemoryView":572 - * if self.view.strides == NULL: - * - * raise ValueError("Buffer view does not expose strides") # <<<<<<<<<<<<<< - * - * return tuple([stride for stride in self.view.strides[:self.view.ndim]]) - */ - __pyx_tuple__13 = PyTuple_Pack(1, __pyx_kp_s_Buffer_view_does_not_expose_stri); if (unlikely(!__pyx_tuple__13)) __PYX_ERR(2, 572, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__13); - __Pyx_GIVEREF(__pyx_tuple__13); - - /* "View.MemoryView":579 - * def suboffsets(self): - * if self.view.suboffsets == NULL: - * return (-1,) * self.view.ndim # <<<<<<<<<<<<<< - * - * return tuple([suboffset for suboffset in self.view.suboffsets[:self.view.ndim]]) - */ - __pyx_tuple__14 = PyTuple_New(1); if (unlikely(!__pyx_tuple__14)) __PYX_ERR(2, 579, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__14); - __Pyx_INCREF(__pyx_int_neg_1); - __Pyx_GIVEREF(__pyx_int_neg_1); - PyTuple_SET_ITEM(__pyx_tuple__14, 0, __pyx_int_neg_1); - __Pyx_GIVEREF(__pyx_tuple__14); - - /* "(tree fragment)":2 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - __pyx_tuple__15 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(2, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__15); - __Pyx_GIVEREF(__pyx_tuple__15); - - /* "(tree fragment)":4 - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - */ - __pyx_tuple__16 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__16); - __Pyx_GIVEREF(__pyx_tuple__16); - - /* "View.MemoryView":684 - * if item is Ellipsis: - * if not seen_ellipsis: - * result.extend([slice(None)] * (ndim - len(tup) + 1)) # <<<<<<<<<<<<<< - * seen_ellipsis = True - * else: - */ - __pyx_slice__17 = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice__17)) __PYX_ERR(2, 684, __pyx_L1_error) - __Pyx_GOTREF(__pyx_slice__17); - __Pyx_GIVEREF(__pyx_slice__17); - - /* "View.MemoryView":705 - * for suboffset in suboffsets[:ndim]: - * if suboffset >= 0: - * raise ValueError("Indirect dimensions not supported") # <<<<<<<<<<<<<< - * - * - */ - __pyx_tuple__18 = PyTuple_Pack(1, __pyx_kp_s_Indirect_dimensions_not_supporte); if (unlikely(!__pyx_tuple__18)) __PYX_ERR(2, 705, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__18); - __Pyx_GIVEREF(__pyx_tuple__18); - - /* "(tree fragment)":2 - * def __reduce_cython__(self): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - */ - __pyx_tuple__19 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(2, 2, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__19); - __Pyx_GIVEREF(__pyx_tuple__19); - - /* "(tree fragment)":4 - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") - * def __setstate_cython__(self, __pyx_state): - * raise TypeError("no default __reduce__ due to non-trivial __cinit__") # <<<<<<<<<<<<<< - */ - __pyx_tuple__20 = PyTuple_Pack(1, __pyx_kp_s_no_default___reduce___due_to_non); if (unlikely(!__pyx_tuple__20)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__20); - __Pyx_GIVEREF(__pyx_tuple__20); - __pyx_tuple__21 = PyTuple_Pack(3, __pyx_int_184977713, __pyx_int_136983863, __pyx_int_112105877); if (unlikely(!__pyx_tuple__21)) __PYX_ERR(2, 4, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__21); - __Pyx_GIVEREF(__pyx_tuple__21); - - /* "pygom/model/_tau_leap.pyx":11 - * @cython.wraparound(False) # Deactivate negative indexing. - * @cython.cdivision(True) # Deactivate the div 0 error checking - * def _cy_test_tau_leap_safety(np.ndarray[np.float64_t] x, # <<<<<<<<<<<<<< - * np.ndarray[np.int64_t, ndim=2] reactant_mat, - * np.ndarray[np.float64_t] rates, - */ - __pyx_tuple__22 = PyTuple_Pack(19, __pyx_n_s_x, __pyx_n_s_reactant_mat, __pyx_n_s_rates, __pyx_n_s_tau_scale, __pyx_n_s_epsilon, __pyx_n_s_rates_view, __pyx_n_s_n_rates, __pyx_n_s_x_view, __pyx_n_s_reactant_mat_view, __pyx_n_s_n_reactants, __pyx_n_s_mu, __pyx_n_s_max_cdf, __pyx_n_s_new_cdf, __pyx_n_s_total_rate, __pyx_n_s_safe, __pyx_n_s_count, __pyx_n_s_cdf_val, __pyx_n_s_i, __pyx_n_s_j); if (unlikely(!__pyx_tuple__22)) __PYX_ERR(0, 11, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__22); - __Pyx_GIVEREF(__pyx_tuple__22); - __pyx_codeobj__23 = (PyObject*)__Pyx_PyCode_New(5, 0, 19, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_pygom_model__tau_leap_pyx, __pyx_n_s_cy_test_tau_leap_safety, 11, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__23)) __PYX_ERR(0, 11, __pyx_L1_error) - - /* "View.MemoryView":287 - * return self.name - * - * cdef generic = Enum("") # <<<<<<<<<<<<<< - * cdef strided = Enum("") # default - * cdef indirect = Enum("") - */ - __pyx_tuple__24 = PyTuple_Pack(1, __pyx_kp_s_strided_and_direct_or_indirect); if (unlikely(!__pyx_tuple__24)) __PYX_ERR(2, 287, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__24); - __Pyx_GIVEREF(__pyx_tuple__24); - - /* "View.MemoryView":288 - * - * cdef generic = Enum("") - * cdef strided = Enum("") # default # <<<<<<<<<<<<<< - * cdef indirect = Enum("") - * - */ - __pyx_tuple__25 = PyTuple_Pack(1, __pyx_kp_s_strided_and_direct); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(2, 288, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__25); - __Pyx_GIVEREF(__pyx_tuple__25); - - /* "View.MemoryView":289 - * cdef generic = Enum("") - * cdef strided = Enum("") # default - * cdef indirect = Enum("") # <<<<<<<<<<<<<< - * - * - */ - __pyx_tuple__26 = PyTuple_Pack(1, __pyx_kp_s_strided_and_indirect); if (unlikely(!__pyx_tuple__26)) __PYX_ERR(2, 289, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__26); - __Pyx_GIVEREF(__pyx_tuple__26); - - /* "View.MemoryView":292 - * - * - * cdef contiguous = Enum("") # <<<<<<<<<<<<<< - * cdef indirect_contiguous = Enum("") - * - */ - __pyx_tuple__27 = PyTuple_Pack(1, __pyx_kp_s_contiguous_and_direct); if (unlikely(!__pyx_tuple__27)) __PYX_ERR(2, 292, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__27); - __Pyx_GIVEREF(__pyx_tuple__27); - - /* "View.MemoryView":293 - * - * cdef contiguous = Enum("") - * cdef indirect_contiguous = Enum("") # <<<<<<<<<<<<<< - * - * - */ - __pyx_tuple__28 = PyTuple_Pack(1, __pyx_kp_s_contiguous_and_indirect); if (unlikely(!__pyx_tuple__28)) __PYX_ERR(2, 293, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__28); - __Pyx_GIVEREF(__pyx_tuple__28); - - /* "(tree fragment)":1 - * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - __pyx_tuple__29 = PyTuple_Pack(5, __pyx_n_s_pyx_type, __pyx_n_s_pyx_checksum, __pyx_n_s_pyx_state, __pyx_n_s_pyx_PickleError, __pyx_n_s_pyx_result); if (unlikely(!__pyx_tuple__29)) __PYX_ERR(2, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__29); - __Pyx_GIVEREF(__pyx_tuple__29); - __pyx_codeobj__30 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__29, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_Enum, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__30)) __PYX_ERR(2, 1, __pyx_L1_error) - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { - if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_112105877 = PyInt_FromLong(112105877L); if (unlikely(!__pyx_int_112105877)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_136983863 = PyInt_FromLong(136983863L); if (unlikely(!__pyx_int_136983863)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_184977713 = PyInt_FromLong(184977713L); if (unlikely(!__pyx_int_184977713)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ - -static int __Pyx_modinit_global_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); - /*--- Global init code ---*/ - generic = Py_None; Py_INCREF(Py_None); - strided = Py_None; Py_INCREF(Py_None); - indirect = Py_None; Py_INCREF(Py_None); - contiguous = Py_None; Py_INCREF(Py_None); - indirect_contiguous = Py_None; Py_INCREF(Py_None); - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); - /*--- Variable export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); - /*--- Function export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_init_code(void) { - __Pyx_RefNannyDeclarations - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); - /*--- Type init code ---*/ - __pyx_vtabptr_array = &__pyx_vtable_array; - __pyx_vtable_array.get_memview = (PyObject *(*)(struct __pyx_array_obj *))__pyx_array_get_memview; - if (PyType_Ready(&__pyx_type___pyx_array) < 0) __PYX_ERR(2, 106, __pyx_L1_error) - #if PY_VERSION_HEX < 0x030800B1 - __pyx_type___pyx_array.tp_print = 0; - #endif - if (__Pyx_SetVtable(__pyx_type___pyx_array.tp_dict, __pyx_vtabptr_array) < 0) __PYX_ERR(2, 106, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_array) < 0) __PYX_ERR(2, 106, __pyx_L1_error) - __pyx_array_type = &__pyx_type___pyx_array; - if (PyType_Ready(&__pyx_type___pyx_MemviewEnum) < 0) __PYX_ERR(2, 280, __pyx_L1_error) - #if PY_VERSION_HEX < 0x030800B1 - __pyx_type___pyx_MemviewEnum.tp_print = 0; - #endif - if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type___pyx_MemviewEnum.tp_dictoffset && __pyx_type___pyx_MemviewEnum.tp_getattro == PyObject_GenericGetAttr)) { - __pyx_type___pyx_MemviewEnum.tp_getattro = __Pyx_PyObject_GenericGetAttr; - } - if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_MemviewEnum) < 0) __PYX_ERR(2, 280, __pyx_L1_error) - __pyx_MemviewEnum_type = &__pyx_type___pyx_MemviewEnum; - __pyx_vtabptr_memoryview = &__pyx_vtable_memoryview; - __pyx_vtable_memoryview.get_item_pointer = (char *(*)(struct __pyx_memoryview_obj *, PyObject *))__pyx_memoryview_get_item_pointer; - __pyx_vtable_memoryview.is_slice = (PyObject *(*)(struct __pyx_memoryview_obj *, PyObject *))__pyx_memoryview_is_slice; - __pyx_vtable_memoryview.setitem_slice_assignment = (PyObject *(*)(struct __pyx_memoryview_obj *, PyObject *, PyObject *))__pyx_memoryview_setitem_slice_assignment; - __pyx_vtable_memoryview.setitem_slice_assign_scalar = (PyObject *(*)(struct __pyx_memoryview_obj *, struct __pyx_memoryview_obj *, PyObject *))__pyx_memoryview_setitem_slice_assign_scalar; - __pyx_vtable_memoryview.setitem_indexed = (PyObject *(*)(struct __pyx_memoryview_obj *, PyObject *, PyObject *))__pyx_memoryview_setitem_indexed; - __pyx_vtable_memoryview.convert_item_to_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *))__pyx_memoryview_convert_item_to_object; - __pyx_vtable_memoryview.assign_item_from_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *, PyObject *))__pyx_memoryview_assign_item_from_object; - if (PyType_Ready(&__pyx_type___pyx_memoryview) < 0) __PYX_ERR(2, 331, __pyx_L1_error) - #if PY_VERSION_HEX < 0x030800B1 - __pyx_type___pyx_memoryview.tp_print = 0; - #endif - if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type___pyx_memoryview.tp_dictoffset && __pyx_type___pyx_memoryview.tp_getattro == PyObject_GenericGetAttr)) { - __pyx_type___pyx_memoryview.tp_getattro = __Pyx_PyObject_GenericGetAttr; - } - if (__Pyx_SetVtable(__pyx_type___pyx_memoryview.tp_dict, __pyx_vtabptr_memoryview) < 0) __PYX_ERR(2, 331, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_memoryview) < 0) __PYX_ERR(2, 331, __pyx_L1_error) - __pyx_memoryview_type = &__pyx_type___pyx_memoryview; - __pyx_vtabptr__memoryviewslice = &__pyx_vtable__memoryviewslice; - __pyx_vtable__memoryviewslice.__pyx_base = *__pyx_vtabptr_memoryview; - __pyx_vtable__memoryviewslice.__pyx_base.convert_item_to_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *))__pyx_memoryviewslice_convert_item_to_object; - __pyx_vtable__memoryviewslice.__pyx_base.assign_item_from_object = (PyObject *(*)(struct __pyx_memoryview_obj *, char *, PyObject *))__pyx_memoryviewslice_assign_item_from_object; - __pyx_type___pyx_memoryviewslice.tp_base = __pyx_memoryview_type; - if (PyType_Ready(&__pyx_type___pyx_memoryviewslice) < 0) __PYX_ERR(2, 967, __pyx_L1_error) - #if PY_VERSION_HEX < 0x030800B1 - __pyx_type___pyx_memoryviewslice.tp_print = 0; - #endif - if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_type___pyx_memoryviewslice.tp_dictoffset && __pyx_type___pyx_memoryviewslice.tp_getattro == PyObject_GenericGetAttr)) { - __pyx_type___pyx_memoryviewslice.tp_getattro = __Pyx_PyObject_GenericGetAttr; - } - if (__Pyx_SetVtable(__pyx_type___pyx_memoryviewslice.tp_dict, __pyx_vtabptr__memoryviewslice) < 0) __PYX_ERR(2, 967, __pyx_L1_error) - if (__Pyx_setup_reduce((PyObject*)&__pyx_type___pyx_memoryviewslice) < 0) __PYX_ERR(2, 967, __pyx_L1_error) - __pyx_memoryviewslice_type = &__pyx_type___pyx_memoryviewslice; - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static int __Pyx_modinit_type_import_code(void) { - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); - /*--- Type import code ---*/ - __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(3, 9, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type", - #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000 - sizeof(PyTypeObject), - #else - sizeof(PyHeapTypeObject), - #endif - __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_7cpython_4type_type) __PYX_ERR(3, 9, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 199, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_ptype_5numpy_dtype = __Pyx_ImportType(__pyx_t_1, "numpy", "dtype", sizeof(PyArray_Descr), __Pyx_ImportType_CheckSize_Ignore); - if (!__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 199, __pyx_L1_error) - __pyx_ptype_5numpy_flatiter = __Pyx_ImportType(__pyx_t_1, "numpy", "flatiter", sizeof(PyArrayIterObject), __Pyx_ImportType_CheckSize_Ignore); - if (!__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 222, __pyx_L1_error) - __pyx_ptype_5numpy_broadcast = __Pyx_ImportType(__pyx_t_1, "numpy", "broadcast", sizeof(PyArrayMultiIterObject), __Pyx_ImportType_CheckSize_Ignore); - if (!__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 226, __pyx_L1_error) - __pyx_ptype_5numpy_ndarray = __Pyx_ImportType(__pyx_t_1, "numpy", "ndarray", sizeof(PyArrayObject), __Pyx_ImportType_CheckSize_Ignore); - if (!__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 238, __pyx_L1_error) - __pyx_ptype_5numpy_generic = __Pyx_ImportType(__pyx_t_1, "numpy", "generic", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_generic) __PYX_ERR(1, 770, __pyx_L1_error) - __pyx_ptype_5numpy_number = __Pyx_ImportType(__pyx_t_1, "numpy", "number", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_number) __PYX_ERR(1, 772, __pyx_L1_error) - __pyx_ptype_5numpy_integer = __Pyx_ImportType(__pyx_t_1, "numpy", "integer", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_integer) __PYX_ERR(1, 774, __pyx_L1_error) - __pyx_ptype_5numpy_signedinteger = __Pyx_ImportType(__pyx_t_1, "numpy", "signedinteger", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_signedinteger) __PYX_ERR(1, 776, __pyx_L1_error) - __pyx_ptype_5numpy_unsignedinteger = __Pyx_ImportType(__pyx_t_1, "numpy", "unsignedinteger", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_unsignedinteger) __PYX_ERR(1, 778, __pyx_L1_error) - __pyx_ptype_5numpy_inexact = __Pyx_ImportType(__pyx_t_1, "numpy", "inexact", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_inexact) __PYX_ERR(1, 780, __pyx_L1_error) - __pyx_ptype_5numpy_floating = __Pyx_ImportType(__pyx_t_1, "numpy", "floating", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_floating) __PYX_ERR(1, 782, __pyx_L1_error) - __pyx_ptype_5numpy_complexfloating = __Pyx_ImportType(__pyx_t_1, "numpy", "complexfloating", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_complexfloating) __PYX_ERR(1, 784, __pyx_L1_error) - __pyx_ptype_5numpy_flexible = __Pyx_ImportType(__pyx_t_1, "numpy", "flexible", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_flexible) __PYX_ERR(1, 786, __pyx_L1_error) - __pyx_ptype_5numpy_character = __Pyx_ImportType(__pyx_t_1, "numpy", "character", sizeof(PyObject), __Pyx_ImportType_CheckSize_Warn); - if (!__pyx_ptype_5numpy_character) __PYX_ERR(1, 788, __pyx_L1_error) - __pyx_ptype_5numpy_ufunc = __Pyx_ImportType(__pyx_t_1, "numpy", "ufunc", sizeof(PyUFuncObject), __Pyx_ImportType_CheckSize_Ignore); - if (!__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 826, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_RefNannyFinishContext(); - return -1; -} - -static int __Pyx_modinit_variable_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); - /*--- Variable import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_import_code(void) { - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); - /*--- Function import code ---*/ - __pyx_t_1 = PyImport_ImportModule("scipy.special.cython_special"); if (!__pyx_t_1) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (__Pyx_ImportFunction(__pyx_t_1, "pdtr", (void (**)(void))&__pyx_f_5scipy_7special_14cython_special_pdtr, "double (double, double, int __pyx_skip_dispatch)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_RefNannyFinishContext(); - return -1; -} - - -#ifndef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#elif PY_MAJOR_VERSION < 3 -#ifdef __cplusplus -#define __Pyx_PyMODINIT_FUNC extern "C" void -#else -#define __Pyx_PyMODINIT_FUNC void -#endif -#else -#ifdef __cplusplus -#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * -#else -#define __Pyx_PyMODINIT_FUNC PyObject * -#endif -#endif - - -#if PY_MAJOR_VERSION < 3 -__Pyx_PyMODINIT_FUNC init_tau_leap(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC init_tau_leap(void) -#else -__Pyx_PyMODINIT_FUNC PyInit__tau_leap(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC PyInit__tau_leap(void) -#if CYTHON_PEP489_MULTI_PHASE_INIT -{ - return PyModuleDef_Init(&__pyx_moduledef); -} -static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { - #if PY_VERSION_HEX >= 0x030700A1 - static PY_INT64_T main_interpreter_id = -1; - PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); - if (main_interpreter_id == -1) { - main_interpreter_id = current_id; - return (unlikely(current_id == -1)) ? -1 : 0; - } else if (unlikely(main_interpreter_id != current_id)) - #else - static PyInterpreterState *main_interpreter = NULL; - PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; - if (!main_interpreter) { - main_interpreter = current_interpreter; - } else if (unlikely(main_interpreter != current_interpreter)) - #endif - { - PyErr_SetString( - PyExc_ImportError, - "Interpreter change detected - this module can only be loaded into one interpreter per process."); - return -1; - } - return 0; -} -static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { - PyObject *value = PyObject_GetAttrString(spec, from_name); - int result = 0; - if (likely(value)) { - if (allow_none || value != Py_None) { - result = PyDict_SetItemString(moddict, to_name, value); - } - Py_DECREF(value); - } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } else { - result = -1; - } - return result; -} -static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { - PyObject *module = NULL, *moddict, *modname; - if (__Pyx_check_single_interpreter()) - return NULL; - if (__pyx_m) - return __Pyx_NewRef(__pyx_m); - modname = PyObject_GetAttrString(spec, "name"); - if (unlikely(!modname)) goto bad; - module = PyModule_NewObject(modname); - Py_DECREF(modname); - if (unlikely(!module)) goto bad; - moddict = PyModule_GetDict(module); - if (unlikely(!moddict)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; - return module; -bad: - Py_XDECREF(module); - return NULL; -} - - -static CYTHON_SMALL_CODE int __pyx_pymod_exec__tau_leap(PyObject *__pyx_pyinit_module) -#endif -#endif -{ - PyObject *__pyx_t_1 = NULL; - static PyThread_type_lock __pyx_t_2[8]; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannyDeclarations - #if CYTHON_PEP489_MULTI_PHASE_INIT - if (__pyx_m) { - if (__pyx_m == __pyx_pyinit_module) return 0; - PyErr_SetString(PyExc_RuntimeError, "Module '_tau_leap' has already been imported. Re-initialisation is not supported."); - return -1; - } - #elif PY_MAJOR_VERSION >= 3 - if (__pyx_m) return __Pyx_NewRef(__pyx_m); - #endif - #if CYTHON_REFNANNY -__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); -if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); -} -#endif - __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit__tau_leap(void)", 0); - if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pxy_PyFrame_Initialize_Offsets - __Pxy_PyFrame_Initialize_Offsets(); - #endif - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pyx_CyFunction_USED - if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_FusedFunction_USED - if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Coroutine_USED - if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Generator_USED - if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_AsyncGen_USED - if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_StopAsyncIteration_USED - if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - /*--- Library function declarations ---*/ - /*--- Threads initialization code ---*/ - #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x030700F0 && defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - PyEval_InitThreads(); - #endif - /*--- Module creation code ---*/ - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_m = __pyx_pyinit_module; - Py_INCREF(__pyx_m); - #else - #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4("_tau_leap", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); - #else - __pyx_m = PyModule_Create(&__pyx_moduledef); - #endif - if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_d); - __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_b); - __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_cython_runtime); - if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Initialize various global constants etc. ---*/ - if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) - if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - if (__pyx_module_is_main_pygom__model___tau_leap) { - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name_2, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - } - #if PY_MAJOR_VERSION >= 3 - { - PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) - if (!PyDict_GetItemString(modules, "pygom.model._tau_leap")) { - if (unlikely(PyDict_SetItemString(modules, "pygom.model._tau_leap", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - } - } - #endif - /*--- Builtin init code ---*/ - if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Constants init code ---*/ - if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Global type/function init code ---*/ - (void)__Pyx_modinit_global_init_code(); - (void)__Pyx_modinit_variable_export_code(); - (void)__Pyx_modinit_function_export_code(); - if (unlikely(__Pyx_modinit_type_init_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - if (unlikely(__Pyx_modinit_type_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - (void)__Pyx_modinit_variable_import_code(); - if (unlikely(__Pyx_modinit_function_import_code() < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Execution code ---*/ - #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) - if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - - /* "pygom/model/_tau_leap.pyx":1 - * import numpy as np # <<<<<<<<<<<<<< - * cimport numpy as np - * - */ - __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "pygom/model/_tau_leap.pyx":11 - * @cython.wraparound(False) # Deactivate negative indexing. - * @cython.cdivision(True) # Deactivate the div 0 error checking - * def _cy_test_tau_leap_safety(np.ndarray[np.float64_t] x, # <<<<<<<<<<<<<< - * np.ndarray[np.int64_t, ndim=2] reactant_mat, - * np.ndarray[np.float64_t] rates, - */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_5pygom_5model_9_tau_leap_1_cy_test_tau_leap_safety, NULL, __pyx_n_s_pygom_model__tau_leap); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_cy_test_tau_leap_safety, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "pygom/model/_tau_leap.pyx":1 - * import numpy as np # <<<<<<<<<<<<<< - * cimport numpy as np - * - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "View.MemoryView":210 - * info.obj = self - * - * __pyx_getbuffer = capsule( &__pyx_array_getbuffer, "getbuffer(obj, view, flags)") # <<<<<<<<<<<<<< - * - * def __dealloc__(array self): - */ - __pyx_t_1 = __pyx_capsule_create(((void *)(&__pyx_array_getbuffer)), ((char *)"getbuffer(obj, view, flags)")); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 210, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem((PyObject *)__pyx_array_type->tp_dict, __pyx_n_s_pyx_getbuffer, __pyx_t_1) < 0) __PYX_ERR(2, 210, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - PyType_Modified(__pyx_array_type); - - /* "View.MemoryView":287 - * return self.name - * - * cdef generic = Enum("") # <<<<<<<<<<<<<< - * cdef strided = Enum("") # default - * cdef indirect = Enum("") - */ - __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_MemviewEnum_type), __pyx_tuple__24, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 287, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XGOTREF(generic); - __Pyx_DECREF_SET(generic, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":288 - * - * cdef generic = Enum("") - * cdef strided = Enum("") # default # <<<<<<<<<<<<<< - * cdef indirect = Enum("") - * - */ - __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_MemviewEnum_type), __pyx_tuple__25, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 288, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XGOTREF(strided); - __Pyx_DECREF_SET(strided, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":289 - * cdef generic = Enum("") - * cdef strided = Enum("") # default - * cdef indirect = Enum("") # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_MemviewEnum_type), __pyx_tuple__26, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 289, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XGOTREF(indirect); - __Pyx_DECREF_SET(indirect, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":292 - * - * - * cdef contiguous = Enum("") # <<<<<<<<<<<<<< - * cdef indirect_contiguous = Enum("") - * - */ - __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_MemviewEnum_type), __pyx_tuple__27, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 292, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XGOTREF(contiguous); - __Pyx_DECREF_SET(contiguous, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":293 - * - * cdef contiguous = Enum("") - * cdef indirect_contiguous = Enum("") # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)__pyx_MemviewEnum_type), __pyx_tuple__28, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 293, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XGOTREF(indirect_contiguous); - __Pyx_DECREF_SET(indirect_contiguous, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_1); - __pyx_t_1 = 0; - - /* "View.MemoryView":317 - * - * DEF THREAD_LOCKS_PREALLOCATED = 8 - * cdef int __pyx_memoryview_thread_locks_used = 0 # <<<<<<<<<<<<<< - * cdef PyThread_type_lock[THREAD_LOCKS_PREALLOCATED] __pyx_memoryview_thread_locks = [ - * PyThread_allocate_lock(), - */ - __pyx_memoryview_thread_locks_used = 0; - - /* "View.MemoryView":318 - * DEF THREAD_LOCKS_PREALLOCATED = 8 - * cdef int __pyx_memoryview_thread_locks_used = 0 - * cdef PyThread_type_lock[THREAD_LOCKS_PREALLOCATED] __pyx_memoryview_thread_locks = [ # <<<<<<<<<<<<<< - * PyThread_allocate_lock(), - * PyThread_allocate_lock(), - */ - __pyx_t_2[0] = PyThread_allocate_lock(); - __pyx_t_2[1] = PyThread_allocate_lock(); - __pyx_t_2[2] = PyThread_allocate_lock(); - __pyx_t_2[3] = PyThread_allocate_lock(); - __pyx_t_2[4] = PyThread_allocate_lock(); - __pyx_t_2[5] = PyThread_allocate_lock(); - __pyx_t_2[6] = PyThread_allocate_lock(); - __pyx_t_2[7] = PyThread_allocate_lock(); - memcpy(&(__pyx_memoryview_thread_locks[0]), __pyx_t_2, sizeof(__pyx_memoryview_thread_locks[0]) * (8)); - - /* "View.MemoryView":551 - * info.obj = self - * - * __pyx_getbuffer = capsule( &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)") # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = __pyx_capsule_create(((void *)(&__pyx_memoryview_getbuffer)), ((char *)"getbuffer(obj, view, flags)")); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 551, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem((PyObject *)__pyx_memoryview_type->tp_dict, __pyx_n_s_pyx_getbuffer, __pyx_t_1) < 0) __PYX_ERR(2, 551, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - PyType_Modified(__pyx_memoryview_type); - - /* "View.MemoryView":997 - * return self.from_object - * - * __pyx_getbuffer = capsule( &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)") # <<<<<<<<<<<<<< - * - * - */ - __pyx_t_1 = __pyx_capsule_create(((void *)(&__pyx_memoryview_getbuffer)), ((char *)"getbuffer(obj, view, flags)")); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 997, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem((PyObject *)__pyx_memoryviewslice_type->tp_dict, __pyx_n_s_pyx_getbuffer, __pyx_t_1) < 0) __PYX_ERR(2, 997, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - PyType_Modified(__pyx_memoryviewslice_type); - - /* "(tree fragment)":1 - * def __pyx_unpickle_Enum(__pyx_type, long __pyx_checksum, __pyx_state): # <<<<<<<<<<<<<< - * cdef object __pyx_PickleError - * cdef object __pyx_result - */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_15View_dot_MemoryView_1__pyx_unpickle_Enum, NULL, __pyx_n_s_View_MemoryView); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyx_unpickle_Enum, __pyx_t_1) < 0) __PYX_ERR(2, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "(tree fragment)":11 - * __pyx_unpickle_Enum__set_state( __pyx_result, __pyx_state) - * return __pyx_result - * cdef __pyx_unpickle_Enum__set_state(Enum __pyx_result, tuple __pyx_state): # <<<<<<<<<<<<<< - * __pyx_result.name = __pyx_state[0] - * if len(__pyx_state) > 1 and hasattr(__pyx_result, '__dict__'): - */ - - /*--- Wrapped vars code ---*/ - - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - if (__pyx_m) { - if (__pyx_d) { - __Pyx_AddTraceback("init pygom.model._tau_leap", __pyx_clineno, __pyx_lineno, __pyx_filename); - } - Py_CLEAR(__pyx_m); - } else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, "init pygom.model._tau_leap"); - } - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - #if CYTHON_PEP489_MULTI_PHASE_INIT - return (__pyx_m != NULL) ? 0 : -1; - #elif PY_MAJOR_VERSION >= 3 - return __pyx_m; - #else - return; - #endif -} - -/* --- Runtime support code --- */ -/* Refnanny */ -#if CYTHON_REFNANNY -static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule(modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, "RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); -end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; -} -#endif - -/* PyObjectGetAttrStr */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro)) - return tp->tp_getattro(obj, attr_name); -#if PY_MAJOR_VERSION < 3 - if (likely(tp->tp_getattr)) - return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); -#endif - return PyObject_GetAttr(obj, attr_name); -} -#endif - -/* GetBuiltinName */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name) { - PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); - if (unlikely(!result)) { - PyErr_Format(PyExc_NameError, -#if PY_MAJOR_VERSION >= 3 - "name '%U' is not defined", name); -#else - "name '%.200s' is not defined", PyString_AS_STRING(name)); -#endif - } - return result; -} - -/* RaiseArgTupleInvalid */ -static void __Pyx_RaiseArgtupleInvalid( - const char* func_name, - int exact, - Py_ssize_t num_min, - Py_ssize_t num_max, - Py_ssize_t num_found) -{ - Py_ssize_t num_expected; - const char *more_or_less; - if (num_found < num_min) { - num_expected = num_min; - more_or_less = "at least"; - } else { - num_expected = num_max; - more_or_less = "at most"; - } - if (exact) { - more_or_less = "exactly"; - } - PyErr_Format(PyExc_TypeError, - "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", - func_name, more_or_less, num_expected, - (num_expected == 1) ? "" : "s", num_found); -} - -/* RaiseDoubleKeywords */ -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, - PyObject* kw_name) -{ - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION >= 3 - "%s() got multiple values for keyword argument '%U'", func_name, kw_name); - #else - "%s() got multiple values for keyword argument '%s'", func_name, - PyString_AsString(kw_name)); - #endif -} - -/* ParseKeywords */ -static int __Pyx_ParseOptionalKeywords( - PyObject *kwds, - PyObject **argnames[], - PyObject *kwds2, - PyObject *values[], - Py_ssize_t num_pos_args, - const char* function_name) -{ - PyObject *key = 0, *value = 0; - Py_ssize_t pos = 0; - PyObject*** name; - PyObject*** first_kw_arg = argnames + num_pos_args; - while (PyDict_Next(kwds, &pos, &key, &value)) { - name = first_kw_arg; - while (*name && (**name != key)) name++; - if (*name) { - values[name-argnames] = value; - continue; - } - name = first_kw_arg; - #if PY_MAJOR_VERSION < 3 - if (likely(PyString_Check(key))) { - while (*name) { - if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) - && _PyString_Eq(**name, key)) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - if ((**argname == key) || ( - (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) - && _PyString_Eq(**argname, key))) { - goto arg_passed_twice; - } - argname++; - } - } - } else - #endif - if (likely(PyUnicode_Check(key))) { - while (*name) { - int cmp = (**name == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : - #endif - PyUnicode_Compare(**name, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - int cmp = (**argname == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : - #endif - PyUnicode_Compare(**argname, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) goto arg_passed_twice; - argname++; - } - } - } else - goto invalid_keyword_type; - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, key); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%.200s() got an unexpected keyword argument '%.200s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - -/* ArgTypeTest */ -static int __Pyx__ArgTypeTest(PyObject *obj, PyTypeObject *type, const char *name, int exact) -{ - if (unlikely(!type)) { - PyErr_SetString(PyExc_SystemError, "Missing type object"); - return 0; - } - else if (exact) { - #if PY_MAJOR_VERSION == 2 - if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1; - #endif - } - else { - if (likely(__Pyx_TypeCheck(obj, type))) return 1; - } - PyErr_Format(PyExc_TypeError, - "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)", - name, type->tp_name, Py_TYPE(obj)->tp_name); - return 0; -} - -/* IsLittleEndian */ -static CYTHON_INLINE int __Pyx_Is_Little_Endian(void) -{ - union { - uint32_t u32; - uint8_t u8[4]; - } S; - S.u32 = 0x01020304; - return S.u8[0] == 4; -} - -/* BufferFormatCheck */ -static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx, - __Pyx_BufFmt_StackElem* stack, - __Pyx_TypeInfo* type) { - stack[0].field = &ctx->root; - stack[0].parent_offset = 0; - ctx->root.type = type; - ctx->root.name = "buffer dtype"; - ctx->root.offset = 0; - ctx->head = stack; - ctx->head->field = &ctx->root; - ctx->fmt_offset = 0; - ctx->head->parent_offset = 0; - ctx->new_packmode = '@'; - ctx->enc_packmode = '@'; - ctx->new_count = 1; - ctx->enc_count = 0; - ctx->enc_type = 0; - ctx->is_complex = 0; - ctx->is_valid_array = 0; - ctx->struct_alignment = 0; - while (type->typegroup == 'S') { - ++ctx->head; - ctx->head->field = type->fields; - ctx->head->parent_offset = 0; - type = type->fields->type; - } -} -static int __Pyx_BufFmt_ParseNumber(const char** ts) { - int count; - const char* t = *ts; - if (*t < '0' || *t > '9') { - return -1; - } else { - count = *t++ - '0'; - while (*t >= '0' && *t <= '9') { - count *= 10; - count += *t++ - '0'; - } - } - *ts = t; - return count; -} -static int __Pyx_BufFmt_ExpectNumber(const char **ts) { - int number = __Pyx_BufFmt_ParseNumber(ts); - if (number == -1) - PyErr_Format(PyExc_ValueError,\ - "Does not understand character buffer dtype format string ('%c')", **ts); - return number; -} -static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) { - PyErr_Format(PyExc_ValueError, - "Unexpected format string character: '%c'", ch); -} -static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) { - switch (ch) { - case '?': return "'bool'"; - case 'c': return "'char'"; - case 'b': return "'signed char'"; - case 'B': return "'unsigned char'"; - case 'h': return "'short'"; - case 'H': return "'unsigned short'"; - case 'i': return "'int'"; - case 'I': return "'unsigned int'"; - case 'l': return "'long'"; - case 'L': return "'unsigned long'"; - case 'q': return "'long long'"; - case 'Q': return "'unsigned long long'"; - case 'f': return (is_complex ? "'complex float'" : "'float'"); - case 'd': return (is_complex ? "'complex double'" : "'double'"); - case 'g': return (is_complex ? "'complex long double'" : "'long double'"); - case 'T': return "a struct"; - case 'O': return "Python object"; - case 'P': return "a pointer"; - case 's': case 'p': return "a string"; - case 0: return "end"; - default: return "unparseable format string"; - } -} -static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) { - switch (ch) { - case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; - case 'h': case 'H': return 2; - case 'i': case 'I': case 'l': case 'L': return 4; - case 'q': case 'Q': return 8; - case 'f': return (is_complex ? 8 : 4); - case 'd': return (is_complex ? 16 : 8); - case 'g': { - PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g').."); - return 0; - } - case 'O': case 'P': return sizeof(void*); - default: - __Pyx_BufFmt_RaiseUnexpectedChar(ch); - return 0; - } -} -static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) { - switch (ch) { - case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; - case 'h': case 'H': return sizeof(short); - case 'i': case 'I': return sizeof(int); - case 'l': case 'L': return sizeof(long); - #ifdef HAVE_LONG_LONG - case 'q': case 'Q': return sizeof(PY_LONG_LONG); - #endif - case 'f': return sizeof(float) * (is_complex ? 2 : 1); - case 'd': return sizeof(double) * (is_complex ? 2 : 1); - case 'g': return sizeof(long double) * (is_complex ? 2 : 1); - case 'O': case 'P': return sizeof(void*); - default: { - __Pyx_BufFmt_RaiseUnexpectedChar(ch); - return 0; - } - } -} -typedef struct { char c; short x; } __Pyx_st_short; -typedef struct { char c; int x; } __Pyx_st_int; -typedef struct { char c; long x; } __Pyx_st_long; -typedef struct { char c; float x; } __Pyx_st_float; -typedef struct { char c; double x; } __Pyx_st_double; -typedef struct { char c; long double x; } __Pyx_st_longdouble; -typedef struct { char c; void *x; } __Pyx_st_void_p; -#ifdef HAVE_LONG_LONG -typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong; -#endif -static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, CYTHON_UNUSED int is_complex) { - switch (ch) { - case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; - case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short); - case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int); - case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long); -#ifdef HAVE_LONG_LONG - case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG); -#endif - case 'f': return sizeof(__Pyx_st_float) - sizeof(float); - case 'd': return sizeof(__Pyx_st_double) - sizeof(double); - case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double); - case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*); - default: - __Pyx_BufFmt_RaiseUnexpectedChar(ch); - return 0; - } -} -/* These are for computing the padding at the end of the struct to align - on the first member of the struct. This will probably the same as above, - but we don't have any guarantees. - */ -typedef struct { short x; char c; } __Pyx_pad_short; -typedef struct { int x; char c; } __Pyx_pad_int; -typedef struct { long x; char c; } __Pyx_pad_long; -typedef struct { float x; char c; } __Pyx_pad_float; -typedef struct { double x; char c; } __Pyx_pad_double; -typedef struct { long double x; char c; } __Pyx_pad_longdouble; -typedef struct { void *x; char c; } __Pyx_pad_void_p; -#ifdef HAVE_LONG_LONG -typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong; -#endif -static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, CYTHON_UNUSED int is_complex) { - switch (ch) { - case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1; - case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short); - case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int); - case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long); -#ifdef HAVE_LONG_LONG - case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG); -#endif - case 'f': return sizeof(__Pyx_pad_float) - sizeof(float); - case 'd': return sizeof(__Pyx_pad_double) - sizeof(double); - case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double); - case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*); - default: - __Pyx_BufFmt_RaiseUnexpectedChar(ch); - return 0; - } -} -static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) { - switch (ch) { - case 'c': - return 'H'; - case 'b': case 'h': case 'i': - case 'l': case 'q': case 's': case 'p': - return 'I'; - case '?': case 'B': case 'H': case 'I': case 'L': case 'Q': - return 'U'; - case 'f': case 'd': case 'g': - return (is_complex ? 'C' : 'R'); - case 'O': - return 'O'; - case 'P': - return 'P'; - default: { - __Pyx_BufFmt_RaiseUnexpectedChar(ch); - return 0; - } - } -} -static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) { - if (ctx->head == NULL || ctx->head->field == &ctx->root) { - const char* expected; - const char* quote; - if (ctx->head == NULL) { - expected = "end"; - quote = ""; - } else { - expected = ctx->head->field->type->name; - quote = "'"; - } - PyErr_Format(PyExc_ValueError, - "Buffer dtype mismatch, expected %s%s%s but got %s", - quote, expected, quote, - __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex)); - } else { - __Pyx_StructField* field = ctx->head->field; - __Pyx_StructField* parent = (ctx->head - 1)->field; - PyErr_Format(PyExc_ValueError, - "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'", - field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex), - parent->type->name, field->name); - } -} -static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) { - char group; - size_t size, offset, arraysize = 1; - if (ctx->enc_type == 0) return 0; - if (ctx->head->field->type->arraysize[0]) { - int i, ndim = 0; - if (ctx->enc_type == 's' || ctx->enc_type == 'p') { - ctx->is_valid_array = ctx->head->field->type->ndim == 1; - ndim = 1; - if (ctx->enc_count != ctx->head->field->type->arraysize[0]) { - PyErr_Format(PyExc_ValueError, - "Expected a dimension of size %zu, got %zu", - ctx->head->field->type->arraysize[0], ctx->enc_count); - return -1; - } - } - if (!ctx->is_valid_array) { - PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d", - ctx->head->field->type->ndim, ndim); - return -1; - } - for (i = 0; i < ctx->head->field->type->ndim; i++) { - arraysize *= ctx->head->field->type->arraysize[i]; - } - ctx->is_valid_array = 0; - ctx->enc_count = 1; - } - group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex); - do { - __Pyx_StructField* field = ctx->head->field; - __Pyx_TypeInfo* type = field->type; - if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') { - size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex); - } else { - size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex); - } - if (ctx->enc_packmode == '@') { - size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex); - size_t align_mod_offset; - if (align_at == 0) return -1; - align_mod_offset = ctx->fmt_offset % align_at; - if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset; - if (ctx->struct_alignment == 0) - ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type, - ctx->is_complex); - } - if (type->size != size || type->typegroup != group) { - if (type->typegroup == 'C' && type->fields != NULL) { - size_t parent_offset = ctx->head->parent_offset + field->offset; - ++ctx->head; - ctx->head->field = type->fields; - ctx->head->parent_offset = parent_offset; - continue; - } - if ((type->typegroup == 'H' || group == 'H') && type->size == size) { - } else { - __Pyx_BufFmt_RaiseExpected(ctx); - return -1; - } - } - offset = ctx->head->parent_offset + field->offset; - if (ctx->fmt_offset != offset) { - PyErr_Format(PyExc_ValueError, - "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected", - (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset); - return -1; - } - ctx->fmt_offset += size; - if (arraysize) - ctx->fmt_offset += (arraysize - 1) * size; - --ctx->enc_count; - while (1) { - if (field == &ctx->root) { - ctx->head = NULL; - if (ctx->enc_count != 0) { - __Pyx_BufFmt_RaiseExpected(ctx); - return -1; - } - break; - } - ctx->head->field = ++field; - if (field->type == NULL) { - --ctx->head; - field = ctx->head->field; - continue; - } else if (field->type->typegroup == 'S') { - size_t parent_offset = ctx->head->parent_offset + field->offset; - if (field->type->fields->type == NULL) continue; - field = field->type->fields; - ++ctx->head; - ctx->head->field = field; - ctx->head->parent_offset = parent_offset; - break; - } else { - break; - } - } - } while (ctx->enc_count); - ctx->enc_type = 0; - ctx->is_complex = 0; - return 0; -} -static PyObject * -__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp) -{ - const char *ts = *tsp; - int i = 0, number, ndim; - ++ts; - if (ctx->new_count != 1) { - PyErr_SetString(PyExc_ValueError, - "Cannot handle repeated arrays in format string"); - return NULL; - } - if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; - ndim = ctx->head->field->type->ndim; - while (*ts && *ts != ')') { - switch (*ts) { - case ' ': case '\f': case '\r': case '\n': case '\t': case '\v': continue; - default: break; - } - number = __Pyx_BufFmt_ExpectNumber(&ts); - if (number == -1) return NULL; - if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) - return PyErr_Format(PyExc_ValueError, - "Expected a dimension of size %zu, got %d", - ctx->head->field->type->arraysize[i], number); - if (*ts != ',' && *ts != ')') - return PyErr_Format(PyExc_ValueError, - "Expected a comma in format string, got '%c'", *ts); - if (*ts == ',') ts++; - i++; - } - if (i != ndim) - return PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d", - ctx->head->field->type->ndim, i); - if (!*ts) { - PyErr_SetString(PyExc_ValueError, - "Unexpected end of format string, expected ')'"); - return NULL; - } - ctx->is_valid_array = 1; - ctx->new_count = 1; - *tsp = ++ts; - return Py_None; -} -static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) { - int got_Z = 0; - while (1) { - switch(*ts) { - case 0: - if (ctx->enc_type != 0 && ctx->head == NULL) { - __Pyx_BufFmt_RaiseExpected(ctx); - return NULL; - } - if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; - if (ctx->head != NULL) { - __Pyx_BufFmt_RaiseExpected(ctx); - return NULL; - } - return ts; - case ' ': - case '\r': - case '\n': - ++ts; - break; - case '<': - if (!__Pyx_Is_Little_Endian()) { - PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler"); - return NULL; - } - ctx->new_packmode = '='; - ++ts; - break; - case '>': - case '!': - if (__Pyx_Is_Little_Endian()) { - PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler"); - return NULL; - } - ctx->new_packmode = '='; - ++ts; - break; - case '=': - case '@': - case '^': - ctx->new_packmode = *ts++; - break; - case 'T': - { - const char* ts_after_sub; - size_t i, struct_count = ctx->new_count; - size_t struct_alignment = ctx->struct_alignment; - ctx->new_count = 1; - ++ts; - if (*ts != '{') { - PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'"); - return NULL; - } - if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; - ctx->enc_type = 0; - ctx->enc_count = 0; - ctx->struct_alignment = 0; - ++ts; - ts_after_sub = ts; - for (i = 0; i != struct_count; ++i) { - ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts); - if (!ts_after_sub) return NULL; - } - ts = ts_after_sub; - if (struct_alignment) ctx->struct_alignment = struct_alignment; - } - break; - case '}': - { - size_t alignment = ctx->struct_alignment; - ++ts; - if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; - ctx->enc_type = 0; - if (alignment && ctx->fmt_offset % alignment) { - ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment); - } - } - return ts; - case 'x': - if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; - ctx->fmt_offset += ctx->new_count; - ctx->new_count = 1; - ctx->enc_count = 0; - ctx->enc_type = 0; - ctx->enc_packmode = ctx->new_packmode; - ++ts; - break; - case 'Z': - got_Z = 1; - ++ts; - if (*ts != 'f' && *ts != 'd' && *ts != 'g') { - __Pyx_BufFmt_RaiseUnexpectedChar('Z'); - return NULL; - } - CYTHON_FALLTHROUGH; - case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I': - case 'l': case 'L': case 'q': case 'Q': - case 'f': case 'd': case 'g': - case 'O': case 'p': - if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) && - (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) { - ctx->enc_count += ctx->new_count; - ctx->new_count = 1; - got_Z = 0; - ++ts; - break; - } - CYTHON_FALLTHROUGH; - case 's': - if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL; - ctx->enc_count = ctx->new_count; - ctx->enc_packmode = ctx->new_packmode; - ctx->enc_type = *ts; - ctx->is_complex = got_Z; - ++ts; - ctx->new_count = 1; - got_Z = 0; - break; - case ':': - ++ts; - while(*ts != ':') ++ts; - ++ts; - break; - case '(': - if (!__pyx_buffmt_parse_array(ctx, &ts)) return NULL; - break; - default: - { - int number = __Pyx_BufFmt_ExpectNumber(&ts); - if (number == -1) return NULL; - ctx->new_count = (size_t)number; - } - } - } -} - -/* BufferGetAndValidate */ - static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { - if (unlikely(info->buf == NULL)) return; - if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; - __Pyx_ReleaseBuffer(info); -} -static void __Pyx_ZeroBuffer(Py_buffer* buf) { - buf->buf = NULL; - buf->obj = NULL; - buf->strides = __Pyx_zeros; - buf->shape = __Pyx_zeros; - buf->suboffsets = __Pyx_minusones; -} -static int __Pyx__GetBufferAndValidate( - Py_buffer* buf, PyObject* obj, __Pyx_TypeInfo* dtype, int flags, - int nd, int cast, __Pyx_BufFmt_StackElem* stack) -{ - buf->buf = NULL; - if (unlikely(__Pyx_GetBuffer(obj, buf, flags) == -1)) { - __Pyx_ZeroBuffer(buf); - return -1; - } - if (unlikely(buf->ndim != nd)) { - PyErr_Format(PyExc_ValueError, - "Buffer has wrong number of dimensions (expected %d, got %d)", - nd, buf->ndim); - goto fail; - } - if (!cast) { - __Pyx_BufFmt_Context ctx; - __Pyx_BufFmt_Init(&ctx, stack, dtype); - if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail; - } - if (unlikely((size_t)buf->itemsize != dtype->size)) { - PyErr_Format(PyExc_ValueError, - "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)", - buf->itemsize, (buf->itemsize > 1) ? "s" : "", - dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : ""); - goto fail; - } - if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones; - return 0; -fail:; - __Pyx_SafeReleaseBuffer(buf); - return -1; -} - -/* PyDictVersioning */ - #if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { - PyObject **dictptr = NULL; - Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; - if (offset) { -#if CYTHON_COMPILING_IN_CPYTHON - dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); -#else - dictptr = _PyObject_GetDictPtr(obj); -#endif - } - return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; -} -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) - return 0; - return obj_dict_version == __Pyx_get_object_dict_version(obj); -} -#endif - -/* GetModuleGlobalName */ - #if CYTHON_USE_DICT_VERSIONS -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) -#else -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) -#endif -{ - PyObject *result; -#if !CYTHON_AVOID_BORROWED_REFS -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 - result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } else if (unlikely(PyErr_Occurred())) { - return NULL; - } -#else - result = PyDict_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } -#endif -#else - result = PyObject_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } - PyErr_Clear(); -#endif - return __Pyx_GetBuiltinName(name); -} - -/* PyCFunctionFastCall */ - #if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { - PyCFunctionObject *func = (PyCFunctionObject*)func_obj; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - assert(PyCFunction_Check(func)); - assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); - assert(nargs >= 0); - assert(nargs == 0 || args != NULL); - /* _PyCFunction_FastCallDict() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!PyErr_Occurred()); - if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { - return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); - } else { - return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); - } -} -#endif - -/* PyFunctionFastCall */ - #if CYTHON_FAST_PYCALL -static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, - PyObject *globals) { - PyFrameObject *f; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject **fastlocals; - Py_ssize_t i; - PyObject *result; - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) { - return NULL; - } - fastlocals = __Pyx_PyFrame_GetLocalsplus(f); - for (i = 0; i < na; i++) { - Py_INCREF(*args); - fastlocals[i] = *args++; - } - result = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return result; -} -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject *closure; -#if PY_MAJOR_VERSION >= 3 - PyObject *kwdefs; -#endif - PyObject *kwtuple, **k; - PyObject **d; - Py_ssize_t nd; - Py_ssize_t nk; - PyObject *result; - assert(kwargs == NULL || PyDict_Check(kwargs)); - nk = kwargs ? PyDict_Size(kwargs) : 0; - if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { - return NULL; - } - if ( -#if PY_MAJOR_VERSION >= 3 - co->co_kwonlyargcount == 0 && -#endif - likely(kwargs == NULL || nk == 0) && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - if (argdefs == NULL && co->co_argcount == nargs) { - result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); - goto done; - } - else if (nargs == 0 && argdefs != NULL - && co->co_argcount == Py_SIZE(argdefs)) { - /* function called with no arguments, but all parameters have - a default value: use default values as arguments .*/ - args = &PyTuple_GET_ITEM(argdefs, 0); - result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); - goto done; - } - } - if (kwargs != NULL) { - Py_ssize_t pos, i; - kwtuple = PyTuple_New(2 * nk); - if (kwtuple == NULL) { - result = NULL; - goto done; - } - k = &PyTuple_GET_ITEM(kwtuple, 0); - pos = i = 0; - while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { - Py_INCREF(k[i]); - Py_INCREF(k[i+1]); - i += 2; - } - nk = i / 2; - } - else { - kwtuple = NULL; - k = NULL; - } - closure = PyFunction_GET_CLOSURE(func); -#if PY_MAJOR_VERSION >= 3 - kwdefs = PyFunction_GET_KW_DEFAULTS(func); -#endif - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); - } - else { - d = NULL; - nd = 0; - } -#if PY_MAJOR_VERSION >= 3 - result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, kwdefs, closure); -#else - result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, closure); -#endif - Py_XDECREF(kwtuple); -done: - Py_LeaveRecursiveCall(); - return result; -} -#endif -#endif - -/* PyObjectCall */ - #if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { - PyObject *result; - ternaryfunc call = Py_TYPE(func)->tp_call; - if (unlikely(!call)) - return PyObject_Call(func, arg, kw); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = (*call)(func, arg, kw); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCall2Args */ - static CYTHON_UNUSED PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) { - PyObject *args, *result = NULL; - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(function)) { - PyObject *args[2] = {arg1, arg2}; - return __Pyx_PyFunction_FastCall(function, args, 2); - } - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(function)) { - PyObject *args[2] = {arg1, arg2}; - return __Pyx_PyCFunction_FastCall(function, args, 2); - } - #endif - args = PyTuple_New(2); - if (unlikely(!args)) goto done; - Py_INCREF(arg1); - PyTuple_SET_ITEM(args, 0, arg1); - Py_INCREF(arg2); - PyTuple_SET_ITEM(args, 1, arg2); - Py_INCREF(function); - result = __Pyx_PyObject_Call(function, args, NULL); - Py_DECREF(args); - Py_DECREF(function); -done: - return result; -} - -/* PyObjectCallMethO */ - #if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { - PyObject *self, *result; - PyCFunction cfunc; - cfunc = PyCFunction_GET_FUNCTION(func); - self = PyCFunction_GET_SELF(func); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = cfunc(self, arg); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallOneArg */ - #if CYTHON_COMPILING_IN_CPYTHON -static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_New(1); - if (unlikely(!args)) return NULL; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, arg); - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, &arg, 1); - } -#endif - if (likely(PyCFunction_Check(func))) { - if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { - return __Pyx_PyObject_CallMethO(func, arg); -#if CYTHON_FAST_PYCCALL - } else if (__Pyx_PyFastCFunction_Check(func)) { - return __Pyx_PyCFunction_FastCall(func, &arg, 1); -#endif - } - } - return __Pyx__PyObject_CallOneArg(func, arg); -} -#else -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_Pack(1, arg); - if (unlikely(!args)) return NULL; - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -#endif - -/* MemviewSliceInit */ - static int -__Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview, - int ndim, - __Pyx_memviewslice *memviewslice, - int memview_is_new_reference) -{ - __Pyx_RefNannyDeclarations - int i, retval=-1; - Py_buffer *buf = &memview->view; - __Pyx_RefNannySetupContext("init_memviewslice", 0); - if (unlikely(memviewslice->memview || memviewslice->data)) { - PyErr_SetString(PyExc_ValueError, - "memviewslice is already initialized!"); - goto fail; - } - if (buf->strides) { - for (i = 0; i < ndim; i++) { - memviewslice->strides[i] = buf->strides[i]; - } - } else { - Py_ssize_t stride = buf->itemsize; - for (i = ndim - 1; i >= 0; i--) { - memviewslice->strides[i] = stride; - stride *= buf->shape[i]; - } - } - for (i = 0; i < ndim; i++) { - memviewslice->shape[i] = buf->shape[i]; - if (buf->suboffsets) { - memviewslice->suboffsets[i] = buf->suboffsets[i]; - } else { - memviewslice->suboffsets[i] = -1; - } - } - memviewslice->memview = memview; - memviewslice->data = (char *)buf->buf; - if (__pyx_add_acquisition_count(memview) == 0 && !memview_is_new_reference) { - Py_INCREF(memview); - } - retval = 0; - goto no_fail; -fail: - memviewslice->memview = 0; - memviewslice->data = 0; - retval = -1; -no_fail: - __Pyx_RefNannyFinishContext(); - return retval; -} -#ifndef Py_NO_RETURN -#define Py_NO_RETURN -#endif -static void __pyx_fatalerror(const char *fmt, ...) Py_NO_RETURN { - va_list vargs; - char msg[200]; -#if PY_VERSION_HEX >= 0x030A0000 || defined(HAVE_STDARG_PROTOTYPES) - va_start(vargs, fmt); -#else - va_start(vargs); -#endif - vsnprintf(msg, 200, fmt, vargs); - va_end(vargs); - Py_FatalError(msg); -} -static CYTHON_INLINE int -__pyx_add_acquisition_count_locked(__pyx_atomic_int *acquisition_count, - PyThread_type_lock lock) -{ - int result; - PyThread_acquire_lock(lock, 1); - result = (*acquisition_count)++; - PyThread_release_lock(lock); - return result; -} -static CYTHON_INLINE int -__pyx_sub_acquisition_count_locked(__pyx_atomic_int *acquisition_count, - PyThread_type_lock lock) -{ - int result; - PyThread_acquire_lock(lock, 1); - result = (*acquisition_count)--; - PyThread_release_lock(lock); - return result; -} -static CYTHON_INLINE void -__Pyx_INC_MEMVIEW(__Pyx_memviewslice *memslice, int have_gil, int lineno) -{ - int first_time; - struct __pyx_memoryview_obj *memview = memslice->memview; - if (unlikely(!memview || (PyObject *) memview == Py_None)) - return; - if (unlikely(__pyx_get_slice_count(memview) < 0)) - __pyx_fatalerror("Acquisition count is %d (line %d)", - __pyx_get_slice_count(memview), lineno); - first_time = __pyx_add_acquisition_count(memview) == 0; - if (unlikely(first_time)) { - if (have_gil) { - Py_INCREF((PyObject *) memview); - } else { - PyGILState_STATE _gilstate = PyGILState_Ensure(); - Py_INCREF((PyObject *) memview); - PyGILState_Release(_gilstate); - } - } -} -static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW(__Pyx_memviewslice *memslice, - int have_gil, int lineno) { - int last_time; - struct __pyx_memoryview_obj *memview = memslice->memview; - if (unlikely(!memview || (PyObject *) memview == Py_None)) { - memslice->memview = NULL; - return; - } - if (unlikely(__pyx_get_slice_count(memview) <= 0)) - __pyx_fatalerror("Acquisition count is %d (line %d)", - __pyx_get_slice_count(memview), lineno); - last_time = __pyx_sub_acquisition_count(memview) == 1; - memslice->data = NULL; - if (unlikely(last_time)) { - if (have_gil) { - Py_CLEAR(memslice->memview); - } else { - PyGILState_STATE _gilstate = PyGILState_Ensure(); - Py_CLEAR(memslice->memview); - PyGILState_Release(_gilstate); - } - } else { - memslice->memview = NULL; - } -} - -/* PyErrFetchRestore */ - #if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - tmp_type = tstate->curexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -} -#endif - -/* GetTopmostException */ - #if CYTHON_USE_EXC_INFO_STACK -static _PyErr_StackItem * -__Pyx_PyErr_GetTopmostException(PyThreadState *tstate) -{ - _PyErr_StackItem *exc_info = tstate->exc_info; - while ((exc_info->exc_type == NULL || exc_info->exc_type == Py_None) && - exc_info->previous_item != NULL) - { - exc_info = exc_info->previous_item; - } - return exc_info; -} -#endif - -/* SaveResetException */ - #if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - #if CYTHON_USE_EXC_INFO_STACK - _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate); - *type = exc_info->exc_type; - *value = exc_info->exc_value; - *tb = exc_info->exc_traceback; - #else - *type = tstate->exc_type; - *value = tstate->exc_value; - *tb = tstate->exc_traceback; - #endif - Py_XINCREF(*type); - Py_XINCREF(*value); - Py_XINCREF(*tb); -} -static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - #if CYTHON_USE_EXC_INFO_STACK - _PyErr_StackItem *exc_info = tstate->exc_info; - tmp_type = exc_info->exc_type; - tmp_value = exc_info->exc_value; - tmp_tb = exc_info->exc_traceback; - exc_info->exc_type = type; - exc_info->exc_value = value; - exc_info->exc_traceback = tb; - #else - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - tstate->exc_type = type; - tstate->exc_value = value; - tstate->exc_traceback = tb; - #endif - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} -#endif - -/* PyErrExceptionMatches */ - #if CYTHON_FAST_THREAD_STATE -static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; icurexc_type; - if (exc_type == err) return 1; - if (unlikely(!exc_type)) return 0; - if (unlikely(PyTuple_Check(err))) - return __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err); - return __Pyx_PyErr_GivenExceptionMatches(exc_type, err); -} -#endif - -/* GetException */ - #if CYTHON_FAST_THREAD_STATE -static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) -#else -static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) -#endif -{ - PyObject *local_type, *local_value, *local_tb; -#if CYTHON_FAST_THREAD_STATE - PyObject *tmp_type, *tmp_value, *tmp_tb; - local_type = tstate->curexc_type; - local_value = tstate->curexc_value; - local_tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -#else - PyErr_Fetch(&local_type, &local_value, &local_tb); -#endif - PyErr_NormalizeException(&local_type, &local_value, &local_tb); -#if CYTHON_FAST_THREAD_STATE - if (unlikely(tstate->curexc_type)) -#else - if (unlikely(PyErr_Occurred())) -#endif - goto bad; - #if PY_MAJOR_VERSION >= 3 - if (local_tb) { - if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0)) - goto bad; - } - #endif - Py_XINCREF(local_tb); - Py_XINCREF(local_type); - Py_XINCREF(local_value); - *type = local_type; - *value = local_value; - *tb = local_tb; -#if CYTHON_FAST_THREAD_STATE - #if CYTHON_USE_EXC_INFO_STACK - { - _PyErr_StackItem *exc_info = tstate->exc_info; - tmp_type = exc_info->exc_type; - tmp_value = exc_info->exc_value; - tmp_tb = exc_info->exc_traceback; - exc_info->exc_type = local_type; - exc_info->exc_value = local_value; - exc_info->exc_traceback = local_tb; - } - #else - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - tstate->exc_type = local_type; - tstate->exc_value = local_value; - tstate->exc_traceback = local_tb; - #endif - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -#else - PyErr_SetExcInfo(local_type, local_value, local_tb); -#endif - return 0; -bad: - *type = 0; - *value = 0; - *tb = 0; - Py_XDECREF(local_type); - Py_XDECREF(local_value); - Py_XDECREF(local_tb); - return -1; -} - -/* RaiseException */ - #if PY_MAJOR_VERSION < 3 -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, - CYTHON_UNUSED PyObject *cause) { - __Pyx_PyThreadState_declare - Py_XINCREF(type); - if (!value || value == Py_None) - value = NULL; - else - Py_INCREF(value); - if (!tb || tb == Py_None) - tb = NULL; - else { - Py_INCREF(tb); - if (!PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto raise_error; - } - } - if (PyType_Check(type)) { -#if CYTHON_COMPILING_IN_PYPY - if (!value) { - Py_INCREF(Py_None); - value = Py_None; - } -#endif - PyErr_NormalizeException(&type, &value, &tb); - } else { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto raise_error; - } - value = type; - type = (PyObject*) Py_TYPE(type); - Py_INCREF(type); - if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto raise_error; - } - } - __Pyx_PyThreadState_assign - __Pyx_ErrRestore(type, value, tb); - return; -raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(tb); - return; -} -#else -static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) { - PyObject* owned_instance = NULL; - if (tb == Py_None) { - tb = 0; - } else if (tb && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto bad; - } - if (value == Py_None) - value = 0; - if (PyExceptionInstance_Check(type)) { - if (value) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto bad; - } - value = type; - type = (PyObject*) Py_TYPE(value); - } else if (PyExceptionClass_Check(type)) { - PyObject *instance_class = NULL; - if (value && PyExceptionInstance_Check(value)) { - instance_class = (PyObject*) Py_TYPE(value); - if (instance_class != type) { - int is_subclass = PyObject_IsSubclass(instance_class, type); - if (!is_subclass) { - instance_class = NULL; - } else if (unlikely(is_subclass == -1)) { - goto bad; - } else { - type = instance_class; - } - } - } - if (!instance_class) { - PyObject *args; - if (!value) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; - } else - args = PyTuple_Pack(1, value); - if (!args) - goto bad; - owned_instance = PyObject_Call(type, args, NULL); - Py_DECREF(args); - if (!owned_instance) - goto bad; - value = owned_instance; - if (!PyExceptionInstance_Check(value)) { - PyErr_Format(PyExc_TypeError, - "calling %R should have returned an instance of " - "BaseException, not %R", - type, Py_TYPE(value)); - goto bad; - } - } - } else { - PyErr_SetString(PyExc_TypeError, - "raise: exception class must be a subclass of BaseException"); - goto bad; - } - if (cause) { - PyObject *fixed_cause; - if (cause == Py_None) { - fixed_cause = NULL; - } else if (PyExceptionClass_Check(cause)) { - fixed_cause = PyObject_CallObject(cause, NULL); - if (fixed_cause == NULL) - goto bad; - } else if (PyExceptionInstance_Check(cause)) { - fixed_cause = cause; - Py_INCREF(fixed_cause); - } else { - PyErr_SetString(PyExc_TypeError, - "exception causes must derive from " - "BaseException"); - goto bad; - } - PyException_SetCause(value, fixed_cause); - } - PyErr_SetObject(type, value); - if (tb) { -#if CYTHON_COMPILING_IN_PYPY - PyObject *tmp_type, *tmp_value, *tmp_tb; - PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb); - Py_INCREF(tb); - PyErr_Restore(tmp_type, tmp_value, tb); - Py_XDECREF(tmp_tb); -#else - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject* tmp_tb = tstate->curexc_traceback; - if (tb != tmp_tb) { - Py_INCREF(tb); - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_tb); - } -#endif - } -bad: - Py_XDECREF(owned_instance); - return; -} -#endif - -/* BytesEquals */ - static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) { -#if CYTHON_COMPILING_IN_PYPY - return PyObject_RichCompareBool(s1, s2, equals); -#else - if (s1 == s2) { - return (equals == Py_EQ); - } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) { - const char *ps1, *ps2; - Py_ssize_t length = PyBytes_GET_SIZE(s1); - if (length != PyBytes_GET_SIZE(s2)) - return (equals == Py_NE); - ps1 = PyBytes_AS_STRING(s1); - ps2 = PyBytes_AS_STRING(s2); - if (ps1[0] != ps2[0]) { - return (equals == Py_NE); - } else if (length == 1) { - return (equals == Py_EQ); - } else { - int result; -#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000) - Py_hash_t hash1, hash2; - hash1 = ((PyBytesObject*)s1)->ob_shash; - hash2 = ((PyBytesObject*)s2)->ob_shash; - if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { - return (equals == Py_NE); - } -#endif - result = memcmp(ps1, ps2, (size_t)length); - return (equals == Py_EQ) ? (result == 0) : (result != 0); - } - } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) { - return (equals == Py_NE); - } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) { - return (equals == Py_NE); - } else { - int result; - PyObject* py_result = PyObject_RichCompare(s1, s2, equals); - if (!py_result) - return -1; - result = __Pyx_PyObject_IsTrue(py_result); - Py_DECREF(py_result); - return result; - } -#endif -} - -/* UnicodeEquals */ - static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) { -#if CYTHON_COMPILING_IN_PYPY - return PyObject_RichCompareBool(s1, s2, equals); -#else -#if PY_MAJOR_VERSION < 3 - PyObject* owned_ref = NULL; -#endif - int s1_is_unicode, s2_is_unicode; - if (s1 == s2) { - goto return_eq; - } - s1_is_unicode = PyUnicode_CheckExact(s1); - s2_is_unicode = PyUnicode_CheckExact(s2); -#if PY_MAJOR_VERSION < 3 - if ((s1_is_unicode & (!s2_is_unicode)) && PyString_CheckExact(s2)) { - owned_ref = PyUnicode_FromObject(s2); - if (unlikely(!owned_ref)) - return -1; - s2 = owned_ref; - s2_is_unicode = 1; - } else if ((s2_is_unicode & (!s1_is_unicode)) && PyString_CheckExact(s1)) { - owned_ref = PyUnicode_FromObject(s1); - if (unlikely(!owned_ref)) - return -1; - s1 = owned_ref; - s1_is_unicode = 1; - } else if (((!s2_is_unicode) & (!s1_is_unicode))) { - return __Pyx_PyBytes_Equals(s1, s2, equals); - } -#endif - if (s1_is_unicode & s2_is_unicode) { - Py_ssize_t length; - int kind; - void *data1, *data2; - if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0)) - return -1; - length = __Pyx_PyUnicode_GET_LENGTH(s1); - if (length != __Pyx_PyUnicode_GET_LENGTH(s2)) { - goto return_ne; - } -#if CYTHON_USE_UNICODE_INTERNALS - { - Py_hash_t hash1, hash2; - #if CYTHON_PEP393_ENABLED - hash1 = ((PyASCIIObject*)s1)->hash; - hash2 = ((PyASCIIObject*)s2)->hash; - #else - hash1 = ((PyUnicodeObject*)s1)->hash; - hash2 = ((PyUnicodeObject*)s2)->hash; - #endif - if (hash1 != hash2 && hash1 != -1 && hash2 != -1) { - goto return_ne; - } - } -#endif - kind = __Pyx_PyUnicode_KIND(s1); - if (kind != __Pyx_PyUnicode_KIND(s2)) { - goto return_ne; - } - data1 = __Pyx_PyUnicode_DATA(s1); - data2 = __Pyx_PyUnicode_DATA(s2); - if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) { - goto return_ne; - } else if (length == 1) { - goto return_eq; - } else { - int result = memcmp(data1, data2, (size_t)(length * kind)); - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(owned_ref); - #endif - return (equals == Py_EQ) ? (result == 0) : (result != 0); - } - } else if ((s1 == Py_None) & s2_is_unicode) { - goto return_ne; - } else if ((s2 == Py_None) & s1_is_unicode) { - goto return_ne; - } else { - int result; - PyObject* py_result = PyObject_RichCompare(s1, s2, equals); - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(owned_ref); - #endif - if (!py_result) - return -1; - result = __Pyx_PyObject_IsTrue(py_result); - Py_DECREF(py_result); - return result; - } -return_eq: - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(owned_ref); - #endif - return (equals == Py_EQ); -return_ne: - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(owned_ref); - #endif - return (equals == Py_NE); -#endif -} - -/* DivInt[Py_ssize_t] */ - static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t a, Py_ssize_t b) { - Py_ssize_t q = a / b; - Py_ssize_t r = a - q*b; - q -= ((r != 0) & ((r ^ b) < 0)); - return q; -} - -/* GetAttr */ - static CYTHON_INLINE PyObject *__Pyx_GetAttr(PyObject *o, PyObject *n) { -#if CYTHON_USE_TYPE_SLOTS -#if PY_MAJOR_VERSION >= 3 - if (likely(PyUnicode_Check(n))) -#else - if (likely(PyString_Check(n))) -#endif - return __Pyx_PyObject_GetAttrStr(o, n); -#endif - return PyObject_GetAttr(o, n); -} - -/* GetItemInt */ - static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyList_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyTuple_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS - if (is_list || PyList_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { - PyObject *r = PyList_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } - else if (PyTuple_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } else { - PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; - if (likely(m && m->sq_item)) { - if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { - Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - } - } - return m->sq_item(o, i); - } - } -#else - if (is_list || PySequence_Check(o)) { - return PySequence_GetItem(o, i); - } -#endif - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -} - -/* ObjectGetItem */ - #if CYTHON_USE_TYPE_SLOTS -static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { - PyObject *runerr = NULL; - Py_ssize_t key_value; - PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; - if (unlikely(!(m && m->sq_item))) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); - return NULL; - } - key_value = __Pyx_PyIndex_AsSsize_t(index); - if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { - return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); - } - if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { - PyErr_Clear(); - PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); - } - return NULL; -} -static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { - PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; - if (likely(m && m->mp_subscript)) { - return m->mp_subscript(obj, key); - } - return __Pyx_PyObject_GetIndex(obj, key); -} -#endif - -/* decode_c_string */ - static CYTHON_INLINE PyObject* __Pyx_decode_c_string( - const char* cstring, Py_ssize_t start, Py_ssize_t stop, - const char* encoding, const char* errors, - PyObject* (*decode_func)(const char *s, Py_ssize_t size, const char *errors)) { - Py_ssize_t length; - if (unlikely((start < 0) | (stop < 0))) { - size_t slen = strlen(cstring); - if (unlikely(slen > (size_t) PY_SSIZE_T_MAX)) { - PyErr_SetString(PyExc_OverflowError, - "c-string too long to convert to Python"); - return NULL; - } - length = (Py_ssize_t) slen; - if (start < 0) { - start += length; - if (start < 0) - start = 0; - } - if (stop < 0) - stop += length; - } - if (unlikely(stop <= start)) - return __Pyx_NewRef(__pyx_empty_unicode); - length = stop - start; - cstring += start; - if (decode_func) { - return decode_func(cstring, length, errors); - } else { - return PyUnicode_Decode(cstring, length, encoding, errors); - } -} - -/* GetAttr3 */ - static PyObject *__Pyx_GetAttr3Default(PyObject *d) { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) - return NULL; - __Pyx_PyErr_Clear(); - Py_INCREF(d); - return d; -} -static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { - PyObject *r = __Pyx_GetAttr(o, n); - return (likely(r)) ? r : __Pyx_GetAttr3Default(d); -} - -/* RaiseTooManyValuesToUnpack */ - static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { - PyErr_Format(PyExc_ValueError, - "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); -} - -/* RaiseNeedMoreValuesToUnpack */ - static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { - PyErr_Format(PyExc_ValueError, - "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", - index, (index == 1) ? "" : "s"); -} - -/* RaiseNoneIterError */ - static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); -} - -/* ExtTypeTest */ - static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) { - if (unlikely(!type)) { - PyErr_SetString(PyExc_SystemError, "Missing type object"); - return 0; - } - if (likely(__Pyx_TypeCheck(obj, type))) - return 1; - PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s", - Py_TYPE(obj)->tp_name, type->tp_name); - return 0; -} - -/* SwapException */ - #if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx__ExceptionSwap(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - #if CYTHON_USE_EXC_INFO_STACK - _PyErr_StackItem *exc_info = tstate->exc_info; - tmp_type = exc_info->exc_type; - tmp_value = exc_info->exc_value; - tmp_tb = exc_info->exc_traceback; - exc_info->exc_type = *type; - exc_info->exc_value = *value; - exc_info->exc_traceback = *tb; - #else - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - tstate->exc_type = *type; - tstate->exc_value = *value; - tstate->exc_traceback = *tb; - #endif - *type = tmp_type; - *value = tmp_value; - *tb = tmp_tb; -} -#else -static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb); - PyErr_SetExcInfo(*type, *value, *tb); - *type = tmp_type; - *value = tmp_value; - *tb = tmp_tb; -} -#endif - -/* Import */ - static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) { - PyObject *empty_list = 0; - PyObject *module = 0; - PyObject *global_dict = 0; - PyObject *empty_dict = 0; - PyObject *list; - #if PY_MAJOR_VERSION < 3 - PyObject *py_import; - py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import); - if (!py_import) - goto bad; - #endif - if (from_list) - list = from_list; - else { - empty_list = PyList_New(0); - if (!empty_list) - goto bad; - list = empty_list; - } - global_dict = PyModule_GetDict(__pyx_m); - if (!global_dict) - goto bad; - empty_dict = PyDict_New(); - if (!empty_dict) - goto bad; - { - #if PY_MAJOR_VERSION >= 3 - if (level == -1) { - if ((1) && (strchr(__Pyx_MODULE_NAME, '.'))) { - module = PyImport_ImportModuleLevelObject( - name, global_dict, empty_dict, list, 1); - if (!module) { - if (!PyErr_ExceptionMatches(PyExc_ImportError)) - goto bad; - PyErr_Clear(); - } - } - level = 0; - } - #endif - if (!module) { - #if PY_MAJOR_VERSION < 3 - PyObject *py_level = PyInt_FromLong(level); - if (!py_level) - goto bad; - module = PyObject_CallFunctionObjArgs(py_import, - name, global_dict, empty_dict, list, py_level, (PyObject *)NULL); - Py_DECREF(py_level); - #else - module = PyImport_ImportModuleLevelObject( - name, global_dict, empty_dict, list, level); - #endif - } - } -bad: - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(py_import); - #endif - Py_XDECREF(empty_list); - Py_XDECREF(empty_dict); - return module; -} - -/* FastTypeChecks */ - #if CYTHON_COMPILING_IN_CPYTHON -static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { - while (a) { - a = a->tp_base; - if (a == b) - return 1; - } - return b == &PyBaseObject_Type; -} -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { - PyObject *mro; - if (a == b) return 1; - mro = a->tp_mro; - if (likely(mro)) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) - return 1; - } - return 0; - } - return __Pyx_InBases(a, b); -} -#if PY_MAJOR_VERSION == 2 -static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { - PyObject *exception, *value, *tb; - int res; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&exception, &value, &tb); - res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - if (!res) { - res = PyObject_IsSubclass(err, exc_type2); - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - } - __Pyx_ErrRestore(exception, value, tb); - return res; -} -#else -static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { - int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; - if (!res) { - res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); - } - return res; -} -#endif -static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - assert(PyExceptionClass_Check(exc_type)); - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; i= 0 || (x^b) >= 0)) - return PyInt_FromLong(x); - return PyLong_Type.tp_as_number->nb_add(op1, op2); - } - #endif - #if CYTHON_USE_PYLONG_INTERNALS - if (likely(PyLong_CheckExact(op1))) { - const long b = intval; - long a, x; -#ifdef HAVE_LONG_LONG - const PY_LONG_LONG llb = intval; - PY_LONG_LONG lla, llx; -#endif - const digit* digits = ((PyLongObject*)op1)->ob_digit; - const Py_ssize_t size = Py_SIZE(op1); - if (likely(__Pyx_sst_abs(size) <= 1)) { - a = likely(size) ? digits[0] : 0; - if (size == -1) a = -a; - } else { - switch (size) { - case -2: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - a = -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { - lla = -(PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case 2: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) { - lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case -3: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - a = -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { - lla = -(PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case 3: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) { - lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case -4: - if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - a = -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { - lla = -(PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - case 4: - if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])); - break; -#ifdef HAVE_LONG_LONG - } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) { - lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0])); - goto long_long; -#endif - } - CYTHON_FALLTHROUGH; - default: return PyLong_Type.tp_as_number->nb_add(op1, op2); - } - } - x = a + b; - return PyLong_FromLong(x); -#ifdef HAVE_LONG_LONG - long_long: - llx = lla + llb; - return PyLong_FromLongLong(llx); -#endif - - - } - #endif - if (PyFloat_CheckExact(op1)) { - const long b = intval; - double a = PyFloat_AS_DOUBLE(op1); - double result; - PyFPE_START_PROTECT("add", return NULL) - result = ((double)a) + (double)b; - PyFPE_END_PROTECT(result) - return PyFloat_FromDouble(result); - } - return (inplace ? PyNumber_InPlaceAdd : PyNumber_Add)(op1, op2); -} -#endif - -/* None */ - static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { - PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); -} - -/* DivInt[long] */ - static CYTHON_INLINE long __Pyx_div_long(long a, long b) { - long q = a / b; - long r = a - q*b; - q -= ((r != 0) & ((r ^ b) < 0)); - return q; -} - -/* ImportFrom */ - static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) { - PyObject* value = __Pyx_PyObject_GetAttrStr(module, name); - if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_ImportError, - #if PY_MAJOR_VERSION < 3 - "cannot import name %.230s", PyString_AS_STRING(name)); - #else - "cannot import name %S", name); - #endif - } - return value; -} - -/* HasAttr */ - static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) { - PyObject *r; - if (unlikely(!__Pyx_PyBaseString_Check(n))) { - PyErr_SetString(PyExc_TypeError, - "hasattr(): attribute name must be string"); - return -1; - } - r = __Pyx_GetAttr(o, n); - if (unlikely(!r)) { - PyErr_Clear(); - return 0; - } else { - Py_DECREF(r); - return 1; - } -} - -/* PyObject_GenericGetAttrNoDict */ - #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject *attr_name) { - PyErr_Format(PyExc_AttributeError, -#if PY_MAJOR_VERSION >= 3 - "'%.50s' object has no attribute '%U'", - tp->tp_name, attr_name); -#else - "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyString_AS_STRING(attr_name)); -#endif - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { - PyObject *descr; - PyTypeObject *tp = Py_TYPE(obj); - if (unlikely(!PyString_Check(attr_name))) { - return PyObject_GenericGetAttr(obj, attr_name); - } - assert(!tp->tp_dictoffset); - descr = _PyType_Lookup(tp, attr_name); - if (unlikely(!descr)) { - return __Pyx_RaiseGenericGetAttributeError(tp, attr_name); - } - Py_INCREF(descr); - #if PY_MAJOR_VERSION < 3 - if (likely(PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS))) - #endif - { - descrgetfunc f = Py_TYPE(descr)->tp_descr_get; - if (unlikely(f)) { - PyObject *res = f(descr, obj, (PyObject *)tp); - Py_DECREF(descr); - return res; - } - } - return descr; -} -#endif - -/* PyObject_GenericGetAttr */ - #if CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP && PY_VERSION_HEX < 0x03070000 -static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_name) { - if (unlikely(Py_TYPE(obj)->tp_dictoffset)) { - return PyObject_GenericGetAttr(obj, attr_name); - } - return __Pyx_PyObject_GenericGetAttrNoDict(obj, attr_name); -} -#endif - -/* SetVTable */ - static int __Pyx_SetVtable(PyObject *dict, void *vtable) { -#if PY_VERSION_HEX >= 0x02070000 - PyObject *ob = PyCapsule_New(vtable, 0, 0); -#else - PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); -#endif - if (!ob) - goto bad; - if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0) - goto bad; - Py_DECREF(ob); - return 0; -bad: - Py_XDECREF(ob); - return -1; -} - -/* PyObjectGetAttrStrNoError */ - static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) { - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) - __Pyx_PyErr_Clear(); -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) { - PyObject *result; -#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1 - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) { - return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1); - } -#endif - result = __Pyx_PyObject_GetAttrStr(obj, attr_name); - if (unlikely(!result)) { - __Pyx_PyObject_GetAttrStr_ClearAttributeError(); - } - return result; -} - -/* SetupReduce */ - static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { - int ret; - PyObject *name_attr; - name_attr = __Pyx_PyObject_GetAttrStr(meth, __pyx_n_s_name_2); - if (likely(name_attr)) { - ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); - } else { - ret = -1; - } - if (unlikely(ret < 0)) { - PyErr_Clear(); - ret = 0; - } - Py_XDECREF(name_attr); - return ret; -} -static int __Pyx_setup_reduce(PyObject* type_obj) { - int ret = 0; - PyObject *object_reduce = NULL; - PyObject *object_getstate = NULL; - PyObject *object_reduce_ex = NULL; - PyObject *reduce = NULL; - PyObject *reduce_ex = NULL; - PyObject *reduce_cython = NULL; - PyObject *setstate = NULL; - PyObject *setstate_cython = NULL; - PyObject *getstate = NULL; -#if CYTHON_USE_PYTYPE_LOOKUP - getstate = _PyType_Lookup((PyTypeObject*)type_obj, __pyx_n_s_getstate); -#else - getstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_getstate); - if (!getstate && PyErr_Occurred()) { - goto __PYX_BAD; - } -#endif - if (getstate) { -#if CYTHON_USE_PYTYPE_LOOKUP - object_getstate = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_getstate); -#else - object_getstate = __Pyx_PyObject_GetAttrStrNoError((PyObject*)&PyBaseObject_Type, __pyx_n_s_getstate); - if (!object_getstate && PyErr_Occurred()) { - goto __PYX_BAD; - } -#endif - if (object_getstate != getstate) { - goto __PYX_GOOD; - } - } -#if CYTHON_USE_PYTYPE_LOOKUP - object_reduce_ex = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; -#else - object_reduce_ex = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce_ex); if (!object_reduce_ex) goto __PYX_BAD; -#endif - reduce_ex = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce_ex); if (unlikely(!reduce_ex)) goto __PYX_BAD; - if (reduce_ex == object_reduce_ex) { -#if CYTHON_USE_PYTYPE_LOOKUP - object_reduce = _PyType_Lookup(&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; -#else - object_reduce = __Pyx_PyObject_GetAttrStr((PyObject*)&PyBaseObject_Type, __pyx_n_s_reduce); if (!object_reduce) goto __PYX_BAD; -#endif - reduce = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_reduce); if (unlikely(!reduce)) goto __PYX_BAD; - if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, __pyx_n_s_reduce_cython)) { - reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_reduce_cython); - if (likely(reduce_cython)) { - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce, reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - } else if (reduce == object_reduce || PyErr_Occurred()) { - goto __PYX_BAD; - } - setstate = __Pyx_PyObject_GetAttrStr(type_obj, __pyx_n_s_setstate); - if (!setstate) PyErr_Clear(); - if (!setstate || __Pyx_setup_reduce_is_named(setstate, __pyx_n_s_setstate_cython)) { - setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, __pyx_n_s_setstate_cython); - if (likely(setstate_cython)) { - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate, setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, __pyx_n_s_setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - } else if (!setstate || PyErr_Occurred()) { - goto __PYX_BAD; - } - } - PyType_Modified((PyTypeObject*)type_obj); - } - } - goto __PYX_GOOD; -__PYX_BAD: - if (!PyErr_Occurred()) - PyErr_Format(PyExc_RuntimeError, "Unable to initialize pickling for %s", ((PyTypeObject*)type_obj)->tp_name); - ret = -1; -__PYX_GOOD: -#if !CYTHON_USE_PYTYPE_LOOKUP - Py_XDECREF(object_reduce); - Py_XDECREF(object_reduce_ex); - Py_XDECREF(object_getstate); - Py_XDECREF(getstate); -#endif - Py_XDECREF(reduce); - Py_XDECREF(reduce_ex); - Py_XDECREF(reduce_cython); - Py_XDECREF(setstate); - Py_XDECREF(setstate_cython); - return ret; -} - -/* TypeImport */ - #ifndef __PYX_HAVE_RT_ImportType -#define __PYX_HAVE_RT_ImportType -static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name, const char *class_name, - size_t size, enum __Pyx_ImportType_CheckSize check_size) -{ - PyObject *result = 0; - char warning[200]; - Py_ssize_t basicsize; -#ifdef Py_LIMITED_API - PyObject *py_basicsize; -#endif - result = PyObject_GetAttrString(module, class_name); - if (!result) - goto bad; - if (!PyType_Check(result)) { - PyErr_Format(PyExc_TypeError, - "%.200s.%.200s is not a type object", - module_name, class_name); - goto bad; - } -#ifndef Py_LIMITED_API - basicsize = ((PyTypeObject *)result)->tp_basicsize; -#else - py_basicsize = PyObject_GetAttrString(result, "__basicsize__"); - if (!py_basicsize) - goto bad; - basicsize = PyLong_AsSsize_t(py_basicsize); - Py_DECREF(py_basicsize); - py_basicsize = 0; - if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) - goto bad; -#endif - if ((size_t)basicsize < size) { - PyErr_Format(PyExc_ValueError, - "%.200s.%.200s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - goto bad; - } - if (check_size == __Pyx_ImportType_CheckSize_Error && (size_t)basicsize != size) { - PyErr_Format(PyExc_ValueError, - "%.200s.%.200s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - goto bad; - } - else if (check_size == __Pyx_ImportType_CheckSize_Warn && (size_t)basicsize > size) { - PyOS_snprintf(warning, sizeof(warning), - "%s.%s size changed, may indicate binary incompatibility. " - "Expected %zd from C header, got %zd from PyObject", - module_name, class_name, size, basicsize); - if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad; - } - return (PyTypeObject *)result; -bad: - Py_XDECREF(result); - return NULL; -} -#endif - -/* CLineInTraceback */ - #ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_line) { - PyObject *use_cline; - PyObject *ptype, *pvalue, *ptraceback; -#if CYTHON_COMPILING_IN_CPYTHON - PyObject **cython_runtime_dict; -#endif - if (unlikely(!__pyx_cython_runtime)) { - return c_line; - } - __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); -#if CYTHON_COMPILING_IN_CPYTHON - cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); - if (likely(cython_runtime_dict)) { - __PYX_PY_DICT_LOOKUP_IF_MODIFIED( - use_cline, *cython_runtime_dict, - __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) - } else -#endif - { - PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); - if (use_cline_obj) { - use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; - Py_DECREF(use_cline_obj); - } else { - PyErr_Clear(); - use_cline = NULL; - } - } - if (!use_cline) { - c_line = 0; - (void) PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); - } - else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { - c_line = 0; - } - __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); - return c_line; -} -#endif - -/* CodeObjectCache */ - static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { - int start = 0, mid = 0, end = count - 1; - if (end >= 0 && code_line > entries[end].code_line) { - return count; - } - while (start < end) { - mid = start + (end - start) / 2; - if (code_line < entries[mid].code_line) { - end = mid; - } else if (code_line > entries[mid].code_line) { - start = mid + 1; - } else { - return mid; - } - } - if (code_line <= entries[mid].code_line) { - return mid; - } else { - return mid + 1; - } -} -static PyCodeObject *__pyx_find_code_object(int code_line) { - PyCodeObject* code_object; - int pos; - if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { - return NULL; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { - return NULL; - } - code_object = __pyx_code_cache.entries[pos].code_object; - Py_INCREF(code_object); - return code_object; -} -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { - int pos, i; - __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; - if (unlikely(!code_line)) { - return; - } - if (unlikely(!entries)) { - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); - if (likely(entries)) { - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = 64; - __pyx_code_cache.count = 1; - entries[0].code_line = code_line; - entries[0].code_object = code_object; - Py_INCREF(code_object); - } - return; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { - PyCodeObject* tmp = entries[pos].code_object; - entries[pos].code_object = code_object; - Py_DECREF(tmp); - return; - } - if (__pyx_code_cache.count == __pyx_code_cache.max_count) { - int new_max = __pyx_code_cache.max_count + 64; - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( - __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); - if (unlikely(!entries)) { - return; - } - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = new_max; - } - for (i=__pyx_code_cache.count; i>pos; i--) { - entries[i] = entries[i-1]; - } - entries[pos].code_line = code_line; - entries[pos].code_object = code_object; - __pyx_code_cache.count++; - Py_INCREF(code_object); -} - -/* AddTraceback */ - #include "compile.h" -#include "frameobject.h" -#include "traceback.h" -#if PY_VERSION_HEX >= 0x030b00a6 - #ifndef Py_BUILD_CORE - #define Py_BUILD_CORE 1 - #endif - #include "internal/pycore_frame.h" -#endif -static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( - const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = NULL; - PyObject *py_funcname = NULL; - #if PY_MAJOR_VERSION < 3 - PyObject *py_srcfile = NULL; - py_srcfile = PyString_FromString(filename); - if (!py_srcfile) goto bad; - #endif - if (c_line) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - if (!py_funcname) goto bad; - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - if (!py_funcname) goto bad; - funcname = PyUnicode_AsUTF8(py_funcname); - if (!funcname) goto bad; - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - if (!py_funcname) goto bad; - #endif - } - #if PY_MAJOR_VERSION < 3 - py_code = __Pyx_PyCode_New( - 0, - 0, - 0, - 0, - 0, - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - py_line, - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - Py_DECREF(py_srcfile); - #else - py_code = PyCode_NewEmpty(filename, funcname, py_line); - #endif - Py_XDECREF(py_funcname); // XDECREF since it's only set on Py3 if cline - return py_code; -bad: - Py_XDECREF(py_funcname); - #if PY_MAJOR_VERSION < 3 - Py_XDECREF(py_srcfile); - #endif - return NULL; -} -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject *ptype, *pvalue, *ptraceback; - if (c_line) { - c_line = __Pyx_CLineForTraceback(tstate, c_line); - } - py_code = __pyx_find_code_object(c_line ? -c_line : py_line); - if (!py_code) { - __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); - py_code = __Pyx_CreateCodeObjectForTraceback( - funcname, c_line, py_line, filename); - if (!py_code) { - /* If the code object creation fails, then we should clear the - fetched exception references and propagate the new exception */ - Py_XDECREF(ptype); - Py_XDECREF(pvalue); - Py_XDECREF(ptraceback); - goto bad; - } - __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); - __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); - } - py_frame = PyFrame_New( - tstate, /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - __pyx_d, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - __Pyx_PyFrame_SetLineNumber(py_frame, py_line); - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - -#if PY_MAJOR_VERSION < 3 -static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) { - if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags); - if (__Pyx_TypeCheck(obj, __pyx_array_type)) return __pyx_array_getbuffer(obj, view, flags); - if (__Pyx_TypeCheck(obj, __pyx_memoryview_type)) return __pyx_memoryview_getbuffer(obj, view, flags); - PyErr_Format(PyExc_TypeError, "'%.200s' does not have the buffer interface", Py_TYPE(obj)->tp_name); - return -1; -} -static void __Pyx_ReleaseBuffer(Py_buffer *view) { - PyObject *obj = view->obj; - if (!obj) return; - if (PyObject_CheckBuffer(obj)) { - PyBuffer_Release(view); - return; - } - if ((0)) {} - view->obj = NULL; - Py_DECREF(obj); -} -#endif - - - /* MemviewSliceIsContig */ - static int -__pyx_memviewslice_is_contig(const __Pyx_memviewslice mvs, char order, int ndim) -{ - int i, index, step, start; - Py_ssize_t itemsize = mvs.memview->view.itemsize; - if (order == 'F') { - step = 1; - start = 0; - } else { - step = -1; - start = ndim - 1; - } - for (i = 0; i < ndim; i++) { - index = start + step * i; - if (mvs.suboffsets[index] >= 0 || mvs.strides[index] != itemsize) - return 0; - itemsize *= mvs.shape[index]; - } - return 1; -} - -/* OverlappingSlices */ - static void -__pyx_get_array_memory_extents(__Pyx_memviewslice *slice, - void **out_start, void **out_end, - int ndim, size_t itemsize) -{ - char *start, *end; - int i; - start = end = slice->data; - for (i = 0; i < ndim; i++) { - Py_ssize_t stride = slice->strides[i]; - Py_ssize_t extent = slice->shape[i]; - if (extent == 0) { - *out_start = *out_end = start; - return; - } else { - if (stride > 0) - end += stride * (extent - 1); - else - start += stride * (extent - 1); - } - } - *out_start = start; - *out_end = end + itemsize; -} -static int -__pyx_slices_overlap(__Pyx_memviewslice *slice1, - __Pyx_memviewslice *slice2, - int ndim, size_t itemsize) -{ - void *start1, *end1, *start2, *end2; - __pyx_get_array_memory_extents(slice1, &start1, &end1, ndim, itemsize); - __pyx_get_array_memory_extents(slice2, &start2, &end2, ndim, itemsize); - return (start1 < end2) && (start2 < end1); -} - -/* Capsule */ - static CYTHON_INLINE PyObject * -__pyx_capsule_create(void *p, CYTHON_UNUSED const char *sig) -{ - PyObject *cobj; -#if PY_VERSION_HEX >= 0x02070000 - cobj = PyCapsule_New(p, sig, NULL); -#else - cobj = PyCObject_FromVoidPtr(p, NULL); -#endif - return cobj; -} - -/* TypeInfoCompare */ - static int -__pyx_typeinfo_cmp(__Pyx_TypeInfo *a, __Pyx_TypeInfo *b) -{ - int i; - if (!a || !b) - return 0; - if (a == b) - return 1; - if (a->size != b->size || a->typegroup != b->typegroup || - a->is_unsigned != b->is_unsigned || a->ndim != b->ndim) { - if (a->typegroup == 'H' || b->typegroup == 'H') { - return a->size == b->size; - } else { - return 0; - } - } - if (a->ndim) { - for (i = 0; i < a->ndim; i++) - if (a->arraysize[i] != b->arraysize[i]) - return 0; - } - if (a->typegroup == 'S') { - if (a->flags != b->flags) - return 0; - if (a->fields || b->fields) { - if (!(a->fields && b->fields)) - return 0; - for (i = 0; a->fields[i].type && b->fields[i].type; i++) { - __Pyx_StructField *field_a = a->fields + i; - __Pyx_StructField *field_b = b->fields + i; - if (field_a->offset != field_b->offset || - !__pyx_typeinfo_cmp(field_a->type, field_b->type)) - return 0; - } - return !a->fields[i].type && !b->fields[i].type; - } - } - return 1; -} - -/* MemviewSliceValidateAndInit */ - static int -__pyx_check_strides(Py_buffer *buf, int dim, int ndim, int spec) -{ - if (buf->shape[dim] <= 1) - return 1; - if (buf->strides) { - if (spec & __Pyx_MEMVIEW_CONTIG) { - if (spec & (__Pyx_MEMVIEW_PTR|__Pyx_MEMVIEW_FULL)) { - if (unlikely(buf->strides[dim] != sizeof(void *))) { - PyErr_Format(PyExc_ValueError, - "Buffer is not indirectly contiguous " - "in dimension %d.", dim); - goto fail; - } - } else if (unlikely(buf->strides[dim] != buf->itemsize)) { - PyErr_SetString(PyExc_ValueError, - "Buffer and memoryview are not contiguous " - "in the same dimension."); - goto fail; - } - } - if (spec & __Pyx_MEMVIEW_FOLLOW) { - Py_ssize_t stride = buf->strides[dim]; - if (stride < 0) - stride = -stride; - if (unlikely(stride < buf->itemsize)) { - PyErr_SetString(PyExc_ValueError, - "Buffer and memoryview are not contiguous " - "in the same dimension."); - goto fail; - } - } - } else { - if (unlikely(spec & __Pyx_MEMVIEW_CONTIG && dim != ndim - 1)) { - PyErr_Format(PyExc_ValueError, - "C-contiguous buffer is not contiguous in " - "dimension %d", dim); - goto fail; - } else if (unlikely(spec & (__Pyx_MEMVIEW_PTR))) { - PyErr_Format(PyExc_ValueError, - "C-contiguous buffer is not indirect in " - "dimension %d", dim); - goto fail; - } else if (unlikely(buf->suboffsets)) { - PyErr_SetString(PyExc_ValueError, - "Buffer exposes suboffsets but no strides"); - goto fail; - } - } - return 1; -fail: - return 0; -} -static int -__pyx_check_suboffsets(Py_buffer *buf, int dim, CYTHON_UNUSED int ndim, int spec) -{ - if (spec & __Pyx_MEMVIEW_DIRECT) { - if (unlikely(buf->suboffsets && buf->suboffsets[dim] >= 0)) { - PyErr_Format(PyExc_ValueError, - "Buffer not compatible with direct access " - "in dimension %d.", dim); - goto fail; - } - } - if (spec & __Pyx_MEMVIEW_PTR) { - if (unlikely(!buf->suboffsets || (buf->suboffsets[dim] < 0))) { - PyErr_Format(PyExc_ValueError, - "Buffer is not indirectly accessible " - "in dimension %d.", dim); - goto fail; - } - } - return 1; -fail: - return 0; -} -static int -__pyx_verify_contig(Py_buffer *buf, int ndim, int c_or_f_flag) -{ - int i; - if (c_or_f_flag & __Pyx_IS_F_CONTIG) { - Py_ssize_t stride = 1; - for (i = 0; i < ndim; i++) { - if (unlikely(stride * buf->itemsize != buf->strides[i] && buf->shape[i] > 1)) { - PyErr_SetString(PyExc_ValueError, - "Buffer not fortran contiguous."); - goto fail; - } - stride = stride * buf->shape[i]; - } - } else if (c_or_f_flag & __Pyx_IS_C_CONTIG) { - Py_ssize_t stride = 1; - for (i = ndim - 1; i >- 1; i--) { - if (unlikely(stride * buf->itemsize != buf->strides[i] && buf->shape[i] > 1)) { - PyErr_SetString(PyExc_ValueError, - "Buffer not C contiguous."); - goto fail; - } - stride = stride * buf->shape[i]; - } - } - return 1; -fail: - return 0; -} -static int __Pyx_ValidateAndInit_memviewslice( - int *axes_specs, - int c_or_f_flag, - int buf_flags, - int ndim, - __Pyx_TypeInfo *dtype, - __Pyx_BufFmt_StackElem stack[], - __Pyx_memviewslice *memviewslice, - PyObject *original_obj) -{ - struct __pyx_memoryview_obj *memview, *new_memview; - __Pyx_RefNannyDeclarations - Py_buffer *buf; - int i, spec = 0, retval = -1; - __Pyx_BufFmt_Context ctx; - int from_memoryview = __pyx_memoryview_check(original_obj); - __Pyx_RefNannySetupContext("ValidateAndInit_memviewslice", 0); - if (from_memoryview && __pyx_typeinfo_cmp(dtype, ((struct __pyx_memoryview_obj *) - original_obj)->typeinfo)) { - memview = (struct __pyx_memoryview_obj *) original_obj; - new_memview = NULL; - } else { - memview = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( - original_obj, buf_flags, 0, dtype); - new_memview = memview; - if (unlikely(!memview)) - goto fail; - } - buf = &memview->view; - if (unlikely(buf->ndim != ndim)) { - PyErr_Format(PyExc_ValueError, - "Buffer has wrong number of dimensions (expected %d, got %d)", - ndim, buf->ndim); - goto fail; - } - if (new_memview) { - __Pyx_BufFmt_Init(&ctx, stack, dtype); - if (unlikely(!__Pyx_BufFmt_CheckString(&ctx, buf->format))) goto fail; - } - if (unlikely((unsigned) buf->itemsize != dtype->size)) { - PyErr_Format(PyExc_ValueError, - "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "u byte%s) " - "does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "u byte%s)", - buf->itemsize, - (buf->itemsize > 1) ? "s" : "", - dtype->name, - dtype->size, - (dtype->size > 1) ? "s" : ""); - goto fail; - } - if (buf->len > 0) { - for (i = 0; i < ndim; i++) { - spec = axes_specs[i]; - if (unlikely(!__pyx_check_strides(buf, i, ndim, spec))) - goto fail; - if (unlikely(!__pyx_check_suboffsets(buf, i, ndim, spec))) - goto fail; - } - if (unlikely(buf->strides && !__pyx_verify_contig(buf, ndim, c_or_f_flag))) - goto fail; - } - if (unlikely(__Pyx_init_memviewslice(memview, ndim, memviewslice, - new_memview != NULL) == -1)) { - goto fail; - } - retval = 0; - goto no_fail; -fail: - Py_XDECREF(new_memview); - retval = -1; -no_fail: - __Pyx_RefNannyFinishContext(); - return retval; -} - -/* ObjectToMemviewSlice */ - static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_ds_double(PyObject *obj, int writable_flag) { - __Pyx_memviewslice result = { 0, 0, { 0 }, { 0 }, { 0 } }; - __Pyx_BufFmt_StackElem stack[1]; - int axes_specs[] = { (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_STRIDED) }; - int retcode; - if (obj == Py_None) { - result.memview = (struct __pyx_memoryview_obj *) Py_None; - return result; - } - retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, 0, - PyBUF_RECORDS_RO | writable_flag, 1, - &__Pyx_TypeInfo_double, stack, - &result, obj); - if (unlikely(retcode == -1)) - goto __pyx_fail; - return result; -__pyx_fail: - result.memview = NULL; - result.data = NULL; - return result; -} - -/* ObjectToMemviewSlice */ - static CYTHON_INLINE __Pyx_memviewslice __Pyx_PyObject_to_MemoryviewSlice_dsds_nn___pyx_t_5numpy_int64_t(PyObject *obj, int writable_flag) { - __Pyx_memviewslice result = { 0, 0, { 0 }, { 0 }, { 0 } }; - __Pyx_BufFmt_StackElem stack[1]; - int axes_specs[] = { (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_STRIDED), (__Pyx_MEMVIEW_DIRECT | __Pyx_MEMVIEW_STRIDED) }; - int retcode; - if (obj == Py_None) { - result.memview = (struct __pyx_memoryview_obj *) Py_None; - return result; - } - retcode = __Pyx_ValidateAndInit_memviewslice(axes_specs, 0, - PyBUF_RECORDS_RO | writable_flag, 2, - &__Pyx_TypeInfo_nn___pyx_t_5numpy_int64_t, stack, - &result, obj); - if (unlikely(retcode == -1)) - goto __pyx_fail; - return result; -__pyx_fail: - result.memview = NULL; - result.data = NULL; - return result; -} - -/* CIntFromPyVerify */ - #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) -#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) -#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ - {\ - func_type value = func_value;\ - if (sizeof(target_type) < sizeof(func_type)) {\ - if (unlikely(value != (func_type) (target_type) value)) {\ - func_type zero = 0;\ - if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ - return (target_type) -1;\ - if (is_unsigned && unlikely(value < zero))\ - goto raise_neg_overflow;\ - else\ - goto raise_overflow;\ - }\ - }\ - return (target_type) value;\ - } - -/* Declarations */ - #if CYTHON_CCOMPLEX - #ifdef __cplusplus - static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { - return ::std::complex< float >(x, y); - } - #else - static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { - return x + y*(__pyx_t_float_complex)_Complex_I; - } - #endif -#else - static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) { - __pyx_t_float_complex z; - z.real = x; - z.imag = y; - return z; - } -#endif - -/* Arithmetic */ - #if CYTHON_CCOMPLEX -#else - static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - return (a.real == b.real) && (a.imag == b.imag); - } - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - __pyx_t_float_complex z; - z.real = a.real + b.real; - z.imag = a.imag + b.imag; - return z; - } - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - __pyx_t_float_complex z; - z.real = a.real - b.real; - z.imag = a.imag - b.imag; - return z; - } - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - __pyx_t_float_complex z; - z.real = a.real * b.real - a.imag * b.imag; - z.imag = a.real * b.imag + a.imag * b.real; - return z; - } - #if 1 - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - if (b.imag == 0) { - return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); - } else if (fabsf(b.real) >= fabsf(b.imag)) { - if (b.real == 0 && b.imag == 0) { - return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag); - } else { - float r = b.imag / b.real; - float s = (float)(1.0) / (b.real + b.imag * r); - return __pyx_t_float_complex_from_parts( - (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); - } - } else { - float r = b.real / b.imag; - float s = (float)(1.0) / (b.imag + b.real * r); - return __pyx_t_float_complex_from_parts( - (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); - } - } - #else - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - if (b.imag == 0) { - return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real); - } else { - float denom = b.real * b.real + b.imag * b.imag; - return __pyx_t_float_complex_from_parts( - (a.real * b.real + a.imag * b.imag) / denom, - (a.imag * b.real - a.real * b.imag) / denom); - } - } - #endif - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) { - __pyx_t_float_complex z; - z.real = -a.real; - z.imag = -a.imag; - return z; - } - static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) { - return (a.real == 0) && (a.imag == 0); - } - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) { - __pyx_t_float_complex z; - z.real = a.real; - z.imag = -a.imag; - return z; - } - #if 1 - static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) { - #if !defined(HAVE_HYPOT) || defined(_MSC_VER) - return sqrtf(z.real*z.real + z.imag*z.imag); - #else - return hypotf(z.real, z.imag); - #endif - } - static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) { - __pyx_t_float_complex z; - float r, lnr, theta, z_r, z_theta; - if (b.imag == 0 && b.real == (int)b.real) { - if (b.real < 0) { - float denom = a.real * a.real + a.imag * a.imag; - a.real = a.real / denom; - a.imag = -a.imag / denom; - b.real = -b.real; - } - switch ((int)b.real) { - case 0: - z.real = 1; - z.imag = 0; - return z; - case 1: - return a; - case 2: - return __Pyx_c_prod_float(a, a); - case 3: - z = __Pyx_c_prod_float(a, a); - return __Pyx_c_prod_float(z, a); - case 4: - z = __Pyx_c_prod_float(a, a); - return __Pyx_c_prod_float(z, z); - } - } - if (a.imag == 0) { - if (a.real == 0) { - return a; - } else if ((b.imag == 0) && (a.real >= 0)) { - z.real = powf(a.real, b.real); - z.imag = 0; - return z; - } else if (a.real > 0) { - r = a.real; - theta = 0; - } else { - r = -a.real; - theta = atan2f(0.0, -1.0); - } - } else { - r = __Pyx_c_abs_float(a); - theta = atan2f(a.imag, a.real); - } - lnr = logf(r); - z_r = expf(lnr * b.real - theta * b.imag); - z_theta = theta * b.real + lnr * b.imag; - z.real = z_r * cosf(z_theta); - z.imag = z_r * sinf(z_theta); - return z; - } - #endif -#endif - -/* Declarations */ - #if CYTHON_CCOMPLEX - #ifdef __cplusplus - static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { - return ::std::complex< double >(x, y); - } - #else - static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { - return x + y*(__pyx_t_double_complex)_Complex_I; - } - #endif -#else - static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) { - __pyx_t_double_complex z; - z.real = x; - z.imag = y; - return z; - } -#endif - -/* Arithmetic */ - #if CYTHON_CCOMPLEX -#else - static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - return (a.real == b.real) && (a.imag == b.imag); - } - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - __pyx_t_double_complex z; - z.real = a.real + b.real; - z.imag = a.imag + b.imag; - return z; - } - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - __pyx_t_double_complex z; - z.real = a.real - b.real; - z.imag = a.imag - b.imag; - return z; - } - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - __pyx_t_double_complex z; - z.real = a.real * b.real - a.imag * b.imag; - z.imag = a.real * b.imag + a.imag * b.real; - return z; - } - #if 1 - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - if (b.imag == 0) { - return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); - } else if (fabs(b.real) >= fabs(b.imag)) { - if (b.real == 0 && b.imag == 0) { - return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag); - } else { - double r = b.imag / b.real; - double s = (double)(1.0) / (b.real + b.imag * r); - return __pyx_t_double_complex_from_parts( - (a.real + a.imag * r) * s, (a.imag - a.real * r) * s); - } - } else { - double r = b.real / b.imag; - double s = (double)(1.0) / (b.imag + b.real * r); - return __pyx_t_double_complex_from_parts( - (a.real * r + a.imag) * s, (a.imag * r - a.real) * s); - } - } - #else - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - if (b.imag == 0) { - return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real); - } else { - double denom = b.real * b.real + b.imag * b.imag; - return __pyx_t_double_complex_from_parts( - (a.real * b.real + a.imag * b.imag) / denom, - (a.imag * b.real - a.real * b.imag) / denom); - } - } - #endif - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) { - __pyx_t_double_complex z; - z.real = -a.real; - z.imag = -a.imag; - return z; - } - static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) { - return (a.real == 0) && (a.imag == 0); - } - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) { - __pyx_t_double_complex z; - z.real = a.real; - z.imag = -a.imag; - return z; - } - #if 1 - static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) { - #if !defined(HAVE_HYPOT) || defined(_MSC_VER) - return sqrt(z.real*z.real + z.imag*z.imag); - #else - return hypot(z.real, z.imag); - #endif - } - static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) { - __pyx_t_double_complex z; - double r, lnr, theta, z_r, z_theta; - if (b.imag == 0 && b.real == (int)b.real) { - if (b.real < 0) { - double denom = a.real * a.real + a.imag * a.imag; - a.real = a.real / denom; - a.imag = -a.imag / denom; - b.real = -b.real; - } - switch ((int)b.real) { - case 0: - z.real = 1; - z.imag = 0; - return z; - case 1: - return a; - case 2: - return __Pyx_c_prod_double(a, a); - case 3: - z = __Pyx_c_prod_double(a, a); - return __Pyx_c_prod_double(z, a); - case 4: - z = __Pyx_c_prod_double(a, a); - return __Pyx_c_prod_double(z, z); - } - } - if (a.imag == 0) { - if (a.real == 0) { - return a; - } else if ((b.imag == 0) && (a.real >= 0)) { - z.real = pow(a.real, b.real); - z.imag = 0; - return z; - } else if (a.real > 0) { - r = a.real; - theta = 0; - } else { - r = -a.real; - theta = atan2(0.0, -1.0); - } - } else { - r = __Pyx_c_abs_double(a); - theta = atan2(a.imag, a.real); - } - lnr = log(r); - z_r = exp(lnr * b.real - theta * b.imag); - z_theta = theta * b.real + lnr * b.imag; - z.real = z_r * cos(z_theta); - z.imag = z_r * sin(z_theta); - return z; - } - #endif -#endif - -/* MemviewSliceCopyTemplate */ - static __Pyx_memviewslice -__pyx_memoryview_copy_new_contig(const __Pyx_memviewslice *from_mvs, - const char *mode, int ndim, - size_t sizeof_dtype, int contig_flag, - int dtype_is_object) -{ - __Pyx_RefNannyDeclarations - int i; - __Pyx_memviewslice new_mvs = { 0, 0, { 0 }, { 0 }, { 0 } }; - struct __pyx_memoryview_obj *from_memview = from_mvs->memview; - Py_buffer *buf = &from_memview->view; - PyObject *shape_tuple = NULL; - PyObject *temp_int = NULL; - struct __pyx_array_obj *array_obj = NULL; - struct __pyx_memoryview_obj *memview_obj = NULL; - __Pyx_RefNannySetupContext("__pyx_memoryview_copy_new_contig", 0); - for (i = 0; i < ndim; i++) { - if (unlikely(from_mvs->suboffsets[i] >= 0)) { - PyErr_Format(PyExc_ValueError, "Cannot copy memoryview slice with " - "indirect dimensions (axis %d)", i); - goto fail; - } - } - shape_tuple = PyTuple_New(ndim); - if (unlikely(!shape_tuple)) { - goto fail; - } - __Pyx_GOTREF(shape_tuple); - for(i = 0; i < ndim; i++) { - temp_int = PyInt_FromSsize_t(from_mvs->shape[i]); - if(unlikely(!temp_int)) { - goto fail; - } else { - PyTuple_SET_ITEM(shape_tuple, i, temp_int); - temp_int = NULL; - } - } - array_obj = __pyx_array_new(shape_tuple, sizeof_dtype, buf->format, (char *) mode, NULL); - if (unlikely(!array_obj)) { - goto fail; - } - __Pyx_GOTREF(array_obj); - memview_obj = (struct __pyx_memoryview_obj *) __pyx_memoryview_new( - (PyObject *) array_obj, contig_flag, - dtype_is_object, - from_mvs->memview->typeinfo); - if (unlikely(!memview_obj)) - goto fail; - if (unlikely(__Pyx_init_memviewslice(memview_obj, ndim, &new_mvs, 1) < 0)) - goto fail; - if (unlikely(__pyx_memoryview_copy_contents(*from_mvs, new_mvs, ndim, ndim, - dtype_is_object) < 0)) - goto fail; - goto no_fail; -fail: - __Pyx_XDECREF(new_mvs.memview); - new_mvs.memview = NULL; - new_mvs.data = NULL; -no_fail: - __Pyx_XDECREF(shape_tuple); - __Pyx_XDECREF(temp_int); - __Pyx_XDECREF(array_obj); - __Pyx_RefNannyFinishContext(); - return new_mvs; -} - -/* CIntToPy */ - static CYTHON_INLINE PyObject* __Pyx_PyInt_From_npy_int64(npy_int64 value) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const npy_int64 neg_one = (npy_int64) -1, const_zero = (npy_int64) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(npy_int64) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(npy_int64) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(npy_int64) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(npy_int64) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(npy_int64) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(npy_int64), - little, !is_unsigned); - } -} - -/* CIntFromPy */ - static CYTHON_INLINE npy_int64 __Pyx_PyInt_As_npy_int64(PyObject *x) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const npy_int64 neg_one = (npy_int64) -1, const_zero = (npy_int64) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(npy_int64) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(npy_int64, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (npy_int64) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (npy_int64) 0; - case 1: __PYX_VERIFY_RETURN_INT(npy_int64, digit, digits[0]) - case 2: - if (8 * sizeof(npy_int64) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) >= 2 * PyLong_SHIFT) { - return (npy_int64) (((((npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(npy_int64) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) >= 3 * PyLong_SHIFT) { - return (npy_int64) (((((((npy_int64)digits[2]) << PyLong_SHIFT) | (npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(npy_int64) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) >= 4 * PyLong_SHIFT) { - return (npy_int64) (((((((((npy_int64)digits[3]) << PyLong_SHIFT) | (npy_int64)digits[2]) << PyLong_SHIFT) | (npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (npy_int64) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(npy_int64) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(npy_int64, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(npy_int64) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(npy_int64, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (npy_int64) 0; - case -1: __PYX_VERIFY_RETURN_INT(npy_int64, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(npy_int64, digit, +digits[0]) - case -2: - if (8 * sizeof(npy_int64) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) - 1 > 2 * PyLong_SHIFT) { - return (npy_int64) (((npy_int64)-1)*(((((npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(npy_int64) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) - 1 > 2 * PyLong_SHIFT) { - return (npy_int64) ((((((npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(npy_int64) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) - 1 > 3 * PyLong_SHIFT) { - return (npy_int64) (((npy_int64)-1)*(((((((npy_int64)digits[2]) << PyLong_SHIFT) | (npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(npy_int64) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) - 1 > 3 * PyLong_SHIFT) { - return (npy_int64) ((((((((npy_int64)digits[2]) << PyLong_SHIFT) | (npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(npy_int64) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) - 1 > 4 * PyLong_SHIFT) { - return (npy_int64) (((npy_int64)-1)*(((((((((npy_int64)digits[3]) << PyLong_SHIFT) | (npy_int64)digits[2]) << PyLong_SHIFT) | (npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(npy_int64) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(npy_int64, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(npy_int64) - 1 > 4 * PyLong_SHIFT) { - return (npy_int64) ((((((((((npy_int64)digits[3]) << PyLong_SHIFT) | (npy_int64)digits[2]) << PyLong_SHIFT) | (npy_int64)digits[1]) << PyLong_SHIFT) | (npy_int64)digits[0]))); - } - } - break; - } -#endif - if (sizeof(npy_int64) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(npy_int64, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(npy_int64) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(npy_int64, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - npy_int64 val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (npy_int64) -1; - } - } else { - npy_int64 val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (npy_int64) -1; - val = __Pyx_PyInt_As_npy_int64(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to npy_int64"); - return (npy_int64) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to npy_int64"); - return (npy_int64) -1; -} - -/* CIntFromPy */ - static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const int neg_one = (int) -1, const_zero = (int) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(int) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (int) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { - return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { - return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { - return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (int) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(int) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) - case -2: - if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - } -#endif - if (sizeof(int) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - int val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (int) -1; - } - } else { - int val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (int) -1; - val = __Pyx_PyInt_As_int(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to int"); - return (int) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to int"); - return (int) -1; -} - -/* CIntFromPy */ - static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const long neg_one = (long) -1, const_zero = (long) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(long) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (long) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { - return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { - return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { - return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (long) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(long) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) - case -2: - if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - } -#endif - if (sizeof(long) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - long val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (long) -1; - } - } else { - long val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (long) -1; - val = __Pyx_PyInt_As_long(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to long"); - return (long) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long) -1; -} - -/* CIntToPy */ - static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const int neg_one = (int) -1, const_zero = (int) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(int) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(int) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(int) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(int), - little, !is_unsigned); - } -} - -/* CIntToPy */ - static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const long neg_one = (long) -1, const_zero = (long) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - -/* CIntFromPy */ - static CYTHON_INLINE char __Pyx_PyInt_As_char(PyObject *x) { -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif - const char neg_one = (char) -1, const_zero = (char) 0; -#ifdef __Pyx_HAS_GCC_DIAGNOSTIC -#pragma GCC diagnostic pop -#endif - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(char) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(char, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (char) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (char) 0; - case 1: __PYX_VERIFY_RETURN_INT(char, digit, digits[0]) - case 2: - if (8 * sizeof(char) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) >= 2 * PyLong_SHIFT) { - return (char) (((((char)digits[1]) << PyLong_SHIFT) | (char)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(char) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) >= 3 * PyLong_SHIFT) { - return (char) (((((((char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(char) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) >= 4 * PyLong_SHIFT) { - return (char) (((((((((char)digits[3]) << PyLong_SHIFT) | (char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (char) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(char) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(char, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(char) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(char, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (char) 0; - case -1: __PYX_VERIFY_RETURN_INT(char, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(char, digit, +digits[0]) - case -2: - if (8 * sizeof(char) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) - 1 > 2 * PyLong_SHIFT) { - return (char) (((char)-1)*(((((char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(char) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) - 1 > 2 * PyLong_SHIFT) { - return (char) ((((((char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(char) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) - 1 > 3 * PyLong_SHIFT) { - return (char) (((char)-1)*(((((((char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(char) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) - 1 > 3 * PyLong_SHIFT) { - return (char) ((((((((char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(char) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) - 1 > 4 * PyLong_SHIFT) { - return (char) (((char)-1)*(((((((((char)digits[3]) << PyLong_SHIFT) | (char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(char) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(char, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(char) - 1 > 4 * PyLong_SHIFT) { - return (char) ((((((((((char)digits[3]) << PyLong_SHIFT) | (char)digits[2]) << PyLong_SHIFT) | (char)digits[1]) << PyLong_SHIFT) | (char)digits[0]))); - } - } - break; - } -#endif - if (sizeof(char) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(char, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(char) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(char, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - char val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (char) -1; - } - } else { - char val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (char) -1; - val = __Pyx_PyInt_As_char(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to char"); - return (char) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to char"); - return (char) -1; -} - -/* CheckBinaryVersion */ - static int __Pyx_check_binary_version(void) { - char ctversion[5]; - int same=1, i, found_dot; - const char* rt_from_call = Py_GetVersion(); - PyOS_snprintf(ctversion, 5, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); - found_dot = 0; - for (i = 0; i < 4; i++) { - if (!ctversion[i]) { - same = (rt_from_call[i] < '0' || rt_from_call[i] > '9'); - break; - } - if (rt_from_call[i] != ctversion[i]) { - same = 0; - break; - } - } - if (!same) { - char rtversion[5] = {'\0'}; - char message[200]; - for (i=0; i<4; ++i) { - if (rt_from_call[i] == '.') { - if (found_dot) break; - found_dot = 1; - } else if (rt_from_call[i] < '0' || rt_from_call[i] > '9') { - break; - } - rtversion[i] = rt_from_call[i]; - } - PyOS_snprintf(message, sizeof(message), - "compiletime version %s of module '%.100s' " - "does not match runtime version %s", - ctversion, __Pyx_MODULE_NAME, rtversion); - return PyErr_WarnEx(NULL, message, 1); - } - return 0; -} - -/* FunctionImport */ - #ifndef __PYX_HAVE_RT_ImportFunction -#define __PYX_HAVE_RT_ImportFunction -static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig) { - PyObject *d = 0; - PyObject *cobj = 0; - union { - void (*fp)(void); - void *p; - } tmp; - d = PyObject_GetAttrString(module, (char *)"__pyx_capi__"); - if (!d) - goto bad; - cobj = PyDict_GetItemString(d, funcname); - if (!cobj) { - PyErr_Format(PyExc_ImportError, - "%.200s does not export expected C function %.200s", - PyModule_GetName(module), funcname); - goto bad; - } -#if PY_VERSION_HEX >= 0x02070000 - if (!PyCapsule_IsValid(cobj, sig)) { - PyErr_Format(PyExc_TypeError, - "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", - PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); - goto bad; - } - tmp.p = PyCapsule_GetPointer(cobj, sig); -#else - {const char *desc, *s1, *s2; - desc = (const char *)PyCObject_GetDesc(cobj); - if (!desc) - goto bad; - s1 = desc; s2 = sig; - while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } - if (*s1 != *s2) { - PyErr_Format(PyExc_TypeError, - "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", - PyModule_GetName(module), funcname, sig, desc); - goto bad; - } - tmp.p = PyCObject_AsVoidPtr(cobj);} -#endif - *f = tmp.fp; - if (!(*f)) - goto bad; - Py_DECREF(d); - return 0; -bad: - Py_XDECREF(d); - return -1; -} -#endif - -/* InitStrings */ - static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { - while (t->p) { - #if PY_MAJOR_VERSION < 3 - if (t->is_unicode) { - *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); - } else if (t->intern) { - *t->p = PyString_InternFromString(t->s); - } else { - *t->p = PyString_FromStringAndSize(t->s, t->n - 1); - } - #else - if (t->is_unicode | t->is_str) { - if (t->intern) { - *t->p = PyUnicode_InternFromString(t->s); - } else if (t->encoding) { - *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); - } else { - *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); - } - } else { - *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); - } - #endif - if (!*t->p) - return -1; - if (PyObject_Hash(*t->p) == -1) - return -1; - ++t; - } - return 0; -} - -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { - return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); -} -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { - Py_ssize_t ignore; - return __Pyx_PyObject_AsStringAndSize(o, &ignore); -} -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -#if !CYTHON_PEP393_ENABLED -static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - char* defenc_c; - PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); - if (!defenc) return NULL; - defenc_c = PyBytes_AS_STRING(defenc); -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - { - char* end = defenc_c + PyBytes_GET_SIZE(defenc); - char* c; - for (c = defenc_c; c < end; c++) { - if ((unsigned char) (*c) >= 128) { - PyUnicode_AsASCIIString(o); - return NULL; - } - } - } -#endif - *length = PyBytes_GET_SIZE(defenc); - return defenc_c; -} -#else -static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - if (likely(PyUnicode_IS_ASCII(o))) { - *length = PyUnicode_GET_LENGTH(o); - return PyUnicode_AsUTF8(o); - } else { - PyUnicode_AsASCIIString(o); - return NULL; - } -#else - return PyUnicode_AsUTF8AndSize(o, length); -#endif -} -#endif -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT - if ( -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - __Pyx_sys_getdefaultencoding_not_ascii && -#endif - PyUnicode_Check(o)) { - return __Pyx_PyUnicode_AsStringAndSize(o, length); - } else -#endif -#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) - if (PyByteArray_Check(o)) { - *length = PyByteArray_GET_SIZE(o); - return PyByteArray_AS_STRING(o); - } else -#endif - { - char* result; - int r = PyBytes_AsStringAndSize(o, &result, length); - if (unlikely(r < 0)) { - return NULL; - } else { - return result; - } - } -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { - int is_true = x == Py_True; - if (is_true | (x == Py_False) | (x == Py_None)) return is_true; - else return PyObject_IsTrue(x); -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { - int retval; - if (unlikely(!x)) return -1; - retval = __Pyx_PyObject_IsTrue(x); - Py_DECREF(x); - return retval; -} -static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(result)) { - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__int__ returned non-int (type %.200s). " - "The ability to return an instance of a strict subclass of int " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(result)->tp_name)) { - Py_DECREF(result); - return NULL; - } - return result; - } -#endif - PyErr_Format(PyExc_TypeError, - "__%.4s__ returned non-%.4s (type %.200s)", - type_name, type_name, Py_TYPE(result)->tp_name); - Py_DECREF(result); - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { -#if CYTHON_USE_TYPE_SLOTS - PyNumberMethods *m; -#endif - const char *name = NULL; - PyObject *res = NULL; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x) || PyLong_Check(x))) -#else - if (likely(PyLong_Check(x))) -#endif - return __Pyx_NewRef(x); -#if CYTHON_USE_TYPE_SLOTS - m = Py_TYPE(x)->tp_as_number; - #if PY_MAJOR_VERSION < 3 - if (m && m->nb_int) { - name = "int"; - res = m->nb_int(x); - } - else if (m && m->nb_long) { - name = "long"; - res = m->nb_long(x); - } - #else - if (likely(m && m->nb_int)) { - name = "int"; - res = m->nb_int(x); - } - #endif -#else - if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { - res = PyNumber_Int(x); - } -#endif - if (likely(res)) { -#if PY_MAJOR_VERSION < 3 - if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { -#else - if (unlikely(!PyLong_CheckExact(res))) { -#endif - return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); - } - } - else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "an integer is required"); - } - return res; -} -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { - Py_ssize_t ival; - PyObject *x; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(b))) { - if (sizeof(Py_ssize_t) >= sizeof(long)) - return PyInt_AS_LONG(b); - else - return PyInt_AsSsize_t(b); - } -#endif - if (likely(PyLong_CheckExact(b))) { - #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)b)->ob_digit; - const Py_ssize_t size = Py_SIZE(b); - if (likely(__Pyx_sst_abs(size) <= 1)) { - ival = likely(size) ? digits[0] : 0; - if (size == -1) ival = -ival; - return ival; - } else { - switch (size) { - case 2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - } - } - #endif - return PyLong_AsSsize_t(b); - } - x = PyNumber_Index(b); - if (!x) return -1; - ival = PyInt_AsSsize_t(x); - Py_DECREF(x); - return ival; -} -static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) { - if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) { - return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o); -#if PY_MAJOR_VERSION < 3 - } else if (likely(PyInt_CheckExact(o))) { - return PyInt_AS_LONG(o); -#endif - } else { - Py_ssize_t ival; - PyObject *x; - x = PyNumber_Index(o); - if (!x) return -1; - ival = PyInt_AsLong(x); - Py_DECREF(x); - return ival; - } -} -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { - return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); -} -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { - return PyInt_FromSize_t(ival); -} - - -#endif /* Py_PYTHON_H */ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..bc779d84 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,78 @@ +[build-system] +requires = ["setuptools>=64", + "setuptools_scm>=8", +# "setuptools_scm_git_archive", + "numpy>=1.24.4", + "cython>=0.29", + "setuptools>=61.0", + "scipy>=1.10.1"] +build-backend = "setuptools.build_meta" + +[project] +name = "pygom" +dynamic = ["version"] +requires-python = ">= 3.9" + +dependencies = [ + "setuptools>=64", + "setuptools_scm>=8", + "setuptools_scm_git_archive", + "dask[complete]>=0.13.0", + "graphviz>=0.4.9", + "matplotlib>=1.0.0", + "numpy>=1.24.4", + "pandas>=2.2.2", + "python-dateutil>=2.0.0", + "scipy>=1.10.1", + "sympy>=1.0.0", + "numpydoc>=0.6.0", + "cython>=0.29" +] +authors = [ + {name="Edwin Tye"}, + {name="Thomas Finnie", email="thomas.finnie@ukhsa.gov.uk"}, + {name="Hannah Williams"}, + {name="Jonty Carruthers"}, + {name="Martin Grunnill"}, + {name="Joe Gibson", email="joseph.gibson@ukhsa.gov.uk"} +] + +description = "ODE modeling in Python." +readme = "README.md" + +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: GNU General Public License v2 (GPLv2)", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering", + "Topic :: Scientific/Engineering :: Mathematics", + "Topic :: Scientific/Engineering :: Physics", + "Development Status :: 5 - Production/Stable" +] + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools.dynamic] +readme = {file = ["README.rst"]} + +[project.urls] +Homepage = "http://ukhsa-collaboration.github.io/pygom/md/intro.html" +Issues = "https://github.com/ukhsa-collaboration/pygom/issues" + +# Options for wheel building with cibuildwheel +[tool.cibuildwheel] +# Normal options, etc. +manylinux-x86_64-image = "manylinux2014" + +# '[tool.setuptools.scm]' needs to be the last line because +# we do an append operation in the deploy.yaml GitHub Actions workflow +# so that we are able to push to test.pypi.org with a proper version +# number +[tool.setuptools_scm] +#version_file = "pygom/_version.py" diff --git a/requirements.txt b/requirements.txt index 55d26c1b..9e410a61 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ dask[complete]>=0.13.0 graphviz>=0.4.9 matplotlib>=1.0.0 -numpy>=1.6.0 -pandas>=0.15.0 +numpy>=2.0.0 +pandas>=2.2.2 python-dateutil>=2.0.0 scipy>=1.4.1 sympy>=1.0.0 @@ -10,5 +10,3 @@ numpydoc>=0.6.0 sphinx>=1.4.1 sphinx_rtd_theme>=0.2.0 cython>=0.29 -nbsphinx -jupyter-book>=0.15.0 diff --git a/setup.py b/setup.py index 934baa63..cf81d157 100644 --- a/setup.py +++ b/setup.py @@ -1,106 +1,21 @@ #!/bin/env python -""" -@author: Edwin Tye (Edwin.Tye@phe.gov.uk) -""" -import re -import subprocess -from setuptools import setup -from setuptools.extension import Extension - -try: - import numpy -except ImportError: - raise ImportError('numpy needs to be installed before PyGOM can be ' - 'installed. Try installing with "pip install numpy" ' - 'before installing PyGOM.') - -## For the cython parts ### -try: - from Cython.Distutils import build_ext -except ImportError: - use_cython = False -else: - use_cython = True - -cmdclass = { } -ext_modules = [ ] - -#For this to work the .c files are not include in GIT except in the release -#release branch (the c files would be created using python setup.py sdist) -if use_cython: - ext_modules += [ - Extension("pygom.model._tau_leap", - ["pygom/model/_tau_leap.pyx"], - include_dirs=[numpy.get_include()], +from setuptools import setup, Extension +from Cython.Build import cythonize +from Cython.Compiler import Options +import numpy + +# Options for the compiled modules +Options.docstrings = True +Options.annotate = False + +extensions = [ + Extension("pygom.model._tau_leap", + ["src/pygom/model/_tau_leap.pyx"], + include_dirs=[numpy.get_include()], + extra_compile_args=['-std=c99'], # extra_compile_args=['-fopenmp'], # extra_link_args=['-fopenmp']), -) - ] - cmdclass.update({'build_ext': build_ext}) -else: -# raise ImportError('You will need Cython installed to create' -# 'the c extensions. Try installing with' -# '"pip install cython" before installing PyGOM.') - ext_modules += [ - Extension("pygom.model._tau_leap", - ["pygom/model/_tau_leap.c"], - include_dirs=[numpy.get_include()], -# extra_compile_args=['-fopenmp'], -# extra_link_args=['-fopenmp']), -) - ] -package_data = { - 'pygom.data': ['eg1.json'],# An example epijson file - } - -# read the requirements file and have use that to populate install_requires -requires = open("requirements.txt").read().strip().split("\n") -install_requires = [] -extras_require = {} -for r in requires: - if ";" in r: - # requirements.txt conditional dependencies need to be reformatted for wheels - # to the form: `'[extra_name]:condition' : ['requirements']` - req, cond = r.split(";", 1) - cond = ":" + cond - cond_reqs = extras_require.setdefault(cond, []) - cond_reqs.append(req) - else: - install_requires.append(r) - -with open('README.rst', 'r') as f: - readme = f.read() - -setup_requires = [ - 'setuptools-scm>=3.2.0', - 'setuptools_scm_git_archive', - 'numpy>=1.12.0' - ] + ) +] -setup( - name='pygom', - use_scm_version=True, - description='ODE modeling in Python', - long_description=readme, - long_description_content_type='text/x-rst', - license="GPL2", - url='https://github.com/PublicHealthEngland/pygom', - author="Thomas Finnie", - author_email="Thomas.Finnie@phe.gov.uk", - packages=[ - 'pygom', - 'pygom.model', - 'pygom.model.ode_utils', - 'pygom.loss', - 'pygom.utilR' - ], - package_data=package_data, - include_package_data=True, - cmdclass=cmdclass, - ext_modules=ext_modules, - install_requires=install_requires, - extras_require=extras_require, - setup_requires=setup_requires, - test_suite='tests', - scripts=[] - ) +setup(ext_modules=cythonize(extensions, compiler_directives={"language_level": 3, "profile": False})) diff --git a/pygom/__init__.py b/src/pygom/__init__.py similarity index 100% rename from pygom/__init__.py rename to src/pygom/__init__.py diff --git a/pygom/approximate_bayesian_computation/__init__.py b/src/pygom/approximate_bayesian_computation/__init__.py similarity index 100% rename from pygom/approximate_bayesian_computation/__init__.py rename to src/pygom/approximate_bayesian_computation/__init__.py diff --git a/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py b/src/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py similarity index 99% rename from pygom/approximate_bayesian_computation/approximate_bayesian_computation.py rename to src/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py index 01114f32..440b2a35 100644 --- a/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py +++ b/src/pygom/approximate_bayesian_computation/approximate_bayesian_computation.py @@ -137,7 +137,7 @@ def create_loss(loss_type, parameters, ode, x0, t0, t, y, state_name, state_weight=None, sigma=None): """ Parameters (see also class `BaseLoss`) - ---------- + -------------------------------------- loss_type: class `BaseLoss` parameters: list a list of objects of class `Parameter` @@ -155,7 +155,8 @@ def create_loss(loss_type, parameters, ode, x0, t0, t, y, state_name, the state(s) which the observations came from state_weight: array like weight for the observations - sigma: + sigma: numeric + sigma for `NormalLoss` function """ assert t0 != t[0], "Make sure that the times, t, do not include t0" assert all(param.name in (ode.param_list+ode.state_list) for param in parameters), "Parameters have been provided that are not in the model" @@ -167,7 +168,7 @@ def create_loss(loss_type, parameters, ode, x0, t0, t, y, state_name, if loss_type == "SquareLoss": return SquareLoss(theta, ode, x0, t0, t, y, state_name, state_weight, target_param, target_state) - elif loss_type == NormalLoss: + elif loss_type == "NormalLoss": return NormalLoss(theta=theta, ode=ode, x0=x0, @@ -179,8 +180,8 @@ def create_loss(loss_type, parameters, ode, x0, t0, t, y, state_name, target_param=target_param, target_state=target_state) - elif loss_type == PoissonLoss: - return PoissonLoss(theta, ode, x0, t0, t, y, state_name, target_param, target_state) + elif loss_type == "PoissonLoss": + return PoissonLoss(theta, ode, x0, t0, t, y, state_name, state_weight, target_param, target_state) else: raise ValueError("Please choose from the available loss functions") @@ -474,7 +475,7 @@ def _perform_generation(self, def continue_posterior_sample(self, N, tol, G=1, q=None, M=None, progress=False): """ Parameters (same as get_posterior_sample) - ---------- + ----------------------------------------- N: integer the number of samples in each generation tol: float or array like @@ -736,4 +737,4 @@ def _log_parameters(self, params): def _vprod(self,a1,a2): diff = (a1-a2).reshape((self.numParam,1)) return np.dot(diff,diff.T) - \ No newline at end of file + diff --git a/pygom/data/eg1.json b/src/pygom/data/eg1.json similarity index 100% rename from pygom/data/eg1.json rename to src/pygom/data/eg1.json diff --git a/pygom/loss/.gitignore b/src/pygom/loss/.gitignore similarity index 100% rename from pygom/loss/.gitignore rename to src/pygom/loss/.gitignore diff --git a/pygom/loss/__init__.py b/src/pygom/loss/__init__.py similarity index 100% rename from pygom/loss/__init__.py rename to src/pygom/loss/__init__.py diff --git a/pygom/loss/base_loss.py b/src/pygom/loss/base_loss.py similarity index 100% rename from pygom/loss/base_loss.py rename to src/pygom/loss/base_loss.py diff --git a/pygom/loss/confidence_interval.py b/src/pygom/loss/confidence_interval.py similarity index 98% rename from pygom/loss/confidence_interval.py rename to src/pygom/loss/confidence_interval.py index 769d0126..b44b7799 100644 --- a/pygom/loss/confidence_interval.py +++ b/src/pygom/loss/confidence_interval.py @@ -301,8 +301,8 @@ def profile(obj, alpha, theta=None, lb=None, ub=None, full_output=False): funcFgradient = _profileFgradient(theta, i, alpha, obj) funcFhessian = _profileFhessian(theta, i, alpha, obj) - lbT = np.ones(p)*-np.Inf if lb is None else lb.copy() - ubT = np.ones(p)*np.Inf if ub is None else ub.copy() + lbT = np.ones(p)*-np.inf if lb is None else lb.copy() + ubT = np.ones(p)*np.inf if ub is None else ub.copy() ubT[i] = theta[i] @@ -318,8 +318,8 @@ def profile(obj, alpha, theta=None, lb=None, ub=None, full_output=False): xhatL, lbT, ubT, True) ## re-adjust the bounds for the other side - lbT = np.ones(p)*-np.Inf if lb is None else lb.copy() - ubT = np.ones(p)*np.Inf if ub is None else ub.copy() + lbT = np.ones(p)*-np.inf if lb is None else lb.copy() + ubT = np.ones(p)*np.inf if ub is None else ub.copy() lbT[i] = theta[i] diff --git a/pygom/loss/epijson_loss.py b/src/pygom/loss/epijson_loss.py similarity index 100% rename from pygom/loss/epijson_loss.py rename to src/pygom/loss/epijson_loss.py diff --git a/pygom/loss/get_init.py b/src/pygom/loss/get_init.py similarity index 98% rename from pygom/loss/get_init.py rename to src/pygom/loss/get_init.py index 78f81ed9..56cb5247 100644 --- a/pygom/loss/get_init.py +++ b/src/pygom/loss/get_init.py @@ -2,7 +2,11 @@ import numpy as np from scipy.interpolate import UnivariateSpline -from scipy.integrate import simps +# TODO: For newer <1.14.0 versions of scipy. Once established remove and leave only except part +try: + from scipy.integrate import simps +except ImportError: + from scipy.integrate import simpson as simps from scipy.optimize import leastsq, minimize_scalar def get_init(y, t, ode, theta=None, full_output=False): diff --git a/pygom/loss/loss_type.py b/src/pygom/loss/loss_type.py similarity index 98% rename from pygom/loss/loss_type.py rename to src/pygom/loss/loss_type.py index 8cad7161..00cdf59a 100644 --- a/pygom/loss/loss_type.py +++ b/src/pygom/loss/loss_type.py @@ -81,7 +81,8 @@ def residual(self, yhat, apply_weighting=True): else: resid = self._y - yhat if apply_weighting: - resid *= self._w + #resid *= self._w + resid = resid*self._w # above multiplication caused error return resid @@ -369,7 +370,7 @@ def diff_loss(self, yhat, apply_weighting=True): Returns ------- first_deriv_yhat: array like - :math:`\\mathcal\\frac{a \\left(\\hat{y} - y\\right)}{\\hat{y}^{2}}` + :math:`\\frac{a \\left(\\hat{y} - y\\right)}{\\hat{y}^{2}}` ''' shape = self._shape @@ -393,7 +394,7 @@ def diff2Loss(self, yhat, apply_weighting=True): Returns ------- scnd_deriv_yhat: array like - :math:`\\mathcal\\frac{a \\left(- \\hat{y} + 2 y\\right)}{\\hat{y}^{3}}` + :math:`\\frac{a \\left(- \\hat{y} + 2 y\\right)}{\\hat{y}^{3}}` ''' if len(yhat.shape) > 1: diff --git a/pygom/loss/ode_loss.py b/src/pygom/loss/ode_loss.py similarity index 100% rename from pygom/loss/ode_loss.py rename to src/pygom/loss/ode_loss.py diff --git a/pygom/loss/read_epijson.py b/src/pygom/loss/read_epijson.py similarity index 100% rename from pygom/loss/read_epijson.py rename to src/pygom/loss/read_epijson.py diff --git a/pygom/model/__init__.py b/src/pygom/model/__init__.py similarity index 100% rename from pygom/model/__init__.py rename to src/pygom/model/__init__.py diff --git a/pygom/model/_model_errors.py b/src/pygom/model/_model_errors.py similarity index 100% rename from pygom/model/_model_errors.py rename to src/pygom/model/_model_errors.py diff --git a/pygom/model/_model_verification.py b/src/pygom/model/_model_verification.py similarity index 100% rename from pygom/model/_model_verification.py rename to src/pygom/model/_model_verification.py diff --git a/pygom/model/_ode_composition.py b/src/pygom/model/_ode_composition.py similarity index 73% rename from pygom/model/_ode_composition.py rename to src/pygom/model/_ode_composition.py index 5596cb65..69ea22cc 100644 --- a/pygom/model/_ode_composition.py +++ b/src/pygom/model/_ode_composition.py @@ -15,129 +15,10 @@ from .base_ode_model import BaseOdeModel from .transition import TransitionType -greekLetter = ('alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta', 'eta', 'theta', - 'iota', 'kappa', 'lambda', 'mu', 'nu', 'xi', 'omicron', 'pi', 'rho', - 'sigma', 'tau', 'upsilon', 'phi', 'chi', 'psi', 'omega') - - -def generateTransitionGraph(ode_model, file_name=None): - """ - Generates the transition graph in graphviz given an ode model with transitions - - Parameters - ---------- - ode_model: OperateOdeModel - an ode model object - file_name: str - location of the file, if none entered, then the default directory is used - - Returns - ------- - dot: graphviz object - """ - assert isinstance(ode_model, BaseOdeModel), "An ode model object required" - - from graphviz import Digraph - - if file_name is None: - dot = Digraph(comment='ode model') - else: - dot = Digraph(comment='ode model', filename=file_name) - - dot.body.extend(['rankdir=LR']) - - param = [str(p) for p in ode_model.param_list] - states = [str(s) for s in ode_model.state_list] - - for s in states: - dot.node(s) - - transition = ode_model.transition_list - bd_list = ode_model.birth_death_list - - for transition in (transition + bd_list): - s1 = transition.origin - eq = _makeEquationPretty(transition.equation, param) - - if transition.transition_type is TransitionType.T: - s2 = transition.destination - dot.edge(s1, s2, label=eq) - elif transition.transition_type is TransitionType.B: - # when we have a birth or death process, do not make the box - dot.node(eq, shape="plaintext", width="0", height="0", margin="0") - dot.edge(eq, s1) - elif transition.transition_type is TransitionType.D: - dot.node(eq, shape="plaintext", width="0", height="0", margin="0") - dot.edge(s1, eq) - else: - pass - - return dot - - -def _makeEquationPretty(eq, param): - """ - Make the equation suitable for graphviz format by converting - beta to β and remove all the multiplication sign - - We do not process ** and convert it to a superscript because - it is only possible with svg (which is a real pain to convert - back to png) and only available from graphviz versions after - 14 Oct 2011 - """ - for p in param: - if p.lower() in greekLetter: - eq = re.sub('(\\W?)(' + p + ')(\\W?)', '\\1&' + p + ';\\3', eq) - # eq = re.sub('\*{1}[^\*]', '', eq) - # eq = re.sub('([^\*]?)\*([^\*]?)', '\\1 \\2', eq) - # eq += " blahYo + haBoo" - return eq - - -def generateDirectedDependencyGraph(ode_matrix, transition=None): - """ - Returns a binary matrix that contains the direction of the transition in - a state - - Parameters - ---------- - ode_matrix: :class:`sympy.matrcies.MatrixBase` - A matrix of size [number of states x 1]. Obtained by - invoking :meth:`DeterministicOde.get_ode_eqn` - transition: list, optional - list of transitions. Can be generated by - :func:`getMatchingExpressionVector` - - Returns - ------- - G: :class:`numpy.ndarray` - Two dimensional array of size [number of state x number of transitions] - where each column has two entry, - -1 and 1 to indicate the direction of the transition and the state. - All column sum to one, i.e. transition must have a source and target. - """ - assert isinstance(ode_matrix, MatrixBase), \ - "Expecting a vector of expressions" - - if transition is None: - transition = getMatchingExpressionVector(ode_matrix, True) - else: - assert isinstance(transition, list), "Require a list of transitions" - - B = np.zeros((len(ode_matrix), len(transition))) - for i, a in enumerate(ode_matrix): - for j, transitionTuple in enumerate(transition): - t1, t2 = transitionTuple - if _hasExpression(a, t1): - B[i, j] += -1 # going out - if _hasExpression(a, t2): - B[i, j] += 1 # coming in - return B - - def getUnmatchedExpressionVector(expr_vec, full_output=False): """ - Return the unmatched expressions from a vector of equations + Return the unmatched expressions from a vector of ODE equations. + e.g [a+b, -a+c, -c+b-d] returns [b, -d, b] Parameters ---------- @@ -393,10 +274,17 @@ def stripBDFromOde(fx, bd_list=None): term_in_expr = list(map(lambda x: x in fxi.expand().args, bd_list)) for j, term in enumerate(bd_list): fx_copy[i] -= term if term_in_expr[j] else 0 - # simplify converts it to an ImmutableMatrix, so we make it into # a mutable object again because we want the expanded form - return sympy.Matrix(sympy.simplify(fx_copy)).expand() + + # simplify() causes issues when we have terms with denominators as + # it will try to give all terms a common denominator thus + # potentially masking terms which should be matched. + # We try leaving it out for now, but some thorough testing is required + # of the unroll pipeline. + + # return sympy.Matrix(sympy.simplify(fx_copy)).expand() + return sympy.Matrix(fx_copy).expand() def odeToPureTransition(fx, states, output_remain=False): @@ -441,7 +329,7 @@ def _odeToPureTransition(fx, terms=None, A=None): Parameters ---------- fx: :class:`sympy.matrices.MatrixBase` - input ode in symbolic form, :math:`f(x)` + input ode with pure transitions in symbolic form, :math:`f(x)` terms: list of two element tuples which contains the matching terms diff --git a/pygom/model/_tau_leap.pyx b/src/pygom/model/_tau_leap.pyx similarity index 60% rename from pygom/model/_tau_leap.pyx rename to src/pygom/model/_tau_leap.pyx index 09e75b27..fcb700db 100644 --- a/pygom/model/_tau_leap.pyx +++ b/src/pygom/model/_tau_leap.pyx @@ -28,33 +28,39 @@ def _cy_test_tau_leap_safety(np.ndarray[np.float64_t] x, cdef double mu, max_cdf, new_cdf cdef double total_rate = np.sum(rates) - safe = False - cdef int count = 0 + safe = False # when True, indicates that tau_scale is sufficiently small + cdef int count = 0 # number of attempts to find acceptable tau_scale while safe is False: + # print(count) + # print(tau_scale) cdf_val = 1.0 - for i in range(n_rates): - #xi = x[reactant_mat[:, i]] - #new_cdf = _ppois(xi, mu=tau_scale*r).min() - for j in range(n_reactants): - if reactant_mat_view[j, i] == 1: - mu = rates_view[i] * tau_scale - new_cdf = csc.pdtr(floor(x_view[i]), mu) - if new_cdf < cdf_val: - cdf_val = new_cdf - if new_cdf < cdf_val: - cdf_val = new_cdf + for i in range(n_rates): # loop over transitions, i + for j in range(n_reactants): # loop over states, j + if reactant_mat_view[j, i] == 1: # is state j involved in transition i? + mu = rates_view[i] * tau_scale # expected number of events for transition i + new_cdf = csc.pdtr(floor(x_view[j]), mu) # prob transitions of order state pop + if new_cdf < cdf_val: + cdf_val = new_cdf + # if new_cdf < cdf_val: # think this extra condition is redundant + # cdf_val = new_cdf #cdf_val[i * reactant_mat.shape[0] : (i * reactant_mat.shape[0]) + len(rates)] = _ppois(xi, mu=tau_scale*r) # the expected probability that our jump will exceed the value max_cdf = 1.0 - cdf_val + # print(max_cdf) # cannot allow it to exceed out epsilon if max_cdf > epsilon: tau_scale /= (max_cdf / epsilon) else: safe = True - if tau_scale*total_rate <= 1.0 or count > 256: + if count > 256: + print("count error") return False + + # if tau_scale*total_rate <= 1.0: # leave out Gillespie regime catch for now + # print("scale error") + # return False count += 1 return tau_scale, True diff --git a/src/pygom/model/_transition_graph.py b/src/pygom/model/_transition_graph.py new file mode 100644 index 00000000..048b3ff6 --- /dev/null +++ b/src/pygom/model/_transition_graph.py @@ -0,0 +1,126 @@ +import re + +from .base_ode_model import BaseOdeModel +from .transition import TransitionType +from sympy.matrices import MatrixBase +from ._ode_composition import getMatchingExpressionVector, _hasExpression + +# Functions to produce transition graph + +greekLetter = ('alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta', 'eta', 'theta', + 'iota', 'kappa', 'lambda', 'mu', 'nu', 'xi', 'omicron', 'pi', 'rho', + 'sigma', 'tau', 'upsilon', 'phi', 'chi', 'psi', 'omega') + +def generateTransitionGraph(ode_model, file_name=None): + """ + Generates the transition graph in graphviz given an ode model with transitions + + Parameters + ---------- + ode_model: OperateOdeModel + an ode model object + file_name: str + location of the file, if none entered, then the default directory is used + + Returns + ------- + dot: graphviz object + """ + assert isinstance(ode_model, BaseOdeModel), "An ode model object required" + + from graphviz import Digraph + + if file_name is None: + dot = Digraph(comment='ode model') + else: + dot = Digraph(comment='ode model', filename=file_name) + + dot.body.extend(['rankdir=LR']) + + param = [str(p) for p in ode_model.param_list] + states = [str(s) for s in ode_model.state_list] + + for s in states: + dot.node(s) + + transition = ode_model.transition_list + bd_list = ode_model.birth_death_list + + for transition in (transition + bd_list): + s1 = transition.origin + eq = _makeEquationPretty(transition.equation, param) + + if transition.transition_type is TransitionType.T: + s2 = transition.destination + dot.edge(s1, s2, label=eq) + elif transition.transition_type is TransitionType.B: + # when we have a birth or death process, do not make the box + dot.node(eq, shape="plaintext", width="0", height="0", margin="0") + dot.edge(eq, s1) + elif transition.transition_type is TransitionType.D: + dot.node(eq, shape="plaintext", width="0", height="0", margin="0") + dot.edge(s1, eq) + else: + pass + + return dot + + +def _makeEquationPretty(eq, param): + """ + Make the equation suitable for graphviz format by converting + beta to β and remove all the multiplication sign + + We do not process ** and convert it to a superscript because + it is only possible with svg (which is a real pain to convert + back to png) and only available from graphviz versions after + 14 Oct 2011 + """ + for p in param: + if p.lower() in greekLetter: + eq = re.sub('(\\W?)(' + p + ')(\\W?)', '\\1&' + p + ';\\3', eq) + # eq = re.sub('\*{1}[^\*]', '', eq) + # eq = re.sub('([^\*]?)\*([^\*]?)', '\\1 \\2', eq) + # eq += " blahYo + haBoo" + return eq + + +def generateDirectedDependencyGraph(ode_matrix, transition=None): + """ + Returns a binary matrix that contains the direction of the transition in + a state + + Parameters + ---------- + ode_matrix: :class:`sympy.matrcies.MatrixBase` + A matrix of size [number of states x 1]. Obtained by + invoking :meth:`DeterministicOde.get_ode_eqn` + transition: list, optional + list of transitions. Can be generated by + :func:`getMatchingExpressionVector` + + Returns + ------- + G: :class:`numpy.ndarray` + Two dimensional array of size [number of state x number of transitions] + where each column has two entry, + -1 and 1 to indicate the direction of the transition and the state. + All column sum to one, i.e. transition must have a source and target. + """ + assert isinstance(ode_matrix, MatrixBase), \ + "Expecting a vector of expressions" + + if transition is None: + transition = getMatchingExpressionVector(ode_matrix, True) + else: + assert isinstance(transition, list), "Require a list of transitions" + + B = np.zeros((len(ode_matrix), len(transition))) + for i, a in enumerate(ode_matrix): + for j, transitionTuple in enumerate(transition): + t1, t2 = transitionTuple + if _hasExpression(a, t1): + B[i, j] += -1 # going out + if _hasExpression(a, t2): + B[i, j] += 1 # coming in + return B diff --git a/pygom/model/base_ode_model.py b/src/pygom/model/base_ode_model.py similarity index 95% rename from pygom/model/base_ode_model.py rename to src/pygom/model/base_ode_model.py index 92ca513a..dea78f0d 100644 --- a/pygom/model/base_ode_model.py +++ b/src/pygom/model/base_ode_model.py @@ -61,14 +61,13 @@ def __init__(self, """ Constructor """ - # the 3 required input when doing evaluation + # the 3 required inputs when doing evaluation self._state = None self._param = None self._time = None - # we always need time to be a symbol... and it should be denoted as t + # we always need time to be a symbol and it should be denoted as t self._t = symbols('t') - # self._isDifficult = False # allows the system to be defined directly self._ode = None @@ -113,18 +112,10 @@ def __init__(self, self._lambdaMat = None self._vMat = None self._GMat = None + self._lambdaMatOD = None # also trialing this matrix indicating if a state is an origin or destination in a transition - if state is not None: - if isinstance(state, str): - state = re_split_string.split(state) - state = filter(lambda x: not len(x.strip()) == 0, state) - self.state_list = list(state) - - if param is not None: - if isinstance(param, str): - param = re_split_string.split(param) - param = filter(lambda x: not len(x.strip()) == 0, param) - self.param_list = list(param) + self._add_list_attr(state, "state_list") + self._add_list_attr(param, "param_list") # this has to go after adding the parameters # because it is suppose to be based on the current @@ -178,9 +169,22 @@ def _get_model_str(self): {str(k): v for k, v in self._parameters.items()} return model_str + def _add_list_attr(self, attr, attr_list_name): + """ + Given an attribute (name attr_name), which is a string of comma + or space separated values, create a new attribute (name attr_name_list) + which is a list of those separated values. + e.g. "a,b,c d ef" returns [a, b, c, d, ef] + """ + if attr is not None: + if isinstance(attr, str): + attr = re_split_string.split(attr) + attr = filter(lambda x: not len(x.strip()) == 0, attr) + self.__setattr__(attr_list_name, list(attr)) + ######################################################################## # - # Getting and setters + # Getters and setters # ######################################################################## @@ -223,6 +227,7 @@ def parameters(self, parameters): if isinstance(parameters, (list, tuple, np.ndarray)): # length checking, we are assuming here that we always set # the full set of parameters + # TODO: for model fitting, we might only want to set a subset of the known ones if len(parameters) == self.num_param: if isinstance(parameters, np.ndarray): if parameters.size == self.num_param: @@ -306,6 +311,7 @@ def parameters(self, parameters): elif self.num_param == 1: # a single parameter ode and you are not evaluating it # analytically! fair enough! no further comments your honour. + # TODO: Can't single parameter ODE's still be complicated? if isinstance(parameters, tuple): param_out[f(parameters[0])] = parameters[1] elif isinstance(parameters, (int, float)): @@ -982,7 +988,9 @@ def _computeReactantMatrix(self): _f, _t, eqn = self._unrollTransitionList(self._getAllTransition()) for j, eqn in enumerate(eqn): for i, state in enumerate(self._stateList): - if self._stateDict[state.ID] in eqn.atoms(): + if type(eqn)==int: + self._lambdaMat[i, j] = 0 + elif self._stateDict[state.ID] in eqn.atoms(): self._lambdaMat[i, j] = 1 return self._lambdaMat @@ -1014,6 +1022,24 @@ def _computeStateChangeMatrix(self): self._vMat[k2, j] += -1 return self._vMat + + # Might replace _computeReactantMatrix. This function gives a matrix + def _computeReactantMatrixOD(self): + """ + The alternative reactant matrix, where + + .. math:: + \\lambda_{i,j} = \\left\\{ 1, &if state i is an origin or destination in transition j, \\\\ + 0, &otherwise \\right. + + OD imples this refers to origin and destination + """ + + x=self._vMat!=0 + x=x.astype(int) + self._lambdaMatOD=x + + return self._lambdaMatOD def _computeDependencyMatrix(self): """ @@ -1024,6 +1050,8 @@ def _computeDependencyMatrix(self): self._computeReactantMatrix() if self._vMat is None: self._computeStateChangeMatrix() + if self._lambdaMatOD is None: + self._computeReactantMatrixOD() nt = self.num_transitions self._GMat = np.zeros((nt, nt), int) @@ -1139,6 +1167,9 @@ def _extractParamIndex(self, input_str): raise InputError("Input parameter: %s does not exist" % input_str) def _extractParamSymbol(self, input_str): + """ + Given a parameter name, input_str + """ if isinstance(input_str, ODEVariable): input_str = input_str.ID diff --git a/pygom/model/common_models.py b/src/pygom/model/common_models.py similarity index 75% rename from pygom/model/common_models.py rename to src/pygom/model/common_models.py index d5098020..91960683 100644 --- a/pygom/model/common_models.py +++ b/src/pygom/model/common_models.py @@ -8,12 +8,13 @@ from collections import OrderedDict from .transition import TransitionType, Transition -from .deterministic import DeterministicOde +#from .deterministic import DeterministicOde +from .simulate import SimulateOde def SIS(param=None): """ - A standard SIS model + Susceptible Infected Susceptible model .. math:: \\frac{dS}{dt} &= -\\beta SI + \\gamma I \\\\ @@ -24,7 +25,7 @@ def SIS(param=None): >>> import numpy as np >>> from pygom import common_models >>> ode = common_models.SIS({'beta':0.5, 'gamma':0.2}) - >>> t = np.linspace(0, 20, 101) + >>> t = np.linspace(0, 20, 100) >>> x0 = [1.0, 0.1] >>> ode.initial_values = (x0, t[0]) >>> solution = ode.integrate(t[1::]) @@ -32,17 +33,15 @@ def SIS(param=None): """ state = ['S', 'I'] - param_list = ['beta', 'gamma'] + param_list = ['beta', 'gamma', 'N'] transition = [ - Transition(origin='S', destination='I', equation='beta*S*I', - transition_type=TransitionType.T), - Transition(origin='I', destination='S', equation='gamma*I', - transition_type=TransitionType.T) + Transition(origin='S', destination='I', equation='beta*S*I/N',transition_type=TransitionType.T), + Transition(origin='I', destination='S', equation='gamma*I',transition_type=TransitionType.T) ] # initialize the model - ode = DeterministicOde(state, - param_list, - transition=transition) + ode = SimulateOde(state, + param_list, + transition=transition) # set return, depending on whether we have input the parameters if param is None: @@ -79,20 +78,22 @@ def SIS_Periodic(param=None): """ state = ['I', 'tau'] - param_list = ['alpha'] - derived_param = [('betaT', '2 - 1.8*cos(5*tau)')] + param_list = ['gamma', 'beta0', 'delta', 'period', 'N'] + # derived_param = [('betaT', '2 - 1.8*cos(5*tau)')] + derived_param = [('betaT', 'beta0*(1-delta*cos(2*3.14159*tau/period))')] ode = [ Transition(origin='I', - equation='(betaT - alpha)*I - betaT*I*I', + equation='(betaT - gamma)*I - (betaT*I*I/N)', transition_type=TransitionType.ODE), Transition(origin='tau', equation='1', transition_type=TransitionType.ODE) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, - derived_param=derived_param, - ode=ode) + ode_obj = SimulateOde(state, + param_list, + derived_param=derived_param, + ode=ode) # set return, depending on whether we have input the parameters if param is None: @@ -107,8 +108,8 @@ def SIR(param=None): A standard SIR model as per [Brauer2008]_ .. math:: - \\frac{dS}{dt} &= -\\beta SI \\\\ - \\frac{dI}{dt} &= \\beta SI - \\gamma I \\\\ + \\frac{dS}{dt} &= -\\ \\frac{beta SI}{N} \\\\ + \\frac{dI}{dt} &= \\ \\frac{beta SI}{N} - \\gamma I \\\\ \\frac{dR}{dt} &= \\gamma I @@ -119,37 +120,26 @@ def SIR(param=None): >>> import numpy as np >>> from pygom import common_models - >>> ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) + >>> N=1e5 + >>> ode = common_models.SIR({'beta':0.5, 'gamma':0.2, 'N':N}) >>> t = np.linspace(0, 730, 1001) - >>> N = 7781984.0 - >>> x0 = [1.0, 10/N, 0.0] - >>> ode.initial_values = (x0, t[0]) - >>> solution = ode.integrate(t[1::]) - >>> ode.plot() - - Second model with a more *realistic* scenario - - >>> import numpy as np - >>> from pygom import common_models - >>> ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) - >>> t = np.linspace(0, 730, 1001) - >>> N = 7781984.0 - >>> x0 = [0.065, 123*(5.0/30.0)/N, 0.0] + >>> i0=1 + >>> x0 = [N-i0, i0, 0.0] >>> ode.initial_values = (x0, t[0]) >>> solution = ode.integrate(t[1::]) >>> ode.plot() """ state = ['S', 'I', 'R'] - param_list = ['beta', 'gamma'] + param_list = ['beta', 'gamma', 'N'] transition = [ - Transition(origin='S', destination='I', equation='beta*S*I', + Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, transition=transition) + ode_obj = SimulateOde(state, param_list, transition=transition) # set return, depending on whether we have input the parameters if param is None: @@ -159,16 +149,16 @@ def SIR(param=None): return ode_obj -def SIR_N(param=None): +def SIR_norm(param=None): """ - A standard SIR model [Brauer2008]_ with population N. This is the unnormalized - version of the SIR model. + A normalized SIR model: .. math:: - \\frac{dS}{dt} &= -\\beta SI/N \\\\ - \\frac{dI}{dt} &= \\beta SI/N- \\gamma I \\\\ + \\frac{dS}{dt} &= -\\beta SI \\\\ + \\frac{dI}{dt} &= \\beta SI - \\gamma I \\\\ \\frac{dR}{dt} &= \\gamma I + Examples -------- The model that produced top two graph in Figure 1.3 of the reference above. @@ -179,7 +169,7 @@ def SIR_N(param=None): >>> ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) >>> t = np.linspace(0, 730, 1001) >>> N = 7781984.0 - >>> x0 = [N, 1.0, 0.0] + >>> x0 = [1.0, 10/N, 0.0] >>> ode.initial_values = (x0, t[0]) >>> solution = ode.integrate(t[1::]) >>> ode.plot() @@ -191,21 +181,22 @@ def SIR_N(param=None): >>> ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) >>> t = np.linspace(0, 730, 1001) >>> N = 7781984.0 - >>> x0 = [int(0.065*N), 21.0, 0.0] + >>> x0 = [0.065, 123*(5.0/30.0)/N, 0.0] >>> ode.initial_values = (x0, t[0]) >>> solution = ode.integrate(t[1::]) >>> ode.plot() + """ state = ['S', 'I', 'R'] - param_list = ['beta', 'gamma', 'N'] + param_list = ['beta', 'gamma'] transition = [ - Transition(origin='S', destination='I', equation='beta*S*I/N', + Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, transition=transition) + ode_obj = SimulateOde(state, param_list, transition=transition) # set return, depending on whether we have input the parameters if param is None: @@ -214,6 +205,113 @@ def SIR_N(param=None): ode_obj.parameters = param return ode_obj +# def SIR_N(param=None, init=None): +# """ +# A standard SIR model [Brauer2008]_ with population N + +# .. math:: +# \\frac{dS}{dt} &= -\\beta SI/N \\\\ +# \\frac{dI}{dt} &= \\beta SI/N- \\gamma I \\\\ +# \\frac{dR}{dt} &= \\gamma I + +# """ +# stateList = ['S', 'I', 'R'] +# paramList = ['beta', 'gamma', 'N'] +# transitionList = [Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), +# Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)] + +# # initialize the model +# ode_obj = SimulateOde(stateList, paramList, transition=transitionList) + +# # set return, depending on whether we have input the parameters + +# if param is not None: +# ode_obj.parameters = param + +# if init is not None: +# ode_obj.initial_values = init + +# return ode_obj + + +def SEIR_N(param=None, init=None): + """ + A standard SIR model [Brauer2008]_ with population N + + """ + stateList = ['S', 'E', 'I', 'R'] + paramList = ['beta', 'alpha', 'gamma', 'N'] + transitionList = [Transition(origin='S', destination='E', equation='beta*S*I/N', transition_type=TransitionType.T), + Transition(origin='E', destination='I', equation='alpha*E', transition_type=TransitionType.T), + Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)] + + # initialize the model + ode_obj = SimulateOde(stateList, paramList, transition=transitionList) + + # set return, depending on whether we have input the parameters + if param is not None: + ode_obj.parameters = param + + if init is not None: + ode_obj.initial_values = init + + return ode_obj + +# def SIR_N(param=None): +# """ +# A standard SIR model [Brauer2008]_ with population N. This is the unnormalized +# version of the SIR model. + +# .. math:: +# \\frac{dS}{dt} &= -\\beta SI/N \\\\ +# \\frac{dI}{dt} &= \\beta SI/N- \\gamma I \\\\ +# \\frac{dR}{dt} &= \\gamma I + +# Examples +# -------- +# The model that produced top two graph in Figure 1.3 of the reference above. +# First, when everyone is susceptible and only one individual was infected. + +# >>> import numpy as np +# >>> from pygom import common_models +# >>> ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) +# >>> t = np.linspace(0, 730, 1001) +# >>> N = 7781984.0 +# >>> x0 = [N, 1.0, 0.0] +# >>> ode.initial_values = (x0, t[0]) +# >>> solution = ode.integrate(t[1::]) +# >>> ode.plot() + +# Second model with a more *realistic* scenario + +# >>> import numpy as np +# >>> from pygom import common_models +# >>> ode = common_models.SIR({'beta':3.6, 'gamma':0.2}) +# >>> t = np.linspace(0, 730, 1001) +# >>> N = 7781984.0 +# >>> x0 = [int(0.065*N), 21.0, 0.0] +# >>> ode.initial_values = (x0, t[0]) +# >>> solution = ode.integrate(t[1::]) +# >>> ode.plot() +# """ +# state = ['S', 'I', 'R'] +# param_list = ['beta', 'gamma', 'N'] +# transition = [ +# Transition(origin='S', destination='I', equation='beta*S*I/N', +# transition_type=TransitionType.T), +# Transition(origin='I', destination='R', equation='gamma*I', +# transition_type=TransitionType.T) +# ] +# # initialize the model +# ode_obj = SimulateOde(state, param_list, transition=transition) + +# # set return, depending on whether we have input the parameters +# if param is None: +# return ode_obj +# else: +# ode_obj.parameters = param +# return ode_obj + def SIR_Birth_Death(param=None): """ @@ -246,27 +344,30 @@ def SIR_Birth_Death(param=None): :func:`.SIR` """ state = ['S', 'I', 'R'] - param_list = ['beta', 'gamma', 'B', 'mu'] + param_list = ['beta', 'gamma', 'mu', 'N'] transition = [ - Transition(origin='S', destination='I', equation='beta*S*I', + Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # our birth and deaths birth_death = [ - Transition(origin='S', equation='B', + Transition(origin='S', equation='mu*N', transition_type=TransitionType.B), Transition(origin='S', equation='mu*S', transition_type=TransitionType.D), Transition(origin='I', equation='mu*I', + transition_type=TransitionType.D), + Transition(origin='R', equation='mu*R', transition_type=TransitionType.D) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, - birth_death=birth_death, - transition=transition) + ode_obj = SimulateOde(state, + param_list, + birth_death=birth_death, + transition=transition) # set return, depending on whether we have input the parameters if param is None: @@ -304,10 +405,10 @@ def SEIR(param=None): """ state = ['S', 'E', 'I', 'R'] - param_list = ['beta', 'alpha', 'gamma'] + param_list = ['beta', 'alpha', 'gamma', 'N'] transition = [ - Transition(origin='S', destination='E', equation='beta*S*I', + Transition(origin='S', destination='E', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='E', destination='I', equation='alpha*E', transition_type=TransitionType.T), @@ -315,7 +416,7 @@ def SEIR(param=None): transition_type=TransitionType.T) ] - ode_obj = DeterministicOde(state, param_list, transition=transition) + ode_obj = SimulateOde(state, param_list, transition=transition) if param is None: return ode_obj @@ -355,10 +456,10 @@ def SEIR_Birth_Death(param=None): """ state = ['S', 'E', 'I', 'R'] - param_list = ['beta', 'alpha', 'gamma', 'mu'] + param_list = ['beta', 'alpha', 'gamma', 'mu', 'N'] transition = [ - Transition(origin='S', destination='E', equation='beta*S*I', + Transition(origin='S', destination='E', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='E', destination='I', equation='alpha*E', transition_type=TransitionType.T), @@ -373,11 +474,11 @@ def SEIR_Birth_Death(param=None): transition_type=TransitionType.D), Transition(origin='I', equation='mu*I', transition_type=TransitionType.D), - Transition(origin='S', equation='mu', + Transition(origin='S', equation='mu*N', transition_type=TransitionType.B) ] - ode_obj = DeterministicOde(state, param_list, + ode_obj = SimulateOde(state, param_list, transition=transition, birth_death=bd_list) @@ -444,7 +545,7 @@ def SEIR_Birth_Death_Periodic(param=None): transition_type=TransitionType.ODE) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, + ode_obj = SimulateOde(state, param_list, derived_param=derived_param, ode=ode) @@ -454,6 +555,51 @@ def SEIR_Birth_Death_Periodic(param=None): ode_obj.parameters = param return ode_obj + +def SEIR_Birth_Death_Periodic_Waning_Intro(param=None): + state = ['S', 'E', 'I', 'R', 'tau'] + param_list = ['mu', 'alpha', 'gamma', 'epsilon', 'w', 'beta0', 'delta', 'period', 'N'] + + derived_param = [('betaT', 'beta0*(1-delta*cos(2*3.14159*tau/period))')] + + transition = [ + Transition(origin='S', destination='E', equation='betaT*S*I/N', + transition_type=TransitionType.T), + Transition(origin='S', destination='E', equation='epsilon*S', + transition_type=TransitionType.T), + Transition(origin='E', destination='I', equation='alpha*E', + transition_type=TransitionType.T), + Transition(origin='I', destination='R', equation='gamma*I', + transition_type=TransitionType.T), + Transition(origin='R', destination='S', equation='w*R', + transition_type=TransitionType.T) + ] + + bd_list = [ + Transition(origin='S', equation='mu*S', + transition_type=TransitionType.D), + Transition(origin='E', equation='mu*E', + transition_type=TransitionType.D), + Transition(origin='I', equation='mu*I', + transition_type=TransitionType.D), + Transition(origin='R', equation='mu*R', + transition_type=TransitionType.D), + Transition(origin='S', equation='mu*N', + transition_type=TransitionType.B), + Transition(origin='tau', equation='1', + transition_type=TransitionType.B) + ] + + ode_obj = SimulateOde(state, param_list, derived_param=derived_param, + transition=transition, + birth_death=bd_list) + + if param is None: + return ode_obj + else: + ode_obj.parameters = param + return ode_obj + def SEIR_Multiple(n=2, param=None): """ An SEIR model that describe spatial heterogeneity [Brauer2008]_, page 180. @@ -550,7 +696,7 @@ def SEIR_Multiple(n=2, param=None): bd_list += [Transition(origin=states[v][i], equation='d*' + states[v][i], transition_type=TransitionType.D)] bd_list += [Transition(origin=states['S'][i], equation='d*' + N[i], transition_type=TransitionType.B)] - ode_obj = DeterministicOde(state_list, + ode_obj = SimulateOde(state_list, param_list, derived_param=derived_param, transition=transition, @@ -591,7 +737,7 @@ def Influenza_SLIARN(param=None): transition_type=TransitionType.ODE) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, ode=ode) + ode_obj = SimulateOde(state, param_list, ode=ode) if param is None: return ode_obj @@ -656,7 +802,7 @@ def Legrand_Ebola_SEIHFR(param=None): ] # alternatively, we can do it on the operate ode model - ode_obj = DeterministicOde(state, params) + ode_obj = SimulateOde(state, params) # add the derived parameter ode_obj.derived_param_list = derived_param @@ -729,19 +875,36 @@ def Lotka_Volterra(param=None): """ # our two state and four parameters - # no idea why they are not in capital state = ['x', 'y'] # while these 4 are - param_list = ['alpha', 'delta', 'c', 'gamma'] + param_list = ['alpha', 'beta', 'gamma', 'delta', 'A'] # then define the set of ode - ode = [ - Transition(origin='x', equation='alpha*x - c*x*y', - transition_type=TransitionType.ODE), - Transition(origin='y', equation='-delta*y + gamma*x*y', - transition_type=TransitionType.ODE) + # ode = [ + # Transition(origin='x', equation='alpha*x - c*x*y', + # transition_type=TransitionType.ODE), + # Transition(origin='y', equation='-delta*y + gamma*x*y', + # transition_type=TransitionType.ODE) + # ] + # ode_obj = SimulateOde(state, param_list, ode=ode) + + # Defining via transitions allows us to solve stochastically too + birth_death = [ + Transition(origin='x', equation='alpha*x', + transition_type=TransitionType.B), + Transition(origin='x', equation='beta*x*y/A', + transition_type=TransitionType.D), + Transition(origin='y', equation='gamma*x*y/A', + transition_type=TransitionType.B), + Transition(origin='y', equation='delta*y', + transition_type=TransitionType.D) ] - ode_obj = DeterministicOde(state, param_list, ode=ode) + # initialize the model + ode_obj = SimulateOde(state, + param_list, + birth_death=birth_death) + + # set return, depending on whether we have input the parameters if param is None: return ode_obj @@ -792,7 +955,7 @@ def Lotka_Volterra_4State(param=None): transition_type=TransitionType.T) ] - ode_obj = DeterministicOde(state, param_list, transition=transition) + ode_obj = SimulateOde(state, param_list, transition=transition) # set return, depending on whether we have input the parameters if param is None: @@ -835,7 +998,7 @@ def FitzHugh(param=None): transition_type=TransitionType.ODE) ] # setup our ode - ode_obj = DeterministicOde(state, param_list, + ode_obj = SimulateOde(state, param_list, derived_param=None, transition=None, birth_death=None, @@ -883,7 +1046,7 @@ def Lorenz(param=None): transition_type=TransitionType.ODE) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, ode=ode) + ode_obj = SimulateOde(state, param_list, ode=ode) if param is None: return ode_obj @@ -892,7 +1055,7 @@ def Lorenz(param=None): return ode_obj -def vanDelPol(param=None): +def vanDerPol(param=None): """ The van der Pol equation [vanderpol1926]_, a second order ode @@ -918,7 +1081,7 @@ def vanDelPol(param=None): >>> from pygom import common_models >>> import numpy >>> t = numpy.linspace(0, 20, 1000) - >>> ode = common_models.vanDelPol({'mu':1.0}) + >>> ode = common_models.vanDerPol({'mu':1.0}) >>> ode.initial_values = ([2.0,0.0], t[0]) >>> solution = ode.integrate(t[1::]) >>> ode.plot() @@ -933,7 +1096,7 @@ def vanDelPol(param=None): transition_type=TransitionType.ODE) ] # initialize the model - ode_obj = DeterministicOde(state_list, param_list, ode=ode) + ode_obj = SimulateOde(state_list, param_list, ode=ode) if param is None: return ode_obj @@ -980,7 +1143,7 @@ def Robertson(param=None): transition_type=TransitionType.T) ] # initialize the model - ode_obj = DeterministicOde(state, param_list, transition=transition) + ode_obj = SimulateOde(state, param_list, transition=transition) if param is None: return ode_obj diff --git a/pygom/model/deterministic.py b/src/pygom/model/deterministic.py similarity index 96% rename from pygom/model/deterministic.py rename to src/pygom/model/deterministic.py index 5679921e..3fafc59c 100644 --- a/pygom/model/deterministic.py +++ b/src/pygom/model/deterministic.py @@ -25,7 +25,8 @@ from ._model_verification import simplifyEquation from . import ode_utils -from . import _ode_composition +# from . import _ode_composition +from . import _transition_graph class HasNewTransition(ode_utils.CompileCanary): states = ['ode', 'Jacobian', 'diffJacobian', 'grad', 'GradJacobian'] @@ -343,7 +344,8 @@ def get_transition_graph(self, file_name=None, show=True): ------- :class:`graphviz.Digraph` ''' - dot = _ode_composition.generateTransitionGraph(self, file_name) + # dot = _ode_composition.generateTransitionGraph(self, file_name) + dot = _transition_graph.generateTransitionGraph(self, file_name) if show: import matplotlib.image as mpimg import matplotlib.pyplot as plt diff --git a/pygom/model/epi_analysis.py b/src/pygom/model/epi_analysis.py similarity index 100% rename from pygom/model/epi_analysis.py rename to src/pygom/model/epi_analysis.py diff --git a/pygom/model/ode_utils/__init__.py b/src/pygom/model/ode_utils/__init__.py similarity index 100% rename from pygom/model/ode_utils/__init__.py rename to src/pygom/model/ode_utils/__init__.py diff --git a/pygom/model/ode_utils/checks_and_conversions.py b/src/pygom/model/ode_utils/checks_and_conversions.py similarity index 100% rename from pygom/model/ode_utils/checks_and_conversions.py rename to src/pygom/model/ode_utils/checks_and_conversions.py diff --git a/pygom/model/ode_utils/compile_canary.py b/src/pygom/model/ode_utils/compile_canary.py similarity index 100% rename from pygom/model/ode_utils/compile_canary.py rename to src/pygom/model/ode_utils/compile_canary.py diff --git a/pygom/model/ode_utils/plot_det.py b/src/pygom/model/ode_utils/plot_det.py similarity index 100% rename from pygom/model/ode_utils/plot_det.py rename to src/pygom/model/ode_utils/plot_det.py diff --git a/pygom/model/ode_utils/plot_stoc.py b/src/pygom/model/ode_utils/plot_stoc.py similarity index 100% rename from pygom/model/ode_utils/plot_stoc.py rename to src/pygom/model/ode_utils/plot_stoc.py diff --git a/pygom/model/ode_variable.py b/src/pygom/model/ode_variable.py similarity index 100% rename from pygom/model/ode_variable.py rename to src/pygom/model/ode_variable.py diff --git a/pygom/model/simulate.py b/src/pygom/model/simulate.py similarity index 78% rename from pygom/model/simulate.py rename to src/pygom/model/simulate.py index 0abf30f7..571b960d 100644 --- a/pygom/model/simulate.py +++ b/src/pygom/model/simulate.py @@ -246,6 +246,198 @@ def sim(x): return Y, solutionList else: return Y + + def solve_determ(self, t, iteration=None, parallel=False, full_output=False): + ''' + Simulate the ode by generating new realization of the stochastic + parameters and integrate the system deterministically. + + Parameters + ---------- + t: array like + the range of time points which we want to see the result of + iteration: int + number of iterations you wish to simulate + parallel: bool, optional + Defaults to True + full_output: bool, optional + if we want additional information, Y_all in the return, + defaults to false + + Returns + ------- + Y: :class:`numpy.ndarray` + of shape (len(t), len(state)), mean of all the simulation + Y_all: :class:`np.ndarray` + of shape (iteration, len(t), len(state)) + ''' + if t is None: + raise InputError("Need to specify the time we wish to observe") + + # If parameters are not random then return one integration + if self._stochasticParam is None: + solution = self.integrate(t) + return solution + + # Otherwise, proceed for random parameters and verify expected extra parameters are present. + if iteration is None: + raise InputError("Need to specify the number of iterations") + + self._odeSolution = self.integrate(t) + + # try to compute the simulation in parallel + if parallel: + try: + for i in self._stochasticParam: + if isinstance(i, scipy.stats._distn_infrastructure.rv_frozen): + raise Exception("Cannot perform parallel simulation " + +"using a serialized object as distribution") + # check the type of parameter we have as input + import dask.bag + y = list() + for i in range(iteration): + y_i = list() + for key, rv in self._stochasticParam.items(): + y_i += [{key:rv.rvs(1)[0]}] + y += [y_i] + # y = [rv.rvs(iteration) for rv in self._stochasticParam.values()] + # y = np.array(list(zip(*y))) + def sim(x): + self.parameters = x + return self.integrate(t) + + # def sim(t1): return(self.integrate(t1)) + + # xtmp = dask.bag.from_sequence([t]*iteration) + xtmp = dask.bag.from_sequence(y) + solutionList = xtmp.map(sim).compute() + except Exception: # as e: + # print(e) + # print("Serial") + solutionList = [self.integrate(t) for i in range(iteration)] + else: + solutionList = [self.integrate(t) for i in range(iteration)] + + # now make our 3D array + # the first dimension is the number of iteration + Y = np.dstack(solutionList).mean(axis=2) + + if full_output: + return Y, solutionList + else: + return Y + + # Same as function below, just trying out new naming convention + def solve_stochast(self, t, iteration, parallel=False, + exact=False, full_output=False): + ''' + Simulate the ode using stochastic simulation. It switches + between a first reaction method and a :math:`\\tau`-leap + algorithm internally. When a parallel backend exists, then a new random + state (seed) will be used for each processor. This is due to a lack + of appropriate parallel seed random number generator in python. + + Parameters + ---------- + t: array like + the range of time points which we want to see the result of + or the final time point + iteration: int + number of iterations you wish to simulate + parallel: bool, optional + Defaults to True + exact: bool, optional + True if exact simulation is desired, defaults to False + full_output: bool, optional + if we want additional information, sim_T + + Returns + ------- + sim_X: list + of length iteration each with (len(t),len(state)) if t is a vector, + else it outputs unequal shape that was record of all the jumps + sim_T: list or :class:`numpy.ndarray` + if t is a single value, it outputs unequal shape that was + record of all the jumps. if t is a vector, it outputs t so that + it is a :class:`numpy.ndarray` instead + + ''' + + assert len(self._odeList) == 0, \ + "Currently only able to simulate when only transitions are present" + assert np.all(np.mod(self._x0, 1) == 0), \ + "Can only simulate a jump process with integer initial values" + + # this determines what type of output we want + timePoint = False + + if isinstance(t, Number):#, (int, float, np.int64, np.float64)): + finalT = t + elif isinstance(t, (list, tuple)): + t = np.array(t) + if len(t) == 1: + finalT = t + else: + finalT = t[-1:] + timePoint = True + elif isinstance(t, np.ndarray): + finalT = t[-1:] + timePoint = True + else: + raise InputError("Unknown data type for time") + + if self._transitionVectorCompile is None: + self._compileTransitionVector() + + if parallel: + try: + import dask.bag + logging.debug("Using Dask for parallel simulation") + def jump_partial(final_t): return(self._jump(final_t, + exact=exact, + full_output=True, + seed=True)) + + xtmp = dask.bag.from_sequence(np.ones(iteration)*finalT) + xtmp = xtmp.map(jump_partial).compute() + except Exception as e: + raise e + logging.warning("Parallel simulation failed reverting to serial") + xtmp = [self._jump(finalT, exact=exact, full_output=True) for _i in range(iteration)] + else: + logging.debug("Performing serial simulation") + xtmp = [self._jump(finalT, exact=exact, full_output=True) for _i in range(iteration)] + + xmat = list(zip(*xtmp)) + simXList, simTList = list(xmat[0]), list(xmat[1]) + ## print("Finish computation") + # now we want to fix our simulation, if they need fixing that is + # print timePoint + if timePoint: + for _i in range(len(simXList)): + # unroll, always the first element + # it is easy to remember that we are accessing the first + # element because pop is spelt similar to poop and we + # all know that your execute first in first out when you + # poop! + simX = simXList.pop(0) + simT = simTList.pop(0) + + x = self._extractObservationAtTime(simX, simT, t) + simTList.append(t) + simXList.append(x) + # note that we have to remain in list form because the number of + # simulation will be different if we are not dealing with + # a specific set of time points + + if full_output: + if timePoint: + return simXList, t + else: + return simXList, simTList + else: + return simXList + def simulate_jump(self, t, iteration, parallel=False, exact=False, full_output=False): @@ -361,6 +553,9 @@ def _jump(self, finalT, exact=False, full_output=True, seed=None): ''' Jumps from the initial time self._t0 to the input time finalT ''' + if isinstance(self._stochasticParam, dict): + self.parameters = self._stochasticParam + # initial time assert self._t0 is not None, "No initial time" assert self._x0 is not None, "No initial state" @@ -372,7 +567,7 @@ def _jump(self, finalT, exact=False, full_output=True, seed=None): xList = [x.copy()] tList = [t] - # we want to construct some jump times + # we want to construct some jump times (TODO: doesn't seem like _GMat is used anywhere) if self._GMat is None: self._computeDependencyMatrix() @@ -387,7 +582,8 @@ def _jump(self, finalT, exact=False, full_output=True, seed=None): else: if np.min(x) > 10: x_tmp, t_tmp, success = tauLeap(x, t, - self._vMat, self._lambdaMat, + # self._vMat, self._lambdaMat, + self._vMat, self._lambdaMatOD, # I think that the wrong matrix has been used, trying this one instead self.transition_vector, self.transition_mean, self.transition_var, @@ -931,24 +1127,29 @@ def get_transitions_from_ode(self): return transition - def get_bd_from_ode(self, A=None): - ''' - Returns a list of:class:`Transition` from this object by unrolling - the odes. All the elements are of TransitionType.B or - TransitionType.D - ''' + def _get_A(self, A=None): if A is None: if not ode_utils.none_or_empty_list(self._odeList): - eqn = [t.equation for t in self._odeList] - A = sympy.Matrix(checkEquation(eqn, + eqn_list = [t.equation for t in self._odeList] + A = sympy.Matrix(checkEquation(eqn_list, *self._getListOfVariablesDict(), subs_derived=False)) + return A else: raise Exception("Object was not initialized using a set of ode") - # A = super(SimulateOde, self).getOde() + else: + return A - bdList, _term = _ode_composition.getUnmatchedExpressionVector(A, True) + def get_bd_from_ode(self, A=None): + ''' + Returns a list of:class:`Transition` from this object by unrolling + the odes. All the elements are of TransitionType.B or + TransitionType.D + ''' + + A=self._get_A(A) + bdList, _term = _ode_composition.getUnmatchedExpressionVector(A, True) if len(bdList) > 0: M = self._generateTransitionMatrix(A) @@ -985,15 +1186,7 @@ def _generateTransitionMatrix(self, A=None):#, transitionExpressionList=None): that the functions called here is focused on the terms of the equation rather than the states. ''' - if A is None: - if not ode_utils.none_or_empty_list(self._odeList): - eqn_list = [t.equation for t in self._odeList] - A = sympy.Matrix(checkEquation(eqn_list, - *self._getListOfVariablesDict(), - subs_derived=False)) - else: - raise Exception("Object was not initialized using a set of ode") - + A=self._get_A(A) bdList, _term = _ode_composition.getUnmatchedExpressionVector(A, True) fx = _ode_composition.stripBDFromOde(A, bdList) states = [s for s in self._iterStateList()] diff --git a/pygom/model/stochastic_simulation.py b/src/pygom/model/stochastic_simulation.py similarity index 96% rename from pygom/model/stochastic_simulation.py rename to src/pygom/model/stochastic_simulation.py index 3c69527c..07adab7b 100644 --- a/pygom/model/stochastic_simulation.py +++ b/src/pygom/model/stochastic_simulation.py @@ -421,7 +421,7 @@ def firstReaction(x, t, state_change_mat, transition_func, seed=None): rates = transition_func(x, t) # find our jump times jump_times = _newJumpTimes(rates, seed=seed) - if np.all(jump_times == np.Inf): + if np.all(jump_times == np.inf): return x, t, False # first jump min_index = np.argmin(jump_times) @@ -461,7 +461,7 @@ def nextReaction(x, t, state_change_mat, dependency_graph, if anew > 0: jump_times[i] = (aold/anew)*(jump_times[i] - t) + t else: - jump_times[i] = np.Inf + jump_times[i] = np.inf # done :) return new_x, t, True, rates, jump_times else: @@ -630,7 +630,7 @@ def _newJumpTimes(rates, seed=None): distribution """ - tau = [rexp(1, r, seed=seed) if r > 0 else np.Inf for r in rates] + tau = [rexp(1, r, seed=seed) if r > 0 else np.inf for r in rates] return np.array(tau) diff --git a/pygom/model/transition.py b/src/pygom/model/transition.py similarity index 100% rename from pygom/model/transition.py rename to src/pygom/model/transition.py diff --git a/pygom/utilR/__init__.py b/src/pygom/utilR/__init__.py similarity index 100% rename from pygom/utilR/__init__.py rename to src/pygom/utilR/__init__.py diff --git a/pygom/utilR/distn.py b/src/pygom/utilR/distn.py similarity index 98% rename from pygom/utilR/distn.py rename to src/pygom/utilR/distn.py index 25cf2628..3dc13767 100644 --- a/pygom/utilR/distn.py +++ b/src/pygom/utilR/distn.py @@ -98,7 +98,7 @@ def gamma_mu_shape(x, mu,shape,log=False): Returns ------- - pdf, :math:`\\mathcal\\{p}(x; \\mu,a) = \\exp(- a \\ln{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\ln{\\left(x \\right)} - \\ln{\\left(\\Gamma\\left(a\\right) \\right)})` + pdf, :math:`\\mathcal{p}(x; \\mu,a) = \\exp(- a \\ln{\\left(\\frac{\\mu}{a} \\right)} - \\frac{a x}{\\mu} + \\left(a - 1\\right) \\ln{\\left(x \\right)} - \\ln{\\left(\\Gamma\\left(a\\right) \\right)})` ` ''' diff --git a/tests/test_abc.py b/tests/test_abc.py index e980d40b..6827e724 100644 --- a/tests/test_abc.py +++ b/tests/test_abc.py @@ -10,7 +10,7 @@ class TestABC(TestCase): def setUp(self): # define the model and parameters - self.ode = common_models.SIR({'beta':0.5, 'gamma':1.0/3.0}) + self.ode = common_models.SIR_norm({'beta':0.5, 'gamma':1.0/3.0}) # the initial state, normalized to one self.x0 = [1, 1.27e-6, 0] @@ -64,7 +64,7 @@ def test_SIR_abc_NormalLoss(self): parameters = [pgabc.Parameter('beta', 'unif', 0, 3, logscale=False), pgabc.Parameter('gamma', 'unif', 0, 3, logscale=False)] - sir_obj = pgabc.create_loss(NormalLoss, parameters, self.ode, self.x0, self.t[0], + sir_obj = pgabc.create_loss("NormalLoss", parameters, self.ode, self.x0, self.t[0], self.t[1::], y, ['I', 'R'], sigma=1.0) sir_abc = pgabc.ABC(sir_obj, parameters) diff --git a/tests/test_epijson.py b/tests/test_epijson.py index d0253478..48c8bc77 100644 --- a/tests/test_epijson.py +++ b/tests/test_epijson.py @@ -18,7 +18,7 @@ def test_read_epijson(self): def test_initialize_epijson_loss(self): data = pkgutil.get_data('pygom', 'data/eg1.json') - ode = common_models.SIR() + ode = common_models.SIR_norm() ode.parameters = [0.5, 0.3] obj = EpijsonLoss([0.005, 0.03], ode, data, 'Death', 'R', [300, 2, 0]) self.assertTrue(np.allclose(obj.cost(), 10.86559460256)) diff --git a/tests/test_model_existing.py b/tests/test_model_existing.py index 2af12ce4..8e53d24e 100644 --- a/tests/test_model_existing.py +++ b/tests/test_model_existing.py @@ -13,7 +13,7 @@ def test_SIR(self): Test the SIR model from the set of pre-defined models in common_models ''' # We we wish to test another (simpler) model - ode = common_models.SIR() + ode = common_models.SIR_norm() # define the parameters param_eval = [ diff --git a/tests/test_ode_func.py b/tests/test_ode_func.py index 22e660ef..127f64f8 100644 --- a/tests/test_ode_func.py +++ b/tests/test_ode_func.py @@ -18,7 +18,7 @@ def setUp(self): self.x0 = np.array([1, 1.27e-6, 0]) # params param_eval = [('beta', 0.5), ('gamma', 1.0 / 3.0)] - self.ode = common_models.SIR(param_eval) + self.ode = common_models.SIR_norm(param_eval) self.ode.initial_values = (self.x0, self.t0) self.d = self.ode.num_state self.p = self.ode.num_param diff --git a/tests/test_ode_simulate_param.py b/tests/test_ode_simulate_param.py index 5d9ff629..61403e2d 100644 --- a/tests/test_ode_simulate_param.py +++ b/tests/test_ode_simulate_param.py @@ -19,7 +19,7 @@ def setUp(self): # set the time sequence that we would like to observe self.t = np.linspace(0, 150, 100) # Standard. Find the solution. - ode = common_models.SIR() + ode = common_models.SIR_norm() ode.parameters = [0.5, 1.0 / 3.0] ode.initial_values = (self.x0, self.t0) self.solution = ode.integrate(self.t[1::], full_output=False) diff --git a/tests/test_sir_estimate.py b/tests/test_sir_estimate.py index 629bcc99..b3d42b07 100644 --- a/tests/test_sir_estimate.py +++ b/tests/test_sir_estimate.py @@ -11,7 +11,7 @@ class TestModelEstimate(TestCase): def setUp(self): # define the model and parameters - self.ode = common_models.SIR({'beta': 0.5, 'gamma': 1.0/3.0}) + self.ode = common_models.SIR_norm({'beta': 0.5, 'gamma': 1.0/3.0}) # the initial state, normalized to zero one self.x0 = [1, 1.27e-6, 0] diff --git a/tests/test_unroll.ipynb b/tests/test_unroll.ipynb new file mode 100644 index 00000000..08f94257 --- /dev/null +++ b/tests/test_unroll.ipynb @@ -0,0 +1,263 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pygom import SimulateOde, Transition, TransitionType\n", + "from pygom.model import _ode_composition, ode_utils, _model_verification\n", + "\n", + "odeList = [\n", + " Transition(transition_type=TransitionType.ODE, origin='S', equation='-beta*S*I/(S+I+R) + B*(S+I+R) - mu*S+G'),\n", + " Transition(transition_type=TransitionType.ODE, origin='I', equation='beta*S*I/(S+I+R) - gamma*I - mu*I'),\n", + " Transition(transition_type=TransitionType.ODE, origin='R', equation='gamma*I*p - mu*R'),\n", + " Transition(transition_type=TransitionType.ODE, origin='D', equation='gamma*I*(1-p)') \n", + "]\n", + "\n", + "stateList = ['S', 'I', 'R']\n", + "paramList = ['beta', 'gamma', 'B', 'mu', 'G', 'p']\n", + "\n", + "model = SimulateOde(state=stateList, param=paramList, ode=odeList)\n", + "A=model._get_A()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bdList, _term = _ode_composition.getUnmatchedExpressionVector(A, True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "map(_ode_composition.getExpressions, A)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from functools import reduce\n", + "\n", + "print(A)\n", + "transition = reduce(lambda x, y: x + y, map(_ode_composition.getExpressions, A))\n", + "print(transition)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def _getBasis(expr):\n", + " \"\"\"\n", + " Given an expression, find the constituent terms.\n", + " e.g. expr=a+b*(c-d) returns [a, b*c, -b*d]\n", + "\n", + " Parameters\n", + " ----------\n", + " expr: sympy type\n", + " An algebraic expression\n", + "\n", + " Returns\n", + " -------\n", + " list:\n", + " Each element being a term of the expression\n", + " \"\"\"\n", + " args=expr.expand().args\n", + "\n", + " #print(args)\n", + "\n", + " for i in range(0, len(args)-1, 1):\n", + " for j in range(i+1, len(args), 1):\n", + " j=j\n", + " #print(args[i]/args[j])\n", + "\n", + " return args\n", + "\n", + "x=_getBasis(A[3])\n", + "\n", + "import sympy\n", + "print(x[0])\n", + "g, I=sympy.symbols('gamma, I')\n", + "print(g)\n", + "(g+2).has(g)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Find basis functions\n", + "\n", + "# x1, x2, x3, x4, x5\n", + "\n", + "# Coefficients in each equation\n", + "\n", + "# (a1, a2, a3, a4, a5)\n", + "# (b1, b2, b3, b4, b5)\n", + "# (c1, c2, c3, c4, c5)\n", + "\n", + "sympy.Symbol('G') in A[0].atoms(sympy.Symbol)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sympy\n", + "x = sympy.Symbol('x')\n", + "y = sympy.Symbol('y')\n", + "a = [4 + x**2 + y, 4 + y**2]\n", + "\n", + "x in a[0].free_symbols" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "param=\"hello there,how are, you\"\n", + "\n", + "import re\n", + "\n", + "re_split_string = re.compile(r',|\\s') # split string into list at commas or spaces.\n", + "\n", + "print(param)\n", + "if param is not None:\n", + " if isinstance(param, str):\n", + " param = re_split_string.split(param)\n", + " print(param)\n", + " param = filter(lambda x: not len(x.strip()) == 0, param)\n", + " param_list = list(param)\n", + "\n", + "print(param_list)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('beta', 1), ('alpha', 1), ('gamma', 1)]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import re\n", + "re_split_string = re.compile(r',|\\s')\n", + "\n", + "class Pets:\n", + " def __init__(self, param):\n", + " self.param=param\n", + " self._add_list_attr(\"param\")\n", + "\n", + " def _add_list_attr(self, attr_name):\n", + " \"\"\"\n", + " Given an attribute (name attr_name), which is a string of comma\n", + " or space separated values, create a new attribute (name attr_name_list)\n", + " which is a list of those separated values.\n", + " e.g. \"a,b,c d ef\" returns [a, b, c, d, ef]\n", + " \"\"\"\n", + " attr=self.__getattribute__(attr_name)\n", + " if attr is not None:\n", + " if isinstance(attr, str):\n", + " attr = re_split_string.split(attr)\n", + " attr = filter(lambda x: not len(x.strip()) == 0, attr)\n", + " self.__setattr__(\"_\".join([attr_name, \"list\"]), list(attr))\n", + "\n", + "params=[('beta', 1), ('alpha', 1), ('gamma', 1)]\n", + "\n", + "x=Pets(params)\n", + "\n", + "x.param_list" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'dog, cat, bird'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mypets.animals" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['dog', 'cat', 'bird']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mypets.animals__list" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pygom_development", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}